Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
0% found this document useful (0 votes)
11 views

Lecture 4 - SystemVerilog-2up

The document provides an overview of SystemVerilog, which is an IEEE standard for hardware description and verification. It describes SystemVerilog features for design such as logic types, always blocks, autoconnect, enums, and packed arrays. It also covers features for verification like structs.
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
11 views

Lecture 4 - SystemVerilog-2up

The document provides an overview of SystemVerilog, which is an IEEE standard for hardware description and verification. It describes SystemVerilog features for design such as logic types, always blocks, autoconnect, enums, and packed arrays. It also covers features for verification like structs.
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 28

1/26/2022

An Overview of SystemVerilog
for Design and Verification
Vighnesh Iyer, EECS 251B

Intention of this Lecture

● We use Chisel for all RTL written at Berkeley


○ Why bother with SystemVerilog?
● SystemVerilog is the de-facto industry standard
○ SV/UVM is used for (nearly) all industry verification
○ You will be asked about it in interviews
● Understand basic dynamic verification concepts
● Understand existing SystemVerilog code
● Inspire extensions to HDLs
SystemVerilog (SV) is an IEEE Standard 1800
https://standards.ieee.org/project/1800.html

Universal Verification Methodology (UVM)


is a standard maintained by Accellera
https://www.accellera.org/downloads/standards/uvm

1
1/26/2022

What is SystemVerilog

● IEEE 1800 standard


● A massive extension of Verilog with new constructs for design and verification
○ New data types (for RTL and testbenches)
○ OOP support
○ Constrained random API
○ Specification language
○ Coverage specification API
● Fixing warts in Verilog
○ Synthesis - simulation mismatch
○ Verilog was initially developed as a simulation language; synthesis emerged later

SystemVerilog for Design

2
1/26/2022

Ending the Wire vs. Reg Confusion


Verilog-2005 SystemVerilog
● wire for LHS of assign statements ● logic for LHS of assign statements
● reg for LHS of code inside always @ ● logic for LHS of code inside always @
blocks blocks

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 <= ____;

Both: the containing statement determines if the net is the


direct output of a register or combinational logic

Signal Your Intent With Specific Always Blocks


Verilog-2005 SystemVerilog
always @(*) begin always_comb begin
if (x) b = a if (x) b = a
else b = !a; else b = !a;
end end

always @(posedge clk) begin always_ff @(posedge clk) begin


if (x) c <= !a; if (x) c <= !a;
else c <= a; else c <= a;
end end

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

Autoconnect (Implicit Port Connections)

● How many times have you done this?

module mod (input a, b, output c); endmodule

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);

● In SystemVerilog, there’s a concise shortcut


mod x (.*);

● Implicit connections only work if port names and widths match

Use Enums Over localparams


Verilog-2005 SystemVerilog
localparam STATE_IDLE = 2’b00; typedef enum logic[1:0] {
localparam STATE_A = 2’b01; STATE_IDLE, STATE_A, STATE_B
localparam STATE_B = 2’b10; } state_t;
reg [1:0] state; state_t state;

always @(posedge clk) begin always_ff @(posedge clk) begin


case (state) case (state)
STATE_IDLE: state <= STATE_A; STATE_IDLE: state <= STATE_A
STATE_A: state <= STATE_B; STATE_A: state <= STATE_B;
STATE_B: state <= STATE_IDLE; STATE_B: state <= STATE_IDLE;
endcase endcase
end end

Enums automatically check whether all values can fit. Can


be used as a net type. Add semantic meaning to constants.

4
1/26/2022

More on Enums

● Common to use enums for attaching semantic strings to values

typedef enum logic {


READ, WRITE
} mem_op_t;

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

● You can force enum values to be associated with a specific value


○ To help match up literals for a port that doesn’t use enums

typedef enum logic [1:0] { STATE_IDLE=3, STATE_A=2, STATE_B=1 } state_t

● You can generate N enum values without typing them out


typedef enum logic [1:0] { STATE[3] } state_t
// STATE0 = 0, STATE1 = 1, STATE2 = 2

● You can generate N enum values in a particular range


typedef enum logic [1:0] { STATE[3:5] } state_t
// STATE3 = 0, STATE4 = 1, STATE5 = 2

10

5
1/26/2022

Even More on Enums

● Enums are a first-class datatype in SystemVerilog


○ Enum instances have native functions defined on them
■ next(): next value from current value
■ prev(): previous value from current value
■ num(): number of elements in enum
■ name(): returns a string with the enum’s name (useful for printing using $display)
● They are weakly typechecked
○ You can’t assign a binary literal to a enum type net
● They show up in waveforms
○ No more confusion trying to correlate literals to a semantic name

11

Multidimensional Packed Arrays

● Packed dimensions are to the left of the variable name


○ Packed dimensions are contiguous (e.g. logic [7:0] a)
● Unpacked dimensions are to the right of the variable name
○ Unpacked dimensions are non-contiguous (e.g. logic a [8])

logic [31:0] memory [32];


// memory[0] is 32 bits wide
// cannot represent more than 1 dimension in memory[0]
// can’t easily byte address the memory

logic [3:0][7:0] memory [32];


// memory[0] is 32 bits wide
// memory[0][0] is 8 bits wide
// memory[0][1] is 8 bits wide

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

typedef struct packed {


logic [31:0] din,
ram_cmd a;
logic [7:0] addr,
always_ff @(posedge clk) begin
logic [3:0] wen,
din <= ____
mem_op op
addr <= ____
} ram_cmd;
wen <= ____
op <= ____
module ram ( end
ram_cmd cmd,
logic [31:0] dout
);

13

Interfaces

● Interfaces allow designers to group together ports


○ Can be parameterized
○ Can contain structs, initial blocks with assertions, and other verification collateral
○ Simplify connections between parent and child modules
module ram (
interface ram_if #(int addr_bits, data_bits) ram_if intf
(input clk); );
logic [addr_bits-1:0] addr; always_ff @(posedge intf.clk)
logic [data_bits-1:0] din; intf.dout <= ram[intf.addr];
logic [data_bits-1:0] dout; endmodule
mem_op op;
endinterface module top();
ram_if #(.addr_bits(8), .data_bits(32)) intf();
ram r (.intf(intf));
assign intf.din = ____
endmodule

14

7
1/26/2022

Modports

● But I didn’t specify the direction (input/output) of the interface ports!


○ This can cause multi-driver issues with improper connections
● Solution: use modports
interface ram_if #(int addr_bits, data_bits)
(input clk);
modport slave (
input addr, din, op, clk, module ram (
output dout ram_if.slave intf
); );
always_ff @(posedge intf.clk)
modport master ( intf.dout <= ram[intf.addr];
output addr, din, op, endmodule
input dout, clk
);
endinterface

15

Typedefs (Type Aliases)

● You probably saw ‘typedef’ everywhere


○ typedef is used to expose user-defined types
● Just like with enums, they help attach semantic meaning to your design
● They are just type aliases

typedef signed logic [7:0] sgn_byte;


typedef unsigned logic [3:0] cache_idx;

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

SystemVerilog for Verification

19

Overview

● The SystemVerilog spec for verification is massive


○ We can’t cover everything in one lecture
● New data structures for writing testbenches
○ Parity with PHP
● OOP
● SystemVerilog Assertions
● Coverage API
● Constrained random

20

10
1/26/2022

New Data Types

● bit, shortint, int, longint


○ 2-state types
● string
○ Now natively supported, some helper methods are defined on string (e.g. substr)

21

Dynamic Arrays

● Typical Verilog arrays are fixed length at compile time


bit [3:0] arr [3]; // a 3 element array of 4 bit values
arr = ‘{12, 10, 3}; // a literal array assignment

● Dynamic arrays are sized at runtime


○ Useful for generating variable length stimulus

bit [3:0] arr []; // a dynamic array of 4 bit values


initial begin
arr = new[2]; // size the array for 2 elements
arr = ‘{12, 10}; // literal assignment

arr = new[10];
arr[3] = 4;
end

22

11
1/26/2022

Queues

● Similar to lists in Scala and Python


○ Useful for hardware modeling (FIFO, stack) - process transactions sequentially

bit [3:0] data [$]; // a queue of 4-bit elements


bit [3:0] data [$] = ‘{1, 2, 3, 4}; // initialized queue
data[0] // first element
data[$] // last element
data.insert(1) // append element
data[1:$] // queue slice excluding first element
x = data.pop_front() // pops first element of queue and returns it
data = {} // clear the queue

23

Associative Arrays

● Similar to Python dicts or Scala Maps


○ Can be used to model a CAM or lookup testbench component settings

int fruits [string];


fruits = ‘{“apple”: 4, “orange”: 10};

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

interface ram_if #(int addr_bits, data_bits)


(input clk);
logic [addr_bits-1:0] addr;
logic [data_bits-1:0] din;
logic [data_bits-1:0] dout;
mem_op op;

clocking ckb @(posedge clk)


default input #1step output negedge;
input dout;
output din, dout, op;
endclocking
● Input/output is from the perspective of the testbench
endinterface ● Can use any delay value or edge event as skew
● intf.ckb.din = 32’d100; @(intf.ckb); x = intf.ckb.dout;

25

OOP in SystemVerilog

● SystemVerilog has your typical object-oriented programming (OOP) constructs


○ Classes, constructors, type generics, inheritance, virtual methods/classes, polymorphism

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

function new (bit [31:0] addr, bit [3:0] wr_strobe =


4’d0);
this.addr = addr;
this.wr_mode = wr_mode;
this.burst_mode = 4’b1010;
this.data = ‘{0, 0, 0, 0};
endfunction
endclass

26

13
1/26/2022

More OOP

● You can extend a class as usual


○ class ALUMessage extends Message
○ call .super() to access superclass functions
○ Polymorphic dynamic dispatch works as usual
● You can declare classes and functions ‘virtual’
○ Forces subclasses to provide an implementation
○ Prevents instantiation of abstract parent class
● Class members can be declared ‘static’
○ The member is shared among all class instances
● OOP constructs are used to:
○ Model transactions
○ Model hardware components (hierarchically and compositionally)

27

Type Generic Classes

● Classes can have parameters, just like modules


○ They can be ints, strings, or types
○ Parameters concretize the class prototype; constructor binds each class member
○ Can’t define type bounds on T

class FIFO #(type T = int, int entries = 8);


T items [entries];
int ptr;

function void push(T entry);


function T pull();
endclass

28

14
1/26/2022

SystemVerilog Assertions (SVA)

29

SystemVerilog Assertions (SVA)

● The most complex component of SystemVerilog


○ Entire books written on just this topic
● SVA: a temporal property specification language
○ Allows you to formally specify expected behavior of RTL
● You are already familiar with ‘assert’ (so-called ‘immediate assertions’)

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

● Concurrent assertions are constantly monitored by the RTL simulator


○ Often embedded in the DUT RTL or an interface

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

● Properties are evaluated on a clock edge


● |->: same-cycle implication
● |=>: next-cycle implication
● These properties can also be formally verified

31

System Functions

● You can call a system function in an SVA expression to simplify checking


historical properties
○ $stable(x): indicates if x was unchanged from the previous clock cycle
○ $rose(x)
○ $fell(x)
○ $past(x): gives you the value of x from 1 cycle ago
■ rs1_mem == $past(rs1_ex)

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

assert property (stall_holds_pc);


endmodule

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

s1 and s2 // sequence s1 and s2 succeed


s1 intersect s2 // sequence s1 and s2 succeed and end at the same time
s1 or s2 // sequence s1 or s2 succeeds

● Sequences are combined with an implication to form a property


○ There’s a lot more to SVA

34

17
1/26/2022

Coverage APIs

35

Coverage

● You’re probably familiar with software coverage tools


○ Track if a line of source code is hit by the unit tests
● Coverage is used to measure the thoroughness of the test suite
○ Are all the interesting cases in the code exercised?
● RTL coverage comes in two forms
○ Structural coverage: line, toggle, condition
○ Functional coverage: did a particular uArch feature specified by the DV engineer get
exercised?
■ e.g. cache eviction, misaligned memory access, interrupt, all opcodes executed

36

18
1/26/2022

Property Coverage

● Any SVA property can be tracked for coverage


○ Instead of ‘assert property’ use ‘cover property’

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

Coverpoints and Covergroups

● Coverpoints track coverage of a single net


○ e.g. FSM state, control signals, data buses
● Covergroups group together coverpoints
○ Each coverpoint refers to a net whose value is tracked at every covergroup event
○ Can be used in RTL and in testbench code
module cpu ();
logic [5:0] rs1, rs2; 15

logic [2:0] funct3; 10 10 10

covergroup c @(posedge clk); 3 3 3


coverpoint rs1;
coverpoint funct3;
0 1 2 3 4 5 6 7 8
funct3 value
endgroup

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

VIPs and Testbench Architecture

● Verification IPs consist of


tasks that encode Testbench
○ How to drive transactions into Mem VIP DUT (Mem)
Stimulus
an interface at cycle Driver Mem Interface
Transaction
Transaction
granularity MemReqTx
Monitor
○ How to translate cycle
granularity interface activity
into transactions Golden Model MemRespTx
● A testbench DUT Resps
○ Generates stimulus
○ Generates golden DUT MemRespTx Assert
Golden Resps Equals
behavior
○ Simulates actual DUT behavior
○ Checks correctness

42

21
1/26/2022

Random Transaction Generation

● How do we generate transaction-level stimulus?


● SystemVerilog class members can be prefixed with the ‘rand’ keyword
○ These fields are marked as randomizable

class MemReqTx(); initial begin


rand bit [31:0] addr; MemReqTx tx = new();
rand bit [31:0] wr_data; tx.randomize();
rand mem_op op; end
endclass

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

constraint cls::extra { min > 5; };


initial begin
cls = new();
cls.randomize() with { min == 10; };
end

44

22
1/26/2022

Randomization of Variable Length Data Structures


class Packet;
rand bit [3:0] data [];

constraint size { data.size() > 5; data.size < 10; }

constraint values {
foreach(data[i]) {
data[i] == i + 1;
data[i] inside {[0:8]};
}
}
endclass

● Many things I haven’t discussed


○ Biasing and distributions, soft constraints, disables, solve before, implications, dynamic
constraint on/off

45

Mailboxes for Safe Inter-Thread Communication


● Mailboxes are like golang channels
○ Bounded queues that allow one thread to send data to another

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

● Let’s test a simple register bank


○ Works like a memory
○ Multi-cycle (potentially variable) read/write latency
○ Uses a ready signal to indicate when a new operation (read/write) can begin

interface reg_if (input clk); module regbank (reg_if.slave if);


logic rst; // implementation
logic [7:0] addr; endmodule
logic [15:0] wdata;
logic [15:0] rdata; // Regbank transaction
mem_op op; class regbank_tx;
logic en; rand bit [7:0] addr;
logic ready; rand bit [15:0] wdata;
// primary/secondary modports bit [15:0] rdata;
// drv_cb/mon_cb clocking blocks rand bit wr;
endinterface endclass

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;

task run(); task run();


@(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

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

● SystemVerilog makes design easier and clearer than plain Verilog


● SystemVerilog has many useful verification features not found in open-source
environments
○ SVA, coverpoints, constrained random
● I’ve only scratched the surface
○ UVM
○ Hardware modeling
○ IPC
● Play around: https://www.edaplayground.com/x/CK
○ https://en.wikipedia.org/wiki/SystemVerilog

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

Advanced notes on SystemVerilog covergroups: https://staging.doulos.com/media/1600/dvclub_austin.pdf

52

26
1/26/2022

Notes on Vendor Support

53

Addendum Points

- Simulation loop, 4 state simulation


- x pessimism / optimism
- sources of mismatch between simulation and synthesis
- multiported memories and collision handling
- literals are 32 bits wide by default
- default_nettype

54

27
1/26/2022

Tagged Unions

- too complicated a subject for this lecture

55

28

You might also like