Introduces sprite channel processing pipeline
Adds modules for sprite operations, including opcode decoding, register handling, and vertical pipeline calculations. Replaces legacy scheduler with a more modular and efficient design. Updates constraints for clock timing. Enhances sprite rendering pipeline with improved modularity and scalability.
This commit is contained in:
232
src/SpriteChannel.vhd
Normal file
232
src/SpriteChannel.vhd
Normal file
@@ -0,0 +1,232 @@
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.numeric_std.all;
|
||||
use ieee.math_real.all;
|
||||
|
||||
entity SpriteChannel is
|
||||
generic (
|
||||
--@ Data width of the operation data.
|
||||
G_OPCodeData_Width : integer := 10;
|
||||
--@ 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 Y position (Line) register
|
||||
G_Y_Width : integer := 10;
|
||||
--@ The height of the sprite in pixels
|
||||
G_Sprite_Height : integer := 16;
|
||||
--@ The width of the sprite in pixels
|
||||
G_Sprite_Width : integer := 16
|
||||
);
|
||||
port (
|
||||
--@ Clock signal; **Rising edge** triggered
|
||||
I_CLK : in std_logic;
|
||||
--@ Clock Enable signal
|
||||
I_CE : in std_logic;
|
||||
--@ Synchronous reset signal
|
||||
I_RST : in std_logic;
|
||||
|
||||
--@ @virtualbus Operation-Write @dir in Operation Write Interface
|
||||
--@ Indicates if the `OPCode` and `OPData` are valid. (**Active high**)
|
||||
I_OP_Valid : in std_logic := '0';
|
||||
--@ Indicates if the decoder is ready to accept data. (**Active high**)
|
||||
O_OP_Ready : out std_logic := '0';
|
||||
--@ Operation code for the sprite channel
|
||||
I_OP_Code : in std_logic_vector(3 downto 0) := (others => '0');
|
||||
--@ Data to be used with the operation code.
|
||||
I_OP_Data : in std_logic_vector(G_OPCodeData_Width - 1 downto 0) := (others => '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(7 downto 0)
|
||||
--@ @end
|
||||
|
||||
);
|
||||
end entity;
|
||||
|
||||
architecture RTL of SpriteChannel 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 : std_logic_vector(G_X_Width - 1 downto 0) := (others => '0');
|
||||
signal R_Y : std_logic_vector(G_Y_Width - 1 downto 0) := (others => '0');
|
||||
signal R_IsVisible : std_logic := '0';
|
||||
|
||||
signal OI_P0_Address_Valid : std_logic := '0';
|
||||
signal IO_P0_Address_Ready : std_logic := '0';
|
||||
signal OI_P0_Address : std_logic_vector(G_Index_Width + G_Offset_Width - 1 downto 0) := (others => '0');
|
||||
|
||||
signal IO_P0_Data_Valid : std_logic := '0';
|
||||
signal OI_P0_Data_Ready : std_logic := '0';
|
||||
signal IO_P0_Data : std_logic_vector(7 downto 0) := (others => '0');
|
||||
|
||||
signal OI_Register_Index_WE : std_logic := '0';
|
||||
signal OI_Register_Index : std_logic_vector(G_Index_Width - 1 downto 0) := (others => '0');
|
||||
signal OI_Register_Offset_WE : std_logic := '0';
|
||||
signal OI_Register_Offset : std_logic_vector(G_Offset_Width - 1 downto 0) := (others => '0');
|
||||
signal OI_Register_X_We : std_logic := '0';
|
||||
signal OI_Register_X : std_logic_vector(G_X_Width - 1 downto 0) := (others => '0');
|
||||
signal OI_Register_Y_WE : std_logic := '0';
|
||||
signal OI_Register_Y : std_logic_vector(G_Y_Width - 1 downto 0) := (others => '0');
|
||||
signal OI_IsVisible_WE : std_logic := '0';
|
||||
signal OI_IsVisible : std_logic := '0';
|
||||
|
||||
signal I_YHitCheck_Ready : std_logic := '0';
|
||||
signal I_YHitCheck_Valid : std_logic := '0';
|
||||
signal I_YHitCheck_IsVisible : std_logic := '0';
|
||||
signal I_YHitCheck_Offset : std_logic_vector(G_Offset_Width - 1 downto 0) := (others => '0');
|
||||
signal O_YHitCheck_Valid : std_logic := '0';
|
||||
signal O_YHitCheck_YToCheck : std_logic_vector(G_Y_Width - 1 downto 0) := (others => '0');
|
||||
signal O_YHitCheck_Ready : std_logic := '0';
|
||||
|
||||
signal OI_CalcPipeline_Valid : std_logic := '0';
|
||||
signal IO_CalcPipeline_Ready : std_logic := '0';
|
||||
signal OI_CalcPipeline_X_Request : std_logic_vector(G_X_Width - 1 downto 0) := (others => '0');
|
||||
begin
|
||||
i_RegisterFile : entity work.RegisterFile
|
||||
generic map(
|
||||
G_Index_Width => G_Index_Width,
|
||||
G_Offset_Width => G_Offset_Width,
|
||||
G_X_Width => G_X_Width,
|
||||
G_Y_Width => G_Y_Width
|
||||
)
|
||||
port map(
|
||||
I_CLK => I_CLK,
|
||||
I_CE => I_CE,
|
||||
I_RST => I_RST,
|
||||
I_Index_WE => OI_Register_Index_WE,
|
||||
I_Index => OI_Register_Index,
|
||||
I_Offset_WE => OI_Register_Offset_WE,
|
||||
I_Offset => OI_Register_Offset,
|
||||
I_X_We => OI_Register_X_We,
|
||||
I_X => OI_Register_X,
|
||||
I_Y_WE => OI_Register_Y_WE,
|
||||
I_Y => OI_Register_Y,
|
||||
I_IsVisible_WE => OI_IsVisible_WE,
|
||||
I_IsVisible => OI_IsVisible,
|
||||
O_Index => R_Index,
|
||||
O_Offset => R_Offset,
|
||||
O_X => R_X,
|
||||
O_Y => R_Y,
|
||||
O_IsVisible => R_IsVisible
|
||||
);
|
||||
|
||||
i_OPDecoder : entity work.OPDecoder
|
||||
generic map(
|
||||
G_OPCodeData_Width => G_OPCodeData_Width,
|
||||
G_Index_Width => G_Index_Width,
|
||||
G_Offset_Width => G_Offset_Width,
|
||||
G_X_Width => G_X_Width,
|
||||
G_Y_Width => G_Y_Width
|
||||
)
|
||||
port map(
|
||||
I_CLK => I_CLK,
|
||||
I_CE => I_CE,
|
||||
I_RST => I_RST,
|
||||
I_OP_Valid => I_OP_Valid,
|
||||
O_OP_Ready => O_OP_Ready,
|
||||
I_OP_Code => I_OP_Code,
|
||||
I_OP_Data => I_OP_Data,
|
||||
O_Register_Index_WE => OI_Register_Index_WE,
|
||||
O_Register_Index => OI_Register_Index,
|
||||
O_Register_Offset_WE => OI_Register_Offset_WE,
|
||||
O_Register_Offset => OI_Register_Offset,
|
||||
O_Register_X_We => OI_Register_X_We,
|
||||
O_Register_X => OI_Register_X,
|
||||
O_Register_Y_WE => OI_Register_Y_WE,
|
||||
O_Register_Y => OI_Register_Y,
|
||||
O_IsVisible_WE => OI_IsVisible_WE,
|
||||
O_IsVisible => OI_IsVisible,
|
||||
|
||||
I_IsVisible => R_IsVisible,
|
||||
|
||||
I_YHitCheck_Ready => I_YHitCheck_Ready,
|
||||
O_YHitCheck_Valid => O_YHitCheck_Valid,
|
||||
O_YHitCheck_YToCheck => O_YHitCheck_YToCheck,
|
||||
O_YHitCheck_Ready => O_YHitCheck_Ready,
|
||||
I_YHitCheck_Valid => I_YHitCheck_Valid,
|
||||
I_YHitCheck_IsVisible => I_YHitCheck_IsVisible,
|
||||
I_YHitCheck_Offset => I_YHitCheck_Offset,
|
||||
|
||||
O_HSpritePipeline_Valid => OI_CalcPipeline_Valid,
|
||||
I_HSpritePipeline_Ready => IO_CalcPipeline_Ready,
|
||||
O_HSpritePipeline_X_Request => OI_CalcPipeline_X_Request
|
||||
);
|
||||
|
||||
i_YHitCheck : entity work.VerticalSpritePipeline
|
||||
generic map(
|
||||
G_Y_Width => G_Y_Width,
|
||||
G_Sprite_Height => G_Sprite_Height,
|
||||
G_Offset_Width => G_Offset_Width,
|
||||
G_PipelineStages => 2
|
||||
)
|
||||
port map(
|
||||
I_CLK => I_CLK,
|
||||
I_CE => I_CE,
|
||||
O_Ready => I_YHitCheck_Ready,
|
||||
I_Valid => O_YHitCheck_Valid,
|
||||
I_YToCheck => O_YHitCheck_YToCheck,
|
||||
I_Y => R_Y,
|
||||
I_Ready => O_YHitCheck_Ready,
|
||||
O_Valid => I_YHitCheck_Valid,
|
||||
O_IsVisible => I_YHitCheck_IsVisible,
|
||||
O_Offset => I_YHitCheck_Offset
|
||||
);
|
||||
|
||||
i_Rom : entity work.Rom
|
||||
generic map(
|
||||
G_Address_Width => 13,
|
||||
G_Data_Width => 8,
|
||||
G_P0_BufferStages => 1,
|
||||
G_P0_ID_Width => 0,
|
||||
G_P1_BufferStages => 0,
|
||||
G_P1_ID_Width => 0,
|
||||
G_RomType => "Block"
|
||||
)
|
||||
port map(
|
||||
I_CLK => I_CLK,
|
||||
I_CE => I_CE,
|
||||
I_P0_Address_Valid => OI_P0_Address_Valid,
|
||||
O_P0_Address_Ready => IO_P0_Address_Ready,
|
||||
I_P0_Address => OI_P0_Address,
|
||||
O_P0_Data_Valid => IO_P0_Data_Valid,
|
||||
I_P0_Data_Ready => OI_P0_Data_Ready,
|
||||
O_P0_Data => IO_P0_Data
|
||||
);
|
||||
|
||||
i_CalcPipeline : entity work.HorizontalSpritePipeline
|
||||
generic map(
|
||||
G_Index_Width => G_Index_Width,
|
||||
G_Offset_Width => G_Offset_Width,
|
||||
G_X_Width => G_X_Width,
|
||||
G_Rom_Width => 8,
|
||||
G_Pixel_Width => 8
|
||||
)
|
||||
port map(
|
||||
I_CLK => I_CLK,
|
||||
I_CE => I_CE,
|
||||
I_RST => I_RST,
|
||||
I_OP_Valid => OI_CalcPipeline_Valid,
|
||||
O_OP_Ready => IO_CalcPipeline_Ready,
|
||||
I_OP_X_Request => OI_CalcPipeline_X_Request,
|
||||
I_OP_Index => R_Index,
|
||||
I_OP_Offset => R_Offset,
|
||||
I_OP_X_Sprite => R_X,
|
||||
O_Rom_Valid => OI_P0_Address_Valid,
|
||||
I_Rom_Ready => IO_P0_Address_Ready,
|
||||
O_Rom_Address => OI_P0_Address,
|
||||
I_Rom_Valid => IO_P0_Data_Valid,
|
||||
O_Rom_Ready => OI_P0_Data_Ready,
|
||||
I_Rom_Data => IO_P0_Data,
|
||||
O_Pixel_Valid => O_Pixel_Valid,
|
||||
I_Pixel_Ready => I_Pixel_Ready,
|
||||
O_Pixel_Data => O_Pixel_Data
|
||||
);
|
||||
|
||||
end architecture RTL;
|
Reference in New Issue
Block a user