当前位置: 首页 > news >正文

苏州知名网站建设开发网站的推广方法

苏州知名网站建设开发,网站的推广方法,基础展示型网站和cms,整合网络营销外包关键词:testbench,仿真,文件读写 Verilog 代码设计完成后,还需要进行重要的步骤,即逻辑功能仿真。仿真激励文件称之为 testbench,放在各设计模块的顶层,以便对模块进行系统性的例化调用进行仿真…

关键词:testbench,仿真,文件读写
Verilog 代码设计完成后,还需要进行重要的步骤,即逻辑功能仿真。仿真激励文件称之为 testbench,放在各设计模块的顶层,以便对模块进行系统性的例化调用进行仿真。

毫不夸张的说,对于稍微复杂的 Verilog 设计,如果不进行仿真,即便是经验丰富的老手,99.9999% 以上的设计都不会正常的工作。不能说仿真比设计更加的重要,但是一般来说,仿真花费的时间会比设计花费的时间要多。有时候,考虑到各种应用场景,testbench 的编写也会比 Verilog 设计更加的复杂。所以,数字电路行业会具体划分设计工程师和验证工程师。

下面,对 testbench 做一个简单的学习。

testbench 结构划分
testbench 一般结构如下:

在这里插入图片描述
其实 testbench 最基本的结构包括信号声明、激励和模块例化。

根据设计的复杂度,需要引入时钟和复位部分。当然更为复杂的设计,激励部分也会更加复杂。根据自己的验证需求,选择是否需要自校验和停止仿真部分。

当然,复位和时钟产生部分,也可以看做激励,所以它们都可以在一个语句块中实现。也可以拿自校验的结果,作为结束仿真的条件。

实际仿真时,可以根据自己的个人习惯来编写 testbench,这里只是做一份个人的总结。

testbench 仿真举例
前面的章节中,已经写过很多的 testbench。其实它们的结构也都大致相同。

下面,我们举一个数据拼接的简单例子,对 testbench 再做一个具体的分析。

一个 2bit 数据拼接成 8bit 数据的功能模块描述如下:

实例

module  data_consolidation(input           clk ,input           rstn ,input [1:0]     din ,          //data ininput           din_en ,output [7:0]    dout ,output          dout_en        //data out);// data shift and counterreg [7:0]            data_r ;reg [1:0]            state_cnt ;always @(posedge clk or negedge rstn) beginif (!rstn) beginstate_cnt     <= 'b0 ;data_r        <= 'b0 ;endelse if (din_en) beginstate_cnt     <= state_cnt + 1'b1 ;    //数据计数data_r        <= {data_r[5:0], din} ;  //数据拼接endelse beginstate_cnt <= 'b0 ;endendassign dout          = data_r ;// data output enreg                  dout_en_r ;always @(posedge clk or negedge rstn) beginif (!rstn) begindout_en_r       <= 'b0 ;end//计数为 3 且第 4 个数据输入时,同步输出数据输出使能信号else if (state_cnt == 2'd3 & din_en) begin  dout_en_r       <= 1'b1 ;endelse begindout_en_r       <= 1'b0 ;endend//这里不直接声明dout_en为reg变量,而是用相关寄存器对其进行assign赋值assign dout_en       = dout_en_r;endmodule

对应的 testbench 描述如下,增加了文件读写的语句:

实例

`timescale 1ns/1ps//============== (1) ==================//signals declaration
module test ;reg          clk;reg          rstn ;reg [1:0]    din ;reg          din_en ;wire [7:0]   dout ;wire         dout_en ;//============== (2) ==================//clock generatingreal         CYCLE_200MHz = 5 ; //always beginclk = 0 ; #(CYCLE_200MHz/2) ;clk = 1 ; #(CYCLE_200MHz/2) ;end//============== (3) ==================//reset generatinginitial beginrstn      = 1'b0 ;#8 rstn      = 1'b1 ;end//============== (4) ==================//motivationint          fd_rd ;reg [7:0]    data_in_temp ;  //for self checkreg [15:0]   read_temp ;     //8bit ascii data, 8bit \ninitial begindin_en    = 1'b0 ;        //(4.1)din       = 'b0 ;open_file("../tb/data_in.dat", "r", fd_rd); //(4.2)wait (rstn) ;    //(4.3)# CYCLE_200MHz ;//read data from filewhile (! $feof(fd_rd) ) begin  //(4.4)@(negedge clk) ;$fread(read_temp, fd_rd);din    = read_temp[9:8] ;data_in_temp = {data_in_temp[5:0], din} ;din_en = 1'b1 ;end//stop data@(posedge clk) ;  //(4.5)#2 din_en = 1'b0 ;end//open tasktask open_file;input string      file_dir_name ;input string      rw ;output int        fd ;fd = $fopen(file_dir_name, rw);if (! fd) begin$display("--- iii --- Failed to open file: %s", file_dir_name);endelse begin$display("--- iii --- %s has been opened successfully.", file_dir_name);endendtask//============== (5) ==================//module instantiationdata_consolidation    u_data_process(.clk              (clk),.rstn             (rstn),.din              (din),.din_en           (din_en),.dout             (dout),.dout_en          (dout_en));//============== (6) ==================//auto checkreg  [7:0]           err_cnt ;int                  fd_wr ;initial beginerr_cnt   = 'b0 ;open_file("../tb/data_out.dat", "w", fd_wr);forever begin@(negedge clk) ;if (dout_en) begin$fdisplay(fd_wr, "%h", dout);endendendalways @(posedge clk) begin#1 ;if (dout_en) beginif (data_in_temp != dout) beginerr_cnt = err_cnt + 1'b1 ;endendend//============== (7) ==================//simulation finishalways begin#100;if ($time >= 10000)  beginif (!err_cnt) begin$display("-------------------------------------");$display("Data process is OK!!!");$display("-------------------------------------");endelse begin$display("-------------------------------------");$display("Error occurs in data process!!!");$display("-------------------------------------");end#1 ;$finish ;endendendmodule // test

仿真结果如下。由图可知,数据整合功能的设计符合要求:加粗样式
在这里插入图片描述
testbench 具体分析
1)信号声明

testbench 模块声明时,一般不需要声明端口。因为激励信号一般都在 testbench 模块内部,没有外部信号。

声明的变量应该能全部对应被测试模块的端口。当然,变量不一定要与被测试模块端口名字一样。但是被测试模块输入端对应的变量应该声明为 reg 型,如 clk,rstn 等,输出端对应的变量应该声明为 wire 型,如 dout,dout_en。

2)时钟生成

生成时钟的方式有很多种,例如以下两种生成方式也可以借鉴。

实例

initial clk = 0 ;
always #(CYCLE_200MHz/2) clk = ~clk;initial beginclk = 0 ;forever begin#(CYCLE_200MHz/2) clk = ~clk;end
end      

需要注意的是,利用取反方法产生时钟时,一定要给 clk 寄存器赋初值。

利用参数的方法去指定时间延迟时,如果延时参数为浮点数,该参数不要声明为 parameter 类型。例如实例中变量 CYCLE_200MHz 的值为 2.5。如果其变量类型为 parameter,最后生成的时钟周期很可能就是 4ns。当然,timescale 的精度也需要提高,单位和精度不能一样,否则小数部分的时间延迟赋值也将不起作用。

3)复位生成

复位逻辑比较简单,一般赋初值为 0,再经过一段小延迟后,复位为 1 即可。

这里大多数的仿真都是用的低有效复位。

4)激励部分

激励部分该产生怎样的输入信号,是根据被测模块的需要来设计的。

本次实例中:

(4.1) 对被测模块的输入信号进行一个初始化,防止不确定值 X 的出现。激励数据的产生,我们需要从数据文件内读入。
(4.2) 处利用一个 task 去打开一个文件,只要指定文件存在,就可以得到一个不为 0 的句柄信号 fp_rd。fp_rd 指定了文件数据的起始地址。
(4.3) 的操作是为了等待复位后,系统有一个安全稳定的可测试状态。
(4.4) 开始循环读数据、给激励。在时钟下降沿送出数据,是为了被测试模块能更好的在上升沿采样数据。
利用系统任务 $fread ,通过句柄信号 fd_rd 将读取的 16bit 数据变量送入到 read_temp 缓存。

输入数据文件前几个数据截图如下。因为 $fread 只能读取 2 进制文件,所以输入文件的第一行对应的 ASCII 码应该是 330a,所以我们想要得到文件里的数据 3,应该取变量 read_temp 的第 9 到第 8bit 位的数据。
在这里插入图片描述
信号 data_in_temp 是对输入数据信号的一个紧随的整合,后面校验模块会以此为参考,来判断仿真是否正常,模块设计是否正确。

(4.5) 选择在时钟上升沿延迟 2 个周期后停止输入数据,是为了被测试模块能够正常的采样到最后一个数据使能信号,并对数据进行正常的整合。
当数据量相对较少时,可以利用 Verilog 中的系统任务 $readmemh 来按行直接读取 16 进制数据。保持文件 data_in.dat 内数据和格式不变,则该激励部分可以描述为:

实例

reg [1:0] data_mem [39:0] ;
reg [7:0] data_in_temp ; //for self check
integer k1 ;
initial begin
din_en = 1’b0 ;
din = 'b0 ;
$readmemh(“…/tb/data_in.dat”, data_mem);
wait (rstn) ;
# CYCLE_200MHz ;

//read data from file
for(k1=0; k1<40; k1=k1+1)  begin@(negedge clk) ;din    = data_mem[k1] ;data_in_temp = {data_in_temp[5:0], din} ;din_en = 1'b1 ;
end//stop data
@(posedge clk) ;
#2 din_en = 1'b0 ;

end

5)模块例化

这里利用 testbench 开始声明的信号变量,对被测试模块进行例化连接。

6)自校验

如果设计比较简单,完全可以通过输入、输出信号的波形来确定设计是否正确,此部分完全可以删除。如果数据很多,有时候拿肉眼观察并不能对设计的正确性进行一个有效判定。此时加入一个自校验模块,会大大增加仿真的效率。

实例中,我们会在数据输出使能 dout_en 有效时,对输出数据 dout 与参考数据 read_temp(激励部分产生)做一个对比,并将对比结果置于信号 err_cnt 中。最后就可以通过观察 err_cnt 信号是否为 0 来直观的对设计的正确性进行判断。

当然如实例中所示,我们也可以将数据写入到对应文件中,利用其他方式做对比。

7)结束仿真

如果我们不加入结束仿真部分,仿真就会无限制的运行下去,波形太长有时候并不方便分析。Verilog 中提供了系统任务 $finish 来停止仿真。

停止仿真之前,可以将自校验的结果,通过系统任务 $display 在终端进行显示。

文件读写选项
用于打开文件的系统任务 $fopen 格式如下:

fd = $fopen("<name_of_file>", "mode")

和 C 语言类似,打开方式的选项 “mode” 意义如下:
在这里插入图片描述

http://www.hkea.cn/news/618044/

相关文章:

  • 孝感做网站公司百度热议排名软件
  • 建设网站费用吗廊坊seo快速排名
  • 网站建设公司怎样拓展网站业务大连网站推广
  • 什么网站可以免费做找客户东莞seo建站推广费用
  • 合肥微信网站建设购物网站如何推广
  • 网站建设课程简介图片百度官网认证免费
  • 月夜影视在线观看免费完整版韩剧关键词排名优化报价
  • 做网站的工作时间兰州seo公司
  • css怎么嵌入到html直通车关键词优化口诀
  • 虚拟网站php专业型seo网站关键词排名提升
  • 找人合伙做网站平台b2b电商平台
  • 手机网站建设技术方案找网站设计公司
  • 杭州如何设计公司网站惠州seo网站推广
  • 成都网站建设门户大连企业网站建站模板
  • 游戏卡充值可以做网站吗百度竞价关键词出价技巧
  • 建设企业网站就等于开展网络营销网店推广实训报告
  • dede无法更新网站主页到百度联盟注册
  • wordpress支持爱奇艺企业网站seo托管怎么做
  • 永川做网站的武汉百度快速排名提升
  • 做网站的故意给中病毒网络营销广告
  • 关于阅读类网站的建设规划书友情链接系统
  • 专业做幼儿园设计的网站百度小程序关键词优化
  • 腾龙时时彩做号网站整站优化关键词排名
  • 正规的网站制作与推广百度广告运营
  • 网站建设估价引擎搜索有哪些
  • 东莞网站建设选菲凡网络如何制作网站
  • 网站收录系统备案查询官网
  • 临朐县网站建设利用搜索引擎营销成功的案例
  • 利用网盘做视频网站镇江优化推广
  • 视频微网站开发哪个公司网站设计好