Search code examples
casevhdlassign

Multiple assignments in CASE statement in VHDL


I am still new to VHDL. I need to assign values to multiple signals in CASE statement, something like this :

CASE input24 IS
WHEN "00" THEN 
                    output0 <= '1' ;
                    output1 <= '0' ;
                    output2 <= '0' ;
                    output3 <= '0' ;

WHEN "01" THEN 
                    output0 <= '0' ;
                    output1 <= '1' ;
                    output2 <= '0' ;
                    output3 <= '0' ;

WHEN "10" THEN 
                    output0 <= '0' ;
                    output1 <= '0' ;
                    output2 <= '1' ;
                    output3 <= '0' ;

WHEN "11" THEN 
                    output0 <= '0' ;
                    output1 <= '0' ;
                    output2 <= '0' ;
                    output3 <= '1' ;

Before trying this I tried assigning the values in a single line like this

WHEN "00" => output0 <= '1', output1 <= '0', output2 <= '0', output3 <= '0' ;

The second one gave an error

found '0' definitions of operator "<=", cannot determine exact 
overloaded matching definition for "<="

while the first one a syntax error.

Where am I going wrong ?

Is there a way to assign values to multiple signals for a single case ?

Thank you


Solution

  • When using CASE the syntax is WHEN "00" =>, thus no use of THEN. The code is therefore:

    CASE input24 IS
      WHEN "00" =>
        output0 <= '1' ;
        output1 <= '0' ;
        output2 <= '0' ;
        output3 <= '0' ;
    ...
    

    If input24 is std_logic_vector you must when the case with a WHEN OTHERS => to handle the remaining encodings of input24. The code is:

    WHEN OTHERS =>
      output0 <= 'X' ;
      output1 <= 'X' ;
      output2 <= 'X' ;
      output3 <= 'X' ;
    

    For writing the assignment in a single like, still use ; as statement separator, thus not , as shown in the question code, and then just remove the whitespace. The code is:

    WHEN "01" => output0 <= '0'; output1 <= '1'; ...
    

    For assign to multiple signals in one statement, the VHDL-2008 supports aggregate assignment, so if you are using VHDL-2008, you can write:

    WHEN "10" =>
      (output3, output2, output1, output0) <= std_logic_vector'("0100");
    

    For VHDL-2003, a solution may be to create an intermediate output signal as std_logic_vector, and then assign to this. Code can then be:

      ...
      signal output : std_logic_vector(3 downto 0);
    begin
      ...
          WHEN "11" =>
            output <= "1000";
      ...
      output0 <= output(0);
      output1 <= output(1);
      output2 <= output(2);
      output3 <= output(3);
    

    If the output is used, then the exact implementation where the case is just used to set the bit with number given in input24 can be made with:

    LIBRARY IEEE;
    USE IEEE.NUMERIC_STD.ALL;
    
    ARCHITECTURE syn OF mdl IS
    
      SIGNAL output : STD_LOGIC_VECTOR(3 DOWNTO 0);
    
    BEGIN
    
      PROCESS (input24) IS
      BEGIN
        output <= (OTHERS => '0');
        output(TO_INTEGER(UNSIGNED(input24))) <= '1';
      END PROCESS;
    
      output0 <= output(0);
      output1 <= output(1);
      output2 <= output(2);
      output3 <= output(3);
    
    END ARCHITECTURE;
    

    Otherwise, if the output signal is not used, then the case can still be simplified through a default assign as '0' to the outputs, thus with the code:

    ARCHITECTURE syn OF mdl IS
    BEGIN
    
      PROCESS (input24) IS
      BEGIN
        output0 <= '1' ;
        output1 <= '0' ;
        output2 <= '0' ;
        output3 <= '0' ;
        CASE input24 IS
          WHEN "00" => output0 <= '1' ;
          WHEN "01" => output1 <= '1';
          WHEN "10" => output2 <= '1' ;
          WHEN "11" => output3 <= '1' ;
          WHEN OTHERS => output0 <= 'X'; output1 <= 'X'; output2 <= 'X'; output3 <= 'X';
        END CASE;
      END PROCESS;
    
    END ARCHITECTURE;