6.Inout双向端口信号处理方法
Verilog中inout端口的使用方法
(本文中所有Verilog描述仅为展示inout端口的用法,实际描述则需要更丰富的功能描述)
Inout端口的使用
在芯片中为了管脚复用,很多管脚都是双向的,既可以输入也可以输出。在Verilog中即为inout型端口。Inout端口的实现是使用三态门,如FPGA中的管脚复用部分:
三态门的第三个状态是高阻态Z。在实际电路中高阻态意味着响应的管脚悬空、断开。当三态门的控制信号为真时,三态门导通;控制信号为假时,三态门的输出端是高阻态。
Verilog中的inout端口被综合为如下形式:
Inout端口是一个很容易出错的地方,理解inout端口模型必须要抓住三点:
- inout端口不可能独立存在;
- 作为输入必须有reg型缓冲(一个inout两个控制信号);
- 相连的两个inout端口由一对信号交错控制;
下面一一分析。
- inout端口不可能独立存在:
分析inout的端口特性,对于一个模块来说,inout端口既可以当做输入,又可以当做输出,那么,与inout端口相连的另一模块是什么情形呢?显然,另一模块也应该是inout端口,inout端口不可能独立存在。但是在实际编写Verilog代码的过程中,却常常忽略这一点,而仅仅是另一模块的一条输出线和一条输入线同时连接到inout端口上,乍看起来符合逻辑,实则不然。
以下图为例:
图中的存储器Memory用RAM实现,无论CPU还是RAM都只有一组数据总线,而图中输入给Memory的有WriteData,从Memory输出的有MemData,这两组其实是一组数据总线,而实现此管脚复用功能的就是管脚复用。在用Verilog描述的过程中,只考虑CPU的数据通路结构时,就容易忽略它的双向端口的具体实现,并非如图中一般,简简单单的与RAM模块的inout端口相连。所以,一定要注意到inout端口不能独立存在,用Verilog描述上图中的CPU模块时也要描述一个inout端口及相关逻辑。
- 作为输入必须有reg型缓冲:
考虑到这种情况:当control信号为真时,三态门导通,这时,DataOut的输出通过双向端口传输到DataBus上。但是DataIn与DataOut直接相连,如何保证DataOut的数据不会影响到DataIn相连的电路呢?
解决这个问题的办法是把DataIn声明为reg型,而reg型的变量在always过程块中被复制,需要再增加一个控制信号,由always敏感表列监控,以此保证inout端口作为输出时不会影响DataIn。
实际用Verilog描述的过程中,常常容易忽略某一个inout端口的reg声明。以CPU和RAM为例,RAM本身作为存储器就是用reg声明的,所以不需要这个reg缓冲(前提是写RAM时一定要在always敏感表列中添加控制信号);而CPU模块的inout端口的reg声明却常常被忽略,因为这个东西看上去"画蛇添足"。这也是初学者使用inout端口时最容易犯错的地方。
- 相连的两个inout端口由一对信号交叉控制:
前面提到inout端口不能独立存在,进一步考虑,当一个模块的inout端口作为输出时,那么另一个模块的inout端口必然作为输入;反之,当一个模块的inout端口作为输入时,那么另一个模块的inout端口必然作为输出。因此,这两个inout端口的控制信号实际上是由一对信号交叉控制。
以下图为例:
CPU控制读写RAM的信号有一对:ReadRAM和WriteRAM。
当ReadRAM有效时,CPU从RAM中读取数据,这时RAM的三态门导通,RAM的inout端口作为输出用,CPU的inout端口作为输入用,并且用ReadRAM信号控制CPU读取;
当WriteRAM有效时,CPU向RAM写入数据,这时CPU的三态门导通,CPU的inout端口作为输出用,RAM的inout端口作为输入用,并且用WriteRAM信号控制RAM写数据。
理解inout端口的实现,并且注意到上面三点,就可以开始用Verilog描述inout端口了。进行抽象:
1.三态门及其高阻态的实现(输出):
Inout DataBus;
Assign DataBus=(Control[0]==1)?DataOut:32'bz;//位宽由实际情况决定
2.输入缓冲(输入):
Reg DataIn;
Always @(Control[1])
If(Control[1])
DataIn<=DataBus;
下面给出真正的inout端口的应用描述,仍以上图中CPU和RAM为例(注意到RAM中没有声明reg型缓冲而CPU则显示声明reg型缓冲,以及两个模块中的一对控制信号的交叉):
module DRAM(DataBus,AddressBus,ReadRAM,WriteRAM);
inout [31:0]DataBus;
input [9:0]AddressBus;
input ReadRAM,WriteRAM;
reg [31:0]RAM[0:1023];
parameter insfile="InstructionFile.txt",
datafile="DataFile.txt";
initial
begin
$readmemh(insfile,RAM,0);
$readmemh(datafile,RAM,512);
End
assign DataBus=(ReadRAM==1)? RAM[AddressBus]:32'bz;
always @(WriteRAM or DataBus)
if(WriteRAM)
RAM[AddressBus] =DataBus;
Endmodule
//仅仅为了说明inout端口用法,真实的CPU描述远非如此
module CPU(DataBus,AddressBus,ReadRAM,WriteRAM,Clock,Reset);
inout [31:0]DataBus;
output [9:0]AddressBus;
output ReadRAM,WriteRAM;
input Clock,Reset;
reg [31:0]DataRead;
assign DataBus=(WriteRAM==1)?DataWrite:32'bz;
always @(ReadRAM)
if(ReadRAM)
DataRead=DataBus;
//CPU中以后的代码就是用DataRead和DataWrite来完成和RAM的数据交换
endmodule
误解:用一对相反的信号控制两个inout端口实现双向传输。
造成这种误解的原因是在两个module中的inout端口中,三态门不可能同时导通,默认两个三态门总是一个导通另一个不导通,忽略了两个都不导通的情况。所以在实际电路中,用于控制两个inout端口的,必然是一对控制信号的交叉形式。
Inout端口的仿真
有关包含inout端口模块的单独仿真和inout端口的应用情况类似,只不过两个模块间的关系不同,需要做一下变动。
Testbench作为最顶层模块,是没有端口列表的,也就不可能为其声明一个inout端口。如前所述,inout端口不可能独立存在。这时候,虽然不能声明一个inout端口,但是可以描述一个和inout端口有相同功能的逻辑。
把inout端口拆分为两个连在一起的输入端口和输出端口,如下图所示。在testbench中,用于给实例输入的信号是reg型,从实例输出的信号被声明为wire型,而inout端口本身必须被声明为wire型。因此,需要定义一个wire型的TestOut和reg型的TestIn。Testbench的目的是为了测试模块的功能而不是跟模块交换数据,因此,在testbench中的"类inout端口"没有真正的inout端口那么多约束。唯一需要注意的是reg型的TestIn向inout被测试模块的inout端口写数据时需要有一个控制信号,这个控制信号就是被测模块内部的WriteRAM。
这样,用于测试上面的RAM模块的Verilog描述如下:
`include "DRAM.v"
module test;
reg [9:0]AddressBus;
reg Read,Write;
wire [31:0]DataBus,TestOut;
reg [31:0]TestIn;
DRAM dram(DataBus,AddressBus,Read,Write);
assign DataBus=(Write==1)?TestIn:32'bz;
assign TestOut=(Read==1)?DataBus:32'bz;
initial
begin
Write=1'b0;Read=1'b0;AddressBus=1'b0;TestIn=1'b0;
#100 Write=1'b1;AddressBus=10'd4;TestIn=32'd64;
#10 Write=1'b0;
#10 Read=1'b1;AddressBus=10'd8;
#30 $stop;
end
endmodule
进一步考虑,testbench中的"inout端口"本身已被声明为wire类型,显然wire型的TestOut就失去了意义,可以将它们合并:wire型的inout足以显示输出信号的变化。最终的testbench模型如下:
改进后的testbench用Verilog描述为:
`include "DRAM.v"
module test;
reg [9:0]AddressBus;
reg Read,Write;
wire [31:0]DataBus;
reg [31:0]TestIn;
DRAM dram(DataBus,AddressBus,Read,Write);
assign DataBus=(Write==1)?TestIn:32'bz;
initial
begin
Write=1'b0;Read=1'b0;AddressBus=1'b0;TestIn=1'b0;
#100 Write=1'b1;AddressBus=10'd4;TestIn=32'd64;
#10 Write=1'b0;
#10 Read=1'b1;AddressBus=10'd8;
#30 $stop;
end
endmodule
总线上的inout端口
实际应用中最常见的应用inout端口的地方是总线,如数据总线、控制总线、地址总线,而总线绝大多数都是双向总线,挂接在总线上的部件往往很多。如果总线上只挂接了两个部件,这种情况就是前面描述的两个inout端口相连接的问题。但是总线上挂接的部件往往很多,这时候应该怎么Verilog描述呢?
其实原理是一样的,最基本的原则就是:
在同一时刻,一条总线上最多只能有一个inout端口作为输出部件。
换句话说,即是在某一时刻,一条总线上最多有一个inout端口作输出,其余的部件要么作为输入部件,要么就是高阻态。这样才能避免数字电路中一个很尴尬的问题:多驱动。
因此,在描述总线的时候,挂接在总线上的部件只要注意到上面的规则避免多驱动,即可实现所需的功能。
6.Inout双向端口信号处理方法的更多相关文章
- GPIO输入输出各种模式(推挽、开漏、准双向端口)详解
转自:https://blog.csdn.net/techexchangeischeap/article/details/72569999 概述 能将处理器的GPIO(General Purpose ...
- Vs2015 win10虚拟机启动问题:无法设置UDP端口 解决方法 合集(转载)
刚装的vs2015 社区版 出现这个问题,wp8.1和win10m模拟器都无法启动,找了好久找到的解决方案,放这儿供大家参考,免得大家像我一样走弯路: Windows Phone emulator n ...
- 三菱plc编程电缆通讯端口设置方法(转载)
三菱plc编程电缆通讯端口如何设置?三菱plc编程电缆通讯端口设置方法 时间:2015-10-21 05:09:20编辑:电工栏目:三菱plc 导读:三菱plc编程电缆通讯端口的设置方法,三菱plc上 ...
- 使用AdvancedInstaller打包web工程设置tomcat端口的方法
原文:使用AdvancedInstaller打包web工程设置tomcat端口的方法 1.首先,要把你要打包的tomcat下的server.xml文件删掉,因为tomcat自带的serv ...
- Windows server 2008R2远程桌面3389端口修改方法技巧
windows server的服务器远程桌面默认端口号是3389,在工作中经常使用远程桌面连接服务器,但是这也是常常被黑客利用的端口号,但是如何修改掉默认端口,预防被黑客利用呢? 可以如下操作配置:很 ...
- Nginx服务器中配置非80端口的端口转发方法详解
这篇文章主要介绍了Nginx服务器中配置非80端口的端口转发方法详解,文中使用到了Nginx中的proxy_pass配置项,需要的朋友可以参考下 nginx可以很方便的配置成反向代理服务器: 1 2 ...
- WINDOWS SERVER 2008远程桌面端口修改方法
微软默认的服务器远程端口是3389,这是被很多黑客利用的端口,如何修改掉了,下面我们来说方法很多朋友在使用WINDOWS操作系统的时候,都喜欢修改远程连接的默认端口.但是很多朋友由于修改端口的方法错误 ...
- 服务器--apache启用多个端口的方法
apache启用多个端口的方法 使用本地ip:端口号,或者修改hosts文件+域名的方法来进行本地多站点web调试. 注意这里是用apache 不是iis 1.安装好AppServ2.5.9软件 官网 ...
- 查看Windows端口及端口关闭方法
一.查看已开放的端口: 1.借助系统自带MS-DOS命令查看开放的端口(Win2000/XP/server2003) 在开始-运行-输入cmd,打入netstat -an(注意-前有个小空格),在IP ...
随机推荐
- SVN与TortoiseSVN实战:补丁详解
硬广:<SVN与TortoiseSVN实战>系列已经写了五篇,第二篇<SVN与TortoiseSVN实战:标签与分支>和第三篇<SVN与TortoiseSVN实战:Tor ...
- A script job for rebuild DB in AX 2012
-- Ensure a USE <databasename> statement has been executed first. SET NOCOUNT ON; DECLARE @obj ...
- 如何避免遭受HTTS中间人攻击
先前为大家说明了如何对App的HTTPS通讯进行中间人攻击,听起来很吓人吧-表示若是使用手机的网银或购物等App,便有可能暴露在风险之中. 会发生HTTPS遭受拦截的主要原因是客户端的App未对服务器 ...
- aspx网页相对布局
网页的布局 <body bgcolor="#b6b7bc"> <form id="form1" runat="server" ...
- 误删ext3的恢复方法
1.Ext3文件系统结构的简单介绍在Linux所 用的Ext3文件系统中,文件是以块为单位存储的,默认情况下每个块的大小是1K,不同的块以块号区分.每个文件还有一个节点,节点中包含有文件所有者, 读写 ...
- ASP.NET 项目 App_Code下无法找到类
APP_CODE 默认情况下,VS2010中新建的WebApplication中是没有App_Code文件夹的,若需要使用,可以自己手动添加文件夹,然后将文件夹名称设置为App_Code,然后在该文件 ...
- SQL SERVER连接字符串学习
在使用connection string时遇到一些问题 字符串如下"Data Source= ******;Initial Catalog=******;Persist Security I ...
- Lucene全文检索框架
1.什么时Lucene? 是一个全文搜索框架,而不是应用产品,他只是一种工具让你能实现某些产品,并不像www.baidu.com拿来就能用 是apache组织的一个用java实现的全文搜索引擎的开源项 ...
- 修改 WordPress 文件上传目录
WordPress 默认的上传目录位于 wp-content/uploads ,并且根据设置还可以按照年月归档.但是如果要上传一个头像,或者幻灯片的话,也跟附件混在一起总是不太好吧?幸好 WordPr ...
- DOS下无法调出中文输入法-Solved
From:http://www.cnblogs.com/killerlegend/p/3750542.html Author:KillerLegend Date:2014.5.24 DOS下无法打开中 ...