Browse Source

Add functional FSM coverage using OSVVM & PSL endpoints

master
T. Meissner 5 years ago
parent
commit
e3e7def867
3 changed files with 184 additions and 0 deletions
  1. +53
    -0
      osvvm_fsm_psl_coverage/Makefile
  2. +6
    -0
      osvvm_fsm_psl_coverage/osvvm_fsm_psl_coverage.tcl
  3. +125
    -0
      osvvm_fsm_psl_coverage/osvvm_fsm_psl_coverage.vhd

+ 53
- 0
osvvm_fsm_psl_coverage/Makefile View File

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

+ 6
- 0
osvvm_fsm_psl_coverage/osvvm_fsm_psl_coverage.tcl View File

@ -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 ]

+ 125
- 0
osvvm_fsm_psl_coverage/osvvm_fsm_psl_coverage.vhd View File

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

Loading…
Cancel
Save