双向数据总线设计

Jak*_*obJ 5 vhdl

我需要通过双向数据总线(ULPI)与芯片通信.

据我所知,数据在时钟上升沿上在ULPI总线上移出,并在下降时钟边沿读取.我的问题是,当读取寄存器时,我首先需要对上升沿敏感(将命令写入数据总线上的芯片),然后在从芯片读取寄存器输出到总线时下降沿.

我不清楚如何设计这个最好的方法.

我尝试了一个有一个case语句的进程,但为了这个工作,我的进程需要对上升和下降边缘敏感,我认为这不好.或者它确实可以吗?

Jos*_*osh 5

通常通过使用三态缓冲器来实现双向总线.当三态缓冲器输出为"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)