I have written this simple process. It's supposed to accumulate ((b-a)/n)*yi terms, where yi is an input that is updated per every clock cycle, and then output the result of the sum.
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity Integrator is
Port ( a : in STD_LOGIC_VECTOR(7 downto 0);
b : in STD_LOGIC_VECTOR(7 downto 0);
n : in STD_LOGIC_VECTOR(7 downto 0);
yi : in STD_LOGIC_VECTOR (15 downto 0);
start : in std_logic;
clk : in std_logic;
output : out signed (15 downto 0);
done : out STD_LOGIC);
end Integrator;
architecture Integrator_arch of Integrator is
signal do : std_logic;
signal i : unsigned(7 downto 0);
signal tmp1, tmp2, tmp3, res : signed(15 downto 0);
begin
process(clk)
begin
if(clk'event and clk='1') then
if(start='1') then
do <= '1';
i <= (others=>'0');
done <= '0';
res <= (others=>'0');
elsif(do='1' and done='0') then
if(i=unsigned(n)) then
output <= res;
do <= '0';
done <= '1';
else
tmp1 <= resize(signed(b)-signed(a),16);
tmp2 <= resize(tmp1/signed(n),16);
tmp3 <= resize(tmp2*signed(yi),16);
res <= res + tmp3;
i <= i+1;
end if;
end if;
end if;
end process;
end Integrator_arch;
And this is the testbench:
architecture Behavioral of Integrator_Testbench is
signal start : std_logic;
signal clk, done : std_logic;
signal yi : std_logic_vector(15 downto 0);
signal O : signed(15 downto 0);
begin
uut: entity work.integrator(integrator_arch)
port map(a=>"11111110", b=>"00000010", n=>"00000100", yi=>yi
,start=>start, clk=>clk, done=>done, output=>O);
process
begin
clk<='0';
start<='1';
wait for 200ns;
clk<='1';
wait for 200ns;
start<='0';
clk<='0';
yi<=x"0003";
wait for 200ns;
clk<='1';
yi<=x"0003";
wait for 200ns;
clk<='0';
yi<=x"0001";
wait for 200ns;
clk<='1';
yi<=x"0001";
wait for 200ns;
clk<='0';
yi<=x"0000";
wait for 200ns;
clk<='1';
yi<=x"0000";
wait for 200ns;
clk<='0';
yi<=x"0002";
wait for 200ns;
clk<='1';
yi<=x"0002";
wait for 200ns;
clk<='0';
yi<=x"0000";
wait for 200ns;
clk<='1';
yi<=x"0000";
wait for 200ns;
clk<='0';
yi<=x"0000";
wait for 200ns;
clk<='1';
yi<=x"0000";
wait for 200ns;
end process;
end Behavioral;
But here's the problem, the output is always reported as unknown (red Xs) when I run a behavioral simulation. What's more weird is that it runs completely fine in a debug session, and by running a line-by-line debug session I was able to get the correct output, which is x"0006"!!!
After two hours of attempting to find the issue, I finally decided to ask. Specially since it runs completely fine and outputs the correct result in a line-by-line debug so I have no idea why the simulation keeps acting out.
Thanks a lot for your time.
Found my own answer by more trial and error
It seems that the result of one line of numeric_std
expression takes one clock cycle to settle down, so when I tried to make it more readable by writing
tmp1 <= resize(signed(b)-signed(a),16);
tmp2 <= resize(tmp1/signed(n),16);
tmp3 <= resize(tmp2*signed(yi),16);
res <= res + tmp3;
It took 4 clock cycles to settle down and before these 4 clock cycles are done, the port is set to unknown. So I shortened all of those lines into one line
res <= res + resize((resize(b-a,16)/signed(n))*yi,16);
And now the result is ready for me in 1 clock cycle just as it should be.