Refactors vertical sprite pipeline for modularity
Reorganizes pipeline logic into distinct stages for clarity Replaces monolithic process with modular components Introduces AXI-like interface for better integration Improves readability and maintainability by renaming signals Updates visibility and offset calculations to use pipeline registers
This commit is contained in:
@@ -11,9 +11,7 @@ entity VerticalSpritePipeline is
|
||||
--@ The height of the sprite in pixels
|
||||
G_Sprite_Height : integer := 16;
|
||||
--@ Width of the sprite offset (Line address) register
|
||||
G_Offset_Width : integer := 8;
|
||||
--@ The pipeline stages for the calculating pipeline (multiply by 2 for the the latency of the pipeline)
|
||||
G_PipelineStages : integer := 2
|
||||
G_Offset_Width : integer := 8
|
||||
);
|
||||
port (
|
||||
--@ Clock signal; (**Rising edge** triggered)
|
||||
@@ -21,35 +19,44 @@ entity VerticalSpritePipeline is
|
||||
--@ Clock enable signal (**Active high**)
|
||||
I_CE : in std_logic := '1';
|
||||
|
||||
--@ @virtualbus YHitCheck-Input-Interface @dir in YHitCheck Input Interface
|
||||
--@ Indicates if the pipeline is ready to accept data. (**Active high**)
|
||||
O_Ready : out std_logic := '0';
|
||||
--@ Indicates if the pipeline is valid. (**Active high**)
|
||||
I_Valid : in std_logic := '0';
|
||||
--@ @virtualbus VSpritePipeline-OP @dir In Vertical sprite pipeline operation interfacee
|
||||
--@ AXI like ready; (**Synchronous**, **Active high**)
|
||||
O_VSpritePipeline_OP_Ready : out std_logic := '0';
|
||||
--@ AXI like valid; (**Synchronous**, **Active high**)
|
||||
I_VSpritePipeline_OP_Valid : in std_logic := '0';
|
||||
--@ The line to check if the sprite is in the line visible.
|
||||
I_YToCheck : in std_logic_vector(G_Y_Width - 1 downto 0) := (others => '0');
|
||||
I_VSpritePipeline_OP_Y_Request : in std_logic_vector(G_Y_Width - 1 downto 0) := (others => '0');
|
||||
--@ The sprite Y position to check if the sprite is in the line visible.
|
||||
I_Y : in std_logic_vector(G_Y_Width - 1 downto 0) := (others => '0');
|
||||
I_VSpritePipeline_OP_Y_Sprite : in std_logic_vector(G_Y_Width - 1 downto 0) := (others => '0');
|
||||
--@ @end
|
||||
|
||||
--@ @virtualbus YHitCheck-Output-Interface @dir out YHitCheck Output Interface
|
||||
--@ Indicates if the pipeline is ready to deliver data. (**Active high**)
|
||||
I_Ready : in std_logic := '0';
|
||||
--@ Indicates if `O_IsVisible` is valid. (**Active high**)
|
||||
O_Valid : out std_logic := '0';
|
||||
--@ @virtualbus VSpritePipeline-Result @dir Out Vertical sprite pipeline result interface
|
||||
--@ AXI like ready; (**Synchronous**, **Active high**)
|
||||
I_VSpritePipeline_Ready : in std_logic := '0';
|
||||
--@ AXI like valid; (**Synchronous**, **Active high**)
|
||||
O_VSpritePipeline_Valid : out std_logic := '0';
|
||||
--@ Indicates if the sprite is visible in the line.
|
||||
O_IsVisible : out std_logic := '0';
|
||||
O_VSpritePipeline_IsVisible : out std_logic := '0';
|
||||
--@ The calculated offset address of the sprite.
|
||||
O_Offset : out std_logic_vector(G_Offset_Width - 1 downto 0) := (others => '0')
|
||||
O_VSpritePipeline_Offset : out std_logic_vector(G_Offset_Width - 1 downto 0) := (others => '0')
|
||||
--@ @end
|
||||
);
|
||||
end entity VerticalSpritePipeline;
|
||||
|
||||
architecture Rtl of VerticalSpritePipeline is
|
||||
--@ Line to check if the sprite is in the line visible
|
||||
signal R_YToCheck : std_logic_vector(G_Y_Width - 1 downto 0) := (others => '0');
|
||||
--@ The sprite Y position to check if the sprite is in the line visible
|
||||
signal R_SpriteY : std_logic_vector(G_Y_Width - 1 downto 0) := (others => '0');
|
||||
--@ (Stage 0) Line to check if the sprite is in the line visible
|
||||
signal R0_Y_Request : std_logic_vector(G_Y_Width - 1 downto 0) := (others => '0');
|
||||
--@ (Stage 1) Line to check if the sprite is in the line visible
|
||||
signal R1_Y_Request : std_logic_vector(G_Y_Width - 1 downto 0) := (others => '0');
|
||||
--@ (Stage 0) The sprite Y position to check if the sprite is in the line visible
|
||||
signal R0_Y_Sprite : std_logic_vector(G_Y_Width - 1 downto 0) := (others => '0');
|
||||
--@ (Stage 1) The sprite Y position to check if the sprite is in the line visible
|
||||
signal R1_Y_Sprite : std_logic_vector(G_Y_Width - 1 downto 0) := (others => '0');
|
||||
|
||||
--@ The bottom Y position of the sprite
|
||||
signal C_Y_Bottom_Sprite : std_logic_vector(G_Y_Width - 1 downto 0) := (others => '0');
|
||||
--@ (Stage 1) The bottom Y position of the sprite
|
||||
signal R1_Y_Bottom_Sprite : std_logic_vector(G_Y_Width - 1 downto 0) := (others => '0');
|
||||
|
||||
--@ Calculated visibility signal
|
||||
signal C_IsVisible : std_logic := '0';
|
||||
@@ -57,106 +64,114 @@ architecture Rtl of VerticalSpritePipeline is
|
||||
signal C_Offset : std_logic_vector(G_Offset_Width - 1 downto 0) := (others => '0');
|
||||
|
||||
--@ Pipeline enable signal
|
||||
signal S_CalculatingPipeline_Enable : std_logic := '0';
|
||||
signal O_VSpritePipeline_Ctrl_Enable : std_logic := '0';
|
||||
begin
|
||||
|
||||
--@ Pipeline controller for the calculating pipeline
|
||||
I_CalculatingPipelineCtrl : entity work.PipelineController
|
||||
INST_VSpritePipeline_Ctrl : entity work.PipelineController
|
||||
generic map(
|
||||
G_PipelineStages => G_PipelineStages * 2
|
||||
G_PipelineStages => 3
|
||||
)
|
||||
port map(
|
||||
I_CLK => I_CLK,
|
||||
I_CE => I_CE,
|
||||
O_Enable => S_CalculatingPipeline_Enable,
|
||||
I_Valid => I_Valid,
|
||||
O_Ready => O_Ready,
|
||||
O_Valid => O_Valid,
|
||||
I_Ready => I_Ready
|
||||
O_Enable => O_VSpritePipeline_Ctrl_Enable,
|
||||
I_Valid => I_VSpritePipeline_OP_Valid,
|
||||
O_Ready => O_VSpritePipeline_OP_Ready,
|
||||
O_Valid => O_VSpritePipeline_Valid,
|
||||
I_Ready => I_VSpritePipeline_Ready
|
||||
);
|
||||
|
||||
--@ Input register for the Y position of the sprite
|
||||
I_Y_InputRegister : entity work.PipelineRegister
|
||||
INST0_VSpritePipeline_Y_Sprite : entity work.PipelineRegister
|
||||
generic map(
|
||||
G_PipelineStages => G_PipelineStages,
|
||||
G_Width => G_Y_Width,
|
||||
G_RegisterBalancing => "forward"
|
||||
G_Width => G_Y_Width
|
||||
)
|
||||
port map(
|
||||
I_CLK => I_CLK,
|
||||
I_Enable => S_CalculatingPipeline_Enable,
|
||||
I_Data => I_Y,
|
||||
O_Data => R_SpriteY
|
||||
I_Enable => O_VSpritePipeline_Ctrl_Enable,
|
||||
I_Data => I_VSpritePipeline_OP_Y_Sprite,
|
||||
O_Data => R0_Y_Sprite
|
||||
);
|
||||
|
||||
--@ Input register for the line to check if the sprite is in the line visible
|
||||
I_YToCheck_InputRegister : entity work.PipelineRegister
|
||||
INST0_VSpritePipeline_Y_Request : entity work.PipelineRegister
|
||||
generic map(
|
||||
G_PipelineStages => G_PipelineStages,
|
||||
G_Width => G_Y_Width,
|
||||
G_RegisterBalancing => "forward"
|
||||
G_Width => G_Y_Width
|
||||
)
|
||||
port map(
|
||||
I_CLK => I_CLK,
|
||||
I_Enable => S_CalculatingPipeline_Enable,
|
||||
I_Data => I_YToCheck,
|
||||
O_Data => R_YToCheck
|
||||
I_Enable => O_VSpritePipeline_Ctrl_Enable,
|
||||
I_Data => I_VSpritePipeline_OP_Y_Request,
|
||||
O_Data => R0_Y_Request
|
||||
);
|
||||
|
||||
--@ Combinatory process to calculate the visibility and offset of the sprite.
|
||||
P_CalculateVisibility : process (R_SpriteY, R_YToCheck)
|
||||
variable V_SpriteY : unsigned(R_SpriteY'range);
|
||||
variable V_YToCheck : unsigned(R_YToCheck'range);
|
||||
variable V_SpriteYBottom : unsigned(R_SpriteY'range);
|
||||
variable V_OffsetLine : integer;
|
||||
variable V_Offset : unsigned(C_Offset'range);
|
||||
begin
|
||||
V_SpriteY := unsigned(R_SpriteY);
|
||||
V_YToCheck := unsigned(R_YToCheck);
|
||||
V_SpriteYBottom := V_SpriteY + to_unsigned(G_Sprite_Height - 1, R_SpriteY'length);
|
||||
--@ Calculate the bottom Y position of the sprite
|
||||
C_Y_Bottom_Sprite <= std_logic_vector(
|
||||
unsigned(R0_Y_Sprite) + to_unsigned(G_Sprite_Height - 1, G_Y_Width)
|
||||
);
|
||||
|
||||
if V_YToCheck >= V_SpriteY and V_YToCheck <= V_SpriteYBottom then
|
||||
C_IsVisible <= '1';
|
||||
else
|
||||
C_IsVisible <= '0';
|
||||
end if;
|
||||
|
||||
V_OffsetLine := to_integer(V_YToCheck - V_SpriteY);
|
||||
-- pragma translate_off
|
||||
if V_OffsetLine < 0 or V_OffsetLine >= K_SPRITE_ROW_OFFSETS'length then
|
||||
V_OffsetLine := 0;
|
||||
end if;
|
||||
-- pragma translate_on
|
||||
|
||||
V_Offset := to_unsigned(K_SPRITE_ROW_OFFSETS(V_OffsetLine), C_Offset'length);
|
||||
C_Offset <= std_logic_vector(V_Offset);
|
||||
end process;
|
||||
|
||||
--@ Output register for the visibility of the sprite
|
||||
I_IsVisible_OutputRegister : entity work.PipelineRegister
|
||||
INST_VSpritePipeline_Y_Bottom_Sprite : entity work.PipelineRegister
|
||||
generic map(
|
||||
G_PipelineStages => G_PipelineStages,
|
||||
G_Width => 1,
|
||||
G_RegisterBalancing => "backward"
|
||||
G_Width => G_Y_Width
|
||||
)
|
||||
port map(
|
||||
I_CLK => I_CLK,
|
||||
I_Enable => S_CalculatingPipeline_Enable,
|
||||
I_Enable => O_VSpritePipeline_Ctrl_Enable,
|
||||
I_Data => C_Y_Bottom_Sprite,
|
||||
O_Data => R1_Y_Bottom_Sprite
|
||||
);
|
||||
|
||||
INST1_VSpritePipeline_Y_Sprite : entity work.PipelineRegister
|
||||
generic map(
|
||||
G_Width => G_Y_Width
|
||||
)
|
||||
port map(
|
||||
I_CLK => I_CLK,
|
||||
I_Enable => O_VSpritePipeline_Ctrl_Enable,
|
||||
I_Data => R0_Y_Sprite,
|
||||
O_Data => R1_Y_Sprite
|
||||
);
|
||||
|
||||
INST1_VSpritePipeline_Y_Request : entity work.PipelineRegister
|
||||
generic map(
|
||||
G_Width => G_Y_Width
|
||||
)
|
||||
port map(
|
||||
I_CLK => I_CLK,
|
||||
I_Enable => O_VSpritePipeline_Ctrl_Enable,
|
||||
I_Data => R0_Y_Request,
|
||||
O_Data => R1_Y_Request
|
||||
);
|
||||
|
||||
--@ Calculate the visibility of the sprite
|
||||
C_IsVisible <= '1' when (
|
||||
(unsigned(R1_Y_Request) >= unsigned(R1_Y_Sprite)) and
|
||||
(unsigned(R1_Y_Request) <= unsigned(R1_Y_Bottom_Sprite))
|
||||
) else '0';
|
||||
|
||||
--@ Calculate the offset address of the sprite
|
||||
C_Offset <= std_logic_vector(
|
||||
to_unsigned(
|
||||
K_SPRITE_ROW_OFFSETS(to_integer(unsigned(R1_Y_Request) - unsigned(R1_Y_Sprite))),
|
||||
C_Offset'length)
|
||||
);
|
||||
|
||||
INST_IsVisible_OutputRegister : entity work.PipelineRegister
|
||||
generic map(
|
||||
G_Width => 1
|
||||
)
|
||||
port map(
|
||||
I_CLK => I_CLK,
|
||||
I_Enable => O_VSpritePipeline_Ctrl_Enable,
|
||||
I_Data(0) => C_IsVisible,
|
||||
O_Data(0) => O_IsVisible
|
||||
O_Data(0) => O_VSpritePipeline_IsVisible
|
||||
);
|
||||
|
||||
--@ Output register for the offset of the sprite
|
||||
I_Offset_OutputRegister : entity work.PipelineRegister
|
||||
INST_Offset_OutputRegister : entity work.PipelineRegister
|
||||
generic map(
|
||||
G_PipelineStages => G_PipelineStages,
|
||||
G_Width => G_Offset_Width,
|
||||
G_RegisterBalancing => "backward"
|
||||
G_Width => G_Offset_Width
|
||||
)
|
||||
port map(
|
||||
I_CLK => I_CLK,
|
||||
I_Enable => S_CalculatingPipeline_Enable,
|
||||
I_Enable => O_VSpritePipeline_Ctrl_Enable,
|
||||
I_Data => C_Offset,
|
||||
O_Data => O_Offset
|
||||
O_Data => O_VSpritePipeline_Offset
|
||||
);
|
||||
end architecture;
|
||||
|
Reference in New Issue
Block a user