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: whitequark/Yumewatari
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: fd7e9b4c5b65
Choose a base ref
...
head repository: whitequark/Yumewatari
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 8afe8ead7ad2
Choose a head ref
  • 1 commit
  • 3 files changed
  • 1 contributor

Commits on Nov 12, 2018

  1. Copy the full SHA
    8afe8ea View commit details
Showing with 155 additions and 19 deletions.
  1. +62 −0 yumewatari/gateware/align.py
  2. +78 −0 yumewatari/test/align.py
  3. +15 −19 yumewatari/testbench/serdes.py
62 changes: 62 additions & 0 deletions yumewatari/gateware/align.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
from migen import *


__all__ = ["SymbolSlip"]


class SymbolSlip(Module):
"""
Symbol slip based comma aligner. Accepts and emits a sequence of words, shifting it such
that if a comma symbol is encountered, it is always placed at the start of a word.
If the input word contains multiple commas, the behavior is undefined.
Parameters
----------
symbol_size : int
Symbol width, in bits.
word_size : int
Word size, in symbols.
comma : int
Comma symbol, ``symbol_size`` bit wide.
Attributes
----------
i : Signal(symbol_size * word_size)
Input word.
o : Signal(symbol_size * word_size)
Output word.
en : Signal
Enable input. If asserted (the default), comma symbol affects alignment. Otherwise,
comma symbol does nothing.
"""
def __init__(self, symbol_size, word_size, comma):
width = symbol_size * word_size

self.i = Signal(width)
self.o = Signal(width)
self.en = Signal(reset=1)

###

shreg = Signal(width * 2)
offset = Signal(max=symbol_size * (word_size - 1))
self.sync += shreg.eq(Cat(shreg[width:], self.i))
self.comb += self.o.eq(shreg.part(offset, width))

commas = Signal(word_size)
self.sync += [
commas[n].eq(self.i.part(symbol_size * n, symbol_size) == comma)
for n in range(word_size)
]

self.sync += [
If(self.en,
Case(commas, {
(1 << n): offset.eq(symbol_size * n)
for n in range(word_size)
})
)
]


78 changes: 78 additions & 0 deletions yumewatari/test/align.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
import unittest
from migen import *

from ..gateware.align import *
from . import simulation_test


class SymbolSlipTestbench(Module):
def __init__(self):
self.submodules.dut = SymbolSlip(symbol_size=8, word_size=4, comma=0xaa)


class SymbolSlipTestCase(unittest.TestCase):
def setUp(self):
self.tb = SymbolSlipTestbench()

@simulation_test
def test_no_slip(self, tb):
yield tb.dut.i.eq(0x04030201)
yield
self.assertEqual((yield tb.dut.o), 0)
yield tb.dut.i.eq(0x08070605)
yield
self.assertEqual((yield tb.dut.o), 0)
yield tb.dut.i.eq(0x0c0b0a09)
yield
self.assertEqual((yield tb.dut.o), 0x04030201)
yield tb.dut.i.eq(0)
yield
self.assertEqual((yield tb.dut.o), 0x08070605)
yield
self.assertEqual((yield tb.dut.o), 0x0c0b0a09)

@simulation_test
def test_slip(self, tb):
yield tb.dut.i.eq(0x0403aa01)
yield
yield tb.dut.i.eq(0x08070605)
yield
self.assertEqual((yield tb.dut.o), 0)
yield tb.dut.i.eq(0x0c0b0a09)
yield
self.assertEqual((yield tb.dut.o), 0x050403aa)
yield tb.dut.i.eq(0x000f0e0d)
yield
self.assertEqual((yield tb.dut.o), 0x09080706)

@simulation_test
def test_slip_2(self, tb):
yield tb.dut.i.eq(0x0403aa01)
yield
yield tb.dut.i.eq(0x080706aa)
yield
self.assertEqual((yield tb.dut.o), 0)
yield tb.dut.i.eq(0x0c0b0a09)
yield
self.assertEqual((yield tb.dut.o), 0xaa0403aa)
yield tb.dut.i.eq(0x000f0e0d)
yield
self.assertEqual((yield tb.dut.o), 0x080706aa)
yield tb.dut.i.eq(0x14131210)
yield
self.assertEqual((yield tb.dut.o), 0x0c0b0a09)

@simulation_test
def test_enable(self, tb):
yield tb.dut.en.eq(0)
yield tb.dut.i.eq(0x0403aa01)
yield
yield tb.dut.i.eq(0x08070605)
yield
self.assertEqual((yield tb.dut.o), 0)
yield tb.dut.i.eq(0x0c0b0a09)
yield
self.assertEqual((yield tb.dut.o), 0x0403aa01)
yield tb.dut.i.eq(0x000f0e0d)
yield
self.assertEqual((yield tb.dut.o), 0x08070605)
34 changes: 15 additions & 19 deletions yumewatari/testbench/serdes.py
Original file line number Diff line number Diff line change
@@ -6,6 +6,8 @@
from migen.genlib.fsm import FSM

from ..gateware.serdes import *
from ..gateware.phy import K
from ..gateware.align import *
from ..gateware.platform.lattice_ecp5 import *
from ..vendor.pads import *
from ..vendor.uart import *
@@ -18,21 +20,27 @@ def __init__(self, capture_depth, **kwargs):
("tp0", 0, Pins("X3:5"), IOStandard("LVCMOS33")),
])

self.submodules.serdes = serdes = LatticeECP5PCIeSERDES(self.platform.request("pcie_x1"))
self.comb += [
serdes.lane.tx_symbol.eq(0x17C),
serdes.lane.rx_align.eq(1),
]

self.clock_domains.cd_ref = ClockDomain()
self.clock_domains.cd_rx = ClockDomain()
self.clock_domains.cd_tx = ClockDomain()

self.submodules.serdes = serdes = \
LatticeECP5PCIeSERDES(self.platform.request("pcie_x1"))
self.comb += [
self.cd_ref.clk.eq(serdes.ref_clk),
serdes.rx_clk_i.eq(serdes.rx_clk_o),
self.cd_rx.clk.eq(serdes.rx_clk_i),
serdes.tx_clk_i.eq(serdes.tx_clk_o),
self.cd_tx.clk.eq(serdes.tx_clk_i),

serdes.lane.tx_symbol.eq(0x17C),
serdes.lane.rx_align.eq(1),
]

self.submodules.aligner = aligner = \
ClockDomainsRenamer("rx")(SymbolSlip(symbol_size=9, word_size=2, comma=K(28,5)))
self.comb += [
aligner.i.eq(serdes.lane.rx_symbol),
]

self.platform.add_platform_command("""FREQUENCY NET "ref_clk" 100 MHz;""")
@@ -65,18 +73,6 @@ def __init__(self, capture_depth, **kwargs):
led_err4.eq(~(0)),
]

self.clock_domains.cd_por = ClockDomain(reset_less=True)
reset_delay = Signal(max=2047, reset=2047)
self.comb += [
self.cd_por.clk.eq(self.cd_ref.clk),
self.cd_ref.rst.eq(reset_delay != 0)
]
self.sync.por += [
If(reset_delay != 0,
reset_delay.eq(reset_delay - 1)
)
]

trigger_rx = Signal()
trigger_ref = Signal()
self.specials += MultiReg(trigger_ref, trigger_rx, odomain="rx")
@@ -88,7 +84,7 @@ def __init__(self, capture_depth, **kwargs):
AsyncFIFO(width=18, depth=capture_depth)
)
self.comb += [
symbols.din.eq(Cat(serdes.lane.rx_symbol)),
symbols.din.eq(Cat(aligner.o)),
symbols.we.eq(capture)
]
self.sync.rx += [