当前位置:   article > 正文

Verilog 双向端口_verilog inout 双向端口

verilog inout 双向端口

1、双向端口简介

实现双向端口的典型方法是三态缓冲器也称三态门,它常用于双向数据总线的构建。在数字电路中,逻辑输出有两个正常态:低电平状态(对应逻辑0)和高电平状态(对应逻辑1);此外,电路还有不属于0和1状态的高阻态(对应逻辑Z  )。所谓高阻,即输出端属于浮空状态,只有很小的漏电流流动,其电平随外部电平高低而定,门电平放弃对输出电路的控制。或者可以理解为输出与电路是断开的。最基本的三态缓冲器的逻辑符号如下图:

当OE为高电平时,Dataout与Datain相连;而OE为低时,Dataout为高阻态,相当于与Datain之间的连线断开。

在应用代码中,Verilog HDL程序模块首先要进行I/O端口(input:输入端口;output:输出端口;inout:双向端口,同时具有输入输出功能的端口)的定义,然后是逻辑功能的描述。在Verilog HDL中,output端口可以定义为寄存器型变量,并在always块内可以被赋值使用,而inout型双向端口信号不能被定义为寄存器型变量,因此在always块内不能直接被赋值。

由于现在FPGA设计和外部存储器或CPU数据交换的频繁运用,以及引脚资源有限,使用双向端口设计可以成倍地节省数据引脚线,所以利用Verilog HDL实现双向端口至关重要。在设计双向端口时应注意两点:其一,要用三态门的控制来处理实现双向端口;其二,要分别指定双向端口作为输出口和输入口时,其外部对象的数据操作。

2、双向端口应用实例

实例假设输入输出数据的位宽为8,使用双向端口设计,需要8根数据线。

例:双向端口的Verilog实例。

  1. module dinout(din,z,clk,dout,dinout)
  2. input [7:0] din;
  3. input z;
  4. input clk;
  5. output [7:0] dout;
  6. inout [7:0] dinout;
  7. reg [7:0] dout;
  8. reg [7:0] din_reg;
  9. assign dinout = (!z)?din_reg:8’bz;
  10. always @(posedge clk)
  11. begin
  12. if(!z)
  13. din_reg=din;
  14. else
  15. dout=dinout;
  16. end
  17. endmodule

 程序在ISE中综合后的RTL级结构图如下图所示。dinout定义为双向端口,即可作为输入端口,又可作为输出端口;当双向端口dinout作为输出口时,从输入端口din输入数据到模块中,让数据从dinout端口输出;当双向端口dinout作为输入口时,数据从dinout口输入,从输出端口dout输出。z为三态门选通信号,当z=1时,三态门置于高阻态,这是dinout作为输入口;当z=0时,开通三态门,dinout作为输出端口。

3、双向端口的仿真

编写测试模块时,对于inout类型的端口,与输出端口一样,需要定义成wire类型的变量,而输入端口定义为reg类型,这两者是有区别的。此外,对于双向端口本身,仿真其输出端口和输入端口的语法是不同的。下面分别给出上例中双向端口的输入、输出特性仿真。

(一)双向端口作为输出端口时仿真

当双向端口作为输出口时,不需要对其进行初始化,只要开通三态门即可。输出端口特性仿真代码如下所示。假设在100ns后,让数据10-20依次从din口输入,然后用10ns的采样时钟从双向端口dinout输出。

  1. module tb_dout
  2. reg [7:0] din;
  3. reg z;
  4. reg clk;
  5. wire [7:0] dout;
  6. wire [7:0] dinout;
  7. integer i;
  8. dinout uut(
  9. .din(din),
  10. .z(z),
  11. .clk(clk),
  12. .dout(dout),
  13. .dinout(dinout)
  14. );
  15. always #5 clk = ~clk;
  16. initial
  17. begin
  18. din=0;
  19. z=0;
  20. clk=0;
  21. #100 din=10;
  22. for(i=0;i<10;i=i+1)
  23. #10 din=din+1;
  24. end
  25. endmoudle

 (二)双向端口作为输入端口时仿真

当双向端口dinout作为输入口时,需要对它进行初始化赋值并关闭三态门。而如果把它跟一般的输入口一样直接初始化赋值,则会出错,这是因为在定义它的时候是wire型的数据变量,而不是reg型数据类型。因此,这里需要用到force命令,用来强制给dinout赋值。同样,下面给出一个Verilog HDL仿真实例,设定在100ns后,让数据20-10从dinout口输入模块,然后用10ns的采样时钟从输出口dout输出。

  1. module tb_din
  2. reg [7:0] din;
  3. reg z;
  4. reg clk;
  5. wire [7:0] dout;
  6. wire [7:0] dinout;
  7. integer i;
  8. dinout uut(
  9. .din(din),
  10. .z(z),
  11. .clk(clk),
  12. .dout(dout),
  13. .dinout(dinout)
  14. );
  15. always #5 clk = ~clk;
  16. initial
  17. begin
  18. z=1;
  19. clk=0;
  20. force dinout = 20;
  21. #100
  22. #100 din=10;
  23. for(i=0;i<10;i=i+1)
  24. #10 dinout=dinout-1;
  25. end
  26. endmoudle

参考文件:

《Verilog HDL程序设计与实践(云创工作室)》

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家自动化/article/detail/420683
推荐阅读
相关标签
  

闽ICP备14008679号