d656eca341005b75628f352134f73861017ec406
[litex.git] / misoclib / com / liteusb / frontend / dma.py
1 from migen.fhdl.std import *
2 from migen.flow.actor import *
3 from migen.flow.network import *
4 from migen.actorlib import structuring, spi
5 from migen.bank.description import *
6 from migen.bank.eventmanager import *
7 from migen.genlib.record import Record
8
9 from misoclib.mem.sdram.frontend import dma_lasmi
10 from misoclib.com.liteusb.common import *
11
12
13 class LiteUSBDMAWriter(Module, AutoCSR):
14 def __init__(self, lasmim):
15 self.sink = sink = Sink(user_description(8))
16
17 # Pack data
18 pack_factor = lasmim.dw//8
19 pack = structuring.Pack(phy_description(8), pack_factor, reverse=True)
20 cast = structuring.Cast(pack.source.payload.layout, lasmim.dw)
21
22 # DMA
23 writer = dma_lasmi.Writer(lasmim)
24 self._reset = CSR()
25 self.dma = InsertReset(spi.DMAWriteController(writer, mode=spi.MODE_SINGLE_SHOT))
26 self.comb += self.dma.reset.eq(self._reset.r & self._reset.re)
27
28 # Remove sop/eop/length/dst fields from payload
29 self.comb += [
30 pack.sink.stb.eq(sink.stb),
31 pack.sink.payload.eq(sink.payload),
32 sink.ack.eq(pack.sink.ack)
33 ]
34
35 # Graph
36 g = DataFlowGraph()
37 g.add_pipeline(pack, cast, self.dma)
38 self.submodules += CompositeActor(g)
39
40 # IRQ
41 self.submodules.ev = EventManager()
42 self.ev.done = EventSourcePulse()
43 self.ev.finalize()
44 self.comb += self.ev.done.trigger.eq(sink.stb & sink.eop)
45
46 # CRC
47 self._crc_failed = CSRStatus()
48 self.sync += \
49 If(sink.stb & sink.eop,
50 self._crc_failed.status.eq(sink.error)
51 )
52
53
54 class LiteUSBDMAReader(Module, AutoCSR):
55 def __init__(self, lasmim, tag):
56 self.source = source = Source(user_description(8))
57
58 reader = dma_lasmi.Reader(lasmim)
59 self.dma = spi.DMAReadController(reader, mode=spi.MODE_SINGLE_SHOT)
60
61 pack_factor = lasmim.dw//8
62 packed_dat = structuring.pack_layout(8, pack_factor)
63 cast = structuring.Cast(lasmim.dw, packed_dat)
64 unpack = structuring.Unpack(pack_factor, phy_description(8), reverse=True)
65
66 # Graph
67 cnt = Signal(32)
68 self.sync += \
69 If(self.dma.generator._shoot.re,
70 cnt.eq(0)
71 ).Elif(source.stb & source.ack,
72 cnt.eq(cnt + 1)
73 )
74 g = DataFlowGraph()
75 g.add_pipeline(self.dma, cast, unpack)
76 self.submodules += CompositeActor(g)
77 self.comb += [
78 source.stb.eq(unpack.source.stb),
79 source.sop.eq(cnt == 0),
80 source.eop.eq(cnt == (self.dma.length*pack_factor-1)),
81 source.length.eq(self.dma.length*pack_factor),
82 source.data.eq(unpack.source.data),
83 source.dst.eq(tag),
84 unpack.source.ack.eq(source.ack)
85 ]
86
87 # IRQ
88 self.submodules.ev = EventManager()
89 self.ev.done = EventSourcePulse()
90 self.ev.finalize()
91 self.comb += self.ev.done.trigger.eq(source.stb & source.eop)
92
93
94 class LiteUSBDMA(Module, AutoCSR):
95 def __init__(self, port, lasmim_dma_wr, lasmim_dma_rd):
96 self.submodules.writer = LiteUSBDMAWriter(lasmim_dma_wr)
97 self.submodules.reader = LiteUSBDMAReader(lasmim_dma_rd, port.tag)
98 self.submodules.ev = SharedIRQ(self.writer.ev, self.reader.ev)
99 self.comb += [
100 Record.connect(port.source, self.writer.sink),
101 Record.connect(self.reader.source, port.sink),
102 ]