OpenCores
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
    /cic_core_2/trunk/rtl/verilog
    from Rev 6 to Rev 7
    Reverse comparison

Rev 6 → Rev 7

/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_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_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
/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
/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
/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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.