diff --git a/libs/PriorityEncoders.vhd b/libs/PriorityEncoders.vhd
deleted file mode 100644
index 0af3b3c..0000000
--- a/libs/PriorityEncoders.vhd
+++ /dev/null
@@ -1,345 +0,0 @@
-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;
diff --git a/test/OPDecoder_tb.vhd b/test/OPDecoder_tb.vhd
new file mode 100644
index 0000000..a83bff9
--- /dev/null
+++ b/test/OPDecoder_tb.vhd
@@ -0,0 +1,221 @@
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+use work.OPCodes.all;
+use std.env.stop;
+
+entity OPDecoder_tb is
+end entity OPDecoder_tb;
+
+architecture bench of OPDecoder_tb is
+ -- Clock period
+ constant K_CLKPeriod : time := 10 ns;
+ -- Generics
+ constant G_OPCodeData_Width : integer := 10;
+ constant G_ROM_DataWidth : integer := 16;
+ constant G_Index_Width : integer := 6;
+ constant G_Offset_Width : integer := 4;
+ constant G_LineData_Width : integer := 16;
+ constant G_X_Width : integer := 10;
+ constant G_Y_Width : integer := 10;
+ constant G_Sprite_Height : integer := 16;
+ constant G_PipelineStages : integer := 2;
+
+ -- Ports
+ signal I_CLK : std_logic;
+ signal I_CE : std_logic;
+ signal I_RST : std_logic;
+ signal I_OP_Valid : std_logic := '0';
+ signal O_OP_Ready : std_logic := '0';
+ signal I_OP_Code : std_logic_vector(3 downto 0) := (others => '0');
+ signal I_OP_Data : std_logic_vector(G_OPCodeData_Width - 1 downto 0) := (others => '0');
+ signal O_Register_Index_WE : std_logic := '0';
+ signal O_Register_Index : std_logic_vector(G_Index_Width - 1 downto 0) := (others => '0');
+ signal O_Register_Offset_WE : std_logic := '0';
+ signal O_Register_Offset : std_logic_vector(G_Offset_Width - 1 downto 0) := (others => '0');
+ signal O_Register_X_We : std_logic := '0';
+ signal O_Register_X : std_logic_vector(G_X_Width - 1 downto 0) := (others => '0');
+ signal O_Register_Y_WE : std_logic := '0';
+ signal O_Register_Y : std_logic_vector(G_Y_Width - 1 downto 0) := (others => '0');
+ signal O_Register_CachedLineData_WE : std_logic := '0';
+ signal O_Register_CachedLineData : std_logic_vector(G_LineData_Width - 1 downto 0) := (others => '0');
+ signal O_Register_CacheValid_WE : std_logic := '0';
+ signal O_Register_CacheValid : std_logic := '0';
+ signal I_YHitCheck_Ready : std_logic := '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 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_Rom_Valid : std_logic := '0';
+ signal I_Rom_Ready : std_logic := '0';
+ signal I_Rom_Valid : std_logic := '0';
+ signal O_Rom_Ready : std_logic := '0';
+ signal I_Rom_Data : std_logic_vector(G_ROM_DataWidth - 1 downto 0) := (others => '0');
+ signal O_CalcPipeline_Valid : std_logic := '0';
+ signal I_CalcPipeline_Ready : std_logic := '0';
+ signal O_CalcPipeline_X : std_logic_vector(G_X_Width - 1 downto 0) := (others => '0');
+
+ signal R1, R2 : std_logic := '0';
+
+ signal TestDone : boolean := false;
+begin
+
+ ClockProc : process
+ begin
+ while TestDone = false loop
+ I_CLK <= '0';
+ wait for K_CLKPeriod / 2;
+ I_CLK <= '1';
+ wait for K_CLKPeriod / 2;
+ end loop;
+
+ I_CLK <= '0';
+ stop(0);
+ wait;
+ end process;
+
+ i_OPDecoder : entity work.OPDecoder
+ generic map(
+ G_OPCodeData_Width => G_OPCodeData_Width,
+ G_ROM_DataWidth => G_ROM_DataWidth,
+ G_Index_Width => G_Index_Width,
+ G_Offset_Width => G_Offset_Width,
+ G_LineData_Width => G_LineData_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 => O_Register_Index_WE,
+ O_Register_Index => O_Register_Index,
+ O_Register_Offset_WE => O_Register_Offset_WE,
+ O_Register_Offset => O_Register_Offset,
+ O_Register_X_We => O_Register_X_We,
+ O_Register_X => O_Register_X,
+ O_Register_Y_WE => O_Register_Y_WE,
+ O_Register_Y => O_Register_Y,
+ O_Register_CachedLineData_WE => O_Register_CachedLineData_WE,
+ O_Register_CachedLineData => O_Register_CachedLineData,
+ O_Register_CacheValid_WE => O_Register_CacheValid_WE,
+ O_Register_CacheValid => O_Register_CacheValid,
+ 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_Rom_Valid => O_Rom_Valid,
+ I_Rom_Ready => I_Rom_Ready,
+ I_Rom_Valid => I_Rom_Valid,
+ O_Rom_Ready => O_Rom_Ready,
+ I_Rom_Data => I_Rom_Data,
+ O_HSpritePipeline_Valid => O_CalcPipeline_Valid,
+ I_HSpritePipeline_Ready => I_CalcPipeline_Ready,
+ O_HSpritePipeline_X_Request => O_CalcPipeline_X
+ );
+
+ I_CalcPipeline_Ready <= O_CalcPipeline_Valid;
+
+ 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 => G_PipelineStages
+ )
+ 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 => "0000000000",
+ I_Ready => O_YHitCheck_Ready,
+ O_Valid => I_YHitCheck_Valid,
+ O_IsVisible => I_YHitCheck_IsVisible,
+ O_Offset => I_YHitCheck_Offset
+ );
+
+ StimulusProc : process
+ type T_OpTest is record
+ Code : std_logic_vector(3 downto 0);
+ Data : std_logic_vector(G_OPCodeData_Width - 1 downto 0);
+ Name : string(1 to 20);
+ end record;
+
+ type T_OpTestArray is array (natural range <>) of T_OpTest;
+
+ constant TestCases : T_OpTestArray := (
+ 0 => (K_OP_NOP, (others => '0'), "NOP "),
+ 1 => (K_OP_SET_ID, std_logic_vector(to_unsigned(2, G_OPCodeData_Width)), "SET_ID "),
+ 2 => (K_OP_SET_X, std_logic_vector(to_unsigned(3, G_OPCodeData_Width)), "SET_X "),
+ 3 => (K_OP_SET_Y, std_logic_vector(to_unsigned(4, G_OPCodeData_Width)), "SET_Y "),
+ 4 => (K_OP_CLEAR_ALL, (others => '1'), "CLEAR_ALL "),
+ 6 => (K_OP_REQ_ROW_DATA, std_logic_vector(to_unsigned(5, G_OPCodeData_Width)), "REQ_ROW_DATA "),
+ 5 => (K_OP_NEWLINE, std_logic_vector(to_unsigned(1, G_Y_Width)), "NEWLINE ")
+ );
+
+ variable i : integer;
+ begin
+ -- Init
+ I_RST <= '1';
+ I_CE <= '1';
+ wait for K_CLKPeriod * 2;
+ I_RST <= '0';
+ wait for K_CLKPeriod * 2;
+
+ for i in TestCases'range loop
+ -- Warte auf Ready
+ wait until rising_edge(I_CLK);
+ while O_OP_Ready /= '1' loop
+ wait until rising_edge(I_CLK);
+ end loop;
+
+ I_OP_Code <= TestCases(i).Code;
+ I_OP_Data <= TestCases(i).Data;
+ I_OP_Valid <= '1';
+
+ wait until rising_edge(I_CLK);
+ I_OP_Valid <= '0';
+
+ -- Einfach ein bisschen warten, bis Modul durch ist
+ -- wait for K_CLKPeriod * 5;
+
+ report "Opcode-Test: " & TestCases(i).Name & " abgeschlossen." severity note;
+ end loop;
+
+ report "Alle OPCodes getestet." severity note;
+ TestDone <= true;
+ wait;
+ end process;
+
+ -- ROM Simulation: immer gültig, gibt X"FFFF" zurück
+ RomProcess : process (I_CLK)
+ begin
+ if rising_edge(I_CLK) then
+ if I_CE = '1' then
+ -- Standard: nichts tun
+ I_Rom_Valid <= '0';
+ I_Rom_Data <= (others => '0');
+
+ -- Prüfen, ob Decoder Daten anfordert
+ if O_Rom_Valid = '1' then
+ I_Rom_Valid <= '1';
+ I_Rom_Data <= (others => '1'); -- z.B. X"FFFF"
+ end if;
+ end if;
+ end if;
+ end process;
+
+ -- ROM ist immer bereit
+ I_Rom_Ready <= '1';
+end architecture;
diff --git a/test/RegisterFile_tb.vhd.bak b/test/RegisterFile_tb.vhd.bak
new file mode 100644
index 0000000..2e682af
--- /dev/null
+++ b/test/RegisterFile_tb.vhd.bak
@@ -0,0 +1,176 @@
+
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+use std.env.stop;
+
+entity SpriteChannel_RegisterFile_tb is
+end;
+
+architecture bench of SpriteChannel_RegisterFile_tb is
+ -- Clock period
+ constant K_CLKPeriod : time := 10 ns;
+
+ -- Generics
+ constant G_SpriteIDWidth : integer := 10;
+ constant G_SpriteLineWidth : integer := 16;
+ constant G_XWidth : integer := 10;
+ constant G_YWidth : integer := 10;
+
+ -- Ports
+ signal I_CLK : std_logic;
+ signal I_CE : std_logic;
+ signal I_RST : std_logic;
+ signal I_SpriteID_WE : std_logic;
+ signal I_SpriteID : std_logic_vector(G_SpriteIDWidth - 1 downto 0);
+ signal I_X_WE : std_logic;
+ signal I_X : std_logic_vector(G_XWidth - 1 downto 0);
+ signal I_Y_WE : std_logic;
+ signal I_Y : std_logic_vector(G_YWidth - 1 downto 0);
+ signal I_SpriteLine_WE : std_logic;
+ signal I_SpriteLine : std_logic_vector(G_SpriteLineWidth - 1 downto 0);
+ signal I_SpriteLineValid_WE : std_logic;
+ signal I_SpriteLineValid : std_logic;
+ signal O_SpriteID : std_logic_vector(G_SpriteIDWidth - 1 downto 0);
+ signal O_X : std_logic_vector(G_XWidth - 1 downto 0);
+ signal O_Y : std_logic_vector(G_YWidth - 1 downto 0);
+ signal O_SpriteLine : std_logic_vector(G_SpriteLineWidth - 1 downto 0);
+ signal O_SpriteLineValid : std_logic;
+
+ -- Test control signals
+ signal TestDone : boolean := false;
+
+ type T_TestCase is record
+ SpriteID : integer;
+ X : integer;
+ Y : integer;
+ SpriteLine : integer;
+ SpriteLineValid : std_logic;
+ end record;
+
+ type T_TestArray is array (natural range <>) of T_TestCase;
+
+ constant TestValues : T_TestArray := (
+ (SpriteID => 5, X => 100, Y => 200, SpriteLine => 1234, SpriteLineValid => '1'),
+ (SpriteID => 42, X => 10, Y => 20, SpriteLine => 65535, SpriteLineValid => '0'),
+ (SpriteID => 0, X => 0, Y => 0, SpriteLine => 0, SpriteLineValid => '1'),
+ (SpriteID => 1023, X => 1023, Y => 1023, SpriteLine => 1, SpriteLineValid => '1')
+ );
+begin
+
+ ClockProc : process
+ begin
+ while TestDone = false loop
+ I_CLK <= '0';
+ wait for K_CLKPeriod / 2;
+ I_CLK <= '1';
+ wait for K_CLKPeriod / 2;
+ end loop;
+
+ I_CLK <= '0';
+ stop(0);
+ wait;
+ end process;
+
+ SpriteChannel_RegisterFile_inst : entity work.RegisterFile
+ generic map(
+ G_SpriteAddrWidth => G_SpriteIDWidth,
+ G_LineData_Width => G_SpriteLineWidth,
+ G_X_Width => G_XWidth,
+ G_Y_Width => G_YWidth
+ )
+ port map(
+ I_CLK => I_CLK,
+ I_CE => I_CE,
+ I_RST => I_RST,
+ I_SpriteAddr_WE => I_SpriteID_WE,
+ I_SpriteAddr => I_SpriteID,
+ I_X_We => I_X_WE,
+ I_X => I_X,
+ I_Y_WE => I_Y_WE,
+ I_Y => I_Y,
+ I_CachedLineData_WE => I_SpriteLine_WE,
+ I_CachedLineData => I_SpriteLine,
+ I_CacheValid_WE => I_SpriteLineValid_WE,
+ I_CacheValid => I_SpriteLineValid,
+ O_SpriteAddr => O_SpriteID,
+ O_X => O_X,
+ O_Y => O_Y,
+ O_CachedRowData => O_SpriteLine,
+ O_CacheValid => O_SpriteLineValid
+ );
+
+ StimulusProc : process
+ variable i : integer;
+ begin
+ -- Init
+ i := 0;
+ I_CE <= '1';
+ I_RST <= '1';
+ I_SpriteID_WE <= '0';
+ I_SpriteID <= (others => '0');
+ I_X_WE <= '0';
+ I_X <= (others => '0');
+ I_Y_WE <= '0';
+ I_Y <= (others => '0');
+ I_SpriteLine_WE <= '0';
+ I_SpriteLine <= (others => '0');
+ I_SpriteLineValid_WE <= '0';
+ I_SpriteLineValid <= '0';
+ wait for K_CLKPeriod * 2;
+ I_RST <= '0';
+ wait for K_CLKPeriod * 2;
+
+ for i in TestValues'range loop
+ -- WRITE phase
+ I_SpriteID <= std_logic_vector(to_unsigned(TestValues(i).SpriteID, G_SpriteIDWidth));
+ I_SpriteID_WE <= '1';
+ I_X <= std_logic_vector(to_unsigned(TestValues(i).X, G_XWidth));
+ I_X_WE <= '1';
+ I_Y <= std_logic_vector(to_unsigned(TestValues(i).Y, G_YWidth));
+ I_Y_WE <= '1';
+ I_SpriteLine <= std_logic_vector(to_unsigned(TestValues(i).SpriteLine, G_SpriteLineWidth));
+ I_SpriteLine_WE <= '1';
+ I_SpriteLineValid <= TestValues(i).SpriteLineValid;
+ I_SpriteLineValid_WE <= '1';
+
+ wait until rising_edge(I_CLK);
+ -- deactivate write signals
+ I_SpriteID_WE <= '0';
+ I_X_WE <= '0';
+ I_Y_WE <= '0';
+ I_SpriteLine_WE <= '0';
+ I_SpriteLineValid_WE <= '0';
+
+ wait for K_CLKPeriod;
+
+ -- READ and CHECK
+ assert O_SpriteID = std_logic_vector(to_unsigned(TestValues(i).SpriteID, G_SpriteIDWidth))
+ report "Fehler: SpriteID falsch bei Test " & integer'image(i)
+ severity error;
+
+ assert O_X = std_logic_vector(to_unsigned(TestValues(i).X, G_XWidth))
+ report "Fehler: X falsch bei Test " & integer'image(i)
+ severity error;
+
+ assert O_Y = std_logic_vector(to_unsigned(TestValues(i).Y, G_YWidth))
+ report "Fehler: Y falsch bei Test " & integer'image(i)
+ severity error;
+
+ assert O_SpriteLine = std_logic_vector(to_unsigned(TestValues(i).SpriteLine, G_SpriteLineWidth))
+ report "Fehler: SpriteLine falsch bei Test " & integer'image(i)
+ severity error;
+
+ assert O_SpriteLineValid = TestValues(i).SpriteLineValid
+ report "Fehler: SpriteLineValid falsch bei Test " & integer'image(i)
+ severity error;
+
+ report "Test " & integer'image(i) & " erfolgreich." severity note;
+ wait for K_CLKPeriod;
+ end loop;
+
+ report "Alle Tests abgeschlossen." severity note;
+ TestDone <= true;
+ wait;
+ end process;
+end;
diff --git a/test/SpriteChannel/CalcPipeline.wcfg b/test/SpriteChannel/CalcPipeline.wcfg
new file mode 100644
index 0000000..f9419bc
--- /dev/null
+++ b/test/SpriteChannel/CalcPipeline.wcfg
@@ -0,0 +1,199 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ i_clk
+ i_clk
+
+
+ i_ce
+ i_ce
+
+
+ i_rst
+ i_rst
+
+
+ Input_OP
+ label
+
+ i_op_valid
+ i_op_valid
+
+
+ o_op_ready
+ o_op_ready
+
+
+ i_op_x_request[9:0]
+ i_op_x_request[9:0]
+ HEXRADIX
+
+
+ i_op_index[4:0]
+ i_op_index[4:0]
+ HEXRADIX
+
+
+ i_op_offset[7:0]
+ i_op_offset[7:0]
+ HEXRADIX
+
+
+ i_op_x_sprite[9:0]
+ i_op_x_sprite[9:0]
+ HEXRADIX
+
+
+
+ o_rom_valid
+ o_rom_valid
+
+
+ i_rom_ready
+ i_rom_ready
+
+
+ o_rom_address[12:0]
+ o_rom_address[12:0]
+ HEXRADIX
+
+
+ i_rom_valid
+ i_rom_valid
+
+
+ o_rom_ready
+ o_rom_ready
+
+
+ i_rom_data[7:0]
+ i_rom_data[7:0]
+ HEXRADIX
+
+
+ o_pixel_valid
+ o_pixel_valid
+
+
+ i_pixel_ready
+ i_pixel_ready
+
+
+ o_pixel_data[7:0]
+ o_pixel_data[7:0]
+ HEXRADIX
+
+
+ k_pipelinestages
+ k_pipelinestages
+
+
+ r_index[4:0]
+ r_index[4:0]
+ HEXRADIX
+
+
+ r_offset[7:0]
+ r_offset[7:0]
+ HEXRADIX
+
+
+ r_x_request[9:0]
+ r_x_request[9:0]
+ HEXRADIX
+
+
+ r_x_sprite[9:0]
+ r_x_sprite[9:0]
+ HEXRADIX
+
+
+ r_address[12:0]
+ r_address[12:0]
+
+
+ r_x_visible
+ r_x_visible
+
+
+ c_address[12:0]
+ c_address[12:0]
+ HEXRADIX
+
+
+ s_calculatingpipeline_enable
+ s_calculatingpipeline_enable
+
+
+ i_calculatingpipeline_ready
+ i_calculatingpipeline_ready
+
+
+ o_calculatingpipeline_valid
+ o_calculatingpipeline_valid
+
+
+ o_romrequest_ready
+ o_romrequest_ready
+
+
+ i_romrequest_valid
+ i_romrequest_valid
+
+
+ r_data[0:0]
+ r_data[0:0]
+ HEXRADIX
+
+ [0]
+ r_data[0]
+ HEXRADIX
+
+
+
+ r_data[0:1]
+ r_data[0:1]
+ HEXRADIX
+ true
+ #ff0000
+
+ [0]
+ r_data[0]
+ HEXRADIX
+ true
+ #ff0000
+
+
+ [1]
+ r_data[1]
+ HEXRADIX
+ true
+ #ff0000
+
+
+
+ o_enable
+ o_enable
+
+
+ r_valid[1:0]
+ r_valid[1:0]
+
+
diff --git a/test/SpriteChannel/Default.wcfg b/test/SpriteChannel/Default.wcfg
new file mode 100644
index 0000000..bb0fec4
--- /dev/null
+++ b/test/SpriteChannel/Default.wcfg
@@ -0,0 +1,292 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ i_clk
+ i_clk
+
+
+ i_ce
+ i_ce
+ true
+ #ffffff
+
+
+ i_rst
+ i_rst
+ true
+ #ffffff
+
+
+ i_op_valid
+ i_op_valid
+ true
+ #008080
+
+
+ o_op_ready
+ o_op_ready
+ true
+ #008080
+
+
+ i_op_code[3:0]
+ i_op_code[3:0]
+ true
+ #008080
+
+
+ i_op_data[9:0]
+ i_op_data[9:0]
+ true
+ #008080
+
+
+ r_index[4:0]
+ r_index[4:0]
+ true
+ #008080
+
+
+ r_offset[7:0]
+ r_offset[7:0]
+ true
+ #008080
+
+
+ r_x[9:0]
+ r_x[9:0]
+ true
+ #008080
+
+
+ r_isvisible
+ r_isvisible
+ true
+ #008080
+
+
+ oi_p0_address_valid
+ oi_p0_address_valid
+ true
+ #008080
+
+
+ io_p0_address_ready
+ io_p0_address_ready
+ true
+ #008080
+
+
+ oi_p0_address[12:0]
+ oi_p0_address[12:0]
+ UNSIGNEDDECRADIX
+ true
+ #008080
+
+
+ io_p0_data_valid
+ io_p0_data_valid
+ true
+ #008080
+
+
+ oi_p0_data_ready
+ oi_p0_data_ready
+ true
+ #008080
+
+
+ io_p0_data[7:0]
+ io_p0_data[7:0]
+ HEXRADIX
+ true
+ #008080
+
+
+ oi_register_index_we
+ oi_register_index_we
+ true
+ #008080
+
+
+ oi_register_index[4:0]
+ oi_register_index[4:0]
+ true
+ #008080
+
+
+ oi_register_offset_we
+ oi_register_offset_we
+ true
+ #008080
+
+
+ oi_register_offset[7:0]
+ oi_register_offset[7:0]
+ true
+ #008080
+
+
+ oi_register_x_we
+ oi_register_x_we
+ true
+ #008080
+
+
+ oi_register_x[9:0]
+ oi_register_x[9:0]
+ true
+ #008080
+
+
+ oi_register_y_we
+ oi_register_y_we
+ true
+ #008080
+
+
+ oi_register_y[9:0]
+ oi_register_y[9:0]
+ true
+ #008080
+
+
+ oi_isvisible_we
+ oi_isvisible_we
+ true
+ #008080
+
+
+ oi_isvisible
+ oi_isvisible
+ true
+ #008080
+
+
+ Intern
+ label
+ 128 128 255
+ 230 230 230
+
+
+ c_nextstate
+ c_nextstate
+
+
+ r_state
+ r_state
+
+
+ r_op_data[9:0]
+ r_op_data[9:0]
+ UNSIGNEDDECRADIX
+
+
+ YHitCheck
+ label
+
+ o_yhitcheck_valid
+ o_yhitcheck_valid
+ true
+ #00ff00
+
+
+ i_yhitcheck_ready
+ i_yhitcheck_ready
+ true
+ #00ff00
+
+
+ o_yhitcheck_ytocheck[9:0]
+ o_yhitcheck_ytocheck[9:0]
+ true
+ #00ff00
+ UNSIGNEDDECRADIX
+
+
+ r_y[9:0]
+ r_y[9:0]
+ true
+ #00ff00
+
+
+ o_yhitcheck_ready
+ o_yhitcheck_ready
+ true
+ #ff0000
+
+
+ i_yhitcheck_valid
+ i_yhitcheck_valid
+ true
+ #ff0000
+
+
+ i_yhitcheck_isvisible
+ i_yhitcheck_isvisible
+ true
+ #ff0000
+
+
+ i_yhitcheck_offset[7:0]
+ i_yhitcheck_offset[7:0]
+ true
+ #ff0000
+
+
+
+ oi_calcpipeline_valid
+ oi_calcpipeline_valid
+ true
+ #008080
+
+
+ io_calcpipeline_ready
+ io_calcpipeline_ready
+ true
+ #008080
+
+
+ oi_calcpipeline_x_request[9:0]
+ oi_calcpipeline_x_request[9:0]
+ true
+ #008080
+ HEXRADIX
+
+
+ o_pixel_valid
+ o_pixel_valid
+ true
+ #ff0000
+
+
+ i_pixel_ready
+ i_pixel_ready
+ true
+ #ff0000
+
+
+ o_pixel_data[7:0]
+ o_pixel_data[7:0]
+ HEXRADIX
+ true
+ #ff0000
+
+
diff --git a/test/SpriteChannel/Rom.wcfg b/test/SpriteChannel/Rom.wcfg
new file mode 100644
index 0000000..3f617bc
--- /dev/null
+++ b/test/SpriteChannel/Rom.wcfg
@@ -0,0 +1,55 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ i_clk
+ i_clk
+
+
+ i_p0_address_valid
+ i_p0_address_valid
+
+
+ o_p0_address_ready
+ o_p0_address_ready
+
+
+ i_p0_address[12:0]
+ i_p0_address[12:0]
+ UNSIGNEDDECRADIX
+
+
+ s_p0_address_valid
+ s_p0_address_valid
+
+
+ c_p0_address_ready
+ c_p0_address_ready
+
+
+ r_p0_address[12:0]
+ r_p0_address[12:0]
+ UNSIGNEDDECRADIX
+
+
+ r_p0_data[7:0]
+ r_p0_data[7:0]
+ HEXRADIX
+
+
diff --git a/test/SpriteChannel/Y_HitCheck.wcfg b/test/SpriteChannel/Y_HitCheck.wcfg
new file mode 100644
index 0000000..5227634
--- /dev/null
+++ b/test/SpriteChannel/Y_HitCheck.wcfg
@@ -0,0 +1,129 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ i_clk
+ i_clk
+
+
+ State
+ label
+
+ r_state
+ r_state
+
+
+ c_nextstate
+ c_nextstate
+
+
+
+ OP Data
+ label
+
+ c_op_data_we
+ c_op_data_we
+
+
+ r_op_data[9:0]
+ r_op_data[9:0]
+
+
+
+ Y_HitCheck
+ label
+
+ o_enable
+ o_enable
+
+
+ r_valid[3:0]
+ r_valid[3:0]
+
+
+ i_data[9:0]
+ i_data[9:0]
+ HEXRADIX
+
+
+ r_data[0:1]
+ r_data[0:1]
+ HEXRADIX
+
+
+ o_data[9:0]
+ o_data[9:0]
+ HEXRADIX
+
+
+
+ O_YHitCheck
+ label
+
+ i_yhitcheck_ready
+ i_yhitcheck_ready
+
+
+ o_yhitcheck_valid
+ o_yhitcheck_valid
+
+
+ o_yhitcheck_ytocheck[9:0]
+ o_yhitcheck_ytocheck[9:0]
+ HEXRADIX
+
+
+
+ I_YHitCheck
+ label
+
+ o_yhitcheck_ready
+ o_yhitcheck_ready
+
+
+ i_yhitcheck_valid
+ i_yhitcheck_valid
+
+
+ i_yhitcheck_isvisible
+ i_yhitcheck_isvisible
+
+
+ i_yhitcheck_offset[7:0]
+ i_yhitcheck_offset[7:0]
+ HEXRADIX
+
+
+
+ Offset
+ label
+
+ i_enable
+ i_enable
+
+
+ i_data[7:0]
+ i_data[7:0]
+
+
+ r_data[0:1]
+ r_data[0:1]
+
+
+
diff --git a/test/SpriteChannel_tb.vhd b/test/SpriteChannel_tb.vhd
new file mode 100644
index 0000000..c926cfa
--- /dev/null
+++ b/test/SpriteChannel_tb.vhd
@@ -0,0 +1,194 @@
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+use std.env.stop;
+use work.OPCodes.all;
+
+entity SpriteChannel_tb is
+end entity SpriteChannel_tb;
+
+architecture Testbench of SpriteChannel_tb is
+ function to_hex(v : std_logic_vector) return string is
+ variable h : string(1 to 8); -- Maximal 8 Hex-Zeichen
+ variable u : unsigned(v'range) := unsigned(v);
+ begin
+ for i in h'range loop
+ exit when i > (v'length + 3) / 4;
+ case to_integer(u((v'length - 1) - (i - 1) * 4 downto v'length - i * 4)) is
+ when 0 => h(i) := '0';
+ when 1 => h(i) := '1';
+ when 2 => h(i) := '2';
+ when 3 => h(i) := '3';
+ when 4 => h(i) := '4';
+ when 5 => h(i) := '5';
+ when 6 => h(i) := '6';
+ when 7 => h(i) := '7';
+ when 8 => h(i) := '8';
+ when 9 => h(i) := '9';
+ when 10 => h(i) := 'A';
+ when 11 => h(i) := 'B';
+ when 12 => h(i) := 'C';
+ when 13 => h(i) := 'D';
+ when 14 => h(i) := 'E';
+ when 15 => h(i) := 'F';
+ when others => h(i) := '?';
+ end case;
+ end loop;
+ return h(1 to (v'length + 3) / 4);
+ end;
+
+ -- Clock period
+ constant K_CLKPeriod : time := 10 ns;
+ -- Generics
+ constant G_OPCodeData_Width : integer := 10;
+ constant G_Index_Width : integer := 5;
+ constant G_Offset_Width : integer := 8;
+ constant G_X_Width : integer := 10;
+ constant G_Y_Width : integer := 10;
+ constant G_Sprite_Height : integer := 16;
+ constant G_Sprite_Width : integer := 16;
+ -- Ports
+ signal I_CLK : std_logic;
+ signal I_CE : std_logic := '1';
+ signal I_RST : std_logic := '0';
+ signal I_OP_Valid : std_logic := '0';
+ signal O_OP_Ready : std_logic := '0';
+ signal I_OP_Code : std_logic_vector(3 downto 0) := (others => '0');
+ signal I_OP_Data : std_logic_vector(G_OPCodeData_Width - 1 downto 0) := (others => '0');
+ signal O_Pixel_Valid : std_logic := '0';
+ signal I_Pixel_Ready : std_logic := '0';
+ signal O_Pixel_Data : std_logic_vector(7 downto 0) := (others => '0');
+
+ signal TestDone : boolean := false;
+
+ -- Testdaten für Befehle
+ type T_Command is record
+ OP_Code : std_logic_vector(3 downto 0);
+ OP_Data : std_logic_vector(G_OPCodeData_Width - 1 downto 0);
+ end record;
+
+ type T_CommandArray is array (natural range <>) of T_Command;
+ constant CommandSequence : T_CommandArray := (
+ (OP_Code => K_OP_NEWLINE, OP_Data => "0000000100"),
+ (OP_Code => K_OP_REQ_ROW_DATA, OP_Data => "0000000000"),
+ (OP_Code => K_OP_REQ_ROW_DATA, OP_Data => "0000000001"),
+ (OP_Code => K_OP_REQ_ROW_DATA, OP_Data => "0000000010"),
+ (OP_Code => K_OP_REQ_ROW_DATA, OP_Data => "0000000011"),
+ (OP_Code => K_OP_REQ_ROW_DATA, OP_Data => "0000000100"),
+ (OP_Code => K_OP_REQ_ROW_DATA, OP_Data => "0000000101"),
+ (OP_Code => K_OP_REQ_ROW_DATA, OP_Data => "0000000110"),
+ (OP_Code => K_OP_REQ_ROW_DATA, OP_Data => "0000000111"),
+ (OP_Code => K_OP_REQ_ROW_DATA, OP_Data => "0000001000"),
+ (OP_Code => K_OP_REQ_ROW_DATA, OP_Data => "0000001001"),
+ (OP_Code => K_OP_REQ_ROW_DATA, OP_Data => "0000001010"),
+ (OP_Code => K_OP_REQ_ROW_DATA, OP_Data => "0000001011"),
+ (OP_Code => K_OP_REQ_ROW_DATA, OP_Data => "0000001100"),
+ (OP_Code => K_OP_REQ_ROW_DATA, OP_Data => "0000001101"),
+ (OP_Code => K_OP_REQ_ROW_DATA, OP_Data => "0000001110"),
+ (OP_Code => K_OP_REQ_ROW_DATA, OP_Data => "0000001111"),
+ (OP_Code => K_OP_REQ_ROW_DATA, OP_Data => "0000010000"),
+ (OP_Code => K_OP_REQ_ROW_DATA, OP_Data => "0000010001")
+
+ );
+begin
+
+ ClockProc : process
+ begin
+ while TestDone = false loop
+ I_CLK <= '0';
+ wait for K_CLKPeriod / 2;
+ I_CLK <= '1';
+ wait for K_CLKPeriod / 2;
+ end loop;
+
+ I_CLK <= '0';
+ stop(0);
+ wait;
+ end process;
+
+ StimulusProc : process
+ variable i : integer := 0;
+ begin
+ -- Initialisierung
+ I_RST <= '1';
+ wait for K_CLKPeriod * 2;
+ I_RST <= '0';
+ wait for K_CLKPeriod * 2;
+
+ -- Befehle senden
+ for i in CommandSequence'range loop
+ -- Warten, bis das Modul bereit ist
+ wait until rising_edge(I_CLK);
+ while O_OP_Ready /= '1' loop
+ wait until rising_edge(I_CLK);
+ end loop;
+
+ -- Befehl setzen
+ I_OP_Code <= CommandSequence(i).OP_Code;
+ I_OP_Data <= CommandSequence(i).OP_Data;
+ I_OP_Valid <= '1';
+
+ -- Einen Takt warten
+ wait until rising_edge(I_CLK);
+ I_OP_Valid <= '0';
+
+ -- Warten, bis der Befehl verarbeitet wurde
+ while O_OP_Ready /= '1' loop
+ wait until rising_edge(I_CLK);
+ end loop;
+
+ -- Optional: Ergebnisse prüfen (falls relevant)
+ report "Befehl " & integer'image(i) & " erfolgreich gesendet." severity note;
+ end loop;
+
+ wait for K_CLKPeriod * 10;
+ -- Test abgeschlossen
+ report "Alle Befehle erfolgreich gesendet." severity note;
+ TestDone <= true;
+ wait;
+ end process;
+
+ AXIReceiverProc : process
+ variable V_PacketCount : integer := 0;
+ begin
+ -- Initialisierung
+ I_Pixel_Ready <= '1'; -- Signalisiert, dass Daten empfangen werden können
+
+ while TestDone = false loop
+ -- Warten, bis gültige Daten anliegen
+ wait until rising_edge(I_CLK);
+ if O_Pixel_Valid = '1' then
+ report "Empfangenes Paket #" & integer'image(V_PacketCount) &
+ " (hex): " & to_hex(O_Pixel_Data)
+ severity note;
+ V_PacketCount := V_PacketCount + 1;
+ end if;
+ end loop;
+
+ wait;
+ end process;
+
+ i_SpriteChannel : entity work.SpriteChannel
+ 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,
+ G_Sprite_Height => G_Sprite_Height,
+ G_Sprite_Width => G_Sprite_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_Pixel_Valid => O_Pixel_Valid,
+ I_Pixel_Ready => I_Pixel_Ready,
+ O_Pixel_Data => O_Pixel_Data
+ );
+
+end architecture;
diff --git a/test/YHitCheck_tb.vhd b/test/YHitCheck_tb.vhd
new file mode 100644
index 0000000..f222121
--- /dev/null
+++ b/test/YHitCheck_tb.vhd
@@ -0,0 +1,165 @@
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+use std.env.stop;
+use work.SpriteRom.all;
+
+entity YHitCheck_tb is
+end;
+
+architecture bench of YHitCheck_tb is
+ -- Clock period
+ constant K_CLKPeriod : time := 10 ns;
+ -- Generics
+ constant G_YWidth : integer := 10;
+ constant G_SpriteHeight : integer := 16;
+ -- Ports
+ signal I_CLK : std_logic := '0';
+ signal I_CE : std_logic;
+ signal O_Ready : std_logic;
+ signal I_Valid : std_logic;
+ signal I_YToCheck : std_logic_vector(G_YWidth - 1 downto 0);
+ signal I_Y : std_logic_vector(G_YWidth - 1 downto 0);
+ signal I_Ready : std_logic;
+ signal O_Valid : std_logic;
+ signal O_IsVisible : std_logic;
+ signal O_Offset : std_logic_vector(7 downto 0);
+
+ type T_TestData is record
+ YToCheck : integer;
+ SpriteY : integer;
+ ExpectedVisible : std_logic;
+ ExpectedOffset : integer; -- NEU
+ end record;
+
+ type T_TestArray is array (natural range <>) of T_TestData;
+ constant TestValues : T_TestArray := (
+ (10, 10, '1', 0),
+ (25, 10, '1', K_SPRITE_ROW_OFFSETS(15)),
+ (26, 10, '0', 0),
+ (9, 10, '0', 0),
+ (15, 0, '1', K_SPRITE_ROW_OFFSETS(15)),
+ (31, 16, '1', K_SPRITE_ROW_OFFSETS(15)),
+ (32, 16, '0', 0),
+ (984, 459, '0', 0),
+ (360, 972, '0', 0),
+ (160, 434, '0', 0),
+ (996, 713, '0', 0),
+ (63, 184, '0', 0),
+ (700, 376, '0', 0),
+ (702, 69, '0', 0),
+ (583, 181, '0', 0),
+ (302, 974, '0', 0),
+ (985, 392, '0', 0),
+ (0, 0, '1', 0),
+ (15, 0, '1', K_SPRITE_ROW_OFFSETS(15)),
+ (16, 0, '0', 0),
+ (0, 1, '0', 0),
+ (1023, 1008, '1', K_SPRITE_ROW_OFFSETS(15)),
+ (1023, 1007, '0', 0),
+ (1007, 1007, '1', 0),
+ (1008, 1008, '1', 0),
+ (1009, 1008, '1', K_SPRITE_ROW_OFFSETS(1)),
+ (1023, 1008, '1', K_SPRITE_ROW_OFFSETS(15))
+ );
+
+ signal TestDone : boolean := false;
+begin
+
+ ClockProc : process
+ begin
+ while TestDone = false loop
+ I_CLK <= '0';
+ wait for K_CLKPeriod / 2;
+ I_CLK <= '1';
+ wait for K_CLKPeriod / 2;
+ end loop;
+
+ I_CLK <= '0';
+ stop(0);
+ wait;
+ end process;
+
+ SpriteChannel_YHitCheck_inst : entity work.VerticalSpritePipeline
+ generic map(
+ G_Y_Width => G_YWidth,
+ G_Sprite_Height => G_SpriteHeight
+ )
+ port map(
+ I_CLK => I_CLK,
+ I_CE => I_CE,
+ O_Ready => O_Ready,
+ I_Valid => I_Valid,
+ I_YToCheck => I_YToCheck,
+ I_Y => I_Y,
+ I_Ready => I_Ready,
+ O_Valid => O_Valid,
+ O_IsVisible => O_IsVisible,
+ O_Offset => O_Offset
+ );
+
+ StimulusProc : process
+ variable i : integer := 0;
+ begin
+ -- Init
+ i := 0;
+ I_CE <= '1';
+ I_Valid <= '0';
+ I_Ready <= '1';
+ I_Y <= (others => '0');
+ I_YToCheck <= (others => '0');
+ wait for K_CLKPeriod * 5;
+
+ for i in TestValues'range loop
+ -- Warte auf Ready
+ wait until rising_edge(I_CLK);
+ while O_Ready /= '1' loop
+ wait until rising_edge(I_CLK);
+ end loop;
+
+ -- Werte setzen
+ I_Y <= std_logic_vector(to_unsigned(TestValues(i).SpriteY, G_YWidth));
+ I_YToCheck <= std_logic_vector(to_unsigned(TestValues(i).YToCheck, G_YWidth));
+ I_Valid <= '1';
+
+ wait until rising_edge(I_CLK);
+ I_Valid <= '0';
+
+ -- Warte auf O_Valid
+ while O_Valid /= '1' loop
+ wait until rising_edge(I_CLK);
+ end loop;
+
+ -- Ergebnis prüfen
+ if O_IsVisible /= TestValues(i).ExpectedVisible then
+ assert false
+ report "Fehler bei Test " & integer'image(i) &
+ ": SpriteY=" & integer'image(TestValues(i).SpriteY) &
+ " YToCheck=" & integer'image(TestValues(i).YToCheck) &
+ " Erwartet Sichtbarkeit=" & std_logic'image(TestValues(i).ExpectedVisible) &
+ " Tatsaechlich=" & std_logic'image(O_IsVisible)
+ severity error;
+ elsif O_IsVisible = '1' then
+ -- Nur prüfen, wenn sichtbar
+ if to_integer(unsigned(O_Offset)) /= TestValues(i).ExpectedOffset then
+ assert false
+ report "Fehler bei Test " & integer'image(i) &
+ ": Falscher Offset. Erwartet=" & integer'image(TestValues(i).ExpectedOffset) &
+ " Tatsaechlich=" & integer'image(to_integer(unsigned(O_Offset)))
+ severity error;
+ else
+ report "Test " & integer'image(i) & " erfolgreich." severity note;
+ end if;
+ else
+ -- Unsichtbarer Fall, Sichtbarkeit korrekt => Erfolg
+ report "Test " & integer'image(i) & " erfolgreich." severity note;
+ end if;
+
+ wait for K_CLKPeriod * 2;
+ end loop;
+
+ report "Alle Tests abgeschlossen." severity note;
+ TestDone <= true;
+ wait;
+ end process;
+end;