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 3 to Rev 4
- ↔ Reverse comparison
Rev 3 → Rev 4
/cic_core_2/trunk/trunk/doc/src/CIC_filter_ug.odt
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
cic_core_2/trunk/trunk/doc/src/CIC_filter_ug.odt
Property changes :
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Index: cic_core_2/trunk/trunk/rtl/verilog/cic_d.sv
===================================================================
--- cic_core_2/trunk/trunk/rtl/verilog/cic_d.sv (nonexistent)
+++ cic_core_2/trunk/trunk/rtl/verilog/cic_d.sv (revision 4)
@@ -0,0 +1,232 @@
+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 "../src/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
Index: cic_core_2/trunk/trunk/rtl/verilog/cic_functions.vh
===================================================================
--- cic_core_2/trunk/trunk/rtl/verilog/cic_functions.vh (nonexistent)
+++ cic_core_2/trunk/trunk/rtl/verilog/cic_functions.vh (revision 4)
@@ -0,0 +1,157 @@
+/**
+ * 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
+
Index: cic_core_2/trunk/trunk/rtl/verilog/cic_i.sv
===================================================================
--- cic_core_2/trunk/trunk/rtl/verilog/cic_i.sv (nonexistent)
+++ cic_core_2/trunk/trunk/rtl/verilog/cic_i.sv (revision 4)
@@ -0,0 +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
Index: cic_core_2/trunk/trunk/rtl/verilog/comb.sv
===================================================================
--- cic_core_2/trunk/trunk/rtl/verilog/comb.sv (nonexistent)
+++ cic_core_2/trunk/trunk/rtl/verilog/comb.sv (revision 4)
@@ -0,0 +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
Index: cic_core_2/trunk/trunk/rtl/verilog/downsampler.sv
===================================================================
--- cic_core_2/trunk/trunk/rtl/verilog/downsampler.sv (nonexistent)
+++ cic_core_2/trunk/trunk/rtl/verilog/downsampler.sv (revision 4)
@@ -0,0 +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
Index: cic_core_2/trunk/trunk/rtl/verilog/integrator.sv
===================================================================
--- cic_core_2/trunk/trunk/rtl/verilog/integrator.sv (nonexistent)
+++ cic_core_2/trunk/trunk/rtl/verilog/integrator.sv (revision 4)
@@ -0,0 +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
Index: cic_core_2/trunk/trunk/sim/rtl_sim/run/cic_d_gtkwave_run.sh
===================================================================
--- cic_core_2/trunk/trunk/sim/rtl_sim/run/cic_d_gtkwave_run.sh (nonexistent)
+++ cic_core_2/trunk/trunk/sim/rtl_sim/run/cic_d_gtkwave_run.sh (revision 4)
@@ -0,0 +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
cic_core_2/trunk/trunk/sim/rtl_sim/run/cic_d_gtkwave_run.sh
Property changes :
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: cic_core_2/trunk/trunk/sim/rtl_sim/run/cic_d_sim_run.sh
===================================================================
--- cic_core_2/trunk/trunk/sim/rtl_sim/run/cic_d_sim_run.sh (nonexistent)
+++ cic_core_2/trunk/trunk/sim/rtl_sim/run/cic_d_sim_run.sh (revision 4)
@@ -0,0 +1,6 @@
+#!/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"
cic_core_2/trunk/trunk/sim/rtl_sim/run/cic_d_sim_run.sh
Property changes :
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: cic_core_2/trunk/trunk/sim/rtl_sim/src/cic_core_tb.gtkw
===================================================================
--- cic_core_2/trunk/trunk/sim/rtl_sim/src/cic_core_tb.gtkw (nonexistent)
+++ cic_core_2/trunk/trunk/sim/rtl_sim/src/cic_core_tb.gtkw (revision 4)
@@ -0,0 +1,32 @@
+[*]
+[*] GTKWave Analyzer v3.3.86 (w)1999-2017 BSI
+[*] Mon Aug 19 14:58:47 2019
+[*]
+[dumpfile] "/home/ibragimove/My_Designs/Hydra_SoC/trunk/Hydra_SoC_AFE5808_to_MSGDMA_8_as_1/CIC_core/trunk/sim/cic_d_tb.vcd"
+[dumpfile_mtime] "Mon Aug 19 14:49:53 2019"
+[dumpfile_size] 8766018
+[savefile] "/home/ibragimove/My_Designs/Hydra_SoC/trunk/Hydra_SoC_AFE5808_to_MSGDMA_8_as_1/CIC_core/trunk/sim/cic_core_tb.gtkw"
+[timestart] 0
+[size] 1020 597
+[pos] 61 31
+*-18.000000 127000 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
+[treeopen] cic_d_tb.
+[sst_width] 223
+[signals_width] 271
+[sst_expanded] 1
+[sst_vpaned_height] 151
+@28
+cic_d_tb.clk
+@8420
+cic_d_tb.filter_inp_data[17:0]
+cic_d_tb.filter_out[17:0]
+@28
+cic_d_tb.filter_out_str
+@8420
+cic_d_tb.filter_out_ref[17:0]
+@28
+cic_d_tb.phase_curr
+cic_d_tb.samp_duty_rdy
+cic_d_tb.phase_step
+[pattern_trace] 1
+[pattern_trace] 0
Index: cic_core_2/trunk/trunk/sim/rtl_sim/src/cic_d_tb.sv
===================================================================
--- cic_core_2/trunk/trunk/sim/rtl_sim/src/cic_d_tb.sv (nonexistent)
+++ cic_core_2/trunk/trunk/sim/rtl_sim/src/cic_d_tb.sv (revision 4)
@@ -0,0 +1,252 @@
+`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
+