Search code examples
memoryverilogsimulatetest-benchicarus

I see undefined output sequences reading a memory in simulation


I have a question related to the implementation of a clocked SRAM memory which is is supposed to store data written by user and then display the memory content. In addition, I created a module named display which eases the reading process so that there is no need to provide the memory address from which data should be extracted, by incrementing a register after each reading. Nevertheless, when I simulate the circuit, I cannot see the correct output; thus, when I read the memory, I notice some undefined output sequences. I posted the corresponding code below.

//stores output data
module sram_1port_data(
    input clk,//clocked memory
    input wr_en,//when high, data is written, otherwise is read
    input [15:0] address_in,//suppose timer cannout count more than 13ms
    input [3:0] wr_data,//memory does not sotre values greater than 13(ms)
    output reg [3:0] rd_data
);

reg [3:0] memory [2 ** 15 - 1 : 0];

always @(posedge clk) begin
    if(wr_en) memory[address_in] <= wr_data;
    else rd_data <= memory[address_in];
end

endmodule

//display interfacedesigned for the second memory
module display(
    input clk,
    input wr_en,
    input [15:0] address_in,
    input [3:0] wr_data,
    output [3:0] rd_data
);

reg [15:0] pointer,address;

initial pointer = 16'd0;

sram_1port_data i0(.clk(clk),.wr_en(wr_en),.address_in(address),.wr_data(wr_data),.rd_data(rd_data));

always @(posedge clk) begin
    if(!wr_en) begin
        address <= pointer;
        pointer <= pointer + 1;
    end 
    else address <= address_in;
end

endmodule

//tb for display
module display_tb(
    output reg clk,
    output reg wr_en,
    output reg [15:0] address_in,
    output reg [3:0] wr_data,
    output [3:0] rd_data
);

display i0(.clk(clk),.wr_en(wr_en),.address_in(address_in),.wr_data(wr_data),.rd_data(rd_data));

initial $dumpvars(0,display_tb);

initial begin
    clk = 1'd1;
    repeat (2000)
    #100 clk = ~clk;
end

initial begin
    wr_en = 1'd1;
    #100000 wr_en = 1'd0;
end

integer i;

initial begin
    wr_data = 3'd0;
    for(i = 1;i < 500;i = i + 1) begin
    #200 wr_data = i;
    end
end

initial begin
    address_in = 16'd0;
    for(i = 1;i < 500;i = i + 1) begin
    #200 address_in = i;
    end
end

endmodule

Solution

  • When I look at waveforms, I see that rd_data is unknown (X) on every other read. Looking at an internal address signal, I see that the unknowns are only for even addresses. Early in the simulation, you are only writing to even addresses.

    In your testbench, you are using the same variable (i) in 2 different for loops. In your 2nd for loop, use a different variable name (j, for example):

    integer j;
    initial begin
        address_in = 16'd0;
        for(j = 1;j < 500;j = j + 1) begin
        #200 address_in = j;
        end
    end
    

    Now, all reads have known values because it writes to all addresses (even and odd).


    You could also set the address inside the same for loop as the write data. This is likely a better approach in this case.

    initial begin
        wr_data    =  3'd0;
        address_in = 16'd0;
        for(i = 1;i < 500;i = i + 1) begin
            #200;
            wr_data    = i;
            address_in = i;
        end
    end