2

I have a in std_logic_vector(3 downto 0) and a out std_logic_vector(6 downto 0). With a process and case, I am checking all possible binary conditions such as when "0000" => output_var <= "1111111"; and so on. My program works for all specified binary combinations input to output in simulation.

I added this additional line in cases: when "ZZZZ" => output_var <= "0000000"; but this never works, in simulation(quartus) outputs undefined when input is "ZZZZ". What might I be doing wrong, is check of "ZZZZ" not allowed?

EDIT1:

library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;

entity my_entity is
    port(
        input_var : in std_logic_vector(3 downto 0);
        output_var : out std_logic_vector(3 downto 0));
end my_entity;

architecture arch of my_entity is
begin
    process(input_var) begin
        case input_var is
            when "0000" => output_var <= "1011110";
            when "0001" => output_var <= "0100000";
            when "0010" => output_var <= "0101101"; -- and so on
            when "ZZZZ" => output_var <= "0000000"; -- ++
        end case;
    end process;
end arch; 

EDIT2:

Top most is the 4 input, bottom: expanded 7 output; waveform simulation (EDIT 3: for not the same exact code shown above, - but to demonstrate example of what the simulation shows when ZZZZ)

enter image description here

Robert C. Holland
  • 1,651
  • 4
  • 24
  • 57
  • Is the case statement in a testbench or in a synthesizable block/module? –  Jul 22 '17 at 17:35
  • @ahmedus Sorry I don't understand enough about this subject to understand the question. I have a vhdl file with entity and architecture that I compiled. After that, I created a "University program VWF" file importing the nodes from compiled and setup some input waveform for simulation/test. All in Quartus Prime Lite software. – Robert C. Holland Jul 22 '17 at 17:39
  • @ahmedus Thanks. Could you suggest me keywords I can look up to understand why output can be Z but not for the inputs checks? – Robert C. Holland Jul 22 '17 at 19:15
  • 1
    IEEE Std 1076-2008 **16.8.2.4.10 Interpretation of the high-impedance value ('Z')** paragraph 4 - *Whenever a static high-impedance value occurs in any context other than a value expression in an assignment statement, a synthesis tool shall treat it as equivalent to a static metalogical value.* **16.8.2.4.5 Metalogical values as a choice in a case statement** para 1 (in part) - *If a metalogical value occurs as a choice, or as an element of a choice, in a case statement that is interpreted by a synthesis tool, the synthesis tool shall interpret the choice as one that can never occur. ...* –  Jul 22 '17 at 22:23
  • @user1155120 I edited the question to add relevant part of the code. – Robert C. Holland Jul 22 '17 at 22:55
  • @user1155120 Added picture of the waveform simulation – Robert C. Holland Jul 22 '17 at 23:33
  • @user1155120 having it as others in case also produces undefined in simulation. – Robert C. Holland Jul 23 '17 at 00:26
  • @user1155120: the question post is not your scratchpad to use for comments. – Martijn Pieters Jul 23 '17 at 13:23
  • The simulation is clearly not the result of the shown code fragment. Output for `0000` input is `0000001` as opposed to `1011110`... – FRob Jul 24 '17 at 23:33

1 Answers1

4

The tool you are using to validate your design is probably not a VHDL simulator. More likely, it is a logic synthesizer, coupled with a gate-level simulator. It first generates a gate-level implementation of your design and next simulates it.

It is important to distinguish simulation of the VHDL code, synthesis of the VHDL code and simulation of the synthesis results.

  1. Let's start with simulation

    std_logic is a nine-values enumerated type ('0', '1'and 'Z' are 3 of them, the 6 others are '-', 'U', 'X', 'H', 'L', 'W'). Your 4-bits std_logic_vector input_var can thus take 9^4 = 6561 different values. Your first code is invalid and should not even compile because your case statement does not list all possible values of the selector. The use of the special choice others, that covers all not yet listed choices, is an elegant way to deal with this kind of situation:

    process (input_var) 
    begin
      case input_var is
        when "0000" => output_var <= "1011110";
        when "0001" => output_var <= "0100000";
        when "0010" => output_var <= "0101101"; -- and so on
        when "ZZZZ" => output_var <= "0000000"; -- ++
        when others => output_var <= "0000000"; -- others
      end case;
    end process;
    

    With this error fixed, your code should compile, simulate and produce the exact results you are expecting: when the selector takes value "ZZZZ", the output should take value "0000000". For the simulator "ZZZZ" is just one of the possible values of input_var, without any special meaning, just like "1111" or "1010". Any valid simulator (that is respecting the VHDL standard) would behave the same. This code is valid.

  2. Synthesis

    Logic synthesis is the process of assembling logic gates (registers, and, or, xor, not...) to implement the behaviour of your VHDL code. And there, you have a problem because it would be very difficult to create hardware that would detect value "ZZZZ", especially to distinguish 'Z' from 'H', 'L' and 'W', which are other high-impedance values. Even with a type limited to '0', '1' and 'Z' (which is not the case of std_logic), detecting high-impedance in hardware is probably not impossible but difficult. As you are using Quartus, I guess that your target is an Altera FPGA. There is no such high-impedance detection hardware in FPGAs.

  3. Post-synthesis simulation

    Simulating the result of synthesis brings us back in the simulation (computer science) world. The handling of weak ('Z', 'L', 'H' or 'W') or unknown ('U', 'X' or '-') values is tool-dependent. In most cases gate-level simulators highlight these values because, except in rare cases, they are undesirable and the consequence of design or coding errors. And the tool may chose to over-exaggerate by propagating these values even when real hardware would not. It is a way to warn you that something is wrong (again, except in very rare cases, you do not want these values in your digital hardware).

Anyway, what you apparently design is a 7-segments controller. Handle all values that are not '0' or '1' in an others choice that will also cover your last valid configuration. This should work as expected both in simulation, synthesis and post-synthesis simulation. If you really want to be warned when one of your inputs is not '0' or '1', during pre-synthesis simulation, you can add a non-synthesizable assertion, something like:

architecture arch of my_entity is

  function is_01(v: std_logic_vector) return boolean is
  begin
    for i in v'range loop
      if v(i) /= '0' and v(i) /= '1' then
        return false;
      end if;
    end loop;
    return true;
  end function is_01;

begin

-- pragma synthesis_off
  assert is_01(input_var) report "Invalid input" severity error; 
-- pragma synthesis_on

  process (input_var) 
  begin
    case input_var is
      when "0000" => output_var <= "1011110";
      when "0001" => output_var <= "0100000";
      when others => output_var <= "0101101"; -- others, including "0010"
    end case;
  end process;

end architecture arch;
Renaud Pacalet
  • 25,260
  • 3
  • 34
  • 51
  • 1
    Great answer. But maybe better to use standardized function `Is_X` from `std_logic_1164`, possibly succeeded by `to_x01` if it passes? – JHBonarius Jul 23 '17 at 11:33
  • `ieee.std_logic_1164.is_x` is slightly different: it returns false on `L` and `H`. – Renaud Pacalet Jul 23 '17 at 13:17
  • That's why I suggested to follow up with `to_x01` in order to resolve the weak high and weak low.... – JHBonarius Jul 23 '17 at 14:35
  • 2
    Yep, but `to_x01` converts `'L'` to `'0'` and `'H'` to `'1'`. I am not saying it is a wrong idea, just that it differs from the `is_01` I propose. – Renaud Pacalet Jul 23 '17 at 16:46