About
AxisLiteRegister now accepts outstandings of 2 in read transactions.
The axi lite protocol requires that the number of outstandings be less than 1.
Expected
Set the maximum number of outstandings for AxiLiteSlave transactions to 1.
Environment
- Ubuntu 18.04.4 LTS
- Python 3.8.13
- pyverilog 1.3.0
- veriloggen v2.1.0 - v2.1.1
Debug
I suspect that the "ack" signal generated by push_read_data()
in types/axi.py:AxiLiteSlave
class is not correct.
In thread/axis.py
, this "ack" is observed and FSM of AXISLiteRegister is set back to init.
The "ack" signal is not a handshake notification of rdata
, but rather a push notification of rdata, so it make fsm into init, despite handshake for read channel has not been established.
The fsm state returns to init even if the handshake has not been established, and the next address request is accepted.
As a result, the number of outstandings seems to be more than 1.
-
https://github.com/PyHDI/veriloggen/blame/c548d58fc6c72efaf0994682a07d0a4f52b737cf/veriloggen/types/axi.py#L1850-L1877
|
def push_read_data(self, data, cond=None): |
|
""" |
|
@return ack |
|
""" |
|
if self._read_disabled: |
|
raise TypeError('Read disabled.') |
|
|
|
if cond is not None: |
|
self.seq.If(cond) |
|
|
|
ack = vtypes.Ors(self.rdata.rready, vtypes.Not(self.rdata.rvalid)) |
|
|
|
self.seq.If(ack)( |
|
self.rdata.rdata(data), |
|
self.rdata.rvalid(1) |
|
) |
|
|
|
# de-assert |
|
self.seq.Delay(1)( |
|
self.rdata.rvalid(0) |
|
) |
|
|
|
# retry |
|
self.seq.If(vtypes.Ands(self.rdata.rvalid, vtypes.Not(self.rdata.rready)))( |
|
self.rdata.rvalid(self.rdata.rvalid) |
|
) |
|
|
|
return ack |
-
https://github.com/PyHDI/veriloggen/blame/c548d58fc6c72efaf0994682a07d0a4f52b737cf/veriloggen/thread/axis.py#L290-L325
|
init_state = fsm.current |
|
|
|
# read |
|
read_state = fsm.current + 1 |
|
fsm.If(readvalid).goto_from(init_state, read_state) |
|
fsm.set_index(read_state) |
|
|
|
rdata = self.m.TmpWire(self.datawidth, signed=True, prefix='axislite_rdata') |
|
pat = [(maskaddr == i, r) for i, r in enumerate(self.register)] |
|
pat.append((None, vtypes.IntX())) |
|
rval = vtypes.PatternMux(pat) |
|
rdata.assign(rval) |
|
|
|
flag = self.m.TmpWire(prefix='axislite_flag') |
|
pat = [(maskaddr == i, r) for i, r in enumerate(self.flag)] |
|
pat.append((None, vtypes.IntX())) |
|
rval = vtypes.PatternMux(pat) |
|
flag.assign(rval) |
|
|
|
resetval = self.m.TmpWire(self.datawidth, signed=True, prefix='axislite_resetval') |
|
pat = [(maskaddr == i, r) for i, r in enumerate(self.resetval)] |
|
pat.append((None, vtypes.IntX())) |
|
rval = vtypes.PatternMux(pat) |
|
resetval.assign(rval) |
|
|
|
ack = self.push_read_data(rdata, cond=fsm) |
|
|
|
# flag reset |
|
state_cond = fsm.state == fsm.current |
|
for i, r in enumerate(self.register): |
|
self.seq.If(state_cond, ack, flag, maskaddr == i)( |
|
self.register[i](resetval), |
|
self.flag[i](0) |
|
) |
|
|
|
fsm.If(ack).goto_init() |