FPGA BRAM协议栈实现Xilinx 7系列

时间:2013-11-03 21:09:58

标签: hardware vhdl fpga xilinx

我正在zynq soc上创建一个基于artix-7结构的堆栈。为了创建堆栈,我想使用BRAM,我遇到的问题是BRAM读取输出没有改变,我之前使用过很多次BRAMS(不是7系列,所以我可能会遗漏一些微妙的东西)而且我是完全不知道为什么要这样做。

我在堆栈中填充了值:1,2,3

当我接着连续调用pop时,它读出的唯一值是每个弹出和读取地址3(即使在等待一个时钟读取延迟之后)。我也尝试使用双端口rams并遇到同样的问题,我坚持使用单端口,因为它更容易尝试并且可以解决出错的问题!

我已经使用基于数组的ram验证了逻辑行为,该ram具有正确的行为。为了验证,我还检查了此来源的逻辑: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;

非常感谢 萨姆

1 个答案:

答案 0 :(得分: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位的RAM ...大概是128 Gbits,我猜错了。

但是,为了提出更清晰的问题,您应该只留下与您遇到问题的内存解决方案相关的代码。

3)你的代码确实包含了一些你应该修复的拼写错误,比如在过程中分配“doutb”,而我想你想要分配data_out:

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

这就是为什么你没有在输出中看到你想要的东西。