systemverilog
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
systemverilog
SystemVerilog语⾔简介
1. 接⼝(Interface)
Verilog模块之间的连接是通过模块端⼝进⾏的。
为了给组成设计的各个模块定义端⼝,我们必须对期望的硬件设计有⼀个详细的认识。
不幸的是,在设计的早期,我们很难把握设计的细节。
⽽且,⼀旦模块的端⼝定义完成后,我们也很难改变端⼝的配置。
另外,⼀个设计中的许多模块往往具有相同的端⼝定义,在Verilog中,我们必须在每个模块中进⾏相同的定义,这为我们增加了⽆谓的⼯作量。
SystemVerilog提供了⼀个新的、⾼层抽象的模块连接,这个连接被称为接⼝(Interface)。
接⼝在关键字interface和endinterface之间定义,它独⽴于模块。
接⼝在模块中就像⼀个单⼀的端⼝⼀样使⽤。
在最简单的形式下,⼀个接⼝可以认为是⼀组线⽹。
例如,可以将PCI 总线的所有信号绑定在⼀起组成⼀个接⼝。
通过使⽤接⼝,我们在进⾏⼀个设计的时候可以不需要⾸先建⽴各个模块间的互连。
随着设计的深⼊,各个设计细节也会变得越来越清晰,⽽接⼝内的信号也会很容易地表⽰出来。
当接⼝发⽣变化时,这些变化也会在使⽤该接⼝的所有模块中反映出来,⽽⽆需更改每⼀个模块。
下⾯是⼀个接⼝的使⽤实例:
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
module top;
reg clk =0;
chip_bus a;// 实例接⼝
// 将接⼝连接到模块实例
RAM mem(a, clk);
CPU cpu(a, clk);
endmodule
实际上,SystemVerilog的接⼝不仅仅可以表⽰信号的绑定和互连。
由于SystemVerilog的接⼝中可以包含参数、常量、变量、结构、函数、任务、initial块、always块以及连续赋值语句,所以SystemVerilog的接⼝还可以包含内建的协议检查以及被使⽤该接⼝的模块所共⽤的功能。
2. 全局声明和语句
在Verilog中,除了⼀个模块可以作为模块实例引⽤其他模块外,并不存在⼀个全局空间。
另外,Verilog允许任意数⽬的顶层模块,因此会产⽣毫⽆关联的层次树。
root的隐含的顶级层次。
任何在模块边界之外的声明和语句都存在于
SystemVeriog增加了⼀个被称为root空间中。
所有的模块,⽆论它处于哪⼀个设计层次,都可以引⽤$root中声明的名字。
这样,如果某些变量、函数或其它信息被设计中的所有模块共享,那么我们就可以将它们作为全局声明和语句。
全局声明和语句的⼀个使⽤实例如下:
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. 时间单位和精度
在Verilog中,表⽰时间的值使⽤⼀个数来表⽰,⽽不带有任何时间单位。
例如:
forever #5 clock =~clock;
从这⼀句中我们⽆法判断5代表的是5ns? 5ps? 还是其他。
Verilog的时间单位和精度是作为每⼀个模块的属性,并使⽤编译器指
令timescale来设置。
使⽤这种⽅法具有固有的缺陷,因为编译器指令的执⾏依赖于源代码的编译顺序,编译器总是将它遇到的最后⼀个timescale设置的时间单位和精度作为之后的标准。
那么,假如有些模块之前没有使⽤`timescale设置时间单位和精度,这就有可能出现同⼀个源代码的不同仿真会出现不同结果的情况。
SystemVerilog为了控制时间单位加⼊了两个重要的增强。
⾸先,时间值可以显式地指定⼀个单位。
时间单位可以是s、ms、ns、ps或fs。
时间单位作为时间值的后缀出现。
例如:
forever #5ns clock =~clock;
其次,SystemVerilog允许使⽤新的关键字(timeunits和timeprecision)来指定时间单位和精度。
这些声明可以在任何模块中指定,同时也可以在$root空间中全局指定。
时间单位和精度必须是10的幂,范围可以从s到fs。
例如:
timeunits 1ns;
timeprecision 10ps;
4. 抽象数据类型
Verilog提供了⾯向底层硬件的线⽹、寄存器和变量数据类型。
这些类型代表了4态逻辑值,通常⽤来在底层上对硬件进⾏建模和验证。
线⽹数据类型还具有多个强度级别,并且能够为多驱动源的线⽹提供解析功能。
SystemVerilog包括了C语⾔的char和int数据类型,它允许在Verilog模型和验证程序中直接使⽤C和C++代码。
Verilog PLI不再需要集成总线功能模型、算法模型和C函数。
SystemVerilog还为Verilog加⼊了⼏个新的数据类型,以便能够在更抽象的层次上建模硬件。
1. char:⼀个两态的有符号变量,它与C语⾔中的char数据类型相同,可以是⼀个8位整数(ASCII)或short
int(Unicode);
2. int:⼀个两态的有符号变量,它与C语⾔中的int数据类型相似,但被精确地定义成32位;
3. shortint:⼀个两态的有符号变量,被精确地定义成16位;
4. longint:⼀个两态的有符号变量,它与C语⾔中的long数据类型相似,但被精确地定义成64位;
5. byte:⼀个两态的有符号变量,被精确地定义成8位;
6. bit:⼀个两态的可以具有任意向量宽度的⽆符号数据类型,可以⽤来替代Verilog的reg数据类型;
7. logic:⼀个四态的可以具有任意向量宽度的⽆符号数据类型,可以⽤来替代Verilog的线⽹或reg数据类型,但具有某些限制;
8. shortreal:⼀个两态的单精度浮点变量,与C语⾔的float类型相同;
9. void:表⽰没有值,可以定义成⼀个函数的返回值,与C语⾔中的含义相同。
SystemVerilog的bit和其他数据类型允许⽤户使⽤两态逻辑对设计建模,这种⽅法对仿真性能更有效率。
由于Verilog语⾔没有两态数据类型,因此许多仿真器都通过将这种功能作为仿真器的⼀个选项提供。
这些选项不能够在所有的仿真器之间移植,⽽且在需要时⽤三态或四态逻辑的设计中强制使⽤两态逻辑还具有副作⽤。
SystemVerilog的bit数据类型能够极⼤改进仿真器的性能,同时在需要的时候仍然可以使⽤三态或四态逻辑。
通过使⽤具有确定⾏为的数据类型来代替专有的仿真器选项,两态模型能够在所有的SystemVerilog仿真器间移植。
SystemVerilog的logic数据类型⽐Verilog的线⽹和寄存器数据类型更加灵活,它使得在任何抽象层次上建模硬件都更加容易。
logic类型能够以下⾯的任何⼀种⽅法赋值:
通过任意数⽬的过程赋值语句赋值,能够替代Verilog的reg类型;
通过单⼀的连续赋值语句赋值,能够有限制地替代Verilog的wire类型;
连接到⼀个单⼀原语的输出,能够有限制地替代Verilog的wire类型;
由于logic数据类型能够被⽤来替代Verilog的reg或wire(具有限制),这就使得能够在⼀个更⾼的抽象层次上建模,并且随着设计的不断深⼊能够加⼊⼀些设计细节⽽不必改变数据类型的声明。
logic数据类型不会表⽰信号的强度也不具有线逻辑的解析功能,因此logic数据类型⽐Verilog的wire类型更能有效地仿真和综合。
5. 有符号和⽆符号限定符
缺省情况下,Verilog net和reg数据类型是⽆符号类型,integer类型是⼀个有符号类型。
Verilog-2001标准允许使⽤signed关键字将⽆符号类型显式地声明成有符号类型。
SystemVerilog加⼊了相似的能⼒,它可以通过unsigned关键字将有符号数据类型显式地声明成有⽆符号数据类型。
例如:
int unsigned j;
值得注意的是unsigned在Verilog中是⼀个保留字,但并没有被Verilog标准使⽤。
6. ⽤户定义的类型
Verilog不允许⽤户定义新的数据类型。
SystemVerilog通过使⽤typedef提供了⼀种⽅法来定义新的数据类型,这⼀点与C语⾔类似。
⽤户定义的类型可以与其它数据类型⼀样地使⽤在声明当中。
例如:
typedef unsigned int uint;
uint a, b;
⼀个⽤户定义的数据类型可以在它的定义之前使⽤,只要它⾸先在空的typedef中说明,例如:
typedef int48;// 空的typedef,在其他地⽅进⾏完整定义
int48 c;
7. 枚举类型
在Verilog语⾔中不存在枚举类型。
标识符必须被显式地声明成⼀个线⽹、变量或参数并被赋值。
SystemVerilog允许使⽤类似于C的语法产⽣枚举类型。
⼀个枚举类型具有⼀组被命名的值。
缺省情况下,值从初始值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;
8. 结构体和联合体
在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};
结构体可以作为⼀个整体传递到函数或任务,也可以从函数或任务传递过来,也可以作为模块端⼝进⾏传递。
9. 数组
在Verilog中可以声明⼀个数组类型,reg和线⽹类型还可以具有⼀个向量宽度。
在⼀个对象名前⾯声明的尺⼨表⽰向量的宽度,在⼀个对象名后⾯声明的尺⼨表⽰数组的深度。
例如:
reg [7:0] r1 [1:256];// 256个8位的变量
在SystemVerilog中我们使⽤不同的术语表⽰数组:使⽤“压缩数组(packed array)”这⼀术语表⽰在对象名前声明尺⼨的数组;使
⽤“⾮压缩数组(unpacked array)”这⼀术语表⽰在对象名后⾯声明尺⼨的数组。
压缩数组可以由下⾯的数据类型组成:bit、logic、reg、wire以及其它的线⽹类型。
⽆论是压缩数组还是⾮压缩数组都可以声明成多维的尺⼨。
bit [7:0] a;// ⼀个⼀维的压缩数组
bit b [7:0];//⼀个⼀维的⾮压缩数组
bit [0:11][7:0] c;//⼀个⼆维的压缩数组
bit [3:0][7:0] d [1:10];// ⼀个包含10个具有4个8位字节的压缩数组的
⾮压缩数组
⾮压缩尺⼨在压缩尺⼨之前引⽤,这就允许将整个压缩数组作为⼀个单⼀的元素进⾏引⽤。
在上⾯的例⼦中,d[1]引⽤⾮压缩数组的⼀个单⼀元素,这个元素是⼀个包含4个字节的数组。
10. 在为命名的块中声明
Verilog允许变量在⼀个命名的begin-end或fork-join语句组中声明。
相对于语句组来说,这些变量是本地的,但它们可以被层次化地引⽤。
在SystemVerilog中,既可以在命名的块中也可以在未命名的块中声明。
在未命名的块中,不能够使⽤层次名来访问变量。
所有的变量类型,包括⽤户定义的类型、枚举类型、结构体和联合体都可以在begin-end或fork-join语句组中声明。
11. 常量
在Verilog中有三种特性类型的常量:parameter、specparam和localparam。
⽽在SystemVerilog中,允许使⽤const关键字声明常量。
例如:
const char colon = “:”;
12. 可重定义的数据类型
SystemVerilog扩展了Verilog的parameter,使其可以包含类型。
这个强⼤的功能使得⼀个模块中的数据类型在模块的每⼀个实例中重新定义。
例如:
module foo;
# (parameter type VAR_TYPE = shortint;)
(input logic [7:0] i, output logic [7:0] o);
VAR_TYPE j =0;// 如果不重新定义,j的数据类型为shortint
…
endmodule
module bar;
logic [3:0] i, o;
foo #(.VAR_TYPE(int)) u1 (i, o);// 重新将VAR_TYPE定义成int类型
endmodule
13. 模块端⼝连接
在Verilog中,可以连接到模块端⼝的数据类型被限制为线⽹类型以及变量类型中的reg、integer和time。
⽽在SystemVerilog中则去除了这种限制,任何数据类型都可以通过端⼝传递,包括实数、数组和结构体。
14. 字母值
在Verilog中,当指定或赋值字母值的时候存在⼀些限制。
⽽SystemVerilog则为字母值如何指定作了下⾯的增强:
⼀个字母值的所有位均可以使⽤0、1、z或x作相同的填充。
这就允许填充⼀个任意宽度的向量,⽽⽆需显式地指定向量的宽度,例如:bit [63:0] data;
data = `1; //将data的所有位设置成1
⼀个字符串可以赋值成⼀个字符数组,象C语⾔⼀样加⼊⼀个空结束符。
如果尺⼨不同,它象C中⼀样进⾏左调整,例如:
char foo [0:12] = “hello worldn”;
加⼊了⼏个特殊的串字符:
v:垂直TAB
f:换页
a:响铃
x02:⽤⼗六进制数来表⽰⼀个ASCII字符
数组可以使⽤类似于C初始化的语法赋值成字符值,但它还允许复制操作符。
括号的嵌套必须精确地匹配数组的维数(这⼀点与C不同),例如:
int n [1: 2] [1:3] = {{0, 1, 2}, {3{4}}};
15. 强制类型转换
Verilog不能将⼀个值强制转换成不同的数据类型。
SystemVerilog通过使⽤’操作符提供了数据类型的强制转换功能。
这种强制转换可以转换成任意类型,包括⽤户定义的类型。
例如:
int’ (2.0*3.0)// 将结果转换为int类型
mytype’ (foo)// 将foo转换为mytype类型
⼀个值还可以通过在强制转换操作符前指定⼀个10进制数来转换成不同的向量宽度,例如:
17’ (x - 2) // 将结果转换为17位宽度
也可以将结果转换成有符号值,例如:
signed’ (x) // 将x转换为有符号值
16. 操作符
Verilog没有C语⾔的递增(++)和递减(–)操作符。
⽽SystemVerilog加⼊了⼏个新的操作符:
++和–:递增和递减操作符;
+=、-=、*=、/=、%=、&=、^=、|=、<<=、>>=、<<<=和>>>=赋值操作符;
17. 唯⼀性和优先级决定语句
在Verilog中,如果没有遵循严格的编码风格,它的if-else和case语句会在RTL仿真和RTL综合间具有不⼀致的结果。
如果没有正确使⽤full_case和parallel_case综合指令还会引起⼀些其它的错误。
SystemVerilog能够显式地指明什么时候⼀条决定语句的分⽀是唯⼀的,或者什么时候需要计算优先级。
我们可以在if或case关键字之前使⽤unique或requires关键字。
这些关键字可以向仿真器、综合编译器、以及其它⼯具指⽰我们期望的硬件类型。
⼯具使⽤这些信息来检查if 或case语句是否正确建模了期望的逻辑。
例如,如果使⽤unique限定了⼀个决定语句,那么在不希望的case值出现的时候仿真器就能够发布⼀个警告信息。
bit [2:0] a;
unique if((a==0)||(a==1)) y = in1;
else if(a==2) y = in2;
else if(a==4) y = in3;// 值3、5、6、7会引起⼀个警告
priority if(a[2:1]==0) y = in1;// a是0或1
else if(a[2]==0) y = in2;// a是2或3
else y = in3;// 如果a为其他的值
unique case(a)
0,1: y = in1;
2: y = in2;
4: y = in3;
endcase // 值3、5、6、7会引起⼀个警告
priority casez (a)
2’b00?: y = in1;// a是0或1
2’b0??: y = in2;// a是2或3
default: y = in3;//如果a为其他的值
endcase
18. 底部检测的循环
Verilog包含for、while和repeat循环,这⼏个循环都是在循环的起始处检测循环条件。
SystemVerilog加⼊了⼀个do-while循环,这种循环在执⾏语句的结尾处检测循环条件。
19. 跳转语句
在语句的执⾏过程中,C语⾔提供了⼏种⽅式来跳转到新的语句,包括:return、break、continue和goto。
在Verilog中除了通过使⽤disable语句跳转到语句组的尾部外,没有提供任何其它跳转语句。
使⽤disable语句执⾏中⽌和继续功能要求加⼊块的名字,并且会产⽣不直观的代码。
SystemVerilog加⼊了C语⾔的break和continue关键字,这两个关键字不要求使⽤块名字。
另外,SystemVerilog还加⼊了⼀个return关键字,它可以⽤来在任何执⾏点上退出⼀个任务或函数。
break:退出⼀个循环,与C语⾔相同;
continue:跳转到⼀个循环的尾部,与C语⾔相同;
return表达式:退出⼀个函数;
return:退出⼀个任务或void类型的函数。
SystemVerilog没有包含C语⾔中的goto语句。
20. 块名字和语句标签
在Verilog中,我们可以通过在begin或fork关键字之后指定名字来为begin-end或fork-jion语句指定名字。
这个指定的名字代表整个语句块。
SystemVerilog还允许在end或jion关键字之后指定⼀个匹配的块名字。
这种机制很容易将end或jion与对应的begin或fork联系起来,尤其是在⼀个长的块或嵌套的块中。
块结尾处的名字是可选的,但如果使⽤的话,它必须与块起始处的名字相同。
例如:
begin: foo // 在begin之后的块名字
…
fork: bar // 具有名字的嵌套的块
…
jion: bar // 必须具有相同的名字
…
end: foo // 必须具有相同的名字
SystemVerilog还允许像C语⾔⼀样为单个语句设置标签。
语句标签放置在语句的前⾯,⽤来标识这条语句。
例如:
initial begin
test1: read_enable =0;
…
test2:for(i=0; i<=255; i++)
…
end
21. 对事件控制的增强
Verilog使⽤@标记来控制基于特定事件的执⾏流,SystemVerilog增强了@事件控制。
有条件的事件控制
@标记的⼀个基本应⽤就是推断⼀个具有使能输⼊的锁存器。
下⾯的例⼦演⽰了⼀个锁存器建模的基本风格。
always @(data or en)
if (en) y <= data;
这种编码风格对仿真来说是效率低下的,因为即使在使能输⼊⽆效的时候,数据输⼊的每次改变都会触发事件控制。
SystemVerilog在事件控制中加⼊了⼀个iff条件。
只有iff条件为真的条件下,事件控制才会被触发。
通过将使能判断移⼊到事件控制⾥⾯,使得只有在锁存器输出能够改变的时候事件控制才会被触发。
例如:
always @(a or en iff en==1)
y <= a;
事件控制中的表达式
Verilog允许在@事件控制列表中使⽤表达式,例如:
always @((a * b))
always @(memory[address])
在第⼀个例⼦中,是当操作数发⽣改变的时候还是只有当运算结果发⽣改变的时候才会触发事件控制?在第⼆个例⼦中,是当memory的地址发⽣变化的时候还是只有当memory的值发⽣变化的时候才会触发事件控制?当@事件控制中包含表达式的时候,IEEE Verilog标准允许仿真器进⾏不同的优化。
这就可能导致在不同的仿真器间有不同的仿真结果,可能还会导致仿真与综合之间的结果不⼀致。
SystemVerilog 加⼊了⼀个changed关键字,在事件控制列表中它被⽤作⼀个修饰符。
@(changed (表达式))能够显式地定义只有当表达式的结果发⽣改变的时候才会触发事件控制。
例如:
always @(changed (a * b))
always @(changed memory[address])
事件控制中的赋值
Verilog不允许在事件控制中使⽤赋值。
SystemVerilog允许在事件控制中使⽤赋值表达式。
事件控制仅仅敏感于赋值表达式右侧的变化。
例如:
always @(y = a * b)
22. 新的过程
Verilog使⽤always过程来表⽰时序逻辑、组合逻辑和锁存逻辑的RTL模型。
综合⼯具和其它软件⼯具必须根据过程起始处的事件控制列表以及过程内的语句来推断always过程的意图。
这种推断会导致仿真结果和综合结果之间的不⼀致。
SystemVerilog增加了三个新的过程来显式地指⽰逻辑的意图。
always_ff:表⽰时序逻辑的过程;
always_comb:表⽰组合逻辑的过程;
always_latch:表⽰锁存逻辑的过程。
例如:
always_comb @(a or b or sel) begin
if(sel) y = a;
else y = b;
end
软件⼯具能够检查事件控制敏感列表和过程的内容来保证逻辑的功能匹配过程的类型。
例如,⼯具能够检查⼀个always_comb过程能够敏感过程内读取的所有外部值,对逻辑的每⼀个分⽀的相同变量进⾏赋值,并且检查分⽀是否覆盖了所有可能的条件。
如果任何⼀个条件没有满⾜,软件⼯具均会报告该过程没有正确建模组合逻辑。
23. 动态过程
Verilog通过使⽤fork-jion提供了⼀种静态的并发过程。
每⼀个分⽀都是⼀个分离的、并⾏的过程。
fork-jion中任何语句的执⾏必须在组内的每⼀个过程完成后才会执⾏。
例如:
initial begin
fork
send_packet_task (1,255,0);
send_packet_task (7,128,5);
watch_result_task (1,255,0);
watch_result_task (7,128,5);
jion // 所有的任务必须完成后才会到达这⾥
end
SystemVerilog通过process关键字加⼊了⼀个新的、动态的过程。
它为⼀个过程产⽣分⽀,然后继续执⾏⽽⽆需等待其他过程完成。
过程不会阻塞过程或任务内的语句执⾏。
这种⽅式能够建模多线程的过程。
例如:
initial begin
process send_packet_task (1,255,0);
process send_packet_task (7,128,5);
process watch_result_task (1,255,0);
process watch_result_task (7,128,5);
end // 所有的过程并⾏运⾏
24. 任务和函数增强
SystemVerilog为Verilog的任务和函数作了⼏个增强。
静态和⾃动的存储
缺省情况下,在Verilog任务或函数内的所有存储都是静态的。
Verilog-2001允许将任务和函数声明成⾃动的。
在SystemVerilog中:(1).在⼀个静态任务和函数内的特定数据可以显式地声明成⾃动的。
声明成⾃动的数据在块中具有完整的⽣命周期,并且在任务和函数调⽤的⼊⼝处初始化;(2). 在⼀个⾃动的任务或函数中的特定数据可以显式地声明成静态的。
⾃动的任务或函数中声明成静态的数据在⼀个块的本地范围内具有静态的⽣命周期。
从任何点返回
Verilog在⼀个任务或函数中执⾏到endtask或endfunction关键字的时候返回。
函数的返回值是给函数名赋的最后⼀个值。
SystemVerilog加⼊了⼀个return关键字,使⽤这个关键字,⼀个任务或函数可以在任何点上返回。
多语句
Verilog要求⼀个任务或函数只具有⼀个语句或语句块。
多条语句必须组合到⼀个单⼀的begin-end或fork-jion块中。
SystemVerilog去除了这种限制。
因此,多条语句可以在⼀个任务或函数中列出⽽⽆需使⽤的begin-end或fork-jion。
每有分组的语句就像在begin-end中⼀样顺序执⾏。
我们还可以产⽣⼀个没有语句的任务或函数定义。
void函数
Verilog要求⼀个函数具有⼀个返回值,函数的调⽤接收这个返回值。
SystemVerilog加⼊了⼀个void数据类型,这个数据类型可以作为⼀个函数的返回值类型。
void函数可以像Verilog任务⼀样进⾏调⽤,⽽⽆需接收⼀个返回值。
void函数和任务的差别在于函数存在⼏个限制,例如没有时间控制等。
函数的输⼊和输出
Verilog标准要求⼀个函数⾄少具有⼀个输⼊并且函数只能具有输⼊。
SystemVerilog去除了这些限制。
函数可以具有任意数⽬的输⼊、输出以及输⼊输出,也可以什么也没有。
25. 连续赋值的增强
在Verilog中,连续赋值语句的左侧只能是线⽹类型,例如wire。
连续赋值语句被认为是线⽹的驱动源,⽽线⽹可以拥有任意数据的驱动源。
SystemVerilog允许除reg类型以外的任何数据类型⽤于连续赋值语句的左侧。
与线⽹不同,所有其它数据类型被限制为只能有⼀个连续赋值语句驱动。
为相同的变量混合使⽤连续赋值语句和过程赋值语句是不被允许的。
26. $bit系统函数
在Verilog中没有类似于C语⾔中sizeof的函数。
SystemVerilog加⼊⼀个新的$bit内建函数。
这个函数返回保存⼀个值所需的硬件位的数⽬(⼀个四态值要求⼀个硬件位),这个函数还可以⽤来确定⼀个结构体所代表的硬件位的数⽬。
27. `define的增强
SystemVerilog增强了define编译器指令的能⼒以便⽀持将字符串作为宏的参数。
宏的⽂本字符串中可以包含⼀个隔离的引号,它的前⾯必须具有⼀个反勾号(”),这就允许字符串中包含宏参数。
宏⽂本可以在⾏的尾部包含⼀个反斜杠(’’)来表⽰在下⼀⾏继续。
如果宏⽂本字符串中包含反斜杠,则反斜杠应该被放在两个反勾号之间,这样它就不会被认为是Verilog转义标识符的开始。
宏⽂本字符串还可以包含双反勾号
(``),它允许标识符能够从参数中构建。
这些增强使得define指令更加灵活。
例如:include指令后可以紧跟⼀个宏名字来替代⼀个字符串。
`define f1 “../project_top/opcode_defines”
`include `f1
28. 状态机建模
SystemVerilog允许在更⾼的抽象层次上对状态机建模。
这些结构包括:
枚举类型
⼀个特殊的state数据类型;
⼀个迁移语句
⼀个迁移操作符
29. 断⾔
SystemVerilog中加⼊了断⾔的功能来改善系统的验证过程。
30. 结论
SystemVerilog为Verilog-2001标准提供了⼀系列的扩展。
这些扩展使得⼤型设计的建模和验证更加容易。
31. package
systemverilog⾥⾯的package有点类似C++中的名字空间namespace。
通过import package可以获得package⾥⾯声明的类型或变量。
32.SystemC与SystemVerilog特点⽐较
就SystemC和SystemVerilog这两种语⾔⽽⾔, SystemC扩展了C++在硬件⽅⾯的适⽤范围,⽽SystemVerilog扩展了Verilog在基于对象和验证平台⽅⾯的适⽤范围。
⽽这两种语⾔均⽀持诸如信号、事件、接⼝和⾯向对象的概念,但每⼀种语⾔⼜均拥有⾃⼰明确的应⽤重点:
●SystemC对于体系架构开发编写抽象事务处理级(TL)模型、或执⾏建模来说最为有效,特别是对于具有很强C++实⼒的团队和有基于C/C++ IP 集成要求(如处理器仿真器),以及为早期软件开发设计的虚拟原型来说,更是如此。
●SystemVerilog对于RTL、抽象模型和先进的验证平台的开发来说最有效率,因为它具备了执⾏这⽅⾯任务所需的基础架构,例如受限制随机激励⽣成、功能覆盖或断⾔。
●SystemVerilog显然是描述最终的RTL设计本⾝的⾸选语⾔,不仅在于其描述真实硬件和断⾔的能⼒,还在于对⼯具⽀持⽅⾯的考虑。
这并不意味着每种语⾔不可以⽤在不同的应⽤中。
实际上,SystemC可以⽤于验证平台和描述RTL结构,⽽SystemVerilog也可以⽤于编写⾼层事务处理级模型。
但是,每⼀种语⾔都⽤于⾃⼰的重点应⽤时,它们可以达到最佳的效率。
这点对于复杂的项⽬特别适⽤,在这种项⽬中,不同的任务分属于不同的组,通常有不同的技能要求。
注重实效的解决⽅案以及符合设计团队的多种技术要求的⽅法是同时使⽤SystemC和SystemVerilog来开发和验证当今设计流程需要的虚拟原型的事务处理级模型。
’ 单引号语法。