Return to previous page Advance to next page

Behavioral Verilog Features

This section contains descriptions of the behavioral features of Verilog.

Variable Declaration

Variables in Verilog may be declared as integers or real. These declarations are intended only for use in test code. Verilog provides data types such as reg and wire for actual hardware description.

The difference between reg and wire is whether the variable is given its value in a procedural block (reg) or in a continuous assignment (wire) Verilog code. Both reg and wire have a default width being one bit wide (scalar). To specify an N-bit width (vectors) for a declared reg or wire, the left and right bit positions are defined in square brackets separated by a colon. In Verilog-2001, both reg and wire data types can be signed or unsigned.

Example:

reg [3:0] arb_priority;
wire [31:0] arb_request;
wire signed [8:0] arb_signed;

where arb_request[31] is the MSB and arb_request[0] is the LSB.

Initial Values

In Verilog-2001, you can initialize registers when you declare them.

The value:

When you give a register an initial value in a declaration, XST sets this value on the output of the register at global reset, or at power up. A value assigned this way is carried in the NGC file as an INIT attribute on the register, and is independent of any local reset.

Example:

reg arb_onebit = 1'b0;
reg [3:0] arb_priority = 4'b1011;

You can also assign a set/reset (initial) value to a register via your behavioral Verilog code. Do this by assigning a value to a register when the register’s reset line goes to the appropriate value as in the following example.

Example:

always @(posedge clk)
  begin
    if (rst)
      arb_onebit <= 1'b0;
  end
end

When you set the initial value of a variable in the behavioral code, it is implemented in the design as a flip-flop whose output can be controlled by a local reset; as such it is carried in the NGC file as an FDP or FDC flip-flop.

Local Reset ¼ Global Reset

Note that local reset is independent of global reset. Registers controlled by a local reset may be set to a different value than ones whose value is only reset at global reset (power up). In the following example, the register, arb_onebit, is set to '0' at global reset, but a pulse on the local reset (rst) can change its value to '1'.

Example:

module mult(clk, rst, A_IN, B_OUT);
  input clk,rst,A_IN;
  output B_OUT;
  reg arb_onebit = 1'b0;
  always @(posedge clk or posedge rst)
    begin
      if (rst)
        arb_onebit <= 1'b1;
      else
        arb_onebit <= A_IN;
      end
  end
B_OUT <= arb_onebit;
endmodule

This sets the set/reset value on the register’s output at initial power up, but since this is dependent upon a local reset, the value changes whenever the local set/reset is activated.

Arrays

Verilog allows arrays of reg and wires to be defined as in the following two examples:

reg [3:0] mem_array [31:0];

The above describes an array of 32 elements each, 4 bits wide which can be assigned via behavioral Verilog code.

wire [7:0] mem_array [63:0];

The above describes an array of 64 elements each 8 bits wide which can only be assigned via structural Verilog code.

Multi-dimensional Arrays

XST supports multi-dimensional array types of up to two dimensions. Multi-dimensional arrays can be any net or any variable data type. You can code assignments and arithmetic operations with arrays, but you cannot select more than one element of an array at one time. You cannot pass multi-dimensional arrays to system tasks or functions, or regular tasks or functions.

Examples

The following describes an array of 256 x 16 wire elements each 8 bits wide, which can only be assigned via structural Verilog code.

wire [7:0] array2 [0:255][0:15];

The following describes an array of 256 x 8 register elements, each 64 bits wide, which can be assigned via behavioral Verilog code.

reg [63:0] regarray2 [255:0][7:0];

The following is a three dimensional array. It can be described as an array of 15 arrays of 256 x 16 wire elements, each 8 bits wide, which can be assigned via structural Verilog code.

wire [7:0] array3 [0:15][0:255][0:15];

Data Types

The Verilog representation of the bit data type contains the following four values:

XST includes support for the following Verilog data types:

Net and registers can be either single bit (scalar) or multiple bit (vectors).

The following example gives some examples of Verilog data types (as found in the declaration section of a Verilog module).

Example 7-1 Basic Data Types

wire net1;                        // single bit net
reg r1;                           // single bit register
tri [7:0] bus1;                   // 8 bit tristate bus
reg [15:0] bus1;                  // 15 bit register
reg [7:0] mem[0:127];             // 8x128 memory register
parameter state1 = 3’b001;        // 3 bit constant
parameter component = "TMS380C16";  // string

Legal Statements

The following are statements that are legal in behavioral Verilog.

Variable and signal assignment:

Note: All variables are declared as integer or reg. A variable cannot be declared as a wire.

Expressions

An expression involves constants and variables with arithmetic (+, -, *,**, /,%), logical (&, &&, |, ||, ^, ~,~^, ^~, <<, >>,<<<,>>>), relational (<, ==, ===, <=, >=,!=,!==, >), and conditional (?) operators. The logical operators are further divided as bit-wise versus logical depending on whether it is applied to an expression involving several bits or a single bit. The following table lists the expressions supported by XST.

Table 7-1: Expressions
Concatenation
{}
Supported
Replication
{{}}
Supported
 
Arithmetic
 
+, -, *,**
Supported
/
Supported only if second operand is a power of 2
Modulus
%
Supported only if second operand is a power of 2
Addition
+
Supported
Subtraction
-
Supported
Multiplication
*
Supported
Power
**
Supported
  • Both operands must be constants with the second operand being non-negative.
  • If the first operand is a 2, then the second operand may be a variable.
  • XST does not support the real data type. Any combination of operands that results in a real type causes an error.
  • The values X (unknown) and Z (high impedance) are not allowed.
Division
/
Supported
XST generates incorrect logic for the division operator between signed and unsigned constants. Example: -1235/3’b111
Relational
>, <, >=, <=
Supported
Logical Negation
!
Supported
Logical AND
&&
Supported
Logical OR
||
Supported
Logical Equality
==
Supported
Logical Inequality
!=
Supported
Case Equality
===
Supported
Case Inequality
!==
Supported
Bitwise Negation
~
Supported
Bitwise AND
&
Supported
Bitwise Inclusive OR
|
Supported
Bitwise Exclusive OR
^
Supported
Bitwise Equivalence
~^, ^~
Supported
Reduction AND
&
Supported
Reduction NAND
~&
Supported
Reduction OR
|
Supported
Reduction NOR
~|
Supported
Reduction XOR
^
Supported
Reduction XNOR
~^, ^~
Supported
Left Shift
<<
Supported
Right Shift Signed
>>>
Supported
Left Shift Signed
<<<
Supported
Right Shift
>>
Supported
Conditional
?:
Supported
Event OR
or, ','
Supported

The following table lists the results of evaluating expressions using the more frequently used operators supported by XST.

Note: The (===) and (!==) are special comparison operators useful in simulations to check if a variable is assigned a value of (x) or (z). They are treated as (==) or (!=) in synthesis.

Table 7-2: Results of Evaluating Expressions
a b
a==b
a===b
a!=b
a!==b
a&b
a&&b
a|b
a||b
a^b
0 0
1
1
0
0
0
0
0
0
0
0 1
0
0
1
1
0
0
1
1
1
0 x
x
0
x
1
0
0
x
x
x
0 z
x
0
x
1
0
0
x
x
x
1 0
0
0
1
1
0
0
1
1
1
1 1
1
1
0
0
1
1
1
1
0
1 x
x
0
x
1
x
x
1
1
x
1 z
x
0
x
1
x
x
1
1
x
x 0
x
0
x
1
0
0
x
x
x
x 1
x
0
x
1
x
x
1
1
x
x x
x
1
x
0
x
x
x
x
x
x z
x
0
x
1
x
x
x
x
x
z 0
x
0
x
1
0
0
x
x
x
z 1
x
0
x
1
x
x
1
1
x
z x
x
0
x
1
x
x
x
x
x
z z
x
1
x
0
x
x
x
x
x

Blocks

Block statements are used to group statements together. XST only supports sequential blocks. Within these blocks, the statements are executed in the order listed. Parallel blocks are not supported by XST. Block statements are designated by begin and end keywords, and are discussed within examples later in this chapter.

Modules

In Verilog a design component is represented by a module. The connections between components are specified within module instantiation statements. Such a statement specifies an instance of a module. Each module instantiation statement must be given a name (instance name). In addition to the name, a module instantiation statement contains an association list that specifies which actual nets or ports are associated with which local ports (formals) of the module declaration.

All procedural statements occur in blocks that are defined inside modules. There are two kinds of procedural blocks: the initial block and the always block. Within each block, Verilog uses a begin and end to enclose the statements. Since initial blocks are ignored during synthesis, only always blocks are discussed. Always blocks usually take the following format:

always
  begin
  statement
  …...
end

where each statement is a procedural assignment line terminated by a semicolon.

Module Declaration

In the module declaration, the I/O ports of the circuit are declared. Each port has a name and a mode (in, out, and inout) as shown in the example below.

module EXAMPLE (A, B, C, D, E);
  input A, B, C;
  output D;
  inout E;
  wire D, E;
  ...
  assign E = oe ? A : 1’bz;
  assign D = B & E;
  ...
endmodule

The input and output ports defined in the module declaration called EXAMPLE are the basic input and output I/O signals for the design. The inout port in Verilog is analogous to a bi-directional I/O pin on the device with the data flow for output versus input being controlled by the enable signal to the tristate buffer. The preceding example describes E as a tristate buffer with a high-true output enable signal. If oe = 1, the value of signal A is output on the pin represented by E. If oe = 0, then the buffer is in high impedance (Z) and any input value driven on the pin E (from the external logic) is brought into the device and fed to the signal represented by D.

Verilog Assignments

There are two forms of assignment statements in the Verilog language:

Continuous Assignments

Continuous assignments are used to model combinatorial logic in a concise way. Both explicit and implicit continuous assignments are supported. Explicit continuous assignments are introduced by the assign keyword after the net has been separately declared. Implicit continuous assignments combine declaration and assignment.

Note: Delays and strengths given to a continuous assignment are ignored by XST.

Example of an explicit continuous assignment:

wire par_eq_1;
…...
assign par_eq_1 = select ? b : a;

Example of an implicit continuous assignment:

wire temp_hold = a | b;

Note: Continuous assignments are only allowed on wire and tri data types.

Procedural Assignments

Procedural assignments are used to assign values to variables declared as regs and are introduced by always blocks, tasks, and functions. Procedural assignments are usually used to model registers and FSMs.

XST includes support for combinatorial functions, combinatorial and sequential tasks, and combinatorial and sequential always blocks.

Combinatorial Always Blocks

Combinatorial logic can be modeled efficiently using two forms of time control, the # and @ Verilog time control statements. The # time control is ignored for synthesis and hence this section describes modeling combinatorial logic with the @ statement.

A combinatorial always block has a sensitivity list appearing within parentheses after the word "always @". An always block is activated if an event (value change or edge) appears on one of the sensitivity list signals. This sensitivity list can contain any signal that appears in conditions (If, Case, for example), and any signal appearing on the right hand side of an assignment. By substituting a * without parentheses, for a list of signals, the always block is activated for an event in any of the always block’s signals as described above.

Note: In combinatorial processes, if a signal is not explicitly assigned in all branches of "If" or "Case" statements, XST generates a latch to hold the last value. To avoid latch creation, be sure that all assigned signals in a combinatorial process are always explicitly assigned in all paths of the process statements.

Different statements can be used in a process:

The following sections provide examples of each of these statements.

If...Else Statement

If... else statements use true/false conditions to execute statements. If the expression evaluates to true, the first statement is executed. If the expression evaluates to false (or x or z), the else statement is executed. A block of multiple statements may be executed using begin and end keywords. If...else statements may be nested. The following example shows how a MUX can be described using an If...else statement.

Example 7-2 MUX Description Using If... Else Statement

module mux4 (sel, a, b, c, d, outmux);
input [1:0] sel;
input [1:0] a, b, c, d;
output [1:0] outmux;
reg [1:0] outmux;
  always @(sel or a or b or c or d)
  begin
    if (sel[1])
      if (sel[0])
        outmux = d;
      else
        outmux = c;
    else
      if (sel[0])
        outmux = b;
      else
        outmux = a;
      end
endmodule

Case Statement

Case statements perform a comparison to an expression to evaluate one of a number of parallel branches. The Case statement evaluates the branches in the order they are written. The first branch that evaluates to true is executed. If none of the branches match, the default branch is executed.

Note: Do not use unsized integers in case statements. Always size integers to a specific number of bits, or results can be unpredictable.

Casez treats all z values in any bit position of the branch alternative as a don’t care.

Casex treats all x and z values in any bit position of the branch alternative as a don’t care.

The question mark (?) can be used as a "don’t care" in either the casez or casex case statements. The following example shows how a MUX can be described using a Case statement.

Example 7-3 MUX Description Using Case Statement

module mux4 (sel, a, b, c, d, outmux);
input [1:0] sel;
input [1:0] a, b, c, d;
output [1:0] outmux;
reg [1:0] outmux;
always @(sel or a or b or c or d)
  begin
    case (sel)
      2'b00: outmux = a;
      2'b01: outmux = b;
      2'b10: outmux = c;
      default: outmux = d;
    endcase
  end
endmodule

The preceding Case statement evaluates the values of the input sel in priority order. To avoid priority processing, it is recommended that you use a parallel-case Verilog meta comment which ensures parallel evaluation of the sel inputs as in the following.

Example:

case(sel)   //synthesis parallel_case

For and Repeat Loops

When using always blocks, repetitive or bit slice structures can also be described using the "for" statement or the "repeat" statement.

The "for" statement is supported for:

The repeat statement is only supported for constant values.

The following example shows the use of a For Loop.

Example 7-4 For Loop Description

module countzeros (a, Count);
input [7:0] a;
output [2:0] Count;
reg [2:0] Count;
reg [2:0] Count_Aux;
integer i;
always @(a)
  begin
    Count_Aux = 3'b0;
  for (i = 0; i < 8; i = i+1)
    begin
      if (!a[i])
        Count_Aux = Count_Aux+1;
      end
  Count = Count_Aux;
  end
endmodule

While Loops

When using always blocks, use the "while" statement to execute repetitive procedures. A "while" loop executes other statements until its test expression becomes false. It is not executed if the test expression is initially false.

The following example shows the use of a While Loop.

Example 7-5 While Loop Description

parameter P = 4;
always @(ID_complete)
  begin : UNIDENTIFIED
    integer i;
    reg found;
    unidentified = 0;
    i = 0;
    found = 0;
    while (!found && (i < P))
      begin
        found = !ID_complete[i];
        unidentified[i] = !ID_complete[i];
        i = i + 1;
      end
  end

Sequential Always Blocks

Sequential circuit description is based on always blocks with a sensitivity list.

The sensitivity list contains a maximum of three edge-triggered events: the clock signal event (which is mandatory), possibly a reset signal event, and a set signal event. One, and only one "If...else" statement is accepted in such an always block.

An asynchronous part may appear before the synchronous part in the first and the second branch of the "If...else" statement. Signals assigned in the asynchronous part must be assigned to the constant values '0', '1', 'X' or 'Z' or any vector composed of these values.

These same signals must also be assigned in the synchronous part (that is, the last branch of the "if-else" statement). The clock signal condition is the condition of the last branch of the "if-else" statement. The following example gives the description of an 8-bit register.

Example 7-6 8 Bit Register Using an Always Block

module seq1 (DI, CLK, DO);
  input [7:0] DI;
  input CLK;
  output [7:0] DO;
  reg [7:0] DO;
  always @(posedge CLK)
    DO <= DI ;
endmodule

The following example gives the description of an 8-bit register with a clock signal and an asynchronous reset signal.

Example 7-7 8 Bit Register with Asynchronous Reset (high-true) Using an Always Block

module EXAMPLE (DI, CLK, RST, DO);
  input [7:0] DI;
  input CLK, RST;
  output [7:0] DO;
  reg [7:0] DO;
  always @(posedge CLK or posedge RST)
    if (RST == 1'b1)
      DO <= 8'b00000000;
    else
      DO <= DI;
endmodule

The following example describes an 8-bit counter.

Example 7-8 8 Bit Counter with Asynchronous Reset (low-true) Using an Always Block

module seq2 (CLK, RST, DO);
  input CLK, RST;
  output [7:0] DO;
  reg [7:0] DO;
  always @(posedge CLK or posedge RST)
    if (RST == 1'b1)
      DO <= 8'b00000000;
    else
      DO <= DO + 8'b00000001;
endmodule

Assign and Deassign Statements

Assign and deassign statements are supported within simple templates.

The following is an example of the general template for assign / deassign statements:

module assig (RST, SELECT, STATE, CLOCK, DATA_IN);
  input RST;
  input SELECT;
  input CLOCK;
  input [0:3] DATA_IN;
  output [0:3] STATE;
  reg [0:3] STATE;
always @ (RST)
  if(RST)
    begin
      assign STATE = 4'b0;
    end
  else
    begin
      deassign STATE;
    end
always @ (posedge CLOCK)
  begin
    STATE <= DATA_IN;
  end
endmodule

The main limitations on support of the assign/deassign statement in XST are as follows:

module dflop (RST, SET, STATE, CLOCK, DATA_IN);
  input RST;
  input SET;
  input CLOCK;
  input DATA_IN;
  output STATE;
  reg STATE;
always @ (RST)            // block b1
  if(RST)
    assign STATE = 1'b0;
  else
    deassign STATE;
always @ (SET)            // block b1
  if(SET)
    assign STATE = 1'b1;
  else
    deassign STATE;
always @ (posedge CLOCK)  // block b2
  begin
    STATE <= DATA_IN;
  end
endmodule
module dflop (RST, SET, STATE, CLOCK, DATA_IN);
  input RST;
  input SET;
  input CLOCK;
  input DATA_IN;
  output STATE;
  reg STATE;
always @ (RST or SET)       // block b1
case ({RST,SET})
  2'b00: assign STATE = 1'b0;
  2'b01: assign STATE = 1'b0;
  2'b10: assign STATE = 1'b1;
  2'b11: deassign STATE;
endcase
always @ (posedge CLOCK)    // block b2
  begin
    STATE <= DATA_IN;
  end
endmodule
module assig (RST, SELECT, STATE, CLOCK,DATA_IN);
  input RST;
  input SELECT;
  input CLOCK;
  input [0:7] DATA_IN;
  output [0:7] STATE;
  reg [0:7] STATE;
  always @ (RST)            // block b1
    if(RST)
      begin
        assign STATE[0:7] = 8'b0;
      end
    else
      begin
        deassign STATE[0:7];
      end
always @ (posedge CLOCK)    // block b2
  begin
    if (SELECT)
      STATE [0:3] <= DATA_IN[0:3];
    else
      STATE [4:7] <= DATA_IN[4:7];
end

Assignment Extension Past 32 Bits

If the expression on the left-hand side of an assignment is wider than the expression on the right-hand side, the left-hand side is padded to the left according to the following rules.

Note: The above rules follow the Verilog-2001 standard, and are not backward compatible with Verilog-1995.

Tasks and Functions

The declaration of a function or task is intended for handling blocks used multiple times in a design. They must be declared and used in a module. The heading part contains the parameters: input parameters (only) for functions and input/output/inout parameters for tasks. The return value of a function can be declared either signed or unsigned. The content is similar to the combinatorial always block content.

Example 7-9 shows a function declared within a module. The ADD function declared is a single-bit adder. This function is called 4 times with the proper parameters in the architecture to create a 4-bit adder. The same example, described with a task, is shown in Example 7-10.

Example 7-9 Function Declaration and Function Call

module comb15 (A, B, CIN, S, COUT);
  input [3:0] A, B;
  input CIN;
  output [3:0] S;
  output COUT;
  wire [1:0] S0, S1, S2, S3;
  function signed [1:0] ADD;
    input A, B, CIN;
    reg S, COUT;
    begin
      S = A ^ B ^ CIN;
      COUT = (A&B) | (A&CIN) | (B&CIN);
      ADD = {COUT, S};
    end
  endfunction
  assign S0 = ADD (A[0], B[0], CIN),
    S1 = ADD (A[1], B[1], S0[1]),
    S2 = ADD (A[2], B[2], S1[1]),
    S3 = ADD (A[3], B[3], S2[1]),
    S = {S3[0], S2[0], S1[0], S0[0]},
    COUT = S3[1];
endmodule

Example 7-10 Task Declaration and Task Enable

module EXAMPLE (A, B, CIN, S, COUT);
  input [3:0] A, B;
  input CIN;
  output [3:0] S;
  output COUT;
  reg [3:0] S;
  reg COUT;
  reg [1:0] S0, S1, S2, S3;
  task ADD;
    input A, B, CIN;
    output [1:0] C;
    reg [1:0] C;
    reg S, COUT;
    begin
      S = A ^ B ^ CIN;
      COUT = (A&B) | (A&CIN) | (B&CIN);
      C = {COUT, S};
    end
  endtask
  always @(A or B or CIN)
  begin
    ADD (A[0], B[0], CIN, S0);
    ADD (A[1], B[1], S0[1], S1);
    ADD (A[2], B[2], S1[1], S2);
    ADD (A[3], B[3], S2[1], S3);
    S = {S3[0], S2[0], S1[0], S0[0]};
    COUT = S3[1];
  end
endmodule

Recursive Tasks and Functions

Verilog-2001 adds support for recursive tasks and functions. You can only use recursion with the automatic keyword.

The syntax using recursion is shown in the following example:

function automatic [31:0] fac;
input [15:0] n;
if (n == 1)
  fac = 1;
else
  fac = n * fac(n-1); //recursive function call
endfunction

Blocking Versus Non-Blocking Procedural Assignments

The # and @ time control statements delay execution of the statement following them until the specified event is evaluated as true. Use of blocking and non-blocking procedural assignments have time control built into their respective assignment statement.

The # delay is ignored for synthesis.

The syntax for a blocking procedural assignment is shown in the following example:

reg a;
a = #10 (b | c);

or

if (in1) out = 1'b0;
else out = in2;

As the name implies, these types of assignments block the current process from continuing to execute additional statements at the same time. These should mainly be used in simulation.

Non-blocking assignments, on the other hand, evaluate the expression when the statement executes, but allow other statements in the same process to execute as well at the same time. The variable change only occurs after the specified delay.

The syntax for a non-blocking procedural assignment is as follows:

variable <= @(posedge_or_negedge_bit) expression;

The following shows an example of how to use a non-blocking procedural assignment.

if (in1) out <= 1'b1;
else out <= in2;

Constants, Macros, Include Files and Comments

This section discusses constants, macros, include files, and comments.

Constants

By default, constants in Verilog are assumed to be decimal integers. They can be specified explicitly in binary, octal, decimal or hexadecimal by prefacing them with the appropriate syntax. For example, 4'b1010, 4'o12, 4'd10 and 4'ha all represent the same value.

Macros

Verilog provides a way to define macros as shown in the following example.

`define TESTEQ1 4'b1101

Later in the design code a reference to the defined macro is made as follows.

if (request == `TESTEQ1)

This is shown in the following example.

`define myzero 0
assign mysig = `myzero;

Verilog provides the `ifdef and `endif constructs to determine whether a macro is defined or not. These constructs are used to define conditional compilation. If the macro called out by the `ifdef command has been defined, that code is compiled. If not, the code following the `else command is compiled. The `else is not required, but the `endif must complete the conditional statement. The `ifdef and `endif constructs are shown in the following example.

`ifdef MYVAR
module if_MYVAR_is_declared;
...
endmodule
`else
module if_MYVAR_is_not_declared;
...
endmodule
`endif

Include Files

Verilog allows separating source code into more than one file. To use the code contained in another file, the current file has the following syntax:

`include "path/file-to-be-included"

Note: The path can be relative or absolute.

Multiple `include statements are allowed in a single Verilog file. This feature makes your code modular and more manageable in a team design environment where different files describe different modules of the design.

To have the file in your `include statement recognized, you must identify the directory where it resides either to ISE™ or to XST.

Be aware that conflicts can occur. For example, at the top of a Verilog file you might see the following:

`timescale 1 ns/1 ps
`include "modules.v"
...

If the specified file (in this case, modules.v) has been added to an ISE project directory and is specified with an `include, conflicts may occur and an error message displays:

ERROR:Xst:1068 - fifo.v, line 2. Duplicate declarations of module'RAMB4_S8_S8'

Comments

There are two forms of comments in Verilog similar to the two forms found in a language like C++.

Generate Statement

Generate is a construct that allows you to dynamically create Verilog code from conditional statements. This allows you to create repetitive structures or structures that are only appropriate under certain conditions. Structures that are likely to be created via a generate statement are:

XST supports the following types of generate statements:

Generate For

Use a generate for loop to create one or more instances that can be placed inside a module. Use the generate for loop the same way you would a normal Verilog for loop with the following limitations.

The following is an example of an 8-bit adder using a generate for loop.

generate
genvar i;
  for (i=0; i<=7; i=i+1)
    begin : for_name
      adder add (a[8*i+7 : 8*i], b[8*i+7 : 8*i],
        ci[i], sum_for[8*i+7 : 8*i], c0_or[i+1]);
    end
endgenerate

Generate If... else

A generate if statement can be used inside a generate block to conditionally control what objects get generated.

The following is an example of a generate If... else statement. The generate controls what type of multiplier is instantiated. Please note that the contents of each branch of the if... else statement must be enclosed by begin and end statements, and the begin statement must be named with a unique qualifier.

generate
  if (IF_WIDTH < 10)
    begin : if_name
      adder # (IF_WIDTH) u1 (a, b, sum_if);
    end
  else
    begin : else_name
      subtractor # (IF_WIDTH) u2 (a, b, sum_if);
    end
endgenerate

Generate Case

A generate case statement can be used inside a generate block to conditionally control what objects get generated. Use a generate case statement when there are several conditions to be tested to determine what the generated code would be. Please note that each test statement in a generate case statement must be enclosed by begin and end statements, and the begin statement must be named with a unique qualifier.

The following is an example of a generate case statement. The generate controls what type of adder is instantiated.

generate
  case (WIDTH)
    1:
      begin : case1_name
        adder #(WIDTH*8) x1 (a, b, ci, sum_case, c0_case);
      end
    2:
      begin : case2_name
        adder #(WIDTH*4) x2 (a, b, ci, sum_case, c0_case);
      end
    default:
      begin : d_case_name
        adder x3 (a, b, ci, sum_case, c0_case);
      end
  endcase
endgenerate
Return to previous page Advance to next page

www.xilinx.com