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: GlasgowEmbedded/glasgow
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: cd921fda78d5
Choose a base ref
...
head repository: GlasgowEmbedded/glasgow
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: ee0c1ae88e6d
Choose a head ref
  • 1 commit
  • 1 file changed
  • 1 contributor

Commits on Apr 3, 2019

  1. Copy the full SHA
    ee0c1ae View commit details
Showing with 49 additions and 20 deletions.
  1. +49 −20 software/glasgow/gateware/fx2.py
69 changes: 49 additions & 20 deletions software/glasgow/gateware/fx2.py
Original file line number Diff line number Diff line change
@@ -36,15 +36,22 @@ class _DummyFIFO(Module, _FIFOInterface):
def __init__(self, width):
super().__init__(width, 0)

self.submodules.fifo = _FIFOInterface(width, 0)


class _FIFOWithOverflow(Module, _FIFOInterface):
"""
A FIFO with an overflow buffer in front of it. Useful when the FIFO is fed from a pipeline
that reacts to the ``writable`` flag with a latency, and writes must not be lost.
"""
def __init__(self, fifo, overflow_depth=2):
_FIFOInterface.__init__(self, fifo.width, fifo.depth)

if fifo.depth > 0:
overflow = SyncFIFO(fifo.width, overflow_depth)
else:
overflow = _DummyFIFO(fifo.width)

self.submodules.fifo = fifo
self.submodules.overflow = overflow = SyncFIFO(fifo.width, overflow_depth)
self.submodules.overflow = overflow

self.dout = fifo.dout
self.re = fifo.re
@@ -71,6 +78,11 @@ def __init__(self, fifo, overflow_depth=2):


class _FIFOWithFlush(Module, _FIFOInterface):
"""
A FIFO with a sideband flag indicating whether the FIFO has enough data to read from it yet.
Useful when the data read from the FIFO is packetized, but there is no particular framing
available to optimize the packet boundaries.
"""
def __init__(self, fifo, asynchronous=False, auto_flush=True):
_FIFOInterface.__init__(self, fifo.width, fifo.depth)

@@ -116,7 +128,7 @@ def get_bit(signal, bit):
for bit in range(io.nbits):
self.specials += \
Instance("SB_IO",
# PIN_INPUT_REGISTERED|PIN_OUTPUT_REGISTERED_ENABLE_REGISTERED
# PIN_INPUT_DDR|PIN_OUTPUT_REGISTERED_ENABLE_REGISTERED
p_PIN_TYPE=C(0b110100, 6),
io_PACKAGE_PIN=get_bit(io, bit),
i_OUTPUT_ENABLE=self.oe,
@@ -179,7 +191,6 @@ def do_finalize(self):
[fifo.readable | fifo.queued for fifo in self. in_fifos]) &
flag),
self.out_fifos[addr[0]].din.eq(bus.fd_t.i),
self.in_fifos[addr[0]].flushed.eq(pend),
bus.fd_t.o.eq(self.in_fifos[addr[0]].dout),
bus.fd_t.oe.eq(fdoe),
bus.sloe_t.oe.eq(1),
@@ -192,6 +203,22 @@ def do_finalize(self):
bus.pktend_t.o.eq(~pend),
]

# Derive the control signals for the FPGA-side FIFOs from the FX2 bus control signals.
# This is done independently from the main FSM because registers in the FX2 output path
# add latency, complicating logic.
slrd_r = Signal()
self.sync += [
slrd_r.eq(slrd),
]
self.comb += [
If(addr[1],
self.in_fifos [addr[0]].re.eq(slwr),
self.in_fifos [addr[0]].flushed.eq(pend),
).Else(
self.out_fifos[addr[0]].we.eq(slrd_r & flag.part(addr, 1)),
)
]

# Calculate the address of the next ready FIFO in a round robin process.
naddr = Signal(2)
naddr_c = {}
@@ -227,17 +254,18 @@ def do_finalize(self):
)
self.fsm.act("SETUP",
If(addr[1],
NextState("SETUP-IN")
NextState("IN-SETUP")
).Else(
NextState("SETUP-OUT")
NextState("OUT-SETUP")
)
)
self.fsm.act("SETUP-IN",
NextState("XFER-IN")

# IN endpoint handling
self.fsm.act("IN-SETUP",
NextState("IN-XFER")
)
self.fsm.act("XFER-IN",
self.fsm.act("IN-XFER",
If(flag.part(addr, 1) & self.in_fifos[addr[0]].readable,
self.in_fifos[addr[0]].re.eq(1),
slwr.eq(1)
).Elif(~flag.part(addr, 1) & ~self.in_fifos[addr[0]].readable,
# The ~FULL flag went down, and it goes down one sample earlier than the actual
@@ -249,32 +277,33 @@ def do_finalize(self):
# and commit a packet one byte shorter than the complete FIFO.
#
# This shouldn't cause any problems.
NextState("PKTEND-IN")
NextState("IN-PKTEND")
).Elif(flag.part(addr, 1) & self.in_fifos[addr[0]].queued,
# The FX2-side FIFO is not full yet, but the flush flag is asserted.
# Commit the short packet.
NextState("PKTEND-IN")
NextState("IN-PKTEND")
).Else(
# Either the FPGA-side FIFO is empty, or the FX2-side FIFO is full, or the flush
# flag is not asserted.
# FX2 automatically commits a full FIFO, so we don't need to do anything here.
NextState("NEXT")
)
)
self.fsm.act("PKTEND-IN",
self.fsm.act("IN-PKTEND",
# See datasheet "Slave FIFO Synchronous Packet End Strobe Parameters" for
# an explanation of why this is asserted one cycle after the last SLWR pulse.
pend.eq(1),
NextState("NEXT")
)
self.fsm.act("SETUP-OUT",

# OUT endpoint handling
self.fsm.act("OUT-SETUP",
slrd.eq(1),
NextState("XFER-OUT")
NextState("OUT-XFER")
)
self.fsm.act("XFER-OUT",
self.out_fifos[addr[0]].we.eq(flag.part(addr, 1)),
If(rdy.part(addr, 1),
slrd.eq(self.out_fifos[addr[0]].fifo.writable),
self.fsm.act("OUT-XFER",
If(flag.part(addr, 1) & self.out_fifos[addr[0]].fifo.writable,
slrd.eq(1),
).Else(
NextState("NEXT")
)