TestBlinkingLed.vhd
-------------------------------------------------------------------------------
-- Copyright (c) 2016 by Stefan Milch. All rights reserved.
-------------------------------------------------------------------------------
--! @file TestBlinkingLed.vhd
--! @brief Test shell for module BlinkingLed. \n
--!
-------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use std.textio.all;
entity TestBlinkingLed is
end TestBlinkingLed;
architecture behavior of TestBlinkingLed is
-- Component Declaration for the Unit Under Test (UUT)
component BlinkingLed
port (
EXT_CLK : in std_logic; --! 125 MHz system clock
BTN : in std_logic_vector(3 downto 0); --! Button inputs, high acitve
LED : out std_logic --! LED output, high acitve
);
end component;
-- Time definitions
constant Clk_period : time := 8 ns; --! ZYBO Clock frequency is 125 MHz
-- constant Clk_period : time := 10 ns; --! ARTY Clock frequency is 100 MHz
constant LED_min_per : time := 400 ns; --! LED period in fastest mode
constant LED_res_per : time := LED_min_per*256; --! LED period after reset
constant LED_max_per : time := LED_res_per*16; --! LED period in slowest mode
--Inputs
signal Button : std_logic_vector(3 downto 0) := (others => '0');
signal Ext_Clk : std_logic := '0';
--Outputs
signal Led : std_logic;
--Test
file report_file : text;
signal TestCase : integer;
signal TestErr : std_logic := '0';
signal LED_per : time := 0 ns;
--! print to output file
procedure tb_report(constant report_text : in string) is
variable line_out: line;
begin
write(line_out,report_text);
writeline(report_file, line_out);
end tb_report;
--! wait a number of cycles
procedure WaitCycles(constant cycles : in integer) is
variable i : integer;
begin
for i in 1 to cycles loop
wait until rising_edge(Ext_Clk);
end loop;
end WaitCycles;
--! measure LED period
procedure MeasureLedPeriod(constant maxCycles : in integer; signal Led_period : out time) is
variable i : integer;
variable s : integer;
variable rise_1 : integer;
variable rise_2 : integer;
begin
s := 0; -- initial state
Led_period <= 0 ns; -- timeout return value
for i in 1 to maxCycles loop -- timeout condition
wait until rising_edge(Ext_Clk); -- measure in clock ticks
case s is
when 0 => -- wait for initial condition
if (Led = '0') then
s := 1; -- initial condition reached
end if;
when 1 => -- wait for rising edge
if (Led = '1') then
s := 2; -- first rising edge reached
rise_1 := i; -- remember clock tick
end if;
when 2 => -- wait for LED being off again
if (Led = '0') then
s := 3; -- LED is off again reached
end if;
when 3 => -- wait for rising edge
if (Led = '1') then
s := 4; -- nothing more to do
rise_2 := i; -- remember clock tick
Led_period <= (rise_2 - rise_1) * Clk_period;
wait for 10 ps; -- Let variable value settle
return; -- got result
end if;
when others =>
return;
end case;
end loop;
end MeasureLedPeriod;
--! measure LED period
procedure CheckLedPeriod(constant expected : in time; signal LED_period : inout time;
signal TestErr : out std_logic) is
begin
MeasureLedPeriod(2*expected/Clk_period, LED_period);
if (LED_period = expected) then
tb_report(" Expected " & time'Image(expected) & ": passed.");
else
TestErr <= '1';
tb_report(" Expected " & time'Image(expected) & "; Found " & time'Image(LED_per) & ": Failed!");
end if;
end CheckLedPeriod;
begin
-- Instantiate the Unit Under Test (UUT)
uut: BlinkingLed port map (
EXT_CLK => Ext_Clk,
BTN => Button,
LED => Led
);
--! Generate system clock
p_clk : process
begin
Ext_Clk <= not Ext_Clk;
wait for Clk_period/2;
end process;
--! Check for test bench time out
p_control : process
begin
wait for 20 ms;
-- the test bench should already have terminated!
assert false
report "Test timed out!"
severity failure;
end process;
-- Stimulus process
stim_proc: process
variable expected_time : time;
begin
-- prepare reporting
file_open(report_file,"../../../TestBlinkingLed.log",WRITE_MODE);
tb_report("Testing BlinkingLed:");
tb_report("====================");
TestCase <= 1;
TestCase <= 0;
WaitCycles(1);
TestErr <= not TestErr;
WaitCycles(1);
TestErr <= not TestErr;
WaitCycles(500);
if (TestErr = '0') then
tb_report("Test completed successfully");
else
tb_report("Test completed with error(s)");
end if;
file_close(report_file);
assert false
report "Test terminated. This is not a failiure!"
severity failure;
wait;
end process;
end;