(转)system verilog 初探
转载地址:http://blog.ednchina.com/windzjy/310477/Message.aspx#
转载请声明:
http://space.ednchina.com/Blog/post.aspx?id=310477
这是一个sv的验证平台的基本框架,自己画的,对错待证!
1,关于clocking block
举例如下:
待证设计
module COUNTER (input Clock, Reset, Enable, Load, UpDn, input [7:0] Data, output reg[7:0] Q);
always @(posedge Clock or posedge Reset)
if (Reset)
Q <= 0;
else if (Enable)
begin
if (Load)
Q <= Data;
else if (UpDn)
Q <= Q + 1;
else
Q <= Q - 1;
end
endmodule
testbench:
module Test_Counter_w_clocking;
timeunit 1ns;
reg Clock = 0, Reset, Enable, Load, UpDn;
reg [7:0] Data;
wire [7:0] Q;
// Clock generator
always
begin
#5 Clock = 1;
#5 Clock = 0;
end
// Test program
program test_counter;
// SystemVerilog "clocking block"
// Clocking outputs are DUT inputs and vice versa
clocking cb_counter @(posedge Clock);
default input #1step output #4;
output negedge Reset;
output Enable, Load, UpDn, Data;
input Q;
endclocking // Apply the test stimulus
initial begin
// Set all inputs at the beginning
Enable = 0;
Load = 0;
UpDn = 1;
Reset = 1;
##1 cb_counter.Reset <= 0; // Will be applied 4ns after the clock!
##1 cb_counter.Enable <= 1;
##2 cb_counter.UpDn <= 0;
##4 cb_counter.UpDn <= 1;
// etc. ...
end
// Check the results - could combine with stimulus block
initial
begin
##1 // Sampled 1ps (or whatever the precision is) before posedge clock
##1 assert (cb_counter.Q == 8'b00000000);
##1 assert (cb_counter.Q == 8'b00000000);
##2 assert (cb_counter.Q == 8'b00000010);
##4 assert (cb_counter.Q == 8'b11111110);
// etc. ... end // Simulation stops automatically when both initials have been completed
endprogram
// Instance the counter
COUNTER G1 (Clock, Reset, Enable, Load, UpDn, Data, Q);
// Instance the test program - not required, because program will be
// instanced implicitly.
// test_COUNTER T1 ();
endmodule
自己分析的时序,如下图所示:
1,接口
interface chip_bus; // 定义接口
wire read_request, read_grant;
wire [7:0] address, data;
endinterface: chip_bus
module RAM (chip_bus io, // 使用接口
input clk);
// 可以使用io.read_request引用接口中的一个信号
endmodule
module CPU(chip_bus io, input clk);
...
endmodule
就像一个数据类型一样,可以用它来定义,或者说引用?
2,如果某些变量、函数或其它信息被设计中的所有模块共享,
那么我们就可以将它们作为全局声明和语句。全局声明和语句的一个使用实例如下:
reg error _flag; // 全局变量
function compare (...); // 全局函数
always @(error_flag) // 全局语句
...
module test;
chip1 u1 (...)
endmodule
module chip1 (...);
FSM u2 (...);
always @(data)
error_flag = compare(data, expected);
endmodule
module FSM (...);
...
always @(state)
error_flag = compare(state, expected);
endmodule
3,抽象数据类型
char
int
shortint
longint
byte
bit
logic,4 states
shortreal
void
logic类型能够以下面的任何一种方法赋值:
a,通过任意数目的过程赋值语句赋值,能够替代Verilog的reg类型;
b,通过单一的连续赋值语句赋值,能够有限制地替代Verilog的wire类型;
c,连接到一个单一原语的输出,能够有限制地替代Verilog的wire类型;
4,用户定义的数据类型
SystemVerilog通过使用typedef提供了一种方法来定义新的数据类型,
这一点与C语言类似。用户定义的类型可以与其它数据类型一样地使用在声明当中。例如:
typedef unsigned int uint;
uint a, b;
5,枚举类型
值从初始值0开始递增,但是我们可以显式地指定初始值。枚举类型的例子如下:
enum {red, yellow, green} RGB;
enum {WAIT=2’b01, LOAD, DONE} states;
我们还可以使用typedef为枚举类型指定一个名字,从而允许这个枚举类型可以在许多地方使用。例如:
typedef enum {FALSE=1’b0, TRUE} boolean;
boolean ready;
boolean test_complete;
6,结构体和联合体
在Verilog语言中不存在结构体或联合体,而结构体或联合体在将几个声明组合在一起的时候
非常有用。SystemVerilog增加了结构体和联合体,它们的声明语法类似于C。
struct {
reg [15:0] opcode;
reg [23:0] addr;
} IR;
union {
int I;
shortreal f;
} N;
结构体或联合体中的域可以通过在变量名和域名字之间插入句点(.)来引用:
IR.opcode = 1; // 设置IR变量中的opcode域
N.f = 0.0; // 将N设置成浮点数的值
我们可以使用typedef为结构体或联合体的定义指定一个名字。
typedef struct {
reg [7:0] opcode;
reg [23:0] addr;
} instruction; // 命名的结构体
instruction IR; // 结构体实例
一个结构体可以使用值的级联来完整地赋值,例如:
instruction = {5, 200}; //IR = {5,200}???jyz
结构体可以作为一个整体传递到函数或任务,也可以从函数或任务传递过来,也可以作为模块端口进行传递。
7,数组
8,assertions
assert (A == B); // Asserts that A equals B; if not, an error is generated
就是如果在这个时候A不等于B的话,那么就会报出一个错误的信息供你debug。
9,A class is a user-defined data type. Classes consist of data (called properties) and tasks
and functions to access the data (called methods). Classes are used in object-oriented programming.
In SystemVerilog, classes support the following aspects of object-orientation – encapsulation, data
hiding, inheritance and polymorphism.
10,Classes may be parameterised in the same way that modules may.
class #(parameter int N = 1) Register;
It is also possible to pass a data type to a class:
class #(parameter type T = int) Register; T data; ... endclass Register Rint;
// data is int Register #(bit [7:0]) Rint; // data is bit [7:0]
11,One of the key features of object-oriented programming is the ability to create new classes that are based on existing classes. A derived class by default inherits the properties and methods of its parent or base class. However, the derived class may add new properties and methods, or modify the inherited properties and methods. In other words, the new class is a more specialised version of the original class.
In SystemVerilog the syntax for deriving or inheriting one class from another is this:
class Derived extends BaseClass; // New and overridden property and method declarations. endclass
12,vitual class
Sometimes, it is useful to create a class without intending to create any objects of the class. The class exists simply as a base class from which other classes can be derived. In SystemVerilog this is called an abstract class and is declared by using the word virtual:
virtual class Register; ... endclass
13,Traditionally, simulation-based verification has used a directed testing approach. In other words,
a testbench implements tests using specific data values.
14,struct packed { bit [10:0] ID; // 11-bit identifier bit RTR; // reply required? bit [1:0] rsvd; // "reserved for expansion" bits bit [3:0] DLC; // 4-bit Data Length Code byte data[]; // data payload bit [14:0] CRC; // 15-bit checksum } message;
We have used struct packed to define a packed data structure. This means that the data structure can be packed into a single vector,
15,Constraints direct the random generator to choose values that satisfy the properties you specify in your constraints. Within the limits of your constraints, the values are still randomly chosen. The process of choosing values that satisfy the constraints is called solving. The verification tool that
does this is called the solver;
16,
SystemVerilog 3.1a adds important new constructs to Verilog-2001, including:
a, New data types: byte, shortint, int, longint, bit, logic, string, chandle.
b, Typedef, struct, union, tagged union, enum
c, Dynamic and associative arrays; queues
d, Classes
e, Automatic/static specification on a per variable instance basis
f, Packages and support for Compilation Units
g, Extensions to Always blocks for modelling combinational, latched or clocked processes
h, Jump Statements (return, break and continue)
i, Extensions to fork-join, disable and wait to support dynamic processes.
j, Interfaces to encapsulate communication
k, Clocking blocks to support cycle-based methodologies
l, Program blocks for describing tests
m, Randomization and constraints for random and directed-random verification
n, Procedural and concurrent assertions and Coverage for verification
o, Enhancements to events and new Mailbox and Semaphore built-in classes for inter-process communication.
p, The Direct Programming Interface, which allows C functions to be called directly from SystemVerilog (and vice versa) without using the PLI.
q, Assertions and Coverage Application Programming Interfaces (APIs) and extensions to the Verilog Procedural Interface
(VPI) – details of these are outside the scope of the SystemVerilog Golden Reference Guide
17,The clocking event of a clocking block can be accessed directly by using the clocking block name, e.g. @(cb) is equivalent to @(posedge Clk).
18,将设计的端口和测试的端口放在同一个interface中,引用的时候可以只引用内部的一个modport
19,The program block can read and write all signals in modules, and can call
routines in modules, but a module has no visibility into a program.
用于模块之间进行交互的。
20,However, using a module to
hold the testbench often causes timing problems around driving and sampling,
so SystemVerilog introduces the program block to separate the testbench,
both logically and temporally.
21,The simplest interface is just a bundle of nondirectional signals. Use
logic so you can drive the signals from procedural statements.
22,The modport construct
in an interface lets you group signals and specify directions.仅仅是interface的一个子集而已。
23,you should always declare your
program block as automatic so that it behaves more like the
routines in stack-based languages you may have worked with,
such as C.
24,In SystemVerilog you can put tasks, functions, classes, and initial
blocks in a program, but not always blocks.
25,fork join_none指的是到了该执行这个语句块的是,不执行,然后执行,该语句块后面的语句。然后再执行该语句块。
fork join_any,执行完第一个以后
fork...join_none is non-blocking, so all processes in the
fork...join_none start at the same time as the code following the
fork......join_none and the following code continues on.
fork
task_that_may_lock_up;
begin
repeat(10000)
begin
@(posedge clk);
end
$display("Error: Possible lock-up in task_that_may_lock_up");
end
join_any
// Finish will be called even if task_that_may_lock_up never completes
$finish;
最新理解:
fork join;指的是fork join这个语句块和外面的begin end其他的语句串行执行,fork join内部的执行完毕才执行之后的语句。
fork join_none:指的是,这个fork join_none语句块和其后的其他语句块是并行的,也就是说这个fork join_none并不影响其后的语句的执行。
而fork join_any:要执行了fork join_any语句块中的第一个语句,然后fork join_any后面的语句开始执行,同时fork join_any之内的其他语句也开始并行的执行。
reg[5:0] a ;
initial
a = 6'd0;
#1;
begin
fork
#1 a = 6'd1;#2 a = 6'd2;#3 a = 6'd3; #4 a = 6'd4;
join
#5 a = 6'd5;
# 7 a = 6'd6;
#10 a = 6'd7;
end
结果:0 2 3 4 5 10 17 27
0 1 2 3 4 5 6 7
initial
a = 6'd0;
#1;
begin
fork
#1 a = 6'd1;#2 a = 6'd2;#3 a = 6'd3; #4 a = 6'd4;
join_none
#5 a = 6'd5;
# 7 a = 6'd6;
#10 a = 6'd7;
end
结果:0 2 3 4 5 6 13 23
0 1 2 3 4 5 6 7
initial
a = 6'd0;
#1;
begin
fork
#1 a = 6'd1;#2 a = 6'd2;#3 a = 6'd3; #4 a = 6'd4;
join_any
#5 a = 6'd5;
# 7 a = 6'd6;
#10 a = 6'd7;
end
结果:0 2 3 4 5 7 14 24
0 1 2 3 4 5 6 7
26,How do you pass information between two threads?
The solution is a SystemVerilog mailbox.
From a hardware point of view,
the easiest way to think about a mailbox is that it is just a FIFO, with a source
and sink. The source puts data into the mailbox, and the sink gets values from
the mailbox. Mailboxes can have a maximum size or can be unlimited.
27,Consider what happens if a block of code is missing from the
design. Code coverage cannot catch this mistake, but functional coverage can.
28,All storage is static, meaning that
all variables are alive for the entire simulation and routines cannot use a stack
to hold arguments and local values.
the classic reg data type so that it can be driven by
continuous assignments, gates and modules,
SystemVerilog stores each element on a longword (32-bit) boundary. So a
byte, shortint, and int are all stored in a single longword,
The unpacked array of bytes, b_unpacked, is stored in three longwords.
Figure 2-1 Unpacked array storage,浪费了72bits的空间。
VCS对systemverilog 编译的时候要加上选项 -sverilog 才可以。
动态数组,可以改变数组的大小。
int dyn[], d2[]; // Empty dynamic arrays
initial begin
dyn = new[5]; // Allocate 5 elements
foreach (dyn[j])
dyn[j] = j; // Initialize the elements
d2 = dyn; // Copy a dynamic array
d2[0] = 5; // Modify the copy
$display(dyn[0],d2[0]); // See both values (0 & 5)
dyn = new[20](dyn); // Expand and copy
dyn = new[100]; // Allocate 100 new integers
// Old values are lost
dyn.delete; // Delete all elements
end
When you copy a fixed-size array to a dynamic array, SystemVerilog calls
new[] constructor to allocate space, and then copies the values.
29,You can take even more shortcuts with declaring routine arguments. The
direction and type default to “input logic” and are sticky, so you don’t have to
repeat these for similar arguments.
task T3;
input a, b;
logic a, b;
output [15:0] u, v;
bit [15:0] u, v;
...
endtask
You could rewrite this as follows.
Example 3-9 Routine arguments with sticky types
task T3(a, b, output bit [15:0] u, v);
主要就是task,function,program class等。
class BusTran;
endclass: BusTran
BusTran b; // Declare a handle
b = new; // Allocate a BusTran object
30,
by using a virtual interface that is merely a handle to
a physical interface.
在verilog中,tb和设计之间的连接是通过net来连接的,但是有的时候接口上有重复的定义,或者说很多具有相同性质的
接口,这样连接的时候就会很麻烦,这个时候就可以通过虚拟的接口来省事。
A SystemVerilog interface is more than just signals — you can put executable
code inside.
?? Class – a basic building block containing routines(methods) and variables(properties). The
analogue in Verilog is a module.
?? Object – an instance of a class. In Verilog, you need to instantiate a
module to use it.
?? Handle – a pointer to an object. In Verilog, you use the name of an
instance when you refer to signals and methods from outside the
module. An OOP handle is like the address of the object, but is stored
in a pointer that can only refer to one type.
?? Property – a variable that holds data. In Verilog, this is a signal such
as a register or wire.
?? Method – the procedural code that manipulates variables, contained
in tasks and functions. Verilog modules have tasks and functions plus
initial and always blocks.
?? Prototype – the header of a routine that shows the name, type, and
argument list. The body of the routine contains the executable code.
How does SystemVerilog know which new function to call? It looks at the
type of the handle on the left side of the assignment.
1,顶层的虚拟接口传递给program,然后再通过class的new函数传给class,然后开始对接口做一些动作。
2,A scope is a block of code such as a module, program, task, function,
class, or begin-end block.
A name can be relative to the current scope or absolute starting with
$root.
3,
In Example 4-16, the keyword “this”
removes the ambiguity to let SystemVerilog know that you are assigning the
local variable, oname, to the class variable, oname.
class Scoping;
string oname;
function new(string oname);
this.oname = oname; // class oname = local oname
endfunction
endclass
Either way,
when you call the routine, you pass a handle to the object, not the object itself.
A common coding mistake is to forget to use ref on routine
arguments that you want to modify, especially handles.
如果想在routing中改变handles,必须将此routing的argument 生命为ref
The core of OOP is to encapsulate(压缩) data and related routines into a class.
The calc_crc
function in the extended class calls calc_crc in the base class using the
super prefix. You can call
terms. As explained in Chapter 4, the OOP
term for a variable in a class is “property,” and a task or function is called a
“method.”
clocking block 中的input delay 和outputdelay:
inputdelay:就是说我testbench需要你design在active edge 之前的这个delay输出有效的结果,我好进行分析比较。
outputdelay:就是在active edge之后的delay输出给design的信号。
module COUNTER (input Clock, Reset, Enable, Load, UpDn, input [7:0] Data, output reg[7:0] Q);
always @(posedge Clock or posedge Reset)
if (Reset)
Q <= 0;
else if (Enable)
begin
if (Load)
Q <= Data;
else if (UpDn)
Q <= Q + 1;
else
Q <= Q - 1;
end
endmodule
module Test_Counter_w_clocking;
timeunit 1ns;
reg Clock = 0, Reset, Enable, Load, UpDn;
reg [7:0] Data;
wire [7:0] Q;
// Clock generator
always
begin
#5 Clock = 1;
#5 Clock = 0;
end
// Test program
program test_counter;
// SystemVerilog "clocking block"
// Clocking outputs are DUT inputs and vice versa
clocking cb_counter @(posedge Clock);
default input #1step output #4;
output negedge Reset;
output Enable, Load, UpDn, Data;
input Q;
endclocking // Apply the test stimulus
initial begin
// Set all inputs at the beginning
Enable = 0;
Load = 0;
UpDn = 1;
Reset = 1;
##1 cb_counter.Reset <= 0; // Will be applied 4ns after the clock!
##1 cb_counter.Enable <= 1;
##2 cb_counter.UpDn <= 0;
##4 cb_counter.UpDn <= 1;
// etc. ...
end
// Check the results - could combine with stimulus block
initial
begin
##1 // Sampled 1ps (or whatever the precision is) before posedge clock
##1 assert (cb_counter.Q == 8'b00000000);
##1 assert (cb_counter.Q == 8'b00000000);
##2 assert (cb_counter.Q == 8'b00000010);
##4 assert (cb_counter.Q == 8'b11111110);
// etc. ... end // Simulation stops automatically when both initials have been completed
endprogram
// Instance the counter
COUNTER G1 (Clock, Reset, Enable, Load, UpDn, Data, Q);
// Instance the test program - not required, because program will be
// instanced implicitly.
// test_COUNTER T1 ();
endmodule
1,为什么要用virtual?
In SystemVerilog, most methods should be declared virtual to give
the possibility of being adapted to the extensions of each derived
class and maintain the behavior expected by existing code that uses
the original base class.
我们自己的验证主要是基于functional verification
test 和 verification 这两个概念还是有很大区别的。
VMM的介绍:
The SystemVerilog class construct deserves some explanation because classes are core to the
VMM methodology.
VMM represents a methodology supported by a standard library
that consists of a set of base and utility classes to implement a VMM-compliant verification
environment and verification components.
channel 的概念:其实就是一个fifo的意思,先进先出。
-----------------------------
put() |nthput ......2sedput 1stput| get()
-----------------------------
Transactor is a term used to define and identify component of verification that acts upon or executes and observes transactions over various paths and cycle time in dynamic verificaiton environments.
class内部的函数和任务不会设计到具体的东西,当对其进行例化的时候说明才真正的要用它了。
class Packet;
// The random variables
rand bit [31:0] src, dst, data[8];
randc bit [7:0] kind;
// Limit the values for src
constraint c {src > 10;
src < 15;}
endclass
Packet p;
initial begin
p = new; // Create a packet
assert (p.randomize());
transmit(p);
end
This class has four random variables. The first three use the rand modifier,
so that every time you randomize the class, the variables are assigned a
value.
每次调用class object.randomize就可以随机产生一些数据。
scoreboard:
used to hold the expected data for ease of comparison against the
monitored output values.Each scoreboard is designed to
meet the needs of the self-checking requirements.