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;
|