Files
SpriteChannel/src/SpriteChannel.vhd
MaxP 3c641355fc 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.
2025-04-21 15:25:12 +00:00

233 lines
10 KiB
VHDL

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;