liteusb: continue refactoring (virtual UART and DMA working on minispartan6)
- 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
This commit is contained in:
parent
8aa3fb3eb7
commit
603b4cdc8c
|
@ -3,6 +3,7 @@ from migen.genlib.fsm import *
|
||||||
from migen.actorlib.fifo import *
|
from migen.actorlib.fifo import *
|
||||||
from migen.flow.actor import EndpointDescription
|
from migen.flow.actor import EndpointDescription
|
||||||
from migen.actorlib.packet import *
|
from migen.actorlib.packet import *
|
||||||
|
from migen.actorlib.structuring import Pipeline
|
||||||
|
|
||||||
|
|
||||||
packet_header_length = 9
|
packet_header_length = 9
|
||||||
|
@ -49,11 +50,12 @@ class LiteUSBMasterPort:
|
||||||
|
|
||||||
|
|
||||||
class LiteUSBSlavePort:
|
class LiteUSBSlavePort:
|
||||||
def __init__(self, dw):
|
def __init__(self, dw, tag):
|
||||||
self.sink = Sink(user_description(dw))
|
self.sink = Sink(user_description(dw))
|
||||||
self.source = Source(user_description(dw))
|
self.source = Source(user_description(dw))
|
||||||
|
self.tag = tag
|
||||||
|
|
||||||
|
|
||||||
class LiteUSBUserPort(LiteUSBSlavePort):
|
class LiteUSBUserPort(LiteUSBSlavePort):
|
||||||
def __init__(self, dw):
|
def __init__(self, dw, tag):
|
||||||
LiteUSBSlavePort.__init__(self, dw)
|
LiteUSBSlavePort.__init__(self, dw, tag)
|
||||||
|
|
|
@ -3,29 +3,29 @@ from misoclib.com.liteusb.core.packet import LiteUSBPacketizer, LiteUSBDepacketi
|
||||||
from misoclib.com.liteusb.core.crc import LiteUSBCRC32Inserter, LiteUSBCRC32Checker
|
from misoclib.com.liteusb.core.crc import LiteUSBCRC32Inserter, LiteUSBCRC32Checker
|
||||||
from misoclib.com.liteusb.core.crossbar import LiteUSBCrossbar
|
from misoclib.com.liteusb.core.crossbar import LiteUSBCrossbar
|
||||||
|
|
||||||
# XXX Header should be protected by CRC
|
|
||||||
|
|
||||||
class LiteUSBCore(Module):
|
class LiteUSBCore(Module):
|
||||||
def __init__(self, phy):
|
def __init__(self, phy, clk_freq, with_crc=True):
|
||||||
|
rx_pipeline = [phy]
|
||||||
|
tx_pipeline = [phy]
|
||||||
|
|
||||||
# depacketizer / packetizer
|
# depacketizer / packetizer
|
||||||
self.submodules.depacketizer = LiteUSBDepacketizer()
|
self.submodules.depacketizer = LiteUSBDepacketizer(clk_freq)
|
||||||
self.submodules.packetizer = LiteUSBPacketizer()
|
self.submodules.packetizer = LiteUSBPacketizer()
|
||||||
self.comb += [
|
rx_pipeline += [self.depacketizer]
|
||||||
Record.connect(phy.source, self.depacketizer.sink),
|
tx_pipeline += [self.packetizer]
|
||||||
Record.connect(self.packetizer.source, phy.sink)
|
|
||||||
]
|
|
||||||
|
|
||||||
# crc checker / inserter
|
if with_crc:
|
||||||
self.submodules.crc_rx = LiteUSBCRC32Checker()
|
# crc checker / inserter
|
||||||
self.submodules.crc_tx = LiteUSBCRC32Inserter()
|
self.submodules.crc_rx = LiteUSBCRC32Checker()
|
||||||
self.comb += [
|
self.submodules.crc_tx = LiteUSBCRC32Inserter()
|
||||||
Record.connect(self.depacketizer.source, self.crc_rx.sink),
|
rx_pipeline += [self.crc_rx]
|
||||||
Record.connect(self.crc_tx.source, self.packetizer.sink)
|
tx_pipeline += [self.crc_tx]
|
||||||
]
|
|
||||||
|
|
||||||
# crossbar
|
# crossbar
|
||||||
self.submodules.crossbar = LiteUSBCrossbar()
|
self.submodules.crossbar = LiteUSBCrossbar()
|
||||||
self.comb += [
|
rx_pipeline += [self.crossbar.master]
|
||||||
Record.connect(self.crossbar.master.source, self.crc_tx.sink),
|
tx_pipeline += [self.crossbar.master]
|
||||||
Record.connect(self.crc_rx.source, self.crossbar.master.sink)
|
|
||||||
]
|
# graph
|
||||||
|
self.submodules.rx_pipeline = Pipeline(*rx_pipeline)
|
||||||
|
self.submodules.tx_pipeline = Pipeline(*reversed(tx_pipeline))
|
||||||
|
|
|
@ -9,7 +9,7 @@ class LiteUSBCrossbar(Module):
|
||||||
self.dispatch_param = "dst"
|
self.dispatch_param = "dst"
|
||||||
|
|
||||||
def get_port(self, dst):
|
def get_port(self, dst):
|
||||||
port = LiteUSBUserPort(8)
|
port = LiteUSBUserPort(8, dst)
|
||||||
if dst in self.users.keys():
|
if dst in self.users.keys():
|
||||||
raise ValueError("Destination {0:#x} already assigned".format(dst))
|
raise ValueError("Destination {0:#x} already assigned".format(dst))
|
||||||
self.users[dst] = port
|
self.users[dst] = port
|
||||||
|
|
|
@ -66,7 +66,7 @@ class LiteUSBPacketizer(Module):
|
||||||
|
|
||||||
|
|
||||||
class LiteUSBDepacketizer(Module):
|
class LiteUSBDepacketizer(Module):
|
||||||
def __init__(self, timeout=10):
|
def __init__(self, clk_freq, timeout=10):
|
||||||
self.sink = sink = Sink(phy_description(8))
|
self.sink = sink = Sink(phy_description(8))
|
||||||
self.source = source = Source(user_description(8))
|
self.source = source = Source(user_description(8))
|
||||||
|
|
||||||
|
@ -116,9 +116,9 @@ class LiteUSBDepacketizer(Module):
|
||||||
header_pack.source.ack.eq(1),
|
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.comb += [
|
||||||
self.timeout.reset.eq(fsm.ongoing("WAIT_SOP")),
|
self.timeout.reset.eq(fsm.ongoing("IDLE")),
|
||||||
self.timeout.ce.eq(1)
|
self.timeout.ce.eq(1)
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
|
@ -16,7 +16,7 @@ class LiteUSBDMAWriter(Module, AutoCSR):
|
||||||
|
|
||||||
# Pack data
|
# Pack data
|
||||||
pack_factor = lasmim.dw//8
|
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)
|
cast = structuring.Cast(pack.source.payload.layout, lasmim.dw)
|
||||||
|
|
||||||
# DMA
|
# DMA
|
||||||
|
@ -61,12 +61,12 @@ class LiteUSBDMAReader(Module, AutoCSR):
|
||||||
pack_factor = lasmim.dw//8
|
pack_factor = lasmim.dw//8
|
||||||
packed_dat = structuring.pack_layout(8, pack_factor)
|
packed_dat = structuring.pack_layout(8, pack_factor)
|
||||||
cast = structuring.Cast(lasmim.dw, packed_dat)
|
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
|
# Graph
|
||||||
cnt = Signal(32)
|
cnt = Signal(32)
|
||||||
self.sync += \
|
self.sync += \
|
||||||
If(self.dma.generator._r_shoot.re,
|
If(self.dma.generator._shoot.re,
|
||||||
cnt.eq(0)
|
cnt.eq(0)
|
||||||
).Elif(source.stb & source.ack,
|
).Elif(source.stb & source.ack,
|
||||||
cnt.eq(cnt + 1)
|
cnt.eq(cnt + 1)
|
||||||
|
@ -92,12 +92,11 @@ class LiteUSBDMAReader(Module, AutoCSR):
|
||||||
|
|
||||||
|
|
||||||
class LiteUSBDMA(Module, AutoCSR):
|
class LiteUSBDMA(Module, AutoCSR):
|
||||||
def __init__(self, lasmim_dma_wr, lasmim_dma_rd, tag):
|
def __init__(self, port, lasmim_dma_wr, lasmim_dma_rd):
|
||||||
self.tag = tag
|
|
||||||
|
|
||||||
self.submodules.writer = LiteUSBDMAWriter(lasmim_dma_wr)
|
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.submodules.ev = SharedIRQ(self.writer.ev, self.reader.ev)
|
||||||
|
self.comb += [
|
||||||
self.sink = self.writer.sink
|
Record.connect(port.source, self.writer.sink),
|
||||||
self.source = self.reader.source
|
Record.connect(self.reader.source, port.sink),
|
||||||
|
]
|
||||||
|
|
|
@ -1,59 +1,35 @@
|
||||||
from migen.fhdl.std import *
|
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.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):
|
class LiteUSBUART(UART):
|
||||||
def __init__(self, tag, fifo_depth=64):
|
def __init__(self, port,
|
||||||
self.tag = tag
|
tx_fifo_depth=16,
|
||||||
|
rx_fifo_depth=16):
|
||||||
|
|
||||||
self._rxtx = CSR(8)
|
phy = LiteUSBUARTPHY()
|
||||||
|
UART.__init__(self, phy, tx_fifo_depth, rx_fifo_depth)
|
||||||
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))
|
|
||||||
|
|
||||||
# # #
|
|
||||||
|
|
||||||
# TX
|
# 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 += [
|
self.comb += [
|
||||||
source.sop.eq(1),
|
port.sink.stb.eq(phy.sink.stb),
|
||||||
source.eop.eq(1),
|
port.sink.sop.eq(1),
|
||||||
source.length.eq(1),
|
port.sink.eop.eq(1),
|
||||||
source.dst.eq(self.tag),
|
port.sink.length.eq(1),
|
||||||
tx_done.eq(source.stb & source.ack),
|
port.sink.dst.eq(port.tag),
|
||||||
|
port.sink.data.eq(phy.sink.data),
|
||||||
|
phy.sink.ack.eq(port.sink.ack)
|
||||||
]
|
]
|
||||||
|
|
||||||
# RX
|
# RX
|
||||||
rx_available = self.ev.rx.trigger
|
|
||||||
|
|
||||||
rx_fifo = SyncFIFO(8, fifo_depth)
|
|
||||||
self.submodules += rx_fifo
|
|
||||||
self.comb += [
|
self.comb += [
|
||||||
Record.connect(sink, rx_fifo.sink),
|
phy.source.stb.eq(port.source.stb),
|
||||||
|
phy.source.data.eq(port.source.data),
|
||||||
rx_fifo.we.eq(sink.stb),
|
port.source.ack.eq(phy.source.ack)
|
||||||
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)
|
|
||||||
]
|
]
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
import math
|
||||||
|
|
||||||
from migen.fhdl.std import *
|
from migen.fhdl.std import *
|
||||||
from migen.flow.actor import *
|
from migen.flow.actor import *
|
||||||
from migen.actorlib.fifo import SyncFIFO, AsyncFIFO
|
from migen.actorlib.fifo import SyncFIFO, AsyncFIFO
|
||||||
|
@ -24,39 +26,31 @@ def anti_starvation(module, timeout):
|
||||||
return en, max_time
|
return en, max_time
|
||||||
|
|
||||||
|
|
||||||
class FT2232HPHYSynchronous(Module):
|
class FT245PHYSynchronous(Module):
|
||||||
def __init__(self, pads,
|
def __init__(self, pads, clk_freq,
|
||||||
fifo_depth=32,
|
fifo_depth=32,
|
||||||
read_time=16,
|
read_time=128,
|
||||||
write_time=16):
|
write_time=128):
|
||||||
dw = flen(pads.data)
|
dw = flen(pads.data)
|
||||||
|
|
||||||
#
|
# read fifo (FTDI --> SoC)
|
||||||
# Read / Write Fifos
|
|
||||||
#
|
|
||||||
|
|
||||||
# Read Fifo (Ftdi --> SoC)
|
|
||||||
read_fifo = RenameClockDomains(AsyncFIFO(phy_description(8), fifo_depth),
|
read_fifo = RenameClockDomains(AsyncFIFO(phy_description(8), fifo_depth),
|
||||||
{"write": "ftdi", "read": "sys"})
|
{"write": "ftdi", "read": "sys"})
|
||||||
read_buffer = RenameClockDomains(SyncFIFO(phy_description(8), 4),
|
read_buffer = RenameClockDomains(SyncFIFO(phy_description(8), 4),
|
||||||
{"sys": "ftdi"})
|
{"sys": "ftdi"})
|
||||||
self.comb += read_buffer.source.connect(read_fifo.sink)
|
self.comb += read_buffer.source.connect(read_fifo.sink)
|
||||||
|
|
||||||
# Write Fifo (SoC --> Ftdi)
|
# write fifo (SoC --> FTDI)
|
||||||
write_fifo = RenameClockDomains(AsyncFIFO(phy_description(8), fifo_depth),
|
write_fifo = RenameClockDomains(AsyncFIFO(phy_description(8), fifo_depth),
|
||||||
{"write": "sys", "read": "ftdi"})
|
{"write": "sys", "read": "ftdi"})
|
||||||
|
|
||||||
self.submodules += read_fifo, read_buffer, write_fifo
|
self.submodules += read_fifo, read_buffer, write_fifo
|
||||||
|
|
||||||
#
|
# sink / source interfaces
|
||||||
# Sink / Source interfaces
|
|
||||||
#
|
|
||||||
self.sink = write_fifo.sink
|
self.sink = write_fifo.sink
|
||||||
self.source = read_fifo.source
|
self.source = read_fifo.source
|
||||||
|
|
||||||
#
|
# read / write arbitration
|
||||||
# Read / Write Arbitration
|
|
||||||
#
|
|
||||||
wants_write = Signal()
|
wants_write = Signal()
|
||||||
wants_read = Signal()
|
wants_read = Signal()
|
||||||
|
|
||||||
|
@ -102,14 +96,13 @@ class FT2232HPHYSynchronous(Module):
|
||||||
NextState("READ")
|
NextState("READ")
|
||||||
)
|
)
|
||||||
|
|
||||||
#
|
# databus tristate
|
||||||
# Read / Write Actions
|
|
||||||
#
|
|
||||||
|
|
||||||
data_w = Signal(dw)
|
data_w = Signal(dw)
|
||||||
data_r = Signal(dw)
|
data_r = Signal(dw)
|
||||||
data_oe = Signal()
|
data_oe = Signal()
|
||||||
|
self.specials += Tristate(pads.data, data_w, data_oe, data_r)
|
||||||
|
|
||||||
|
# read / write actions
|
||||||
pads.oe_n.reset = 1
|
pads.oe_n.reset = 1
|
||||||
pads.rd_n.reset = 1
|
pads.rd_n.reset = 1
|
||||||
pads.wr_n.reset = 1
|
pads.wr_n.reset = 1
|
||||||
|
@ -145,43 +138,35 @@ class FT2232HPHYSynchronous(Module):
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
|
|
||||||
#
|
|
||||||
# Databus Tristate
|
|
||||||
#
|
|
||||||
self.specials += Tristate(pads.data, data_w, data_oe, data_r)
|
|
||||||
|
|
||||||
self.debug = Signal(8)
|
class FT245PHYAsynchronous(Module):
|
||||||
self.comb += self.debug.eq(data_r)
|
|
||||||
|
|
||||||
|
|
||||||
class FT2232HPHYAsynchronous(Module):
|
|
||||||
def __init__(self, pads, clk_freq,
|
def __init__(self, pads, clk_freq,
|
||||||
fifo_depth=32,
|
fifo_depth=32,
|
||||||
read_time=16,
|
read_time=128,
|
||||||
write_time=16):
|
write_time=128):
|
||||||
dw = flen(pads.data)
|
dw = flen(pads.data)
|
||||||
|
self.clk_freq = clk_freq
|
||||||
|
|
||||||
#
|
# timings
|
||||||
# Read / Write Fifos
|
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 (FTDI --> SoC)
|
||||||
read_fifo = SyncFIFO(phy_description(8), fifo_depth)
|
read_fifo = SyncFIFO(phy_description(8), fifo_depth)
|
||||||
|
|
||||||
# Write Fifo (SoC --> Ftdi)
|
# write fifo (SoC --> FTDI)
|
||||||
write_fifo = SyncFIFO(phy_description(8), fifo_depth)
|
write_fifo = SyncFIFO(phy_description(8), fifo_depth)
|
||||||
|
|
||||||
self.submodules += read_fifo, write_fifo
|
self.submodules += read_fifo, write_fifo
|
||||||
|
|
||||||
#
|
# sink / source interfaces
|
||||||
# Sink / Source interfaces
|
|
||||||
#
|
|
||||||
self.sink = write_fifo.sink
|
self.sink = write_fifo.sink
|
||||||
self.source = read_fifo.source
|
self.source = read_fifo.source
|
||||||
|
|
||||||
#
|
# read / write arbitration
|
||||||
# Read / Write Arbitration
|
|
||||||
#
|
|
||||||
wants_write = Signal()
|
wants_write = Signal()
|
||||||
wants_read = Signal()
|
wants_read = Signal()
|
||||||
|
|
||||||
|
@ -233,9 +218,7 @@ class FT2232HPHYAsynchronous(Module):
|
||||||
NextState("READ")
|
NextState("READ")
|
||||||
)
|
)
|
||||||
|
|
||||||
#
|
# databus tristate
|
||||||
# Databus Tristate
|
|
||||||
#
|
|
||||||
data_w = Signal(dw)
|
data_w = Signal(dw)
|
||||||
data_r_async = Signal(dw)
|
data_r_async = Signal(dw)
|
||||||
data_r = Signal(dw)
|
data_r = Signal(dw)
|
||||||
|
@ -245,10 +228,8 @@ class FT2232HPHYAsynchronous(Module):
|
||||||
MultiReg(data_r_async, data_r)
|
MultiReg(data_r_async, data_r)
|
||||||
]
|
]
|
||||||
|
|
||||||
#
|
|
||||||
# Read / Write Actions
|
# read actions
|
||||||
#
|
|
||||||
pads.wr_n.reset = 1
|
|
||||||
pads.rd_n.reset = 1
|
pads.rd_n.reset = 1
|
||||||
|
|
||||||
read_fsm = FSM(reset_state="IDLE")
|
read_fsm = FSM(reset_state="IDLE")
|
||||||
|
@ -267,7 +248,7 @@ class FT2232HPHYAsynchronous(Module):
|
||||||
read_fsm.act("PULSE_RD_N",
|
read_fsm.act("PULSE_RD_N",
|
||||||
pads.rd_n.eq(0),
|
pads.rd_n.eq(0),
|
||||||
read_counter.ce.eq(1),
|
read_counter.ce.eq(1),
|
||||||
If(read_counter.value == 15, # XXX Compute exact value
|
If(read_counter.value == max((tRD-1), (tRDDataSetup + tMultiReg -1)),
|
||||||
NextState("ACQUIRE_DATA")
|
NextState("ACQUIRE_DATA")
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
@ -282,6 +263,9 @@ class FT2232HPHYAsynchronous(Module):
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# write actions
|
||||||
|
pads.wr_n.reset = 1
|
||||||
|
|
||||||
write_fsm = FSM(reset_state="IDLE")
|
write_fsm = FSM(reset_state="IDLE")
|
||||||
write_counter = Counter(8)
|
write_counter = Counter(8)
|
||||||
self.submodules += write_fsm, write_counter
|
self.submodules += write_fsm, write_counter
|
||||||
|
@ -299,7 +283,7 @@ class FT2232HPHYAsynchronous(Module):
|
||||||
data_oe.eq(1),
|
data_oe.eq(1),
|
||||||
data_w.eq(write_fifo.source.data),
|
data_w.eq(write_fifo.source.data),
|
||||||
write_counter.ce.eq(1),
|
write_counter.ce.eq(1),
|
||||||
If(write_counter.value == 5, # XXX Compute exact value
|
If(write_counter.value == (tWRDataSetup-1),
|
||||||
write_counter.reset.eq(1),
|
write_counter.reset.eq(1),
|
||||||
NextState("PULSE_WR_N")
|
NextState("PULSE_WR_N")
|
||||||
)
|
)
|
||||||
|
@ -309,7 +293,7 @@ class FT2232HPHYAsynchronous(Module):
|
||||||
data_w.eq(write_fifo.source.data),
|
data_w.eq(write_fifo.source.data),
|
||||||
pads.wr_n.eq(0),
|
pads.wr_n.eq(0),
|
||||||
write_counter.ce.eq(1),
|
write_counter.ce.eq(1),
|
||||||
If(write_counter.value == 15, # XXX Compute exact value
|
If(write_counter.value == (tWR-1),
|
||||||
NextState("WAIT_TXE_N")
|
NextState("WAIT_TXE_N")
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
@ -319,3 +303,17 @@ class FT2232HPHYAsynchronous(Module):
|
||||||
NextState("IDLE")
|
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)
|
|
@ -3,11 +3,11 @@ PYTHON = python3
|
||||||
|
|
||||||
CMD = PYTHONPATH=$(MSCDIR) $(PYTHON)
|
CMD = PYTHONPATH=$(MSCDIR) $(PYTHON)
|
||||||
|
|
||||||
ft2232h_sync_tb:
|
ft245_sync_tb:
|
||||||
$(CMD) ft2232h_sync_tb.py
|
$(CMD) ft245_sync_tb.py
|
||||||
|
|
||||||
ft2232h_async_tb:
|
ft245_async_tb:
|
||||||
$(CMD) ft2232h_async_tb.py
|
$(CMD) ft245_async_tb.py
|
||||||
|
|
||||||
core_tb:
|
core_tb:
|
||||||
$(CMD) core_tb.py
|
$(CMD) core_tb.py
|
||||||
|
|
|
@ -5,18 +5,22 @@ from migen.fhdl.specials import *
|
||||||
from migen.sim.generic import run_simulation
|
from migen.sim.generic import run_simulation
|
||||||
|
|
||||||
from misoclib.com.liteusb.common import *
|
from misoclib.com.liteusb.common import *
|
||||||
from misoclib.com.liteusb.phy.ft2232h import FT2232HPHYAsynchronous
|
from misoclib.com.liteusb.phy.ft245 import FT245PHYAsynchronous
|
||||||
from misoclib.com.liteusb.test.common import *
|
from misoclib.com.liteusb.test.common import *
|
||||||
|
|
||||||
# XXX for now use it from liteeth to avoid duplication
|
# XXX for now use it from liteeth to avoid duplication
|
||||||
from misoclib.com.liteeth.test.common import *
|
from misoclib.com.liteeth.test.common import *
|
||||||
|
|
||||||
class FT2232HAsynchronousModel(Module, RandRun):
|
class FT245AsynchronousModel(Module):
|
||||||
def __init__(self, rd_data):
|
def __init__(self, clk_freq, rd_data):
|
||||||
RandRun.__init__(self, 10)
|
self.clk_freq = clk_freq
|
||||||
self.rd_data = [0] + rd_data
|
self.rd_data = [0] + rd_data
|
||||||
self.rd_idx = 0
|
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
|
# pads
|
||||||
self.data = Signal(8)
|
self.data = Signal(8)
|
||||||
self.rxf_n = Signal(reset=1)
|
self.rxf_n = Signal(reset=1)
|
||||||
|
@ -48,11 +52,10 @@ class FT2232HAsynchronousModel(Module, RandRun):
|
||||||
else:
|
else:
|
||||||
if (not selfp.wr_n and self.last_wr_n) and not selfp.txe_n:
|
if (not selfp.wr_n and self.last_wr_n) and not selfp.txe_n:
|
||||||
self.wr_data.append(selfp.data_w)
|
self.wr_data.append(selfp.data_w)
|
||||||
self.wr_delay = 20 # XXX FIXME
|
self.wr_delay = self.tWRInactive
|
||||||
self.last_wr_n = selfp.wr_n
|
self.last_wr_n = selfp.wr_n
|
||||||
|
|
||||||
if self.run:
|
selfp.txe_n = 0
|
||||||
selfp.txe_n = 0
|
|
||||||
|
|
||||||
def rd_sim(self, selfp):
|
def rd_sim(self, selfp):
|
||||||
if self.rd_delay:
|
if self.rd_delay:
|
||||||
|
@ -60,12 +63,9 @@ class FT2232HAsynchronousModel(Module, RandRun):
|
||||||
self.rd_delay = self.rd_delay - 1
|
self.rd_delay = self.rd_delay - 1
|
||||||
else:
|
else:
|
||||||
rxf_n = selfp.rxf_n
|
rxf_n = selfp.rxf_n
|
||||||
if self.run:
|
if self.rd_idx < len(self.rd_data)-1:
|
||||||
if self.rd_idx < len(self.rd_data)-1:
|
self.rd_done = selfp.rxf_n
|
||||||
self.rd_done = selfp.rxf_n
|
selfp.rxf_n = 0
|
||||||
selfp.rxf_n = 0
|
|
||||||
else:
|
|
||||||
selfp.rxf_n = self.rd_done
|
|
||||||
else:
|
else:
|
||||||
selfp.rxf_n = self.rd_done
|
selfp.rxf_n = self.rd_done
|
||||||
|
|
||||||
|
@ -75,12 +75,11 @@ class FT2232HAsynchronousModel(Module, RandRun):
|
||||||
selfp.data_r = self.rd_data[self.rd_idx]
|
selfp.data_r = self.rd_data[self.rd_idx]
|
||||||
self.rd_done = 1
|
self.rd_done = 1
|
||||||
if selfp.rd_n and not self.last_rd_n:
|
if selfp.rd_n and not self.last_rd_n:
|
||||||
self.rd_delay = 4 # XXX FIXME
|
self.rd_delay = self.tRDInactive
|
||||||
|
|
||||||
self.last_rd_n = selfp.rd_n
|
self.last_rd_n = selfp.rd_n
|
||||||
|
|
||||||
def do_simulation(self, selfp):
|
def do_simulation(self, selfp):
|
||||||
RandRun.do_simulation(self, selfp)
|
|
||||||
if self.init:
|
if self.init:
|
||||||
selfp.rxf_n = 0
|
selfp.rxf_n = 0
|
||||||
self.wr_data = []
|
self.wr_data = []
|
||||||
|
@ -88,13 +87,21 @@ class FT2232HAsynchronousModel(Module, RandRun):
|
||||||
self.wr_sim(selfp)
|
self.wr_sim(selfp)
|
||||||
self.rd_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)]
|
test_packet = [i%256 for i in range(128)]
|
||||||
|
|
||||||
|
|
||||||
class TB(Module):
|
class TB(Module):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.submodules.model = FT2232HAsynchronousModel(test_packet)
|
clk_freq = 50*1000000
|
||||||
self.submodules.phy = FT2232HPHYAsynchronous(self.model, 50000000)
|
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 = PacketStreamer(phy_description(8))
|
||||||
self.submodules.streamer_randomizer = AckRandomizer(phy_description(8), level=10)
|
self.submodules.streamer_randomizer = AckRandomizer(phy_description(8), level=10)
|
|
@ -5,13 +5,13 @@ from migen.fhdl.specials import *
|
||||||
from migen.sim.generic import run_simulation
|
from migen.sim.generic import run_simulation
|
||||||
|
|
||||||
from misoclib.com.liteusb.common import *
|
from misoclib.com.liteusb.common import *
|
||||||
from misoclib.com.liteusb.phy.ft2232h import FT2232HPHYSynchronous
|
from misoclib.com.liteusb.phy.ft245 import FT245PHYSynchronous
|
||||||
from misoclib.com.liteusb.test.common import *
|
from misoclib.com.liteusb.test.common import *
|
||||||
|
|
||||||
# XXX for now use it from liteeth to avoid duplication
|
# XXX for now use it from liteeth to avoid duplication
|
||||||
from misoclib.com.liteeth.test.common import *
|
from misoclib.com.liteeth.test.common import *
|
||||||
|
|
||||||
class FT2232HSynchronousModel(Module, RandRun):
|
class FT245SynchronousModel(Module, RandRun):
|
||||||
def __init__(self, rd_data):
|
def __init__(self, rd_data):
|
||||||
RandRun.__init__(self, 10)
|
RandRun.__init__(self, 10)
|
||||||
self.rd_data = [0] + rd_data
|
self.rd_data = [0] + rd_data
|
||||||
|
@ -82,8 +82,8 @@ test_packet = [i%256 for i in range(512)]
|
||||||
|
|
||||||
class TB(Module):
|
class TB(Module):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.submodules.model = FT2232HSynchronousModel(test_packet)
|
self.submodules.model = FT245SynchronousModel(test_packet)
|
||||||
self.submodules.phy = FT2232HPHYSynchronous(self.model)
|
self.submodules.phy = FT245PHYSynchronous(self.model)
|
||||||
|
|
||||||
self.submodules.streamer = PacketStreamer(phy_description(8))
|
self.submodules.streamer = PacketStreamer(phy_description(8))
|
||||||
self.submodules.streamer_randomizer = AckRandomizer(phy_description(8), level=10)
|
self.submodules.streamer_randomizer = AckRandomizer(phy_description(8), level=10)
|
Loading…
Reference in New Issue