0
\$\begingroup\$

I'm new to VHDL so I just have a question to ask about why this produces an error. I have an ALU defined in VHDL:

c <=        a + b       WHEN opc="0111"
ELSE        a - b       WHEN opc="1000"
ELSE        -a          WHEN opc="1011"
ELSE        -b          WHEN opc="0001"
ELSE        ABS(a)      WHEN opc="1110"
ELSE        ABS (b)     WHEN opc="1010"
ELSE        NOT a       WHEN opc="0010"
ELSE        NOT b       WHEN opc="1100"
ELSE        a AND b     WHEN opc="0100"
ELSE        a OR b      WHEN opc="0110"
ELSE        a XOR b     WHEN opc="0101"

(this is the architecture)

But then I want to make it synchronous,

PROCESS (clock)
BEGIN
    IF(rising_edge(clock)) THEN
        c <=        a + b       WHEN opc="0101"
        ELSE        a - b       WHEN opc="1000"
        ELSE        -a          WHEN opc="1011"
        ELSE        -b          WHEN opc="0001"
        ELSE        ABS(a)      WHEN opc="1110"
        ELSE        ABS (b)     WHEN opc="1010"
        ELSE        NOT a       WHEN opc="0010"
        ELSE        NOT b       WHEN opc="1100"
        ELSE        a AND b     WHEN opc="0100"
        ELSE        a OR b      WHEN opc="0110"
        ELSE        a XOR b     WHEN opc="0111" 
    END IF
END PROCESS;

This doesn't work, it comes up with various errors like:

';' expected.
Keyword "end" expected.

So I have now changed my code to:

PROCESS (clock)
BEGIN
    IF(rising_edge(clock)) THEN 
        CASE opc IS
            WHEN "0101" => c <= a+b;       
            WHEN "1000" => c <= a-b;      
            WHEN "1011" => c <= -a;   
            WHEN "0001" => c <= -b;   
            WHEN "1110" => c <= ABS(a);  
            WHEN "1010" => c <= ABS(b); 
            WHEN "0010" => c <= NOT a;   
            WHEN "1100" => c <= NOT b;  
            WHEN "0100" => c <= a AND b;  
            WHEN "0110" => c <= a OR b;  
            WHEN "0111" => c <= a XOR b; 
        END CASE; 
    END IF; 
END PROCESS;

And this doesn't produce any errors. But why does the original code which worked when put in a process not work unless I use the case statement?

Thanks in advance.

\$\endgroup\$
  • 3
    \$\begingroup\$ The ternary operator c <= a when condition else b; is not allowed inside of process statements prior to VHDL-2008. SO you can enable VHDL-2008 support if your tool supports this or you use your later code example, which is much nicer :) \$\endgroup\$ – Paebbels Jan 12 '15 at 22:14
  • \$\begingroup\$ Paebbels is correct, and I have to add that if you are designing for ASIC or FPGA (specially) you should avoid nested If-Then-Elest statement. Also, at the end of your process add the "others" to make sure all the cases are covered with that statement. \$\endgroup\$ – FarhadA Jan 13 '15 at 9:30
  • \$\begingroup\$ Nitpick: conditional assignment is not exactly a "ternary operator", though it functions like one in this case. \$\endgroup\$ – fru1tbat Jan 14 '15 at 14:02
1
\$\begingroup\$

In order of effort:

  • If you have access to VHDL 2008 in your tools, enable it. If not, bug the vendor to support it!
  • add an extra signal calling c_sync and then add a line:

    c_sync <= c when rising_edge(clk);

  • Change your code to a set of if then statements.

\$\endgroup\$
1
\$\begingroup\$

Your first try to make it synchronous didn't work because:

  • You haven't enabled VHDL 2008 (as stated in the other answers/comments)
  • the end of the conditional assignment is missing a ;
  • your END IF is missing a ;

Your second try works, because it doesn't require VHDL 2008:

The case-statement has been supported in processes since the first VHDL version, while the conditional assignment was previously forbidden inside processes (which has been changed with VHDL 2008).

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.