|
|
- import cocotb
- from cocotb.triggers import RisingEdge, Timer
- from cocotb.queue import QueueEmpty, Queue
- from cocotb.clock import Clock
- import logging
- import enum
- import pyuvm
-
-
- # Logger setup
- logging.basicConfig(level=logging.NOTSET)
- logger = logging.getLogger()
- logger.setLevel(logging.DEBUG)
-
-
- # AES mode enum
- @enum.unique
- class Mode(enum.IntEnum):
- Encrypt = 0
- Decrypt = 1
-
-
- # VAI BFM with queues for
- class VaiBfm(metaclass=pyuvm.Singleton):
- """Valid-Accept Bfm"""
-
- def __init__(self):
- self.log = logging.getLogger()
- self.log.info("Valid-accept BFM")
- self.log.info(" Copyright (c) 2024 Torsten Meissner")
- self.dut = cocotb.top
- self.driver_queue = Queue(maxsize=1)
- self.in_monitor_queue = Queue(maxsize=0)
- self.out_monitor_queue = Queue(maxsize=0)
- self.clock = Clock(
- self.dut.clk_i, 10, units="ns"
- ) # Create a 10 ns period clock
- cocotb.start_soon(self.clock.start())
-
- # Reset coroutine
- async def reset(self):
- self.dut.reset_i.value = 0
- self.dut.valid_i.value = 0
- self.dut.mode_i.value = 0
- self.dut.key_i.value = 0
- self.dut.data_i.value = 0
- self.dut.accept_i.value = 0
- await Timer(100, units="ns")
- self.dut.reset_i.value = 1
-
- # VAI input driver
- async def __driver(self):
- self.dut.valid_i.value = 0
- self.dut.key_i.value = 0
- self.dut.data_i.value = 0
- while True:
- await RisingEdge(self.dut.clk_i)
- if not self.dut.valid_i.value:
- try:
- (mode, key, data) = self.driver_queue.get_nowait()
- self.dut.mode_i.value = mode
- self.dut.key_i.value = key
- self.dut.data_i.value = data
- self.dut.valid_i.value = 1
- except QueueEmpty:
- continue
- else:
- if self.dut.accept_o.value:
- self.dut.valid_i.value = 0
-
- # VAI output receiver
- # We ignore data out, we use the output monitor instead
- async def __receiver(self):
- self.dut.accept_i.value = 0
- while True:
- await RisingEdge(self.dut.clk_i)
- if self.dut.valid_o.value and not self.dut.accept_i.value:
- self.dut.accept_i.value = 1
- else:
- self.dut.accept_i.value = 0
-
- # VAI input monitor
- async def __in_monitor(self):
- while True:
- await RisingEdge(self.dut.clk_i)
- if self.dut.valid_i.value and self.dut.accept_o.value:
- in_tuple = (
- self.dut.mode_i.value,
- self.dut.key_i.value,
- self.dut.data_i.value,
- )
- self.in_monitor_queue.put_nowait(in_tuple)
-
- # VAI output monitor
- async def __out_monitor(self):
- while True:
- await RisingEdge(self.dut.clk_i)
- if self.dut.valid_o.value and self.dut.accept_i.value:
- out_data = self.dut.data_o.value
- self.out_monitor_queue.put_nowait(out_data)
-
- # Launching the coroutines using start_soon
- def start_tasks(self):
- cocotb.start_soon(self.__driver())
- cocotb.start_soon(self.__receiver())
- cocotb.start_soon(self.__in_monitor())
- cocotb.start_soon(self.__out_monitor())
-
- # The get_input() coroutine returns the next VAI input
- async def get_input(self):
- data = await self.in_monitor_queue.get()
- return data
-
- # The get_output() coroutine returns the next VAI output
- async def get_output(self):
- data = await self.out_monitor_queue.get()
- return data
-
- # send_op puts the VAI input operation into the driver queue
- async def send_op(self, mode, key, data):
- await self.driver_queue.put((mode, key, data))
|