FPGA 高手养成记-Test bench文件结构一览无余

文章目录

01. 前言

02. 完成的 Test bench 文件结构

03. 时钟激励设计

  • 时钟激励产生方法一

  • 时钟激励产生方法二

  • 时钟激励产生方法三

  • 时钟激励产生方法四

04. 复位信号设计

  • 复位信号产生方法一

  • 复位信号产生方法二

  • 复位信号产生方法三

05. 双向信号设计

  • 双向信号描述一

  • 双向信号描述二

06. 特殊信号设计

  • 特殊激励信号产生描述一

  • 特殊激励信号产生描述二

  • 特殊激励信号产生描述三

07. 仿真控制语句及系统任务描述

  • 仿真控制语句及系统任务描述

  • 仿真终端显示描述

  • 文本输入方式

08. 总结

 

01,前言

    Verilog测试平台是一个例化的待测(MUT)模块,重要的是给它施加激励并观测其输出。逻辑模块与其对应的测试平台共同组成仿真模型,应用这个模型可以测试该模块能否符合自己的设计要求。

    编写TESTBENCH的目的是为了对使用硬件描述语言设计的电路进行仿真验证,测试设计电路的功能、性能与设计的预期是否相符。通常,编写测试文件的过程如下:

  • 产生模拟激励(波形);

  • 将产生的激励加入到被测试模块中并观察其响应;

  • 将输出响应与期望值相比较。

02,完成的Test bench文件结构

通常,一个完整的测试文件其结构为

  • module Test_bench();//通常无输入无输出

  • 信号或变量声明定义

  • 逻辑设计中输入对应reg型

  • 逻辑设计中输出对应wire型

  • 使用initial或always语句产生激励

  • 例化待测试模块

  • 监控和比较输出响应

  • endmodule

03,时钟激励设计

    下面列举出一些常用的封装子程序, 这些是常用的写法, 在很多应用中都能用到。


3.1,时钟激励产生方法一

50%占空比时钟

parameter ClockPeriod=10;


initial


begin


clk_i=0;


forever


#(ClockPeriod/2) clk_i=~clk_i;


end

3.2,时钟激励产生方法二

50%占空比时钟

initial


begin


clk_i=0;


always #(ClockPeriod/2) clk_i=~clk_i;


end

3.3,时钟激励产生方法三:

产生固定数量的时钟脉冲

initial


begin


clk_i=0;


repeat(6)


#(ClockPeriod/2) clk_i=~clk_i;


end

3.4,时钟激励产生方法四

产生非占空比为50%的时钟

initial


begin


clk_i=0;


forever


begin


#((ClockPeriod/2)-2) clk_i=0;


#((ClockPeriod/2)+2) clk_i=1;


end


end

04,复位信号设计

4.1,复位信号产生方法一

异步复位

initial

begin


rst_n_i=1;


#100;


rst_n_i=0;


#100;


rst_n_i=1;


end

4.2,复位信号产生方法二

同步复位

initial

begin


rst_n_i=1;


@(negedge clk_i)


rst_n_i=0;


#100; //固定时间复位


repeat(10) @(negedge clk_i); //固定周期数复位


@(negedge clk_i)


rst_n_i=1;


end

4.3复位信号产生方法三

复位任务封装

task reset;

input [31:0] reset_time; //复位时间可调,输入复位时间


RST_ING=0; //复位方式可调,低电平或高电平


begin


rst_n=RST_ING; //复位中


#reset_time; //复位时间


rst_n_i=~RST_ING; //撤销复位,复位结束


end


endtask

05,双向信号设计

5.1,双向信号描述一

inout在testbench中定义为wire型变量

//为双向端口设置中间变量inout_reg作为inout的输出寄存,其中inout变


//量定义为wire型,使用输出使能控制传输方向


//inout bir_port;


wire bir_port;


reg bir_port_reg;


reg bi_port_oe;


assign bi_port=bi_port_oe ? bir_port_reg : 1'bz;

5.2双向信号描述二

强制force

//当双向端口作为输出口时,不需要对其进行初始化,而只需开通三态门


//当双向端口作为输入时,只需要对其初始化并关闭三态门,初始化赋值需


//使用wire型数据,通过force命令来对双向端口进行输入赋值


//assign dinout=(!en) din :16'hz; 完成双向赋值


initial


begin


force dinout=20;


#200


force dinout=dinout-1;


end

06,特殊信号设计

6.1特殊激励信号产生描述一

输入信号任务封装

task i_data;


input [7:0] dut_data;


begin


@(posedge data_en); send_data=0;


@(posedge data_en); send_data=dut_data[0];


@(posedge data_en); send_data=dut_data[1];


@(posedge data_en); send_data=dut_data[2];


@(posedge data_en); send_data=dut_data[3];


@(posedge data_en); send_data=dut_data[4];


@(posedge data_en); send_data=dut_data[5];


@(posedge data_en); send_data=dut_data[6];


@(posedge data_en); send_data=dut_data[7];


@(posedge data_en); send_data=1;


#100;


end


endtask


//调用方法:i_data(8'hXX);

6.2特殊激励信号产生描述二

多输入信号任务封装

task more_input;

input [7:0] a;


input [7:0] b;


input [31:0] times;


output [8:0] c;


begin


repeat(times) //等待times个时钟上升沿


@(posedge clk_i)


c=a+b; //时钟上升沿a,b相加


end


endtask


//调用方法:more_input(x,y,t,z);  //按声明顺序

6.3,特殊激励信号产生描述三

输入信号产生,一次SRAM写信号产生

initial

begin


cs_n=1; //片选无效


wr_n=1; //写使能无效


rd_n=1; //读使能无效


addr=8'hxx; //地址无效


data=8'hzz; //数据无效


#100;


cs_n=0; //片选有效


wr_n=0; //写使能有效


addr=8'hF1; //写入地址


data=8'h2C; //写入数据


#100;


cs_n=1;


wr_n=1;


#10;


addr=8'hxx;


data=8'hzz;


end

Testbench中@与wait

//@使用沿触发

//wait语句都是使用电平触发


initial


begin


start=1'b1;


wait(en=1'b1);


#10;


start=1'b0;


end

07,仿真控制语句及系统任务描述

7.1,仿真控制语句及系统任务描述

$stop     //停止运行仿真,modelsim中可继续仿真

$stop(n) //带参数系统任务,根据参数0,1或2不同,输出仿真信息


$finish   //结束运行仿真,不可继续仿真


$finish(n)  //带参数系统任务,根据参数0,1或2不同,输出仿真信息


//0:不输出任何信息


//1:输出当前仿真时刻和位置


//2:输出当前仿真时刻、位置和仿真过程中用到的memory以及CPU时间的统计


$random //产生随机数


$random % n //产生范围-n到n之间的随机数


{$random} % n //产生范围0到n之间的随机数

7.2,仿真终端显示描述

$monitor //仿真打印输出,大印出仿真过程中的变量,使其终端显示

/*


$monitor($time,,,"clk=%d reset=%d out=%d",clk,reset,out);


*/


$display //终端打印字符串,显示仿真结果等


/*


$display(” Simulation start ! ");


$display(” At time %t,input is %b%b%b,output is %b",$time,a,b,en,z);


*/


$time //返回64位整型时间


$stime //返回32位整型时间


$realtime //实行实型模拟时间

7.3文本输入方式

$readmemb/$readmemh

//激励具有复杂的数据结构


//verilog提供了读入文本的系统函数


$readmemb/$readmemh("<数据文件名>",<存储器名>);


$readmemb/$readmemh("<数据文件名>",<存储器名>,<起始地址>);


$readmemb/$readmemh("<数据文件名>",<存储器名>,<起始地址>,<结束地址>);


$readmemb:/*读取二进制数据,读取文件内容只能包含:空白位置,注释行,二进制数


数据中不能包含位宽说明和格式说明,每个数字必须是二进制数字。*/


$readmemh:/*读取十六进制数据,读取文件内容只能包含:空白位置,注释行,十六进制数


数据中不能包含位宽说明和格式说明,每个数字必须是十六进制数字。*/


      /*当地址出现在数据文件中,格式为@hh...h,地址与数字之间不允许空白位置,


可出现多个地址*/


module


reg [7:0] memory[0:3];//声明8个8位存储单元


integer i;


initial


begin


$readmemh("mem.dat",memory);//读取系统文件到存储器中的给定地址


//显示此时存储器内容


for(i=0;i<4;i=i+1)


$display("Memory[%d]=%h",i,memory[i]);


end


endmodule

/*mem.dat文件内容

@001

AB CD

@003

A1

*/

//仿真输出为

Memory[0] = xx;

Memory[1] = AB;

Memory[2] = CD;

Memory[3] = A1;

08,总结

     一个完整的设计,除了好的功能描述代码,对于程序的仿真验证是必不可少的。学会如何去验证自己所写的程序,即如何调试自己的程序是一件非常重要的事情。而RTL逻辑设计中,学会根据硬件逻辑来写测试程序,即Testbench是尤其重要的。

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

OpenFPGA

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值