Реализация стека FPGA BRAM Xilinx 7-Series

Создаю стек на основе ткани artix-7 на zynq soc. Чтобы создать стек, я хочу использовать BRAM, у меня проблема с тем, что вывод чтения BRAM не меняется, я использовал BRAMS много раз раньше (не 7-й серии, поэтому мне может не хватать чего-то тонкого), и я полностью озадачен, почему он это делает.

Я заполнил стек значениями: 1, 2, 3

Когда я затем последовательно вызываю pop, единственное значение, которое он считывает, - 3 для каждого адреса pop и чтения (даже после ожидания задержки чтения в один такт). Я также пробовал с двухпортовыми барабанами и имел ту же проблему, я придерживаюсь одного порта, так как проще попытаться разобраться в том, что идет не так!

Я проверил логическое поведение с использованием оперативной памяти на основе массива, которая имеет правильное поведение. Для проверки я также проверил логику из этого источника: http://vhdlguru.blogspot.co.uk/2011/01/implementation-of-stack-in-vhdl.html.

Таким образом, проблема, похоже, связана с BRAM, либо он не читает должным образом, либо по какой-то причине он записывает значение 3 на все предыдущие адреса памяти, что не имеет смысла, поскольку каждый элемент данных синхронизируется с сигналом записи и правильным адресом.

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use ieee.std_logic_unsigned.all;
use IEEE.numeric_std.ALL;

-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned values
--use IEEE.NUMERIC_STD.ALL;

-- Uncomment the following library declaration if instantiating
-- any Xilinx primitives in this code.
library UNISIM;
use UNISIM.VComponents.all;

-- Stack implementation for 32 bit data items using BRAM componenets
entity stack_32_BRAM is
    generic( ADDR : integer :=32);
    Port ( clk : in  STD_LOGIC;
           rst : in  STD_LOGIC;
           en : in  STD_LOGIC;
           push_pop : in  STD_LOGIC;
           data_in : in  STD_LOGIC_VECTOR (31 downto 0);
           data_out : out  STD_LOGIC_VECTOR (31 downto 0));
end stack_32_BRAM;

architecture Behavioral of stack_32_BRAM is

COMPONENT BRAM_32_1K
  PORT (
    clka : IN STD_LOGIC;
    rsta : IN STD_LOGIC;
    wea : IN STD_LOGIC_VECTOR(3 DOWNTO 0);
    addra : IN STD_LOGIC_VECTOR(31 DOWNTO 0);
    dina : IN STD_LOGIC_VECTOR(31 DOWNTO 0);
    douta : OUT STD_LOGIC_VECTOR(31 DOWNTO 0);
    clkb : IN STD_LOGIC;
    rstb : IN STD_LOGIC;
    web : IN STD_LOGIC_VECTOR(3 DOWNTO 0);
    addrb : IN STD_LOGIC_VECTOR(31 DOWNTO 0);
    dinb : IN STD_LOGIC_VECTOR(31 DOWNTO 0);
    doutb : OUT STD_LOGIC_VECTOR(31 DOWNTO 0)
  );
END COMPONENT;

COMPONENT BRAM_32_1K_SP
  PORT (
    clka : IN STD_LOGIC;
    rsta : IN STD_LOGIC;
    wea : IN STD_LOGIC_VECTOR(3 DOWNTO 0);
    addra : IN STD_LOGIC_VECTOR(31 DOWNTO 0);
    dina : IN STD_LOGIC_VECTOR(31 DOWNTO 0);
    douta : OUT STD_LOGIC_VECTOR(31 DOWNTO 0)
  );
END COMPONENT;

--The read ptr is a function of the write ptr
signal stack_ptr_read, stack_ptr_write : std_logic_vector(ADDR-1 downto 0) := (others =>'0');
signal full, empty : std_logic := '0';

 signal     WEA : std_logic_vector(3 downto 0) :=(others=>'0');                      -- 4-bit input: A port write enable
 signal         addra, addrb, dinb, doutb, dina, douta : std_logic_vector(31 downto 0) := (others => '0');
 signal         rsta, rstb :std_logic := '0' ; 

 type ram is array (4 downto -2) of std_logic_vector(31 downto 0) ;
 signal mem : ram :=(others=>(others=>'0'));

begin

 ---STACK LOGIC ---

 PUSH : process (clk, push_pop, en, full, empty)
    begin
        if(clk'event and clk='1') then
        WEA <= "0000";          
            if(en='1' and push_pop = '1' and full = '0') then
                mem(to_integer(unsigned(stack_ptr_write))) <= data_in;
                WEA <= "1111";  
                dina <= data_in ;
                ADDRA <= stack_ptr_write;
                stack_ptr_write <= stack_ptr_write + 1; 
            elsif(en='1' and push_pop = '0' and empty = '0') then   
                data_out <= douta ;--
                doutb <= mem(to_integer(unsigned(stack_ptr_write - 1)));
                ADDRA <= stack_ptr_write - 1;
                stack_ptr_write <= stack_ptr_write - 1;
            end if;
        end if;
    end process;

BRAM_SP : BRAM_32_1K_SP
  PORT MAP (
    clka => clk,
    rsta => rsta,
    wea => wea,
    addra => addra,
    dina => dina,
    douta => douta
  );






end Behavioral;

Большое спасибо Сэм


person Sam Palmer    schedule 03.11.2013    source источник


Ответы (1)


Решение влечет за собой несколько вещей:

1) Вы должны явно сбрасывать сигналы с первого порта в каждом процессе. Инициализация их в их объявлении просто не помогает. Тогда код процесса с правильным списком сброса и чувствительности должен выглядеть так:

PUSH : process (rst, clk)
begin
    if (rst = '1') then --supposing active-high async. reset
       WEA <= (others => '0');
       ADDRA <= (others => '0');
       dina <= (others => '0');
       data_out <= (others => '0');
       full <= '0';
       empty <= '0';
       stack_ptr_write <= (others => '0');
    elsif(clk'event and clk='1') then
       --your code

2) Насколько я понимаю, у вас есть несколько слоев / попыток кода в одном и том же месте. Это неприятно читать. Я вижу, что вы используете "mem" для хранения вашего примера (так что WEA, ADDRA, dina и т. Д. Игнорируются), но когда вы вернетесь к BRAM_32_1K_SP, не забудьте проверить, что он имеет 32-битные адреса, которые в сочетании с 32-битными данными, означает, что у вас есть 32 * 2 ** 32-битная память ... это около 128 Гбит, я думаю, опечатка.

Однако, чтобы задать более четкий вопрос, вы должны оставить только код, относящийся к решению проблемы памяти, с которой у вас возникла проблема.

3) ваш код действительно содержит некоторые опечатки, которые вы должны исправить, например, присвоение "doutb" в процессе, тогда как я предполагаю, что вы хотели вместо этого назначить data_out:

data_out <= mem(to_integer(unsigned(stack_ptr_write - 1)));

И это причина того, что вы не видите на выходе то, что хотите.

person Galland    schedule 11.11.2013
comment
В конце концов, я и мой руководитель не смогли понять, что было не так, поэтому вместо этого я теперь делаю вывод о BRAM (что также лучше для переносимости дизайна). И да, я признаю, что приведенный мною пример был запутанным и запутанным после многих попыток! Но спасибо за ваше время. Сэм - person Sam Palmer; 11.11.2013