- rename ft2232h phy to ft245.
- make crc optional
- fix depacketizer
- refactor uart (it's now only a wrapper around standard UART)
- fix and update dma
from migen.actorlib.fifo import *
from migen.flow.actor import EndpointDescription
from migen.actorlib.packet import *
+from migen.actorlib.structuring import Pipeline
packet_header_length = 9
class LiteUSBSlavePort:
- def __init__(self, dw):
+ def __init__(self, dw, tag):
self.sink = Sink(user_description(dw))
self.source = Source(user_description(dw))
+ self.tag = tag
class LiteUSBUserPort(LiteUSBSlavePort):
- def __init__(self, dw):
- LiteUSBSlavePort.__init__(self, dw)
+ def __init__(self, dw, tag):
+ LiteUSBSlavePort.__init__(self, dw, tag)
from misoclib.com.liteusb.core.crc import LiteUSBCRC32Inserter, LiteUSBCRC32Checker
from misoclib.com.liteusb.core.crossbar import LiteUSBCrossbar
-# XXX Header should be protected by CRC
-
class LiteUSBCore(Module):
- def __init__(self, phy):
+ def __init__(self, phy, clk_freq, with_crc=True):
+ rx_pipeline = [phy]
+ tx_pipeline = [phy]
+
# depacketizer / packetizer
- self.submodules.depacketizer = LiteUSBDepacketizer()
+ self.submodules.depacketizer = LiteUSBDepacketizer(clk_freq)
self.submodules.packetizer = LiteUSBPacketizer()
- self.comb += [
- Record.connect(phy.source, self.depacketizer.sink),
- Record.connect(self.packetizer.source, phy.sink)
- ]
+ rx_pipeline += [self.depacketizer]
+ tx_pipeline += [self.packetizer]
- # crc checker / inserter
- self.submodules.crc_rx = LiteUSBCRC32Checker()
- self.submodules.crc_tx = LiteUSBCRC32Inserter()
- self.comb += [
- Record.connect(self.depacketizer.source, self.crc_rx.sink),
- Record.connect(self.crc_tx.source, self.packetizer.sink)
- ]
+ if with_crc:
+ # crc checker / inserter
+ self.submodules.crc_rx = LiteUSBCRC32Checker()
+ self.submodules.crc_tx = LiteUSBCRC32Inserter()
+ rx_pipeline += [self.crc_rx]
+ tx_pipeline += [self.crc_tx]
- # crossbar
+ # crossbar
self.submodules.crossbar = LiteUSBCrossbar()
- self.comb += [
- Record.connect(self.crossbar.master.source, self.crc_tx.sink),
- Record.connect(self.crc_rx.source, self.crossbar.master.sink)
- ]
+ rx_pipeline += [self.crossbar.master]
+ tx_pipeline += [self.crossbar.master]
+
+ # graph
+ self.submodules.rx_pipeline = Pipeline(*rx_pipeline)
+ self.submodules.tx_pipeline = Pipeline(*reversed(tx_pipeline))
self.dispatch_param = "dst"
def get_port(self, dst):
- port = LiteUSBUserPort(8)
+ port = LiteUSBUserPort(8, dst)
if dst in self.users.keys():
raise ValueError("Destination {0:#x} already assigned".format(dst))
self.users[dst] = port
class LiteUSBDepacketizer(Module):
- def __init__(self, timeout=10):
+ def __init__(self, clk_freq, timeout=10):
self.sink = sink = Sink(phy_description(8))
self.source = source = Source(user_description(8))
header_pack.source.ack.eq(1),
)
- self.submodules.timeout = Timeout(60000000*timeout) #XXX use clk_freq
+ self.submodules.timeout = Timeout(clk_freq*timeout)
self.comb += [
- self.timeout.reset.eq(fsm.ongoing("WAIT_SOP")),
+ self.timeout.reset.eq(fsm.ongoing("IDLE")),
self.timeout.ce.eq(1)
]
# Pack data
pack_factor = lasmim.dw//8
- pack = structuring.Pack(phy_layout, pack_factor, reverse=True)
+ pack = structuring.Pack(phy_description(8), pack_factor, reverse=True)
cast = structuring.Cast(pack.source.payload.layout, lasmim.dw)
# DMA
pack_factor = lasmim.dw//8
packed_dat = structuring.pack_layout(8, pack_factor)
cast = structuring.Cast(lasmim.dw, packed_dat)
- unpack = structuring.Unpack(pack_factor, phy_layout, reverse=True)
+ unpack = structuring.Unpack(pack_factor, phy_description(8), reverse=True)
# Graph
cnt = Signal(32)
self.sync += \
- If(self.dma.generator._r_shoot.re,
+ If(self.dma.generator._shoot.re,
cnt.eq(0)
).Elif(source.stb & source.ack,
cnt.eq(cnt + 1)
class LiteUSBDMA(Module, AutoCSR):
- def __init__(self, lasmim_dma_wr, lasmim_dma_rd, tag):
- self.tag = tag
-
+ def __init__(self, port, lasmim_dma_wr, lasmim_dma_rd):
self.submodules.writer = LiteUSBDMAWriter(lasmim_dma_wr)
- self.submodules.reader = LiteUSBDMAReader(lasmim_dma_rd, self.tag)
+ self.submodules.reader = LiteUSBDMAReader(lasmim_dma_rd, port.tag)
self.submodules.ev = SharedIRQ(self.writer.ev, self.reader.ev)
-
- self.sink = self.writer.sink
- self.source = self.reader.source
+ self.comb += [
+ Record.connect(port.source, self.writer.sink),
+ Record.connect(self.reader.source, port.sink),
+ ]
from migen.fhdl.std import *
-from migen.bank.description import *
-from migen.bank.eventmanager import *
-from migen.actorlib.fifo import SyncFIFO
from misoclib.com.liteusb.common import *
+from misoclib.com.uart import UART
+class LiteUSBUARTPHY:
+ def __init__(self):
+ self.sink = Sink([("data", 8)])
+ self.source = Source([("data", 8)])
-class LiteUSBUART(Module, AutoCSR):
- def __init__(self, tag, fifo_depth=64):
- self.tag = tag
+class LiteUSBUART(UART):
+ def __init__(self, port,
+ tx_fifo_depth=16,
+ rx_fifo_depth=16):
- self._rxtx = CSR(8)
-
- self.submodules.ev = EventManager()
- self.ev.tx = EventSourcePulse()
- self.ev.rx = EventSourceLevel()
- self.ev.finalize()
-
- self.source = source = Source(user_description(8))
- self.sink = sink = Sink(user_description(8))
-
- # # #
+ phy = LiteUSBUARTPHY()
+ UART.__init__(self, phy, tx_fifo_depth, rx_fifo_depth)
# TX
- tx_start = self._rxtx.re
- tx_done = self.ev.tx.trigger
-
- self.sync += \
- If(tx_start,
- source.stb.eq(1),
- source.data.eq(self._rxtx.r),
- ).Elif(tx_done,
- source.stb.eq(0)
- )
-
self.comb += [
- source.sop.eq(1),
- source.eop.eq(1),
- source.length.eq(1),
- source.dst.eq(self.tag),
- tx_done.eq(source.stb & source.ack),
+ port.sink.stb.eq(phy.sink.stb),
+ port.sink.sop.eq(1),
+ port.sink.eop.eq(1),
+ port.sink.length.eq(1),
+ port.sink.dst.eq(port.tag),
+ port.sink.data.eq(phy.sink.data),
+ phy.sink.ack.eq(port.sink.ack)
]
# RX
- rx_available = self.ev.rx.trigger
-
- rx_fifo = SyncFIFO(8, fifo_depth)
- self.submodules += rx_fifo
self.comb += [
- Record.connect(sink, rx_fifo.sink),
-
- rx_fifo.we.eq(sink.stb),
- sink.ack.eq(sink.stb & rx_fifo.writable),
- rx_fifo.din.eq(sink.data),
- rx_available.eq(rx_fifo.stb),
- rx_fifo.ack.eq(self.ev.rx.clear),
- self._rxtx.w.eq(rx_fifo.dout)
+ phy.source.stb.eq(port.source.stb),
+ phy.source.data.eq(port.source.data),
+ port.source.ack.eq(phy.source.ack)
]
+++ /dev/null
-from migen.fhdl.std import *
-from migen.flow.actor import *
-from migen.actorlib.fifo import SyncFIFO, AsyncFIFO
-from migen.fhdl.specials import *
-from migen.genlib.cdc import MultiReg
-
-from misoclib.com.liteusb.common import *
-
-
-def anti_starvation(module, timeout):
- en = Signal()
- max_time = Signal()
- if timeout:
- t = timeout - 1
- time = Signal(max=t+1)
- module.comb += max_time.eq(time == 0)
- module.sync += If(~en,
- time.eq(t)
- ).Elif(~max_time,
- time.eq(time - 1)
- )
- else:
- module.comb += max_time.eq(0)
- return en, max_time
-
-
-class FT2232HPHYSynchronous(Module):
- def __init__(self, pads,
- fifo_depth=32,
- read_time=16,
- write_time=16):
- dw = flen(pads.data)
-
- #
- # Read / Write Fifos
- #
-
- # Read Fifo (Ftdi --> SoC)
- read_fifo = RenameClockDomains(AsyncFIFO(phy_description(8), fifo_depth),
- {"write": "ftdi", "read": "sys"})
- read_buffer = RenameClockDomains(SyncFIFO(phy_description(8), 4),
- {"sys": "ftdi"})
- self.comb += read_buffer.source.connect(read_fifo.sink)
-
- # Write Fifo (SoC --> Ftdi)
- write_fifo = RenameClockDomains(AsyncFIFO(phy_description(8), fifo_depth),
- {"write": "sys", "read": "ftdi"})
-
- self.submodules += read_fifo, read_buffer, write_fifo
-
- #
- # Sink / Source interfaces
- #
- self.sink = write_fifo.sink
- self.source = read_fifo.source
-
- #
- # Read / Write Arbitration
- #
- wants_write = Signal()
- wants_read = Signal()
-
- txe_n = Signal()
- rxf_n = Signal()
-
- self.comb += [
- txe_n.eq(pads.txe_n),
- rxf_n.eq(pads.rxf_n),
- wants_write.eq(~txe_n & write_fifo.source.stb),
- wants_read.eq(~rxf_n & read_fifo.sink.ack),
- ]
-
- read_time_en, max_read_time = anti_starvation(self, read_time)
- write_time_en, max_write_time = anti_starvation(self, write_time)
-
- data_w_accepted = Signal(reset=1)
-
- fsm = FSM(reset_state="READ")
- self.submodules += RenameClockDomains(fsm, {"sys": "ftdi"})
-
- fsm.act("READ",
- read_time_en.eq(1),
- If(wants_write,
- If(~wants_read | max_read_time,
- NextState("RTW")
- )
- )
- )
- fsm.act("RTW",
- NextState("WRITE")
- )
- fsm.act("WRITE",
- write_time_en.eq(1),
- If(wants_read,
- If(~wants_write | max_write_time,
- NextState("WTR")
- )
- ),
- write_fifo.source.ack.eq(wants_write & data_w_accepted)
- )
- fsm.act("WTR",
- NextState("READ")
- )
-
- #
- # Read / Write Actions
- #
-
- data_w = Signal(dw)
- data_r = Signal(dw)
- data_oe = Signal()
-
- pads.oe_n.reset = 1
- pads.rd_n.reset = 1
- pads.wr_n.reset = 1
-
- self.sync.ftdi += [
- If(fsm.ongoing("READ"),
- data_oe.eq(0),
-
- pads.oe_n.eq(0),
- pads.rd_n.eq(~wants_read),
- pads.wr_n.eq(1)
-
- ).Elif(fsm.ongoing("WRITE"),
- data_oe.eq(1),
-
- pads.oe_n.eq(1),
- pads.rd_n.eq(1),
- pads.wr_n.eq(~wants_write),
-
- data_w_accepted.eq(~txe_n)
-
- ).Else(
- data_oe.eq(1),
-
- pads.oe_n.eq(~fsm.ongoing("WTR")),
- pads.rd_n.eq(1),
- pads.wr_n.eq(1)
- ),
- read_buffer.sink.stb.eq(~pads.rd_n & ~rxf_n),
- read_buffer.sink.data.eq(data_r),
- If(~txe_n & data_w_accepted,
- data_w.eq(write_fifo.source.data)
- )
- ]
-
- #
- # Databus Tristate
- #
- self.specials += Tristate(pads.data, data_w, data_oe, data_r)
-
- self.debug = Signal(8)
- self.comb += self.debug.eq(data_r)
-
-
-class FT2232HPHYAsynchronous(Module):
- def __init__(self, pads, clk_freq,
- fifo_depth=32,
- read_time=16,
- write_time=16):
- dw = flen(pads.data)
-
- #
- # Read / Write Fifos
- #
-
- # Read Fifo (Ftdi --> SoC)
- read_fifo = SyncFIFO(phy_description(8), fifo_depth)
-
- # Write Fifo (SoC --> Ftdi)
- write_fifo = SyncFIFO(phy_description(8), fifo_depth)
-
- self.submodules += read_fifo, write_fifo
-
- #
- # Sink / Source interfaces
- #
- self.sink = write_fifo.sink
- self.source = read_fifo.source
-
- #
- # Read / Write Arbitration
- #
- wants_write = Signal()
- wants_read = Signal()
-
- txe_n = Signal()
- rxf_n = Signal()
-
- self.specials += [
- MultiReg(pads.txe_n, txe_n),
- MultiReg(pads.rxf_n, rxf_n)
- ]
-
- self.comb += [
- wants_write.eq(~txe_n & write_fifo.source.stb),
- wants_read.eq(~rxf_n & read_fifo.sink.ack),
- ]
-
- read_time_en, max_read_time = anti_starvation(self, read_time)
- write_time_en, max_write_time = anti_starvation(self, write_time)
-
- fsm = FSM(reset_state="READ")
- self.submodules += fsm
-
- read_done = Signal()
- write_done = Signal()
- commuting = Signal()
-
- fsm.act("READ",
- read_time_en.eq(1),
- If(wants_write & read_done,
- If(~wants_read | max_read_time,
- commuting.eq(1),
- NextState("RTW")
- )
- )
- )
- fsm.act("RTW",
- NextState("WRITE")
- )
- fsm.act("WRITE",
- write_time_en.eq(1),
- If(wants_read & write_done,
- If(~wants_write | max_write_time,
- commuting.eq(1),
- NextState("WTR")
- )
- )
- )
- fsm.act("WTR",
- NextState("READ")
- )
-
- #
- # Databus Tristate
- #
- data_w = Signal(dw)
- data_r_async = Signal(dw)
- data_r = Signal(dw)
- data_oe = Signal()
- self.specials += [
- Tristate(pads.data, data_w, data_oe, data_r_async),
- MultiReg(data_r_async, data_r)
- ]
-
- #
- # Read / Write Actions
- #
- pads.wr_n.reset = 1
- pads.rd_n.reset = 1
-
- read_fsm = FSM(reset_state="IDLE")
- read_counter = Counter(8)
- self.submodules += read_fsm, read_counter
-
- read_fsm.act("IDLE",
- read_done.eq(1),
- read_counter.reset.eq(1),
- If(fsm.ongoing("READ") & wants_read,
- If(~commuting,
- NextState("PULSE_RD_N")
- )
- )
- )
- read_fsm.act("PULSE_RD_N",
- pads.rd_n.eq(0),
- read_counter.ce.eq(1),
- If(read_counter.value == 15, # XXX Compute exact value
- NextState("ACQUIRE_DATA")
- )
- )
- read_fsm.act("ACQUIRE_DATA",
- read_fifo.sink.stb.eq(1),
- read_fifo.sink.data.eq(data_r),
- NextState("WAIT_RXF_N")
- )
- read_fsm.act("WAIT_RXF_N",
- If(rxf_n,
- NextState("IDLE")
- )
- )
-
- write_fsm = FSM(reset_state="IDLE")
- write_counter = Counter(8)
- self.submodules += write_fsm, write_counter
-
- write_fsm.act("IDLE",
- write_done.eq(1),
- write_counter.reset.eq(1),
- If(fsm.ongoing("WRITE") & wants_write,
- If(~commuting,
- NextState("SET_DATA")
- )
- )
- )
- write_fsm.act("SET_DATA",
- data_oe.eq(1),
- data_w.eq(write_fifo.source.data),
- write_counter.ce.eq(1),
- If(write_counter.value == 5, # XXX Compute exact value
- write_counter.reset.eq(1),
- NextState("PULSE_WR_N")
- )
- )
- write_fsm.act("PULSE_WR_N",
- data_oe.eq(1),
- data_w.eq(write_fifo.source.data),
- pads.wr_n.eq(0),
- write_counter.ce.eq(1),
- If(write_counter.value == 15, # XXX Compute exact value
- NextState("WAIT_TXE_N")
- )
- )
- write_fsm.act("WAIT_TXE_N",
- If(txe_n,
- write_fifo.source.ack.eq(1),
- NextState("IDLE")
- )
- )
--- /dev/null
+import math
+
+from migen.fhdl.std import *
+from migen.flow.actor import *
+from migen.actorlib.fifo import SyncFIFO, AsyncFIFO
+from migen.fhdl.specials import *
+from migen.genlib.cdc import MultiReg
+
+from misoclib.com.liteusb.common import *
+
+
+def anti_starvation(module, timeout):
+ en = Signal()
+ max_time = Signal()
+ if timeout:
+ t = timeout - 1
+ time = Signal(max=t+1)
+ module.comb += max_time.eq(time == 0)
+ module.sync += If(~en,
+ time.eq(t)
+ ).Elif(~max_time,
+ time.eq(time - 1)
+ )
+ else:
+ module.comb += max_time.eq(0)
+ return en, max_time
+
+
+class FT245PHYSynchronous(Module):
+ def __init__(self, pads, clk_freq,
+ fifo_depth=32,
+ read_time=128,
+ write_time=128):
+ dw = flen(pads.data)
+
+ # read fifo (FTDI --> SoC)
+ read_fifo = RenameClockDomains(AsyncFIFO(phy_description(8), fifo_depth),
+ {"write": "ftdi", "read": "sys"})
+ read_buffer = RenameClockDomains(SyncFIFO(phy_description(8), 4),
+ {"sys": "ftdi"})
+ self.comb += read_buffer.source.connect(read_fifo.sink)
+
+ # write fifo (SoC --> FTDI)
+ write_fifo = RenameClockDomains(AsyncFIFO(phy_description(8), fifo_depth),
+ {"write": "sys", "read": "ftdi"})
+
+ self.submodules += read_fifo, read_buffer, write_fifo
+
+ # sink / source interfaces
+ self.sink = write_fifo.sink
+ self.source = read_fifo.source
+
+ # read / write arbitration
+ wants_write = Signal()
+ wants_read = Signal()
+
+ txe_n = Signal()
+ rxf_n = Signal()
+
+ self.comb += [
+ txe_n.eq(pads.txe_n),
+ rxf_n.eq(pads.rxf_n),
+ wants_write.eq(~txe_n & write_fifo.source.stb),
+ wants_read.eq(~rxf_n & read_fifo.sink.ack),
+ ]
+
+ read_time_en, max_read_time = anti_starvation(self, read_time)
+ write_time_en, max_write_time = anti_starvation(self, write_time)
+
+ data_w_accepted = Signal(reset=1)
+
+ fsm = FSM(reset_state="READ")
+ self.submodules += RenameClockDomains(fsm, {"sys": "ftdi"})
+
+ fsm.act("READ",
+ read_time_en.eq(1),
+ If(wants_write,
+ If(~wants_read | max_read_time,
+ NextState("RTW")
+ )
+ )
+ )
+ fsm.act("RTW",
+ NextState("WRITE")
+ )
+ fsm.act("WRITE",
+ write_time_en.eq(1),
+ If(wants_read,
+ If(~wants_write | max_write_time,
+ NextState("WTR")
+ )
+ ),
+ write_fifo.source.ack.eq(wants_write & data_w_accepted)
+ )
+ fsm.act("WTR",
+ NextState("READ")
+ )
+
+ # databus tristate
+ data_w = Signal(dw)
+ data_r = Signal(dw)
+ data_oe = Signal()
+ self.specials += Tristate(pads.data, data_w, data_oe, data_r)
+
+ # read / write actions
+ pads.oe_n.reset = 1
+ pads.rd_n.reset = 1
+ pads.wr_n.reset = 1
+
+ self.sync.ftdi += [
+ If(fsm.ongoing("READ"),
+ data_oe.eq(0),
+
+ pads.oe_n.eq(0),
+ pads.rd_n.eq(~wants_read),
+ pads.wr_n.eq(1)
+
+ ).Elif(fsm.ongoing("WRITE"),
+ data_oe.eq(1),
+
+ pads.oe_n.eq(1),
+ pads.rd_n.eq(1),
+ pads.wr_n.eq(~wants_write),
+
+ data_w_accepted.eq(~txe_n)
+
+ ).Else(
+ data_oe.eq(1),
+
+ pads.oe_n.eq(~fsm.ongoing("WTR")),
+ pads.rd_n.eq(1),
+ pads.wr_n.eq(1)
+ ),
+ read_buffer.sink.stb.eq(~pads.rd_n & ~rxf_n),
+ read_buffer.sink.data.eq(data_r),
+ If(~txe_n & data_w_accepted,
+ data_w.eq(write_fifo.source.data)
+ )
+ ]
+
+
+class FT245PHYAsynchronous(Module):
+ def __init__(self, pads, clk_freq,
+ fifo_depth=32,
+ read_time=128,
+ write_time=128):
+ dw = flen(pads.data)
+ self.clk_freq = clk_freq
+
+ # timings
+ tRD = self.ns(30) # RD# active pulse width (t4)
+ tRDDataSetup = self.ns(14) # RD# to DATA (t3)
+ tWRDataSetup = self.ns(5) # DATA to WR# active setup time (t8)
+ tWR = self.ns(30) # WR# active pulse width (t10)
+ tMultiReg = 2
+
+ # read fifo (FTDI --> SoC)
+ read_fifo = SyncFIFO(phy_description(8), fifo_depth)
+
+ # write fifo (SoC --> FTDI)
+ write_fifo = SyncFIFO(phy_description(8), fifo_depth)
+
+ self.submodules += read_fifo, write_fifo
+
+ # sink / source interfaces
+ self.sink = write_fifo.sink
+ self.source = read_fifo.source
+
+ # read / write arbitration
+ wants_write = Signal()
+ wants_read = Signal()
+
+ txe_n = Signal()
+ rxf_n = Signal()
+
+ self.specials += [
+ MultiReg(pads.txe_n, txe_n),
+ MultiReg(pads.rxf_n, rxf_n)
+ ]
+
+ self.comb += [
+ wants_write.eq(~txe_n & write_fifo.source.stb),
+ wants_read.eq(~rxf_n & read_fifo.sink.ack),
+ ]
+
+ read_time_en, max_read_time = anti_starvation(self, read_time)
+ write_time_en, max_write_time = anti_starvation(self, write_time)
+
+ fsm = FSM(reset_state="READ")
+ self.submodules += fsm
+
+ read_done = Signal()
+ write_done = Signal()
+ commuting = Signal()
+
+ fsm.act("READ",
+ read_time_en.eq(1),
+ If(wants_write & read_done,
+ If(~wants_read | max_read_time,
+ commuting.eq(1),
+ NextState("RTW")
+ )
+ )
+ )
+ fsm.act("RTW",
+ NextState("WRITE")
+ )
+ fsm.act("WRITE",
+ write_time_en.eq(1),
+ If(wants_read & write_done,
+ If(~wants_write | max_write_time,
+ commuting.eq(1),
+ NextState("WTR")
+ )
+ )
+ )
+ fsm.act("WTR",
+ NextState("READ")
+ )
+
+ # databus tristate
+ data_w = Signal(dw)
+ data_r_async = Signal(dw)
+ data_r = Signal(dw)
+ data_oe = Signal()
+ self.specials += [
+ Tristate(pads.data, data_w, data_oe, data_r_async),
+ MultiReg(data_r_async, data_r)
+ ]
+
+
+ # read actions
+ pads.rd_n.reset = 1
+
+ read_fsm = FSM(reset_state="IDLE")
+ read_counter = Counter(8)
+ self.submodules += read_fsm, read_counter
+
+ read_fsm.act("IDLE",
+ read_done.eq(1),
+ read_counter.reset.eq(1),
+ If(fsm.ongoing("READ") & wants_read,
+ If(~commuting,
+ NextState("PULSE_RD_N")
+ )
+ )
+ )
+ read_fsm.act("PULSE_RD_N",
+ pads.rd_n.eq(0),
+ read_counter.ce.eq(1),
+ If(read_counter.value == max((tRD-1), (tRDDataSetup + tMultiReg -1)),
+ NextState("ACQUIRE_DATA")
+ )
+ )
+ read_fsm.act("ACQUIRE_DATA",
+ read_fifo.sink.stb.eq(1),
+ read_fifo.sink.data.eq(data_r),
+ NextState("WAIT_RXF_N")
+ )
+ read_fsm.act("WAIT_RXF_N",
+ If(rxf_n,
+ NextState("IDLE")
+ )
+ )
+
+ # write actions
+ pads.wr_n.reset = 1
+
+ write_fsm = FSM(reset_state="IDLE")
+ write_counter = Counter(8)
+ self.submodules += write_fsm, write_counter
+
+ write_fsm.act("IDLE",
+ write_done.eq(1),
+ write_counter.reset.eq(1),
+ If(fsm.ongoing("WRITE") & wants_write,
+ If(~commuting,
+ NextState("SET_DATA")
+ )
+ )
+ )
+ write_fsm.act("SET_DATA",
+ data_oe.eq(1),
+ data_w.eq(write_fifo.source.data),
+ write_counter.ce.eq(1),
+ If(write_counter.value == (tWRDataSetup-1),
+ write_counter.reset.eq(1),
+ NextState("PULSE_WR_N")
+ )
+ )
+ write_fsm.act("PULSE_WR_N",
+ data_oe.eq(1),
+ data_w.eq(write_fifo.source.data),
+ pads.wr_n.eq(0),
+ write_counter.ce.eq(1),
+ If(write_counter.value == (tWR-1),
+ NextState("WAIT_TXE_N")
+ )
+ )
+ write_fsm.act("WAIT_TXE_N",
+ If(txe_n,
+ write_fifo.source.ack.eq(1),
+ NextState("IDLE")
+ )
+ )
+
+ def ns(self, t, margin=True):
+ clk_period_ns = 1000000000/self.clk_freq
+ if margin:
+ t += clk_period_ns/2
+ return math.ceil(t/clk_period_ns)
+
+
+def FT245PHY(pads, *args, **kwargs):
+ # autodetect PHY
+ if hasattr(pads, "oe_n"):
+ return FT245PHYSynchronous(pads, *args, **kwargs)
+ else:
+ return FT245PHYAsynchronous(pads, *args, **kwargs)
CMD = PYTHONPATH=$(MSCDIR) $(PYTHON)
-ft2232h_sync_tb:
- $(CMD) ft2232h_sync_tb.py
+ft245_sync_tb:
+ $(CMD) ft245_sync_tb.py
-ft2232h_async_tb:
- $(CMD) ft2232h_async_tb.py
+ft245_async_tb:
+ $(CMD) ft245_async_tb.py
core_tb:
$(CMD) core_tb.py
+++ /dev/null
-from migen.fhdl.std import *
-from migen.flow.actor import *
-from migen.fhdl.specials import *
-
-from migen.sim.generic import run_simulation
-
-from misoclib.com.liteusb.common import *
-from misoclib.com.liteusb.phy.ft2232h import FT2232HPHYAsynchronous
-from misoclib.com.liteusb.test.common import *
-
-# XXX for now use it from liteeth to avoid duplication
-from misoclib.com.liteeth.test.common import *
-
-class FT2232HAsynchronousModel(Module, RandRun):
- def __init__(self, rd_data):
- RandRun.__init__(self, 10)
- self.rd_data = [0] + rd_data
- self.rd_idx = 0
-
- # pads
- self.data = Signal(8)
- self.rxf_n = Signal(reset=1)
- self.txe_n = Signal(reset=1)
- self.rd_n = Signal(reset=1)
- self.wr_n = Signal(reset=1)
-
- self.init = True
- self.wr_data = []
- self.wait_wr_n = False
- self.rd_done = 0
-
-
- self.data_w = Signal(8)
- self.data_r = Signal(8)
-
- self.specials += Tristate(self.data, self.data_r, ~self.rd_n, self.data_w)
-
- self.last_wr_n = 1
- self.last_rd_n = 1
-
- self.wr_delay = 0
- self.rd_delay = 0
-
- def wr_sim(self, selfp):
- if self.wr_delay:
- selfp.txe_n = 1
- self.wr_delay = self.wr_delay - 1
- else:
- if (not selfp.wr_n and self.last_wr_n) and not selfp.txe_n:
- self.wr_data.append(selfp.data_w)
- self.wr_delay = 20 # XXX FIXME
- self.last_wr_n = selfp.wr_n
-
- if self.run:
- selfp.txe_n = 0
-
- def rd_sim(self, selfp):
- if self.rd_delay:
- selfp.rxf_n = 1
- self.rd_delay = self.rd_delay - 1
- else:
- rxf_n = selfp.rxf_n
- if self.run:
- if self.rd_idx < len(self.rd_data)-1:
- self.rd_done = selfp.rxf_n
- selfp.rxf_n = 0
- else:
- selfp.rxf_n = self.rd_done
- else:
- selfp.rxf_n = self.rd_done
-
- if not selfp.rd_n and self.last_rd_n:
- if self.rd_idx < len(self.rd_data)-1:
- self.rd_idx += not rxf_n
- selfp.data_r = self.rd_data[self.rd_idx]
- self.rd_done = 1
- if selfp.rd_n and not self.last_rd_n:
- self.rd_delay = 4 # XXX FIXME
-
- self.last_rd_n = selfp.rd_n
-
- def do_simulation(self, selfp):
- RandRun.do_simulation(self, selfp)
- if self.init:
- selfp.rxf_n = 0
- self.wr_data = []
- self.init = False
- self.wr_sim(selfp)
- self.rd_sim(selfp)
-
-test_packet = [i%256 for i in range(128)]
-
-
-class TB(Module):
- def __init__(self):
- self.submodules.model = FT2232HAsynchronousModel(test_packet)
- self.submodules.phy = FT2232HPHYAsynchronous(self.model, 50000000)
-
- self.submodules.streamer = PacketStreamer(phy_description(8))
- self.submodules.streamer_randomizer = AckRandomizer(phy_description(8), level=10)
-
- self.submodules.logger_randomizer = AckRandomizer(phy_description(8), level=10)
- self.submodules.logger = PacketLogger(phy_description(8))
-
- self.comb += [
- Record.connect(self.streamer.source, self.streamer_randomizer.sink),
- self.phy.sink.stb.eq(self.streamer_randomizer.source.stb),
- self.phy.sink.data.eq(self.streamer_randomizer.source.data),
- self.streamer_randomizer.source.ack.eq(self.phy.sink.ack),
-
- self.logger_randomizer.sink.stb.eq(self.phy.source.stb),
- self.logger_randomizer.sink.data.eq(self.phy.source.data),
- self.phy.source.ack.eq(self.logger_randomizer.sink.ack),
- Record.connect(self.logger_randomizer.source, self.logger.sink)
- ]
-
- def gen_simulation(self, selfp):
- yield from self.streamer.send(Packet(test_packet))
- for i in range(4000):
- yield
- s, l, e = check(test_packet, self.model.wr_data)
- print("shift " + str(s) + " / length " + str(l) + " / errors " + str(e))
-
- s, l, e = check(test_packet, self.logger.packet)
- print("shift " + str(s) + " / length " + str(l) + " / errors " + str(e))
-
-
-def main():
- run_simulation(TB(), ncycles=8000, vcd_name="my.vcd", keep_files=True)
-
-if __name__ == "__main__":
- main()
\ No newline at end of file
+++ /dev/null
-from migen.fhdl.std import *
-from migen.flow.actor import *
-from migen.fhdl.specials import *
-
-from migen.sim.generic import run_simulation
-
-from misoclib.com.liteusb.common import *
-from misoclib.com.liteusb.phy.ft2232h import FT2232HPHYSynchronous
-from misoclib.com.liteusb.test.common import *
-
-# XXX for now use it from liteeth to avoid duplication
-from misoclib.com.liteeth.test.common import *
-
-class FT2232HSynchronousModel(Module, RandRun):
- def __init__(self, rd_data):
- RandRun.__init__(self, 10)
- self.rd_data = [0] + rd_data
- self.rd_idx = 0
-
- # pads
- self.data = Signal(8)
- self.rxf_n = Signal(reset=1)
- self.txe_n = Signal(reset=1)
- self.rd_n = Signal(reset=1)
- self.wr_n = Signal(reset=1)
- self.oe_n = Signal(reset=1)
- self.siwua = Signal()
- self.pwren_n = Signal(reset=1)
-
- self.init = True
- self.wr_data = []
- self.wait_wr_n = False
- self.rd_done = 0
-
-
- self.data_w = Signal(8)
- self.data_r = Signal(8)
-
- self.specials += Tristate(self.data, self.data_r, ~self.oe_n, self.data_w)
-
- def wr_sim(self, selfp):
- if not selfp.wr_n and not selfp.txe_n:
- self.wr_data.append(selfp.data_w)
- self.wait_wr_n = False
-
- if not self.wait_wr_n:
- if self.run:
- selfp.txe_n = 1
- else:
- if selfp.txe_n:
- self.wait_wr_n = True
- selfp.txe_n = 0
-
- def rd_sim(self, selfp):
- rxf_n = selfp.rxf_n
- if self.run:
- if self.rd_idx < len(self.rd_data)-1:
- self.rd_done = selfp.rxf_n
- selfp.rxf_n = 0
- else:
- selfp.rxf_n = self.rd_done
- else:
- selfp.rxf_n = self.rd_done
-
- if not selfp.rd_n and not selfp.oe_n:
- if self.rd_idx < len(self.rd_data)-1:
- self.rd_idx += not rxf_n
- selfp.data_r = self.rd_data[self.rd_idx]
- self.rd_done = 1
-
- def do_simulation(self, selfp):
- RandRun.do_simulation(self, selfp)
- if self.init:
- selfp.rxf_n = 0
- self.wr_data = []
- self.init = False
- self.wr_sim(selfp)
- self.rd_sim(selfp)
-
-test_packet = [i%256 for i in range(512)]
-
-
-class TB(Module):
- def __init__(self):
- self.submodules.model = FT2232HSynchronousModel(test_packet)
- self.submodules.phy = FT2232HPHYSynchronous(self.model)
-
- self.submodules.streamer = PacketStreamer(phy_description(8))
- self.submodules.streamer_randomizer = AckRandomizer(phy_description(8), level=10)
-
- self.submodules.logger_randomizer = AckRandomizer(phy_description(8), level=10)
- self.submodules.logger = PacketLogger(phy_description(8))
-
- self.comb += [
- Record.connect(self.streamer.source, self.streamer_randomizer.sink),
- self.phy.sink.stb.eq(self.streamer_randomizer.source.stb),
- self.phy.sink.data.eq(self.streamer_randomizer.source.data),
- self.streamer_randomizer.source.ack.eq(self.phy.sink.ack),
-
- self.logger_randomizer.sink.stb.eq(self.phy.source.stb),
- self.logger_randomizer.sink.data.eq(self.phy.source.data),
- self.phy.source.ack.eq(self.logger_randomizer.sink.ack),
- Record.connect(self.logger_randomizer.source, self.logger.sink)
- ]
-
- # Use sys_clk as ftdi_clk in simulation
- self.comb += [
- ClockSignal("ftdi").eq(ClockSignal()),
- ResetSignal("ftdi").eq(ResetSignal())
- ]
-
- def gen_simulation(self, selfp):
- yield from self.streamer.send(Packet(test_packet))
- for i in range(2000):
- yield
- s, l, e = check(test_packet, self.model.wr_data)
- print("shift " + str(s) + " / length " + str(l) + " / errors " + str(e))
-
- s, l, e = check(test_packet, self.logger.packet[1:])
- print("shift " + str(s) + " / length " + str(l) + " / errors " + str(e))
-
-
-def main():
- run_simulation(TB(), ncycles=8000, vcd_name="my.vcd", keep_files=True)
-
-if __name__ == "__main__":
- main()
\ No newline at end of file
--- /dev/null
+from migen.fhdl.std import *
+from migen.flow.actor import *
+from migen.fhdl.specials import *
+
+from migen.sim.generic import run_simulation
+
+from misoclib.com.liteusb.common import *
+from misoclib.com.liteusb.phy.ft245 import FT245PHYAsynchronous
+from misoclib.com.liteusb.test.common import *
+
+# XXX for now use it from liteeth to avoid duplication
+from misoclib.com.liteeth.test.common import *
+
+class FT245AsynchronousModel(Module):
+ def __init__(self, clk_freq, rd_data):
+ self.clk_freq = clk_freq
+ self.rd_data = [0] + rd_data
+ self.rd_idx = 0
+
+ # timings
+ self.tRDInactive = self.ns(49) # RXF# inactive after RD# cycle
+ self.tWRInactive = self.ns(49) # TXE# inactive after WR# cycle
+
+ # pads
+ self.data = Signal(8)
+ self.rxf_n = Signal(reset=1)
+ self.txe_n = Signal(reset=1)
+ self.rd_n = Signal(reset=1)
+ self.wr_n = Signal(reset=1)
+
+ self.init = True
+ self.wr_data = []
+ self.wait_wr_n = False
+ self.rd_done = 0
+
+
+ self.data_w = Signal(8)
+ self.data_r = Signal(8)
+
+ self.specials += Tristate(self.data, self.data_r, ~self.rd_n, self.data_w)
+
+ self.last_wr_n = 1
+ self.last_rd_n = 1
+
+ self.wr_delay = 0
+ self.rd_delay = 0
+
+ def wr_sim(self, selfp):
+ if self.wr_delay:
+ selfp.txe_n = 1
+ self.wr_delay = self.wr_delay - 1
+ else:
+ if (not selfp.wr_n and self.last_wr_n) and not selfp.txe_n:
+ self.wr_data.append(selfp.data_w)
+ self.wr_delay = self.tWRInactive
+ self.last_wr_n = selfp.wr_n
+
+ selfp.txe_n = 0
+
+ def rd_sim(self, selfp):
+ if self.rd_delay:
+ selfp.rxf_n = 1
+ self.rd_delay = self.rd_delay - 1
+ else:
+ rxf_n = selfp.rxf_n
+ if self.rd_idx < len(self.rd_data)-1:
+ self.rd_done = selfp.rxf_n
+ selfp.rxf_n = 0
+ else:
+ selfp.rxf_n = self.rd_done
+
+ if not selfp.rd_n and self.last_rd_n:
+ if self.rd_idx < len(self.rd_data)-1:
+ self.rd_idx += not rxf_n
+ selfp.data_r = self.rd_data[self.rd_idx]
+ self.rd_done = 1
+ if selfp.rd_n and not self.last_rd_n:
+ self.rd_delay = self.tRDInactive
+
+ self.last_rd_n = selfp.rd_n
+
+ def do_simulation(self, selfp):
+ if self.init:
+ selfp.rxf_n = 0
+ self.wr_data = []
+ self.init = False
+ self.wr_sim(selfp)
+ self.rd_sim(selfp)
+
+ def ns(self, t, margin=True):
+ clk_period_ns = 1000000000/self.clk_freq
+ if margin:
+ t += clk_period_ns/2
+ return math.ceil(t/clk_period_ns)
+
+
+test_packet = [i%256 for i in range(128)]
+
+
+class TB(Module):
+ def __init__(self):
+ clk_freq = 50*1000000
+ self.submodules.model = FT245AsynchronousModel(clk_freq, test_packet)
+ self.submodules.phy = FT245PHYAsynchronous(self.model, clk_freq)
+
+ self.submodules.streamer = PacketStreamer(phy_description(8))
+ self.submodules.streamer_randomizer = AckRandomizer(phy_description(8), level=10)
+
+ self.submodules.logger_randomizer = AckRandomizer(phy_description(8), level=10)
+ self.submodules.logger = PacketLogger(phy_description(8))
+
+ self.comb += [
+ Record.connect(self.streamer.source, self.streamer_randomizer.sink),
+ self.phy.sink.stb.eq(self.streamer_randomizer.source.stb),
+ self.phy.sink.data.eq(self.streamer_randomizer.source.data),
+ self.streamer_randomizer.source.ack.eq(self.phy.sink.ack),
+
+ self.logger_randomizer.sink.stb.eq(self.phy.source.stb),
+ self.logger_randomizer.sink.data.eq(self.phy.source.data),
+ self.phy.source.ack.eq(self.logger_randomizer.sink.ack),
+ Record.connect(self.logger_randomizer.source, self.logger.sink)
+ ]
+
+ def gen_simulation(self, selfp):
+ yield from self.streamer.send(Packet(test_packet))
+ for i in range(4000):
+ yield
+ s, l, e = check(test_packet, self.model.wr_data)
+ print("shift " + str(s) + " / length " + str(l) + " / errors " + str(e))
+
+ s, l, e = check(test_packet, self.logger.packet)
+ print("shift " + str(s) + " / length " + str(l) + " / errors " + str(e))
+
+
+def main():
+ run_simulation(TB(), ncycles=8000, vcd_name="my.vcd", keep_files=True)
+
+if __name__ == "__main__":
+ main()
\ No newline at end of file
--- /dev/null
+from migen.fhdl.std import *
+from migen.flow.actor import *
+from migen.fhdl.specials import *
+
+from migen.sim.generic import run_simulation
+
+from misoclib.com.liteusb.common import *
+from misoclib.com.liteusb.phy.ft245 import FT245PHYSynchronous
+from misoclib.com.liteusb.test.common import *
+
+# XXX for now use it from liteeth to avoid duplication
+from misoclib.com.liteeth.test.common import *
+
+class FT245SynchronousModel(Module, RandRun):
+ def __init__(self, rd_data):
+ RandRun.__init__(self, 10)
+ self.rd_data = [0] + rd_data
+ self.rd_idx = 0
+
+ # pads
+ self.data = Signal(8)
+ self.rxf_n = Signal(reset=1)
+ self.txe_n = Signal(reset=1)
+ self.rd_n = Signal(reset=1)
+ self.wr_n = Signal(reset=1)
+ self.oe_n = Signal(reset=1)
+ self.siwua = Signal()
+ self.pwren_n = Signal(reset=1)
+
+ self.init = True
+ self.wr_data = []
+ self.wait_wr_n = False
+ self.rd_done = 0
+
+
+ self.data_w = Signal(8)
+ self.data_r = Signal(8)
+
+ self.specials += Tristate(self.data, self.data_r, ~self.oe_n, self.data_w)
+
+ def wr_sim(self, selfp):
+ if not selfp.wr_n and not selfp.txe_n:
+ self.wr_data.append(selfp.data_w)
+ self.wait_wr_n = False
+
+ if not self.wait_wr_n:
+ if self.run:
+ selfp.txe_n = 1
+ else:
+ if selfp.txe_n:
+ self.wait_wr_n = True
+ selfp.txe_n = 0
+
+ def rd_sim(self, selfp):
+ rxf_n = selfp.rxf_n
+ if self.run:
+ if self.rd_idx < len(self.rd_data)-1:
+ self.rd_done = selfp.rxf_n
+ selfp.rxf_n = 0
+ else:
+ selfp.rxf_n = self.rd_done
+ else:
+ selfp.rxf_n = self.rd_done
+
+ if not selfp.rd_n and not selfp.oe_n:
+ if self.rd_idx < len(self.rd_data)-1:
+ self.rd_idx += not rxf_n
+ selfp.data_r = self.rd_data[self.rd_idx]
+ self.rd_done = 1
+
+ def do_simulation(self, selfp):
+ RandRun.do_simulation(self, selfp)
+ if self.init:
+ selfp.rxf_n = 0
+ self.wr_data = []
+ self.init = False
+ self.wr_sim(selfp)
+ self.rd_sim(selfp)
+
+test_packet = [i%256 for i in range(512)]
+
+
+class TB(Module):
+ def __init__(self):
+ self.submodules.model = FT245SynchronousModel(test_packet)
+ self.submodules.phy = FT245PHYSynchronous(self.model)
+
+ self.submodules.streamer = PacketStreamer(phy_description(8))
+ self.submodules.streamer_randomizer = AckRandomizer(phy_description(8), level=10)
+
+ self.submodules.logger_randomizer = AckRandomizer(phy_description(8), level=10)
+ self.submodules.logger = PacketLogger(phy_description(8))
+
+ self.comb += [
+ Record.connect(self.streamer.source, self.streamer_randomizer.sink),
+ self.phy.sink.stb.eq(self.streamer_randomizer.source.stb),
+ self.phy.sink.data.eq(self.streamer_randomizer.source.data),
+ self.streamer_randomizer.source.ack.eq(self.phy.sink.ack),
+
+ self.logger_randomizer.sink.stb.eq(self.phy.source.stb),
+ self.logger_randomizer.sink.data.eq(self.phy.source.data),
+ self.phy.source.ack.eq(self.logger_randomizer.sink.ack),
+ Record.connect(self.logger_randomizer.source, self.logger.sink)
+ ]
+
+ # Use sys_clk as ftdi_clk in simulation
+ self.comb += [
+ ClockSignal("ftdi").eq(ClockSignal()),
+ ResetSignal("ftdi").eq(ResetSignal())
+ ]
+
+ def gen_simulation(self, selfp):
+ yield from self.streamer.send(Packet(test_packet))
+ for i in range(2000):
+ yield
+ s, l, e = check(test_packet, self.model.wr_data)
+ print("shift " + str(s) + " / length " + str(l) + " / errors " + str(e))
+
+ s, l, e = check(test_packet, self.logger.packet[1:])
+ print("shift " + str(s) + " / length " + str(l) + " / errors " + str(e))
+
+
+def main():
+ run_simulation(TB(), ncycles=8000, vcd_name="my.vcd", keep_files=True)
+
+if __name__ == "__main__":
+ main()
\ No newline at end of file