-
Notifications
You must be signed in to change notification settings - Fork 11
/
core.py
150 lines (122 loc) · 5.04 KB
/
core.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
from functools import reduce
from operator import and_
from migen import *
from migen.genlib.cdc import MultiReg, ElasticBuffer
from migen.genlib.misc import WaitTimer
from migen.genlib.io import DifferentialInput
from misoc.interconnect.csr import *
from jesd204b.transport import (JESD204BTransportTX,
JESD204BSTPLGenerator)
from jesd204b.link import JESD204BLinkTX
class JESD204BCoreTX(Module):
def __init__(self, phys, jesd_settings, converter_data_width, tx_half=False):
self.enable = Signal()
self.jsync = Signal()
self.jref = Signal()
self.phy_done = Signal()
self.ready = Signal()
self.prbs_config = Signal(4)
self.stpl_enable = Signal()
self.sink = Record([("converter"+str(i), converter_data_width)
for i in range(jesd_settings.nconverters)])
# # #
# restart when disabled or on re-synchronization request
self.jsync_sys = Signal()
self.specials += MultiReg(self.jsync, self.jsync_sys)
self.jsync_jesd = Signal()
self.specials += MultiReg(self.jsync, self.jsync_jesd, "jesd")
# transport layer
transport = JESD204BTransportTX(jesd_settings, converter_data_width)
transport = ClockDomainsRenamer("jesd")(transport)
self.submodules.transport = transport
# stpl
stpl = JESD204BSTPLGenerator(jesd_settings, converter_data_width)
stpl = ClockDomainsRenamer("jesd")(stpl)
self.submodules += stpl
stpl_enable = Signal()
self.specials += MultiReg(self.stpl_enable, stpl_enable, "jesd")
self.comb += \
If(stpl_enable,
transport.sink.eq(stpl.source)
).Else(
transport.sink.eq(self.sink)
)
links = []
phy_done = Signal()
self.comb += phy_done.eq(reduce(and_, [phy.transmitter.init.done for phy in phys]))
for n, (phy, lane) in enumerate(zip(phys, transport.source.flatten())):
phy_name = "phy{}".format(n)
phy_cd = phy_name + "_tx"
phy_half_cd = phy_name + "_tx_half"
# claim the phy
setattr(self.submodules, phy_name, phy)
ebuf = ElasticBuffer(
len(phy.data) + len(phy.ctrl),
4, "jesd", phy_half_cd if tx_half else phy_cd
)
setattr(self.submodules, "ebuf{}".format(n), ebuf)
link = ClockDomainsRenamer("jesd")(
JESD204BLinkTX(len(phy.data),
jesd_settings, n)
)
self.submodules += link
links.append(link)
self.comb += [
link.reset.eq(~phy_done),
link.jsync.eq(self.jsync_jesd),
link.jref.eq(self.jref)
]
# connect data
self.comb += [
link.sink.data.eq(lane),
ebuf.din[:len(phy.data)].eq(link.source.data),
ebuf.din[len(phy.data):].eq(link.source.ctrl),
phy.data.eq(ebuf.dout[:len(phy.data)]),
phy.ctrl.eq(ebuf.dout[len(phy.data):])
]
# connect control
self.comb += phy.transmitter.init.restart.eq(~self.enable)
self.specials += MultiReg(self.prbs_config,
phy.transmitter.prbs_config,
phy_half_cd if tx_half else phy_cd)
ready = Signal()
self.comb += ready.eq(reduce(and_, [link.ready for link in links]))
self.specials += [
MultiReg(phy_done, self.phy_done),
MultiReg(ready, self.ready)
]
# JSYNC is asynchronous and the I/O can be passed directly to the core.
def register_jsync(self, jsync):
self.jsync_registered = True
if isinstance(jsync, Signal):
self.comb += self.jsync.eq(jsync)
elif isinstance(jsync, Record):
self.specials += DifferentialInput(jsync.p, jsync.n, self.jsync)
else:
raise ValueError
# JREF needs to be sampled externally to the core, and needs to be
# synchronous to the jesd clock domain.
def register_jref(self, jref):
self.jref_registered = True
self.comb += self.jref.eq(jref)
def do_finalize(self):
assert hasattr(self, "jsync_registered")
assert hasattr(self, "jref_registered")
class JESD204BCoreTXControl(Module, AutoCSR):
def __init__(self, core):
self.enable = CSRStorage()
self.phy_done = CSRStatus()
self.ready = CSRStatus()
self.prbs_config = CSRStorage(4)
self.stpl_enable = CSRStorage()
self.jsync = CSRStatus()
# # #
# core control/status
self.comb += [
core.enable.eq(self.enable.storage),
core.prbs_config.eq(self.prbs_config.storage),
core.stpl_enable.eq(self.stpl_enable.storage),
self.jsync.status.eq(core.jsync_sys),
self.phy_done.status.eq(core.phy_done),
self.ready.status.eq(core.ready)
]