【问题标题】:Bidirectional databus design双向数据总线设计
【发布时间】:2012-08-15 13:06:09
【问题描述】:

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

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

我不清楚如何设计这个最好的方式。

我尝试了一个具有 case 语句的进程,但要使其工作,我的进程需要对上升沿和下降沿都敏感,我认为这不好。还是真的没问题?

【问题讨论】:

    标签: vhdl


    【解决方案1】:

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

    备注。

    注意跨时钟域交叉。这里有许多可能的数据输出和来自总线的交叉,特别是如果您的内部逻辑驱动在与总线时钟不同的时钟上。如果没有更详细的信息,我无法提出建议。

    如果您希望综合工具推断出三态缓冲区的行为表示,您可以这样做,而不是使用 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;
    

    【讨论】:

      【解决方案2】:

      我知道这是一篇非常古老的文章,但我的评论是针对想要连接/实施 ULPI 的人。在 ULPI 中没有三态数据缓冲区。 如果您想了解如何在 ULPI 中实现传输/传输,请阅读“ULPI 接口规范”中的第 2.3.1 章总线所有权。

      如果您在接受的答案中编写 vhdl,您的代码将不会一直有效。您必须注意的一些事项是:

      • 转身循环
      • 中止数据

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-07-11
        • 1970-01-01
        • 2020-09-11
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多