Skip to content

Commit

Permalink
Add new i2c test
Browse files Browse the repository at this point in the history
  • Loading branch information
M0stafaRady committed Oct 2, 2024
1 parent 160dbc6 commit 9174134
Show file tree
Hide file tree
Showing 5 changed files with 122 additions and 46 deletions.
6 changes: 3 additions & 3 deletions verify/uvm-python/i2c_ref_model/i2c_ref_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ def write_bus(self, tr):

elif td.kind == bus_item.READ:
if td.addr == self.regs.reg_name_to_address["Data"]:
td.data = self.fifo_rx.get_nowait() | (0b1 << 8) # add valid data bit
td.data = (self.fifo_rx.get_nowait() | (0b1 << 8)) & 0x1FF # add valid data bit, remove last bit
self.bus_bus_export.write(td) # this is output to the scoreboard

def decode_command(self, command):
Expand Down Expand Up @@ -198,9 +198,9 @@ def write(self, address, value):
if not (0 <= address < self.size):
raise ValueError(f"Invalid address {address}. Must be between 0 and {self.size - 1}.")
if not (0 <= value <= self.max_value):
raise ValueError(f"Invalid value {value}. Must be between 0 and {self.max_value}.")
uvm_warning("MemoryBlock",f"Invalid value {value}. Must be between 0 and {self.max_value}.")
self.memory[address] = value
uvm_info("MemoryBlock",f"Wrote value {hex(value)} to address {hex(address)}.", UVM_LOW)
uvm_info("MemoryBlock",f"Wrote value {hex(value)} to address {hex(address)}.", UVM_HIGH)



Expand Down
61 changes: 59 additions & 2 deletions verify/uvm-python/i2c_seq_lib/i2c_bus_seq_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ def __init__(self, name="i2c_bus_seq_base"):
uvm_fatal(self.tag, "No json file wrapper regs")
else:
self.regs = regs_arr[0]
self.slave0 = slave_valid_addr(0b1010101)
self.slave1 = slave_valid_addr(0b1010110)


async def body(self):
await super().body()
Expand All @@ -28,7 +31,30 @@ async def body(self):

async def change_PR(self, val):
await self.send_req(is_write=True, reg="PR", data_value=val)


async def write_multiple(self, slave_address, address, data):
uvm_info(self.tag, f"write_multiple slave address = 0x{slave_address:X}, address = 0x{address:X}, data = {data}", UVM_MEDIUM)
# address write_mul
commad_write = slave_address | 1 << 10
command_write_mul = slave_address | 1 << 11
await self.wait_data_fifo_not_full()
await self.send_req(is_write=True, reg="Command", data_value=commad_write) # issue write command
await self.send_req(is_write=True, reg="Data", data_value=(address>>8) & 0xFF) # address high
await self.wait_data_fifo_not_full()
await self.send_req(is_write=True, reg="Command", data_value=commad_write) # issue write command
await self.send_req(is_write=True, reg="Data", data_value=address & 0xFF) # address low
# write mul
await self.send_req(is_write=True, reg="Command", data_value=command_write_mul) # issue write command
for i in data[:-1]: # data
await self.wait_data_fifo_not_full()
await self.send_req(is_write=True, reg="Data", data_value=i) # data
# send last data and add data last bit
await self.wait_data_fifo_not_full()
await self.send_req(is_write=True, reg="Data", data_value=data[-1] | 1 << 9) # data
command_stop = slave_address | 1 << 12 # stop
await self.send_req(is_write=True, reg="Command", data_value=command_stop) # issue write command
await Timer(100, "us")

async def write_address(self, slave_address, address, data):
uvm_info(self.tag, f"write_address slave address = 0x{slave_address:X}, address = 0x{address:X}, data = {data}", UVM_MEDIUM)
# address write
Expand All @@ -49,7 +75,7 @@ async def write_address(self, slave_address, address, data):

async def read_address(self, slave_address, address, number_of_reads=1):
# address read
commad_write = slave_address | 1 << 10
commad_write = slave_address | 1 << 10
commad_read = slave_address | 1 << 9
await self.wait_data_fifo_not_full()
await self.send_req(is_write=True, reg="Command", data_value=commad_write) # issue read command
Expand Down Expand Up @@ -101,3 +127,34 @@ async def wait_data_rx_not_empty(self):
await self.send_nop()

uvm_object_utils(i2c_bus_seq_base)



class slave_valid_addr():
def __init__(self, address):
self.slave_address = address
self.valid_address = []

def write_address(self):
address = random.randint(0, 8191) & 0x1FE0 # 0x1FE0 ensures the first 5 bits are 0
number_of_data = random.randint(1, 7)
for i in range(number_of_data):
self.valid_address.append(address + i)
return (self.slave_address, "write",address, number_of_data)

def read_address(self):
if len(self.valid_address) == 0:
return self.write_address()
address = random.choice(self.valid_address)
number_of_data = random.randint(1, 7)
for i in range(number_of_data):
if (address + i) not in self.valid_address:
number_of_data = i
break
return (self.slave_address, "read", address, number_of_data)

def choose_op(self):
if random.random() > 0.75:
return self.write_address()
else:
return self.read_address()
38 changes: 38 additions & 0 deletions verify/uvm-python/i2c_seq_lib/i2c_write_mul_seq.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
from uvm.seq import UVMSequence
from uvm.macros.uvm_object_defines import uvm_object_utils
from uvm.macros.uvm_message_defines import uvm_fatal
from uvm.base.uvm_config_db import UVMConfigDb
from EF_UVM.bus_env.bus_seq_lib.bus_seq_base import bus_seq_base
from cocotb.triggers import Timer
from uvm.macros.uvm_sequence_defines import uvm_do_with, uvm_do
from i2c_seq_lib.i2c_bus_seq_base import i2c_bus_seq_base
import random
from uvm.macros import uvm_component_utils, uvm_info, uvm_error, uvm_warning
from uvm.base.uvm_object_globals import UVM_HIGH, UVM_LOW, UVM_MEDIUM


class i2c_write_mul_seq(i2c_bus_seq_base):
# use this sequence write or read from register by the bus interface
# this sequence should be connected to the bus sequencer in the testbench
# you should create as many sequences as you need not only this one
def __init__(self, name="i2c_write_mul_seq"):
super().__init__(name)

async def body(self):
await super().body()
address = random.randint(0, 8191)
data = [random.randint(0, 255) for i in range(random.randint(1, 10))]
for i in range(10):
if random.random() > 0.5:
slave_address = self.slave0.slave_address
else:
slave_address = self.slave1.slave_address
await self.write_multiple(slave_address, address, data)
await self.read_address(slave_address, address, len(data))
# read rx fifo
for i in range(len(data)):
await self.wait_data_rx_not_empty()
await self.send_req(is_write=False, reg="Data") # read all so the fifo will not get full


uvm_object_utils(i2c_write_mul_seq)
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,13 @@
from uvm.base.uvm_object_globals import UVM_HIGH, UVM_LOW, UVM_MEDIUM


class i2c_bus_seq(i2c_bus_seq_base):
class i2c_write_read_seq(i2c_bus_seq_base):
# use this sequence write or read from register by the bus interface
# this sequence should be connected to the bus sequencer in the testbench
# you should create as many sequences as you need not only this one
def __init__(self, name="i2c_bus_seq"):
super().__init__(name)
self.slave0 = slave_valid_addr(0b1010101)
self.slave1 = slave_valid_addr(0b1010110)

async def body(self):
await super().body()
for i in range(100):
Expand All @@ -38,34 +37,4 @@ async def body(self):
await self.wait_data_rx_not_empty()
await self.send_req(is_write=False, reg="Data") # read all so the fifo will not get full

uvm_object_utils(i2c_bus_seq)


class slave_valid_addr():
def __init__(self, address):
self.slave_address = address
self.valid_address = []

def write_address(self):
address = random.randint(0, 8191) & 0x1FE0 # 0x1FE0 ensures the first 5 bits are 0
number_of_data = random.randint(1, 7)
for i in range(number_of_data):
self.valid_address.append(address + i)
return (self.slave_address, "write",address, number_of_data)

def read_address(self):
if len(self.valid_address) == 0:
return self.write_address()
address = random.choice(self.valid_address)
number_of_data = random.randint(1, 7)
for i in range(number_of_data):
if (address + i) not in self.valid_address:
number_of_data = i
break
return (self.slave_address, "read", address, number_of_data)

def choose_op(self):
if random.random() > 0.75:
return self.write_address()
else:
return self.read_address()
uvm_object_utils(i2c_bus_seq_base)
26 changes: 19 additions & 7 deletions verify/uvm-python/test_lib.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@
from EF_UVM.base_test import base_test

# seqences import
from i2c_seq_lib.i2c_bus_seq import i2c_bus_seq
from i2c_seq_lib.i2c_write_read_seq import i2c_write_read_seq
from i2c_seq_lib.i2c_write_mul_seq import i2c_write_mul_seq
from i2c_seq_lib.i2c_ip_seq import i2c_ip_seq

# override classes
Expand Down Expand Up @@ -82,20 +83,31 @@ def build_phase(self, phase):
uvm_component_utils(i2c_base_test)


class i2c_first_test(i2c_base_test):
class i2c_write_read_test(i2c_base_test):
def __init__(self, name="i2c__first_test", parent=None):
super().__init__(name, parent=parent)
self.tag = name

async def main_phase(self, phase):
uvm_info(self.tag, f"Starting test {self.__class__.__name__}", UVM_LOW)
phase.raise_objection(self, f"{self.__class__.__name__} OBJECTED")
bus_seq = i2c_bus_seq("i2c_bus_seq")
ip_seq = i2c_ip_seq("i2c_ip_seq")
bus_seq = i2c_write_read_seq("i2c_write_read_seq")
await bus_seq.start(self.bus_sqr)
# await ip_seq.start(self.ip_sqr)
await Timer(100000 , "ns")
await Timer(10000 , "ns")
phase.drop_objection(self, f"{self.__class__.__name__} drop objection")

class i2c_write_mul_test(i2c_base_test):
def __init__(self, name="i2c_write_mul_test", parent=None):
super().__init__(name, parent=parent)
self.tag = name

async def main_phase(self, phase):
uvm_info(self.tag, f"Starting test {self.__class__.__name__}", UVM_LOW)
phase.raise_objection(self, f"{self.__class__.__name__} OBJECTED")
bus_seq = i2c_write_mul_seq("i2c_write_mul_seq")
await bus_seq.start(self.bus_sqr)
await Timer(10000 , "ns")
phase.drop_objection(self, f"{self.__class__.__name__} drop objection")


uvm_component_utils(i2c_first_test)
uvm_component_utils(i2c_write_mul_test)

0 comments on commit 9174134

Please sign in to comment.