在VHDL中访问同一数组的2个元素

时间:2013-10-26 13:16:46

标签: vhdl

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

感谢。

2 个答案:

答案 0 :(得分:0)

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

答案 1 :(得分:0)

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

Altera在Advanced Synthesis Cookbook中有一个这样的记忆的例子。下图显示了相关部分:

Altera Simple Quad Port RAM Example

如果使用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;