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;