该博文在lab1的基础上,根据说明以及solution里的文件,实现了接口发送时序。简单对代码进行分析。分析的内容在文章的注释区中。对于不是很清楚的语法进行解释。最后在原文件的基础上给出增加了相关打印信息的版本。

sv_labs学习笔记——sv_lab2(System Verilog)

  • lab2
    • DUT接口时序简述
    • 需要完成的任务
    • 代码分析
    • 相关语法解释
      • $urandom_range(,)
      • $urandom
      • foreach
    • 添加信息打印版本

lab2

DUT接口时序简述

我们首先了解下接口的时序。首先是输入信号,然后是输出接口的信号。

  • 输入接口时序
  • 输出接口时序


简单叙述下时序的一些要点。首先是输入信号,我们看到先是发送地址,需要在发送的时候拉低frame_n,然后在发送一个地址,4bit,这个时候不关心vaild_n信号。但是建议为高。然后发送pad,需要5个cycle。这时信号din以及vaild_n都是高,但是frame_n为低。接下来发送数据din信号开始发送数据,发送nbit的数据。在D<sub>n-1</sub>的时候拉高frame_n信号。din有效时,vaild_n为低。就是输入的波形时序了。这里的A为Destination Address。就是目的地址,波形中就是在输出的那一根信号可以看到输出的波形。然后时输出时序。默认vaildo_n以及framo_n高电平。拉低frameo_n。下一个cycle拉低valido_nvalido_n为低电平时对应输出dout有效,反之。只有frameo_n为低,则表示输出有效。输出的数据是否有效,则看vaildo_n的信号即可。以上就是输入输出的时序波形了。注意这里的sada表示16个并行输入输出的某一个端口。

需要完成的任务

在本节lab2中,在lab1的基础上,产生激励。就是模拟发送的时序。实现的框图见下图

可以看到,在之前的基础上,添加了几个简单的功能模拟发送时序。接下来具体看实现的代码。最后,博主提供了添加打印信息的版本。打印了一些比较重要的信息。

代码分析

lab2的coding只需要将之前的lab1复制过来。在linux环境下执行make mycopy即可。可以大概看看Makefile文件。这里对make的使用不进行解释。同时我们只需要对test.sv进行修改即可。
与前面的相比,增加了这么几个变化。首先是新增加了四个变量,其中sa作为发送激励的端口。da作为数据发送出去的接口。(前面有看过router功能是一个0-15输入数据,送到0-15输出)
其中定义了一个payload。是一个队列,队列中的元素为一个8bit的数。用来对需要发送的数据进行缓存。详细的使用见绿皮书2.4队列一节。这里简单解释下。就是用来存储元素,其声明方式是使用[]。队列元素的编号从0−]。队列元素的编号从0-]。队列元素的编号从0−。使用时可以使用方法对其中的元素进行增加或删除。最后定义了一个元素,run_for_n_packets,用来判断需要进行几次发送。

program automatic test(router_io.TB rtr_io);bit[3:0] sa;bit[3:0] da;logic[7:0] payload[$];int run_for_n_packets;initial begin //$vcdpluson;//用于存储波形的方法,在使用questa-sim进行仿真的时候不需要reset();run_for_n_packets = 3;repeat(run_for_n_packets) begingen();//产生发送数据send();//产生激励,与时序保持一致endrepeat(10) @(rtr_io.cb);//每次发送结束间隔一定的时钟周期
endtask reset();rtr_io.reset_n = 1'b0;rtr_io.cb.frame_n <= '1;rtr_io.cb.valid_n <= '1;##2 rtr_io.cb.reset_n <= 1'b1;repeat(15) @(rtr_io.cb);
endtask: resettask gen();//该task定义了发送接收的端口。sa = 3;//发送的端口为3da = 7;//接收数据的端口为7payload.delete(); //clear previous data 删除原始数据,推荐使用repeat($urandom_range(9,2))//重复2-9次,该函数后续进行说明payload.push_back($urandom);//在队列中写入数据,一次只能写队列的一个元素,就是8bit,这里返回的是一个32bit的数。会截取低八位。该函数后续进行介绍。
endtask: gentask send();//这个任务将分为三个任务,注意对于任务拆分的思想!!!
//我们看到,发送的时序分为三段,第一段发送地址,然后发送pad,最后实现数据的发送。这里均进行了模拟。且并没有揉在一起。简化简洁。send_addrs();send_pad();send_payload();
endtask: sendtask send_addrs();//发送的前一个时钟上升沿将frame_n拉低,frame_n有16个bit。拉低的哪一位就是需要发送的数据了。rtr_io.cb.frame_n[sa] <= 1'b0; //start of packetfor(int i = 0; i<4; i++) beginrtr_io.cb.din[sa] <= da[i]; //i'th bit of da同时在这个相同的时钟沿将接收地址发送出去@(rtr_io.cb);然后改变推进一个时钟周期。同时进行循环四次。end
endtask: send_addrstask send_pad();//发送pad时序需要将din,valid_n拉高,frame_n保持为低即可。维持5个cyclertr_io.cb.frame_n[sa] <= 1'b0;rtr_io.cb.valid_n[sa] <= 1'b1;rtr_io.cb.din[sa] <= 1'b1;repeat(5) @(rtr_io.cb);
endtask: send_padtask send_payload();//将准备好的数据进行发送foreach(payload[index])//循环次数为队列元素的个数$display(index,payload[index]);for(int i=0; i<8; i++) beginrtr_io.cb.din[sa] <= payload[index][i];//注意这里发送的高低位,先发送的是地位rtr_io.cb.valid_n[sa] <= 1'b0; //driving a valid bitrtr_io.cb.frame_n[sa] <= ((i == 7) && (index == (payload.size() - 1)));//frame_n根据时序,在适当的时候拉高。@(rtr_io.cb);endrtr_io.cb.valid_n[sa] <= 1'b1;//当完成发送的时候,valid_n也拉高,相比较于frame_n后延时一个cycle
endtask: send_payload
endprogram: test

相关语法解释

$urandom_range(,)

函数的作用是:返回指定范围内的无符号整数。

$urandom

系统函数$urandom提供了一种生成伪随机数的机制。这个函数每次调用时返回一个新的32位随机数。数字为无符号。
使用的语法为$urandom [ (int seed ) ]
。其中seed作为一个随机种子是可选的。seed是一个可选参数,用于确定生成的随机数序列。种子可以是任何积分表达式。随机数发生器(RNG)应生成相同的序列每次使用同一种子时的随机数。RNG是确定性的。每次程序执行时,它都会循环执行相同的随机序列。通过在$urandom函数中植入外部随机变量,可以使该序列不确定变量,例如一天中的时间。$random,系统随机化调用函数,返回32bit有符号数。
同样看下面这个实例来理解给个函数。

module urandom();
bit [64:1] addr;
bit [ 3:0] number;
initial begin addr[32:1] = $urandom(); // Initialize the generator// get 32-bit random number$display("message 1 :addr is %0h,number is %0h",addr,number);addr = {$urandom, $urandom}; // 64-bit random numbernumber= $urandom & 15; // 4-bit random  number$display("message 2 :addr is %0h,number is %0h",addr,number);
end
endmodule

结果如下。

message 1 :addr is eb5aa3b8,number is 0
message 2 :addr is 17750c269d0db966,number is 6

无论运行多少次,结果都是一样的,有兴趣可以自己尝试。或者使用repeat()函数,就不会产生一样的随机结果。

module urandom();
bit [64:1] addr;
bit [ 3:0] number;
initial begin repeat(3) begin addr[32:1] = $urandom(); // Initialize the generator// get 32-bit random number$display("message 1 :addr is %0h",addr);addr = {$urandom, $urandom}; // 64-bit random numbernumber= $urandom % 15; // 4-bit random  number$display("message 2 :addr is %0h,number is %0h",addr,number);end
end
endmodule

仿真结果如下,但是你再进行仿真,这个结果还是不会变。

message 1 :addr is eb5aa3b8
message 2 :addr is 17750c269d0db966,number is 2
message 1 :addr is 17750c26510e08c6
message 2 :addr is 83956e463bd10f72,number is 7
message 1 :addr is 83956e46fa374467
message 2 :addr is 3386553a46f91c6a,number is 8

foreach

这里简单解释,foreach(array[i])就是将其中的变量进行遍历。直接看输出会更清楚。

module tb_foreach();
string words [2] = '{ "hello", "world" };
int prod [1:8] [1:3];
initial begin foreach( words[j] ) begin$display("j is %0d,words index is j  is %0s",j,words[j]); // print each index and valueendforeach( prod[k,m] ) begin prod[k][m] = k * m; // initialize$display("current k is %0d,current m is %0d,the value in prod[k,j] is %0d",k,m,prod[k][m]); endend
endmodule

对应的输出为

# j is 0,words index is j  is hello
# j is 1,words index is j  is world
# current k is 1,current m is 1,the value in prod[k,j] is 1
# current k is 1,current m is 2,the value in prod[k,j] is 2
# current k is 1,current m is 3,the value in prod[k,j] is 3
# current k is 2,current m is 1,the value in prod[k,j] is 2
......
# current k is 7,current m is 3,the value in prod[k,j] is 21
# current k is 8,current m is 1,the value in prod[k,j] is 8
# current k is 8,current m is 2,the value in prod[k,j] is 16
# current k is 8,current m is 3,the value in prod[k,j] is 24

添加信息打印版本

简单补充后的代码如下

program automatic test(router_io.TB rtr_io);bit[3:0] sa;bit[3:0] da;logic[7:0] payload[$];int run_for_n_packets;integer repeat_times = 1;
initial begin$vcdpluson;reset();run_for_n_packets = 3;repeat(run_for_n_packets) begin$display("repeat time is %0d",repeat_times);repeat_times = repeat_times + 1;gen();$display("payload is ",payload);send();endrepeat(10) @(rtr_io.cb);
endtask reset();rtr_io.reset_n = 1'b0;rtr_io.cb.frame_n <= '1;rtr_io.cb.valid_n <= '1;##2 rtr_io.cb.reset_n <= 1'b1;repeat(15) @(rtr_io.cb);
endtask: resettask gen();sa = 3;da = 7;payload.delete(); //clear previous datarepeat($urandom_range(9,2))payload.push_back($urandom());
endtask: gentask send();send_addrs();send_pad();send_payload();
endtask: sendtask send_addrs();rtr_io.cb.frame_n[sa] <= 1'b0; //start of packetfor(int i = 0; i<4; i++) beginrtr_io.cb.din[sa] <= da[i]; //i'th bit of da@(rtr_io.cb);end
endtask: send_addrstask send_pad();rtr_io.cb.frame_n[sa] <= 1'b0;rtr_io.cb.valid_n[sa] <= 1'b1;rtr_io.cb.din[sa] <= 1'b1;repeat(5) @(rtr_io.cb);
endtask: send_padtask send_payload();foreach(payload[index]) begin $display("index is %0d,payload[index] is %0h ",index,payload[index]);for(int i=0; i<8; i++) beginrtr_io.cb.din[sa] <= payload[index][i];rtr_io.cb.valid_n[sa] <= 1'b0; //driving a valid bitrtr_io.cb.frame_n[sa] <= ((i == 7) && (index == (payload.size() - 1)));@(rtr_io.cb);endendrtr_io.cb.valid_n[sa] <= 1'b1;
endtask: send_payloadendprogram: test

打印的信息为

repeat time is 1
payload is '{'h3c, 'h7d, 'he2, 'hb, 'hdf, 'h40, 'hf7, 'ha6}
index is 0,payload[index] is 3c
index is 1,payload[index] is 7d
index is 2,payload[index] is e2
index is 3,payload[index] is b
index is 4,payload[index] is df
index is 5,payload[index] is 40
index is 6,payload[index] is f7
index is 7,payload[index] is a6
repeat time is 2
payload is '{'hb5, 'hfa, 'h4e, 'h15, 'h7d}
index is 0,payload[index] is b5
index is 1,payload[index] is fa
index is 2,payload[index] is 4e
index is 3,payload[index] is 15
index is 4,payload[index] is 7d
repeat time is 3
payload is '{'h96, 'h31, 'hc4, 'haa}
index is 0,payload[index] is 96
index is 1,payload[index] is 31
index is 2,payload[index] is c4
index is 3,payload[index] is aa

sv_labs学习笔记——sv_lab2(System Verilog)相关推荐

  1. sv_labs学习笔记——sv_lab4(System Verilog)

    sv_labs学习笔记--sv_lab4(System Verilog) lab4 OOP encapsulation 实验概述 任务代码解析 Packat实现与理解 语法点解析 randomize( ...

  2. sv_labs学习笔记——sv_lab3(System Verilog)

    这里我们在前两个lab的基础上继续完善,搭建一个数据接受的功能.在lab2 中我们实现了相关发送信息的打印,选择发送接受的端口,完善发送时序,在这一小节中将实现对端口发送数据的回收,然后进行比较发送的 ...

  3. sv_labs学习笔记——sv_lab1(System Verilog)

    sv_labs学习笔记--sv_lab1(System Verilog) 概述 lab1 功能简述 代码分析 仿真精度 理解repeat(15) @(rtr_io.cb); 理解$timeformat ...

  4. sv_labs学习笔记 专栏说明博文目录

    栏目说明 专栏主要提供sv_labs学习过程中笔者认为比较重要的点以及相关延申.本文假设读者已经具有相关语言的背景.不会过分纠结语言本身,但会重点对于一些语言进行理解.语言的理解见笔者的另外一个专栏S ...

  5. sv_labs学习笔记——sv_lab5_下(System Verilog)

    本文延续前一篇sv_labs学习笔记--sv_lab5_上(System Verilog),进一步学习完善lab5的内容 sv_labs学习笔记--sv_lab5_下(System Verilog) ...

  6. sv_labs学习笔记——sv_lab5_上(System Verilog)

    本节将介绍lab5的第一部分,主要总结一般设计学习与思考的方式与需要着重学习的点,同时以lab5作为参考,分析数据流流向,验证组件的通信与抽象化,实现的整体思路. sv_labs学习笔记--sv_la ...

  7. 【芯片验证学习纪实】System Verilog语法(1)

    [芯片验证学习纪实]System Verilog语法(1) 继学习了FPGA设计之后,学习IC验证也有一段时间了,学习过程中参考了很多互联网上的优秀资源,在此感谢各位前辈们的无私分享!现在,利用闲暇之 ...

  8. b 计数器位选信号 verilog_Verilog HDL菜鸟学习笔记———三、Verilog常用语法之一...

    1.一个完整版实例 上一次Verilog学习笔记中,我通过几个小例子,较为直观的对Verilog编程有了一些了解.这次笔记,我开始着重的系统学习Verilog编程语法基础.在我系统学习语法之前,我先用 ...

  9. 【学习笔记-FPGA】verilog语言中assign的使用

    个人笔记. assign在verilog语言中一般用于连接两个变量,将一个变量的值不断赋值给另一个变量,比如在顶层模块中调用另一模块的变量. 例: ///二级模块 module compile( in ...

最新文章

  1. android连接usb外设通讯_iOS App连接外设的几种方式
  2. 视频 + PPT 下载 | 挣脱流量束缚,社交电商的未来在哪里?
  3. C++输入输出流进制转换
  4. 【网址收藏】windows安装Docker Desktop常见问题整理
  5. mysql表设计讲解_MySQL中数据库的设计归纳讲解
  6. 主打轻薄长续航搭载骁龙730 联想Z6发布 1899元起!
  7. 嵌入式和fpga哪个好前景_二建考试选哪个专业比较好?其市场需求和就业前景如何? - 二级建造师...
  8. 夺标查询和联合查询有什么区别么
  9. 广义相对论-学习记录4-第三章-张量分析与黎曼几何1
  10. 小程序列表页制作优惠券效果
  11. Python + qrcode 实现文字转二维码
  12. 七牛判断上传图片文件是否重复
  13. 理解数据仓库中星型模型和雪花模型
  14. python怎么念1001python怎么念-python 星号的使用
  15. 高级攻防研究员-红队管理
  16. MIT研究团队开发由磁铁控制的小型机器人,可在人体内提供治疗
  17. 百度地图离线开发demo(vue+百度地图3.0+百度瓦片)(仅供参考,学习探讨)
  18. uniapp 路由uni.navigateTo 传参
  19. 货币的价值--钱的价值与投资
  20. matlab期末考试河北大学,河北大学matlab习题答案.doc

热门文章

  1. 解决问题 “You don‘t have permission to access /index.html on this server.”
  2. SCSS和Sass有什么区别?
  3. java中值滤波_Java实现图像中值滤波
  4. python全0序列_Python合集之Python序列(一)
  5. Linux命令:XZ解压tar.xz后缀的压缩包
  6. 2021普通高考重庆成绩查询平台,2021年重庆高考成绩查询时间及查分方式
  7. gulp html页面路径,通过gulp-connect部署静态页面,html页面中include路径无法get!
  8. linux显示3个字符,Linux驱动学习笔记(3)字符设备驱动
  9. 链接标签(HTML)
  10. PCL之多可视化窗口