Conditional Statements

We already have a view of the conditional statement in the previous blog, but let’s see with more explanation.

Conditional statements are used to base decisions on certain criteria. These criteria are used to determine whether or not to execute a statement.

if-else statement

For conditional statements, the keywords if and else are used. Conditional statements are classified into three categories: For formal syntax, use the conditional statements provided below.

//Type 1 conditional statement. No else statement.
 if (<expression>) true statement; 

//Type 2 conditional statement. One else statement
if (<expression>) true statement; else false statement ;

//Type 3 conditional statement. Nested if-else-if.
if (<expression1>) true_statement1 ;
else if (<expression2>) true statement2;
 else if (<expression3>) true statement3;
 else default_statement ;

The <expression> is tested. The true statement is executed if it is true (1 or a non-zero value). If it is false (zero) or ambiguous (x or z), however, the false statement is executed.

Each true_statement or false_statement might be either a single statement or a group of statements. A block must be grouped, which is usually done with the keywords “begin” and “end”. A single statement does not need to be grouped.

Here’s a complete Verilog code sample with if else expressions. This is an adder/subtractor that uses the ‘addnsub’ signal to regulate addition and subtraction.

module addsub (a, b, addnsub, result);

        input[7:0]  a;
        input[7:0]  b;
        input       addnsub;
        output[8:0] result;

        reg[8:0]    result;

        always @(a or b or addnsub)
           if (addnsub)
              result = a + b;
              result = a - b;

Multiway Branching

If there are too many choices, the stacked if-else-if might get cumbersome. Using case statements to achieve the same effect is a shortcut.

Case statement

The case statement employs the terms case, endcase, and default.

case (expression)
    alternative 1 : statement1;
alternative 2 : statement2;
    default : default_statement;

The statement1, statement2, …., default statement might be a single statement or a group of statements. A block of many sentences must be separated by the keywords “begin” and “and”.

In the order in which they are written, the expression is compared against the alternatives. The related statement or block is performed for the first matching alternative.

A default_statement is performed if none of the options match. The default_statement parameter is optional. It is not permitted to include several default statements in a single case statement. Nested case statements are possible.

To understand clearly let’s go through a example:

//execute statements on ALU control
reg [1:0] alu_con;
case ( alu_con)
    2’d0 : y = x-z;
    2’d1 : y = x*z;
    2’d2 : y = x+z;
    default : $display(*invalid*);

Case x, case z keywords

The case statement comes in two flavours. They are identified by the terms “casex” and “casez.”

All z values in the case alternatives or the case expression are treated as don’t care by “casez”. All z-bit locations can be represented by? in that place.

All x and z values in the case item or case expression are treated as don’t care by “casex”.

The usage of “casex” and “casez” allows only non-x or -z places in the case expression and case alternatives to be compared.

reg [3:0] encoding;
integer state;
casex (encoding) // shows don’t care bit
4’b1xxx : next_state = 3;
4’bx1xx : next_state = 2;
4’bxx1x : next_state = 1;
4’bxxx1 : next_state = 0;
default : next_state = 0;

Example above shows how to use a “casex” command to decode state bits in a finite state machine. The “casez” is used in a similar way. The other bits are disregarded, and just one bit is used to determine the next state.

A very good example is the priority encoder. A common use of priority encoders is for interrupt controllers, where we select the most critical out of multiple interrupt requests.

Here is the truth table and block diagram of a 4 input and 3 output priority encoder.

Fig 1: Prioriy Encoder

Let’s see the Verilog of this priority encoder for more clarification shown below:

module  priory_encoder_casez
input wire  [4:1] A,
output reg  [2:0]  pcode 
always  @ *
casez  (A)
4'b1zzz :
pcode  = 3'b100;
4'b01zz :
pcode  =  3'b011 ;
4'b001z :
pcode  =  3'b010;
4'b0001 :
pcode =  3'b001;
4'b0000  : 
pcode = 3'b000;

Take note of the statement.

4 ‘b1zzz:
pcode = 3’b100;

That is, we don’t care if the bits [2:0] are 0 or 1 or z. The preceding sentence might alternatively be phrased as

4’b1??? :

pcode = 3’b100;

Casex and casez may both be synthesised. For undefined state points, Casex constructs a don’t-care space. Casez represents a don’t-care bit with a “Z logic value.”

Hence, we understood all the facts related to the if-else statement, case statement, and casex and casez keywords.

Let’s summarise the whole blog in a few questions:

  1. What is a conditional statement?
  2. What do you mean by the if-else statement?
  3. What is a nested if-else-if statement?
  4. What is multiway branching?
  5. What’s the distinction between codex and codez?
Notify of
Inline Feedbacks
View all comments