Skip to content

Commit 25555e9

Browse files
committed
types.AxiMaster and AxiLiteMaster use SkidBuffer for write_data and read_data.
1 parent 5367cb2 commit 25555e9

File tree

2 files changed

+234
-2
lines changed

2 files changed

+234
-2
lines changed

veriloggen/types/axi.py

Lines changed: 123 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515

1616
from veriloggen.seq.seq import make_condition
1717
from . import util
18+
from .skidbuffer import SkidBuffer
1819

1920

2021
BURST_FIXED = 0b00
@@ -480,6 +481,7 @@ def connect(self, ports, name):
480481

481482

482483
class AxiMasterWriteData(AxiWriteData):
484+
_O = util.t_Output
483485

484486
def __init__(self, m, name, clk, rst, datawidth=32, addrwidth=32,
485487
id_width=0, user_width=0,
@@ -497,6 +499,39 @@ def __init__(self, m, name, clk, rst, datawidth=32, addrwidth=32,
497499
if self.wuser is not None:
498500
self.wuser.assign(user_mode)
499501

502+
# user-side signals before skidbuffer
503+
wdata = m.TmpRegLike(self.wdata, prefix='_'.join(['', name, 'wdata', 'sb']))
504+
wstrb = m.TmpRegLike(self.wstrb, prefix='_'.join(['', name, 'wstrb', 'sb']))
505+
wlast = m.TmpRegLike(self.wlast, prefix='_'.join(['', name, 'wlast', 'sb']))
506+
wvalid = m.TmpRegLike(self.wvalid, prefix='_'.join(['', name, 'wvalid', 'sb']))
507+
wready = m.TmpWireLike(self.wready, prefix='_'.join(['', name, 'wready', 'sb']))
508+
509+
# skidbuffer
510+
sb = SkidBuffer(m, clk, rst,
511+
wvalid, self.wready, *[wdata, wstrb, wlast],
512+
prefix='_'.join(['', 'sb', name, 'writedata']))
513+
wready.assign(sb.ready)
514+
515+
# AXI-side signals after skidbuffer
516+
self.wdata.assign(sb[0])
517+
self.wstrb.assign(sb[1])
518+
self.wlast.assign(sb[2])
519+
self.wvalid.assign(sb.valid)
520+
521+
# save AXI-side references
522+
self.orig_wdata = self.wdata
523+
self.orig_wstrb = self.wstrb
524+
self.orig_wlast = self.wlast
525+
self.orig_wvalid = self.wvalid
526+
self.orig_wready = self.wready
527+
528+
# update references for user-side
529+
self.wdata = wdata
530+
self.wstrb = wstrb
531+
self.wlast = wlast
532+
self.wvalid = wvalid
533+
self.wready = wready
534+
500535
def disable_write(self):
501536
ports = [self.wdata(0),
502537
self.wstrb(0),
@@ -708,6 +743,35 @@ def __init__(self, m, name, clk, rst, datawidth=32, addrwidth=32,
708743
self.clk = clk
709744
self.rst = rst
710745

746+
# user-side signals before skidbuffer
747+
rdata = m.TmpWireLike(self.rdata, prefix='_'.join(['', name, 'rdata', 'sb']))
748+
rlast = m.TmpWireLike(self.rlast, prefix='_'.join(['', name, 'rlast', 'sb']))
749+
rvalid = m.TmpWireLike(self.rvalid, prefix='_'.join(['', name, 'rvalid', 'sb']))
750+
rready = m.TmpWireLike(self.rready, prefix='_'.join(['', name, 'rready', 'sb']))
751+
752+
# skidbuffer
753+
sb = SkidBuffer(m, clk, rst,
754+
self.rvalid, rready, *[self.rdata, self.rlast],
755+
prefix='_'.join(['', 'sb', name, 'readdata']))
756+
rdata.assign(sb[0])
757+
rlast.assign(sb[1])
758+
rvalid.assign(sb.valid)
759+
760+
# AXI-side signals after skidbuffer
761+
self.rready.assign(sb.ready)
762+
763+
# save AXI-side references
764+
self.orig_rdata = self.rdata
765+
self.orig_rlast = self.rlast
766+
self.orig_rvalid = self.rvalid
767+
self.orig_rready = self.rready
768+
769+
# update references for user-side
770+
self.rdata = rdata
771+
self.rlast = rlast
772+
self.rvalid = rvalid
773+
self.rready = rready
774+
711775
def disable_read(self):
712776
self.rready.assign(0)
713777

@@ -820,6 +884,7 @@ def connect(self, ports, name):
820884

821885

822886
class AxiLiteMasterWriteData(AxiLiteWriteData):
887+
_O = util.t_Output
823888

824889
def __init__(self, m, name, clk, rst, datawidth=32, addrwidth=32,
825890
itype=None, otype=None):
@@ -831,6 +896,35 @@ def __init__(self, m, name, clk, rst, datawidth=32, addrwidth=32,
831896
self.rst = rst
832897
self.seq = Seq(m, name + '_wdata', clk, rst)
833898

899+
# user-side signals before skidbuffer
900+
wdata = m.TmpRegLike(self.wdata, prefix='_'.join(['', name, 'wdata', 'sb']))
901+
wstrb = m.TmpRegLike(self.wstrb, prefix='_'.join(['', name, 'wstrb', 'sb']))
902+
wvalid = m.TmpRegLike(self.wvalid, prefix='_'.join(['', name, 'wvalid', 'sb']))
903+
wready = m.TmpWireLike(self.wready, prefix='_'.join(['', name, 'wready', 'sb']))
904+
905+
# skidbuffer
906+
sb = SkidBuffer(m, clk, rst,
907+
wvalid, self.wready, *[wdata, wstrb],
908+
prefix='_'.join(['', 'sb', name, 'writedata']))
909+
wready.assign(sb.ready)
910+
911+
# AXI-side signals after skidbuffer
912+
self.wdata.assign(sb[0])
913+
self.wstrb.assign(sb[1])
914+
self.wvalid.assign(sb.valid)
915+
916+
# save AXI-side references
917+
self.orig_wdata = self.wdata
918+
self.orig_wstrb = self.wstrb
919+
self.orig_wvalid = self.wvalid
920+
self.orig_wready = self.wready
921+
922+
# update references for user-side
923+
self.wdata = wdata
924+
self.wstrb = wstrb
925+
self.wvalid = wvalid
926+
self.wready = wready
927+
834928
def disable_write(self):
835929
ports = [self.wdata(0),
836930
self.wstrb(0),
@@ -980,6 +1074,31 @@ def __init__(self, m, name, clk, rst, datawidth=32, addrwidth=32,
9801074
self.clk = clk
9811075
self.rst = rst
9821076

1077+
# user-side signals before skidbuffer
1078+
rdata = m.TmpWireLike(self.rdata, prefix='_'.join(['', name, 'rdata', 'sb']))
1079+
rvalid = m.TmpWireLike(self.rvalid, prefix='_'.join(['', name, 'rvalid', 'sb']))
1080+
rready = m.TmpWireLike(self.rready, prefix='_'.join(['', name, 'rready', 'sb']))
1081+
1082+
# skidbuffer
1083+
sb = SkidBuffer(m, clk, rst,
1084+
self.rvalid, rready, *[self.rdata],
1085+
prefix='_'.join(['', 'sb', name, 'readdata']))
1086+
rdata.assign(sb[0])
1087+
rvalid.assign(sb.valid)
1088+
1089+
# AXI-side signals after skidbuffer
1090+
self.rready.assign(sb.ready)
1091+
1092+
# save AXI-side references
1093+
self.orig_rdata = self.rdata
1094+
self.orig_rvalid = self.rvalid
1095+
self.orig_rready = self.rready
1096+
1097+
# update references for user-side
1098+
self.rdata = rdata
1099+
self.rvalid = rvalid
1100+
self.rready = rready
1101+
9831102
def disable_read(self):
9841103
self.rready.assign(0)
9851104

@@ -1152,6 +1271,7 @@ def __init__(self, m, name, clk, rst, datawidth=32, addrwidth=32,
11521271

11531272
itype = util.t_Wire if noio else None
11541273
otype = util.t_Reg if noio else None
1274+
wdata_otype = util.t_Wire if noio else None
11551275
rdata_otype = util.t_Wire if noio else None
11561276

11571277
self.waddr = AxiMasterWriteAddress(m, name, clk, rst, datawidth, addrwidth,
@@ -1162,7 +1282,7 @@ def __init__(self, m, name, clk, rst, datawidth=32, addrwidth=32,
11621282
self.wdata = AxiMasterWriteData(m, name, clk, rst, datawidth, addrwidth,
11631283
wdata_id_width, wdata_user_width,
11641284
wdata_user_mode,
1165-
itype, otype)
1285+
itype, wdata_otype)
11661286
self.wresp = AxiMasterWriteResponse(m, name, clk, rst, datawidth, addrwidth,
11671287
wresp_id_width, wresp_user_width, itype, otype)
11681288
self.raddr = AxiMasterReadAddress(m, name, clk, rst, datawidth, addrwidth,
@@ -1332,13 +1452,14 @@ def __init__(self, m, name, clk, rst, datawidth=32, addrwidth=32,
13321452

13331453
itype = util.t_Wire if noio else None
13341454
otype = util.t_Reg if noio else None
1455+
wdata_otype = util.t_Wire if noio else None
13351456
rdata_otype = util.t_Wire if noio else None
13361457

13371458
self.waddr = AxiLiteMasterWriteAddress(m, name, clk, rst, datawidth, addrwidth,
13381459
waddr_cache_mode, waddr_prot_mode,
13391460
itype, otype)
13401461
self.wdata = AxiLiteMasterWriteData(m, name, clk, rst, datawidth, addrwidth,
1341-
itype, otype)
1462+
itype, wdata_otype)
13421463
self.wresp = AxiLiteMasterWriteResponse(m, name, clk, rst, datawidth, addrwidth,
13431464
itype, otype)
13441465
self.raddr = AxiLiteMasterReadAddress(m, name, clk, rst, datawidth, addrwidth,

veriloggen/types/skidbuffer.py

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
from __future__ import absolute_import
2+
from __future__ import print_function
3+
4+
import veriloggen.core.vtypes as vtypes
5+
from veriloggen.seq.seq import TmpSeq
6+
7+
8+
class SkidBuffer(vtypes.VeriloggenNode):
9+
10+
def __init__(self, m, clk, rst,
11+
s_valid, m_ready, *s_values, prefix=None):
12+
13+
if prefix is None:
14+
prefix = 'skidbuffer'
15+
16+
if not s_values:
17+
raise ValueError("'s_values' must not be empty.")
18+
19+
self.m = m
20+
self.clk = clk
21+
self.rst = rst
22+
self.s_values = s_values
23+
self.s_valid = s_valid
24+
self.m_ready = m_ready
25+
26+
width = 0
27+
for s_value in s_values:
28+
w = s_value.get_width()
29+
if w is None:
30+
w = 1
31+
width += w
32+
33+
s_data = m.TmpWire(width, prefix=prefix + '_data')
34+
s_data.assign(vtypes.Cat(*s_values))
35+
36+
(m_data, m_valid, s_ready) = make_skidbuffer(m, clk, rst,
37+
s_data, s_valid, m_ready,
38+
prefix=prefix)
39+
40+
self.m_values = []
41+
msb = width - 1
42+
for s_value in s_values:
43+
v = m.TmpWireLike(s_value, prefix=prefix + '_value')
44+
w = v.get_width()
45+
if w is None:
46+
w = 1
47+
lsb = msb - w + 1
48+
v.assign(vtypes.Slice(m_data, msb, lsb))
49+
self.m_values.append(v)
50+
msb -= w
51+
52+
self.m_valid = m_valid
53+
self.s_ready = s_ready
54+
55+
@property
56+
def values(self):
57+
return self.m_values
58+
59+
@property
60+
def valid(self):
61+
return self.m_valid
62+
63+
@property
64+
def ready(self):
65+
return self.s_ready
66+
67+
def __getitem__(self, index):
68+
return self.m_values[index]
69+
70+
71+
def make_skidbuffer(m, clk, rst,
72+
s_data, s_valid, m_ready,
73+
prefix=None):
74+
75+
if prefix is None:
76+
if hasattr(s_data, 'name'):
77+
prefix = '_'.join([s_data.name, 'skidbuffer'])
78+
else:
79+
prefix = 'skidbuffer'
80+
81+
m_data = m.TmpRegLike(s_data, prefix=prefix + '_data')
82+
m_valid = m.TmpReg(prefix=prefix + '_valid', initval=0)
83+
84+
s_ready = m.TmpWire(prefix=prefix + '_ready')
85+
86+
tmp_data = m.TmpRegLike(s_data, prefix=prefix + '_tmp_data')
87+
tmp_valid = m.TmpReg(prefix=prefix + '_tmp_valid', initval=0)
88+
89+
next_data = m.TmpWireLike(s_data, prefix=prefix + '_next_data')
90+
next_valid = m.TmpWire(prefix=prefix + '_next_valid')
91+
92+
s_ready.assign(vtypes.Not(tmp_valid))
93+
94+
next_data.assign(vtypes.Mux(tmp_valid, tmp_data, s_data))
95+
next_valid.assign(vtypes.Ors(tmp_valid, s_valid))
96+
97+
seq = TmpSeq(m, clk, rst, prefix=prefix + '_seq')
98+
99+
seq.If(vtypes.Ors(m_ready, vtypes.Not(m_valid)))(
100+
m_data(next_data),
101+
m_valid(next_valid),
102+
)
103+
seq.If(vtypes.Not(tmp_valid), m_valid, vtypes.Not(m_ready))(
104+
tmp_data(s_data),
105+
tmp_valid(s_valid),
106+
)
107+
seq.If(tmp_valid, m_ready)(
108+
tmp_valid(0)
109+
)
110+
111+
return m_data, m_valid, s_ready

0 commit comments

Comments
 (0)