Search code examples
vhdlverilogsystem-verilog

Can a constant expression ever be valid in a VHDL case statement?


I recall that in Verilog it can be valid to use a constant in the expression of a case statement, but is it also valid in VHDL?

// Verilog example
case(1'b1)                                
  A[2]:   Y<=2'b11;  
  A[1]:   Y<=2'b10;  
  A[0]:   Y<=2'b01;  
  default:Y<=2'b00;
endcase

Solution

  • No you can't express the case statement as a VHDL case statement

    Unlike Verilog, IEEE Std 1364-2005 9.5 Case statement para 4:

    The case expression and the case item expression can be computed at run time; neither expression is required to be a constant expression.

    In IEEE Std 1076-1993 8.8 Case statement, para 8 (also representative of -2008):

    The simple expression and discrete ranges given as choices in a case statement must be locally static. A choice defined by a discrete range stands for all values in the corresponding range. 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. An element simple name (see 7.3.2 ) is not allowed as a choice of a case statement alternative.

    From the glossary:

    locally static expression: An expression that can be evaluated during the analysis of the design unit in which it appears.

    analysis: The syntactic and semantic analysis of source code in a VHDL design file and the insertion of intermediate form representations of design units into a design library.

    (A fancy way of telling us compile time as opposed to elaboration (linking and loading). VHDL's definitions also embrace interpretive implementation.)

    The definition of a locally static expression requires A to be declared as a constant and in the VHDL LRM -1993 version a slice name or index name isn't locally static (See IEEE Std 1076-1993, 7.4.1 Locally static primaries para 1, 7.4.2 Globally static primaries, r. - globally static means at elaboration time). This is changed in the IEEE Std 1076-2008 for static index expressions or static index ranges (See IEEE Std 1076-2008, 9.4.2, n. and o.). It's likely synthesis vendors tools lag, even if you can simulate it, you likely can't synthesis it today.

    There's also the issue of multiple choices with the same value. See IEEE Std 1076-1993 8.8 Case statement, para 3 (also representative of -2008 for this issue):

    The expression must be of a discrete type, or of a one-dimensional array type whose element base type is a character type. This type must be determinable independently of the context in which the expression occurs, but using the fact that the expression must be of a discrete type or a one-dimensional character array type. Each choice in a case statement alternative must be of the same type as the expression; the list of choices specifies for which values of the expression the alternative is chosen.

    Where the expressions std_logic'('1') or S have a base type of std_ulogic. And this eliminates choices that are not of the base type of std_logic (std_ulogic - 'U', 'X', '0', '1', 'Z', 'W', 'L', 'H', '-', See IEEE Std 1076-2008 16.7 Standard multivalue logic package and Annex A footnote 15 which provides a link to the source for package std_logic_1164).

    Notice fru1tbat showed choices '0', '1' and others, evaluation of the expressions A(2), A(1) or A(0) returns a std_ulogic subtype and would give you multiple choices representing the same value ('1'). See IEEE Std 1076-1993, 8.8 para 7:

    For other forms of expression, each value of the (base) type of the expression must be represented once and only once in the set of choices, and no other value is allowed.

    So the case statement isn't directly expressible in VHDL, we're only interested in cases where A(2), A(1) and A(0) are '1' and only one choice is allowed. Instead we can use a conditional signal assignment statement:

    library ieee;
    use ieee.std_logic_1164.all;
    
    entity constexp is
    end entity;
    
    architecture foo of constexp is
        signal A:   std_logic_vector (2 downto 0) := "001";
        signal Y:   std_logic_vector (1 downto 0);
    begin
        
    COND: -- Conditional Signal Assignment statement
    
        Y <= "11" when A(2) = '1' else
             "10" when A(1) = '1' else
             "01" when A(0) = '1' else
             "00";
        
    end architecture;
    

    (And this design specification analyzes, elaborates and simulates.)

    A conditional signal assignment is a concurrent statement in the 1076-1993 standard (See 9.5.1 Conditional signal assignments) while a conditional signal assignment can be used as a sequential statement as well in the 1076-2008 standard (See 11.6 Concurrent signal assignment statements and 10.5.3 Conditional signal assignment). Today it's likely synthesis vendors would be -1993 compliant.

    And by definition any of the constructs here can be devolved into if statements which are sequential statements.