URL
https://opencores.org/ocsvn/cic_core_2/cic_core_2/trunk
Subversion Repositories cic_core_2
Compare Revisions
- This comparison shows the changes necessary to convert path
/
- from Rev 6 to Rev 7
- ↔ Reverse comparison
Rev 6 → Rev 7
/cic_core_2/trunk/rtl/verilog/cic_d.sv
1,232 → 1,233
module cic_d |
/*********************************************************************************************/ |
#( |
parameter INP_DW = 18, ///< input data width |
parameter OUT_DW = 18, ///< output data width |
parameter CIC_R = 100, ///< decimation ratio |
parameter CIC_N = 7, ///< number of stages |
parameter CIC_M = 1, ///< delay in comb |
parameter SMALL_FOOTPRINT = 1 ///< reduced registers usage, f_clk / (f_samp/CIC_R) > CIC_N required |
) |
/*********************************************************************************************/ |
( |
input clk, |
input reset_n, |
input clear, |
input wire signed [INP_DW-1:0] inp_samp_data, |
input inp_samp_str, |
output wire signed [OUT_DW-1:0] out_samp_data, |
output out_samp_str |
); |
/*********************************************************************************************/ |
`include "cic_functions.vh" |
/*********************************************************************************************/ |
localparam B_max = clog2_l((CIC_R * CIC_M) ** CIC_N) + INP_DW - 1; |
/*********************************************************************************************/ |
|
genvar i; |
generate |
for (i = 0; i < CIC_N; i = i + 1) begin : int_stage |
localparam B_j = B(i + 1, CIC_R, CIC_M, CIC_N, INP_DW, OUT_DW); |
localparam B_jm1 = B(i , CIC_R, CIC_M, CIC_N, INP_DW, OUT_DW); |
localparam logic [127:0 ] F_sq_j = F_sq(i , CIC_R, CIC_M, CIC_N); |
localparam dw_cur = B_max - B_j + 1; |
localparam odw_cur = dw_cur; |
localparam B_dw_prev = (i != 0) ? B_max - B_jm1 + 1 : 0; |
localparam odw_prev = (B_dw_prev > 1) ? B_dw_prev : 2; /// icarus stops with error if in [a -: b] a is <= 0 |
localparam idw_cur = dw_cur > 0 ? dw_cur : 1; |
wire signed [idw_cur - 1 : 0] int_in; |
if ( i == 0 ) assign int_in = inp_samp_data; |
else assign int_in = int_stage[i - 1].int_out[odw_prev - 1 -: idw_cur]; |
wire signed [odw_cur - 1 : 0] int_out; |
integrator #( |
idw_cur, |
odw_cur |
) |
int_inst( |
.clk (clk), |
.reset_n (reset_n), |
.clear (clear) , |
.inp_samp_data (int_in), |
.inp_samp_str (inp_samp_str), |
.out_samp_data (int_out) |
); |
initial begin |
//$display("i:%d integ dw %d B(%d, %d, %d, %d, %d, %d)=%d, F_sq=%d", i, odw_cur, i + 1, CIC_R, CIC_M, CIC_N, INP_DW, OUT_DW, B_j, F_sq_j); |
$display("i:%d integ dw %d ", i, odw_cur); |
end |
end |
endgenerate |
/*********************************************************************************************/ |
localparam B_m = B(CIC_N, CIC_R, CIC_M, CIC_N, INP_DW, OUT_DW); |
localparam ds_dw = B_max - B_m + 1; |
wire signed [ds_dw - 1 : 0] ds_out_samp_data; |
wire ds_out_samp_str; |
/*********************************************************************************************/ |
initial begin |
//$display("i downsamp dw %d , int_stage[%2d].dw_out = %2d", ds_dw, CIC_N - 1, int_stage[CIC_N - 1].odw_cur); |
$display("i downsamp dw %d", ds_dw); |
end |
downsampler #( |
.DATA_WIDTH_INP (ds_dw), |
.CIC_R (CIC_R) |
) |
downsampler_inst |
( |
.clk (clk), |
.reset_n (reset_n), |
.clear (clear), |
.inp_samp_data (int_stage[CIC_N - 1].int_out), |
.inp_samp_str (inp_samp_str), |
.out_samp_data (ds_out_samp_data), |
.out_samp_str (ds_out_samp_str) |
); |
/*********************************************************************************************/ |
genvar j; |
wire comb_chain_out_str; |
reg [CIC_N : 0] comb_inp_str_d; |
generate |
wire summ_rdy_str; |
if (SMALL_FOOTPRINT != 0) begin |
always @(negedge reset_n or posedge clk) |
if (~reset_n) comb_inp_str_d <= '0; |
else if (clear) comb_inp_str_d <= '0; |
else comb_inp_str_d <= {comb_inp_str_d[CIC_N - 1 : 0], ds_out_samp_str}; |
end |
|
if (SMALL_FOOTPRINT == 0) assign summ_rdy_str = '0; |
else assign summ_rdy_str = comb_inp_str_d[CIC_N]; |
|
|
for (j = 0; j < CIC_N; j = j + 1) begin : comb_stage |
localparam j_cic = CIC_N + j + 1; |
localparam B_m_j = B( j_cic, CIC_R, CIC_M, CIC_N, INP_DW, OUT_DW); |
localparam F_sq_j = F_sq( j_cic, CIC_R, CIC_M, CIC_N); |
localparam B_m_j_m1 = B( CIC_N + j, CIC_R, CIC_M, CIC_N, INP_DW, OUT_DW); |
localparam F_sq_2Np1 = F_sq(2 * CIC_N + 1, CIC_R, CIC_M, CIC_N); |
localparam idw_cur = B_max - B_m_j + 1; |
localparam odw_cur = idw_cur; |
localparam odw_prev = (j != 0) ? B_max - B_m_j_m1 + 1 : 0; |
wire signed [idw_cur - 1 : 0] comb_in; |
wire signed [odw_cur - 1 : 0] comb_out; |
wire comb_dv; |
if (j == 0) assign comb_in = ds_out_samp_data[ds_dw - 1 -: idw_cur]; |
else assign comb_in = comb_stage[j - 1].comb_out[odw_prev - 1 -: idw_cur]; |
comb #( |
.SAMP_WIDTH (idw_cur), |
.CIC_M (CIC_M), |
.SMALL_FOOTPRINT(SMALL_FOOTPRINT) |
) |
comb_inst( |
.clk (clk), |
.reset_n (reset_n), |
.clear (clear), |
.samp_inp_str (ds_out_samp_str), |
.samp_inp_data (comb_in), |
.summ_rdy_str (summ_rdy_str), |
.samp_out_str (comb_dv), |
.samp_out_data (comb_out) |
); |
if (SMALL_FOOTPRINT == 0) assign comb_chain_out_str = comb_stage[CIC_N - 1].comb_dv; |
else assign comb_chain_out_str = comb_inp_str_d[CIC_N - 1]; |
initial begin |
//$display("i:%d comb dw %d inp comb_out[%2d -: %2d]; B(%2d, %1d, %1d, %1d, %1d, %1d)=%2d, ln(F_sq)=%4d, F_sq=%8d", j, odw_cur, odw_prev - 1, idw_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); |
$display("i:%d comb dw %d", j, odw_cur); |
end |
end |
endgenerate |
/*********************************************************************************************/ |
localparam dw_out = B_max - B(2 * CIC_N, CIC_R, CIC_M, CIC_N, INP_DW, OUT_DW) + 1; |
reg signed [OUT_DW-1:0] comb_out_samp_data_reg; |
reg comb_out_samp_str_reg; |
|
always @(negedge reset_n or posedge clk) |
begin |
if (~reset_n) comb_out_samp_data_reg <= '0; |
else if (comb_chain_out_str) comb_out_samp_data_reg <= comb_stage[CIC_N - 1].comb_out[dw_out - 1 -: OUT_DW]; |
end |
|
always @(negedge reset_n or posedge clk) |
if (~reset_n) comb_out_samp_str_reg <= '0; |
else if (clear) comb_out_samp_str_reg <= '0; |
else comb_out_samp_str_reg <= comb_chain_out_str; |
|
assign out_samp_data = comb_out_samp_data_reg; |
assign out_samp_str = comb_out_samp_str_reg; |
/*********************************************************************************************/ |
task print_parameters_nice; |
integer tot_registers; |
integer j; |
integer B_2Np1; |
integer dw_j; |
integer B_j; |
reg [127:0] h_f0_pre; |
integer log2_h_f0_pre; |
integer h_f0_pre_limit_prec; |
integer h_f0_pre_divider; |
integer h_f0_divider_exp; |
integer h_f0_x_mul; |
integer x_multiplier; |
reg [127:0] F_sq_curr; |
x_multiplier = 100000; |
B_2Np1 = B_max - dw_out + 1; |
h_f0_pre = (CIC_R*CIC_M)**CIC_N; |
h_f0_divider_exp = (B_2Np1 + 1); |
h_f0_pre_limit_prec = 30; |
log2_h_f0_pre = clog2_l(h_f0_pre); |
if (log2_h_f0_pre > h_f0_pre_limit_prec) begin |
//$display(" log2_h_f0_pre = %2d, lim %2d", log2_h_f0_pre, h_f0_pre_limit_prec); |
h_f0_pre_divider = log2_h_f0_pre - h_f0_pre_limit_prec; |
//$display(" h_f0_pre_divider = %2d", h_f0_pre_divider); |
h_f0_pre = h_f0_pre >> h_f0_pre_divider; |
h_f0_divider_exp = h_f0_divider_exp - h_f0_pre_divider; |
//$display(" log2_h_f0_pre limited = %2d, divider_exp limited %2d", log2_h_f0_pre, h_f0_divider_exp); |
h_f0_x_mul = x_multiplier * h_f0_pre / 2**(h_f0_divider_exp); |
end |
else begin |
h_f0_x_mul = x_multiplier * h_f0_pre / 2**(B_2Np1 + 1); |
end |
$display("CIC inp_dw %d", INP_DW); |
$display("CIC out_dw %d", OUT_DW); |
$display("CIC B_max %d", B_max); |
$display("CIC B_2Np1 %d", B_2Np1); |
$display("CIC h(f=0) %1d.%1d", h_f0_x_mul / x_multiplier, h_f0_x_mul % x_multiplier); |
$display(" clog2_l((r*m)**n) %d", clog2_l((CIC_R*CIC_M)**CIC_N)); |
tot_registers = 0; |
for (j = 1; j < 2 * CIC_N + 2; j = j + 1) begin : check_Bj |
F_sq_curr = F_sq(j, CIC_R, CIC_M, CIC_N); |
B_j = B(j, CIC_R, CIC_M, CIC_N, INP_DW, OUT_DW); |
dw_j = B_max - B_j + 1; |
tot_registers = tot_registers + dw_j; |
end |
$display("CIC total registers %2d", tot_registers); |
endtask |
|
|
generate |
initial begin : initial_print_parameters |
if (0) begin |
print_parameters_nice; |
end |
|
end |
if (0) begin |
for (j = 0; j < CIC_N; j = j + 1) begin : print_int_stage |
initial begin |
$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); |
end |
end |
initial begin |
$display("CIC downsampler B %2d ds_dw %3d", B_m, ds_dw); |
end |
for (j = 0; j < CIC_N; j = j + 1) begin : print_comb_stage |
initial begin |
$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); |
end |
end |
initial begin |
$display("CIC out odw %3d", OUT_DW); |
end |
end |
endgenerate |
endmodule |
module cic_d |
/*********************************************************************************************/ |
#( |
parameter INP_DW = 18, ///< input data width |
parameter OUT_DW = 18, ///< output data width |
parameter CIC_R = 100, ///< decimation ratio |
parameter CIC_N = 7, ///< number of stages |
parameter CIC_M = 1, ///< delay in comb |
parameter SMALL_FOOTPRINT = 1 ///< reduced registers usage, f_clk / (f_samp/CIC_R) > CIC_N required |
) |
/*********************************************************************************************/ |
( |
input clk, |
input reset_n, |
input clear, |
input wire signed [INP_DW-1:0] inp_samp_data, |
input inp_samp_str, |
output wire signed [OUT_DW-1:0] out_samp_data, |
output out_samp_str |
); |
/*********************************************************************************************/ |
`include "cic_functions.vh" |
/*********************************************************************************************/ |
localparam B_max = clog2_l((CIC_R * CIC_M) ** CIC_N) + INP_DW - 1; |
/*********************************************************************************************/ |
|
genvar i; |
generate |
for (i = 0; i < CIC_N; i = i + 1) begin : int_stage |
localparam B_jm1 = B_calc(i , CIC_N, CIC_R, CIC_M, INP_DW, OUT_DW); |
localparam B_j = B_calc(i + 1, CIC_N, CIC_R, CIC_M, INP_DW, OUT_DW); |
localparam F_sq_j = 0; |
localparam idw_cur = B_max - B_jm1 + 1; |
localparam odw_cur = B_max - B_j + 1; |
localparam B_dw_prev = (i != 0) ? B_max - B_jm1 + 1 : 0; |
wire signed [idw_cur - 1 : 0] int_in; |
if ( i == 0 ) assign int_in = inp_samp_data; |
else assign int_in = int_stage[i - 1].int_out; |
wire signed [idw_cur - 1 : 0] int_inst_out; |
wire signed [odw_cur - 1 : 0] int_out; |
assign int_out = int_inst_out[idw_cur - 1 -: odw_cur]; |
integrator #( |
idw_cur, |
idw_cur |
) |
int_inst( |
.clk (clk), |
.reset_n (reset_n), |
.clear (clear) , |
.inp_samp_data (int_in), |
.inp_samp_str (inp_samp_str), |
.out_samp_data (int_inst_out) |
); |
initial begin |
//$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); |
$display("i:%d integ idw=%d ", i, idw_cur); |
end |
end |
endgenerate |
/*********************************************************************************************/ |
localparam B_m = B_calc(CIC_N, CIC_N, CIC_R, CIC_M, INP_DW, OUT_DW); |
localparam ds_dw = B_max - B_m + 1; |
wire signed [ds_dw - 1 : 0] ds_out_samp_data; |
wire ds_out_samp_str; |
/*********************************************************************************************/ |
initial begin |
//$display("i downsamp dw %d , int_stage[%2d].dw_out = %2d", ds_dw, CIC_N - 1, int_stage[CIC_N - 1].odw_cur); |
$display("i downsamp dw %d", ds_dw); |
end |
downsampler #( |
.DATA_WIDTH_INP (ds_dw), |
.CIC_R (CIC_R) |
) |
downsampler_inst |
( |
.clk (clk), |
.reset_n (reset_n), |
.clear (clear), |
.inp_samp_data (int_stage[CIC_N - 1].int_out), |
.inp_samp_str (inp_samp_str), |
.out_samp_data (ds_out_samp_data), |
.out_samp_str (ds_out_samp_str) |
); |
/*********************************************************************************************/ |
genvar j; |
wire comb_chain_out_str; |
reg [CIC_N : 0] comb_inp_str_d; |
generate |
wire summ_rdy_str; |
if (SMALL_FOOTPRINT != 0) begin |
always @(negedge reset_n or posedge clk) |
if (~reset_n) comb_inp_str_d <= '0; |
else if (clear) comb_inp_str_d <= '0; |
else comb_inp_str_d <= {comb_inp_str_d[CIC_N - 1 : 0], ds_out_samp_str}; |
end |
|
if (SMALL_FOOTPRINT == 0) assign summ_rdy_str = '0; |
else assign summ_rdy_str = comb_inp_str_d[CIC_N]; |
|
|
for (j = 0; j < CIC_N; j = j + 1) begin : comb_stage |
localparam B_m_j_m1 = B_calc(CIC_N + j , CIC_N, CIC_R, CIC_M, INP_DW, OUT_DW); |
localparam B_m_j = B_calc(CIC_N + j + 1, CIC_N, CIC_R, CIC_M, INP_DW, OUT_DW); |
localparam F_sq_j = 1; |
localparam idw_cur = B_max - B_m_j_m1 + 1; |
localparam odw_cur = B_max - B_m_j + 1; |
wire signed [idw_cur - 1 : 0] comb_in; |
wire signed [idw_cur - 1 : 0] comb_inst_out; |
wire signed [odw_cur - 1 : 0] comb_out; |
wire comb_dv; |
if (j == 0) assign comb_in = ds_out_samp_data; |
else assign comb_in = comb_stage[j - 1].comb_out; |
assign comb_out = comb_inst_out[idw_cur - 1 -: odw_cur]; |
comb #( |
.SAMP_WIDTH (idw_cur), |
.CIC_M (CIC_M), |
.SMALL_FOOTPRINT(SMALL_FOOTPRINT) |
) |
comb_inst( |
.clk (clk), |
.reset_n (reset_n), |
.clear (clear), |
.samp_inp_str (ds_out_samp_str), |
.samp_inp_data (comb_in), |
.summ_rdy_str (summ_rdy_str), |
.samp_out_str (comb_dv), |
.samp_out_data (comb_inst_out) |
); |
if (SMALL_FOOTPRINT == 0) assign comb_chain_out_str = comb_stage[CIC_N - 1].comb_dv; |
else assign comb_chain_out_str = comb_inp_str_d[CIC_N - 1]; |
initial begin |
//$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); |
//if (j != 0) $display("odw_prev=%2d, comb_stage[j - 1].odw_cur=%2d", odw_prev, comb_stage[j - 1].odw_cur); |
$display("i:%d comb idw=%d", j, idw_cur); |
end |
end |
endgenerate |
/*********************************************************************************************/ |
localparam dw_out = B_max - B_calc(2 * CIC_N, CIC_N, CIC_R, CIC_M, INP_DW, OUT_DW) + 1; |
reg signed [OUT_DW-1:0] comb_out_samp_data_reg; |
reg comb_out_samp_str_reg; |
|
always @(negedge reset_n or posedge clk) |
begin |
if (~reset_n) comb_out_samp_data_reg <= '0; |
else if (comb_chain_out_str) comb_out_samp_data_reg <= comb_stage[CIC_N - 1].comb_out[dw_out - 1 -: OUT_DW]; |
end |
|
always @(negedge reset_n or posedge clk) |
if (~reset_n) comb_out_samp_str_reg <= '0; |
else if (clear) comb_out_samp_str_reg <= '0; |
else comb_out_samp_str_reg <= comb_chain_out_str; |
|
assign out_samp_data = comb_out_samp_data_reg; |
assign out_samp_str = comb_out_samp_str_reg; |
/*********************************************************************************************/ |
task print_parameters_nice; |
integer tot_registers; |
integer j; |
integer B_2Np1; |
integer dw_j; |
integer B_j; |
reg [127:0] h_f0_pre; |
integer log2_h_f0_pre; |
integer h_f0_pre_limit_prec; |
integer h_f0_pre_divider; |
integer h_f0_divider_exp; |
integer h_f0_x_mul; |
integer x_multiplier; |
reg [127:0] F_sq_curr; |
x_multiplier = 100000; |
B_2Np1 = B_max - dw_out + 1; |
h_f0_pre = (CIC_R*CIC_M)**CIC_N; |
h_f0_divider_exp = (B_2Np1 + 1); |
h_f0_pre_limit_prec = 30; |
log2_h_f0_pre = clog2_l(h_f0_pre); |
if (log2_h_f0_pre > h_f0_pre_limit_prec) begin |
//$display(" log2_h_f0_pre = %2d, lim %2d", log2_h_f0_pre, h_f0_pre_limit_prec); |
h_f0_pre_divider = log2_h_f0_pre - h_f0_pre_limit_prec; |
//$display(" h_f0_pre_divider = %2d", h_f0_pre_divider); |
h_f0_pre = h_f0_pre >> h_f0_pre_divider; |
h_f0_divider_exp = h_f0_divider_exp - h_f0_pre_divider; |
//$display(" log2_h_f0_pre limited = %2d, divider_exp limited %2d", log2_h_f0_pre, h_f0_divider_exp); |
h_f0_x_mul = x_multiplier * h_f0_pre / 2**(h_f0_divider_exp); |
end |
else begin |
h_f0_x_mul = x_multiplier * h_f0_pre / 2**(B_2Np1 + 1); |
end |
$display("CIC inp_dw %d", INP_DW); |
$display("CIC out_dw %d", OUT_DW); |
$display("CIC B_max %d", B_max); |
$display("CIC B_out %d", dw_out); |
$display("CIC B_2Np1 %d", B_2Np1); |
$display("CIC h(f=0) %1d.%1d", h_f0_x_mul / x_multiplier, h_f0_x_mul % x_multiplier); |
$display(" clog2_l((r*m)**n) %d", clog2_l((CIC_R*CIC_M)**CIC_N)); |
tot_registers = 0; |
for (j = 1; j < 2 * CIC_N + 2; j = j + 1) begin : check_Bj |
F_sq_curr = F_sq_calc(j, CIC_N, CIC_R, CIC_M); |
B_j = B_calc(j, CIC_N, CIC_R, CIC_M, INP_DW, OUT_DW); |
dw_j = B_max - B_j + 1; |
tot_registers = tot_registers + dw_j; |
end |
$display("CIC total registers %2d", tot_registers); |
endtask |
|
|
generate |
initial begin : initial_print_parameters |
if (1) begin |
print_parameters_nice; |
end |
|
end |
if (0) begin |
for (j = 0; j < CIC_N; j = j + 1) begin : print_int_stage |
initial begin |
$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); |
end |
end |
initial begin |
$display("CIC downsampler B %2d ds_dw %3d", B_m, ds_dw); |
end |
for (j = 0; j < CIC_N; j = j + 1) begin : print_comb_stage |
initial begin |
$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); |
end |
end |
initial begin |
$display("CIC out odw %3d", OUT_DW); |
end |
end |
endgenerate |
endmodule |
/cic_core_2/trunk/rtl/verilog/cic_functions.vh
1,157 → 1,163
/** |
* Library: cic_functions |
* |
* library with functions for calculating parameters for CIC filter and Hogenauer pruning |
*/ |
`ifndef _CIC_FUNCTIONS_VH_ |
`define _CIC_FUNCTIONS_VH_ |
`define M_PI 3.14159265359 // not all simulator defines PI |
/*********************************************************************************************/ |
function reg unsigned [127 : 0] nchoosek; ///< Binomial coefficient |
input integer n; |
input integer k; |
reg unsigned [127:0] tmp; |
integer i; |
begin |
tmp = 1.0; |
for (i = 1; i <= (n - k); i = i + 1) |
tmp = tmp * (k + i) / i; |
nchoosek = tmp; |
end |
endfunction |
/*********************************************************************************************/ |
function integer clog2_l; |
input reg unsigned [127:0] depth; |
reg unsigned [127:0] i; |
begin |
clog2_l = 0; |
if (depth > 0) begin |
i = depth - 1; // with "- 1" clog2(2^N) will be N, not N + 1 |
for(clog2_l = 0; i > 0; clog2_l = clog2_l + 1) |
i = i >> 1; |
end else |
clog2_l = -1; |
end |
endfunction |
/*********************************************************************************************/ |
function integer B_max_calc; |
input integer N; |
input integer R; |
input integer M; |
input integer INP_DW; |
reg unsigned [127:0] RMpN; |
begin |
RMpN = (R * M) ** N; |
B_max_calc = clog2_l(RMpN) + INP_DW - 1; |
end |
endfunction |
/*********************************************************************************************/ |
function integer B_out_calc; |
input integer N; |
input integer R; |
input integer M; |
input integer INP_DW; |
input integer OUT_DW; |
begin |
B_out_calc = B_max_calc(N, R, M, OUT_DW) - B(2 * N, R, M, N, INP_DW, OUT_DW) + 1; |
end |
endfunction |
/*********************************************************************************************/ |
function integer flog2_l; |
input reg unsigned [127:0] depth; |
reg unsigned [127:0] i; |
begin |
i = depth; |
for(flog2_l = 0; i > 1; flog2_l = flog2_l + 1) |
i = i >> 1; |
end |
endfunction |
/*********************************************************************************************/ |
function reg signed [127:0] h; |
input integer j; |
input integer k; |
input integer R; |
input integer M; |
input integer N; |
integer c_stop; |
integer i; |
reg signed [127:0] tmp; |
reg signed [127:0] prod_1; |
reg signed [127:0] prod_2; |
reg signed [127:0] summ; |
begin |
c_stop = k / (R * M); |
if ((j >= 1)&&( j<=N )) begin |
tmp = 0; |
for (i = 0; i <= c_stop; i = i + 1) begin |
prod_1 = nchoosek(N, i); |
prod_2 = nchoosek(N - j + k - R * M * i, k - R * M * i); |
summ = prod_1 * prod_2; |
if (i % 2) summ = -summ; |
tmp = tmp + summ; |
end |
end |
else begin |
tmp = nchoosek(2 * N + 1 - j, k); |
if (k % 2) tmp = -tmp; |
end |
h = tmp; |
end |
endfunction |
/*********************************************************************************************/ |
function reg signed [127:0] F_sq; ///< F()**2 |
input integer j; |
input integer R; |
input integer M; |
input integer N; |
integer c_stop; |
reg signed [127:0] tmp; |
integer i; |
reg signed [127:0] h_jk; |
begin |
tmp = 0; |
if (j <= N) |
c_stop = (((R * M -1 ) * N) + j - 1); |
else |
c_stop = 2 * N + 1 - j; |
for (i = 0;i <= c_stop; i = i + 1) begin |
h_jk = h(j, i, R, M, N); |
tmp = tmp + h_jk ** 2; |
end |
F_sq = tmp; |
end |
endfunction |
/*********************************************************************************************/ |
function integer B; |
input integer j; |
input integer R; |
input integer M; |
input integer N; |
input integer dw_in; |
input integer dw_out; |
integer B_max; |
reg signed [127:0] sigma_T_2Np1_sq; |
reg signed [127:0] B_2Np1; |
reg signed [127:0] B_exp_real; |
integer B_out; |
reg signed [127:0] F_sq_j; |
reg signed [127:0] F_sq_2Np1; |
begin |
B_max = B_max_calc(N, R, M, dw_in); |
if (j == 2 * N + 1) begin |
B = B_max - dw_out + 1; |
end else begin |
B_2Np1 = B_max - dw_out + 1; |
F_sq_j = F_sq(j, R, M, N); |
F_sq_2Np1 = F_sq(2 * N + 1, R, M, N); |
sigma_T_2Np1_sq = (128'b1 << (2 * B_2Np1)) * F_sq_2Np1 / 12; |
B_exp_real = (sigma_T_2Np1_sq / F_sq_j * 6 / N); |
B_out = flog2_l(B_exp_real) / 2; |
B = B_out; |
end |
end |
endfunction |
/*********************************************************************************************/ |
|
`endif |
|
/** |
* Library: cic_functions |
* |
* library with functions for calculating parameters for CIC filter and Hogenauer pruning |
*/ |
`ifndef _CIC_FUNCTIONS_VH_ |
`define _CIC_FUNCTIONS_VH_ |
`define M_PI 3.14159265359 // not all simulator defines PI |
|
function reg unsigned [127 : 0] nchoosek; ///< Binomial coefficient |
input integer n; |
input integer k; |
reg unsigned [127:0] tmp; |
integer i; |
begin |
tmp = 1.0; |
for (i = 1; i <= (n - k); i = i + 1) |
tmp = tmp * (k + i) / i; |
nchoosek = tmp; |
end |
endfunction |
|
function integer clog2_l; |
input reg unsigned [127:0] depth; |
reg unsigned [127:0] i; |
begin |
clog2_l = 0; |
if (depth > 0) begin |
i = depth - 1; // with "- 1" clog2(2^N) will be N, not N + 1 |
for(clog2_l = 0; i > 0; clog2_l = clog2_l + 1) |
i = i >> 1; |
end else |
clog2_l = -1; |
end |
endfunction |
|
function integer B_max_calc; |
input integer N; |
input integer R; |
input integer M; |
input integer INP_DW; |
reg unsigned [127:0] RMpN; |
begin |
RMpN = (R * M) ** N; |
B_max_calc = clog2_l(RMpN) + INP_DW - 1; |
//$display("B_max_calc: N=%2d, R=%2d, M=%2d, ret=%2d", N, R, M, B_max_calc); |
end |
endfunction |
|
function integer B_out_calc; |
input integer N; |
input integer R; |
input integer M; |
input integer INP_DW; |
input integer OUT_DW; |
begin |
B_out_calc = B_max_calc(N, R, M, OUT_DW) - B_calc(2 * N, N, R, M, INP_DW, OUT_DW) + 1; |
end |
endfunction |
|
|
function integer flog2_l; |
input reg unsigned [127:0] depth; |
reg unsigned [127:0] i; |
begin |
i = depth; |
for(flog2_l = 0; i > 1; flog2_l = flog2_l + 1) |
i = i >> 1; |
end |
endfunction |
|
|
function reg signed [127:0] h_calc; |
input integer j; |
input integer k; |
input integer N; |
input integer R; |
input integer M; |
integer c_stop; |
integer i; |
reg signed [127:0] tmp; |
reg signed [127:0] prod_1; |
reg signed [127:0] prod_2; |
reg signed [127:0] summ; |
begin |
c_stop = k / (R * M); |
if ((j >= 1)&&( j<=N )) begin |
tmp = 0; |
for (i = 0; i <= c_stop; i = i + 1) begin |
prod_1 = nchoosek(N, i); |
prod_2 = nchoosek(N - j + k - R * M * i, k - R * M * i); |
summ = prod_1 * prod_2; |
if (i % 2) summ = -summ; |
tmp = tmp + summ; |
end |
end |
else begin |
tmp = nchoosek(2 * N + 1 - j, k); |
if (k % 2) tmp = -tmp; |
end |
h_calc = tmp; |
end |
endfunction |
|
function reg signed [127:0] F_sq_calc; ///< F()**2 |
input integer j; |
input integer N; |
input integer R; |
input integer M; |
integer c_stop; |
reg signed [127:0] tmp; |
integer i; |
reg signed [127:0] h_jk; |
begin |
tmp = 0; |
if (j <= N) |
c_stop = (((R * M -1 ) * N) + j - 1); |
else |
c_stop = 2 * N + 1 - j; |
for (i = 0;i <= c_stop; i = i + 1) begin |
h_jk = h_calc(j, i, N, R, M); |
tmp = tmp + h_jk ** 2; |
end |
F_sq_calc = tmp; |
end |
endfunction |
|
function integer B_calc; |
input integer j; |
input integer N; |
input integer R; |
input integer M; |
input integer dw_in; |
input integer dw_out; |
integer B_max; |
reg signed [127:0] sigma_T_2Np1_sq; |
reg signed [127:0] B_2Np1; |
reg signed [127:0] B_exp_real; |
integer B_out; |
reg signed [127:0] F_sq_j; |
reg signed [127:0] F_sq_2Np1; |
begin |
if (j <= 0) begin |
B_calc = 0; |
end else begin |
B_max = B_max_calc(N, R, M, dw_in); |
if (j == 2 * N + 1) begin |
B_calc = B_max - dw_out + 1; |
end else begin |
B_2Np1 = B_max - dw_out + 1; |
F_sq_j = F_sq_calc(j, N, R, M); |
F_sq_2Np1 = F_sq_calc(2 * N + 1, N, R, M); |
sigma_T_2Np1_sq = (128'b1 << (2 * B_2Np1)) * F_sq_2Np1 / 12; |
B_exp_real = (sigma_T_2Np1_sq / F_sq_j * 6 / N); |
B_out = flog2_l(B_exp_real) / 2; |
B_calc = B_out; |
end |
end |
end |
endfunction |
|
`endif |
|
/cic_core_2/trunk/rtl/verilog/cic_i.sv
1,53 → 1,53
module cic_i |
/*********************************************************************************************/ |
#(parameter dw = 8, r = 4, m = 4, g = 1) |
/*********************************************************************************************/ |
//m - CIC order (comb chain length, integrator chain length) |
//r - interpolation ratio |
//dw - input data width |
//g - differential delay in combs |
/*********************************************************************************************/ |
( |
input clk, |
input reset_n, |
input in_dv, |
input signed [dw-1:0] data_in, |
output signed [dw+$clog2((r**(m))/r)-1:0] data_out |
); |
/*********************************************************************************************/ |
wire signed [dw+m-2:0] upsample; |
/*********************************************************************************************/ |
genvar i; |
generate |
for (i = 0; i < m; i++) begin:comb_stage |
wire signed [dw+i-1:0] comb_in; |
localparam odw = (i == m - 1) ? dw+i : dw+i+1; |
if (i!=0) |
assign comb_in = comb_stage[i-1].comb_out; |
else |
assign comb_in = data_in; |
wire signed [odw-1:0] comb_out; |
comb #(dw+i, odw, g) comb_inst(.clk(clk) , .reset_n(reset_n) , .in_dv(in_dv) , .data_in(comb_in) , .data_out(comb_out)); |
end |
endgenerate |
/*********************************************************************************************/ |
assign upsample = (in_dv) ? comb_stage[m-1].comb_out : 0; |
/*********************************************************************************************/ |
genvar j; |
generate |
for (j = 0; j < m; j++) begin:int_stage |
localparam idw = (j == 0) ? dw+m-1 : dw+$clog2(((2**(m-j))*(r**(j)))/r); |
localparam odw = dw+$clog2(((2**(m-j-1))*(r**(j+1)))/r); |
wire signed [idw-1:0] int_in; |
if (j==0) |
assign int_in = upsample; |
else |
assign int_in = int_stage[j-1].int_out; |
wire signed [odw-1:0] int_out; |
integrator #(idw, odw) int_inst(.clk(clk) , .reset_n(reset_n) , .data_in(int_in) , .data_out(int_out)); |
end |
endgenerate |
/*********************************************************************************************/ |
assign data_out = int_stage[m-1].int_out; |
/*********************************************************************************************/ |
endmodule |
module cic_i |
/*********************************************************************************************/ |
#(parameter dw = 8, r = 4, m = 4, g = 1) |
/*********************************************************************************************/ |
//m - CIC order (comb chain length, integrator chain length) |
//r - interpolation ratio |
//dw - input data width |
//g - differential delay in combs |
/*********************************************************************************************/ |
( |
input clk, |
input reset_n, |
input in_dv, |
input signed [dw-1:0] data_in, |
output signed [dw+$clog2((r**(m))/r)-1:0] data_out |
); |
/*********************************************************************************************/ |
wire signed [dw+m-2:0] upsample; |
/*********************************************************************************************/ |
genvar i; |
generate |
for (i = 0; i < m; i++) begin:comb_stage |
wire signed [dw+i-1:0] comb_in; |
localparam odw = (i == m - 1) ? dw+i : dw+i+1; |
if (i!=0) |
assign comb_in = comb_stage[i-1].comb_out; |
else |
assign comb_in = data_in; |
wire signed [odw-1:0] comb_out; |
comb #(dw+i, odw, g) comb_inst(.clk(clk) , .reset_n(reset_n) , .in_dv(in_dv) , .data_in(comb_in) , .data_out(comb_out)); |
end |
endgenerate |
/*********************************************************************************************/ |
assign upsample = (in_dv) ? comb_stage[m-1].comb_out : 0; |
/*********************************************************************************************/ |
genvar j; |
generate |
for (j = 0; j < m; j++) begin:int_stage |
localparam idw = (j == 0) ? dw+m-1 : dw+$clog2(((2**(m-j))*(r**(j)))/r); |
localparam odw = dw+$clog2(((2**(m-j-1))*(r**(j+1)))/r); |
wire signed [idw-1:0] int_in; |
if (j==0) |
assign int_in = upsample; |
else |
assign int_in = int_stage[j-1].int_out; |
wire signed [odw-1:0] int_out; |
integrator #(idw, odw) int_inst(.clk(clk) , .reset_n(reset_n) , .data_in(int_in) , .data_out(int_out)); |
end |
endgenerate |
/*********************************************************************************************/ |
assign data_out = int_stage[m-1].int_out; |
/*********************************************************************************************/ |
endmodule |
/cic_core_2/trunk/rtl/verilog/comb.sv
1,83 → 1,83
`timescale 1ns / 1ns |
/** |
* Module: comb |
* |
* Comb stage for CIC filter |
* There is two variants of realisation. |
* Ordinary (SMALL_FOOTPRINT = 0). |
* For every stage in the output extra register added for isolation combinatorial logic outside own adder. |
* Small footprint (SMALL_FOOTPRINT = 1) |
* No additional register, adders are in the chain of CIC_N cells. |
* Output sample generated after CIC_N clocks, f_clk / f_comb_samp > CIC_N required. |
* |
*/ |
module comb |
/*********************************************************************************************/ |
#( |
parameter SAMP_WIDTH = 8, |
parameter CIC_M = 1, |
//parameter CIC_N = 1, |
parameter SMALL_FOOTPRINT = 0 ///< set to 1 for less registers usage, but for every sample CIC_N clocks required |
) |
/*********************************************************************************************/ |
( |
input clk, |
input reset_n, |
input clear, |
input wire signed [SAMP_WIDTH - 1:0] samp_inp_data, |
input samp_inp_str, |
input summ_rdy_str, ///< for SMALL_FOOTPRINT set 1 after CIC_N cycles from inp_str to load FIFO registers with new sample |
///< output data must be latched before summ_rdy_str is set, read output data at CIC_N - 1 clock after inp_str |
output wire signed [SAMP_WIDTH - 1:0] samp_out_data, |
output wire samp_out_str |
); |
/*********************************************************************************************/ |
integer i; |
reg signed [SAMP_WIDTH - 1 : 0] data_reg[CIC_M - 1 : 0]; ///< the storage for the FIFO register |
wire data_reg_push_str; ///< strobe to push data into data_reg FIFO |
/*********************************************************************************************/ |
|
|
generate |
if (SMALL_FOOTPRINT == 0) begin |
reg samp_out_str_reg; |
reg signed [SAMP_WIDTH - 1 : 0] data_out_reg; |
assign data_reg_push_str = samp_inp_str; |
always @(posedge clk or negedge reset_n) |
begin |
if (!reset_n) data_out_reg <= '0; |
else if (clear) data_out_reg <= '0; |
else if (samp_inp_str) data_out_reg <= samp_inp_data - data_reg[CIC_M - 1]; |
end |
assign samp_out_data = data_out_reg; |
always @(posedge clk or negedge reset_n) |
begin |
if (!reset_n) samp_out_str_reg <= '0; |
else if (clear) samp_out_str_reg <= '0; |
else samp_out_str_reg <= samp_inp_str; |
end |
assign samp_out_str = samp_out_str_reg; |
|
end else begin |
assign data_reg_push_str = summ_rdy_str; |
assign #4 samp_out_data = samp_inp_data - data_reg[CIC_M - 1]; // delay for 18x18 multiplier of Cyclone V SE is 3.4 ns |
assign samp_out_str = summ_rdy_str; |
|
end |
endgenerate |
|
|
/*********************************************************************************************/ |
// FIFO register with reset and clear |
always @(posedge clk or negedge reset_n) |
begin |
if (!reset_n) for (i = 0; i < CIC_M; i = i + 1) data_reg[i] <= '0; |
else if (clear) for (i = 0; i < CIC_M; i = i + 1) data_reg[i] <= '0; |
else if (data_reg_push_str) begin |
data_reg[0] <= samp_inp_data; |
for (i = 1; i < CIC_M; i = i + 1) data_reg[i] <= data_reg[i - 1]; |
end |
end |
|
/*********************************************************************************************/ |
endmodule |
`timescale 1ns / 1ns |
/** |
* Module: comb |
* |
* Comb stage for CIC filter |
* There is two variants of realisation. |
* Ordinary (SMALL_FOOTPRINT = 0). |
* For every stage in the output extra register added for isolation combinatorial logic outside own adder. |
* Small footprint (SMALL_FOOTPRINT = 1) |
* No additional register, adders are in the chain of CIC_N cells. |
* Output sample generated after CIC_N clocks, f_clk / f_comb_samp > CIC_N required. |
* |
*/ |
module comb |
/*********************************************************************************************/ |
#( |
parameter SAMP_WIDTH = 8, |
parameter CIC_M = 1, |
//parameter CIC_N = 1, |
parameter SMALL_FOOTPRINT = 0 ///< set to 1 for less registers usage, but for every sample CIC_N clocks required |
) |
/*********************************************************************************************/ |
( |
input clk, |
input reset_n, |
input clear, |
input wire signed [SAMP_WIDTH - 1:0] samp_inp_data, |
input samp_inp_str, |
input summ_rdy_str, ///< for SMALL_FOOTPRINT set 1 after CIC_N cycles from inp_str to load FIFO registers with new sample |
///< output data must be latched before summ_rdy_str is set, read output data at CIC_N - 1 clock after inp_str |
output wire signed [SAMP_WIDTH - 1:0] samp_out_data, |
output wire samp_out_str |
); |
/*********************************************************************************************/ |
integer i; |
reg signed [SAMP_WIDTH - 1 : 0] data_reg[CIC_M - 1 : 0]; ///< the storage for the FIFO register |
wire data_reg_push_str; ///< strobe to push data into data_reg FIFO |
/*********************************************************************************************/ |
|
|
generate |
if (SMALL_FOOTPRINT == 0) begin |
reg samp_out_str_reg; |
reg signed [SAMP_WIDTH - 1 : 0] data_out_reg; |
assign data_reg_push_str = samp_inp_str; |
always @(posedge clk or negedge reset_n) |
begin |
if (!reset_n) data_out_reg <= '0; |
else if (clear) data_out_reg <= '0; |
else if (samp_inp_str) data_out_reg <= samp_inp_data - data_reg[CIC_M - 1]; |
end |
assign samp_out_data = data_out_reg; |
always @(posedge clk or negedge reset_n) |
begin |
if (!reset_n) samp_out_str_reg <= '0; |
else if (clear) samp_out_str_reg <= '0; |
else samp_out_str_reg <= samp_inp_str; |
end |
assign samp_out_str = samp_out_str_reg; |
|
end else begin |
assign data_reg_push_str = summ_rdy_str; |
assign #4 samp_out_data = samp_inp_data - data_reg[CIC_M - 1]; // delay for 18x18 multiplier of Cyclone V SE is 3.4 ns |
assign samp_out_str = summ_rdy_str; |
|
end |
endgenerate |
|
|
/*********************************************************************************************/ |
// FIFO register with reset and clear |
always @(posedge clk or negedge reset_n) |
begin |
if (!reset_n) for (i = 0; i < CIC_M; i = i + 1) data_reg[i] <= '0; |
else if (clear) for (i = 0; i < CIC_M; i = i + 1) data_reg[i] <= '0; |
else if (data_reg_push_str) begin |
data_reg[0] <= samp_inp_data; |
for (i = 1; i < CIC_M; i = i + 1) data_reg[i] <= data_reg[i - 1]; |
end |
end |
|
/*********************************************************************************************/ |
endmodule |
/cic_core_2/trunk/rtl/verilog/downsampler.sv
1,46 → 1,46
module downsampler |
/*********************************************************************************************/ |
#( |
parameter DATA_WIDTH_INP = 8, |
parameter CIC_R = 4 |
) |
/*********************************************************************************************/ |
( |
input clk, |
input reset_n, |
input clear, |
input wire signed [DATA_WIDTH_INP - 1:0] inp_samp_data, |
input inp_samp_str, |
output reg signed [DATA_WIDTH_INP - 1:0] out_samp_data, |
output reg out_samp_str |
); |
/*********************************************************************************************/ |
localparam DECIM_COUNTER_WIDTH = $clog2(CIC_R); |
reg [DECIM_COUNTER_WIDTH - 1 : 0] counter; |
/*********************************************************************************************/ |
// decimation counter |
always @(posedge clk or negedge reset_n) |
begin |
if (!reset_n) counter <= '0; |
else if (clear) counter <= '0; |
else if (inp_samp_str) counter <= (counter < CIC_R - 1) ? counter + {{(DECIM_COUNTER_WIDTH - 1){1'b0}}, 1'b1} : '0; |
end |
/*********************************************************************************************/ |
// output register |
always @(posedge clk or negedge reset_n) |
begin |
if (!reset_n) out_samp_data <= '0; |
else if (clear) out_samp_data <= '0; |
else if (inp_samp_str) out_samp_data <= (counter < CIC_R - 1) ? out_samp_data : inp_samp_data; |
end |
/*********************************************************************************************/ |
// data valid register |
always @(posedge clk or negedge reset_n) |
begin |
if (!reset_n) out_samp_str <= 1'b0; |
else if (clear) out_samp_str <= 1'b0; |
else if (inp_samp_str) out_samp_str <= (counter == CIC_R - 1); |
else out_samp_str <= 1'b0; |
end |
/*********************************************************************************************/ |
endmodule |
module downsampler |
/*********************************************************************************************/ |
#( |
parameter DATA_WIDTH_INP = 8, |
parameter CIC_R = 4 |
) |
/*********************************************************************************************/ |
( |
input clk, |
input reset_n, |
input clear, |
input wire signed [DATA_WIDTH_INP - 1:0] inp_samp_data, |
input inp_samp_str, |
output reg signed [DATA_WIDTH_INP - 1:0] out_samp_data, |
output reg out_samp_str |
); |
/*********************************************************************************************/ |
localparam DECIM_COUNTER_WIDTH = $clog2(CIC_R); |
reg [DECIM_COUNTER_WIDTH - 1 : 0] counter; |
/*********************************************************************************************/ |
// decimation counter |
always @(posedge clk or negedge reset_n) |
begin |
if (!reset_n) counter <= '0; |
else if (clear) counter <= '0; |
else if (inp_samp_str) counter <= (counter < CIC_R - 1) ? counter + {{(DECIM_COUNTER_WIDTH - 1){1'b0}}, 1'b1} : '0; |
end |
/*********************************************************************************************/ |
// output register |
always @(posedge clk or negedge reset_n) |
begin |
if (!reset_n) out_samp_data <= '0; |
else if (clear) out_samp_data <= '0; |
else if (inp_samp_str) out_samp_data <= (counter < CIC_R - 1) ? out_samp_data : inp_samp_data; |
end |
/*********************************************************************************************/ |
// data valid register |
always @(posedge clk or negedge reset_n) |
begin |
if (!reset_n) out_samp_str <= 1'b0; |
else if (clear) out_samp_str <= 1'b0; |
else if (inp_samp_str) out_samp_str <= (counter == CIC_R - 1); |
else out_samp_str <= 1'b0; |
end |
/*********************************************************************************************/ |
endmodule |
/cic_core_2/trunk/rtl/verilog/integrator.sv
1,24 → 1,24
`timescale 1ns / 1ns |
module integrator |
/*********************************************************************************************/ |
#(parameter DATA_WIDTH_INP = 8 , DATA_WIDTH_OUT = 9) |
/*********************************************************************************************/ |
( |
input clk, |
input reset_n, |
input clear, |
input wire signed [DATA_WIDTH_INP - 1:0] inp_samp_data, |
input inp_samp_str, |
output reg signed [DATA_WIDTH_OUT - 1:0] out_samp_data |
); |
/*********************************************************************************************/ |
wire signed [DATA_WIDTH_OUT - 1:0] sum; |
assign #4 sum = out_samp_data + inp_samp_data; // delay for 18x18 multiplier of Cyclone V SE is 3.4 ns |
always @(posedge clk or negedge reset_n) |
begin |
if (!reset_n) out_samp_data <= '0; |
else if (clear) out_samp_data <= '0; |
else if (inp_samp_str) out_samp_data <= sum; |
end |
/*********************************************************************************************/ |
endmodule |
`timescale 1ns / 1ns |
module integrator |
/*********************************************************************************************/ |
#(parameter DATA_WIDTH_INP = 8 , DATA_WIDTH_OUT = 9) |
/*********************************************************************************************/ |
( |
input clk, |
input reset_n, |
input clear, |
input wire signed [DATA_WIDTH_INP - 1:0] inp_samp_data, |
input inp_samp_str, |
output reg signed [DATA_WIDTH_OUT - 1:0] out_samp_data |
); |
/*********************************************************************************************/ |
wire signed [DATA_WIDTH_OUT - 1:0] sum; |
assign #4 sum = out_samp_data + inp_samp_data; // delay for 18x18 multiplier of Cyclone V SE is 3.4 ns |
always @(posedge clk or negedge reset_n) |
begin |
if (!reset_n) out_samp_data <= '0; |
else if (clear) out_samp_data <= '0; |
else if (inp_samp_str) out_samp_data <= sum; |
end |
/*********************************************************************************************/ |
endmodule |
/cic_core_2/trunk/rtl_sim/run/cic_d_gtkwave_run.sh
1,3 → 1,3
#!/bin/sh |
gtkwave ../out/cic_d_tb.vcd ./cic_d_tb.gtkw |
#shmidcat ../out/cic_d_tb.vcd | gtkwave -v -I ./cic_d_tb.gtkw |
#!/bin/sh |
gtkwave ../out/cic_d_tb.vcd ./cic_d_tb.gtkw |
#shmidcat ../out/cic_d_tb.vcd | gtkwave -v -I ./cic_d_tb.gtkw |
/cic_core_2/trunk/rtl_sim/run/cic_d_sim_run.sh
1,6 → 1,7
#!/bin/sh |
PATH_CIC=../../../rtl/verilog |
iverilog -g2005-sv -g2012 -o ../out/cic_d.out -I $PATH_CIC/ $PATH_CIC/cic_functions.vh $PATH_CIC/cic_d.sv $PATH_CIC/integrator.sv $PATH_CIC/comb.sv $PATH_CIC/downsampler.sv ../src/cic_d_tb.sv || exit # if error then stop |
echo "iverilog ready, run vvp" |
vvp ../out/cic_d.out |
echo "vvp ready" |
#!/bin/sh |
PATH_CIC=../../rtl/verilog |
mkdir -p ../out |
iverilog -g2005-sv -g2012 -o ../out/cic_d.out -I $PATH_CIC/ $PATH_CIC/cic_functions.vh $PATH_CIC/cic_d.sv $PATH_CIC/integrator.sv $PATH_CIC/comb.sv $PATH_CIC/downsampler.sv ../src/cic_d_tb.sv || exit # if error then stop |
echo "iverilog ready, run vvp" |
vvp ../out/cic_d.out |
echo "vvp ready" |
/cic_core_2/trunk/rtl_sim/src/cic_d_tb.sv
1,252 → 1,275
`timescale 1ns / 1ns |
module cic_d_tb |
( |
); |
`include "../../../rtl/verilog/cic_functions.vh" |
`define M_PI 3.14159265359 // not all simulators defines PI |
/* |
// U. Meyer-Baese, Digital Signal Processing with Field Programmable Gate Arrays, 2nd Edition, Spinger, 2004. |
// Example 5.5: Three-Stages CIC Decimator II |
localparam CIC_R = 32; |
localparam SAMP_INP_DW = 8; |
localparam SAMP_OUT_DW = 10; |
localparam CIC_N = 3; |
localparam CIC_M = 2;*/ |
localparam CIC_R = 100; |
localparam SAMP_INP_DW = 18; |
localparam SAMP_OUT_DW = 18; |
localparam INP_SAMP_WIDTH_TO_SIGNAL_WIDTH = 2; |
localparam CIC_N = 7; |
localparam CIC_M = 1; |
localparam SMALL_FOOTPRINT = 1; ///< set to 1 for less registers usage, but for every sample CIC_N clocks required |
/* |
//https://www.so-logic.net/documents/trainings/03_so_implementation_of_filters.pdf |
localparam CIC_R = 16; |
localparam SAMP_INP_DW = 16; |
localparam SAMP_OUT_DW = 16; |
localparam INP_SAMP_WIDTH_TO_SIGNAL_WIDTH = 1; |
localparam CIC_N = 3; |
localparam CIC_M = 1; |
localparam SMALL_FOOTPRINT = 1; |
*/ |
/*localparam CIC_R = 25; |
localparam SAMP_INP_DW = 16; |
localparam SAMP_OUT_DW = 16; |
localparam CIC_N = 4; |
localparam CIC_M = 1;*/ |
/*localparam R = 8; |
localparam SAMP_INP_DW = 12; |
localparam SAMP_OUT_DW = 12; |
localparam M = 3; |
localparam G = 1;*/ |
/*localparam CIC_R = 100; |
localparam SAMP_INP_DW = 17; |
localparam SAMP_OUT_DW = 14; |
localparam CIC_N = 7; |
localparam CIC_M = 1;*/ |
|
/*************************************************************/ |
localparam integer CIC_RM = CIC_R * CIC_M; |
localparam real T_clk_ns = 8;//ns |
localparam time half_T = T_clk_ns/2; |
/// parameters of CIC filter with bits prune |
localparam B_max = B_max_calc(CIC_N, CIC_R, CIC_M, SAMP_INP_DW); |
localparam B_out = B_out_calc(CIC_N, CIC_R, CIC_M, SAMP_INP_DW, SAMP_OUT_DW); |
localparam B_2Np1 = B_max - SAMP_OUT_DW + 1; |
|
localparam delta_f_offs = 200; /// clock number to start delta-function in simulation |
/*************************************************************/ |
reg clk; ///< clock |
reg reset_n; ///< reset, active 0 |
wire signed [SAMP_INP_DW-1:0] filter_inp_data; ///< input test data of filter |
reg signed [SAMP_INP_DW-1:0] filter_inp_data_d[0:2]; ///< delayed filter_inp_data, for reference model |
wire filter_out_str; ///< filter output sample ready strobe |
reg filter_out_str_d; ///< filter_out_str delayed |
wire signed [SAMP_OUT_DW-1:0] filter_out; ///< filter output data |
reg signed [SAMP_OUT_DW-1:0] filter_out_reg; ///< |
wire signed [SAMP_OUT_DW-1:0] filter_out_ref_wire; ///< reference filter output data |
reg signed [SAMP_OUT_DW-1:0] filter_out_ref; ///< |
reg signed [SAMP_OUT_DW-1:0] filter_out_diff; ///< subtracting tested filter output and reference filter output |
integer clk_counter; ///< counter of clock periods |
integer samp_counter; ///< counter of input samples |
real phase_curr; ///< phase of input signal |
real phase_step; ///< step of input signal phase increment |
integer N_t_samp = 2; ///< period of input samples frequency in clocks |
integer samples_period_ctr; ///< counter for generating input samples period |
integer samples_period_val; ///< period of input samples in clocks |
wire samples_period_rdy; ///< signal is set at the end of input samples period |
real carry_freq; ///< frequency of test sin signal |
longint cic_taps[CIC_R * CIC_M * CIC_N]; ///< storage of internal state of reference CIC filter model |
integer cic_push_ptr; ///< pointer to the FIFO buffer of reference CIC model |
integer cic_model_out_int; ///< output of reference CIC model |
integer cic_B_prune; |
integer cic_B_prune_last_stage; |
longint cic_S_prune; |
longint cic_S_prune_last_stage; |
|
/// the reference model of a CIC filter |
task cic_model_reset; ///< set filter to the initial state |
integer i_s; |
integer i_t; |
for(i_s = CIC_N - 1; i_s >= 0; i_s = i_s - 1) |
for(i_t = 0; i_t < CIC_RM; i_t = i_t + 1) |
cic_taps[i_t + i_s * CIC_RM] = 0; |
cic_push_ptr = 0; |
endtask |
|
task cic_model_push(longint inp_samp); ///< add input sample |
integer i_s; |
for (i_s = CIC_N - 1; i_s >= 1; i_s = i_s - 1) |
cic_taps[cic_push_ptr + i_s * CIC_RM] = cic_model_stage_get_out(i_s - 1); |
cic_taps[cic_push_ptr] = inp_samp; |
if (cic_push_ptr < CIC_RM - 1) cic_push_ptr = cic_push_ptr + 1; |
else cic_push_ptr = 0; |
endtask |
|
function longint cic_model_stage_get_out(integer stage); ///< get output of stage |
integer i_t; |
cic_model_stage_get_out = 0; |
for(i_t = 0; i_t < CIC_RM; i_t = i_t + 1) |
cic_model_stage_get_out = cic_model_stage_get_out + cic_taps[i_t + stage * CIC_RM]; |
cic_model_stage_get_out = cic_model_stage_get_out / cic_S_prune; |
if (stage == CIC_N - 1) |
cic_model_stage_get_out = cic_model_stage_get_out / cic_S_prune_last_stage; |
endfunction |
|
/*************************************************************/ |
initial begin : clk_gen |
clk = 1'b0; |
clk_counter = 0; |
carry_freq = 10000; |
samples_period_val = 6; |
samples_period_ctr = 0; |
phase_curr <= 0; |
phase_step = T_clk_ns * samples_period_val * 2 * carry_freq * `M_PI * 0.000000001; |
cic_model_reset(); |
samp_counter <= 0; |
#half_T forever #half_T clk = ~clk; |
end |
/*************************************************************/ |
|
initial begin |
$dumpfile("../out/cic_d_tb.vcd"); |
$dumpvars(4, cic_d_tb); |
end |
|
|
initial begin : reset_gen |
|
reg [127:0] h_f0_pre; |
integer log2_h_f0_pre; |
integer h_f0_pre_limit_prec; |
integer h_f0_pre_divider; |
integer h_f0_divider_exp; |
real h_f0; |
integer B_max; |
integer B_out; |
integer B_2Np1; |
$display("tb CIC INP_DW %d", SAMP_INP_DW); |
$display("tb CIC OUT_DW %d", SAMP_OUT_DW); |
$display("tb CIC R %d", CIC_R); |
$display("tb CIC N %d", CIC_N); |
$display("tb CIC M %d", CIC_M); |
B_max = B_max_calc(CIC_N, CIC_R, CIC_M, SAMP_INP_DW); |
B_out = B_out_calc(CIC_N, CIC_R, CIC_M, SAMP_INP_DW, SAMP_OUT_DW); |
B_2Np1 = B_max - B_out + 1; |
$display("B_max= %2d, B_out = %2d, B_2N+1 = %2d", B_max, B_out, B_2Np1); |
h_f0_pre = (CIC_R*CIC_M)**CIC_N; |
h_f0_divider_exp = (B_2Np1 + 1); |
h_f0_pre_limit_prec = 30; |
log2_h_f0_pre = clog2_l(h_f0_pre); |
if (log2_h_f0_pre > h_f0_pre_limit_prec) begin |
$display(" log2_h_f0_pre = %2d, lim %2d", log2_h_f0_pre, h_f0_pre_limit_prec); |
h_f0_pre_divider = log2_h_f0_pre - h_f0_pre_limit_prec; |
$display(" h_f0_pre_divider = %2d", h_f0_pre_divider); |
h_f0_pre = h_f0_pre >> h_f0_pre_divider; |
h_f0_divider_exp = h_f0_divider_exp - h_f0_pre_divider; |
$display(" log2_h_f0_pre limited = %2d, divider_exp limited %2d", log2_h_f0_pre, h_f0_divider_exp); |
h_f0 = 1.0 * h_f0_pre / 2**(h_f0_divider_exp); |
end |
else begin |
h_f0 = h_f0 / 2**(B_2Np1 + 1); |
end |
$display("tb CIC h fwd %2.8f", h_f0); |
// to avoid overflow in reference model, use cic_B_prune to |
//cic_B_prune = B_2Np1 / CIC_N; |
cic_B_prune = 0; |
cic_S_prune = 1 << cic_B_prune; |
cic_B_prune_last_stage = B_2Np1 + 1 - cic_B_prune * CIC_N; |
cic_S_prune_last_stage = 1 << cic_B_prune_last_stage; |
$display("cic_B_prune = %2d, cic_B_prune_last = %2d, ", cic_B_prune, cic_B_prune_last_stage); |
$display($time, " << Starting the Simulation >>"); |
reset_n = 1'b0; |
repeat (2) @(negedge clk); |
$display($time, " << Coming out of reset >>"); |
reset_n = 1'b1; |
repeat (40000) @(posedge clk); |
@(posedge clk); |
$display($time, " << Simulation done >>"); |
$finish; |
|
end |
|
always @(posedge clk) if (~clk) clk_counter <= clk_counter + 1; |
/*************************************************************/ |
assign samples_period_rdy = samples_period_ctr >= (samples_period_val - 1); |
always @(posedge clk) |
if (samples_period_rdy) samples_period_ctr <= 0; |
else samples_period_ctr <= samples_period_ctr + 1; |
|
always @(posedge clk) |
begin |
if (samples_period_rdy == 1'b1) begin |
for (int i1 = 2; i1 >= 1; i1 = i1 - 1) filter_inp_data_d[i1] <= filter_inp_data_d[i1 - 1]; |
filter_inp_data_d[0] <= filter_inp_data; |
cic_model_push(filter_inp_data_d[1]); |
samp_counter <= samp_counter + 1; |
phase_curr <= phase_curr + phase_step; |
end |
end |
/*************************************************************/ |
assign filter_inp_data = $rtoi((2**(SAMP_INP_DW - INP_SAMP_WIDTH_TO_SIGNAL_WIDTH - 1) - 1)*($sin(phase_curr))); |
//assign filter_inp_data = samp_counter == delta_f_offs ? 10000 : 0; ///< delta function |
//assign filter_inp_data = samp_counter >= delta_f_offs && samp_counter < delta_f_offs + CIC_N ? 10000 : 0; |
//assign filter_inp_data = samp_counter >= delta_f_offs ? 10000 : 0; ///< Hamming function |
/*************************************************************/ |
cic_d #( |
.INP_DW (SAMP_INP_DW), |
.OUT_DW (SAMP_OUT_DW), |
.CIC_R (CIC_R), |
.CIC_N (CIC_N), |
.CIC_M (CIC_M), |
.SMALL_FOOTPRINT (SMALL_FOOTPRINT) |
) |
dut1 |
( |
.clk (clk), |
.reset_n (reset_n), |
.clear (1'b0), |
.inp_samp_data (filter_inp_data), |
.inp_samp_str (samples_period_rdy), |
.out_samp_data (filter_out), |
.out_samp_str (filter_out_str) |
); |
always @(posedge clk) |
filter_out_str_d <= filter_out_str; |
always @(posedge clk) |
begin |
if (filter_out_str == 1'b1) begin |
filter_out_reg <= filter_out; |
filter_out_ref <= cic_model_stage_get_out(CIC_N - 1); |
end |
end |
always @(posedge clk) |
begin |
if (filter_out_str_d == 1'b1) begin |
filter_out_diff <= filter_out - filter_out_ref; |
end |
end |
|
/*************************************************************/ |
endmodule |
|
`timescale 1ns / 1ns |
module cic_d_tb |
( |
); |
`include "../../rtl/verilog/cic_functions.vh" |
`define M_PI 3.14159265359 // not all simulators defines PI |
|
// U. Meyer-Baese, Digital Signal Processing with Field Programmable Gate Arrays, 2nd Edition, Spinger, 2004. |
// Example 5.5: Three-Stages CIC Decimator II |
/* |
localparam CIC_R = 32; |
localparam SAMP_INP_DW = 8; |
localparam SAMP_OUT_DW = 10; |
localparam INP_SAMP_WIDTH_TO_SIGNAL_WIDTH = 2; |
localparam CIC_N = 3; |
localparam CIC_M = 2; |
localparam SMALL_FOOTPRINT = 1; |
*/ |
/*localparam CIC_R = 100; |
localparam SAMP_INP_DW = 18; |
localparam SAMP_OUT_DW = 18; |
localparam INP_SAMP_WIDTH_TO_SIGNAL_WIDTH = 2; |
localparam CIC_N = 7; |
localparam CIC_M = 1; |
localparam SMALL_FOOTPRINT = 1; ///< set to 1 for less registers usage, but for every sample CIC_N clocks required |
*/ |
/* |
//https://www.so-logic.net/documents/trainings/03_so_implementation_of_filters.pdf |
localparam CIC_R = 16; |
localparam SAMP_INP_DW = 16; |
localparam SAMP_OUT_DW = 16; |
localparam INP_SAMP_WIDTH_TO_SIGNAL_WIDTH = 1; |
localparam CIC_N = 3; |
localparam CIC_M = 1; |
localparam SMALL_FOOTPRINT = 1; |
*/ |
/* |
// Eugene B. Hogenauer paper |
// B: 1, 6, 9, 13, 14, 15, 16, 17 |
localparam CIC_R = 25; |
localparam SAMP_INP_DW = 16; |
localparam SAMP_OUT_DW = 16; |
localparam CIC_N = 4; |
localparam CIC_M = 1; |
localparam SMALL_FOOTPRINT = 1; |
localparam INP_SAMP_WIDTH_TO_SIGNAL_WIDTH = 0; |
*/ |
/*localparam R = 8; |
localparam SAMP_INP_DW = 12; |
localparam SAMP_OUT_DW = 12; |
localparam M = 3; |
localparam G = 1;*/ |
|
localparam CIC_R = 100; |
localparam SAMP_INP_DW = 17; |
localparam SAMP_OUT_DW = 14; |
localparam CIC_N = 7; |
localparam CIC_M = 1; |
localparam SMALL_FOOTPRINT = 1; |
localparam INP_SAMP_WIDTH_TO_SIGNAL_WIDTH = 0; |
|
/*************************************************************/ |
localparam integer CIC_RM = CIC_R * CIC_M; |
localparam real T_clk_ns = 8;//ns |
localparam time half_T = T_clk_ns/2; |
/// parameters of CIC filter with bits prune |
localparam B_max = B_max_calc(CIC_N, CIC_R, CIC_M, SAMP_INP_DW); |
localparam B_out = B_out_calc(CIC_N, CIC_R, CIC_M, SAMP_INP_DW, SAMP_OUT_DW); |
localparam B_2Np1 = B_max - SAMP_OUT_DW + 1; |
|
localparam delta_f_offs = 200; /// clock number to start delta-function in simulation |
/*************************************************************/ |
reg clk; ///< clock |
reg reset_n; ///< reset, active 0 |
wire signed [SAMP_INP_DW-1:0] filter_inp_data; ///< input test data of filter |
reg signed [SAMP_INP_DW-1:0] filter_inp_data_d[0:2]; ///< delayed filter_inp_data, for reference model |
wire filter_out_str; ///< filter output sample ready strobe |
reg filter_out_str_d; ///< filter_out_str delayed |
wire signed [SAMP_OUT_DW-1:0] filter_out; ///< filter output data |
reg signed [SAMP_OUT_DW-1:0] filter_out_reg; ///< |
wire signed [SAMP_OUT_DW-1:0] filter_out_ref_wire; ///< reference filter output data |
reg signed [SAMP_OUT_DW-1:0] filter_out_ref; ///< |
reg signed [SAMP_OUT_DW-1:0] filter_out_diff; ///< subtracting tested filter output and reference filter output |
integer clk_counter; ///< counter of clock periods |
integer samp_counter; ///< counter of input samples |
real phase_curr; ///< phase of input signal |
real phase_step; ///< step of input signal phase increment |
integer N_t_samp = 2; ///< period of input samples frequency in clocks |
integer samples_period_ctr; ///< counter for generating input samples period |
integer samples_period_val; ///< period of input samples in clocks |
wire samples_period_rdy; ///< signal is set at the end of input samples period |
real carry_freq; ///< frequency of test sin signal |
longint cic_taps[CIC_R * CIC_M * CIC_N]; ///< storage of internal state of reference CIC filter model |
integer cic_push_ptr; ///< pointer to the FIFO buffer of reference CIC model |
integer cic_model_out_int; ///< output of reference CIC model |
integer cic_B_scale_out; |
integer cic_B_prune; |
integer cic_B_prune_last_stage; |
longint cic_S_prune; |
longint cic_S_prune_last_stage; |
|
/// the reference model of a CIC filter |
task cic_model_reset; ///< set filter to the initial state |
integer i_s; |
integer i_t; |
for(i_s = CIC_N - 1; i_s >= 0; i_s = i_s - 1) |
for(i_t = 0; i_t < CIC_RM; i_t = i_t + 1) |
cic_taps[i_t + i_s * CIC_RM] = 0; |
cic_push_ptr = 0; |
endtask |
|
task cic_model_push(longint inp_samp); ///< add input sample |
integer i_s; |
for (i_s = CIC_N - 1; i_s >= 1; i_s = i_s - 1) |
cic_taps[cic_push_ptr + i_s * CIC_RM] = cic_model_stage_get_out(i_s - 1); |
cic_taps[cic_push_ptr] = inp_samp; |
if (cic_push_ptr < CIC_RM - 1) cic_push_ptr = cic_push_ptr + 1; |
else cic_push_ptr = 0; |
endtask |
|
function longint cic_model_stage_get_out(integer stage); ///< get output of stage |
integer i_t; |
cic_model_stage_get_out = 0; |
for(i_t = 0; i_t < CIC_RM; i_t = i_t + 1) |
cic_model_stage_get_out = cic_model_stage_get_out + cic_taps[i_t + stage * CIC_RM]; |
cic_model_stage_get_out = cic_model_stage_get_out / cic_S_prune; |
if (stage == CIC_N - 1) |
cic_model_stage_get_out = cic_model_stage_get_out / cic_S_prune_last_stage; |
endfunction |
|
/*************************************************************/ |
initial begin : clk_gen |
clk = 1'b0; |
clk_counter = 0; |
carry_freq = 10000; |
samples_period_val = 6; |
samples_period_ctr = 0; |
phase_curr <= 0; |
phase_step = T_clk_ns * samples_period_val * 2 * carry_freq * `M_PI * 0.000000001; |
cic_model_reset(); |
samp_counter <= 0; |
#half_T forever #half_T clk = ~clk; |
end |
/*************************************************************/ |
|
initial begin |
$dumpfile("../out/cic_d_tb.vcd"); |
$dumpvars(4, cic_d_tb); |
end |
|
|
initial begin : reset_gen |
|
reg [127:0] h_f0_pre; |
integer log2_h_f0_pre; |
integer h_f0_pre_limit_prec; |
integer h_f0_pre_divider; |
integer h_f0_divider_exp; |
real h_f0; |
integer B_max; |
integer B_out; |
integer B_2Np1; |
$display("tb CIC INP_DW %d", SAMP_INP_DW); |
$display("tb CIC OUT_DW %d", SAMP_OUT_DW); |
$display("tb CIC R %d", CIC_R); |
$display("tb CIC N %d", CIC_N); |
$display("tb CIC M %d", CIC_M); |
B_max = B_max_calc(CIC_N, CIC_R, CIC_M, SAMP_INP_DW); |
B_out = B_out_calc(CIC_N, CIC_R, CIC_M, SAMP_INP_DW, SAMP_OUT_DW); |
//B_2Np1 = B_max - B_out + 1; |
B_2Np1 = B_calc(CIC_N * 2, CIC_N, CIC_R, CIC_M, SAMP_INP_DW, SAMP_OUT_DW); |
$display("B_max= %2d, B_out = %2d, B_2N+1 = %2d", B_max, B_out, B_2Np1); |
h_f0_pre = (CIC_R*CIC_M)**CIC_N; |
h_f0_divider_exp = (B_2Np1 + 1); |
h_f0_pre_limit_prec = 30; |
log2_h_f0_pre = clog2_l(h_f0_pre); |
$display(" log2_h_f0_pre = %2d, lim %2d", log2_h_f0_pre, h_f0_pre_limit_prec); |
if (log2_h_f0_pre > h_f0_pre_limit_prec) begin |
h_f0_pre_divider = log2_h_f0_pre - h_f0_pre_limit_prec; |
$display(" h_f0_pre_divider = %2d", h_f0_pre_divider); |
h_f0_pre = h_f0_pre >> h_f0_pre_divider; |
h_f0_divider_exp = h_f0_divider_exp - h_f0_pre_divider; |
$display(" log2_h_f0_pre limited = %2d, divider_exp limited %2d", log2_h_f0_pre, h_f0_divider_exp); |
h_f0 = 1.0 * h_f0_pre / 2**(h_f0_divider_exp); |
end |
else begin |
h_f0 = h_f0_pre / 2**(B_2Np1 + 1); |
end |
$display("tb CIC h fwd %2.8f", h_f0); |
// to avoid overflow in reference model, use cic_B_prune to |
//cic_B_prune = B_2Np1 / CIC_N; |
cic_B_scale_out = B_max + 1 - SAMP_OUT_DW; |
cic_B_prune = 0; |
cic_S_prune = 1 << cic_B_prune; |
//cic_B_prune_last_stage = B_2Np1 + 1 - cic_B_prune * CIC_N; |
cic_B_prune_last_stage = cic_B_scale_out - cic_B_prune * CIC_N; |
cic_S_prune_last_stage = 1 << cic_B_prune_last_stage; |
$display("model:"); |
$display(" B_max=%2d; B_out=%2d; cic_B_scale_out=%2d", B_max, B_out, cic_B_scale_out); |
$display("cic_B_prune = %2d, cic_B_prune_last = %2d, ", cic_B_prune, cic_B_prune_last_stage); |
$display($time, " << Starting the Simulation >>"); |
reset_n = 1'b0; |
repeat (2) @(negedge clk); |
//$finish; |
$display($time, " << Coming out of reset >>"); |
reset_n = 1'b1; |
repeat (40000) @(posedge clk); |
@(posedge clk); |
$display($time, " << Simulation done >>"); |
$finish; |
|
end |
|
always @(posedge clk) if (~clk) clk_counter <= clk_counter + 1; |
/*************************************************************/ |
assign samples_period_rdy = samples_period_ctr >= (samples_period_val - 1); |
always @(posedge clk) |
if (samples_period_rdy) samples_period_ctr <= 0; |
else samples_period_ctr <= samples_period_ctr + 1; |
|
always @(posedge clk) |
begin |
if (samples_period_rdy == 1'b1) begin |
for (int i1 = 2; i1 >= 1; i1 = i1 - 1) filter_inp_data_d[i1] <= filter_inp_data_d[i1 - 1]; |
filter_inp_data_d[0] <= filter_inp_data; |
cic_model_push(filter_inp_data_d[1]); |
samp_counter <= samp_counter + 1; |
phase_curr <= phase_curr + phase_step; |
end |
end |
/*************************************************************/ |
assign filter_inp_data = $rtoi((2**(SAMP_INP_DW - INP_SAMP_WIDTH_TO_SIGNAL_WIDTH - 1) - 1)*($sin(phase_curr))); |
//assign filter_inp_data = samp_counter == delta_f_offs ? 10000 : 0; ///< delta function |
//assign filter_inp_data = samp_counter >= delta_f_offs && samp_counter < delta_f_offs + CIC_N ? 10000 : 0; |
//assign filter_inp_data = samp_counter >= delta_f_offs ? 1 << (SAMP_INP_DW / 2) : 0; ///< Hamming function |
//assign filter_inp_data = samp_counter >= delta_f_offs ? 1 << (SAMP_INP_DW - INP_SAMP_WIDTH_TO_SIGNAL_WIDTH -1 ) : 0; ///< Hamming function |
/*************************************************************/ |
|
cic_d #( |
.INP_DW (SAMP_INP_DW), |
.OUT_DW (SAMP_OUT_DW), |
.CIC_R (CIC_R), |
.CIC_N (CIC_N), |
.CIC_M (CIC_M), |
.SMALL_FOOTPRINT (SMALL_FOOTPRINT) |
) |
dut1 |
( |
.clk (clk), |
.reset_n (reset_n), |
.clear (1'b0), |
.inp_samp_data (filter_inp_data), |
.inp_samp_str (samples_period_rdy), |
.out_samp_data (filter_out), |
.out_samp_str (filter_out_str) |
); |
always @(posedge clk) |
filter_out_str_d <= filter_out_str; |
always @(posedge clk) |
begin |
if (filter_out_str == 1'b1) begin |
filter_out_reg <= filter_out; |
filter_out_ref <= cic_model_stage_get_out(CIC_N - 1); |
end |
end |
always @(posedge clk) |
begin |
if (filter_out_str_d == 1'b1) begin |
filter_out_diff <= filter_out - filter_out_ref; |
end |
end |
|
/*************************************************************/ |
endmodule |
|