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.

220 lines
6.1 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 {not Reset_n_i[*3]; Reset_n_i[+]}[*1];
  91. -- Inputs are low during reset for simplicity
  92. assume always not Reset_n_i -> not Wen_i and not Ren_i;
  93. -- Asynchronous (unclocked) Reset asserts
  94. FULL_RESET : process (all) is
  95. begin
  96. if (not Reset_n_i) then
  97. RESET_FULL : assert not Full_o;
  98. RESET_EMPTY : assert Empty_o;
  99. RESET_WERROR : assert not Werror_o;
  100. RESET_RERROR : assert not Rerror_o;
  101. RESET_WRITE_PNT : assert s_write_pnt = 0;
  102. RESET_READ_PNT : assert s_read_pnt = 0;
  103. end if;
  104. end process;
  105. -- No write pointer change when writing into full fifo
  106. WRITE_PNT_STABLE_WHEN_FULL : assert always
  107. Wen_i and Full_o ->
  108. next stable(s_write_pnt);
  109. -- No read pointer change when reading from empty fifo
  110. READ_PNT_STABLE_WHEN_EMPTY : assert always
  111. Ren_i and Empty_o ->
  112. next stable(s_read_pnt);
  113. -- Full when write and no read and write pointer ran up to read pointer
  114. FULL : assert always
  115. Wen_i and not Ren_i and
  116. (s_write_pnt = s_read_pnt - 1 or s_write_pnt = t_fifo_pnt'high and s_read_pnt = t_fifo_pnt'low) ->
  117. next Full_o;
  118. -- Not full when read and no write
  119. NOT_FULL : assert always
  120. not Wen_i and Ren_i ->
  121. next not Full_o;
  122. -- Empty when read and no write and read pointer ran up to write pointer
  123. EMPTY : assert always
  124. not Wen_i and Ren_i and
  125. (s_read_pnt = s_write_pnt - 1 or s_read_pnt = t_fifo_pnt'high and s_write_pnt = t_fifo_pnt'low) ->
  126. next Empty_o;
  127. -- Not empty when write and no read
  128. NOT_EMPTY : assert always
  129. Wen_i and not Ren_i ->
  130. next not Empty_o;
  131. -- Write error when writing into full fifo
  132. WERROR : assert always
  133. Wen_i and Full_o ->
  134. next Werror_o;
  135. -- No write error when writing into not full fifo
  136. NO_WERROR : assert always
  137. Wen_i and not Full_o ->
  138. next not Werror_o;
  139. -- Read error when reading from empty fifo
  140. RERROR : assert always
  141. Ren_i and Empty_o ->
  142. next Rerror_o;
  143. -- No read error when reading from not empty fifo
  144. NO_RERROR : assert always
  145. Ren_i and not Empty_o ->
  146. next not Rerror_o;
  147. -- Write pointer increment when writing into not full fifo
  148. -- and write pointer isn't at end value
  149. WRITE_PNT_INCR : assert always
  150. Wen_i and not Full_o and s_write_pnt /= t_fifo_pnt'high ->
  151. next s_write_pnt = prev(s_write_pnt) + 1;
  152. -- Write pointer wraparound when writing into not full fifo
  153. -- and write pointer is at end value
  154. WRITE_PNT_WRAP : assert always
  155. Wen_i and not Full_o and s_write_pnt = t_fifo_pnt'high ->
  156. next s_write_pnt = 0;
  157. -- Read pointer increment when reading from not empty fifo
  158. -- and read pointer isn't at end value
  159. READ_PNT_INCR : assert always
  160. Ren_i and not Empty_o and s_read_pnt /= t_fifo_pnt'high ->
  161. next s_read_pnt = prev(s_read_pnt) + 1;
  162. -- Read pointer wraparound when reading from not empty fifo
  163. -- and read pointer is at end value
  164. READ_PNT_WRAP : assert always
  165. Ren_i and not Empty_o and s_read_pnt = t_fifo_pnt'high ->
  166. next s_read_pnt = 0;
  167. -- Correct input data stored after valid write access
  168. DIN_VALID : assert always
  169. Wen_i and not Full_o ->
  170. next s_fifo_mem(s_write_pnt - 1) = prev(Din_i);
  171. -- Correct output data after valid read access
  172. DOUT_VALID : assert always
  173. Ren_i and not Empty_o ->
  174. next Dout_o = s_fifo_mem(s_read_pnt - 1);
  175. end generate FormalG;
  176. end architecture rtl;