我需要通过双向数据总线(ULPI)与芯片进行通信。双向数据总线设计
据我所知,数据在ULPI总线上在时钟上升沿移出,并在时钟下降沿读取。看到我的问题是,在读取寄存器时,首先需要对上升沿(将数据写入芯片的命令)和从芯片读取寄存器输出到总线上的下降沿敏感。
这给我很多麻烦,试图弄清楚如何设计最好的。
我尝试过一个有case语句的进程,但为了这个工作,我的进程需要对上升沿和下降沿都敏感,我认为这并不好?要么?
我需要通过双向数据总线(ULPI)与芯片进行通信。双向数据总线设计
据我所知,数据在ULPI总线上在时钟上升沿移出,并在时钟下降沿读取。看到我的问题是,在读取寄存器时,首先需要对上升沿(将数据写入芯片的命令)和从芯片读取寄存器输出到总线上的下降沿敏感。
这给我很多麻烦,试图弄清楚如何设计最好的。
我尝试过一个有case语句的进程,但为了这个工作,我的进程需要对上升沿和下降沿都敏感,我认为这并不好?要么?
双向总线通常通过使用三态缓冲器来实现。当三态缓冲器输出为“Z”时,您可以从inout
端口读取缓冲器驱动线路时的输出。在VHDL中,可以通过直接实例化原语(例如Xilinx器件的IOBUF
)或通过让综合工具通过如上所述的逻辑描述逻辑来推断三态缓冲器来实现。
有你在这里处理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;
注意事项。
请注意跨时钟域交叉。这里有很多可能的数据传输来自总线,特别是如果你的内部逻辑是在与总线时钟不同的时钟驱动。没有更多细节我不能提出建议。
如果你想三态缓冲器的行为表示由综合工具来推断,你可以可以做这样的事情,而不是使用新跃大学图书馆和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;
感谢的人!当场就好了。 – JakobJ 2012-08-15 20:27:46