仅对英特尔可见 — GUID: mwh1409959591173
Ixiasoft
1.4.2. 从HDL代码推断ROM功能
当CASE语句存在时(在CASE语句中的每个选择都被设置为一个常量) ,综合工具推断ROM。
由于小型ROM通常在使用普通逻辑中的寄存器进行实现时会获得最佳性能,因此每个ROM功能必须满足最小尺寸要求,以在存储器中进行推断和布局。
对于包含同步RAM模块的器件体系结构,要推断一个ROM模块,综合必须使用寄存器作为地址或输出。当设计使用输出寄存器时,综合会从RAM模块的输入寄存器实现寄存器,而不会影响ROM的功能。如果寄存地址,那么已推断的ROM的上电状态可能不同于HDL设计。在这种情况下, Intel® Quartus® Prime综合会发出警告。
以下ROM示例直接映射到Intel FPGA存储器体系结构。
Verilog HDL同步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同步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;
使用readmemb的Verilog HDL双端口同步ROM
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双端口同步ROM
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;