Examples of using PSL for functional and formal verification of VHDL with GHDL (and SymbiYosys)
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.

86 lines
3.0 KiB

  1. library ieee;
  2. use ieee.std_logic_1164.all;
  3. use work.pkg.all;
  4. entity psl_cover is
  5. port (
  6. clk : in std_logic
  7. );
  8. end entity psl_cover;
  9. architecture psl of psl_cover is
  10. signal req, busy, done : std_logic;
  11. begin
  12. -- 0123456789
  13. SEQ_REQ : sequencer generic map ("_-________") port map (clk, req);
  14. SEQ_BUSY : sequencer generic map ("__-_-_-___") port map (clk, busy);
  15. SEQ_DONE : sequencer generic map ("________-_") port map (clk, done);
  16. -- All is sensitive to rising edge of clk
  17. default clock is rising_edge(clk);
  18. -- Covers a transfer request
  19. -- This cover directive holds at cycle 1
  20. COVER_0_c : cover {req}
  21. report "Transfer requested";
  22. -- Covers started processing of transfers
  23. -- This cover directive holds at cycle 2
  24. COVER_1_c : cover {req; {{busy[=1]} && {not done[+]}}}
  25. report "Transfer in progress";
  26. -- Covers each transfer with length in range 1 to 8
  27. -- This cover directive holds at cycle 8
  28. COVER_2_c : cover {req; {{busy[=1 to 8]} && {not done[+]}}; done}
  29. report "Transfer done";
  30. -- Cover transfers with length in range 1 to 8 separately
  31. cover_transfer_lengths : for i in 1 to 8 generate
  32. begin
  33. -- Don't works with GHDL, but should? Is a defined as static in the
  34. -- generate body?
  35. --COVER_TRANSFER_LENGTH_c : cover {req; {{busy[=i]} && {not done[+]}}; done};
  36. end generate cover_transfer_lengths;
  37. -- Workaround: writing separate cover directives for
  38. -- each length, very tedious
  39. -- Only length 3 holds at cycle 8, all others not
  40. COVER_LENGTH_1_c : cover {req; {{busy[=1]} && {not done[+]}}; done};
  41. COVER_LENGTH_2_c : cover {req; {{busy[=2]} && {not done[+]}}; done};
  42. COVER_LENGTH_3_c : cover {req; {{busy[=3]} && {not done[+]}}; done};
  43. COVER_LENGTH_4_c : cover {req; {{busy[=4]} && {not done[+]}}; done};
  44. COVER_LENGTH_5_c : cover {req; {{busy[=5]} && {not done[+]}}; done};
  45. COVER_LENGTH_6_c : cover {req; {{busy[=6]} && {not done[+]}}; done};
  46. COVER_LENGTH_7_c : cover {req; {{busy[=7]} && {not done[+]}}; done};
  47. COVER_LENGTH_8_c : cover {req; {{busy[=8]} && {not done[+]}}; done};
  48. -- BTW: GHDL synthesis creates a cover directive for each assert directive
  49. -- which is really nice. So you can run SymbiYosys in cover mode
  50. -- to see if your assertions can actually be active.
  51. -- This assertion checks for the final done at the end of transfer.
  52. -- In cover mode, the LHS side of the property has to hold.
  53. -- This cover directive holds at cycle 7
  54. ASSERT_a : assert always {req; {{busy[=3]} && {not done[+]}}; not done} |=> {done};
  55. -- For simulation, you have to write a separate cover directive when
  56. -- you want to check if your assertion can be active
  57. -- Simply use the LHS of the asserts property
  58. COVER_A : cover {req; {{busy[=3]} && {not done[+]}}; not done}
  59. report "Transfer of length 3";
  60. -- Stop simulation after longest running sequencer is finished
  61. -- Simulation only code by using pragmas
  62. -- synthesis translate_off
  63. stop_sim(clk, 10);
  64. -- synthesis translate_on
  65. end architecture psl;