原创 Writing Testbench——结构化Testbench

2009-4-8 18:34 8263 7 11 分类: FPGA/CPLD

Writing Testbench——结构化Testbench<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />


 


         特权同学为testbench的结构化以及可重用性设计发愁许久,终于在《writing testbench》一书的ch6章节里找到了答案,可谓柳暗花明又一村。原来Testbench还是可以做到可重用化的设计。下面以特权同学常用模块做一个结构化可重用的示例。


 


这是假设的待验证模块的顶层:


module prj_top(clk,rst_n,dsp_addr,dsp_data,dsp_rw……);


         input clk;


         input rst_n;


         input[23:0] dsp_addr;


         input dsp_rw;


         inout[15:0] dsp_data;


……


……


……


endmodule


 


这是testbench的顶层:


module tf_prj_top;


 


/*这个例化适用于被例化文件(这里是print_task.v)不对待验证模块接口进行控制*/


//print_task.v里包含常用信息打印任务封装


print_task         print();


 


/*这个例化适用于被例化文件需要对待验证模块接口进行控制,和通常RTL设计中例化方法时一样的*/


//sys_ctrl_task.v里包含系统时钟产生单元和系统复位任务


sys_ctrl_task   sys_ctrl(


                                                        .clk(clk),


                                                        .rst_n(rst_n)


                                               );


                                              


//dsp_ctrl_task.v包含DSP读写控制模拟


dsp_ctrl_task  dsp_ctrl(


                                                        .dsp_rw(DSP_RW),


                                                        .dsp_addr(dsp_addr),


                                                        .dsp_data(dsp_data),


                                                        ……


                                               );               


 


/*这里的端口例化需要注意的时,原来被测试模块的outputreg,如果被底层的例化模块所控制,那么这个reg要改为wire类型进行定义,而底层模块要将其定义为reg*/


         wire clk;


         wire rst_n;


         wire[23:0] dsp_addr;


         wire dsp_rw;


         wire[15:0] dsp_data;


         ……


 


//例化待验证工程顶层


prj_top              uut(


.clk(clk),


.rst_n(rst_n),


.dsp_addr(dsp_addr),


.dsp_data(dsp_data),


.dsp_rw(dsp_rw),


……


);


 


/*注意下面调用底层模块的任务的方式,例如sys_ctrl表示上面例化的sys_ctrl_task.vsys_reset是例化文件中的一个任务,用”.”做分割*/


Initial begin


         sys_ctrl.sys_reset(32’d1000);                   //系统复位1000ns


         #1000;


         dsp_ctrl.task_dsp_write(SELECT_STRB0,24'h000001,16’h00ff);   //DSP写任务调用


         #1000;


         dsp_ctrl.task_dsp_read(SELECT_STRB0,24'h000008,dsp_rd_data);     //DSP读任务调用


……


print.terminate;


end


 


endmodule


 


//调用层1


module print_task;


 


//----------------------------------------------------------------------//


//常用信息打印任务封装


//----------------------------------------------------------------------//           


//警告信息打印任务


task warning;


         input[80*8:1] msg;


         begin


                   $write("WARNING at %t : %s",$time,msg);


         end


endtask


 


//错误信息打印任务


task error;


         input[80*8:1] msg;


         begin


                   $write("ERROR at %t : %s",$time,msg);


         end


endtask


 


//致命错误打印并停止仿真任务


task fatal;


         input[80*8:1] msg;


         begin


                   $write("FATAL at %t : %s",$time,msg);


                   $write("Simulation false\n");


                   $stop;


         end


endtask


 


//完成仿真任务


task terminate;       


         begin


                   $write("Simulation Successful\n");


                   $stop;               


         end


endtask   


                  


endmodule


 


 


//调用层2


module sys_ctrl_task(


                                               clk,rst_n


                                               );


 


output reg clk; //时钟信号


output reg rst_n;     //复位信号


 


parameter      PERIOD   = 20;                   //时钟周期,单位ns


parameter      RST_ING          = 1'b0;      //有效复位值,默认低电平复位                                    


 


//----------------------------------------------------------------------//


//系统时钟信号产生


//----------------------------------------------------------------------//           


initial begin


         clk = 0;


         forever


                   #(PERIOD/2) clk = ~clk;


end


                


//----------------------------------------------------------------------//


//系统复位任务封装


//----------------------------------------------------------------------//           


task sys_reset;


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


         begin


                   rst_n = RST_ING;              //复位中


                   #reset_time;                      //复位时间


                   rst_n = ~RST_ING;            //撤销复位


         end


endtask            


                  


                  


endmodule


 


//调用层3


module dsp_ctrl_task(


                                               dsp_rw,dsp_strb0,dsp_strb1,dsp_iostrb,


                                               dsp_addr,dsp_data


                                               );


 


output reg dsp_rw;          //DSP读写信号,低--写,高--


output reg dsp_strb0;     //DSP存储空间STRB0选通信号


output reg dsp_strb1;     //DSP存储空间STRB1选通信号


output reg dsp_iostrb;    //DSP存储空间IOSTRB选通信号


output reg [23:0] dsp_addr;    //DSP地址总线


 


inout wire [15:0] dsp_data;     //DSP数据总线


                  


//print_task.v里包含常用信息打印任务封装


print_task         print();              


                  


//----------------------------------------------------------------------//


//模拟DSP读写任务封装


//----------------------------------------------------------------------//  


//DSP地址空间选择//


parameter        SELECT_STRB0         = 2'd1,


                                     SELECT_STRB1         = 2'd2,


                                     SELECT_IOSTRB       = 2'd3;


                                    


reg[15:0] dsp_data_reg; //DSP数据总线寄存器


 


assign dsp_data = dsp_rw ? 16'hzz : dsp_data_reg;


 


reg rd_flag;      //任务忙标志位,用于防止同时调用该任务


reg wr_flag;     //任务忙标志位,用于防止同时调用该任务


 


initial begin


         rd_flag = 0;       //DSP读任务不忙


         wr_flag = 0;      //DSP写任务不忙 


         //DSP信号接口初始化


         dsp_rw = 1;


         dsp_data_reg = 16'hzzzz;


         dsp_addr = 24'hzzzzzz;


         dsp_strb0 = 1;


         dsp_strb1 = 1;


         dsp_iostrb = 1;


end


 


reg h1;     //DSP时钟模拟,h1DSP指令周期


initial begin


         h1 = 1'b0;


         forever


         #20 h1 = ~h1;


end


 


//模拟 DSPFPGA任务


task task_dsp_read;


         input[1:0] tcs;           //片选输入


         input[23:0] taddr;    //地址输入


         output[15:0] tdata; //数据读出


         begin


                   ……


         end


endtask


 


//模拟DSPFPGA任务


task task_dsp_write;


         input[1:0] tcs;           //片选输入


         input[23:0] taddr;    //地址输入


         input[15:0] tdata;    //数据写入


         begin


                   ……


         end


endtask            


                  


endmodule


 


 


 

PARTNER CONTENT

文章评论4条评论)

登录后参与讨论

用户306131 2012-3-31 07:30

牛B的总结啊。

用户913751 2011-9-9 14:37

很好的testbench ,以后多学习!

用户347941 2011-7-26 10:11

挺不错的东西,在别的设计中,调用它们,验证结果比波形分析简单多了

用户251222 2010-11-1 17:15

有点复杂,看的我晕了

用户1442484 2009-4-11 23:05

博主你好,你在中嵌学过,我现在正在中嵌学习,能告诉我你的QQ吗?以后多交流交流。
相关推荐阅读
特权ilove314 2016-06-30 21:16
例说FPGA连载6:FPGA开发所需的技能
例说FPGA连载6:FPGA开发所需的技能 特权同学,版权所有 配套例程和更多资料下载链接: http://pan.baidu.com/s/1c0nf6Qc   前面的文字已经做了很多铺垫,相信读...
特权ilove314 2016-06-28 21:09
例说FPGA连载5:FPGA的优势与局限性
例说FPGA连载5:FPGA的优势与局限性 特权同学,版权所有 配套例程和更多资料下载链接: http://pan.baidu.com/s/1c0nf6Qc   若要准确评估FPGA技术能否满足开...
特权ilove314 2016-06-28 21:05
例说FPGA连载5:FPGA的优势与局限性
例说FPGA连载5:FPGA的优势与局限性 特权同学,版权所有 配套例程和更多资料下载链接: http://pan.baidu.com/s/1c0nf6Qc   若要准确评估FPGA技术能否满足开...
特权ilove314 2016-06-26 22:11
例说FPGA连载4:FPGA语言与厂商介绍
例说FPGA连载4:FPGA语言与厂商介绍 特权同学,版权所有 配套例程和更多资料下载链接: http://pan.baidu.com/s/1c0nf6Qc   Verilog与VHDL 说到FP...
特权ilove314 2016-06-23 21:26
例说FPGA连载3:FPGA与其它主流芯片的比较
例说FPGA连载3:FPGA与其它主流芯片的比较 特权同学,版权所有 配套例程和更多资料下载链接: http://pan.baidu.com/s/1c0nf6Qc   FPGA、ASIC和ASSP...
特权ilove314 2016-06-21 20:32
例说FPGA连载2:FPGA是什么
例说FPGA连载2:FPGA是什么 特权同学,版权所有 配套例程和更多资料下载链接: http://pan.baidu.com/s/1c0nf6Qc   2015年伊始,Intel欲出资百亿美金收...
EE直播间
更多
我要评论
4
7
关闭 站长推荐上一条 /3 下一条