Return to previous page Advance to next page
Verilog Reference Guide
Chapter 5: Functional Descriptions

Function Statements

Foundation Express supports the following function statements.

Procedural Assignments

Procedural assignments are assignment statements used inside a function. They are similar to the continuous assignment statements described in the “Continuous Assignment” section of the “Structural Descriptions” chapter except that the left side of a procedural assignment can contain only reg variables and integers. Assignment statements set the value of the left side to the current value of the right side. The right side of the assignment can contain any arbitrary expression of the data types described in the “Structural Data Types” section of the “Structural Descriptions” chapter including simple constants and variables.

The left side of the procedural assignment statement can contain only the following data types.

Foundation Express assigns the low bit on the right side to the low bit on the left side.

Foundation Express allows multiple procedural assignments. The following example shows procedural assignments.

sum = a + b; 
control[5] = (instruction == 8'h2e);
{carry_in, a[7:0]} = 9'h 120;

RTL Assignments

Foundation Express handles variables driven by an RTL (nonblocking) assignment differently than those driven by a procedural (blocking) assignment.

In procedural assignments, a value passed along from variable A to variable B to variable C results in all three variables having the same value in every clock cycle. In the netlist, procedural assignments are indicated when the input net of one flip-flop is connected to the input net of another flip-flop. Both flip-flops input the same value in the same clock cycle.

In RTL assignments, however, values are passed on in the next clock cycle. Assignment from variable A to variable B occurs after one clock cycle, if variable A has been a previous target of an RTL assignment. Assignment from variable B to variable C always takes place after one clock cycle, because B is the target when RTL assigns variable A's value to B. In the netlist, an RTL assignment shows flip-flop B receiving its input from the output net of flip-flop A. It takes one clock cycle for the value held by flip-flop Ato propagate to flip-flop B.

A variable can follow only one assignment method and, therefore, cannot be the target of RTL as well as procedural assignments.

The following example is a description of a serial register implemented with RTL assignments. The resulting schematic follows the example.

module rtl (clk,data, regc, regd);
input data, clk;
output regc, regd;

reg regc, regd;

always @ (posedge clk)
begin
   regc <= data;
   regd <= regc;
end
endmodule

Figure 5.1 Schematic of RTL Assignments

If you use a procedural assignment, as in the figure above, Foundation Express does not synthesize a serial register. Therefore, the recently assigned value of rega, which is data, is assigned to regb, as the schematic in the following figure indicates.

The following example shows a blocking assignment.

module rtl (clk,data, rega, regb);
input data, clk;
output rega, regb;

reg rega, regb;

always @(posedge clk)
begin
   rega = data;
   regb = rega;
end
endmodule

Figure 5.2 Schematic of Blocking Assignment

begin...end Block Statements

Block statements are a way of syntactically grouping several statements into a single statement.

In Verilog, sequential blocks are delimited by the keywords begin and end. These begin...end blocks are commonly used in conjunction with if, case, and for statements to group several statements together. Functions and always blocks that contain more than one statement require a begin...end block to group the statements. Verilog also supplies a construct called a named block, as shown in the example below.

begin : block_name 
   reg local_variable_1;
      integer local_variable_2;
      parameter local variable_3;
      ... statements...
end

In Verilog, no semicolon (;) follows the begin or end keywords. You identify named blocks by following the begin keyword with a colon (:) and a block_name, as shown. You can use Verilog syntax to declare variables locally in a named block. You can include reg, integer, and parameter declarations within a named block but not in an unnamed block. Named blocks allow you to use the disable statement.

if...else Statements

The if...else statements execute a block of statements according to the value of one or more expressions.

The syntax of if...else statements follows.

if (expr)
   begin
   ... statements...
   end
else
   begin
   ... statements...
   end

The if statement consists of the keyword if, followed by an expression enclosed in parentheses. The if statement is followed by a statement or block of statements enclosed with the begin and end keywords. If the value of the expression is nonzero, the expression is true, and the statement block that follows is executed. If the value of the expression is zero, the expression is false, and the statement block that follows is not executed.

An optional else statement can follow an if statement. If the expression following the if keyword is false, the statement or block of statements following the else keyword is executed.

The if...else statements can cause registers to be synthesized. Registers are synthesized when you do not assign a value to the same reg variable in all branches of a conditional construct. Information on registers is detailed in the “Register Inference” section of the “Register and Three-State Inference” chapter.

Foundation Express synthesizes multiplexer logic (or similar select logic) from a single if statement. The conditional expression in an if statement is synthesized as a control signal to a multiplexer, which determines the appropriate path through the multiplexer. For example, the statements in the following example create multiplexer logic controlled by c and place either a or b in the variable x.

if (c)
   x = a;
else
   x = b;

The following example illustrates how if and else can be used to create an arbitrarily long if...else if...else structure.

if (instruction == ADD)
   begin
      carry_in = 0;
      complement_arg = 0;
   end
else if (instruction == SUB)
   begin
      carry_in = 1;
      complement_arg = 1;
   end
else
   illegal_instruction = 1;

The following example shows nested if and else statements.

if (select [1])
   begin
      if (select[0]) out = in[3];
      else out = in[2];
   end
else
   begin
      if (select[0]) out = in[1];
      else out = in[0];
   end

Conditional Assignments

Foundation Express can synthesize a latch for a conditionally assigned variable. If a path exists that does not explicitly assign a value to a variable, the variable is conditionally assigned. See the “Understanding the Limitations of D Flip-Flop Inference” section of the “Register and Three-State Inference” chapter for more information.

In the following example, the variable value is conditionally driven. If c is not true, value is not assigned and retains its previous value.

always begin
   if (c) begin
   value = x;
   end
   y = value;    //causes a latch to be synthesized                 //for value
end

case Statements

The case statement is similar in function to the if...else conditional statement. The case statement allows a multipath branch in logic that is based on the value of an expression. One way to describe a multicycle circuit is with a case statement (see the case statement example after the case statement syntax). Another way is with multiple @ (clock edge) statements, which are discussed later in the loop section.

The syntax for a case statement is shown below.

case (expr)
   case_item1 : begin

   ...statements...

   end
   case_item2 : begin

   ...statements...

   end
   default : begin

   ...statements...
   end
endcase

The case statement consists of the keyword case, followed by an expression in parentheses, followed by one or more case items (and associated statements to be executed), followed by the keyword endcase. A case item consists of an expression (usually a simple constant) or a list of expressions separated by commas, followed by a colon (:).

The expression following the case keyword is compared with each case item expression, one by one. When the expressions are equal, the condition evaluates to TRUE. Multiple expressions separated by commas can be used in each case item. When multiple expressions are used, the condition is said to be TRUE if any of the expressions in the case item match the expression following the case keyword.

The first case item that evaluates to TRUE determines the path. All subsequent case items are ignored, even if they are true. If no case item is true, no action is taken. You can define a default case item with the expression default, which is used when no other case item is true.

The following example shows a case statement.

case (state) 
   IDLE: begin
      if (start)
         next_state = STEP1;
      else
         next_state = IDLE;
   end
   STEP1: begin
      //do first state processing here
      next_state = STEP2;
   end
   STEP2: begin
      //do second state processing here
      next_state = IDLE;
   end
endcase

Full Case and Parallel Case

Foundation Express automatically determines whether a case statement is full or parallel. A case statement is referred to as full case if all possible branches are specified. If you do not specify all possible branches, but you know that one or more branches can never occur, you can declare a case statement as full case with the //synopsys full_case directive. Otherwise, Foundation Express synthesizes a latch. See the “parallel_case Directive” section of the “Foundation Express Directives” chapter and “full_case Directive” section of the “Foundation Express Directives” chapter for more information.

Foundation Express synthesizes optimal logic for the control signals of a case statement. If Foundation Express cannot statically determine that branches are parallel, it synthesizes hardware that includes a priority encoder. If Foundation Express can determine that no cases overlap (parallel case), it synthesizes a multiplexer, because a priority encoder is not necessary. You can also declare a case statement as parallel case with the //synopsys parallel_case directive. Refer to the “parallel_case Directive” section of the “Foundation Express Directives” chapter.

The following example is a case statement that is both full and parallel and does not result in either a latch or a priority encoder.

input [1:0] a;
always @(a or w or x or y or z) begin
   case (a)
      2'b11:
         b = w ;
      2'b10:
         b = x ;
      2'b01:
         b = y ;
      2'b00:
         b = z ;
   endcase
end

The following example shows a case statement that is parallel but not full that is missing branches for the cases 2'b01 and 2'b10. This example infers a latch for b.

input [1:0] a;
always @(a or w or z) begin
   case (a)
      2'b11:
         b = w ;
      2'b00:
         b = z ;
   endcase
end

The case statement in the following example is not parallel or full, because the input values of w and x cannot be determined. However, if you know that only one of the inputs equals 2'b11 at a given time, you can use the // synopsys parallel_case directive to avoid synthesizing a priority encoder. If you know that either w or x always equals 2'b11 (a situation known as a one-branch tree), you can use the //synopsys full_case directive to avoid synthesizing a latch.

always @( w or x) begin
   case (2'b11)
      w:
         b = 10 ;
      x:
         b = 01 ;
   endcase
end

casex Statements

The casex statement allows a multipath branch in logic according to the value of an expression, just like the case statement. The differences between the case statement and the casex statement are the keyword and the processing of the expressions.

The syntax for a casex statement follows.

casex (expr)
   case_item1: begin
   ...statements...
   end
   case_item2: begin
   ...statements...
   end
   default: begin
   ...statements...
   end
endcase

A case item can have expressions consisting of the following.

When a z, x, or ? appears in a case-item expression, it means that the corresponding bit of the casex expression is not compared. The following example shows a case item that includes an x.

reg [3:0] cond;
casex (cond)
   4'b100x: out = 1;
   default: out = 0;
endcase

In the above example, out is set to 1 if cond is equal to 4'b1000 or 4'b1001, because the last bit of cond is defined as x.

The following example shows a complicated section of code that can be simplified with a casex statement that uses the ? value.

if (cond[3]) out = 0;
else if (!cond[3] & cond[2] ) out = 1;
else if (!cond[3] & !cond[2] & cond[1] ) out = 2;
else if (!cond[3] & !cond[2] & !cond[1] & cond[0] ) out = 3;
else if (!cond[3] & !cond[2] & !cond[1] & !cond[0] ) out = 4;

The following example shows the simplified version of the same code.

casex (cond) 
   4'b1???: out = 0;
   4'b01??: out = 1;
   4'b001?: out = 2;
   4'b0001: out = 3;
   4'b0000: out = 4;
endcase

Foundation Express allows ?, z, and x bits in case items, but not in casex expressions. The following example shows an invalid casex expression.

express = 3'bxz?;
   ...
casex (express)    //illegal testing of an expression
   ...
endcase

casez Statements

The casez statement allows a multipath branch in logic according to the value of an expression, just like the case statement. The differences between the case statement and the casez statement are the keyword and the way the expressions are processed. The casez statement acts exactly the same as casex, except that x is not allowed in case item; only z and ? are accepted as special characters.

The syntax for a casez statement follows.

casez ( expr )
   case_item1: begin
   ... statements ...
   end
   case_item2: begin
   ... statements ...
   end
   default: begin
   ... statements ...
   end
endcase

A case item can have expressions consisting of the following.

When a casez statement is evaluated, the value z in the case item is ignored. An example of a casez statement with z in the case item is shown in the following example.

casez (what_is_it) 
   2'bz0: begin
      //accept anything with least significant bit       //zero
      it_is = even;
   end
   2'bz1: begin
      //accept anything with least significant bit       //one
      it_is = odd;
   end
endcase

Foundation Express allows ? and z bits in case items but not in casez expressions.

The following example shows an invalid expression in a casez statement.

express = 1'bz;
   ...
casez (express)   // illegal testing of an expression
   ...
endcase

for Loops

The for loop repeatedly executes a single statement or block of statements. The repetitions are performed over a range determined by the range expressions assigned to an index. Two range expressions appear in each for loop: low_range and high_range. In the syntax lines that follow, high_range is greater than or equal to low_range. Foundation Express recognizes both incrementing and decrementing loops. The statement to be duplicated is surrounded by begin and end statements.

Note: Foundation Express allows four syntax forms for a for loop. They include the following.

for (index = low_range;index < high_range;index = index + step)
for (index = high_range;index > low_range;index = index - step)
for (index = low_range;index <= high_range;index = index + step)
for (index = high_range;index >= low_range;index = index - step)

The following example shows a simple for loop.

for (i = 0; i <= 31; i = i + 1) begin 
   s[i] = a[i] ^ b[i] ^ carry;
   carry = a[i] & b[i] | a[i] & carry |
                           b[i] & carry;
end

For loops can be nested, as shown in the following example.

for (i = 6; i >= 0; i = i - 1) 
   for (j = 0; j <= i; j = j + 1)
      if (value[j] > value[j+1]) begin
         temp = value[j+1];
         value[j+1] = value[j];
         value[j] = temp;
      end

You can use for loops as duplicating statements. The following example shows a for loop.

for ( i=0; i < 8; i = i+1 ) 
   example[i] = a[i] & b[7-i];

The following example is the above for loop expanded into its longhand equivalent.

example[0] = a[0] & b[7]; 
example[1] = a[1] & b[6];
example[2] = a[2] & b[5];
example[3] = a[3] & b[4];
example[4] = a[4] & b[3];
example[5] = a[5] & b[2];
example[6] = a[6] & b[1];
example[7] = a[7] & b[0];

while Loops

The while loop executes a statement until the controlling expression evaluates to FALSE. A while loop creates a conditional branch that must be broken by one of the following statements to prevent combinatorial feedback.

@ (posedge clock) or @ (negedge clock)

Foundation Express supports while loops if you insert one of the following expressions in every path through the loop.

@ (posedge clock) or @ (negedge clock)

The following example shows an unsupported while loop that has no event expression.

always
   while (x < y)
      x = x + z;

If you add @ (posedge clock) expressions after the while loop in the above example you get the supported version shown in the following example.

always
   begin @ (posedge clock)
      while (x < y)
      begin
         @ (posedge clock);
         x = x + z;
   end
end;

forever Loops

Infinite loops in Verilog use the keyword forever. You must break up an infinite loop with an @ (posedge clock) or @ (negedge clock) expression to prevent combinatorial feedback, as shown in the example below.

always
   forever
   begin
      @ (posedge clock);
      x = x + z;
   end

You can use forever loops with a disable statement to implement synchronous resets for flip-flops. The disable statement is described in the next section. See the “Register Inference” section of the “Register and Three-State Inference” chapter for more information on synchronous resets.

Using the style illustrated in the example of the supported forever loop above is not recommended, because you cannot test it. The synthesized state machine does not reset to a known state; therefore, it is impossible to create a test program for the state machine. The example of the synchronous reset of state register using disable in a forever loop (in the next section) illustrates how a synchronous reset for the state machine can be synthesized.

disable Statements

Foundation Express supports the disable statement when you use it in named blocks. When a disable statement is executed, it causes the named block to terminate. A comparator description that uses disable is shown in the following example.

begin : compare 
   for (i = 7; i >= 0; i = i - 1) begin
   if (a[i] != b[i]) begin
      greater_than = a[i];
      less_than = ~a[i];
      equal_to = 0;
      // comparison is done so stop looping
      disable compare;
   end
  end

//If we get here a == b 
//If the disable statement is executed,the next three //lines will not be executed
   greater_than = 0;
   less_than = 0;
   equal_to = 1;
end

Note that the above example describes a combinatorial comparator. Although the description appears sequential, the generated logic runs in a single clock cycle.

You can also use a disable statement to implement a synchronous reset, as shown in the following example.

always
   forever
   begin: Block
      @ (posedge clock)
      if (Reset)
         begin
            z <= 1'b0
            disable Block;
         end
            z = a;
   end

The disable statement in the example above causes the block reset_label to immediately terminate and return to the beginning of the block.