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

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

1.4.1.10. バイト・イネーブル信号を備えるRAM

このセクションのRAMコード例では、SystemVerilogおよびVHDLのコードでRAMを推論します。また、メモリーワードに1バイトを書き込むための制御をバイト・イネーブル信号で行います。

合成では、2つのインデックスをもつ書き込み式を作成し、RAMの「ワード」の一部を書き込むことにより、バイト・イネーブル信号をモデル化します。この実装では、適切にバイト・イネーブルを有効にすることで、一度に複数のバイトを書き込むこともできます。

Verilog-1995は混合幅のRAMをサポートしません。この規格には異なる読み出し幅、書き込み幅、またはその両方をモデル化する多次元配列がありません。Verilog-2001は混合幅のRAMをサポートしません。このタイプのロジックにはパッキングされた次元が複数必要です。合成ツールによっては、これらのメモリーのサポートが異なる場合があります。このセクションでは、 インテル® Quartus® Prime プロ・エディションの合成における推論規則について説明します。

インテル® Quartus® PrimeのHDLテンプレートを参照し、異なるアドレス幅で使用することができるパラメーター化済みの例を確認してください。また、2つの読み出しポートと2つの書き込みポートを備えるトゥルー・デュアルポートRAMの例も提供されています。

SystemVerilogシンプル・デュアルポート同期RAM (バイト・イネーブルあり)

module byte_enabled_simple_dual_port_ram  
( 
    input we, clk,
    input [ADDRESS_WIDTH-1:0] waddr, raddr,// address width = 6 
    input [NUM_BYTES-1:0] be, // 4 bytes per word
    input [(BYTE_WIDTH * NUM_BYTES -1):0] wdata, // byte width = 8, 4 bytes per word
    output reg [(BYTE_WIDTH * NUM_BYTES -1):0] q // byte width = 8, 4 bytes per word
);

   parameter ADDRESS_WIDTH = 6;
   parameter DEPTH = 2**ADDRESS_WIDTH;
   parameter BYTE_WIDTH = 8;
   parameter NUM_BYTES = 4;

   // use a multi-dimensional packed array
   //to model individual bytes within the word
   logic [NUM_BYTES-1:0][BYTE_WIDTH-1:0] ram[0:DEPTH-1]; 
     // # words = 1 << address width

	// port A
   always@(posedge clk)
   begin
	   if(we) begin
          for (int i = 0; i < NUM_BYTES; i = i + 1) begin
            if(be[i]) ram[waddr][i] <= wdata[i*BYTE_WIDTH +: BYTE_WIDTH];
          end
      end
      q <= ram[raddr];
   end
endmodule

VHDLシンプル・デュアルポート同期RAM (バイト・イネーブルあり)

library ieee;
use ieee.std_logic_1164.all;
library work;

entity byte_enabled_simple_dual_port_ram is
generic (DEPTH      : integer := 64;
         NUM_BYTES  : integer :=  4;
         BYTE_WIDTH : integer :=  8
);
port (
    we, clk : in  std_logic;
    waddr, raddr : in  integer range 0 to DEPTH -1 ;     -- address width = 6
    be   : in  std_logic_vector (NUM_BYTES-1 downto 0);   -- 4 bytes per word
    wdata: in  std_logic_vector((NUM_BYTES * BYTE_WIDTH -1) downto 0);   -- width = 32
    q    : out std_logic_vector((NUM_BYTES * BYTE_WIDTH -1) downto 0) ); -- width = 32
end byte_enabled_simple_dual_port_ram;

architecture rtl of byte_enabled_simple_dual_port_ram is

    --  build up 2D array to hold the memory
    type word_t is array (0 to NUM_BYTES-1) of std_logic_vector(BYTE_WIDTH-1 downto 0);
    type ram_t is array (0 to DEPTH-1) of word_t;

    signal ram : ram_t;
    signal q_local : word_t;

    begin  -- Re-organize the read data from the RAM to match the output
        unpack: for i in 0 to NUM_BYTES-1 generate    
            q(BYTE_WIDTH*(i+1) - 1 downto BYTE_WIDTH*i) <= q_local(i);
    end generate unpack;
        
    -- port A
    process(clk)
    begin
        if(rising_edge(clk)) then 
            if(we = '1') then
                for I in (NUM_BYTES-1) downto 0 loop
                    if(be(I) = '1') then
                        ram(waddr)(I) <= wdata(((I+1)*BYTE_WIDTH-1) downto I*BYTE_WIDTH);
                    end if;
                 end loop;
            end if;
            q_local <= ram(raddr);
        end if;
    end process;  
end rtl;