当前位置:   article > 正文

【Verilog】inout 端口信号的使用_verilog inout

verilog inout

inout 介绍

芯片的许多外部引脚使用输入式来节省管脚。通常,当信号线用于双向数据传输(例如总线)时,使用 inout 类型。也就是说,端口同时用于输入和输出。inout 通常在特定实现中通过三态门实现。三态栅极的第三种状态是高阻抗'Z'。当输入端口不输出时,将三态栅极设置为高阻抗。这样,信号就不会因为两端同时输出而出错。

使用说明

1. 使用 inout 类型数据,可以这样写:

  1. inout data_inout;
  2. input data_in;
  3. reg data_reg;
  4. reg link_data;
  5. assign data_inout = link_data? data_reg: 1'bz;

对于 data_reg,可以通过组合逻辑或顺序逻辑根据data_in进行分配。

通过控制 link_data 级的高、低功率,从而设置 data_inout 输出数据或处于高阻抗状态,如果处于高阻抗状态,此时作为输入端口可以通过使用 link_data 相关电路进行控制。

2. 写入测试模块,对于输入类型的端口,需要定义为 wire 类型变量,而其他输入端口都定义为 reg 类型,

两者是有区别的。

当将上面示例中的data_inout用作输入时,需要将其分配给data_inout,其余部分可以断开连接。

这时,可以使用 assign 语句来实现:assign data_inout = link?Data_in_t: 1'bz;

其中 link 和 data_in_t 是 reg 类型变量,在测试模块中分配值。

此外,可以设置输出端口以观察 data_inout 用作输出的情况:

并且在 RTL 中,inout 在顶部模块中输入使用  不要在子模块中使用 inout(tri)  

换句话说,最好不要在内部模块中有 inout。如果确实需要它,请使用两个端口来实现它,然后在达到顶层时使用三态实现。原因是:如果一个非顶层模块中使用了一个双向端口,那么这个双向端口的上层必须连接到它。由于是双向端口,因此至少将一个输入端口和一个输出端口连接到上层的双向端口,并且将两个内部输出单元连接在一起,这在合成过程中经常出错。对于双向端口,我们可以将其理解为两个组件:输入组件和输出组件。此外,还需要一个控制信号来控制输出组件的输出时间。

  1. module dual_port (
  2. inout_pin,
  3. );
  4. inout inout_pin;
  5. wire inout_pin;
  6. wire input_of_inout;
  7. wire output_of_inout;
  8. wire out_en;
  9. assign input_of_inout = inout_pin;
  10. assign inout_pin = out_en? output_of_inout: 1'bz;
  11. endmodule

可以看出,此时 input_of_inout 和 output_of_inout 可以作为普通信号使用。

在仿真过程中,要注意双向端口的处理。如果直接连接到另一个模块的双向端口,就足以保证当一个模块输出时,另一个模块没有输出(处于高阻抗状态)。

如果在 ModelSim 中作为单独的模块进行仿真,那么当模块输出时,不能使用 force 命令将其设置为高阻抗,而是使用释放命令来释放总线。

源代码:

  1. module xx(data_inout , ........);
  2. inout data_inout;
  3. assign data_inout = (!link) ? datareg : 1'bz;
  4. endmodule

方法一:使用相反的控制信号输入端口,相当于在两个模块之间使用 inout 双向端口互连。这种方法应该注意,赋值语句只能放在 initial 和 always 块中。

  1. module test();
  2. wire data_inout;
  3. reg data_reg;
  4. reg link;
  5. initial begin
  6. ..........
  7. end
  8. assign data_inout = link ? data_reg : 1'bz;
  9. endmodule

方法2:使用force和reless语句,但这种方法不能准确反映双向端口的信号变化,但这种方法可以在块中反转。

  1. module test();
  2. wire data_inout;
  3. reg data_reg;
  4. reg link;
  5. initial begin
  6. .....
  7. end
  8. assign data_inout = link ? data_reg : 1'bz;
  9. endmodule

示例

  1. module bidirection_io(
  2. inner_port,
  3. out_en,
  4. outer_port
  5. );
  6. input out_en;
  7. inout [7:0] inner_port;
  8. inout [7:0] outer_port;
  9. assign outer_port = (out_en==1) ? inner_port : 8'hzz;
  10. assign inner_port = (out_en==0) ? outer_port : 8'hzz;
  11. endmodule

在仿真过程中,需要验证双向端口是否正确输出数据并正确读取数据。因此,有必要驱动out_en端口。

当 out_en 端口为1时,测试平台驱动 inner_port 端口,然后检查 outer_port 端口输出的数据是否正确;当 out_en 端口为0时,测试台驱动 outer_port 端口,然后检查 inner_port 端口读取的数据是否正确。由于 inner_port 和 outer_port 端口都是双向端口,因此驱动方法与单向端口不同。

用Verilog代码编写的 testbench 如下。

  1. `timescale 1ns/10ps
  2. module tb();
  3. reg [7:0] inner_port_tb_reg;
  4. wire [7:0] inner_port_tb_wire;
  5. reg [7:0] outer_port_tb_reg;
  6. wire [7:0] outer_port_tb_wire;
  7. reg out_en_tb;
  8. integer i;
  9. initial begin
  10. out_en_tb=0;
  11. inner_port_tb_reg=0;
  12. outer_port_tb_reg=0;
  13. i=0;
  14. repeat(20)
  15. begin
  16. #50
  17. i=$random;
  18. out_en_tb=i[0];
  19. inner_port_tb_reg=$random;
  20. outer_port_tb_reg=$random;
  21. end
  22. end
  23. assign inner_port_tb_wire=(out_en_tb==1)?inner_port_tb_reg:8'hzz;
  24. assign outer_port_tb_wire=(out_en_tb==0)?outer_port_tb_reg:8'hzz;
  25. bidirection_io bidirection_io_inst(
  26. .inner_port (inner_port_tb_wire),
  27. .out_en (out_en_tb),
  28. .outer_port (outer_port_tb_wire)
  29. );
  30. endmodule

 

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

闽ICP备14008679号