All previously discussed signal assignments were assumed to have a single driver for each signal. In order to describe such hardware structures as (bidirectional) buses, wired-or, wire-and, and so on, special mechanisms, known as resolution functions, are used.
In general, VHDL was not designed to handle signals with multiple drivers. The reason is that either wired-or, wired-and or some other logical behavior is produced depending on the employed circuit implementation methodology. Therefore, it was assumed that a vendor is responsible to deliever required packages with multi-valued logic type declarations and corresponding resolution functions.
There are, however, methods to deal with situations when several drivers are driving a signal. To have multiple drivers usually means that a signal is assigned concurrently by parallel processes, concurrent signal assignments, concurrent procedure calls, and so on.
Syntax:
subtype subtype_name is resolution_func_name type_name;
With this approach, when a signal assignment of type subtype_name happens, an associated function, which determines
the final signal value, is implicitly called.
Analogous to the subtype, a resolved signal can also be declared as: signal_name : resolution_func_name type_name;
as usual: | |
- | arguments are of the input mode and are passed by value. |
- | a function returns only one value. |
additional features of resulution functions: | |
- | an array of variable length with elements of the type type_name is passed as the function argument. |
- | the return value of the function is of the original type: type_name. |
- | the function is associated with a subtype; the function is called every time a signal of this type is assigned. |
In the following example, a wired-or resolution function with a four-value data type is described. A tristate driver is modeled by two processes which write to the same output signal.
Example:
-- 4-value type and the corresponding array type for the function --
type BIT4 is ('X', '0', '1', 'Z');
type BIT4_VECTOR is array (integer range <>) of BIT4;
-- resulution function --
function WIRED_OR (INP: BIT4_VECTOR) return BIT4 is
variable RESULT: BIT4 := '0'; result, bus with a pull-down
begin
for I in INP'range loop for each input
if INP(I) = '1' then
RESULT := '1';
exit; jump out of the loop
elsif INP(I) = 'X' then
RESULT := 'X';
else null; INP(I) = 'Z' or = '0'
end if;
end loop;
return RESULT;
end WIRED_OR;
-- subtype with the resolution function --
subtype RESOLVED_BIT4 is WIRED_OR BIT4;
...
architecture BEHAVE of TRISTATE is
signal ASEL, BSEL: boolean; select signals
signal SIGA, SIGB: BIT4; inputs
signal SIGS: RESOLVED_BIT4; resolved output signal
begin
SOURCE1: process (ASEL, SIGA) first output source
begin
SIGS <= 'Z';
if (ASEL) then
SIGS <= SIGA;
end if;
end process;
SOURCE2: process (BSEL, SIGB) second output source
begin
SIGS <= 'Z';
if (BSEL) then
SIGS <= SIGB;
end if;
end process;
end BEHAVE;
![]() |
The STD_LOGIC_1164
package defines resolution functions for
std_logic
data types. Types std_logic
/
std_logic_vector
, which implicitly have resolution functions,
are subtypes of std_ulogic
/ std_ulogic_vector
( unresolved).
The following example illustrates modeling of bidirectional buses. Here is the description of a 4-bit bus driver/receiver.
Example:
library IEEE;
use IEEE.std_logic_1164.all;
entity BUSIO is
port( OEN: in std_logic;
IBUS: in std_logic_vector (3 downto 0);
OBUS: out std_logic_vector (3 downto 0);
IOBUS: inout std_logic_vector (3 downto 0));
end BUSIO;
architecture BEHAV of BUSIO is
begin
P: process (OEN, IBUS, IOBUS)
begin
if (OEN = '1') then drive bus
IOBUS <= IBUS;
else read bus
IOBUS <= "
ZZZZ"
; explicit assignment of 'Z'
end if;
OBUS <= IOBUS;
end process;
end BEHAV;