Verilog中inout端口的使用方法

(本文中所有Verilog描述仅为展示inout端口的用法,实际描述则需要更丰富的功能描述)

Inout端口的使用

在芯片中为了管脚复用,很多管脚都是双向的,既可以输入也可以输出。在Verilog中即为inout型端口。Inout端口的实现是使用三态门,如FPGA中的管脚复用部分:

三态门的第三个状态是高阻态Z。在实际电路中高阻态意味着响应的管脚悬空、断开。当三态门的控制信号为真时,三态门导通;控制信号为假时,三态门的输出端是高阻态。

Verilog中的inout端口被综合为如下形式:

Inout端口是一个很容易出错的地方,理解inout端口模型必须要抓住三点:

  1. inout端口不可能独立存在;
  2. 作为输入必须有reg型缓冲(一个inout两个控制信号);
  3. 相连的两个inout端口由一对信号交错控制;

下面一一分析。

  1. inout端口不可能独立存在:

分析inout的端口特性,对于一个模块来说,inout端口既可以当做输入,又可以当做输出,那么,与inout端口相连的另一模块是什么情形呢?显然,另一模块也应该是inout端口,inout端口不可能独立存在。但是在实际编写Verilog代码的过程中,却常常忽略这一点,而仅仅是另一模块的一条输出线和一条输入线同时连接到inout端口上,乍看起来符合逻辑,实则不然。

以下图为例:

图中的存储器Memory用RAM实现,无论CPU还是RAM都只有一组数据总线,而图中输入给Memory的有WriteData,从Memory输出的有MemData,这两组其实是一组数据总线,而实现此管脚复用功能的就是管脚复用。在用Verilog描述的过程中,只考虑CPU的数据通路结构时,就容易忽略它的双向端口的具体实现,并非如图中一般,简简单单的与RAM模块的inout端口相连。所以,一定要注意到inout端口不能独立存在,用Verilog描述上图中的CPU模块时也要描述一个inout端口及相关逻辑。

  1. 作为输入必须有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端口时最容易犯错的地方。

  1. 相连的两个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端口作输出,其余的部件要么作为输入部件,要么就是高阻态。这样才能避免数字电路中一个很尴尬的问题:多驱动。

因此,在描述总线的时候,挂接在总线上的部件只要注意到上面的规则避免多驱动,即可实现所需的功能。

Verilog中inout端口的使用方法相关推荐

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

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

  2. Verilog中inout的用法(二)

    芯片外部引脚很多都使用 inout 类型的,为的是节省管腿.一般信号线用做总线等双向数据传输的时候就要用到 INOUT 类型了.就是一个端口同时做输入和 输出. inout 在具体实现上一般用三态门来 ...

  3. Verilog中inout的用法

    芯片外部引脚很多都使用 inout 类型的,为的是节省管腿.一般信号线用做总线等双向数据传输的时候就要用到 INOUT 类型了.就是一个端口同时做输入和 输出. inout 在具体实现上一般用三态门来 ...

  4. Verilog中InOut引脚、三态门实现、仿真

    三态门 三态门中,EN'为0时,门电路正常工作,EN'为1时,T1.T2均截止,整个门电路不对外输出,成高阻态,三态门常用在总线传输中,多个器件共用一个数据总线,通过控制多个EN唯一导通,实现指定器件 ...

  5. win10 设备管理器中没端口选项解决方法

    win10 设备管理器中没端口选项是怎么回事? 解决方法: 被隐藏了,点击上面的查看,勾选显示隐藏的设备就可以找到端口了 转载来源:https://zhidao.baidu.com/question/ ...

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

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

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

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

  8. 在ADS中查看端口输入阻抗的方法

    在ADS的S参数仿真中可以查看网络端口的输入阻抗,现在以一个简单的阻抗匹配网络设计实验来介绍这个功能. 搭建一个阻抗匹配网络 在ADS中搭建一个由理想微带线构成的阻抗匹配网络,端口1的阻抗为50 Ω, ...

  9. Verilog中inout的使用

    刚开始学,用到inout,记录一下 只写核心部分 inout data:reg inout_ctrl;//控制输入输出模式 reg data_out://输出模式时需要输出的数值 //当inout_c ...

最新文章

  1. 自己封装js组件 - 中级
  2. 神经网络的分类行为怎么就不能是一种力的行为?
  3. mysql数据库备份心得
  4. nginx php oracle,第8天 ORACLE安装及NGINX整合PHP环境
  5. C++中的指针与引用(转)
  6. 【Python CheckiO 题解】Xs and Os Referee
  7. 带有返回值的装饰器_如何使用带有工厂功能的装饰器
  8. NET学习笔记-3:垃圾回收与内存管理
  9. ipad文献管理软件_【MAC上写论文有哪些好的文献管理软件可以推荐?】-看准网
  10. Android加载网络GIF完整解决方案
  11. EasyPR--开发详解
  12. TMOD、TCON、SCON、PCON、SBUF寄存器说明
  13. 国际电话登机英文术语
  14. 马云的“虚拟信用卡”动了谁的奶酪?
  15. struggle for English college test band 6
  16. 电缆 电流_如何不用电缆观看每项运动(运动返回时)
  17. 人脸识别系列(十七):ArcFace/Insight Face
  18. R语言基础教程6:程序设计基础
  19. 爬虫例子——多页、函数模板
  20. uniapp,小程序倒计时结束后在哪个页面就在哪个页面弹出全局弹窗

热门文章

  1. RT-Thread智能车培训计划-2021
  2. 基于SP4062电路IO接口八通道保护板
  3. 什么是清华大学的“三好”学生?
  4. python linux arm_[Python]python for ARM/LINUX
  5. hadoop和python的关系_Python 的 map 和 reduce 和 Hadoop 的 MapReduce 有什么关系?
  6. 修改 mysql 字符集_如何修改MySQL字符集
  7. java base64 压缩_在线等(急)Base64(带压缩)出问题
  8. php 位运算与权限,PHP巧妙利用位运算实现网站权限管理的方法
  9. 如何保证两个不同宽高的canvas用同一组坐标正常显示_如何1人5天开发完3D数据可视化大屏 【一】...
  10. HDLBits 系列(31)Serial Receiver and Datapath