SV和Verilog的语法类似,和C/C++也有些共性,基本SV可包含Verilog的所有规则,本文会在以下博文内容外做补充,若有相异处下文会特意指出。Verilog语法可参考该链接第1大节。链接:IC设计——Verilog HDL学习笔记_KGback的博客-CSDN博客
1. 数据类型
- 二值逻辑和四值逻辑
编码时一定要注意操作符左右两侧的符号类型要一致
二值逻辑:包括 bit, byte, shortint, int, longint等,均为有符号类型(bit除外);这些类型的值只包含{0,1},目的是模拟计算机验证环境,提高仿真性能,节约空间。若有四值逻辑数给其赋值,x,z会默认被赋值为0,因此二值逻辑数要远离DUT
四值逻辑:包括logic, integer, reg, wire等,均为无符号变量(integer除外);目的是模拟外部物理世界 - logic
用法既拓展了传统的reg型,也可以像wire那样连线,但既然被应用在验证场景中,因此无需关心对应的逻辑是否被综合为寄存器还是线网,只需作为简单的变量赋值即可。
注意:当含有多驱动(multi-drive)的场景是必须使用wire型。 - 动态数组和联合数组
int array[]; //动态数组,compile时长度不确定,simulation时长度确定
array = new[20]; //new分配空间logic [31:0] array[*]; //联合数组,目的是节约空间
- 队列
概念类似C语言里的队列,用法也类似,可自由插入删除数据,
shortint queue[$] = { 1,2,3 }
queue.insert(1,7); //{1,7,2,3} 在第一个数后面插入一个7
queue.delete(1); //{1,2,3}
queue.push_front(6); //{6,1,2,3} 在队列前插入6
queue.push_back(7); //{6,1,2,3,7} 在队列后插入7
j = queue.pop_front; //{1,2,3,7} 同理pop_back - 结构体
类似C语言里的结构体,包括概念和用法
struct {bit [7:0] r,g,b;} pixel; - 枚举
enum logic [1:0] {…} state; //可定义z,x状态 - 字符串
SV里的字符串单个字符是用byte类型,且不像C语言,字符串的结尾不带标识符null,因此\0相关操作将无效
string s = “Kevin “;
$display(s.getc(0)); //显示第一个字符的ASCII码
$display(s.tolower()); //显示整个字符串的小写kevin
$display(s.toupper()); //显示整个字符串的大写KEVIN
s.putc(s.len()-1, “-“); //将字符-写在字符串的s.len()-1位置上 Kevin-
s = {s, “Gu”} //合并字符串
$display(s.substr(2,5)); //提取从位置2到5间的所有字符
2. 关键词
- typedef
定义新的类型
typedef reg [15:0] opreg_t; //创建新的类型opreg_t等价于reg [15:0]
typedef class Packet //创建一个类别名
- 一些关键词
- ref…
用在function/task赋值,ref参数只能被用于带自动存储的子程序中,若使用automatic,则整个子程序内部都是自动存储的
function automatic void f1( ref data ) //此处data和外部定义的data共用同一物理地址,因此两值同时变化
endfunction //若希望内部值的改变不影响外部值的改变,可在内部定义为const ref data - automatic和static
automatic变量类似于软件中的局部变量,在它的作用域生命结束时被销毁回收存储空间
static变量若在仿真开始时被创建,在进程执行过程中自身不会被销毁,且会被多个进程共享。 - inside
if((a==1)||(a==2)||(a==3)) 等价于if( a inside {1,2,3}) - with
一般和randomize(value)连用,with后接对value的约束 - time
64bit的整数,小数部分会被舍入。描述时间,单位为timescale定义的精度
time tdelay = 800fs //0.1ps - rand
随机成员要带有关键字rand,只能在类中声明
rand bit [7:0] data1; //data1值取0-255中的任意数
randc bit [7:0] data2; //data2取0-255中任意值,但每次取值都不一样,只限于bit和enum类型
constraint range1{ //约束data1范围
data1>100; data1<200;
data1>data2; } - dist { value1 := weight1 value2 :/ weight2 }
划分权重,用在随机化操作中
[1:2]:=40; //每个数权重都是40
[1:2]:/40; //每个数权重是20 - solve…before…
用在随机数产生时,constraint魔窟啊里面
solve y before x //先产生x,再产生y - semaphore
创建对象可复用 - mailbox
创建一个信箱,使通信数据在不同process交换,可理解成fifo
- 类相关
- virtual function
SystemVerilog提供了2种构造方法来创建一个可以共享的基类:第一种是抽象类,即可以被扩展但是不能被直接实例化的类,使用virtual
关键词进行修饰;第二种是纯虚方法,用关键词pure
修饰,如下2所述。
通过virtual function,在派生类必须具有该函数的具体实现 - pure virtual function
定义没有实体的纯虚函数。这是一种没有实体的方法原型,并且纯虚方法只能够在抽象类中定义。
virtual和pure virtual的区别:如果有一个带有pure virtual function的Virtual Class,则必须在子类中对其具体实现。但对于virtual function,可以覆盖也可以不覆盖。System Verilog的抽象类(abstract class)和纯虚方法(pure virtual )_飞飞飞C的博客-CSDN博客
3. 特殊符号及搭配
- 通配符 .*
可以把相同名字的net和port连在一起
test test1( .a(a), .b(b), .c(c) ); //或者 test test1( .a, .b, .c );
等同于 test t1( .* ); - ==? / !=?
判断符号两边是否像相等或不等,x,z处做通配处理 - ++
SV里面可以用自增符 - ‘value 赋值
data0 = ‘x //SV中赋值可无需添加b,o,h等代表进制的符号
data1 = ‘1 //SV中可给某个值赋值全1,注意Verilog中不行 - int'( value)
强制类型转换,int也可以是其他数据类型或unsigned,signed - value1′( value2 )
位宽强制转换,value1是位宽值 - ##
延迟一个时钟周期 - |->
在当前时钟周期 - ::
域名索引符
4. 内建函数
- $cast
参考链接:SystemVerilog中类型转换$cast的使用_254、小小黑的博客-CSDN博客
- 随机函数
- randomize(value)
- urandom() //返回无符号的32bit数
- urandom_range(val1, val2) //返回在[val1, val2]区间内无符号的32bit数
- random() //返回有符号的32bit数
- 数组的操作函数
bit on[10] ={ 2{1,2,3,4,5}};
int tq[*];
sum1 = on.sum; //数组求和,积(product),与(and),或(or),异或(xor),最小值(min),最大值(max),相异值(unipue)
sum2 = on.sum with (int'(item)); //使用带32比特有符号数显示,在条件语句with中,item是缺省值
tq = on.find with(item >3); //找出所有大于3的元素
on.reverse(); //数组反向排列,升序(sort),降序(rsort),混排(shuffle)
5. 语句块
- 循环语句块
循环语句用于控制执行语句的执行次数,用于在仿真代码中生成仿真激励信号。循环里面一定要有时间在运行,如@(clk)等等,否则会陷入死循环且时间不走动。
for(int i=0; i<=5; i++)… //for循环,相较于verilog,i可以内部定义,且作为局部变量,作用范围只限于for循环
while(i<5) begin…end //while循环,同样存在do…while()
foreach(src[i]) //foreach循环,和for功能类似,但foreach多了可编译的功能,及判断条件里可有变量
src[i] = i;
- 过程语句块
- always_comb
组合逻辑,无需敏感信号,避免产生latch警告always_comb //若需要latch警告,则使用always_latch
if (a == 1)
b <= 5; - always_ff
时序电路,需要敏感信号,且一定是边沿敏感,避免出现flip-flop触发器警告always_ff( posedge clk )
if ( en )
a <= b; - final块
这个块在Verilog中是没有的,当遇到$finish的时候,会进入到final块中。一般用在打印一些信息,注意final块中是不能加延迟#操作的,不然会报错。
- program
program将DUT和testbench作了清晰的划分,可以将设计和验证的调度区域通过显式的方式来安排。
可以将program看成是按软件的方式运行的,编写该部分代码时完全可以用C语言的思维,无需考虑代码并行执行的情况(除了jork等并行语句),所以非常适合在该块中进行该测试用例产生,发送以及比较数据的接收。
可在module直接被例化,但是语句块里面不能出现和硬件相关的过程语句和实例(如always,module等),也不能由其他program语句,可以有initial,task等块。
program内部定义的变量赋值的方式应该采用阻塞赋值(软件方式),在驱动外部的硬件信号时应该使用非阻塞赋值(硬件方式)。$exit()强制结束该系统函数所在的program。
program中的initial块会在reactive区执行,外部的initial会在active区执行。
program execute_test
initial begin
…
end
task task1()
…
endtask
endprogram
- interface
作为中间模块将testbench和DUT连接,可以将它看成一个“路由器”,集合多个信号,简化连接,方便调用。
interface可以包含过程语句(always和initial)和连续赋值语句
interface若要与DUT相连需要用四值逻辑,不能用二值逻辑
interface可以定义参数、输入输出端口,若接口对不同连接模块的方向不同,可以将端口定义在modpot中。
- clocking
为了避免冒险竞争,通常会把clk驱动的同步信号封装在一个模块里,由interface调用。 - modport
用来来连接不同的测试情况
interface signal_test( input bit clk ); //定义
logic [1:0] A, B;
logic reset;
clocking dram @( posedge clk)
input #1ps A;
input #5
output #6 B;
endclocking
modport user1( output A, input B, reset); //声明的端口可以在不同的modport里定义为不同的输入输出模式
modport user2( clocking cb, input reset); //调用clocking,port输入输出和user1不一样
endinterface
always #5 clk = ~clk;
signal_test.user1 signal1(clk); //声明user1模式
signal_temp signal2( .A(signal1.A), ……); //interface互相直接连接
test test1( signal1 ); //interface与module连接
- package
可利用package(包)实现在module,interface和program中共享parameter、data、task、class等。
即将不同模块的类定义规整到不同package中,在单一的命名空间下,使得分数不同模块验证环境的类来自不同的package,从而解决类的归属问题。
package regs_pkg; //定义
`include “simulator.sv”
`include “monitor.sv”
endpackage
package arb_pkg; //定义
`include “simulator.sv”
`include “monitor.sv”
endpackage
module mcdf_tb; //调用
reg_pkg::monitor mon1 = new(); //l两个package中同名类monitor的内容不同,实现不同的功能
arb_pkg::monitor mon2 = new();
endmodule
- sequence
序列内的语句按顺序执行。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/82522.html