Search code examples
vhdl

for generate with conditional logic


I am implementing the following module:

library ieee;
use ieee.std_logic_1164.all;

entity Grant_Logic is
    generic (
        N : positive := 4
    );
    Port (
        Priority_Logic0 :   in std_logic_vector(N-1 downto 0);
        Priority_Logic1 :   in std_logic_vector(N-1 downto 0);
        Priority_Logic2 :   in std_logic_vector(N-1 downto 0);
        Priority_Logic3 :   in std_logic_vector(N-1 downto 0);
        Gnt             :   out std_logic_vector (N-1 downto 0)
    );
end Grant_Logic;

architecture Behavioral of Grant_Logic is

begin

    gnt(0) <= Priority_Logic0(0) or Priority_Logic1(3) or Priority_Logic2(2) or Priority_Logic3(1);
    gnt(1) <= Priority_Logic0(1) or Priority_Logic1(0) or Priority_Logic2(3) or Priority_Logic3(2);
    gnt(2) <= Priority_Logic0(2) or Priority_Logic1(1) or Priority_Logic2(0) or Priority_Logic3(3);
    gnt(3) <= Priority_Logic0(3) or Priority_Logic1(2) or Priority_Logic2(1) or Priority_Logic3(0);

end Behavioral;

I want to take advantage of for ... generate to implement the same circuit when N changes. I am using Xilinx so Vivado (vhdl'93) does not support custom types for ports in the IP generation. However, for the architecture I would like to use for ... generate. The issue is that some logic is needed to generate each bit of gnt. What I have so far is:

gen_gnt_vertical: for y in 0 to N-1 generate 
    constant val, index : integer := 0;
    begin
    s_result <= '0';
    gen_gnt_horizontal: for x in 0 to N-1 generate
        begin
             LOGIC BASED ON val, x and y to obtain the index
             s_result <= s_result or s_Priority_Logic(x)(index);
    end generate;
    gnt(y) <= s_result;        
end generate;

The logic to compute index is:

    if(x>0)
    {
        val = y - x;
        if (val < 0)
        {
            index = N + val;
        }
        else
            index = val;
    }
    else
    {
        index = y;
    }

I have a script that generates a vhdl file based on N but I would like to do it directly on vhdl. Is that possible?

Thanks for the help

EDIT: As @Tricky replied, a function did the trick. So, I have the following:

function index( N, x,y : natural) return natural is
    variable val     : integer;
    variable index : integer := 0; 
    begin                   
        if(x>0) then
            val := y - x;
            if(val < 0) then
                index := N + val;
            else
                index := val;
            end if;    
        else
            index := y;
        end if;
    return index;
end function;

And the architecture:

architecture Behavioral of Grant_Logic is
    signal s_Priority_Logic : t_Priority_logic;
    signal s_result : std_logic_vector(N-1 downto 0) := (others=>'0');
begin

    s_Priority_Logic(0) <= Priority_Logic0;
    s_Priority_Logic(1) <= Priority_Logic1;
    s_Priority_Logic(2) <= Priority_Logic2;
    s_Priority_Logic(3) <= Priority_Logic3;


    process(s_Priority_Logic)
        variable result : std_logic;
    begin
        for y in 0 to N-1 loop
            result := '0';
            for x in 0 to N-1 loop
                result := result or s_Priority_logic(x)(index(N, x, y));
            end loop;
            gnt_g(y) <= result;
        end loop;
    end process;   

end Behavioral;

Solution

  • @Tricky using a function was the correct thing to get the index value. Alo for generate was not correct but for loop. I edited my question to show the final result