I have the task of designing an 8x8 bit memory in Verilog using CMOS. (orginally asked at Verilog - 8x8 memory unit - wrong value read, but asked to provide more details).
Currently, I have the following:
- Bitcell - takes in signals sel (if its selected), rw (read = 0, write = 1) and input. If sel=0, output is high impedance. If sel=1, it either reads, or writes (and outputs the written value).
- word_8 - Collection of 8 bitcells that also take in sel and rw (forwarded to each cell individually). 8 input and 8 output wires to each bitcell.
- decoder_3to8 - decoder that's supposed to take in an address, and select the word which is supposed to be read.
I'm running a testbench, where I try:
- Write cell 0
- Write cell 1
- Read cell 0
While the write operations work successfully, reading back from cell 0 seems to give me the value from cell 1.
My memory_8x8
:
module memory_8x8 (
input[2:0] addr,
input[7:0] inp,
input op,
input select,
output[7:0] outp
);
wire[7:0] selected_cell;
decoder_3to8 decoder(
.valid(select),
.addr(addr),
.sel(selected_cell)
);
genvar i;
generate
for (i = 0; i < 8; i = i + 1) begin
word_8 word_instance(
.sel(selected_cell[i]),
.rw(op),
.inp(inp),
.outp(outp)
);
end
endgenerate
endmodule
My word_8
:
module word_8 (
input sel,
input rw,
input[7:0] inp,
output[7:0] outp
);
genvar i;
generate
for (i = 0; i < 8; i = i + 1) begin : BITCELLS
bitcell bitcell_instance(
.sel(sel),
.rw(rw),
.inp(inp[i]),
.outp(outp[i])
);
end
endgenerate
endmodule
My decoder_3to8
:
module decoder_3to8 (
input valid,
input[2:0] addr,
output[7:0] sel
);
wire addr_NOT[2:0];
// Generate NOT addresses
not(addr_NOT[0], addr[0]);
not(addr_NOT[1], addr[1]);
not(addr_NOT[2], addr[2]);
// nb - verilog indexing reverse way - addr[0] corresponds to 00X, addr[2] is MSB
and(sel[0], addr_NOT[2], addr_NOT[1], addr_NOT[0], valid);
and(sel[1], addr_NOT[2], addr_NOT[1], addr[0], valid);
and(sel[2], addr_NOT[2], addr[1], addr_NOT[0], valid);
and(sel[3], addr_NOT[2], addr[1], addr[0], valid);
and(sel[4], addr[2], addr_NOT[1], addr_NOT[0], valid);
and(sel[5], addr[2], addr_NOT[1], addr[0], valid);
and(sel[6], addr[2], addr[1], addr_NOT[0], valid);
and(sel[7], addr[2], addr[1], addr[0], valid);
endmodule
Testbench for memory_8x8
:
`timescale 1ns / 1ps
module memory_8x8_tb_basic;
reg[2:0] addr;
reg[7:0] inp;
reg op;
reg select;
wire[7:0] outp;
reg[7:0] expected_outp;
integer i;
memory_8x8 uut (
.addr(addr),
.inp(inp),
.op(op),
.select(select),
.outp(outp)
);
initial begin
$monitor("\tSelected cell: %b", uut.selected_cell);
end
initial begin
// Initialize inputs
select = 0;
op = 0;
addr = 3'b000;
inp = 8'b00000000;
expected_outp = 8'bXXXXXXXX;
#10;
// Stage 0
$display("Test stage 0 - Write to cell 0, write to cell 1, read cell 0\n");
// Write to cell 0
select = 1;
op = 1;
addr = 3'b000;
inp = 8'hAA;
expected_outp = inp;
#10;
if (outp !== expected_outp) begin
$display("Write to cell 0 FAILED at time %0t ns: Address %b, Expected %b, Got %b",
$time, addr, expected_outp, outp);
end else begin
$display("Write to cell 0 PASSED at time %0t ns: Address %b, Data %b",
$time, addr, outp);
end
// Write to cell 1
addr = 3'b001;
inp = 8'hBB;
expected_outp = inp;
#10;
if (outp !== expected_outp) begin
$display("Write to cell 1 FAILED at time %0t ns: Address %b, Expected %b, Got %b",
$time, addr, expected_outp, outp);
end else begin
$display("Write to cell 1 PASSED at time %0t ns: Address %b, Data %b",
$time, addr, outp);
end
// Read cell 0
op = 0;
addr = 3'b000;
expected_outp = 8'hAA;
#10;
if (outp !== expected_outp) begin
$display("Read cell 0 FAILED at time %0t ns: Address %b, Expected %b, Got %b",
$time, addr, expected_outp, outp);
end else begin
$display("Read cell 0 PASSED at time %0t ns: Address %b, Data %b",
$time, addr, outp);
end
select = 0;
#10;
// Read cell 2
op = 0;
addr = 3'b001;
expected_outp = 8'hBB;
#10;
if (outp !== expected_outp) begin
$display("Read cell 1 FAILED at time %0t ns: Address %b, Expected %b, Got %b",
$time, addr, expected_outp, outp);
end else begin
$display("Read cell 1 PASSED at time %0t ns: Address %b, Data %b",
$time, addr, outp);
end
$finish;
end
endmodule
This gives the following (unexpected) output:
Selected cell: 00000000
Test stage 0 - Write to cell 0, write to cell 1, read cell 0
Selected cell: 00000001
Write to cell 0 PASSED at time 20000 ns: Address 000, Data 10101010
Selected cell: 00000010
Write to cell 1 PASSED at time 30000 ns: Address 001, Data 10111011
Selected cell: 00000001
Read cell 0 FAILED at time 40000 ns: Address 000, Expected 10101010, Got 10111011
Selected cell: 00000000
Read cell 1 FAILED at time 60000 ns: Address 001, Expected 10111011, Got zzzzzzzz
memory_8x8_tb_basic.v:98: $finish called at 60000 (1ps)
1 Answer 1
the write operations work successfully
There is insufficient evidence of that in your question. Instead of relying solely on the information in your simulation log file, you should also dump waveforms. All simulators support dumping VCD waves because it is part of the IEEE Std 1800-2023. Add this code to your testbench:
initial $dumpvars;
This will create a waveform file that you can load into a waveform viewer (this is specific to the simulation tools you are using). Once you have waves, you can scope down into your bitcell
module, which you did not provide in your question.
Then you will be able to see what value outp
has for each instance of the bitcell
module. The key to debugging Verilog simulations is gaining access to all signals throughout the design hierarchy. Your $monitor
and $display
statements are only giving you pieces of the puzzle, but not the whole picture.
This is what I see:
I obviously can not show what is inside bitcell
because you did not provide that code. You should focus your debug efforts on the bitcell
module contents.
-
\$\begingroup\$ Thank you, using the waveform dump as you suggested led me to figure something weird was going on in the bitcell. For some reason, adding a delay in the buildin SR latch fixed the issue. \$\endgroup\$Gronnmann– Gronnmann2024年11月17日 14:06:46 +00:00Commented Nov 17, 2024 at 14:06
-
\$\begingroup\$ @Gronnmann: You're welcome. I'm glad this answer helped point the way to an eventual solution. \$\endgroup\$toolic– toolic2024年11月18日 13:26:27 +00:00Commented Nov 18, 2024 at 13:26