Cover

CONTENTS

Preface

Acknowledgments

PART I BASIC DIGITAL CIRCUITS

1 Gate-level combinational circuit

1.1 Introduction

1.2 General description

1.3 Basic lexical elements and data types

1.4 Data types

1.5 Program skeleton

1.6 Structural description

1.7 Testbench

1.8 Bibliographic notes

1.9 Suggested experiments

2 Overview of FPGA and EDA software

2.1 Introduction

2.2 FPGA

2.3 Overview of the Digilent S3 board

2.4 Development flow

2.5 Overview of the Xilinx ISE project navigator

2.6 Short tutorial on ISE project navigator

2.7 Short tutorial on the ModelSim HDL simulator

2.8 Bibliographic notes

2.9 Suggested experiments

3 RT-level combinational circuit

3.1 Introduction

3.2 Operators

3.3 Always block for a combinational circuit

3.4 If statement

3.5 Case statement

3.6 Routing structure of conditional control constructs

3.7 General coding guidelines for an always block

3.8 Parameter and constant

3.9 Design examples

3.10 Bibliographic notes

3.11 Suggested experiments

4 Regular Sequential Circuit

4.1 Introduction

4.2 HDL code of the FF and register

4.3 Simple design examples

4.4 Testbench for sequential circuits

4.5 Case study

4.6 Bibliographic notes

4.7 Suggested experiments

5 FSM

5.1 Introduction

5.2 FSM code development

5.3 Design examples

5.4 Bibliographic notes

5.5 Suggested experiments

6 FSMD

6.1 Introduction

6.2 Code development of an FSMD

6.3 Design examples

6.4 Bibliographic notes

6.5 Suggested experiments

7 Selected Topics of Verilog

7.1 Blocking versus nonblocking assignment

7.2 Alternative coding style for sequential circuit

7.3 Use of the signed data type

7.4 Use of function in synthesis

7.5 Additional constructs for testbench development

7.6 Bibliographic notes

7.7 Suggested experiments

PART II I/O MODULES

8 UART

8.1 Introduction

8.2 UART receiving subsystem

8.3 UART transmitting subsystem

8.4 Overall UART system

8.5 Customizing a UART

8.6 Bibliographic notes

8.7 Suggested experiments

9 PS2 Keyboard

9.1 Introduction

9.2 PS2 receiving subsystem

9.3 PS2 keyboard scan code

9.4 PS2 keyboard interface circuit

9.5 Bibliographic notes

9.6 Suggested experiments

10 PS2 Mouse

10.1 Introduction

10.2 PS2 mouse protocol

10.3 PS2 transmitting subsystem

10.4 Bidirectional PS2 interface

10.5 PS2 mouse interface

10.6 Bibliographic notes

10.7 Suggested experiments

11 External SRAM

11.1 Introduction

11.2 Specification of the IS61LV25616AL SRAM

11.3 Basic memory controller

11.4 A safe design

11.5 More aggressive design

11.6 Bibliographic notes

11.7 Suggested experiments

12 Xilinx Spartan-3 Specific Memory

12.1 Introduction

12.2 Embedded memory of Spartan-3 device

12.3 Method to incorporate memory modules

12.4 HDL templates for memory inference

12.5 Bibliographic notes

12.6 Suggested experiments

13 VGA controller I: graphic

13.1 Introduction

13.2 VGA synchronization

13.3 Overview of the pixel generation circuit

13.4 Graphic generation with an object-mapped scheme

13.5 Graphic generation with a bit-mapped scheme

13.6 Bibliographic notes

13.7 Suggested experiments

14 VGA controller II: text

14.1 Introduction

14.2 Text generation

14.3 Full-screen text display

14.4 The complete pong game

14.5 Bibliographic notes

14.6 Suggested experiments

PART III PICOBLAZE MICROCONTROLLER XILINX SPECIFIC

15 PicoBlaze Overview

15.1 Introduction

15.2 Customized hardware and customized software

15.3 Overview of PicoBlaze

15.4 Development flow

15.5 Instruction set

15.6 Assembler directives

15.7 Bibliographic notes

16 PicoBlaze Assembly Code Development

16.1 Introduction

16.2 Useful code segments

16.3 Subroutine development

16.4 Program development

16.5 Processing of the assembly code

16.6 Syntheses with PicoBlaze

16.7 Bibliographic notes

16.8 Suggested experiments

17 PicoBlaze I/O Interface

17.1 Introduction

17.2 Output port

17.3 Input port

17.4 Square program with a switch and seven-segment LED display interface

17.5 Square program with a combinational multiplier and UART console

17.6 Bibliographic notes

17.7 Suggested experiments

18 PicoBlaze Interrupt Interface

18.1 Introduction

18.2 Interrupt handling in PicoBlaze

18.3 External interface

18.4 Software development considerations

18.5 Design example

18.6 Bibliographic notes

18.7 Suggested experiments

Appendix A: Sample Verilog templates

A.1 Numbers and operators

A.2 General Verilog constructs

A.3 Routing with conditional operator and if and case statements

A.4 Combinational circuit using an always block

A.5 Memory Components

A.6 Regular sequential circuits

A.7 FSM

A.8 FSMD

A.9 S3 board constraint file (s3. ucf)

References

Topic Index

image

In memory of my father, Chia Chi Chu

PREFACE

HDL (hardware description language) and FPGA (field-programmable gate array) devices allow designers to quickly develop and simulate a sophisticated digital circuit, realize it on a prototyping device, and verify operation of the physical implementation. As these technologies mature, they have become mainstream practice. We can now use a PC and an inexpensive FPGA prototyping board to construct a complex and sophisticated digital system. This book uses a “learning by doing” approach and illustrates the FPGA and HDL development and design process by a series of examples. A wide range of examples is included, from a simple gate-level circuit to an embedded system with an 8-bit soft-core microcontroller and customized I/O peripherals. All examples can be synthesized and physically tested on a prototyping board.

Focus and audience

Focus   The main focus of this book is on the effective derivation of hardware, not the syntax of HDL. Instead of explaining every language construct, the book focuses on a small synthesizable subset and uses about a dozen code templates to provide the skeletons of various types of circuits. These templates are general and can easily be integrated to construct a large, complex system. Although this approach limits the “freedom” of syntactic expression, it will not prevent us from developing innovative hardware architecture. Because of the generality and flexibility of HDL, the same circuit can usually be described by a wide variety of language constructs and coding styles. Many of these codes are intended for modeling. They may lead to unnecessarily complex hardware implementation and sometimes cannot be synthesized at all. The template approach actually forces us to think more about hardware and develop a good coding practice for synthesis. Since we are more interested in hardware, it is more beneficial to spend time on developing 10 different hardware architectures with the same code template rather than describing the same circuit with 10 different versions of codes.

There are two popular HDLs, VHDL and Verilog. Both languages are used widely and are IEEE standards. This book uses Verilog, and a separate book with a similar title uses VHDL. Despite the drastic syntactic differences in the two languages, their capabilities are very similar, particularly for our purposes. After we comprehend the design practice and coding methodology in one language, learning the other language is rather straightforward.

Although the book is intended for beginning designers, the examples follow strict design guidelines and prepare readers for future endeavors. The coding and design practice is “forward compatible,” which means that:

• The same practice can be applied to large design in the future.

• The same practice can aid other system development tasks, including simulation, timing analysis, verification, and testing.

• The same practice can be applied to ASIC technology and different types of FPGA devices.

• The code can be accepted by synthesis software from different vendors.

In summary, the book is a hands-on, hardware-centric text that involves minimal HDL overhead and follows good design and coding practice to achieve maximal forward comparability.

Audience and perquisites   The book contains three major parts: basic digital circuits, peripheral modules, and embedded microcontroller. The intended audience is students in an introductory or advanced digital system design course as well as practicing engineers who wish to learn FPGA- and HDL-based development. For the materials in the first two parts, readers need to have a basic knowledge of digital systems, usually a required course in electrical engineering and computer engineering curricula. For the materials in the third part, prior exposure to assembly language programming will be helpful.

Logistics

Although a major goal of this book is to teach readers to develop software-independent and device-neutral HDL codes, we have to choose a software package and a prototyping board to synthesize and implement the design examples. The synthesis software and FPGA devices from Xilinx, a leading manufacture in this area, are used in the book.

Software   The synthesis software used in the book is the Web version of the Xilinx ISE package. The functionality of this version is similar to that of the full version but supports only a limited number of devices. Most introductory development boards use FPGA devices from the inexpensive Spartan-3 family. Since the Web version supports the Spartan-3 device, it fits our needs. The simulation software used in the book is the starter version of Mentor Graphics’ ModelSim XE III package. It is a customized edition of ModelSim. Both software packages are free and can be downloaded from Xilinx’s Web site.

FPGA prototyping board   This book is prepared to be used with several entry-level FPGA prototyping boards manufactured by Digilent Inc., including the Spartan-3 Starter, Nexys-2, and Basys boards, all of which contain a Spartan-3/3E FPGA device and have similar I/O peripherals. The design examples in the book are based on the Spartan-3 Starter board (or simply the S3 board), but most of them can be used directly on other boards as well. The applicability of the HDL codes is summarized below.

Spartan-3 Starter (S3) board. The S3 board contains all the peripherals and no additional accessory module is needed. All HDL codes and discussions can be applied to this board directly.

Nexys-2 board. The Nexys-2 board is a newer board, which contains a larger FPGA device and a larger memory chip. Its peripherals are similar to those on the S3 board. There are two differences. First, the “color depth” of its VGA interface is expanded from 3 bits to 8 bits. Thus, the output of the VGA interface circuits discussed in Chapters 13 and 14 needs to be modified accordingly. Second, the Nexys-2 board contains a more sophisticated external memory device. Although the device can be configured as an asynchronous SRAM, the timing characteristics are different from those of the S3 board’s memory device, and thus the HDL codes for the memory controller in Chapter 11 cannot be used directly. However, the same design principle can be applied to construct a new controller.

Basys board. The Basys board is a simpler board. It lacks the RS-232 connector. To implement the UART module and the serial interface discussed in Chapter 8, we need Digilent’s RS-232 converter peripheral module. The Basys board has no external memory devices, and thus the discussion of the memory controller in Chapter 11 is not applicable.

Other FPGA boards. Most peripherals discussed in this book are de facto industrial standards, and the corresponding HDL codes can be used as long as a board provides proper analog interface circuits and connectors. Except for the Xilinx-specific portions, the codes can be applied to the boards based on the FPGA devices from other manufacturers as well.

PC Accessories   The design examples include interfaces to several PC peripheral devices. A keyboard, a mouse, and a VGA monitor are required for the respective modules, and a “straight-through” serial cable (the most commonly used type) is required for the UART module. These accessories are widely available and can probably be obtained from an old PC.

Book organization

The book is divided into three major parts. Part I introduces the elementary HDL constructs and their hardware counterparts, and demonstrates the construction of a basic digital circuit with these constructs. It consists of six chapters:

• Chapter 1 describes the skeleton of an HDL program, basic language syntax, and logical operators. Gate-level combinational circuits are derived with these language constructs.

• Chapter 2 provides an overview of an FPGA device, prototyping board, and development flow. The development process is demonstrated by a tutorial on Xilinx ISE synthesis software and a tutorial on Mentor Graphics ModelSim simulation software.

• Chapter 3 introduces HDL’s relational and arithmetic operators and routing constructs. These correspond to medium-sized components, such as comparators, adders, and multiplexers. Module-level combinational circuits are derived with these language constructs.

• Chapter 4 covers the codes for memory elements and the construction of “regular” sequential circuits, such as counters and shift registers, in which the state transitions exhibit a regular pattern.

• Chapter 5 discusses the construction of a finite state machine (FSM), which is a sequential circuit whose state transitions do not exhibit a simple, regular pattern.

• Chapter 6 presents the construction of an FSM with data path (FSMD). The FSMD is used to implement register transfer (RT) methodology, in which the system operation is described by data transfers and manipulations among registers.

• Chapter 7 discusses several more advanced topics on language constructs and coding techniques and introduces the development of more sophisticated testbenches. This chapter can be skipped without affecting the remaining chapters.

Part II applies the techniques from Part I to design an array of peripheral modules for the prototyping board. Each chapter covers the development, implementation, and verification of an individual peripheral. These modules can be incorporated to a larger project. Part II consists of seven chapters:

• Chapter 8 discusses the design of a universal asynchronous receiver and transmitter (UART), which provides a serial link to receive and transmit data via the prototyping board’s RS-232 port.

• Chapter 9 covers the design of a keyboard interface, which reads scan code from a keyboard. The keyboard is connected via the prototyping board’s PS2 port.

• Chapter 10 covers the design of a mouse interface, which obtains the button and movement information from a mouse. The mouse is also connected via the prototyping board’s PS2 port.

• Chapter 11 discusses the implementation and timing issues of a memory controller. The controller is used to read data from and write data to the two static random access memory (SRAM) devices on the S3 board.

• Chapter 12 discusses the inference and application of Spartan-3 device-specific components. The focus is on the FPGA’s internal memory blocks.

• Chapter 13 presents the design and implementation of a video controller. The discussion covers the generation of video synchronization signals and shows the construction of simple bit- and object-mapped graphical interfaces. The monitor is connected to the prototyping board’s VGA port.

• Chapter 14 continues development of the video controller. The discussion illustrates the construction of text interface and general tile-mapped scheme.

Part III introduces an FPGA-based soft-core microcontroller, known as PicoBlaze, and demonstrates the integration of a general-purpose processor and customized circuit. It includes four chapters:

• Chapter 15 provides an overview of the organization and instruction set of PicoBlaze.

• Chapter 16 introduces the basic assembly programming and provides an overview of the development process.

• Chapter 17 discusses PicoBlaze’s I/O feature and illustrates the procedure to derive customized circuits to interface other I/O peripherals.

• Chapter 18 discusses PicoBlaze’s interrupt capability and demonstrates the construction of a customized interrupt-handling circuit.

In addition to regular chapters, the appendix summarizes and lists all code templates.

Special marksxilinx specific We use two special paragraph marks in the book: one for a Xilinx-specific feature and one for Verilog-1995 constructs. While the examples described in the book are implemented on a Xilinx-based prototyping board and the codes are synthesized by Xilinx ISE software, we try to make the HDL codes as device independent and software neutral as possible. Most discussions and codes can be applied to different target devices and different synthesis software as well. However, certain codes or device features are unique to Xilinx ISE software or Spartan-3 FPGA devices. We use the Xilinx specific superscript, as in the heading of this section, to indicate that the discussion in the corresponding section or chapter is unique to Xilinx.

Similarly, we use marginal notes, as shown on the outer edge, to indicate that the discussion in a paragraph is unique to Xilinx. This note indicates that the code or design is no longer portable and needs to be revised when a different software package or target device is used.

The Verilog language was first ratified in 1995 (referred to as Verilog-1995) and then revised in 2001 (referred to as Verilog-2001). Many useful enhancements are added in the revised version. We use Verilog-2001 in this book. If a language construct differs in the two versions, we describe the old syntax briefly in a separate paragraph and use a marginal note, as shown on the outer edge, for this type of discussion. It indicates “for your information” and the materials are included to help readers understand the older Verilog codes.

Instructional use

The book can be a good companion text for an introductory digital systems course or an advanced project-oriented course. In an introductory digital systems course, the book supplies the lab portion of the curriculum. The chapters in Part I basically follow the sequence of a typical curriculum and can be presented along with regular lectures. One or two peripheral modules can be selected as case studies, and corresponding experiments can be used as term projects.

In an advanced project-oriented course, the book provides a base for independent projects. The materials in Part I should be treated as an overview or refresher, which provides a general background on HDL, synthesis, and FPGA boards. Some modules in Part II can be used to demonstrate the design of more complex circuits. These modules can also be considered as building blocks (i.e., IPs) or subsystems to be integrated into final projects. The PicoBlaze microcontroller discussed in Part III can be used as a general-purpose processor if an embedded-system type of project is desired.

Companion Web site

An accompanying Web site (http://academic.csuohio.edu/chu_p/rtl) provides additional information, including the following materials:

• Errata

• Code templates

• HDL code listing and relevant files

• Links to synthesis and simulation software

• Links to referenced materials

• Additional project ideas

Errata   The book is self-prepared, which means that the author has produced all aspects of the text, including illustrations, tables, code listings, indexing, and formatting. As errors are always bound to happen, the accompanying Web site provides an updated errata sheet and a place to report errors.

P. P. CHU

Cleveland, Ohio
January 2008

ACKNOWLEDGMENTS

The author would like to express his gratitude to Professor George L. Kramerich for his encouragement and help.

The author also thanks John Wiley & Sons, Inc. for giving permission to use Figures 3.1, 3.2,4.2,4.10,4.11, 6.5, and 7.2 from my text RTL Hardware Design Using VHDL: Coding for Efficiency, Portability, and Scalability, and Xilinx, Inc. for giving permission to use Figures 2.3 and 9.3 from the Spartan-3 Starter Kit Board User Guide.

All trademarks used or referred to in this book are the property of their respective owners.

P. P. Chu

PART I

BASIC DIGITAL CIRCUITS

CHAPTER 1

GATE-LEVEL COMBINATIONAL CIRCUIT

1.1 INTRODUCTION

Verilog is a hardware description language. It was developed in the mid-1980s and later transferred to the IEEE (Institute of Electrical and Electronics Engineers). The language is formally defined by IEEE Standard 1364. The standard was ratified in 1995 (referred to as Verilog-1995) and revised in 2001 (referred to as Verilog-2001). Many useful enhancements are added in the revised version. We use Verilog-2001 in this book.

Verilog is intended for describing and modeling a digital system at various levels and is an extremely complex language. The focus of this book is on hardware design rather than the language. Instead of covering every aspect of Verilog, we introduce the key Verilog synthesis constructs by examining a collection of examples. Several advanced topics are examined further in Chapter 7 and detailed Verilog coverage may be explored through the sources listed in the bibliographic section at the end of the chapter.

Although the syntax of Verilog is somewhat like that of the C language, its semantics (i.e., “meaning”) is based on concurrent hardware operation and is totally different from the sequential execution of C. The subtlety of some language constructs and certain inherent non-deterministic behavior of Verilog can lead to difficult-to-detect errors and introduce a discrepancy between simulation and synthesis. The coding of this book follows a “better-safe-than-buggy” philosophy. Instead of writing quick and short codes, the focus is on style and constructs that are clear and synthesizable and can accurately describe the desired hardware.

Table 1.1 Truth table of 1-bit equality comparator

input

output

i0 il

eq

00

1

01

0

10

0

11

1

In this chapter, we use a simple comparator to illustrate the skeleton of a Verilog program. The description uses only logic operators and represents a gate-level combinational circuit, which is composed of simple logic gates. In Chapter 3, we cover the remaining Verilog operators and constructs and examine the register-transfer-level combinational circuits, which are composed of intermediate-sized components, such as adders, comparators, and multiplexers.

1.2 GENERAL DESCRIPTION

Consider a 1-bit equality comparator with two inputs, i0 and i1, and an output, eq. The eq signal is asserted when i0 and i1 are equal. The truth table of this circuit is shown in Table 1.1.

Assume that we want to use basic logic gates, which include not, and, or, and xor cells, to implement the circuit. One way to describe the circuit is to use a sum-of-products format. The logic expression is

c01e001

One possible Verilog code is shown in Listing 1.1. We examine the language constructs and statements of this code in the following subsections.

Listing 1.1 Gate-level implementation of a 1-bit comparator

c01p001

Figure 1.1 Graphical representation of a comparator program.

c01f001

The best way to understand an HDL (hardware description language) program is to think in terms of hardware circuits. This program consists of three portions. The I/O port portion describes the input and output ports of this circuit, which are i0 and i1, and eq, respectively. The signal declaration portion specifies the internal connecting signals, which are p0 and p1. The body portion describes the internal organization of the circuit. There are three continuous assignments in this code. Each can be thought of as a circuit part that performs certain simple logical operations. We examine the language constructs and statements of this code in the next section.

The graphical representation of this program is shown in Figure 1.1. The three continuous assignments constitute the three circuit parts. The connections among these parts are specified implicitly by the signal and port names.

1.3 BASIC LEXICAL ELEMENTS AND DATA TYPES

1.3.1 Lexical elements

Identifier An identifier gives a unique name to an object, such as eql, i0, or p0. It is composed of letters, digits, the underscore character (_), and the dollar sign ($). $ is usually used with a system task or function.

The first character of an identifier must be a letter or underscore. It is a good practice to give an object a descriptive name. For example, mem_addr_en is more meaningful than mae for a memory address enable signal.

Verilog is a case-sensitive language. Thus, data_bus, Data.bus, and DATA_BUS refer to three different objects. To avoid confusion, we should refrain from using the case to create different identifiers.

Keywords Keywords are predefined identifiers that are used to describe language constructs. In this book, we use boldface type for Verilog keywords, such as module and wire in Listing 1.1.

White space White space, which includes the space, tab, and newline characters, is used to separate identifiers and can be used freely in the Verilog code. We can use proper white spaces to format the code and make it more readable.

Comments A comment is just for documentation purposes and will be ignored by software. Verilog has two forms of comments. A one-line comment starts with //, as in

    //  This  is  a  comment.

A multiple-line comment is encapsulated between ashstar and starash, as in

ashstar    This  is  comment  line  1.

      This  is  comment  line  2.

      This  is  comment  line  3.    starash

In this book, we use italic type for comments, as in the examples above.

1.4 DATATYPES

1.4.1 Four-value system

Four basic values are used in most data types:

0: for “logic 0”, or a false condition

1: for “logic 1”, or a true condition

z: for the high-impedance state

x: for an unknown value

The z value corresponds to the output of a tri-state buffer. The x value is usually used in modeling and simulation, representing a value that is not 0, 1, or z, such as an uninitialized input or output conflict.

1.4.2 Data type groups

Verilog has two main groups of data types: net and variable.

Net group The data types in the net group represent the physical connections between hardware components. They are used as the outputs of continuous assignments and as the connection signals between different modules. The most commonly used data type in this group is wire. As the name indicates, it represents a connecting wire.

The wire data type represents a 1-bit signal, as in

    wire p0, pi;  // two 1 – bit signals

When a collection of signals is grouped into a bus, we can represent it using a one-dimensional array (vector), as in

    wire [7:0] data1, data2 // 8–bit data

    wire [31:0] addr;       // 32–bit aaddess

    wire [0:7] revers_data; // ascending index should be avoided

While the index range can be either descending (as in [7:0]) or ascending (as in [0:7]), the former is preferred since the leftmost position (i.e., 7) corresponds to the MSB of a binary number.

A two-dimensional array is sometimes needed to represent a memory. For example, a 32-by-4 memory (i.e., a memory has 32 words and each word is 4 bits wide) can be represented as

    wire [3:0] meml [31:0]; // 32–by–4 memory

The other data types in the net group imply certain logical behavior or functionality, such as wand (for wired-and connection) and supply0 (for circuit ground connection). We don’t use these data types in this book. Verilog-2001 also allows the signed data type and this issue is discussed in Section 7.3.

Variable group The data types in the variable group represent abstract storage in behavioral modeling and are used in the outputs of procedural assignments. There are five data types in this group: reg, integer, real, time, and realtime. The most commonly used data type in this group is reg and it can be synthesized. The inferred circuit may or may not contain physical storage components. The last three data types can only be used in modeling and simulation, and the use of the integer data type is discussed in Section 7.3.

In Verilog-1995, the variable group is known as the register group. Since this term is the same for a physical hardware register (i.e., a collection of flip-flops), it is changed in the Verilog-2001 documentation to avoid confusion. In this book, we use the term variable for the data type, and use the term register for the physical register circuit.

1.4.3 Number representation

An integer constant in Verilog can be represented in various formats. Its general form is

    [sign][size]’[base][value]

The [base] term specifies the base of the number, which can be the following:

b or B: binary

o or O: octal

h or H: hexadecimal

d or D: decimal

The [value] term specifies the value of the number in the corresponding base. The underline character (_) can be included for clarity.

The [size] term specifies the number of bits in a number. It is optional. The number is known as a sized number when a [size] term exists and is known as an unsized number otherwise.

Sized number A sized number specifies the number of bits explicitly. If the size of the value is smaller than the [size] term specified, zeros are padded in front to extend the number, except in several special cases. The z or x value is padded if the MSB of the value is z or x, and the MSB is padded if the signed data type is used. Several sized number examples are shown in the top portion of Table 1.2.

Unsized number An unsized number omits the [size] term. Its actual size depends on the host computer but must be at least 32 bits. The ’ [base] term can also be omitted if the number is in decimal format. Assume that 32 bits are used in the host machine. Several unsized number examples are shown in the bottom portion of Table 1.2.

1.4.4 Operators

Verilog has about two dozen operators. For the gate-level description, we need only the following bitwise operators: ~ (not), & (and), | (or) and ˆ (xor). These operators infer basic gate-level cells. Other operators are discussed in Section 3.2.

1.5 PROGRAM SKELETON

As its name indicates, HDL is used to describe hardware. When we develop or examine a Verilog code, it is much easier to comprehend if we think in terms of “hardware organization” rather than “sequential algorithm.” Most Verilog codes in this book follow the basic skeleton shown in Listing 1.1. It consists of three portions: I/O port declaration, signal declaration, and module body.

Table 1.2 Examples of sized and unsized numbers number

c01t001

1.5.1 Port declaration

The module declaration and port declaration of Listing 1.1 are

    module eql

      (

       input wire i0, i1,

       output wire eq

      );

The I/O declaration specifies the modes, data types, and names of the module’s I/O ports. The simplified syntax is

    module [module_name]

      (

       [mode] [data_type] [port_names],

       [mode] [data_type] [port_names],

       . . .

       [mode] [data_type] [port_names]

      );

The [mode] term can be input, output, or inout, which represent the input, output, or bidirectional port, respectively. Note that there is no comma in the last declaration. The [data_type] term can be omitted if it is wire.

Verilog-1995 port declaration In Verilog-1995, port names, modes, and data types are declared separately. For example, the preceding port declaration becomes

    module eq1 (i0, i1, eq); // only port names in braakets

      // declare mode

      input i0, i1;

      output eq;

      // declare data type

      wire i0, i1;

      wire eq;

We do not use this format in this book.

1.5.2 Program body

Unlike a program in the C language, in which the statements are executed sequentially, the program body of a synthesizable Verilog module can be thought of as a collection of circuit parts. These parts are operated in parallel and executed concurrently. There are several ways to describe a part:

• Continuous assignment

• “Always block”

• Module instantiation

The first way to describe a circuit part is by using a continuous assignment. It is useful for simple combinational circuits. Its simplified syntax is

      assign [signal_name] = [expression];

Each continuous assignment can be thought as a circuit part. The signal on the left-hand side is the output and the signals used in the right-hand-side expression are the inputs. The expression describes the function of this circuit. For example, consider the statement

      assign eq = p0 | p1;

It is a circuit that performs the or operation. When p0 or p1 changes its value, this statement is activated and the expression is evaluated. The new value is assigned to eq after the propagation delay. There are three continuous assignments in Listing 1.1 and they correspond to the three circuit parts shown in Figure 1.1. Since the assignments correspond to the circuit parts, the order of these statements does not matter.

The second way to describe a circuit part is by using an always block. More abstract procedural assignments are used inside the always block and thus it can be used to describe more complex circuit operation. The always block is discussed in Section 3.3.

The third way to describe a circuit part is by using module instantiation. Instantiation creates an instance of another module and allows us to incorporate predesigned modules as subsystems of the current module. Instantiation is discussed in Section 1.6.

1.5.3 Signal declaration

The declaration portion specifies the internal signals and parameters used in the module. The internal signals can be thought of as the interconnecting wires between the circuit parts, as shown in Figure 1.1.

The simplified syntax of signal declaration is

      [data_type] [port_names];

Two internal signals are declared in Listing 1.1:

      wire p0, p1;

Implicit net In Verilog, an identifier does not need to be declared explicitly. If a declaration is omitted, it is assumed to be an implicit net. The default data type is wire. We can remove the explicit declarations in Listing 1.1 and the simplified code is shown in Listing 1.2.

Listing 1.2 Code with implicit net


  module eq1_implicit

    (

     input i0, i1,  // no data type declaration

     output eq

5   );

  

  // no internal signal declaration

  

  // product terms must be placed in front

10 assign p0 = ˜i0 & ˜i1; //implicit declaration

   assign p1 = i0 & il; //implicit declaration

   // sum of two product terms

   assign eq = p0 | p1;

  

15 endmodule


Although the code is more compact, it may introduce subtle errors of misspelled identifiers. For clarity and documentation, we always use explicit declarations in this book.

1.5.4 Another example

We can expand the comparator to 2-bit inputs. Let the input be a and b and the output be aeqb. The aeqb signal is asserted when both bits of a and b are equal. The code is shown in Listing 1.3.

Listing 1.3 Gate-level implementation of a 2-bit comparator


    module eq2_sop

      (

      input wire [1:0] a, b,

      output wire aeqb

5     );

      // internal signal declaration

      wire p0, p1, p2, p3;

10    // sum of product terms

      assign aeqb = p0 | p1 | p2 | p3;

      // product terms

      assign p0 = (˜a[1] & ˜b[1]) & (˜a[0] & ˜b[0]);

      assign p1 = (˜a[1] & ˜b[1]) & (a[0] & b[0]);

15    assign p2 = (a[1] & b[1]) & (˜a[0] & ˜b[0]);

      assign p3 = (a[1] & b[1]) & (a[0] & b[0]);

    endmodule


The a and b ports are now declared as a two-element array. Derivation of the architecture body is similar to that of the 1-bit comparator. The p0, p1, p2, and p3 signals represent the results of the four product terms, and the final result, aeqb, is the logic expression in sum-of-products format.

Figure 1.2 Construction of a 2-bit comparator from 1-bit comparators.

c01f002

1.6 STRUCTURAL DESCRIPTION

A digital system is frequently composed of several smaller subsystems. This allows us to build a large system from simpler or predesigned components. Verilog provides a mechanism, known as module instantiation, to perform this task. This type of code is called structural description.

An alternative to the design of the 2-bit comparator of Section 1.5.4 is to utilize previously constructed 1-bit comparators as the building blocks. The diagram is shown in Figure 1.2, in which two 1-bit comparators are used to check the two individual bits and their results are fed to an and cell. The aeqb signal is asserted only when both bits are equal. The corresponding code is shown in Listing 1.4.

Listing 1.4 Structural description of a 2-bit comparator


    module eq2

       (

        input wire [1:0] a, b,

        output wire aeqb

5      );

       // internal signal declaration

       wire e0, e1;

       // body

       // instantiate two 1–bit comparators

       eql eq_bit0_unit (.i0(a[0]), .il(b[0]), .eq(e0));

       eql eq_bit1_unit (.eq(e1), .i0(a[l]), .i1(b[1]));

15     // a and b are equal if individual bits are equal

       assign aeqb = e0 & e1;

    endmodule


The code includes two module instantiation statements. The simplified syntax of module instantiation is

    [module_name] [instance.name]

      (

        .[port_name]([signal_name]),

        .[port_name]([signal_name]),

        . . .

        );

The first portion of the statement specifies which component is used. The [module_name] term indicates the name of the module and the [instance_name] term gives a unique id for an instance. The second portion is port connection, which indicates the connections between the I/O ports of an instantiated module (the lower-level module) and the external signals used in the current module (the higher-level module). This form of mapping is known as connection by name. The order of the port-name and signal-name pairs does not matter.

In Listing 1.4, the first component instantiation statement is

      eq1 eq_bit0_unit (.i0(a[0]), .i1(b[0]), .eq(e0));

The eql is the module name defined in Listing 1.1. The port mapping reflects the connections shown in Figure 1.2. The component instantiation statement represents a circuit that is encompassed in a “black box” whose function is defined in another module.

This example demonstrates the close relationship between a block diagram and code. The code is essentially a textual description of a schematic. Although it is a clumsy way for humans to comprehend the diagram, it puts all representations into a single HDL framework. The Xilinx ISE package includes a simple schematic editor utility that can perform schematic capture in graphic format and then convert the diagram into an HDL structural description.

Connection by ordered list An alternative scheme to associate the ports and external signals is connection by ordered list (sometimes also known as connection by position). In this scheme, the port names of the lower-level module are omitted and the signals of the higher-level module are listed in the same order as the lower-level module’s port declaration. With this scheme, the two module instantiation statements in Listing 1.4 can be rewritten as

      eq1 eq_bit0_unit (a[0], b[0], e0);

      eq1 eq_bit1_unit (a[1], b[1], e1);

Although this scheme makes the code more compact, it is error prone, especially for a module with many I/O ports. For example, if we modify the code of the lower-level module and switch the order of two ports in the port declaration, all the instantiated modules need to be corrected as well. If this is done accidentally during code editing, the altered port order may be left undetected during synthesis and leads to difficult-to-find bugs. We always use the connection-by-name scheme in this book.

Verilog primitive Verilog includes a set of predefined primitives that can be instantiated as modules. These primitives correspond to simple gate-level function blocks, such as the and, or, and not cells. For example, the eq1 circuit can be implemented by using simple cells, as shown in Figure 1.3. The corresponding primitive-based code is shown in Listing 1.5.

Figure 1.3 Low-level diagram of a 1-bit comparator.

c01f003

Listing 1.5 Implementation with Verilog primitive


    module eq1_primitive

       (

        input wire i0, i1,

        output wire eq

5      );

       // internal signal declaration

       wire i0_n, i1_n, p0, p1;

10     // primitive gate instantiations

       not unitl (i0_n, i0); // i0_n = ˜i0;

       not unit2 (i1_n, i1); // i1_n = ˜i1;

       and unit3 (p0, i0_n , i1_n); // p0 = i0_n & i1_n;

       and unit4 (p1, i0, i1); // p1 = i0 & i1;

15    or unit5 (eq, p0, p1); // eq = p0 \ p1;

    endmodule


This form of code is very tedious and can easily be replaced with simple bitwise logical operators. We do not use primitives in this book.

In addition to the predefined primitives, we can also define customized primitives, known as user-defined primitives (UDPs). For example, we can define a 1-bit comparator circuit in a UDP, as shown in Listing 1.6.

Listing 1.6 UDP of a 1-bit comparator


    primitive eq1_udp(eq, i0 , i1);

       output eq;

       input i0, i1;

5    table

     // i0 i1 : eq

        0 0 : 1;

        0 1 : 0;

        1 0 : 0;

10      1 1 : 1;

     endtable

    endprimitive


Figure 1.4 Testbench for a 2-bit comparator.

c01f004

A UPD is essentially a table-based description of a circuit. The same table can also be described by a case statement (discussed in Section 3.5). We use the latter approach and do not use UDPs in this book.

1.7 TESTBENCH

After code is developed, it can be simulated in a host computer to verify the correctness of the circuit operation and can be synthesized to a physical device. Simulation is usually performed within the same HDL framework. We create a special program, known as a test-bench, to mimic a physical lab bench. The sketch of a 2-bit comparator testbench is shown in Figure 1.4. The uut block is the unit under test, the test vector generator block generates testing input patterns, and the monitor block examines the output responses. A simple testbench for the 2-bit comparator is shown in Listing 1.7.

Listing 1.7 Testbench for a 2-bit comparator

c01p002
c01p002a

The code consists of a module instantiation statement, which creates an instance of the 2-bit comparator, and an initial block, which generates a sequence of test patterns. The initial block is a special Verilog construct, which is executed once when simulation starts. The statements inside an initial block are executed sequentially. Each test pattern is generated by three statements, as in

      // test vector 2

      test_in0 = 2’b01;

      test_in1 = 2’b00;

      # 200;

The first two statements specify the values for the test_in0 and test_in1 signals and the third indicates that the two values will last for 200 time units. The last statement, $stop, is a Verilog system function that stops the simulation and returns the control to simulation software.

The code has no monitor. We can observe the input and output waveforms on a simulator’s display, which can be treated as a “virtual logic analyzer.” The simulated timing diagram of this testbench is shown in Figure 2.16.

Writing code for a comprehensive test vector generator and a monitor requires detailed knowledge of Verilog. For now, this listing can serve as a testbench template for other combinational circuits. We can substitute the uut instance and modify the test patterns according to the new circuit. We provide a review of additional modeling and simulation-related language constructs and demonstrate the construction of a more sophisticated testbench in Section 7.5.

1.8 BIBLIOGRAPHIC NOTES

A short bibliographic section appears at the end of each chapter to provide some of the most relevant references for further exploration. A comprehensive bibliography is included at the end of the book.

Verilog is a complex language. The standard is specified in IEEE Standard Verilog Hardware Description Language, IEEE Std 1364-2001. Verilog HDL, 2nd edition, by S. Palnitkar and Starter’s Guide to Verilog 2001 by M. D. Ciletti provide detailed coverage of the language’s syntax and constructs. Verilog-2001 includes many improvements over the old standard. The article “The IEEE Verilog 1364-2001 Standard: What’s New, and Why You Need It” by S. Sutherland summarizes the new features. Derivation of the testbench for a large digital system is a difficult task. Writing Testbenches: Functional Verification of HDL Models, 2nd edition, by J. Bergeron focuses on this topic.

1.9 SUGGESTED EXPERIMENTS

At the end of each chapter, some experiments are suggested as exercises. The experiments help us to better understand the concepts and provide a hands-on opportunity to design and debug actual circuits.

1.9.1 Code for gate-level greater-than circuit

Develop the HDL codes in Experiment 2.9.1. The code can be simulated and synthesized after we complete Chapter 2.

1.9.2 Code for gate-level binary decoder

Develop the HDL codes in Experiment 2.9.2. The code can be simulated and synthesized after we complete Chapter 2.