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

ID 683082
日付 4/13/2020
Public

このドキュメントの新しいバージョンが利用できます。お客様は次のことを行ってください。 こちらをクリック 最新バージョンに移行する。

ドキュメント目次

1.4.1.10. バイトイネーブル信号付きRAM

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

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

Verilog-1995は、異なるリード幅、ライト幅、またはその両方をモデル化するための多次元配列がないため、混合幅RAMをサポートしていません。 Verilog-2001は、このタイプのロジックが複数のパック・ディメンションを必要とするため、混合幅RAMをサポートしません。異なる合成ツールは、これらのメモリーのサポートが異なる場合があります。このセクションでは、 インテル® Quartus® Primeプロ・エディション合成について説明します。

異なるアドレス幅に使用できるパラメーター化された例の インテル® Quartus® Prime HDLテンプレート、および2つのリード・ポートと2つのライト・ポートを備えたトゥルー・デュアル・ポートRAMの例を参照してください。

SystemVerilog Simple Dual-Port Synchronous RAM with Byte Enable

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 Simple Dual-Port Synchronous RAM with Byte Enable

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;