Microsoft PowerPoint – HW_Verification_Lecture_2
Hardware Verification –
Copyright By PowCoder代写 加微信 powcoder
Autumn term 2022
• Effective verification of hardware requires a number of approaches:
• Constrained random unit-level testing on each module of a design
• Directed testing – e.g. running self-testing code on a CPU
• Assertion-based design enables formal verification
• Coverage is needed to measure quality and completeness of testing
• Code coverage
• Functional coverage
• SystemVerilog will be the language used to build a testbench
• SystemVerilog Assertions will be used to write properties
SystemVerilog – a language for verification
• SystemVerilog has some rich features that make it easier to build
testbenches and perform hardware verification
• In this lecture, we will cover:
• Data types
• Procedural statements and routines
• Connecting the testbench to the design
• In the next lecture:
• OOP features
• Randomisation and constrained random verification
• SystemVerilog Assertions (SVAs)
Agenda – Data types
• Built-in data types
• Arrays: fixed, packed, dynamic, associative
• New types with typedef
• User-defined structures
• Enumerated types
Agenda – Procedural Statements and Routines
• Operators and statements that are new for SystemVerilog
• Tasks and Functions
• Routine arguments
• Return statements
• Automatic storage
• Time values
Agenda – Connecting the testbench to the design
• Ports and interfaces
• Modports
• Stimulus timing
• Clocking blocks
• Clock generation
• Connecting the DUT, testbench and interfaces
• Introduction to SystemVerilog assertions
The Logic Type
• Verilog has wire and reg
• SystemVerilog introduces logic
• logic type can be used for any net, unless it has multiple drivers
• Use wire if there are multiple drivers (e.g. for a bidirectional bus)
• logic, wire and reg are 4-state types (0,1,X,Z)
logic clk, rst_n;
logic [31:0] data_in;
wire [31:0] data_in_out;
2-State Data Types
• 2-state types introduced to SystemVerilog
• bit – always unsigned
• byte, shortint, int and longint are signed by default
• But you can cast these to be unsigned
bit flag;
bit [31:0] dataword; 32-bit unsigned integer
int datavalue; 32-bit signed integer
int unsigned u_datavalue; 32-bit unsigned integer
byte databyte; 8-bit signed integer
shortint data16; 16-bit signed integer
longint data64; 64-bit signed integer
real value_of_pi; double-precision floating point
4-State Data Types
integer dataword; 32-bit signed integer
time timestamp; 64-bit unsigned integer
Connecting 2-state types to DUT
• Beware of connecting 2-state types between testbench and DUT
• If output from DUT goes X or Z, testbench won’t know unless you test
• If you do this, test for it with $isunknown()
• Probably best to avoid this!
• Fixed arrays – SystemVerilog allows shortcut of just giving array size
• Unpacked arrays – specify dimensions after variable name
• Arrays can be multi-dimensional
• Initialise arrays with array literal – ‘{initial_values}
• Manipulate arrays with for and foreach
• Use $size to return size of array
int sig_reg [4]; (equivalent to int sig_reg [3:0])
int mem_array [32] [8]; (multi-dimensional array)
sigreg = ‘{3,2,1,0};
sigreg = ‘{4{0}};
Packed Arrays
• Packed arrays – specify dimensions before variable name
• Dimensions must be in [msb:lsb] format, not [size]
bit [7:0] [7:0] word64; // pack 8 bytes into a 64-bit element
Dynamic Arrays
• Use a dynamic array if you don’t know the array size at compile time
• Specify dynamic array with empty subscripts [ ]
• Initially empty so call new[] to allocate space
int array1[];
initial begin
array1 = new[25];
foreach (array1[k]) array1[k] = 1;
array1 = new[75];
array1.delete();
• New for SystemVerilog – combines linked list and array – always dynamic
• Can add or remove elements anywhere in the queue
• Declare queue with subscripts containing ‘$’
• Queue operators: insert, delete, push_front(/back), pop_front(/back)
queue1[$] = {0,1,2,3,4,5,6,7};
queue1.insert(5,9); // insert value 9 before element #5
queue1.delete(7); // delete element #7
queue1.push_front(0); // insert 0 at front of queue
fifo_out = queue1.pop_back; //pop from the end of the queue
Associative Arrays
• Use an associate array if you want to model a large memory but your
data is sparse
• Declare associate array with data type in []
• Get index value with functions: first, next
• Delete elements with delete
int assoc_array[int], index;
initial begin
assoc_array[7] = 0;
if assoc_array.first[index]
$display(“index=%d”, index];
while assoc_array.next[index];
Array Methods
• Array reduction methods: sum, product, and, or, xor
• Array locator methods: min, max, unique
• Find elements in array: find_index with (item…)
• Also find_first, find_last, find_first_index,
find_last_index
• Array sorting: sort, rsort, shuffle, reverse
array_sum = array1.sum();
q2 = q1.min();
q3 = q1.find_index with (item>31);
data1.sort();
User-defined data types
• Define new type with typedef
• Convention is to identify user types with _t suffix, e.g. vec16_t
typedef logic [15:0] vec16_t;
vec16_t operand1, operand2;
typedef bit [31:0] unsigned_int_t;
unsigned_int_t data_width;
typedef byte byte_array_t[8];
User-defined structures
• A struct groups data fields together – use _s suffix
• A struct is not packed by default
• Use typedef to create a new structure type
• Assign values to struct as with an array
• Use a union to store different types in the same location
struct {bit sign, bit[4:0] exponent, bit[9:0] mantissa;} float16;
typedef struct {bit sign, bit[4:0] exponent, bit[9:0] mantissa;} float16_s;
float16_s float_register;
typedef union { bit[15:0] int_value; float16_s float_value; } dpreg_u;
dpreg_u dpreg;
Packed structures
• Both struct and union can be packed
• Can make more efficient use of memory
typedef struct packed {
logic valid;
logic [7:0] addr;
tag_t my_tag;
logic [8:0] vec;
vec = my_tag;
vec[8] = my_tag.valid; vec[7:0] = my_tag.addr; // equivalent to previous line
my_tag = vec;
• A package enables you to share declarations among other building
blocks, like modules
• Import symbols from a package with import statement
package float_types;
parameter int float_width = 16;
typedef logic [15:0] vec16_t;
typedef struct {bit sign, bit[4:0] exponent, bit[9:0] mantissa;} float16_s;
endpackage
module float_test;
import float_types::*;
float_reg float_16_s;
Enumerated Types
• Enumerated types let you create a set of unique but related constants
• Declare with typedef so it can be used for declaring multiple variables
• Values count up from zero by default – but you can declare your own values
• Functions for stepping through enums: first(), last(), next(), next (N), prev, prev(N)
typedef enum {RED, AMBER, GREEN} traffic_light_colours_e; // Take values 0,1,2
typedef enum {RED, AMBER=4, GREEN} traffic_light_colours_e; // Take values 0,4,5
traffic_light_colour_e tr_colour;
tr_colour = tr_colour.first;
• SystemVerilog string holds variable-length strings
• Each element of the string is a byte
• Elements of string of length N are numbered from 0 to N-1
• getc(N) returns byte at location N
• putc(N, char) writes a byte char into string at location N
string str;
initial begin
str = “Imperial College “;
str = {str, “,London”};
Procedural Statements and Routines
• Operators and statements that are new for SystemVerilog
• Tasks and Functions
• Routine arguments
• Return statements
• Automatic storage
New operators and statements
• SystemVerilog adopts many operators and statements from C and C++
• For example:
• Declare a loop variable in a for loop, to restrict its scope
• Auto-increment and auto-decrement operators: ++, —
• Compound assignments: +=, -=, ^=
• Labels can be added to begin/end, fork/join
• Labels can be added to endmodule, endtask, endfunction
• Use continue and break in a loop
• return statement added
begin : new_ops
for (int j=0; j < 5; j++)
mem[j] = 0;
acc += result;
end : new_ops
Tasks and Functions
• In Verilog, task consumes time, function cannot
• In SystemVerilog, a function can call a task – but only using
fork..join_none
• If you have a SystemVerilog task that does not consume time, you
should make it a void function
• Any debug routines should be a void function, so that it can be
called from any task or function
• Cast result of function to void if you want to ignore its return value
void’ (myfunction(myval));
Routine arguments
• Type and direction of routine arguments can be combined
• Default is input logic and is sticky
• But don’t rely on this – it’s best to declare all types and directions
• Arguments can be passed by reference, using ref
• Default values can be used for arguments
• Names of arguments can be specified
task convert_float_to_int (output logic [31:0] int_value,
input logic [31:0] float_single);
Automatic Storage
• SystemVerilog uses static storage by default for modules and program
• Make program blocks and their routines use automatic storage (use
the stack), by putting automatic in the program statement
• You can then call tasks defined in the program multiple times
program automatic my_program();
task check_error (input logic [7:0] error,
output logic exception)
if (error == ’h39) exception = 1;
Connecting the testbench to the design
• Ports and interfaces
• Modports
• Stimulus timing
• Clocking blocks
• Clock generation
• Connecting the DUT, testbench and interfaces
• Introduction to SystemVerilog assertions
Separating testbench from the design
• DUT and testbench in separate
modules separates them
• SystemVerilog introduces the
program block, to separate
both logically and temporally
• It also introduces the
interface, to reduce wiring and
timing errors
Connect to design with ports
• Part of multiplier example – see Exercise 1
module multiplier ( input logic clk,
input logic rst_n,
input logic req,
output logic rdy );
logic busy;
assign start = req & rdy;
always @(posedge clk or negedge rst_n)
if (!rst_n) busy <= 1’b0;
else if (start) busy <= 1’b1;
Create testbench with ports
module multiplier_test ( input logic clk,
output logic rst_n,
input logic rdy,
output logic req );
initial begin
rst_n = 0;
#100 rst_n = 1;
@(posedge clk);
@(posedge clk);
if (rdy == 1) $display ("rdy is high");
Connect design and testbench with top module
module top;
logic rdy, req;
initial begin
forever #100 clk = !clk;
multiplier mul1 (clk, rst_n, req, rdy);
multiplier_test mul1_test (clk, rst_n, rdy, req);
Add an interface to bundle wires together
interface mult_if (input bit clk);
logic req, rdy, rst;
endinterface
DUTTESTBENCH
Multiplier design with interface
module multiplier (mult_if multif);
logic busy;
assign start = multif.req & multif.rdy;
always @(posedge multif.clk or negedge multif.rst_n)
if (!multif.rst_n) busy <= 1’b0;
else if (start) busy <= 1’b1;
Create testbench with interface
module multiplier_test (mult_if multif);
initial begin
multif.rst_n <= 0;
#100 multif.rst_n <= 1;
@(posedge multif.clk);
multif.req <= 1;
@(posedge multif.clk);
if (multif.rdy == 1) $display ("rdy is high");
Connect design and testbench with interface
module top;
logic rdy, req;
initial begin
forever #100 clk = !clk;
mult_if multif(clk); // Instantiate the interface
multiplier mul1 (multif); // Instantiate the design
multiplier_test mul1_test (multif); // Instantiate the testbench
Use program for testbench to give temporal separation
• Provides entry to test-bench execution
• Encapsulates data, tasks and functions
program automatic multiplier_test (mult_if multif);
initial begin
multif.rst_n <= 0;
#100 multif.rst_n <= 1;
@(posedge multif.clk);
multif.req <= 1;
@(posedge multif.clk);
if (multif.rdy == 1) $display ("rdy is high");
endprogram
• The modport in an interface lets you group signals and specify their
direction.
interface mult_if (input bit clk);
logic req, rdy, rst_n;
modport TEST (input rdy, clk,
output req, rst_n);
modport DUT (input req, clk, rst_n,
output rdy);
endinterface
Including modports in modules
• Add modport to interface name in module declarations
• Top module can stay the same
module multiplier (mult_if.DUT multif);
module multiplier_test (mult_if.TEST multif);
Clocking blocks
• Interface should contain a clocking block
• It specifies timing of synchronous signals relative to the clock
• The signal directions are relative to the modport where they are used
interface mult_if (input bit clk);
logic req, rdy, rst_n;
clocking cb @(posedge clk);
input rdy;
output req;
endclocking
modport TEST (output rst_n,
clocking cb);
modport DUT (input req, clk, rst_n,
output rdy);
endinterface
Using clocking block in a module
module multiplier_test (mult_if.TEST multif);
initial begin
multif.rst_n <= 0;
#100 multif.rst_n <= 1;
@multif.cb;
multif.cb.req <= 1;
@multif.cb;
wait (multif.cb.rdy == 1); // Wait until rdy goes high
$display ("rdy is high");
Introduction to SystemVerilog Assertions (SVA)
• Use assertions to check signal behaviour and temporal relationships
• Two main types: Immediate and Concurrent Assertions
• Immediate - checks that statement is true when it is executed
• Concurrent - checks behaviour continuously throughout simulation
assert (ack == 1’b0); // Immediate - Checks ack is low at this point in simulation
assert (ack == 1’b0) // With error message if assertion fails
else $error (“Error: ack not negated”);
property check_result; // Concurrent – requires a sampling clock
@(posedge clk) disable iff (!rst_n)
result == a+b;
endproperty
assert_check_result: assert property (check_result);
Recommended reading
• Updated reading list (contains links to on-line versions):
• https://imperial.alma.exlibrisgroup.com/leganto/readinglist/lists/39647687740001591?institute=44IMP_INS
T&institute=44IMP_INST&fromSaml=true&auth=SAML
• SystemVerilog For Verification 3rd Edition, Spear and Tumbush, Springer (online version now available)
• SystemVerilog Language Reference Manual (LRM) - Formal
Verification – An Essential Toolkit for Modern VLSI Design Seligman, Schubert and
• SystemVerilog Assertions (SVA)
• Mentor QuestaSim – Help pages within tool
• Gold – Help pages within tool
Exercises related to Lecture #2
• Access the 3rd Edition of ‘SystemVerilog for Verification’ (Red cover)
• Look for the ‘Exercises’ at the end of Chapters 2, 3 and 4
• Do any of these if you want some practice at writing SystemVerilog
• If you have problems, you can raise these in the Lab Session
• Not assessed
Next lecture:
SystemVerilog (continued) and more on
SystemVerilog Assertions (SVA)
Testbench timing issues
Introduction to Object-Oriented Programming features
Randomisation
Principles of unit-level constrained random simulation
More details on writing SVAs
程序代写 CS代考 加微信: powcoder QQ: 1823890830 Email: powcoder@163.com