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

ID 683082
日期 9/28/2020
Public

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

文档目录

1.4.1.6. 具有新数据Read-During-Write行为的单时钟同步RAM

本节中的示例描述了RAM模块,其中read-during-write行为返回正在写入存储器地址的新值。

为了在目标器件中实现此行为,综合工具在RAM模块周围添加了旁路逻辑。如果RAM模块是设计关键路径的一部分,那么此旁路逻辑会增加设计的面积使用,并降低性能。如果在单端口模式下(相同的时钟,相同的读取地址和相同的写入地址)器件存储器支持新数据read-during-write行为,那么Verilog存储器模块不需要任何旁路逻辑。有关目标器件的规范,请参考相应的器件手册。

以下示例使用一个blocking assignment进行写操作,以便在中间分配数据。

具有新数据Read-During-Write行为的Verilog HDL,单时钟,简单双端口同步RAM

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

具有新数据Read-During-Write行为的VHDL,单时钟,简单双端口同步RAM

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;

通过使用assign语句读取mem的地址并创建输出q,可以创建单时钟RAM。RTL本身描述了新数据read-during-write行为。但是,如果RAM输出为另一个层次结构中的寄存器提供数据,那么read-during-write会生成旧数据。如果综合工具无法确定所描述的行为(例如,当存储器提供一个硬分层分区边界时),那么综合工具可能不会推断RAM模块。请避免这种类型的RTL。

避免具有不确定read-during-write行为的Verilog编码样式

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

避免具有不确定read-during-write行为的VHDL编码样式

下面的示例使用一个并发信号分配来读取RAM,并表现出类似的行为。

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;