VHDL coding tips and tricks: VHDL: What are BIT, STD_ULOGIC and STD_LOGIC data types?

Tuesday, March 9, 2010

VHDL: What are BIT, STD_ULOGIC and STD_LOGIC data types?

THIS BLOG POST WAS UPDATED ON 5th MAR 2024!

BIT:

The Bit type is predefined in the Standard package as an enumerated data type with only two allowable values: '0' and '1'. 

Since it has only two possible values, it can be used to represent logical values but not 'Z', 'U' etc...

Signals of the bit type are NOT resolved.

Since its defined in the standard VHDL package, it can be used without declaring any additional libraries. 

Example:
signal my_bit_signal : bit;

STD_ULOGIC:

STD_ULOGIC is an unresolved enumerated data type defined in the std_logic_1164 library. Its defined as:

     TYPE std_ulogic IS ('U',  -- Uninitialized
                         'X',  -- Forcing  Unknown
                         '0',  -- Forcing  0
                         '1',  -- Forcing  1
                         'Z',  -- High Impedance   
                         'W',  -- Weak     Unknown
                         'L',  -- Weak     0       
                         'H',  -- Weak     1       
                         '-'   -- Don't care
                       );

As you can see it can hold 9 types of values.

    STD_ULOGIC is classified as unresolved because it lacks a resolution function that can determine which driver supersedes the others. Consequently, signals of this type cannot be driven by multiple sources simultaneously. Attempting to do so will prompt the compiler to detect the issue and prevent simulation of the design altogether.

    It's advisable to declare a signal as STD_ULOGIC when you're confident that the signal isn't driven by multiple sources simultaneously. This practice aids in early error detection during the coding phase, sparing the need for extensive simulation and detailed debugging later on.

Example:
signal my_signal : std_ulogic;

STD_LOGIC:

Similar to STD_ULOGIC, STD_LOGIC is defined within the std_logic_1164 library. However, it serves as the resolved counterpart to STD_ULOGIC. Its defined as:

subtype std_logic is resolved std_ulogic;

It can also hold 9 values : 'U', 'X', '0', '1', 'Z', 'W', 'L' ,'H' and '-'.

What does resolved mean?

A resolve is needed, whenever there is a conflict between two or more things, in this case the sources which drive a particular signal. 

Whenever two or more sources drive a single STD_LOGIC signal, the resolution function is called in order to avoid this conflict.

Example:
signal my_signal : std_logic;

Now, let's delve into the intricacies of the resolution function. The following code snippet is copied from std_logic_1164.vhd package file. This will help us see how std_logic is resolved from std_ulogic.

-------------------------------------------------------------------    
    -- resolution function
    -------------------------------------------------------------------    
    CONSTANT resolution_table : stdlogic_table := (
    --      ---------------------------------------------------------
    --      |  U    X    0    1    Z    W    L    H    -        |   |  
    --      ---------------------------------------------------------
            ( 'U', 'U', 'U', 'U', 'U', 'U', 'U', 'U', 'U' ), -- | U |
            ( 'U', 'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X' ), -- | X |
            ( 'U', 'X', '0', 'X', '0', '0', '0', '0', 'X' ), -- | 0 |
            ( 'U', 'X', 'X', '1', '1', '1', '1', '1', 'X' ), -- | 1 |
            ( 'U', 'X', '0', '1', 'Z', 'W', 'L', 'H', 'X' ), -- | Z |
            ( 'U', 'X', '0', '1', 'W', 'W', 'W', 'W', 'X' ), -- | W |
            ( 'U', 'X', '0', '1', 'L', 'W', 'L', 'W', 'X' ), -- | L |
            ( 'U', 'X', '0', '1', 'H', 'W', 'W', 'H', 'X' ), -- | H |
            ( 'U', 'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X' )  -- | - |
        );

        
    FUNCTION resolved ( s : std_ulogic_vector ) RETURN std_ulogic IS
        VARIABLE result : std_ulogic := 'Z';  -- weakest state default  
    BEGIN
        -- the test for a single driver is essential otherwise the
        -- loop would return 'X' for a single driver of '-' and that
        -- would conflict with the value of a single driver unresolved
        -- signal.
        IF    (s'LENGTH = 1) THEN    RETURN s(s'LOW);
        ELSE
            FOR i IN s'RANGE LOOP
                result := resolution_table(result, s(i));
            END LOOP;
        END IF;
        RETURN result;
    END resolved;

The resolution_table meticulously handles all combinations of source values to ensure assigning a single final value to the signal.

Should I be using std_logic or std_ulogic?

    There is no definite answer to this question. Std_logic is well-suited for general-purpose digital signal modeling, where a single signal may be driven by multiple drivers. In those cases, we need a resolution function which the std_logic provides. 

On the other hand, std_ulogic finds its place in designs, where avoiding conflicts during simulation takes precedence and multiple driver resolution isn't necessary.

In most simple cases its okay to use std_logic, but just be aware of the nuances hidden behind your decision. 

I hope this discussion has shed light on your uncertainties regarding this topic. Feel free to share your thoughts in the comments section below.

1 comment:

  1. Good explanation ;)
    So, when you use std_logic type, it's easier to detect multisourced signal and correct if it needs to be corrected (it appears red in modelsim wave window by example).

    ReplyDelete