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