Adds priority encoders and pipeline-based modules

Implements various priority encoder components with combinatorial logic for encoding input vectors to output codes of varying widths.

Introduces pipeline-based modules for handling calculation, ROM data fetching, and scheduling operations with AXI-like handshaking interfaces.

Facilitates modular and reusable design for priority encoding and data processing tasks.
This commit is contained in:
2025-04-20 03:02:02 +00:00
commit bbe0ff9b9e
4 changed files with 1001 additions and 0 deletions

345
libs/PriorityEncoders.vhd Normal file
View File

@@ -0,0 +1,345 @@
library ieee;
use ieee.std_logic_1164.all;
--@ Priority Encoder (2 to 1 bits)
--@ This is a combinatorial priority encoder that encodes the highest priority
--@ bit in the input vector to a 1-bit output code.
entity PriorityEncoder_2 is
port (
--@ Input vector to be encoded.
--@ The least significant bit has the highest priority.
I_Select : in std_logic_vector(1 downto 0) := (others => '0');
--@ Output code.
--@ The output code is the index of the highest priority bit in the input vector.
O_Code : out std_logic_vector(0 downto 0) := (others => '0')
);
end entity PriorityEncoder_2;
architecture Combinatoric of PriorityEncoder_2 is
--@ Internal signal to hold the encoded output.
signal C_Code : std_logic_vector(0 downto 0);
--@ Attribute to force the synthesis tool (XST, old Parser) to treat this as a combinatorial signal.
attribute PRIORITY_EXTRACT : string;
attribute PRIORITY_EXTRACT of C_Code : signal is "force";
begin
C_Code <= "0" when I_Select(1) = '1' else
"1" when I_Select(0) = '1' else
"-";
O_Code <= C_Code;
end architecture;
library ieee;
use ieee.std_logic_1164.all;
--@ Priority Encoder (4 to 2 bits)
--@ This is a combinatorial priority encoder that encodes the highest priority
--@ bit in the input vector to a 2-bit output code.
entity PriorityEncoder_4 is
port (
--@ Input vector to be encoded.
--@ The least significant bit has the highest priority.
I_Select : in std_logic_vector(3 downto 0) := (others => '0');
--@ Output code.
--@ The output code is the index of the highest priority bit in the input vector.
O_Code : out std_logic_vector(1 downto 0) := (others => '0')
);
end entity PriorityEncoder_4;
architecture Combinatoric of PriorityEncoder_4 is
--@ Internal signal to hold the encoded output.
signal C_Code : std_logic_vector(1 downto 0);
--@ Attribute to force the synthesis tool (XST, old Parser) to treat this as a combinatorial signal.
attribute PRIORITY_EXTRACT : string;
attribute PRIORITY_EXTRACT of C_Code : signal is "force";
begin
C_Code <= "00" when I_Select(3) = '1' else
"01" when I_Select(2) = '1' else
"10" when I_Select(1) = '1' else
"11" when I_Select(0) = '1' else
"--";
O_Code <= C_Code;
end architecture;
library ieee;
use ieee.std_logic_1164.all;
--@ Priority Encoder (8 to 3 bits)
--@ This is a combinatorial priority encoder that encodes the highest priority
--@ bit in the input vector to a 3-bit output code.
entity PriorityEncoder_8 is
port (
--@ Input vector to be encoded.
--@ The least significant bit has the highest priority.
I_Select : in std_logic_vector(7 downto 0) := (others => '0');
--@ Output code.
--@ The output code is the index of the highest priority bit in the input vector.
O_Code : out std_logic_vector(2 downto 0) := (others => '0')
);
end entity PriorityEncoder_8;
architecture Combinatoric of PriorityEncoder_8 is
--@ Internal signal to hold the encoded output.
signal C_Code : std_logic_vector(2 downto 0);
--@ Attribute to force the synthesis tool (XST, old Parser) to treat this as a combinatorial signal.
attribute PRIORITY_EXTRACT : string;
attribute PRIORITY_EXTRACT of C_Code : signal is "force";
begin
C_Code <= "000" when I_Select(7) = '1' else
"001" when I_Select(6) = '1' else
"010" when I_Select(5) = '1' else
"011" when I_Select(4) = '1' else
"100" when I_Select(3) = '1' else
"101" when I_Select(2) = '1' else
"110" when I_Select(1) = '1' else
"111" when I_Select(0) = '1' else
"---";
O_Code <= C_Code;
end architecture;
library ieee;
use ieee.std_logic_1164.all;
--@ Priority Encoder (16 to 4 bits)
--@ This is a combinatorial priority encoder that encodes the highest priority
--@ bit in the input vector to a 4-bit output code.
entity PriorityEncoder_16 is
port (
--@ Input vector to be encoded.
--@ The least significant bit has the highest priority.
I_Select : in std_logic_vector(15 downto 0) := (others => '0');
--@ Output code.
--@ The output code is the index of the highest priority bit in the input vector.
O_Code : out std_logic_vector(3 downto 0) := (others => '0')
);
end entity PriorityEncoder_16;
architecture Combinatoric of PriorityEncoder_16 is
--@ Internal signal to hold the encoded output.
signal C_Code : std_logic_vector(3 downto 0);
--@ Attribute to force the synthesis tool (XST, old Parser) to treat this as a combinatorial signal.
attribute PRIORITY_EXTRACT : string;
attribute PRIORITY_EXTRACT of C_Code : signal is "force";
begin
C_Code <= "0000" when I_Select(15) = '1' else
"0001" when I_Select(14) = '1' else
"0010" when I_Select(13) = '1' else
"0011" when I_Select(12) = '1' else
"0100" when I_Select(11) = '1' else
"0101" when I_Select(10) = '1' else
"0110" when I_Select(9) = '1' else
"0111" when I_Select(8) = '1' else
"1000" when I_Select(7) = '1' else
"1001" when I_Select(6) = '1' else
"1010" when I_Select(5) = '1' else
"1011" when I_Select(4) = '1' else
"1100" when I_Select(3) = '1' else
"1101" when I_Select(2) = '1' else
"1110" when I_Select(1) = '1' else
"1111" when I_Select(0) = '1' else
"----";
O_Code <= C_Code;
end architecture;
library ieee;
use ieee.std_logic_1164.all;
--@ Priority Encoder (32 to 5 bits)
--@ This is a combinatorial priority encoder that encodes the highest priority
--@ bit in the input vector to a 5-bit output code.
entity PriorityEncoder_32 is
port (
--@ Input vector to be encoded.
--@ The least significant bit has the highest priority.
I_Select : in std_logic_vector(31 downto 0) := (others => '0');
--@ Output code.
--@ The output code is the index of the highest priority bit in the input vector.
O_Code : out std_logic_vector(4 downto 0) := (others => '0')
);
end entity PriorityEncoder_32;
architecture Combinatoric of PriorityEncoder_32 is
--@ Internal signal to hold the encoded output.
signal C_Code : std_logic_vector(4 downto 0);
--@ Attribute to force the synthesis tool (XST, old Parser) to treat this as a combinatorial signal.
attribute PRIORITY_EXTRACT : string;
attribute PRIORITY_EXTRACT of C_Code : signal is "force";
begin
C_Code <= "00000" when I_Select(31) = '1' else
"00001" when I_Select(30) = '1' else
"00010" when I_Select(29) = '1' else
"00011" when I_Select(28) = '1' else
"00100" when I_Select(27) = '1' else
"00101" when I_Select(26) = '1' else
"00110" when I_Select(25) = '1' else
"00111" when I_Select(24) = '1' else
"01000" when I_Select(23) = '1' else
"01001" when I_Select(22) = '1' else
"01010" when I_Select(21) = '1' else
"01011" when I_Select(20) = '1' else
"01100" when I_Select(19) = '1' else
"01101" when I_Select(18) = '1' else
"01110" when I_Select(17) = '1' else
"01111" when I_Select(16) = '1' else
"10000" when I_Select(15) = '1' else
"10001" when I_Select(14) = '1' else
"10010" when I_Select(13) = '1' else
"10011" when I_Select(12) = '1' else
"10100" when I_Select(11) = '1' else
"10101" when I_Select(10) = '1' else
"10110" when I_Select(9) = '1' else
"10111" when I_Select(8) = '1' else
"11000" when I_Select(7) = '1' else
"11001" when I_Select(6) = '1' else
"11010" when I_Select(5) = '1' else
"11011" when I_Select(4) = '1' else
"11100" when I_Select(3) = '1' else
"11101" when I_Select(2) = '1' else
"11110" when I_Select(1) = '1' else
"11111" when I_Select(0) = '1' else
"-----";
O_Code <= C_Code;
end architecture;
library ieee;
use ieee.std_logic_1164.all;
--@ Priority Encoder (64 to 6 bits)
--@ This is a combinatorial priority encoder that encodes the highest priority
--@ bit in the input vector to a 6-bit output code.
entity PriorityEncoder_64 is
port (
--@ Input vector to be encoded.
--@ The least significant bit has the highest priority.
I_Select : in std_logic_vector(63 downto 0) := (others => '0');
--@ Output code.
--@ The output code is the index of the highest priority bit in the input vector.
O_Code : out std_logic_vector(5 downto 0) := (others => '0')
);
end entity PriorityEncoder_64;
architecture Combinatoric of PriorityEncoder_64 is
--@ Internal signal to hold the encoded output.
signal C_Code : std_logic_vector(5 downto 0);
--@ Attribute to force the synthesis tool (XST, old Parser) to treat this as a combinatorial signal.
attribute PRIORITY_EXTRACT : string;
attribute PRIORITY_EXTRACT of C_Code : signal is "force";
begin
C_Code <= "000000" when I_Select(63) = '1' else
"000001" when I_Select(62) = '1' else
"000010" when I_Select(61) = '1' else
"000011" when I_Select(60) = '1' else
"000100" when I_Select(59) = '1' else
"000101" when I_Select(58) = '1' else
"000110" when I_Select(57) = '1' else
"000111" when I_Select(56) = '1' else
"001000" when I_Select(55) = '1' else
"001001" when I_Select(54) = '1' else
"001010" when I_Select(53) = '1' else
"001011" when I_Select(52) = '1' else
"001100" when I_Select(51) = '1' else
"001101" when I_Select(50) = '1' else
"001110" when I_Select(49) = '1' else
"001111" when I_Select(48) = '1' else
"010000" when I_Select(47) = '1' else
"010001" when I_Select(46) = '1' else
"010010" when I_Select(45) = '1' else
"010011" when I_Select(44) = '1' else
"010100" when I_Select(43) = '1' else
"010101" when I_Select(42) = '1' else
"010110" when I_Select(41) = '1' else
"010111" when I_Select(40) = '1' else
"011000" when I_Select(39) = '1' else
"011001" when I_Select(38) = '1' else
"011010" when I_Select(37) = '1' else
"011011" when I_Select(36) = '1' else
"011100" when I_Select(35) = '1' else
"011101" when I_Select(34) = '1' else
"011110" when I_Select(33) = '1' else
"011111" when I_Select(32) = '1' else
"100000" when I_Select(31) = '1' else
"100001" when I_Select(30) = '1' else
"100010" when I_Select(29) = '1' else
"100011" when I_Select(28) = '1' else
"100100" when I_Select(27) = '1' else
"100101" when I_Select(26) = '1' else
"100110" when I_Select(25) = '1' else
"100111" when I_Select(24) = '1' else
"101000" when I_Select(23) = '1' else
"101001" when I_Select(22) = '1' else
"101010" when I_Select(21) = '1' else
"101011" when I_Select(20) = '1' else
"101100" when I_Select(19) = '1' else
"101101" when I_Select(18) = '1' else
"101110" when I_Select(17) = '1' else
"101111" when I_Select(16) = '1' else
"110000" when I_Select(15) = '1' else
"110001" when I_Select(14) = '1' else
"110010" when I_Select(13) = '1' else
"110011" when I_Select(12) = '1' else
"110100" when I_Select(11) = '1' else
"110101" when I_Select(10) = '1' else
"110110" when I_Select(9) = '1' else
"110111" when I_Select(8) = '1' else
"111000" when I_Select(7) = '1' else
"111001" when I_Select(6) = '1' else
"111010" when I_Select(5) = '1' else
"111011" when I_Select(4) = '1' else
"111100" when I_Select(3) = '1' else
"111101" when I_Select(2) = '1' else
"111110" when I_Select(1) = '1' else
"111111" when I_Select(0) = '1' else
"------";
O_Code <= C_Code;
end architecture;
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use ieee.math_real.all;
--@ Priority Encoder (Generic)
--@ This is a combinatorial priority encoder that encodes the highest priority
--@ bit in the input vector to a 6-bit output code.
entity PriorityEncoder_G is
generic (
--@ Code width with minimum 2 bits and maximum 6 bits.
G_CodeWidth : integer := 6
);
port (
--@ Input vector to be encoded.
--@ The least significant bit has the highest priority.
I_Select : in std_logic_vector(2 ** G_CodeWidth - 1 downto 0);
--@ Output code.
--@ The output code is the index of the highest priority bit in the input vector.
O_Code : out std_logic_vector(G_CodeWidth - 1 downto 0)
);
end entity PriorityEncoder_G;
architecture Combinatoric of PriorityEncoder_G is
signal C_Select : std_logic_vector(63 downto 0) := (others => '-');
signal C_Code : std_logic_vector(5 downto 0) := (others => '-');
begin
entity_inst : entity work.PriorityEncoder_64
port map(
I_Select => C_Select,
O_Code => C_Code
);
C_Select(G_CodeWidth * 2 - 1 downto 0) <= I_Select;
O_Code <= C_Code(G_CodeWidth - 1 downto 0);
end architecture;

207
src/CalcPipeline.vhd Normal file
View File

@@ -0,0 +1,207 @@
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use ieee.math_real.all;
entity CalcPipeline is
generic (
--@ Width of the sprite index (Base address) register
G_Index_Width : integer := 5;
--@ Width of the sprite offset (Line address) register
G_Offset_Width : integer := 8;
--@ Width of the X position (Row) register
G_X_Width : integer := 10;
--@ Width of the pixel data from rom
G_Rom_Width : integer := 8;
--@ Width of the pixel data output
G_Pixel_Width : integer := 8
);
port (
--@ Clock; (**Rising edge** triggered)
I_CLK : in std_logic;
--@ Clock Enable; (**Synchronous**, **Active high**)
I_CE : in std_logic;
--@ Reset; (**Synchronous**, **Active high**)
I_RST : in std_logic;
--@ @virtualbus Start-OP @dir In Start calculation bus
--@ AXI like valid; (**Synchronous**, **Active high**)
I_OP_Valid : in std_logic;
--@ AXI like ready; (**Synchronous**, **Active high**)
O_OP_Ready : out std_logic;
--@ Index address
I_OP_Index : in std_logic_vector(G_Index_Width - 1 downto 0);
--@ Offset address
I_OP_Offset : in std_logic_vector(G_Offset_Width - 1 downto 0);
--@ X position of the request
I_OP_X_Request : in std_logic_vector(G_X_Width - 1 downto 0);
--@ X position of the sprite
I_OP_X_Sprite : in std_logic_vector(G_X_Width - 1 downto 0);
--@ @end
--@ @virtualbus Rom-Address @dir Out Request rom data bus
--@ AXI like valid; (**Synchronous**, **Active high**)
O_Rom_Valid : out std_logic;
--@ AXI like ready; (**Synchronous**, **Active high**)
I_Rom_Ready : in std_logic;
--@ Rom address
O_Rom_Address : out std_logic_vector(G_Index_Width + G_Offset_Width - 1 downto 0);
--@ @end
--@ @virtualbus Rom-Data @dir In Rom data bus
--@ AXI like valid; (**Synchronous**, **Active high**)
I_Rom_Valid : in std_logic;
--@ AXI like ready; (**Synchronous**, **Active high**)
O_Rom_Ready : out std_logic;
--@ Rom data
I_Rom_Data : in std_logic_vector(G_Rom_Width - 1 downto 0);
--@ @end
--@ @virtualbus Pixel-Data @dir Out Pixel data output bus
--@ AXI like valid; (**Synchronous**, **Active high**)
O_Pixel_Valid : out std_logic;
--@ AXI like ready; (**Synchronous**, **Active high**)
I_Pixel_Ready : in std_logic;
--@ Pixel data
O_Pixel_Data : out std_logic_vector(G_Pixel_Width - 1 downto 0)
--@ @end
);
end entity CalcPipeline;
architecture RTL of CalcPipeline is
signal R_Index : std_logic_vector(G_Index_Width - 1 downto 0) := (others => '0');
signal R_Offset : std_logic_vector(G_Offset_Width - 1 downto 0) := (others => '0');
signal R_X_Request : std_logic_vector(G_X_Width - 1 downto 0) := (others => '0');
signal R_X_Sprite : std_logic_vector(G_X_Width - 1 downto 0) := (others => '0');
signal C_Address : std_logic_vector(G_Index_Width + G_Offset_Width - 1 downto 0) := (others => '0');
signal R_Address : std_logic_vector(G_Index_Width + G_Offset_Width - 1 downto 0) := (others => '0');
signal I_I_Calculating_Ready : std_logic := '0';
signal O_I_Calculating_Valid : std_logic := '0';
signal I_O_Calculating_Ready : std_logic := '0';
signal O_O_Calculating_Valid : std_logic := '0';
signal C_X_Visible : std_logic := '0';
signal R_X_Visible : std_logic := '0';
signal I_RomRequest_Valid : std_logic := '0';
signal O_RomRequest_Ready : std_logic := '0';
begin
INST_I_Calculating : entity work.PipelineStage
generic map(
G_PipelineStages => 1,
G_D0_Width => G_Index_Width,
G_D1_Width => G_Offset_Width,
G_D2_Width => G_X_Width,
G_D3_Width => G_X_Width
)
port map(
I_CLK => I_CLK,
I_CE => I_CE,
I_RST => I_RST,
I_Valid => I_OP_Valid,
O_Ready => O_OP_Ready,
I_Data_0 => I_OP_Index,
I_Data_1 => I_OP_Offset,
I_Data_2 => I_OP_X_Request,
I_Data_3 => I_OP_X_Sprite,
O_Valid => O_I_Calculating_Valid,
I_Ready => I_I_Calculating_Ready,
O_Data_0 => R_Index,
O_Data_1 => R_Offset,
O_Data_2 => R_X_Request,
O_Data_3 => R_X_Sprite
);
process (R_Offset, R_Index, R_X_Request, R_X_Sprite)
variable V_Offset : unsigned(G_Offset_Width - 1 downto 0);
variable V_X_Request : unsigned(G_X_Width - 1 downto 0);
variable V_X_Sprite : unsigned(G_X_Width - 1 downto 0);
variable V_RelativeOffset : unsigned(G_X_Width - 1 downto 0);
variable V_CalculateOffset : unsigned(G_Offset_Width - 1 downto 0);
begin
V_Offset := unsigned(R_Offset);
V_X_Request := unsigned(R_X_Request);
V_X_Sprite := unsigned(R_X_Sprite);
V_RelativeOffset := V_X_Request - V_X_Sprite;
V_CalculateOffset := V_Offset + V_RelativeOffset(G_Offset_Width - 1 downto 0);
if V_CalculateOffset > 15 then
C_X_Visible <= '0';
else
C_X_Visible <= '1';
end if;
C_Address <= R_Index & std_logic_vector(V_CalculateOffset);
end process;
INST_O_Calculating : entity work.PipelineStage
generic map(
G_PipelineStages => 1,
G_D0_Width => G_Index_Width + G_Offset_Width,
G_D1_Width => 1
)
port map(
I_CLK => I_CLK,
I_CE => I_CE,
I_RST => I_RST,
I_Valid => O_I_Calculating_Valid,
O_Ready => I_I_Calculating_Ready,
I_Data_0 => C_Address,
I_Data_1(0) => C_X_Visible,
O_Valid => O_O_Calculating_Valid,
I_Ready => I_O_Calculating_Ready,
O_Data_0 => R_Address,
O_Data_1(0) => R_X_Visible
);
process (R_X_Visible, O_O_Calculating_Valid, O_RomRequest_Ready)
begin
if R_X_Visible = '0' then
I_RomRequest_Valid <= '0';
I_O_Calculating_Ready <= '1';
else
I_RomRequest_Valid <= O_O_Calculating_Valid;
I_O_Calculating_Ready <= O_RomRequest_Ready;
end if;
end process;
INST_RomRequest : entity work.PipelineStage
generic map(
G_PipelineStages => 1,
G_D0_Width => G_Index_Width + G_Offset_Width
)
port map(
I_CLK => I_CLK,
I_CE => I_CE,
I_RST => I_RST,
I_Valid => I_RomRequest_Valid,
O_Ready => O_RomRequest_Ready,
I_Data_0 => R_Address,
O_Valid => O_Rom_Valid,
I_Ready => I_Rom_Ready,
O_Data_0 => O_Rom_Address
);
I_ForwardPixelData : entity work.PipelineStage
generic map(
G_PipelineStages => 1,
G_D0_Width => G_Pixel_Width
)
port map(
I_CLK => I_CLK,
I_CE => I_CE,
I_RST => I_RST,
I_Valid => I_Rom_Valid,
O_Ready => O_Rom_Ready,
I_Data_0 => I_Rom_Data,
O_Valid => O_Pixel_Valid,
I_Ready => I_Pixel_Ready,
O_Data_0 => O_Pixel_Data
);
end architecture;

305
src/Rom.vhd Normal file
View File

@@ -0,0 +1,305 @@
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use ieee.math_real.all;
use work.SpriteRom.all;
entity Rom is
generic (
--@ ROM Address Width
G_Address_Width : integer := 13;
--@ ROM Data Width
G_Data_Width : integer := 8;
--@ Port-0 In/Out Buffer Stages
G_P0_BufferStages : integer := 1;
--@ Port-0 Identifier Width
G_P0_ID_Width : integer := 4;
--@ Port-1 In/Out Buffer Stages
G_P1_BufferStages : integer := 1;
--@ Port-1 Identifier Width
G_P1_ID_Width : integer := 4;
--@ Implementation of the ROM: "Block" or "Distributed"
G_RomType : string := "Block"
);
port (
--@ Clock signal; (**Rising edge** triggered)
I_CLK : in std_logic := '0';
--@ Clock enable signal (**Active high**)
I_CE : in std_logic := '1';
--@ @virtualbus Address-Port-0 @dir in Address Port 0
I_P0_Address_Valid : in std_logic := '0';
O_P0_Address_Ready : out std_logic := '0';
I_P0_Address : in std_logic_vector(G_Address_Width - 1 downto 0) := (others => '0');
I_P0_ID : in std_logic_vector(G_P0_ID_Width - 1 downto 0) := (others => '0');
--@ @end
--@ @virtualbus Address-Port-0 @dir in Address Port 0
I_P1_Address_Valid : in std_logic := '0';
O_P1_Address_Ready : out std_logic := '0';
I_P1_Address : in std_logic_vector(G_Address_Width - 1 downto 0) := (others => '0');
I_P1_ID : in std_logic_vector(G_P1_ID_Width - 1 downto 0) := (others => '0');
--@ @end
--@ @virtualbus Data-Port-0 @dir out Data Port 0
O_P0_Data_Valid : out std_logic := '0';
I_P0_Data_Ready : in std_logic := '0';
O_P0_Data : out std_logic_vector(G_Data_Width - 1 downto 0) := (others => '0');
O_P0_ID : out std_logic_vector(G_P0_ID_Width - 1 downto 0) := (others => '0');
--@ @end
--@ @virtualbus Data-Port-1 @dir out Data Port 1
O_P1_Data_Valid : out std_logic := '0';
I_P1_Data_Ready : in std_logic := '0';
O_P1_Data : out std_logic_vector(G_Data_Width - 1 downto 0) := (others => '0');
O_P1_ID : out std_logic_vector(G_P1_ID_Width - 1 downto 0) := (others => '0')
--@ @end
);
end entity Rom;
architecture Rtl of Rom is
signal Rom : T_Rom := K_SPRITE_ROM;
attribute ROM_STYLE : string;
attribute ROM_STYLE of Rom : signal is G_RomType;
signal S_P0_InBufferEnable : std_logic := '0';
signal S_P0_OutBufferEnable : std_logic := '0';
signal S_P0_Address_Valid : std_logic := '0';
signal R_P0_Address : std_logic_vector(G_Address_Width - 1 downto 0) := (others => '0');
signal R_P0_Address_ID : std_logic_vector(G_P0_ID_Width - 1 downto 0) := (others => '0');
signal R_P0_Data_Valid : std_logic := '0';
signal C_P0_Address_Ready : std_logic := '0';
signal S_P0_Data_Ready : std_logic := '0';
signal R_P0_Data : std_logic_vector(G_Data_Width - 1 downto 0) := (others => '0');
signal R_P0_Data_ID : std_logic_vector(G_P0_ID_Width - 1 downto 0) := (others => '0');
signal S_P1_InBufferEnable : std_logic := '0';
signal S_P1_OutBufferEnable : std_logic := '0';
signal S_P1_Address_Valid : std_logic := '0';
signal R_P1_Address : std_logic_vector(G_Address_Width - 1 downto 0) := (others => '0');
signal R_P1_Address_ID : std_logic_vector(G_P1_ID_Width - 1 downto 0) := (others => '0');
signal R_P1_Data_Valid : std_logic := '0';
signal C_P1_Address_Ready : std_logic := '0';
signal S_P1_Data_Ready : std_logic := '0';
signal R_P1_Data : std_logic_vector(G_Data_Width - 1 downto 0) := (others => '0');
signal R_P1_Data_ID : std_logic_vector(G_P1_ID_Width - 1 downto 0) := (others => '0');
begin
I_P0_InBufferCtrl : entity work.PipelineController
generic map(
G_PipelineStages => G_P0_BufferStages
)
port map(
I_CLK => I_CLK,
I_CE => I_CE,
O_Enable => S_P0_InBufferEnable,
I_Valid => I_P0_Address_Valid,
O_Ready => O_P0_Address_Ready,
O_Valid => S_P0_Address_Valid,
I_Ready => C_P0_Address_Ready
);
I_P0_InBuffer_Data : entity work.PipelineRegister
generic map(
G_PipelineStages => G_P0_BufferStages,
G_Width => G_Address_Width,
G_RegisterBalancing => "forward"
)
port map(
I_CLK => I_CLK,
I_Enable => S_P0_InBufferEnable,
I_Data => I_P0_Address,
O_Data => R_P0_Address
);
I_P0_InBuffer_ID : entity work.PipelineRegister
generic map(
G_PipelineStages => G_P0_BufferStages,
G_Width => G_P0_ID_Width,
G_RegisterBalancing => "forward"
)
port map(
I_CLK => I_CLK,
I_Enable => S_P0_InBufferEnable,
I_Data => I_P0_ID,
O_Data => R_P0_Address_ID
);
C_P0_Address_Ready <= not R_P0_Data_Valid;
P_P0_Flags : process (I_CLK)
begin
if rising_edge(I_CLK) then
if I_CE = '1' then
if S_P0_Address_Valid = '1' and C_P0_Address_Ready = '1' then
R_P0_Data_Valid <= '1';
R_P0_Data_ID <= R_P0_Address_ID;
end if;
if S_P0_Data_Ready = '1' and R_P0_Data_Valid = '1' then
R_P0_Data_Valid <= '0';
end if;
end if;
end if;
end process;
P_P0_Read : process (I_CLK)
begin
if rising_edge(I_CLK) then
if I_CE = '1' then
R_P0_Data <= Rom(to_integer(unsigned(R_P0_Address)));
end if;
end if;
end process;
I_P0_OutBufferCtrl : entity work.PipelineController
generic map(
G_PipelineStages => G_P0_BufferStages
)
port map(
I_CLK => I_CLK,
I_CE => I_CE,
O_Enable => S_P0_OutBufferEnable,
I_Valid => R_P0_Data_Valid,
O_Ready => S_P0_Data_Ready,
O_Valid => O_P0_Data_Valid,
I_Ready => I_P0_Data_Ready
);
I_P0_OutBuffer_Data : entity work.PipelineRegister
generic map(
G_PipelineStages => G_P0_BufferStages,
G_Width => G_Data_Width,
G_RegisterBalancing => "backward"
)
port map(
I_CLK => I_CLK,
I_Enable => S_P0_OutBufferEnable,
I_Data => R_P0_Data,
O_Data => O_P0_Data
);
I_P0_OutBuffer_ID : entity work.PipelineRegister
generic map(
G_PipelineStages => G_P0_BufferStages,
G_Width => G_P0_ID_Width,
G_RegisterBalancing => "backward"
)
port map(
I_CLK => I_CLK,
I_Enable => S_P0_OutBufferEnable,
I_Data => R_P0_Data_ID,
O_Data => O_P0_ID
);
-----------------------
I_P1_InBufferCtrl : entity work.PipelineController
generic map(
G_PipelineStages => G_P1_BufferStages
)
port map(
I_CLK => I_CLK,
I_CE => I_CE,
O_Enable => S_P1_InBufferEnable,
I_Valid => I_P1_Address_Valid,
O_Ready => O_P1_Address_Ready,
O_Valid => S_P1_Address_Valid,
I_Ready => C_P1_Address_Ready
);
I_P1_InBuffer_Data : entity work.PipelineRegister
generic map(
G_PipelineStages => G_P1_BufferStages,
G_Width => G_Address_Width,
G_RegisterBalancing => "forward"
)
port map(
I_CLK => I_CLK,
I_Enable => S_P1_InBufferEnable,
I_Data => I_P1_Address,
O_Data => R_P1_Address
);
I_P1_InBuffer_ID : entity work.PipelineRegister
generic map(
G_PipelineStages => G_P1_BufferStages,
G_Width => G_P1_ID_Width,
G_RegisterBalancing => "forward"
)
port map(
I_CLK => I_CLK,
I_Enable => S_P1_InBufferEnable,
I_Data => I_P1_ID,
O_Data => R_P1_Address_ID
);
C_P1_Address_Ready <= not R_P1_Data_Valid;
P_P1_Flags : process (I_CLK)
begin
if rising_edge(I_CLK) then
if I_CE = '1' then
if S_P1_Address_Valid = '1' and C_P1_Address_Ready = '1' then
R_P1_Data_Valid <= '1';
R_P1_Data_ID <= R_P1_Address_ID;
end if;
if S_P1_Data_Ready = '1' and R_P1_Data_Valid = '1' then
R_P1_Data_Valid <= '0';
end if;
end if;
end if;
end process;
P_P1_Read : process (I_CLK)
begin
if rising_edge(I_CLK) then
if I_CE = '1' then
R_P1_Data <= Rom(to_integer(unsigned(R_P1_Address)));
end if;
end if;
end process;
I_P1_OutBufferCtrl : entity work.PipelineController
generic map(
G_PipelineStages => G_P1_BufferStages
)
port map(
I_CLK => I_CLK,
I_CE => I_CE,
O_Enable => S_P1_OutBufferEnable,
I_Valid => R_P1_Data_Valid,
O_Ready => S_P1_Data_Ready,
O_Valid => O_P1_Data_Valid,
I_Ready => I_P1_Data_Ready
);
I_P1_OutBuffer : entity work.PipelineRegister
generic map(
G_PipelineStages => G_P1_BufferStages,
G_Width => G_Data_Width,
G_RegisterBalancing => "backward"
)
port map(
I_CLK => I_CLK,
I_Enable => S_P1_OutBufferEnable,
I_Data => R_P1_Data,
O_Data => O_P1_Data
);
I_P1_OutBuffer_ID : entity work.PipelineRegister
generic map(
G_PipelineStages => G_P1_BufferStages,
G_Width => G_P1_ID_Width,
G_RegisterBalancing => "backward"
)
port map(
I_CLK => I_CLK,
I_Enable => S_P1_OutBufferEnable,
I_Data => R_P1_Data_ID,
O_Data => O_P1_ID
);
end architecture;

144
src/Scheduler.vhd Normal file
View File

@@ -0,0 +1,144 @@
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use ieee.math_real.all;
entity AXI_Handshaking_Scheduler_4 is
generic (
G_DataWidth : integer := 32
);
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;
--@ @virtualbus P0 @dir in P0 interface
I_P0_Valid : in std_logic := '0';
O_P0_Ready : out std_logic := '0';
I_P0_Data : in std_logic_vector(G_DataWidth - 1 downto 0) := (others => '0');
--@ @end
--@ @virtualbus P1 @dir in P1 interface
I_P1_Valid : in std_logic := '0';
O_P1_Ready : out std_logic := '0';
I_P1_Data : in std_logic_vector(G_DataWidth - 1 downto 0) := (others => '0');
--@ @end
--@ @virtualbus P2 @dir in P2 interface
I_P2_Valid : in std_logic := '0';
O_P2_Ready : out std_logic := '0';
I_P2_Data : in std_logic_vector(G_DataWidth - 1 downto 0) := (others => '0');
--@ @end
--@ @virtualbus P3 @dir in P3 interface
I_P3_Valid : in std_logic := '0';
O_P3_Ready : out std_logic := '0';
I_P3_Data : in std_logic_vector(G_DataWidth - 1 downto 0) := (others => '0');
--@ @end
--@ @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(1 downto 0) := (others => '0')
--@ @end
);
end entity AXI_Handshaking_Scheduler_4;
architecture Rtl of AXI_Handshaking_Scheduler_4 is
signal R_Counter : unsigned(1 downto 0) := (others => '0');
signal C_Select : std_logic_vector(3 downto 0) := (others => '0');
signal C_Code : std_logic_vector(1 downto 0) := (others => '0');
signal C_CodeReverse : std_logic_vector(1 downto 0) := (others => '0');
begin
i_PriorityEncoder_4 : entity work.PriorityEncoder_4
port map(
I_Select => C_Select,
O_Code => C_Code
);
P_SelectMux : process (R_Counter, I_P0_Valid, I_P1_Valid, I_P2_Valid, I_P3_Valid)
begin
if R_Counter = "00" then
C_Select <= I_P0_Valid & I_P1_Valid & I_P2_Valid & I_P3_Valid;
elsif R_Counter = "01" then
C_Select <= I_P1_Valid & I_P2_Valid & I_P3_Valid & I_P0_Valid;
elsif R_Counter = "10" then
C_Select <= I_P2_Valid & I_P3_Valid & I_P0_Valid & I_P1_Valid;
elsif R_Counter = "11" then
C_Select <= I_P3_Valid & I_P0_Valid & I_P1_Valid & I_P2_Valid;
else
C_Select <= (others => '-');
end if;
end process;
P_CodeReverse : process (C_Code, R_Counter)
begin
C_CodeReverse <= std_logic_vector(unsigned(C_Code) + R_Counter);
end process;
P_OutMux : process (
C_CodeReverse, I_P0_Data, I_P1_Data, I_P2_Data, I_P3_Data,
I_P0_Valid, I_P1_Valid, I_P2_Valid, I_P3_Valid,
I_Out_Ready)
begin
O_Out_Valid <= '0';
O_P0_Ready <= '0';
O_P1_Ready <= '0';
O_P2_Ready <= '0';
O_P3_Ready <= '0';
O_Out_Data <= (others => '0');
O_Out_Address <= C_CodeReverse;
case C_CodeReverse is
when "00" =>
O_Out_Valid <= I_P0_Valid;
O_P0_Ready <= I_Out_Ready;
O_Out_Data <= I_P0_Data;
when "01" =>
O_Out_Valid <= I_P1_Valid;
O_P1_Ready <= I_Out_Ready;
O_Out_Data <= I_P1_Data;
when "10" =>
O_Out_Valid <= I_P2_Valid;
O_P2_Ready <= I_Out_Ready;
O_Out_Data <= I_P2_Data;
when "11" =>
O_Out_Valid <= I_P3_Valid;
O_P3_Ready <= I_Out_Ready;
O_Out_Data <= I_P3_Data;
when others =>
null;
end case;
end process;
P_Counter : process (I_CLK)
begin
if rising_edge(I_CLK) then
if I_CE = '1' then
if I_RST = '1' then
R_Counter <= (others => '0');
else
if I_Out_Ready = '1' then
case C_CodeReverse is
when "00" =>
R_Counter <= "01";
when "01" =>
R_Counter <= "10";
when "10" =>
R_Counter <= "11";
when "11" =>
R_Counter <= "00";
when others =>
R_Counter <= "00";
end case;
end if;
end if;
end if;
end if;
end process P_Counter;
end architecture;