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.

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