Training Manual for Fpga Programming Using Verilog Hdl Language

100
Summer Training (03 rd Aug, 2011 to 23 rd Aug, 2011) FPGA Programming using Verilog HDL Language Training Manual 1

Transcript of Training Manual for Fpga Programming Using Verilog Hdl Language

Page 1: Training Manual for Fpga Programming Using Verilog Hdl Language

Summer Training(03rd Aug, 2011 to 23rd Aug, 2011)

FPGA Programming using Verilog HDL Language

Training Manual

1

Conducted by:

BHUBANESWAR INSTITUTE OF TECHNOLOGYInfovalley, Harapur, Bhubaneswar, Orissa - 752054, India

Ph - +91-674-2113498, Fax - +91-674-2113497, Email: [email protected] Website: www.bit.edu.in

Page 2: Training Manual for Fpga Programming Using Verilog Hdl Language

Training Coordinator

Er. Sidhartha Sankar RoutLecturer,

ECE Department,BIT, Bhubaneswar

2

Page 3: Training Manual for Fpga Programming Using Verilog Hdl Language

Dedicated to,

~~~Maa~~~

3

Page 4: Training Manual for Fpga Programming Using Verilog Hdl Language

Contents:

i) Acknowledgement……………………………. p.5ii) Course Objective………………………………. p.6iii) ISE 10.1………………………………………... p.07 to p.22iv) Verilog Programming Language………............. p.23 to p.61v) Function and Task………………………........... p.61 to p.64vi) Modeling Finite State Machine……………….. p.64 to p.67vii) Writing Test Benches…………………………. p.67 to p.73viii) Basics of FPGA……………………………….. p.74 to p.75

4

Page 5: Training Manual for Fpga Programming Using Verilog Hdl Language

Acknowledgement

We convey our heartiest gratitude to Prof. Rabi N Mahapatra (Chairman, BIT) for his words of inspiration. He willingly extracted time from his busy schedule while helping us technically by providing esteemed tutorials (of his own that he uses to teach undergraduates of Texas A&M Univ., USA) regarding FPGA programming.

We are highly thankful to Mr. Arun Prusty (H.O.D, ECE Dept, BIT) and the system support team for their full time support in configuring ISE and ADEPT to all the systems. The successful design of this training manual would not have happened without the full time endeavor of Mr. Prabhas Nanda (Placement & Training Officer).

We tried our level best in designing an error free manual for the trainees. We welcome everyone’s feedback regarding improvement of this manual.

Sidhartha Sankar Rout Lecturer, ECE Dept, BIT. Dharanidhar Dang Lecturer,

ECE Dept, BIT.

5

Page 6: Training Manual for Fpga Programming Using Verilog Hdl Language

COURSE OBJECTIVE

Create and implement designs by using the ISE software design environment and Basys-2 Spartan3E FPGA board.

Verilog code for synthesis

Functions and Tasks

Creating Finite State Machine (FSM) by using Verilog

Verilog test fixtures for simulation

Introduction to FPGA

Project Work

6

Page 7: Training Manual for Fpga Programming Using Verilog Hdl Language

1. ISE 10.1

Before you start using the FPGA board you will have to be familiar with ISE 10.1.It would lead you to create, verify and implement logic on FPGA board.

This tutorial contains the following sections:• “Getting Started”• “Create a New Project”• “Create an HDL Source”• “Design Simulation”• “Create Timing Constraints”• “Implement Design and Verify Constraints”• “Reimplement Design and Verify Pin Locations”• “Download Design to the Spartan™-3 Demo Board”For an in-depth explanation of the ISE design tools, see the ISE In-Depth Tutorial on theXilinx® web site at: http://www.xilinx.com/support/techsup/tutorials/

1.1 GETTING STARTEDStarting the ISE SoftwareTo start ISE, double-click the desktop icon,

or start ISE from the Start menu by selecting:Start → All Programs →Xilinx ISE Design Suite 10.1→ISE→ Project Navigator

Accessing HelpAt any time you can access online help for additional information about the ISE software and related tools. To open Help, do either of the following:

Press F1 to view Help for the specific tool or function that you have selected or highlighted.

Launch the ISE Help Contents from the Help menu. It contains information about creating and maintaining your complete design flow in ISE.

7

Page 8: Training Manual for Fpga Programming Using Verilog Hdl Language

1.2 CREATE A NEW PROJECTCreate a new ISE project which will target the FPGA device. To create a new project:

1. Select File > New Project... The New Project Wizard appears.2. Type tutorial (any Project name) in the Project Name field.3. Enter or browse to a location (directory path) for the new project. A tutorial

subdirectory is created automatically.4. Verify that HDL is selected from the Top-Level Source Type list.5. Click Next to move to the device properties page.6. Fill in the properties in the table as shown below:

Product Category: All Family: Spartan3E Device: XC3S100E Package: CP132 Speed Grade: -5 Top-Level Source Type: HDL Synthesis Tool: XST (VHDL/Verilog) Simulator: ISE Simulator (VHDL/Verilog) Preferred Language: Verilog Verify that Enable Enhanced Design Summary is selected.

Leave the default values in the remaining fields.When the table is complete, your project properties will look like the following:

7. Click Next to proceed to the Create New Source window in the New Project Wizard. At the end of the next section, your new project will be complete.

8

Page 9: Training Manual for Fpga Programming Using Verilog Hdl Language

1.3 CREATE AN HDL SOURCEIn this section, you will create the top-level HDL file for your design. Determine the language as Verilog to use for the tutorial.

Create the top-level Verilog source file for the project as follows: Click New Source in the New Project dialog box. Select Verilog Module as the source type in the New Source dialog box. Type in the file name counter. Verify that the Add to Project checkbox is selected. Click Next. Declare the ports for the counter design by filling in the port information as shown

below:

Click Next, then Finish in the New Source Information dialog box to complete the new source file template.

Click Next, then Next, then Finish.

The source file containing the counter module displays in the Workspace, and the counter displays in the Sources tab, as shown below:

9

Page 10: Training Manual for Fpga Programming Using Verilog Hdl Language

Using Language Templates (Verilog)The next step in creating the new source is to add the behavioral description for counter. Use a simple counter code example from the ISE Language Templates and customize it for the counter design.

Place the cursor on the line below the output [3:0] COUNT_OUT; statement. Open the Language Templates by selecting Edit → Language Templates…

You can tile the Language Templates and the counter file by selecting Window → Tile Vertically to make them both visible.

Using the “+” symbol, browse to the following code example: Verilog → Synthesis Constructs → Coding Examples → Counters → Binary →

Up/Down Counters → Simple Counter With Simple Counter selected, select Edit → Use in File. This step copies the template

into the counter source file. Close the Language Templates.

Final Editing of the Verilog Source To declare and initialize the register that stores the counter value, modify the declaration

statement in the first line of the template as follows: replace “reg [<upper>:0] <reg_name>;” with “reg [3:0] count_int = 0;” Customize the template for the counter design by replacing the port and signal name.

10

Page 11: Training Manual for Fpga Programming Using Verilog Hdl Language

o replace all occurrences of <clock> with CLOCKo replace all occurrences of <up_down> with DIRECTIONo replace all occurrences of <reg_name> with count_int

Add the following line just above the endmodule statement to assign the register value to the output port:

assign COUNT_OUT = count_int; Save the file by selecting File → Save.

When you are finished, the code for the counter will look like the following:module counter(CLOCK, DIRECTION, COUNT_OUT);input CLOCK;input DIRECTION;output [3:0] COUNT_OUT;);reg [3:0] count_int = 0;always @(posedge CLOCK)if (DIRECTION)count_int <= count_int + 1;elsecount_int <= count_int - 1;assign COUNT_OUT = count_int;endmodule

Checking the Syntax of the New Counter Module When the source files are complete, check the syntax of the design to find errors. Verify that Implementation is selected from the drop-down list in the Sources window. Select the counter design source in the Sources window to display the related processes

in the Processes window. Click the “+” next to the Synthesize-XST process to expand the process group. Double-click the Check Syntax process. You must correct any errors found in your source files. You can check for errors in the

Console tab of the Transcript window. If you continue without valid syntax, you will not be able to simulate or synthesize your design.

Close the HDL file.

1.4 DESIGN SIMULATIONCreate a test bench waveform containing input stimulus where you can verify the functionality of the counter module. The test bench waveform is a graphical view of a test bench.Create the test bench waveform as follows:

Select the counter HDL file in the Sources window. Create a new test bench source by selecting Project → New Source. In the New Source Wizard, select Test Bench Waveform as the source type, and type

counter_tbw in the File Name field. Click Next. The Associated Source page shows that you are associating the test bench waveform with

the source file counter. Click Next.

11

Page 12: Training Manual for Fpga Programming Using Verilog Hdl Language

The Summary page shows that the source will be added to the project, and it displays the source directory, type, and name. Click Finish.

You need to set the clock frequency, setup time and output delay times in the Initialize Timing dialog box before the test bench waveform editing window opens.

The requirements for this design are the following: The counter must operate correctly with an input clock frequency = 25 MHz. The DIRECTION input will be valid 10 ns before the rising edge of CLOCK. The output (COUNT_OUT) must be valid 10 ns after the rising edge of CLOCK.

The design requirements correspond with the values below.Fill in the fields in the Initialize Timing dialog box with the following information:

Clock High Time: 20 ns. Clock Low Time: 20 ns. Input Setup Time: 10 ns. Output Valid Delay: 10 ns. Offset: 0 ns. Global Signals: GSR (FPGA)

Note: When GSR (FPGA) is enabled, 100 ns. is added to the Offset value automatically. Initial Length of Test Bench: 1500 ns.

Leave the default values in the remaining fields.

Click Finish to complete the timing initialization. The blue shaded areas that precede the rising edge of the CLOCK correspond to the Input

Setup Time in the Initialize Timing dialog box. Toggle the DIRECTION port to define the input stimulus for the counter design as follows:

12

Page 13: Training Manual for Fpga Programming Using Verilog Hdl Language

o Click on the blue cell at approximately the 300 ns to assert DIRECTION high so that the counter will count up.

o Click on the blue cell at approximately the 900 ns to assert DIRECTION low so that the counter will count down.

Save the waveform. In the Sources window, select the Behavioral Simulation view to see that the test bench

waveform file is automatically added to your project.

Close the test bench waveform.

Simulating Design FunctionalityVerify that the counter design functions as you expect by performing behavior simulation as follows:

Verify that Behavioral Simulation and counter_tbw are selected in the Sources window.

In the Processes tab, click the “+” to expand the Xilinx ISE Simulator process and double-click the Simulate Behavioral Model process.

The ISE Simulator opens and runs the simulation to the end of the test bench. To view your simulation results, select the Simulation tab and zoom in on the transitions.

The simulation waveform results will look like the following:

13

Page 14: Training Manual for Fpga Programming Using Verilog Hdl Language

Verify that the counter is counting up and down as expected. Close the simulation view. If you are prompted with the following message, “You have

an active simulation open. Are you sure you want to close it?” Click Yes to continue.You have now completed simulation of your design using the ISE Simulator.

1.5 CREATE TIMING CONSTRAINTSSpecify the timing between the FPGA and its surrounding logic as well as the frequency the design must operate at internal to the FPGA. The timing is specified by entering constraints that guide the placement and routing of the design. It is recommended that you enter global constraints. The clock period constraint specifies the clock frequency at which your design must operate inside the FPGA. The offset constraints specify when to expect valid data at the FPGA inputs and when valid data will be available at the FPGA outputs.

Entering Timing ConstraintsTo constrain the design do the following:

Select Implementation from the drop-down list in the Sources window. Select the counter HDL source file. Click the “+” sign next to the User Constraints processes group, and double-click the

Create Timing Constraints process.ISE runs the Synthesis and Translate steps and automatically creates a User Constraints File (UCF). You will be prompted with the following message:

Click Yes to add the UCF file to your project. The counter.ucf file is added to your project and is visible in the Sources window. The Xilinx Constraints Editor opens automatically.

Note: You can also create a UCF file for your project by selecting Project → Create New Source.

14

Page 15: Training Manual for Fpga Programming Using Verilog Hdl Language

In the Timing Constraints dialog, enter the following in the Period, Pad to Setup, and CLock to Pad fields:♦ Period: 40♦ Pade to Setup: 10♦ Clock to Pad: 10Press Enter.After the information has been entered, the dialog should look like what is shown below.

Select Timing Constraints under Constraint Type in the Timing Constraints tab and the newly created timing constraints are displayed as follows:

15

Page 16: Training Manual for Fpga Programming Using Verilog Hdl Language

Save the timing constraints. If you are prompted to rerun the TRANSLATE or XST step, click OK to continue.9. Close the Constraints Editor.

1.6 IMPLEMENT DESIGN AND VERIFY CONSTRAINTSImplement the design and verify that it meets the timing constraints specified in the previous section.Implementing the Design

Select the counter source file in the Sources window. Open the Design Summary by double-clicking the View Design Summary process in the

Processes tab. Double-click the Implement Design process in the Processes tab. Notice that after Implementation is complete, the Implementation processes have a green

check mark next to them indicating that they completed successfully without Errors or Warnings.

16

Page 17: Training Manual for Fpga Programming Using Verilog Hdl Language

Post Implementation Design Summary Locate the Performance Summary table near the bottom of the Design Summary. Click the All Constraints Met link in the Timing Constraints field to view the Timing

Constraints report. Verify that the design meets the specified timing requirements.

All Constraints Met Report Close the Design Summary.

Assigning Pin Location ConstraintsSpecify the pin locations for the ports of the design so that they are connected correctly on the Spartan-3E Basys-2 board.To constrain the design ports to package pins, do the following:

Verify that counter is selected in the Sources window. Double-click the Floorplan Area/IO/Logic - Post Synthesis process found in the User

Constraints process group. The Xilinx Pinout and Area Constraints Editor (PACE) opens. Select the Package View tab. In the Design Object List window, enter a pin location for each pin in the Loc column

using the following information:♦ CLOCK input port connects to FPGA pin C8 (RCCLK signal on board)♦ COUNT_OUT<0> output port connects to FPGA pin M5 (LD0 signal on board)♦ COUNT_OUT<1> output port connects to FPGA pin M11 (LD1 signal on board)♦ COUNT_OUT<2> output port connects to FPGA pin P7 (LD2 signal on board)♦ COUNT_OUT<3> output port connects to FPGA pin P6 (LD3 signal on board)♦ DIRECTION input port connects to FPGA pin P11 (SW0 signal on board)

17

Page 18: Training Manual for Fpga Programming Using Verilog Hdl Language

Select File → Save. You are prompted to select the bus delimiter type based on the synthesis tool you are using. Select XST Default <> and click OK.

Close PACE.Notice that the Implement Design processes have an orange question mark next to them, indicating they are out-of-date with one or more of the design files. This is because the UCF file has been modified.

1.7 REIMPLEMENT DESIGN AND VERIFY PIN LOCATIONSReimplement the design and verify that the ports of the counter design are routed to the package pins specified in the previous section. First, review the Pinout Report from the previous implementation by doing the following:

Open the Design Summary by double-clicking the View Design Summary process in the Processes window.

Select the Pinout Report and select the Signal Name column header to sort the signal names. Notice the Pin Numbers assigned to the design ports in the absence of location constraints.

18

Page 19: Training Manual for Fpga Programming Using Verilog Hdl Language

Reimplement the design by double-clicking the Implement Design process. Select the Pinout Report again and select the Signal Name column header to sort the

signal names. Verify that signals are now being routed to the correct package pins.

Close the Design Summary.

19

Page 20: Training Manual for Fpga Programming Using Verilog Hdl Language

1.8 DOWNLOAD DESIGN TO THE SPARTA-3E BASYS-2 BOARDThis is the last step in the design verification process. This section provides simple instructions for downloading the counter design to the Spartan-3E Basys-2 board.

Select Implementation from the drop-down list in the Sources window. Select counter in the Sources window. In the Process window, double-click the Configure Target Device process. Click OK in the following warning.

Click finish on the iMPACT window

20

Page 21: Training Manual for Fpga Programming Using Verilog Hdl Language

Now connect the Basys-2 board to the PC through the USB cable. Power on the board through the power sliding switch. Then open the Adept software. Then click “Initialize Chain”.

To program a device: Click the Browse button next to the device icon in the window. An Open dialog box

appears. Select the appropriate configuration file (.bit file) in the Open dialog box and click the

Open button. Adept displays a history of configuration files in the drop-down list box next to the device.

Click the Program button or right-click on the device icon and select Program Device.

21

Page 22: Training Manual for Fpga Programming Using Verilog Hdl Language

The Test Tab

Adept can run simple diagnostic tests on boards so that you can verify that the board is functioning properly. To begin a test of the board, click the Start Test button. This automatically loads a diagnostic test configuration to the FPGA. The red button changes to green. You see "PASS" and "128" appear alternately on the 7-seg display. Play with the 8 switches and notice that the 8 singular LEDs on the board follow the switches. The test can be stopped any time by pressing the Stop Test button, switching to a different tab, or changing the connected device.

22

Page 23: Training Manual for Fpga Programming Using Verilog Hdl Language

VERILOG PROGRAMMING

LANGUAGE

23

Page 24: Training Manual for Fpga Programming Using Verilog Hdl Language

1. INTRODUCTION

The complexity of hardware design has grown exponentially in the last decade. The exponential growth is fueled by new advances in design technology as well as the advances in fabrication technology. The usage of Hardware Description Language (HDL) to model, simulate, synthesize, analyze, and test the design has been a cornerstone of this rapid development. Verilog HDL is a Hardware Description Language. A Hardware Description Language is a language used to describe a digital system: for example, a network switches, a microprocessor or a memory or a simple flip-flop. HDL allows the design to be simulated earlier in the design cycle in order to correct errors or experiment with different architectures. Designs described in HDL are technology-independent, easy to design and debug, and are usually more readable than schematics, particularly for large circuits. One may describe a digital system at several levels. For example, an HDL might describe the layout of the wires, resistors and transistors on an Integrated Circuit (IC) chip, i.e., the switch level. Or, it might describe the logical gates and flip flops in a digital system, i.e., the gate level. An even higher level describes the registers and the transfers of vectors of information between registers. This is called the Register Transfer Level (RTL). Verilog supports all of these levels.

1.1 WHAT IS VERILOG?

Verilog is one of the two major Hardware Description Languages (HDL) used by hardware designers in industry and academia. VHDL is the other one. The industry is currently split on which is better. Many feel that Verilog is easier to learn. Verilog is very C-like and liked by electrical and computer engineers as most learn the C language in college. VHDL is very Ada-like and most engineers have no experience with Ada.

Verilog was introduced in 1985 by Gateway Design System Corporation, now a part of Cadence Design Systems. Until May, 1990, with the formation of Open Verilog International (OVI), Verilog HDL was a proprietary language of Cadence. Cadence was motivated to open the language to the Public Domain with the expectation that the market for Verilog HDL-related software products would grow more rapidly with broader acceptance of the language.

Verilog HDL allows a hardware designer to describe designs at a high level of abstraction such as at the architectural or behavioral level as well as the lower implementation levels (i.e., gate and switch levels) leading to Very Large Scale Integration (VLSI) Integrated Circuits (IC) layouts and chip fabrication. A primary use of HDLs is the simulation of designs before the designer must commit to fabrication.

1.2 WHY USE VERILOG HDL?

Digital systems are highly complex. At their most detailed level, they may consist of millions of elements, i.e., transistors or logic gates. Therefore, for large digital systems, gate-level design is dead. For many decades, logic schematics served as the bridge language of logic design, but not anymore. Today, hardware complexity has grown to such a degree that a schematic with logic gates is almost useless as it shows only a web of connectivity and not the functionality of design.

24

Page 25: Training Manual for Fpga Programming Using Verilog Hdl Language

Since the 1970s, Computer engineers and electrical engineers have moved toward hardware description languages (HDLs). The most prominent modern HDLs in industry are Verilog and VHDL. Verilog is the top HDL used by over 10,000 designers at such hardware vendors as Sun Microsystems, Apple Computer and Motorola. The Verilog language provides the digital designer with a means of describing a digital system at a wide range of levels of abstraction and at the same time provides access to computer-aided design tools to aid in the design process at these levels. Verilog allows hardware designers to express their design with behavioral constructs, deterring the details of implementation to a later stage of design. An abstract representation helps the designer explore architectural alternatives through simulations and to detect design bottlenecks before detailed design begins. Computer-aided-design tools, i.e., programs, exist which will “compile” programs in the Verilog notation to the level of circuits consisting of logic gates and flip flops. One could then go to the lab and wire up the logical circuits and have a functioning system. And, other tools can “compile” programs in Verilog notation to a description of the integrated circuit masks for very large scale integration (VLSI). Verilog also allows the designer to specific designs at the logical gate level using gate constructs and the transistor level using switch constructs. Verilog allows engineers to optimize the logical circuits and VLSI layouts to maximize speed and minimize area of the VLSI chip.

1.3 HIERARCHICAL MODELING CONCEPTS

Before we discuss the details of the Verilog language, we must first understand basic hierarchical modeling concepts in digital design.

Design Methodologies

There are two basic types of digital design methodologies: a top-down design methodology and a bottom-up design methodology. In a top-down design methodology, we define the top-level block and identify the sub-blocks necessary to build the top-level block. We further subdivide the sub-blocks until we come to leaf cells, which are the cells that cannot further be divided. Figure 1-1 shows the top-down design process.

Figure 1-1. Top-down Design Methodology

25

Page 26: Training Manual for Fpga Programming Using Verilog Hdl Language

In a bottom-up design methodology, we first identify the building blocks that are available to us. We build bigger cells, using these building blocks. These cells are then used for higher-level blocks until we build the top-level block in the design.

Figure 1-2. Bottom-up Design Methodology

Typically, a combination of top-down and bottom-up flows is used. Design architects define the specifications of the top-level block. Logic designers decide how the design should be structured by breaking up the functionality into blocks and sub-blocks. At the same time, circuit designers are designing optimized circuits for leaf-level cells. They build higher-level cells by using these leaf cells. The flow meets at an intermediate point where the switch-level circuit designers have created a library of leaf cells by using switches, and the logic level designers have designed from top-down until all modules are defined in terms of leaf cells.

26

Page 27: Training Manual for Fpga Programming Using Verilog Hdl Language

2. VERILOG FOR DESCRIPTION

2.1 MODULE DEFINITION

Verilog provides the concept of a module. A module is the basic building block in Verilog. A module can be an element or a collection of lower-level design blocks. Typically, elements are grouped into modules to provide common functionality that is used at many places in the design. A module provides the necessary functionality to the higher-level block through its port interface (inputs and outputs), but hides the internal implementation. This allows the designer to modify module internals without affecting the rest of the design. Modules communicate with the outside world through input, output and bi-directional (inout) ports. In Verilog, a module is declared by the keyword module. A corresponding keyword endmodule must appear at the end of the module definition. Each module must have a module_name, which is the identifier for the module, and a port list, which describes the input and output terminals of the module. Design functionality is implemented inside module, after port declaration. The design functionality implementation part is represented as “body” here.

Syntax:

27

Page 28: Training Manual for Fpga Programming Using Verilog Hdl Language

Example:

module MAT (enable, data, all_zero, result, status);

input enable; // scalar input

input [3:0] data; // vector input

output all_zero; // scalar output

output [3:0] result; // vector output

Inout [1:0] status // bi-directional port

……

endmodule

To make code easy to read, use self-explanatory port names. For the purpose of conciseness, use short port names. In vector port declaration, MSB can be smaller index.

For e.g. output [0:3] result (result[0] is the MSB)

2.1.1 THE MODULE NAME

The module name, formally called an identifier serves documentation purpose. Based on this in your module names you should use such noun phrases that best describes what the system is doing. Each identifier in Verilog, including module names must follow these rules:

It can be composed of letters, digits, dollar sign ($), and underscore characters (_) only. It must start with a letter or underscore. No spaces are allowed inside an identifier. Upper and lower case characters are distinguished (Verilog is case sensitive) Reserved keywords cannot be used as identifiers.

Ex: Counter_4Bit, ALU, Receiver, UART_Transmit

2.1.2 PORTS

Ports provide a means for a module to communicate through input and output. Every port in the port list must be declared as input, output or inout, in the module. All ports declared as one of the above is assumed to be a wire by default, to declare it otherwise it is neccessary to declare it again. For example in the D-type flip flop we want the ouput to hold on to its value until the next clock edge so it has to be a register.

module d_ff(q, d, reset, clock);

28

MAT

enable

data[3:0]

all_zero

result[3:0]

status[1:0]

LSBMSB

Page 29: Training Manual for Fpga Programming Using Verilog Hdl Language

output q; // all ports must be declaredinput d, reset, clock; // as input or outputreg q; // the ports can be declared again as required.

Note: by convention, outputs of the module are always first in the port list. This convention is also used in the predefined modules in Verilog.

Input ports:In an inner module inputs must always be of a net type, since values will be driven into them. In the outer module the input may be a net type or a reg.Output ports:In an inner module outputs can be of a net type or a reg. In an outer module the output must be of a net type since values will be driven into them by the inner module.Inout ports:Inouts must always be of a net type.

Port Matching:When calling a module the width of each port must be the same, eg, a 4-bit register cannot be matched to a 2-bit register. However, output ports may remain unconnected, by missing out their name in the port list. This would be useful if some outputs were for debugging purposes or if some outputs of a more general module were not required in a particular context. However input ports cannot be omitted.For example:d_ff dff0( , d, reset, clock); // the output (q) has been omitted// the comma is ESSENTIAL

2.2 ONE LANGUAGE, MANY CODING STYLES

Verilog is both a behavioral and a structural language. Internals of each module can be defined at four levels of abstraction, depending on the needs of the design. The module behaves identically with the external environment irrespective of the level of abstraction at which the module is described. The internals of the module are hidden from the environment. Thus, the level of abstraction to describe a module can be changed without any change in the environment.

2.2.1 BEHAVIORAL OR ALGORITHMIC LEVEL

This is the highest level of abstraction provided by Verilog HDL. A module can be implemented in terms of the desired design algorithm without concern for the hardware implementation details. Designing at this level is very similar to C programming.

29

Page 30: Training Manual for Fpga Programming Using Verilog Hdl Language

2.2.2 DATAFLOW LEVEL

At this level, the module is designed by specifying the data flow. The designer is aware of how data flows between hardware registers and how the data is processed in the design. Here a circuit can be specified with assignment statements and can be expressed as a list of outputs and expressions that transform the input values to the desired outputs. The expressions can be based on a broad range of operators such as logical operators, bit-wise, reduction, arithmetic, conditional and concatenation operators. All of them can be applied to the assignment statements making data flow style more universal than logical equations.

30

Page 31: Training Manual for Fpga Programming Using Verilog Hdl Language

2.2.3 GATE LEVEL or STRUCTURAL LEVEL

The module is implemented in terms of logic gates and interconnections between these gates. Design at this level is similar to describing a design in terms of a gate-level logic diagram. It resembles a schematic drawing with components connected with signals. The functionality of the design is hidden inside the component. The components in structural specification can be either primitives or instantiated modules. The former ones are such simple components as gates and flip-flops (or other small scale blocks), and the latter ones can be of any complexity.

A change in the value of any input signal of a component activates the component. If two or more components are activated concurrently, they will perform their actions concurrently as well.

31

Page 32: Training Manual for Fpga Programming Using Verilog Hdl Language

2.2.4 SWITCH LEVEL

This is the lowest level of abstraction provided by Verilog. A module can be implemented in terms of transistors, switches, storage nodes, and the interconnections between them. Design at this level requires knowledge of switch-level implementation details.

Verilog allows the designer to mix and match all four levels of abstractions in a design. In the digital design community, the term register transfer level (RTL) is frequently used for a Verilog description that uses a combination of behavioral and dataflow constructs and is acceptable to logic synthesis tools. If a design contains four modules, Verilog allows each of the modules to be

32

Page 33: Training Manual for Fpga Programming Using Verilog Hdl Language

written at a different level of abstraction. As the design matures, most modules are replaced with gate-level implementations. Normally, the higher the level of abstraction, the more flexible and technology-independent the design. As one goes lower toward switch-level design, the design becomes technology-dependent and inflexible. A small modification can cause a significant number of changes in the design. Consider the analogy with C programming and assembly language programming. It is easier to program in a higher-level language such as C. The program can be easily ported to any machine. However, if you design at the assembly level, the program is specific for that machine and cannot be easily ported to another machine.

2.3 MODULE INSTANTIATION

A module provides a template from which you can create actual objects. When a module is invoked, Verilog creates a unique object from the template. Each object has its own name, variables, parameters, and I/O interface. The process of creating objects from a module template is called instantiation, and the objects are called instances. A module can be instantiated in another module thus creating hierarchy.

Syntax:Module_name Instance_name (Port_Association_List)

Module instantiation consists of module_name followed by instance_name and port_association_list. Need of instance_name is, we can have multiple instance of same module in the same program. Instance name should be unique for each instance of the same module. Port_association_list shows how ports are mapped. Port mapping can be done in two different ways i.e. “Port mapping by order” and “Port mapping by name’. Let us take an example of 4-bit adder for explaining module instantiation.

Example of 4-bit adder:module fulladder_4bit(sum, cout, a, b, cin);//input output port declarationsoutput [3:0] sum;output cout;input [3:0] a, b;input cin;wire c1, c2, c3; // Instantiate four 1-bit full addersfulladd f0 (sum[0], c1, a[0], b[0], cin);fulladd f1 (sum[1], c2, a[1], b[1], c1);fulladd f2 (sum[2], c3, a[2], b[2], c2);fulladd f3 (sum[3], cout, a[3], b[3], c3);endmodule;

33

module fulladd (s, c_out, ain, bin, c_in);

output s, c_out;

input ain, bin, c_in;

assign s = (ain ^ bin) ^ c_in;

assign c_out = (a & b) | (b & c_in) | (c_in & a);

endmodule;

Page 34: Training Manual for Fpga Programming Using Verilog Hdl Language

SYNCHRO

D

CLK

DFF Q

CLK

DFF

D

Q SYNC

CLOCK

ASYNC

DFF1 DFF2

C1_ASYNC

Module for 1-bit adder is fulladd. This 1-bit adder is instantiated ‘4’ times to get functionality of 4-bit adder i.e. fulladder_4bit. Each instance of full adder has different instance name and port association list.

AN EXAMPLE:

Figure shows an example for module instantiation. Figure shows module “SYNCHRO” which consists of 2 ‘D’ flip-flops and are connected in serial fashion. Module “SYNCHRO” has 2 input ports “ASYNC” and “CLOCK” and 1 output port “SYNC”. The first ‘D’ flip-flop has 2 inputs “ASYNC” and “CLOCK” and 1 output “C1_ASYNC”. The second ‘D’ flip-flop 2 inputs “C1_ASYNC” and “CLOCK” and 1 output “SYNC”.

2.3.1 MODULE PORT CONNECTION BY ORDER

module SYNCHRO(ASYNC,SYNC,CLOCK);input ASYNC;input CLOCK;output SYNC;wire C1_ASYNC;

DFF DFF1 (C1_ASYNC, ASYNC, CLOCK);DFF DFF2 (SYNC, C1_ASYNC, CLOCK);

//DFF DFF1 (ASYNC, C1_ASYNC, CLOCK);//DFF DFF2 (SYNC, C1_ASYNC, CLOCK);

endmodule

Here first instance name of ‘D’ flip-flop is “DFF1” and second instance name is “DFF2”. In this module ports are connected by order. Order of ports in instantiation of DFF1 and DFF2 is

34

Verilog Programming for DFF

module DFF (Q, D, CLK);input D, CLK;output Q;reg Q;always @ (posedge CLK)Q <= D;endmodule

Page 35: Training Manual for Fpga Programming Using Verilog Hdl Language

same as order of ports in DFF. If the number of ports increased, then it is very difficult to do “module ports connection by order”.

2.3.2 MODULE PORT CONNECTION BY NAME

Module SYNCHRO (ASYNC, SYNC, CLOCK);input ASYNC;input CLOCK;output SYNC;wire C1_ASYNC;

DFF DFF1 (.D (ASYNC), .CLK (CLOCK), .Q (C1_ASYNC));DFF DFF2 (.D (C1_ASYNC), .Q (SYNC), .CLK (CLOCK));

endmodule;

In this module ports are connected by Name. Order of ports in instantiation of DFF1 and DFF2 is different from order of ports in DFF. In this ‘.’ Is used to represent port name followed by associated port name in small brackets i.e. “()”. Advantage of using “port connection by name” is, it is easy to port map for large number of ports in a design.

Note: Always connect ports by name.

Inside the same module, instance names of particular module should be different. In the same way, inside the same module, instance name of different modules should be different.

For example:module A();

DFF DFF1();DFFE DFF1();

endmoduleIS NOT ALLOWED

Above example shows module ‘A’ is top-level module, in that ‘2’ different modules “DFF” and “DFFE” are instantiated with same instance name “DFF1”. Since instance name is same, this is not allowed.

35

Page 36: Training Manual for Fpga Programming Using Verilog Hdl Language

Figure shows a Design hierarchy. In this “ABC” is the top-level module. Two scenarios are shown here. In first scenario “ABC” is the top-level module and “SYNCHRO1” and “SYNCHRO2” are instance names. Under “SYNCHRO1”, “DFF1” and “DFF2” are instance names. Under “SYNCHRO2”, “DFF1” and “DFF2” are instance names. In this instance names are different at same hierarchy. Hence this is allowed in scenario-1.

In second scenario “ABC” is the top-level module and “SYNCHRO1” and “SYNCHRO1” are instance names. Under “SYNCHRO1”, “DFF1” and “DFF2” are instance names. Under another “SYNCHRO1”, “DFF1” and “DFF2” are instance names. In this instance names “SYNCHRO1” and “SYNCHRO1” are same at the same hierarchy. Hence this is not allowed in scenario2

Note: At the same hierarchy the instance name should not be same.

2.4 LEXICOGRAPHY

Verilog, like any high level language has a number of tokens like comments, operators, numbers, strings, identifiers and keywords.

2.4.1 COMMENTS

Comments can be inserted in the code for readability and documentation. There are two ways to write comments. A one line comment starts with "//". Verilog skips from that point to the end of line. A multiple-line comment block comment starts with "/*" and ends with "*/". Multiple-line comments cannot be nested. However, one-line comments can be embedded in multiple-line comments.

36

ALLOWED NOT ALLOWED

Page 37: Training Manual for Fpga Programming Using Verilog Hdl Language

a = b && c; // This is a one-line comment/* This is a multiple linecomment *//* This is /* an illegal */ comment *//* This is //a legal comment */

2.4.2 OPERATORS

Verilog has three types of operators; they take either one, two or three operands. Unary operators appear on the left of their operand, binary in the middle, and ternary separates its three operands by two operators.

clock = ~clock; // ~ is the unary bitwise negation operator, clock is the operandc = a || b; // || is the binary logical or, a and b are the operandsr = s ? t : u; // ?: is the ternary conditional operator, which// reads r = [if s is true then t else u]

2.4.3 NUMBERS

Integers

Integers can be in binary ( b or B ), decimal ( d or D ), hexidecimal ( h or H ) or octal ( o or O ).Numbers are specified by1. <size>'<base><number> : for a full description2. <base><number>: this is given a default size which is machine dependant but at least 32 bits.3. <number> : this is given a default base of decimalThe size specifies the exact number of bits used by the number. For example, a 4 bit binary will have 4 as the size specification and a 4 digit hexadecimal will have 16 as the size specification since each hexadecimal digit requires 4 bits.

8'b10100010 // 8 bit number in binary representation8'hA2 // 8 bit number in hexadecimal representation

X and Z values

x represents an unknown, and z a high impedance value. An x declares 4 unknown bits in hexadecimal, 3 in octal and 1 in binary. z declares high impedance values similarly.

4'b10x0 // 4 bit binary with 2nd least sig. fig. unknown4'b101z // 4 bit binary with least sig. fig. of high impedance12'dz // 12 bit decimal high impedance number

37

Page 38: Training Manual for Fpga Programming Using Verilog Hdl Language

Negative numbersA number can be declared to be negative by putting a minus sign in front of the <size>. It must not appear between the <size> and <base>, nor between the <base> and the number.-8'd5 // 2's compliment of 5, held in 8 bits8'b-5 // illegal syntax

UnderscoreUnderscores can be put anywhere in a number, except the beginning, to improve readability.16'b0001_1010_1000_1111 // use of underscore to improve readability8'b_0001_1010 // illegal use of underscore

RealReal numbers can be in either decimal or scientific format, if expressed in decimal format they must have at least one digit either side of the decimal point.1.83_2387.3398_30473.8e10 // e or E for exponent2.1e-93. // illegal

2.4.4 STRINGS

Strings are delimited by " ... ", and cannot be on multiple lines. "hello world"; // legal string"goodbyeworld"; // illegal string

2.4.5 IDENTIFIERS

Identifiers are user-defined words for variables, function names, module names, block names and instance names. Identifiers begin with a letter or underscore (Not with a number or $) and can include any number of letters, digits and underscores. Identifiers in Verilog are case-sensitive.

_ABC_ /* is not the same as */ _abc_

38

Page 39: Training Manual for Fpga Programming Using Verilog Hdl Language

2.4.6 VERILOG KEYWORDS

These are words that have special meaning in Verilog. Some examples are assign, case, while, wire, reg, and, or, nand, module etc. They should not be used as identifiers. All keywords must be in lower case

2.5 DATA TYPES

2.5.1 DATA VALUES

Value Level Condition in Hardware Circuits (Logic State)

0 Logic Zero/ False Condition/ Ground1 Logic One/ True Condition/ Powerx Unknown/ Uninitializedz High Impedance/ Floating

Values ‘x’ and ‘z’ are case insensitive.

2.5.2 NETS

Keywords: wire, tri, supply0, supply1Default value: zDefault size: 1 bit

Nets represent the continuous updating of outputs with respect to their changing inputs. For example in the figure below, c is connected to a by a not gate. If c is declared and initialized as shown, it will continuously be driven by the changing value of a, its new value will not have to be explicitly assigned to it.

If the drivers of a wire have the same value, the wire assumes this value. If the drivers have different values it chooses the strongest, if the strengths are the same the wire assumes the value of unknown, ‘x’. If no driver is connected it defaults to value of ‘z’.

The net types wire and tri shall be identical in their syntax and functions. A wire net can be used for nets that are driven by a single gate or continuous assignment. The tri net type can be used where multiple drivers drive a net.

39

Page 40: Training Manual for Fpga Programming Using Verilog Hdl Language

Supply0 and supply1 define wires tied to logic 0 (ground) and logic 1 (power), respectively.supply0 my_gnd; // equivalent to a wire assigned 0supply1 a, b;

2.5.3 REGISTERS

Keywords: regDefault value: xDefault size: 1 bitRegisters represent data storage elements. Registers retain value until another value is placed onto them. Do not confuse the term registers in Verilog with hardware registers built from edge-triggered flip-flops in real circuits. In Verilog, the term register merely means a variable that can hold a value. Unlike a net, a register does not need a driver. Verilog registers do not need a clock as hardware registers do. Values of registers can be changed anytime in a simulation by assigning a new value to the register. Register data types are commonly declared by the keyword reg. The default value for a reg data type is x.

reg a; // single 1-bit register variablereg [7:0] b; // an 8-bit vector; a bank of 8 registers.

An example of how registers are used is shown. Any object assigned within a Verilog procedural block (always and initial) must be declared as a reg data type.

reg reset; // declare a variable reset that can hold its valueinitial // this construct will be discussed laterbeginreset = 1'b1; //initialize reset to 1 to reset the digital circuit.#100 reset = 1'b0; // after 100 time units reset is deasserted.end

Comparing reg versus wire:Comparison between reg and wire can be done through an example for multiplexure.

module MUX21 (input A, B, SEL, output wire OUT1);assign OUT1 = (A & SEL) | (B & ~SEL);endmodule

OUT1 is a wire by default

module MUX21 (input A, B, SEL, output reg OUT1);

40

Page 41: Training Manual for Fpga Programming Using Verilog Hdl Language

always @ (A, B, SEL)if (SEL)

OUT1 = A;else

OUT1 = B;endmodule

OUT1 must be declared as reg

2.5.4 VECTORS and ARRAYS

Nets or reg data types can be declared as vectors (multiple bit widths). If bit width is not specified, the default is scalar (1-bit).wire a; // scalar net variablewire [7:0] bus; // 8-bit buswire [31:0] busA,busB,busC; // 3 buses of 32-bit width.reg clock; // scalar registerreg [0:40] virtual_addr; // Vector register, virtual address 41 bits wideVectors can be declared at [high# : low#] or [low# : high#], but the left number in the squared brackets is always the most significant bit of the vector. In the example shown above, bit 0 is the most significant bit of vector virtual_addr.

Vector Part Select:

For the vector declarations shown above, it is possible to address bits or parts of vectors.busA[7] // bit # 7 of vector busAbusB[2:0] /* Three least significant bits of vector bus. Using busB[0:2] is illegal because the significant bit should always be on the left of a range specification. */virtual_addr[0:1] // Two most significant bits of vector virtual_addr

Multi-dimensional arrays can also be declared with any number of dimensions.reg [4:0] port_id[0:7]; // Array of 8 port_ids; each port_id is 5 bits wide

2.5.5 MEMORIES

In digital simulation, one often needs to model register files, RAMs, and ROMs. Memories are modeled in Verilog simply as a one-dimensional array of registers. Each element of the array is known as an element or word and is addressed by a single array index. Each word can be one or

41

Page 42: Training Manual for Fpga Programming Using Verilog Hdl Language

more bits. It is important to differentiate between n 1-bit registers and one n-bit register. A particular word in memory is obtained by using the address as a memory array subscript.

reg mem1bit[0:1023]; // Memory mem1bit with 1K 1-bit wordsreg [7:0] membyte[0:1023]; // Memory membyte with 1K 8-bit words(bytes)membyte[511] // Fetches 1 byte word whose address is 511.

2.5.6 “INTEGER”, “REAL”, AND “TIME” REGISTER DATA TYPES

Integer, real, and time register data types are supported in Verilog.

Integer:

An integer is a general purpose register data type used for manipulating quantities. Integers are declared by the keyword integer. Although it is possible to use reg as a general-purpose variable, it is more convenient to declare an integer variable for purposes such as counting. The default width for an integer is the host-machine word size, which is implementation-specific but is at least 32 bits. Registers declared as data type reg store values as unsigned quantities, whereas integers store values as signed quantities.integer counter; // general purpose variable used as a counter.initialcounter = -1; // A negative one is stored in the counter

Real:

Real number constants and real register data types are declared with the keyword real. They can be specified in decimal notation (e.g., 3.14) or in scientific notation (e.g., 3e6, which is 3x106). Real numbers cannot have a range declaration, and their default value is 0. When a real value is assigned to an integer, the real number is rounded off to the nearest integer.

real delta; // Define a real variable called deltainitialbegindelta = 4e10; // delta is assigned in scientific notationdelta = 2.13; // delta is assigned a value 2.13endinteger i; // Define an integer iinitiali = delta; // i gets the value 2 (rounded value of 2.13)

Time:

Verilog simulation is done with respect to simulation time. A special time register data type is used in Verilog to store simulation time. A time variable is declared with the keyword time. The

42

Page 43: Training Manual for Fpga Programming Using Verilog Hdl Language

width for time register data types is implementation-specific but is at least 64 bits. The system function $time is invoked to get the current simulation time.

time save_sim_time; // Define a time variable save_sim_timeinitialsave_sim_time = $time; // Save the current simulation time

Simulation time is measured in terms of simulation seconds. The unit is denoted by s, the same as real time. However, the relationship between real time in the digital circuit and simulation time is left to the user.

2.5.7 PARAMETERS

Verilog allows constants to be defined in a module by the keyword parameter. Parameters cannot be used as variables. Parameter types and sizes can also be defined.parameter port_id = 5; // Defines a constant port_idparameter signed [15:0] WIDTH; // Fixed sign and range for parameter WIDTH

2.5.8 STRINGS

Strings can be stored in reg. The width of the register variables must be large enough to hold the string. Each character in the string takes up 8 bits (1 byte). If the width of the register is greater than the size of the string, Verilog fills bits to the left of the string with zeros. If the register width is smaller than the string width, Verilog truncates the leftmost bits of the string. It is always safe to declare a string that is slightly wider than necessary.

reg [8*18:1] string_value; // Declare a variable that is 18 bytes wideinitialstring_value = "Hello Verilog World"; // String can be stored in variable

2.6 EXPRESSIONS, OPERANDS AND OPERATORS

Dataflow modeling describes the design in terms of expressions instead of primitive gates. Expressions, operators, and operands form the basis of dataflow modeling.

2.6.1 EXPRESSIONS

Expressions are constructs that combine operators and operands to produce a result.

// Examples of expressions. Combines operands and operatorsa ^ baddr1[20:17] + addr2[20:17]

43

Page 44: Training Manual for Fpga Programming Using Verilog Hdl Language

in1 | in2

2.6.2 OPERANDS

Operands can be any one of the data types defined in Section 2.5, Data Types. Operands can be constants, integers, real numbers, nets, registers, times, bit-select (one bit of vector net or a vector register), part-select (selected bits of the vector net or register vector), and memories or function calls.

integer count, final_count;final_count = count + 1; //count is an integer operand

2.6.3 OPERATORS

Operators act on the operands to produce desired results. Verilog provides various types of operators. Operators can be arithmetic, logical, relational, equality, bitwise, reduction, shift, concatenation, or conditional.

Operator Types and Symbols:

Operator Type Operator Symbol Operation Performed Number of Operands

Arithmetic

* multiply two/ divide two+ add two- subtract two% modulus two** power (exponent) two

Logical

! logical negation one&& logical and two|| logical or two

Relational

> greater than two< less than two>= greater than or equal two<= less than or equal two

Equality

== equality two!= inequality two=== case equality two!== case inequality two

Bitwise

~ bitwise negation one& bitwise and two| bitwise or two^ bitwise xor two^~ or ~^ bitwise xnor two

Reduction & reduction and one

44

Page 45: Training Manual for Fpga Programming Using Verilog Hdl Language

~& reduction nand one| reduction or one~| reduction nor one^ reduction xor one^~ or ~^ reduction xnor one

Shift

>> Right shift two<< Left shift two>>> Arithmetic right shift two<<< Arithmetic left shift two

Concatenation { } Concatenation any number

Replication { { } } Replication any number

Conditional ?: Conditional threeOperator Order of Precedence:

2.6.3.1 Arithmetic Operators:There are two types of arithmetic operators: binary and unary.

Binary operatorsBinary arithmetic operators are multiply (*), divide (/), add (+), subtract (-), power (**), and modulus (%). Binary operators take two operands.A = 4'b0011; B = 4'b0100; // A and B are register vectors

45

Page 46: Training Manual for Fpga Programming Using Verilog Hdl Language

D = 6; E = 4; F=2; // D and E are integersA * B // Multiply A and B. Evaluates to 4'b1100D / E // Divide D by E. Evaluates to 1. Truncates any fractional part.F = E ** F; //E to the power F, yields 16If any operand bit has a value x, then the result of the entire expression is x. Modulus operators produce the remainder from the division of two numbers. They operate similarly to the modulus operator in the C programming language.13 % 3 // Evaluates to 116 % 4 // Evaluates to 0-7 % 2 // Evaluates to -1, takes sign of the first operand7 % -2 // Evaluates to +1, takes sign of the first operandUnary operatorsThe operators + and - can also work as unary operators. They are used to specify the positive or negative sign of the operand. Unary + or - operators have higher precedence than the binary + or - operators.-4 // Negative 4+5 // Positive 5Negative numbers are represented as 2's complement internally in Verilog.

2.6.3.2 Logical Operators:Logical operators are logical-and (&&), logical-or (||) and logical-not (!). Operators && and || are binary operators. Operator ! is a unary operator. Logical operators always evaluate to a 1-bit value, 0 (false), 1 (true), or x (ambiguous).// Logical operationsA = 3; B = 0;A && B // Evaluates to 0. Equivalent to (logical-1 && logical-0)A || B // Evaluates to 1. Equivalent to (logical-1 || logical-0)!A // Evaluates to 0. Equivalent to not(logical-1)// UnknownsA = 2'b0x; B = 2'b10;A && B // Evaluates to x. Equivalent to (x && logical 1)// Expressions(a == 2) && (b == 3) // Evaluates to 1 if both a == 2 and b == 3 are true.// Evaluates to 0 if either is false.

2.6.3.3 Relational Operators:Relational operators are greater-than (>), less-than (<), greater-than-or-equal-to (>=), and less-than-or-equal-to (<=). If relational operators are used in an expression, the expression returns a logical value of 1 if the expression is true and 0 if the expression is false. If there are any unknown or z bits in the operands, the expression takes a value x. These operators function exactly as the corresponding operators in the C programming language.// A = 4, B = 3

46

Page 47: Training Manual for Fpga Programming Using Verilog Hdl Language

// X = 4'b1010, Y = 4'b1101, Z = 4'b1xxxA <= B // Evaluates to a logical 0A > B // Evaluates to a logical 1Y >= X // Evaluates to a logical 1Y < Z // Evaluates to an x

2.6.3.4 Equality Operators:Equality operators are logical equality (==), logical inequality (!=), case equality (===), and case inequality (!==). When used in an expression, equality operators return logical value 1 if true, 0 if false. These operators compare the two operands bit by bit, with zero filling if the operands are of unequal length. It is important to note the difference between the logical equality operators (==, !=) and case equality operators (===, !==). The logical equality operators (==, !=) will yield an x if either operand has x or z in its bits. However, the case equality operators (===, !== ) compare both operands bit by bit and compare all bits, including x and z. The result is 1 if the operands match exactly, including x and z bits. The result is 0 if the operands do not match exactly. Case equality operators never result in an x.// A = 4, B = 3// X = 4'b1010, Y = 4'b1101// Z = 4'b1xxz, M = 4'b1xxz, N = 4'b1xxxA == B // Results in logical 0X != Y // Results in logical 1X == Z // Results in xZ === M // Results in logical 1 (all bits match, including x and z)Z === N // Results in logical 0 (least significant bit does not match)M !== N // Results in logical 1

2.6.3.5 Bitwise Operators:Bitwise operators are negation (~), and (&), or (|), xor (^), xnor (^~, ~^). Bitwise operators perform a bit-by-bit operation on two operands. They take each bit in one operand and perform the operation with the corresponding bit in the other operand. If one operand is shorter than the other, it will be bit-extended with zeros to match the length of the longer operand. A z is treated as an x in a bitwise operation. The exception is the unary negation operator (~), which takes only one operand and operates on the bits of the single operand.

47

Page 48: Training Manual for Fpga Programming Using Verilog Hdl Language

// X = 4'b1010, Y = 4'b1101// Z = 4'b10x1~X // Negation. Result is 4'b0101X | Y // Bitwise or. Result is 4'b1111X ^~ Y // Bitwise xnor. Result is 4'b1000X & Z // Result is 4'b10x0It is important to distinguish bitwise operators ~, &, and | from logical operators !, &&, ||. Logical operators always yield a logical value 0, 1, x, whereas bitwise operators yield a bit-by-bit value. Logical operators perform a logical operation, not a bit-by-bit operation.// X = 4'b1010, Y = 4'b0000X | Y // bitwise operation. Result is 4'b1010X || Y // logical operation. Equivalent to 1 || 0. Result is 1.

2.6.3.6 Reduction Operators:Reduction operators are and (&), nand (~&), or (|), nor (~|), xor (^), and xnor (~^, ^~). Reduction operators take only one operand. Reduction operators perform a bitwise operation on a single vector operand and yield a 1-bit result. The logic tables for the operators are the same as shown for Bitwise Operators. The difference is that bitwise operations are on bits from two different operands, whereas reduction operations are on the bits of the same operand. Reduction operators work bit by bit from right to left. Reduction nand, reduction nor, and reduction xnor are computed by inverting the result of the reduction and, reduction or, and reduction xor, respectively.// X = 4'b1010&X //Equivalent to 1 & 0 & 1 & 0. Results in 1'b0^X //Equivalent to 1 ^ 0 ^ 1 ^ 0. Results in 1'b0

2.6.3.7 Shift Operators:Shift operators are right shift ( >>), left shift (<<), arithmetic right shift (>>>), and arithmetic left shift (<<<). Regular shift operators shift a vector operand to the right or the left by a specified number of bits. When the bits are shifted, the vacant bit positions are filled with zeros.

48

Page 49: Training Manual for Fpga Programming Using Verilog Hdl Language

i0

i1

s

Arithmetic shift operators use the context of the expression to determine the value with which to fill the vacated bits.// X = 4'b1100Y = X >> 1; //Y is 4'b0110. Shift right 1 bit. 0 filled in MSB position.Y = X << 2; //Y is 4'b0000. Shift left 2 bits.

2.6.3.8 Concatenation Operator:The concatenation operator ( {, } ) provides a mechanism to append multiple operands. The operands must be sized. Unsized operands are not allowed because the size of each operand must be known for computation of the size of the result.// A = 1'b1, B = 2'b00, C = 2'b10, D = 3'b110Y = {B , C} // Result Y is 4'b0010Y = {A , B[0], C[1]} // Result Y is 3'b101

2.6.3.9 Replication Operator:Repetitive concatenation of the same number can be expressed by using a replication constant. A replication constant specifies how many times to replicate the number inside the brackets ( { } ).A = 1'b1; B = 2'b00; C = 2'b10;Y = { 4{A} } // Result Y is 4'b1111Y = { 4{A} , 2{B} , C } // Result Y is 8'b1111000010

2.6.3.10 Conditional Operator:The conditional operator (?:) takes three operands.Usage: condition_expr ? true_expr : false_expr ;The condition expression (condition_expr) is first evaluated. If the result is true (logical 1), then the true_expr is evaluated. If the result is false (logical 0), then the false_expr is evaluated.

49

Page 50: Training Manual for Fpga Programming Using Verilog Hdl Language

2-to-1 Multiplexer, Using Logic Equations// Module 2-to-1 multiplexer using data flow. Logic equationmodule mux2_to_1 (out, i0, i1, s);// Port declarations from the I/O diagramoutput out;input i0, i1;input s;//Logic equation for outassign out = (~s & i0) | (s & i1);endmodule

2-to-1 Multiplexer, Using Conditional Operators// Module 2-to-1 multiplexer using data flow. Conditional operator.module multiplexer2_to_1 (out, i0, i1, s);// Port declarations from the I/O diagramoutput out;input i0, i1;input s;assign out = s ? i1 : i0;endmodule

2.7 SYSTEM TASKS AND COMPILER DIRECTIVESIn this section, we introduce two special concepts used in Verilog: system tasks and compiler directives.

2.7.1 SYSTEM TASKSVerilog provides standard system tasks for certain routine operations. All system tasks appear in the form $<keyword>.

System Task Description Usage

$display Prints the formatted message once when the statement is executed during simulation. A new line is automatically added at the end of its output.

Exampleinitial $display(“Hello World”);Prints the string between the quotation marks with a new line added at the end of the string.

50

Page 51: Training Manual for Fpga Programming Using Verilog Hdl Language

$write Prints the formatted message once when the statement is executed during simulation. No newline is added at the end of its output.

Exampleinitial $write(“Hello World”);Prints the string between the quotation marks with no new line added at the end of the string.

$strobe It executes after all simulation events in the current time step have executed. Prints the formatted message once when executed. This task guarantees that the printed values for the signals/variables are the final values the signals/ variables can have at that time step.

Exampleinitial $strobe(“Current values of A, B and C are A=%b, B=%b, C=%b”, A, B, C);Prints A, B and C and prints their value in binary format after all simulation events in the current time step have executed.

$monitor Invokes a background process that continuously monitors the signals listed, and prints the formatted message whenever one of the signals changes. A newline is automatically added at the end of its output. Only one $monitor can be active at a time.

Exampleinitial $monitor(“Current values of A, B and C are A=%b, B=%b, C=%b”, A, B, C);Monitors A, B and C and prints their value in binary format whenever one of the signals (i.e A or B or C) changes its value during simulation.

$time Returns the current simulation time as a 64-bit integer.

Exampleinitial $monitor(“time = %d, A = %d”, $time, A);Prints the current simulation time as a 64-bit decimal whenever $monitor gets executed.

$finish Finishes a simulation and exits the simulation process.

Exampleinitial $finish;

$stop Halts a simulation and enters an interactive debug mode.

Exampleinitial $stop;

2.7.2 COMPILER DIRECTIVES

Compiler Directives direct the pre-processor part of Verilog Parser or Simulator. They are not bound by modules or files. When a Simulator encounters a compiler directive, the directive remains in effect until another compiler directive either modifies it or turns it off. All compiler directives are defined by using the `<keyword> construct.

51

Page 52: Training Manual for Fpga Programming Using Verilog Hdl Language

Compiler Directive Description Usage

‘include File inclusion. The contents of another Verilog source file is inserted where the ‘include directive appears.

Here the contents of ‘define.h’ are included within the ‘idu’ module.

‘define Allows a text string to be defined as a macro name.

Example‘define gate_regression 1Allows ‘gate_regression’ to be substituted by 1 where ever it gets used.

2.8 WHAT ARE THE TIMING CONTROL STATEMENTS IN VERILOG

Timing Controls Description

#

It delays execution for a specific amount of time, ‘delay’ may be a number, a variable or an expression. Example of a procedural block using ‘#” is shown below.

Here ‘(c & d)’ gets evaluated at time 0 but gets assigned to ‘a’ after 2 time units whereas gets evaluated after 3 time units and gets assigned to ‘e’ immediately.

52

Page 53: Training Manual for Fpga Programming Using Verilog Hdl Language

@

It delays execution until there is a transition on any one of the signals in the sensitivity list. ‘edge’ may be either a posedge or negedge. If no edge is specified then any logic transition is used. Signals here may be scalar or vector, and any data type. Example of a procedural block using ‘@’ is shown below.

Here the statement within the always block gets evaluated whenever there is a transition on ‘b’ or ‘c’.

wait

It delays execution until the condition evaluates as true. Example of a procedural block using ‘wait’ is shown below.

Here we wait for ‘a’ to be equal to 2 before evaluating ‘e’.

2.9 BASIC BLOCKS

2.9.1 INTRODUCTION TO PROCEDURAL CONSTRUCTSThere are two kinds of assignment, continuous and procedural. Continuous assignments can only be made to nets, or a concatenation of nets. The operands can be of any data type. If one of the operands on the right hand side (RHS) of the assignment change, as the name suggests, the net on the left hand side (LHS) of the assignment is updated. In this way values are said to be driven into nets. Continuous assignments can be used to replace gate level descriptions with a higher level of abstraction.Procedural assignments are made to reg, integer, real or time, they need updating constantly to reflect any change in the value of the operands on the RHS. Procedural blocks in Verilog are used to model both combinatorial and sequential logic. They are also used in building a test bench environment for a design. There are two types of Procedural blocks which are ‘initial’ and ‘always’.

2.9.2 INITIAL BLOCKKeywords: initial

53

Page 54: Training Manual for Fpga Programming Using Verilog Hdl Language

An initial block consists of a statement or a group of statements enclosed in begin... end which will be executed only once at simulation time 0. If there is more than one block they execute concurrently and independently. The initial block is normally used for initialization, monitoring, generating wave forms (eg, clock pulses) and processes which are executed once in a simulation. An example of initialization and wave generation is given below.initialclock = 1'b0; // variable initializationinitialbegin // multiple statements have to be groupedalpha = 0;#10 alpha = 1; // waveform generation#20 alpha = 0;#5 alpha = 1;end;

2.9.3 ALWAYS BLOCKKeywords: alwaysAn always block is similar to the initial block, but the statements inside an always block will repeated continuously, in a looping fashion, until stopped by $finish or $stop.Note: the $finish command actually terminates the simulation where as $stop merely pauses it and awaits further instructions. Thus $finish is the preferred command unless you are using an interactive version of the simulator.One way to simulate a clock pulse is shown in the example below. module pulse;reg clock;initial clock = 1'b0; // start the clock at 0always #10 clock = ~clock; // toggle every 10 time unitsinitial #5000 $finish // end the simulation after 5000 time unitsendmodule

2.10 BEHAVIORAL MODELINGThe Behavioral or procedural level statements are used to model a design at a higher level of abstraction than the other levels. They provide powerful ways of doing complex designs. However small changes n coding methods can cause large changes in the hardware generated.

2.10.1 PROCEDURAL ASSIGNMENTSProcedural assignments are assignment statements used within Verilog procedures (always and initial blocks). Only reg variables and integers (and their bit/part-selects and concatenations) can be placed left of the “=” in procedures. The right hand side of the assignment is an expression which may use any of the operator types.2.10.2 DELAY IN ASSIGNMENT (not for synthesis)

54

Page 55: Training Manual for Fpga Programming Using Verilog Hdl Language

In a delayed assignment Δt time units pass before the statement is executed and the left-hand assignment is made. With intra-assignment delay, the right side is evaluated immediately but there is a delay of Δt before the result is place in the left hand assignment. Delays are not supported by synthesis tools.

Syntax for Procedural Assignmentvariable = expressionDelayed assignment#Δt variable = expression;Intra-assignment delayvariable = #Δt expression;

2.10.3 BLOCKING ASSIGNMENTSProcedural (blocking) assignments (=) are done sequentially in the order the statements are written. A second assignment is not started until the preceding one is complete. Syntaxvariable = expression;variable = #Δt expression;grab inputs now, deliver ans. later.#Δt variable = expression;grab inputs later, deliver ans. later

Example: For simulationinitialbegina=1; b=2; c=3;#5 a = b + c; // wait for 5 units, and execute a= b + c =5.d = a; // Time continues from last line, d=5 = b+c at t=5.

2.10.4 NONBLOCKING (RTL) ASSIGNMENTS RTL (nonblocking) assignments (<=), which follow each other in the code, are started in parallel. The right hand side of nonblocking assignments is evaluated starting from the completion of the last blocking assignment or if none, the start of the procedure. The transfer to the left hand side is made according to the delays. An intra-assignment delay in a non-blocking statement will not delay the start of any subsequent statement blocking or non-blocking. However normal delays will are cumulative and will delay the output.

For synthesis One must not mix “<=” or “=” in the same procedure. “<=” best mimics what physical flip-flops do; use it for “always @ (posedge clk ..) type

procedures.

55

Page 56: Training Manual for Fpga Programming Using Verilog Hdl Language

“=” best corresponds to what c/c++ code would do; use it for combinational procedures.

Syntaxvariable <= expression;variable <= #Δt expression;#Δt variable <= expression;

Example: For simulationinitialbegin#3 b <= a; /* grab a at t=0 Deliver b at t=3.#6 x <= b + c; // grab b+c at t=0, wait and assign x at t=6.x is unaffected by b’s change. */

The following example shows interactions between blocking and non-blocking for simulation. Do not mix the two types in one procedure for synthesis.

Example: for simulation onlyinitial begina=1; b=2; c=3; x=4;#5 a = b + c; // wait for 5 units, then grab b,c and execute a=2+3.d = a; // Time continues from last line, d=5 = b+c at t=5.x <= #6 b + c; // grab b+c now at t=5, don’t stop, make x=5 at t=11.b <= #2 a; /* grab a at t=5 (end of last blocking statement).Deliver b=5 at t=7. Previous x is unaffected by b change. */y <= #1 b + c; // grab b+c at t=5, don’t stop, make y=5 at t=6.#3 z = b + c; // grab b+c at t=8 (#5+#3), make z=8 (b =5 at t=7 and c = 3) at t=8.w <= x // make w=4 at t=8. Starting at last blocking assignm.

2.10.5 PROCEDURAL ASSIGNMENT GROUPS

If a procedure block contains more than one statement, those statements must be enclosed withinSequential begin - end blockParallel fork - join block

When using begin-end, we can give name to that group. This is called named blocks.Example: "begin-end" and "fork - join"

56

Page 57: Training Manual for Fpga Programming Using Verilog Hdl Language

Begin: clk gets 0 after 1 time unit, reset gets 0 after 6 time units, enable after 11 time units, data after 13 units. All the statements are executed in sequentially.Fork: clk gets value after 1 time unit, reset after 5 time units, enable after 5 time units, data after 2 time units. All the statements are executed in parallel.

Sequential Statement GroupsThe begin - end keywords group several statements together and cause the statements to be evaluated in sequentially (one at a time). Any timing within the sequential groups is relative to the previous statement. Delays in the sequence accumulate (each delay is added to the previous delay). Block finishes after the last statement in the block.

Parallel Statement GroupsThe fork - join keywords group several statements together and cause the statements to be evaluated in parallel (all at the same time). Timing within parallel group is absolute to the beginning of the group. Block finishes after the last statement completes (Statement with high delay, it can be the first statement in the block).

2.10.6 CONTINUOUS ASSIGNMENT STATEMENTSContinuous assignment statements drive nets (wire data type). They represent structural connections. They can be used for modeling combinational logic. They are outside the procedural blocks (always and initial blocks). The left-hand side of a continuous assignment must be net data type.Syntax : assign # delay net = expression;Example: 1-bit Addermodule adder (a,b,sum,carry);input a, b;output sum, carry;assign #5 {carry,sum} = a+b;endmodule

57

Page 58: Training Manual for Fpga Programming Using Verilog Hdl Language

2.10.7 VARIOUS PROGRAMMING STATEMENTS USED IN VERILOG

ProgrammingStatem

ents

Usage Example

if

It executes the statement or statement_group if the condition evaluates as true. If we need more than one statement (i.e statement_group) then we need to use begin-end or a fork-join block. The condition here can be an expression or a single value. If the condition evaluates to ‘0’ or unknown then the condition is considered false, and if the condition evaluates to ‘1’ or more then the condition is considered true.

if (alu_func == 2’b00)aluout = a + b;else if (alu_func == 2’b01)aluout = a - b;else if (alu_func == 2’b10)aluout = a & b;else // alu_func == 2’b11aluout = a | b;

if (a == b) begin x = 1; ot = 4’b1111;end

if-elseIt executes the first statement or statement_group if the condition evaluates as true and executes the second statement or statement_group if the condition evaluates as false. The condition here can be an expression or a single value. If the condition evaluates to ‘0’ or unknown then the condition is considered false, and if the condition evaluates to ‘ 1’ or more then the condition is considered true.

58

Page 59: Training Manual for Fpga Programming Using Verilog Hdl Language

case

It compares the expression with each of the case_item’s and executes the statement or statement_group associated with the first matching case_item.It executes the default if none of the case_item’s match. Here the default case is optional.

case (alu_ctr)2’b00: aluout = a + b;2’b01: aluout = a - b;2’b10: aluout = a & b;default: aluout = 1’bx; /* Treated as don’t cares for minimum logic generation. */endcase

case (x, y, z)2’b00: aluout = a + b; /*case if x or y or z is 2’b00.*/2’b01: aluout = a - b;2’b10: aluout = a & b;default: aluout = a | b;endcase

casez

It is special version of case statement where ‘z’ and ‘?’ are treated as don’t cares. Similar to case statement it compares the expression with each of the case_item’s and executes the statement or statement_group associated with the first matching case_item. It executes the default if none of the case_item’s match. Here the default case is optional.

casez (d)3’b1??: b = 2’b11; /* b = 11 if d = 100 or 101 or 110 or 111 */3’b01?: b = 2’b10; // b = 10 if d = 010 or 011default: b = 2’b00;endcase

59

Page 60: Training Manual for Fpga Programming Using Verilog Hdl Language

casex

It is special version of case statement where ‘x’, ‘z’ and ‘?’ are treated as don’t cares. Similar to case statement it compares the expression with each of the case_item’s and executes the statement or statement_group associated with the first matching case_item. It executes the default if none of the case_item’s match. Here the default case is optional.

casex (a)2’b1x: msb = 1; // msb = 1 if a = 10 or a = 11/* If this were case(a) then only a=1x would match.*/default: msb = 0;endcase

forever

It is an infinite loop that continuously executes the statement or statement_group.

forever begin@(posedge clk); // or use a= #9 a+1;a = a + 1;end

repeat

Syntaxrepeat(expression)statement or statement _group

Like forever it is a loop that executes the statement or statement _group a fixed number of times based on the expression.

repeat (2) begin // after 50, a = 00,#50 a = 2’b00; // after 100, a = 01,#50 a = 2’b01; // after 150, a = 00,end// after 200, a = 01

while

Syntaxwhile(condition)statement or statement_group

It executes the statement or statement_group as long as the condition evaluates as true.

while (!overflow) begin@(posedge clk);a = a + 1;end

for Syntaxfor(initial_value; condition; step)statement or statement_group

The for loop here uses three expressions separated by semicolons to control the loop. The first expression (initial_value) is executed

for (j = 0; j <= 7; j = j + 1)beginc[j] = a[j] & b[j];d[j] = a[j] | b[j];end

60

Page 61: Training Manual for Fpga Programming Using Verilog Hdl Language

once before entering the loop the first time. The second expression (condition) is evaluated to determine if the contents of the loop (i.e statement or statement_group) should be executed. If the loop condition expression is true, the loop is entered. The final expression (step) is evaluated at the end of the loop.

disable

Syntaxdisable group_name;

It discontinues execution of a named group of statements.

begin: accumulateforeverbegin@(posedge clk);a = a + 1;if (a == 2’b0111) disable accumulate;endend

3. FUNCTION and TASK

Verilog provides Functions and Tasks to allow the behavioral description of a module to be broken into more manageable parts allowing better readability and manageability. Functions and Tasks are useful for several reasons which are, they allow often used behavioral sequences to be written once and called when needed, they allow for a cleaner writing style and finally they allow data to be hidden from other parts of the design.

3.1 FUNCTIONFunctions are defined in the module in which they are used. It is possible to define function in separate file and use compile directive 'include to include the function in the file which instantiates the function. Function can call other functions, but cannot call task.The following are some of the general rules for functions:

Functions must contain at least one input argument and cannot drive more than one output.

Functions cannot contain an inout or output declaration. Functions cannot contain time controlled statements (#, @, wait), i.e., it cannot contain

delays . Function cannot include timing delays, like posedge, negedge, # delay. Which means that

function should be executed in "zero" time delay. Functions must contain a statement that assigns the return value to the implicit function

name register. The variables declared within the function are local to that function. The order of

declaration within the function defines how the variables passed to the function by the caller are used.

61

Page 62: Training Manual for Fpga Programming Using Verilog Hdl Language

Syntax Function begins with keyword function and ends with keyword endfunction. Inputs are declared after the keyword function.

function [msb:lsb] function_name;input [msb:lsb] input_arguments;reg [msb:lsb] reg_variable_list;parameter [msb:lsb] parameter_list;integer [msb:lsb] integer_list;... statements ...endfunction

Examplefunction [7:0] my_func; // function return 8-bit valueinput [7:0] i;reg [3:0] temp;integer n;temp= i[7:4] | ( i[3:0]);my_func = {temp, i[3:0]};endfunction

Example: Simple Functionfunction myfunction;input a, b, c, d;beginmyfunction = ((a+b) + (c-d));endendfunction

Calling a FunctionLet’s assume that function in above example is stored in a file called myfunction.v. Advantage of coding function in separate file is that, it can be used in multiple module's.module func_test(a, b, c, d, e, f);input a, b, c, d, e ;output f;wire f;`include "myfunction.v"assign f = (myfunction (a,b,c,d)) ? e :0;endmodule

3.2 TASK

62

Page 63: Training Manual for Fpga Programming Using Verilog Hdl Language

Tasks are used in all programming languages, generally known as procedures or sub routines. A task is similar to a function, but unlike a function it has any number input and output ports. Therefore tasks do not return values. Included in the main body of code tasks can be called many times, reducing code repetition. Tasks are defined in the module in which they are used. It is possible to define task in separate file and use compile directive 'include to include the task in the file which instantiates the task. Task can include timing delays, like posedge, negedge, # delay. The variables declared within the task are local to that task. The order of declaration within the task defines how the variables passed to the task by the caller are used. Task can call another task or function. Syntax

Task begins with keyword task and end's with keyword endtask Input and output are declared after the keyword task. Local variables are declared after input and output declaration.

task task_name;input [msb:lsb] input_port_list;output [msb:lsb] output_port_list;reg [msb:lsb] reg_variable_list;parameter [msb:lsb] parameter_list;integer [msb:lsb] integer_list;... statements ...endtaskExample : Simple Tasktask convert;input [7:0] temp_in;output [7:0] temp_out;begintemp_out = (9/5) *( temp_in + 32);endendtask

Example : Task using Global Variablestask convert;begintemp_out = (9/5) *( temp_in + 32);endendtask

Calling a Task

63

Page 64: Training Manual for Fpga Programming Using Verilog Hdl Language

Let’s assume that task in example “Simple Task” is stored in a file called mytask.v. Advantage of coding task in separate file is that, it can be used in multiple modules.module temp_cal (temp_a, temp_b, temp_c, temp_d);input [7:0] temp_a, temp_c;output [7:0] temp_b, temp_d;reg [7:0] temp_b, temp_d;`include "mytask.v"always @ (temp_a)convert (temp_a, temp_b);always @ (temp_c)convert (temp_c, temp_d);endmodule

4. MODELING FINITE STATE MACHINE (FSM)

State machine or FSM are the heart of any digital design. There are two types of state machines classified by the types of outputs generated from each. The first is the Moore State Machine where the outputs are only a function of the present state, the second is the Mealy State Machine where one or more of the outputs are a function of the present state and one or more of the inputs.

Mealy Model

Moore Model

Modeling State machines.

64

Page 65: Training Manual for Fpga Programming Using Verilog Hdl Language

One thing that needs to be kept in mind when coding FSM is that, combinational logic and sequence logic should be in two different always blocks. In the above two figures, next state logic is always the combinational logic. State Registers and Output logic are sequential logic. It is very important that any asynchronous signal to the next state logic should be synchronized before feeding to FSM. Always try to keep FSM in separate Verilog file.Using constants declaration like parameter or `define to define states of the FSM, this makes code more readable and easy to manage.

State Diagram.

Verilog Code

FSM code should have three sections, Encoding style. Combinational part. Sequential part.

Encoding Style

One Hot Encodingparameter [1:0] IDLE = 3'b001,GNT0 = 3'b010,GNT1 = 3'b100;

Binary Encodingparameter [1:0] IDLE = 2'b00,GNT0 = 2'b01,GNT1 = 2'b10;

Combinational Section

65

Page 66: Training Manual for Fpga Programming Using Verilog Hdl Language

This section can be modeled using function, assign statement or using always block with case statement. For time being let’s see always block version.

next_state = 3'b000case(state)IDLE : if (req_0 == 1'b1)next_state = GNT0;else if (req_1 == 1'b1)next_state= GNT1;elsenext_state = IDLE;GNT0 : if (req_0 == 1'b1)next_state = GNT0;elsenext_state = IDLE;GNT1 : if (req_1 == 1'b1) beginnext_state = GNT1;elsenext_state =1 IDLE;default : next_state = IDLEendcaseend

Sequential SectionThis section has be modeled using only edge sensitive logic such as always block with posedge or negedge of clock.

always @ (posedge clock)begin : OUTPUT_LOGIC

if (reset == 1'b1) begin

gnt_0 <= #1 1'b0;gnt_1 <= #1 1'b0;state <= #1 IDLE;

endelse begin

state <= #1 next_state;case(state)IDLE :begin

66

Page 67: Training Manual for Fpga Programming Using Verilog Hdl Language

gnt_0 <= #1 1'b0;gnt_1 <= #1 1'b0;

endGNT0 : begin

gnt_0 <= #1 1'b1;gnt_1 <= #1 1'b0;

endGNT1 : begin

gnt_0 <= #1 1'b0;gnt_1 <= #1 1'b1;

enddefault : begin

gnt_0 <= #1 1'b0;gnt_1 <= #1 1'b0;

endendcase

endend

5. WRITING TESTBENCHES

Writing a testbench is as complex as writing the RTL code itself. These days ASICs are getting more and more complex and thus verifying these complex ASIC has become a challenge. Typically 60-70% of time needed for any ASIC is spent on verification/validation/testing. For writing testbench it is important to have the design specification of "design under test" or simply DUT. Specs need to be understood clearly and test plan is made, which basically documents the test bench architecture and the test scenarios ( test cases) in detail.

Example : CounterLet’s assume that we have to verify a simple 4-bit up counter, which increments its count when ever enable is high and resets to zero, when reset is asserted high. Reset is synchronous to clock.Code for Countermodule counter (clk, reset, enable, count);input clk, reset, enable;output [3:0] count;reg [3:0] count;always @ (posedge clk)if (reset == 1'b1)

67

Page 68: Training Manual for Fpga Programming Using Verilog Hdl Language

count <= 0;else if ( enable == 1'b1)count <= count + 1;endmoduleTest PlanWe will write self checking test bench, but we will do this in steps to help you understand the concept of writing automated test benches. Our testbench environment will look something like shown in below figure.

DUT is instantiated in testbench, and testbench will contain a clock generator, reset generator, enable logic generator, compare logic, which basically calculate the expected count value of counter and compare the output of counter with calculated value.Test Cases

Reset Test : We can start with reset deasserted, followed by asserting reset for few clock ticks and deasserting the reset, See if counter sets its output to zero.

Enable Test : Assert/deassert enable after reset is applied. Random Assert/deassert of enable and reset.

Writing TestBenchFirst step of any testbench creation is to create a dummy template which basically declares inputs to DUT as reg and outputs from DUT as wire, instantiate the DUT as shown in code below. Note: there is no port list for the test bench.Test Benchmodule counter_tb;reg clk, reset, enable;wire [3:0] count;counter U0 (.clk (clk),.reset (reset),.enable (enable),

68

Page 69: Training Manual for Fpga Programming Using Verilog Hdl Language

.count (count));endmodule

Next step would be to add clock generator logic. Before we add clock generator we need to drive all the inputs to DUT to some known state as shown in code below.Test Bench with Clock genmodule counter_tb;reg clk, reset, enable;wire [3:0] count;counter U0 (.clk (clk),.reset (reset),.enable (enable),.count (count));initialbeginclk = 0;reset = 0;enable = 0;endalways#5 clk = !clk;endmodule

Initial block in verilog is executed only once, thus simulator sets the value of clk, reset and enable to 0, which by looking at the counter code (of course you will be refering to the the DUT specs) could be found that driving 0 makes all this signals disabled. There are many ways to generate clock, one could use forever loop inside an initial block as an alternate to above code. At this point, you would like test if the testbench is generating the clock correctly. You will see that simulator does not come out, or print anything on screen or does it dump any waveform. Thus we need to add support for all the above as shown in code below.

Test Bench continues...module counter_tb;reg clk, reset, enable;wire [3:0] count;counter U0 (

69

Page 70: Training Manual for Fpga Programming Using Verilog Hdl Language

.clk (clk),

.reset (reset),

.enable (enable),

.count (count));initialbeginclk = 0;reset = 0;enable = 0;endalways#5 clk = !clk;initialbegin$dumpfile ("counter.vcd");$dumpvars;endinitialbegin$display("\t\ttime,\tclk,\treset,\tenable,\tcount");$monitor("%d,\t%b,\t%b,\t%b,\t%d",$time, clk, reset, enable, count);endinitial#100 $finish;//Rest of testbench code after this lineendmodule

$dumpfile is used for specifying the file that simulator will use to store the waveform, that can be used later to view using waveform viewer. $dumpvars basically instructs the Verilog compiler to start dumping all the signals to "counter.vcd".$display is used for printing text or variables to stdout (screen), \t is for inserting tab. Syntax is same as printf. Second line $monitor is bit different, $monitor keeps track of changes to the variables that are in the list (clk, reset, enable, count). Whenever anyone of them changes, it prints their value, in the respective radix specified.$finish is used for terminating simulation after #100 time units (note, all the initial, always blocks start execution at time 0).Adding Reset LogicOnce we have the basic logic to allow us to see what our testbench is doing, we can next add the reset logic, If we look at the testcases, we see that we had added a constraint that it should be possible to activate reset anytime during simulation. To achieve this we have many approaches,

70

Page 71: Training Manual for Fpga Programming Using Verilog Hdl Language

but we will follow something that will go long way. There is something called 'events' in Verilog, events can be triggered, and also monitored to see, if an event has occurred. Lets code our reset logic in such a way that it waits for the trigger event "reset_trigger" to happen, when this event happens, reset logic asserts reset at negative edge of clock and de-asserts on next negative edge as shown in code below. Also after de-asserting the reset, reset logic triggers another event called "reset_done_trigger". This trigger event can then be used at somewhere else in test bench to sync up.

Code of reset logicevent reset_trigger;event reset_done_trigger;initial beginforever begin@ (reset_trigger);@ (negedge clk);reset = 1;@ (negedge clk);reset = 0;-> reset_done_trigger;endend

Adding test case logicMoving forward, let’s add logic to generate the test cases, ok we have three testcases as in the first part of this tutorial. Lets list them again.

Reset Test : We can start with reset deasserted, followed by asserting reset for few clock ticks and deasserting the reset, See if counter sets its output to zero.

Enable Test : Assert/deassert enable after reset is applied. Random Assert/deassert of enable and reset.

Test Case # 1 : Asserting/ Deasserting resetIn this test case, we will just trigger the event reset_trigger after 10 simulation units.initialbegin: TEST_CASE#10 -> reset_trigger;endTest Case # 2 : Asserting/ Deasserting enable after reset is applied.In this test case, we will trigger the reset logic and wait for the reset logic tocomplete its operation, before we start driving enable signal to logic 1.initialbegin: TEST_CASE

71

Page 72: Training Manual for Fpga Programming Using Verilog Hdl Language

#10 -> reset_trigger;@ (reset_done_trigger);@ (negedge clk);enable = 1;repeat (10) begin@ (negedge clk);endenable = 0;end

Test Case # 3 : Asserting/Deasserting enable and reset randomly.In this testcase we assert the reset, and then randomly drive values on to enable and reset signal.initialbegin : TEST_CASE#10 -> reset_trigger;@ (reset_done_trigger);fork beginrepeat (10) begin@ (negedge clk);enable = $random;repeat (10) begin@ (negedge clk);reset = $random;endendend

Well you might ask, are all this three test case exist in same file, well the answer is no. If we try to have all three test cases on one file, then we end up having race condition due to three initial blocks driving reset and enable signal. So normally, once test bench coding is done, test cases are coded separately and included in testbench as `include directive as shown below. If you look closely all the three test cases, you will find that, even through test case execution is not complete, simulation terminates. To have better control, what we can do is, add a event like "terminate_sim" and execute $finish only when this event is triggered. We can trigger this event at the end of test case execution. The code for $finish now could look as below.event terminate_sim;initial begin@ (terminate_sim);#5 $finish;End

72

Page 73: Training Manual for Fpga Programming Using Verilog Hdl Language

and the modified test case #2 would like.initialbegin: TEST_CASE#10 -> reset_trigger;@ (reset_done_trigger);@ (negedge clk);enable = 1;repeat (10) begin@ (negedge clk);endenable = 0;#5 -> terminate_sim;end

BASICS OF FPGA

A Hard-Coded World – ASICASIC stands for Application Specific Integrated Circuit. ASIC design flow takes huge amount of time and hence costly. It is an IC which is designed only for a particular application; i.e., one time programmability. For Example Pentium chips (P I, P II) are ASIC chips. ASIC involves huge rework cost. Aim should be for right output from first time even in re-work cycle.

A Re-programmability World

73

Page 74: Training Manual for Fpga Programming Using Verilog Hdl Language

Rehearse your act as many times till perfection. Very less turnaround time involved. Can afford to commit initial mistakes. Proto-type complex systems before going to a hard coded world.

Emulation platform can be developed using FPGA’s to validate designs at system level. Designs can be downloaded into an FPGA based system to validate the functionality. If any defects are encountered during the validation process the design can be fixed and verified using the same platform.

What Re-programmability means to H/W Same piece of hardware.

Different types of functionality. Matter of loading a new bitmap.

Easy design changes. Faster development cycle. Suitable for low volume production.

The same piece of hardware can be used multiple times to validate either new designs or modified (bug fixes, feature enhancement) designs. The development cycle is faster as this involves only the design and verification cycle followed by synthesis and FPGA P&R instead of the entire backend flow and fabrication of the hardware.

NOTE: ASIC is cost effective for mass production & FPGA is effective for low volume production.

So What’s an FPGA? Field Programmable Gate Array. Gate Array – a custum VLSI circuit consisting of huge number of unconnected gates. Circuit function determined at the field by the user. Re-programmable. Pre tested for manufacturing defects. It is:

An ASIC for FPGA manufacturer. An FPGA for the user.

Comes as chip ready to operate.Field Programmable means that the FPGA’s function is defined by a user’s program rather than by the manufacturer of the device. A typical integrated circuit performs a particular function defined at the time of manufacturer. In contrast, the FPGA’s function is defined by a program written by someone other than the device manufacturer. This user programmability gives the user access to complex integrated designs without the high engineering costs associated with application specific integrated circuit.

74

Page 75: Training Manual for Fpga Programming Using Verilog Hdl Language

The FPGA is an integrated circuit that contains many identical logic cells that can be viewed as standard components. The individual cells are interconnected by a matrix of wires and programmable switches. A user’s design is implemented by specifying the simple logic function for each cell and selectively closing the switches in the interconnected matrix. The array of logic cells and interconnects from a fabric of basic building blocks for logic circuits. Complex designs are created by combining these basic blocks to create the desired circuit.

FPGA Devices

Xilinx Devices Vertex Series

o Vertex-5 family, Vertex-4 family, Vertex II family, Vertex family

o High cost, Highly efficient

Spartan Serieso Spartan-3A, 3E, 3 family, Spartan IIE, II family, Spartan family

o Low cost, Low efficient

Altera Devices Stratix Series

o Stratix III family, Stratix II (GX) family, Stratix (GX) family

Cyclone Serieso Cyclone III family, Cyclone II family, Cyclone family

75