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 ポート メモリではない場合でも、おそらく 1 ポートあたりで実装できます。

Altera のAdvanced Synthesis Cookbookには、このようなメモリの例があります。以下の図は、関連する部分を示しています。

アルテラのシンプルなクワッド ポート RAM の例

アルテラのサンプル ファイルを使用すると、アルテラのプリミティブがインスタンス化され、ストレージに 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 配列の 2 つのコピーを作成し、それぞれにインデックスを付けることができます。

于 2013-10-26T15:34:27.937 に答える