Skip to content

Commit 0b1a2e1

Browse files
committedApr 26, 2015
liteeth: do MII/GMII detection in gateware for gmii_mii phy
1 parent 07b7c2a commit 0b1a2e1

File tree

5 files changed

+63
-83
lines changed

5 files changed

+63
-83
lines changed
 

Diff for: ‎misoclib/com/liteeth/phy/gmii_mii.py

+50-30
Original file line numberDiff line numberDiff line change
@@ -83,58 +83,78 @@ def __init__(self, pads, mode):
8383

8484

8585
class LiteEthGMIIMIIModeDetection(Module, AutoCSR):
86-
def __init__(self):
87-
self._reset = CSRStorage()
88-
self._counter = CSRStatus(32)
89-
self._mode = CSRStorage()
86+
def __init__(self, clk_freq):
9087
self.mode = Signal()
88+
self._mode = CSRStatus()
9189

9290
# # #
9391

94-
# Note:
95-
# For now mode detection is done with gateware and software.
96-
# We will probably do it in gateware in the future
97-
# (we will need to pass clk_freq parameter to PHY)
92+
mode = Signal()
93+
update_mode = Signal()
94+
self.sync += \
95+
If(update_mode,
96+
self.mode.eq(mode)
97+
)
98+
self.comb += self._mode.status.eq(self.mode)
9899

99100
# Principle:
100101
# sys_clk >= 125MHz
101102
# eth_rx <= 125Mhz
102-
# We generate a pulse in eth_rx clock domain that increments
103-
# a counter in sys_clk domain.
103+
# We generate ticks every 1024 clock cycles in eth_rx domain
104+
# and measure ticks period in sys_clk domain.
104105

105-
# Generate a pulse every 4 clock cycles (eth_rx clock domain)
106-
eth_pulse = Signal()
107-
eth_counter = Signal(2)
106+
# Generate a tick every 1024 clock cycles (eth_rx clock domain)
107+
eth_tick = Signal()
108+
eth_counter = Signal(10)
108109
self.sync.eth_rx += eth_counter.eq(eth_counter + 1)
109-
self.comb += eth_pulse.eq(eth_counter == 0)
110+
self.comb += eth_tick.eq(eth_counter == 0)
110111

111-
# Synchronize pulse (sys clock domain)
112-
sys_pulse = Signal()
112+
# Synchronize tick (sys clock domain)
113+
sys_tick = Signal()
113114
eth_ps = PulseSynchronizer("eth_rx", "sys")
114115
self.comb += [
115-
eth_ps.i.eq(eth_pulse),
116-
sys_pulse.eq(eth_ps.o)
116+
eth_ps.i.eq(eth_tick),
117+
sys_tick.eq(eth_ps.o)
117118
]
118119
self.submodules += eth_ps
119120

120-
# Count pulses (sys clock domain)
121-
counter = Counter(32)
122-
self.submodules += counter
123-
self.comb += [
124-
counter.reset.eq(self._reset.storage),
125-
counter.ce.eq(sys_pulse)
126-
]
127-
self.comb += self._counter.status.eq(counter.value)
121+
# sys_clk domain counter
122+
sys_counter = Counter(24)
123+
self.submodules += sys_counter
124+
125+
fsm = FSM(reset_state="IDLE")
126+
self.submodules += fsm
128127

129-
# Output mode
130-
self.comb += self.mode.eq(self._mode.storage)
128+
fsm.act("IDLE",
129+
sys_counter.reset.eq(1),
130+
If(sys_tick,
131+
NextState("COUNT")
132+
)
133+
)
134+
fsm.act("COUNT",
135+
sys_counter.ce.eq(1),
136+
If(sys_tick,
137+
NextState("DETECTION")
138+
)
139+
)
140+
fsm.act("DETECTION",
141+
update_mode.eq(1),
142+
# if freq < 125MHz-5% use MII mode
143+
If(sys_counter.value > int((clk_freq/125000000)*1024*1.05),
144+
mode.eq(1)
145+
# if freq >= 125MHz-5% use GMII mode
146+
).Else(
147+
mode.eq(0)
148+
),
149+
NextState("IDLE")
150+
)
131151

132152

133153
class LiteEthPHYGMIIMII(Module, AutoCSR):
134-
def __init__(self, clock_pads, pads, with_hw_init_reset=True):
154+
def __init__(self, clock_pads, pads, clk_freq, with_hw_init_reset=True):
135155
self.dw = 8
136156
# Note: we can use GMII CRG since it also handles tx clock pad used for MII
137-
self.submodules.mode_detection = LiteEthGMIIMIIModeDetection()
157+
self.submodules.mode_detection = LiteEthGMIIMIIModeDetection(clk_freq)
138158
mode = self.mode_detection.mode
139159
self.submodules.crg = LiteEthPHYGMIICRG(clock_pads, pads, with_hw_init_reset, mode == modes["MII"])
140160
self.submodules.tx = RenameClockDomains(LiteEthPHYGMIIMIITX(pads, mode), "eth_tx")

Diff for: ‎software/bios/main.c

+3-8
Original file line numberDiff line numberDiff line change
@@ -497,21 +497,16 @@ static int test_user_abort(void)
497497

498498
static void boot_sequence(void)
499499
{
500-
int eth_ok;
501-
502500
if(test_user_abort()) {
503501
#ifdef FLASH_BOOT_ADDRESS
504502
flashboot();
505503
#endif
506504
serialboot();
507505
#ifdef CSR_ETHPHY_MODE_DETECTION_MODE_ADDR
508-
eth_ok = eth_mode_detection();
509-
#else
510-
eth_ok = 1;
506+
eth_mode();
511507
#endif
512508
#ifdef CSR_ETHMAC_BASE
513-
if (eth_ok)
514-
netboot();
509+
netboot();
515510
#endif
516511
printf("No boot medium found\n");
517512
}
@@ -531,7 +526,7 @@ int main(int i, char **c)
531526
crcbios();
532527
id_print();
533528
#ifdef CSR_ETHMAC_BASE
534-
ethreset();
529+
eth_init();
535530
#endif
536531
#ifdef CSR_SDRAM_BASE
537532
sdr_ok = sdrinit();

Diff for: ‎software/include/net/microudp.h

+2-2
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ int microudp_send(unsigned short src_port, unsigned short dst_port, unsigned int
1414
void microudp_set_callback(udp_callback callback);
1515
void microudp_service(void);
1616

17-
void ethreset(void);
18-
int eth_mode_detection(void);
17+
void eth_init(void);
18+
void eth_mode(void);
1919

2020
#endif /* __MICROUDP_H */

Diff for: ‎software/libnet/microudp.c

+7-42
Original file line numberDiff line numberDiff line change
@@ -433,7 +433,7 @@ static void busy_wait(unsigned int ds)
433433
while(timer0_value_read()) timer0_update_value_write(1);
434434
}
435435

436-
void ethreset(void)
436+
void eth_init(void)
437437
{
438438
ethphy_crg_reset_write(0);
439439
busy_wait(2);
@@ -445,50 +445,15 @@ void ethreset(void)
445445
}
446446

447447
#ifdef CSR_ETHPHY_MODE_DETECTION_MODE_ADDR
448-
static int eth_test_frequency(unsigned int freq, unsigned int target, unsigned int margin)
448+
void eth_mode(void)
449449
{
450-
if (freq < (target - margin))
451-
return 0;
452-
else if (freq > (target + margin))
453-
return 0;
454-
else
455-
return 1;
456-
}
457-
458-
int eth_mode_detection(void)
459-
{
460-
unsigned int frequency;
461-
462-
ethphy_mode_detection_reset_write(1);
463-
busy_wait(1);
464-
ethphy_mode_detection_reset_write(0);
465-
busy_wait(1);
466-
frequency = ethphy_mode_detection_counter_read()*4*10;
467-
ethphy_mode_detection_reset_write(1);
468-
469450
printf("Ethernet phy mode: ");
470-
/* 10Mbps */
471-
if(eth_test_frequency(frequency, 2500000, 1000000)) {
472-
ethphy_mode_detection_mode_write(1);
473-
printf("10Mbps (MII)\n");
474-
return 1;
475-
/* 100Mbps */
476-
} else if(eth_test_frequency(frequency, 25000000, 1000000)) {
477-
ethphy_mode_detection_mode_write(1);
478-
printf("100Mbps (MII)\n");
479-
return 1;
480-
/* 1Gbps */
481-
} else if(eth_test_frequency(frequency, 125000000, 1000000)) {
482-
ethphy_mode_detection_mode_write(0);
483-
printf("1Gbps (GMII)\n");
484-
return 1;
485-
/* Failed */
486-
} else {
487-
printf("Failed to detect link speed\n");
488-
return 0;
489-
}
451+
if (ethphy_mode_detection_mode_read())
452+
printf("MII");
453+
else
454+
printf("GMII");
455+
printf("\n");
490456
}
491457
#endif
492458

493459
#endif
494-

Diff for: ‎targets/kc705.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ class MiniSoC(BaseSoC):
122122
def __init__(self, platform, **kwargs):
123123
BaseSoC.__init__(self, platform, **kwargs)
124124

125-
self.submodules.ethphy = LiteEthPHY(platform.request("eth_clocks"), platform.request("eth"))
125+
self.submodules.ethphy = LiteEthPHY(platform.request("eth_clocks"), platform.request("eth"), clk_freq=self.clk_freq)
126126
self.submodules.ethmac = LiteEthMAC(phy=self.ethphy, dw=32, interface="wishbone")
127127
self.add_wb_slave(mem_decoder(self.mem_map["ethmac"]), self.ethmac.bus)
128128
self.add_memory_region("ethmac", self.mem_map["ethmac"]+self.shadow_address, 0x2000)

0 commit comments

Comments
 (0)
Please sign in to comment.