updated wiki url
[debian/gnuradio] / usrp2 / fpga / sdr_lib / hb_dec.v
1 // Final halfband decimator 
2 // Implements impulse responses of the form [A 0 B 0 C .. 0 H 0.5 H 0 .. C 0 B 0 A]
3 // Strobe in cannot come faster than every 2nd clock cycle
4 // These taps designed by halfgen4 from ldoolittle
5 // myfilt = round(2^18 * halfgen4(.7/4,8))
6
7 module hb_dec
8   #(parameter IWIDTH=18, OWIDTH=18, CWIDTH=18, ACCWIDTH=24)
9     (input clk,
10      input rst,
11      input bypass,
12      input run,
13      input [8:0] cpi,  // Clocks per input -- equal to the decimation ratio ahead of this block
14      input stb_in,
15      input [IWIDTH-1:0] data_in,
16      output reg stb_out,
17      output reg [OWIDTH-1:0] data_out);
18
19    // Control
20    reg [3:0]            addr_odd_a, addr_odd_b, addr_odd_c, addr_odd_d;
21    wire                 write_odd, write_even, do_mult;
22    reg                  odd;
23    reg [2:0]            phase, phase_d1;
24    reg                  stb_out_int;
25    wire                 clear, do_acc;
26    assign               do_mult = 1;
27    
28    always @(posedge clk)
29      if(rst | ~run)
30        odd <= 0;
31      else if(stb_in)
32        odd <= ~odd;
33
34    assign               write_odd = stb_in & odd;
35    assign               write_even = stb_in & ~odd;
36
37    always @(posedge clk)
38      if(rst | ~run)
39        phase <= 0;
40      else if(stb_in & odd)
41        phase <= 1;
42      else if(phase == 4)
43        phase <= 0;
44      else if(phase != 0)
45        phase <= phase + 1;
46
47    always @(posedge clk)
48      phase_d1 <= phase;
49    
50    reg [15:0]           stb_out_pre;
51    always @(posedge clk)
52      if(rst)
53        stb_out_pre <= 0;
54      else
55        stb_out_pre <= {stb_out_pre[14:0],(stb_in & odd)};
56
57    always @*
58      case(phase)
59        1 : begin addr_odd_a = 0; addr_odd_b = 15; end
60        2 : begin addr_odd_a = 1; addr_odd_b = 14; end
61        3 : begin addr_odd_a = 2; addr_odd_b = 13; end
62        4 : begin addr_odd_a = 3; addr_odd_b = 12; end
63        default : begin addr_odd_a = 0; addr_odd_b = 15; end
64      endcase // case(phase)
65
66    always @*
67      case(phase)
68        1 : begin addr_odd_c = 4; addr_odd_d = 11; end
69        2 : begin addr_odd_c = 5; addr_odd_d = 10; end
70        3 : begin addr_odd_c = 6; addr_odd_d = 9; end
71        4 : begin addr_odd_c = 7; addr_odd_d = 8; end
72        default : begin addr_odd_c = 4; addr_odd_d = 11; end
73      endcase // case(phase)
74
75    assign do_acc = |stb_out_pre[6:3];
76    assign clear = stb_out_pre[3];
77    
78    // Data
79    wire [IWIDTH-1:0] data_odd_a, data_odd_b, data_odd_c, data_odd_d;
80    wire [IWIDTH-1:0] sum1, sum2;        
81    wire [OWIDTH-1:0] final_sum;
82    reg [CWIDTH-1:0]  coeff1, coeff2;
83    wire [35:0]       prod1, prod2;
84
85    always @*            // Outer coeffs
86      case(phase_d1)
87        1 : coeff1 = -107;
88        2 : coeff1 = 445;
89        3 : coeff1 = -1271;
90        4 : coeff1 = 2959;
91        default : coeff1 = -107;
92      endcase // case(phase)
93    
94    always @*            //  Inner coeffs
95      case(phase_d1)
96        1 : coeff2 = -6107;
97        2 : coeff2 = 11953;
98        3 : coeff2 = -24706;
99        4 : coeff2 = 82359;
100        default : coeff2 = -6107;
101      endcase // case(phase)
102    
103    srl #(.WIDTH(IWIDTH)) srl_odd_a
104      (.clk(clk),.write(write_odd),.in(data_in),.addr(addr_odd_a),.out(data_odd_a));
105    srl #(.WIDTH(IWIDTH)) srl_odd_b
106      (.clk(clk),.write(write_odd),.in(data_in),.addr(addr_odd_b),.out(data_odd_b));
107    srl #(.WIDTH(IWIDTH)) srl_odd_c
108      (.clk(clk),.write(write_odd),.in(data_in),.addr(addr_odd_c),.out(data_odd_c));
109    srl #(.WIDTH(IWIDTH)) srl_odd_d
110      (.clk(clk),.write(write_odd),.in(data_in),.addr(addr_odd_d),.out(data_odd_d));
111
112    add2_reg /*_and_round_reg*/ #(.WIDTH(IWIDTH)) add1 (.clk(clk),.in1(data_odd_a),.in2(data_odd_b),.sum(sum1));
113    add2_reg /*_and_round_reg*/ #(.WIDTH(IWIDTH)) add2 (.clk(clk),.in1(data_odd_c),.in2(data_odd_d),.sum(sum2));
114
115    wire [IWIDTH-1:0] data_even;
116    reg [3:0]         addr_even;
117
118    always @(posedge clk)
119      case(cpi)
120        //  1 is an error
121        2 : addr_even <= 9;  // Maximum speed (overall decim by 4)
122        3, 4, 5, 6, 7 : addr_even <= 8;
123        default : addr_even <= 7;
124      endcase // case(cpi)
125    
126    srl #(.WIDTH(IWIDTH)) srl_even
127      (.clk(clk),.write(write_even),.in(data_in),.addr(addr_even),.out(data_even));
128
129    localparam           MWIDTH = ACCWIDTH-2;   
130    wire [MWIDTH-1:0]    sum_of_prod;
131
132    MULT18X18S mult1(.C(clk), .CE(do_mult), .R(rst), .P(prod1), .A(coeff1), .B(sum1) );
133    MULT18X18S mult2(.C(clk), .CE(do_mult), .R(rst), .P(prod2), .A(coeff2), .B(sum2) );
134    add2_and_round_reg #(.WIDTH(MWIDTH)) 
135      add3 (.clk(clk),.in1(prod1[35:36-MWIDTH]),.in2(prod2[35:36-MWIDTH]),.sum(sum_of_prod));
136
137    wire [ACCWIDTH-1:0]  acc_out;
138    
139    acc #(.IWIDTH(MWIDTH),.OWIDTH(ACCWIDTH)) 
140      acc (.clk(clk),.clear(clear),.acc(do_acc),.in(sum_of_prod),.out(acc_out));
141
142    localparam           SHIFT_FACTOR = ACCWIDTH-IWIDTH-5;
143    wire [ACCWIDTH-1:0]  data_even_signext;
144    wire [ACCWIDTH:0]    final_sum_unrounded;
145
146    sign_extend #(.bits_in(IWIDTH),.bits_out(ACCWIDTH-SHIFT_FACTOR))
147      signext_data_even (.in(data_even),.out(data_even_signext[ACCWIDTH-1:SHIFT_FACTOR]));
148    assign               data_even_signext[SHIFT_FACTOR-1:0] = 0;
149    
150    add2_reg /* add2_and_round_reg */ #(.WIDTH(ACCWIDTH+1)) 
151      final_adder (.clk(clk), .in1({acc_out,1'b0}), .in2({data_even_signext,1'b0}), .sum(final_sum_unrounded));
152
153    round_reg #(.bits_in(ACCWIDTH-4),.bits_out(OWIDTH))
154      final_round (.clk(clk),.in(final_sum_unrounded[ACCWIDTH-5:0]),.out(final_sum));
155
156    // Output
157    always @(posedge clk)
158      if(bypass)
159        data_out <= data_in;
160      else if(stb_out_pre[9])
161        data_out <= final_sum;
162
163    always @(posedge clk)
164      if(rst)
165        stb_out <= 0;
166      else if(bypass)
167        stb_out <= stb_in;
168      else
169        stb_out <= stb_out_pre[9];
170  
171 endmodule // hb_dec