You are on page 1of 11

1 2

Purpose
• HDL’s were originally used to model and
simulate hardware before building it
Verilog HDL • In the past 20 years, synthesis tools were
developed that can essentially build the
hardware from the same description
Mark Redekopp

3 4

Differences from Software Modules


• Software programming languages are inherently sequential • Each Verilog designs starts as a block diagram (called
– Operations executed in sequential order (next, next, next)
• Hardware blocks always run in parallel (at the same time)
a “module” in Verilog)
– Uses event-driven paradigm (change in inputs causes expression to be • Start with input and output signals, then describe
evaluated)
how to produce outputs from inputs
• HDL’s provide constructs for both parallel & sequential operation

Software Hardware
Perform x+y and when that is This description models 2 gates
x module m1(x,y,z,f,g);
done assign d-c to tmp working at the same time
f
// circuit
var = x+y; f = a & b; y Module // description
g
tmp = d-c; g = a | b; z[2:0] endmodule
Event Driven Paradigm:
If a or b changes, f and g Software analogy: Modules are like functions, but also like classes in
will be re-evaluated that they are objects that you can instantiate multiple times.
5 6

Ports Signal Types


• Input and output signals of a module are called “ports” • Signals represent the inputs, outputs, and
internal values
(similar to parameters/arguments of a software function)
• Signals need to be typed module m1(x,y,z,f,g);
• Unlike software, ports need to be declared as “input” or – Similar to variables in software (e.g. int, char) input x,y;
“output” • 2 basic types input [2:0] z
– Wire: Represents a node connecting two output f;
• Vectors declared using [MSB : LSB] notation logic elements output reg [1:0] g;
• Only for modeling combinational logic
• Used in “assign” statements
• Use for signals connecting outputs of wire n1, n2;
These are the ports
instantiated modules (structural modeling) reg n3, n4;
x module m1(x,y,z,f,g); – Reg(ister): Used for signals that are ...
f described behaviorally endmodule
input x,y; • Used to model combinational & sequential
y Module input [2:0] z; logic Inputs are always type
g[1:0] • Used for anything produced by an “always” or ‘wire’. Outputs are assumed
z[2:0]
output f; “initial” block ‘wire’ but can be redefined
output [1:0] g; as ‘reg’
endmodule

7 8

Constants Structural vs. Behavioral Modeling


• Multiple bit constants can be written in the form:
Structural Behavioral
– [size] `base value
• size is number of bits in constant
• Starting with primitive • Describe behavior and let
gates, build up a hierarchy synthesis tools select
• base is o or O for octal, b or B for binary, d or D for decimal, h or H for
hexadecimal
of components and specify internal components and
• value is sequence of digits valid for specified base
how they should be connections
– Values a through f (for hexadecimal base) are case-insensitive
connected
• Examples:
– 4’b0000 // 4-bits binary
– 6’b101101 // 6-bits binary
– 8’hfC // 8-bits in hex
– Decimal is default
– 17 // 17 decimal converted to appropriate # of unsigned bits
9 10

Structural Modeling Structural Modeling of Logic Gates


• Starting with primitive gates, build module ha(x,y,s,co); • Modules and primitive gates can be instantiated
up a hierarchy of components and
specify how they should be
input
output
x,y;
s,co;
using the following format:
connected module_name instance_name(output, input1, input2,…)
xor i1(s,x,y);
and i2(co,x,y); • Input and outputs must be wire types
X Y endmodule

Co module incrementer(a,z); • Supported Gates: and, or, not, nand, nor, xor, xnor
Structural input [3:0] a;
Half specification of output [3:0] z;
Adder a half adder module m1(c16,c8,c4,f);
wire [3:1] c; input c16,c8,c4;
S
ha ha0(a[0],1,z[0],c[1]); output f;
ha ha1(a[1],c[1],z[1],c[2]); wire n1;
ha ha2(a[2],c[2],z[2],c[3]); or i1(n1,c8,c4);
ha ha3(a[3],c[3],z[3], ); nand i2(f,c16,n1);
endmodule “i2” endmodule
“n1” instance name
net (wire)
Use HA’s to structurally describe incrementer Verilog Description

11 12

Instantiating User-Defined Modules Internal Signals


• Format: module_name instance_name(port1, port2, port3, …)
• Positional mapping • Define signals (wire or reg) for each internal
– Signals of instantiation ports are associated using the order of module’s port
declaration (i.e. order is everything) signal/wire
• Named mapping
module m2(x,y,z,f);
– Signals of instantiation ports are explicitly associated with module’s ports (i.e.
order is unimportant) input x,y,z;
– module_name instance_name(.module_port_name(signal_name),…); output f;
wire n1,n2,n3;

module ha(x,y,s,co); module ha(x,y,s,co);


and u1(n1,x,z); // instance names need
... ... and u2(n2,x,y); // not be declared
endmodule endmodule not u3(n3,z);
module incrementer(a,z); module incrementer(a,z);
Named
or u4(f,n1,n2,n3);
ha ha0(a[0],1,z[0],c[1]); ha ha0(.x(a[0]),
Mapping
... .s(z[0]), endmodule
endmodule .y(1),
.co(c[1]) );
Positional mapping ...
endmodule
13 14

Behavioral Modeling Operators


• Describe behavior and let synthesis tools select internal • Operator types
components and connections – Non-blocking / Blocking assignment ( <=, = )
• Advantages: – Arithmetic (+, -, *, /, %)
– Easier to specify – Relational (<, <=, >, >=)
– Synthesis tool can pick appropriate implementation (for – Equality (= =, !=, = = = , ! = =)
speed / area / etc.) – Logical (&&, ||, !)

module incrementer(a,z); – Bitwise (~, &, |, ^, ~^)


input [3:0] a; Could instantiate a ripple- – Reduction (&, ~&, |, ~|, ^, ~^)
output [3:0] z; carry adder, a fast carry-
assign z = a + 1'b1;
lookahead adder, etc. as – Shift (<<, >>)
needed
endmodule – Conditional ( ? : )
– Concatenation and replication
Use higher level operations and let synthesis
tools infer the necessary logic

15 16

Assign Statement Multi-bit (Vector) Signals


• Used for combinational logic
expressions (must output to a ‘wire’ • Reference individual bits module m1(x,f);
signal type) or groups of bits by input [2:0] x;
• Can be used anywhere in the body of a
module m1(c16,c8,c4,f);
placing the desired index output f;
module’s code input c16,c8,c4; in brackets // f = minterm 5
• All ‘assign’ statements run in parallel output f; (e.g. x[3] or x[2:1]) assign f = x[2] & ~x[1] & x[0];
wire n1;
• Change of any signal on RHS (right- endmodule
hand side) triggers re-evaluation of or i1(n1,c8,c4);
• Form vector from
LHS (output) nand i2(f,c16,n1); individual signals by
• Format: endmodule placing signals in module incrementer(a,x,y,z);

– assign output = expr; brackets input [2:0] a;


output x,y,z;
module m1(c16,c8,c4,f);
• ‘&’ means AND
input c16,c8,c4; (i.e. { }) and separate
• ‘|’ means OR
• ‘~’ means NOT
output f; with commas assign {x,y,z} = a + 1;
assign f = ~(c16 & (c8 | c4)); endmodule
• ‘^’ means XOR
endmodule
17 18

More Assign Statement Always Block (Combinational)


• Primary unit of parallelism in code module addsub(a,b,sub,s);
• Can be used with other
– ‘always’ and ‘assign’ statements run in parallel
input [3:0] a,b;
operators besides simple module m1(x,y,sub,s,cout,d,z,f,g); – Statements w/in always blocks are executed input sub;
input [3:0] x,y; sequentially
logic functions input sub; output reg [3:0] s;
• Format reg [3:0] newb;
– Arithmetic (+, -, *, /, output [3:0] s,d;
– always @(sensitivity list)
output [3:0] z; begin
%=modulo/remainder) output cout,f,g; statements always @(b,sub)
– Shifting (<<, >>) assign {cout,s} = {0,x} + {0,y}; end begin
assign d = x – y; • Always blocks are “executed” when there is a change if(sub == 1)
– Relational assign f = (x == 4’h5); in a signal in the sensitivity list newb = ~b;
(<, <=, >, >=, !=, ==) assign g = (y < 0); • When modeling combinational logic, sensitivity lists else
assign z = (sub==1) ? x-y : x+y; newb = b;
• Produces a single bit output should include ALL inputs (i.e. all signals in the RHS’s)
endmodule end
(‘1’ = true / ‘0’ false) • Generation of a signal must be done within a single
Sample “Assign” statements always block (not spread across multiple always always @*
– Conditional operator ( ? : ) blocks) begin
• Syntax: – Signals generated in an always block must be declared s = a + newb + sub;
condition ? statement_if_true : statement_if_false; type ‘reg’ end
endmodule

19 20

Always Block (Sequential) Procedural Statements


module accumulator(x,z,clk,rst);
• Flip-flops (sequential logic) • Must appear inside an always or initial block
input [3:0] x;
are modeled using an input clk,rst;
always block sensitive to the output [3:0] z; • Procedural statements include
reg [3:0] z;
edge (posedge or negedge) – if…else if…else…
of the clock always @(posedge clk)
– block will only be executed on begin – case statement
if(rst == 1)
the positive edge of the clock z <= 4’b0000; – for loop (usually unnecessary for describing logic)
else
• Use the non-blocking z <= z + x; – while loop (usually unnecessary for describing logic)
assignment operator (<=) in end
clocked “always” blocks endmodule
21 22

If…Else If…Else Statements Case Statements


• Syntax // 4-to-1 mux description
• Syntax // 4-to-1 mux description

if(expr) always @(i0,i1,i2,i3,sel) always @(i0,i1,i2,i3,sel)


case(expr)
begin begin
begin if(sel == 2’b00) option 1: begin case(sel)
statements; y <= i0; statements; 2’b00: y <= i0;
else if(sel == 2’b01) 2’b01: y <= i1;
end y <= i1; end 2’b10: y <= i2;
else if(expr) else if(sel == 2’b10) option 2: statement; default: y <= i3;
y <= i2; endcase
statement; else [default: statement;] end
else y <= i3; endcase
end
statement; ...

• If multiple statements as the body of if…else if…else then • Default statement is optional
enclose in begin…end construct • If multiple statements as the body of an option then enclose
in begin…end construct

23 24

Traffic Light State Machine Understanding Simulation Timing


module trafficlight(s1, s2, clk, rst, msg, ssg, mtg, always @(posedge clk)
msr, ssr, mtr); begin
input s1, s2, clk, rst;
output msg, ssg, mtg, msr, ssr, mtr;
if(rst == 1)
state <= SS;
• When expressing parallelism, an understanding of
reg msg, ssg, mtg, msr, ssr, mtr;
else
state <= state_d;
how time works is crucial
end
reg [1:0]
reg [1:0]
state;
state_d; always @(state)
• Even though ‘always’ and ‘assign’ statements specify
wire
parameter
s;
MT = 2'b11;
begin
mtg <= 0; msg <= 0; ssg <= 0;
operations to be run in parallel, simulator tools run
parameter MS = 2'b10;
parameter SS = 2'b00;
mtr <= 0; msr <= 0; ssr <= 0;
case(state) on traditional computers that can only execute
MT:
assign s = s1 | s2;
always @(state, s)
begin
mtg <= 1; ssr <= 1; msr <= 1;
sequential operations
begin end
if(state == MS)
state_d <= SS;
MS: • To maintain the appearance of parallelism, the
begin
else if(state == SS)
if(s == 1)
msg <= 1; ssr <= 1; mtr <= 1;
end
simulator keeps track of events in a sorted event
state_d <= MT;
else
SS:
begin
queue and updates signal values at appropriate
state_d <= MS; ssg <= 1; msr <= 1; mtr <= 1;
else // state == MT
state_d <= MS;
end times, triggering more statements to be executed
endcase
end end
endmodule
25 26

Explicit Time Delays Explicit Time Delays

• In testbenches, explicit module m1_tb; • Assignments to the same module m1_tb;


reg a,b,c; reg a,b,c;
delays can be specified wire w,x,y,z; signal without an wire w,x,y,z;

using ‘# delay’ assign a = 1;


intervening delay will cause assign a = 1;
#5 // delay 5 ns (ns = default) #5 // delay 5 ns (ns = default)
– When this is done, the RHS of assign a = 0; only the last assignment to assign a = 0;
the expression is evaluated at assign b = 0; be seen assign a = 1;
time t but the LHS is not #2 // delay 2 more ns endmodule

updated until t+delay assign a = 1;


endmodule

Time Event Time Event


0 ns a=1 0 ns a=1
Simulator Event Queue Simulator Event Queue
5 ns a=0 5 ns a = 0→1
5 ns b=0 5 ns b=0
7 ns a=1 7 ns a=1

27 28

Explicit Propagation Delay Implicit Time Delays


always @(a,b,c,w,x,y)
• When modeling logic, explicit propagation module m1(a,b,c,w,x,y,z);
input a,b,c; • Normal behavioral descriptions don’t begin
w <= a ^ b;
delays can be inserted output w,x,y,z; model propagation delay until the x <= b | c;
Equivalent
Implementations
– Normally behavioral descriptions should avoid y <= w & x;
always @(a,b,c)
this since the delays will be determined by the begin
code is synthesized end
z <= ~y;
assign w = a ^ b;
assign x = b | c;
synthesis tools w <= #4 a ^ b; • To operate correctly the simulators assign y = w & x;
assign z = ~y;
• Verilog supports different propagation x <= #5 b | c;
end event queue must have some notion
delay paradigms
endmodule of what happens first, second, third, Time Event Triggers
• One paradigm is to specify the delay with
the RHS of an assignment in an always etc. 0 ns a,b,c = 0,0,1 w and x assigns
block. • Delta (δ) time is used
Time Event 0+δ w=0, x=1 y assign
• When this is done, the RHS of the – Delta times are purely for ordering
expression is evaluated at time t but the 0 ns a,b,c = 0,0,1 events and all occur in “0 time” 0 + 2δ y=0 z assign
LHS is not updated until t+delay 4 ns w=0 – The first event(s) occur at time 0 ns 0 + 3δ z=1 Anything
• This is called “transport” delay since we are 5 ns x=1 – Next event(s) occur at time 0 + δ sensitive to z
specifying the time to transport the value
Simulator Event Queue – Next event(s) occur at time 0 + 2δ
from inputs to output
Simulator Event Queue
29 30

Synthesized Logic & Timing


• Synthesis tools have to determine // 2-to-1 mux description

whether you are describing always @(i0,i1,sel)


begin
combinational or sequential logic in an y = i1;
always block if(sel == 0)
y = i0;
• If we reach the end of a block end
attempting to model combinational Default assignment of y
logic without assigning a signal then it overwritten if necessary

infers that the signal should be // 2-to-1 mux description

remembered (i.e. sequential logic) and always @(i0,i1,sel)


begin
a latch results (usually undesired)
• When modeling combinational logic
if(sel == 0)
y = i0; TESTBENCHES
else
ALWAYS: y = i1;
– Provide a default assignment or endcase
end
– Provide an else/default case
Else case acts as a catch-all /
default case.

31 32

Testbenches Testbench Modules


• Generate input stimulus (values) to Testbench Module • Declared as a module module my_tb;
your design over time
• Simulator will run the inputs through Code to generate
just like the design // testbench code
the circuit you described and find input stimulus circuit endmodule
what the output from your circuit
would be • No inputs or outputs
• Designer checks whether the output
is as expected, given the input Inputs Outputs
sequence Unit Under Test (UUT)
• Testbenches consist of code to (Your design module)
generate the inputs as well as
instantiating the design/unit under
test and possibly automatically
checking the results
33 34

Testbench Signals UUT Instantiation


• Declare signals in the module m1(x,y,z,f,g); • Instantiate your design module module m1(x,y,z,f,g);

testbench for the inputs and input x,y,z; as a component (just like you input x,y,z;
output f,g;
outputs of the design under output f,g; instantiate a gate in you design) ...
test ... • Pass the input and output endmodule
– inputs to your design should Unit Under Test
signals to the ports of the Unit Under Test
be declared type ‘reg’ in the design
module my_tb;
testbench (since you are module my_tb; • For designs with more than 4 or
driving them and their value reg x,y,z;
reg x,y,z;
5 ports, use named mapping wire f,g;
should be retained until you
change them) wire f,g; rather than positional mapping m1 uut(x,y,z,f,g);
/* m1 uut(.x(x), .y(y),
– outputs from your design endmodule .z(z), .f(f),
.g(g));
should be declared type ‘wire’ */
since your design is driving Testbench endmodule
them Testbench

35 36

Generating Input Stimulus (Values) Initial Block Statement


• Now use Verilog code module m1(x,y,z,f,g); • Tells the simulator to run this module my_tb;
input x,y,z; code just once (vs. always block reg x,y,z;
to generate the input output f,g; that runs on changes in wire f,g;
... sensitivity list signals)
values over a period of endmodule m1 uut(x,y,z,f,g);
• Inside the “initial” block we can
time Unit Under Test
write code to generate values initial
on the inputs to our design begin
module my_tb;
reg x,y,z; • Use “begin…end” to bracket the // input stimulus
wire f,g; code (similar to { .. } in C or // code
m1 uut(x,y,z,f,g); Java) end
/* m1 uut(.x(x), .y(y),
.z(z), .f(f), endmodule
.g(g));
*/
endmodule
Testbench
Testbench
37 38

Assignment Statement Aggregate Assignment Statement


• Use ‘=‘ to assign a module my_tb; • Can assign multiple signals at module my_tb;
reg x,y,z; once reg x,y,z;
signal a value wire f,g; • Place signals in brackets wire f,g;
– Can assign constants m1 uut(x,y,z,f,g);
(i.e. { }) and separate with m1 uut(x,y,z,f,g);
commas
• x = 0; y = 1; initial initial
• Multiple bit constants can be
begin begin
– Can assign logical written in the form:
relationships x = 0; • num_bits ’{b,o,d,h} value {x,y,z} = 3’b000;

• x = ~x // x = not x end – 4’b0000 // 4-bits binary end


endmodule – 6’b101101 // 6-bits binary endmodule
• x = y & z // x = y and z – 8’hFF // 8-bits in hex
– Decimal is default
– 17 // 17 decimal
Testbench Testbench

39 40

Time Integer Signal Type


• We must explicitly module my_tb; • To model a collection of bits module my_tb;
representing a number, declare reg w,x,y,z;
indicate when and how reg x,y,z;
signals as type ‘integer’ integer num;
wire f,g;
much time should pass • Assigning an integer to a bit or initial
m1 dut(x,y,z,f,g);
between assignments group of bits will cause them to begin
num = 15;
initial get the binary equivalent
• Statement (‘#’ indicates a begin
• Assigning an integer value too
{w,x,y,z} = num;
// assigns
time delay): {x,y,z} = 3’b000; large for the number of bits will // w,x,y,z = 1111
#10; cause just the LSB’s of the #10;
– # 10; // wait 10 ns; {x,y,z} = 3’b001; num = num+1;
number to be assigned
– # 50; // wait 50 ns; #25;
– Assigning 810=10002 to a 3-bit value
// num = 16
{w,x,y,z} = num;
• Default timescale is end will cause the 3-bit value to be 000 // w,x,y,z = 0000
(i.e. the 3 LSB’s of 1000) end
nanoseconds (ns) endmodule endmodule
Testbench Testbench
41 42

For loop For loop


• Integers can also be usedmodule my_tb; • Question: How much time module my_tb;

as program control reg a,b; passes between reg a,b;

variables
integer i; You can’t do assignments to {a,b} integer i;
“i++” as in
initial C/C++ or Java • Answer: 0 time…in fact if initial
• Verilog supports ‘for’ begin
you look at a waveform, begin
for(i=0;i<4;i=i+1) for(i=0;i<4;i=i+1)
loops to repeatedly begin {a,b} will just be equal to begin
a,b = 00,
execute a statement {a,b} = i; then 01, 1,1…you’ll never see any {a,b} = i;
end then 10, #10;
• Format: then 11 other combinations
end end
– for(initial_condition; endmodule • We must explicitly insert end
end_condition; increment Here, ‘i’ acts as a counter for a loop. time delays! endmodule

statement) Each time through the loop, i is


incremented and then the decimal value Now, 10 nanoseconds will pass before
is converted to binary and assigned to a we start the next iteration of the loop
and b

43

Generating Sequential Stimulus


• Clock Generation module my_tb;
reg clk, rst, s;
– Initialize in an initial block
– Continue toggling via an always always #5 clk = ~clk;
process
• Reset generation initial begin
– Activate in initial block clk = 1; rst = 1; s=0;
// wait 2 clocks
– Deactivate after some period of @(posedge clk);
time @(posedge clk);
– Can wait for each clock edge via rst = 0;
@(posedge clk) s=1;
@(posedge clk);
CLK s=0;
end
RST endmodule
S
Generated stimulus

You might also like