]> git.gag.com Git - debian/gnuradio/blob - usrp2/fpga/sdr_lib/small_hb_dec.v
Synchronize the internal phase of the halfband filters to the
[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 run,
12      input stb_in,
13      input [WIDTH-1:0] data_in,
14      output reg stb_out,
15      output [WIDTH-1:0] data_out);
16
17    reg                  stb_in_d1;
18    reg [WIDTH-1:0]      data_in_d1;
19    always @(posedge clk) stb_in_d1 <= stb_in;
20    always @(posedge clk) data_in_d1 <= data_in;
21    
22    wire                 go;
23    reg                  phase, go_d1, go_d2, go_d3, go_d4;
24    always @(posedge clk)
25      if(rst | ~run)
26        phase <= 0;
27      else if(stb_in_d1)
28        phase <= ~phase;
29    assign               go = stb_in_d1 & phase;
30    always @(posedge clk) 
31      if(rst | ~run)
32        begin
33           go_d1 <= 0;
34           go_d2 <= 0;
35           go_d3 <= 0;
36           go_d4 <= 0;
37        end
38      else
39        begin
40           go_d1 <= go;
41           go_d2 <= go_d1;
42           go_d3 <= go_d2;
43           go_d4 <= go_d3;
44        end
45
46    wire [17:0]          coeff_a = -10690;
47    wire [17:0]          coeff_b = 75809;
48    
49    reg [WIDTH-1:0]      d1, d2, d3, d4 , d5, d6;
50    always @(posedge clk)
51      if(stb_in_d1 | rst)
52        begin
53           d1 <= data_in_d1;
54           d2 <= d1;
55           d3 <= d2;
56           d4 <= d3;
57           d5 <= d4;
58           d6 <= d5;
59        end
60
61    reg [17:0] sum_a, sum_b, middle, middle_d1;
62    wire [17:0] sum_a_unreg, sum_b_unreg;
63    add2 #(.WIDTH(18)) add2_a (.in1(data_in_d1),.in2(d6),.sum(sum_a_unreg));
64    add2 #(.WIDTH(18)) add2_b (.in1(d2),.in2(d4),.sum(sum_b_unreg));
65    
66    always @(posedge clk)
67      if(go)
68        begin
69           sum_a <= sum_a_unreg;
70           sum_b <= sum_b_unreg;
71           middle <= d3;
72        end
73
74    always @(posedge clk)
75      if(go_d1)
76        middle_d1 <= middle;
77    
78    wire [17:0] sum = go_d1 ? sum_b : sum_a;
79    wire [17:0] coeff = go_d1 ? coeff_b : coeff_a;
80    wire [35:0]   prod;   
81    MULT18X18S mult(.C(clk), .CE(go_d1 | go_d2), .R(rst), .P(prod), .A(coeff), .B(sum) );
82    
83    reg [35:0]    accum;
84    always @(posedge clk)
85      if(rst)
86        accum <= 0;
87      else if(go_d2)
88        accum <= {middle_d1[17],middle_d1[17],middle_d1,16'd0} + {prod};
89      else if(go_d3)
90        accum <= accum + {prod};
91    
92    wire [17:0]   accum_rnd;
93    round #(.bits_in(36),.bits_out(18)) round_acc (.in(accum),.out(accum_rnd));
94
95    reg [17:0]    final_sum;
96    always @(posedge clk)
97      if(bypass)
98        final_sum <= data_in_d1;
99      else if(go_d4)
100        final_sum <= accum_rnd;
101
102    assign        data_out = final_sum;
103
104    always @(posedge clk)
105      if(rst)
106        stb_out <= 0;
107      else if(bypass)
108        stb_out <= stb_in_d1;
109      else
110        stb_out <= go_d4;
111 endmodule // small_hb_dec