I have the following code for sinc3 digital filter in verilog:-
`timescale 1ns / 1ps
module dec256sinc24b
(input mclk1, /* used to clk filter */
input reset, /* used to reset filter */
input mdata1, /* input data to be filtered */
output reg [15:0] DATA, /* filtered output*/
output reg data_en,
input [15:0] dec_rate
);
/* Data is read on negative clk edge */
reg [36:0] ip_data1;
reg [36:0] acc1;
reg [36:0] acc2;
reg [36:0] acc3;
reg [36:0] acc3_d2;
reg [36:0] diff1;
reg [36:0] diff2;
reg [36:0] diff3;
reg [36:0] diff1_d;
reg [36:0] diff2_d;
reg [15:0] word_count;
reg word_clk;
reg enable;
/*Perform the Sinc action*/
always @ (mdata1)
if(mdata1==0)
ip_data1 <= 37'd0;
/* change 0 to a -1 for twos complement */
else
ip_data1 <= 37'd1;
/*Accumulator (Integrator)
Perform the accumulation (IIR) at the speed of the modulator.
Z = one sample delay MCLKOUT = modulators conversion bit rate */
always @ (negedge mclk1, posedge reset)
begin
if (reset)
begin
/* initialize acc registers on reset*/
acc1 <= 37'd0;
acc2 <= 37'd0;
acc3 <= 37'd0;
end
else
begin
/*perform accumulation process */
acc1 <= acc1 + ip_data1;
acc2 <= acc2 + acc1;
acc3 <= acc3 + acc2;
end
end
/*decimation stage (MCLKOUT/WORD_CLK) */
always @ (negedge mclk1, posedge reset)
begin
if (reset)
word_count <= 16'd0;
else
begin
if ( word_count == dec_rate - 1 )
word_count <= 16'd0;
else
word_count <= word_count + 16'b1;
end
end
always @ ( negedge mclk1, posedge reset )
begin
if ( reset )
word_clk <= 1'b0;
else
begin
if ( word_count == dec_rate/2 - 1 )
word_clk <= 1'b1;
else if ( word_count == dec_rate - 1 )
word_clk <= 1'b0;
end
end
/*Differentiator (including decimation stage)
Perform the differentiation stage (FIR) at a lower speed.
Z = one sample delay WORD_CLK = output word rate */
always @ (negedge word_clk, posedge reset)
begin
if(reset)
begin
acc3_d2 <= 37'd0;
diff1_d <= 37'd0;
diff2_d <= 37'd0;
diff1 <= 37'd0;
diff2 <= 37'd0;
diff3 <= 37'd0;
end
else
begin
diff1 <= acc3 - acc3_d2;
diff2 <= diff1 - diff1_d;
diff3 <= diff2 - diff2_d;
acc3_d2 <= acc3;
diff1_d <= diff1;
diff2_d <= diff2;
end
end
/* Clock the Sinc output into an output register
WORD_CLK = output word rate */
always @ (negedge word_clk )
begin
case ( dec_rate )
16'd32:begin
DATA <= (diff3[15:0] == 16'h8000) ? 16'hFFFF : {diff3[14:0], 1'b0};
end
16'd64:begin
DATA <= (diff3[18:2] == 17'h10000) ? 16'hFFFF : diff3[17:2];
end
16'd128:begin
DATA <= (diff3[21:5] == 17'h10000) ? 16'hFFFF : diff3[20:5];
end
16'd256:begin
DATA <= (diff3[24:8] == 17'h10000) ? 16'hFFFF : diff3[23:8];
end
16'd512:begin
DATA <= (diff3[27:11] == 17'h10000) ? 16'hFFFF : diff3[26:11];
end
16'd1024:begin
DATA <= (diff3[30:14] == 17'h10000) ? 16'hFFFF : diff3[29:14];
end
16'd2048:begin
DATA <= (diff3[33:17] == 17'h10000) ? 16'hFFFF : diff3[32:17];
end
16'd4096:begin
DATA <= (diff3[36:20] == 17'h10000) ? 16'hFFFF : diff3[35:20];
end
default:begin
DATA <= (diff3[24:8] == 17'h10000) ? 16'hFFFF : diff3[23:8];
end
endcase
end
/* Synchronize Data Output*/
always@ (negedge mclk1, posedge reset )
begin
if ( reset )
begin
data_en <= 1'b0;
enable <= 1'b1;
end
else
begin
if ( (word_count == dec_rate/2 - 1) && enable )
begin
data_en <= 1'b1;
enable <= 1'b0;
end
else if ( (word_count == dec_rate - 1) && ~enable )
begin
data_en <= 1'b0;
enable <= 1'b1;
end
else
data_en <= 1'b0;
end
end
endmodule
I have written a testbench for the same, with the following inputs: mclk1 = 10MHz, mdata1 = 5MHz and dec_rate = 64
`timescale 1ns / 1ps
`define SIM_CYCLE 8192
module sinc3_tb;
//Inputs
reg mclk1;
reg reset;
reg mdata1;
reg [15:0] dec_rate;
//outputs
wire [15:0] DATA;
wire data_en;
//debug
wire [36:0] diff3 = dec256sinc24b_inst.diff3;
// Instantiate the Unit Under Test (UUT)
dec256sinc24b dec256sinc24b_inst(
.mclk1(mclk1),
.reset(reset),
.dec_rate(dec_rate),
/*************************************/
.mdata1(mdata1),
.DATA(DATA),
.data_en(data_en)
);
/*************************************/
// mclk1 = 10MHz
always#(50)
begin
mclk1 <= ~mclk1;
end
// mdata1 = 5MHz
always@(posedge mclk1)
begin
mdata1 <= ~mdata1;
end
initial begin
// Initialize Inputs
mclk1 = 1'b0;
reset = 1'b0;
mdata1 = 1'b0;
dec_rate = 16'd64;
// Add stimulus here
#5 reset = 1'b1;
#(`SIM_CYCLE) $finish;
end
endmodule
When I run the simulation, I don’t get any output for the DATA and diff3 as seen in the simulation below. Any suggestions how should I fix this issue?
Also why is the dec_rate = 40? Since, I have set it to 64?
>Solution :
The problem is how you are driving the reset from your testbench. Your design uses an active-high reset, but your testbench sets the reset to 1 for most of the simulation, keeping the design always in reset.
You need to invert the polarity of the reset signal inside the testbench. Assert the reset at time 0, then release the reset at time 5:
initial begin
// Initialize Inputs
mclk1 = 1'b0;
reset = 1'b1;
mdata1 = 1'b0;
dec_rate = 16'd64;
// Add stimulus here
#5 reset = 1'b0;
#(`SIM_CYCLE) $finish;
end
Also, run your simulation for more time to see DATA change from 0. For example:
`define SIM_CYCLE 8192*10
If you want to run for 1ms:
`define SIM_CYCLE 1_000_000
Your waveform display is set to hexadecimal format. 40 is 0x40, which is the same as 64 decimal.
