Visible to Intel only — GUID: mwh1409959587208
Ixiasoft
Visible to Intel only — GUID: mwh1409959587208
Ixiasoft
1.4.1.8. True Dual-Port Synchronous RAM
Intel FPGA synchronous memory blocks have two independent address ports, allowing for operations on two unique addresses simultaneously. A read operation and a write operation can share the same port if they share the same address.
The Intel® Quartus® Prime software infers true dual-port RAMs in Verilog HDL and VHDL, with the following characteristics:
- Any combination of independent read or write operations in the same clock cycle.
- At most two unique port addresses.
- In one clock cycle, with one or two unique addresses, they can perform:
- Two reads and one write
- Two writes and one read
- Two writes and two reads
In the synchronous RAM block architecture, there is no priority between the two ports. Therefore, if you write to the same location on both ports at the same time, the result is indeterminate in the device architecture. You must ensure your HDL code does not imply priority for writes to the memory block, if you want the design to be implemented in a dedicated hardware memory block. For example, if both ports are defined in the same process block, the code is synthesized and simulated sequentially so that there is a priority between the two ports. If your code does imply a priority, the logic cannot be implemented in the device RAM blocks and is implemented in regular logic cells. You must also consider the read-during-write behavior of the RAM block to ensure that it can be mapped directly to the device RAM architecture.
When a read and write operation occurs on the same port for the same address, the read operation may behave as follows:
- Read new data— Intel® Arria® 10 and Intel® Stratix® 10 devices support this behavior.
- Read old data—Not supported.
When a read and write operation occurs on different ports for the same address (also known as mixed port), the read operation may behave as follows:
- Read new data— Intel® Quartus® Prime Pro Edition synthesis supports this mode by creating bypass logic around the synchronous memory block.
- Read old data— Intel® Arria® 10 and Intel® Cyclone® 10 devices support this behavior.
- Read don’t care—Synchronous memory blocks support this behavior in simple dual-port mode.
The Verilog HDL single-clock code sample maps directly into synchronous Intel® Arria® 10 memory blocks. When a read and write operation occurs on the same port for the same address, the new data being written to the memory is read. When a read and write operation occurs on different ports for the same address, the old data in the memory is read. Simultaneous writes to the same location on both ports results in indeterminate behavior.
If you generate a dual-clock version of this design describing the same behavior, the inferred memory in the target device presents undefined mixed port read-during-write behavior, because it depends on the relationship between the clocks.
Verilog HDL True Dual-Port RAM with Single Clock
/ Quartus Prime Verilog Template
// True Dual Port RAM with single clock
//
// Read-during-write behavior is undefined for mixed ports
// and "new data" on the same port
module true_dual_port_ram_single_clock
#(parameter DATA_WIDTH=8, parameter ADDR_WIDTH=6)
(
input [(DATA_WIDTH-1):0] data_a, data_b,
input [(ADDR_WIDTH-1):0] addr_a, addr_b,
input we_a, we_b, clk,
output reg [(DATA_WIDTH-1):0] q_a, q_b
);
// Declare the RAM variable
reg [DATA_WIDTH-1:0] ram[2**ADDR_WIDTH-1:0];
// Port A
always @ (posedge clk)
begin
if (we_a)
begin
ram[addr_a] = data_a;
end
q_a <= ram[addr_a];
end
// Port B
always @ (posedge clk)
begin
if (we_b)
begin
ram[addr_b] = data_b;
end
q_b <= ram[addr_b];
end
endmodule
VHDL Read Statement Example
-- Port A
process(clk)
begin
if(rising_edge(clk)) then
if(we_a = '1') then
ram(addr_a) := data_a;
end if;
q_a <= ram(addr_a);
end if;
end process;
-- Port B
process(clk)
begin
if(rising_edge(clk)) then
if(we_b = '1') then
ram(addr_b) := data_b;
end if;
q_b <= ram(addr_b);
end if;
end process;
The VHDL single-clock code sample maps directly into Intel FPGA synchronous memory. When a read and write operation occurs on the same port for the same address, the new data writing to the memory is read. When a read and write operation occurs on different ports for the same address, the behavior results in old data for Intel® Arria® 10 and Intel® Cyclone® 10 devices , and is undefined for Intel® Stratix® 10 devices. Simultaneous write operations to the same location on both ports results in indeterminate behavior.
If you generate a dual-clock version of this design describing the same behavior, the memory in the target device presents undefined mixed port read-during-write behavior because it depends on the relationship between the clocks.
VHDL True Dual-Port RAM with Single Clock
-- Quartus Prime VHDL Template
-- True Dual-Port RAM with single clock
--
-- Read-during-write behavior is undefined for mixed ports
-- and "new data" on the same port
library ieee;
use ieee.std_logic_1164.all;
entity true_dual_port_ram_single_clock is
generic
(
DATA_WIDTH : natural := 8;
ADDR_WIDTH : natural := 6
);
port
(
clk : in std_logic;
addr_a : in natural range 0 to 2**ADDR_WIDTH - 1;
addr_b : in natural range 0 to 2**ADDR_WIDTH - 1;
data_a : in std_logic_vector((DATA_WIDTH-1) downto 0);
data_b : in std_logic_vector((DATA_WIDTH-1) downto 0);
we_a : in std_logic := '1';
we_b : in std_logic := '1';
q_a : out std_logic_vector((DATA_WIDTH -1) downto 0);
q_b : out std_logic_vector((DATA_WIDTH -1) downto 0)
);
end true_dual_port_ram_single_clock;
architecture rtl of true_dual_port_ram_single_clock is
-- Build a 2-D array type for the RAM
subtype word_t is std_logic_vector((DATA_WIDTH-1) downto 0);
type memory_t is array(2**ADDR_WIDTH-1 downto 0) of word_t;
-- Declare the RAM
shared variable ram : memory_t;
begin
-- Port A
process(clk)
begin
if(rising_edge(clk)) then
if(we_a = '1') then
ram(addr_a) := data_a;
end if;
q_a <= ram(addr_a);
end if;
end process;
-- Port B
process(clk)
begin
if(rising_edge(clk)) then
if(we_b = '1') then
ram(addr_b) := data_b;
end if;
q_b <= ram(addr_b);
end if;
end process;
end rtl;