From 0b1a2e102251a0476294c4958d7edf4a5dfe2c87 Mon Sep 17 00:00:00 2001 From: Florent Kermarrec Date: Sun, 26 Apr 2015 17:32:25 +0200 Subject: [PATCH] liteeth: do MII/GMII detection in gateware for gmii_mii phy --- misoclib/com/liteeth/phy/gmii_mii.py | 80 +++++++++++++++++----------- software/bios/main.c | 11 ++-- software/include/net/microudp.h | 4 +- software/libnet/microudp.c | 49 +++-------------- targets/kc705.py | 2 +- 5 files changed, 63 insertions(+), 83 deletions(-) diff --git a/misoclib/com/liteeth/phy/gmii_mii.py b/misoclib/com/liteeth/phy/gmii_mii.py index b2b9b8d2..d1bd7d7f 100644 --- a/misoclib/com/liteeth/phy/gmii_mii.py +++ b/misoclib/com/liteeth/phy/gmii_mii.py @@ -83,58 +83,78 @@ class LiteEthPHYGMIIMIIRX(Module): class LiteEthGMIIMIIModeDetection(Module, AutoCSR): - def __init__(self): - self._reset = CSRStorage() - self._counter = CSRStatus(32) - self._mode = CSRStorage() + def __init__(self, clk_freq): self.mode = Signal() + self._mode = CSRStatus() # # # - # Note: - # For now mode detection is done with gateware and software. - # We will probably do it in gateware in the future - # (we will need to pass clk_freq parameter to PHY) + mode = Signal() + update_mode = Signal() + self.sync += \ + If(update_mode, + self.mode.eq(mode) + ) + self.comb += self._mode.status.eq(self.mode) # Principle: # sys_clk >= 125MHz # eth_rx <= 125Mhz - # We generate a pulse in eth_rx clock domain that increments - # a counter in sys_clk domain. + # We generate ticks every 1024 clock cycles in eth_rx domain + # and measure ticks period in sys_clk domain. - # Generate a pulse every 4 clock cycles (eth_rx clock domain) - eth_pulse = Signal() - eth_counter = Signal(2) + # Generate a tick every 1024 clock cycles (eth_rx clock domain) + eth_tick = Signal() + eth_counter = Signal(10) self.sync.eth_rx += eth_counter.eq(eth_counter + 1) - self.comb += eth_pulse.eq(eth_counter == 0) + self.comb += eth_tick.eq(eth_counter == 0) - # Synchronize pulse (sys clock domain) - sys_pulse = Signal() + # Synchronize tick (sys clock domain) + sys_tick = Signal() eth_ps = PulseSynchronizer("eth_rx", "sys") self.comb += [ - eth_ps.i.eq(eth_pulse), - sys_pulse.eq(eth_ps.o) + eth_ps.i.eq(eth_tick), + sys_tick.eq(eth_ps.o) ] self.submodules += eth_ps - # Count pulses (sys clock domain) - counter = Counter(32) - self.submodules += counter - self.comb += [ - counter.reset.eq(self._reset.storage), - counter.ce.eq(sys_pulse) - ] - self.comb += self._counter.status.eq(counter.value) + # sys_clk domain counter + sys_counter = Counter(24) + self.submodules += sys_counter + + fsm = FSM(reset_state="IDLE") + self.submodules += fsm - # Output mode - self.comb += self.mode.eq(self._mode.storage) + fsm.act("IDLE", + sys_counter.reset.eq(1), + If(sys_tick, + NextState("COUNT") + ) + ) + fsm.act("COUNT", + sys_counter.ce.eq(1), + If(sys_tick, + NextState("DETECTION") + ) + ) + fsm.act("DETECTION", + update_mode.eq(1), + # if freq < 125MHz-5% use MII mode + If(sys_counter.value > int((clk_freq/125000000)*1024*1.05), + mode.eq(1) + # if freq >= 125MHz-5% use GMII mode + ).Else( + mode.eq(0) + ), + NextState("IDLE") + ) class LiteEthPHYGMIIMII(Module, AutoCSR): - def __init__(self, clock_pads, pads, with_hw_init_reset=True): + def __init__(self, clock_pads, pads, clk_freq, with_hw_init_reset=True): self.dw = 8 # Note: we can use GMII CRG since it also handles tx clock pad used for MII - self.submodules.mode_detection = LiteEthGMIIMIIModeDetection() + self.submodules.mode_detection = LiteEthGMIIMIIModeDetection(clk_freq) mode = self.mode_detection.mode self.submodules.crg = LiteEthPHYGMIICRG(clock_pads, pads, with_hw_init_reset, mode == modes["MII"]) self.submodules.tx = RenameClockDomains(LiteEthPHYGMIIMIITX(pads, mode), "eth_tx") diff --git a/software/bios/main.c b/software/bios/main.c index e6b5a818..bb854df0 100644 --- a/software/bios/main.c +++ b/software/bios/main.c @@ -497,21 +497,16 @@ static int test_user_abort(void) static void boot_sequence(void) { - int eth_ok; - if(test_user_abort()) { #ifdef FLASH_BOOT_ADDRESS flashboot(); #endif serialboot(); #ifdef CSR_ETHPHY_MODE_DETECTION_MODE_ADDR - eth_ok = eth_mode_detection(); -#else - eth_ok = 1; + eth_mode(); #endif #ifdef CSR_ETHMAC_BASE - if (eth_ok) - netboot(); + netboot(); #endif printf("No boot medium found\n"); } @@ -531,7 +526,7 @@ int main(int i, char **c) crcbios(); id_print(); #ifdef CSR_ETHMAC_BASE - ethreset(); + eth_init(); #endif #ifdef CSR_SDRAM_BASE sdr_ok = sdrinit(); diff --git a/software/include/net/microudp.h b/software/include/net/microudp.h index 36ac5288..f148a341 100644 --- a/software/include/net/microudp.h +++ b/software/include/net/microudp.h @@ -14,7 +14,7 @@ int microudp_send(unsigned short src_port, unsigned short dst_port, unsigned int void microudp_set_callback(udp_callback callback); void microudp_service(void); -void ethreset(void); -int eth_mode_detection(void); +void eth_init(void); +void eth_mode(void); #endif /* __MICROUDP_H */ diff --git a/software/libnet/microudp.c b/software/libnet/microudp.c index 1bb56f24..c92e4453 100644 --- a/software/libnet/microudp.c +++ b/software/libnet/microudp.c @@ -433,7 +433,7 @@ static void busy_wait(unsigned int ds) while(timer0_value_read()) timer0_update_value_write(1); } -void ethreset(void) +void eth_init(void) { ethphy_crg_reset_write(0); busy_wait(2); @@ -445,50 +445,15 @@ void ethreset(void) } #ifdef CSR_ETHPHY_MODE_DETECTION_MODE_ADDR -static int eth_test_frequency(unsigned int freq, unsigned int target, unsigned int margin) +void eth_mode(void) { - if (freq < (target - margin)) - return 0; - else if (freq > (target + margin)) - return 0; - else - return 1; -} - -int eth_mode_detection(void) -{ - unsigned int frequency; - - ethphy_mode_detection_reset_write(1); - busy_wait(1); - ethphy_mode_detection_reset_write(0); - busy_wait(1); - frequency = ethphy_mode_detection_counter_read()*4*10; - ethphy_mode_detection_reset_write(1); - printf("Ethernet phy mode: "); - /* 10Mbps */ - if(eth_test_frequency(frequency, 2500000, 1000000)) { - ethphy_mode_detection_mode_write(1); - printf("10Mbps (MII)\n"); - return 1; - /* 100Mbps */ - } else if(eth_test_frequency(frequency, 25000000, 1000000)) { - ethphy_mode_detection_mode_write(1); - printf("100Mbps (MII)\n"); - return 1; - /* 1Gbps */ - } else if(eth_test_frequency(frequency, 125000000, 1000000)) { - ethphy_mode_detection_mode_write(0); - printf("1Gbps (GMII)\n"); - return 1; - /* Failed */ - } else { - printf("Failed to detect link speed\n"); - return 0; - } + if (ethphy_mode_detection_mode_read()) + printf("MII"); + else + printf("GMII"); + printf("\n"); } #endif #endif - diff --git a/targets/kc705.py b/targets/kc705.py index cdffafda..b0d477fd 100644 --- a/targets/kc705.py +++ b/targets/kc705.py @@ -122,7 +122,7 @@ class MiniSoC(BaseSoC): def __init__(self, platform, **kwargs): BaseSoC.__init__(self, platform, **kwargs) - self.submodules.ethphy = LiteEthPHY(platform.request("eth_clocks"), platform.request("eth")) + self.submodules.ethphy = LiteEthPHY(platform.request("eth_clocks"), platform.request("eth"), clk_freq=self.clk_freq) self.submodules.ethmac = LiteEthMAC(phy=self.ethphy, dw=32, interface="wishbone") self.add_wb_slave(mem_decoder(self.mem_map["ethmac"]), self.ethmac.bus) self.add_memory_region("ethmac", self.mem_map["ethmac"]+self.shadow_address, 0x2000) -- 2.30.2