Browse Source

Add simple FIFO model incl. formal tests

T. Meissner 1 month ago
parent
commit
705171911a
3 changed files with 260 additions and 0 deletions
  1. 18
    0
      fifo/Makefile
  2. 220
    0
      fifo/fifo.vhd
  3. 22
    0
      fifo/symbiyosys.sby

+ 18
- 0
fifo/Makefile View File

@@ -0,0 +1,18 @@
1
+DUT := fifo
2
+
3
+.PHONY: cover bmc prove synth all clean
4
+
5
+all: cover bmc prove
6
+
7
+cover bmc prove: ${DUT}.vhd symbiyosys.sby
8
+	sby --yosys "yosys -m ghdl" -f -d work/${DUT}-$@ symbiyosys.sby $@
9
+
10
+$(DUT)_synth.vhd: ${DUT}.vhd
11
+	ghdl --synth --std=08 --no-formal -gDepth=16 -gWidth=16 $(DUT).vhd -e $(DUT) > $(DUT)_synth.vhd
12
+
13
+synth: fifo.json
14
+fifo.json: $(DUT)_synth.vhd
15
+	yosys -m ghdl -p 'ghdl --std=08 --no-formal -gDepth=16 -gWidth=16 $(DUT).vhd -e $(DUT); synth_ice40 -json $@'
16
+
17
+clean:
18
+	rm -rf work $(DUT).json $(DUT)_synth.vhd

+ 220
- 0
fifo/fifo.vhd View File

@@ -0,0 +1,220 @@
1
+library ieee;
2
+use ieee.std_logic_1164.all;
3
+use ieee.numeric_std.all;
4
+
5
+
6
+
7
+entity fifo is
8
+  generic (
9
+    Formal : boolean := true;
10
+    Depth  : positive := 16;
11
+    Width  : positive := 16
12
+  );
13
+  port (
14
+    Reset_n_i    : in  std_logic;
15
+    Clk_i        : in  std_logic;
16
+    -- write
17
+    Wen_i        : in  std_logic;
18
+    Din_i        : in  std_logic_vector(Width-1 downto 0);
19
+    Full_o       : out std_logic;
20
+    Werror_o     : out std_logic;
21
+    -- read
22
+    Ren_i        : in  std_logic;
23
+    Dout_o       : out std_logic_vector(Width-1 downto 0);
24
+    Empty_o      : out std_logic;
25
+    Rerror_o     : out std_logic
26
+  );
27
+end entity fifo;
28
+
29
+
30
+architecture rtl of fifo is
31
+
32
+
33
+  subtype t_fifo_pnt is natural range 0 to Depth-1;
34
+  signal s_write_pnt : t_fifo_pnt;
35
+  signal s_read_pnt  : t_fifo_pnt;
36
+
37
+  type t_fifo_mem is array (t_fifo_pnt'low to t_fifo_pnt'high) of std_logic_vector(Din_i'range);
38
+  signal s_fifo_mem : t_fifo_mem;
39
+
40
+  function incr_pnt (data : t_fifo_pnt) return t_fifo_pnt is
41
+  begin
42
+    if (data = t_fifo_mem'high) then
43
+      return 0;
44
+    end if;
45
+    return data + 1;
46
+  end function incr_pnt;
47
+
48
+
49
+begin
50
+
51
+
52
+  WriteP : process (Reset_n_i, Clk_i) is
53
+  begin
54
+    if (Reset_n_i = '0') then
55
+      s_write_pnt <= 0;
56
+      Werror_o    <= '0';
57
+    elsif (rising_edge(Clk_i)) then
58
+      Werror_o <= Wen_i and Full_o;
59
+      if (Wen_i = '1' and Full_o = '0') then
60
+        s_fifo_mem(s_write_pnt) <= Din_i;
61
+        s_write_pnt <= incr_pnt(s_write_pnt);
62
+      end if;
63
+    end if;
64
+  end process WriteP;
65
+
66
+
67
+  ReadP : process (Reset_n_i, Clk_i) is
68
+  begin
69
+    if (Reset_n_i = '0') then
70
+      s_read_pnt <= 0;
71
+      Rerror_o   <= '0';
72
+    elsif (rising_edge(Clk_i)) then
73
+      Rerror_o <= Ren_i and Empty_o;
74
+      if (Ren_i = '1' and Empty_o = '0') then
75
+        Dout_o <= s_fifo_mem(s_read_pnt);
76
+        s_read_pnt <= incr_pnt(s_read_pnt);
77
+      end if;
78
+    end if;
79
+  end process ReadP;
80
+
81
+
82
+  FlagsP : process (Reset_n_i, Clk_i) is
83
+  begin
84
+    if (Reset_n_i = '0') then
85
+      Full_o  <= '0';
86
+      Empty_o <= '1';
87
+    elsif (rising_edge(Clk_i)) then
88
+      if (Wen_i = '1' and Ren_i = '0') then
89
+        if ((s_write_pnt = s_read_pnt - 1) or
90
+            (s_write_pnt = t_fifo_mem'high and s_read_pnt = t_fifo_mem'low)) then
91
+          Full_o <= '1';
92
+        end if;
93
+        Empty_o <= '0';
94
+      end if;
95
+      if (Ren_i = '1' and Wen_i = '0') then
96
+        if ((s_read_pnt = s_write_pnt - 1) or
97
+            (s_read_pnt = t_fifo_mem'high and s_write_pnt = t_fifo_mem'low)) then
98
+          Empty_o <= '1';
99
+        end if;
100
+        Full_o <= '0';
101
+      end if;
102
+    end if;
103
+  end process FlagsP;
104
+
105
+
106
+  FormalG : if Formal generate
107
+
108
+    default clock is rising_edge(Clk_i);
109
+
110
+    -- Initial reset
111
+    restrict {not Reset_n_i[*3]; Reset_n_i[+]}[*1];
112
+
113
+    -- Inputs are low during reset for simplicity
114
+    assume always not Reset_n_i -> not Wen_i and not Ren_i;
115
+
116
+
117
+    -- Asynchronous (unclocked) Reset asserts
118
+    FULL_RESET : process (all) is
119
+    begin
120
+      if (not Reset_n_i) then
121
+        RESET_FULL      : assert not Full_o;
122
+        RESET_EMPTY     : assert Empty_o;
123
+        RESET_WERROR    : assert not Werror_o;
124
+        RESET_RERROR    : assert not Rerror_o;
125
+        RESET_WRITE_PNT : assert s_write_pnt = 0;
126
+        RESET_READ_PNT  : assert s_read_pnt = 0;
127
+      end if;
128
+    end process;
129
+
130
+
131
+    -- No write pointer change when writing into full fifo
132
+    WRITE_PNT_STABLE_WHEN_FULL : assert always
133
+      Wen_i and Full_o ->
134
+      next stable(s_write_pnt);
135
+
136
+    -- No read pointer change when reading from empty fifo
137
+    READ_PNT_STABLE_WHEN_EMPTY : assert always
138
+      Ren_i and Empty_o ->
139
+      next stable(s_read_pnt);
140
+
141
+    -- Full when write and no read and write pointer ran up to read pointer
142
+    FULL : assert always
143
+      Wen_i and not Ren_i and
144
+      (s_write_pnt = s_read_pnt - 1 or s_write_pnt = t_fifo_pnt'high and s_read_pnt = t_fifo_pnt'low) ->
145
+      next Full_o;
146
+
147
+    -- Not full when read and no write
148
+    NOT_FULL : assert always
149
+      not Wen_i and Ren_i ->
150
+      next not Full_o;
151
+
152
+    -- Empty when read and no write and read pointer ran up to write pointer
153
+    EMPTY : assert always
154
+      not Wen_i and Ren_i and
155
+      (s_read_pnt = s_write_pnt - 1 or s_read_pnt = t_fifo_pnt'high and s_write_pnt = t_fifo_pnt'low) ->
156
+      next Empty_o;
157
+
158
+    -- Not empty when write and no read
159
+    NOT_EMPTY : assert always
160
+      Wen_i and not Ren_i ->
161
+      next not Empty_o;
162
+
163
+    -- Write error when writing into full fifo
164
+    WERROR : assert always
165
+      Wen_i and Full_o ->
166
+        next Werror_o;
167
+
168
+    -- No write error when writing into not full fifo
169
+    NO_WERROR : assert always
170
+      Wen_i and not Full_o ->
171
+        next not Werror_o;
172
+
173
+    -- Read error when reading from empty fifo
174
+    RERROR : assert always
175
+      Ren_i and Empty_o ->
176
+      next Rerror_o;
177
+
178
+    -- No read error when reading from not empty fifo
179
+    NO_RERROR : assert always
180
+      Ren_i and not Empty_o ->
181
+      next not Rerror_o;
182
+
183
+    -- Write pointer increment when writing into not full fifo
184
+    -- and write pointer isn't at end value
185
+    WRITE_PNT_INCR : assert always
186
+      Wen_i and not Full_o and s_write_pnt /= t_fifo_pnt'high ->
187
+      next s_write_pnt = prev(s_write_pnt) + 1;
188
+
189
+    -- Write pointer wraparound when writing into not full fifo
190
+    -- and write pointer is at end value
191
+    WRITE_PNT_WRAP : assert always
192
+      Wen_i and not Full_o and s_write_pnt = t_fifo_pnt'high ->
193
+      next s_write_pnt = 0;
194
+
195
+    -- Read pointer increment when reading from not empty fifo
196
+    -- and read pointer isn't at end value
197
+    READ_PNT_INCR  : assert always
198
+      Ren_i and not Empty_o and s_read_pnt /= t_fifo_pnt'high ->
199
+      next s_read_pnt = prev(s_read_pnt) + 1;
200
+
201
+    -- Read pointer wraparound when reading from not empty fifo
202
+    -- and read pointer is at end value
203
+    READ_PNT_WRAP  : assert always
204
+      Ren_i and not Empty_o and s_read_pnt = t_fifo_pnt'high ->
205
+      next s_read_pnt = 0;
206
+
207
+    -- Correct input data stored after valid write access
208
+    DIN_VALID : assert always
209
+      Wen_i and not Full_o ->
210
+      next s_fifo_mem(s_write_pnt - 1) = prev(Din_i);
211
+
212
+    -- Correct output data after valid read access
213
+    DOUT_VALID : assert always
214
+      Ren_i and not Empty_o ->
215
+      next Dout_o = s_fifo_mem(s_read_pnt - 1);
216
+
217
+  end generate FormalG;
218
+
219
+
220
+end architecture rtl;

+ 22
- 0
fifo/symbiyosys.sby View File

@@ -0,0 +1,22 @@
1
+[tasks]
2
+cover
3
+bmc
4
+prove
5
+
6
+[options]
7
+depth 25
8
+cover: mode cover
9
+bmc: mode bmc
10
+prove: mode prove
11
+
12
+[engines]
13
+cover: smtbmc z3
14
+bmc: abc bmc3
15
+prove: abc pdr
16
+
17
+[script]
18
+ghdl --std=08 -gFormal=true -gDepth=16 -gWidth=16 fifo.vhd -e fifo
19
+prep -auto-top
20
+
21
+[files]
22
+fifo.vhd