Skip to content

Commit ef5f9ee

Browse files
committed
mac/core: Add docstrings/comments to ease understanding module and internal connections.
1 parent ec68688 commit ef5f9ee

File tree

1 file changed

+99
-2
lines changed

1 file changed

+99
-2
lines changed

liteeth/mac/core.py

Lines changed: 99 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,23 @@
2121
# MAC Core -----------------------------------------------------------------------------------------
2222

2323
class LiteEthMACCore(LiteXModule):
24+
"""
25+
Core module for LiteEth MAC handling TX and RX data paths.
26+
27+
This module integrates TX and RX datapaths, managing clock domains, data width conversions,
28+
and optional features like preamble/CRC insertion/checking and padding.
29+
30+
Parameters:
31+
- phy : PHY instance connected to the MAC.
32+
- dw : Data width of the core (in bits).
33+
- with_sys_datapath: Use system clock for datapath (default: False).
34+
- with_preamble_crc: Enable preamble and CRC handling (default: True).
35+
- with_padding : Enable padding insertion/checking (default: True).
36+
- tx_cdc_depth : Depth of TX CDC FIFO (default: 32).
37+
- tx_cdc_buffered : Use buffered TX CDC (default: False).
38+
- rx_cdc_depth : Depth of RX CDC FIFO (default: 32).
39+
- rx_cdc_buffered : Use buffered RX CDC (default: False).
40+
"""
2441
def __init__(self, phy, dw,
2542
with_sys_datapath = False,
2643
with_preamble_crc = True,
@@ -32,13 +49,18 @@ def __init__(self, phy, dw,
3249
):
3350

3451
# Endpoints.
52+
# ----------
53+
# TX/RX stream endpoints for data transfer.
3554
self.sink = stream.Endpoint(eth_phy_description(dw))
3655
self.source = stream.Endpoint(eth_phy_description(dw))
3756

3857
# Parameters.
58+
# -----------
59+
# Local variables for core and PHY data widths.
3960
core_dw = dw
4061
phy_dw = phy.dw
4162

63+
# Clock domain selections based on datapath configuration.
4264
if with_sys_datapath:
4365
cd_tx = "sys"
4466
cd_rx = "sys"
@@ -48,23 +70,37 @@ def __init__(self, phy, dw,
4870
cd_rx = "eth_rx"
4971
datapath_dw = phy_dw
5072

51-
# If the PHY specifies preamble, CRC, or padding behavior, use it.
73+
# Override preamble/CRC and padding if specified by PHY.
5274
if hasattr(phy, "with_preamble_crc"):
5375
with_preamble_crc = phy.with_preamble_crc
5476
if hasattr(phy, "with_padding"):
5577
with_padding = phy.with_padding
5678

5779
# CSRs.
80+
# -----
81+
# Control/Status Registers for optional features.
5882
if with_preamble_crc:
5983
self.preamble_crc = CSRStatus(reset=1)
6084

6185
# TX Data-Path (Core --> PHY).
6286
# ------------------------------------------------------------------------------------------
6387
class TXDatapath(LiteXModule):
88+
"""
89+
TX datapath module for handling data from core to PHY.
90+
91+
Builds a pipeline of stages for CDC, conversion, padding, CRC, preamble, and gap insertion.
92+
"""
6493
def __init__(self):
94+
# Pipeline list to hold processing stages.
6595
self.pipeline = []
6696

6797
def add_cdc(self, dw):
98+
"""
99+
Add Clock Domain Crossing (CDC) stage to the pipeline.
100+
101+
Parameters:
102+
- dw: Data width for the CDC description.
103+
"""
68104
tx_cdc = stream.ClockDomainCrossing(eth_phy_description(dw),
69105
cd_from = "sys",
70106
cd_to = "eth_tx",
@@ -75,6 +111,12 @@ def add_cdc(self, dw):
75111
self.pipeline.append(tx_cdc)
76112

77113
def add_converter(self, cd):
114+
"""
115+
Add stride converter for data width adjustment.
116+
117+
Parameters:
118+
- cd: Clock domain for the converter.
119+
"""
78120
tx_converter = stream.StrideConverter(
79121
description_from = eth_phy_description(core_dw),
80122
description_to = eth_phy_description(phy_dw))
@@ -83,37 +125,47 @@ def add_converter(self, cd):
83125
self.pipeline.append(tx_converter)
84126

85127
def add_last_be(self):
128+
"""Add last byte enable handler for TX path."""
86129
tx_last_be = last_be.LiteEthMACTXLastBE(phy_dw)
87130
tx_last_be = ClockDomainsRenamer("eth_tx")(tx_last_be)
88131
self.submodules += tx_last_be
89132
self.pipeline.append(tx_last_be)
90133

91134
def add_padding(self):
135+
"""Add padding inserter to ensure minimum frame length."""
92136
tx_padding = padding.LiteEthMACPaddingInserter(datapath_dw, (eth_min_frame_length - eth_fcs_length))
93137
tx_padding = ClockDomainsRenamer(cd_tx)(tx_padding)
94138
self.submodules += tx_padding
95139
self.pipeline.append(tx_padding)
96140

97141
def add_crc(self):
142+
"""Add CRC32 inserter for frame check sequence."""
98143
tx_crc = crc.LiteEthMACCRC32Inserter(eth_phy_description(datapath_dw))
99144
tx_crc = BufferizeEndpoints({"sink": DIR_SINK})(tx_crc) # FIXME: Still required?
100145
tx_crc = ClockDomainsRenamer(cd_tx)(tx_crc)
101146
self.submodules += tx_crc
102147
self.pipeline.append(tx_crc)
103148

104149
def add_preamble(self):
150+
"""Add preamble inserter for frame synchronization."""
105151
tx_preamble = preamble.LiteEthMACPreambleInserter(datapath_dw)
106152
tx_preamble = ClockDomainsRenamer(cd_tx)(tx_preamble)
107153
self.submodules += tx_preamble
108154
self.pipeline.append(tx_preamble)
109155

110156
def add_gap(self):
157+
"""Add inter-frame gap inserter."""
111158
tx_gap = gap.LiteEthMACGap(phy_dw)
112159
tx_gap = ClockDomainsRenamer("eth_tx")(tx_gap)
113160
self.submodules += tx_gap
114161
self.pipeline.append(tx_gap)
115162

116163
def add_domain_switch(self):
164+
"""
165+
Add stages for clock domain switch and width handling.
166+
167+
Determines order of converter and CDC based on data widths.
168+
"""
117169
dw = core_dw
118170
if core_dw < phy_dw:
119171
dw = phy_dw
@@ -124,69 +176,96 @@ def add_domain_switch(self):
124176
self.add_last_be()
125177

126178
def do_finalize(self):
179+
"""Finalize the TX pipeline by connecting all stages."""
127180
self.submodules += stream.Pipeline(*self.pipeline)
128181

129182
self.tx_datapath = tx_datapath = TXDatapath()
183+
# Connect sink to the start of the pipeline.
130184
tx_datapath.pipeline.append(self.sink)
185+
# Add domain switch if not using system datapath.
131186
if not with_sys_datapath:
132187
tx_datapath.add_domain_switch()
188+
# Add padding if enabled.
133189
if with_padding:
134190
tx_datapath.add_padding()
191+
# Add CRC and preamble if enabled.
135192
if with_preamble_crc:
136193
tx_datapath.add_crc()
137194
tx_datapath.add_preamble()
195+
# Add domain switch if using system datapath.
138196
if with_sys_datapath:
139197
tx_datapath.add_domain_switch()
198+
# Add gap unless PHY has integrated inserter.
140199
# Gap insertion has to occurr in phy tx domain to ensure gap is correctly maintained.
141200
if not getattr(phy, "integrated_ifg_inserter", False):
142201
tx_datapath.add_gap()
202+
# Connect PHY to the end of the pipeline.
143203
tx_datapath.pipeline.append(phy)
144204

145205
# RX Data-Path (PHY --> Core).
146206
# ------------------------------------------------------------------------------------------
147207
class RXDatapath(LiteXModule):
208+
"""
209+
RX datapath module for handling data from PHY to core.
210+
211+
Builds a pipeline of stages for preamble/CRC checking, padding, conversion, and CDC.
212+
"""
148213
def __init__(self):
214+
# Pipeline list to hold processing stages.
149215
self.pipeline = []
216+
# CSRs for error counters if preamble/CRC enabled.
150217
if with_preamble_crc:
151218
self.preamble_errors = CSRStatus(32)
152219
self.crc_errors = CSRStatus(32)
153220

154221
def add_preamble(self):
222+
"""Add preamble checker and error synchronizer."""
155223
rx_preamble = preamble.LiteEthMACPreambleChecker(datapath_dw)
156224
rx_preamble = ClockDomainsRenamer(cd_rx)(rx_preamble)
157225
self.submodules += rx_preamble
158226
self.pipeline.append(rx_preamble)
159227

228+
# Synchronize preamble error to sys domain.
160229
ps = PulseSynchronizer(cd_rx, "sys")
161230
self.submodules += ps
162231
self.comb += ps.i.eq(rx_preamble.error)
163232
self.sync += If(ps.o, self.preamble_errors.status.eq(self.preamble_errors.status + 1))
164233

165234
def add_crc(self):
235+
"""Add CRC32 checker and error synchronizer."""
166236
rx_crc = crc.LiteEthMACCRC32Checker(eth_phy_description(datapath_dw))
167237
rx_crc = BufferizeEndpoints({"sink": DIR_SINK})(rx_crc) # FIXME: Still required?
168238
rx_crc = ClockDomainsRenamer(cd_rx)(rx_crc)
169239
self.submodules += rx_crc
170240
self.pipeline.append(rx_crc)
171241

242+
# Synchronize CRC error to sys domain.
172243
ps = PulseSynchronizer(cd_rx, "sys")
173244
self.submodules += ps
174245
self.comb += ps.i.eq(rx_crc.error),
175246
self.sync += If(ps.o, self.crc_errors.status.eq(self.crc_errors.status + 1))
176247

177248
def add_padding(self):
249+
"""Add padding checker for minimum frame length."""
178250
rx_padding = padding.LiteEthMACPaddingChecker(datapath_dw, (eth_min_frame_length - eth_fcs_length))
179251
rx_padding = ClockDomainsRenamer(cd_rx)(rx_padding)
180252
self.submodules += rx_padding
181253
self.pipeline.append(rx_padding)
182254

183255
def add_last_be(self):
256+
"""Add last byte enable handler for RX path."""
184257
rx_last_be = last_be.LiteEthMACRXLastBE(phy_dw)
185258
rx_last_be = ClockDomainsRenamer("eth_rx")(rx_last_be)
186259
self.submodules += rx_last_be
187260
self.pipeline.append(rx_last_be)
188261

189262
def add_converter(self, cd):
263+
"""
264+
Add stride converter for data width adjustment.
265+
266+
Parameters:
267+
- cd: Clock domain for the converter.
268+
"""
190269
rx_converter = stream.StrideConverter(
191270
description_from = eth_phy_description(phy_dw),
192271
description_to = eth_phy_description(core_dw))
@@ -195,6 +274,12 @@ def add_converter(self, cd):
195274
self.pipeline.append(rx_converter)
196275

197276
def add_cdc(self, dw):
277+
"""
278+
Add Clock Domain Crossing (CDC) stage to the pipeline.
279+
280+
Parameters:
281+
- dw: Data width for the CDC description.
282+
"""
198283
rx_cdc = stream.ClockDomainCrossing(eth_phy_description(dw),
199284
cd_from = "eth_rx",
200285
cd_to = "sys",
@@ -205,6 +290,11 @@ def add_cdc(self, dw):
205290
self.pipeline.append(rx_cdc)
206291

207292
def add_domain_switch(self):
293+
"""
294+
Add stages for clock domain switch and width handling.
295+
296+
Determines order of last BE, converter, and CDC based on data widths.
297+
"""
208298
dw = phy_dw
209299
if phy_dw < core_dw:
210300
dw = core_dw
@@ -218,17 +308,24 @@ def add_domain_switch(self):
218308
self.pipeline.append(last_handler)
219309

220310
def do_finalize(self):
311+
"""Finalize the RX pipeline by connecting all stages."""
221312
self.submodules += stream.Pipeline(*self.pipeline)
222313

223314
self.rx_datapath = rx_datapath = RXDatapath()
315+
# Connect PHY to the start of the pipeline.
224316
rx_datapath.pipeline.append(phy)
317+
# Add domain switch if using system datapath.
225318
if with_sys_datapath:
226319
rx_datapath.add_domain_switch()
320+
# Add preamble and CRC if enabled.
227321
if with_preamble_crc:
228322
rx_datapath.add_preamble()
229323
rx_datapath.add_crc()
324+
# Add padding if enabled.
230325
if with_padding:
231326
rx_datapath.add_padding()
327+
# Add domain switch if not using system datapath.
232328
if not with_sys_datapath:
233329
rx_datapath.add_domain_switch()
234-
rx_datapath.pipeline.append(self.source)
330+
# Connect source to the end of the pipeline.
331+
rx_datapath.pipeline.append(self.source)

0 commit comments

Comments
 (0)