{% set addr_width = (num_ports - 1).bit_length() %} library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; use ieee.math_real.all; entity AXI_Handshaking_Scheduler_{{ num_ports }} is generic ( G_DataWidth : integer := 8; G_InBufferStages : integer := 1; G_OutBufferStages : integer := 1 ); port ( --@ Clock signal; (**Rising edge** triggered) I_CLK : in std_logic; --@ Clock enable signal (**Active high**) I_CE : in std_logic; --@ Synchronous reset signal (**Active high**) I_RST : in std_logic; {% for i in range(num_ports) %} --@ @virtualbus P{{ i }} @dir in P{{ i }} interface I_P{{ i }}_Valid : in std_logic := '0'; O_P{{ i }}_Ready : out std_logic := '0'; I_P{{ i }}_Data : in std_logic_vector(G_DataWidth - 1 downto 0) := (others => '0'); --@ @end {% endfor %} --@ @virtualbus Out @dir out Output interface O_Out_Valid : out std_logic := '0'; I_Out_Ready : in std_logic := '0'; O_Out_Data : out std_logic_vector(G_DataWidth - 1 downto 0) := (others => '0'); O_Out_Address : out std_logic_vector({{ addr_width - 1 }} downto 0) := (others => '0') --@ @end ); end entity AXI_Handshaking_Scheduler_{{ num_ports }}; architecture Rtl of AXI_Handshaking_Scheduler_{{ num_ports }} is signal R_SelectRotator : unsigned({{ addr_width - 1 }} downto 0) := (others => '0'); signal R1_SelectRotator : unsigned({{ addr_width - 1 }} downto 0) := (others => '0'); signal C_Select : std_logic_vector({{ num_ports - 1 }} downto 0) := (others => '0'); signal C_Code : std_logic_vector({{ addr_width - 1 }} downto 0) := (others => '0'); signal R_Code : std_logic_vector({{ addr_width - 1 }} downto 0) := (others => '0'); signal C_CodeUnrotated : std_logic_vector({{ addr_width - 1 }} downto 0) := (others => '0'); {% for i in range(num_ports) %} signal S_P{{ i }}_InBufferEnable : std_logic := '0'; signal S_P{{ i }}_Ready : std_logic := '0'; signal S_P{{ i }}_Valid : std_logic := '0'; signal S_P{{ i }}_Data : std_logic_vector(G_DataWidth - 1 downto 0) := (others => '0'); {% endfor %} signal S_OutBufferEnable : std_logic := '0'; signal S_Out_Ready : std_logic := '0'; signal S_Out_Valid : std_logic := '0'; signal S_Out_Data : std_logic_vector(G_DataWidth - 1 downto 0) := (others => '0'); signal S_Out_Address : std_logic_vector({{ addr_width - 1 }} downto 0) := (others => '0'); begin {% for i in range(num_ports) %} I_P{{ i }}_InBufferCtrl : entity work.PipelineController generic map( G_PipelineStages => G_InBufferStages ) port map( I_CLK => I_CLK, I_CE => I_CE, I_RST => I_RST, O_Enable => S_P{{ i }}_InBufferEnable, I_Valid => I_P{{ i }}_Valid, O_Ready => O_P{{ i }}_Ready, O_Valid => S_P{{ i }}_Valid, I_Ready => S_P{{ i }}_Ready ); I_P{{ i }}_InBuffer : entity work.PipelineRegister generic map( G_PipelineStages => G_InBufferStages, G_Width => G_DataWidth, G_RegisterBalancing => "forward" ) port map( I_CLK => I_CLK, I_Enable => S_P{{ i }}_InBufferEnable, I_Data => I_P{{ i }}_Data, O_Data => S_P{{ i }}_Data ); {% endfor %} I_PriorityEncoder_{{ num_ports }} : entity work.PriorityEncoder_{{ num_ports }} port map( I_Select => C_Select, O_Code => C_Code ); P_SelectMux : process (R_SelectRotator {%- for i in range(num_ports) %}, S_P{{ i }}_Valid{% endfor %}) begin case R_SelectRotator is {%- for r in range(num_ports) %} when "{{ '{:0{}b}'.format(r, addr_width) }}" => C_Select <= {%- for i in range(num_ports) -%} S_P{{ (i + r) % num_ports }}_Valid{% if not loop.last %} & {% endif %} {%- endfor %}; {% endfor %} when others => C_Select <= (others => '-'); end case; end process; P_CodeUnrotating : process (R_Code, R1_SelectRotator) begin C_CodeUnrotated <= std_logic_vector(unsigned(R_Code) + R1_SelectRotator); end process; P_OutMux : process ( C_CodeUnrotated {%- for i in range(num_ports) %}, S_P{{ i }}_Data{% endfor %} {%- for i in range(num_ports) %}, S_P{{ i }}_Valid{% endfor %} , S_Out_Ready) begin S_Out_Valid <= '0'; {%- for i in range(num_ports) %} S_P{{ i }}_Ready <= '0'; {%- endfor %} S_Out_Data <= (others => '-'); S_Out_Address <= C_CodeUnrotated; case C_CodeUnrotated is {%- for i in range(num_ports) %} when "{{ '{:0{}b}'.format(i, addr_width) }}" => S_Out_Valid <= S_P{{ i }}_Valid; S_P{{ i }}_Ready <= S_Out_Ready; S_Out_Data <= S_P{{ i }}_Data; {%- endfor %} when others => S_Out_Address <= (others => '-'); end case; end process; P_SelectRotator : process (I_CLK) begin if rising_edge(I_CLK) then if I_CE = '1' then if I_RST = '1' then R_SelectRotator <= (others => '0'); R1_SelectRotator <= (others => '0'); R_Code <= (others => '0'); else R1_SelectRotator <= R_SelectRotator; R_Code <= C_Code; if I_Out_Ready = '1' then R_SelectRotator <= unsigned(C_CodeUnrotated) + 1; end if; end if; end if; end if; end process P_SelectRotator; I_OutBufferCtrl : entity work.PipelineController generic map( G_PipelineStages => G_OutBufferStages ) port map( I_CLK => I_CLK, I_CE => I_CE, I_RST => I_RST, O_Enable => S_OutBufferEnable, I_Valid => S_Out_Valid, O_Ready => S_Out_Ready, O_Valid => O_Out_Valid, I_Ready => I_Out_Ready ); I_OutDataBuffer : entity work.PipelineRegister generic map( G_PipelineStages => G_OutBufferStages, G_Width => G_DataWidth, G_RegisterBalancing => "backward" ) port map( I_CLK => I_CLK, I_Enable => S_OutBufferEnable, I_Data => S_Out_Data, O_Data => O_Out_Data ); I_OutAddressBuffer : entity work.PipelineRegister generic map( G_PipelineStages => G_OutBufferStages, G_Width => {{ addr_width }}, G_RegisterBalancing => "backward" ) port map( I_CLK => I_CLK, I_Enable => S_OutBufferEnable, I_Data => S_Out_Address, O_Data => O_Out_Address ); end architecture;