memoryverilogiverilog

Cannot load/store data from/in SRAM: read data is unknown


I have a question related to a Verilog implementation of an SRAM memory. Module sram_1port is supposed to be a clocked address addressable SRAM memory which has a read enable signal and a write enable signal. Module control_sram is supposed to read/write data in SRAM. Data is stored contiguously, at consecutive memory addresses. The issue occurs when I try to simulate the circuit behaviour, thus the rd_data signal is undetermined during the whole simulation. So, the memory content couldn't be output, and I don't even know why. Is there a problem when data is stored, or when the content should be output, or both are problematic?

here you can see the diagram

module sram_1port(
    input clk,
    input [15:0] address,
    input wr,rd,
    input [2:0] wr_data,
    output reg [2:0] rd_data
);

reg [2:0] mem_reg [15:0];

always @ (posedge clk) begin
    if(wr) mem_reg[address] <= wr_data;
    else if(rd) rd_data <= mem_reg[address];
end

endmodule
//automaton
module control_sram(
    input clk, wr, rd,
    input [2:0] wr_data,//read 1 instruction/clk
    output [2:0] rd_data,//output
    output reg [15:0] out//outputs address
);

reg [15:0] address,address_rd,address_wr;

initial address = 16'd0;
initial address_wr = 16'd0;
initial address_rd = 16'd0;

sram_1port i0(.clk(clk),.address(address),.wr(wr),
.rd(rd),.wr_data(wr_data),.rd_data(rd_data));

always @(posedge clk) begin
    if(wr) begin
        address_wr = address_wr + 1;
        address = address_wr;
        address_rd = 16'd0;
    end
    else if(rd) begin
        address_rd = address_rd + 1;
        address = address_rd;
        address_wr = 16'd0;
    end
end

always @ * out = address;

endmodule
//tb for control_sram
module control_sram_tb(
    output reg clk,wr,rd,
    output reg [2:0] wr_data,
    output [2:0] rd_data,
    output [15:0] out
);

control_sram cut(.clk(clk),.wr(wr),.rd(rd),.wr_data(wr_data),
.rd_data(rd_data),.out(out));

initial $dumpvars(0,control_sram_tb);

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

initial begin
    wr_data = 3'd1;
    #3000000 wr_data = 3'd2;
    #1000000 wr_data = 3'd1;
    #3000000 wr_data = 3'd0;
    #2000000 wr_data = 3'd3;
    #1000000 wr_data = 3'd1;
end

initial begin
    rd = 1'b0;
    #13000000 rd = 1'b1;
end

initial begin
    wr = 1'b1;
    #13000000 wr = 1'b0;
end

endmodule
 

Solution

  • When I run your simulation, I see rd_data go from X to 1 at time 13_000_200ns, and it stays at 1 for 3_000ns, then it returns to X. You should see that if you zoom in on your waveforms to that time interval. If you don't see that with icarus, run your simulation on edaplayground with different simulators.

    Also, you declared your memory (mem_reg) to have 16 locations ([15:0]). However, I see your address take on the values of 17, 18, 19, etc. for your writes and reads. It seems strange that you are trying to access locations that are not in your memory. When you do this for reads, you get X (as expected). It seems like you only need a 4-bit address, not a 16-bit address.