> 文档中心 > 通俗易懂的带你解读inout双向端口【Verilog高级教程】

通俗易懂的带你解读inout双向端口【Verilog高级教程】

Verilog中inout双向端口的使用说明书

    • 一、写在前面
    • 二、什么是inout双向端口
    • 三、inout端口的综合
    • 四、inout双向端口的要求
    • 五、inout端口的赋值
      • 设计文件的赋值
      • 仿真文件的赋值
    • 六、更多资料
    • 七、往期【Verilog】高级教程文章

一、写在前面

本专栏为作者在 【数字IC手撕代码】 【数字IC笔试面经分享】 【数字IC工具解析】 以外开设的第四个独立专栏,旨在学习并提供有关Verilog硬件描述语言中非基础性的高阶语法特性知识,因本身专栏的独特定位,因此作者并不会涉及基础Verilog语言如阻塞式非阻塞赋值,过程块,数据类型等内容;同时受限于作者知识有限,本专栏也不会涉及System Verilog的相关内容,若按照IEEE的相关标准来看,本专栏将会聚焦Verilog-2005,即“IEEE Std 1364™-2005”以及之前的有关内容,提供相关的IC设计领域语法特性。以下为Verilog的进阶框图,有更多学习需求的读者可以检索相关英文标准进行学习。
在这里插入图片描述

二、什么是inout双向端口

在Verilog中,inout是一个双向接口(区别于input与output),也是一个可综合语句,广泛的应用于比如I2C等协议的设计中,声明inout端口,意味着数据既可以从主设备流向从设备,也可以从从设备流向主设备。

三、inout端口的综合

inout端口会被综合成为如下所示的三态门高阻态的引入,有效的消除了电路中其他部分对于此门的影响,也解决了常规端口可能会出现的多驱动的问题,因此,三态门广泛的应用于总线互联的端口,也是我们今天所讨论的inout端口的综合结果
通俗易懂的带你解读inout双向端口【Verilog高级教程】

四、inout双向端口的要求

  • inout端口默认为wire型,这意味着我们不能在always中对其进行赋值,而需要使用assign进行赋值
  • 每一个inout端口都需要一个reg型的buffer来做缓冲器

考虑这种情况:
当控制信号为真时,三态门开启,此时DataOut的输出通过双向端口传输到数据总线上。
但是DataIn和DataOut是直接相连的,如何保证DataOut的数据不会影响到与DataIn相连的电路呢?
解决这个问题的方法是将DataIn声明为reg类型,将reg类型变量复制到always进程块中,需要添加一个控制信号,由always敏感表监控,保证inout端口的输出不能直接贯通到Datain处。

在Verilog描述的实际过程中,往往容易忽略某个inout端口的reg语句。以 CPU 或 RAM 为例。RAM本身是作为内存用reg声明的,所以不需要这个reg缓冲区;而 CPU 模块的 inout 端口的 reg 语句经常被忽略,因为这东西看起来“多余”。这也是初学者在使用 inout 端口时最容易出错的地方。

  • 我们没有办法同时对inout端口既写又读(即同一时刻,数据只能有一个方向),配合着三态门的综合结果,在接收数据的的时候我们使其保持高高阻态
  • inout 端口不能独立存在

对于一个模块,inout 端口可以用作输入和输出。那么,连接到inout口的另一个模块是什么情况呢?显然,另一个模块也应该是一个inout端口,一个inout端口不能独立存在。但在实际编写 Verilog 代码的过程中,这点往往被忽略。

  • 对inout的赋值需要使用一对信号来完成

如前所述,inout 端口不能独立存在。为了进一步考虑,当一个模块的inout端口作为输出时,那么另一个模块的inout端口必须作为输入;反之,当一个模块的inout口用作输入时,那么另一个模块的inout口一定是输出口。因此,两个inout端口的控制信号实际上是由一对信号控制的。

五、inout端口的赋值

设计文件的赋值

方法一:声明一个受control信号控制的inout型的myport,当control为1时,赋值为data,control为0时,赋值为高阻态,推荐这个方法

assign myport = control ? data : 'z;

方法二:虽然本专栏在探讨IEEE Verilog-2005的相关设计标准,但是都说到这里了,作者再补充以下System Verilog出现后,inout端口新的赋值方法,以下的赋值看起来会比较奇特,因为正常的寄存器不产生Z值,但是在System Verilog的编译条件下,这种方法也是可行的。

logic myport_reg;assign myport = myport_reg;] // in procedural code    myport_reg <= data; // myport becomes an output    myport_reg <= 'z; // myport becomes an input

仿真文件的赋值

testbench没有端口名称,因此我们没有办法在testbench中将其声明为inout端口,为了在testbench中体现inout,首先,我们需要将inout端口声明为wire型,例化的时候与设计文件连接,其次,我们要分别模拟input和output的行为,读取的时间高阻态,发送的时间有相对应的值,下文的案例为SRAM的testbench,其中Databus在设计文件中声明为了inout端口

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;initialbeginWrite=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;endendmodule

六、更多资料

有更多学习需求的读者可以直接参考以下连接的文章,虽然是英文的,不过应该可以说将inout讲的非常清晰明了,作者的本篇博客也参考了很多下面的文章内容
How to use the inout port in Verilog

七、往期【Verilog】高级教程文章

  • 多维数组:灭霸打个响指的功夫,看懂Verilog多维数组
  • clog2系统函数: 关于Verilog自动计算位宽的系统函数$clog2,这些是你不得不知道的
  • UDP用户原语:玩转UDP用户原语,这篇文章就够了
  • $monitor系统函数:放学前的最后几分钟,看懂Verilog中的monitor系统函数
  • generate语句:一把王者的时间,学会Verilog中的generate语句
  • parameter常量:玩转parameter与localparameter,这篇文章就够了
  • inout双向端口:通俗易懂的带你解读inout双向端口

天天排行榜