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_OPDecoder_Valid => I_OP_Valid, O_OPDecoder_Ready => O_OP_Ready, I_OPDecoder_Code => I_OP_Code, I_OPDecoder_Data => I_OP_Data, O_RFile_Wr_Index_WE => O_Register_Index_WE, O_RFile_Wr_Index => O_Register_Index, O_RFile_Wr_Offset_WE => O_Register_Offset_WE, O_RFile_Wr_Offset => O_Register_Offset, O_RFile_Wr_X_We => O_Register_X_We, O_RFile_Wr_X => O_Register_X, O_RFile_Wr_Y_WE => O_Register_Y_WE, O_RFile_Wr_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_VSpritePipeline_Ready => I_YHitCheck_Ready, O_VSpritePipeline_Valid => O_YHitCheck_Valid, O_VSpritePipeline_YToCheck => O_YHitCheck_YToCheck, O_VSpritePipeline_Ready => O_YHitCheck_Ready, I_VSpritePipeline_Valid => I_YHitCheck_Valid, I_VSpritePipeline_IsVisible => I_YHitCheck_IsVisible, I_VSpritePipeline_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_VSpritePipeline_OP_Ready => I_YHitCheck_Ready, I_VSpritePipeline_OP_Valid => O_YHitCheck_Valid, I_VSpritePipeline_OP_Y_Request => O_YHitCheck_YToCheck, I_VSpritePipeline_OP_Y_Sprite => "0000000000", I_VSpritePipeline_Ready => O_YHitCheck_Ready, O_VSpritePipeline_Valid => I_YHitCheck_Valid, O_VSpritePipeline_IsVisible => I_YHitCheck_IsVisible, O_VSpritePipeline_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;