转载自:点击打开链接

1 testbench 的技巧

1)如果激励中有一些重复的项目,可以考虑将这些语句编写成一个 task,这样会给书写和仿真带来很大方便。例如,
    一个存储器的 testbench 的激励可以包含 write, read 等 task。

2)如果 DUT 中包含双向信号(inout),在编写 testbench 时要注意。需要一个 reg 变量来表示其输入,还需要一个 wire
    变量表示其输出。

3)如果 initial 块语句过于复杂,可以考虑将其分为互补相干的几个部分,用数个 initial 块来描述。在仿真时,这些
    initial 块会并发运行。这样方便阅读和修改。

4)每个 testbench 都最好包含$stop 语句,用以指明仿真何时结束。

5)加载测试向量时,避免在时钟的上下沿变化,比如数据最好在时钟上升沿之前变化,这也符合建立时间的要求。

2 一个简单的例子

DUT:

[plain] view plain copy
  1. module counter (
  2. clk,
  3. reset,
  4. enable,
  5. count
  6. );
  7. input         clk;
  8. input         reset;
  9. input         enable;
  10. output [3:0]  count;
  11. reg    [3:0]  count;
  12. always @ (posedge clk)
  13. if (reset == 1'b1) begin
  14. count <= 0;
  15. end else if ( enable == 1'b1) begin
  16. count <= count + 1;
  17. end
  18. endmodule

testbench:

[plain] view plain copy
  1. module counter_tb;
  2. reg        clk;
  3. reg        reset;
  4. reg        enable;
  5. wire [3:0] count;
  6. counter U0 (
  7. .clk    (clk),
  8. .reset  (reset),
  9. .enable (enable),
  10. .count  (count)
  11. );
  12. initial begin
  13. clk = 0;
  14. reset = 0;
  15. enable = 0;
  16. end
  17. always #5 clk = ! clk;
  18. initial begin
  19. $dumpfile ("counter.vcd");
  20. $dumpvars;
  21. end
  22. initial begin
  23. $display("\t\ttime,\tclk,\treset,\tenable,\tcount");
  24. $monitor("‰d,\t‰b,\t‰b,\t‰b,\t‰d",$time, clk,reset,enable,count);
  25. end
  26. initial #100 $finish;
  27. //Rest of testbench code after this line
  28. endmodule

3 双向端口

这个没用过,从网上找的,如果有问题,大家再讨论吧
芯片外部引脚很多都使用 inout 类型的,为的是节省管腿。一般信号线用做总线等双向数据传输的时候就要用到 INOUT
类型了。就是一个端口同时做输入和 输出。 inout 在具体实现上一般用三态门来实现。三态门的第三个状态就是高阻
'Z'。当 inout 端口不输出时,将三态门置高阻。这样信号就不会因为两端同时 输出而出错了,更详细的内容可以搜索一
下三态门 tri-state 的资料

1 使用 inout 类型数据,可以用如下写法:
  
  inout    data_inout;
  input    data_in;
  reg      data_reg;//data_inout 的映象寄存器
  reg      link_data;
  assign data_inout = link_data ? data_reg : 1’bz; //link_data 控制三态门
  
对于 data_reg,可以通过组合逻辑或者时序逻辑根据 data_in 对其赋值.
通过控制 link_data 的高低电平,从而设置 data_inout
是输出数据还是处于高阻态,如果处于高阻态,则此时当作输入端口使用.link_data 可以通过相关电路来控制.

2 编写测试模块时,对于 inout 类型的端口,需要定义成 wire 类型变量,而其它输入端口都定义成 reg 类型,
这两者是有区别的.

当上面例子中的 data_inout 用作输入时,需要赋值给 data_inout,其余情况可以断开.
此时可以用 assign 语句实现:assign data_inout = link ? data_in_t : 1’bz;
其中的 link ,data_in_t 是 reg 类型变量,在测试模块中赋值.
另外,可以设置一个输出端口观察 data_inout 用作输出的情况:

[plain] view plain copy
  1. Wire   data_out;
  2. assign data_out_t = (!link) ? data_inout : 1’bz;
  3. else, in RTL
  4. inout use in top module(PAD)
  5. dont use inout(tri) in sub module

也就是说, 在内部模块最好不要出现 inout,如果确实需要,那么用两个 port 实现,到顶层的时候再用三态实现。理由
是:在非顶层模块用双向口的话,该双向口必然有它的上层跟它相连。既然是双向口,则上层至少有一个输入口和一
个输出口联到该双向口上,则发生两个内部输出单元连接到一起的情况出现,这样在综合时往往会出错。

对双向口,我们可以将其理解为 2 个分量:一个输入分量,一个输出分量。另外还需要一个控制信号控制输出分量何
时输出。此时,我们就可以很容易地对双向端口建模。
例子:

CODE:

[plain] view plain copy
  1. module dual_port (
  2. ....
  3. inout_pin,
  4. ....
  5. );
  6. inout   inout_pin;
  7. wire    inout_pin;
  8. wire    input_of_inout;
  9. wire    output_of_inout;
  10. wire    out_en;
  11. assign input_of_inout = inout_pin;
  12. assign inout_pin = out_en ? output_of_inout : 高阻;
  13. endmodule

可见,此时 input_of_inout 和 output_of_inout 就可以当作普通信号使用了。
在仿真的时候, 需要注意双向口的处理。如果是直接与另外一个模块的双向口连接,那么只要保证一个模块在输出的
时候,另外一个模块没有输出(处于高阻态)就可以了。

如果是在 ModelSim 中作为单独的模块仿真,那么在模块输出的时候,不能使用 force 命令将其设为高阻态,而是使用
release 命令将总线释放掉

很多初学者在写 testbench 进行仿真和验证的时候,被 inout 双向口难住了。仿真器老是提示错误不能进行。下面是我个
人对 inout 端口写 testbench 仿真的一些总结,并举例进行说明。在这里先要说明一下 inout 口在 testbench 中要定义为
wire 型变量。

先假设有一源代码为:

[plain] view plain copy
  1. module xx(data_inout , ........);
  2. inout data_inout;
  3. ........................
  4. assign data_inout = (!link) ? datareg : 1'bz;
  5. endmodule

方法一:使用相反控制信号 inout 口,等于两个模块之间用 inout 双向口互连。这种方法要注意 assign 语句只能放在 initial
和 always 块内。

[plain] view plain copy
  1. module test();
  2. wire  data_inout;
  3. reg   data_reg;
  4. reg   link;
  5. initial begin
  6. ..........
  7. end
  8. assign data_inout = link ? data_reg : 1'bz;
  9. endmodule

方法二: 使用 force 和 release 语句,但这种方法不能准确反映双向端口的信号变化,但这种方法可以反在块内。

[plain] view plain copy
  1. module test();
  2. wire   data_inout;
  3. reg    data_reg;
  4. reg    link;
  5. #xx; //延时
  6. force data_inout = 1'bx; //强制作为输入端口
  7. ...............
  8. #xx;
  9. release data_inout; //释放输入端口
  10. endmodule

很多读者反映仿真双向端口的时候遇到困难,这里介绍一下双向端口的仿真方法。一个典型的双向端口如图所示。

典型的双向端口可以用 Verilog 语言描述如下:

[plain] view plain copy
  1. module bidirection_io(
  2. inner_port,
  3. out_en,
  4. outer_port
  5. );
  6. input      out_en;
  7. inout[7:0] inner_port;
  8. inout[7:0] outer_port;
  9. assign outer_port = (out_en==1) ? inner_port : 8'hzz;
  10. assign inner_port = (out_en==0) ? outer_port : 8'hzz;
  11. endmodule

仿真时需要验证双向端口能正确输出数据,以及正确读入数据,因此需要驱动 out_en 端口,

当 out_en 端口为 1 时,testbench 驱动 inner_port 端口,
然后检查 outer_port 端口输出的数据是否正确;

当 out_en 端口为 0 时, testbench 驱动outer_port 端口,
然后检查 inner_port 端口读入的数据是否正确。由于 inner_port 和 outer_port 端口都是双向端口 (在 VHDL
和 Verilog 语言中都用 inout 定义),因此驱动方法与单向端口有所不同。

用 Verilog 代码编写的 testbench 如下,其中使用了自动结果比较,随机化激励产生等技术。

[plain] view plain copy
  1. `timescale 1ns/10ps
  2. module tb();
  3. reg   [7:0] inner_port_tb_reg;
  4. wire  [7:0] inner_port_tb_wire;
  5. reg   [7:0] outer_port_tb_reg;
  6. wire  [7:0] outer_port_tb_wire;
  7. reg         out_en_tb;
  8. integer     i;
  9. initial
  10. begin
  11. out_en_tb=0;
  12. inner_port_tb_reg=0;
  13. outer_port_tb_reg=0;
  14. i=0;
  15. repeat(20)
  16. begin
  17. #50
  18. i=$random;
  19. out_en_tb=i[0]; //randomize out_en_tb
  20. inner_port_tb_reg=$random; //randomize data
  21. outer_port_tb_reg=$random;
  22. end
  23. end
  24. //**** drive the ports connecting to bidirction_io
  25. assign inner_port_tb_wire=(out_en_tb==1)?inner_port_tb_reg:8'hzz;
  26. assign outer_port_tb_wire=(out_en_tb==0)?outer_port_tb_reg:8'hzz;
  27. //instatiate the bidirction_io module
  28. bidirection_io bidirection_io_inst(
  29. .inner_port (inner_port_tb_wire),
  30. .out_en     (out_en_tb),
  31. .outer_port (outer_port_tb_wire)
  32. );
  33. //***** monitor ******
  34. always@(out_en_tb,inner_port_tb_wire,outer_port_tb_wire)
  35. begin
  36. #1;
  37. if(outer_port_tb_wire===inner_port_tb_wire) begin
  38. $display("\n **** time=%t ****",$time);
  39. $display("OK! out_en=%d",out_en_tb);
  40. $display("OK! outer_port_tb_wire=%d,inner_port_tb_wire=%d",
  41. outer_port_tb_wire,inner_port_tb_wire);
  42. end
  43. else begin
  44. $display("\n **** time=%t ****",$time);
  45. $display("ERROR! out_en=%d",out_en_tb);
  46. $display("ERROR! outer_port_tb_wire != inner_port_tb_wire" );
  47. $display("ERROR! outer_port_tb_wire=%d, inner_port_tb_wire=%d",
  48. outer_port_tb_wire,inner_port_tb_wire);
  49. end
  50. end
  51. endmodule

testbench inout端口处理相关推荐

  1. Verilog中inout端口的使用方法

    Verilog中inout端口的使用方法 (本文中所有Verilog描述仅为展示inout端口的用法,实际描述则需要更丰富的功能描述) Inout端口的使用 在芯片中为了管脚复用,很多管脚都是双向的, ...

  2. FPGA中inout端口使用方法总结

     输入端口可以由wire/reg驱动,但输入端口只能是wire:输出端口可以使wire/reg类型,输出端口只能驱动wire:若输出端口在过程块中赋值则为reg型,若在过程块外赋值则为net型.用关键 ...

  3. 双向端口inout端口

    verilog里如何处理io成双向 在查阅了各种书和帖子之后,总结了以下inout端口的使用注意事项. (以下资料来源: <Xilinx FPGA开发实用教程 第二版> https://w ...

  4. Verilog inout端口使用详解

    理解 来源特权同学-https://www.eefocus.com/ilove314/blog/11-09/231507_10e01.htmlinout用法浅析有感于之前IIC通信中第一次使用veri ...

  5. FPGA设计中inout端口信号的仿真测试

    inout端口作为输入输出口,其在综合中以三态门的硬件形式而存在.但在波形仿真中,其具有输入输出性质就需要特别的操作手法才可以观察到正确的仿真波形. 在inout端口信号的仿真中,测试激励文件中Ino ...

  6. VIVADO inout 端口的使用

    使用2018.1版本编译带有INOUT 端口的代码,代码逻辑没问题,写了三态控制.但是下板子,inout端口输入数据一直是0. 最终查找原因,看RTL级原理图,并没有三态控制,端口信号只是被认为一个简 ...

  7. inout端口使用,一看即懂

    inout端口引入:节省引脚资源. inout端口功能:数据线,既可以作为输入端口接收数据:也可以作为输出端口发出数据. 图例:在FPGA中,通过三态门来控制inout端口,如下. 使用: 当z=0 ...

  8. 【Verilog】inout 端口信号的使用

    inout 介绍 芯片的许多外部引脚使用输入式来节省管脚.通常,当信号线用于双向数据传输(例如总线)时,使用 inout 类型.也就是说,端口同时用于输入和输出.inout 通常在特定实现中通过三态门 ...

  9. verilog中的inout端口与三态门、高阻态的使用

    高阻态 百度百科:高阻态是一个数字电路里常见的术语,指的是电路的一种输出状态,既不是高电平也不是低电平,如果高阻态再输入下一级电路的话,对下级电路无任何影响,和没接一样,如果用万用表测的话有可能是高电 ...

最新文章

  1. SOC,System on-a-Chip技术初步
  2. 观察者模式C#实现实例(一)
  3. (附视频) | AI奠基人、美国AI科学家特伦斯谈深度学习​
  4. linux shell find命令 查找多种文件后缀
  5. python中文注释缩进_Python入门学习之注释、行与缩进
  6. MyEclipse9安装Checkstyle5.5插件(图解)
  7. MVC中helper的用法。
  8. 碎片化学习前端资料分享~
  9. 面向接口编程的优点_为什么我们要面向接口编程
  10. html5怎么设置li向下移,请问如何实现鼠标移到li上改变另一个div的样式
  11. @codeforces - 786E@ ALT
  12. 德国 IT 薪酬大揭秘!
  13. sqlserver 没有备份误删数据_数据库服务器如何备份详细教程!
  14. Linux学习笔记(4)
  15. Java之JSON详解
  16. 网页设计\网页制作常用软件大全
  17. 安装axios及其基础用法
  18. AppCan 携手腾讯微博开放平台共推跨平台开发工具
  19. msvcr100.dll丢失的解决方法?哪种解决方法方便点
  20. 2月14日快到了, 把 ChatGPT 调教成了情诗王子, 为你守护你的爱情

热门文章

  1. Idea 安装 Python 支持的包(numpy等等)
  2. H5播放器使用方法。
  3. React 项目:计算器
  4. Excel将两个表格关联数据
  5. 大型网站后台稳定性技术策略
  6. [IT 男人帮 -11-08] 刘强东:自主经营B2C将在5年内超过淘宝
  7. Java基础学习-1
  8. QQ小程序流量主怎么开通的,流量主开通技巧。
  9. linux 解压iso文件后挂载live系统
  10. 矩阵乘法结合律的理解