Day One
Day One
VERILOG
Dina Tantawy
OBJECTIVES
▪ Learn basic usage of Verilog.
▪ Learn primitive types and data types.
▪ Learn creating concurrent modules and reusing it.
What is Verilog? And Why?
▪ Verilog is another type
of Hardware Description
Language(HDL).
What is Verilog? And Why?
▪ Verilog is easier to learn and use than VHDL.
▪ Verilog is C-like .
▪ Verilog like any other language has
➢ Variables
➢ Data types
➢ Operators
➢ Conditions
➢ Loops
➢ Functions
➢ …..
▪ But it is different than other languages in the implementation of the code
▪Verilog is now part of SystemVerilog.
Why Verilog?
▪Simulation
▪Synthesis
▪Timing analysis
▪Test analysis
▪Extensible via Programming Language Interface (PLI)
History of Verilog
• Verilog was started initially as a proprietary hardware modeling language
by Gateway Design Automation Inc. around 1980.
• Verilog was standardized as IEEE 1364 in 1995, and has undergone several
revisions since then.
• The most recent version is IEEE 1800-2017, which merged Verilog with
SystemVerilog, a superset of Verilog that adds many features for verification
and design
DESIGN MODELING
▪ We can model design using:
➢Behavioral Modeling.
➢Structural Modeling.
➢Mix between ways (which is the usual)
▪ Another Model is
➢RTL is used to describe the behavior of the circuit from a register to the next
one using the data flow through basic components like mux, adders, ..etc.
➢Now, RTL “Register transfer level” is defined as any synthesizable code. In other
words , any code that can be converted to hardware
How can we build a Half adder in
Verilog?
▪Behavioral model
▪Structural model using primitives.
HALF ADDER BEHAVIORAL
Module name ports
assign s = A ^ B;
assign c = A & B;
Module implementation
endmodule
HALF ADDER BEHAVIORAL
Module name ports
endmodule
HALF ADDER STRUCT USING PRIMITIVES
Module name ports
xor my_xor(s,A,B);
and my_and(c,A,B); Module implementation
using primitive instances
endmodule
How can we build full-adder in Verilog?
▪Behavioral model
▪Structural model other modules
FULL ADDER BEHAVIORAL … 1
ports
Module name
assign S = ( A ^ B ) ^ Cin;
assign Cout = ((A ^ B) & Cin ) | (A & B);
endmodule
Module implementation
describing data flow
FULL ADDER BEHAVIORAL … 2
ports
Module name
Remember:
module half_adder(A, B, s, c);
FULL ADDER BEHAVIORAL … 3
Remember:
module half_adder(A, B, s, c);
FULL ADDER BEHAVIORAL … 3
What if we don’t need to connect all Ports?
▪<size> : contains decimal digitals that specify the size of the constant in the
number of bits. [optional]
x = -16; //1111_0000
y = -16; //1111_0000
#2 $display(" x > 2 is %b, y > 2 is %b", x>2,y>2);
add_1 = 2'd3;
add_2 = -4'd3 ;
add_3 = 4'd3;
#5;
add_1 = add_1 + x;
add_2 = add_2 - y ;
add_3 = add_3 + y;
#5; //add_1 = -13 , add_2=-243, add_3 = 243
end Can you explain how did we get those numbers?
Shift operators
a = 8'b1111_0000;
b = 2;
It returns 1-bit either true or false, any number that is not zero is considered true
Unary Reduction Operators
a = 8'b1111_0000;
b = 8'b0000_1111;
Testing only
Conditional operator
1 module conditional_operator();
3 wire out;
4 reg enable,data;
5 // Tri state buffer
6 assign out = (enable) ? data : 1'bz;
7
8 initial begin
9 $display ("time\t enable data out");
10 $monitor ("%g\t %b %b %b",$time,enable,data,out);
11 enable = 0;
12 data = 0; time enable data out
13 #1 data = 1; 0 0 0 z
14 #1 data = 0; 1 0 1 z
15 #1 enable = 1; 2 0 0 z
16 #1 data = 1; 3 1 0 0
17 #1 data = 0; 4 1 1 1
18 #1 enable = 0; 5 1 0 0
19 #10 $finish; 6 0 0 z
20 end
21 endmodule
Concatenation Operator
1 module concatenation_operator();
2
3 initial begin
4 // concatenation
5 $display (" {4'b1001,4'b10x1} = %b", {4'b1001,4'b10x1});
6 #10 $finish;
7 end {4'b1001,4'b10x1} = 100110x1
8
9 endmodule
Replication Operator
1 module replication_operator();
2
3 initial begin
4 // replication
5 $display (" {4{4'b1001}} = %b", {4{4'b1001}});
6 // replication and concatenation
7 $display (" {4{4'b1001,1'bz}} = %b", {4{4'b1001,1'bz}});
8 #10 $finish;
9 end
10 {4{4'b1001} = 1001100110011001
11 endmodule {4{4'b1001,1'bz} = 1001z1001z1001z1001z
OPERATOR PRECEDENCE
QUIZ
▪ For
➢a = 8'b1111_0000;
➢b = 8'b0000_1111;
▪ Evaluate the following expression:
➢ assign F = {a[3:1],b[3:1]}*2 < {3{a[4:3]}} & 6’h03
➢ assign Y = -b >> 2;
Data Types
What do data types have to do with hardware?
Nothing, actually because everything is just ‘0’ & ‘1’. People just wanted to write
one more language that had data types in it. there's no point.
A driver is a data type which can drive a load. Basically, in a physical circuit, a
driver would be anything that electrons can move through/into.
Declaring an array
reg [signed] <reg_name> [<range>] ;
Declaring memory
reg [signed] [<range>] <memory_name> [<start_addr> : <end_addr>];
Variable Declaration with size variations
Examples
• reg r; // 1-bit reg variable
• wire w1, w2; // 2 1-bit wire variable
• reg [7:0] vreg; // 8-bit register
• reg areg [0:7]; // an array of 1-bit register
• reg [7:0] memory [0:1023]; // a 1 KB memory or an array of 1024
register where each register is 8-bits
QUIZ
▪ Which of the following is an illegal assignment, and what is the final value
➢wire [7:0] a = 10’h2FF;
➢reg [7:0] a = 568;
➢b[3:2] = 2’b10;
➢reg c [0:3] = 4’b1111;
➢reg d [0:5]; assign d[0] = 1;
➢reg [4:0] mem [0:14] ; mem = 5;
➢reg [4:0] mem [0:14] ; mem[0] = 5;
➢reg [4:0] mem [0:14] ; mem[0][2:0] = 5;
Can We Make A Shift Operation Using
Concatenation?
wire [7:0] a,b;
▪ Shift left
➢ assign a = {b[6:0], 1’b0}
▪ Shift right
➢ assign a = {1’b0,b[7:1]}
▪ Shift left 4 bits
➢assign a = {b[3:0],4’b0}
▪ What about Rotate right ??
ARRAY Declaration
Assignment
LET’S DESIGN SOME CIRCUITS
COMBINATIONAL
Structural Modeling
Example: //Using 2 input and, design a 3 input and
module AND(in1, in2, out2);
input in1,in2;
output out2;
and and2(out2,in1,in2);// first port must be output.
endmodule
AND3
module AND3 (i0, i1, i2, op);
input i0, i1, i2; i0
output op;
wire temp; i1
o
AND a0 (.in1(i0), .in2(i1), .out2(temp)); i2
AND a1 (.in1(i2), .in2(temp), .out2(op));
endmodule
Primitive Gates
endmodule
https://www.referencedesigner.com/tutorials/verilog/verilog_11.php
Structural Modeling
Example: What hardware will we get if we did the following
module AND3 (i0, i1, i2, op);
input i0, i1, i2;
output op;
wire temp;
endmodule i0
i1
o
i2
• Verilog Structural modeling describes hardware and connections,
• hardware executes concurrently.
• Several connections on same wire will lead to unknown behavior ‘x’
• Each component should have a different wire connected to the output ports
• Exception exists for tri-stated components.
• Input ports can share connections
Behavioral Modeling
▪ Continuous assignment
➢ Starts with reserve word ‘assign’
➢ Continuous execution (concurrent as well)
➢ Models combinational circuits
F
SUMMARY
▪ Motivation
▪ Verilog lexical conventions, operators and constructs.
▪ Program structure.
▪ Modeling Methods.
➢Structural
➢Behavioral
THANK YOU
Next time: Testing And Verification, does the code do what it promises ?
Rest of behavioral modeling
COMBINATIONAL
LOGIC
AGENDA
▪ Review Last Lecture
▪ Language features:
➢ Parameters
▪ Continuous Statements
➢ For Generate Statements
▪ Sequential Statements
➢ Reg vs Wire
➢ Conditional Statements
▪ Testbenches
▪ Next Time: Sequential Logic
How To Make 2-bit adder
A[1:0] B[1:0]
S[1:0]
How To Make N-bit adder … 1
A[N-1:0] B[N-1:0]
N=?
S[N-1:0]
How To Make N-bit adder … 2
How many bits do we need? N=4 A[N-1:0] B[N-1:0]
Module Definition 1. Define a variable parameter
module Decode;
parameter Width = 8;
Defined Inside module parameter Polarity = 1;
Constants
parameter Add = 8'b1111_0000,
Halt= 8'hFF,
Sub = 4'o12;
Note that synthesis tools do not generally support hierarchical names. The alternative
approach is to use the `include directive as will be shown later
module testparam;
parameter t1 = 100;
parameter t2 = 200;
localparam localt = 600 ;
block myblock();
initial begin
$monitor("t1 %d, t2 %d, t3 %d",t1,t2,localt);
#1;
$display("c_a %b, c_b %b", c.c_a, c.c_b);
#1;
$display("b1 %d, b2 %s", myblock.b1, myblock.b2);
#1;
$finish; test_tb
end
endmodule
constants c defparam_tb t testparam top
Note that synthesis tools do not generally support hierarchical names. The alternative
approach is to use the `include directive as will be shown later
Using Parameters
• As Size
➢ reg [Width-1] data;
• As constant (magic number)
➢ assign finish = Bus == Halt ? 1'b1:1'b0;
• As width in replica operator
➢assign Bus = Enable? dataIn : {Width{1'bz}}; //assign high
impedance on the bus
How To Make 2-bit Ripple adder … 1
A[1:0] B[1:0]
S[1:0]
This is not necessary a ripple adder ! Let’s do it structural
How To Make 2-bit adder … 2
A[1] B[1] A[0] B[0]
module twobit_2 (a,b,cin,s,cout);
input [1:0] a,b;
output [1:0] s;
input cin;
Cin Full Adder Full Adder Cout
output cout;
wire w;
onebit f1(a[0],b[0],cin,s[0],w);
onebit f2(a[1],b[1],w,s[1],cout); S[1] S[0]
endmodule
How To Make 4-bit adder
module fourbit (a,b,cin,s,cout);
input [3:0] a,b;
output [3:0] s;
input cin;
output cout;
wire [2:0] w;
onebit f1(a[0],b[0],cin,s[0],w[0]);
onebit f2(a[1],b[1],w[0],s[1],w[1]);
onebit f3(a[2],b[2],w[1],s[2],w[2]);
onebit f4(a[3],b[3],w[2],s[3],cout);
endmodule
How To Make N-bit adder
1. Define a variable parameter
module fourbit (a,b,cin,s,cout); module adder #(parameter N=8) (a,b,cin,s,cout);
input [3:0] a,b; input [N-1:0] a,b;
output [3:0] s; output [N-1:0] s; 2. Use the parameter to
input cin; input cin; decide size of inputs/outputs
output cout; output cout; 3. Update implementation if
wire [2:0] w; wire [N:0] w; required
genvar k;
generate
for (k = 0; k < 4; k=k+1) begin
assign val[k] = a[k] & b[k];
and ax (res[k],a[k],c[k]);
end
endgenerate
Generate … for (Continuous/ Concurrent for)
1. Define a loop parameter, this is not a wire or
reg, this is just a control parameter and doesn’t
synthesize to any hardware
genvar k; 3. Create for loop with constant assign val[0] = a[0] & b[0];
generate condition and ax_1 (res[0],a[0],c[0]);
for (k = 0; k < 4; k=k+1) begin assign val[1] = a[1] & b[1];
assign val[k] = a[k] & b[k]; and ax_2 (res[1],a[1],c[1]);
and ax (res[k],a[k],c[k]); Expands to assign val[2] = a[2] & b[2];
end and ax_3 (res[2],a[2],c[2]);
4. Loop will be unrolled and everything
endgenerate assign val[3] = a[3] & b[3];
inside the loop will be repeated the
and ax_4 (res[3],a[3],c[3]);
2. Define generate block same number of times as the loop
Generate … for (Continuous/ Concurrent for)
genvar k;
generate always@(posedge clk) begin
for (k = 0; k < 4; k++) begin val[0] = a[0] & b[0];
always@(posedge clk) begin val[1] = a[1] & b[1];
val[k] = a[k] & b[k]; Expands to val[2] = a[2] & b[2];
end val[3] = a[3] & b[3];
end end
endgenerate
Source: https://vlsiverify.com/
Generate … for (Continuous/ Concurrent for)
Source: https://vlsiverify.com/
Generate … for (Continuous/ Concurrent for)
Source: https://vlsiverify.com/
Generate … if (Continuous/ Concurrent if)
generate
if(sel) begin
full_adder fa(A, B, Cin, S, Cout);
end
else begin
half_adder ha(A, B, S, Cout);
end
endgenerate
endmodule
Source: https://vlsiverify.com/
Generate … if (Continuous/ Concurrent if)
Source: https://vlsiverify.com/
Generate … else (Continuous/Concurrent case)
module gen_if_ex #(parameter sel = 0)(
input A, B, Cin,
output S, Cout);
generate
case(sel)
0: begin
half_adder ha(A, B, S, Cout);
end
1: begin
full_adder fa(A, B, Cin, S, Cout);
end
endcase
endgenerate
endmodule
PROCEDURAL BLOCKS
SEQUENTIAL STATEMENTS
Behavioral Modeling
▪ Review: Continuous assignment
➢ Starts with reserve word ‘assign’
➢ Continuous execution
➢ Models combinational circuits
➢ Concurrent execution
▪ Procedural blocks
➢ Initial blocks: executed once, used in test-benches only
➢ Always block: always executed, can model both combinational
and sequential circuits.
➢ Code inside it is executed sequential.
Sensitivity List
The sensitivity list is used at the beginning of an always procedure to infer
combinational logic or sequential logic behavior in simulation and synthesis.
▪ Procedural assignments
▪ Conditional statements (this is different from generate if/case)
➢If-else
➢case
▪ Looping statements (this is different from generate for)
➢for
➢while
➢repeat
Data Types
▪ Review : Nets (continuous statements)
▪ Registers (sequential statements)
◦Implicit storage – unless variable of this type is modified it retains previously
assigned value
◦Does not necessarily imply a hardware register
◦Register type is denoted by reg , others like (integer, real, time) are
constrained reg types.
◦Any variable gets assigned inside an always block or initial block must be of
reg type.
Procedural Block To Generate Combinational Circuit
Example : Half adder
module half_adder(x, y, s, c);
input x, y;
output s, c;
assign s = x ^ y;
assign c = x & y;
endmodule
always @(*)
assign w = a |b; begin
assign d = c & w; w = a |b;
d = c & w;
assign w = b & c;
assign e = w | a; w = b & c;
e = w | a;
end
assign g = w;
assign g = w;
endmodule
endmodule
EXAMPLE :
EQUIVALENT ?
module randomCir1(a,b,c,d,e,g);
input a,b,c;
output d,e;
output g;
wire w; • w will have a conflict, because on wire is
connected to two different drivers in
assign w = a |b; continuous assignment.
assign d = c & w;
assign w = b & c;
• Continuous assignment draws the hardware
assign e = w | a; once it sees the assign statement.
• All statement are concurrent, order doesnot
assign g = w;
matter.
endmodule
EXAMPLE :
EQUIVALENT ?
In procedural blocks: module randomCir2(a,b,c,d,e,g);
• Code is executed line by input a,b,c;
line. output reg d,e;
output g;
• Order matters and changing reg w;
order might result in
different hardware. always @(*)
begin
• A net assigned more than w = a |b;
once is treated as more than d = c & w;
one net.
w = b & c;
• If we reads the net assigned e = w | a;
more than once in the end
procedural block, then we
are reading the last changed assign g = w;
instance of it.
endmodule
SEQUENTIAL CONDITIONAL OPERATOR “IF”
Sequential Conditional Operator “if”
wire sel,a,b;
reg y,tempOut;
always@(*)
begin
if (sel == 0)
y = a; //single statement
else begin
y = b; //multiple statements require begin/end
tempOut = a;
end
end If conditions only exist in Procedural Blocks
– If you don't like typing the else part, then you must initialize all
the variables at the beginning of the procedural block.
Get rid of unwanted latches
wire sel,a,b; Get rid of unwanted latches.
reg y,tempOut;
always@(*)
begin
y=0;
tempOut=0;
if (sel == 0)
y = a; //single statement 0
else begin
y = b; //multiple statements require begin/end
tempOut = a;
end
end
Sequential Conditional Operator “if”
always@(*)
begin
if (sel == 0)
y = a;
else if (sel == 1 & a~= 0)
y = b;
else if (b == 1)
y = c;
end
endmodule
EXAMPLE :
EQUIVALENT ?
module randomCir2(a,b,c1,c2,w);
input a,b,c1,c2;
output reg w;
always @(*)
begin
if (c1)
begin
if (c2)
w = a;
end
else
w = b;
end
endmodule
EXAMPLE :
EQUIVALENT ?
module randomCir1(a,b,c1,c2,w);
input a,b,c1,c2;
output reg w;
always @(*)
begin
if (c1)
if (c2)
w = a;
else
w = b;
end
endmodule
EXAMPLE :
EQUIVALENT ?
SEQUENTIAL CONDITIONAL OPERATOR “CASE”
EXAMPLE : 3-TO-8 DECODER
module decoder (in,out);
input [2:0] in;
output reg [7:0] out;
always @(*)
begin
case(in)
3'b000: out = 8'b0000_0001;
3'b001: out = 8'b0000_0010;
3'b010: out = 8'b0000_0100;
3'b011: out = 8'b0000_1000;
3'b100: out = 8'b0001_0000;
3'b101: out = 8'b0010_0000;
3'b110: out = 8'b0100_0000;
3'b111: out = 8'b1000_0000;
default: out = 8'b0000_0000; “_” in a number is a syntactic sugar
endcase
Do we really need the default case here?
end
endmodule
EXAMPLE :
module randomCir5 (in,out);
input [2:0] in;
output reg [3:0] out;
always @(*)
begin a “?” is a don’t care, can be 0 or 1 but NOT x or z
case(in)
3'b000: out = 4'b0001;
3'b001: out = 4'b0010;
3’b01?: out = 4'b0100;
3’b1??: out = 4’b4000;
default: out = 4'b0000;
endcase
end
endmodule
EXAMPLE :
module randomCir5 (in,out);
input [2:0] in;
output reg [3:0] out;
always @(*)
begin a “?” is a don’t care, can be 0 or 1 or z
casez(in)
3'b000: out = 4'b0001;
3'b001: out = 4'b0010;
3’b01?: out = 4'b0100;
3’b1??: out = 4’b4000;
default: out = 4'b0000;
endcase
end
endmodule
EXAMPLE :
module randomCir5 (in,out);
input [2:0] in;
output reg [3:0] out;
always @(*)
begin Z is treated as ? Both are don’t cares
casez(in)
3'b000: out = 4'b0001;
3'b001: out = 4'b0010;
3’b01?: out = 4'b0100;
3’b1ZZ: out = 4’b4000;
default: out = 4'b0000;
endcase
end
endmodule
It produces the exact same hardware; however, it will
have different simulation results.
EXAMPLE :
module randomCir5 (in,out);
input [2:0] in;
output reg [3:0] out;
always @(*)
begin a “?” is a don’t care, can be 0 or 1 or x or z
casex(in)
3'b000: out = 4'b0001;
3'b001: out = 4'b0010;
3’b01?: out = 4'b0100;
3’b1??: out = 4’b4000;
default: out = 4'b0000;
endcase
end
endmodule
• Guideline: Code all intentional priority encoders using if-else-if statements. It is easier for a typical design
engineer to recognize a priority encoder when it is coded as an if-else-if statement.
• Guideline: Case statements can be used to create tabular coded parallel logic. Coding with case statements is
recommended when a truth-table-like structure makes the Verilog code more concise and readable.
• Guideline: Change the case statement code, as outlined in the above coding guidelines, whenever the
synthesis tool reports that the case statement is not parallel (whenever the synthesis tool reports "no" for
"parallel_case").
• Although good priority encoders can be inferred from case statements, following the above coding guidelines
will help to prevent mistakes and mismatches between pre-synthesis and postsynthesis simulations.
TESTBENCH
LET’S VERIFY SOME CIRCUITS
INTRODUCTION TO TEST BENCHES
▪ Test benches are used for the verification of the digital hardware design.
Verification is required to ensure the design meets the timing and functionality
requirements.
▪ Test benches are used to simulate and analyze designs without the need for any
physical hardware or any hardware device. you can inspect every signal /variable
(reg, wire in Verilog) in the design.
▪ Test benches saves cost and time.
▪ Test benches automate testing.
▪ Test benches don’t synthesize, the don’t generate any hardware
TEST BENCH FOR N-BIT ADDER
initial
begin
$monitor("Status: %s \t, T: %t \t,A:%d\t + B:%d\t + Cin:%d\t = Sum:%d\t , Caryy:%d",
(A+B+Cin) == {Cout,S} ? "Success":"Failure",$time,A,B,Cin,S,Cout);
A=3;B=5; Cin = 0;
#T Cin =1;
#T A=6; B=9; Cin=0;
#T Cin=1;
#T A=9; B=7; Cin=0;
#T Cin=1;
$stop;
end
endmodule
module tb_adder();
localparam N=4; Since testbench doesn’t simulate a real circuit
localparam T=100; and only used for testing, it has no input or
reg [N-1:0] A,B; output ports
reg Cin;
wire[N-1:0] S; Make sense?
wire Cout;
initial
begin
$monitor("Status: %s \t, T: %t \t,A:%d\t + B:%d\t + Cin:%d\t = Sum:%d\t , Caryy:%d",
(A+B+Cin) == {Cout,S} ? "Success":"Failure",$time,A,B,Cin,S,Cout);
A=3;B=5; Cin = 0;
#T Cin =1;
#T A=6; B=9; Cin=0;
#T Cin=1;
#T A=9; B=7; Cin=0;
#T Cin=1;
$stop;
end
endmodule
module tb_adder();
localparam N=4; Remember parameters, they are constants
localparam T=100; we can use in the testbench
reg [N-1:0] A,B;
reg Cin;
wire[N-1:0] S;
wire Cout;
initial
begin
$monitor("Status: %s \t, T: %t \t,A:%d\t + B:%d\t + Cin:%d\t = Sum:%d\t , Caryy:%d",
(A+B+Cin) == {Cout,S} ? "Success":"Failure",$time,A,B,Cin,S,Cout);
A=3;B=5; Cin = 0;
#T Cin =1;
#T A=6; B=9; Cin=0;
#T Cin=1;
#T A=9; B=7; Cin=0;
#T Cin=1;
$stop;
end
endmodule
module tb_adder();
localparam N=4;
localparam T=100;
reg [N-1:0] A,B; Remember, any Net changes value inside
reg Cin; initial or always block has to be of type reg,
wire[N-1:0] S; we use those nets to act as input to unit
wire Cout; under test (N-bit adder)
initial
begin
$monitor("Status: %s \t, T: %t \t,A:%d\t + B:%d\t + Cin:%d\t = Sum:%d\t , Caryy:%d",
(A+B+Cin) == {Cout,S} ? "Success":"Failure",$time,A,B,Cin,S,Cout);
A=3;B=5; Cin = 0;
#T Cin =1;
#T A=6; B=9; Cin=0;
#T Cin=1;
#T A=9; B=7; Cin=0;
#T Cin=1;
$stop;
end
endmodule
module tb_adder();
localparam N=4;
localparam T=100;
reg [N-1:0] A,B; We use those nets to read output from unit
reg Cin; under test, why they are not reg despite
wire[N-1:0] S; being read in initial block?
wire Cout;
initial
begin
$monitor("Status: %s \t, T: %t \t,A:%d\t + B:%d\t + Cin:%d\t = Sum:%d\t , Caryy:%d",
(A+B+Cin) == {Cout,S} ? "Success":"Failure",$time,A,B,Cin,S,Cout);
A=3;B=5; Cin = 0;
#T Cin =1;
#T A=6; B=9; Cin=0;
#T Cin=1;
#T A=9; B=7; Cin=0;
#T Cin=1;
$stop;
end
endmodule
module tb_adder();
localparam N=4;
localparam T=100;
reg [N-1:0] A,B; This is the module we want to test, can we
reg Cin; add it below the initial block ?
wire[N-1:0] S;
wire Cout;
initial
begin
$monitor("Status: %s \t, T: %t \t,A:%d\t + B:%d\t + Cin:%d\t = Sum:%d\t , Caryy:%d",
(A+B+Cin) == {Cout,S} ? "Success":"Failure",$time,A,B,Cin,S,Cout);
A=3;B=5; Cin = 0;
#T Cin =1;
#T A=6; B=9; Cin=0;
#T Cin=1;
#T A=9; B=7; Cin=0;
#T Cin=1;
$stop;
end
endmodule
module tb_adder();
localparam N=4;
localparam T=100;
reg [N-1:0] A,B;
reg Cin;
wire[N-1:0] S;
wire Cout;
initial
begin
$monitor("Status: %s \t, T: %t \t,A:%d\t + B:%d\t + Cin:%d\t = Sum:%d\t , Caryy:%d",
(A+B+Cin) == {Cout,S} ? "Success":"Failure",$time,A,B,Cin,S,Cout);
initial
begin
$monitor("Status: %s \t, T: %t \t,A:%d\t + B:%d\t + Cin:%d\t = Sum:%d\t , Caryy:%d",
(A+B+Cin) == {Cout,S} ? "Success":"Failure",$time,A,B,Cin,S,Cout);
A=3;B=5; Cin = 0; • We added 6 test cases, and separate each test case by a
#T Cin =1; delay (#T)
#T A=6; B=9; Cin=0; • What is the value of the delay?
#T Cin=1; • What will happen if we didn’t add delay?
#T A=9; B=7; Cin=0; • How does our UUT read the changed input ?
#T Cin=1;
$stop;
end
endmodule
module tb_adder();
localparam N=4;
localparam T=100;
reg [N-1:0] A,B;
reg Cin;
wire[N-1:0] S;
wire Cout;
initial
begin
$monitor("Status: %s \t, T: %t \t,A:%d\t + B:%d\t + Cin:%d\t = Sum:%d\t , Caryy:%d",
(A+B+Cin) == {Cout,S} ? "Success":"Failure",$time,A,B,Cin,S,Cout);
initial
begin
$monitor("Status: %s \t, T: %t \t,A:%d\t + B:%d\t + Cin:%d\t = Sum:%d\t , Caryy:%d",
(A+B+Cin) == {Cout,S} ? "Success":"Failure",$time,A,B,Cin,S,Cout);
initial
begin
$monitor("Status: %s \t, T: %t \t,A:%d\t + B:%d\t + Cin:%d\t = Sum:%d\t , Caryy:%d",
(A+B+Cin) == {Cout,S} ? "Success":"Failure",$time,A,B,Cin,S,Cout);
initial
begin
$monitor("Status: %s \t, T: %t \t,A:%d\t + B:%d\t + Cin:%d\t = Sum:%d\t , Caryy:%d",
(A+B+Cin) == {Cout,S} ? "Success":"Failure",$time,A,B,Cin,S,Cout);