summaryrefslogtreecommitdiffstats
path: root/usrp2/sdr_lib
diff options
context:
space:
mode:
authorMatt Ettus <matt@ettus.com>2010-06-01 18:53:59 -0700
committerMatt Ettus <matt@ettus.com>2010-06-01 18:53:59 -0700
commitaef34710a38bfe3e54c1a577b934a32be14becc1 (patch)
treefe9b4bfb579ab35c014969a086b78a54307eb063 /usrp2/sdr_lib
parentb96282d6d9d7aad94d82f2ac6487460f4850a55c (diff)
parent2d45c8537171f8a82baf13674fbe9ccefa2cc0c0 (diff)
downloaduhd-aef34710a38bfe3e54c1a577b934a32be14becc1.tar.gz
uhd-aef34710a38bfe3e54c1a577b934a32be14becc1.tar.bz2
uhd-aef34710a38bfe3e54c1a577b934a32be14becc1.zip
Merge branch 'ise12_exp' into u1e
* ise12_exp: zero out debug pins. helps timing a little bit. non-udp uses a different address for the tx dsp core manual merge to use localparams from udp version from UDP branch, changed names because I want these separate from the non-udp versions ignore output files new files from udp branch added to main Makefile change the debug pins, which makes it more reliable. This is unnerving. experimental mods to make ram loader fully synchronous. Based on IJB's work fixes from IJB from 5/24. Basically connect unconnected wires. removes the icache and pipelines the reads
Diffstat (limited to 'usrp2/sdr_lib')
-rw-r--r--usrp2/sdr_lib/dsp_core_rx.v16
-rw-r--r--usrp2/sdr_lib/dsp_core_rx_udp.v183
2 files changed, 191 insertions, 8 deletions
diff --git a/usrp2/sdr_lib/dsp_core_rx.v b/usrp2/sdr_lib/dsp_core_rx.v
index 1e689fc7f..aba18fccb 100644
--- a/usrp2/sdr_lib/dsp_core_rx.v
+++ b/usrp2/sdr_lib/dsp_core_rx.v
@@ -1,6 +1,6 @@
+`define DSP_CORE_RX_BASE 160
module dsp_core_rx
- #(parameter BASE = 160)
(input clk, input rst,
input set_stb, input [7:0] set_addr, input [31:0] set_data,
@@ -37,33 +37,33 @@ module dsp_core_rx
wire [31:4] UNUSED_2;
wire [31:2] UNUSED_3;
- setting_reg #(.my_addr(BASE+0)) sr_0
+ setting_reg #(.my_addr(`DSP_CORE_RX_BASE+0)) sr_0
(.clk(clk),.rst(rst),.strobe(set_stb),.addr(set_addr),
.in(set_data),.out(phase_inc),.changed());
- setting_reg #(.my_addr(BASE+1)) sr_1
+ setting_reg #(.my_addr(`DSP_CORE_RX_BASE+1)) sr_1
(.clk(clk),.rst(rst),.strobe(set_stb),.addr(set_addr),
.in(set_data),.out({scale_i,scale_q}),.changed());
- setting_reg #(.my_addr(BASE+2)) sr_2
+ setting_reg #(.my_addr(`DSP_CORE_RX_BASE+2)) sr_2
(.clk(clk),.rst(rst),.strobe(set_stb),.addr(set_addr),
.in(set_data),.out({UNUSED_1, enable_hb1, enable_hb2, cic_decim_rate}),.changed());
- rx_dcoffset #(.WIDTH(14),.ADDR(BASE+3)) rx_dcoffset_a
+ rx_dcoffset #(.WIDTH(14),.ADDR(`DSP_CORE_RX_BASE+6)) rx_dcoffset_a
(.clk(clk),.rst(rst),.set_stb(set_stb),.set_addr(set_addr),.set_data(set_data),
.adc_in(adc_a),.adc_out(adc_a_ofs));
- rx_dcoffset #(.WIDTH(14),.ADDR(BASE+4)) rx_dcoffset_b
+ rx_dcoffset #(.WIDTH(14),.ADDR(`DSP_CORE_RX_BASE+7)) rx_dcoffset_b
(.clk(clk),.rst(rst),.set_stb(set_stb),.set_addr(set_addr),.set_data(set_data),
.adc_in(adc_b),.adc_out(adc_b_ofs));
wire [3:0] muxctrl;
- setting_reg #(.my_addr(BASE+5)) sr_8
+ setting_reg #(.my_addr(`DSP_CORE_RX_BASE+8)) sr_8
(.clk(clk),.rst(rst),.strobe(set_stb),.addr(set_addr),
.in(set_data),.out({UNUSED_2,muxctrl}),.changed());
wire [1:0] gpio_ena;
- setting_reg #(.my_addr(BASE+6)) sr_9
+ setting_reg #(.my_addr(`DSP_CORE_RX_BASE+9)) sr_9
(.clk(clk),.rst(rst),.strobe(set_stb),.addr(set_addr),
.in(set_data),.out({UNUSED_3,gpio_ena}),.changed());
diff --git a/usrp2/sdr_lib/dsp_core_rx_udp.v b/usrp2/sdr_lib/dsp_core_rx_udp.v
new file mode 100644
index 000000000..1e689fc7f
--- /dev/null
+++ b/usrp2/sdr_lib/dsp_core_rx_udp.v
@@ -0,0 +1,183 @@
+
+module dsp_core_rx
+ #(parameter BASE = 160)
+ (input clk, input rst,
+ input set_stb, input [7:0] set_addr, input [31:0] set_data,
+
+ input [13:0] adc_a, input adc_ovf_a,
+ input [13:0] adc_b, input adc_ovf_b,
+
+ input [15:0] io_rx,
+
+ output [31:0] sample,
+ input run,
+ output strobe,
+ output [31:0] debug
+ );
+
+ wire [15:0] scale_i, scale_q;
+ wire [13:0] adc_a_ofs, adc_b_ofs;
+ reg [13:0] adc_i, adc_q;
+ wire [31:0] phase_inc;
+ reg [31:0] phase;
+
+ wire [35:0] prod_i, prod_q;
+ wire [23:0] i_cordic, q_cordic;
+ wire [23:0] i_cic, q_cic;
+ wire [17:0] i_cic_scaled, q_cic_scaled;
+ wire [17:0] i_hb1, q_hb1;
+ wire [17:0] i_hb2, q_hb2;
+ wire [15:0] i_out, q_out;
+
+ wire strobe_cic, strobe_hb1, strobe_hb2;
+ wire enable_hb1, enable_hb2;
+ wire [7:0] cic_decim_rate;
+
+ wire [31:10] UNUSED_1;
+ wire [31:4] UNUSED_2;
+ wire [31:2] UNUSED_3;
+
+ setting_reg #(.my_addr(BASE+0)) sr_0
+ (.clk(clk),.rst(rst),.strobe(set_stb),.addr(set_addr),
+ .in(set_data),.out(phase_inc),.changed());
+
+ setting_reg #(.my_addr(BASE+1)) sr_1
+ (.clk(clk),.rst(rst),.strobe(set_stb),.addr(set_addr),
+ .in(set_data),.out({scale_i,scale_q}),.changed());
+
+ setting_reg #(.my_addr(BASE+2)) sr_2
+ (.clk(clk),.rst(rst),.strobe(set_stb),.addr(set_addr),
+ .in(set_data),.out({UNUSED_1, enable_hb1, enable_hb2, cic_decim_rate}),.changed());
+
+ rx_dcoffset #(.WIDTH(14),.ADDR(BASE+3)) rx_dcoffset_a
+ (.clk(clk),.rst(rst),.set_stb(set_stb),.set_addr(set_addr),.set_data(set_data),
+ .adc_in(adc_a),.adc_out(adc_a_ofs));
+
+ rx_dcoffset #(.WIDTH(14),.ADDR(BASE+4)) rx_dcoffset_b
+ (.clk(clk),.rst(rst),.set_stb(set_stb),.set_addr(set_addr),.set_data(set_data),
+ .adc_in(adc_b),.adc_out(adc_b_ofs));
+
+ wire [3:0] muxctrl;
+ setting_reg #(.my_addr(BASE+5)) sr_8
+ (.clk(clk),.rst(rst),.strobe(set_stb),.addr(set_addr),
+ .in(set_data),.out({UNUSED_2,muxctrl}),.changed());
+
+ wire [1:0] gpio_ena;
+ setting_reg #(.my_addr(BASE+6)) sr_9
+ (.clk(clk),.rst(rst),.strobe(set_stb),.addr(set_addr),
+ .in(set_data),.out({UNUSED_3,gpio_ena}),.changed());
+
+ // The TVRX connects to what is called adc_b, thus A and B are
+ // swapped throughout the design.
+ //
+ // In the interest of expediency and keeping the s/w sane, we just remap them here.
+ // The I & Q fields are mapped the same:
+ // 0 -> "the real A" (as determined by the TVRX)
+ // 1 -> "the real B"
+ // 2 -> const zero
+
+ always @(posedge clk)
+ case(muxctrl[1:0]) // The I mapping
+ 0: adc_i <= adc_b_ofs; // "the real A"
+ 1: adc_i <= adc_a_ofs;
+ 2: adc_i <= 0;
+ default: adc_i <= 0;
+ endcase // case(muxctrl[1:0])
+
+ always @(posedge clk)
+ case(muxctrl[3:2]) // The Q mapping
+ 0: adc_q <= adc_b_ofs; // "the real A"
+ 1: adc_q <= adc_a_ofs;
+ 2: adc_q <= 0;
+ default: adc_q <= 0;
+ endcase // case(muxctrl[3:2])
+
+ always @(posedge clk)
+ if(rst)
+ phase <= 0;
+ else if(~run)
+ phase <= 0;
+ else
+ phase <= phase + phase_inc;
+
+ MULT18X18S mult_i
+ (.P(prod_i), // 36-bit multiplier output
+ .A({{4{adc_i[13]}},adc_i} ), // 18-bit multiplier input
+ .B({{2{scale_i[15]}},scale_i}), // 18-bit multiplier input
+ .C(clk), // Clock input
+ .CE(1), // Clock enable input
+ .R(rst) // Synchronous reset input
+ );
+
+ MULT18X18S mult_q
+ (.P(prod_q), // 36-bit multiplier output
+ .A({{4{adc_q[13]}},adc_q} ), // 18-bit multiplier input
+ .B({{2{scale_q[15]}},scale_q}), // 18-bit multiplier input
+ .C(clk), // Clock input
+ .CE(1), // Clock enable input
+ .R(rst) // Synchronous reset input
+ );
+
+
+ cordic_z24 #(.bitwidth(24))
+ cordic(.clock(clk), .reset(rst), .enable(run),
+ .xi(prod_i[23:0]),. yi(prod_q[23:0]), .zi(phase[31:8]),
+ .xo(i_cordic),.yo(q_cordic),.zo() );
+
+ cic_strober cic_strober(.clock(clk),.reset(rst),.enable(run),.rate(cic_decim_rate),
+ .strobe_fast(1),.strobe_slow(strobe_cic) );
+
+ cic_decim #(.bw(24))
+ decim_i (.clock(clk),.reset(rst),.enable(run),
+ .rate(cic_decim_rate),.strobe_in(1'b1),.strobe_out(strobe_cic),
+ .signal_in(i_cordic),.signal_out(i_cic));
+
+ cic_decim #(.bw(24))
+ decim_q (.clock(clk),.reset(rst),.enable(run),
+ .rate(cic_decim_rate),.strobe_in(1'b1),.strobe_out(strobe_cic),
+ .signal_in(q_cordic),.signal_out(q_cic));
+
+ round_reg #(.bits_in(24),.bits_out(18)) round_icic (.clk(clk),.in(i_cic),.out(i_cic_scaled));
+ round_reg #(.bits_in(24),.bits_out(18)) round_qcic (.clk(clk),.in(q_cic),.out(q_cic_scaled));
+ reg strobe_cic_d1;
+ always @(posedge clk) strobe_cic_d1 <= strobe_cic;
+
+ small_hb_dec #(.WIDTH(18)) small_hb_i
+ (.clk(clk),.rst(rst),.bypass(~enable_hb1),.run(run),
+ .stb_in(strobe_cic_d1),.data_in(i_cic_scaled),.stb_out(strobe_hb1),.data_out(i_hb1));
+
+ small_hb_dec #(.WIDTH(18)) small_hb_q
+ (.clk(clk),.rst(rst),.bypass(~enable_hb1),.run(run),
+ .stb_in(strobe_cic_d1),.data_in(q_cic_scaled),.stb_out(),.data_out(q_hb1));
+
+ wire [8:0] cpi_hb = enable_hb1 ? {cic_decim_rate,1'b0} : {1'b0,cic_decim_rate};
+ hb_dec #(.IWIDTH(18), .OWIDTH(18), .CWIDTH(18), .ACCWIDTH(24)) hb_i
+ (.clk(clk),.rst(rst),.bypass(~enable_hb2),.run(run),.cpi(cpi_hb),
+ .stb_in(strobe_hb1),.data_in(i_hb1),.stb_out(strobe_hb2),.data_out(i_hb2));
+
+ hb_dec #(.IWIDTH(18), .OWIDTH(18), .CWIDTH(18), .ACCWIDTH(24)) hb_q
+ (.clk(clk),.rst(rst),.bypass(~enable_hb2),.run(run),.cpi(cpi_hb),
+ .stb_in(strobe_hb1),.data_in(q_hb1),.stb_out(),.data_out(q_hb2));
+
+ round #(.bits_in(18),.bits_out(16)) round_iout (.in(i_hb2),.out(i_out));
+ round #(.bits_in(18),.bits_out(16)) round_qout (.in(q_hb2),.out(q_out));
+
+ // Streaming GPIO
+ //
+ // io_rx[15] => I channel LSB if gpio_ena[0] high
+ // io_rx[14] => Q channel LSB if gpio_ena[1] high
+
+ reg [31:0] sample_reg;
+ always @(posedge clk)
+ begin
+ sample_reg[31:17] <= i_out[15:1];
+ sample_reg[15:1] <= q_out[15:1];
+ sample_reg[16] <= gpio_ena[0] ? io_rx[15] : i_out[0];
+ sample_reg[0] <= gpio_ena[1] ? io_rx[14] : q_out[0];
+ end
+
+ assign sample = sample_reg;
+ assign strobe = strobe_hb2;
+ assign debug = {enable_hb1, enable_hb2, run, strobe, strobe_cic, strobe_cic_d1, strobe_hb1, strobe_hb2};
+
+endmodule // dsp_core_rx