Search code examples
vhdlquartus

How to check for "ZZZZ" input in VHDL?


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


Solution

  • 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;