Search code examples
memoryverilogsimulationhdlicarus

Can't see anything when accessing RAM contents in simulation


I encountered an issue trying to design a SRAM memory. To be more specific, the memory is clocked, has a write enable - when high, one could write data and when low, one could read data - , an address input, which specifies the memory address to/from which data is written/read. Then, I created a module named user, which facilitates the write operation; thus, there is no need to provide a memory address when writing data.

My problem occurs when I try to simulate the circuit, because there cannot be seen anything when accessing the content of the memory. Within the test bench, I specified some values to be stored in the memory, then, I extracted data, but no success.

I attached the code here.

//stores instructions
module sram_1port_instructions(
    input clk,//clocked memory
    input wr_en,//when high, data is writeen, otherwise is read
    input [15:0] address_in,//suppose timer cannot count more than 13ms
    input [2:0] wr_data,//3 bit instructions
    output reg [2:0] rd_data
);

reg [2: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

//user interface designed for the first memory
module user(
    input clk,
    input wr_en,
    input [15:0] address_in,
    input [2:0] wr_data,
    output [2:0] rd_data
);

reg [15:0] pointer,address;

initial pointer = 16'd0;

sram_1port_instructions i0(.clk(clk),.wr_en(wr_en),.address_in(address_in),.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

//user tb
module user_tb(
    output reg clk, wr_en, 
    output reg [15:0] address_in,
    output reg [2:0] wr_data,
    output [2:0] rd_data
);

user cut(.clk(clk),.wr_en(wr_en),.address_in(address_in),.wr_data(wr_data),.rd_data(rd_data));

initial $dumpvars(0,user_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;
    #100000 address_in = 16'd0;
    for(i = 1;i < 500;i = i + 1) begin
    #200 address_in = i;
    end
end

endmodule

Solution

  • When I run your simulation and look at waveforms, I see rd_data=3 at time 100000. At that time, you read address 0, and that is the last value you wrote to address 0. Otherwise, all your reads of other addresses return X (unknown). When you do all your writes, you only write to address 0. From time=0 to time=100000, wr_en=1, and address_in=0 (inside your sram_1port_instructions module). You can see this when you look at the waveforms in your VCD file. wr_data changes every clock cycle, but you write to the same address every cycle.

    But, in user, if you connect the address signal to the to address_in port of the sram_1port_instructions module, you will write to different addresses.

    Change:

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

    to:

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

    Your code has the constant address_in signal connected to the address_in port.

    When I make that change, I see all different values being read from the RAM.