Browse Source

Add functional FSM coverage using OSVVM & PSL endpoints

T. Meissner 3 years ago
parent
commit
e3e7def867

+ 53
- 0
osvvm_fsm_psl_coverage/Makefile View File

@@ -0,0 +1,53 @@
1
+OSVVM := ../../OSVVM
2
+
3
+
4
+.PHONY: sim compile clean wave
5
+
6
+
7
+sim \
8
+work/osvvm_fsm_psl_coverage \
9
+work/osvvm_fsm_psl_coverage.ghw: work/work/osvvm_fsm_psl_coverage.o log
10
+	@echo Run test ...
11
+	@cd work; ghdl -r --std=08 -fpsl osvvm_fsm_psl_coverage \
12
+                    --psl-report=../log/osvvm_fsm_psl_coverage.json \
13
+                    --wave=../log/osvvm_fsm_psl_coverage.ghw \
14
+                    --stop-time=200ns
15
+
16
+
17
+work/osvvm/%.o: work/osvvm
18
+	@echo "Analyse OSVVM library ..."
19
+	@cd work; ghdl -a --std=08 --work=osvvm --workdir=osvvm ../$(OSVVM)/NamePkg.vhd
20
+	@cd work; ghdl -a --std=08 --work=osvvm --workdir=osvvm ../$(OSVVM)/TranscriptPkg.vhd
21
+	@cd work; ghdl -a --std=08 --work=osvvm --workdir=osvvm ../$(OSVVM)/OsvvmGlobalPkg.vhd
22
+	@cd work; ghdl -a --std=08 --work=osvvm --workdir=osvvm ../$(OSVVM)/TextUtilPkg.vhd
23
+	@cd work; ghdl -a --std=08 --work=osvvm --workdir=osvvm ../$(OSVVM)/AlertLogPkg.vhd
24
+	@cd work; ghdl -a --std=08 --work=osvvm --workdir=osvvm ../$(OSVVM)/RandomBasePkg.vhd
25
+	@cd work; ghdl -a --std=08 --work=osvvm --workdir=osvvm ../$(OSVVM)/SortListPkg_int.vhd
26
+	@cd work; ghdl -a --std=08 --work=osvvm --workdir=osvvm ../$(OSVVM)/RandomPkg.vhd
27
+	@cd work; ghdl -a --std=08 --work=osvvm --workdir=osvvm ../$(OSVVM)/MessagePkg.vhd
28
+	@cd work; ghdl -a --std=08 --work=osvvm --workdir=osvvm ../$(OSVVM)/CoveragePkg.vhd
29
+	@cd work; ghdl -a --std=08 --work=osvvm --workdir=osvvm ../$(OSVVM)/MemoryPkg.vhd
30
+
31
+
32
+compile \
33
+work/work/osvvm_fsm_psl_coverage.o: osvvm_fsm_psl_coverage.vhd log work work/work work/osvvm/CoveragePkg.o
34
+	@echo "Analyse & elaborate test ..."
35
+	@cd work; ghdl -a --std=08 -fpsl --workdir=work -Posvvm ../osvvm_fsm_psl_coverage.vhd
36
+	@cd work; ghdl -e --std=08 -fpsl --workdir=work -Posvvm -o osvvm_fsm_psl_coverage osvvm_fsm_psl_coverage >& /dev/null
37
+
38
+
39
+wave: work/osvvm_fsm_psl_coverage.ghw
40
+	@echo Run waveform viewer ...
41
+	@gtkwave log/osvvm_fsm_psl_coverage.ghw -S osvvm_fsm_psl_coverage.tcl &
42
+
43
+
44
+work \
45
+work/osvvm \
46
+work/work \
47
+log:
48
+	@mkdir $@
49
+
50
+
51
+clean:
52
+	@echo Remove generated files ...
53
+	@rm -rf work log

+ 6
- 0
osvvm_fsm_psl_coverage/osvvm_fsm_psl_coverage.tcl View File

@@ -0,0 +1,6 @@
1
+set signals [list]
2
+lappend signals "top.osvvm_fsm_psl_coverage.s_reset_n"
3
+lappend signals "top.osvvm_fsm_psl_coverage.s_clk"
4
+lappend signals "top.osvvm_fsm_psl_coverage.s_fsm_state"
5
+lappend signals "top.osvvm_fsm_psl_coverage.s_state_cover"
6
+set num_added [ gtkwave::addSignalsFromList $signals ]

+ 125
- 0
osvvm_fsm_psl_coverage/osvvm_fsm_psl_coverage.vhd View File

@@ -0,0 +1,125 @@
1
+library ieee;
2
+  use ieee.std_logic_1164.all;
3
+  use ieee.numeric_std.all;
4
+
5
+library std;
6
+  use std.env.all;
7
+
8
+library osvvm;
9
+  use osvvm.NamePkg.all ;
10
+  use osvvm.TranscriptPkg.all ;
11
+  use osvvm.OsvvmGlobalPkg.all ;
12
+  use osvvm.AlertLogPkg.all ;
13
+  use osvvm.RandomPkg.all ;
14
+  use osvvm.CoveragePkg.all ;
15
+  use osvvm.MemoryPkg.all ;
16
+
17
+
18
+
19
+entity osvvm_fsm_psl_coverage is
20
+end entity osvvm_fsm_psl_coverage;
21
+
22
+
23
+
24
+architecture sim of osvvm_fsm_psl_coverage is
25
+
26
+
27
+  type t_fsm_state is (IDLE, ADDR, DATA);
28
+  signal s_fsm_state : t_fsm_state;
29
+
30
+  signal s_clk     : std_logic := '0';
31
+  signal s_reset_n : std_logic := '0';
32
+
33
+  signal s_state_cover : unsigned(2 downto 0);
34
+
35
+  shared variable sv_cover : CovPType;
36
+
37
+
38
+begin
39
+
40
+
41
+  s_clk     <= not(s_clk) after 5 ns;
42
+  s_reset_n <= '1' after 20 ns;
43
+
44
+
45
+  FsmP : process (s_reset_n, s_clk) is
46
+  begin
47
+    if (s_reset_n = '0') then
48
+      s_fsm_state <= IDLE;
49
+    elsif (rising_edge(s_clk)) then
50
+      case s_fsm_state is
51
+        when IDLE => s_fsm_state <= ADDR;
52
+        when ADDR => s_fsm_state <= DATA;
53
+        when DATA => s_fsm_state <= IDLE;
54
+        when others =>
55
+          null;
56
+      end case;
57
+    end if;
58
+  end process FsmP;
59
+
60
+
61
+  -- psl endpoint E_IDLE_ADDR is {s_fsm_state = IDLE; s_fsm_state = ADDR}@s_clk'active;
62
+  -- psl endpoint E_ADDR_DATA is {s_fsm_state = ADDR; s_fsm_state = DATA}@s_clk'active;
63
+  -- psl endpoint E_DATA_IDLE is {s_fsm_state = DATA; s_fsm_state = IDLE}@s_clk'active;
64
+
65
+
66
+  EndpointRegP : process is
67
+  begin
68
+    s_state_cover <= (others => '0');
69
+    if (E_IDLE_ADDR) then
70
+      s_state_cover(0) <= '1';
71
+    end if;
72
+    if (E_ADDR_DATA) then
73
+      s_state_cover(1) <= '1';
74
+    end if;
75
+    if (E_DATA_IDLE) then
76
+      s_state_cover(2) <= '1';
77
+    end if;
78
+    wait until rising_edge(s_clk);
79
+  end process;
80
+
81
+
82
+  sv_cover.AddBins("IDLE->ADDR", GenBin(1));
83
+  sv_cover.AddBins("ADDR->DATA", GenBin(2));
84
+  sv_cover.AddBins("DATA->IDLE", GenBin(4));
85
+  sv_cover.AddBins(ALL_ILLEGAL);
86
+
87
+
88
+  CovCollectP : process is
89
+  begin
90
+    wait until s_reset_n = '1' and rising_edge(s_clk);
91
+    -- we have to wait another cycle because endpoints are delayed by one cycle
92
+    -- if we don't wait, we get an illegal BIN hit in second cycle after released reset
93
+    wait until rising_edge(s_clk);
94
+    loop
95
+      wait until rising_edge(s_clk);
96
+      sv_cover.ICover(to_integer(s_state_cover));
97
+    end loop;
98
+  end process CovCollectP; 
99
+
100
+
101
+  FinishP : process is
102
+  begin
103
+    wait until s_clk'active;
104
+    if (sv_cover.IsCovered) then
105
+      Log("FSM full covered :)", ALWAYS);
106
+      sv_cover.SetName("FSM state coverage report");
107
+      sv_cover.WriteBin;
108
+      stop(0);
109
+    end if;
110
+  end process FinishP;
111
+
112
+
113
+  -- psl default clock is rising_edge(s_clk);
114
+
115
+  -- psl IDLE_ADDR : assert always (s_fsm_state = IDLE and s_reset_n = '1') -> next (s_fsm_state = ADDR) abort not(s_reset_n)
116
+  --  report "FSM error: IDLE should be followed by ADDR state";
117
+
118
+  -- psl ADDR_DATA : assert always (s_fsm_state = ADDR and s_reset_n = '1') -> next (s_fsm_state = DATA) abort not(s_reset_n);
119
+  --  report "FSM error: ADDR should be followed by DATA state";
120
+
121
+  -- psl DATA_IDLE : assert always (s_fsm_state = DATA and s_reset_n = '1') -> next (s_fsm_state = IDLE) abort not(s_reset_n);
122
+  --  report "FSM error: DATA should be followed by IDLE state";
123
+
124
+
125
+end architecture sim;