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

Shift Register or FIFO in block RAM (Xilinx)

我必须在一个很大的缓冲区中缓冲一些数据。它不是通常的移位寄存器或 FIFO,因为我还必须能够从缓冲区中间读取数据。 我设法以某种方式实现了它,因此我可以根据需要使用它。问题是,它确实为此使用了 LUT,这在我的设计中需要很多 space。我想更改我的设计,以便将缓冲区推断为 Block RAM。使用 ram_style "block" 没有帮助。有什么想法或建议可以实现吗? 更新:buf_size 在包中声明: 常量 buf_size : 自然 := 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;

如果你想使用block RAM,你需要考虑到block RAM只有2个端口。您不能随意查看 RAM 中的数据:您需要通过任一端口访问它。

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

所以如果我们查看您的代码,它已经开始有问题了:

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

您已将整个 RAM 连接到输出端口!我不知道你在用这个组件对实体中的内容做什么,但正如我所说:你不能自由访问块 RAM 的内容。您需要遵循正确的块 RAM 设计指南。

请参阅 Xilinx Synthesis User Guide 实例以了解正确的块 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 个读取端口。就像我说的:块 RAM 只有 2 个端口。

您可以实施代码以使用 4 个块 RAM 实例。但是这些块 RAM 的所有端口仍然会被占用。因此,不会留下任何端口来提供对 RAM 中所有数据的随机访问,如您所愿。


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