2121# MAC Core -----------------------------------------------------------------------------------------
2222
2323class 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