Lecture 4 - SystemVerilog-2up
Lecture 4 - SystemVerilog-2up
An Overview of SystemVerilog
for Design and Verification
Vighnesh Iyer, EECS 251B
1
1/26/2022
What is SystemVerilog
2
1/26/2022
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
3
1/26/2022
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);
4
1/26/2022
More on Enums
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
10
5
1/26/2022
11
12
6
1/26/2022
Structs
● Similar to Bundle in Chisel
○ Allows designer to group nets together, helps encapsulation of signals, easy declaration
○ Can be used within a module or in a module’s ports
○ Structs themselves can’t be parameterized
■ but can be created inside a parameterized module/interface
13
Interfaces
14
7
1/26/2022
Modports
15
16
8
1/26/2022
Unique
● Sometimes we want to make sure synthesis infers parallel logic vs priority mux
● The ‘unique’ keyword applied to a ‘if’ or ‘case’ statement
○ Adds simulation assertions to make sure only one branch condition is true
○ Tells synthesis tools to operate under that assumption
○ Legacy: ‘synopsys parallel_case full_case’
always_comb begin
unique if (x == 2’b10) a = ____;
else if (y && x == 2’b11) a = ____;
else a = ____;
end
17
Packages / Namespacing
● Verilog has a global namespace
○ Often naming conflicts in large projects
○ `include is hacky and requires `ifdef guards
● SystemVerilog allows you to encapsulate constructs in a package
○ modules, functions, structs, typedefs, classes
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
18
9
1/26/2022
19
Overview
20
10
1/26/2022
21
Dynamic Arrays
arr = new[10];
arr[3] = 4;
end
22
11
1/26/2022
Queues
23
Associative Arrays
fruits[“apple”]
fruits.exists(“lemon”)
fruits.delete(“orange”)
24
12
1/26/2022
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
25
OOP in SystemVerilog
class Message;
initial begin
bit [31:0] addr;
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
26
13
1/26/2022
More OOP
27
28
14
1/26/2022
29
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
30
15
1/26/2022
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
31
System Functions
32
16
1/26/2022
Sequences
● Properties are made up of sequences + an implication
○ Many interfaces come with sequence libraries you can use to build complex properties
module cpu();
sequence stall
mem_stall;
endsequence
sequence unchanged_pc
##1 $stable(pc);
endsequence
property stall_holds_pc
@(posedge clk) stall |-> unchanged_pc;
endproperty
33
Sequence Combinators
● Sequences are the core of SVA: they describe temporal RTL behavior
● Sequences can be combined with temporal operators
a ##1 b // a then b on the next cycle
a ##N b // a then b on the Nth cycle
a ##[1:4] b // a then b on the 1-4th subsequent cycle
a ##[2:$] b // a then b after 2 or more cycles
34
17
1/26/2022
Coverage APIs
35
Coverage
36
18
1/26/2022
Property Coverage
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?
37
endmodule
38
19
1/26/2022
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
39
Transaction-Level Modeling
40
20
1/26/2022
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
41
42
21
1/26/2022
43
Constrained Random
● 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
44
22
1/26/2022
constraint values {
foreach(data[i]) {
data[i] == i + 1;
data[i] inside {[0:8]};
}
}
endclass
45
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
46
23
1/26/2022
Testbench Example
47
Register Bank
48
24
1/26/2022
VIP Implementation
class driver; class monitor;
virtual reg_if vif; virtual reg_if vif;
mailbox drv_mbx; mailbox mon_mbx;
49
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
50
25
1/26/2022
Conclusion
51
References
https://en.wikipedia.org/wiki/SystemVerilog
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
52
26
1/26/2022
53
Addendum Points
54
27
1/26/2022
Tagged Unions
55
28