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