1
0
mirror of https://github.com/corundum/corundum.git synced 2025-01-30 08:32:52 +08:00

Update AXI simulation model

This commit is contained in:
Alex Forencich 2020-07-02 21:28:35 -07:00
parent 281e1a2156
commit ebae4e436d

292
tb/axi.py
View File

@ -73,6 +73,15 @@ AWCACHE_WRITE_BACK_READ_ALLOC = 0b0111
AWCACHE_WRITE_BACK_WRITE_ALLOC = 0b1111 AWCACHE_WRITE_BACK_WRITE_ALLOC = 0b1111
AWCACHE_WRITE_BACK_READ_AND_WRIE_ALLOC = 0b1111 AWCACHE_WRITE_BACK_READ_AND_WRIE_ALLOC = 0b1111
PROT_PRIVILEGED = 0b001
PROT_NONSECURE = 0b010
PROT_INSTRUCTION = 0b100
RESP_OKAY = 0b00
RESP_EXOKAY = 0b01
RESP_SLVERR = 0b10
RESP_DECERR = 0b11
class AXIMaster(object): class AXIMaster(object):
def __init__(self): def __init__(self):
self.write_command_queue = [] self.write_command_queue = []
@ -101,19 +110,21 @@ class AXIMaster(object):
self.int_read_addr_sync = Signal(False) self.int_read_addr_sync = Signal(False)
self.int_read_resp_command_queue = [] self.int_read_resp_command_queue = []
self.int_read_resp_command_sync = Signal(False) self.int_read_resp_command_sync = Signal(False)
self.int_read_resp_queue = [] self.int_read_resp_queue_list = {}
self.int_read_resp_sync = Signal(False) self.int_read_resp_sync = Signal(False)
self.in_flight_operations = 0 self.in_flight_operations = 0
self.max_burst_len = 256
self.has_logic = False self.has_logic = False
self.clk = None self.clk = None
def init_read(self, address, length, burst=0b01, size=None, lock=0b0, cache=0b0000, prot=0b010, qos=0b0000, region=0b0000, user=None): def init_read(self, address, length, burst=0b01, size=None, lock=0b0, cache=0b0011, prot=0b010, qos=0b0000, region=0b0000, user=None):
self.read_command_queue.append((address, length, burst, size, lock, cache, prot, qos, region, user)) self.read_command_queue.append((address, length, burst, size, lock, cache, prot, qos, region, user))
self.read_command_sync.next = not self.read_command_sync self.read_command_sync.next = not self.read_command_sync
def init_write(self, address, data, burst=0b01, size=None, lock=0b0, cache=0b0000, prot=0b010, qos=0b0000, region=0b0000, user=None): def init_write(self, address, data, burst=0b01, size=None, lock=0b0, cache=0b0011, prot=0b010, qos=0b0000, region=0b0000, user=None):
self.write_command_queue.append((address, data, burst, size, lock, cache, prot, qos, region, user)) self.write_command_queue.append((address, data, burst, size, lock, cache, prot, qos, region, user))
self.write_command_sync.next = not self.write_command_sync self.write_command_sync.next = not self.write_command_sync
@ -179,6 +190,12 @@ class AXIMaster(object):
m_axi_ruser=None, m_axi_ruser=None,
m_axi_rvalid=Signal(bool(False)), m_axi_rvalid=Signal(bool(False)),
m_axi_rready=Signal(bool(False)), m_axi_rready=Signal(bool(False)),
pause=False,
awpause=False,
wpause=False,
bpause=False,
arpause=False,
rpause=False,
name=None name=None
): ):
@ -186,26 +203,25 @@ class AXIMaster(object):
raise Exception("Logic already instantiated!") raise Exception("Logic already instantiated!")
if m_axi_wdata is not None: if m_axi_wdata is not None:
assert m_axi_awid is not None if m_axi_awid is not None:
assert m_axi_bid is not None assert m_axi_bid is not None
assert len(m_axi_awid) == len(m_axi_bid) assert len(m_axi_awid) == len(m_axi_bid)
assert m_axi_awaddr is not None assert m_axi_awaddr is not None
assert len(m_axi_wdata) % 8 == 0 assert len(m_axi_wdata) % 8 == 0
assert len(m_axi_wdata) / 8 == len(m_axi_wstrb) assert len(m_axi_wdata) / 8 == len(m_axi_wstrb)
w = len(m_axi_wdata) w = len(m_axi_wdata)
if m_axi_rdata is not None: if m_axi_rdata is not None:
assert m_axi_arid is not None if m_axi_arid is not None:
assert m_axi_rid is not None assert m_axi_rid is not None
assert len(m_axi_arid) == len(m_axi_rid) assert len(m_axi_arid) == len(m_axi_rid)
assert m_axi_araddr is not None assert m_axi_araddr is not None
assert len(m_axi_rdata) % 8 == 0 assert len(m_axi_rdata) % 8 == 0
w = len(m_axi_rdata) w = len(m_axi_rdata)
if m_axi_wdata is not None: if m_axi_wdata is not None:
assert len(m_axi_wdata) == len(m_axi_rdata)
assert len(m_axi_awid) == len(m_axi_arid)
assert len(m_axi_awaddr) == len(m_axi_araddr) assert len(m_axi_awaddr) == len(m_axi_araddr)
assert len(m_axi_wdata) == len(m_axi_rdata)
bw = int(w/8) bw = int(w/8)
@ -214,12 +230,28 @@ class AXIMaster(object):
self.has_logic = True self.has_logic = True
self.clk = clk self.clk = clk
m_axi_bvalid_int = Signal(bool(False))
m_axi_bready_int = Signal(bool(False))
m_axi_rvalid_int = Signal(bool(False))
m_axi_rready_int = Signal(bool(False))
@always_comb
def pause_logic():
m_axi_bvalid_int.next = m_axi_bvalid and not (pause or bpause)
m_axi_bready.next = m_axi_bready_int and not (pause or bpause)
m_axi_rvalid_int.next = m_axi_rvalid and not (pause or rpause)
m_axi_rready.next = m_axi_rready_int and not (pause or rpause)
@instance @instance
def write_logic(): def write_logic():
while True: while True:
if not self.write_command_queue: if not self.write_command_queue:
yield self.write_command_sync yield self.write_command_sync
if m_axi_awaddr is None:
print("Error: attempted write on read-only interface")
raise StopSimulation
addr, data, burst, size, lock, cache, prot, qos, region, user = self.write_command_queue.pop(0) addr, data, burst, size, lock, cache, prot, qos, region, user = self.write_command_queue.pop(0)
self.in_flight_operations += 1 self.in_flight_operations += 1
@ -269,12 +301,17 @@ class AXIMaster(object):
if n >= burst_length: if n >= burst_length:
transfer_count += 1 transfer_count += 1
n = 0 n = 0
burst_length = min(cycles-k, 256) # max len burst_length = min(cycles-k, min(max(self.max_burst_len, 1), 256)) # max len
burst_length = min(burst_length, 0x1000-(cur_addr&0xfff)) # 4k align burst_length = int((min(burst_length*num_bytes, 0x1000-(cur_addr&0xfff))+num_bytes-1)/num_bytes) # 4k align
awid = self.cur_write_id awid = self.cur_write_id
self.cur_write_id = (self.cur_write_id + 1) % 2**len(m_axi_awid) if m_axi_awid is not None:
self.cur_write_id = (self.cur_write_id + 1) % 2**len(m_axi_awid)
else:
self.cur_write_id = 0
self.int_write_addr_queue.append((cur_addr, awid, burst_length-1, size, burst, lock, cache, prot, qos, region, user)) self.int_write_addr_queue.append((cur_addr, awid, burst_length-1, size, burst, lock, cache, prot, qos, region, user))
self.int_write_addr_sync.next = not self.int_write_addr_sync self.int_write_addr_sync.next = not self.int_write_addr_sync
if name is not None:
print("[%s] Write burst awid: 0x%x awaddr: 0x%08x awlen: %d awsize: %d" % (name, awid, cur_addr, burst_length-1, size))
n += 1 n += 1
self.int_write_data_queue.append((val, strb, n >= burst_length)) self.int_write_data_queue.append((val, strb, n >= burst_length))
self.int_write_data_sync.next = not self.int_write_data_sync self.int_write_data_sync.next = not self.int_write_data_sync
@ -299,7 +336,7 @@ class AXIMaster(object):
while not self.int_write_resp_queue: while not self.int_write_resp_queue:
yield clk.posedge yield clk.posedge
cycle_resp = self.int_write_resp_queue.pop(0) cycle_id, cycle_resp, cycle_user = self.int_write_resp_queue.pop(0)
if cycle_resp != 0: if cycle_resp != 0:
resp = cycle_resp resp = cycle_resp
@ -315,7 +352,8 @@ class AXIMaster(object):
yield clk.posedge yield clk.posedge
addr, awid, length, size, burst, lock, cache, prot, qos, region, user = self.int_write_addr_queue.pop(0) addr, awid, length, size, burst, lock, cache, prot, qos, region, user = self.int_write_addr_queue.pop(0)
m_axi_awaddr.next = addr if m_axi_awaddr is not None:
m_axi_awaddr.next = addr
m_axi_awid.next = awid m_axi_awid.next = awid
m_axi_awlen.next = length m_axi_awlen.next = length
m_axi_awsize.next = size m_axi_awsize.next = size
@ -327,11 +365,12 @@ class AXIMaster(object):
m_axi_awregion.next = region m_axi_awregion.next = region
if m_axi_awuser is not None: if m_axi_awuser is not None:
m_axi_awuser.next = user m_axi_awuser.next = user
m_axi_awvalid.next = True m_axi_awvalid.next = not (pause or awpause)
yield clk.posedge yield clk.posedge
while m_axi_awvalid and not m_axi_awready: while not m_axi_awvalid or not m_axi_awready:
m_axi_awvalid.next = m_axi_awvalid or not (pause or awpause)
yield clk.posedge yield clk.posedge
m_axi_awvalid.next = False m_axi_awvalid.next = False
@ -343,11 +382,12 @@ class AXIMaster(object):
yield clk.posedge yield clk.posedge
m_axi_wdata.next, m_axi_wstrb.next, m_axi_wlast.next = self.int_write_data_queue.pop(0) m_axi_wdata.next, m_axi_wstrb.next, m_axi_wlast.next = self.int_write_data_queue.pop(0)
m_axi_wvalid.next = True m_axi_wvalid.next = not (pause or wpause)
yield clk.posedge yield clk.posedge
while m_axi_wvalid and not m_axi_wready: while not m_axi_wvalid or not m_axi_wready:
m_axi_wvalid.next = m_axi_wvalid or not (pause or wpause)
yield clk.posedge yield clk.posedge
m_axi_wvalid.next = False m_axi_wvalid.next = False
@ -355,12 +395,21 @@ class AXIMaster(object):
@instance @instance
def write_resp_interface_logic(): def write_resp_interface_logic():
while True: while True:
m_axi_bready.next = True m_axi_bready_int.next = True
yield clk.posedge yield clk.posedge
if m_axi_bready & m_axi_bvalid: if m_axi_bready and m_axi_bvalid_int:
self.int_write_resp_queue.append(int(m_axi_bresp)) if m_axi_bid is not None:
bid = int(m_axi_bid)
else:
bid = 0
bresp = int(m_axi_bresp)
if m_axi_buser is not None:
buser = int(m_axi_buser)
else:
buser = 0
self.int_write_resp_queue.append((bid, bresp, buser))
self.int_write_resp_sync.next = not self.int_write_resp_sync self.int_write_resp_sync.next = not self.int_write_resp_sync
@instance @instance
@ -369,6 +418,10 @@ class AXIMaster(object):
if not self.read_command_queue: if not self.read_command_queue:
yield self.read_command_sync yield self.read_command_sync
if m_axi_araddr is None:
print("Error: attempted read on write-only interface")
raise StopSimulation
addr, length, burst, size, lock, cache, prot, qos, region, user = self.read_command_queue.pop(0) addr, length, burst, size, lock, cache, prot, qos, region, user = self.read_command_queue.pop(0)
self.in_flight_operations += 1 self.in_flight_operations += 1
@ -385,7 +438,9 @@ class AXIMaster(object):
cycles = int((length + num_bytes-1 + (addr % num_bytes)) / num_bytes) cycles = int((length + num_bytes-1 + (addr % num_bytes)) / num_bytes)
self.int_read_resp_command_queue.append((addr, length, size, cycles, prot)) burst_list = []
self.int_read_resp_command_queue.append((addr, length, size, cycles, prot, burst_list))
self.int_read_resp_command_sync.next = not self.int_read_resp_command_sync self.int_read_resp_command_sync.next = not self.int_read_resp_command_sync
cur_addr = aligned_addr cur_addr = aligned_addr
@ -398,22 +453,30 @@ class AXIMaster(object):
n += 1 n += 1
if n >= burst_length: if n >= burst_length:
n = 0 n = 0
burst_length = min(cycles-k, 256) # max len burst_length = min(cycles-k, min(max(self.max_burst_len, 1), 256)) # max len
burst_length = min(burst_length, 0x1000-((aligned_addr+k*num_bytes)&0xfff))# 4k align burst_length = int((min(burst_length*num_bytes, 0x1000-(cur_addr&0xfff))+num_bytes-1)/num_bytes) # 4k align
arid = self.cur_read_id arid = self.cur_read_id
self.cur_read_id = (self.cur_read_id + 1) % 2**len(m_axi_arid) if m_axi_arid is not None:
self.cur_read_id = (self.cur_read_id + 1) % 2**len(m_axi_arid)
else:
self.cur_read_id = 0
burst_list.append((arid, burst_length))
self.int_read_addr_queue.append((cur_addr, arid, burst_length-1, size, burst, lock, cache, prot, qos, region, user)) self.int_read_addr_queue.append((cur_addr, arid, burst_length-1, size, burst, lock, cache, prot, qos, region, user))
self.int_read_addr_sync.next = not self.int_read_addr_sync self.int_read_addr_sync.next = not self.int_read_addr_sync
if name is not None:
print("[%s] Read burst arid: 0x%x araddr: 0x%08x arlen: %d arsize: %d" % (name, arid, cur_addr, burst_length-1, size))
cur_addr += num_bytes cur_addr += num_bytes
burst_list.append(None)
@instance @instance
def read_resp_logic(): def read_resp_logic():
while True: while True:
if not self.int_read_resp_command_queue: if not self.int_read_resp_command_queue:
yield self.int_read_resp_command_sync yield self.int_read_resp_command_sync
addr, length, size, cycles, prot = self.int_read_resp_command_queue.pop(0) addr, length, size, cycles, prot, burst_list = self.int_read_resp_command_queue.pop(0)
num_bytes = 2**size num_bytes = 2**size
assert 0 <= size <= int(math.log(bw, 2)) assert 0 <= size <= int(math.log(bw, 2))
@ -429,29 +492,46 @@ class AXIMaster(object):
resp = 0 resp = 0
for k in range(cycles): first = True
if not self.int_read_resp_queue:
yield self.int_read_resp_sync
cycle_data, cycle_resp, cycle_last = self.int_read_resp_queue.pop(0) while True:
while not burst_list:
yield clk.posedge
if cycle_resp != 0: cur_burst = burst_list.pop(0)
resp = cycle_resp
start = cycle_offset if cur_burst is None:
stop = cycle_offset+num_bytes break
if k == 0: rid = cur_burst[0]
start = start_offset burst_length = cur_burst[1]
if k == cycles-1:
stop = end_offset
assert cycle_last == (k == cycles - 1) for k in range(burst_length):
self.int_read_resp_queue_list.setdefault(rid, [])
while not self.int_read_resp_queue_list[rid]:
yield self.int_read_resp_sync
for j in range(start, stop): cycle_id, cycle_data, cycle_resp, cycle_last, cycle_user = self.int_read_resp_queue_list[rid].pop(0)
data += bytearray([(cycle_data >> j*8) & 0xff])
cycle_offset = (cycle_offset + num_bytes) % bw if cycle_resp != 0:
resp = cycle_resp
start = cycle_offset
stop = cycle_offset+num_bytes
if first:
start = start_offset
assert cycle_last == (k == burst_length - 1)
for j in range(start, stop):
data += bytearray([(cycle_data >> j*8) & 0xff])
cycle_offset = (cycle_offset + num_bytes) % bw
first = False
data = data[:length]
if name is not None: if name is not None:
print("[%s] Read data addr: 0x%08x prot: 0x%x data: %s" % (name, addr, prot, " ".join(("{:02x}".format(c) for c in bytearray(data))))) print("[%s] Read data addr: 0x%08x prot: 0x%x data: %s" % (name, addr, prot, " ".join(("{:02x}".format(c) for c in bytearray(data)))))
@ -468,7 +548,8 @@ class AXIMaster(object):
addr, arid, length, size, burst, lock, cache, prot, qos, region, user = self.int_read_addr_queue.pop(0) addr, arid, length, size, burst, lock, cache, prot, qos, region, user = self.int_read_addr_queue.pop(0)
m_axi_araddr.next = addr m_axi_araddr.next = addr
m_axi_arid.next = arid if m_axi_arid is not None:
m_axi_arid.next = arid
m_axi_arlen.next = length m_axi_arlen.next = length
m_axi_arsize.next = size m_axi_arsize.next = size
m_axi_arburst.next = burst m_axi_arburst.next = burst
@ -479,11 +560,12 @@ class AXIMaster(object):
m_axi_arregion.next = region m_axi_arregion.next = region
if m_axi_aruser is not None: if m_axi_aruser is not None:
m_axi_aruser.next = user m_axi_aruser.next = user
m_axi_arvalid.next = True m_axi_arvalid.next = not (pause or arpause)
yield clk.posedge yield clk.posedge
while m_axi_arvalid and not m_axi_arready: while not m_axi_arvalid or not m_axi_arready:
m_axi_arvalid.next = m_axi_arvalid or not (pause or arpause)
yield clk.posedge yield clk.posedge
m_axi_arvalid.next = False m_axi_arvalid.next = False
@ -491,12 +573,24 @@ class AXIMaster(object):
@instance @instance
def read_resp_interface_logic(): def read_resp_interface_logic():
while True: while True:
m_axi_rready.next = True m_axi_rready_int.next = True
yield clk.posedge yield clk.posedge
if m_axi_rready & m_axi_rvalid: if m_axi_rready and m_axi_rvalid_int:
self.int_read_resp_queue.append((int(m_axi_rdata), int(m_axi_rresp), int(m_axi_rlast))) if m_axi_rid is not None:
rid = int(m_axi_rid)
else:
rid = 0
rdata = int(m_axi_rdata)
rresp = int(m_axi_rresp)
rlast = int(m_axi_rlast)
if m_axi_buser is not None:
ruser = int(m_axi_ruser)
else:
ruser = 0
self.int_read_resp_queue_list.setdefault(rid, [])
self.int_read_resp_queue_list[rid].append((rid, rdata, rresp, rlast, ruser))
self.int_read_resp_sync.next = not self.int_read_resp_sync self.int_read_resp_sync.next = not self.int_read_resp_sync
return instances() return instances()
@ -525,7 +619,7 @@ class AXIRam(object):
def write_mem(self, address, data): def write_mem(self, address, data):
self.mem.seek(address % self.size) self.mem.seek(address % self.size)
self.mem.write(data) self.mem.write(bytes(data))
def create_port(self, def create_port(self,
clk, clk,
@ -564,35 +658,56 @@ class AXIRam(object):
s_axi_rlast=Signal(bool(True)), s_axi_rlast=Signal(bool(True)),
s_axi_rvalid=Signal(bool(False)), s_axi_rvalid=Signal(bool(False)),
s_axi_rready=Signal(bool(False)), s_axi_rready=Signal(bool(False)),
pause=False,
awpause=False,
wpause=False,
bpause=False,
arpause=False,
rpause=False,
name=None name=None
): ):
if s_axi_wdata is not None: if s_axi_wdata is not None:
assert s_axi_awid is not None if s_axi_awid is not None:
assert s_axi_bid is not None assert s_axi_bid is not None
assert len(s_axi_awid) == len(s_axi_bid) assert len(s_axi_awid) == len(s_axi_bid)
assert s_axi_awaddr is not None assert s_axi_awaddr is not None
assert len(s_axi_wdata) % 8 == 0 assert len(s_axi_wdata) % 8 == 0
assert len(s_axi_wdata) / 8 == len(s_axi_wstrb) assert len(s_axi_wdata) / 8 == len(s_axi_wstrb)
w = len(s_axi_wdata) w = len(s_axi_wdata)
if s_axi_rdata is not None: if s_axi_rdata is not None:
assert s_axi_arid is not None if s_axi_arid is not None:
assert s_axi_rid is not None assert s_axi_rid is not None
assert len(s_axi_arid) == len(s_axi_rid) assert len(s_axi_arid) == len(s_axi_rid)
assert s_axi_araddr is not None assert s_axi_araddr is not None
assert len(s_axi_rdata) % 8 == 0 assert len(s_axi_rdata) % 8 == 0
w = len(s_axi_rdata) w = len(s_axi_rdata)
if s_axi_wdata is not None: if s_axi_wdata is not None:
assert len(s_axi_wdata) == len(s_axi_rdata)
assert len(s_axi_awid) == len(s_axi_arid)
assert len(s_axi_awaddr) == len(s_axi_araddr) assert len(s_axi_awaddr) == len(s_axi_araddr)
assert len(s_axi_wdata) == len(s_axi_rdata)
bw = int(w/8) bw = int(w/8)
assert bw in (1, 2, 4, 8, 16, 32, 64, 128) assert bw in (1, 2, 4, 8, 16, 32, 64, 128)
s_axi_awvalid_int = Signal(bool(False))
s_axi_awready_int = Signal(bool(False))
s_axi_wvalid_int = Signal(bool(False))
s_axi_wready_int = Signal(bool(False))
s_axi_arvalid_int = Signal(bool(False))
s_axi_arready_int = Signal(bool(False))
@always_comb
def pause_logic():
s_axi_awvalid_int.next = s_axi_awvalid and not (pause or awpause)
s_axi_awready.next = s_axi_awready_int and not (pause or awpause)
s_axi_wvalid_int.next = s_axi_wvalid and not (pause or wpause)
s_axi_wready.next = s_axi_wready_int and not (pause or wpause)
s_axi_arvalid_int.next = s_axi_arvalid and not (pause or arpause)
s_axi_arready.next = s_axi_arready_int and not (pause or arpause)
@instance @instance
def write_logic(): def write_logic():
while True: while True:
@ -601,6 +716,9 @@ class AXIRam(object):
addr, awid, length, size, burst, lock, cache, prot = self.int_write_addr_queue.pop(0) addr, awid, length, size, burst, lock, cache, prot = self.int_write_addr_queue.pop(0)
if name is not None:
print("[%s] Write burst awid: 0x%x awaddr: 0x%08x awlen: %d awsize: %d" % (name, awid, addr, length, size))
num_bytes = 2**size num_bytes = 2**size
assert 0 < num_bytes <= bw assert 0 < num_bytes <= bw
@ -622,25 +740,28 @@ class AXIRam(object):
for n in range(length): for n in range(length):
cur_word_addr = int(cur_addr/bw)*bw cur_word_addr = int(cur_addr/bw)*bw
self.mem.seek(cur_word_addr % self.size)
if not self.int_write_data_queue: if not self.int_write_data_queue:
yield self.int_write_data_sync yield self.int_write_data_sync
wdata, strb, last = self.int_write_data_queue.pop(0) wdata, strb, last = self.int_write_data_queue.pop(0)
self.mem.seek(cur_word_addr % self.size)
data = bytearray() data = bytearray()
for i in range(bw): for i in range(bw):
data.extend(bytearray([wdata & 0xff])) data.extend(bytearray([wdata & 0xff]))
wdata >>= 8 wdata >>= 8
for i in range(bw): for i in range(bw):
if strb & (1 << i): if strb & (1 << i):
self.mem.write(data[i:i+1]) self.mem.write(bytes(data[i:i+1]))
else: else:
self.mem.seek(1, 1) self.mem.seek(1, 1)
if n == length-1: if n == length-1:
self.int_write_resp_queue.append((awid, 0b00)) self.int_write_resp_queue.append((awid, 0b00))
self.int_write_resp_sync.next = not self.int_write_resp_sync self.int_write_resp_sync.next = not self.int_write_resp_sync
if last != (n == length-1):
print("Error: bad last assert")
raise StopSimulation
assert last == (n == length-1) assert last == (n == length-1)
if name is not None: if name is not None:
print("[%s] Write word id: %d addr: 0x%08x prot: 0x%x wstrb: 0x%02x data: %s" % (name, awid, cur_addr, prot, s_axi_wstrb, " ".join(("{:02x}".format(c) for c in bytearray(data))))) print("[%s] Write word id: %d addr: 0x%08x prot: 0x%x wstrb: 0x%02x data: %s" % (name, awid, cur_addr, prot, s_axi_wstrb, " ".join(("{:02x}".format(c) for c in bytearray(data)))))
@ -655,13 +776,16 @@ class AXIRam(object):
@instance @instance
def write_addr_interface_logic(): def write_addr_interface_logic():
while True: while True:
s_axi_awready.next = True s_axi_awready_int.next = True
yield clk.posedge yield clk.posedge
if s_axi_awready & s_axi_awvalid: if s_axi_awready and s_axi_awvalid_int:
addr = int(s_axi_awaddr) addr = int(s_axi_awaddr)
awid = int(s_axi_awid) if s_axi_awid is not None:
awid = int(s_axi_awid)
else:
awid = 0
length = int(s_axi_awlen) length = int(s_axi_awlen)
size = int(s_axi_awsize) size = int(s_axi_awsize)
burst = int(s_axi_awburst) burst = int(s_axi_awburst)
@ -674,11 +798,11 @@ class AXIRam(object):
@instance @instance
def write_data_interface_logic(): def write_data_interface_logic():
while True: while True:
s_axi_wready.next = True s_axi_wready_int.next = True
yield clk.posedge yield clk.posedge
if s_axi_wready & s_axi_wvalid: if s_axi_wready and s_axi_wvalid_int:
data = int(s_axi_wdata) data = int(s_axi_wdata)
strb = int(s_axi_wstrb) strb = int(s_axi_wstrb)
last = bool(s_axi_wlast) last = bool(s_axi_wlast)
@ -691,12 +815,16 @@ class AXIRam(object):
while not self.int_write_resp_queue: while not self.int_write_resp_queue:
yield clk.posedge yield clk.posedge
s_axi_bid.next, s_axi_bresp.next = self.int_write_resp_queue.pop(0) bid, bresp = self.int_write_resp_queue.pop(0)
s_axi_bvalid.next = True if s_axi_bid is not None:
s_axi_bid.next = bid
s_axi_bresp.next = bresp
s_axi_bvalid.next = not (pause or bpause)
yield clk.posedge yield clk.posedge
while s_axi_bvalid and not s_axi_bready: while not s_axi_bvalid or not s_axi_bready:
s_axi_bvalid.next = s_axi_bvalid or not (pause or bpause)
yield clk.posedge yield clk.posedge
s_axi_bvalid.next = False s_axi_bvalid.next = False
@ -709,6 +837,9 @@ class AXIRam(object):
addr, arid, length, size, burst, lock, cache, prot = self.int_read_addr_queue.pop(0) addr, arid, length, size, burst, lock, cache, prot = self.int_read_addr_queue.pop(0)
if name is not None:
print("[%s] Read burst arid: 0x%x araddr: 0x%08x arlen: %d arsize: %d" % (name, arid, addr, length, size))
num_bytes = 2**size num_bytes = 2**size
assert 0 < num_bytes <= bw assert 0 < num_bytes <= bw
@ -752,13 +883,16 @@ class AXIRam(object):
@instance @instance
def read_addr_interface_logic(): def read_addr_interface_logic():
while True: while True:
s_axi_arready.next = True s_axi_arready_int.next = True
yield clk.posedge yield clk.posedge
if s_axi_arready & s_axi_arvalid: if s_axi_arready and s_axi_arvalid_int:
addr = int(s_axi_araddr) addr = int(s_axi_araddr)
arid = int(s_axi_arid) if s_axi_arid is not None:
arid = int(s_axi_arid)
else:
arid = 0
length = int(s_axi_arlen) length = int(s_axi_arlen)
size = int(s_axi_arsize) size = int(s_axi_arsize)
burst = int(s_axi_arburst) burst = int(s_axi_arburst)
@ -774,12 +908,18 @@ class AXIRam(object):
while not self.int_read_resp_queue: while not self.int_read_resp_queue:
yield clk.posedge yield clk.posedge
s_axi_rid.next, s_axi_rdata.next, s_axi_rresp.next, s_axi_rlast.next = self.int_read_resp_queue.pop(0) rid, rdata, rresp, rlast = self.int_read_resp_queue.pop(0)
s_axi_rvalid.next = True if s_axi_rid is not None:
s_axi_rid.next = rid
s_axi_rdata.next = rdata
s_axi_rresp.next = rresp
s_axi_rlast.next = rlast
s_axi_rvalid.next = not (pause or rpause)
yield clk.posedge yield clk.posedge
while s_axi_rvalid and not s_axi_rready: while not s_axi_rvalid or not s_axi_rready:
s_axi_rvalid.next = s_axi_rvalid or not (pause or rpause)
yield clk.posedge yield clk.posedge
s_axi_rvalid.next = False s_axi_rvalid.next = False