ECE 111 TUTORIAL 1
The purpose of this tutorial is introduce you to the IEEE standard hardware description language, Verilog HDL,
and to the tool chain. The tool chain consists of the Modelsim simulation tool and the Synopsys synthesis tool.
The ultimate goal of chip-level design is to actually produce a chip.
There are many steps involved in doing this, and this tutorial focuses on two
of them: simulation and synthesis.
A simulator accepts inputs that you specify and displays what the design's
anticipated outputs will be. In this tutorial, we will be doing RTL
(register transfer level) simulation, in which the input to the simulator is the
compiled Verilog HDL source code. Verilog HDL is a programming language for
defining the structural and behavioral description of digital circuits.
In RTL simulation, since no delay information is present, the simulation has no delays in it.
The simulator that you will be using is the ModelSim simulator.
Synthesis is the process of taking human-readable input such as
Verilog HDL source code files and creating a low-level
description which describes the design in terms of simple gates.
The synthesis tool you will be using is the Altera software package.
Below are example Verilog files.
Verilog source code is plain text contained in a single file or
a group of files. Verilog text files use the file extension, .v .
Processes in Verilog are modeled with the always block.
In hardware description languages, processes are blocks of statements.
Processes are of two types: unclocked and clocked. An unclocked
process models combinational logic; a clocked process models synchronous
logic. A process is executed concurrently with respect to other
processes and continuous signal assignment statements.
Processes offer a variety of powerful statements and constructs
that make them very suitable for high level behavioral descriptions.
Verilog source code for 1-bit full adder is contained in the file, full_adder.v.
- The basic building block in Verilog is the module. In this case, the module's name is full_adder.
- Comments in Verilog source code are prefaced by //.
- Verilog is a weakly-typed language
- Verilog is case-sensitive.
Verilog source code for a hierarchical 4-bit adder is contained in the file, h4ba.v.
This module instantiates the full adder four times to construct the 4-bit adder.
Three signals are declared to be used as wires to connect the four instantiations of the
full adder together to obtain the four-bit adder. The carry-out of each of the three
lowest bit adders are each connected to the carry-in of the next highest bit adder.
The wiring together of the four 1-bit adders is done by explicit port mapping.
Explicit port mapping has the syntax, .formal(actual) in the instantiations of the full adder.
The formal parameter is a signal from the port of the full adder.
The actual parameter is a signal from either the port of the h4ba module
or from the set of three wires declared in the h4ba module.
Each instantiation of a full adder is given a unique name, i.e., fa0.
Verilog source code for the testbench for testing the h4ba module is contained in the file, tb_h4ba.v.
A testbench is for simulation only and is not synthesizable. The testbench instantiates h4ba as a component and applies test vectors, which are input values, to the component in a sequential manner using an inital block. An initial block is executed once starting at the beginning of the simulation with the statements in the inital block executed sequentially. Since we don't synthesize the testbench, we can use the full range of the Verilog language in a testbench, whereas for a Verilog design that we are going to synthesize, we can only use the subset of the Verilog language that is synthesizable. For example, "# 15", where # is the delay operator, is not synthesizable, but we can use it in a testbench since we are not going to synthesize it.
The Verilog description of a 4-bit adder using a process with a sensitivity list is
p4ba.v. The sensitivity list is to the right of [email protected]
Generally, for an unclocked always block (no clock in the sensitivity list),
signals that are read in the always construct should be placed in the sensitivity list.
Since the signals, addend_one, addend_two, and carry_in are read in the process, they are included in the sensitivity list.
Whenever one of the signals in the sensitivity list changes value, the always block will be executed.
The assignment statements in the unclocked process use the blocking assignment operator, =.
Signals written to with the blocking assignment operator are updated instantaneously.
Combinational logic (unclocked always block (no clock in the sensitivity list)) should be described using the blocking assignment operator. In an unclocked always block, statements are executed sequentially.
The other type of Verilog assignment operator is the non-blocking assignment operator, <=. When a signal is written to with the non-blocking assignment operator, it is scheduled to be assigned the new value at the end of the current time unit. Sequential logic (clocked always block (clock in the sensitity list)) should be described using the nonblocking assignment operator. In a clocked process using only the nonblocking assignment operator, all assignments are executed concurrently and the order does not matter. In a clocked process, only the clock and reset (if the reset is asynchronous) should be included in the sensitivity list.
In the Verilog module, sum, carry_out, and carry are declared to be of type reg
because they are assigned to in the always block. No registers will be synthesized as no edge is specified in the event specification list (sensitivity list).
Moore state machine: moore.v. The value of output Z depends on the
value of CURRENT_STATE. The fsm is composed of
two always blocks. One unclocked always block is used to hold the combinational elements
and one clocked always block is used to hold the synchronous elements.
The always block to hold the combinational elements uses a sensitivity list which is comprised of
signals read in the always block, X and CURRENT_STATE.
Signals assigned to in an unclocked always block are synthesized as wires if no memory is inferred
or as latches if memory is inferred. In this unclocked always block, Z and NEXT_STATE are synthesized
The clocked always block
to hold the sequential elements uses the keyword posedge to signify the rising edge and using it in the second always block enables synthesis of CURRENT_STATE as the state register.
When the value of the signal CLK changes from 0 to 1, CURRENT_STATE is scheduled to be assigned the value of NEXT_STATE.
Signals assigned to in a clocked always block enables synthesis as registers. CURRENT_STATE is synthesized as the
state register of the state machine.
Mealy state machine: mealy.v.
The output value Z depends on both the value of CURRENT_STATE and the value of the input X.
A sample Verilog testbench for the moore state machine is provided:
A four 32-bit register file example is
Some designers prefer to keep synchronous elements in a
separate always block from the combinational elements.
The functional_rtl module is rewritten using this style in
frtl2.v. The default case in the
combinational always block is needed to avoid latches being
synthesized for the signals assigned to in the always block.
In this example, we purposely use a set of function calls to illustrate the use of functions as a way to encapsulate a complex amount of logic. This encapsulated logic could then be used with non-blocking assignment statements in a clocked always statement.