Verilog 1
Verilog 1
Verilog 1
org
A Brief Introduction to
Verilog
Hardware Definition Language (HDL)
Forward
Verilog is a “Hardware Description” language (HDL) that is used to define the structure
and/or behavior of digital circuits. Verilog is a “concurrent” language, different than a
“procedural” language like C or Java.
Verilog is the most widely used HDL industry today, but VHDL is catching up. Although
the two languages are different, they are quite similar in many ways. If you learn
Verilog, it will only take a few hours to convert to VHDL.
Concepts: Behavioral vs. Structural Models
“Behavioral” code defines outputs as functions of inputs, without describing any
circuit components or modules that might be used in constructing the circuit.
“Structural” code is a form of netlist, defining a circuit as a collection of subordinate
components or modules and their interconnecting wires.
A B C Y I$001: INV(B,N$001)
Drive an output B
C I$002: AND2(N$001,C,N$002)
signal Y to a 1
whenever input B is Y I$003: INV(C,N$003)
not asserted at the A I$004: AND2(A,N$003,N$004)
same time C is, or I$005: OR2(N$002,N$004,Y)
when A is asserted
when C is not.
Behavioral descriptions are more abstract, higher-level, quicker and easier to write,
easier for others to understand and follow, and largely self documenting.
Structural descriptions are often used when existing IP blocks can be reused. They
are easier to debug, easier to analyze (for timing and area), and can be easier to
optimize.
Most designers write behavioral code for individual, lower-level circuits, and
structural code when reusing existing IP or connecting lower-level blocks into
more complex circuits.
Example: Behavioral vs. Structural Models
This example compares a structural 4-bit comparator schematic a Verilog behavioral
description. The Verilog description is far easier and faster to create, its function is clear to
the reader, and it is portable between CAD tools.
Behavioral Adder
Simpler and easier to read.
Many free VHDL and Verilog tools are available, and lots of reference and example
designs in both languages can be found around the internet
Design Projects
Verilog tools organize the workspace using “Projects”. Projects contain all the source
files needed for a given design. External files can also be used by placing them in a
library, and making the library visible within a project.
Source files include Verilog modules, constraint files used by the synthesizer to guide
implementation, and .sdf files that store signal node timing data.
Verilog source files use modules. Modules are basic Verilog constructs that define
circuits. A simple design might use a single module; more complex designs might use
several. A project can include any number of modules.
Any Verilog module can be used as a component in any other Verilog source file.
Verilog modules stored in external libraries can be used in other projects.
Verilog code can be written to model and study circuits; to specify circuits and
document behavioral requirements; to use/reuse specific pre-existing IP blocks; and to
define circuits for synthesis.
Models for Synthesis
Verilog code written to define circuits for synthesis must model physical wires. Wires
transport signals between Verilog modules, or between modules and the “outside
world”. (Note: the outside world is typically a signal connection to a physical pin on an
IC package).
Verilog uses the data type “wire” to model physical wires; only wires can transport
data.
Simple
The module declaration statement
Z
defines the “bounding box”, and the A X
module body statements define the
circuit functions B Y
is used.
.component_port(topmodule_port)
Concept: Sequential vs. Concurrent Models
• A sequential processing algorithm defines a set of steps that are taken in a
specific order
• Concurrent processing steps occur whenever new input data is available, with no
implied sequence relationship between separate concurrent processes
• Consider a simulation of a 2-input mux: At what time(s) should gate A1 be
simulated? What about gate O1?
A
A N2
A1
B B
N1 O1 Y
C
A2
C N3
Y
T0 T1 T2 T3 T4 T5 T6
HDL simulators model time by dividing it into arbitrarily small “simulator time steps”, which are the
smallest amounts of time that are relevant to the circuit (typically 10ps).
In any given simulator time step, the CPU only simulates circuit components whose inputs have
changed. Each simulator time step can take as much CPU time as is needed - during some time steps,
many circuit nodes may change, requiring a lot of CPU time. During other steps, very few nodes may
change, requiring almost no CPU time.
Concurrency: Modelling time
A B
N$60 I$19: NAND3(N$43,N$41,N$44,N$53)
Block 1 N$42 I$22
N$43 I$20: OR3(N$45,N$43,N$46,N$54)
N$53
I$19 N$61 I$21: NAND2(N$53,N$54,N$58)
N$44
N$58 I$23 I$25 I$22: OR2(B,N$42,N$60)
B I$21 N$64 I$23: OR2(N$42,N$58,N$61)
Block 3 N$45
Clk N$46 I$20 N$62 I$24: FF(Clk,B,N$62)
N$54 I$25: AND3(N$60,N$61,N$62,N$54)
I$24
Clk
Block 2
...
Block 3 expanded into a schematic and netlist.
B ... 0 0 0 - - - ...
All “instances” and “nets” that are not given names in N$42 ... 1 1 0 - - - ...
the source file are assigned auto-generated identifiers. N$43 ... 1 1 1 - - - ...
Clk ... 0 0 1 - - - ...
Only some nets will change in any given time step. N$54 ... 1 1 1 - - - ...
Here, only N$42 and Clk change. Only instances N$58 ... 0 0 0 - - - ...
whose inputs have changed in a given step are N$61 ... 0 0 0 - - - ...
simulated. This is called “event driven simulation”.
...
Time
Concurrency: Modeling time
Assigning new values to output nets requires a variable amount of CPU time for each simulator step,
depending on how many different signal assignments must be simulated. “Simulator time” is held
constant until all circuit nodes have been simulated and there are no more changes in that step. Only
then does simulator time advance.
Verilog combinational assignments are “continuous”. The left hand side is always driven and new
output values are assigned as soon as the right hand side is evaluated.
Memory requires a “procedural assignment” so that a timing signal can be checked. Memory
assignments use the “non-blocking” operator that updates outputs at the end of the simulation step.
Non-blocking procedural assignments can only occur inside an “always” block (described later).
In Verilog, flip-flop outputs are updated after a “procedure” checks for a clock edge. If an edge has
occurred in the current time step, any required output changes take effect at the end of the time step
Verilog Concurrency Model
Combinational Non-blocking assignments are used for memory. They
Evaluating outputs requires
assignments are are concurrent, and must be inside of an always block.
variable amounts of CPU time, concurrent and take There can be any number of them, but they all take
depending on the number of effect immediately effect at the end of the simulation step.
instances that must be
simulated. “Simulator time” is
held constant during the
simulator time step, until all assign x = ... assign x = ... assign x = ... assign x = ...
assign y = ... assign y = ...
circuit nodes/instances have assign y = ...
assign z = ...
assign z = ... always @ (A)
been simulated and there are begin always @ (B)
no more changes. Only then GRN <= 1'b0 begin
does simulator time advance. If.. BLUE <=...
else if...
Red <=...
end
always @ (B)
begin
CPU
Simulation Step Step 1 Step 2 Step 3 Step 4 Time
Simulation Time 000001 000002 000003 000004
CPU time per simulation step (represented by colored box size) depends on
how much processing is required; it will vary for every step. Simulation Time is
fixed during each Simulation Step, and only increments at the end of the step.
The Verilog Language
Verilog Syntax: Identifiers and Numbers
Identifiers: space-free upper and lower case letters, numbers, _, and $. Can’t
begin with a digit; limited to 1024 characters. Verilog is case sensitive.
Numbers: <size>’ <base> <value>
size: decimal number that specifies number of bits
base: ‘ character followed by b (binary), d (decimal), h (hex)
value: set of digits
Examples:
White Space: Spaces, tabs, and new lines and form feeds can separate words
and are ignored.
Localparam is the same, but constants cannot be changed. Localparam is often used
to define numbers or state identifiers (Localparam is most commonly used).
Global constants (and macros) can be defined using the ‘define keyword. They are
visible outside the module, throughout the project.
Examples:
Verilog Syntax: Operators
Possible values for reg and wire variables are 0, 1, X (unknown), and Z (high
impedance)
Wires and Assignments
“assign” statements assign values to wires, but not to variable types like reg. “assign”
statements are “continuous assignment” statements, which means they are always active and
take effect immediately. Wires must be declared prior to use with a wire statement. Examples:
All module input signals (ports) must be wires. Wires declared inside a module are not visible
outside that module.
Registers and Assignments
reg variable types are assigned in “procedural assignment” statements; procedural
assignments store their outputs in registers (reg) types. Verilog has two procedural
assignments: “initial”, run once at the start of simulation, and “always”, which always runs.
Registers/memory device outputs can only be assigned within an always block, and they
using the blocking (=) or non-blocking (<=) assignment operator. Wires cannot be assigned in
an always block.
Registers store the last value that was assigned to them (wires store nothing). Reg types are
required for instantiating memory. Registers are declared prior to use with a reg statement.
Examples:
Registers can connect to module outputs, but not to inputs (only wires can connect to module
inputs).
Blocking vs. Non-blocking Procedural Assignments
Reg variables are assigned new values with “blocking” or “non-blocking” assignments.
Blocking assignments (=) are executed in the order they appear, and they take effect
immediately. Non-blocking assignments (<=) are concurrent, and they take effect at the end
of the simulation step (they are called non-blocking because they schedule assignments to
take place at a later time, and so do not block the execution of statements that follow).
Always blocks can define combinational logic, sequential logic, or a mixture of both. If only
combinational logic is defined, then use blocking assignments; otherwise, use non-blocking.
Flip-flops are inferred (created) using an always block that checks for a posedge on clk
(and/or rst). Output values are assigned using a non blocking (<=) assignment.
Do not make assignments to the same variable from more than one always block.
A module can have as many procedural (always) blocks as necessary. Statements in a
procedural block are executed in order, but the blocks themselves are concurrent to other
blocks.
“Initial” procedural blocks are similar to always blocks, but they execute only once at the very
start of a simulation. Initial blocks are used to setup initial conditions for simulation.
Modules
Modules are the principle design entity in Verilog. The
keyword “module” is followed by the module name and
the port list.
The port list names all port signals as inputs, outputs,
or inout (bi-directional). Locally declared wires and regs
are typically declared immediately following the
module/port statement.
Within a module, combinational assignments use the
assign statement, and sequential assignments are
made inside an always block. A module can have any
number of assign statements and always blocks.
Cin Cin
Larger digital systems use X[15:0] Cin x0 A
B
Cin
fa1
x0
hierarchical design, with a x
sum
Y[15:0]
Y
sum0
modules. x
Cin
x1 A
B
Cin
fa2
y1 Y
sum sum1
Data B
Each module at every level Adder_16bit y
Cout
is designed and tested Digital System Cout
Cin
independently. Leaf modules x
x2 A Cin
fa3
typically use behavioral y
sum y2 B
Y
sum2
Adder_4bit
Structural Verilog: Using modules as building blocks
Cin
A Cin
x0
B
fa1
x0
This example uses the Verilog “built in” logic Y
sum0
modules of and, or, and xor. These module
instantiations use “positional association”,
which means the order of signals must match Cout
Cout
A Cin
x2
B
fa3
y2 Y
sum2
Cout
A Cin
x3
B
fa4
y3 Y
sum3
Cout
cout
Adder_4bit
Verilog Multiplexor Examples
Using if statement
Verilog Decoder Examples
Using assign statement
Truth Table
A B C X Y
0 0 0 1 0
0 0 1 1 1
0 1 0 0 1
0 1 1 0 1
1 0 0 0 0
1 0 1 1 0
1 1 0 0 1
1 1 1 0 1
Using Assign statement
ALU Example
Flip-Flops and Latch
D Flip-flop
Asynch reset
D Flip-flop
Synch reset
State Machine Models
Present
State
Circuit Combo Circuit
Inputs Logic Outputs
Next-State Next State Output Circuit
Logic State Register Logic Outputs
Next
State
Circuit
Inputs Present
State State
Register
Clk Clk
RST
RST
Mealy Model State Machine Combined Model State Machine
Background
State Machines
X
init
X
BELL
pick
Y Y
Z Z
Z
left right
LED1 Z LED1
LED2
X
BELL
pick
Y Y
Z Z
Z
left right
LED1 Z LED1
LED2
The remainder of the testbench source file drives inputs into the
simulator.
Testbench con’t
Memory Arrays: Verilog models memory as an array of regs. Memories are accessed by providing an
array access. Examples:
Other types: “Integer”, “time”, and “real” are legal Verilog variable types that are used in behavioral
modeling and in simulation, but rarely in sauce code intended for synthesis.