1 |
7 |
Juzujka |
module cic_d
|
2 |
|
|
/*********************************************************************************************/
|
3 |
|
|
#(
|
4 |
|
|
parameter INP_DW = 18, ///< input data width
|
5 |
|
|
parameter OUT_DW = 18, ///< output data width
|
6 |
|
|
parameter CIC_R = 100, ///< decimation ratio
|
7 |
|
|
parameter CIC_N = 7, ///< number of stages
|
8 |
|
|
parameter CIC_M = 1, ///< delay in comb
|
9 |
|
|
parameter SMALL_FOOTPRINT = 1 ///< reduced registers usage, f_clk / (f_samp/CIC_R) > CIC_N required
|
10 |
|
|
)
|
11 |
|
|
/*********************************************************************************************/
|
12 |
|
|
(
|
13 |
|
|
input clk,
|
14 |
|
|
input reset_n,
|
15 |
|
|
input clear,
|
16 |
|
|
input wire signed [INP_DW-1:0] inp_samp_data,
|
17 |
|
|
input inp_samp_str,
|
18 |
|
|
output wire signed [OUT_DW-1:0] out_samp_data,
|
19 |
|
|
output out_samp_str
|
20 |
|
|
);
|
21 |
|
|
/*********************************************************************************************/
|
22 |
|
|
`include "cic_functions.vh"
|
23 |
|
|
/*********************************************************************************************/
|
24 |
|
|
localparam B_max = clog2_l((CIC_R * CIC_M) ** CIC_N) + INP_DW - 1;
|
25 |
|
|
/*********************************************************************************************/
|
26 |
|
|
|
27 |
|
|
genvar i;
|
28 |
|
|
generate
|
29 |
|
|
for (i = 0; i < CIC_N; i = i + 1) begin : int_stage
|
30 |
|
|
localparam B_jm1 = B_calc(i , CIC_N, CIC_R, CIC_M, INP_DW, OUT_DW);
|
31 |
|
|
localparam B_j = B_calc(i + 1, CIC_N, CIC_R, CIC_M, INP_DW, OUT_DW);
|
32 |
|
|
localparam F_sq_j = 0;
|
33 |
|
|
localparam idw_cur = B_max - B_jm1 + 1;
|
34 |
|
|
localparam odw_cur = B_max - B_j + 1;
|
35 |
|
|
localparam B_dw_prev = (i != 0) ? B_max - B_jm1 + 1 : 0;
|
36 |
|
|
wire signed [idw_cur - 1 : 0] int_in;
|
37 |
|
|
if ( i == 0 ) assign int_in = inp_samp_data;
|
38 |
|
|
else assign int_in = int_stage[i - 1].int_out;
|
39 |
|
|
wire signed [idw_cur - 1 : 0] int_inst_out;
|
40 |
|
|
wire signed [odw_cur - 1 : 0] int_out;
|
41 |
|
|
assign int_out = int_inst_out[idw_cur - 1 -: odw_cur];
|
42 |
|
|
integrator #(
|
43 |
|
|
idw_cur,
|
44 |
|
|
idw_cur
|
45 |
|
|
)
|
46 |
|
|
int_inst(
|
47 |
|
|
.clk (clk),
|
48 |
|
|
.reset_n (reset_n),
|
49 |
|
|
.clear (clear) ,
|
50 |
|
|
.inp_samp_data (int_in),
|
51 |
|
|
.inp_samp_str (inp_samp_str),
|
52 |
|
|
.out_samp_data (int_inst_out)
|
53 |
|
|
);
|
54 |
|
|
initial begin
|
55 |
|
|
//$display("i:%d integ idw=%2d odw=%2d B(%2d, %3d, %2d, %2d, %2d, %2d)=%2d, Bj-1=%2d, F_sq=%8d", i, idw_cur, odw_cur, i + 1, CIC_R, CIC_M, CIC_N, INP_DW, OUT_DW, B_j, B_jm1, F_sq_j);
|
56 |
|
|
$display("i:%d integ idw=%d ", i, idw_cur);
|
57 |
|
|
end
|
58 |
|
|
end
|
59 |
|
|
endgenerate
|
60 |
|
|
/*********************************************************************************************/
|
61 |
|
|
localparam B_m = B_calc(CIC_N, CIC_N, CIC_R, CIC_M, INP_DW, OUT_DW);
|
62 |
|
|
localparam ds_dw = B_max - B_m + 1;
|
63 |
|
|
wire signed [ds_dw - 1 : 0] ds_out_samp_data;
|
64 |
|
|
wire ds_out_samp_str;
|
65 |
|
|
/*********************************************************************************************/
|
66 |
|
|
initial begin
|
67 |
|
|
//$display("i downsamp dw %d , int_stage[%2d].dw_out = %2d", ds_dw, CIC_N - 1, int_stage[CIC_N - 1].odw_cur);
|
68 |
|
|
$display("i downsamp dw %d", ds_dw);
|
69 |
|
|
end
|
70 |
|
|
downsampler #(
|
71 |
|
|
.DATA_WIDTH_INP (ds_dw),
|
72 |
|
|
.CIC_R (CIC_R)
|
73 |
|
|
)
|
74 |
|
|
downsampler_inst
|
75 |
|
|
(
|
76 |
|
|
.clk (clk),
|
77 |
|
|
.reset_n (reset_n),
|
78 |
|
|
.clear (clear),
|
79 |
|
|
.inp_samp_data (int_stage[CIC_N - 1].int_out),
|
80 |
|
|
.inp_samp_str (inp_samp_str),
|
81 |
|
|
.out_samp_data (ds_out_samp_data),
|
82 |
|
|
.out_samp_str (ds_out_samp_str)
|
83 |
|
|
);
|
84 |
|
|
/*********************************************************************************************/
|
85 |
|
|
genvar j;
|
86 |
|
|
wire comb_chain_out_str;
|
87 |
|
|
reg [CIC_N : 0] comb_inp_str_d;
|
88 |
|
|
generate
|
89 |
|
|
wire summ_rdy_str;
|
90 |
|
|
if (SMALL_FOOTPRINT != 0) begin
|
91 |
|
|
always @(negedge reset_n or posedge clk)
|
92 |
|
|
if (~reset_n) comb_inp_str_d <= '0;
|
93 |
|
|
else if (clear) comb_inp_str_d <= '0;
|
94 |
|
|
else comb_inp_str_d <= {comb_inp_str_d[CIC_N - 1 : 0], ds_out_samp_str};
|
95 |
|
|
end
|
96 |
|
|
|
97 |
|
|
if (SMALL_FOOTPRINT == 0) assign summ_rdy_str = '0;
|
98 |
|
|
else assign summ_rdy_str = comb_inp_str_d[CIC_N];
|
99 |
|
|
|
100 |
|
|
|
101 |
|
|
for (j = 0; j < CIC_N; j = j + 1) begin : comb_stage
|
102 |
|
|
localparam B_m_j_m1 = B_calc(CIC_N + j , CIC_N, CIC_R, CIC_M, INP_DW, OUT_DW);
|
103 |
|
|
localparam B_m_j = B_calc(CIC_N + j + 1, CIC_N, CIC_R, CIC_M, INP_DW, OUT_DW);
|
104 |
|
|
localparam F_sq_j = 1;
|
105 |
|
|
localparam idw_cur = B_max - B_m_j_m1 + 1;
|
106 |
|
|
localparam odw_cur = B_max - B_m_j + 1;
|
107 |
|
|
wire signed [idw_cur - 1 : 0] comb_in;
|
108 |
|
|
wire signed [idw_cur - 1 : 0] comb_inst_out;
|
109 |
|
|
wire signed [odw_cur - 1 : 0] comb_out;
|
110 |
|
|
wire comb_dv;
|
111 |
|
|
if (j == 0) assign comb_in = ds_out_samp_data;
|
112 |
|
|
else assign comb_in = comb_stage[j - 1].comb_out;
|
113 |
|
|
assign comb_out = comb_inst_out[idw_cur - 1 -: odw_cur];
|
114 |
|
|
comb #(
|
115 |
|
|
.SAMP_WIDTH (idw_cur),
|
116 |
|
|
.CIC_M (CIC_M),
|
117 |
|
|
.SMALL_FOOTPRINT(SMALL_FOOTPRINT)
|
118 |
|
|
)
|
119 |
|
|
comb_inst(
|
120 |
|
|
.clk (clk),
|
121 |
|
|
.reset_n (reset_n),
|
122 |
|
|
.clear (clear),
|
123 |
|
|
.samp_inp_str (ds_out_samp_str),
|
124 |
|
|
.samp_inp_data (comb_in),
|
125 |
|
|
.summ_rdy_str (summ_rdy_str),
|
126 |
|
|
.samp_out_str (comb_dv),
|
127 |
|
|
.samp_out_data (comb_inst_out)
|
128 |
|
|
);
|
129 |
|
|
if (SMALL_FOOTPRINT == 0) assign comb_chain_out_str = comb_stage[CIC_N - 1].comb_dv;
|
130 |
|
|
else assign comb_chain_out_str = comb_inp_str_d[CIC_N - 1];
|
131 |
|
|
initial begin
|
132 |
|
|
//$display("i:%d comb idw=%2d odw=%2d B(%2d, %3d, %2d, %2d, %2d, %2d)=%2d, ln(F_sq)=%4d, F_sq=%8d", j, idw_cur, odw_cur, CIC_N + j + 1, CIC_R, CIC_M, CIC_N, INP_DW, OUT_DW, B_m_j, $ln(F_sq_j), F_sq_j);
|
133 |
|
|
//if (j != 0) $display("odw_prev=%2d, comb_stage[j - 1].odw_cur=%2d", odw_prev, comb_stage[j - 1].odw_cur);
|
134 |
|
|
$display("i:%d comb idw=%d", j, idw_cur);
|
135 |
|
|
end
|
136 |
|
|
end
|
137 |
|
|
endgenerate
|
138 |
|
|
/*********************************************************************************************/
|
139 |
|
|
localparam dw_out = B_max - B_calc(2 * CIC_N, CIC_N, CIC_R, CIC_M, INP_DW, OUT_DW) + 1;
|
140 |
|
|
reg signed [OUT_DW-1:0] comb_out_samp_data_reg;
|
141 |
|
|
reg comb_out_samp_str_reg;
|
142 |
|
|
|
143 |
|
|
always @(negedge reset_n or posedge clk)
|
144 |
|
|
begin
|
145 |
|
|
if (~reset_n) comb_out_samp_data_reg <= '0;
|
146 |
|
|
else if (comb_chain_out_str) comb_out_samp_data_reg <= comb_stage[CIC_N - 1].comb_out[dw_out - 1 -: OUT_DW];
|
147 |
|
|
end
|
148 |
|
|
|
149 |
|
|
always @(negedge reset_n or posedge clk)
|
150 |
|
|
if (~reset_n) comb_out_samp_str_reg <= '0;
|
151 |
|
|
else if (clear) comb_out_samp_str_reg <= '0;
|
152 |
|
|
else comb_out_samp_str_reg <= comb_chain_out_str;
|
153 |
|
|
|
154 |
|
|
assign out_samp_data = comb_out_samp_data_reg;
|
155 |
|
|
assign out_samp_str = comb_out_samp_str_reg;
|
156 |
|
|
/*********************************************************************************************/
|
157 |
|
|
task print_parameters_nice;
|
158 |
|
|
integer tot_registers;
|
159 |
|
|
integer j;
|
160 |
|
|
integer B_2Np1;
|
161 |
|
|
integer dw_j;
|
162 |
|
|
integer B_j;
|
163 |
|
|
reg [127:0] h_f0_pre;
|
164 |
|
|
integer log2_h_f0_pre;
|
165 |
|
|
integer h_f0_pre_limit_prec;
|
166 |
|
|
integer h_f0_pre_divider;
|
167 |
|
|
integer h_f0_divider_exp;
|
168 |
|
|
integer h_f0_x_mul;
|
169 |
|
|
integer x_multiplier;
|
170 |
|
|
reg [127:0] F_sq_curr;
|
171 |
|
|
x_multiplier = 100000;
|
172 |
|
|
B_2Np1 = B_max - dw_out + 1;
|
173 |
|
|
h_f0_pre = (CIC_R*CIC_M)**CIC_N;
|
174 |
|
|
h_f0_divider_exp = (B_2Np1 + 1);
|
175 |
|
|
h_f0_pre_limit_prec = 30;
|
176 |
|
|
log2_h_f0_pre = clog2_l(h_f0_pre);
|
177 |
|
|
if (log2_h_f0_pre > h_f0_pre_limit_prec) begin
|
178 |
|
|
//$display(" log2_h_f0_pre = %2d, lim %2d", log2_h_f0_pre, h_f0_pre_limit_prec);
|
179 |
|
|
h_f0_pre_divider = log2_h_f0_pre - h_f0_pre_limit_prec;
|
180 |
|
|
//$display(" h_f0_pre_divider = %2d", h_f0_pre_divider);
|
181 |
|
|
h_f0_pre = h_f0_pre >> h_f0_pre_divider;
|
182 |
|
|
h_f0_divider_exp = h_f0_divider_exp - h_f0_pre_divider;
|
183 |
|
|
//$display(" log2_h_f0_pre limited = %2d, divider_exp limited %2d", log2_h_f0_pre, h_f0_divider_exp);
|
184 |
|
|
h_f0_x_mul = x_multiplier * h_f0_pre / 2**(h_f0_divider_exp);
|
185 |
|
|
end
|
186 |
|
|
else begin
|
187 |
|
|
h_f0_x_mul = x_multiplier * h_f0_pre / 2**(B_2Np1 + 1);
|
188 |
|
|
end
|
189 |
|
|
$display("CIC inp_dw %d", INP_DW);
|
190 |
|
|
$display("CIC out_dw %d", OUT_DW);
|
191 |
|
|
$display("CIC B_max %d", B_max);
|
192 |
|
|
$display("CIC B_out %d", dw_out);
|
193 |
|
|
$display("CIC B_2Np1 %d", B_2Np1);
|
194 |
|
|
$display("CIC h(f=0) %1d.%1d", h_f0_x_mul / x_multiplier, h_f0_x_mul % x_multiplier);
|
195 |
|
|
$display(" clog2_l((r*m)**n) %d", clog2_l((CIC_R*CIC_M)**CIC_N));
|
196 |
|
|
tot_registers = 0;
|
197 |
|
|
for (j = 1; j < 2 * CIC_N + 2; j = j + 1) begin : check_Bj
|
198 |
|
|
F_sq_curr = F_sq_calc(j, CIC_N, CIC_R, CIC_M);
|
199 |
|
|
B_j = B_calc(j, CIC_N, CIC_R, CIC_M, INP_DW, OUT_DW);
|
200 |
|
|
dw_j = B_max - B_j + 1;
|
201 |
|
|
tot_registers = tot_registers + dw_j;
|
202 |
|
|
end
|
203 |
|
|
$display("CIC total registers %2d", tot_registers);
|
204 |
|
|
endtask
|
205 |
|
|
|
206 |
|
|
|
207 |
|
|
generate
|
208 |
|
|
initial begin : initial_print_parameters
|
209 |
|
|
if (1) begin
|
210 |
|
|
print_parameters_nice;
|
211 |
|
|
end
|
212 |
|
|
|
213 |
|
|
end
|
214 |
|
|
if (0) begin
|
215 |
|
|
for (j = 0; j < CIC_N; j = j + 1) begin : print_int_stage
|
216 |
|
|
initial begin
|
217 |
|
|
$display("CIC integrator j:%2d B %2d B_ jm1 %2d odw_prev %2d in_dw %3d out_dw %3d data_width_pass %3d", j + 1, int_stage[j].B_j, int_stage[j].B_jm1, int_stage[j].odw_prev, int_stage[j].idw_cur, int_stage[j].odw_cur, 0);
|
218 |
|
|
end
|
219 |
|
|
end
|
220 |
|
|
initial begin
|
221 |
|
|
$display("CIC downsampler B %2d ds_dw %3d", B_m, ds_dw);
|
222 |
|
|
end
|
223 |
|
|
for (j = 0; j < CIC_N; j = j + 1) begin : print_comb_stage
|
224 |
|
|
initial begin
|
225 |
|
|
$display("CIC comb j:%2d B %2d B_mjm1 %2d in_dw %3d out_dw %3d", j, comb_stage[j].B_m_j, comb_stage[j].B_m_j_m1, comb_stage[j].idw_cur, comb_stage[j].odw_cur);
|
226 |
|
|
end
|
227 |
|
|
end
|
228 |
|
|
initial begin
|
229 |
|
|
$display("CIC out odw %3d", OUT_DW);
|
230 |
|
|
end
|
231 |
|
|
end
|
232 |
|
|
endgenerate
|
233 |
|
|
endmodule
|