Memory Synthesis in Verilog
Most synthesizers implement a Verilog memory array, such as the one shown in the following code, as an array of latches or flip-flops.
reg [31:0] MyMemory [3:0]; // a 4 x 32-bit register
For example, the following code models a small RAM, and the synthesizer maps the memory array to sequential logic:
module RAM_1(A, CEB, WEB, OEB, INN, OUTT);
input [6:0] A; input CEB,WEB,OEB; input [4:0]INN;
reg [4:0] OUTT; reg [4:0] int_bus; reg [4:0] memory [127:0];
if (WEB == 1) int_bus = memory[A];
else if (WEB == 0) begin memory[A] = INN; int_bus = INN; end
always @(OEB or int_bus) begin
case (OEB) 0 : OUTT = int_bus;
default : OUTT = 5'bzzzzz; endcase
Memory synthesis using random control logic and transparent latches for each bit is reasonable only for small, fast register files, or for local RAM on an MGA or CBIC. For large RAMs synthesized memory becomes very expensive and instead you should normally use a dedicated RAM compiler.
Typically there will be restrictions on synthesizing RAM with multiple read/writes:
- If you write to the same memory in two different processes, be careful to avoid address contention.
- You need a multiport RAM if you read or write to multiple locations simultaneously.
- If you write and read the same memory location, you have to be very careful. To mimic hardware you need to read before you write so that you read the old memory value. If you attempt to write before reading, the difference between blocking and nonblocking assignments can lead to trouble.
You cannot make a memory access that depends on another memory access in the same clock cycle. For example, you cannot do this:
memory[i + 1] = memory[i]; // needs two clock cycles
pointer = memory[memory[i]]; // needs two clock cycles
For the same reason (but less obviously) we cannot do this:
pc = memory[addr1]; memory[addr2] = pc + 1; // not on the same cycle