Nigel Davies
Nigel Davies

Reputation: 1690

VHDL: When can ports be used as signals?

Please help me understand when ports can be used as signals in VHDL.

I am asking this question because I am using ports to move data from one component to another in Xilinx ISim, but the data remains undefined at it's destination. My problems could be caused if I am inferring data transfer by wiring port to port as in my first and third examples below without an explicity assignment statement.

I believe this is valid use of a ports from the entity as a signals wired to the ports of an included component.

-- 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;

I am not sure this is valid. Are extra signals required to wire components together or can the entity ports be used? (I realise there could be a problem joining to inout ports together, but this question is about when ports can be used as signals).

-- 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

If the entity port definition does not include the ports, signals are required and cannot be inferred from ports.

-- 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

This is wrong because neither signals nor entity ports are defined.

-- 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

Upvotes: 2

Views: 2167

Answers (1)

Jackkilby
Jackkilby

Reputation: 162

I will refer to your example codes as 1, 2 3 and 4.

1) Example 1 is correct. This is a viable way to connect port in a hierarchical way.

2) For sure you will have compilation/synthesis errors in particular for the output ports. In fact you will have multiple drivers (each of the out ports of the instantiated components) impacting on the same signal/port of the top entity. It will be easy to see in a simulation too, since you will see 'X's appear at that port (indicating multiple driver to the same signal). Please note that multiple input ports can be connected to a single driver (e.g. same input port of top entity, same signal, etc...)

3) It is partially correct! You have the same issue as in example 2 with the multiple drivers acting on the same signal.

4) This is definitely wrong!. You have not defined neither ports nor signals to be bonded to

UPDATE after changes in entity:

1) It is still correct, entity port can be used as (implicit) signal in this way. You can imagine the top entity just as a container for the 2 sub-component where you have "soldered" the pin of the components to the pins of the top-entity/container (the soldering material provides the electrical continuity)

2) This might be OK when the inout ports are used as input, but when you try to use then as outputs, there might be issues. There is a heavy dependency on how they component are described. If the components use weak logic values ('L' & 'H') then if you drive strong values ('0' & '1') then it might behave OK. It would be better to use intermediate signal end probably some sort of mux/demux to select/steer the data to/from the proper internal component.

3) From the pure interconnect point of view, this is OK. However, from the functional point of view you have to be sure that there is always on component that is acting as a driver and the other as a receiver. Otherwise you will have either undefined value on the internal signal or 'X' due to multiple drivers. However, for the address signal, no one is driving it, so it will be always 'U' (undifined). You need something (a port in top entity, a process, etc...) this si driving some kind of value on it.

4) As before, this is incorrect. The port of the component are connected to nothing. Please note that VHDL (but the same is valid for verilog) is a description language; you try to describe an actual circuit (like one made of chips on a PCB). Like in a real circuit you need some sort of wire to connect one pin of a chip to another pin in another IC, then also in VHDL/verilog you need an equivalent "object" to enabel the interconnection.Thus, you need to define the object (in this case the signal) and then describe its behavior (in this case bind together 2 ports of 2 components).

I hope this time is a bit clearer

Upvotes: 1

Related Questions