The following standalone VHDL file is simplified from CLaSH's output, which should explain its somewhat weird structure.
The intention is to increment s.tup2_sel1(0) in the cycle where s.tup2_sel0 is "01". However, what I see in a VHDL simulator is that OUTPUT (and thus, s.tup2_sel1(0)) becomes unknoqn (its value is "XXXXXXXX") after the array update. Why does the array element become corrupted?
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
use work.all;
entity CHIP8 is
port(-- clock
CLK : in std_logic;
-- asynchronous reset: active high
RESET : in std_logic;
OUTPUT : out unsigned(7 downto 0));
type array_of_unsigned_8 is array (integer range <>) of unsigned(7 downto 0);
type tup2 is record
tup2_sel0 : std_logic_vector(1 downto 0);
tup2_sel1 : array_of_unsigned_8(0 to 1);
end record;
end;
architecture structural of CHIP8 is
signal y1 : array_of_unsigned_8(0 to 1);
signal s : tup2;
signal s1 : tup2;
signal y : array_of_unsigned_8(0 to 1);
signal x : unsigned(7 downto 0);
begin
y <= s.tup2_sel1;
x <= y(0);
process(y)
variable ivec : array_of_unsigned_8(0 to 1);
begin
ivec := y;
ivec(0) := x + 1;
y1 <= ivec;
end process;
with s.tup2_sel0 select
s1 <= (tup2_sel0 => "01", tup2_sel1 => y) when "00",
(tup2_sel0 => "10", tup2_sel1 => y1) when "01",
(tup2_sel0 => "10", tup2_sel1 => y) when others;
process(CLK,RESET)
begin
if RESET = '1' then
s <= (tup2_sel0 => "00", tup2_sel1 => array_of_unsigned_8'(0 to 1 => to_unsigned(0,8)));
elsif rising_edge(CLK) then
s <= s1;
end if;
end process;
OUTPUT <= x;
end;
My toplevel testbench generates the RESET signal:
LIBRARY ieee;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
use work.all;
ENTITY TB IS
END TB;
ARCHITECTURE behavior OF TB IS
signal CLK : std_logic := '0';
signal RESET : std_logic := '0';
signal OUTPUT : unsigned(7 downto 0);
constant CLK_period : time := 10 ns;
BEGIN
uut: entity work.CHIP8 PORT MAP (
CLK => CLK,
RESET => RESET,
OUTPUT => OUTPUT);
CLK_proc :process
begin
CLK <= '0';
wait for CLK_period/2;
CLK <= '1';
wait for CLK_period/2;
end process;
RESET_proc: process
begin
RESET <= '1';
wait for CLK_period * 2;
RESET <= '0';
wait;
end process;
END;
Signal
xis missing in the sensitivity list ofprocess(y). This can be by intention, but in 99% it's a mistake.Because it's generated code, I cannot tell if the people who wrote the code emitter are clever VHDL programmers like me knowing that a sensitivity list is a syntactic sugar or if they just missed to add more signals to the sensitivity list...
How is a sensitivity list translated?
See this example:
Is translated to:
So if they are clever, they could speculate to resume a process only on
yevents, but not on 'x' events. Some VHDL gurus might use this to optimize process wake-ups, others would call it a tricky code-line.Xvalues can be generated, when a signal contains meta values likeU,-,X,Wand arithmetic like+ 1is used.I don't see any init values for
tup2_sel1, except for a reset condition.So, have you applied RESET in your simulation?