通常通过使用三态缓冲器来实现双向总线.当三态缓冲器输出为"Z"时,您可以从inout端口读取,当缓冲器驱动线路时,它充当输出.在VHDL中,这可以通过直接实例化原语(例如,IOBUF用于Xilinx器件),或通过让您的综合工具通过描述如上所述的逻辑来推断三态缓冲器来实现.
您在这里处理3个信号:
T这是你的三态控制.知道ULPI的协议,该信号将从您的同步逻辑中获得.那是因为总线是共享的,必须有一些方法可以知道何时应该接收数据而不是发送数据.I 这是您希望通过适当的时钟注册后通过总线发送的输入数据.O 这是您在任何注册/同步之前通过总线接收的输出数据.密钥:三态缓冲区不同步.这是你在三态缓冲器之前/之后做的,它将正确地同步你的信号.在这种情况下,必须在上升时钟边沿将输入同步到三态缓冲器(待发送),并在下降时钟沿同步从三态缓冲器/ IOBUF接收的寄存数据.
样本设计.
library ieee;
use ieee.std_logic_1164.all;
library unisim; -- for xilinx IOBUF
use unisim.vcomponents.all;
entity iobuffer_example is
port (
I_CLK : in std_logic; -- synchronized with bidir bus
IO_DATA : inout std_logic; -- data to/from external pin on bidir bus
I_DIR_CTRL : in std_logic; -- from other VHDL logic, controlling bidir bus direction
O_DATA_FROM_EXTERNAL : out std_logic; -- data received over bidir bus
I_DATA_TO_EXTERNAL : in std_logic); -- data to send over bidir bus
end entity iobuffer_example;
architecture io_buffer_arch of iobuffer_example is
signal data_in : std_logic;
signal data_out : std_logic;
begin
IOBUF_Inst : IOBUF
port map (
O => data_in, -- data from bidir bus
IO => IO_DATA, -- data on bidir bus
I => data_out, -- data to bidir bus
T => I_DIR_CTRL); -- 3-state enable input, high=input, low=output
Register_Input : process (I_CLK) is
begin
if (falling_edge(I_CLK)) then
O_DATA_FROM_EXTERNAL <= data_in;
end if;
end process Register_Input;
Register_Output : process (I_CLK) is
begin
if (rising_edge(I_CLK)) then
data_out <= I_DATA_TO_EXTERNAL;
end if;
end process Register_Output;
end architecture io_buffer_arch;
Run Code Online (Sandbox Code Playgroud)
笔记.
注意跨时钟域的交叉.这里有许多可能的交叉点用于数据流出和来自总线,特别是如果你的内部逻辑是在与总线时钟不同的时钟上驱动的话.没有更多细节,我无法提出建议.
如果你想通过综合工具推断三态缓冲区的行为表示,你可以做这样的事情,而不是使用unisim库和IOBUF:
PROCESS (I_DIR_CTRL, IO_DATA)
BEGIN
IF( I_DIR_CTRL = '1') THEN
IO_DATA <= 'Z';
ELSE
IO_DATA <= data_out;
END IF;
data_in <= IO_DATA;
END PROCESS;
Run Code Online (Sandbox Code Playgroud)