0 votes
in VHDL by (200 points)

What is a VHDL case statement, and what is the code for them?

4 Answers

0 votes
by (1.8k points)

VHDL Case Statements

Quick Syntax

case my_state is
when "00" =>
my_output <= 0;
when "01" =>
my_output <= 2;
when "10" =>
my_output <= 4;
when others =>
my_output <= 7;
end case;

Purpose

The case statement is one of your main bread and butter abilities in VHDL. You can do so many different things with it, it's important to master using it. For example, you can do things like advanced muxes, state machines, decoders, etc. It's typically found all over the place in protocol interfaces, memory interfaces, register reads and writes, and so on.

Keep in mind that the case statement has to be inside a process block. It's intended to allow you to specifically name the states or you can enumerate your own custom states which is recommended in state machines.

Example

In this example, we are using a case statement to create registers that we can write to on a bus. You would normally have an equivalent read process and case statement to handle the reads. Using constants at the top (or even in a package) makes it convenient for changing the bus addresses for re-use.
constant FPGA_VERSION            : std_logic_vector(7 downto 0)   := x"10";
constant OUTPUT_SETTINGS : std_logic_vector(7 downto 0) := x"11";
constant REPORT_SETTINGS : std_logic_vector(7 downto 0) := x"12";
constant SET_BUFFER : std_logic_vector(7 downto 0) := x"13";

-- Write Command PROC_WRITE_CMD : process (clk)
begin

if rising_edge(clk) then

-- defaults response_pending <= '0';
read_error <= '0';

-- write enable if write_en = '1' then

case write_addr is

when FPGA_VERSION =>
response_pending <= '1';

when OUTPUT_SETTINGS =>
out_settings_int <= cmd_message_in_data;

when REPORT_SETTINGS =>
response_pending <= '1';
report_settings_int <= cmd_message_in_data(7 downto 0);

when SET_BUFFER =>
buffer_update_int <= cmd_message_in_data(15 downto 8);

---- many other address registers here as needed
when others =>
read_error <= '1';

end case;
end if;
end if;
end process;
If you want to enumerate the states, like in a state machine, here's how you can do it:
-- states
type my_states is (idle, start, stop);
signal sm_state : my_states;

PROC_SM : process (clk)
begin

if rising_edge(clk) then

case sm_state is

when idle =>
my_output <= 0;

when start =>
my_output <= 2;

when stop =>
my_output <= 4;

when others =>
my_output <= 7;

end case;
end if;
end process;

Best Practices

1. Use case statements instead of if statements when the if statement has more than 3-5 options. Why? Case statements are much easier to read and edit and make for much cleaner code. It's debatable on whether one or the other is more efficient in hardware given today's advanced synthesis tools. It just depends on the situation.

2. Cover all of the possible states with your when statements. Also, always use a when others at the end, even if you have covered all of the known states. Why? Because someone (or even you) might come in after you and remove a state above thinking it's not needed anymore for the design and now it opens the design up to a bug.

3. For bigger case statements with many output signals, I like to use "defaults" at the top before the case to cover signals that don't change when going from state to state, that way you don't have to keep listing the same signals and driving them at each state. It makes for much cleaner code and you only have to code the signals that do change at each state. Remember a process goes from top to bottom and a signal becomes the last valid line in the process on the next clock cycle. So using defaults at the top makes sure that all signals are driven unless updated below in the process.

4. For clocked case statements, if an input signal is used to determine the state, it must be on the same clock domain as the case block, otherwise you will run into metastability problems which can make the state unknown or wrong. All incoming signals should adhere to proper clock domain crossing best practices, like registering it twice (or 3 times) on the new clock domain before reading the signal to determine the state. If all inputs and outputs in regards to the case statement are on the same clock, you don't have to worry about this.
0 votes
by (700 points)

The VHDL "case" statement is very similar to the switch statement in C. It's used for non-prioritized conditional execution ( compared to if-else ).

Example :

case_example : process ( some_integer ) is
begin
       case some_integer is
               when 1 =>
                       output <= 1 ;
               when 2 =>
                       output <= 3 ;
               when 3 =>
                       output <= 2 ;
               when others =>
                       output <= 4 ;
       end case ;
end process case_example ;
0 votes
by (700 points)

From the VHDL standard:
A case statement selects for execution one of a number of alternative sequences of statements. The chosen alternative is defined by the value of an expression.

Syntax:

   case_statement = [case_lable : ] case expression is
   case_satement_alternative
   {case_satement_alternative}
   end case [case_lable] ;

case_satement_alternative = when choices => sequence_of_statements

process (all)
variable v_state : state_t;
   begin
   v_state := state;

   case state is
       when idle =>
           ....do some stuff
       when ctrl_configured =>
           ....do other stuff
       when config_ram =>
           ....do more
       when scan_ram_state =>
           ....do less
       when others => null;
   end case;
       state_next <= v_state;
end process;

case ram_segment_mode_control is
   when x"0" | x"3" | x"4" =>
       null;
   when x"1" =>
       ...do some stuff
   when x"2" =>
       ...do some stuff
   when x"5" =>
       case internal_profile_control is
           when "001" =>
               ....
           when "010" =>
               ....
           when "011" =>
               ....
           when others =>
               null;
       end case;
   when others => null;
end case;
0 votes
by (700 points)

If you are familiar with the 'switch' statement in the C language then understanding the case statement in VHDL will be pretty easy. An input is compared against multiple cases to see which one it satisfies and statements are executed accordingly. A default is also set which is executed when the input does not satisfy any of the cases.

An important thing to note here is that unlike other conditional statements, the case statement does not allow the use of relational operators like 'less than' or 'greater than'. Only equality operator can be used.

However, the synthesis of the case statement is more efficient than the synthesis of the if-else statement.

case expression is
   when choice =>
       sequential_statements
   when choice =>
     sequential_statements
   . . .
   end case;
Example code is given below to further explain this concept. Out_2 is assigned a value depending on the value of example.
case example is
   when "00" =>
   Out_2 <= 0;
   when "01" =>
   Out_2 <= 1;
   when "10" =>
   Out_2 <= 2;
   when "11" =>
   Out_2 <= 3;
end case;
Hardware Coder Community

© 2022 by Hardware Coder. User contributions are licensed under cc by-sa 4.0 with attribution required. Attribution means a link to the question, answer, user, etc on this site.

This site is owned and operated by Hardware Coder in McKinney, Texas.

Send Us A Message
About Us

By using this site, you agree to the following:

Privacy Policy
Terms and Conditions
DMCA Policy
Earnings Disclaimer
Legal Disclaimer

...