262 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			VHDL
		
	
	
	
	
	
			
		
		
	
	
			262 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			VHDL
		
	
	
	
	
	
| LIBRARY Common_test;
 | |
|   USE Common_test.testUtils.all;
 | |
| 
 | |
| ARCHITECTURE test OF ahbGpio_tester IS
 | |
|                                                               -- reset and clock
 | |
|   constant clockPeriod: time := (1.0/clockFrequency) * 1 sec;
 | |
|   signal clock_int: std_uLogic := '1';
 | |
|   signal reset_int: std_uLogic;
 | |
|                                                              -- test information
 | |
|   signal noteTopSeparator : string(1 to 80) := (others => '-');
 | |
|   signal errorTopSeparator : string(1 to 80) := (others => '#');
 | |
|   signal bottomSeparator : string(1 to 80) := (others => '.');
 | |
|   signal indentation : string(1 to 2) := (others => ' ');
 | |
|   signal noteInformation : string(1 to 9) := (others => ' ');
 | |
|   signal errorInformation : string(1 to 10) := (others => ' ');
 | |
|   signal failureInformation : string(1 to 12) := (others => ' ');
 | |
|   signal testInformation : string(1 to 50) := (others => ' ');
 | |
|                                                           -- register definition
 | |
|   constant peripheralBaseAddress: natural := 2**4;
 | |
|   constant dataRegisterAddress: natural := 0;
 | |
|   constant outputEnableRegisterAddress: natural := 1;
 | |
|                                                               -- AMBA bus access
 | |
|   signal registerAddress: natural;
 | |
|   signal registerData: integer;
 | |
|   signal registerWrite: std_uLogic;
 | |
|   signal registerRead: std_uLogic;
 | |
|   signal writeFlag, readFlag, readFlag1: std_uLogic;
 | |
|   signal writeData, readData: integer;
 | |
|                                                                   -- GPIO access
 | |
|   signal ioData: integer;
 | |
|   signal ioMask: integer;
 | |
| 
 | |
| BEGIN
 | |
|   ------------------------------------------------------------------------------
 | |
|                                                               -- reset and clock
 | |
|   reset_int <= '1', '0' after 2*clockPeriod;
 | |
|   hReset_n <= not(reset_int);
 | |
| 
 | |
|   clock_int <= not clock_int after clockPeriod/2;
 | |
|   hClk <= transport clock_int after clockPeriod*9.0/10.0;
 | |
| 
 | |
|   ------------------------------------------------------------------------------
 | |
|                                                                 -- test sequence
 | |
|   testSequence: process
 | |
|   begin
 | |
|     registerAddress <= 0;
 | |
|     registerData <= 0;
 | |
|     registerWrite <= '0';
 | |
|     registerRead <= '0';
 | |
|     ioData <= 0;
 | |
|     ioMask <= 0;
 | |
|     wait for 100 ns;
 | |
| 
 | |
|     ----------------------------------------------------------------------------
 | |
|                                                                   -- simple test
 | |
|                                                                 -- write en mask
 | |
|     testInformation <= pad("Writing data on the GPIO", testInformation'length);
 | |
|     wait for 0 ns;
 | |
|     assert false
 | |
|       report
 | |
|         noteTopSeparator & cr &
 | |
|         noteInformation & indentation & testInformation & cr &
 | |
|         noteInformation & bottomSeparator
 | |
|       severity note;
 | |
|     ioData <= 16#AA#;
 | |
|     ioMask <= 16#0F#; wait for 0 ns;
 | |
|     registerAddress <= outputEnableRegisterAddress;
 | |
|     registerData <= ioMask;
 | |
|     registerWrite <= '1', '0' after clockPeriod/2;
 | |
|     wait for 4*clockPeriod;
 | |
|                                                         -- write output data 55h
 | |
|     registerAddress <= dataRegisterAddress;
 | |
|     registerData <= 16#55#;
 | |
|     registerWrite <= '1', '0' after clockPeriod;
 | |
|     wait for 4*clockPeriod;
 | |
|     assert io = x"A5"
 | |
|       report
 | |
|         errorTopSeparator & cr &
 | |
|         noteInformation & indentation & "IO data not as expected" & cr &
 | |
|         noteInformation & bottomSeparator
 | |
|       severity error;
 | |
|                                                                     -- read data
 | |
|     testInformation <= pad("Reading data from the GPIO", testInformation'length);
 | |
|     wait for 0 ns;
 | |
|     assert false
 | |
|       report
 | |
|         noteTopSeparator & cr &
 | |
|         noteInformation & indentation & testInformation & cr &
 | |
|         noteInformation & bottomSeparator
 | |
|       severity note;
 | |
|     registerAddress <= dataRegisterAddress;
 | |
|     registerRead <= '1', '0' after clockPeriod;
 | |
|     for index in 1 to 4 loop
 | |
|       wait until rising_edge(clock_int);
 | |
|     end loop;
 | |
|     assert readData = 16#A5#
 | |
|       report
 | |
|         errorTopSeparator & cr &
 | |
|         noteInformation & indentation & "read data not as expected" & cr &
 | |
|         noteInformation & bottomSeparator
 | |
|       severity error;
 | |
|     wait for 100 ns;
 | |
| 
 | |
|     ----------------------------------------------------------------------------
 | |
|                                            -- test with a different base address
 | |
|                                                                 -- write en mask
 | |
|     testInformation <= pad(
 | |
|       "Writing data to a different base address", testInformation'length
 | |
|     );
 | |
|     wait for 0 ns;
 | |
|     assert false
 | |
|       report
 | |
|         noteTopSeparator & cr &
 | |
|         noteInformation & indentation & testInformation & cr &
 | |
|         noteInformation & bottomSeparator
 | |
|       severity note;
 | |
|     ioData <= 16#AA#;
 | |
|     ioMask <= 16#F0#; wait for 0 ns;
 | |
|     registerAddress <= peripheralBaseAddress + outputEnableRegisterAddress;
 | |
|     registerData <= ioMask;
 | |
|     registerWrite <= '1', '0' after clockPeriod;
 | |
|     wait for 4*clockPeriod;
 | |
|                                                         -- write output data 55h
 | |
|     registerAddress <= peripheralBaseAddress + dataRegisterAddress;
 | |
|     registerData <= 16#55#;
 | |
|     registerWrite <= '1', '0' after clockPeriod;
 | |
|     wait for 4*clockPeriod;
 | |
|                                                                     -- read data
 | |
|     registerAddress <= peripheralBaseAddress + dataRegisterAddress;
 | |
|     registerRead <= '1', '0' after clockPeriod;
 | |
|     for index in 1 to 4 loop
 | |
|       wait until rising_edge(clock_int);
 | |
|     end loop;
 | |
|     assert readData = 16#5A#
 | |
|       report
 | |
|         errorTopSeparator & cr &
 | |
|         noteInformation & indentation & "read data not as expected" & cr &
 | |
|         noteInformation & bottomSeparator
 | |
|       severity error;
 | |
|     wait for 4*clockPeriod;
 | |
| 
 | |
|     ----------------------------------------------------------------------------
 | |
|                                                           -- access back to back
 | |
|                                                                 -- write en mask
 | |
|     testInformation <= pad("Accessing at full speed", testInformation'length);
 | |
|     wait for 0 ns;
 | |
|     assert false
 | |
|       report
 | |
|         noteTopSeparator & cr &
 | |
|         noteInformation & indentation & testInformation & cr &
 | |
|         noteInformation & bottomSeparator
 | |
|       severity note;
 | |
|     wait until rising_edge(clock_int);
 | |
|     ioData <= 16#AA#;
 | |
|     ioMask <= 16#0F#; wait for 0 ns;
 | |
|     registerAddress <= outputEnableRegisterAddress;
 | |
|     registerData <= ioMask;
 | |
|     registerWrite <= '1' after clockPeriod/4, '0' after clockPeriod/2;
 | |
|                                                         -- write output data 55h
 | |
|     wait until rising_edge(clock_int);
 | |
|     registerAddress <= dataRegisterAddress;
 | |
|     registerData <= 16#55#;
 | |
|     registerWrite <= '1' after clockPeriod/4, '0' after clockPeriod/2;
 | |
|                                                                     -- read data
 | |
|     wait until rising_edge(clock_int);
 | |
|     registerAddress <= dataRegisterAddress;
 | |
|     registerRead <= '1' after clockPeriod/4, '0' after clockPeriod/2;
 | |
|     for index in 1 to 4 loop
 | |
|       wait until rising_edge(clock_int);
 | |
|     end loop;
 | |
|     assert readData = 16#A5#
 | |
|       report
 | |
|         errorTopSeparator & cr &
 | |
|         noteInformation & indentation & "read data not as expected" & cr &
 | |
|         noteInformation & bottomSeparator
 | |
|       severity error;
 | |
|     wait for 4*clockPeriod;
 | |
|                                                             -- end of simulation
 | |
|     wait for 100 ns;
 | |
|     testInformation <= pad("End of tests", testInformation'length);
 | |
|     wait for 0 ns;
 | |
|     assert false
 | |
|       report
 | |
|         noteTopSeparator & cr &
 | |
|         failureInformation & indentation & testInformation & cr &
 | |
|         failureInformation & bottomSeparator
 | |
|       severity failure;
 | |
|     wait;
 | |
|   end process testSequence;
 | |
| 
 | |
|   ------------------------------------------------------------------------------
 | |
|                                                               -- AMBA bus access
 | |
|                                                 -- phase 1: address and controls
 | |
|   busAccess1: process
 | |
|     variable writeAccess: boolean := false;
 | |
|   begin
 | |
|     wait on reset_int, registerWrite, registerRead;
 | |
|     if falling_edge(reset_int) then
 | |
|       hAddr <= (others => '-');
 | |
|       hTrans <= transIdle;
 | |
|       hSel <= '0';
 | |
|       writeFlag <= '0';
 | |
|     end if;
 | |
|     if rising_edge(registerWrite) or rising_edge(registerRead) then
 | |
|       writeAccess := false;
 | |
|       if rising_edge(registerWrite) then
 | |
|         writeAccess := true;
 | |
|       end if;
 | |
|       wait until rising_edge(clock_int);
 | |
|       hAddr <= to_unsigned(registerAddress, hAddr'length),
 | |
|         (others => '-') after clockPeriod + 1 ns;
 | |
|       hTrans <= transNonSeq, transIdle after clockPeriod + 1 ns;
 | |
|       hSel <= '1', '0' after clockPeriod + 1 ns;
 | |
|       if writeAccess then
 | |
|         writeFlag <= '1', '0' after clockPeriod + 1 ns;
 | |
|         writeData <= registerData;
 | |
|       else
 | |
|       readFlag <= '1', '0' after clockPeriod + 1 ns;
 | |
|       end if;
 | |
|     end if;
 | |
|   end process busAccess1;
 | |
| 
 | |
|   hWrite <= writeFlag;
 | |
|                                                           -- phase 2: data write
 | |
|   busAccess2: process
 | |
|   begin
 | |
|     wait until rising_edge(clock_int);
 | |
|     hWData <= (others => '-');
 | |
|     readFlag1 <= '0';
 | |
|     if writeFlag = '1' then
 | |
|       hWData <= std_uLogic_vector(to_signed(writeData, hWData'length));
 | |
|     end if;
 | |
|     readFlag1 <= readFlag;
 | |
|   end process busAccess2;
 | |
|                                                            -- phase 3: data read
 | |
|   busAccess3: process
 | |
|   begin
 | |
|     wait until rising_edge(clock_int);
 | |
|     if readFlag1 = '1' then
 | |
|       readData <= to_integer(to_01(unsigned(hRData)));
 | |
|     end if;
 | |
|   end process busAccess3;
 | |
| 
 | |
|   ------------------------------------------------------------------------------
 | |
|                                                                   -- GPIO access
 | |
|   linesAccess: process(ioData, ioMask)
 | |
|     variable ioDataVector: unsigned(io'range);
 | |
|     variable ioMaskVector: unsigned(io'range);
 | |
|   begin
 | |
|     ioDataVector := to_unsigned(ioData, ioDataVector'length);
 | |
|     ioMaskVector := to_unsigned(ioMask, ioMaskVector'length);
 | |
|     for index in io'range loop
 | |
|       if ioMaskVector(index) = '1' then
 | |
|         io(index) <= 'Z';
 | |
|       else
 | |
|         io(index) <= ioDataVector(index);
 | |
|       end if;
 | |
|     end loop;
 | |
|   end process;
 | |
| 
 | |
| END ARCHITECTURE test;
 |