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

ID 683082
日付 4/13/2020
Public

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

ドキュメント目次

1.4.2. HDL コードからのROMファンクションの推測

合成ツールは、CASEステートメントのすべての選択肢に対して値が定数に設定されているCASEステートメントが存在する場合にROMを推測します。

通常、小さなROMは通常のロジックのレジスターを使用して実装したときに最高のパフォーマンスを実現するため、各ROM関数は推論とメモリーへの配置の最小サイズ要件を満たす必要があります。

同期RAMブロックを備えたデバイス・アーキテクチャーの場合、ROMブロックを推測するために、合成はアドレスまたは出力のいずれかにレジスターを使用する必要があります。デザインで出力レジスターを使用する場合、合成はROMの機能に影響を与えることなくRAMブロックの入力レジスターからレジスターを実装します。アドレスをレジスターすると、推論されたROMのパワーアップ状態がHDLデザインと異なる場合があります。このシナリオでは、 インテル® Quartus® Prime合成は警告を発行します。

次のROMの例は、 Intel FPGAメモリー・アーキテクチャーに直接にマップします。

Verilog HDL Synchronous ROM

module sync_rom (clock, address, data_out);
	input clock;
	input [7:0] address;
	output reg [5:0] data_out;
	reg [5:0] data_out;

	always @ (posedge clock)
	begin
		case (address)
			8'b00000000: data_out = 6'b101111;
			8'b00000001: data_out = 6'b110110;
			...
			8'b11111110: data_out = 6'b000001;
			8'b11111111: data_out = 6'b101010;
		endcase
	end
endmodule

VHDL Synchronous ROM

LIBRARY ieee;
USE ieee.std_logic_1164.all;

ENTITY sync_rom IS
	PORT (
		clock: IN STD_LOGIC;
		address: IN STD_LOGIC_VECTOR(7 downto 0);
		data_out: OUT STD_LOGIC_VECTOR(5 downto 0)
	);
END sync_rom;

ARCHITECTURE rtl OF sync_rom IS
BEGIN
PROCESS (clock)
	BEGIN
	IF rising_edge (clock) THEN
		CASE address IS
			WHEN "00000000" => data_out <= "101111";
			WHEN "00000001" => data_out <= "110110";
			...
			WHEN "11111110" => data_out <= "000001";
			WHEN "11111111" => data_out <= "101010";
			WHEN OTHERS     => data_out <= "101111";
		END CASE;
	END IF;
	END PROCESS;
END rtl;

Verilog HDL Dual-Port Synchronous ROM Using readmemb

module dual_port_rom
#(parameter data_width=8, parameter addr_width=8)
(
	input [(addr_width-1):0] addr_a, addr_b,
	input clk, 
	output reg [(data_width-1):0] q_a, q_b
);
	reg [data_width-1:0] rom[2**addr_width-1:0];

	initial // Read the memory contents in the file
			 //dual_port_rom_init.txt. 
	begin
		$readmemb("dual_port_rom_init.txt", rom);
	end

	always @ (posedge clk)
	begin
		q_a <= rom[addr_a];
		q_b <= rom[addr_b];
	end
endmodule

VHDL Dual-Port Synchronous ROM Using Initialization Function

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity dual_port_rom is
	generic (
		DATA_WIDTH : natural := 8;
		ADDR_WIDTH : natural := 8
	);
	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;
		q_a     : out std_logic_vector((DATA_WIDTH -1) downto 0);
		q_b     : out std_logic_vector((DATA_WIDTH -1) downto 0)
	);
end entity;

architecture rtl of dual_port_rom is
	-- Build a 2-D array type for the ROM
	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;

	function init_rom
		return memory_t is 
		variable tmp : memory_t := (others => (others => '0'));
	begin 
		for addr_pos in 0 to 2**ADDR_WIDTH - 1 loop 
			-- Initialize each address with the address itself
			tmp(addr_pos) := std_logic_vector(to_unsigned(addr_pos, DATA_WIDTH));
		end loop;
		return tmp;
	end init_rom;	 

	-- Declare the ROM signal and specify a default initialization value.
	signal rom : memory_t := init_rom;
begin
	process(clk)
	begin
	if (rising_edge(clk)) then
		q_a <= rom(addr_a);
		q_b <= rom(addr_b);
	end if;
	end process;
end rtl;