From e3e7def867919c61b5b342cf56b2345a675f1192 Mon Sep 17 00:00:00 2001 From: tmeissner Date: Sat, 9 Apr 2016 21:44:01 +0200 Subject: [PATCH] Add functional FSM coverage using OSVVM & PSL endpoints --- osvvm_fsm_psl_coverage/Makefile | 53 ++++++++ .../osvvm_fsm_psl_coverage.tcl | 6 + .../osvvm_fsm_psl_coverage.vhd | 125 ++++++++++++++++++ 3 files changed, 184 insertions(+) create mode 100644 osvvm_fsm_psl_coverage/Makefile create mode 100644 osvvm_fsm_psl_coverage/osvvm_fsm_psl_coverage.tcl create mode 100644 osvvm_fsm_psl_coverage/osvvm_fsm_psl_coverage.vhd diff --git a/osvvm_fsm_psl_coverage/Makefile b/osvvm_fsm_psl_coverage/Makefile new file mode 100644 index 0000000..7cbf3d6 --- /dev/null +++ b/osvvm_fsm_psl_coverage/Makefile @@ -0,0 +1,53 @@ +OSVVM := ../../OSVVM + + +.PHONY: sim compile clean wave + + +sim \ +work/osvvm_fsm_psl_coverage \ +work/osvvm_fsm_psl_coverage.ghw: work/work/osvvm_fsm_psl_coverage.o log + @echo Run test ... + @cd work; ghdl -r --std=08 -fpsl osvvm_fsm_psl_coverage \ + --psl-report=../log/osvvm_fsm_psl_coverage.json \ + --wave=../log/osvvm_fsm_psl_coverage.ghw \ + --stop-time=200ns + + +work/osvvm/%.o: work/osvvm + @echo "Analyse OSVVM library ..." + @cd work; ghdl -a --std=08 --work=osvvm --workdir=osvvm ../$(OSVVM)/NamePkg.vhd + @cd work; ghdl -a --std=08 --work=osvvm --workdir=osvvm ../$(OSVVM)/TranscriptPkg.vhd + @cd work; ghdl -a --std=08 --work=osvvm --workdir=osvvm ../$(OSVVM)/OsvvmGlobalPkg.vhd + @cd work; ghdl -a --std=08 --work=osvvm --workdir=osvvm ../$(OSVVM)/TextUtilPkg.vhd + @cd work; ghdl -a --std=08 --work=osvvm --workdir=osvvm ../$(OSVVM)/AlertLogPkg.vhd + @cd work; ghdl -a --std=08 --work=osvvm --workdir=osvvm ../$(OSVVM)/RandomBasePkg.vhd + @cd work; ghdl -a --std=08 --work=osvvm --workdir=osvvm ../$(OSVVM)/SortListPkg_int.vhd + @cd work; ghdl -a --std=08 --work=osvvm --workdir=osvvm ../$(OSVVM)/RandomPkg.vhd + @cd work; ghdl -a --std=08 --work=osvvm --workdir=osvvm ../$(OSVVM)/MessagePkg.vhd + @cd work; ghdl -a --std=08 --work=osvvm --workdir=osvvm ../$(OSVVM)/CoveragePkg.vhd + @cd work; ghdl -a --std=08 --work=osvvm --workdir=osvvm ../$(OSVVM)/MemoryPkg.vhd + + +compile \ +work/work/osvvm_fsm_psl_coverage.o: osvvm_fsm_psl_coverage.vhd log work work/work work/osvvm/CoveragePkg.o + @echo "Analyse & elaborate test ..." + @cd work; ghdl -a --std=08 -fpsl --workdir=work -Posvvm ../osvvm_fsm_psl_coverage.vhd + @cd work; ghdl -e --std=08 -fpsl --workdir=work -Posvvm -o osvvm_fsm_psl_coverage osvvm_fsm_psl_coverage >& /dev/null + + +wave: work/osvvm_fsm_psl_coverage.ghw + @echo Run waveform viewer ... + @gtkwave log/osvvm_fsm_psl_coverage.ghw -S osvvm_fsm_psl_coverage.tcl & + + +work \ +work/osvvm \ +work/work \ +log: + @mkdir $@ + + +clean: + @echo Remove generated files ... + @rm -rf work log diff --git a/osvvm_fsm_psl_coverage/osvvm_fsm_psl_coverage.tcl b/osvvm_fsm_psl_coverage/osvvm_fsm_psl_coverage.tcl new file mode 100644 index 0000000..fa83e84 --- /dev/null +++ b/osvvm_fsm_psl_coverage/osvvm_fsm_psl_coverage.tcl @@ -0,0 +1,6 @@ +set signals [list] +lappend signals "top.osvvm_fsm_psl_coverage.s_reset_n" +lappend signals "top.osvvm_fsm_psl_coverage.s_clk" +lappend signals "top.osvvm_fsm_psl_coverage.s_fsm_state" +lappend signals "top.osvvm_fsm_psl_coverage.s_state_cover" +set num_added [ gtkwave::addSignalsFromList $signals ] diff --git a/osvvm_fsm_psl_coverage/osvvm_fsm_psl_coverage.vhd b/osvvm_fsm_psl_coverage/osvvm_fsm_psl_coverage.vhd new file mode 100644 index 0000000..e114fa6 --- /dev/null +++ b/osvvm_fsm_psl_coverage/osvvm_fsm_psl_coverage.vhd @@ -0,0 +1,125 @@ +library ieee; + use ieee.std_logic_1164.all; + use ieee.numeric_std.all; + +library std; + use std.env.all; + +library osvvm; + use osvvm.NamePkg.all ; + use osvvm.TranscriptPkg.all ; + use osvvm.OsvvmGlobalPkg.all ; + use osvvm.AlertLogPkg.all ; + use osvvm.RandomPkg.all ; + use osvvm.CoveragePkg.all ; + use osvvm.MemoryPkg.all ; + + + +entity osvvm_fsm_psl_coverage is +end entity osvvm_fsm_psl_coverage; + + + +architecture sim of osvvm_fsm_psl_coverage is + + + type t_fsm_state is (IDLE, ADDR, DATA); + signal s_fsm_state : t_fsm_state; + + signal s_clk : std_logic := '0'; + signal s_reset_n : std_logic := '0'; + + signal s_state_cover : unsigned(2 downto 0); + + shared variable sv_cover : CovPType; + + +begin + + + s_clk <= not(s_clk) after 5 ns; + s_reset_n <= '1' after 20 ns; + + + FsmP : process (s_reset_n, s_clk) is + begin + if (s_reset_n = '0') then + s_fsm_state <= IDLE; + elsif (rising_edge(s_clk)) then + case s_fsm_state is + when IDLE => s_fsm_state <= ADDR; + when ADDR => s_fsm_state <= DATA; + when DATA => s_fsm_state <= IDLE; + when others => + null; + end case; + end if; + end process FsmP; + + + -- psl endpoint E_IDLE_ADDR is {s_fsm_state = IDLE; s_fsm_state = ADDR}@s_clk'active; + -- psl endpoint E_ADDR_DATA is {s_fsm_state = ADDR; s_fsm_state = DATA}@s_clk'active; + -- psl endpoint E_DATA_IDLE is {s_fsm_state = DATA; s_fsm_state = IDLE}@s_clk'active; + + + EndpointRegP : process is + begin + s_state_cover <= (others => '0'); + if (E_IDLE_ADDR) then + s_state_cover(0) <= '1'; + end if; + if (E_ADDR_DATA) then + s_state_cover(1) <= '1'; + end if; + if (E_DATA_IDLE) then + s_state_cover(2) <= '1'; + end if; + wait until rising_edge(s_clk); + end process; + + + sv_cover.AddBins("IDLE->ADDR", GenBin(1)); + sv_cover.AddBins("ADDR->DATA", GenBin(2)); + sv_cover.AddBins("DATA->IDLE", GenBin(4)); + sv_cover.AddBins(ALL_ILLEGAL); + + + CovCollectP : process is + begin + wait until s_reset_n = '1' and rising_edge(s_clk); + -- we have to wait another cycle because endpoints are delayed by one cycle + -- if we don't wait, we get an illegal BIN hit in second cycle after released reset + wait until rising_edge(s_clk); + loop + wait until rising_edge(s_clk); + sv_cover.ICover(to_integer(s_state_cover)); + end loop; + end process CovCollectP; + + + FinishP : process is + begin + wait until s_clk'active; + if (sv_cover.IsCovered) then + Log("FSM full covered :)", ALWAYS); + sv_cover.SetName("FSM state coverage report"); + sv_cover.WriteBin; + stop(0); + end if; + end process FinishP; + + + -- psl default clock is rising_edge(s_clk); + + -- psl IDLE_ADDR : assert always (s_fsm_state = IDLE and s_reset_n = '1') -> next (s_fsm_state = ADDR) abort not(s_reset_n) + -- report "FSM error: IDLE should be followed by ADDR state"; + + -- psl ADDR_DATA : assert always (s_fsm_state = ADDR and s_reset_n = '1') -> next (s_fsm_state = DATA) abort not(s_reset_n); + -- report "FSM error: ADDR should be followed by DATA state"; + + -- psl DATA_IDLE : assert always (s_fsm_state = DATA and s_reset_n = '1') -> next (s_fsm_state = IDLE) abort not(s_reset_n); + -- report "FSM error: DATA should be followed by IDLE state"; + + +end architecture sim;