Pressing_Keys_24_7
Pressing_Keys_24_7

Reputation: 1863

No output data in sinc3 filter simulation

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?

enter image description here

Also why is the dec_rate = 40? Since, I have set it to 64?

Upvotes: 1

Views: 323

Answers (2)

toolic
toolic

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

Mikef
Mikef

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.

enter image description here

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

Related Questions