Lecture 4 - SystemVerilog
Lecture 4 - SystemVerilog
wire a; logic a, b, c;
reg b, c; assign a = ____;
assign a = ____; always @(* ) b = ____;
always @(* ) b = ____; always @(posedge clk) c <= ____;
always @(posedge clk) c <= ____;
Coding style is used to verify that c infers New always_comb and always_ff
as a register and b as comb logic statements for safety
Autoconnect (Implicit Port Connections)
reg a, b; wire c;
mod x (.a(a), .b(b), .c(c));
● If the net names and their corresponding port names match, there’s a shortcut
mod x ( . a , . b, . c) ;
module memory (
input [ 4: 0] addr,
input mem_op_t op,
input [ 31: 0] din,
output logic [ 31: 0] dout
);
● Note that input/output net types are by default ‘wire’, you can override them as
logic
Even More on Enums
package my_pkg;
typedef enum logic [ 1: 0] { STATE[ 4] } state_t; import my_pkg::* ;
function show_vals();
state_t s = STATE0; module ex ( input clk);
for ( int i = 0; i < s.num; i = i + 1) begin state_t s;
$display (s.name()); always_ff @(posedge clk) begin
s = s.next(); s <= STATE0;
end end
endfunction endmodule
endpackage
SystemVerilog for Verification
Overview
bit [ 3: 0] a r r [ ] ; / / a dy na mi c a r r a y of 4 bi t v a l ue s
initial begin
a r r = new[ 2] ; / / s i z e t he a r r a y f or 2 el ement s
a r r = ‘ { 12, 10} ; / / l i t e r a l a s s i gnme nt
a r r = new[ 10] ;
a r r [ 3] = 4;
end
Queues
fruits[ “ apple ” ]
fruits.exists( “ lemon ” )
fruits.delete( “ orange ” )
Clocking Blocks
● There is often confusion when you should drive DUT inputs and sample DUT
outputs relative to the clock edge
○ Solution: encode the correct behavior in the interface by using clocking blocks
class Message;
bit [ 31: 0] addr; initial begin
msg = new Message( 32’ d4,
bit [ 3: 0] wr_strobe;
4’ b1111);
bit [ 3: 0] burst_mode; $display (msg.burst_mode);
bit [ 31: 0] data [ 4]; end
module testbench();
dut d (.addr, .dout);
● But how do I express properties that involve
initial begin the uArch of the RTL?
addr = ‘ h40; ● Can I express these properties (e.g. req-ack)
assert (dout == ‘ hDEADBEEF);
end
in a concise way?
endmodule
Concurrent Assertions
module cpu();
assert property @(posedge clk) mem_addr[ 1: 0] != 2’ d0 && load_word | - > unaligned_load
assert property @(posedge clk) opcode == 0 | - > take_exception
assert property @(posedge clk) mem_stall |=> $stable(pc)
endmodule
sequence unchanged_pc
##1 $stable(pc);
endsequence
property stall_holds_pc
@(posedge clk) stall | - > unchanged_pc;
endproperty
● Sequences are the core of SVA: they describe temporal RTL behavior
● Sequences can be combined with temporal operators
a ## 1 b / / a t hen b on t he nex t c y c l e
a # # N b / / a t hen b on t he Nt h c y c l e
a # # [ 1: 4] b / / a t hen b on t he 1- 4t h s ubs equent c y c l e
a # # [ 2: $] b / / a t hen b a f t er 2 or mor e c y c l es
s 1 and s 2 / / s equenc e s 1 a nd s 2 s uc c ee d
s 1 intersect s 2 / / s equenc e s 1 a nd s 2 s uc c ee d a nd end a t t he s a me t i me
s 1 or s 2 / / s equenc e s 1 or s 2 s uc c ee ds
property req_ack;
req ##[ 1: 10] ack
endproperty
cover property (req_ack)
● Property covers are used in RTL to check that some multi -cycle uArch
behavior is exercised
○ e.g. did this req-ack handshake ever occur?
○ e.g. did a branch mispredict and predictor update happen?
Coverpoints and Covergroups
logic [ 2: 0] funct3; 10 10 10
endmodule
Coverpoint Bins
● Sometimes we don’t want to track each value a net can take on individually
○ Use the bins API to group some values together
module alu( input [ 31: 0] a, input [ 31: 0] b, input [ 3: 0] op, output [ 31: 0] out);
covergroup c();
coverpoint a{
bins zero = { 0};
bins max = { 32’ hffff_ffff};
// automatically allocate 100 uniformly sized bins for the remaining numbers
bins in_the_middle[ 100 ] = {[ 1: 32’ hffff_ffff - 1]};
}
endgroup
endmodule
Transaction-Level Modeling
Transactions
● Our testbenches are usually written at cycle-granularity
○ Leads to mixing of driving/monitoring protocols, timing details, golden modeling, and stimulus
○ Each of these concerns should be separated
● Model a single interaction with the DUT as a ‘transaction’
○ It can take multiple cycles
● We can build a stimulus generator and golden model at transaction-level
class MemReqTx();
bit [ 31: 0] addr;
bit [ 31: 0] wr_data; class Mem();
mem_op op; bit [ 31: 0] ram [];
endclass function MemRespTx processTx(MemReqTx tx);
endclass
class MemRespTx();
bit [ 31: 0] rd_data;
endclass
VIPs and Testbench Architecture
● You can constrain the random fields of a class inside or outside the class
○ You can add ad-hoc constraints when calling .randomize
class cls;
rand bit [ 7: 0] min, typ, max;
constraint range {
0 < min; typ < max; typ > min; max < 128 ;
}
extern constraint extra;
endclass
constraint values {
foreach (data[i]) {
data[i] == i + 1;
data[i] inside {[ 0: 8]};
}
}
endclass
module example;
mailbox #( int ) m = new( 100 );
initial begin
for ( int i = 0; i < 200 ; i ++)
#1 m.put(i);
end
initial begin
for ( int i = 0; i < 200 ; i ++) begin
int i; # 2 m.get(i);
$display (i, m.num());
end
end
endmodule
Testbench Example
Register Bank
taskrun(); taskrun();
@(vif.drv_cb); @(vif.mon_cb);
forever begin if (vif.en) begin
regbank_tx tx; regbank_tx tx = new();
drv_mbx.get(tx); tx.addr = vif.mon_cb.addr;
vif.drv_cb.en <= 1; // assign op and wdata
vif.drv_cb.addr <= tx.addr; if (vif.mon_cb.op == READ) begin
// assign op and wdata @(vif.mon_cb);
@(vif.drv_cb); tx.rdata = vif.mon_cb.rdata;
while ( ! vif.drv_cb.ready) end
@(vif.drv_cb) mon_mbx.put(tx);
end end
endtask endtask
endclass endclass
Top-Level
● A rough sketch of the testbench top
module tb();
regbank dut (. * );
initial begin
// initialize driver/monitor classes
regbank_tx stim [ 100 ];
stim.randomize();
fork
drv.run(); mon.run();
join_none
drv.drv_mbx.put(stim);
while (mon.mon_mbx.size < 100 )
@(dut.drv_cb);
// Pull tx from mon_mbx and check correctness
end
endmodule
Conclusion
https://verificationguide.com/systemverilog/systemverilog-tutorial/
https://www.chipverify.com/systemverilog/systemverilog-tutorial
https://www.doulos.com/knowhow/systemverilog/systemverilog-tutorials/systemverilog-assertions-tutorial/
https://www.systemverilog.io/sva-basics