TA的每日心情 | 开心 2021-12-31 09:03 |
---|
高级会员
- 积分
- 976
|
在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 : 1'bz ;
- assign O_data_out = IO_data ;
- endmodule
复制代码
1、 当Control为1时,IO_data为输出,输出I_data_in的值。
2、 当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、 在vivado中,可以采用例化原语的方法
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
);
|
|