Browse Source

Add simple example verifying an aes unit

master
T. Meissner 3 years ago
parent
commit
3f97ee4f30
5 changed files with 128 additions and 6 deletions
  1. +3
    -0
      .gitignore
  2. +5
    -1
      env-setup.sh
  3. +1
    -0
      requirements.txt
  4. +14
    -5
      tests/Vai.py
  5. +105
    -0
      tests/tb_aes.py

+ 3
- 0
.gitignore View File

@ -0,0 +1,3 @@
cryptocores
libvhdl
cocotbext-wishbone

+ 5
- 1
env-setup.sh View File

@ -7,5 +7,9 @@ if [ ! -d cocotbext-wishbone/.git ]; then
fi fi
if [ ! -d libvhdl/.git ]; then if [ ! -d libvhdl/.git ]; then
git clone https://github.com/tmeissner/libvhdl.git
git clone https://github.com/tmeissner/libvhdl.git
fi
if [ ! -d cryptocores/.git ]; then
git clone https://github.com/tmeissner/cryptocores.git
fi fi

+ 1
- 0
requirements.txt View File

@ -15,3 +15,4 @@ pyuvm
# utilities # utilities
wavedrom wavedrom
pycryptodome

+ 14
- 5
tests/Vai.py View File

@ -8,7 +8,7 @@ class Vai:
def __init__(self, clock, data, valid, accept, *args, **kwargs): def __init__(self, clock, data, valid, accept, *args, **kwargs):
self._version = "0.0.1" self._version = "0.0.1"
self.log = logging.getLogger(f"cocotb.{data._path}")
self.log = logging.getLogger(f"cocotb.{valid._path}")
self._data = data self._data = data
self._valid = valid self._valid = valid
@ -28,17 +28,26 @@ class VaiDriver(Vai):
self.log.info(" cocotbext-vai version %s", self._version) self.log.info(" cocotbext-vai version %s", self._version)
self.log.info(" Copyright (c) 2022 Torsten Meissner") self.log.info(" Copyright (c) 2022 Torsten Meissner")
# Drive input defaults (setimmediatevalue to avoid x asserts)
self._data.setimmediatevalue(0)
# Hack to drive lists of signals
if isinstance(self._data, list):
for entry in self._data:
entry.setimmediatevalue(0)
else:
self._data.setimmediatevalue(0)
self._valid.setimmediatevalue(0) self._valid.setimmediatevalue(0)
async def send(self, data, sync=True): async def send(self, data, sync=True):
if sync: if sync:
await self._clkedge await self._clkedge
self.log.info("Sending data: %s", hex(data))
self._valid.value = 1 self._valid.value = 1
self._data.value = data
# Hack to drive lists of signals
if isinstance(self._data, list):
for i in range(len(self._data)):
self._data[i].value = data[i]
else:
self.log.info("Sending data: %s", hex(data))
self._data.value = data
while True: while True:
await ReadOnly() await ReadOnly()


+ 105
- 0
tests/tb_aes.py View File

@ -0,0 +1,105 @@
import logging
import random
import cocotb
import pprint
from Vai import VaiDriver, VaiReceiver
from cocotb.clock import Clock
from cocotb.triggers import FallingEdge, RisingEdge, Timer, ReadOnly
from Crypto.Cipher import AES
from Crypto.Util.number import long_to_bytes, getRandomNBitInteger
import binascii
# Reset coroutine
async def reset_dut(reset_n, duration_ns):
reset_n.value = 0
await Timer(duration_ns, units="ns")
reset_n.value = 1
@cocotb.test()
async def test_aes_enc(dut):
""" Test AES encryption """
clkedge = RisingEdge(dut.clk_i)
# Connect reset
reset = dut.reset_i
# Instantiate VAI driver & receiver
_input = [dut.mode_i, dut.key_i, dut.data_i]
vai_driver = VaiDriver(dut.clk_i, _input, dut.valid_i, dut.accept_o)
vai_receiver = VaiReceiver(dut.clk_i, dut.data_o, dut.valid_o, dut.accept_i)
# Drive input defaults (setimmediatevalue to avoid x asserts)
dut.mode_i.setimmediatevalue(0)
dut.key_i.setimmediatevalue(0)
dut.data_i.setimmediatevalue(0)
dut.valid_i.setimmediatevalue(0)
dut.accept_i.setimmediatevalue(0)
clock = Clock(dut.clk_i, 10, units="ns") # Create a 10 ns period clock
cocotb.start_soon(clock.start()) # Start the clock
# Execution will block until reset_dut has completed
dut._log.info("Hold reset")
await reset_dut(reset, 100)
dut._log.info("Released reset")
# Test 10 AES calculations
for i in range(10):
await clkedge
_key = getRandomNBitInteger(128)
_data = getRandomNBitInteger(128)
# Drive AES inputs
await vai_driver.send([0, _key, _data])
# Calc reference data
_aes = AES.new(long_to_bytes(_key), AES.MODE_ECB)
_ref = _aes.encrypt(long_to_bytes(_data))
# Get DUT output data
_rec = await vai_receiver.receive()
assert _rec.buff == _ref, f"Encrypt error, got {_rec.buff}, expected {_ref}"
@cocotb.test()
async def test_aes_dec(dut):
""" Test AES decryption """
clkedge = RisingEdge(dut.clk_i)
# Connect reset
reset = dut.reset_i
# Instantiate VAI driver & receiver
_input = [dut.mode_i, dut.key_i, dut.data_i]
vai_driver = VaiDriver(dut.clk_i, _input, dut.valid_i, dut.accept_o)
vai_receiver = VaiReceiver(dut.clk_i, dut.data_o, dut.valid_o, dut.accept_i)
# Drive input defaults (setimmediatevalue to avoid x asserts)
dut.mode_i.setimmediatevalue(0)
dut.key_i.setimmediatevalue(0)
dut.data_i.setimmediatevalue(0)
dut.valid_i.setimmediatevalue(0)
dut.accept_i.setimmediatevalue(0)
clock = Clock(dut.clk_i, 10, units="ns") # Create a 10 ns period clock
cocotb.start_soon(clock.start()) # Start the clock
# Execution will block until reset_dut has completed
dut._log.info("Hold reset")
await reset_dut(reset, 100)
dut._log.info("Released reset")
# Test 10 AES calculations
for i in range(10):
await clkedge
_key = getRandomNBitInteger(128)
_data = getRandomNBitInteger(128)
# Drive AES inputs
await vai_driver.send([1, _key, _data])
# Calc reference data
_aes = AES.new(long_to_bytes(_key), AES.MODE_ECB)
_ref = _aes.decrypt(long_to_bytes(_data))
# Get DUT output data
_rec = await vai_receiver.receive()
assert _rec.buff == _ref, f"Decrypt error, got {_rec.buff}, expected {_ref}"

Loading…
Cancel
Save