in vhdl case statements,how to deal with 4 value logic?

1.3k views Asked by At

I am a newer to vhdl, and I'm working for a project.

but something block me recently:

   if reset='0' then 
      prstate<="00";
      else if rising_edge(clock)  then
      case  prstate  is
          when "00"=> 
               if wd_link='1'   then
               prstate<="01";
          when "01"=> 
               (do something and) prstate<="10";
          when "10"=> 
                (do something and) prstate<="11";  
          when "11"=> 
                (do something and) prstate<="00";  
          when others=>   prstate<="00"; ----please pay attention to this line

RTL simulation:

at first,I deleted the last line,but modelsim tell me there are only 4 case statements out of 81.My god,I studied that 1 bit contains 9 values.maybe the last line is used to correct errors? maybe when prstate is "0x" or "xx",this line bring it to 00?ok,maybe.

after synthesizing by synopsys DC,there is a warning(about the case):the default branch of case cannot be reached. hah!i don't know why and i don't care.

Post simulation(using the same testbench and the netlist):

after I set and release the reset input,modelsim showed that another module give the wd_link an "x",which cause a big error=>the prstate<="xx" and xx,and xx,and end to xx...even wd_link recover to 0 or 1.

I guess:DC disagree 4 value logic(01xz) or 9 value logic.so the last line is killed.but what can i do?

Please help me,all you are my god.Thank you! sincerely.

2

There are 2 answers

5
Morten Zilmer On BEST ANSWER

If the value of prstate is always to be well defined ("00", "01", "10" or "11"), then you can propagate any undefined values if you use:

when others => prstate <= (others => "XX");

Simulation will then show 'X's in more places in case of a bug, thus making catching easier.

Synthesis will usually use the 'X's as a freedom to make the netlist smaller or faster, depending on requirements.

1
AudioBubble On

std_logic is a multivalue logic system with 9 values.

A case statement (IEEE Std 1076-2008 10.9 Case statement) requires all values to be represented as choices (paragraph 5).

There are a couple of other things you could do besides Morten's answer. You could convert a std_logic_vector case expression to bit_vector variable via the package std_logic_1164 function to_bitvector (noting you haven't demonstrated the declaration for prstate).

architecture fum of others_case is
    signal wd_link:     std_logic;
    signal prstate:     std_logic_vector(1 downto 0);

   function do_something return boolean is
    begin
        return true;
    end function;
begin

    process (reset, clock)
        variable prstate_proxy: bit_vector (1 downto 0); -- locally static range
    begin
        if reset = '0' then 
            prstate <= "00";
        elsif rising_edge(clock)  then
            prstate_proxy := to_bitvector(prstate);
            case  prstate_proxy  is
                when "00" => 
                    if wd_link = '1'   then
                        prstate <= "01";
                    end if;  -- ADDED
               when "01" => 
                     if do_something then
                         prstate <= "10";
                     end if;
               when "10" => 
                   if do_something then
                       prstate <= "11";
                   end if; 
               when "11" => 
                   if do_something then
                       prstate <= "10";
                   end if; 
               -- when others =>  ----please pay attention to this line
           end case;
       end if;
    end process;
end architecture;

Note the range of single dimensional array used as a case statement expression needs to be known at analysis time (locally static). This is satisfied by the variable declaration.

You can also leave the 'sequence of statements' for the others choice empty with all the binary value choices present:

library ieee;
use ieee.std_logic_1164.all;

entity others_case is
    port (
        reset:  in  std_logic;
        clock:  in  std_logic
    );
end entity;

architecture foo of others_case is
    signal wd_link:     std_logic;
    signal prstate:     std_logic_vector(1 downto 0);

   function do_something return boolean is
    begin
        return true;
    end function;
begin

    process (reset, clock)
    begin
        if reset = '0' then 
            prstate <= "00";
        elsif rising_edge(clock)  then
            case  prstate  is
                when "00" => 
                    if wd_link = '1'   then
                        prstate <= "01";
                    end if;  -- ADDED
               when "01" => 
                     if do_something then
                         prstate <= "10";
                     end if;
               when "10" => 
                   if do_something then
                       prstate <= "11";
                   end if; 
               when "11" => 
                   if do_something then
                       prstate <= "10";
                   end if; 
               when others =>  ----please pay attention to this line
           end case;
       end if;
    end process;

end architecture;

Note the lack of a semicolon (statement separator) in the others choice when no statement is present before the end statement. This provides the equivalent effect to Morten's answer.

These architectures and entity declaration represent a Minimal, Complete, and Verifiable example and while doing nothing interesting when simulated should be valid for synthesis.

Without seeing the rest of your design specification you don't need deal with metalogical values in your case statement when you reset prstate. Assignments to metalogical values are not valid for synthesis.

The others choice stands for all possible choices not mentioned specifically in preceding case statement alternatives or may stand for none.

The 9 value std_ulogic representation is categorized into three classes for synthesis. Values that map into binary values, metalogical values and the high-impedence value ('Z').

'H' and 'L' are mapped to '1' and '0' respectively for synthesis.

The metalogical values ('U', 'W', 'X' and '-') are not used as inputs evaluating VHDL code during synthesis.

'Z' represents a value that can be overridden by an additional driver.

It's not possible to make assignment or driving choices based a 'Z' value in a logic gate level (RTL) primitive library. They could have as easily found the others choice stood for no choice.

IEEE Std 1076-2008, 10.9 case statement paragraph 9:

The choice others is only allowed for the last alternative and as its only choice; it stands for all values (possibly none) not given in the choices of previous alternatives.

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, paragraph 1:

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. That is, the interpretation that is generated is not required to contain any constructs corresponding to the presence or absence of the sequence of statements associated with the choice.

Synopsys is warning of a problem that doesn't exist in RTL synthesis (also see the withdrawn IEEE Std-1076.6-2004, 5. Verification methodology, validating a synthesized design specification does not depend on inputting metalogical values).