インテル® Quartus® Prime プロ・エディションのユーザーガイド: デザインの推奨事項

ID 683082
日付 8/03/2023
Public
ドキュメント目次

1.4.1.6. シングルクロック同期RAM (新しいデータでのRead-During-Write動作)

このセクションの例で説明するRAMブロックでは、Read-During-Write動作においてメモリーアドレスに書き込まれた新しい値を返します。

この動作をターゲットデバイスに実装するため、合成ツールではバイパスロジックをRAMブロックの周りに追加します。このバイパスロジックにより、デザインの領域使用率が増加します。また、RAMブロックがデザインのクリティカルなパスの一部である場合はパフォーマンスが低下します。デバイスメモリーが新しいデータでのRead-During-Write動作をシングルポート・モードでサポートする場合 (同じクロック、同じ読み出しアドレス、同じ書き込みアドレス)、Verilogメモリーブロックにバイパスロジックは必要ありません。該当するデバイス・ハンドブックを参照し、ターゲットデバイスの仕様を確認してください。

ここで示されている例では、書き込みにブロッキング割り当てを使用し、データが中間的に割り当てられるようにしています。

Verilog HDLシングルクロック、シンプル・デュアルポート同期RAM (新しいデータでのRead-During-Write動作)

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シングルクロック、シンプル・デュアルポート同期RAM (新しいデータでのRead-During-Write動作)

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は避けてください。

回避すべきVerilogコーディング・スタイル (あいまいなRead-During-Write動作がある)

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

回避すべきVHDLコーディング・スタイル (あいまいなRead-During-Write動作がある)

次の例では、同時信号割り当てを使用して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;