Реализация простого двухпортового блока памяти в VHDL не работает должным образом - PullRequest
0 голосов
/ 31 мая 2018

Я пытался реализовать простую двухпортовую оперативную память в VHDL, но она не дает ожидаемых результатов при моделировании.Вот код:

library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_unsigned.all;

entity rams is
generic ( g_adress_width: integer:= 18;
          g_ram_size: integer:= 1000
        );
 port(
    clka : in std_logic;
    clkb : in std_logic;
    wea : in std_logic;
    web : in std_logic;
    addra : in std_logic_vector(g_adress_width-1 downto 0);
    addrb : in std_logic_vector(g_adress_width-1 downto 0);
    dia : in std_logic_vector(15 downto 0);
    dib : in std_logic_vector(15 downto 0);
    doa : out std_logic_vector(15 downto 0);
    dob : out std_logic_vector(15 downto 0));
end rams;
architecture syn of rams is
    type ram_type is array (g_ram_size-1 downto 0) of std_logic_vector(15 downto 0);
     signal RAM : ram_type; 
begin
 process (CLKA)
 begin
    if CLKA'event and CLKA = '1' then
            DOA <= RAM(conv_integer(ADDRA));
            if WEA = '1' then --always 0
                RAM(conv_integer(ADDRA)) <= DIA; --does not execute
        end if;
    end if;
 end process;

 process (CLKB)
 begin
 if CLKB'event and CLKB = '1' then
        DOB <= RAM(conv_integer(ADDRB));
        if WEB = '1' then
            RAM(conv_integer(ADDRB)) <= DIB;
    end if;
 end if;

end process;
end syn; 

А вот симуляция:

Simulation

Оба clka и clkb подключены к одним и тем же часам.Я даю несколько произвольных значений (без знака 300 и 355) dib .

По сути, doa всегда читает, поэтому я ожидаю, что он будет неопределенным, пока что-то не будет записано в адреса этих блоков памяти с dib , но оно показывает неопределенные значениявсегда.

Я ожидаю, что doa будет читать 300, когда addra снова в 0, и читать 355, когда addra в 15. Примерно так (извините за мои навыки рисования):

enter image description here

Был бы признателен, если бы кто-то мог указать мне в правильном направлении, что яделать неправильно.Спасибо.

РЕДАКТИРОВАТЬ: Код изменен к этому, и теперь он работает (благодаря решению Paebbels):

     signal RAM : ram_type; 
begin
 process (CLKA)
 begin
    if CLKA'event and CLKA = '1' then
            DOA <= RAM(to_integer(unsigned(ADDRA)));
            if WEA = '1' then --always 0
                    RAM(to_integer(unsigned(ADDRA))) <= DIA; --does not happen
        end if;

    end if;

    if CLKA'event and CLKA = '1' then
        DOB <= RAM(to_integer(unsigned(ADDRB)));
        if WEB = '1' then
            RAM(to_integer(unsigned(ADDRB))) <= DIB;
    end if;
 end if;

 end process;
end syn; 

1 Ответ

0 голосов
/ 31 мая 2018

Это описание ОЗУ с двумя часами неверно.Вам необходимо использовать:

  • процесс с двумя часами или
  • совместно используемую переменную.

Использование одного сигнала и двух процессов не является правильным,Создает несколько дисков по сигналу.Это, в свою очередь, создает проблему с несколькими источниками.Хотя ваше моделирование будет работать, из-за разрешенного типа std_logic_vector в вашем определяемом пользователем типе массива синтез не удастся.

Кроме того, чтобы разрешить вывод BlockRAM, вам необходимо представить внутреннюю структуру BlockRAM вВы VHDL код.Это означает, что вам нужно добавить конвейерные регистры в адресный путь.

Вы должны прочитать UG901 - Руководство по синтезу Vivado и найти «Методы кодирования HDL RAM».

Далееболее того, вы должны использовать пакет numeric_std вместо std_logic_unsigned, который не является официальным пакетом IEEE.


Работающую реализацию BlockRAM в режиме true-dual-port (TDP) можно найти в PoC-библиотека : PoC.mem.ocram.tdp .Эта реализация также будет работать на FPGA Altera / Intel и на решетчатых FPGA.

    -- RAM can be inferred correctly only if '-use_new_parser yes' is enabled in XST options
    subtype word_t is std_logic_vector(D_BITS - 1 downto 0);
    type    ram_t  is array(0 to DEPTH - 1) of word_t;

    signal ram          : ram_t;
    signal a1_reg       : unsigned(A_BITS-1 downto 0);
    signal a2_reg       : unsigned(A_BITS-1 downto 0);

begin

    process (clk1, clk2)
    begin   -- process
        if rising_edge(clk1) then
            if ce1 = '1' then
                if we1 = '1' then
                    ram(to_integer(a1)) <= d1;
                end if;

                a1_reg <= a1;
            end if;
        end if;

        if rising_edge(clk2) then
            if ce2 = '1' then
                if we2 = '1' then
                    ram(to_integer(a2)) <= d2;
                end if;

                a2_reg <= a2;
            end if;
        end if;
    end process;

    q1 <= (others => 'X') when SIMULATION and is_x(std_logic_vector(a1_reg)) else
                ram(to_integer(a1_reg));        -- returns new data
    q2 <= (others => 'X') when SIMULATION and is_x(std_logic_vector(a2_reg)) else
                ram(to_integer(a2_reg));        -- returns new data
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...