Examples of using cocotb for functional verification of VHDL designs with GHDL.
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.

105 lines
3.3 KiB

  1. import logging
  2. import random
  3. import cocotb
  4. import pprint
  5. from Vai import VaiDriver, VaiReceiver
  6. from cocotb.clock import Clock
  7. from cocotb.triggers import FallingEdge, RisingEdge, Timer, ReadOnly
  8. from Crypto.Cipher import AES
  9. from Crypto.Util.number import long_to_bytes, getRandomNBitInteger
  10. import binascii
  11. # Reset coroutine
  12. async def reset_dut(reset_n, duration_ns):
  13. reset_n.value = 0
  14. await Timer(duration_ns, units="ns")
  15. reset_n.value = 1
  16. @cocotb.test()
  17. async def test_aes_enc(dut):
  18. """ Test AES encryption """
  19. clkedge = RisingEdge(dut.clk_i)
  20. # Connect reset
  21. reset = dut.reset_i
  22. # Instantiate VAI driver & receiver
  23. _input = [dut.mode_i, dut.key_i, dut.data_i]
  24. vai_driver = VaiDriver(dut.clk_i, _input, dut.valid_i, dut.accept_o)
  25. vai_receiver = VaiReceiver(dut.clk_i, dut.data_o, dut.valid_o, dut.accept_i)
  26. # Drive input defaults (setimmediatevalue to avoid x asserts)
  27. dut.mode_i.setimmediatevalue(0)
  28. dut.key_i.setimmediatevalue(0)
  29. dut.data_i.setimmediatevalue(0)
  30. dut.valid_i.setimmediatevalue(0)
  31. dut.accept_i.setimmediatevalue(0)
  32. clock = Clock(dut.clk_i, 10, units="ns") # Create a 10 ns period clock
  33. cocotb.start_soon(clock.start()) # Start the clock
  34. # Execution will block until reset_dut has completed
  35. dut._log.info("Hold reset")
  36. await reset_dut(reset, 100)
  37. dut._log.info("Released reset")
  38. # Test 10 AES calculations
  39. for i in range(10):
  40. await clkedge
  41. _key = getRandomNBitInteger(128)
  42. _data = getRandomNBitInteger(128)
  43. # Drive AES inputs
  44. await vai_driver.send([0, _key, _data])
  45. # Calc reference data
  46. _aes = AES.new(long_to_bytes(_key), AES.MODE_ECB)
  47. _ref = _aes.encrypt(long_to_bytes(_data))
  48. # Get DUT output data
  49. _rec = await vai_receiver.receive()
  50. assert _rec.buff == _ref, f"Encrypt error, got {_rec.buff}, expected {_ref}"
  51. @cocotb.test()
  52. async def test_aes_dec(dut):
  53. """ Test AES decryption """
  54. clkedge = RisingEdge(dut.clk_i)
  55. # Connect reset
  56. reset = dut.reset_i
  57. # Instantiate VAI driver & receiver
  58. _input = [dut.mode_i, dut.key_i, dut.data_i]
  59. vai_driver = VaiDriver(dut.clk_i, _input, dut.valid_i, dut.accept_o)
  60. vai_receiver = VaiReceiver(dut.clk_i, dut.data_o, dut.valid_o, dut.accept_i)
  61. # Drive input defaults (setimmediatevalue to avoid x asserts)
  62. dut.mode_i.setimmediatevalue(0)
  63. dut.key_i.setimmediatevalue(0)
  64. dut.data_i.setimmediatevalue(0)
  65. dut.valid_i.setimmediatevalue(0)
  66. dut.accept_i.setimmediatevalue(0)
  67. clock = Clock(dut.clk_i, 10, units="ns") # Create a 10 ns period clock
  68. cocotb.start_soon(clock.start()) # Start the clock
  69. # Execution will block until reset_dut has completed
  70. dut._log.info("Hold reset")
  71. await reset_dut(reset, 100)
  72. dut._log.info("Released reset")
  73. # Test 10 AES calculations
  74. for i in range(10):
  75. await clkedge
  76. _key = getRandomNBitInteger(128)
  77. _data = getRandomNBitInteger(128)
  78. # Drive AES inputs
  79. await vai_driver.send([1, _key, _data])
  80. # Calc reference data
  81. _aes = AES.new(long_to_bytes(_key), AES.MODE_ECB)
  82. _ref = _aes.decrypt(long_to_bytes(_data))
  83. # Get DUT output data
  84. _rec = await vai_receiver.receive()
  85. assert _rec.buff == _ref, f"Decrypt error, got {_rec.buff}, expected {_ref}"