4

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;
Cactus
  • 27,075
  • 9
  • 69
  • 149
  • `x` is missing in the sensitivity list of `process(y)`. This can be by intention, but in 99% it's a mistake. `X` can be generated, when a signal contains meta values and `+ 1` is used. I don't see any init values for `tup2_sel1`, except for a reset condition. So, have you applied `RESET` in your simulation? – Paebbels Oct 02 '18 at 09:56
  • @Paebbels: Yes, I have applied RESET externally in a toplevel test bench. Maybe I should include its code in the question. – Cactus Oct 02 '18 at 10:03
  • 1
    As [Paebbels comments](https://i.stack.imgur.com/F0PRZ.jpg). While you're question isn't a [mcve] it's worth searching for questions whose answers are adding missing signals from process sensitivity lists. If Jim Lewis were to read this he'd recommend -2008 and the single element `all` in the sensitivity list. (And labeling process statements is useful here). –  Oct 02 '18 at 10:03
  • @Paebbels: Indeed, it is the missing sensitivity! Please post it as an answer so I can accept it. I am going to add this info to [the relevant CLaSH ticket](https://github.com/clash-lang/clash-compiler/issues/365). – Cactus Oct 02 '18 at 10:06
  • I'd vote to close this question. The problem isn't clear (from your narrative). See [What topics can I ask about here?] **Some questions are still off-topic, even if they fit into one of the categories listed above:** "1. Questions seeking debugging help *("why isn't this code working?")* must include the desired behavior, a specific problem or error and the shortest code necessary to reproduce it in the question itself. Questions without a clear problem statement are not useful to other readers. See: How to create a [mcve]. –  Oct 02 '18 at 10:12
  • 11
    @user1155120: Let's take this to meta, then; because the situation here is that making the code any "more minimal" is only possible once the actual solution/explanation is known. Before Paebbels's helpful comment, I had no idea that it is just that single process that I should be focusing on. This was as minimal as it got for me: this question started with me noticing the bug in a CPU in ~300 lines of CLaSH, which I had cut down to something that emitted VHDL which I then cut down to this. All in all, it started from ~6000 lines of VHDL.) – Cactus Oct 02 '18 at 10:17
  • 2
    [This question is being discussed on meta.](https://meta.stackoverflow.com/questions/374829/questions-where-the-code-could-be-made-more-minimal-but-only-once-the-answer-is) – Script47 Oct 02 '18 at 15:02
  • It's doesn't need to be "more minimal". The issue a lack of clear problem statement and reproducibility before the testbench was added (complete and verifiable). The accepted answer describes analysis based on personal experience (still asks about reset, demonstrated by the testbench). My comment demonstrating Paebbels first 'guess' was correct was prior to the testbench being added. The problem statement (para 2) depends on simulation (observation) and is still not apparent ("unknoqn" or at least not clear).May not help future readers (logical fallacy "more minimal" propagated to meta aside). –  Oct 02 '18 at 22:25

1 Answers1

3

Signal x is missing in the sensitivity list of process(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:

process(y, x)
begin
  -- some code
end process;

Is translated to:

process
begin
  -- some code
  wait on y, x;
end process;

So if they are clever, they could speculate to resume a process only on y events, but not on 'x' events. Some VHDL gurus might use this to optimize process wake-ups, others would call it a tricky code-line.


X values can be generated, when a signal contains meta values like U, -, X, W and arithmetic like + 1 is used.

I don't see any init values for tup2_sel1, except for a reset condition.
So, have you applied RESET in your simulation?

Paebbels
  • 15,573
  • 13
  • 70
  • 139
  • [The OP's `output` depends on the non-updated value](https://i.stack.imgur.com/7ALnD.jpg). IEEE Std 1076.6-2004, RTL Synthesis (withdrawn) required simulation match (5. Verfication methodology "The process of verifying synthesis results using simulation consists of applying equivalent inputs to both the original model and synthesized model and then comparing their outputs to ensure that they are equivalent.", 6.4 Combinational logic "For combinational logic, the process sensitivity list shall list all signals read within the process statement.") The models aren't equivalent. –  Oct 02 '18 at 23:41
  • The missing sensitivity on `x` is not intentional; in fact, it seems its absence is the resurfacing of a CLaSH bug thought to be already fixed: https://github.com/clash-lang/clash-compiler/issues/365 – Cactus Oct 03 '18 at 17:11