热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

systemveriloginterface

背景DUT和tb之间的port口的数量较多,很容易犯错,可以将interface看成一根巨大的线缆,然后线缆里面包括了许多传输线

背景

DUT和tb之间的port口的数量较多,很容易犯错,可以将interface看成一根巨大的线缆,然后线缆里面包括了许多传输线,连接不同的设备。


interface的定义和使用

需要注意的:


  • 如果是使用logic clk,会出现logic的默认值是x,如果后续的tb没有对clk进行赋值,则他可能会出现一直是x的状态。把if的clk设为bit的话默认为0。

interface arb_if(input bit clk);//类似module和endmodule,arb_if是interface名,portlistlogic[1:0] grant,request;//三把线,grant表示授予权限logic grant_valid;logic rst;
endinterfacemodule arb(arb_if arbif);//例化接口并且使用标识符
...always@(posedge arbif.clk or posedge arbi.rst);//interface的标识符(例化名).里面的线

连接top和子模块

module top;bit clk;always # 5 clk = ~clk;arb_if arbif(clk);//实例化if,然后传入clk;arb a(arbif);//DUT用实例化的arbif;test t(arbif);//TB传入实例化的arbif;//arb_port al(.grant(arbif.grant),.request(arbif.request),.rst(arbif.rst),.clk(arbif.clk);第二种方式:连接端口和接口的
endmodule

如果都没有使用interface的话

moduel top;
bit clk;
always #5 clk=~clk;
arb_if arbif(clk);
//端口连接
test_arbif t1(.grant(grant),.request(request),.rst(rst),.clk(clk));
arb_port u0_arbport(.grant(grant),.request(request),.rst(rst),.clk(clk));endmodule

modport

之前的interface是没有指出方向的,我们可以在interface里面通过modport指出方向,并且

interface arb_if(input bit clk);//如果方向错了也是会报错的,实际上用的人比较少 logic[1:0]grant,request;logic rst;modport TEST(output request,rst,input grant,clk);//modport的input是不能给他驱动的modport DUT(input request,rst,clk,output grant);modport MONITOR(input request,grant,rst,clk);
endinterface

modport使用

module arb(arb_if.DUT arbif);
...
endmodulemodule TEST(arb_if.TEST arbif);
...
endmodulemodule monitor(arb_if.MONITOR arbif);
...
endmodule

module和interface区别


  • interface不能例化module的,module可以例化interface;
  • 不能将module里面portlist含有另一个module的,可以含有interface
  • 如果function、task的端口声明中声明为ref,那么function、task必须是automatic!
  • 在program或者module中,function、task默认都是static

激励时序


竞争与冒险

组合逻辑中可能会传输不同的路径,有先后顺序,然后到达输出门的时间不同,这个现象是竞争;产生毛刺现象(冒险);后仿真比较容易看到延迟,打开dtelt-cycle,可以看到;
#0 能强制让b进程晚于a进程,避免竞争冒险的,一般会在验证环境中,


delta cycle


  • 实际具体的电路中,会有一定的延迟时间,但是我们是无法得知是多少的,所以我们在仿真过程中会人为地在模拟过程中的时钟电路驱动添加一个无限小的时间delta cycle的延迟。
  • 如果仿真器进行一个run 0 ,就可以运行一个delta cycle。
  • 在时钟有效沿之后才进行有效采样,也就是说我们想得到我们想要的数,我们需要在时间有效沿后一点点位置进行采样。

module top_tb;
bit clk1,clk2;
bit rst;
logic [1:0] data;//产生时钟
initial beginforever #1 clk1 = ~clk1;
end
//基于clk1产生时钟
always &#64;(clk1)beginclk2 <&#61; clk1;
end
initial begin#2 rst &#61; 1&#39;b0;#4 rst &#61; 1&#39;b1;#10 $stop;
endalways &#64;(posedge clk1 or negedge rst)beginif(!rst) data <&#61; 2&#39;b00;elsedata <&#61; data&#43;2&#39;b01;end
always &#64;(posedge clk1)begin$display("clk1 &#64;%t : data is %h",$time,data);
end
always &#64;(posedge clk2)begin$display("clk2 &#64;%t : data is %h",$time,data);
end
endmodule

这里使用verdi进行仿真&#xff0c;在./simv &#43;fsdb&#43;delta 才能使用view-expand delta ,怎么使用verdi进行看delta
在这里插入图片描述在这里插入图片描述
在这里插入图片描述
如果设计和测试同时对同一个信号进行访问&#xff0c;例如&#xff1a;tb正在初始化某一变量&#xff0c;而RTL同时也要读这个变量&#xff0c;读回来的是初始化前的值。


timing region

在Verilog进行仿真时&#xff0c;在一个timeslot里面的语句是按照一定事件顺序执行的&#xff1b;


  • Active Events&#xff1a;1&#xff09;blocking assignments&#xff1b;2&#xff09;nonblocking assignment RHS计算&#xff1b;3&#xff09;连续赋值&#xff1b;4&#xff09;$display command execution&#xff1b;
  • Inactive Events&#xff1a;#0 blocking assignment
  • Nonblocking Events:nonblocking assignment RHS更新到左边的赋值过程&#xff1b;
  • Monitor Event:1)$monitor;2) $strobe
    在这里插入图片描述

sig1<&#61;sig2&sig3;
$display(sig1);//发生在active
$monitor(sig1);//monitor events

为避免仿真和设计竞争问题(race condition)&#xff0c;systemverilog中引入了program的概念。
在这里插入图片描述
关于timing region的说明


  • 经常有说往前采值&#xff0c;就是说的是往preponed区进行采值&#xff0c;当前的preponed区的值也就是上一个timeslot的postponed值&#xff1b;
  • Observed区是触发clocking block&#xff0c;同时的并行断言也是这里进行的&#xff1b;
  • 一般后面的sv的区&#xff0c;是通过program区进行的&#xff0c;其中名字就是Verilog里面的前面加上一个re&#xff1b;

program为了区分验证环境和设计环境&#xff0c;它不能包含任何的层次结构&#xff0c;也就是他不能包含module、interface、program&#xff1b;
但是在UVM里面没什么人使用program了&#xff0c;都是会使用class&#xff0c;在program里面能够做的事情在module里面都可以进行。
program里面不能使用always&#xff1a;


  • tb中程序一般会遵循初始化-驱动激励信号-获取DUT对激励的反馈&#xff0c;直到结束&#xff0c;当最后一个initial模块结束后&#xff0c;这个仿真就结束了&#xff0c;就像执行$finish一样。
  • always语句是没有结束&#xff0c;需要$exit来指定才能接受。
  • 如果需要一个类似always块的功能&#xff0c;可以使用“initial forever”来完成相同的事&#xff0c;所以initial forever可以在tb中可以使用。

program需要注意的&#xff1a;


  • program中不能例化其他program和module 不能出现interface和always&#xff0c;可以使用initial forever替代always program内部可以发起多个initial块
  • program中内部定义的变量最好采用阻塞赋值&#xff0c;当然采用非阻塞仿真器也不会产生error&#xff0c;驱动外部信号则应该采用非阻塞赋值
  • program中的initial块和module中的initial块执行位置不同&#xff0c;前者在reactive&#xff0c;后者在active块中执行。
  • program中存在的多个initial块中&#xff0c;如果有一个initial采用了退出系统函数$exit&#xff08;&#xff09;&#xff0c;则会结束该program&#xff0c;而不仅仅是该initial块。

program和module的相似和不同


  • module里可以定义program&#xff0c;而program里不能定义module;
  • module里不能调用program里定义的task,function&#xff0c;而program可以调用module里定义的task和function&#xff1b;
  • program里不能例化module,interface,其它program,也不能包含always块·。
  • 最主要的区别是program是在inactive时域执行的&#xff0c;而module在active时域执行的&#xff0c;所以program在module后执行&#xff0c;可以解决竞争冒险现象

clocking block

systemverilog通过clocking的来实现这个采样和驱动过程

interface tb_itf(input bit clk);parameter setup_time &#61; 3;
parameter hold_time &#61; 2;
logic [1:0] dat_in,dat_out;clocking cb&#64;(posedge clk);//这里再interface里使用&#xff0c;但是它也可以再module、program也是可以使用的。default input #setup_time output #hold_time;//在clk上升沿的前3ns对其进行输入采样&#xff0c;在完成事件后的2ns进行输出驱动output dat_in;//out tb to dutinput dat_out;//from dut to tb
endclockingmodport TEST(clocking cb);
modport DUT(input dat_in,output dat_out);
endinterface//tb_itfmodule duv(tb_itf.DUT itf);
initial beginitf.dat_out &#61; 2&#39;b01;#19 itf.dat_out &#61; 2&#39;b11;#7 itf.dat_out &#61; 2&#39;b10;#14 itf.dat_out &#61; 2&#39;b01;
end
endmodulemodule test(tb_itf.TEST itf);
initial beginitf.cb.dat_in <&#61; 2&#39;b00;#9 itf.cb.dat_in <&#61; 2&#39;b11;#13 itf.cb.dat_in <&#61; 2&#39;b11;#16 itf.cb.dat_in <&#61; 2&#39;b11;#14 itf.cb.dat_in <&#61; 2&#39;b11;#50 $finish;
end
endmodule

进行top模块连接

module top_tb;
bit clk,rst;
initial beginclk &#61; 1&#39;b1;forever #5 clk &#61; ~clk;
end
tb_itf itf(clk);
duv dut(itf);
test tb(itf);
$monitor("&#64;%0t dat_in &#61; %d",$time,itf.cb.dat_in);
$monitor("&#64;%0t dat_out &#61; %d",$time,itf.cb.dat_out);endmodule

推荐阅读
  • 个人学习使用:谨慎参考1Client类importcom.thoughtworks.gauge.Step;importcom.thoughtworks.gauge.T ... [详细]
  • 如何自行分析定位SAP BSP错误
    The“BSPtag”Imentionedintheblogtitlemeansforexamplethetagchtmlb:configCelleratorbelowwhichi ... [详细]
  • Nginx使用(server参数配置)
    本文介绍了Nginx的使用,重点讲解了server参数配置,包括端口号、主机名、根目录等内容。同时,还介绍了Nginx的反向代理功能。 ... [详细]
  • 本文分享了一个关于在C#中使用异步代码的问题,作者在控制台中运行时代码正常工作,但在Windows窗体中却无法正常工作。作者尝试搜索局域网上的主机,但在窗体中计数器没有减少。文章提供了相关的代码和解决思路。 ... [详细]
  • 自动轮播,反转播放的ViewPagerAdapter的使用方法和效果展示
    本文介绍了如何使用自动轮播、反转播放的ViewPagerAdapter,并展示了其效果。该ViewPagerAdapter支持无限循环、触摸暂停、切换缩放等功能。同时提供了使用GIF.gif的示例和github地址。通过LoopFragmentPagerAdapter类的getActualCount、getActualItem和getActualPagerTitle方法可以实现自定义的循环效果和标题展示。 ... [详细]
  • 前景:当UI一个查询条件为多项选择,或录入多个条件的时候,比如查询所有名称里面包含以下动态条件,需要模糊查询里面每一项时比如是这样一个数组条件:newstring[]{兴业银行, ... [详细]
  • 本文讨论了在openwrt-17.01版本中,mt7628设备上初始化启动时eth0的mac地址总是随机生成的问题。每次随机生成的eth0的mac地址都会写到/sys/class/net/eth0/address目录下,而openwrt-17.01原版的SDK会根据随机生成的eth0的mac地址再生成eth0.1、eth0.2等,生成后的mac地址会保存在/etc/config/network下。 ... [详细]
  • 基于PgpoolII的PostgreSQL集群安装与配置教程
    本文介绍了基于PgpoolII的PostgreSQL集群的安装与配置教程。Pgpool-II是一个位于PostgreSQL服务器和PostgreSQL数据库客户端之间的中间件,提供了连接池、复制、负载均衡、缓存、看门狗、限制链接等功能,可以用于搭建高可用的PostgreSQL集群。文章详细介绍了通过yum安装Pgpool-II的步骤,并提供了相关的官方参考地址。 ... [详细]
  • Iamtryingtomakeaclassthatwillreadatextfileofnamesintoanarray,thenreturnthatarra ... [详细]
  • 这是原文链接:sendingformdata许多情况下,我们使用表单发送数据到服务器。服务器处理数据并返回响应给用户。这看起来很简单,但是 ... [详细]
  • springmvc学习笔记(十):控制器业务方法中通过注解实现封装Javabean接收表单提交的数据
    本文介绍了在springmvc学习笔记系列的第十篇中,控制器的业务方法中如何通过注解实现封装Javabean来接收表单提交的数据。同时还讨论了当有多个注册表单且字段完全相同时,如何将其交给同一个控制器处理。 ... [详细]
  • 猜字母游戏
    猜字母游戏猜字母游戏——设计数据结构猜字母游戏——设计程序结构猜字母游戏——实现字母生成方法猜字母游戏——实现字母检测方法猜字母游戏——实现主方法1猜字母游戏——设计数据结构1.1 ... [详细]
  • [大整数乘法] java代码实现
    本文介绍了使用java代码实现大整数乘法的过程,同时也涉及到大整数加法和大整数减法的计算方法。通过分治算法来提高计算效率,并对算法的时间复杂度进行了研究。详细代码实现请参考文章链接。 ... [详细]
  • 本文介绍了南邮ctf-web的writeup,包括签到题和md5 collision。在CTF比赛和渗透测试中,可以通过查看源代码、代码注释、页面隐藏元素、超链接和HTTP响应头部来寻找flag或提示信息。利用PHP弱类型,可以发现md5('QNKCDZO')='0e830400451993494058024219903391'和md5('240610708')='0e462097431906509019562988736854'。 ... [详细]
  • 本文详细介绍了如何使用MySQL来显示SQL语句的执行时间,并通过MySQL Query Profiler获取CPU和内存使用量以及系统锁和表锁的时间。同时介绍了效能分析的三种方法:瓶颈分析、工作负载分析和基于比率的分析。 ... [详细]
author-avatar
liuleyi
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有