diff options
Diffstat (limited to 'fpga/usrp1/sdr_lib/hb')
| -rw-r--r-- | fpga/usrp1/sdr_lib/hb/acc.v | 22 | ||||
| -rw-r--r-- | fpga/usrp1/sdr_lib/hb/coeff_rom.v | 19 | ||||
| -rw-r--r-- | fpga/usrp1/sdr_lib/hb/halfband_decim.v | 163 | ||||
| -rw-r--r-- | fpga/usrp1/sdr_lib/hb/halfband_interp.v | 121 | ||||
| -rw-r--r-- | fpga/usrp1/sdr_lib/hb/hbd_tb/HBD | 80 | ||||
| -rw-r--r-- | fpga/usrp1/sdr_lib/hb/hbd_tb/really_golden | 142 | ||||
| -rw-r--r-- | fpga/usrp1/sdr_lib/hb/hbd_tb/regression | 95 | ||||
| -rwxr-xr-x | fpga/usrp1/sdr_lib/hb/hbd_tb/run_hbd | 4 | ||||
| -rw-r--r-- | fpga/usrp1/sdr_lib/hb/hbd_tb/test_hbd.v | 75 | ||||
| -rw-r--r-- | fpga/usrp1/sdr_lib/hb/mac.v | 58 | ||||
| -rw-r--r-- | fpga/usrp1/sdr_lib/hb/mult.v | 16 | ||||
| -rw-r--r-- | fpga/usrp1/sdr_lib/hb/ram16_2port.v | 22 | ||||
| -rw-r--r-- | fpga/usrp1/sdr_lib/hb/ram16_2sum.v | 27 | ||||
| -rw-r--r-- | fpga/usrp1/sdr_lib/hb/ram32_2sum.v | 22 | 
14 files changed, 866 insertions, 0 deletions
| diff --git a/fpga/usrp1/sdr_lib/hb/acc.v b/fpga/usrp1/sdr_lib/hb/acc.v new file mode 100644 index 000000000..195d5ea94 --- /dev/null +++ b/fpga/usrp1/sdr_lib/hb/acc.v @@ -0,0 +1,22 @@ + + +module acc (input clock, input reset, input clear, input enable_in, output reg enable_out, +	    input signed [30:0] addend, output reg signed [33:0] sum ); + +   always @(posedge clock) +     if(reset) +       sum <= #1 34'd0; +     //else if(clear & enable_in) +     //  sum <= #1 addend; +     //else if(clear) +     //  sum <= #1 34'd0; +     else if(clear) +       sum <= #1 addend; +     else if(enable_in) +       sum <= #1 sum + addend; + +   always @(posedge clock) +     enable_out <= #1 enable_in; +    +endmodule // acc + diff --git a/fpga/usrp1/sdr_lib/hb/coeff_rom.v b/fpga/usrp1/sdr_lib/hb/coeff_rom.v new file mode 100644 index 000000000..7f8886b4e --- /dev/null +++ b/fpga/usrp1/sdr_lib/hb/coeff_rom.v @@ -0,0 +1,19 @@ + + +module coeff_rom (input clock, input [2:0] addr, output reg [15:0] data); + +   always @(posedge clock) +     case (addr) +       3'd0 : data <= #1 -16'd49; +       3'd1 : data <= #1 16'd165; +       3'd2 : data <= #1 -16'd412; +       3'd3 : data <= #1 16'd873; +       3'd4 : data <= #1 -16'd1681; +       3'd5 : data <= #1 16'd3135; +       3'd6 : data <= #1 -16'd6282; +       3'd7 : data <= #1 16'd20628; +     endcase // case(addr) +       +endmodule // coeff_rom + + diff --git a/fpga/usrp1/sdr_lib/hb/halfband_decim.v b/fpga/usrp1/sdr_lib/hb/halfband_decim.v new file mode 100644 index 000000000..dff4d902c --- /dev/null +++ b/fpga/usrp1/sdr_lib/hb/halfband_decim.v @@ -0,0 +1,163 @@ +/* -*- verilog -*- + *  + *  USRP - Universal Software Radio Peripheral + *  + *  Copyright (C) 2005 Matt Ettus + *  + *  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 + */ + +/* + * This implements a 31-tap halfband filter that decimates by two. + * The coefficients are symmetric, and with the exception of the middle tap, + * every other coefficient is zero.  The middle section of taps looks like this: + * + *  ..., -1468, 0, 2950, 0, -6158, 0, 20585, 32768, 20585, 0, -6158, 0, 2950, 0, -1468, ... + *                                             | + *                           middle tap -------+ + * + * See coeff_rom.v for the full set.  The taps are scaled relative to 32768, + * thus the middle tap equals 1.0.  Not counting the middle tap, there are 8 + * non-zero taps on each side, and they are symmetric.  A naive implementation + * requires a mulitply for each non-zero tap.  Because of symmetry, we can + * replace 2 multiplies with 1 add and 1 multiply.  Thus, to compute each output + * sample, we need to perform 8 multiplications.  Since the middle tap is 1.0, + * we just add the corresponding delay line value. + * + * About timing: We implement this with a single multiplier, so it takes + * 8 cycles to compute a single output.  However, since we're decimating by two  + * we can accept a new input value every 4 cycles.  strobe_in is asserted when + * there's a new input sample available.  Depending on the overall decimation + * rate, strobe_in may be asserted less frequently than once every 4 clocks. + * On the output side, we assert strobe_out when output contains a new sample. + * + * Implementation: Every time strobe_in is asserted we store the new data into + * the delay line.  We split the delay line into two components, one for the + * even samples, and one for the odd samples.  ram16_odd is the delay line for + * the odd samples.  This ram is written on each odd assertion of strobe_in, and + * is read on each clock when we're computing the dot product.  ram16_even is + * similar, although because it holds the even samples we must be able to read + * two samples from different addresses at the same time, while writing the incoming + * even samples. Thus it's "triple-ported". + */ + +module halfband_decim +  (input clock, input reset, input enable, input strobe_in, output wire strobe_out, +   input wire [15:0] data_in, output reg [15:0] data_out,output wire [15:0] debugctrl); + +   reg [3:0] rd_addr1; +   reg [3:0] rd_addr2; +   reg [3:0] phase; +   reg [3:0] base_addr; + +   wire      signed [15:0] mac_out,middle_data, sum, coeff; +   wire      signed [30:0] product; +   wire      signed [33:0] sum_even; +   wire      clear; +   reg 	     store_odd; +    +   always @(posedge clock) +     if(reset) +       store_odd <= #1 1'b0; +     else +       if(strobe_in) +	 store_odd <= #1 ~store_odd; + +   wire      start = strobe_in & store_odd; +   always @(posedge clock) +     if(reset) +       base_addr <= #1 4'd0; +     else if(start) +       base_addr <= #1 base_addr + 4'd1; + +   always @(posedge clock) +     if(reset) +       phase <= #1 4'd8; +     else if (start) +       phase <= #1 4'd0; +     else if(phase != 4'd8) +       phase <= #1 phase + 4'd1; + +   reg 	     start_d1,start_d2,start_d3,start_d4,start_d5,start_d6,start_d7,start_d8,start_d9,start_dA,start_dB,start_dC,start_dD; +   always @(posedge clock) +     begin +	start_d1 <= #1 start; +	start_d2 <= #1 start_d1; +	start_d3 <= #1 start_d2; +	start_d4 <= #1 start_d3; +	start_d5 <= #1 start_d4; +	start_d6 <= #1 start_d5; +	start_d7 <= #1 start_d6; +	start_d8 <= #1 start_d7; +	start_d9 <= #1 start_d8; +	start_dA <= #1 start_d9; +	start_dB <= #1 start_dA; +	start_dC <= #1 start_dB; +	start_dD <= #1 start_dC; +     end // always @ (posedge clock) +    +   reg 	  mult_en, mult_en_pre; +   always @(posedge clock) +     begin +	mult_en_pre <= #1 phase!=8; +	mult_en <= #1 mult_en_pre; +     end +    +   assign clear = start_d4; // was dC +   wire   latch_result = start_d4; // was dC +   assign strobe_out = start_d5; // was dD +   wire   acc_en; +    +   always @* +     case(phase[2:0]) +       3'd0 : begin rd_addr1 = base_addr + 4'd0; rd_addr2 = base_addr + 4'd15; end +       3'd1 : begin rd_addr1 = base_addr + 4'd1; rd_addr2 = base_addr + 4'd14; end +       3'd2 : begin rd_addr1 = base_addr + 4'd2; rd_addr2 = base_addr + 4'd13; end +       3'd3 : begin rd_addr1 = base_addr + 4'd3; rd_addr2 = base_addr + 4'd12; end +       3'd4 : begin rd_addr1 = base_addr + 4'd4; rd_addr2 = base_addr + 4'd11; end +       3'd5 : begin rd_addr1 = base_addr + 4'd5; rd_addr2 = base_addr + 4'd10; end +       3'd6 : begin rd_addr1 = base_addr + 4'd6; rd_addr2 = base_addr + 4'd9; end +       3'd7 : begin rd_addr1 = base_addr + 4'd7; rd_addr2 = base_addr + 4'd8; end +       default: begin rd_addr1 = base_addr + 4'd0; rd_addr2 = base_addr + 4'd15; end +     endcase // case(phase) +    +   coeff_rom coeff_rom (.clock(clock),.addr(phase[2:0]-3'd1),.data(coeff)); +    +   ram16_2sum ram16_even (.clock(clock),.write(strobe_in & ~store_odd), +			  .wr_addr(base_addr),.wr_data(data_in), +			  .rd_addr1(rd_addr1),.rd_addr2(rd_addr2), +			  .sum(sum)); + +   ram16 ram16_odd (.clock(clock),.write(strobe_in & store_odd),  // Holds middle items +		    .wr_addr(base_addr),.wr_data(data_in), +		    //.rd_addr(base_addr+4'd7),.rd_data(middle_data)); +		    .rd_addr(base_addr+4'd6),.rd_data(middle_data)); + +   mult mult(.clock(clock),.x(coeff),.y(sum),.product(product),.enable_in(mult_en),.enable_out(acc_en)); + +   acc acc(.clock(clock),.reset(reset),.enable_in(acc_en),.enable_out(), +	   .clear(clear),.addend(product),.sum(sum_even)); + +   wire signed [33:0] dout = sum_even + {{4{middle_data[15]}},middle_data,14'b0}; // We already divided product by 2!!!! + +   always @(posedge clock) +     if(reset) +       data_out <= #1 16'd0; +     else if(latch_result) +       data_out <= #1 dout[30:15] + (dout[33]& |dout[14:0]); + +   assign  debugctrl = { clock,reset,acc_en,mult_en,clear,latch_result,store_odd,strobe_in,strobe_out,phase}; +    +endmodule // halfband_decim diff --git a/fpga/usrp1/sdr_lib/hb/halfband_interp.v b/fpga/usrp1/sdr_lib/hb/halfband_interp.v new file mode 100644 index 000000000..cdb11c1f6 --- /dev/null +++ b/fpga/usrp1/sdr_lib/hb/halfband_interp.v @@ -0,0 +1,121 @@ + + +module halfband_interp  +  (input clock, input reset, input enable, +   input strobe_in, input strobe_out, +   input [15:0] signal_in_i, input [15:0] signal_in_q,  +   output reg [15:0] signal_out_i, output reg [15:0] signal_out_q, +   output wire [12:0] debug); +    +   wire [15:0] 	coeff_ram_out; +   wire [15:0] 	data_ram_out_i; +   wire [15:0] 	data_ram_out_q; + +   wire [3:0] 	data_rd_addr; +   reg [3:0] 	data_wr_addr; +   reg [2:0] 	coeff_rd_addr; + +   wire 		filt_done; +    +   wire [15:0] 	mac_out_i; +   wire [15:0] 	mac_out_q; +   reg [15:0] 	delayed_middle_i, delayed_middle_q; +   wire [7:0] 	shift = 8'd9; + +   reg 		stb_out_happened; + +   wire [15:0] 	data_ram_out_i_b; +    +   always @(posedge clock) +     if(strobe_in) +       stb_out_happened <= #1 1'b0; +     else if(strobe_out) +       stb_out_happened <= #1 1'b1; +    +assign debug = {filt_done,data_rd_addr,data_wr_addr,coeff_rd_addr}; + +   wire [15:0] 	signal_out_i = stb_out_happened ? mac_out_i : delayed_middle_i; +   wire [15:0] 	signal_out_q = stb_out_happened ? mac_out_q : delayed_middle_q; + +/*   always @(posedge clock) +     if(reset) +       begin +	  signal_out_i <= #1 16'd0; +	  signal_out_q <= #1 16'd0; +       end +     else if(strobe_in) +       begin +	  signal_out_i <= #1 delayed_middle_i; // Multiply by 1 for middle coeff +	  signal_out_q <= #1 delayed_middle_q; +       end +     //else if(filt_done&stb_out_happened) +     else if(stb_out_happened) +       begin +	  signal_out_i <= #1 mac_out_i; +	  signal_out_q <= #1 mac_out_q; +       end +*/ +    +   always @(posedge clock) +     if(reset) +       coeff_rd_addr <= #1 3'd0; +     else if(coeff_rd_addr != 3'd0) +       coeff_rd_addr <= #1 coeff_rd_addr + 3'd1; +     else if(strobe_in) +       coeff_rd_addr <= #1 3'd1; + +   reg filt_done_d1; +   always@(posedge clock) +     filt_done_d1 <= #1 filt_done; +    +   always @(posedge clock) +     if(reset) +       data_wr_addr <= #1 4'd0; +   //else if(strobe_in) +     else if(filt_done & ~filt_done_d1) +       data_wr_addr <= #1 data_wr_addr + 4'd1; + +   always @(posedge clock) +     if(coeff_rd_addr == 3'd7) +       begin +	  delayed_middle_i <= #1 data_ram_out_i_b; +	//  delayed_middle_q <= #1 data_ram_out_q_b; +       end +    +//   always @(posedge clock) +//     if(reset) +//       data_rd_addr <= #1 4'd0; +//     else if(strobe_in) +//       data_rd_addr <= #1 data_wr_addr + 4'd1; +//     else if(!filt_done) +//       data_rd_addr <= #1 data_rd_addr + 4'd1; +//     else +//       data_rd_addr <= #1 data_wr_addr; +   +   wire [3:0] data_rd_addr1 = data_wr_addr + {1'b0,coeff_rd_addr}; +   wire [3:0] data_rd_addr2 = data_wr_addr + 15 - {1'b0,coeff_rd_addr}; +//   always @(posedge clock) +//     if(reset) +//       filt_done <= #1 1'b1; +//     else if(strobe_in) + //      filt_done <= #1 1'b0; +//     else if(coeff_rd_addr == 4'd0) +//       filt_done <= #1 1'b1; + +   assign filt_done = (coeff_rd_addr == 3'd0); +    +   coeff_ram coeff_ram ( .clock(clock),.rd_addr({1'b0,coeff_rd_addr}),.rd_data(coeff_ram_out) ); +    +   ram16_2sum data_ram_i ( .clock(clock),.write(strobe_in),.wr_addr(data_wr_addr),.wr_data(signal_in_i), +		      .rd_addr1(data_rd_addr1),.rd_addr2(data_rd_addr2),.rd_data(data_ram_out_i_b),.sum(data_ram_out_i)); +    +   ram16_2sum data_ram_q ( .clock(clock),.write(strobe_in),.wr_addr(data_wr_addr),.wr_data(signal_in_q), +		      .rd_addr1(data_rd_addr1),.rd_addr2(data_rd_addr2),.rd_data(data_ram_out_q)); +    +   mac mac_i (.clock(clock),.reset(reset),.enable(~filt_done),.clear(strobe_in), +	      .x(data_ram_out_i),.y(coeff_ram_out),.shift(shift),.z(mac_out_i) ); +    +   mac mac_q (.clock(clock),.reset(reset),.enable(~filt_done),.clear(strobe_in), +	      .x(data_ram_out_q),.y(coeff_ram_out),.shift(shift),.z(mac_out_q) ); + +endmodule // halfband_interp diff --git a/fpga/usrp1/sdr_lib/hb/hbd_tb/HBD b/fpga/usrp1/sdr_lib/hb/hbd_tb/HBD new file mode 100644 index 000000000..574fbba91 --- /dev/null +++ b/fpga/usrp1/sdr_lib/hb/hbd_tb/HBD @@ -0,0 +1,80 @@ +*-6.432683 5736 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 +@28 +test_hbd.clock +test_hbd.reset +@420 +test_hbd.halfband_decim.middle_data[15:0] +@22 +test_hbd.halfband_decim.sum_even[33:0] +test_hbd.halfband_decim.base_addr[3:0] +@420 +test_hbd.i_in[15:0] +@24 +test_hbd.halfband_decim.phase[3:0] +test_hbd.halfband_decim.ram16_even.rd_addr1[3:0] +test_hbd.halfband_decim.ram16_even.rd_addr2[3:0] +test_hbd.halfband_decim.ram16_even.wr_addr[3:0] +test_hbd.halfband_decim.ram16_even.wr_data[15:0] +@28 +test_hbd.halfband_decim.ram16_even.write +@420 +test_hbd.halfband_decim.sum[15:0] +test_hbd.halfband_decim.product[30:0] +test_hbd.halfband_decim.dout[33:0] +test_hbd.halfband_decim.sum_even[33:0] +@22 +test_hbd.halfband_decim.acc.addend[30:0] +@28 +test_hbd.halfband_decim.acc.reset +@420 +test_hbd.halfband_decim.acc.sum[33:0] +test_hbd.halfband_decim.mult.x[15:0] +test_hbd.halfband_decim.mult.y[15:0] +@28 +test_hbd.halfband_decim.acc.clear +test_hbd.strobe_in +test_hbd.strobe_out +test_hbd.halfband_decim.acc_en +@420 +test_hbd.i_out[15:0] +@28 +test_hbd.halfband_decim.mult_en +test_hbd.halfband_decim.latch_result +@420 +test_hbd.halfband_decim.sum[15:0] +test_hbd.halfband_decim.sum_even[33:0] +test_hbd.halfband_decim.dout[33:0] +test_hbd.halfband_decim.data_out[15:0] +@22 +test_hbd.halfband_decim.data_out[15:0] +@28 +test_hbd.halfband_decim.dout[33:0] +@29 +test_hbd.halfband_decim.acc_en +@22 +test_hbd.halfband_decim.base_addr[3:0] +@28 +test_hbd.halfband_decim.clear +test_hbd.halfband_decim.latch_result +test_hbd.halfband_decim.mult_en +test_hbd.halfband_decim.mult_en_pre +@22 +test_hbd.halfband_decim.phase[3:0] +@28 +test_hbd.halfband_decim.start +test_hbd.halfband_decim.start_d1 +test_hbd.halfband_decim.start_d2 +test_hbd.halfband_decim.start_d3 +test_hbd.halfband_decim.start_d4 +test_hbd.halfband_decim.start_d5 +test_hbd.halfband_decim.start_d6 +test_hbd.halfband_decim.start_d7 +test_hbd.halfband_decim.start_d8 +test_hbd.halfband_decim.start_d9 +test_hbd.halfband_decim.start_dA +test_hbd.halfband_decim.start_dB +test_hbd.halfband_decim.start_dC +test_hbd.halfband_decim.start_dD +test_hbd.halfband_decim.store_odd +test_hbd.halfband_decim.strobe_in +test_hbd.halfband_decim.strobe_out diff --git a/fpga/usrp1/sdr_lib/hb/hbd_tb/really_golden b/fpga/usrp1/sdr_lib/hb/hbd_tb/really_golden new file mode 100644 index 000000000..2d24a9e14 --- /dev/null +++ b/fpga/usrp1/sdr_lib/hb/hbd_tb/really_golden @@ -0,0 +1,142 @@ +VCD info: dumpfile test_hbd.vcd opened for output. +    x +    x +    x +    x +    x +    x +    x +    x +    x +    x +    x +    x +    x +    x +    x +    x +    0 +    0 +    0 +    0 +    0 +    0 +    0 +    0 +    0 +    0 +    0 + 8192 +    0 +    0 +    0 +    0 +    0 +    0 +    0 +    0 +    0 +    0 +    0 +    0 +    0 +-     4 +   18 +-    63 +  167 +-   367 +  737 +-  1539 + 5146 + 5146 +-  1539 +  737 +-   367 +  167 +-    63 +   18 +-     4 +    0 +    0 +    0 +    0 +    0 +-     4 +   14 +-    49 +  118 +-   249 +  488 + 7141 +12287 +17433 +15894 +16631 +16264 +16432 +16368 +16387 +16383 +16383 +16383 +16383 +16383 +16387 +16368 +16432 +16264 +16631 +15894 + 9241 + 4095 +-  1051 +  488 +-   249 +  118 +-    49 +   14 +-     4 +    0 +    0 +    0 +    0 +    0 +-     4 +   14 +-    49 +  118 +-   249 +  488 +-  1051 +12287 +17433 +15894 +16631 +16264 +16432 +16368 +16387 +16383 +16383 +16383 +16383 +16383 +16387 +16368 +16432 +16264 +16631 +15894 +17433 + 4095 +-  1051 +  488 +-   249 +  118 +-    49 +   14 +-     4 +    0 +    0 +    0 +    0 diff --git a/fpga/usrp1/sdr_lib/hb/hbd_tb/regression b/fpga/usrp1/sdr_lib/hb/hbd_tb/regression new file mode 100644 index 000000000..fc279c2f2 --- /dev/null +++ b/fpga/usrp1/sdr_lib/hb/hbd_tb/regression @@ -0,0 +1,95 @@ +echo "Baseline 1000" +iverilog -y .. -o test_hbd -DRATE=1000 test_hbd.v  ; ./test_hbd >golden +diff golden really_golden + +echo +echo "Test 100" +iverilog -y .. -o test_hbd -DRATE=100 test_hbd.v  ; ./test_hbd >output ; diff output golden + +echo +echo "Test 50" +iverilog -y .. -o test_hbd -DRATE=50 test_hbd.v  ; ./test_hbd >output ; diff output golden + +echo +echo "Test 40" +iverilog -y .. -o test_hbd -DRATE=40 test_hbd.v  ; ./test_hbd >output ; diff output golden + +echo +echo "Test 30" +iverilog -y .. -o test_hbd -DRATE=30 test_hbd.v  ; ./test_hbd >output ; diff output golden + +echo +echo "Test 25" +iverilog -y .. -o test_hbd -DRATE=25 test_hbd.v  ; ./test_hbd >output ; diff output golden + +echo +echo "Test 20" +iverilog -y .. -o test_hbd -DRATE=20 test_hbd.v  ; ./test_hbd >output ; diff output golden + +echo +echo "Test 19" +iverilog -y .. -o test_hbd -DRATE=19 test_hbd.v  ; ./test_hbd >output ; diff output golden + +echo +echo "Test 18" +iverilog -y .. -o test_hbd -DRATE=18 test_hbd.v  ; ./test_hbd >output ; diff output golden + +echo +echo "Test 17" +iverilog -y .. -o test_hbd -DRATE=17 test_hbd.v  ; ./test_hbd >output ; diff output golden + +echo +echo "Test 16" +iverilog -y .. -o test_hbd -DRATE=16 test_hbd.v  ; ./test_hbd >output ; diff output golden + +echo +echo "Test 15" +iverilog -y .. -o test_hbd -DRATE=15 test_hbd.v  ; ./test_hbd >output ; diff output golden + +echo +echo "Test 14" +iverilog -y .. -o test_hbd -DRATE=14 test_hbd.v  ; ./test_hbd >output ; diff output golden + +echo +echo "Test 13" +iverilog -y .. -o test_hbd -DRATE=13 test_hbd.v  ; ./test_hbd >output ; diff output golden + +echo +echo "Test 12" +iverilog -y .. -o test_hbd -DRATE=12 test_hbd.v  ; ./test_hbd >output ; diff output golden + +echo +echo "Test 11" +iverilog -y .. -o test_hbd -DRATE=11 test_hbd.v  ; ./test_hbd >output ; diff output golden + +echo +echo "Test 10" +iverilog -y .. -o test_hbd -DRATE=10 test_hbd.v  ; ./test_hbd >output ; diff output golden + +echo +echo "Test 9" +iverilog -y .. -o test_hbd -DRATE=9 test_hbd.v  ; ./test_hbd >output ; diff output golden + +echo +echo "Test 8" +iverilog -y .. -o test_hbd -DRATE=8 test_hbd.v  ; ./test_hbd >output ; diff output golden + +echo +echo "Test 7" +iverilog -y .. -o test_hbd -DRATE=7 test_hbd.v  ; ./test_hbd >output ; diff output golden + +echo +echo "Test 6" +iverilog -y .. -o test_hbd -DRATE=6 test_hbd.v  ; ./test_hbd >output ; diff output golden + +echo +echo "Test 5" +iverilog -y .. -o test_hbd -DRATE=5 test_hbd.v  ; ./test_hbd >output ; diff output golden + +echo +echo "Test 4" +iverilog -y .. -o test_hbd -DRATE=4 test_hbd.v  ; ./test_hbd >output ; diff output golden + +echo +echo "Test 3" +iverilog -y .. -o test_hbd -DRATE=3 test_hbd.v  ; ./test_hbd >output ; diff output golden diff --git a/fpga/usrp1/sdr_lib/hb/hbd_tb/run_hbd b/fpga/usrp1/sdr_lib/hb/hbd_tb/run_hbd new file mode 100755 index 000000000..b8aec7574 --- /dev/null +++ b/fpga/usrp1/sdr_lib/hb/hbd_tb/run_hbd @@ -0,0 +1,4 @@ +#!/bin/sh + +iverilog -y .. -o test_hbd test_hbd.v +./test_hbd diff --git a/fpga/usrp1/sdr_lib/hb/hbd_tb/test_hbd.v b/fpga/usrp1/sdr_lib/hb/hbd_tb/test_hbd.v new file mode 100644 index 000000000..01ab5e7e0 --- /dev/null +++ b/fpga/usrp1/sdr_lib/hb/hbd_tb/test_hbd.v @@ -0,0 +1,75 @@ + + +module test_hbd(); + +   reg clock; +   initial clock = 1'b0; +   always #5 clock <= ~clock; + +   reg reset; +   initial reset = 1'b1; +   initial #1000 reset = 1'b0; +    +   initial $dumpfile("test_hbd.vcd"); +   initial $dumpvars(0,test_hbd); + +   reg [15:0] i_in, q_in; +   wire [15:0] i_out, q_out; + +   reg 	       strobe_in; +   wire        strobe_out; +   reg 	       coeff_write; +   reg [15:0]  coeff_data; +   reg [4:0]   coeff_addr; +    +   halfband_decim halfband_decim  +     ( .clock(clock),.reset(reset),.enable(),.strobe_in(strobe_in),.strobe_out(strobe_out), +       .data_in(i_in),.data_out(i_out) ); +    +   always @(posedge strobe_out) +     if(i_out[15]) +       $display("-%d",65536-i_out); +     else +       $display("%d",i_out); + +   initial +     begin +	strobe_in = 1'b0; +	@(negedge reset); +	@(posedge clock); +	while(1) +	  begin +	     strobe_in <= #1 1'b1; +	     @(posedge clock); +	     strobe_in <= #1 1'b0; +	     repeat (`RATE) +	       @(posedge clock); +	  end +     end + +   initial #10000000 $finish;    // Just in case... + +   initial +     begin +	i_in <= #1 16'd0; +	repeat (40) @(posedge strobe_in); +	i_in <= #1 16'd16384; +	@(posedge strobe_in); +	i_in <= #1 16'd0; +	repeat (40) @(posedge strobe_in); +	i_in <= #1 16'd16384; +	@(posedge strobe_in); +	i_in <= #1 16'd0; +	repeat (40) @(posedge strobe_in); +	i_in <= #1 16'd16384; +	repeat (40) @(posedge strobe_in); +	i_in <= #1 16'd0; +	repeat (41) @(posedge strobe_in); +	i_in <= #1 16'd16384; +	repeat (40) @(posedge strobe_in); +	i_in <= #1 16'd0; +	repeat (40) @(posedge strobe_in); +	repeat (7) @(posedge clock); +	$finish; +     end // initial begin +endmodule // test_hb diff --git a/fpga/usrp1/sdr_lib/hb/mac.v b/fpga/usrp1/sdr_lib/hb/mac.v new file mode 100644 index 000000000..5a270bc73 --- /dev/null +++ b/fpga/usrp1/sdr_lib/hb/mac.v @@ -0,0 +1,58 @@ + + +module mac (input clock, input reset, input enable, input clear, +	    input signed [15:0] x, input signed [15:0] y, +	    input [7:0] shift, output [15:0] z ); + +   reg signed [30:0] product; +   reg signed [39:0] z_int; +   reg signed [15:0] z_shift; + +   reg enable_d1; +   always @(posedge clock) +     enable_d1 <= #1 enable; +    +   always @(posedge clock) +     if(reset | clear) +       z_int <= #1 40'd0; +     else if(enable_d1) +       z_int <= #1 z_int + {{9{product[30]}},product}; + +   always @(posedge clock) +     product <= #1 x*y; + +   always @*   // FIXME full case? parallel case? +     case(shift) +       //8'd0 : z_shift <= z_int[39:24]; +       //8'd1 : z_shift <= z_int[38:23]; +       //8'd2 : z_shift <= z_int[37:22]; +       //8'd3 : z_shift <= z_int[36:21]; +       //8'd4 : z_shift <= z_int[35:20]; +       //8'd5 : z_shift <= z_int[34:19]; +       8'd6 : z_shift <= z_int[33:18]; +       8'd7 : z_shift <= z_int[32:17]; +       8'd8 : z_shift <= z_int[31:16]; +       8'd9 : z_shift <= z_int[30:15]; +       8'd10 : z_shift <= z_int[29:14]; +       8'd11 : z_shift <= z_int[28:13]; +       //8'd12 : z_shift <= z_int[27:12]; +       //8'd13 : z_shift <= z_int[26:11]; +       //8'd14 : z_shift <= z_int[25:10]; +       //8'd15 : z_shift <= z_int[24:9]; +       //8'd16 : z_shift <= z_int[23:8]; +       //8'd17 : z_shift <= z_int[22:7]; +       //8'd18 : z_shift <= z_int[21:6]; +       //8'd19 : z_shift <= z_int[20:5]; +       //8'd20 : z_shift <= z_int[19:4]; +       //8'd21 : z_shift <= z_int[18:3]; +       //8'd22 : z_shift <= z_int[17:2]; +       //8'd23 : z_shift <= z_int[16:1]; +       //8'd24 : z_shift <= z_int[15:0]; +       default : z_shift <= z_int[15:0]; +     endcase // case(shift) +    +   // FIXME do we need to saturate? +   //assign z = z_shift; +   assign z = z_int[15:0]; +    +endmodule // mac diff --git a/fpga/usrp1/sdr_lib/hb/mult.v b/fpga/usrp1/sdr_lib/hb/mult.v new file mode 100644 index 000000000..a8d4cb1b7 --- /dev/null +++ b/fpga/usrp1/sdr_lib/hb/mult.v @@ -0,0 +1,16 @@ + + +module mult (input clock, input signed [15:0] x, input signed [15:0] y, output reg signed [30:0] product, +	     input enable_in, output reg enable_out ); + +   always @(posedge clock) +     if(enable_in) +       product <= #1 x*y; +     else +       product <= #1 31'd0; +    +   always @(posedge clock) +     enable_out <= #1 enable_in; +    +endmodule // mult + diff --git a/fpga/usrp1/sdr_lib/hb/ram16_2port.v b/fpga/usrp1/sdr_lib/hb/ram16_2port.v new file mode 100644 index 000000000..e1761a926 --- /dev/null +++ b/fpga/usrp1/sdr_lib/hb/ram16_2port.v @@ -0,0 +1,22 @@ + + +module ram16_2port (input clock, input write,  +		    input [3:0] wr_addr, input [15:0] wr_data, +		    input [3:0] rd_addr1, output reg [15:0] rd_data1, +		    input [3:0] rd_addr2, output reg [15:0] rd_data2); +    +   reg [15:0] 			ram_array [0:31]; +    +   always @(posedge clock) +     rd_data1 <= #1 ram_array[rd_addr1]; +    +   always @(posedge clock) +     rd_data2 <= #1 ram_array[rd_addr2]; +    +   always @(posedge clock) +     if(write) +       ram_array[wr_addr] <= #1 wr_data; +    +endmodule // ram16_2port + + diff --git a/fpga/usrp1/sdr_lib/hb/ram16_2sum.v b/fpga/usrp1/sdr_lib/hb/ram16_2sum.v new file mode 100644 index 000000000..559b06fd5 --- /dev/null +++ b/fpga/usrp1/sdr_lib/hb/ram16_2sum.v @@ -0,0 +1,27 @@ + + +module ram16_2sum (input clock, input write,  +		   input [3:0] wr_addr, input [15:0] wr_data, +		   input [3:0] rd_addr1, input [3:0] rd_addr2, +                   output reg [15:0] sum); +    +   reg signed [15:0] 	  ram_array [0:15]; +   reg signed [15:0] 	  a,b; +   wire signed [16:0] 	  sum_int; +    +   always @(posedge clock) +     if(write) +       ram_array[wr_addr] <= #1 wr_data; +       +   always @(posedge clock) +     begin +	a <= #1 ram_array[rd_addr1]; +	b <= #1 ram_array[rd_addr2]; +     end +    +   assign sum_int = {a[15],a} + {b[15],b}; +    +   always @(posedge clock) +     sum <= #1 sum_int[16:1] + (sum_int[16]&sum_int[0]); +      +endmodule // ram16_2sum diff --git a/fpga/usrp1/sdr_lib/hb/ram32_2sum.v b/fpga/usrp1/sdr_lib/hb/ram32_2sum.v new file mode 100644 index 000000000..d1f55b7d0 --- /dev/null +++ b/fpga/usrp1/sdr_lib/hb/ram32_2sum.v @@ -0,0 +1,22 @@ + + +module ram32_2sum (input clock, input write,  +		   input [4:0] wr_addr, input [15:0] wr_data, +		   input [4:0] rd_addr1, input [4:0] rd_addr2, +		   output reg [15:0] sum); +    +   reg [15:0] 			ram_array [0:31]; +   wire [16:0] 			sum_int; +    +   always @(posedge clock) +     if(write) +       ram_array[wr_addr] <= #1 wr_data; + +   assign sum_int = ram_array[rd_addr1] + ram_array[rd_addr2]; + +   always @(posedge clock) +     sum <= #1 sum_int[16:1] + (sum_int[16]&sum_int[0]); + +    +endmodule // ram32_2sum + | 
