commit-gnuradio
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Commit-gnuradio] r8864 - usrp2/trunk/fpga/sdr_lib


From: matt
Subject: [Commit-gnuradio] r8864 - usrp2/trunk/fpga/sdr_lib
Date: Thu, 10 Jul 2008 19:00:39 -0600 (MDT)

Author: matt
Date: 2008-07-10 19:00:37 -0600 (Thu, 10 Jul 2008)
New Revision: 8864

Added:
   usrp2/trunk/fpga/sdr_lib/hb_interp_tb.v
Modified:
   usrp2/trunk/fpga/sdr_lib/dsp_core_tx.v
   usrp2/trunk/fpga/sdr_lib/hb_interp.v
Log:
believed to be working hb_interp, plus changes to dsp_core_tx to tell it the 
decimation rate


Modified: usrp2/trunk/fpga/sdr_lib/dsp_core_tx.v
===================================================================
--- usrp2/trunk/fpga/sdr_lib/dsp_core_tx.v      2008-07-11 00:33:32 UTC (rev 
8863)
+++ usrp2/trunk/fpga/sdr_lib/dsp_core_tx.v      2008-07-11 01:00:37 UTC (rev 
8864)
@@ -69,11 +69,15 @@
    wire [17:0] i_interp, q_interp;
 
    wire [17:0] hb1_i, hb1_q, hb2_i, hb2_q;
+
+   wire [7:0]  cpo = enable_hb2 ? ({interp_rate,1'b0}) : interp_rate;
+   // Note that max CIC rate is 128, which would give an overflow on cpo if 
enable_hb2 is true,
+   //   but the default case inside hb_interp handles this
    
-   hb_interp #(.WIDTH(18)) hb_interp_i
-     
(.clk(clk),.rst(rst),.bypass(~enable_hb1),.stb_in(strobe_hb1),.data_in(bb_i),.stb_out(strobe_hb2),.data_out(hb1_i));
-   hb_interp #(.WIDTH(18)) hb_interp_q
-     
(.clk(clk),.rst(rst),.bypass(~enable_hb1),.stb_in(strobe_hb1),.data_in(bb_q),.stb_out(strobe_hb2),.data_out(hb1_q));
+   hb_interp #(.IWIDTH(18),.OWIDTH(18),.ACCWIDTH(24)) hb_interp_i
+     
(.clk(clk),.rst(rst),.bypass(~enable_hb1),.cpo(cpo),.stb_in(strobe_hb1),.data_in(bb_i),.stb_out(strobe_hb2),.data_out(hb1_i));
+   hb_interp #(.IWIDTH(18),.OWIDTH(18),.ACCWIDTH(24)) hb_interp_q
+     
(.clk(clk),.rst(rst),.bypass(~enable_hb1),.cpo(cpo),.stb_in(strobe_hb1),.data_in(bb_q),.stb_out(strobe_hb2),.data_out(hb1_q));
    
    small_hb_int #(.WIDTH(18)) small_hb_interp_i
      
(.clk(clk),.rst(rst),.bypass(~enable_hb2),.stb_in(strobe_hb2),.data_in(hb1_i),

Modified: usrp2/trunk/fpga/sdr_lib/hb_interp.v
===================================================================
--- usrp2/trunk/fpga/sdr_lib/hb_interp.v        2008-07-11 00:33:32 UTC (rev 
8863)
+++ usrp2/trunk/fpga/sdr_lib/hb_interp.v        2008-07-11 01:00:37 UTC (rev 
8864)
@@ -1,22 +1,157 @@
-// Short halfband decimator (intended to be followed by another stage)
-// Implements impulse responses of the form [A 0 B 0.5 B 0 A]
-//
-// These taps designed by halfgen4 from ldoolittle:
-//   2 * 131072 * halfgen4(.75/8,2)
+// First halfband iterpolator 
+// Implements impulse responses of the form [A 0 B 0 C .. 0 H 0.5 H 0 .. C 0 B 
0 A]
+// Strobe in cannot come faster than every 4th clock cycle, 
+// Strobe out cannot come faster than every 2nd clock cycle
+
+// These taps designed by halfgen4 from ldoolittle
+// myfilt = round(2^18 * halfgen4(.7/4,8))
+
 module hb_interp
-  #(parameter WIDTH=18)
+  #(parameter IWIDTH=18, OWIDTH=18, ACCWIDTH=24)
     (input clk,
      input rst,
      input bypass,
+     input [7:0] cpo, //  Clocks per output, must be at least 2
      input stb_in,
-     input [WIDTH-1:0] data_in,
+     input [IWIDTH-1:0] data_in,
      input stb_out,
-     output reg [WIDTH-1:0] data_out);
+     output reg [OWIDTH-1:0] data_out);
 
+   localparam MWIDTH = ACCWIDTH-2;
+   localparam CWIDTH = 18;
+
+   reg [CWIDTH-1:0] coeff1, coeff2;
+   reg [3:0]       addr_a, addr_b, addr_c, addr_d, addr_e;
+   wire [IWIDTH-1:0] data_a, data_b, data_c, data_d, data_e, sum1, sum2;
+   wire [35:0]              prod1, prod2;
+
+   reg [2:0]        phase, phase_d1, phase_d2, phase_d3, phase_d4, phase_d5;
+
    always @(posedge clk)
+     if(rst)
+       phase <= 0;
+     else
+       if(stb_in)
+        phase <= 1;
+       else if(phase==4)
+        phase <= 0;
+       else if(phase!=0)
+        phase <= phase + 1;
+   always @(posedge clk) phase_d1 <= phase;
+   always @(posedge clk) phase_d2 <= phase_d1;
+   always @(posedge clk) phase_d3 <= phase_d2;
+   always @(posedge clk) phase_d4 <= phase_d3;
+   always @(posedge clk) phase_d5 <= phase_d4;     
+   
+   srl #(.WIDTH(IWIDTH)) srl_a
+     (.clk(clk),.write(stb_in),.in(data_in),.addr(addr_a),.out(data_a));
+   srl #(.WIDTH(IWIDTH)) srl_b
+     (.clk(clk),.write(stb_in),.in(data_in),.addr(addr_b),.out(data_b));
+   srl #(.WIDTH(IWIDTH)) srl_c
+     (.clk(clk),.write(stb_in),.in(data_in),.addr(addr_c),.out(data_c));
+   srl #(.WIDTH(IWIDTH)) srl_d
+     (.clk(clk),.write(stb_in),.in(data_in),.addr(addr_d),.out(data_d));
+   srl #(.WIDTH(IWIDTH)) srl_e
+     (.clk(clk),.write(stb_in),.in(data_in),.addr(addr_e),.out(data_e));
+
+   always @*
+     case(phase)
+       1 : begin addr_a = 0; addr_b = 15; end
+       2 : begin addr_a = 1; addr_b = 14; end
+       3 : begin addr_a = 2; addr_b = 13; end
+       4 : begin addr_a = 3; addr_b = 12; end
+       default : begin addr_a = 0; addr_b = 15; end
+     endcase // case(phase)
+
+   always @*
+     case(phase)
+       1 : begin addr_c = 4; addr_d = 11; end
+       2 : begin addr_c = 5; addr_d = 10; end
+       3 : begin addr_c = 6; addr_d = 9; end
+       4 : begin addr_c = 7; addr_d = 8; end
+       default : begin addr_c = 4; addr_d = 11; end
+     endcase // case(phase)
+
+   always @*
+     case(cpo)
+       2 : addr_e <= 9;
+       3,4,5,6,7,8 : addr_e <= 8;
+       default : addr_e <= 7;  // This case works for 256, which = 0 due to 
overflow outside this block
+     endcase // case(cpo)
+   
+   always @*            // Outer coeffs
+     case(phase_d1)
+       1 : coeff1 = -107;
+       2 : coeff1 = 445;
+       3 : coeff1 = -1271;
+       4 : coeff1 = 2959;
+       default : coeff1 = -107;
+     endcase // case(phase)
+   
+   always @*            //  Inner coeffs
+     case(phase_d1)
+       1 : coeff2 = -6107;
+       2 : coeff2 = 11953;
+       3 : coeff2 = -24706;
+       4 : coeff2 = 82359;
+       default : coeff2 = -6107;
+     endcase // case(phase)
+
+   add2_reg /*_and_round_reg*/ #(.WIDTH(IWIDTH)) add1 
(.clk(clk),.in1(data_a),.in2(data_b),.sum(sum1));
+   add2_reg /*_and_round_reg*/ #(.WIDTH(IWIDTH)) add2 
(.clk(clk),.in1(data_c),.in2(data_d),.sum(sum2));
+   // sum1, sum2 available on phase_d1
+
+   wire do_mult = 1;
+   MULT18X18S mult1(.C(clk), .CE(do_mult), .R(rst), .P(prod1), .A(coeff1), 
.B(sum1) );
+   MULT18X18S mult2(.C(clk), .CE(do_mult), .R(rst), .P(prod2), .A(coeff2), 
.B(sum2) );
+   // prod1, prod2 available on phase_d2
+   
+   wire [MWIDTH-1:0] sum_of_prod;
+   
+   add2_and_round_reg #(.WIDTH(MWIDTH)) 
+     add3 
(.clk(clk),.in1(prod1[35:36-MWIDTH]),.in2(prod2[35:36-MWIDTH]),.sum(sum_of_prod));
+   // sum_of_prod available on phase_d3
+   
+   wire [ACCWIDTH-1:0] acc_out;
+   wire [OWIDTH-1:0]   acc_round;
+
+   wire               clear = (phase_d3 == 1);
+   wire               do_acc = (phase_d3 != 0);
+   
+   acc #(.IWIDTH(MWIDTH),.OWIDTH(ACCWIDTH)) 
+     acc 
(.clk(clk),.clear(clear),.acc(do_acc),.in(sum_of_prod),.out(acc_out));   
+   // acc_out available on phase_d4
+   
+   wire [ACCWIDTH-6:0] clipped_acc;
+   clip #(.bits_in(ACCWIDTH),.bits_out(ACCWIDTH-5)) 
final_clip(.in(acc_out),.out(clipped_acc));
+   
+   reg [ACCWIDTH-6:0]   clipped_reg;
+   always @(posedge clk)
+     if(phase_d4 == 4)
+       clipped_reg <= clipped_acc;
+   // clipped_reg available on phase_d5
+   
+   wire [OWIDTH-1:0]   data_out_round;
+   round #(.bits_in(ACCWIDTH-5),.bits_out(OWIDTH)) final_round 
(.in(clipped_reg),.out(data_out_round));
+
+   reg                       odd;
+   always @(posedge clk)
+     if(rst)
+       odd <= 0;
+     else if(stb_in)
+       odd <= 0;
+     else if(stb_out)
+       odd <= 1;
+
+   always @(posedge clk)
      if(bypass)
        data_out <= data_in;
-     else
-       data_out <= 0;
+     else if(stb_out)
+       if(odd)
+        data_out <= data_e;
+       else
+        data_out <= data_out_round;
 
+   // data_out available on phase_d6
+   
 endmodule // hb_interp

Added: usrp2/trunk/fpga/sdr_lib/hb_interp_tb.v
===================================================================
--- usrp2/trunk/fpga/sdr_lib/hb_interp_tb.v                             (rev 0)
+++ usrp2/trunk/fpga/sdr_lib/hb_interp_tb.v     2008-07-11 01:00:37 UTC (rev 
8864)
@@ -0,0 +1,132 @@
+module hb_interp_tb( ) ;
+   
+   // Parameters for instantiation
+   parameter               clocks  = 8'd2 ; // Number of clocks per output
+   parameter               decim   = 1 ; // Sets the filter to decimate
+   parameter               rate    = 2 ; // Sets the decimation rate
+   
+   reg                     clock ;
+   reg                     reset ;
+   reg                     enable ;
+   wire                   strobe_in ;
+   reg                            signed  [17:0]  data_in ;
+   wire                    strobe_out ;
+   wire                   signed  [17:0]  data_out ;
+   
+   initial
+     begin
+       $dumpfile("hb_interp_tb.vcd");
+       $dumpvars(0,hb_interp_tb);
+     end
+   
+   // Setup the clock
+   initial clock = 1'b0 ;
+   always #5 clock <= ~clock ;
+   
+   // Come out of reset after a while
+   initial reset = 1'b1 ;
+   initial #1000 reset = 1'b0 ;
+
+   always @(posedge clock)
+     enable <= ~reset;
+   
+   // Instantiate UUT
+   /*
+    halfband_ideal 
+      #(
+        .decim      ( decim         ),
+        .rate       ( rate          )
+      ) uut(
+        .clock      ( clock         ),
+        .reset      ( reset         ),
+        .enable     ( enable        ),
+        .strobe_in  ( strobe_in     ),
+        .data_in    ( data_in       ),
+        .strobe_out ( strobe_out    ),
+        .data_out   ( data_out      )
+      ) ;
+    */
+
+   cic_strober #(.WIDTH(8))
+     out_strober(.clock(clock),.reset(reset),.enable(enable),.rate(clocks),
+                .strobe_fast(1),.strobe_slow(strobe_out) );
+   
+   cic_strober #(.WIDTH(8))
+     in_strober(.clock(clock),.reset(reset),.enable(enable),.rate(2),
+               .strobe_fast(strobe_out),.strobe_slow(strobe_in) );
+   
+   hb_interp #() uut
+     
(.clk(clock),.rst(reset),.bypass(0),.cpo(clocks),.stb_in(strobe_in),.data_in(data_in),
+      .stb_out(strobe_out),/* .output_rate(clocks), */ .data_out(data_out) );
+   
+   integer i, ri, ro, infile, outfile ;
+   
+   always @(posedge clock)
+     begin
+       if(strobe_out)
+         $display(data_out);
+     end
+   
+   // Setup file IO
+   initial begin
+      infile = $fopen("input.dat","r") ;
+      outfile = $fopen("output.dat","r") ;
+      $timeformat(-9, 2, " ns", 10) ;
+   end
+   
+   reg                 endofsim ;
+   reg                        signed  [17:0]  compare ;
+   integer             noe ;
+   initial             noe = 0 ;
+   
+   initial begin
+      // Initialize inputs
+      data_in <= 18'd0 ;
+      
+      // Wait for reset to go away
+      @(negedge reset) #0 ;
+      
+      // While we're still simulating ...
+      while( !endofsim ) begin
+        
+         // Write the input from the file or 0 if EOF...
+         @( negedge clock ) begin
+            if(strobe_in)
+              if( !$feof(infile) )
+                ri <= #1 $fscanf( infile, "%d", data_in ) ;
+              else
+                data_in <= 18'd0 ;
+         end
+      end
+      
+      // Print out the number of errors that occured
+      if( noe )
+        $display( "FAILED: %d errors during simulation", noe ) ;
+      else
+        $display( "PASSED: Simulation successful" ) ;
+      
+      $finish ;
+   end
+   
+   // Output comparison of simulated values versus known good values
+   always @ (posedge clock) begin
+      if( reset )
+        endofsim <= 1'b0 ;
+      else begin
+         if( !$feof(outfile) ) begin
+            if( strobe_out ) begin
+               ro = $fscanf( outfile, "%d\n", compare ) ;
+               if( compare != data_out ) begin
+                  //$display( "%t: %d != %d", $realtime, data_out, compare ) ;
+                  noe = noe + 1 ;
+               end
+            end
+         end else begin
+            // Signal end of simulation when no more outputs
+           if($feof(infile))
+              endofsim <= 1'b1 ;
+         end
+      end
+   end     
+   
+endmodule // small_hb_int_tb





reply via email to

[Prev in Thread] Current Thread [Next in Thread]