首页 > 解决方案 > VHDL:端口什么时候可以用作信号?

问题描述

请帮助我了解何时可以将端口用作 VHDL 中的信号。

我问这个问题是因为我在 Xilinx ISim 中使用端口将数据从一个组件移动到另一个组件,但数据在其目的地仍未定义。如果我在下面的第一个和第三个示例中通过连接端口到端口来推断数据传输而没有明确的赋值语句,则可能会导致我的问题。

我相信这是有效使用实体的端口作为连接到包含组件端口的信号。

-- Example 1 - Use ports instead of signals
entity user is
  port(
    data_bus   : inout std_logic_vector(15 downto 0);
    address_bus: in    std_logic_vector(12 downto 0)
  );
end user;    
architecture Behavioral of user is
  -- Component Port Definitions
  component memory
    port(
    mem_data_bus   : inout std_logic_vector(15 downto 0);
    mem_address_bus: in    std_logic_vector(12 downto 0)
    );
  end component memory;
begin
  -- some logic
  -- Instantiate thing
  a_memory : memory
    port map(
      mem_data_bus     => data_bus,
      mem_address_bus  => address_bus
    );
end architecture;

我不确定这是否有效。将组件连接在一起是否需要额外的信号,或者是否可以使用实体端口?(我意识到将 inout 端口连接在一起可能会出现问题,但这个问题是关于何时可以将端口用作信号)。

-- Example 2 - connect ports to multiple components
entity user is
  port(
    data_bus   : inout std_logic_vector(15 downto 0);
    address_bus: in    std_logic_vector(12 downto 0)
  );
end entity user;
architecture Behavioral of user is
  -- Component Port Definitions
  component memory_a
    port(
    ma_data_bus   : inout std_logic_vector(15 downto 0);
    ma_address_bus: in    std_logic_vector(12 downto 0)
    );
  end component memory_a;
  component memory_b
    port(
    mb_data_bus   : inout std_logic_vector(15 downto 0);
    mb_address_bus: in    std_logic_vector(12 downto 0)
    );
  end component memory_b;
begin
  -- some logic
  -- Instantiate memories
  a_memory_a : memory_a
    port map(
      ma_data_bus     => data_bus,       
      ma_address_bus  => address_bus
    );
  a_memory_b : memory_b
    port map(
      mb_data_bus     => data_bus,
      mb_address_bus  => address_bus 
    );
end architecture

如果实体端口定义不包括端口,则需要信号并且不能从端口推断。

-- Example 3 - Use signals for inteconnection as no suitable ports available
entity user is
end user;

architecture Behavioral of user is
  -- Component Port Definitions
  component memory_a
    port(
    data_bus   : inout std_logic_vector(15 downto 0);
    address_bus: in    std_logic_vector(12 downto 0)
    );
  end component memory_a;
  component memory_b
    port(
    data_bus   : inout std_logic_vector(15 downto 0);
    address_bus: in    std_logic_vector(12 downto 0)
    );
  end component memory_b;
  signal data_bus_sig  : std_logic_vector(15 downto 0);
  signal address_bus_sig  : std_logic_vector(12 downto 0);
begin
  -- some logic
  -- Instantiate memories
  a_memory_a : memory_a
    port map(
      data_bus     => data_bus_sig,
      address_bus  => address_bus_sig
    );
  a_memory_b : memory_b
    port map(
      data_bus     => data_bus_sig,
      address_bus  => address_bus_sig 
    );
end architecture

这是错误的,因为既没有定义信号也没有定义实体端口。

-- Example 4 - WRONG? - Try to infer ports
entity user is
end user;

architecture Behavioral of user is
  -- Component Port Definitions
  component memory_a
    port(
    data_bus   : inout std_logic_vector(15 downto 0);
    address_bus: in    std_logic_vector(12 downto 0)
    );
  end component memory_a;

  component memory_b
    port(
    data_bus   : inout std_logic_vector(15 downto 0);
    address_bus: out   std_logic_vector(12 downto 0)
    );
  end component memory_b;
begin
  -- some logic
  -- Instantiate memories
  a_memory_a : memory_a
    port map(
      data_bus     => data_bus,  
      address_bus  => address_bus
    );
  a_memory_b : memory_b
    port map(
      data_bus     => data_bus,  
      address_bus  => address_bus
    );
end architecture

标签: vhdlfpgaxilinx-ise

解决方案


我将您的示例代码称为 1、2、3 和 4。

1) 例 1 是正确的。这是一种以分层方式连接端口的可行方式。

2)肯定会出现编译/综合错误,特别是对于输出端口。实际上,您将有多个驱动程序(实例化组件的每个输出端口)影响顶级实体的同一信号/端口。在模拟中也很容易看到,因为您会看到“X”出现在该端口(表示多个驱动程序对同一信号)。请注意,多个输入端口可以连接到单个驱动程序(例如顶级实体的相同输入端口,相同信号等......)

3) 部分正确!您遇到与示例 2 相同的问题,多个驱动程序作用于同一信号。

4)这绝对是错误的!您尚未定义要绑定的端口和信号

实体更改后更新:

1)还是正确的,实体端口可以通过这种方式作为(隐式)信号。您可以将顶部实体想象为 2 个子组件的容器,您将组件的引脚“焊接”到顶部实体/容器的引脚(焊接材料提供电气连续性)

2) 当 inout 端口用作输入时,这可能没问题,但是当您尝试将 then 用作输出时,可能会出现问题。对它们的组件的描述方式有很大的依赖性。如果组件使用弱逻辑值(“L”和“H”),那么如果您驱动强值(“0”和“1”),那么它可能表现正常。最好使用中间信号端(可能是某种多路复用器/解复用器)来选择/引导数据进出正确的内部组件。

3)从纯互连的角度来看,这是可以的。但是,从功能的角度来看,您必须确保始终有一个组件充当驱动程序,另一个充当接收器。否则,由于多个驱动程序,您将在内部信号或“X”上有未定义的值。但是,对于地址信号,没有人在驱动它,所以它总是'U'(未定义)。您需要一些东西(顶级实体中的端口、进程等......)这会在其上驱动某种价值。

4)和以前一样,这是不正确的。组件的端口没有连接。请注意,VHDL(但同样适用于 verilog)是一种描述语言;您尝试描述一个实际的电路(例如由 PCB 上的芯片制成的电路)。就像在实际电路中,您需要某种电线将芯片的一个引脚连接到另一个 IC 中的另一个引脚,然后在 VHDL/verilog 中,您也需要一个等效的“对象”来启用互连。因此,您需要定义对象(在本例中为信号),然后描述其行为(在本例中将 2 个组件的 2 个端口绑定在一起)。

我希望这次更清楚一点


推荐阅读