首页 > 其他分享 >三态(tri-state)门、双向(bi-directional)端口的建模、仿真和综合

三态(tri-state)门、双向(bi-directional)端口的建模、仿真和综合

时间:2022-12-20 22:12:06浏览次数:62  
标签:tri directional OE 端口 bi diq WIDTH 双向 DIQ

目录

1. 概要

2. 三态门 

2.1 概念

2.2 三态门建模

3. 双向端口

3.1 HDL语言描述

3.2 直接调用元件库中的模块

3. 仿真

4. 综合


1. 概要

        双向端口顾名思义是一种既可以作为输入端口接收数据,也可以作为输出端口发出数据,它对数据的操作是双向的。比如某个设计需要一个 16 位的数据输入口和一个16 位的数据输出口,并且数据输入和输出不会同时发生。 如果数据输入口和输出口分别设计则需要32根数据线,而用双向端口来设计,则只需要16根数据线,这样就节省了16根数据线引脚。在很多情况下,芯片端口是宝贵的设计资源,而且芯片间的连线少对于板级设计也非常有利。因此,双向端口常用于芯片间需要进行半双工双向通信的场合,可以节省一半芯片端口以及减少板上芯片间连接的走线。

        常见的一些例子有:

        . I2C总线中的SDA信号线

        . AXI总线中的数据线

        . JESD207接口中的数据线DIQ、等等

        在电路层面,双向端口是通过三态缓冲器(也称三态门)控制实现的。在数字电路中,逻辑输出有两个正常态:低电平状态(逻辑0)和高电平状态(逻辑1),此外,电路还有不属于0和1的高阻态(逻辑Z)。所谓高阻,即输出端处于浮空状态,只有很小的漏电流流动,其电平随外部电平的高低而定,门电平放弃对输出电路的控制,或者可以理解为输出和电路是断开的。

2. 三态门 

2.1 概念

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

        当OE为高电平时,Dataout与Datain相连,数据流向是从Datain向Dataout;而OE为低时,Dataout为高阻态,相当于与Datain之间的连线断开,此时可以从外部向Dataout驱动信号,实现相反方向的数据流向。

2.2 三态门建模

        三态门的RTL描述方式有以下两种等价的方式。

  1.   // Tristate Description Using Combinatorial Always Block
  2.   // File: tristates_1.v
  3.   //
  4.    
  5.   module tristates_1 (OE, I, O);
  6.    
  7.   input OE, I;
  8.   output O;
  9.   reg O;
  10.    
  11.   always @(OE or I)
  12.   begin
  13.   if (OE)
  14.   O = I;
  15.   else
  16.   O = 1'bZ;
  17.   end
  18.    
  19.   endmodule
  1.   // Tristate Description Using Concurrent Assignment
  2.   // File: tristates_2.v
  3.   //
  4.    
  5.   module tristates_2 (OE, I, O);
  6.    
  7.   input T, I;
  8.   output O;
  9.    
  10.   assign O = (OE) ? I: 1'bZ;
  11.    
  12.   endmodule

3. 双向端口

        通常两种双向端口建模的方法。

        第一种是直接用HDL语言进行行为级描述,基于以上三态门的RTL描述,稍作修改即可。另一种则是直接调用元件库(cell library)中的模块,比如说Xilinx FPGA中的IOBUF等。后者通常只用于在纯粹的FPGA开发(即FPGA实现就是最终实现)中,在芯片开发中,应该采用第一种,如果采用第二种描述的话,将会导致FPGA综合代码与芯片实现代码不一致,并导致FPGA原型验证的有效性受损,这是应该尽量避免的。

3.1 HDL语言描述

        以下为双向端口的两个行为级描述的module例。其中第一个有时钟控制,以同步于时钟沿的方式工作,第二个是存粹的组合逻辑描述方式。前者从综合时序的角度来说会更好一些。

  1.   module BIDIR_CLKED
  2.   #(
  3.   parameter P_WIDTH = 6'd1 //
  4.   )
  5.   (
  6.   input CLK ,
  7.   input OE , // 1: Output port; 0: Input port
  8.   input [P_WIDTH-1:0] DIN ,
  9.   output [P_WIDTH-1:0] DOUT ,
  10.   inout [P_WIDTH-1:0] BIDIR
  11.   );
  12.    
  13.   reg [P_WIDTH-1:0] din_reg;
  14.   reg [P_WIDTH-1:0] dout_reg;
  15.    
  16.   assign BIDIR = OE ? din_reg : {P_WIDTH{1'bZ}};
  17.   assign DOUT = dout_reg;
  18.    
  19.   // Pipelining
  20.   always @ (posedge CLK)
  21.   begin
  22.   din_reg <= DIN;
  23.   dout_reg <= BIDIR;
  24.   end
  25.    
  26.   endmodule
  1.   module BIDIR
  2.   #(
  3.   parameter P_WIDTH = 6'd1 //
  4.   )
  5.   (
  6.   input CLK ,
  7.   input OE , // 1: Output port; 0: Input port
  8.   input [P_WIDTH-1:0] DIN ,
  9.   output [P_WIDTH-1:0] DOUT ,
  10.   inout [P_WIDTH-1:0] BIDIREC
  11.   );
  12.    
  13.   assign BIDIREC = OE ? DIN : {P_WIDTH{1'bZ}}; // DIN --> BIDIREC
  14.   assign DOUT = {P_WIDTH{~OE}} & BIDIREC; // BIDIREC --> DOUT
  15.    
  16.   endmodule

3.2 直接调用元件库中的模块

        不管是FPGA还是ASIC其标准单元库中通常都会包含双向端口单元。以Xilinx为例,它提供了IOBUF单元(另外,还有IOBUF_DIFF_OUT、IOBUFDS等),IOBUF的符号、真值表如下所示(参见UG768):

         以下是两个直接实例化IOBUF的代码例。第一个是1比特的双向端口的IOBUF实例化;第二个是一个多比特的双向总线模块,在该模块中实例化了多个IOBUF。

3. 仿真

        以下案例取自于一个实际的JESD207接口设计,JESD207接口中DIQ信号线是双向信号线。上半部分代码是DUT中实例化BIDIR_CLKED实现双向端口JESD207.DIQ;下半部分为testbench中的处理。

  1.   // ***************************************************************************
  2.   //BIDIR instantiation in DUT
  3.   wire [11:0] diq_tx;
  4.   wire [11:0] diq_rx;
  5.   assign diq_rx = ...;
  6.   BIDIR_CLKED #(12) u_BIDIR_CLKED
  7.   (
  8.   .CLK (CLK ),
  9.   .OE (DIQ_OE ), // 0: RX; 1: TX
  10.   .DIN (diq_tx ),
  11.   .DOUT (diq_rx ),
  12.   .BIDIREC(DIQ )
  13.   );
  14.    
  15.   // ***************************************************************************
  16.   //Signal assignment in testbench.
  17.   logic diq_oe; // Connect to DUT.DIQ_OE port
  18.   wire [11:0] tx_diq;
  19.   wire [11:0] rx_diq;
  20.   wire [11:0] diq; // Connect to DUT.DIQ port
  21.   assign diq = diq_oe ? {12{1'bZ}}: rx_diq;
  22.   assign tx_diq = diq;
  23.   // ***************************************************************************

        需要注意的是,在testbench中,对应于DIQ的信号需要定义成wire类型。此外,对于双向端口/信号的描述,在DUT和testbench中是互补的。如以上代码例所示,由当DUT.DIQ在DIQ_OE的控制下作为输出端口使用,testbench中则应该是要作为输入信号处理,即接收DUT输出的信号;反之,当DUT.DIQ在DIQ_OE的控制下作为输入端口使用,testbench中则应该是要作为输出信号处理,即对DIQ信号进行驱动赋值。

4. 综合

        如上所述,作为芯片设计的FPGA原型验证时,应该使用行为级的方式描述双向端口。但是如何确认描述是否正确呢?一般来说仿真当然可以在很大程度确认这一点,但是更为直接方式是针对综合生成电路进行直接确认,确认综合工具是否正确地将行为级描述正确地推断(infer)为IOBUF。

     以上所述的JESD207接口的Vivado综合为例,在综合结束后,从Vivado界面点击SynthesisàOpen Synthesized DesignàSchematic打开综合生成的电路图,可以找到如下图所示的对应JESD_DIQ接口电路图。从图中可以明确地看出JESD207接口的DIQ端口被正确地推断为IOBUF。

        不管用BIDIR还是用BIDIR_CLKED都可以综合得出以上结果。        

        芯片综合工具通常也提供查看综合后电路的功能,可以以相同的方式进行直接确认。

参考文献

[1] Tristates • Vivado Design Suite User Guide: Synthesis (UG901) 

标签:tri,directional,OE,端口,bi,diq,WIDTH,双向,DIQ
From: https://www.cnblogs.com/amxiang/p/16995221.html

相关文章