我想询问是否可以使用inout引脚作为inout和normal out?这两种行为应该通过MUX切换。这种奇怪的实现的原因是我有两个板,我想使用相同的比特流。在一块电路板上,相同的引脚通过GPIO连接到LED,另一块连接到I2C总线连接。软件尝试检测I2C,如果成功则设置寄存器。如果没有,它会清除它。
LED_or_SDA : inout std_logic; -- port definition
process (register)
begin
if ( register = '1') then -- software sets this register
LED_or_SDA <= I2C_SDA; -- here I want to use it as inout
else
LED_or_SDA <= gpio_reg; -- here I want to use it as normal out
end if;
end process;
此实现会抛出错误&#34; bidirect pad net正在驱动非缓冲原语&#34;在翻译期间。有解决方案吗?
答案 0 :(得分:0)
不,你不能。多路复用器不是开关,它是逻辑功能。这条线
LED_or_SDA <= I2C_SDA;
从LED_or_SDA
强烈推动I2C_SDA
。它不以允许双向数据流的方式连接两个网络。
您需要将两个方向分开:
I2C_SDA_in <= LED_or_SDA;
LED_or_SDA <= gpio_reg WHEN (register = '1') ELSE
'0' WHEN (I2C_SDA_out = '0') ELSE
'Z';
大多数I2C逻辑块无论如何都有单独的数据输入和输出信号,直到外部接口,在那里你找到一个三态缓冲区,其表达方式与我给你的代码大致相同。您只需要在I2C模块上将输入和输出数据分开设置。
不幸的是,内部信号的弱驱动状态可能不可以被内部逻辑访问,所以这些不会工作:
LED_or_SDA <= gpio_reg WHEN (register = '1') ELSE
I2C_SDA_out;
LED_or_SDA <= gpio_reg WHEN (register = '1') ELSE
'Z' WHEN (I2C_SDA_out = 'Z') ELSE
I2C_SDA_out;
VHDL编译器实际上是跟踪三态控制信号,并通过端口语句传播,直到它到达外部引脚并将其连接到实际(硬件)三态缓冲器。但是在大多数编译器中,您无法为自己的逻辑访问该控制信号。
答案 1 :(得分:0)
根据您的错误消息猜测我假设我们正在谈论Xilinx系统,例如:围绕Microblaze - 如果不是这样,请更新您的问题,并指定您正在使用的确切GPIO核心。
默认情况下,这些GPIO块通常已包含IO缓冲区宏。该IOBUF位于物理引脚旁边,无法驱动FPGA上的任何其他信号。因此,GPIO模块旨在用于芯片的顶层,并直接连接到引脚。但是,通常还有一种方法可以在IOBUF之前访问信号:例如。在Xilinx Platform Studio的“端口”选项卡上,您可以选择使用GPIO_IO
(缓冲后),GPIO_IO_I
(纯输入),GPIO_IO_O
(纯输出),{{ 1}}(三态)或类似的。
答案 2 :(得分:0)
是的,诀窍是将它始终视为三态缓冲区,并根据寄存器状态控制输出
-- define a tristate pin the usual way.
LED_or_SDA <= LED_or_SDA_out when LED_or_SDA_tristate = '0' else 'Z';
LED_or_SDA_in <= LED_or_SDA
-- then control the data onto it, and the tristate control line
LED_or_SDA_tristate <= '0' when register = '0' else ICD_SDA;
LED_or_SDA_out <= gpio_reg when register = '0' else '0';