Controlling STD_LOGIC_ARITH Warning Messages

Johan M. Sandstrom

Sandstrom Engineering

johan@sandstrom.org

 

ABSTRACT

 

VHDL simulation startup usually fills the screen with assert warnings from std_logic_arith 
functions such as: 

  1. There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand,the result will be 'X'(es).
  2. CONV_INTEGER: There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, and it has been converted to 0. 

In this paper, Johan describes his techniques to intelligently intercept the std_logic_arith function 
calls: 

  • Asserting a warning message just the first time a function call argument is contiguously "is_x".
  • Asserting a warning message about "is_x" on a bus, not every bit of the bus.

After the offending function call argument is "clean" (is_x = false) the std_logic_arith function call
is no longer intercepted. Actually, if the argument was "clean" at time zero the std_logic_arith
function call would never be intercepted. 

VHDL simulation startup usually fills the screen with assert warnings such as:

There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, the result will be 'X'(es).

CONV_INTEGER: There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, and it has been converted
to 0. 

These std_logic_arith function warnings typically go away after the TestBench has applied enough stimulus and the unit_under_simulation has "flushed" the stimulus through the design.

These warnings are issued every time the function call is encountered, and for every bit of a bus in
the CONV_INTEGER function call. This not only takes a lot of time, but also masks any "real" 
notes, warnings, errors, even failures. 

1)    Don't turn off the warnings; Intelligently intercept
      the std_logic_arith function calls.
2)    Assert your own warning message just the first time a 
      function call argument is contiguously "is_x".
3)    Assert your own warning message about "is_x" on a bus,
      not every bit of the bus.
4)    After the offending function call argument is "clean" 
      (is_x = false) the std_logic_arith function call is no longer
      intercepted. Actually, if the argument was "clean" at time zero
      the std_logic_arith function call would never be intercepted.
5)    List of std_logic_arith operator functions with annoying messages 
      when arguments contain std_ulogic, std_logic_vector, unsigned, or 
      signed inputs:
 
       ieee.std_logic_arith."+"
       ieee.std_logic_arith."-"
       ieee.std_logic_arith."*"
       ieee.std_logic_arith."<"
       ieee.std_logic_arith."<="
       ieee.std_logic_arith.">"
       ieee.std_logic_arith.">="
       ieee.std_logic_arith."="
       ieee.std_logic_arith."/="
       ieee.std_logic_arith.shl
       ieee.std_logic_arith.shr
       ieee.std_logic_arith.conv_integer
       ieee.std_logic_arith.conv_unsigned
       ieee.std_logic_arith.conv_signed
       ieee.std_logic_arith.conv_std_logic_vector
       ieee.std_logic_arith.ext
       ieee.std_logic_arith.sxt
6)    The intercept code can be put into a component, then instantiated.
7)    This technique can and should be tailored to your unique simulation 
      "problems".
      To implement this "silencer" create a separate process for each signal
      that's causing the annoying warning messages:
   a) Determine if the signal has a 'U'|'X'|'W'|'Z'|'-' in any position 
      by using the ieee.std_logic_1164.is_x function.
   b) When the signal comes "clean" set an ok signal to true, then suspend
      the process forever.
   c) Use the ok signal to conditionally call the offending
      std_logic_arith function.

Here's an example of the process:

-- synopsys translate_off
a_ok_process : process
  variable first : boolean;
begin
  if a_ok then
    wait;
  else
    if is_x(a) then
      assert first report "is_x reported in a" severity warning; 
      first := true;
    else
      a_ok <= true;
    end if;
  end if;
  wait on a;
end process a_ok_process;
-- synopsys translate_on

Here's the full example with 1 entity and 4 architectures: 


-- model supplier:    Johan Sandstrom   310.977.9435 
--                                      johan@sandstrom.org
-- project:           Home study.
-- description:       Intercept overloaded operators.
-- filename:          silencer.vhd
-- design_unit(s):    silencer(rtl) = entity(architecture) 
-- synthesizable?     Yes.
-- yyyy/mm/dd         Modifier          Description of Change
-- ----------         --------          -------------------------------------
-- 1996/11/20         Johan             Work In Process.

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

entity silencer is
port(w : in std_logic;
     a : in std_logic_vector(3 downto 0);
     b : in std_logic_vector(3 downto 0);
     y : out std_logic_vector(3 downto 0));
end silencer;

architecture before_concurrent of silencer is 
begin

  y <= signed(a) + signed(b);

end before_concurrent; 


architecture after_concurrent of silencer is 
  signal a_ok : boolean;
  signal b_ok : boolean;
begin
 
  y <= signed(a) + signed(b)
     -- synopsys translate_off
     when a_ok and b_ok else (others => 'X')
     -- synopsys translate_on
     ;
 
  -- synopsys translate_off
  a_ok_process : process
    variable first : boolean;
  begin
    if a_ok then
      wait;
    else
      if is_x(a) then
        assert first report "is_x reported in a" severity warning; 
        first := true;
      else
        a_ok <= true;
      end if;
    end if;
    wait on a;
  end process a_ok_process;
  -- synopsys translate_on
 
  -- synopsys translate_off
  b_ok_process : process
    variable first : boolean;
  begin
    if b_ok then
      wait;
    else
      if is_x(b) then
        assert first report "is_x reported in b" severity warning; 
        first := true;
      else
        b_ok <= true;
      end if;
    end if;
    wait on b;
  end process b_ok_process;
  -- synopsys translate_on
 
end after_concurrent;

architecture before_sequential of silencer is 
  type mem_type is array (0 to 15) of std_logic_vector(3 downto 0); 
begin
 
  combinatorial : process(a, b, w)
    variable memory : mem_type;
  begin
    if w = '1' then
      memory(conv_integer(unsigned(a))) := b; -- write
    elsif w = '0' then
      y <= memory(conv_integer(unsigned(a))); -- read
    end if;
  end process combinatorial;
 
end before_sequential;

architecture after_sequential of silencer is 
  type mem_type is array (0 to 15) of std_logic_vector(3 downto 0); 
  signal a_ok : boolean;
begin
 
  combinatorial : process(a, b, w, a_ok)
    variable memory : mem_type;
  begin
    -- synopsys translate_off
    if a_ok then
    -- synopsys translate_on
      if w = '1' then
        memory(conv_integer(unsigned(a))) := b; -- write
      elsif w = '0' then
        y <= memory(conv_integer(unsigned(a))); -- read
      end if;
      -- synopsys translate_off
    else
      y <= (others => 'X');
    end if;
    -- synopsys translate_on
  end process combinatorial;
 
  -- synopsys translate_off
  a_ok_process : process
    variable first : boolean;
  begin
    if a_ok then
      wait;
    else
      if is_x(a) then
        assert first report "is_x reported in a" severity warning; 
        first := true;
      else
        a_ok <= true;
      end if;
    end if;
    wait on a;
  end process a_ok_process;
  -- synopsys translate_on
 
end after_sequential;

Here's the TestBench:

-- model supplier:   Johan Sandstrom   310.977.9435 
--                                      johan@sandstrom.org
-- project:          Home study
-- description:      Intercept overloaded operators.
-- filename:         silencer_tb.vhd
-- design_unit(s):   silencer_tb(bhv) = entity(architecture) 
-- synthesizable?    No.
-- yyyy/mm/dd        Modifier    Description of Change
-- ----------        --------    -------------------------------------
-- 1996/11/20        Johan       Work In Process.

library ieee; use ieee.std_logic_1164.all; 
              use ieee.std_logic_arith.all
 
entity silencer_tb is end silencer_tb
 
architecture bhv of silencer_tb is 
 
  component silencer
    port(w : in std_logic;
         a : in std_logic_vector(3 downto 0);
         b : in std_logic_vector(3 downto 0);
         y : out std_logic_vector(3 downto 0));
  end component;
 
  signal clk : std_logic := '1';
  signal w : std_logic := '1';
  signal a : std_logic_vector(3 downto 0); 
  signal b : std_logic_vector(3 downto 0); 
  signal y : std_logic_vector(3 downto 0); 
 
begin
 
  i1 : silencer
    port map(w => w,
             a => a,
             b => b,
             y => y);
 
  clk <= not(clk) after 5 ns;
 
  process
  begin
    stimulus_loop : for i in 0 to 15 loop
      case i is
        when  0 => a <= "UUUU"; w <= '0';
        when  1 => b <= "000X"; w <= '1';
        when  2 => a <= "00Z0"; w <= '0';
        when  3 => b <= "00ZZ"; w <= '1';
        when  4 => a <= "0X00"; w <= '0';
        when  5 => b <= "0101"; w <= '1';
        when  6 => a <= "0110"; w <= '0';
        when  7 => b <= "0111"; w <= '1';
        when  8 => a <= "1000"; w <= '0';
        when  9 => b <= "X00X"; w <= '1';
        when 10 => a <= "1010"; w <= '0';
        when 11 => b <= "1011"; w <= '1';
        when 12 => a <= "XX00"; w <= '0';
        when 13 => b <= "1101"; w <= '1';
        when 14 => a <= "1110"; w <= '0';
        when 15 => b <= "1111"; w <= '1';
      end case;
      wait until rising_edge(clk);
    end loop stimulus_loop;
    assert false report "Not really a failure, just ending the simulation." 
      severity failure;
    wait;
  end process;
 
end bhv;
 
configuration silencer_tb_cfg of silencer_tb is 
  for bhv
    -- choose one of the following:
--  for i1: silencer use entity work.silencer(before_concurrent); end for; 
--  for i1: silencer use entity work.silencer(after_concurrent); end for; 
--  for i1: silencer use entity work.silencer(before_sequential); end for; 
    for i1: silencer use entity work.silencer(after_sequential); end for; 
  end for;
end silencer_tb_cfg;
 

Here's the before_concurrent simulation transcript and listing: 

Loading work.silencer(before_concurrent

** Warning: There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, 
                                            the result will be 'X'(es)! 
Time: 0 ns Iteration: 0 Instance:/i1 

** Warning: There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, 
                                            the result will be 'X'(es)! 
Time: 0 ns Iteration: 0 Instance:/i1 

** Warning: There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, 
                                            the result will be 'X'(es)! 
Time: 10 ns Iteration: 1 Instance:/i1 

** Warning: There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, 
                                            the result will be 'X'(es)! 
Time: 10 ns Iteration: 1 Instance:/i1 

** Warning: There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, 
                                            the result will be 'X'(es)! 
Time: 20 ns Iteration: 1 Instance:/i1 

** Warning: There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, 
                                            the result will be 'X'(es)! 
Time: 20 ns Iteration: 1 Instance:/i1 

** Warning: There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, 
                                            the result will be 'X'(es)! 
Time: 30 ns Iteration: 1 Instance:/i1 

** Warning: There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, 
                                            the result will be 'X'(es)! 
Time: 30 ns Iteration: 1 Instance:/i1 

** Warning: There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, 
                                            the result will be 'X'(es)! 
Time: 40 ns Iteration: 1 Instance:/i1 

** Warning: There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, 
                                            the result will be 'X'(es)! 
Time: 40 ns Iteration: 1 Instance:/i1 

** Warning: There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, 
                                            the result will be 'X'(es)! 
Time: 50 ns Iteration: 1 Instance:/i1 

** Warning: There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, 
                                            the result will be 'X'(es)! 
Time: 90 ns Iteration: 1 Instance:/i1 

** Warning: There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, 
                                            the result will be 'X'(es)! 
Time: 100 ns Iteration: 1 Instance:/i1 

** Warning: There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, 
                                            the result will be 'X'(es)! 
Time: 120 ns Iteration: 1 Instance:/i1 

** Warning: There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, 
                                            the result will be 'X'(es)! 
Time: 130 ns Iteration: 1 Instance:/i1 

** Failure: Not really a failure, just ending the simulation. 
Time: 160 ns Iteration: 0 Instance:/ 

ns delta  w    a    b    y 
 0  +0    0 UUUU UUUU XXXX 
10  +0    1 UUUU 000X XXXX 
20  +0    0 00Z0 000X XXXX 
30  +0    1 00Z0 00ZZ XXXX 
40  +0    0 0X00 00ZZ XXXX 
50  +0    1 0X00 0101 XXXX 
60  +0    0 0110 0101 1011 
70  +0    1 0110 0111 1101 
80  +0    0 1000 0111 1111 
90  +0    1 1000 X00X XXXX 
100 +0    0 1010 X00X XXXX 
110 +0    1 1010 1011 0101 
120 +0    0 XX00 1011 XXXX 
130 +0    1 XX00 1101 XXXX 
140 +0    0 1110 1101 1011 
150 +0    1 1110 1111 1101


Here's the after_concurrent simulation transcript and listing: 

Loading work.silencer(after_concurrent

** Warning: is_x reported in b 
Time: 0 ns Iteration: 0 Instance:/i1 

** Warning: is_x reported in a 
Time: 0 ns Iteration: 0 Instance:/i1 

** Warning: There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, 
                                            the result will be 'X'(es)! 
Time: 90 ns Iteration: 1 Instance:/i1 

** Warning: There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, 
                                            the result will be 'X'(es)! 
Time: 100 ns Iteration: 1 Instance:/i1 

** Warning: There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, 
                                            the result will be 'X'(es)! 
Time: 120 ns Iteration: 1 Instance:/i1 

** Warning: There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, 
                                            the result will be 'X'(es)! 
Time: 130 ns Iteration: 1 Instance:/i1 

** Failure: Not really a failure, just ending the simulation. 
Time: 160 ns Iteration: 0 Instance:/ 

ns delta w    a    b    y 
0   +0   0 UUUU UUUU XXXX 
10  +0   1 UUUU 000X XXXX 
20  +0   0 00Z0 000X XXXX 
30  +0   1 00Z0 00ZZ XXXX 
40  +0   0 0X00 00ZZ XXXX 
50  +0   1 0X00 0101 XXXX 
60  +0   0 0110 0101 1011 
70  +0   1 0110 0111 1101 
80  +0   0 1000 0111 1111 
90  +0   1 1000 X00X XXXX 
100 +0   0 1010 X00X XXXX 
110 +0   1 1010 1011 0101 
120 +0   0 XX00 1011 XXXX 
130 +0   1 XX00 1101 XXXX 
140 +0   0 1110 1101 1011 
150 +0   1 1110 1111 1101


Here's the before_sequential simulation transcript and listing: 

Loading work.silencer(before_sequential

** Warning: CONV_INTEGER: There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic 
                          operand, and it has been converted to 0! 
Time: 0 ns Iteration: 0 Instance:/i1 

** Warning: CONV_INTEGER: There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic 
                          operand, and it has been converted to 0! 
Time: 0 ns Iteration: 0 Instance:/i1 

** Warning: CONV_INTEGER: There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic 
                          operand, and it has been converted to 0! 
Time: 0 ns Iteration: 0 Instance:/i1 

** Warning: CONV_INTEGER: There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic 
                          operand, and it has been converted to 0! 
Time: 0 ns Iteration: 0 Instance:/i1 

** Warning: CONV_INTEGER: There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic 
                          operand, and it has been converted to 0! 
Time: 0 ns Iteration: 1 Instance:/i1 

** Warning: CONV_INTEGER: There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic 
                          operand, and it has been converted to 0! 
Time: 0 ns Iteration: 1 Instance:/i1 

** Warning: CONV_INTEGER: There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic 
                          operand, and it has been converted to 0! 
Time: 0 ns Iteration: 1 Instance:/i1 

** Warning: CONV_INTEGER: There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic 
                          operand, and it has been converted to 0! 
Time: 0 ns Iteration: 1 Instance:/i1

** Warning: CONV_INTEGER: There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic 
                          operand, and it has been converted to 0! 
Time: 10 ns Iteration: 1 Instance:/i1 

** Warning: CONV_INTEGER: There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic 
                          operand, and it has been converted to 0! 
Time: 10 ns Iteration: 1 Instance:/i1 

** Warning: CONV_INTEGER: There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic 
                          operand, and it has been converted to 0! 
Time: 10 ns Iteration: 1 Instance:/i1 

** Warning: CONV_INTEGER: There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic 
                          operand, and it has been converted to 0! 
Time: 10 ns Iteration: 1 Instance:/i1 

** Warning: CONV_INTEGER: There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic 
                          operand, and it has been converted to 0! 
Time: 20 ns Iteration: 1 Instance:/i1 

** Warning: CONV_INTEGER: There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic 
                          operand, and it has been converted to 0! 
Time: 30 ns Iteration: 1 Instance:/i1 

** Warning: CONV_INTEGER: There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic 
                          operand, and it has been converted to 0! 
Time: 40 ns Iteration: 1 Instance:/i1 

** Warning: CONV_INTEGER: There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic 
                          operand, and it has been converted to 0! 
Time: 50 ns Iteration: 1 Instance:/i1 

** Warning: CONV_INTEGER: There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic 
                          operand, and it has been converted to 0! 
Time: 120 ns Iteration: 1 Instance:/i1 

** Warning: CONV_INTEGER: There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic 
                          operand, and it has been converted to 0! 
Time: 120 ns Iteration: 1 Instance:/i 

** Warning: CONV_INTEGER: There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic 
                          operand, and it has been converted to 0! 
Time: 130 ns Iteration: 1 Instance:/i1 

** Warning: CONV_INTEGER: There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic 
                          operand, and it has been converted to 0! 
Time: 130 ns Iteration: 1 Instance:/i1 

** Failure: Not really a failure, just ending the simulation. 
Time: 160 ns Iteration: 0 Instance:/ 

ns delta w    a    b    y 
0   +0   0 UUUU UUUU XXXX 
10  +0   1 UUUU 000X XXXX 
20  +0   0 00Z0 000X XXXX 
30  +0   1 00Z0 00ZZ XXXX 
40  +0   0 0X00 00ZZ XXXX 
50  +0   1 0X00 0101 XXXX 
60  +0   0 0110 0101 UUUU 
70  +0   1 0110 0111 UUUU 
80  +0   0 1000 0111 UUUU 
90  +0   1 1000 X00X UUUU 
100 +0   0 1010 X00X UUUU 
110 +0   1 1010 1011 UUUU 
120 +0   0 XX00 1011 UUUU 
130 +0   1 XX00 1101 UUUU 
140 +0   0 1110 1101 UUUU 
150 +0   1 1110 1111 UUUU

Summary:

I've demonstrated an elementary implementation of this interception technique:

    a) Starting at simulation time zero. 
    b) Severity of warning. 
    c) Std_Logic_Arith functions. 

This intercept technique can also be applied to user written routines that use textio or
asserts of any severity, and can be executed any time during the simulation with
appropriate conditionals like "if (now > some_time) and (is_x(some_signal)) then ...".

You can make your VHDL simulator much more efficient! 

 

 

Home | About Us | Demo | Products| Articles | Methodology | Vocation | Avocation