Files
SpriteChannel/test/SpriteChannel_tb.vhd

195 lines
7.4 KiB
VHDL

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;