caravel/verilog/dv/cocotb/tests/spi_master/SPI_VIP.py

87 lines
3.0 KiB
Python

import random
import cocotb
from cocotb.triggers import FallingEdge,RisingEdge,ClockCycles,Timer
import cocotb.log
from tests.common_functions.test_functions import *
from tests.bitbang.bitbang_functions import *
#VIP for SPI
"""
support commands
00000000 -> No operation
00000011 -> Read in streaming mode
"""
async def SPI_VIP(csb,clk,SDI,SDO,mem):
while True:
await FallingEdge(csb)
cocotb.log.info (f"[SPI_VIP] CSB is asserted operation has begin ")
op = await cocotb.start(SPI_op(clk,SDI,SDO,mem))
await csb_watcher(csb,op)
cocotb.log.info (f"[SPI_VIP] CSB is deasserted operation has been killed")
# watch the csb and when it's diable kill the SPI_op thread
async def csb_watcher(csb,thread):
cocotb.log.info (f"[csb_watcher] start CSB watching")
await RisingEdge(csb)
thread.kill()
# detect command and address and apply the command
async def SPI_op(clk,SDI,SDO,mem):
address =''
command =''
await RisingEdge(clk)
# command
for i in range(8):
command = command + SDI.value.binstr
await RisingEdge(clk)
cocotb.log.info (f"[SPI_VIP] [SPI_op] command = {command}")
# address
address =''
for i in range(8*3): # address is 3 parts each part are 8 bits
address = address + SDI.value.binstr
if i != 23: # skip last cycle wait
await RisingEdge(clk)
cocotb.log.info (f"[SPI_VIP] [SPI_op] address = {address}")
address = int(address,2)
#data
if command == "10000000" and False: # not sure about the read command
for i in range(8):
data_in += SDI
await RisingEdge(clk)
elif command == "00000011":
await FallingEdge(clk)
while True:
data = bin(mem[address])[2:].zfill(8)
for i in range(8):
SDO[0].value = 1 # enable
SDO[1].value = int(data[i],2) # bin
cocotb.log.debug (f"[SPI_VIP] [SPI_op] SDO = {data[i]} ")
await FallingEdge(clk)
SDO[0].value = 0 # enable
cocotb.log.info (f"[SPI_VIP] [SPI_op] finish reading address {hex(address) } data = {hex(int(data,2))} ")
address +=1
def read_mem (file_name):
with open(file_name, 'r') as file:
lines = file.readlines()
mem = dict()
for line in lines:
if line[0] == "@":
address = int(line[1:],16)
cocotb.log.debug (f" found line = {line} address = {hex(address)} ")
else:
line_no_space = line.strip().replace(' ','')
for i in range (0,len(line_no_space),2):
cocotb.log.debug (f" i = {i} ine_no_space[{i}:{i+2}] = {line_no_space[i:i+2]} address = {hex(address)}")
mem[address] = int(line_no_space[i:i+2],16)
address +=1
cocotb.log.debug (f" found line = {line} line_no_space = {line_no_space} size = {len(line_no_space)}")
cocotb.log.info (f"[read_mem] SPI mem = {mem}")
return mem