Reputation: 1863
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?
Upvotes: 1
Views: 323
Reputation: 62019
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.
Upvotes: 1
Reputation: 2508
DATA is stuck at 0 because its re-timed by word_clk, and word_clk is stuck at 0.
The signal word_clk is stuck at 0 because reset is high and it holds word_clk at 0.
You are also not running it for enough time to see any data come out.
Try runing for 8192*8 rather than 8192 cycles.
The entire design is held in reset forever.
By the way its bad practice to generate clocks using always blocks in your RTL. It might work in simulation and not in a synthesis/build flow.
A best practice is to use an PLL or MMCM or other vendor apparatus to generate your clocks.
Express time in ms like this:
localparam NUM_MS = 2;
// other code
#(NUM_MS*1ms);
Upvotes: 1