块 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,你应该改变你的算法。
我必须在一个很大的缓冲区中缓冲一些数据。它不是通常的移位寄存器或 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,你应该改变你的算法。