块RAM(Xilinx)中的移位寄存器或FIFO

时间:2017-09-15 09:00:12

标签: vhdl ram xilinx xilinx-ise

我必须在一个相当大的缓冲区中缓冲一些数据。它不是通常的移位寄存器或FIFO,因为我必须能够从缓冲区的中间读取数据。 我设法以某种方式实现它,所以我可以在需要时使用它。问题是,它确实使用了LUT,这在我的设计中占用了大量空间。我想改变我的设计,以便将缓冲区推断为Block RAM。使用ram_style" block"没有帮助。有什么想法或建议我怎么能做到这一点? 更新:buf_size在包中声明:     常量buf_size:natural:= 5;

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity deriv_buffer is
  generic(
    NSAMPLES : natural := 16
  );
  port(   
    clk : in std_logic;
    rst : in std_logic;
    deriv_s : in t_deriv_array( NSAMPLES - 1 downto 0 );
    deriv_buf : out t_deriv_array( buf_size * NSAMPLES - 1 downto 0 )
  );
end deriv_buffer;

architecture Behavioral of deriv_buffer is

  signal deriv_buf_s : t_deriv_array( (buf_size-1) * NSAMPLES - 1 downto 0 );
  attribute ram_style : string;
  attribute ram_style of deriv_buf_s : signal is "block";

begin

  deriv_buf( buf_size * NSAMPLES - 1 downto (buf_size - 1) * NSAMPLES ) <= deriv_s;

  buffer_p : process( rst, clk )
  begin
    if rst = '1' then
      deriv_buf_s <= ( others => ( others => '0' ) );
    elsif rising_edge( clk ) then
      deriv_buf_s( (buf_size - 1) * NSAMPLES - 1 downto (buf_size - 2) * NSAMPLES ) <= deriv_s;
      deriv_buf_s( (buf_size - 2) * NSAMPLES - 1 downto (buf_size - 3) * NSAMPLES ) <= deriv_buf_s( (buf_size - 1) * NSAMPLES - 1 downto (buf_size - 2) * NSAMPLES );
      deriv_buf_s( (buf_size - 3) * NSAMPLES - 1 downto (buf_size - 4) * NSAMPLES ) <= deriv_buf_s( (buf_size - 2) * NSAMPLES - 1 downto (buf_size - 3) * NSAMPLES );
      deriv_buf_s( (buf_size - 4) * NSAMPLES - 1 downto (buf_size - 5) * NSAMPLES ) <= deriv_buf_s( (buf_size - 3) * NSAMPLES - 1 downto (buf_size - 4) * NSAMPLES );
    end if;
  end process buffer_p;

  deriv_buf( (buf_size-1)*NSAMPLES - 1 downto 0 ) <= deriv_buf_s;

end Behavioral;

1 个答案:

答案 0 :(得分:1)

如果您想使用Block RAM,则需要考虑Block RAM只有2个端口。您无法自由查看RAM中的数据:您需要通过任一端口访问它。

此外,读取和/或写入需要一个时钟周期来处理。

因此,如果我们查看您的代码,它已经开始出现问题:

entity deriv_buffer is
    [...]
    port(
        [...]
        deriv_buf : out t_deriv_array( buf_size * NSAMPLES - 1 downto 0 )

您将整个RAM连接到输出端口!我不知道你在使用这个组件的实体中的内容做了什么,但正如我所说:你没有可以自由访问Block RAM的内容。您需要遵循适当的Block RAM设计指南。

例如,请参考Xilinx Synthesis User Guide进行正确的Block RAM实例化。 (第4章HDL编码技术,部分RAM HDL编码技术)

下一个问题:重置

if rst = '1' then
    deriv_buf_s <= ( others => ( others => '0' ) );

无法重置RAM。如果确实想要清除RAM,则需要在每个单独的地址位置写一个(others=>'0')。因此,您需要控制逻辑来执行此操作。但现在,使用此重置代码将不允许实例化块RAM。

然后在你的代码中你有部分

deriv_buf_s( (buf_size - 1) * NSAMPLES - 1 downto (buf_size - 2) * NSAMPLES ) <= deriv_s;
deriv_buf_s( (buf_size - 2) * NSAMPLES - 1 downto (buf_size - 3) * NSAMPLES ) <= deriv_buf_s( (buf_size - 1) * NSAMPLES - 1 downto (buf_size - 2) * NSAMPLES );
deriv_buf_s( (buf_size - 3) * NSAMPLES - 1 downto (buf_size - 4) * NSAMPLES ) <= deriv_buf_s( (buf_size - 2) * NSAMPLES - 1 downto (buf_size - 3) * NSAMPLES );
deriv_buf_s( (buf_size - 4) * NSAMPLES - 1 downto (buf_size - 5) * NSAMPLES ) <= deriv_buf_s( (buf_size - 3) * NSAMPLES - 1 downto (buf_size - 4) * NSAMPLES );

此代码有两个大问题:

  • 您尝试在一个时钟周期内进行读写操作。但就像我说的那样,读取块RAM需要一个时钟周期,写入第二个时钟周期。
  • 此代码实例化4个写端口和3个读端口。就像我说的:一个Block RAM只有2个端口。

您可以实现代码以使用4个块RAM实例。但是,这些Block RAM的所有端口仍将被占用。因此,没有任何端口可以随意访问RAM中的所有数据,如您所愿。

最后:我认为你应该重新考虑你的要求。您想要的是块RAM中不可能的。如果要使用Block RAM,则应更改算法。