博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
System Verilog基础(二)
阅读量:6294 次
发布时间:2019-06-22

本文共 4522 字,大约阅读时间需要 15 分钟。

    这一篇笔记主要记录Procedural,Process,Task and function,Interface和Communication中值得注意的点。

1.Procedural

    写testbench的时候,除了tb与硬件交互的地方使用非阻塞赋值,tb里面其他地方一律用阻塞赋值,OK

1 logic [3:0]        d0,d1;2 initial    begin3     d0 <= 3;4     $display("d0 value %0d",d0);    //d0=x;logic在未被初始化的时候是x5     d1 = 4;6     $display("d1 value %0d d0 value %0d",d1);    //d1=4,d0=x;注意这个时候d0依然是x7     #18     $display("d1 value %0d d0 value %0d",d1);    //d1=4,d0=3;只有#1往前走了之后,<=才会赋值生效9 end

     Loop循环中的foreach,是专门针对数组轮询时候用的。对二维数组遍历,如下代码:

1 int data[3][4];2 initial3     foreach(data[1]) begin4         foreach(data[i][j]) begin5             
6 end7
8 end9 end

     在两个for循环中,可以在里面直接定义index,例如for(int i; i<10; i++) 这样,如果有两个for里面都定义了int i,这两个index i是相互不影响的。

    哪些地方可以加label? Module...endmodule; begin...end; task...endtask; fork...join; interface...endinterface; 加标签的主要好处是增加代码的可读性,例如下面的代码:

1 module test(); 2     begin: b0 3     <...> 4         begin: b1 5             <...> 6         end: b1 7     end: b0 8      9     begin: b210         <...>11     end: b212 endmodule:test

    Final Blocks。这个块在Verilog中没有,当遇到$finish的时候,会进入到final块中。一般用在打印一些信息,注意final块中是不能加延迟#操作的,不然会报错。

2.Process

    initial块和always块都会产生进程Process。在SV中,可以使用fork来动态地产生子进程。fork有三种形式:fork...join  fork...join_any  fork...join_none 。使用fork...join_none时,不等待子进程执行,直接先执行主进程,就是fork...join_none外面的代码,但是fork...join_none里面的代码在后台也在执行,注意执行的先后顺序。如下代码:

1 fork: fork 1 2     begin 3         #1; 4     end 5     begin 6         #2; 7     end 8 join 9 $dispaly($time);    // time is 2ns10 fork: fork 211     begin12         #1;13     end14     begin15         #2;16     end17 join_any18 $dispaly($time);    // time is 1ns19 fork: fork 320     begin21         #1;22     end23     begin24         #2;25     end26 join_none27 $dispaly($time);    // time is 0ns

    使用wait fork来等待所有的进程执行完,如下代码,只有exec1(), exec2(), exec3(), exec4()都执行完了,task才会结束。

1 task mytask; 2     fork: fork1 3         exec1(); 4         exec2(); 5     join_any 6     fork: fork2 7         exec3(); 8         exec4(); 9     join_none10     11     wait fork;12 endtask

    使用disable fork,可以停止后台挂起的进程。在fork...join_any中disable fork使用的较多,用来检测程序,当fork...join_any中的任何一个监测进程执行OK后,就会使用disable fork来杀死fork中剩余的其他监测进程。

    为了对Process更精细控制,SV中内建有Class,在UVM中使用到。(遇到再更新吧~.~)

3. task and function

1 task mytask(a, int b, output logic [15:0]u, v)2 // a没有定方向和类型,默认input logic;3 // b默认是input方向4 // v的方向和类型会继承前一个参数,所以v也是output logic [15:0]5     <...>6 endtask

    task和function也可以加标签,如下代码:

1 task mytask(a = 3, int b, output logic [15:0]u, v);2 // a的默认值是3,如果传参没有传,就会使用默认值3      <...>4 endtask: mytask5 function my_func (a, int b, output logic [15:0]u, v);6     <...>7 endfunction: my_func

   C语言有数值传参和指针传参,SV也有,在定义task的时候使用ref关键字去修饰形参,还可以加const,参考C语言的用法。

    task中可以有时间消耗,function中不能有时间消耗。task可以调用function,反过来不可以。

4. Interface

    使用interface...endinterface来定义,用来解决模块之间的连接,模块和硬件件的连接问题。可以像理解module一样去理解interface,如下代码:

1 // 定义一个interface类型 2 interface bus_A (input clk);        //定义interface时可以像module一样有端口 3     logic         req; 4     logic [7:0]    addr,data; 5     logic        start,rdy; 6 endinterface 7 // 使用这个interface,在module中例化 8 module tb_top; 9     logic clk = 0;10     bus_A sb_intf(clk);        //例化11     memMode u_inst_mem1(clk,sb_intf); //把memMode模块,通过名字相同的线与sb_intf连接起来12 endmodule

    在定义interface的里面,使用modport来对一些信号接口做子集分类,这样在外层module中,例化一个模块,模块可以只连接interface其中的一个子集。

    interface可以像module一样,用#(AWIDTH=8,BWIDTH=9)来定义参数,在传递的过程中来改变值。

    interface里面还可以使用clock块,在实际项目中遇到了再总结吧(~.~)!

    在calss中使用interface,必须使用关键字virtual interface

5. 同步和通信

    同步和通信有三种:Semaphone, Event, Mailbox。最后一个是用来传递数据的。

5.1 Semaphones

  解决进程资源间共享问题,提供四个函数:new, put, get, try_get。其中get相当于一个task,里面有延迟,会阻塞其他的get拿到钥匙,try_get相当于一个function,立即执行,不会产生阻塞。下面代码示例:

1 semaphone sem0 = new(1);    //钥匙数量为1 2 initial begin:process 0 3     #10ns 4     void'(sem0.try_get())    //不会阻塞,拿不到钥匙直接执行下面的语句;拿到钥匙返回值为1 5     sem0.get();                //不会拿到钥匙,会一直阻塞在这里,直到下面的进程100ns之后把钥匙还了 6     sem0.put();                //还钥匙 7 end:process 1 8  9 initial begin:process 110     sem0.get();11     #100ns12     sem0.put();        //还钥匙,key number 为113 end:process 1

5.2 Event

    用来触发事件,使用->;用来等待事件使用@或者wait。那么@和wait有什么区别呢?看下面的代码:

1 event a;    //使用关键字event来声明一个事件a 2 initial begin 3     #1; 4     ->a; 5 end 6 initial    begin 7     #1; 8     @a;        //第一个进程在1ns后触发了事件a,那么第二个进程在1ns的时候等待a,有可能等的到,有可能等不到,产生竞争 9 end10 initial begin11     #1;12     wait(a.triggered); //使用wait来等待事件a,这种方式是一定可以等到a的,这是和使用@来等待的区别13 end

wait像是增强版的@,用来解决同一时刻的竞争冒险问题。

5.3 Mailbox

    可以理解为能存储任意数据类型的队列。先挖坑,以后遇到了再做笔记(~.~)!

转载于:https://www.cnblogs.com/yiwenbo/p/10299192.html

你可能感兴趣的文章
Python系语言发展综述
查看>>
新手 开博
查看>>
借助开源工具高效完成Java应用的运行分析
查看>>
163 yum
查看>>
第三章:Shiro的配置——深入浅出学Shiro细粒度权限开发框架
查看>>
80后创业的经验谈(转,朴实但实用!推荐)
查看>>
让Windows图片查看器和windows资源管理器显示WebP格式
查看>>
我的友情链接
查看>>
vim使用点滴
查看>>
embedded linux学习中几个需要明确的概念
查看>>
mysql常用语法
查看>>
Morris ajax
查看>>
【Docker学习笔记(四)】通过Nginx镜像快速搭建静态网站
查看>>
ORA-12514: TNS: 监听程序当前无法识别连接描述符中请求的服务
查看>>
<转>云主机配置OpenStack使用spice的方法
查看>>
java jvm GC 各个区内存参数设置
查看>>
[使用帮助] PHPCMS V9内容模块PC标签调用说明
查看>>
关于FreeBSD的CVSROOT的配置
查看>>
基于RBAC权限管理
查看>>
数学公式的英语读法
查看>>