Intel® Quartus® Prime Pro Edition用户指南: 设计建议

ID 683082
日期 9/28/2020
Public

本文档可提供新的版本。客户应 单击此处 前往查看最新版本。

文档目录

1.4.1.8. 真双端口同步RAM

本节中的代码示例显示了推断双端口同步RAM的Verilog HDL和VHDL代码。 不同的综合工具对这些类型的存储器的支持可能有所不同。

Intel FPGA同步存储器模块有两个独立的地址端口,允许同时在两个唯一地址上进行操作。如果读取操作和写入操作共享相同的地址,那么它们可以共享相同的端口。

Intel® Quartus® Prime软件可在Verilog HDL和VHDL中推断真双端口RAM,具有以下特征:

  • 在同一时钟周期内独立读取或写入操作的任意组合。
  • 最多两个唯一的端口地址。
  • 在一个时钟周期中,具有一个或两个唯一地址,它们可以执行:
    • 两次读取和一次写入
    • 两次写入和一次读取
    • 两次写入和两次读取

在同步RAM模块体系结构中,两个端口之间没有优先级。因此,如果同时在两个端口上写入相同的位置,那么结果在器件体系结构中是不确定的。如果要在专用硬件存储器模块中实现设计,那么必须确保HDL代码不暗含写入存储器模块的优先级。例如,如果两个端口都在同一处理模块中定义,那么代码将被综合和顺序仿真,以使两个端口之间具有优先级。如果代码确实暗含了优先级,那么该逻辑不能在器件RAM模块中实现,而是在普通逻辑单元中实现。您还必须考虑RAM模块的read-during-write行为,以确保能够将其直接映射到器件RAM体系结构。

当在同一端口上对同一地址进行读取和写入操作时,读取操作可能会表现如下:

  • Read new data Intel® Arria® 10 Intel® Stratix® 10 器件支持此行为。
  • Read old data不支持。

当在同一地址的不同端口上发生读取和写入操作(也称为混合端口)时,读取操作可能会表现如下:

  • Read new data Intel® Quartus® Prime Pro Edition synthesis通过在同步存储器模块周围创建旁路逻辑来支持此模式。
  • Read old data Intel® Arria® 10 Intel® Cyclone® 10器件支持此行为。
  • Read don’t care—同步存储器模块在简单双端口模式下支持此行为。

Verilog HDL单时钟代码样例直接映射到同步 Intel® Arria® 10存储器模块 。当在同一端口上对同一地址进行读写操作时,将读取正在写入存储器的新数据。当在同一地址的不同端口上进行读写操作时,将读取存储器中的旧数据。同时写入两个端口上的相同位置会导致不确定行为。

如果生成此设计的双时钟版本来描述相同的行为,那么目标器件中的推断存储器将呈现未定义的混合端口read-during-write行为,因为这取决于时钟之间的关系。

具有单时钟的Verilog HDL真双端口RAM

/ 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读语句示例

-- 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;

VHDL单时钟代码样例直接映射到Intel FPGA同步存储器。当在同一端口上对同一地址进行读写操作时,将读取写入存储器的新数据。当在同一地址的不同端口上进行读取和写入操作时,此行为将 Intel® Arria® 10 Intel® Cyclone® 10器件产生旧数据 对于 Intel® Stratix® 10器件是未定义的 。对两个端口上相同位置的同时写操作将导致不确定的行为。

如果生成此设计的双时钟版本来描述相同的行为,那么目标器件中的存储器将呈现未定义的混合端口read-during-write行为,因为这取决于时钟之间的关系。

具有单时钟的VHDL真双端口RAM

-- 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;