I'm trying to set up a simple bruteforce convolution processor with my DE0 Nano Altera FPGA board. Here's what my code looks like :
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;
My problem is : the index of impulse(impulse_length-1-i
) doesn't decrease during the successive for loops, but the index of audio_buffer(i)
does. That's what I fond out simulating the code and figuring out why my results are wrong.
I tried to put (impulse_length-1-i
) into a signal to be able to watch it in ModelSim, and it starts at max/min 32 bits signed range (+/- 2 147 483 647) and the next cycle jumps to zero, and stays at zero.
I also tried to use a variable j
inside the process, to be able to initiate it at zero at the beginning of the process and use it as an index for my arrays instead of i and increment it after the actual calculation, but that made ModelSim to report a fatal error, can't figure out why neither.
Could someone explain me what I did wrong ?
Thanx in advance.
Main problem is that you don't understand how signals and for loops work when you're describing hardware instead of writing software.
Each iteration of the second for loop is assigning a value to the same signal. Within a process, only the last signal assignment to the named signal matters, and all reads of a signal use the value it held before the start of the process. This means that only the (impulse_length-1)
iteration of your second for loop does anything.
I wrote an answer a few years ago about how signals and variables work within a VHDL process which can give you a bit more detail on this: https://stackoverflow.com/a/19234859/1360002
If you write it such that all 10 add/multiply operations happen on the same cycle (such as using a variable in place of seq_buffer
to calculate the value you actually assign to the seq_buffer
signal), you're describing hardware that will have a very long logic path and won't work if your clock rate is even moderately high. This may not be an issue for your case.
Furthermore, you might have problems with the result width coming out of the multiply operator, but I can't be sure as I don't imply multiply units so I'm unfamiliar with the details of the associated operator function.