Search code examples
typescastingvhdl

VHDL Type of xxx is incompatible with type of xxx


Ich have two different types:

type signal_4bit_t is
record
   signals_v      : STD_ULOGIC_VECTOR (3 downto 0);
end record;

 type signal_8bit_t is
record
   signals_v      : STD_ULOGIC_VECTOR (7 downto 0);
end record;

and I create two Arrays:

 type Array_signal_4bit_t   is array (0 to 2) of signal_4bit_t;
 type Array_signal_8bit_t   is array (0 to 2) of signal_8bit_t;

and one entity uses the 4bit Array as Input:

entity test_input is
    Port ( 
           hx_i      : in  Array_signal_4bit_t;
           lx_i      : in  Array_signal_4bit_t;
          );
end test;

and another uses the 8bit Array as Output:

entity test_ouput is
    Port ( 
           out_o      : out Array_signal_8bit_t
          );
end test;

For the Conncetion between the two components I use the signal:

signal tets_out_to_test_in   : Array_signal_8bit_t;

The Instantation looks like this:

in: test_input 
    Port Map ( 
           hx_i  =>    tets_out_to_test_in(7 downto 4),
           lx_i  =>    tets_out_to_test_in(3 downto 0)
          );

out: test_out 
    Port Map ( 
           out_o  =>    tets_out_to_test_in
          );

Now I get the error "Type of hx_i is incompatible with type of tets_out_to_test_in. I see that Array_signal_4bit_t is different to Array_signal_8bit_t, but is there a "easy" way to fix this problem without chanching my entites? Or any idea how I can solve this problem?


Solution

  • Creating a Minimum, Verifiable and Complete example:

    library ieee;
    use ieee.std_logic_1164.all;
    
    package somepack is
        type signal_4bit_t is
        record
           signals_v      : std_ulogic_vector (3 downto 0);
        end record;
    
         type signal_8bit_t is
        record
           signals_v      : std_ulogic_vector (7 downto 0);
        end record;
        type array_signal_4bit_t   is array (0 to 2) of signal_4bit_t;
        type array_signal_8bit_t   is array (0 to 2) of signal_8bit_t;
    end package;
    
    use work.somepack.all;
    entity test_input is
        port ( 
               hx_i      : in  array_signal_4bit_t;
               lx_i      : in  array_signal_4bit_t
             );
    end test_input;
    
    architecture foo of test_input is
    begin
    end architecture;
    
    use work.somepack.all;
    entity test_output is
        port ( 
               out_o      : out array_signal_8bit_t
             );
    end test_output;
    
    architecture foo of test_output is
    begin
    end architecture;
    
    library ieee;
    use ieee.std_logic_1164.all;
    use work.somepack.all;
    
    entity sometestbench is
    end entity;
    
    architecture foo of sometestbench is
        signal tets_out_to_test_in: array_signal_8bit_t;
        component test_input is
            port (
                hx_i: in  array_signal_4bit_t;
                lx_i: in  array_signal_4bit_t
            );
        end component;
        component test_output is
            port (
               out_o      : out array_signal_8bit_t        
            );
        end component;    
    
        signal hx_i_high: array_signal_4bit_t;
        signal lx_i_low:  array_signal_4bit_t;
    
    begin
    
        hx_i_high(0).signals_v <= tets_out_to_test_in(0).signals_v(7 downto 4);
        hx_i_high(1).signals_v <= tets_out_to_test_in(1).signals_v(7 downto 4);
        hx_i_high(2).signals_v <= tets_out_to_test_in(2).signals_v(7 downto 4);
        lx_i_low(0).signals_v  <= tets_out_to_test_in(0).signals_v(3 downto 0);
        lx_i_low(1).signals_v  <= tets_out_to_test_in(1).signals_v(3 downto 0);
        lx_i_low(2).signals_v  <= tets_out_to_test_in(2).signals_v(3 downto 0);                
    
    label_in: test_input 
        port map ( 
              --  hx_i  =>    tets_out_to_test_in(7 downto 4),
              hx_i => hx_i_high,
              --lx_i  =>    tets_out_to_test_in(3 downto 0)
              lx_i => lx_i_low
        );
    
    
    label_out: test_output 
        port map ( 
               out_o  =>    tets_out_to_test_in
              );    
    end architecture;
    

    There were various punctuation issues and spelling mismatches, in and out can't be used as identifiers (labels) they're reserved words. The component test_out should be test_output,...

    There's also a bit more direct, constructing an array_signal_4bit_t type from elements extracted from the array_signal_8bit_t type:

        hx_i_high <= array_signal_4bit_t'(
                   0 => (signals_v => tets_out_to_test_in(0).signals_v(7 downto 4)),
                   1 => (signals_v => tets_out_to_test_in(1).signals_v(7 downto 4)),
                   2 => (signals_v => tets_out_to_test_in(2).signals_v(7 downto 4))
                   );
    
        lx_i_low <= array_signal_4bit_t'(
                   0 => (signals_v => tets_out_to_test_in(0).signals_v(3 downto 0)),
                   1 => (signals_v => tets_out_to_test_in(1).signals_v(3 downto 0)),
                   2 => (signals_v => tets_out_to_test_in(2).signals_v(3 downto 0))
                   );
    

    You can't do this in the actual in the association list because the expression operand of the qualified expressions must be globally static (historically (-1993) and likely for synthesis still). (In IEEE Std 1076-2008, 6.5.6.3 Port clauses, para 6):

    If the actual part of a given association element for a formal port of a block is the reserved word inertial followed by an expression, or is an expression that is not globally static, then the given association element is equivalent to association of the port with an anonymous signal implicitly declared in the declarative region that immediately encloses the block. The signal has the same subtype as the formal port and is the target of an implicit concurrent signal assignment statement of the form

    anonymous <= E;  
    

    where E is the expression in the actual part of the given association element. The concurrent signal assignment statement occurs in the same statement part as the block.

    The above examples also make the point you don't have to have a loop.

    This MVCe analyzes, elaborates and simulates (while doing nothing particularly interesting).

    A slightly different architecture uses a procedure:

    architecture fie of sometestbench is
        signal tets_out_to_test_in: array_signal_8bit_t;
        component test_input is
            port (
                hx_i: in  array_signal_4bit_t;
                lx_i: in  array_signal_4bit_t
            );
        end component;
        component test_output is
            port (
               out_o      : out array_signal_8bit_t        
            );
        end component;    
    
        signal hx_i_high: array_signal_4bit_t;
        signal lx_i_low:  array_signal_4bit_t;
    
        procedure slice_array_signal_8bit (
                signal input:   in  array_signal_8bit_t; 
                signal low:     out array_signal_4bit_t;
                signal high:    out array_signal_4bit_t
        ) is
        begin
            for i in array_signal_4bit_t'range loop
                high(i).signals_v <= input(i).signals_v(7 downto 4);
                low(i).signals_v  <= input(i).signals_v(3 downto 0);
            end loop;
        end procedure;
    
    begin
    
    BREAKOUT: 
    slice_array_signal_8bit ( tets_out_to_test_in, hx_i_high, lx_i_low);             
    
    label_in: test_input 
        port map ( 
              hx_i => hx_i_high,
              lx_i => lx_i_low
        );
    
    
    label_out: test_output 
        port map ( 
               out_o  =>    tets_out_to_test_in
              );    
    end architecture;
    

    Which also tells us how to use a process statement:

    architecture foe of sometestbench is
        signal tets_out_to_test_in: array_signal_8bit_t;
        component test_input is
            port (
                hx_i: in  array_signal_4bit_t;
                lx_i: in  array_signal_4bit_t
            );
        end component;
        component test_output is
            port (
               out_o      : out array_signal_8bit_t        
            );
        end component;    
    
        signal hx_i_high: array_signal_4bit_t;
        signal lx_i_low:  array_signal_4bit_t;
    
    begin
    
    BREAKOUT: 
        process (tets_out_to_test_in)
        begin
            for i in array_signal_4bit_t'range loop
                hx_i_high(i).signals_v <= tets_out_to_test_in(i).signals_v(7 downto 4);
                lx_i_low(i).signals_v  <= tets_out_to_test_in(i).signals_v(3 downto 0);
            end loop;
        end process;          
    
    label_in: test_input 
        port map ( 
              hx_i => hx_i_high,
              lx_i => lx_i_low
        );
    
    
    label_out: test_output 
        port map ( 
               out_o  =>    tets_out_to_test_in
              );    
    end architecture;
    

    And finally, the simplest way:

    architecture fum of sometestbench is
        signal tets_out_to_test_in: array_signal_8bit_t;
        component test_input is
            port (
                hx_i: in  array_signal_4bit_t;
                lx_i: in  array_signal_4bit_t
            );
        end component;
        component test_output is
            port (
               out_o      : out array_signal_8bit_t
            );
        end component;
    begin
    
    label_in: test_input
        port map (
              hx_i(0).signals_v => tets_out_to_test_in(0).signals_v(7 downto 4),
              hx_i(1).signals_v => tets_out_to_test_in(1).signals_v(7 downto 4),
              hx_i(2).signals_v => tets_out_to_test_in(2).signals_v(7 downto 4),
              lx_i(0).signals_v => tets_out_to_test_in(0).signals_v(3 downto 0),
              lx_i(1).signals_v => tets_out_to_test_in(1).signals_v(3 downto 0),
              lx_i(2).signals_v => tets_out_to_test_in(2).signals_v(3 downto 0)
        );
    
    label_out: test_output
        port map (
               out_o  =>    tets_out_to_test_in
              );
    end architecture;
    

    We get to map elements of formal's composite type to actual elements individually in a port association list. And this form should be synthesis eligible.