今天在看黑金AX309FPGA开发板自带教程中的EEPROM那一章,考虑如何写其中iic_com模块的TestBench,难点在于1. 该模块存在一个inout型的端口信号;2. 时序较为复杂,不可能在TestBench中完全计算出准确的延时;3. 存在应答信号。具体的模块设计内容见附件。

对于该模块,首先需要对iic_com模块做一定的修改,在信号列表中,加入如下内容:

 //////////////////////////////////////////////
output is_out_w; //只是为了TestBench用
output [:] i_w;
/////////////////////////////////////////////
 ////////////////////////////////////////////////
assign is_out_w = is_out; //只是为了TestBench用
assign i_w = i;
////////////////////////////////////////////////

即把is_out信号和i信号作为输出信号引出来,这样在写TestBench的时候就可以根据这两个信号的变化来作出具体的驱动变化。

  然后,因为原模块中存在inout型的端口信号,而对于这种信号一般的处理方法是利用一个寄存器变量来控制器方向,该变量在iic_com模块就是is_out,如下所示:

assign sda = is_out ? r_sda : 'bz;

若is_out为1,则sda作为输出,输出值为r_sda;若is_out为0,则sda为高阻,即作为输入使用。而在TestBench中,同样需要考虑其输入输出问题,而且我们知道TestBench相当于是给原模块一个激励信号,所以必须要设计好不能使得两个模块输入输出冲突,所以我在TestBench中同样采用一个寄存器变量来控制器方向,但该寄存器和原模块中is_out的值正好相反,如下所示:

assign sda = (!is_out) ? sda_r : 'bz;

注意is_out前面有一个“!”。

  接下来,需要考虑其时序复杂问题,其实时序复杂并不是问题,但是如果因为时序复杂而一点一点计算出用了多少个clock,然后在TestBench中用#延时的方法就有点不够灵活了。我在处理中根据引入的i信号来做处理,这个i在原模块中是用来存储状态值的,所以我在TestBench中可以根据i的值来判断当前进入到了哪个状态,然后根据状态值来作出相应的处理。

  最后一点是应答信号,这里我是把应答信号给屏蔽掉了,也是为了简化TestBench的书写复杂度,当然也可以设计更为复杂的TestBench来一并测试应答信号,屏蔽的方式如下:

         :    begin
if (is_ack != ) //don't receive acknowledge signal
//i <= 5'd0;
i <= go; /////////////////测试/////////////////
else
i <= go;
end

即不论is_ack的值是多少,都会继续进行状态转移。

我设计的TestBench模块内容如下:

 `timescale 1ns / 1ps
module iic_com_tb;
reg clk; //系统时钟
reg rst_n; //复位信号
reg [:] start_sig; //写读开始信号
reg [:] addr_sig; //写读地址信号
reg [:] wr_data; //写数据输入
wire [:] rd_data; //读数据输出
wire done_sig; //写读完成标志
wire scl; //IIC SCL
wire sda; //IIC SDA
wire is_out; //控制SDA输入输出方向的信号
wire [:] i; //存储状态机状态值 reg sda_r;
assign sda = (!is_out) ? sda_r : 'bz; //is_out控制sda的方向,注意is_out前面的!,即控制其方向与原模块中不同 //生成时钟,周期为20ns
initial
begin
clk = ;
forever
#
clk = ~clk;
end //生成复位信号
initial
begin
rst_n = ;
#
rst_n =;
end //写读地址和写数据位固定值
initial
begin
addr_sig = 'b1010_1010;
wr_data = 'b0101_0101;
end //根据状态值,产生不同的驱动信号
reg c; //c信号没有实际作用,只是用于后面的延时
initial
begin
c = ;
start_sig = 'b00;
sda_r = ;
#
start_sig = 'b01; //01代表写
while (i != ) //状态6是写过程中的最后一个状态
begin
c = # c + ; //用该方式延时1个时间单位
end
# //这个延时是必须的,延时一个时钟周期,不能多也不能少
start_sig = 'b10; //10代表读
while (i >= && i <= && i != ) //状态8是读过程中的最后一个状态
begin
if (i >= && i <= ) //19到26状态时用于读取sda信号线上的值
begin
case (i)
: begin sda_r = 'b1; c = #1 c + 1; end
: begin sda_r = 'b1; c = #1 c + 1; end
: begin sda_r = 'b1; c = #1 c + 1; end
: begin sda_r = 'b1; c = #1 c + 1; end
: begin sda_r = 'b0; c = #1 c + 1; end
: begin sda_r = 'b0; c = #1 c + 1; end
: begin sda_r = 'b0; c = #1 c + 1; end
: begin sda_r = 'b0; c = #1 c + 1; end
endcase
end
else
begin
c = # c + ;
end
end
$stop();
end iic_com inst(
.clk (clk),
.rst_n (rst_n),
.start_sig (start_sig),
.addr_sig (addr_sig),
.wr_data (wr_data),
.rd_data (rd_data),
.done_sig (done_sig),
.scl (scl),
.sda (sda),
.is_out_w (is_out),
.i_w (i)
); endmodule

仿真波形如下:

我的邮箱地址:zhsj1993@126.com。欢迎大家来信交流讨论。另外,附上两个文件iic_com.v和iic_com_tb.v:http://files.cnblogs.com/files/zhsj/iic_com.zip

声明:源文件中的iic_com.v是来自黑金教程中的代码,为了写TestBench本人做了一定的修改,如果存在版权问题,请通知我,我会第一时间删帖!

IIC模块TestBench的书写方法的更多相关文章

  1. Python的re模块,正则表达式书写方法

    Python的re模块,正则表达式 #导入re模块 import  re 1.match方法的使用: result = re.match(正则表达式,待匹配的字符串) 正则表达式写法: 第一部分: 字 ...

  2. Node.js process 模块常用属性和方法

    Node.js是常用的Javascript运行环境,本文和大家发分享的主要是Node.js中process 模块的常用属性和方法,希望通过本文的分享,对大家学习Node.js http://www.m ...

  3. python3 中mlpy模块安装 出现 failed with error code 1的决绝办法(其他模块也可用本方法)

    在python3 中安装其它模块时经常出现 failed with error code 1等状况,使的安装无法进行.而解决这个问题又非常麻烦. 接下来以mlpy为例,介绍一种解决此类安装问题的办法. ...

  4. Node.js -- Router模块中有一个param方法

    这段时间一直有在看Express框架的API,最近刚看到Router,以下是我认为需要注意的地方: Router模块中有一个param方法,刚开始看得有点模糊,官网大概是这么描述的: 1 Map lo ...

  5. python inspect 模块 和 types 模块 判断是否是方法,模块,函数等内置特殊属性

    python inspect 模块 和 types 模块 判断是否是方法,模块,函数等内置特殊属性 inspect import inspect def fun(): pass inspect.ism ...

  6. os、os.path模块(文件/目录方法)

    1.模块的概念:模块是一个包含所有定义的变量.函数的文件,模块可以被其余模块调用. 2.利用OS模块实现对系统文件的. os模块中常见的方法: gercwd()     返回当前工作目录 chdir( ...

  7. Linux上安装Perl模块的两种方法

    Linux/Unix下安装Perl模块有两种方法:手工安装和自动安装.第一种方法是从CPAN上下载  您需要的模块,手工编译.安装.第二种方法是联上internet,使用一个叫做CPAN的模块自动完 ...

  8. import 和 from … import 模块的变量、方法引用差异

    import 和 from … import 模块的变量.方法引用差异 还是上面例子中的模块 support.py: def print_func( par ): print "Hello ...

  9. YII2中使用RBAC对模块,控制器,方法的权限控制以及规则的使用

    在使用YII2中自带的RBAC时,需要先配置config/web.php: return [ // ... 'components' => [ 'authManager' => [ 'cl ...

随机推荐

  1. 安装SVN报无法访问windows installer服务。

    第一步:点击开始--运行,输入:cmd 第二步:输入regsvr32 msi.dll然后回车,会提示成功. 第三步:点击开始--运行,输入:services.msc按回车 第四部:调到页面后找到Win ...

  2. java入门知识

    Java特性 简单.面向对象.支持网络.解释性.健壮性.安全性.高性能.可移植(跨平台) Java特点 开源.免费.跨平台.面向对象 应用平台 JavaSE(standard edition)(c/s ...

  3. Javascript基础知识小测试(一)

    这里罗列了<你不知道的js>上卷的一些知识点以及小问题,如果你想巩固一下js那么就和我一起来看看吧. 如果你能不看书就回答上80%的问题说明你js的这一部分学得还不错,再接再厉. 作用域和 ...

  4. 队列工厂之RedisMQ

    本次和大家分享的是RedisMQ队列的用法,前两篇文章队列工厂之(MSMQ)和队列工厂之RabbitMQ分别简单介绍对应队列环境的搭建和常用方法的使用,加上本篇分享的RedisMQ那么就完成了咋们队列 ...

  5. android添加权限--eclipse

    首先进入清单文件 2.点击下面的permissions----Add 3.选择Uses permission-----OK 4.选择需要的权限 5.查看代码,,已经添加完毕

  6. HTML5 移动页面自适应手机屏幕四类方法

    1.使用meta标签:viewport H5移动端页面自适应普遍使用的方法,理论上讲使用这个标签是可以适应所有尺寸的屏幕的,但是各设备对该标签的解释方式及支持程度不同造成了不能兼容所有浏览器或系统. ...

  7. PHP的错误处理

    PHP的错误处理机制 php的错误处理是比较复杂的, 本文讲解php中所有错误相关的重要知识点做一次梳理, 便于理解php的错误机制. 基础知识 在此之前, 先熟悉一下php error的基础知识 预 ...

  8. node.js平台下的mysql数据库配置及连接

    首先下载mysql模块包 npm install mysql --save-dev 专门为数据库创建一个模块,放入一个文件中. var mysql=require("mysql") ...

  9. CSS左侧固定宽 右侧自适应(兼容所有浏览器)

    左侧固定宽,右侧自适应屏幕宽: 左右两列,等高布局: 左右两列要求有最小高度,例如:200px;(当内容超出200时,会自动以等高的方式增高) 要求不用JS或CSS行为实现: 仔细分析试题要求,要达到 ...

  10. Java EE基础之JSP(三)

         原来准备简单点,用一篇文章介绍完JSP的,没想到细节很多.这是第三篇也是最后一篇,这三篇文章介绍了基本的JSP知识,很多名词概念和用法,一定要在实践项目中使用之后才会有更加亲切的体会.第三篇 ...