1//
2// Copyright 2011 Ettus Research LLC
3// Copyright 2018 Ettus Research, a National Instruments Company
4//
5// SPDX-License-Identifier: LGPL-3.0-or-later
6//
7
8
9// First halfband iterpolator
10// Implements impulse responses of the form [A 0 B 0 C .. 0 H 0.5 H 0 .. C 0 B 0 A]
11// Strobe in cannot come faster than every 4th clock cycle,
12// Strobe out cannot come faster than every 2nd clock cycle
13
14// These taps designed by halfgen4 from ldoolittle
15// myfilt = round(2^18 * halfgen4(.7/4,8))
16
17module hb_interp
18  #(parameter IWIDTH=18, OWIDTH=18, ACCWIDTH=24)
19    (input clk,
20     input rst,
21     input bypass,
22     input [7:0] cpo, //  Clocks per output, must be at least 2
23     input stb_in,
24     input [IWIDTH-1:0] data_in,
25     input stb_out,
26     output reg [OWIDTH-1:0] data_out);
27
28   localparam MWIDTH = ACCWIDTH-2;
29   localparam CWIDTH = 18;
30
31   reg [CWIDTH-1:0] coeff1, coeff2;
32   reg [3:0] 	    addr_a, addr_b, addr_c, addr_d, addr_e;
33   wire [IWIDTH-1:0] data_a, data_b, data_c, data_d, data_e, sum1, sum2;
34   wire [35:0] 	     prod1, prod2;
35
36   reg [2:0] 	     phase, phase_d1, phase_d2, phase_d3, phase_d4, phase_d5;
37
38   always @(posedge clk)
39     if(rst)
40       phase <= 0;
41     else
42       if(stb_in)
43	 phase <= 1;
44       else if(phase==4)
45	 phase <= 0;
46       else if(phase!=0)
47	 phase <= phase + 1;
48   always @(posedge clk) phase_d1 <= phase;
49   always @(posedge clk) phase_d2 <= phase_d1;
50   always @(posedge clk) phase_d3 <= phase_d2;
51   always @(posedge clk) phase_d4 <= phase_d3;
52   always @(posedge clk) phase_d5 <= phase_d4;
53
54   srl #(.WIDTH(IWIDTH)) srl_a
55     (.clk(clk),.rst(rst),.write(stb_in),.in(data_in),.addr(addr_a),.out(data_a));
56   srl #(.WIDTH(IWIDTH)) srl_b
57     (.clk(clk),.rst(rst),.write(stb_in),.in(data_in),.addr(addr_b),.out(data_b));
58   srl #(.WIDTH(IWIDTH)) srl_c
59     (.clk(clk),.rst(rst),.write(stb_in),.in(data_in),.addr(addr_c),.out(data_c));
60   srl #(.WIDTH(IWIDTH)) srl_d
61     (.clk(clk),.rst(rst),.write(stb_in),.in(data_in),.addr(addr_d),.out(data_d));
62   srl #(.WIDTH(IWIDTH)) srl_e
63     (.clk(clk),.rst(rst),.write(stb_in),.in(data_in),.addr(addr_e),.out(data_e));
64
65   always @*
66     case(phase)
67       1 : begin addr_a = 0; addr_b = 15; end
68       2 : begin addr_a = 1; addr_b = 14; end
69       3 : begin addr_a = 2; addr_b = 13; end
70       4 : begin addr_a = 3; addr_b = 12; end
71       default : begin addr_a = 0; addr_b = 15; end
72     endcase // case(phase)
73
74   always @*
75     case(phase)
76       1 : begin addr_c = 4; addr_d = 11; end
77       2 : begin addr_c = 5; addr_d = 10; end
78       3 : begin addr_c = 6; addr_d = 9; end
79       4 : begin addr_c = 7; addr_d = 8; end
80       default : begin addr_c = 4; addr_d = 11; end
81     endcase // case(phase)
82
83   always @*
84     case(cpo)
85       2 : addr_e <= 9;
86       3,4,5,6,7,8 : addr_e <= 8;
87       default : addr_e <= 7;  // This case works for 256, which = 0 due to overflow outside this block
88     endcase // case(cpo)
89
90   always @*            // Outer coeffs
91     case(phase_d1)
92       1 : coeff1 = -107;
93       2 : coeff1 = 445;
94       3 : coeff1 = -1271;
95       4 : coeff1 = 2959;
96       default : coeff1 = -107;
97     endcase // case(phase)
98
99   always @*            //  Inner coeffs
100     case(phase_d1)
101       1 : coeff2 = -6107;
102       2 : coeff2 = 11953;
103       3 : coeff2 = -24706;
104       4 : coeff2 = 82359;
105       default : coeff2 = -6107;
106     endcase // case(phase)
107
108   add2_reg /*_and_round_reg*/ #(.WIDTH(IWIDTH)) add1 (.clk(clk),.in1(data_a),.in2(data_b),.sum(sum1));
109   add2_reg /*_and_round_reg*/ #(.WIDTH(IWIDTH)) add2 (.clk(clk),.in1(data_c),.in2(data_d),.sum(sum2));
110   // sum1, sum2 available on phase_d1
111
112   wire do_mult = 1;
113   MULT18X18S mult1(.C(clk), .CE(do_mult), .R(rst), .P(prod1), .A(coeff1), .B(sum1) );
114   MULT18X18S mult2(.C(clk), .CE(do_mult), .R(rst), .P(prod2), .A(coeff2), .B(sum2) );
115   // prod1, prod2 available on phase_d2
116
117   wire [MWIDTH-1:0] sum_of_prod;
118
119   add2_and_round_reg #(.WIDTH(MWIDTH))
120     add3 (.clk(clk),.in1(prod1[35:36-MWIDTH]),.in2(prod2[35:36-MWIDTH]),.sum(sum_of_prod));
121   // sum_of_prod available on phase_d3
122
123   wire [ACCWIDTH-1:0] acc_out;
124
125   wire 	       clear = (phase_d3 == 1);
126   wire 	       do_acc = (phase_d3 != 0);
127
128   acc #(.IWIDTH(MWIDTH),.OWIDTH(ACCWIDTH)) //IJB rst
129     acc (.clk(clk),.clear(rst|clear),.acc(do_acc),.in(sum_of_prod),.out(acc_out));
130   // acc_out available on phase_d4
131
132   wire [ACCWIDTH-6:0] clipped_acc;
133   clip #(.bits_in(ACCWIDTH),.bits_out(ACCWIDTH-5)) final_clip(.in(acc_out),.out(clipped_acc));
134
135   reg [ACCWIDTH-6:0]   clipped_reg;
136   always @(posedge clk)
137     if (rst)
138       clipped_reg <= 0;
139     else  if(phase_d4 == 4)
140       clipped_reg <= clipped_acc;
141   // clipped_reg available on phase_d5
142
143   wire [OWIDTH-1:0]   data_out_round;
144   round #(.bits_in(ACCWIDTH-5),.bits_out(OWIDTH)) final_round (.in(clipped_reg),.out(data_out_round));
145
146   reg 		      odd;
147   always @(posedge clk)
148     if(rst)
149       odd <= 0;
150     else if(stb_in)
151       odd <= 0;
152     else if(stb_out)
153       odd <= 1;
154
155   always @(posedge clk)
156     if (rst)
157       data_out <= 0;
158     else if(bypass)
159       data_out <= data_in;
160     else if(stb_out)
161       if(odd)
162	 data_out <= data_e;
163       else
164	 data_out <= data_out_round;
165
166   // data_out available on phase_d6
167
168endmodule // hb_interp
169