在 FPGA 设计开发中, 很多场合会遇到同一根信号既可以是输入信号, 又可以是输出信号, 即 IO 类型 (Verilog 定义成 inout).
对于 inout 型的信号, 我们既可以使用 FPGA 原语来实现, 也可以使用 Verilog 代码来实现. 下面将介绍在 Xilinx 7 系列 FPGA 上两种实现方式的差别和注意点.
不管哪种方式实现 IO 功能, 从编译结果看都会调用 IOBUF 原语, 为此, 我们先来看一下 IOBUF 的结构, 如下图所示.
1.FPGA 原语实现
首先, 我们编写的代码如下:
- `define PRIMITIVE
- module io_buf(
- input T ,
- input I ,
- output O ,
- inout IO
- );
- `ifdef PRIMITIVE
- 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 ), // Buffer output
- .IO (IO ), // Buffer inout port (connect directly to top-level port)
- .I (I ), // Buffer input
- .T (T ) // 3-state enable input, high=input, low=output
- );
- `else
- assign IO = T? I:1'bz;
- assign O = IO;
- `endif
- endmodule
该代码通过原语 IOBUF 实现 IO 功能, 使用 Vivado 编译后的原理图如下图所示. 可以看到 IOBUF 内部由 OBUFT 和 IBUF 原语构成.
2. 使用 Verilog 实现
把 `define PRIMITIVE 注释掉, 则为通过 Verilog 的实现方式, 如下图:
- //`define PRIMITIVE
- module io_iobuf(
- input T ,
- input I ,
- output O ,
- inout IO
- );
- `ifdef PRIMITIVE
- 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 ), // Buffer output
- .IO (IO ), // Buffer inout port (connect directly to top-level port)
- .I (I ), // Buffer input
- .T (T ) // 3-state enable input, high=input, low=output
- );
- `else
- assign IO = T? I:1'bz;
- assign O = IO;
- `endif
- endmodule
该代码使用 Vivado 编译后的原理图如下图所示. 该实现方式也会调用 IOBUF 原语, 但多消耗了一个 LUT 资源.
通过 Verilog 实现时, 我们在把 IO 信号当成输入时给赋值高阻态 (1'bz). 假如我们把此时的 IO 信号赋值 1'b0 或者 1'b1, 会出现什么情况呢? 我们把 1'bz 写成 1'b1, 如下所示:
- //`define PRIMITIVE
- module io_iobuf(
- input T ,
- input I ,
- output O ,
- inout IO
- );
- `ifdef PRIMITIVE
- 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 ), // Buffer output
- .IO (IO ), // Buffer inout port (connect directly to top-level port)
- .I (I ), // Buffer input
- .T (T ) // 3-state enable input, high=input, low=output
- );
- `else
- assign IO = T? I:1'b1;
- assign O = IO;
- `endif
- endmodule
编译后的原理图如下, 可以看到并不会调用 IOBUF 原语, IO 的不能实现输入功能, 这就是解释了为什么在使用 Verilog 实现一根信号的 IO 功能时需要赋值 1'bz.
来源: https://www.cnblogs.com/lai-jian-tao/p/12143866.html