我目前正在尝试用VHDL开发Sobel滤波器。我正在使用存储在BRAM中的640x480图片。该算法使用图像的3×3像素矩阵来处理每个输出像素。我的问题是我目前只知道将图像放入BRAM,其中BRAM的每个地址都包含一个像素值。这意味着我每个时钟只能读取一个像素。我的问题是我正在尝试传输数据,所以理想情况下我需要能够每个时钟获得三个像素值(图片的每一行一个),所以在我的初始延迟后,我可以加载三个新的像素值时钟并在每个时钟上获得一个输出像素。我正在寻找一种方法来做到这一点,但无法弄明白。
我能想到解决这个问题的唯一方法就是将图像放在3个BRAM中。这样我就可以读取每个时钟周期3行的值。但是,没有足够的内存空间来容纳一个足够大的RAM以适应640x480图像,更不用说三个。我可以通过这种方式降低图片大小,但我真的想用我当前的640x480图片大小来做。
非常感谢任何帮助或指导。
答案 0 :(得分:2)
一个简单的解决方案是将图像的1/4存储在4个独立的存储器中。第一个存储器包含每4行,第4行每秒,从第2行开始,等等。即使你需要3行,我也会使用4,因为4平均分为480和其他所有标准分辨率。此外,找到模4的二进制数是微不足道的,这是订购存储器所必需的。
您可以使用行号的MSB来寻址您的RAM,并使用LSB来计算每个RAM输出的相对顺序(代码仅用于演示想法,它不可用... ):
address <= line(line'left downto 2) & col; -- Or something more efficent on packing
data0 <= ram0(address);
data1 <= ram1(address);
data2 <= ram2(address);
data3 <= ram3(address);
case line(1 downto 0) is
when "00" =>
line0 <= data0;
line1 <= data1;
line2 <= data2;
when "01" =>
line0 <= data1;
line1 <= data2;
line2 <= data3;
when "10" =>
line0 <= data2;
line1 <= data3;
line2 <= data0;
when "11" =>
line0 <= data3;
line1 <= data0;
line2 <= data1;
when others => null;
end case;
答案 1 :(得分:2)
architecture rtl of matrix_3x3_builder_8b is
type fifo_t is array (0 to 2*IM_WIDTH + 2) of std_logic_vector(7 downto 0);
signal fifo_int : fifo_t;
begin
p0_build_5x5: process(rst_i,clk_i)
begin
if( rst_i = '1' )then
fifo_int <= (others => (others => '0'));
elsif( rising_edge(clk_i) )then
if(data_valid_i = '1')then
for i in 1 to 2*IM_WIDTH + 2 loop
fifo_int(i) <= fifo_int(i-1);
end loop;
fifo_int(0) <= data_i;
end if;
end if;
end process p0_build_5x5;
data_o1 <= fifo_int(0*IM_WIDTH + 0);
data_o2 <= fifo_int(0*IM_WIDTH + 1);
data_o3 <= fifo_int(0*IM_WIDTH + 2);
data_o4 <= fifo_int(1*IM_WIDTH + 0);
data_o5 <= fifo_int(1*IM_WIDTH + 1);
data_o6 <= fifo_int(1*IM_WIDTH + 2);
data_o7 <= fifo_int(2*IM_WIDTH + 0);
data_o8 <= fifo_int(2*IM_WIDTH + 1);
data_o9 <= fifo_int(2*IM_WIDTH + 2);
end rtl;
在这里,您逐个像素地读取图像以构建3x3矩阵。管道填充时间较长,但一旦完成,每个时钟脉冲都会有一个新的矩阵。
答案 2 :(得分:1)
如果你想继续存储整个图像,那么我会按照Jonathan Drolet的建议,在四个公羊之间循环,同时写入并同时读取所有4个(将你关注的三个复用到3个寄存器中)。 这是有效的,因为你的公羊足够深,你仍然可以在1/4深度(仍然是77k深度)获得完整的BRAM利用率,并且你的读数可以预测为分段。
对于这个问题的细节,Nicolas Roudel的方法对于BRAM来说要便宜得多,尽管你不能同时存储整个图像,所以无论你发送什么结果你的结果都不能反压你,除非你可以反压你的数据源。这对您的申请可能有影响,也可能无关紧要。
当你尝试用非常宽但相当浅(1k深)的rams分段来做这样的事情时,会使用更多的块ram(甚至开始推断分布式ram)。当读取不遵循特定模式时(在您的情况下,模式是它们都是顺序和相邻位置),ram不能被分段。保持高效BRAM使用的最佳策略通常是通过使用与正常时钟相位对齐的2倍时钟为本机双端口块RAM构建四端口RAM,允许您每1x时钟进行一次写入和3次读取周期。