1. 程式人生 > >【設計經驗】1、如何規範的處理inout信號

【設計經驗】1、如何規範的處理inout信號

spi 輸出 def 出現 inf 結果 中一 就是 rate

  在FPGA的設計過程中,有時候會遇到雙向信號(既能作為輸出,也能作為輸入的信號叫雙向信號)。比如,IIC總線中的SDA信號就是一個雙向信號,QSPI Flash的四線操作的時候四根信號線均為雙向信號。在Verilog中用關鍵字inout定義雙向信號,這總結一下雙向信號的處理方法。

  實際上,雙向信號的本質是由一個三態門組成的,三態門可以輸出高電平,低電平和高阻態三種狀態,在FPGA中,一個三態門的結構如下圖所示:

    技術分享圖片

  描述這個邏輯的Verilog代碼如下:

module inout_top
(
input       I_data_in        ,
inout       IO_data          ,
output O_data_out , input Control ); assign IO_data = Control ? I_data_in : 1bz ; assign O_data_out = IO_data ; endmodule

  當Control為1時,IO_data為輸出,輸出I_data_in的值

  當Control為0時,IO_data為輸入,把輸入的信號賦值給O_data_out

  這段代碼在Vivado2015.4.2編譯環境下的RTL圖如下圖所示

技術分享圖片

  在ISE14.7的編譯環境下的RTL圖如下圖所示

  技術分享圖片

  可以發現在Vivado2015.4.2環境的Control信號的IBUF後面居然還綜合出了一個LUT,在ISE14.7環境下Control信號後面綜合出了一個反向器,出現這個LUT和反向器的原因是Control為1才把IO_data設置成輸出,而在Xilinx中一個IOBUF資源默認T端為0時IO端才為輸出,T端為1時,IO端為輸入,所以把

  assign IO_data = Control ? I_data_in : 1‘bz ;

  改為

  assign IO_data = (Control == 1’b0) ? I_data_in : 1‘bz ;

  在Vivado2015.4.2環境下綜合出的RTL圖為下圖

  技術分享圖片

  在ISE14.7的環境下綜合出的RTL圖如下圖所示

  技術分享圖片

  顯然,Vivado環境中LUT和ISE環境中的反相器不見了,節省了1個Cell資源。

  以上是處理inout的第一種方法,第二種處理inout信號的方法是調用Xilinx的IOBUF原語,IOBUF的原語可以在Vivado2015.4.2的Language Templates中找到

  技術分享圖片

  調用這個原語的Verilog代碼如下:

module inout_top
(
input   I_data_in,
inout   IO_data  ,
output  O_data_out  ,
input   Control
);

IOBUF #(
  .DRIVE(12), // Specify the output drive strength
  .IBUF_LOW_PWR("TRUE"),  // Low Power - "TRUE", High Performance = "FALSE"
  .IOSTANDARD("DEFAULT"), // Specify the I/O standard
  .SLEW("SLOW") // Specify the output slew rate
) IOBUF_inst (
  .O(O_data_out),     // Buffer output
  .IO(IO_data),   // Buffer inout port (connect directly to top-level port)
  .I(I_data_in),     // Buffer input
  .T(Control)      // 3-state enable input, high=input, low=output
);

endmodule

  在Vivado2015.4.2環境下綜合出的RTL圖如下圖所示

  技術分享圖片

  在ISE14.7環境下綜合出的RTL圖如下圖所示

  技術分享圖片

  顯然和 assign IO_data = (Control == 1’b0) ? I_data_in : 1‘bz ;這種情況下綜合出的RTL完全一樣。

總結,利用Verilog處理雙向信號有兩種方式:

  1、寫代碼

    assign IO_data = (Control == 1’b0)? I_data_in : 1‘bz ;

    assign O_data_out = IO_data ;

  2、例化IOBUF原語

    IOBUF #(

     .DRIVE(12), // Specify the output drive strength

    .IBUF_LOW_PWR("TRUE"), // Low Power - "TRUE", High Performance = "FALSE"

    .IOSTANDARD("DEFAULT"), // Specify the I/O standard

    .SLEW("SLOW") // Specify the output slew rate

    ) IOBUF_inst (

    .O(O_data_out), // Buffer output

    .IO(IO_data), // Buffer inout port (connect directly to top-level port)

     .I(I_data_in), // Buffer input

    .T(Control) // 3-state enable input, high=input, low=output

    );

題外話:

  最近調一套代碼,代碼是前輩寫的,之前都是用ISE開發,那套代碼用ISE編譯出的bit文件可以正常運行,但是最新的項目由於要添加更多的功能,所以選用了K7系列的FPGA,在Vivado下開發,結果發現原來正常運行的代碼在Vivado下就不能運行了,通過反復檢查與定位,發現原來的那套代碼對inout信號的處理十分不規範,而且沒有加Control這個控制信號來控制inout的方向,直接想當然的作為輸入或者輸出來使用。最後我們把inout信號全部采用上面兩種規範的處理方法處理以後,代碼正常運行。所以平時在設計的過程中一定要多註意細節,力求規範。

歡迎關註我的公眾號:FPGA之禪

技術分享圖片

【設計經驗】1、如何規範的處理inout信號