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.

195 lines
6.6 KiB

  1. vunit formal (vai_reg(rtl)) {
  2. signal s_addr : natural range 0 to 15;
  3. type t_cmd is (READ, WRITE, NOP);
  4. signal s_cmd : t_cmd;
  5. type t_vai is record
  6. Start : std_logic;
  7. Stop : std_logic;
  8. Data : std_logic_vector(7 downto 0);
  9. Valid : std_logic;
  10. Accept : std_logic;
  11. end record t_vai;
  12. signal s_job_req : t_vai;
  13. signal s_job_ack : t_vai;
  14. -- VHDL helper logic
  15. process is
  16. begin
  17. wait until rising_edge(Clk_i);
  18. s_job_req <= (DinStart_i, DinStop_i, Din_i, DinValid_i, DinAccept_o);
  19. s_job_ack <= (DoutStart_o, DoutStop_o, Dout_o, DoutValid_o, DoutAccept_i);
  20. if (s_fsm_state = GET_HEADER) then
  21. if (DinValid_i = '1' and DinStart_i = '1') then
  22. s_cmd <= READ when Din_i(3 downto 0) = x"0" else
  23. WRITE when Din_i(3 downto 0) = x"1" else
  24. NOP;
  25. s_addr <= to_integer(unsigned(Din_i(7 downto 4)));
  26. end if;
  27. end if;
  28. end process;
  29. default clock is rising_edge(Clk_i);
  30. -- RESTRICTIONS
  31. -- Initial reset
  32. INITIAL_RESET : restrict {Reset_n_i = '0'[*2]; Reset_n_i = '1'[+]}[*1];
  33. -- CONSTRAINTS
  34. -- Valid stable until accepted
  35. JOB_REQ_VALID_STABLE : assume always
  36. DinValid_i and not DinAccept_o -> next (DinValid_i until_ DinAccept_o);
  37. -- Start stable until accepted
  38. JOB_REQ_START_STABLE : assume always
  39. DinValid_i and not DinAccept_o -> next (DinStart_i = s_job_req.Start until_ DinAccept_o);
  40. -- Stop stable until accepted
  41. JOB_REQ_STOP_STABLE : assume always
  42. DinValid_i and not DinAccept_o -> next (DinStop_i = s_job_req.Stop until_ DinAccept_o);
  43. -- Data stable until accepted
  44. JOB_REQ_DIN_STABLE : assume always
  45. DinValid_i and not DinAccept_o -> next (Din_i = s_job_req.Data until_ DinAccept_o);
  46. -- ASSERTIONS
  47. -- Reset values
  48. AFTER_RESET : assert always
  49. not Reset_n_i
  50. ->
  51. s_fsm_state = IDLE and
  52. not DinAccept_o and
  53. not DoutStart_o and
  54. not DoutStop_o and
  55. not DoutValid_o and
  56. s_register = (0 to 7 => x"00");
  57. -- FSM states in valid range
  58. FSM_STATES_VALID : assert always
  59. s_fsm_state = IDLE or s_fsm_state = GET_HEADER or
  60. s_fsm_state = GET_DATA or s_fsm_state = SET_DATA or
  61. s_fsm_state = SEND_HEADER or s_fsm_state = SEND_DATA or
  62. s_fsm_state = SEND_FOOTER;
  63. -- Discard jobs with invalid command
  64. INV_CMD_DISCARD : assert always
  65. s_fsm_state = GET_HEADER and DinValid_i = '1' and DinStart_i = '1' and
  66. Din_i(3 downto 0) /= x"0" and Din_i(3 downto 0) /= x"1"
  67. ->
  68. next s_fsm_state = IDLE;
  69. -- Discard read job with invalid stop flags
  70. READ_INV_FLAGS_DISCARD : assert always
  71. s_fsm_state = GET_HEADER and DinValid_i = '1' and DinStart_i = '1' and
  72. Din_i(3 downto 0) = x"0" and DinStop_i = '0'
  73. ->
  74. next s_fsm_state = IDLE;
  75. -- Discard write job with invalid stop flags
  76. WRITE_INV_FLAGS_DISCARD : assert always
  77. s_fsm_state = GET_HEADER and DinValid_i = '1' and DinStart_i = '1' and
  78. Din_i(3 downto 0) = x"1" and DinStop_i = '1'
  79. ->
  80. next s_fsm_state = IDLE;
  81. -- After a valid job read request,
  82. -- a job read acknowledge has to follow
  83. READ_VALID_ACK : assert always
  84. {s_fsm_state = GET_HEADER and DinValid_i = '1' and DinStart_i = '1' and
  85. Din_i(3 downto 0) = x"0" and DinStop_i = '1'}
  86. |=>
  87. {-- Job ack header cycle
  88. not DoutValid_o [*];
  89. DoutValid_o and DoutStart_o and not DoutAccept_i [*];
  90. DoutValid_o and DoutStart_o and DoutAccept_i;
  91. -- Job ack data cycle
  92. not DoutValid_o [*];
  93. DoutValid_o and not DoutStart_o and not DoutStop_o and not DoutAccept_i [*];
  94. DoutValid_o and not DoutStart_o and not DoutStop_o and DoutAccept_i;
  95. -- Job ack footer cycle
  96. not DoutValid_o [*];
  97. DoutValid_o and DoutStop_o};
  98. -- After a valid job write request,
  99. -- a job read acknowledge has to follow
  100. WRITE_VALID_ACK : assert always
  101. {s_fsm_state = GET_HEADER and DinValid_i = '1' and DinStart_i = '1' and
  102. Din_i(3 downto 0) = x"1" and DinStop_i = '0';
  103. not DinValid_i [*];
  104. DinValid_i and DinStop_i}
  105. |=>
  106. {-- Job ack header cycle
  107. not DoutValid_o [*];
  108. DoutValid_o and DoutStart_o and not DoutAccept_i [*];
  109. DoutValid_o and DoutStart_o and DoutAccept_i;
  110. -- Job ack footer cycle
  111. not DoutValid_o [*];
  112. DoutValid_o and DoutStop_o};
  113. -- Start & stop flag have to be exclusive
  114. JOB_ACK_NEVER_START_STOP : assert never
  115. DoutStart_o and DoutStop_o;
  116. -- Start & Stop have to be active together with valid
  117. JOB_ACK_START_STOP_VALID : assert always
  118. DoutStart_o or DoutStop_o -> DoutValid_o;
  119. -- Valid has to be stable until accepted
  120. JOB_ACK_VALID_STABLE : assert always
  121. DoutValid_o and not DoutAccept_i -> next (DoutValid_o until_ DoutAccept_i);
  122. -- Start has to be stable until accepted
  123. JOB_ACK_START_STABLE : assert always
  124. DoutValid_o and not DoutAccept_i -> next (DoutStart_o = s_job_ack.Start until_ DoutAccept_i);
  125. -- Stop has to be stable until accepted
  126. JOB_ACK_STOP_STABLE : assert always
  127. DoutValid_o and not DoutAccept_i -> next (DoutStop_o = s_job_ack.Stop until_ DoutAccept_i);
  128. -- Data has to be stable until accepted
  129. JOB_ACK_DOUT_STABLE : assert always
  130. DoutValid_o and not DoutAccept_i -> next (Dout_o = s_job_ack.Data until_ DoutAccept_i);
  131. -- Data from selected address has to be read
  132. READ_DATA : assert always
  133. DoutValid_o and not DoutStart_o and not DoutStop_o and s_addr <= 7
  134. ->
  135. Dout_o = s_register(s_addr);
  136. -- 0 has to be read when invalid address is given
  137. READ_DATA_INV_ADDR : assert always
  138. DoutValid_o and not DoutStart_o and not DoutStop_o and s_addr > 7
  139. ->
  140. Dout_o = x"00";
  141. -- Register has to be written at given address with given data
  142. -- when correct job req write occurs
  143. WRITE_DATA : assert always
  144. -- Job req header cycle
  145. {s_fsm_state = GET_HEADER and DinValid_i = '1' and DinStart_i = '1' and
  146. Din_i(3 downto 0) = x"1" and unsigned(Din_i(7 downto 4)) <= 7 and DinStop_i = '0';
  147. -- Job req data / footer cycle
  148. not DinValid_i [*];
  149. DinValid_i and not DinStart_i and DinStop_i and not DinAccept_o [*];
  150. DinValid_i and not DinStart_i and DinStop_i and DinAccept_o}
  151. |=>
  152. {s_register(s_addr) = s_job_req.Data};
  153. -- FUNCTIONAL COVERAGE
  154. FOOTER_VALID : cover {DoutValid_o = '1' and DoutStop_o = '1' and Dout_o = 8x"0"};
  155. FOOTER_ERR : cover {DoutValid_o = '1' and DoutStop_o = '1' and Dout_o = 8x"1"};
  156. }