Trying to verify Verilog/VHDL designs with formal methods and tools
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

230 lines
6.3 KiB

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