Search code examples
arraysintegervhdlvivado

Comparing integer values for assignment to a std_logic_vector


I have a array of integers range 0 to 23 which stores value of range 0 to 2 like ex:

type t_slave_24symbol is array (0 to 23) of integer range 0 to 2;
signal slave_24symbol   : t_slave_24symbol;

type nibble_array is array (0 to 7) of STD_LOGIC_VECTOR(3 downto 0); 
signal nibble : nibble_array;

signal nibble_full : STD_LOGIC_VECTOR(31 downto 0) := "00000000000000000000000000000000";

now I want to split this string into sequences of 3 and compare like

nibble(0) <= "0000" when slave_24symbol(012) = 120 else-- 
        "0001" when slave_24symbol(012)= 200 else
        "0010" when slave_24symbol(012)= 020 else
        "1111";

but later

nibble(3) <= "0000" when slave_24symbol(91011) = 012 else

. . .

and at the end

nibble_full <= nibble(0) & nibble(1) & nibble(2) & nibble(3) & nibble(4) 
& nibble(5) & nibble(6) & nibble(7);

how do I do? because I want to assign char 9 10 and 11 and so on.


Solution

  • The question shows python syntax thinking.

    There's an array of constrained integers being converted to binary representation in a std_logic_vector array.

    First a working Minimal, Complete, and Verifiable example for assigning one element of nibble:

    library ieee;
    use ieee.std_logic_1164.all;
    
    entity depython is
    end entity;
    
    architecture foo of depython is 
        type t_slave_24symbol is array (natural range <>) of integer range 0 to 2;
        signal slave_24symbol: t_slave_24symbol (0 to 23);
    
        type nibble_array is array (0 to 7) of std_logic_vector(3 downto 0); 
        signal nibble:      nibble_array;
        signal nibble_full: std_logic_vector(31 downto 0) := (others => '0');
        subtype nyyblet is t_slave_24symbol (0 to 2);
    begin
    
        -- nibble(0) <= "0000" when slave_24symbol(012) = 120 else--
        --         "0001" when slave_24symbol(012)= 200 else
        --         "0010" when slave_24symbol(012)= 020 else
        --         "1111";
    
        -- BECOMES:
    
        nibble(0) <= "0000" when slave_24symbol(0 to 2) = nyyblet'(1, 2, 0) else
                     "0001" when slave_24symbol(0 to 2) = nyyblet'(2, 0, 0) else
                     "0010" when slave_24symbol(0 to 2) = nyyblet'(0, 2, 0) else
                     "1111";
    end architecture; 
    

    The type t_slave_24symbol has been changed to an unconstrained array definition with the declaration of signal slave_24symbol providing the subtype. (This is called an unbounded array definition in -2008).

    The index range of a slice of slave_24symbol is changed to VHDL syntax. The value range of the expression evaluated in each condition has been changed to VHDL syntax using an aggregate whose type is provided by qualified expression requiring the subtype definition. The subtype declaration requires the unconstrained/unbounded array definition.

    The qualified expression is required to specify the subtype because the predefined equality operator for an array type operates on unconstrained operands - you can test equality of two different length arrays and they will always be unequal. (Comes in handy when dealing with null arrays).

    Note that the type of a string literal (e.g. "0010") is determined by context and element values ('0', '1') must be compatible with the element type (here std_ulogic) of the array type (here std_logic_vector).

    This analyzes, elaborates and simulates (using the default value (0, 0, 0) for each element of slave_24symbol, each process will execute once during initialization, a concurrent assignment statement is elaborated into an equivalent sequential assignment statement contained in a process statement).

    Now we address how to convert all the elements of nibble in a new architecture:

    architecture sequential of depython is
        type t_slave_24symbol is array (natural range <>) of integer range 0 to 2;
        signal slave_24symbol: t_slave_24symbol (0 to 23);
    
        type nibble_array is array (0 to 7) of std_logic_vector(3 downto 0); 
        signal nibble:      nibble_array;
        signal nibble_full: std_logic_vector(31 downto 0) := (others => '0');
        subtype nyyblet is t_slave_24symbol (0 to 2);
    
        function nybble (nyb: nyyblet) return std_logic_vector is
           --  retv:   std_logic_vector(3 downto 0);
        begin
            if    nyb = nyyblet'(1, 2, 0) then
                return "0000";
            elsif nyb = nyyblet'(2, 0, 0) then
                return "0001";
            elsif nyb = nyyblet'(0, 2, 0) then 
                return "0010";
            else 
                return "1111";
            end if;
        end function;
    begin    
    
        -- nibble(0) <= "0000" when slave_24symbol(0 to 2) = nyyblet'(1,2,0) else
        --              "0001" when slave_24symbol(0 to 2) = nyyblet'(2,0,0) else
        --              "0010" when slave_24symbol(0 to 2) = nyyblet'(0,2,0) else
        --              "1111";
    
    -- but later
    --
    -- nibble(3) <= "0000" when slave_24symbol(91011) = 012 else
    --
    -- . . .
    --
    -- and at the end
    --
    -- nibble_full <= nibble(0) & nibble(1) & nibble(2) & nibble(3) & nibble(4)
    -- & nibble(5) & nibble(6) & nibble(7);
    
        process (slave_24symbol)
        begin
            for i in nibble'range loop
                nibble(i) <= nybble(slave_24symbol(3 * i to 2 + i * 3));
            end loop;
        end process;
    
    end architecture;
    

    Here a function call is used to hide some of the complexity. The sequential assignment statement in a loop statement (a sequential statement itself) uses offset arithmetic to address all eight slices of three constrained integers of of slave_24symbol being evaluated.

    And because the question showed a nibble element being assigned in a conditional signal assignment (here a concurrent signal assignment), a concurrent assignment version using a generate statement:

    architecture concurrent of depython is
        type t_slave_24symbol is array (natural range <>) of integer range 0 to 2;
        signal slave_24symbol: t_slave_24symbol (0 to 23);
    
        type nibble_array is array (0 to 7) of std_logic_vector(3 downto 0); 
        signal nibble:      nibble_array;
        signal nibble_full: std_logic_vector(31 downto 0) := (others => '0');
        subtype nyyblet is t_slave_24symbol (0 to 2);
    
        function nybble (nyb: nyyblet) return std_logic_vector is
           --  retv:   std_logic_vector(3 downto 0);
        begin
            if    nyb = nyyblet'(1, 2, 0) then
                return "0000";
            elsif nyb = nyyblet'(2, 0, 0) then
                return "0001";
            elsif nyb = nyyblet'(0, 2, 0) then 
                return "0010";
            else 
                return "1111";
            end if;
        end function;
    begin    
    
        -- process (slave_24symbol)
        -- begin
        --     for i in nibble'range loop
        --         nibble(i) <= nybble(slave_24symbol(3 * i to 2 + i * 3));
        --     end loop;
        -- end process;
    NIBBLE_IT:
        for i in nibble'range generate
            nibble(i) <= nybble(slave_24symbol(3 * i to 2 + i * 3));
        end generate;
    
    end architecture;
    

    All the shown architectures analyze, elaborate and simulate demonstrating all the indexes and slices fall within subtype bounds.

    Note you could also pour the loop statement into a function with a parameter type of t_slave_24symbol and perform one assignment either concurrently or sequentially. This would also allow detection of a parameter value that isn't comprised of a multiple of 3 integers (because type t_slave_24symbol is declared unconstrained/unbounded). It's possible to avoid any parameter value detection by declaring a new type and making t_slave_24symbol and nyyblet subtypes of the new type:

    architecture all_in_one_function of depython is
        type c_integer_array is array (natural range <>) of integer range 0 to 2;
        subtype t_slave_24symbol is c_integer_array (0 to 23);
        signal slave_24symbol: t_slave_24symbol := (
                        1,2,0, 2,0,0, 0,2,0, 0,0,0, 0,0,1, 0,0,2, 0,1,0, 0,1,1);
        signal nibble_full:    std_logic_vector (31 downto 0);
    
        function nybble (slave: t_slave_24symbol) return std_logic_vector is
            type nibble_array is array (0 to 7) of std_logic_vector(3 downto 0); 
            variable nib:      nibble_array;
            subtype nyyblet is c_integer_array (0 to 2);
        begin
            for i in nib'range loop
                if    slave(3 * i to 2 + i * 3) = nyyblet'(1, 2, 0) then
                    nib(i) := "0000";
                elsif slave(3 * i to 2 + i * 3) = nyyblet'(2, 0, 0) then
                    nib(i) := "0001";
                elsif slave(3 * i to 2 + i * 3) = nyyblet'(0, 2, 0) then 
                    nib(i) := "0010";
                else 
                    nib(i) := "1111";
                end if;
            end loop;
            return nib(0) & nib(1) & nib(2) & nib(3) & 
                   nib(4) & nib(5) & nib(5) & nib(7);
        end function;
    
        function to_string (inp: std_logic_vector) return string is
            variable image_str: string (1 to inp'length);
            alias input_str:  std_logic_vector (1 to inp'length) is inp;
        begin
            for i in input_str'range loop
                image_str(i) := character'VALUE(std_ulogic'IMAGE(input_str(i)));
            end loop;
            return image_str;
        end function;
    begin    
    NIBBLE_IT:
        nibble_full <= nybble(slave_24symbol);
        process
        begin
            wait for 0 ns;
            report "nibble_full = " & to_string (nibble_full);
            wait;
        end process;
    end architecture;
    

    The to_string function is added for compatibility with VHDL revisions earlier than -2008. The signal _slave_24symbol is initialized to demonstrate the conversion is successful:

    /usr/local/bin/ghdl -a depython1.vhdl
    /usr/local/bin/ghdl -e depython
    /usr/local/bin/ghdl -r depython
    depython1.vhdl:79:9:@0ms:(report note): nibble_full = 00000001001011111111111111111111