188.8.131.52. Single-Clock Synchronous RAM with New Data Read-During-Write Behavior
To implement this behavior in the target device, synthesis tools add bypass logic around the RAM block. This bypass logic increases the area utilization of the design, and decreases the performance if the RAM block is part of the design’s critical path. If the device memory supports new data read-during-write behavior when in single-port mode (same clock, same read address, and same write address), the Verilog memory block doesn't require any bypass logic. Refer to the appropriate device handbook for specifications on your target device.
For Intel® Quartus® Prime Standard Edition integrated synthesis, if you do not require the read-through-write capability, add the synthesis attribute ramstyle="no_rw_check" to allow the Intel® Quartus® Prime software to choose the read-during-write behavior of a RAM, rather than using the behavior specified by your HDL code. This attribute may prevent generation of extra bypass logic, but it is not always possible to eliminate the requirement for bypass logic.
The following examples use a blocking assignment for the write so that the data is assigned intermediately.
Verilog HDL Single-Clock, Simple Dual-Port Synchronous RAM with New Data Read-During-Write Behavior
module single_clock_wr_ram( output reg [7:0] q, input [7:0] d, input [6:0] write_address, read_address, input we, clk ); reg [7:0] mem [127:0]; always @ (posedge clk) begin if (we) mem[write_address] = d; q = mem[read_address]; // q does get d in this clock // cycle if we is high end endmodule
VHDL Single-Clock, Simple Dual-Port Synchronous RAM with New Data Read-During-Write Behavior:
LIBRARY ieee; USE ieee.std_logic_1164.all; ENTITY single_clock_ram IS PORT ( clock: IN STD_LOGIC; data: IN STD_LOGIC_VECTOR (2 DOWNTO 0); write_address: IN INTEGER RANGE 0 to 31; read_address: IN INTEGER RANGE 0 to 31; we: IN STD_LOGIC; q: OUT STD_LOGIC_VECTOR (2 DOWNTO 0) ); END single_clock_ram; ARCHITECTURE rtl OF single_clock_ram IS TYPE MEM IS ARRAY(0 TO 31) OF STD_LOGIC_VECTOR(2 DOWNTO 0); BEGIN PROCESS (clock) VARIABLE ram_block: MEM; BEGIN IF (rising_edge(clock)) THEN IF (we = '1') THEN ram_block(write_address) := data; END IF; q <= ram_block(read_address); -- VHDL semantics imply that q doesn't get data -- in this clock cycle END IF; END PROCESS; END rtl;
It is possible to create a single-clock RAM by using an assign statement to read the address of mem and create the output q. By itself, the RTL describes new data read-during-write behavior. However, if the RAM output feeds a register in another hierarchy, a read-during-write results in the old data. Synthesis tools may not infer a RAM block if the tool cannot determine which behavior is described, such as when the memory feeds a hard hierarchical partition boundary. Avoid this type of RTL.
Avoid Verilog Coding Style with Vague read-during-write Behavior
reg [7:0] mem [127:0]; reg [6:0] read_address_reg; always @ (posedge clk) begin if (we) mem[write_address] <= d; read_address_reg <= read_address; end assign q = mem[read_address_reg];
Avoid VHDL Coding Style with Vague read-during-write Behavior
The following example uses a concurrent signal assignment to read from the RAM, and presents a similar behavior.
ARCHITECTURE rtl OF single_clock_rw_ram IS TYPE MEM IS ARRAY(0 TO 31) OF STD_LOGIC_VECTOR(2 DOWNTO 0); SIGNAL ram_block: MEM; SIGNAL read_address_reg: INTEGER RANGE 0 to 31; BEGIN PROCESS (clock) BEGIN IF (rising_edge(clock)) THEN IF (we = '1') THEN ram_block(write_address) <= data; END IF; read_address_reg <= read_address; END IF; END PROCESS; q <= ram_block(read_address_reg); END rtl;