diff options
author | jcorgan <jcorgan@221aa14e-8319-0410-a670-987f0aec2ac5> | 2007-05-21 05:58:05 +0000 |
---|---|---|
committer | jcorgan <jcorgan@221aa14e-8319-0410-a670-987f0aec2ac5> | 2007-05-21 05:58:05 +0000 |
commit | 2711e51f33e4c83b07d8293ceca5d6db7830656e (patch) | |
tree | 21be31385aa79dc8d6f3075acd093f8ca9775f3d /gr-sounder/src/fpga/lib | |
parent | 9b7e0f924e4294bff46fa55b9a993b4d529f499a (diff) |
Merged r5463:5504 from jcorgan/snd into trunk. Work in progress, adds digital loopback and receive to FPGA code. Host receive code is still debugging only.
git-svn-id: http://gnuradio.org/svn/gnuradio/trunk@5505 221aa14e-8319-0410-a670-987f0aec2ac5
Diffstat (limited to 'gr-sounder/src/fpga/lib')
-rw-r--r-- | gr-sounder/src/fpga/lib/Makefile.am | 1 | ||||
-rw-r--r-- | gr-sounder/src/fpga/lib/dac_interface.v | 8 | ||||
-rwxr-xr-x | gr-sounder/src/fpga/lib/lfsr_constants.v | 4 | ||||
-rw-r--r-- | gr-sounder/src/fpga/lib/sounder.v | 74 | ||||
-rw-r--r-- | gr-sounder/src/fpga/lib/sounder_rx.v | 87 | ||||
-rw-r--r-- | gr-sounder/src/fpga/lib/sounder_tx.v | 12 | ||||
-rw-r--r-- | gr-sounder/src/fpga/lib/strobe.v | 48 |
7 files changed, 150 insertions, 84 deletions
diff --git a/gr-sounder/src/fpga/lib/Makefile.am b/gr-sounder/src/fpga/lib/Makefile.am index 450981f1a4..0a03147a27 100644 --- a/gr-sounder/src/fpga/lib/Makefile.am +++ b/gr-sounder/src/fpga/lib/Makefile.am @@ -28,3 +28,4 @@ EXTRA_DIST = \ sounder_rx.v \ sounder_tx.v +MOSTLYCLEANFILES = *~
\ No newline at end of file diff --git a/gr-sounder/src/fpga/lib/dac_interface.v b/gr-sounder/src/fpga/lib/dac_interface.v index b97ffa77fd..9042e1c53d 100644 --- a/gr-sounder/src/fpga/lib/dac_interface.v +++ b/gr-sounder/src/fpga/lib/dac_interface.v @@ -27,16 +27,16 @@ module dac_interface(clk_i,rst_i,ena_i,strobe_i,tx_i_i,tx_q_i,tx_data_o,tx_sync_ input ena_i; input strobe_i; - input [15:0] tx_i_i; - input [15:0] tx_q_i; + input [13:0] tx_i_i; + input [13:0] tx_q_i; - output [15:0] tx_data_o; + output [13:0] tx_data_o; output tx_sync_o; `ifdef TX_RATE_MAX wire clk128; reg clk64_d; - reg [15:0] tx_data_o; + reg [13:0] tx_data_o; // Create a 128 MHz clock dacpll pll128(.areset(rst_i),.inclk0(clk_i),.c0(clk128)); diff --git a/gr-sounder/src/fpga/lib/lfsr_constants.v b/gr-sounder/src/fpga/lib/lfsr_constants.v index 79fcb1a2b7..55ee613d28 100755 --- a/gr-sounder/src/fpga/lib/lfsr_constants.v +++ b/gr-sounder/src/fpga/lib/lfsr_constants.v @@ -24,8 +24,8 @@ module lfsr_constants(degree_i,mask_o,len_o); output reg [15:0] mask_o; output wire [15:0] len_o; - assign len_o = (16'b1 << degree_i) - 1; - + assign len_o = (1 << degree_i) - 1; + always @* case (degree_i) 5'd00: mask_o = 16'h0000; diff --git a/gr-sounder/src/fpga/lib/sounder.v b/gr-sounder/src/fpga/lib/sounder.v index ea4007cb84..58b563448d 100644 --- a/gr-sounder/src/fpga/lib/sounder.v +++ b/gr-sounder/src/fpga/lib/sounder.v @@ -22,10 +22,10 @@ `include "../../../../usrp/firmware/include/fpga_regs_common.v" `include "../../../../usrp/firmware/include/fpga_regs_standard.v" -module sounder(clk_i,saddr_i,sdata_i,s_strobe_i,tx_rst_i,tx_enable_i,tx_strobe_i, - tx_dac_i_o,tx_dac_q_o, - rx_rst_i,rx_enable_i,rx_strobe_i,rx_strobe_o, - rx_adc_i_i,rx_adc_q_i,rx_imp_i_o,rx_imp_q_o); +module sounder(clk_i, saddr_i, sdata_i, s_strobe_i, + tx_strobe_i, tx_dac_i_o,tx_dac_q_o, + rx_strobe_i, rx_adc_i_i,rx_adc_q_i, + rx_strobe_o, rx_imp_i_o,rx_imp_q_o); // System interface input clk_i; // Master clock @ 64 MHz @@ -34,53 +34,59 @@ module sounder(clk_i,saddr_i,sdata_i,s_strobe_i,tx_rst_i,tx_enable_i,tx_strobe_i input s_strobe_i; // Configuration bus write // Transmit subsystem - input tx_rst_i; // Independent subsystem reset - input tx_enable_i; // Turn on transmitter functionality input tx_strobe_i; // Generate an transmitter output sample - output [15:0] tx_dac_i_o; // I channel transmitter output to DAC - output [15:0] tx_dac_q_o; // Q channel transmitter output to DAC + output [13:0] tx_dac_i_o; // I channel transmitter output to DAC + output [13:0] tx_dac_q_o; // Q channel transmitter output to DAC // Receive subsystem - input rx_rst_i; // Independent subsystem reset - input rx_enable_i; // Turn on receiver functionality input rx_strobe_i; // Indicates receive sample ready from ADC output rx_strobe_o; // Indicates output samples ready for Rx FIFO - input [15:0] rx_adc_i_i; // I channel input from ADC - input [15:0] rx_adc_q_i; // Q channel input from ADC + input [15:0] rx_adc_i_i; // I channel input from ADC interface module + input [15:0] rx_adc_q_i; // Q channel input from ADC interface module output [15:0] rx_imp_i_o; // I channel impulse response to Rx FIFO output [15:0] rx_imp_q_o; // Q channel impulse response to Rx FIFO + + // Internal variables + wire reset; + wire transmit; + wire receive; + wire loopback; - // Configuration - wire [4:0] degree; // LFSR register length - wire [15:0] mask; // LFSR parity mask - wire [15:0] len; // PN code sequence length - wire loopback; // Enable digital loopback + wire [4:0] degree; + wire [15:0] mask; + wire [15:0] len; - // Loopback implementation - wire [15:0] tx_i, tx_q, rx_i, rx_q; // Internal transmit and receive data bus + setting_reg #(`FR_USER_0) sr_mode + ( .clock(clk_i),.reset(1'b0),.strobe(s_strobe_i),.addr(saddr_i),.in(sdata_i), + .out({loopback,receive,transmit,reset}) ); - assign tx_dac_i_o = loopback ? 16'b0 : tx_i; - assign tx_dac_q_o = loopback ? 16'b0 : tx_q; - assign rx_i = loopback ? tx_i : rx_adc_i_i; - assign rx_q = loopback ? tx_q : rx_adc_q_i; - - setting_reg #(`FR_USER_0) sr_lfsr_degree + setting_reg #(`FR_USER_1) sr_lfsr_degree ( .clock(clk_i),.reset(1'b0),.strobe(s_strobe_i),.addr(saddr_i),.in(sdata_i),.out(degree) ); + + lfsr_constants constants(.degree_i(degree),.mask_o(mask),.len_o(len)); - setting_reg #(`FR_USER_1) sr_mode - ( .clock(clk_i),.reset(1'b0),.strobe(s_strobe_i),.addr(saddr_i),.in(sdata_i), - .out({loopback}) ); + // Loopback implementation + wire [13:0] tx_i, tx_q; + wire [15:0] tx_i_ext, tx_q_ext; + wire [15:0] rx_i, rx_q; - lfsr_constants constants(.degree_i(degree),.mask_o(mask),.len_o(len)); + sign_extend #(14,16) tx_i_extender(tx_i, tx_i_ext); + sign_extend #(14,16) tx_q_extender(tx_q, tx_q_ext); + assign tx_dac_i_o = loopback ? 14'b0 : tx_i; + assign tx_dac_q_o = loopback ? 14'b0 : tx_q; + assign rx_i = loopback ? tx_i_ext : rx_adc_i_i; + assign rx_q = loopback ? tx_q_ext : rx_adc_q_i; + sounder_tx transmitter - ( .clk_i(clk_i),.rst_i(tx_rst_i),.ena_i(tx_enable_i),.strobe_i(tx_strobe_i),.mask_i(mask), + ( .clk_i(clk_i),.rst_i(reset),.ena_i(transmit), + .strobe_i(tx_strobe_i),.mask_i(mask), .tx_i_o(tx_i),.tx_q_o(tx_q) ); sounder_rx receiver - ( .clk_i(clk_i),.rst_i(rx_rst_i),.ena_i(rx_enable_i), - .rx_strobe_i(rx_strobe_i),.tx_strobe_i(tx_strobe_i),.mask_i(mask),.len_i(len), + ( .clk_i(clk_i),.rst_i(reset),.ena_i(receive), + .rx_strobe_i(rx_strobe_i),.tx_strobe_i(tx_strobe_i),.mask_i(mask),.degree_i(degree),.len_i(len), .rx_in_i_i(rx_i),.rx_in_q_i(rx_q),.rx_i_o(rx_imp_i_o),.rx_q_o(rx_imp_q_o), - .rx_strobe_o(rx_strobe_o) ); - + .rx_strobe_o(rx_strobe_o),.loop_i(loopback)); + endmodule // sounder diff --git a/gr-sounder/src/fpga/lib/sounder_rx.v b/gr-sounder/src/fpga/lib/sounder_rx.v index b7c5f48782..338afd55e5 100644 --- a/gr-sounder/src/fpga/lib/sounder_rx.v +++ b/gr-sounder/src/fpga/lib/sounder_rx.v @@ -19,8 +19,9 @@ // Foundation, Inc., 51 Franklin Street, Boston, MA 02110-1301 USA // -module sounder_rx(clk_i,rst_i,ena_i,rx_strobe_i,tx_strobe_i,mask_i,len_i, - rx_in_i_i,rx_in_q_i,rx_i_o,rx_q_o,rx_strobe_o); +module sounder_rx(clk_i,rst_i,ena_i,rx_strobe_i,tx_strobe_i,mask_i,degree_i,len_i, + rx_in_i_i,rx_in_q_i,rx_i_o,rx_q_o,rx_strobe_o, + loop_i); input clk_i; // Master clock input rst_i; // Subsystem reset @@ -29,6 +30,7 @@ module sounder_rx(clk_i,rst_i,ena_i,rx_strobe_i,tx_strobe_i,mask_i,len_i, input tx_strobe_i; // Strobe every transmitted sample input [15:0] mask_i; // PN code LFSR mask + input [4:0] degree_i; // PN code LFSR sequency degree input [15:0] len_i; // PN code LFSR sequence length input [15:0] rx_in_i_i; // I channel on receive input [15:0] rx_in_q_i; // Q channel on receive @@ -37,48 +39,57 @@ module sounder_rx(clk_i,rst_i,ena_i,rx_strobe_i,tx_strobe_i,mask_i,len_i, output [15:0] rx_q_o; // Q channel of impulse response output rx_strobe_o; // Impulse response value ready - // LFSR phase counter - reg [15:0] count; - wire cycle = (count == (len_i - 1)); + input loop_i; // Implement loopback + + wire strobe_in = loop_i ? tx_strobe_i : rx_strobe_i; + wire [16:0] len = loop_i ? (len_i - 1) : ((len_i << 1) - 2); + + strobe #(17) phase_strobe(.clk_i(clk_i),.rst_i(rst_i),.ena_i(ena_i), + .rate_i(len),.strobe_i(strobe_in),.strobe_o(rx_strobe_o), + .count_o()); - always @(posedge clk_i) - if (rst_i | ~ena_i) - count <= 16'b0; - else - if (cycle) - count <= 16'b0; - else - count <= count + 16'b1; - - // Retard LFSR phase once per cycle - wire lfsr_strobe = (tx_strobe_i & ~cycle); + wire pn_ref; + wire ref_strobe = tx_strobe_i & ~rx_strobe_o; // Retard reference phase once per period + lfsr ref_code + ( .clk_i(clk_i),.rst_i(rst_i),.ena_i(ena_i),.strobe_i(ref_strobe),.mask_i(mask_i),.pn_o(pn_ref) ); - // Recreate local reference of transmitted PN code - wire pn; - lfsr reference - ( .clk_i(clk_i),.rst_i(rst_i),.ena_i(ena_i),.strobe_i(lfsr_strobe),.mask_i(mask_i),.pn_o(pn) ); + wire [5:0] offset = (5'd16-degree_i); + + reg [31:0] sum_i, sum_q; + reg [31:0] total_i, total_q; + wire [31:0] scaled_i = total_i << offset; + wire [31:0] scaled_q = total_q << offset; + wire [31:0] i_ext, q_ext; - wire [31:0] rx_i_ext, rx_q_ext; - sign_extend #(16,32) i_extend(rx_in_i_i, rx_i_ext); - sign_extend #(16,32) q_extend(rx_in_q_i, rx_q_ext); + sign_extend #(16,32) i_extender(rx_in_i_i, i_ext); + sign_extend #(16,32) q_extender(rx_in_q_i, q_ext); - reg [31:0] accum; + wire [31:0] prod_i = pn_ref ? i_ext : -i_ext; + wire [31:0] prod_q = pn_ref ? q_ext : -q_ext; + always @(posedge clk_i) if (rst_i | ~ena_i) - accum <= 32'b0; - else - if (rx_strobe_i) - if (cycle) - accum <= 32'b0; - else - if (pn) - accum <= accum + rx_i_ext; - else - accum <= accum - rx_i_ext; + begin + sum_i <= 0; + sum_q <= 0; + total_i <= 0; + total_q <= 0; + end + else if (rx_strobe_o) + begin + total_i <= sum_i + prod_i; + total_q <= sum_q + prod_q; + sum_i <= 0; + sum_q <= 0; + end + else if (strobe_in) + begin + sum_i = sum_i + prod_i; + sum_q = sum_q + prod_q; + end + + assign rx_i_o = scaled_i[31:16]; + assign rx_q_o = scaled_q[31:16]; - assign rx_i_o = accum[31:16]; - assign rx_q_o = accum[15:0]; - assign rx_strobe_o = rx_strobe_i & cycle; - endmodule // sounder_rx diff --git a/gr-sounder/src/fpga/lib/sounder_tx.v b/gr-sounder/src/fpga/lib/sounder_tx.v index d5300fecb9..46165dde5f 100644 --- a/gr-sounder/src/fpga/lib/sounder_tx.v +++ b/gr-sounder/src/fpga/lib/sounder_tx.v @@ -22,8 +22,8 @@ `include "../../../../usrp/firmware/include/fpga_regs_common.v" `include "../../../../usrp/firmware/include/fpga_regs_standard.v" -`define MAX_VALUE 16'h7FFF // 2s complement -`define MIN_VALUE 16'h8000 +`define MAX_VALUE 14'h1FFF // 2s complement +`define MIN_VALUE 14'h2001 module sounder_tx(clk_i,rst_i,ena_i,strobe_i,mask_i,tx_i_o,tx_q_o); input clk_i; @@ -31,15 +31,15 @@ module sounder_tx(clk_i,rst_i,ena_i,strobe_i,mask_i,tx_i_o,tx_q_o); input ena_i; input strobe_i; input [15:0] mask_i; - output [15:0] tx_i_o; - output [15:0] tx_q_o; + output [13:0] tx_i_o; + output [13:0] tx_q_o; wire pn; lfsr pn_code ( .clk_i(clk_i),.rst_i(rst_i),.ena_i(ena_i),.strobe_i(strobe_i),.mask_i(mask_i),.pn_o(pn) ); - assign tx_i_o = pn ? `MAX_VALUE : `MIN_VALUE; // Bipolar - assign tx_q_o = 16'b0; + assign tx_i_o = ena_i ? (pn ? `MAX_VALUE : `MIN_VALUE) : 14'b0; // Bipolar + assign tx_q_o = 14'b0; endmodule // sounder_tx diff --git a/gr-sounder/src/fpga/lib/strobe.v b/gr-sounder/src/fpga/lib/strobe.v new file mode 100644 index 0000000000..ed07f21f46 --- /dev/null +++ b/gr-sounder/src/fpga/lib/strobe.v @@ -0,0 +1,48 @@ +// -*- verilog -*- +// +// USRP - Universal Software Radio Peripheral +// +// Copyright (C) 2007 Corgan Enterprises LLC +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Boston, MA 02110-1301 USA +// + +module strobe(clk_i,rst_i,ena_i,rate_i,strobe_i,strobe_o,count_o); + parameter width = 16; + + input clk_i; + input rst_i; + input ena_i; + input [width-1:0] rate_i; // Desired period minus one + input strobe_i; + output strobe_o; + output [width-1:0] count_o; + + + reg [width-1:0] counter; + + always @(posedge clk_i) + if(rst_i | ~ena_i) + counter <= 32'hFFFFFFFF; // First period is short by one + else if(strobe_i) + if(counter == rate_i) + counter <= 0; + else + counter <= counter + 1; + + assign strobe_o = (counter == rate_i) & strobe_i; + assign count_o = counter; + +endmodule // strobe |