我试图在VHDL中从我的数组中的2个不同地址分配2个值,但不知怎的,它们总是返回给我一个错误的值(大多数时候,零)。我只用1个地址和1个数据输出测试它,它返回了正确的值。
architecture Behavioral of registerFile is
type reg_type is array (31 downto 0) of std_logic_vector (31 downto 0);
signal REG : reg_type := (x"00000031", x"00000030", x"00000029", x"00000028", x"00000027", x"00000026", x"00000025", x"00000024", x"00000023", x"00000022", x"00000021", x"00000020",x"00000019",x"00000018", x"00000017", x"00000016", x"00000015", x"00000014", x"00000013", x"00000012", x"00000011", x"00000010", x"00000009", x"00000008", x"00000007",x"00000006", x"00000005", x"00000004", x"00000003", x"00000004", x"00000001", x"00000000");
begin
process(clk)
begin
if clk'event and clk='1' then
if ENABLE = '1' then
if readReg = '1' then -- read from register
DATAone <= REG(conv_integer(ADDRone));
DATAtwo <= REG(conv_integer(ADDRtwo));
else
REG(conv_integer(ADDRone)) <= DATAone;
REG(conv_integer(ADDRtwo)) <= DATAtwo;
end if;
end if;
end if;
end process;
end Behavioral;
感谢一些帮助,我尝试使用谷歌搜索,但它都是多维数组或一次只能访问1个元素。
感谢。
答案 0 :(得分:0)
我不确定这是否可以在大多数面料中合成。您可以创建reg数组的两个副本并将其索引到每个副本中。
答案 1 :(得分:0)
您似乎正在尝试实现四端口内存。无论如何,即使您的寄存器文件不完全是4端口存储器,它也可以在一个存储器周围实现。
Altera在Advanced Synthesis Cookbook中有一个这样的记忆的例子。下图显示了相关部分:
如果使用Altera示例文件,它将实例化Altera原语,并使用FPGA Block RAM进行存储。如果您担心可移植性,或者您只想查看一些符合您需要的VHDL代码,请查看下面的示例。它实现了与图中所示大致相同的电路,并且很可能在FPGA中合成为分布式存储器。
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
-- Quad-port RAM with 2 read ports 2 write ports. The design uses 2 memory blocks
-- (MAIN_MEMORY and SHADOW_MEMORY) to allow for simultaneous writes. Port A writes to
-- main memory, Port B writes to shadow memory. On a read from either port, data is
-- read from the memory block that was most recently written at the given position.
entity quad_port_ram is
generic (
ADDRESS_WIDTH: natural := 5;
DATA_WIDTH: natural := 32
);
port (
clock: in std_logic;
read_addr_a: in natural range 0 to 2**ADDRESS_WIDTH-1;
read_data_a: out std_logic_vector(DATA_WIDTH-1 downto 0);
write_addr_a: in natural range 0 to 2**ADDRESS_WIDTH-1;
write_data_a: in std_logic_vector(DATA_WIDTH-1 downto 0);
write_enable_a: in std_logic;
read_addr_b: in natural range 0 to 2**ADDRESS_WIDTH-1;
read_data_b: out std_logic_vector(DATA_WIDTH-1 downto 0);
write_addr_b: in natural range 0 to 2**ADDRESS_WIDTH-1;
write_data_b: in std_logic_vector(DATA_WIDTH-1 downto 0);
write_enable_b: in std_logic
);
end;
architecture rtl of quad_port_ram is
type memory_type is (MAIN_MEMORY, SHADOW_MEMORY);
type memory_type_array is array (natural range <>) of memory_type;
-- Keep track of which memory has the most recently written data for each address
signal most_recent_port_for_address: memory_type_array(0 to 2**ADDRESS_WIDTH-1);
type memory_array is array (0 to 2**ADDRESS_WIDTH-1) of std_logic_vector(DATA_WIDTH-1 downto 0);
type dual_memory_array is array (memory_type) of memory_array;
-- Store the actual memory bits. Access like this:
-- memory_data(memory_type)(address)(bit_position)
signal memory_data: dual_memory_array;
-- Auxiliary signals to decide where to read the data from (main or shadow)
signal most_recent_port_for_addr_a, most_recent_port_for_addr_b: memory_type;
begin
process (clock) begin
if rising_edge(clock) then
if write_enable_a then
memory_data(MAIN_MEMORY)(write_addr_a) <= write_data_a;
most_recent_port_for_address(write_addr_a) <= MAIN_MEMORY;
end if;
if write_enable_b then
if (write_enable_a = '0') or (write_addr_a /= write_addr_b) then
memory_data(SHADOW_MEMORY)(write_addr_b) <= write_data_b;
most_recent_port_for_address(write_addr_b) <= SHADOW_MEMORY;
end if;
end if;
end if;
end process;
most_recent_port_for_addr_a <= most_recent_port_for_address(read_addr_a);
most_recent_port_for_addr_b <= most_recent_port_for_address(read_addr_b);
read_data_a <= memory_data(most_recent_port_for_addr_a)(read_addr_a);
read_data_b <= memory_data(most_recent_port_for_addr_b)(read_addr_b);
end;