百度网盘资料有路科V1 V2 V2pro 个人不能区分v2 和v2pro 暂时使用v2pro
使用方法:课件和红皮书大致相同,所以跟着视频看课件,不看红皮书了
1 SV
(1)先看电子版绿皮书对应章节,了解概念性东西
(2)再看路科视频,相当于挑重点
(3)做实验
(4)有时间回看绿皮书,相当于复习
2 UVM
4.1 接口
时间:2024/7/23复习
位置:V2pro-07【SV精通2】接口采样驱动-34接口
学习方法:路科课件、找对应绿皮书部分(说明这块是重点,其他不看)、找网上代码分析一边
学习感悟:绿皮书必须看,路科验证视频句句有知识点
接口与模块类比【interface module】
联系:
interface接口与module使用性质很像
1 可以定义端口、也可也定义双相信号;
端口列表中定义时钟、复位,或者不定义任何端口信号反而在变量列表中定义与DUT和TB连接 的logic变量
3 也可以靠参数化提高复用性
4 接口例化方式和module例化方式一样
5 DUT 和TB组件(比如simulator)在例化时,传递interface变量名即可完成interface变量传递
6 可以使用initial和always【过程块】;也可以定义function和task【任务和函数】
差别:
(1)模块可以例化模块、接口
(2)接口不能例化模块,能例化其他接口【接口是用来数据传递的】
接口作用
(1)用于连接硬件【DUT】和软件环境【TB】
类似插排,DUT和TB之间的数据驱动关系使用插排完成
(2)作为module的端口列表
(3)作为TB中的形式参数
端口和接口
举例:Arbiter和Testbench的连接
(1)端口:Arbiter和TB之间使用clk 、rst [1:0]、request [1:0]、grant连接
(2接口interface:Arbiter和TB各自独立,通过interface进行通信【TB通过interface激励给Arbiter,Arbiter通过interface把信号反馈回TB】
接口定义和例化
信号:clk 、rst [1:0]、request [1:0]、grant
//***************************使用接口简化连接****************************//
//仲裁器的接口 // interface endterface
interface arb_if(input bit clk); //时钟可以是接口的一部分或者一个独立端口
logic [1:0] grant,request; //信号用logic类型
logic rst ;
endinterface
//使用接口的仲裁器arb模块
module arb_with_arbif(arb_if arbif); //arb_if是上述定义的接口名,arbif是接口实例名字,被引用
always @(posedge arb_if.clk or posedge arbif.rst)
begin
if(arbif.rst)
arb_if.grant <= 2'b00;
else if (arbif.request[0])
arb_if.grant <= 2'b01;
else if (arbif.request[1])
arb_if.grant <= 2'b10;
else
arb_if.grant <= next_grant;
end
endmodule
//使用接口的测试平台test模块
module test_with_arbif(arb_if arbif); //module endmodule:test
initial begin
@(posedge arbif.clk); //表示每个clk上升沿做某事
arbif.request <= 2'b01;
$display("@%0t:Drove req = 01",$time);
repeat (2) @(posedge arbif.clk); //延迟2个时钟周期
if(arbif.grant != 2'b01)
$display("@%0t:Error:grant != 2'b01",$time);
$finish;
end
endmodule:test_with_arbif
//顶层top模块 以上所有模块在top中例化和连接
module top; //module endmodule:top
bit clk;
always #50 clk = ~clk;
arb_if arbif(clk);//实例化模块,并连接接口
arb_with_arbif a1(arbif);
test_with_ifc b1(arbif);
endmodule : top
定义(interface endface) 声明 名称 (参数:输入方向 ) 信号
定义arb模块 arb 接口arb_if作为参数 无需规定方向 arbif.表示驱动
定义tb模块 test 接口arb_if作为参数 通过finish结束仿真
顶层top:例化接口arbif 同时把时钟clk传进去、例化arb 名t1、test 名a1要把arbif实例传进去
接口优势
1 将相关信号封装到接口,添加新信号时只需在接口中声明,不需在更高层次模块说明
2 接口interface既可以在硬件module,又可以在软件class中使用,是软硬件交互的媒介
3 多组相同总线的例化和使用时灵活 channel interface
4 在MCDF中接口优势
35 采样和驱动1
接口:数据驱动、采样
36 采样和驱动2
37 测试的开始和结束
38 调试方法
位置:V2pro-07【SV精通2】接口采样驱动-35采样和驱动
硬件和过程快
1 always
-always@(event) - 敏感列表是为了模拟硬件信号的触发行为【描述组合、时序】
(1)always描述时序逻辑【敏感列表有时钟去驱动】:寄存器
(2)always描述组合逻辑【敏感列表无时钟去驱动】:组合逻辑、锁存
-always过程块在module或者interface中使用
解释:
-不同的always之间并行执行【相当于不同的硬件块】
-在always中只能做时序逻辑的复位【硬件行为】,而初始化在定义变量或者initial语句中【软件行为】
2 initial(初始化)
-initial只执行一次【软件行为】
-在initial内部语句顺序执行
-不可综合【不是用来描述电路的】:所有测试语句放在initial中,便于统一管理测试顺序
-initial过程块可以在module、interface、program中使用
3 initial VS always
-inital和always在代码中无论先后顺序如何,都是同时开始执行【优先级相同】,也都无法延迟执行
-initial、always两种过程块都要用begin...end将作用域包住【类似于C语言{...}】
软件方法
1 函数function
-SV函数和C语言非常类似
(1)参数列表:可以指定输入参数(input)、输出参数(output)、输入输出参数(inout)、引用参数(ref)
(2)function可以返回数值【关键词return】或者不返回数值(void)【在声明时采用void function( )】
function int double (input a);
return 2*a;
endfunction
initial begin
$display("double of %0d is %0d,10,double(10))
end
//定义了名为double的函数,输入类型为input的参数a,返回类型为int
//执行将输入参数 a 乘以2的操作,并将结果返回给调用者
//函数定义的结束
//定义一个初始块。初始块在仿真开始时执行一次
//使用 $display 系统任务来输出信息到控制台。%0d 是格式化字符串,用于显示十进制整数。在这个字符串中,%0d 被用来格式化两个整数。
第一个 %0d 将被替换为 double 函数的输入参数 a 的值。
第二个 %0d 将被替换为 double 函数的返回值,即 a 的两倍。
double(10) 是调用 double 函数的一个实例,传入的参数是数字10
(3) function默认的类型是logic(四值)
input [7:0] addr //只指定了输入,没有规定类型默认logic
(4) 数组可以作为形式参数传递
(5) 不太懂
2 任务 task
(1)task无法通过return返回结果,只能通过output、inout、ref的参数返回【返回在参数列表中】
task mytask1(output logic [31:0] x,input logic y); //task和mytask1之间无返回值类型
endtask
(2)task可以加耗时语句:@event、 wait event 、#delay 【但是function不能,必须立刻开始执行】
3 task【任务】和function【函数】区别
1 小白都使用task,有经验要区分:function用于不含耗时的数字运算或逻辑运算,task用于耗时的信号采样或者驱动
2 function可以被function或者task调用,而task只能被task调用
4 习题
【function的参数列表中如果不指定则默认为输入类型】
//默认function中s和t都是输入,所以直到t.cmd t变成 2 0 0(在这之前t是 0 0 0)
除非在function参数列表中明确给output数据类型
5 变量生命周期
(1)在SV中,将数据的生命周期分为动态(automatic)和静态(static)
(2)局部变量:与域共存亡【function/task】
全局变量:从程序开始到结束一直存在【module中默认全局变量】
例子:
(1)动态:每次进入都要初始化,重新赋值
(2)静态:已经保留了上一次的值,第二次进入以后不用初始化
(3)默认:默认静态,即下一次可以接着上一次来
MCDF实验0
接口时序
在Questasim中编译:先编译底层(单个模块),再编译上层模块
在linux中用VCS仿真,需要用到makefile脚本
不要让仿真器优化任何逻辑:simulate without Optimization
随机约束
如何产生一个随机数?
(1)使用系统函数 randomize()
(2)$urandom() $urandom-range(maxval,minval=0)
约束
随机对象?
例1: