Search code examples
arraysvhdlrecordmultiprocesssynthesis

Multiple processes driving an array of records


The following code showcases an array of records. The particularity is that for each element of the array, the field AR is driven by the process process_AR while the field R is driven by the process process_R.

library ieee;
use     ieee.std_logic_1164.all;
use     ieee.numeric_std.all;

entity test_entity is
end entity;

architecture RTL of test_entity is

    -- Try with std_ulogic_vector or std_logic_vector
    subtype slv is std_logic_vector;
    subtype stdl is slv'element;

    type AR_record_t is record
        valid : stdl;
        addr : slv(15 downto 0);
    end record;

    type R_record_t is record
        ready : stdl;
        data : slv(31 downto 0);
    end record;

    type axil_record_t is record
        AR : AR_record_t;
        R  : R_record_t;
    end record;

    type array_of_axil_record_t is array(natural range <>) of axil_record_t;
    signal axil_read_channel : array_of_axil_record_t(0 to 1);

begin

    -- Process only deal with the AR channel
    process_AR : process
    begin
        wait for 20 ps;
        axil_read_channel(0).AR <= (valid => '1', addr => X"CAFE");
        axil_read_channel(1).AR <= (valid => '0', addr => X"DEAD");
    end process;

    -- Process only deal with the R channel
    process_R : process
    begin
        wait for 20 ps;
        axil_read_channel(0).R <= (ready => '0', data => X"12345678");
        axil_read_channel(1).R <= (ready => '1', data => X"89ABCDEF");
    end process;
end architecture;

This code works as (I) expected. Waveform, first code However, change the process_AR by the following (using a for loop now):

-- Process only deal with the AR channel
process_AR : process
begin
    wait for 20 ps;
    for i in axil_read_channel'range loop
        axil_read_channel(i).AR <= (valid => '1', addr => X"CAFE");
    end loop;
end process;

When using non-resolved types (std_ulogic and std_ulogic_vector), this new code fails:

(vsim-3344) Signal "/test_entity/axil_read_channel(0).R.ready" has multiple drivers but is not a resolved signal.

I guess the for loop does not work because the it is sort of a 'dynamical' assignment and therefore axil_read_channel is considered instead of axil_read_channel(i) ? On the other hand, the first version of the code (with hard coded '0' and '1') uses sort of 'static' assignment and therefore considers the two elements axil_read_channel(0) and axil_read_channel(1) as two signals and not element of an array ?

When using resolved types (std_logic and std_logic_vector): Waveform, second code, when using non-resolved types (std_logic and std_logic_vector)

What is the reason behind the difference of behavior between the first code and second code ?

Is there a work around not involving for-generate (not applicable to my current design) for synthesis ?


Solution

  • When you use a loop in a process to drive a signal of a composite type (array or record), the elaboration cannot determine which specific objects require a driver at elaboration time, hence it has to assume all objects within the composite type require a driver. This then creates a driver for the entire array/record, rather than each element that would have occured without the loop.

    This is what is causing your error when you use resolved/unresolved types. The errors occurs with the unresolved types std_ulogic(_vector) because they are not allowed multiple drivers. The resolved types std_logic(_vector) are allowed multiple drivers and all of the elements undriven by you will have 'U' driven on them.