Support pausing channels in AXI models

This commit is contained in:
Alex Forencich 2018-08-11 21:47:08 -07:00
parent 048c0bb5e5
commit 4ee04f6682
2 changed files with 129 additions and 41 deletions

110
tb/axi.py
View File

@ -179,6 +179,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
): ):
@ -215,6 +221,30 @@ class AXIMaster(object):
self.has_logic = True self.has_logic = True
self.clk = clk self.clk = clk
m_axi_awvalid_int = Signal(bool(False))
m_axi_awready_int = Signal(bool(False))
m_axi_wvalid_int = Signal(bool(False))
m_axi_wready_int = Signal(bool(False))
m_axi_bvalid_int = Signal(bool(False))
m_axi_bready_int = Signal(bool(False))
m_axi_arvalid_int = Signal(bool(False))
m_axi_arready_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_awvalid.next = m_axi_awvalid_int and not (pause or awpause)
m_axi_awready_int.next = m_axi_awready and not (pause or awpause)
m_axi_wvalid.next = m_axi_wvalid_int and not (pause or wpause)
m_axi_wready_int.next = m_axi_wready and not (pause or wpause)
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_arvalid.next = m_axi_arvalid_int and not (pause or arpause)
m_axi_arready_int.next = m_axi_arready and not (pause or arpause)
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:
@ -329,14 +359,14 @@ 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_int.next = True
yield clk.posedge yield clk.posedge
while m_axi_awvalid and not m_axi_awready: while m_axi_awvalid_int and not m_axi_awready_int:
yield clk.posedge yield clk.posedge
m_axi_awvalid.next = False m_axi_awvalid_int.next = False
@instance @instance
def write_data_interface_logic(): def write_data_interface_logic():
@ -345,23 +375,23 @@ 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_int.next = True
yield clk.posedge yield clk.posedge
while m_axi_wvalid and not m_axi_wready: while m_axi_wvalid_int and not m_axi_wready_int:
yield clk.posedge yield clk.posedge
m_axi_wvalid.next = False m_axi_wvalid_int.next = False
@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:
if m_axi_bid is not None: if m_axi_bid is not None:
bid = int(m_axi_bid) bid = int(m_axi_bid)
else: else:
@ -491,23 +521,23 @@ 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_int.next = True
yield clk.posedge yield clk.posedge
while m_axi_arvalid and not m_axi_arready: while m_axi_arvalid_int and not m_axi_arready_int:
yield clk.posedge yield clk.posedge
m_axi_arvalid.next = False m_axi_arvalid_int.next = False
@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:
if m_axi_rid is not None: if m_axi_rid is not None:
rid = int(m_axi_rid) rid = int(m_axi_rid)
else: else:
@ -587,6 +617,12 @@ 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
): ):
@ -617,6 +653,30 @@ class AXIRam(object):
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_bvalid_int = Signal(bool(False))
s_axi_bready_int = Signal(bool(False))
s_axi_arvalid_int = Signal(bool(False))
s_axi_arready_int = Signal(bool(False))
s_axi_rvalid_int = Signal(bool(False))
s_axi_rready_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_bvalid.next = s_axi_bvalid_int and not (pause or bpause)
s_axi_bready_int.next = s_axi_bready and not (pause or bpause)
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)
s_axi_rvalid.next = s_axi_rvalid_int and not (pause or rpause)
s_axi_rready_int.next = s_axi_rready and not (pause or rpause)
@instance @instance
def write_logic(): def write_logic():
while True: while True:
@ -682,11 +742,11 @@ 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)
if s_axi_awid is not None: if s_axi_awid is not None:
awid = int(s_axi_awid) awid = int(s_axi_awid)
@ -704,11 +764,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)
@ -725,14 +785,14 @@ class AXIRam(object):
if s_axi_bid is not None: if s_axi_bid is not None:
s_axi_bid.next = bid s_axi_bid.next = bid
s_axi_bresp.next = bresp s_axi_bresp.next = bresp
s_axi_bvalid.next = True s_axi_bvalid_int.next = True
yield clk.posedge yield clk.posedge
while s_axi_bvalid and not s_axi_bready: while s_axi_bvalid_int and not s_axi_bready_int:
yield clk.posedge yield clk.posedge
s_axi_bvalid.next = False s_axi_bvalid_int.next = False
@instance @instance
def read_logic(): def read_logic():
@ -785,11 +845,11 @@ 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)
if s_axi_arid is not None: if s_axi_arid is not None:
arid = int(s_axi_arid) arid = int(s_axi_arid)
@ -816,14 +876,14 @@ class AXIRam(object):
s_axi_rdata.next = rdata s_axi_rdata.next = rdata
s_axi_rresp.next = rresp s_axi_rresp.next = rresp
s_axi_rlast.next = rlast s_axi_rlast.next = rlast
s_axi_rvalid.next = True s_axi_rvalid_int.next = True
yield clk.posedge yield clk.posedge
while s_axi_rvalid and not s_axi_rready: while s_axi_rvalid_int and not s_axi_rready_int:
yield clk.posedge yield clk.posedge
s_axi_rvalid.next = False s_axi_rvalid_int.next = False
return instances() return instances()

View File

@ -79,6 +79,7 @@ def bench():
# AXI4 master # AXI4 master
axi_master_inst = axi.AXIMaster() axi_master_inst = axi.AXIMaster()
axi_master_pause = Signal(bool(False))
axi_master_logic = axi_master_inst.create_logic( axi_master_logic = axi_master_inst.create_logic(
clk, clk,
@ -122,11 +123,13 @@ def bench():
m_axi_rlast=port0_axi_rlast, m_axi_rlast=port0_axi_rlast,
m_axi_rvalid=port0_axi_rvalid, m_axi_rvalid=port0_axi_rvalid,
m_axi_rready=port0_axi_rready, m_axi_rready=port0_axi_rready,
pause=axi_master_pause,
name='master' name='master'
) )
# AXI4 RAM model # AXI4 RAM model
axi_ram_inst = axi.AXIRam(2**16) axi_ram_inst = axi.AXIRam(2**16)
axi_ram_pause = Signal(bool(False))
axi_ram_port0 = axi_ram_inst.create_port( axi_ram_port0 = axi_ram_inst.create_port(
clk, clk,
@ -165,6 +168,7 @@ def bench():
s_axi_rlast=port0_axi_rlast, s_axi_rlast=port0_axi_rlast,
s_axi_rvalid=port0_axi_rvalid, s_axi_rvalid=port0_axi_rvalid,
s_axi_rready=port0_axi_rready, s_axi_rready=port0_axi_rready,
pause=axi_ram_pause,
name='port0' name='port0'
) )
@ -172,6 +176,28 @@ def bench():
def clkgen(): def clkgen():
clk.next = not clk clk.next = not clk
def wait_normal():
while not axi_master_inst.idle():
yield clk.posedge
def wait_pause_master():
while not axi_master_inst.idle():
axi_master_pause.next = True
yield clk.posedge
yield clk.posedge
yield clk.posedge
axi_master_pause.next = False
yield clk.posedge
def wait_pause_slave():
while not axi_master_inst.idle():
axi_ram_pause.next = True
yield clk.posedge
yield clk.posedge
yield clk.posedge
axi_ram_pause.next = False
yield clk.posedge
@instance @instance
def check(): def check():
yield delay(100) yield delay(100)
@ -244,19 +270,20 @@ def bench():
for length in range(1,8): for length in range(1,8):
for offset in range(4,8): for offset in range(4,8):
for size in (2, 1, 0): for size in (2, 1, 0):
axi_ram_inst.write_mem(256*(16*offset+length), b'\xAA'*32) for wait in wait_normal, wait_pause_master, wait_pause_slave:
axi_master_inst.init_write(256*(16*offset+length)+offset, b'\x11\x22\x33\x44\x55\x66\x77\x88'[0:length], size=size) axi_ram_inst.write_mem(256*(16*offset+length), b'\xAA'*32)
axi_master_inst.init_write(256*(16*offset+length)+offset, b'\x11\x22\x33\x44\x55\x66\x77\x88'[0:length], size=size)
yield axi_master_inst.wait() yield wait()
yield clk.posedge yield clk.posedge
data = axi_ram_inst.read_mem(256*(16*offset+length), 32) data = axi_ram_inst.read_mem(256*(16*offset+length), 32)
for i in range(0, len(data), 16): for i in range(0, len(data), 16):
print(" ".join(("{:02x}".format(c) for c in bytearray(data[i:i+16])))) print(" ".join(("{:02x}".format(c) for c in bytearray(data[i:i+16]))))
assert axi_ram_inst.read_mem(256*(16*offset+length)+offset, length) == b'\x11\x22\x33\x44\x55\x66\x77\x88'[0:length] assert axi_ram_inst.read_mem(256*(16*offset+length)+offset, length) == b'\x11\x22\x33\x44\x55\x66\x77\x88'[0:length]
assert axi_ram_inst.read_mem(256*(16*offset+length)+offset-1, 1) == b'\xAA' assert axi_ram_inst.read_mem(256*(16*offset+length)+offset-1, 1) == b'\xAA'
assert axi_ram_inst.read_mem(256*(16*offset+length)+offset+length, 1) == b'\xAA' assert axi_ram_inst.read_mem(256*(16*offset+length)+offset+length, 1) == b'\xAA'
yield delay(100) yield delay(100)
@ -267,14 +294,15 @@ def bench():
for length in range(1,8): for length in range(1,8):
for offset in range(4,8): for offset in range(4,8):
for size in (2, 1, 0): for size in (2, 1, 0):
axi_master_inst.init_read(256*(16*offset+length)+offset, length, size=size) for wait in wait_normal, wait_pause_master, wait_pause_slave:
axi_master_inst.init_read(256*(16*offset+length)+offset, length, size=size)
yield axi_master_inst.wait() yield wait()
yield clk.posedge yield clk.posedge
data = axi_master_inst.get_read_data() data = axi_master_inst.get_read_data()
assert data[0] == 256*(16*offset+length)+offset assert data[0] == 256*(16*offset+length)+offset
assert data[1] == b'\x11\x22\x33\x44\x55\x66\x77\x88'[0:length] assert data[1] == b'\x11\x22\x33\x44\x55\x66\x77\x88'[0:length]
yield delay(100) yield delay(100)