VHDL:for 循环,索引算法不起作用
VHDL : for loop, index arithmetic doesn't work
我正在尝试用我的 DE0 Nano Altera FPGA 板设置一个简单的强力卷积处理器。
这是我的代码的样子:
LIBRARY ieee;
USE ieee.std_logic_1164.all;
use ieee.numeric_bit.all;
ENTITY Convolution IS
PORT( clock : IN std_logic;
audio_in : IN unsigned(15 downto 0);
audio_out : OUT unsigned(31 downto 0) );
END Convolution;
ARCHITECTURE Convolution_Core OF Convolution IS
constant impulse_length : integer := 10;
type array16 is array(0 to impulse_length-1) of unsigned(15 downto 0);
type array32 is array(0 to impulse_length-1) of unsigned(31 downto 0);
constant impulse : array16 := (x"FFFF", x"FFFE", x"FFFD", x"FFFC",
x"FFFB", x"FFFA", x"FFF9", x"FFF8",
x"FFF7", x"FFF6");
signal audio_buffer : array16 := (others=> (others=>'0'));
signal seq_buffer : unsigned(31 downto 0);
BEGIN
process(clock)
begin
if rising_edge(clock) then
-- buffer the audio input in audio_buffer
for i in 0 to (impulse_length-2) loop
audio_buffer(i) <= audio_buffer(i+1);
end loop;
audio_buffer(impulse_length-1) <= audio_in;
for i in 0 to (impulse_length-1) loop
if i = 0 then
seq_buffer <= audio_buffer(i) * impulse(impulse_length-1-i);
else
seq_buffer <= seq_buffer + audio_buffer(i) * impulse(impulse_length-1-i);
end if;
end loop;
end if;
end process;
audio_out <= seq_buffer;
END Convolution_Core;
我的问题是:impulse(impulse_length-1-i
) 的索引在连续的 for 循环中没有减少,但是 audio_buffer(i)
的索引减少了。这就是我喜欢模拟代码并弄清楚为什么我的结果是错误的。
我试图将 (impulse_length-1-i
) 放入信号中以便能够在 ModelSim 中观察它,它从 max/min 32 位带符号范围 (+/- 2 147 483 647) 开始下一个循环跳到零,并保持在零。
我还尝试在流程中使用变量 j
,以便能够在流程开始时将其初始化为零,并将其用作我的数组的索引而不是 i 并递增它经过实际计算,却让ModelSim报了一个致命错误,也想不通为什么。
谁能解释一下我做错了什么?
提前致谢。
主要问题是当您描述硬件而不是编写软件时,您不了解信号和 for 循环的工作原理。
第二个 for 循环的每次迭代都为同一个信号赋值。在一个进程中,只有最后一个信号分配给指定的信号很重要,并且信号的所有读取都使用它在进程开始之前保持的值。这意味着只有第二个 for 循环的 (impulse_length-1)
迭代会执行任何操作。
几年前我写了一个关于信号和变量如何在 VHDL 过程中工作的答案,它可以为您提供更多详细信息:
如果您这样写,所有 10 个 add/multiply 操作都发生在同一个周期(例如使用变量代替 seq_buffer
来计算您实际分配给 seq_buffer
信号),您描述的硬件将具有很长的逻辑路径,并且如果您的时钟速率适度高则无法工作。对于您的情况,这可能不是问题。
此外,您可能对乘法运算符的结果宽度有疑问,但我不能确定,因为我没有暗示乘法单位,所以我不熟悉相关运算符函数的细节.
非常感谢您回答我!
因此,如果我理解正确,在进程中使用带有变量的 for 循环会导致与使用某些 "generate" 语句相同的逻辑实现。也许这就是为什么当我为我的卷积算法尝试类似的东西时它需要很长时间才能编译 ;)
所以我想在 Java 或 C 中做类似 for 循环的唯一方法是 "manually" 为每次迭代计时,切换输入信号并缓冲连续的结果,对吗?
但是我必须说我不明白为什么我写的 "audio buffering" 过程可以正常工作,即使有时间模拟...
此致
我正在尝试用我的 DE0 Nano Altera FPGA 板设置一个简单的强力卷积处理器。 这是我的代码的样子:
LIBRARY ieee;
USE ieee.std_logic_1164.all;
use ieee.numeric_bit.all;
ENTITY Convolution IS
PORT( clock : IN std_logic;
audio_in : IN unsigned(15 downto 0);
audio_out : OUT unsigned(31 downto 0) );
END Convolution;
ARCHITECTURE Convolution_Core OF Convolution IS
constant impulse_length : integer := 10;
type array16 is array(0 to impulse_length-1) of unsigned(15 downto 0);
type array32 is array(0 to impulse_length-1) of unsigned(31 downto 0);
constant impulse : array16 := (x"FFFF", x"FFFE", x"FFFD", x"FFFC",
x"FFFB", x"FFFA", x"FFF9", x"FFF8",
x"FFF7", x"FFF6");
signal audio_buffer : array16 := (others=> (others=>'0'));
signal seq_buffer : unsigned(31 downto 0);
BEGIN
process(clock)
begin
if rising_edge(clock) then
-- buffer the audio input in audio_buffer
for i in 0 to (impulse_length-2) loop
audio_buffer(i) <= audio_buffer(i+1);
end loop;
audio_buffer(impulse_length-1) <= audio_in;
for i in 0 to (impulse_length-1) loop
if i = 0 then
seq_buffer <= audio_buffer(i) * impulse(impulse_length-1-i);
else
seq_buffer <= seq_buffer + audio_buffer(i) * impulse(impulse_length-1-i);
end if;
end loop;
end if;
end process;
audio_out <= seq_buffer;
END Convolution_Core;
我的问题是:impulse(impulse_length-1-i
) 的索引在连续的 for 循环中没有减少,但是 audio_buffer(i)
的索引减少了。这就是我喜欢模拟代码并弄清楚为什么我的结果是错误的。
我试图将 (impulse_length-1-i
) 放入信号中以便能够在 ModelSim 中观察它,它从 max/min 32 位带符号范围 (+/- 2 147 483 647) 开始下一个循环跳到零,并保持在零。
我还尝试在流程中使用变量 j
,以便能够在流程开始时将其初始化为零,并将其用作我的数组的索引而不是 i 并递增它经过实际计算,却让ModelSim报了一个致命错误,也想不通为什么。
谁能解释一下我做错了什么?
提前致谢。
主要问题是当您描述硬件而不是编写软件时,您不了解信号和 for 循环的工作原理。
第二个 for 循环的每次迭代都为同一个信号赋值。在一个进程中,只有最后一个信号分配给指定的信号很重要,并且信号的所有读取都使用它在进程开始之前保持的值。这意味着只有第二个 for 循环的 (impulse_length-1)
迭代会执行任何操作。
几年前我写了一个关于信号和变量如何在 VHDL 过程中工作的答案,它可以为您提供更多详细信息:
如果您这样写,所有 10 个 add/multiply 操作都发生在同一个周期(例如使用变量代替 seq_buffer
来计算您实际分配给 seq_buffer
信号),您描述的硬件将具有很长的逻辑路径,并且如果您的时钟速率适度高则无法工作。对于您的情况,这可能不是问题。
此外,您可能对乘法运算符的结果宽度有疑问,但我不能确定,因为我没有暗示乘法单位,所以我不熟悉相关运算符函数的细节.
非常感谢您回答我!
因此,如果我理解正确,在进程中使用带有变量的 for 循环会导致与使用某些 "generate" 语句相同的逻辑实现。也许这就是为什么当我为我的卷积算法尝试类似的东西时它需要很长时间才能编译 ;)
所以我想在 Java 或 C 中做类似 for 循环的唯一方法是 "manually" 为每次迭代计时,切换输入信号并缓冲连续的结果,对吗?
但是我必须说我不明白为什么我写的 "audio buffering" 过程可以正常工作,即使有时间模拟...
此致