Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: m-labs/misoc
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 130fd19dec29
Choose a base ref
...
head repository: m-labs/misoc
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 07b7c2a13fd7
Choose a head ref
  • 2 commits
  • 5 files changed
  • 1 contributor

Commits on Apr 26, 2015

  1. Copy the full SHA
    ae71bf2 View commit details
  2. Copy the full SHA
    07b7c2a View commit details
Showing with 88 additions and 30 deletions.
  1. +1 −1 misoclib/com/liteeth/phy/gmii.py
  2. +41 −10 misoclib/com/liteeth/phy/gmii_mii.py
  3. +8 −3 software/bios/main.c
  4. +1 −1 software/include/net/microudp.h
  5. +37 −15 software/libnet/microudp.c
2 changes: 1 addition & 1 deletion misoclib/com/liteeth/phy/gmii.py
Original file line number Diff line number Diff line change
@@ -5,7 +5,7 @@


class LiteEthPHYGMIITX(Module):
def __init__(self, pads, pads_register):
def __init__(self, pads, pads_register=True):
self.sink = sink = Sink(eth_phy_description(8))

# # #
51 changes: 41 additions & 10 deletions misoclib/com/liteeth/phy/gmii_mii.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from migen.genlib.io import DDROutput
from migen.flow.plumbing import Multiplexer, Demultiplexer
from migen.genlib.cdc import MultiReg
from migen.genlib.cdc import PulseSynchronizer

from misoclib.com.liteeth.common import *
from misoclib.com.liteeth.generic import *
@@ -82,30 +82,61 @@ def __init__(self, pads, mode):
]


class LiteEthGMIIMIIClockCounter(Module, AutoCSR):
class LiteEthGMIIMIIModeDetection(Module, AutoCSR):
def __init__(self):
self._reset = CSRStorage()
self._value = CSRStatus(32)
self._counter = CSRStatus(32)
self._mode = CSRStorage()
self.mode = Signal()

# # #

counter = RenameClockDomains(Counter(32), "eth_rx")
# 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)

# Principle:
# sys_clk >= 125MHz
# eth_rx <= 125Mhz
# We generate a pulse in eth_rx clock domain that increments
# a counter in sys_clk domain.

# Generate a pulse every 4 clock cycles (eth_rx clock domain)
eth_pulse = Signal()
eth_counter = Signal(2)
self.sync.eth_rx += eth_counter.eq(eth_counter + 1)
self.comb += eth_pulse.eq(eth_counter == 0)

# Synchronize pulse (sys clock domain)
sys_pulse = Signal()
eth_ps = PulseSynchronizer("eth_rx", "sys")
self.comb += [
eth_ps.i.eq(eth_pulse),
sys_pulse.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), # slow, don't need CDC
counter.ce.eq(1),
counter.reset.eq(self._reset.storage),
counter.ce.eq(sys_pulse)
]
self.specials += MultiReg(counter.value, self._value.status)
self.comb += self._counter.status.eq(counter.value)

# Output mode
self.comb += self.mode.eq(self._mode.storage)


class LiteEthPHYGMIIMII(Module, AutoCSR):
def __init__(self, clock_pads, pads, with_hw_init_reset=True):
self.dw = 8
self._mode = CSRStorage()
mode = self._mode.storage
# Note: we can use GMII CRG since it also handles tx clock pad used for MII
self.submodules.mode_detection = LiteEthGMIIMIIModeDetection()
mode = self.mode_detection.mode
self.submodules.crg = LiteEthPHYGMIICRG(clock_pads, pads, with_hw_init_reset, mode == modes["MII"])
self.submodules.clock_counter = LiteEthGMIIMIIClockCounter()
self.submodules.tx = RenameClockDomains(LiteEthPHYGMIIMIITX(pads, mode), "eth_tx")
self.submodules.rx = RenameClockDomains(LiteEthPHYGMIIMIIRX(pads, mode), "eth_rx")
self.sink, self.source = self.tx.sink, self.rx.source
11 changes: 8 additions & 3 deletions software/bios/main.c
Original file line number Diff line number Diff line change
@@ -497,16 +497,21 @@ 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_ADDR
ethmode();
#ifdef CSR_ETHPHY_MODE_DETECTION_MODE_ADDR
eth_ok = eth_mode_detection();
#else
eth_ok = 1;
#endif
#ifdef CSR_ETHMAC_BASE
netboot();
if (eth_ok)
netboot();
#endif
printf("No boot medium found\n");
}
2 changes: 1 addition & 1 deletion software/include/net/microudp.h
Original file line number Diff line number Diff line change
@@ -15,6 +15,6 @@ void microudp_set_callback(udp_callback callback);
void microudp_service(void);

void ethreset(void);
void ethmode(void);
int eth_mode_detection(void);

#endif /* __MICROUDP_H */
52 changes: 37 additions & 15 deletions software/libnet/microudp.c
Original file line number Diff line number Diff line change
@@ -444,27 +444,49 @@ void ethreset(void)
busy_wait(2);
}

#ifdef CSR_ETHPHY_MODE_ADDR
void ethmode(void)
#ifdef CSR_ETHPHY_MODE_DETECTION_MODE_ADDR
static int eth_test_frequency(unsigned int freq, unsigned int target, unsigned int margin)
{
ethphy_clock_counter_reset_write(1);
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_clock_counter_reset_write(0);
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: ");
/* if freq > 120 MHz, use GMII (5MHz margin)*/
if(ethphy_clock_counter_value_read() > 120000000/10) {
ethphy_mode_write(0);
printf("GMII");
/* else use MII */
} else {
ethphy_mode_write(1);
printf("MII");
/* 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;
}
printf("\n");

ethphy_clock_counter_reset_write(1);
}
#endif