You are on page 1of 22

Overview of Verilog HDL Design

Session 2
BITS Pilani Pawan Sharma
Pilani Campus ps@pilani.bits-pilani.ac.in
Example
F = (in1 AND in2) OR (in3 AND in4)

//Structural //Behavioral
module and_or (out,in1, in2, in3, in4); module and_or (out,in1, in2, in3, in4);
input in1, in2, in3, in4; input in1, in2, in3, in4;
output out; output out;
wire tmp,tmp1; reg out;
and #10 u1 (tmp, in1, in2), u2 (tmp1, in3, in4);
or #20 (out, tmp, tmp1); always @(in1 or in2 or in3 or in4)
endmodule begin
if (in1 & in2)
//Data flow out = #30 1;
module and_or (out,in1, in2, in3, in4); else
input in1, in2, in3, in4; out = #30 (in3 & in4);
output out; end
wire tmp; endmodule
assign #10 tmp = in1 & in2;
wire #10 tmp1= in3 & in4;
assign #20 out = tmp | tmp1;
/*The three statements could be condensed
into one*/
//assign #30 out = (in1 & in2) | (in3 & in4);
endmodule
Contd..
//Test fixture for and_or module and_or simulation result
r1r2r3r4 = 0000, o = 0
module test_and_or r1r2r3r4 = 0001, o = 0
reg r1, r2, r3, r4; r1r2r3r4 = 0010, o = 0
wire o; r1r2r3r4 = 0011, o = 1
r1r2r3r4 = 0100, o = 0
and_or u2 (.in2(r2), .in1(r1), .in3(r3), .in4(r4), .out(o)); r1r2r3r4 = 0101, o = 0
r1r2r3r4 = 0110, o = 0
initial begin :b1 r1r2r3r4 = 0111, o = 1
reg [4:0] i1234; r1r2r3r4 = 1000, o = 0
for ( i1234 = 0; i1234 < 16; i1234 = i1234 + 1) r1r2r3r4 = 1001, o = 0
begin r1r2r3r4 = 1010, o = 0
{ r1, r2, r3, r4 } = i1234 [3:0]; r1r2r3r4 = 1011, o = 1
#31 $display (“r1r2r3r4 = %b%b%b%b, o = %b”, r1, r2, r3, r4, o); r1r2r3r4 = 1100, o = 1
end r1r2r3r4 = 1101, o = 1
end r1r2r3r4 = 1110, o = 1
endmodule r1r2r3r4 = 1111, o = 1
Continuous (Dataflow) Assignment

module mux_2_to_1(a, b, out,


outbar, sel); a 1
input a, b, sel; output out
out, outbar;
b 0 outbar
assign out = sel ? a : b;
assign outbar = ~out;
endmodule sel

 Continuous assignments use the assignkeyword


 A simple and natural way to represent combinational logic
 Conceptually, the right-hand expression is continuously evaluated as a function of
arbitrarily- changing inputs…just like dataflow
 The target of a continuous assignment is a net driven by combinational logic
 Left side of the assignment must be a scalar or vector net or a concatenation of scalar and
vector nets. It can’t be a scalar or vector register (discussed later). Right side can be register
or nets
 Dataflow operators are fairly low-level:
 Conditional operator: (conditional_expression) ? (value-if-true) : (value-if-false);
 Boolean logic: ~, &, |, ^
 Arithmetic: +, -, *
 Nested conditional operator (4:1 mux)
 assign out = s1 ? (s0 ? i3 : i2) : (s0? i1 : i0);
Gate Level Description

module muxgate (a, b, out, outbar, sel);


input a, b, sel;
output out, outbar;
a
wire out1, out2, selb;
out1
sel
and a1 (out1, a, sel);
out
not i1 (selb, sel);
and a2 (out2, b , selb); outbar
selb
or o1 (out, out1, out2); out2
assign outbar = ~out; b
endmodule

 Verilog supports basic logic gates as primitives


 and, nand, or, nor, xor, xnor, not, buf
 can be extended to multiple inputs: e.g., nand nand3in (out, in1, in2,in3);
 bufif1 and bufif0 are tri-state buffers
 Net represents connections between hardware elements. Nets are
declared with the keyword wire.
Verilog Registers

 In digital design, registers represent memory elements


 Digital registers need a clock to operate and update their state on certain
phase or edge
 Registers in Verilog should not be confused with hardware registers
 In Verilog, the term register (reg) simply means a variable that can hold a
value
 Verilog registers don’t need a clock.
 reg elements can be connected to the input port of a module instantiation.
Note that reg cannot connect to the output port of a module instantiation.
 reg elements can be used as outputs within an actual module declaration.
Note that reg cannot be used as inputs within an actual module
declaration.
 reg is the only legal type on the left-hand side of an always@ block = or <=
sign.
 reg is the only legal type on the left-hand side of an initial block = sign
(used in Test Benches).
 reg cannot be used on the left-hand side of an assign statement.
 reg can be used to create registers when used in conjunction with
always@(posedge Clock) blocks.
 reg can, therefore, be used to create both combinational and sequential
logic.
The caseStatement
 A case statement is a select-one-of-many construct that is roughly equivalent to an if-
else-if statement.
 case excels when many tests are performed on the same expression
 case and if may be used interchangeably to implement conditional execution within
alwaysblocks
 case is easier to read than a long string of if...elsestatements

module mux_2_to_1(a, b, out, module mux_2_to_1(a, b, out,


outbar, sel); outbar, sel);
input a, b, sel; input a, b, sel;
output out, outbar; output out, outbar;
reg out; reg out;

always @ (a or b or sel) always @ (a or b or sel)


begin begin
if (sel) out = a; case (sel)
else out = b; 1’b1: out = a;
end 1’b0: out = b;
endcase
assign outbar = ~out; end
endmodule assign outbar = ~out;

endmodule Note: cases should be


exhaustive otherwise
you’ll get unexpected
behavior! …
Dangers of Verilog: Incomplete Specification

Goal: Proposed Verilog Code:


module maybe_mux_3to1(a, b, c,
sel, out);
input [1:0] sel;
a input a,b,c;
00 output out;
b out reg out;
01
c
10 always @(a or b or c or sel)
begin
2 case (sel)
sel 2'b00: out = a;
2'b01: out = b;
2'b10: out = c;
3-to-1 MUX endcase
(‘11’ input is a don’t-care) end
endmodule

Is this a 3-to-1 multiplexer?


Incomplete Specification Infers Latches

module maybe_mux_3to1(a, b, c,
sel, out);
input [1:0] sel;
input a,b,c; a
output out; 00
reg out; b D Q
01 out
c
always @(a or b or c or sel) 10
begin G
case (sel)
2
2'b00: out = a;
2'b01: out = b; sel
2'b10: out = c;
endcase sel[1]
end sel[0]
endmodule

if out is not assigned


 Latch memory “latches”
during any pass through old data when G=0 (we
the always block, then the will discuss latches later)
previous value must be  In practice, we almost
retained! never intend this
Avoiding Incomplete Specification

always @(a or b or c or sel)


begin
 Precede all conditionals with out = 1’bx;
case (sel)
a default assignment for all 2'b00: out = a;
signals assigned within 2'b01: out = b;
them… 2'b10: out = c;
endcase
end
endmodule

always @(a or b or c or sel)


begin  …or, fully specify all branches of
case (sel) conditionals and assign all signals
2'b00: out = a;
from all branches
2'b01: out = b;
2'b10: out = c;  For each if, include else
default: out = 1’bx;  For each case, include default
endcase
end
endmodule
Dangers of Verilog: Priority Logic
Goal: Proposed Verilog Code:

4-to-2 Binary Encoder module binary_encoder(i, e);


input [3:0] i;
0 I3 output [1:0] e;
1 I2 E1 reg e;
1
0 I1 E0 0 always @(i)
0 I0 begin
if (i[0]) e = 2’b00;
else if (i[1]) e = 2’b01;
I3 I2 I1 I0 E1 E0 else if (i[2]) e = 2’b10;
else if (i[3]) e = 2’b11;
0001 00 else e = 2’bxx;
0010 01 end
0100 10 endmodule
1000 11
all others XX
What is the resulting circuit?

20
ALU example
Procedural Modeling
 Procedural Verilog code is like programming in a computer
language—with one large exception: Procedural Verilog code
adds a concept of time.
 With a programming language, code is started at a particular
location, for example, at the first line or main function. In
Verilog, code starts running in one of two places: at the initial
statement and at the always statement.
 However, if all the code is started at the initial and always
statements, how can you know the order in which the
statements will run? This is where the model of time comes
into effect.
initial keyword
 Verilog interprets the initial keyword to  Example:
mean “start here at time 0.”

 Sometimes people think the initial initial $display("Hello


keyword is used only for initialization. Verilog");
The keyword initial is used not only for
initialization, but also as a place for
starting code. – It’s a simple initial block that
starts at time 0 and prints out
 Verilog starts all initial statements at the message “Hello Verilog.”
time 0. The time at which the – This initial block is then
statements finish depends on the code finished.
in the initial block. – If you want to do more than
one operation in an initial block,
 When the statements finish, the initial you will need to use a begin-
block is done. end block or fork-join block.
always keyword
 The always keyword is similar in  Example:
behavior to the initial keyword. Verilog
also begins to run always statements always $display("Hello
at time 0. Verilog");
 The difference between initial and
always statements is: what happens
when the statements finish running?  Note:
 The always block starts again when it – Remember that always
finishes. An always block is like an statements can create infinite
initial block with an infinite loop. loops.
 If we change the hello simulation from – Just as the initial statement
an initial to an always as shown in should be remembered as
previous example, the simulation “start here at time 0,”
would continue to print until we kill the
simulation. Simulation time would remember the always
remain stuck at time 0. statement as “start here at time
0, and when done, start again.”
begin-end blocks
 Initial and always can have only module initial_two_begin;
one statement. However, you will initial
often need more than a single begin
statement in your design. The #1 $display("Statement 1");
begin-end block allows a set of $display("Statement 2");
sequential statements to follow an #2 $display("Statement 3");
initial or always statement. end
 The statements in the begin-end initial
block are sequential so we know begin
the statements will execute in the $display("Block 2 Statement 1");
order we would expect. #2 $display("Block 2 Statement 2");
 In begin-end blocks, delays are #2 $display("Block 2 Statement 3");
additive. end
endmodule Block 2 Statement 1
Statement 1
Statement 2
Block 2 Statement 2
Statement 3
Block 2 Statement 3
Blocking vs Nonblocking Assignments

 The simple blocking assignment  The nonblocking assignment is


statement has one of three forms: similar in syntax to the blocking
 lhs-expression = expression assignment, except that the = is
 lhs-expression = #delay expression replaced by <=.
 lhs-expression = @event expression
 lhs-expression <= expression
 In the first term, the simulator evaluates  lhs-expression <= #delay expression
the expression on the RHS and  lhs-expression <= @event expression
immediately assigns it to the LHS
 In the second form, the simulator  Semantically, the difference is that
evaluated the RHS, then waits for the now the RHS is evaluated but is
delay, and then assigns the value to the not immediately assigned to
LHS. the LHS. Instead, it is scheduled
 In the third form, the simulator waits for to be assigned and in the mean
the event to occur before assigning the time control continues to flow to
RHS to the LHS.
the next statement.
 In all three cases, the next
statement will execute only after
the current assignment is made.
self triggering osc.
//Example 1 //Results
module osc1 (clk);  osc1 osc2
output clk;  0: clk1=x clk2=x
reg clk;  10: clk1=0 clk2=0
 20: clk1=1 clk2=1
initial
 30: clk1=1 clk2=0
#10 clk = 0;
 40: clk1=1 clk2=1
always @(clk)  50: clk1=1 clk2=0
#10 clk = ~clk;  60: clk1=1 clk2=1
endmodule  70: clk1=1 clk2=0
 80: clk1=1 clk2=1
//Example 2  90: clk1=1 clk2=0
module osc2 (clk);
output clk; Osc1 not Osc2 is
reg clk; oscillating oscillating
initial
#10 clk = 0;
always @(clk)
#10 clk <= ~clk;
endmodule

You might also like