(System) Verilog Tutorial: Aleksandar Milenković
(System) Verilog Tutorial: Aleksandar Milenković
(System) Verilog Tutorial: Aleksandar Milenković
AleksandarMilenkovi
TheLaCASA Laboratory ElectricalandComputerEngineeringDepartment TheUniversityofAlabamainHuntsville Email:[email protected] Web:http://www.ece.uah.edu/~milenka http://www.ece.uah.edu/~lacasa
Outline
Introduction CombinationalLogic SequentialLogic Memories Testbenches
Introduction
Verilog isaHardwareDescriptionLanguage(HDL) HDLs areusedforlogicsimulationandsynthesis
Simulation:inputsareappliedtoamoduleandtheoutputs arecheckedtoverifythatthemoduleoperatescorrectly Synthesis:thetextualdescriptionofamoduleis transformedintologicgates
Allowdescriptionofadigitalsystemat
BehavioralLevel describeshowtheoutputsarecomputed asfunctionsoftheinputs StructuralLevel describeshowamoduleiscomposedof simplermodulesofbasicprimitives(gatesortransistors)
Designstyles:TopDownvs.BottomUp
3
History
DevelopedbyPhilMoorby atGatewayDesignAutomation asaproprietarylanguageforlogicsimulationin1984 GatewayisacquiredbyCadencein1989 Madeanopenstandardin1990underthecontrolof OpenVerilog International BecameanIEEEstandardin1995and Updatedin2001[IEEE136401] In2005,itwasupdatedagainwithminorclarifications SystemVerilog [IEEE18002009]wasintroduced
StreamlinesmanyoftheannoyancesofVerilog and addshighlevelprogramminglanguagefeatures thathaveprovenusefulinverification
4
Modules
Ablockofhardwarewithinputs andoutputsiscalledamodule Amodulebeginswithalistingof theinputsandoutputs assign statementdescribes combinationallogic
~indicatesNOT,&indicatesAND, and|indicatesOR logicsignalssuchastheinputs andoutputsareBooleanvariables (0or1).Theymayalsohave floating(z)andundefinedvalues (x).
module sillyfunction(input logic a, b, c, output logic y); assign y = ~a & ~b & ~c | a & ~b & ~c | a & ~b & c; endmodule
Thelogictypewasintroducedin SystemVerilog
Itsupersedesthereg type,which wasaperennialsourceof confusioninVerilog shouldbeusedeverywhere exceptonnetswithmultiple drivers
CombinationalLogic
Operators:&,|,~,^ Operands:a,b,y1y5 Expressions:e.g.,(a&b) Statements:e.g.,y5=~(a|b); Assign statementimplies combinationallogic Assign indicatesa continuousassignment statement
Lefthandsideofexpressionis updatedanytimetheright handsidechanges(aorb)
module gates(input logic [3:0] a, b, output logic [3:0] y1, y2, y3, y4, y5); /* Five different two-input logic gates acting on 4 bit busses */ assign y1 = a & b; // AND assign y2 = a | b; // OR assign y3 = a ^ b; // XOR assign y4 = ~(a & b); // NAND assign y5 = ~(a | b); // NOR endmodule
CombinationalLogic(contd)
// full adder module fa (input logic a, b, cin, output logic s, cout); assign s = a ^ b ^ cin; assign cout = (a & b) | (cin & (a | b)); endmodule
Comments
Commentsbeginningwith/* continue,possiblyacrossmultiple lines,tothenext*/ Commentsbeginningwith//continue totheendoftheline
SystemVerilog iscasesensitive
y1andY1aredifferentsignals
Conditionalassignment
conditionaloperator?: chooses,based onafirstexpression,betweena secondandthirdexpression Thefirstexpressioniscalledthe condition.Iftheconditionis1,the operatorchoosesthesecond expression.Iftheconditionis0,the operatorchoosesthethirdexpression Equivalenttothisexpression: Ifs=1,theny=d1. Ifs=0,theny=d0.
/* 4-bit mux; selects one of two 4-bit inputs d0 or d1 */ module mux2_4 (input logic [3:0] d0, d1, input logic s, output logic [3:0] y); assign y = s ? d1 : d0; endmodule
CombinationalLogic(contd)
module and8 (input logic [7:0] a, output logic y); assign y = & a; // &a is much easier to write than // assign y = a[7] & a[6] & a[5] & a[4] // & a[3] & a[2] & a[1] & a[0]; endmodule
CombinationalLogic(contd)
/* 32-bit adder */ module adder (a, b, y); input logic [31:0] a; input logic [31:0] b; output logic [31:0] y; assign y = a + b; endmodule
/* */ module whatami(input logic [3:0] d0, d1, d2, d3, input logic [1:0] s, output logic [3:0] y); assign y = s[1] ? (s[0] ? d3 : d2) : (s[0] ? d1 : d0); endmodule
CombinationalLogic(contd)
module fulladder(input logic a, b, cin, output logic s, cout); logic p, g; assign assign assign assign endmodule p = a ^ b; g = a & b; s = p ^ cin; cout = g | (p & cin);
Internalvariables
Neitherinputsoroutputs
Concurrency
Orderofassignstatements doesnotmatter
10
Verilog OperatorsandOperatorPrecedence
Similartoprecedenceinother languages
assigncout =g|p&cin;
Subtractioninvolvesatwos complementandaddition Multipliersandshiftersuse substantiallymorearea(unless theyinvolveeasyconstants) Divisionandmodulusinhardware issocostlythatitmaynotbe synthesizable Equalitycomparisons(==)implyN 2inputXORs todetermine equalityofeachbitandanNinput ANDtocombineallofthebits Relativecomparisoninvolvesa subtraction
11
Verilog Numbers
SystemVerilog numberscanspecifytheir baseandsize(thenumberofbitsusedto representthem) TheformatfordeclaringconstantsisN'Bvalue
Nisthesizeinbits Bisthebase,and Valuegivesthevalue 9'h25indicatesa9bithexnumber(37 decimalor000100101inbinary)
12
ZsandXs
Zindicatesafloatingvalue
Usefulfordescribingatristate buffer; itsoutputfloatswhentheenableis0 Abuscanbedrivenbyseveraltristate buffers,exactlyoneofwhichshould beenabled
module tristate(input logic [3:0] a, input logic en, output tri [3:0] y); assign y = en ? a : 4'bz; endmodule
Twotypesofnets:tri andtrireg
Onedriverisactiveatatime,andthe nettakesthatvalue; Ifnodriversareenabled,thetrinet floats(z),whilethetrireg netretains thepreviousvalue
Ifnotypeisspecifiedforaninputor output,triisassumed
13
ZsandXs(contd)
SystemVerilog ANDgatetruthtable
Bitswizzling
assign y = {c[2:1], {3{d[0]}}, c[0], 3'b101};
module mul(input logic [7:0] a, b, output logic [7:0] upper, lower); assign {upper, lower} = a*b; endmodule
module signextend(input logic [15:0] a, output logic [31:0] y); assign y = {{16{a[15]}}, a[15:0]}; endmodule
15
Delays
`timescale 1ns/1ps module example(input logic a, b, c, output logic y); logic ab, bb, cb, n1, n2, n3; assign assign assign assign assign endmodule #1 #2 #2 #2 #4 {ab, bb, cb} = ~{a, b, c}; n1 = ab & bb & cb; n2 = a & bb & cb; n3 = a & bb & c; y = n1 | n2 | n3;
Delaysareignoredduringsynthesis
Delayofagateproducedbythe synthesizerdependsonitstpd andtcd specifications
Timescaledirective
`timescaleunit/step
#symbolisusedtoindicatethe numberofunitsofdelay
Itcanbeplacedinassignstatements, aswellasnonblocking (<=)and blocking(=)assignments
16
StructuralModel
Describeamoduleintermsofhow itiscomposedofsimplermodules Mux4outofMux2s TryDec4to16usingDec2to4s?
module mux2_4 (input logic [3:0] d0, d1, input logic s, output logic [3:0] y); assign y = s ? d1 : d0; endmodule
module mux4_4 (input logic [3:0] d0, d1, d2, d3, input logic [1:0] s, output logic [3:0] y); logic [3:0] mol, moh; mux2_4 lowmux(d0, d1, s[0], mol); mux2_4 highmux(d2, d3, s[0], moh); mux2_4 finalmux(mol, moh, s[1], y); endmodule
17
StructuralModeling
module tristate_4 (input logic [3:0] a, input logic en, output tri [3:0] y); assign y = en ? a : 4bz; endmodule // demonstrate selection of ranges on a bus module mux2_8 (input logic [7:0] d0, d1, input logic s, output logic [7:0] y); mux2_4 lsbmux(d0[3:0], d1[3:0], s, y[3:0]); mux2_4 msbmux(d0[7:4], d1[7:4], s, y[7:4]); // mux2 using tristate module mux2_4 (input logic [3:0] d0, d1, input logic s, output tri [3:0] y); tristate(d0, ~s, y); tristate(d1, s, y); endmodule endmodule
18
SequentialLogic
HDLsynthesizersrecognizecertainidiomsandturnthem intospecificsequentialcircuits Othercodingstylesmaysimulatecorrectly,butsynthesize intocircuitswithblatantorsubtleerrors Note:Usetheproperidiomstodescriberegistersand latchesdescribedhere
19
Registers
4bitregister
module flop(input logic clk, input logic [3:0] d, output logic [3:0] q); always_ff @(posedge clk) q <= d; endmodule
alwaysstatementform:
always@(sensitivitylist)statement;
<=iscalledanonblocking assignment
Agroupofnonblocking assignmentsis evaluatedconcurrently alloftheexpressionsontheright handsidesareevaluatedbeforeany ofthelefthandsidesareupdated
20
Flipflops
DFFwith PositiveClock
module flop (C, D, Q); input C, D; output Q; reg Q;
DFFwithNegativeedgeClock andAsync.Clear
module flop (C, D, CLR, Q); input C, D, CLR; output Q; reg Q;
always @(negedge C or posedge CLR) begin if (CLR) Q = 1'b0; else Q = D; end endmodule
21
Flipflops
DFFwithPositiveEdgeClockand SynchronousSet
module flop (C, D, S, Q); input C, D, S; output Q; reg Q; always @(posedge C) begin if (S) Q = 1'b1; else Q = D; end endmodule
DFFwithPositiveEdgeClockand ClockEnable
module flop (C, D, CE, Q); input C, D, CE; output Q; reg Q;
22
ResettableRegisters
module flopr_s(input logic clk, input logic reset, input logic [3:0] d, output logic [3:0] q); // synchronous reset always_ff @(posedge clk) if (reset) q <= 4'b0; else q <= d; endmodule module flopr_a(input logic clk, input logic reset, input logic [3:0] d, output logic [3:0] q); // asynchronous reset always_ff @(posedge clk, posedge reset) if (reset) q <= 4'b0; else q <= d; endmodule
Note:
Synchronousresettakesfewer transistorsandreducestheriskof timingproblemsonthetrailingedge ofreset However,ifclockgatingisused,care mustbetakenthatallflipflops reset properlyatstartup
23
EnabledResettableRegisters
module flopenr(input logic clk, input logic reset, input logic en, input logic [3:0] d, output logic [3:0] q); // synchronous reset always_ff @(posedge clk) if (reset) q <= 4'b0; else if (en) q <= d; endmodule
24
SynchronizerCircuit
module sync(input logic clk, input logic d, output logic q); logic n1;
25
Latches
LatchwithPositiveGate
module latch (G, D, Q); input G, D; output Q; reg Q;
LatchwithPositiveGateand AsynchronousClear
module latch (G, D, CLR, Q); input G, D, CLR; output Q; reg Q;
always @(G or D or CLR) begin if (CLR) Q = 1'b0; else if (G) Q = D; end endmodule
26
4bitLatch
4bitLatchwithInvertedGateand AsynchronousPreset
module latch (G, D, PRE, Q); input G, PRE; input [3:0] D; output [3:0] Q; reg [3:0] Q;
always @(G or D or PRE) begin if (PRE) Q = 4'b1111; else if (~G) Q = D; end endmodule
27
4bitLatch
always_latch
module latch(input logic clk, input logic [3:0] d, output logic [3:0] q); always_latch if (clk) q <= d; endmodule
28
Counters
module counter(input logic clk, input logic reset, output logic [3:0] q); always_ff @(posedge clk) if (reset) q <= 4'b0; else q <= q+1; endmodule module counter(input logic clk, input logic reset, output logic [3:0] q); logic [3:0] nextq; flopr qflop(clk, reset, nextq, q); adder inc(q, 4'b0001, nextq); endmodule
29
Shifters
module shiftreg(input logic clk, input logic reset, load, input logic sin, input logic [3:0] d, output logic [3:0] q, output logic sout); always_ff @(posedge clk) if (reset) q <= 0; else if (load) q <= d; else q <= {q[2:0], sin}; assign sout = q[3]; endmodule
30
CombinationalLogicwithAlwaysBlocks
always_comb
module inv(input logic [3:0] a, output logic [3:0] y); always_comb y = ~a; endmodule
module fulladder(input logic a, b, cin, output logic s, cout); logic p, g; always_comb begin p = a ^ b; // blocking g = a & b; // blocking s = p ^ cin; cout = g | (p & cin); end endmodule
Modelcombinationallogic Reevaluatesthestatements insidethealwaysblockanytime anyofthesignalsontheright handsideof<=or=insidethe alwaysstatementchange Preferredwayofdescribing combinationallogicin SystemVerilog Equivalenttoalways@(*)
=inthealwaysstatementiscalled ablockingassignment
Preferredforcombinationallogic inSystemVerilog
31
TriState
module three_st (T, I, O); input T, I; output O; reg O; module three_st (T, I, O); input T, I; output O;
32
Muxes
module mux2( input d0, d1, s, output y); module mux2( input d0, d1, s, output y); reg y;
reg y;
always @(s or d0 or d1) begin : MUX case(s) 1'b0 : y = d0; 1'b1 : y = d1; endcase end endmodule
always @(*) begin : MUX case(s) 1'b0 : y = d0; 1'b1 : y = d1; endcase end endmodule
33
CaseStatements
module sevenseg(input logic [3:0] data, output logic [6:0] segments); always_comb case (data) // abc_defg 0: segments = 7'b111_1110; 1: segments = 7'b011_0000; 2: segments = 7'b110_1101; 3: segments = 7'b111_1001; 4: segments = 7'b011_0011; 5: segments = 7'b101_1011; 6: segments = 7'b101_1111; 7: segments = 7'b111_0000; 8: segments = 7'b111_1111; 9: segments = 7'b111_1011; default: segments = 7'b000_0000; endcase endmodule module decoder3_8(input logic [2:0] a, output logic [7:0] y); always_comb case (a) 3'b000: y 3'b001: y 3'b010: y 3'b011: y 3'b100: y 3'b101: y 3'b110: y 3'b111: y endcase endmodule
= = = = = = = =
34
Ifelse,Casez
module priorityckt(input logic [3:0] a, output logic [3:0] y); always_comb if (a[3]) y = 4'b1000; else if (a[2]) y = 4'b0100; else if (a[1]) y = 4'b0010; else if (a[0]) y = 4'b0001; else y = 4'b0000; endmodule module priority_casez(input logic [3:0] a, output logic [3:0] y); always_comb casez(a) 4'b1???: 4'b01??: 4'b001?: 4'b0001: default: endcase endmodule
y y y y y
= = = = =
35
BlockingandNonblockingAssignments
Blockingassignments(use=)
Agroupofblockingassignments insideabeginendblockisevaluatedsequentially
Nonblockingassignments(use<=)
Agroupofnonblockingassignmentsareevaluatedin parallel;allofthestatementsareevaluatedbeforeanyof theleftsidesareupdated.
36
Blockingvs.Nonblocking
1.Usealways_ff @(posedge clk) andnonblocking assignmentsto modelsynchronoussequential logic 2.Usecontinuousassignmentsto modelsimplecombinationallogic Usealways_comb andblocking assignmentstomodelmore complicatedcombinationallogic wherethealwaysstatementis helpful 4.Donotmakeassignmentsto thesamesignalinmorethanone alwaysstatementorcontinuous assignmentstatement.Exception: tristate busses.
always_ff @(posedge clk) begin n1 <= d; // nonblocking q <= n1; // nonblocking end
assign y = s ? d1 : d0;
always_comb begin p = a ^ b; // blocking g = a & b; // blocking s = p ^ cin; cout = g | (p & cin); end
37
Blockingvs.Nonblocking (contd)
// nonblocking assignments (not recommended) module fulladder(input logic a, b, cin, output logic s, cout); logic p, g; always_comb begin p <= a ^ b; // nonblocking g <= a & b; // nonblocking s <= p ^ cin; cout <= g | (p & cin); end endmodule a=b=cin=0; // initial conditions p=g=0; a=1; // a changes => trigger always block -------/* all nonblocking assignments are concurently executed; all assume a=1, b=0, cin=0 */ p<=1; // sch. change for next delta (1) g<=0; // no changes s<=0; // no changes cout<=0; // no changes --------------/* move time; p has changed, re-evaluate always block again) (a=1, p=1)*/ .... module fulladder(input logic a, b, cin, output logic s, cout); logic p, g; always_comb begin p = a ^ b; // blocking g = a & b; // blocking s = p ^ cin; cout = g | (p & cin); end a=b=cin=0; // initial conditions a=1; // a changes => trigger always block /* Note that p and g get their new value before s and cout are computed because of the blocking assignments. This is important because we want to compute s and cout using the new values of p and g.*/ ----------------p=1; // immediate assignment g=0; s=1; cout=0;
38
Blockingvs.Nonblocking (contd)
module sync(input logic clk, input logic d, output logic q); logic n1; logic n1; always_ff @(posedge clk) begin n1 <= d; q <= n1; end endmodule always_ff @(posedge clk) begin n1 = d; // blocking q = n1; // blocking end endmodule // Bad implementation using blocking assignments module syncbad(input logic clk, input logic d, output logic q);
39
Blockingvs.Nonblocking (contd)
module shiftreg (input clk, input sin, output reg [3:0] q); always @(posedge clk) begin q[0] <= sin; q[1] <= q[0]; q[2] <= q[1]; q[3] <= q[2]; // could be replaced by // q <= {q[2:0], sin} end endmodule end endmodule // this is incorrect shift register module shiftreg (input clk, input sin, output reg [3:0] q); always @(posedge clk) begin q[0] = sin; q[1] = q[0]; q[2] = q[1]; q[3] = q[2];
40
FiniteStateMachines
41
MooreMachine
module divideby3FSM(input logic clk, input logic reset, output logic y); logic [1:0] state, nextstate; // State Register always_ff @(posedge clk) if (reset) state <= 2'b00; else state <= nextstate; // Next State Logic always_comb case (state) 2'b00: nextstate = 2'b01: nextstate = 2'b10: nextstate = default: nextstate endcase
42
MooreMachine
module divideby3FSM(input logic clk, input logic reset, output logic y); typedef enum logic [1:0] {S0, S1, S2} statetype; statetype state, nextstate; // State Register always_ff @(posedge clk) if (reset) state <= S0; else state <= nextstate; // Next State Logic always_comb case (state) S0: nextstate = S1; S1: nextstate = S2; S2: nextstate = S0; default: nextstate = S0; endcase // Output Logic assign y = (state == S0); endmodule
typedef definesstatetype to beatwobitlogicvaluewith oneofthreepossibilities:S0, S1,orS2 stateandnextstate are statetype signals Enumeratedencodingsdefault tonumericalorder:S0=00,S1 =01,andS2=10 Theencodingscanbeexplicitly setbytheuser
Thefollowingsnippet encodesthestatesas3bit onehotvalues: typedef enum logic[2:0]{S0= 3'b001,S1=3'b010,S2= 3'b100}statetype;
43
MealyMachine
Identify3portions
Stateregister Nextstatelogic Outputlogic
Stateregister
Resetsasynchronouslytothe initialstate Otherwiseadvancestothenext state
Nextlogic
Computesthenextstateasa functionofthecurrentstateand inputs
Outputlogic
Computestheoutputasa functionofthecurrentstateand theinputs
44
MealyMachine(contd)
module historyFSM(input logic clk, input logic reset, input logic a, output logic x, y); typedef enum logic [2:0] {S0, S1, S2, S3, S4} statetype; statetype state, nextstate; always_ff @(posedge clk) if (reset) state <= S0; else state <= nextstate; always_comb case (state) S0: if (a) nextstate else nextstate = S1: if (a) nextstate else nextstate = S2: if (a) nextstate else nextstate = S3: if (a) nextstate else nextstate = S4: if (a) nextstate else nextstate = default: nextstate = endcase 45 //output logic assign x = (state[1] & ~a) | (state[2] & a); assign y = (state[1] & state[0] & ~a) | (state[2] & state[0] & a);
endmodule
= S3; S1; = S3; S2; = S3; S2; = S4; S1; = S4; S1; S0;
TypeIdiosyncracies
StandardVerilog primarilyuses twotypes:reg andwire
reg signalmightormightnotbe associatedwitharegister Wasagreatsourceofconfusion forthoselearningthelanguage
module flop(input clk, input [3:0] d, output reg [3:0] q); always @(posedge clk) q <= d; endmodule
InstandardVerilog
ifasignalappearsontheleft handsideof<=or=inanalways block,itmustbedeclaredasreg Otherwise,itshouldbedeclared aswire Inputandoutputportsdefaultto thewiretypeunlesstheirtypeis explicitlyspecifiedasreg
46
TypeIdiosyncracies (contd)
SystemVerilog introducedthelogictype
logicisasynonymforreg
Logiccanbeusedoutsidealwaysblocks whereawiretraditionallywouldberequired
NearlyallSystemVerilog signalscanbe logic
Themostcommontypeofnetiscalledawire ortri
Synonymous,butwireisconventionally usedwhenasingledriverispresentandtri isusedwhenmultipledriversarepresent wireisobsoleteinSystemVerilog =>use logic
Typesandnetresolution(seetable)
47
ParameterizedModules
2waymux,defaultwidth8
module mux2 #(parameter width = 8) (input logic [width-1:0] d0, d1, input logic s, output logic [width-1:0] y); assign y = s ? d1 : d0; endmodule // use default widths module mux4_8(input logic [7:0] d0, d1, d2, d3, input logic [1:0] s, output logic [7:0] y); logic [7:0] low, hi; mux2 lowmux(d0, d1, s[0], low); mux2 himux(d2, d3, s[0], hi); mux2 outmux(low, hi, s[1], y); endmodule
// 12-bit mux; override default using #() module mux4_12(input logic [11:0] d0, d1, d2, d3, input logic [1:0] s, output logic [11:0] y); logic [11:0] low, hi; mux2 #(12) lowmux(d0, d1, s[0], low); mux2 #(12) himux(d2, d3, s[0], hi); mux2 #(12) outmux(low, hi, s[1], y); endmodule
48
ParameterizedModules
module decoder #(parameter N = 3) (input logic [N-1:0] a, output logic [2**N-1:0] y); always_comb begin y = 0; y[a] = 1; end endmodule
49
GenerateStatement
module andN #(parameter width = 8) (input logic [width-1:0] a, output logic y); genvar i; logic [width-1:1] x; generate for (i=1; i<width; i=i+1) begin:forloop if (i == 1) assign x[1] = a[0] & a[1]; else assign x[i] = a[i] & x[i-1]; end endgenerate assign y = x[width-1]; endmodule
Generatestatementsproduce avariableamountofhardware dependingonthevalueofa parameter Generatesupportsforloops andifstatementstodetermine howmanyofwhattypesof hardwaretoproduce Example:NinputANDfunction fromacascadeof2inputANDs
50
Memories
// separate read and write busses module ram #(parameter N = 6, M = 32) (input logic clk, input logic we, input logic [N-1:0] adr, input logic [M-1:0] din, output logic [M-1:0] dout); logic [M-1:0] mem[2**N-1:0]; always @(posedge clk) if (we) mem[adr] <= din; assign dout = mem[adr]; endmodulev // bidirectional bus module ram #(parameter N = 6, M = 32) (input logic clk, input logic we, input logic [N-1:0] adr, inout tri [M-1:0] data); logic [M-1:0] mem[2**N-1:0]; always @(posedge clk) if (we) mem[adr] <= data; assign data = we ? 'z : mem[adr]; endmodule
51
MultiportedRegisterFiles,ROMs
module ram3port #(parameter N = 6, M = 32) (input logic clk, input logic we3, input logic [N-1:0] a1, a2, a3, output logic [M-1:0] d1, d2, input logic [M-1:0] d3); logic [M-1:0] mem[2**N-1:0]; always @(posedge clk) if (we3) mem[a3] <= d3; assign d1 = mem[a1]; assign d2 = mem[a2]; endmodule module rom(input logic [1:0] adr, output logic [2:0] dout); always_comb case(adr) 2'b00: dout 2'b01: dout 2'b10: dout 2'b11: dout endcase endmodule
= = = =
52
Testbench
Testbench isanHDLmoduleused totestanothermodule,calledthe deviceundertest(DUT) Containsstatementstoapply inputstotheDUTand,ideally,to checkthatthecorrectoutputsare produced
Inputanddesiredoutputpatterns arecalledtestvectors.
module testbench1(); logic a, b, c; logic y; // instantiate device under test sillyfunction dut(a, b, c, y); // apply inputs one at a time initial begin a = 0; b = 0; c = 0; #10; c = 1; #10; b = 1; c = 0; #10; c = 1; #10; a = 1; b = 0; c = 0; #10; c = 1; #10; b = 1; c = 0; #10; c = 1; #10; end endmodule
53
SelfCheckingTestbench
Checkingforcorrectoutputsby handistediousanderrorprone Determiningthecorrectoutputsis mucheasierwhenthedesignis freshinyourmind =>Amuchbetterapproachisto writeaselfcheckingtestbench SystemVerilog assertstatement checksifaspecifiedconditionis true
Ifitisnot,itexecutestheelse statement. $errorsystemtaskintheelse statementprintsanerror messagedescribingthe assertionfailure
module testbench2(); logic a, b, c; logic y; // instantiate device under test sillyfunction dut(a, b, c, y); // apply inputs one at a time // checking results initial begin a = 0; b = 0; c = 0; #10; assert (y === 1) else $error("000 c = 1; #10; assert (y === 0) else $error("001 b = 1; c = 0; #10; assert (y === 0) else $error("010 c = 1; #10; assert (y === 0) else $error("011 a = 1; b = 0; c = 0; #10; assert (y === 1) else $error("100 c = 1; #10; assert (y === 1) else $error("101 b = 1; c = 0; #10; assert (y === 0) else $error("110 c = 1; #10; assert (y === 0) else $error("111 end endmodule
54
Testbench withTestVectorFile
module testbench3(); logic clk, reset; logic a, b, c, yexpected; logic y; logic [31:0] vectornum, errors; logic [3:0] testvectors[10000:0]; // instantiate device under test sillyfunction dut(a, b, c, y); // generate clock always begin clk = 1; #5; clk = 0; #5; end // at start of test, load vectors // and pulse reset initial begin $readmemb("example.tv", testvectors); vectornum = 0; errors = 0; reset = 1; #27; reset = 0; end
example.tv
000_1 001_0 010_0 011_0 100_1 101_1 110_0 111_0
55
Testbench withTestVectorFile(contd)
// apply test vectors on rising edge of clk always @(posedge clk) begin // wait for 1 time unit before assignment #1; {a, b, c, yexpected} = testvectors[vectornum]; end // check results on falling edge of clk always @(negedge clk) if (~reset) begin // skip during reset if (y !== yexpected) begin $display("Error: inputs = %b", {a, b, c}); $display(" outputs = %b (%b expected)", y, yexpected); errors = errors + 1; end vectornum = vectornum + 1; if (testvectors[vectornum] === 'bx) begin $display("%d tests completed with %d errors", vectornum, errors); $finish; end end endmodule
$readmemb readsafileof binarynumbersintoanarray $readmemh readsafileof hexadecimalnumbersintoan array #1;waitsonetimeunitafter therisingedgeoftheclock(to avoidanyconfusionofclock anddatachanging simultaneously) $displayisasystemtaskto printinthesimulatorwindow $finishterminatesthe simulation Notehowweterminate simulationafter8testvectors
56