I have the following code for a memory module:
module memory (
input clk,
we,
input [ADDR_SIZE - 1:0] addr,
input [WORD_SIZE - 1:0] data,
output reg [WORD_SIZE - 1:0] out
);
parameter ADDR_SIZE = 3;
parameter WORD_SIZE = 8;
reg [WORD_SIZE - 1:0] mem[2**ADDR_SIZE - 1:0];
always @(posedge clk) begin
if (we) begin
mem[addr] <= data;
end
out <= mem[addr];
end
endmodule
I use it to create memory A and B of the following circuit:
If I change out <= mem[addr];
to out = mem[addr];
in my memory module, the code doesn’t work anymore.
I know that blocking assignements should not be used inside sequential blocks but in this case I don’t understand the problem. I have tried to understand how verilog deals with both assignements (http://www.sunburst-design.com/papers/CummingsSNUG2000SJ_NBA.pdf) and it appears that:
- first RHS of non-blocking assignements are evaluated
- then blocking assignements are done
- finally, LHS of non-blocking assignements are assigned to the previously evaluated RHS
In this case, if the write is enable:
- first data is evaluated (
mem[addr] <= data;
) - then we assign mem[addr] to out (
out <= mem[addr]
) - finally, we assign data to mem[addr] (
mem[addr] <= data;
)
Which sounds good to me. However, now, instead of having:
| Clock | DOut1 | DOut2 |
| :-: |:-:|:-:|
| 0 | 0 | x |
| 1 | 1 | 0 |
| 2 | 2 | 1 |
| 3 | 3 | 2 |
| 4 | 7 | 3 |
I have:
| Clock | DOut1 | DOut2 |
| :-: |:-:|:-:|
| 0 | 0 | x |
| 1 | 1 | 1 |
| 2 | 2 | 1 |
| 3 | 3 | 3 |
| 4 | 7 | 3 |
and it continues with a completely unpredictable pattern.
How can one explain that changing the non-blocking assignement here by a blocking assignement makes such a thing happen?