Merge branch 'new_eth' of http://gnuradio.org/git/eb into new_eth
[debian/gnuradio] / usrp2 / fpga / sdr_lib / small_hb_dec.v
1 // Short halfband decimator (intended to be followed by another stage)
2 // Implements impulse responses of the form [A 0 B 0.5 B 0 A]
3 //
4 // These taps designed by halfgen4 from ldoolittle:
5 //   2 * 131072 * halfgen4(.75/8,2)
6 module small_hb_dec
7   #(parameter WIDTH=18)
8     (input clk,
9      input rst,
10      input bypass,
11      input stb_in,
12      input [WIDTH-1:0] data_in,
13      output reg stb_out,
14      output [WIDTH-1:0] data_out);
15
16    reg                  stb_in_d1;
17    reg [WIDTH-1:0]      data_in_d1;
18    always @(posedge clk) stb_in_d1 <= stb_in;
19    always @(posedge clk) data_in_d1 <= data_in;
20    
21    wire                 go;
22    reg                  phase, go_d1, go_d2, go_d3, go_d4;
23    always @(posedge clk)
24      if(rst)
25        phase <= 0;
26      else if(stb_in_d1)
27        phase <= ~phase;
28    assign               go = stb_in_d1 & phase;
29    always @(posedge clk) go_d1 <= go;
30    always @(posedge clk) go_d2 <= go_d1;
31    always @(posedge clk) go_d3 <= go_d2;
32    always @(posedge clk) go_d4 <= go_d3;
33
34    wire [17:0]          coeff_a = -10690;
35    wire [17:0]          coeff_b = 75809;
36    
37    reg [WIDTH-1:0]      d1, d2, d3, d4 , d5, d6;
38    always @(posedge clk)
39      if(stb_in_d1 | rst)
40        begin
41           d1 <= data_in_d1;
42           d2 <= d1;
43           d3 <= d2;
44           d4 <= d3;
45           d5 <= d4;
46           d6 <= d5;
47        end
48
49    reg [17:0] sum_a, sum_b, middle, middle_d1;
50    wire [17:0] sum_a_unreg, sum_b_unreg;
51    add2 #(.WIDTH(18)) add2_a (.in1(data_in_d1),.in2(d6),.sum(sum_a_unreg));
52    add2 #(.WIDTH(18)) add2_b (.in1(d2),.in2(d4),.sum(sum_b_unreg));
53    
54    always @(posedge clk)
55      if(go)
56        begin
57           sum_a <= sum_a_unreg;
58           sum_b <= sum_b_unreg;
59           middle <= d3;
60        end
61
62    always @(posedge clk)
63      if(go_d1)
64        middle_d1 <= middle;
65    
66    wire [17:0] sum = go_d1 ? sum_b : sum_a;
67    wire [17:0] coeff = go_d1 ? coeff_b : coeff_a;
68    wire [35:0]   prod;   
69    MULT18X18S mult(.C(clk), .CE(go_d1 | go_d2), .R(rst), .P(prod), .A(coeff), .B(sum) );
70    
71    reg [35:0]    accum;
72    always @(posedge clk)
73      if(rst)
74        accum <= 0;
75      else if(go_d2)
76        accum <= {middle_d1[17],middle_d1[17],middle_d1,16'd0} + {prod};
77      else if(go_d3)
78        accum <= accum + {prod};
79    
80    wire [17:0]   accum_rnd;
81    round #(.bits_in(36),.bits_out(18)) round_acc (.in(accum),.out(accum_rnd));
82
83    reg [17:0]    final_sum;
84    always @(posedge clk)
85      if(bypass)
86        final_sum <= data_in_d1;
87      else if(go_d4)
88        final_sum <= accum_rnd;
89
90    assign        data_out = final_sum;
91
92    always @(posedge clk)
93      if(rst)
94        stb_out <= 0;
95      else if(bypass)
96        stb_out <= stb_in_d1;
97      else
98        stb_out <= go_d4;
99 endmodule // small_hb_dec