OpenCores
URL https://opencores.org/ocsvn/cic_core_2/cic_core_2/trunk

Subversion Repositories cic_core_2

[/] [cic_core_2/] [trunk/] [rtl_sim/] [src/] [cic_d_tb.sv] - Blame information for rev 7

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 7 Juzujka
`timescale 1ns / 1ns
2
module cic_d_tb
3
(
4
);
5
`include "../../rtl/verilog/cic_functions.vh"
6
`define M_PI 3.14159265359      // not all simulators defines PI
7
 
8
// U. Meyer-Baese, Digital Signal Processing with Field Programmable Gate Arrays, 2nd Edition, Spinger, 2004.
9
// Example 5.5: Three-Stages CIC Decimator II
10
/*
11
localparam CIC_R = 32;
12
localparam SAMP_INP_DW = 8;
13
localparam SAMP_OUT_DW = 10;
14
localparam INP_SAMP_WIDTH_TO_SIGNAL_WIDTH = 2;
15
localparam CIC_N = 3;
16
localparam CIC_M = 2;
17
localparam SMALL_FOOTPRINT = 1;
18
*/
19
/*localparam CIC_R = 100;
20
localparam SAMP_INP_DW = 18;
21
localparam SAMP_OUT_DW = 18;
22
localparam INP_SAMP_WIDTH_TO_SIGNAL_WIDTH = 2;
23
localparam CIC_N = 7;
24
localparam CIC_M = 1;
25
localparam SMALL_FOOTPRINT = 1; ///< set to 1 for less registers usage, but for every sample CIC_N clocks required
26
*/
27
/*
28
//https://www.so-logic.net/documents/trainings/03_so_implementation_of_filters.pdf
29
localparam CIC_R = 16;
30
localparam SAMP_INP_DW = 16;
31
localparam SAMP_OUT_DW = 16;
32
localparam INP_SAMP_WIDTH_TO_SIGNAL_WIDTH = 1;
33
localparam CIC_N = 3;
34
localparam CIC_M = 1;
35
localparam SMALL_FOOTPRINT = 1;
36
*/
37
/*
38
// Eugene B. Hogenauer paper
39
// B: 1, 6, 9, 13, 14, 15, 16, 17
40
localparam CIC_R = 25;
41
localparam SAMP_INP_DW = 16;
42
localparam SAMP_OUT_DW = 16;
43
localparam CIC_N = 4;
44
localparam CIC_M = 1;
45
localparam SMALL_FOOTPRINT = 1;
46
localparam INP_SAMP_WIDTH_TO_SIGNAL_WIDTH = 0;
47
*/
48
/*localparam R = 8;
49
localparam SAMP_INP_DW = 12;
50
localparam SAMP_OUT_DW = 12;
51
localparam M = 3;
52
localparam G = 1;*/
53
 
54
localparam CIC_R = 100;
55
localparam SAMP_INP_DW = 17;
56
localparam SAMP_OUT_DW = 14;
57
localparam CIC_N = 7;
58
localparam CIC_M = 1;
59
localparam SMALL_FOOTPRINT = 1;
60
localparam INP_SAMP_WIDTH_TO_SIGNAL_WIDTH = 0;
61
 
62
/*************************************************************/
63
localparam integer CIC_RM = CIC_R * CIC_M;
64
localparam real T_clk_ns = 8;//ns
65
localparam time half_T = T_clk_ns/2;
66
/// parameters of CIC filter with bits prune
67
localparam B_max = B_max_calc(CIC_N, CIC_R, CIC_M, SAMP_INP_DW);
68
localparam B_out = B_out_calc(CIC_N, CIC_R, CIC_M, SAMP_INP_DW, SAMP_OUT_DW);
69
localparam B_2Np1 = B_max - SAMP_OUT_DW + 1;
70
 
71
localparam delta_f_offs = 200;  /// clock number to start delta-function in simulation
72
/*************************************************************/
73
reg                                                                     clk;                                    ///< clock
74
reg                                                                     reset_n;                                ///< reset, active 0
75
wire    signed  [SAMP_INP_DW-1:0]       filter_inp_data;                ///< input test data of filter
76
reg             signed  [SAMP_INP_DW-1:0]       filter_inp_data_d[0:2]; ///< delayed filter_inp_data, for reference model
77
wire                                            filter_out_str;                 ///< filter output sample ready strobe
78
reg                                                                     filter_out_str_d;               ///< filter_out_str delayed
79
wire    signed  [SAMP_OUT_DW-1:0]       filter_out;                             ///< filter output data
80
reg             signed  [SAMP_OUT_DW-1:0]       filter_out_reg;                 ///<
81
wire    signed  [SAMP_OUT_DW-1:0]       filter_out_ref_wire;    ///< reference filter output data
82
reg     signed  [SAMP_OUT_DW-1:0]       filter_out_ref;                 ///<
83
reg             signed  [SAMP_OUT_DW-1:0]       filter_out_diff;                ///< subtracting tested filter output and reference filter output
84
integer clk_counter;    ///< counter of clock periods
85
integer samp_counter;   ///< counter of input samples
86
real phase_curr;                ///< phase of input signal
87
real phase_step;                ///< step of input signal phase increment
88
integer N_t_samp = 2;   ///< period of input samples frequency in clocks
89
integer samples_period_ctr;     ///< counter for generating input samples period
90
integer samples_period_val;     ///< period of input samples in clocks
91
wire    samples_period_rdy;     ///< signal is set at the end of input samples period
92
real    carry_freq;                     ///< frequency of test sin signal
93
longint cic_taps[CIC_R * CIC_M * CIC_N];        ///< storage of internal state of reference CIC filter model
94
integer cic_push_ptr;                                           ///< pointer to the FIFO buffer of reference CIC model
95
integer cic_model_out_int;                                      ///< output of reference CIC model
96
integer cic_B_scale_out;
97
integer cic_B_prune;
98
integer cic_B_prune_last_stage;
99
longint cic_S_prune;
100
longint cic_S_prune_last_stage;
101
 
102
/// the reference model of a CIC filter
103
task cic_model_reset;   ///< set filter to the initial state
104
        integer i_s;
105
        integer i_t;
106
        for(i_s = CIC_N - 1; i_s >= 0; i_s = i_s - 1)
107
                for(i_t = 0; i_t < CIC_RM; i_t = i_t + 1)
108
                        cic_taps[i_t + i_s * CIC_RM] = 0;
109
        cic_push_ptr = 0;
110
endtask
111
 
112
task cic_model_push(longint inp_samp);  ///< add input sample
113
        integer i_s;
114
        for (i_s = CIC_N - 1; i_s >= 1; i_s = i_s - 1)
115
                cic_taps[cic_push_ptr + i_s * CIC_RM] = cic_model_stage_get_out(i_s - 1);
116
        cic_taps[cic_push_ptr] = inp_samp;
117
        if (cic_push_ptr < CIC_RM - 1)          cic_push_ptr = cic_push_ptr + 1;
118
        else                                                            cic_push_ptr = 0;
119
endtask
120
 
121
function longint cic_model_stage_get_out(integer stage);        ///< get output of stage
122
        integer i_t;
123
        cic_model_stage_get_out = 0;
124
        for(i_t = 0; i_t < CIC_RM; i_t = i_t + 1)
125
                cic_model_stage_get_out = cic_model_stage_get_out + cic_taps[i_t + stage * CIC_RM];
126
        cic_model_stage_get_out = cic_model_stage_get_out / cic_S_prune;
127
        if (stage == CIC_N - 1)
128
                cic_model_stage_get_out = cic_model_stage_get_out / cic_S_prune_last_stage;
129
endfunction
130
 
131
/*************************************************************/
132
initial begin : clk_gen
133
        clk = 1'b0;
134
        clk_counter = 0;
135
        carry_freq = 10000;
136
        samples_period_val = 6;
137
        samples_period_ctr = 0;
138
        phase_curr <= 0;
139
        phase_step = T_clk_ns * samples_period_val * 2 * carry_freq * `M_PI * 0.000000001;
140
        cic_model_reset();
141
        samp_counter <= 0;
142
        #half_T forever #half_T clk = ~clk;
143
end
144
/*************************************************************/
145
 
146
initial begin
147
        $dumpfile("../out/cic_d_tb.vcd");
148
        $dumpvars(4, cic_d_tb);
149
end
150
 
151
 
152
initial begin : reset_gen
153
 
154
        reg [127:0] h_f0_pre;
155
        integer log2_h_f0_pre;
156
        integer h_f0_pre_limit_prec;
157
        integer h_f0_pre_divider;
158
        integer h_f0_divider_exp;
159
        real    h_f0;
160
        integer B_max;
161
        integer B_out;
162
        integer B_2Np1;
163
        $display("tb CIC INP_DW      %d", SAMP_INP_DW);
164
        $display("tb CIC OUT_DW      %d", SAMP_OUT_DW);
165
        $display("tb CIC R        %d", CIC_R);
166
        $display("tb CIC N        %d", CIC_N);
167
        $display("tb CIC M        %d", CIC_M);
168
        B_max = B_max_calc(CIC_N, CIC_R, CIC_M, SAMP_INP_DW);
169
        B_out = B_out_calc(CIC_N, CIC_R, CIC_M, SAMP_INP_DW, SAMP_OUT_DW);
170
        //B_2Np1 = B_max - B_out + 1;
171
        B_2Np1 = B_calc(CIC_N * 2, CIC_N, CIC_R, CIC_M, SAMP_INP_DW, SAMP_OUT_DW);
172
        $display("B_max= %2d, B_out = %2d, B_2N+1 = %2d", B_max, B_out, B_2Np1);
173
        h_f0_pre = (CIC_R*CIC_M)**CIC_N;
174
        h_f0_divider_exp = (B_2Np1 + 1);
175
        h_f0_pre_limit_prec = 30;
176
        log2_h_f0_pre = clog2_l(h_f0_pre);
177
        $display(" log2_h_f0_pre = %2d, lim %2d", log2_h_f0_pre, h_f0_pre_limit_prec);
178
        if (log2_h_f0_pre > h_f0_pre_limit_prec) begin
179
                h_f0_pre_divider = log2_h_f0_pre - h_f0_pre_limit_prec;
180
                $display(" h_f0_pre_divider = %2d", h_f0_pre_divider);
181
                h_f0_pre = h_f0_pre >> h_f0_pre_divider;
182
                h_f0_divider_exp = h_f0_divider_exp - h_f0_pre_divider;
183
                $display(" log2_h_f0_pre limited = %2d, divider_exp limited %2d", log2_h_f0_pre, h_f0_divider_exp);
184
                h_f0 = 1.0 * h_f0_pre / 2**(h_f0_divider_exp);
185
        end
186
        else begin
187
                h_f0 = h_f0_pre / 2**(B_2Np1 + 1);
188
        end
189
        $display("tb CIC h fwd    %2.8f", h_f0);
190
        // to avoid overflow in reference model, use cic_B_prune to
191
        //cic_B_prune = B_2Np1 / CIC_N;
192
        cic_B_scale_out = B_max + 1 - SAMP_OUT_DW;
193
        cic_B_prune = 0;
194
        cic_S_prune = 1 << cic_B_prune;
195
        //cic_B_prune_last_stage = B_2Np1 + 1 - cic_B_prune * CIC_N;
196
        cic_B_prune_last_stage = cic_B_scale_out - cic_B_prune * CIC_N;
197
        cic_S_prune_last_stage = 1 << cic_B_prune_last_stage;
198
        $display("model:");
199
        $display(" B_max=%2d; B_out=%2d; cic_B_scale_out=%2d", B_max, B_out, cic_B_scale_out);
200
        $display("cic_B_prune = %2d, cic_B_prune_last = %2d, ", cic_B_prune, cic_B_prune_last_stage);
201
        $display($time, " << Starting the Simulation >>");
202
        reset_n = 1'b0;
203
        repeat (2) @(negedge clk);
204
        //$finish;
205
        $display($time, " << Coming out of reset >>");
206
        reset_n = 1'b1;
207
        repeat (40000) @(posedge clk);
208
        @(posedge clk);
209
        $display($time, " << Simulation done >>");
210
        $finish;
211
 
212
end
213
 
214
always @(posedge clk) if (~clk) clk_counter <= clk_counter + 1;
215
/*************************************************************/
216
assign samples_period_rdy = samples_period_ctr >= (samples_period_val - 1);
217
always @(posedge clk)
218
        if (samples_period_rdy) samples_period_ctr <= 0;
219
        else                            samples_period_ctr <= samples_period_ctr + 1;
220
 
221
always @(posedge clk)
222
begin
223
        if (samples_period_rdy == 1'b1) begin
224
                for (int i1 = 2; i1 >= 1; i1 = i1 - 1) filter_inp_data_d[i1] <= filter_inp_data_d[i1 - 1];
225
                filter_inp_data_d[0] <= filter_inp_data;
226
                cic_model_push(filter_inp_data_d[1]);
227
                samp_counter <= samp_counter + 1;
228
                phase_curr <= phase_curr + phase_step;
229
        end
230
end
231
/*************************************************************/
232
assign filter_inp_data = $rtoi((2**(SAMP_INP_DW - INP_SAMP_WIDTH_TO_SIGNAL_WIDTH - 1) - 1)*($sin(phase_curr)));
233
//assign filter_inp_data = samp_counter == delta_f_offs ? 10000 : 0;    ///< delta function
234
//assign filter_inp_data = samp_counter >= delta_f_offs && samp_counter < delta_f_offs + CIC_N ? 10000 : 0;
235
//assign filter_inp_data = samp_counter >= delta_f_offs ? 1 << (SAMP_INP_DW / 2) : 0;   ///< Hamming function
236
//assign filter_inp_data = samp_counter >= delta_f_offs ? 1 << (SAMP_INP_DW - INP_SAMP_WIDTH_TO_SIGNAL_WIDTH -1 ) : 0;  ///< Hamming function
237
/*************************************************************/
238
 
239
cic_d #(
240
        .INP_DW                         (SAMP_INP_DW),
241
        .OUT_DW                         (SAMP_OUT_DW),
242
        .CIC_R                          (CIC_R),
243
        .CIC_N                          (CIC_N),
244
        .CIC_M                          (CIC_M),
245
        .SMALL_FOOTPRINT        (SMALL_FOOTPRINT)
246
)
247
dut1
248
(
249
    .clk                        (clk),
250
    .reset_n            (reset_n),
251
    .clear                      (1'b0),
252
    .inp_samp_data      (filter_inp_data),
253
    .inp_samp_str       (samples_period_rdy),
254
    .out_samp_data      (filter_out),
255
    .out_samp_str       (filter_out_str)
256
);
257
always @(posedge clk)
258
        filter_out_str_d <= filter_out_str;
259
always @(posedge clk)
260
begin
261
        if (filter_out_str == 1'b1) begin
262
                filter_out_reg  <= filter_out;
263
                filter_out_ref  <= cic_model_stage_get_out(CIC_N - 1);
264
        end
265
end
266
always @(posedge clk)
267
begin
268
        if (filter_out_str_d == 1'b1) begin
269
                filter_out_diff <= filter_out - filter_out_ref;
270
        end
271
end
272
 
273
/*************************************************************/
274
endmodule
275
 

powered by: WebSVN 2.1.0

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