1

我试图在 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 个元素。

谢谢。

4

2 回答 2

0

您似乎正在尝试实现四端口内存。无论如何,即使您的寄存器文件不完全是一个 4 端口内存,它也可能可以围绕一个实现。

Altera 在其Advanced Synthesis Cookbook中提供了此类存储器的示例。下图显示了相关部分:

Altera 简单四端口 RAM 示例

如果使用 Altera 示例文件,它将例化 Altera 原语,并使用 FPGA 块 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;
于 2013-10-27T00:58:11.137 回答
0

我不确定这是否可以在大多数面料中合成。您可以创建 reg 数组的两个副本并索引到每个副本。

于 2013-10-26T15:34:27.937 回答