dvisampler: mostly working, very basic and slightly buggy DMA
authorSebastien Bourdeauducq <sebastien@milkymist.org>
Mon, 6 May 2013 07:58:12 +0000 (09:58 +0200)
committerSebastien Bourdeauducq <sebastien@milkymist.org>
Mon, 6 May 2013 07:58:12 +0000 (09:58 +0200)
milkymist/dvisampler/__init__.py
milkymist/dvisampler/analysis.py [new file with mode: 0644]
milkymist/dvisampler/common.py
milkymist/dvisampler/debug.py [new file with mode: 0644]
milkymist/dvisampler/dma.py [new file with mode: 0644]
milkymist/dvisampler/resdetection.py [deleted file]
milkymist/dvisampler/syncpol.py [deleted file]
top.py

index 7858edc5f9330c9ecfe9ebbadc2f4b11dd9867e0..16ab0715bb25d2328f7a88790f727239f4e0bc87 100644 (file)
@@ -1,8 +1,6 @@
 from migen.fhdl.structure import *
 from migen.fhdl.module import Module
-from migen.bank.description import *
-from migen.genlib.fifo import AsyncFIFO
-from migen.actorlib import structuring, dma_asmi, spi
+from migen.bank.description import AutoCSR
 
 from milkymist.dvisampler.edid import EDID
 from milkymist.dvisampler.clocking import Clocking
@@ -10,11 +8,11 @@ from milkymist.dvisampler.datacapture import DataCapture
 from milkymist.dvisampler.charsync import CharSync
 from milkymist.dvisampler.decoding import Decoding
 from milkymist.dvisampler.chansync import ChanSync
-from milkymist.dvisampler.syncpol import SyncPolarity
-from milkymist.dvisampler.resdetection import ResolutionDetection
+from milkymist.dvisampler.analysis import SyncPolarity, ResolutionDetection, FrameExtraction
+from milkymist.dvisampler.dma import DMA
 
 class DVISampler(Module, AutoCSR):
-       def __init__(self, pads):
+       def __init__(self, pads, asmiport):
                self.submodules.edid = EDID(pads)
                self.submodules.clocking = Clocking(pads)
 
@@ -54,6 +52,8 @@ class DVISampler(Module, AutoCSR):
                        self.chansync.data_in2.eq(self.data2_decod.output),
                ]
 
+               ###
+
                self.submodules.syncpol = SyncPolarity()
                self.comb += [
                        self.syncpol.valid_i.eq(self.chansync.chan_synced),
@@ -64,42 +64,20 @@ class DVISampler(Module, AutoCSR):
 
                self.submodules.resdetection = ResolutionDetection()
                self.comb += [
+                       self.resdetection.valid_i.eq(self.syncpol.valid_o),
                        self.resdetection.de.eq(self.syncpol.de),
                        self.resdetection.vsync.eq(self.syncpol.vsync)
                ]
 
-class RawDVISampler(Module, AutoCSR):
-       def __init__(self, pads, asmiport):
-               self.submodules.edid = EDID(pads)
-               self.submodules.clocking = Clocking(pads)
-
-               invert = False
-               try:
-                       s = getattr(pads, "data0")
-               except AttributeError:
-                       s = getattr(pads, "data0_n")
-                       invert = True
-               self.submodules.data0_cap = DataCapture(8, invert)
+               self.submodules.frame = FrameExtraction()
                self.comb += [
-                       self.data0_cap.pad.eq(s),
-                       self.data0_cap.serdesstrobe.eq(self.clocking.serdesstrobe)
+                       self.frame.valid_i.eq(self.syncpol.valid_o),
+                       self.frame.de.eq(self.syncpol.de),
+                       self.frame.vsync.eq(self.syncpol.vsync),
+                       self.frame.r.eq(self.syncpol.r),
+                       self.frame.g.eq(self.syncpol.g),
+                       self.frame.b.eq(self.syncpol.b)
                ]
 
-               fifo = AsyncFIFO(10, 1024)
-               self.add_submodule(fifo, {"write": "pix", "read": "sys"})
-               self.comb += [
-                       fifo.din.eq(self.data0_cap.d),
-                       fifo.we.eq(1)
-               ]
-
-               pack_factor = asmiport.hub.dw//16
-               self.submodules.packer = structuring.Pack([("word", 10), ("pad", 6)], pack_factor)
-               self.submodules.cast = structuring.Cast(self.packer.source.payload.layout, asmiport.hub.dw)
-               self.submodules.dma = spi.DMAWriteController(dma_asmi.Writer(asmiport), spi.MODE_SINGLE_SHOT)
-               self.comb += [
-                       self.packer.sink.stb.eq(fifo.readable),
-                       fifo.re.eq(self.packer.sink.ack),
-                       self.packer.sink.payload.word.eq(fifo.dout),
-                       self.packer.source.connect(self.cast.sink, match_by_position=True),
-                       self.cast.source.connect(self.dma.data, match_by_position=True)
-               ]
+               self.submodules.dma = DMA(asmiport)
+               self.comb += self.frame.frame.connect(self.dma.frame)
diff --git a/milkymist/dvisampler/analysis.py b/milkymist/dvisampler/analysis.py
new file mode 100644 (file)
index 0000000..4361f0a
--- /dev/null
@@ -0,0 +1,148 @@
+from migen.fhdl.structure import *
+from migen.fhdl.module import Module
+from migen.genlib.cdc import MultiReg
+from migen.genlib.fifo import AsyncFIFO
+from migen.genlib.record import Record
+from migen.bank.description import *
+from migen.flow.actor import *
+
+from milkymist.dvisampler.common import channel_layout, frame_layout
+
+class SyncPolarity(Module):
+       def __init__(self):
+               self.valid_i = Signal()
+               self.data_in0 = Record(channel_layout)
+               self.data_in1 = Record(channel_layout)
+               self.data_in2 = Record(channel_layout)
+
+               self.valid_o = Signal()
+               self.de = Signal()
+               self.hsync = Signal()
+               self.vsync = Signal()
+               self.r = Signal(8)
+               self.g = Signal(8)
+               self.b = Signal(8)
+
+               ###
+
+               de = self.data_in0.de
+               de_r = Signal()
+               c = self.data_in0.c
+               c_polarity = Signal(2)
+               c_out = Signal(2)
+
+               self.comb += [
+                       self.de.eq(de_r),
+                       self.hsync.eq(c_out[0]),
+                       self.vsync.eq(c_out[1])
+               ]
+
+               self.sync.pix += [
+                       self.valid_o.eq(self.valid_i),
+                       self.r.eq(self.data_in2.d),
+                       self.g.eq(self.data_in1.d),
+                       self.b.eq(self.data_in0.d),
+
+                       de_r.eq(de),
+                       If(de_r & ~de,
+                               c_polarity.eq(c),
+                               c_out.eq(0)
+                       ).Else(
+                               c_out.eq(c ^ c_polarity)
+                       )
+               ]
+
+class ResolutionDetection(Module, AutoCSR):
+       def __init__(self, nbits=11):
+               self.valid_i = Signal()
+               self.vsync = Signal()
+               self.de = Signal()
+
+               self._hres = CSRStatus(nbits)
+               self._vres = CSRStatus(nbits)
+
+               ###
+
+               # Detect DE transitions
+               de_r = Signal()
+               pn_de = Signal()
+               self.sync.pix += de_r.eq(self.de)
+               self.comb += pn_de.eq(~self.de & de_r)
+
+               # HRES
+               hcounter = Signal(nbits)
+               self.sync.pix += If(self.valid_i & self.de,
+                               hcounter.eq(hcounter + 1)
+                       ).Else(
+                               hcounter.eq(0)
+                       )
+
+               hcounter_st = Signal(nbits)
+               self.sync.pix += If(self.valid_i,
+                               If(pn_de, hcounter_st.eq(hcounter))
+                       ).Else(
+                               hcounter_st.eq(0)
+                       )
+               self.specials += MultiReg(hcounter_st, self._hres.status)
+
+               # VRES
+               vsync_r = Signal()
+               p_vsync = Signal()
+               self.sync.pix += vsync_r.eq(self.vsync),
+               self.comb += p_vsync.eq(self.vsync & ~vsync_r)
+
+               vcounter = Signal(nbits)
+               self.sync.pix += If(self.valid_i & p_vsync,
+                               vcounter.eq(0)
+                       ).Elif(pn_de,
+                               vcounter.eq(vcounter + 1)
+                       )
+
+               vcounter_st = Signal(nbits)
+               self.sync.pix += If(self.valid_i,
+                               If(p_vsync, vcounter_st.eq(vcounter))
+                       ).Else(
+                               vcounter_st.eq(0)
+                       )
+               self.specials += MultiReg(vcounter_st, self._vres.status)
+
+class FrameExtraction(Module):
+       def __init__(self):
+               # in pix clock domain
+               self.valid_i = Signal()
+               self.vsync = Signal()
+               self.de = Signal()
+               self.r = Signal(8)
+               self.g = Signal(8)
+               self.b = Signal(8)
+
+               # in sys clock domain
+               self.frame = Source(frame_layout)
+               self.busy = Signal()
+
+               ###
+
+               fifo_stb = Signal()
+               fifo_in = Record(frame_layout)
+               self.comb += [
+                       fifo_stb.eq(self.valid_i & self.de),
+                       fifo_in.r.eq(self.r),
+                       fifo_in.g.eq(self.g),
+                       fifo_in.b.eq(self.b),
+               ]
+               vsync_r = Signal()
+               self.sync.pix += [
+                       If(self.vsync & ~vsync_r, fifo_in.parity.eq(~fifo_in.parity)),
+                       vsync_r.eq(self.vsync)
+               ]
+
+               fifo = AsyncFIFO(layout_len(frame_layout), 256)
+               self.add_submodule(fifo, {"write": "pix", "read": "sys"})
+               self.comb += [
+                       fifo.we.eq(fifo_stb),
+                       fifo.din.eq(fifo_in.raw_bits()),
+                       self.frame.stb.eq(fifo.readable),
+                       self.frame.payload.raw_bits().eq(fifo.dout),
+                       fifo.re.eq(self.frame.ack),
+                       self.busy.eq(0)
+               ]
index 7fb9a420a2d28f176b1d4e82ffecf068922fa270..f053237f3f7a101b1a11d895170fdedde9a738d2 100644 (file)
@@ -1,2 +1,3 @@
 control_tokens = [0b1101010100, 0b0010101011, 0b0101010100, 0b1010101011]
 channel_layout = [("d", 8), ("c", 2), ("de", 1)]
+frame_layout = [("parity", 1), ("r", 8), ("g", 8), ("b", 8)]
diff --git a/milkymist/dvisampler/debug.py b/milkymist/dvisampler/debug.py
new file mode 100644 (file)
index 0000000..4693e07
--- /dev/null
@@ -0,0 +1,46 @@
+from migen.fhdl.structure import *
+from migen.fhdl.module import Module
+from migen.genlib.fifo import AsyncFIFO
+from migen.genlib.record import layout_len
+from migen.bank.description import AutoCSR
+from migen.actorlib import structuring, dma_asmi, spi
+
+from milkymist.dvisampler.edid import EDID
+from milkymist.dvisampler.clocking import Clocking
+from milkymist.dvisampler.datacapture import DataCapture
+
+class RawDVISampler(Module, AutoCSR):
+       def __init__(self, pads, asmiport):
+               self.submodules.edid = EDID(pads)
+               self.submodules.clocking = Clocking(pads)
+
+               invert = False
+               try:
+                       s = getattr(pads, "data0")
+               except AttributeError:
+                       s = getattr(pads, "data0_n")
+                       invert = True
+               self.submodules.data0_cap = DataCapture(8, invert)
+               self.comb += [
+                       self.data0_cap.pad.eq(s),
+                       self.data0_cap.serdesstrobe.eq(self.clocking.serdesstrobe)
+               ]
+
+               fifo = AsyncFIFO(10, 256)
+               self.add_submodule(fifo, {"write": "pix", "read": "sys"})
+               self.comb += [
+                       fifo.din.eq(self.data0_cap.d),
+                       fifo.we.eq(1)
+               ]
+
+               pack_factor = asmiport.hub.dw//16
+               self.submodules.packer = structuring.Pack([("word", 10), ("pad", 6)], pack_factor)
+               self.submodules.cast = structuring.Cast(self.packer.source.payload.layout, asmiport.hub.dw)
+               self.submodules.dma = spi.DMAWriteController(dma_asmi.Writer(asmiport), spi.MODE_SINGLE_SHOT, free_flow=True)
+               self.comb += [
+                       self.packer.sink.stb.eq(fifo.readable),
+                       fifo.re.eq(self.packer.sink.ack),
+                       self.packer.sink.payload.word.eq(fifo.dout),
+                       self.packer.source.connect(self.cast.sink, match_by_position=True),
+                       self.cast.source.connect(self.dma.data, match_by_position=True)
+               ]
diff --git a/milkymist/dvisampler/dma.py b/milkymist/dvisampler/dma.py
new file mode 100644 (file)
index 0000000..8238728
--- /dev/null
@@ -0,0 +1,48 @@
+from migen.fhdl.structure import *
+from migen.fhdl.module import Module
+from migen.bank.description import *
+from migen.flow.actor import *
+from migen.actorlib import structuring, dma_asmi, spi
+
+from milkymist.dvisampler.common import frame_layout
+
+class DMA(Module):
+       def __init__(self, asmiport):
+               self.frame = Sink(frame_layout)
+               self.shoot = CSR()
+
+               ###
+
+               sof = Signal()
+               parity_r = Signal()
+               self.comb += sof.eq(self.frame.stb & (parity_r ^ self.frame.payload.parity))
+               self.sync += If(self.frame.stb & self.frame.ack, parity_r.eq(self.frame.payload.parity))
+
+               pending = Signal()
+               frame_en = Signal()
+               self.sync += [
+                       If(sof,
+                               frame_en.eq(0),
+                               If(pending, frame_en.eq(1)),
+                               pending.eq(0)
+                       ),
+                       If(self.shoot.re, pending.eq(1))
+               ]
+
+               pack_factor = asmiport.hub.dw//32
+               self.submodules.packer = structuring.Pack(list(reversed([("pad", 2), ("r", 10), ("g", 10), ("b", 10)])), pack_factor)
+               self.submodules.cast = structuring.Cast(self.packer.source.payload.layout, asmiport.hub.dw, reverse_from=False)
+               self.submodules.dma = spi.DMAWriteController(dma_asmi.Writer(asmiport), spi.MODE_EXTERNAL)
+               self.comb += [
+                       self.dma.generator.trigger.eq(self.shoot.re),
+                       self.packer.sink.stb.eq(self.frame.stb & frame_en),
+                       self.frame.ack.eq(self.packer.sink.ack | (~frame_en & ~(pending & sof))),
+                       self.packer.sink.payload.r.eq(self.frame.payload.r << 2),
+                       self.packer.sink.payload.g.eq(self.frame.payload.g << 2),
+                       self.packer.sink.payload.b.eq(self.frame.payload.b << 2),
+                       self.packer.source.connect(self.cast.sink, match_by_position=True),
+                       self.cast.source.connect(self.dma.data, match_by_position=True)
+               ]
+
+       def get_csrs(self):
+               return [self.shoot] + self.dma.get_csrs()
diff --git a/milkymist/dvisampler/resdetection.py b/milkymist/dvisampler/resdetection.py
deleted file mode 100644 (file)
index c345be3..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-from migen.fhdl.structure import *
-from migen.fhdl.module import Module
-from migen.genlib.cdc import MultiReg
-from migen.bank.description import *
-
-class ResolutionDetection(Module, AutoCSR):
-       def __init__(self, nbits=11):
-               self.vsync = Signal()
-               self.de = Signal()
-
-               self._hres = CSRStatus(nbits)
-               self._vres = CSRStatus(nbits)
-
-               ###
-
-               # Detect DE transitions
-               de_r = Signal()
-               pn_de = Signal()
-               self.sync.pix += de_r.eq(self.de)
-               self.comb += pn_de.eq(~self.de & de_r)
-
-               # HRES
-               hcounter = Signal(nbits)
-               self.sync.pix += If(self.de,
-                               hcounter.eq(hcounter + 1)
-                       ).Else(
-                               hcounter.eq(0)
-                       )
-
-               hcounter_st = Signal(nbits)
-               self.sync.pix += If(pn_de, hcounter_st.eq(hcounter))
-               self.specials += MultiReg(hcounter_st, self._hres.status)
-
-               # VRES
-               vsync_r = Signal()
-               p_vsync = Signal()
-               self.sync.pix += vsync_r.eq(self.vsync),
-               self.comb += p_vsync.eq(self.vsync & ~vsync_r)
-
-               vcounter = Signal(nbits)
-               self.sync.pix += If(p_vsync,
-                               vcounter.eq(0)
-                       ).Elif(pn_de,
-                               vcounter.eq(vcounter + 1)
-                       )
-
-               vcounter_st = Signal(nbits)
-               self.sync.pix += If(p_vsync, vcounter_st.eq(vcounter))
-               self.specials += MultiReg(vcounter_st, self._vres.status)
diff --git a/milkymist/dvisampler/syncpol.py b/milkymist/dvisampler/syncpol.py
deleted file mode 100644 (file)
index 2ef752a..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-from migen.fhdl.structure import *
-from migen.fhdl.module import Module
-from migen.genlib.record import Record
-
-from milkymist.dvisampler.common import channel_layout
-
-class SyncPolarity(Module):
-       def __init__(self):
-               self.valid_i = Signal()
-               self.data_in0 = Record(channel_layout)
-               self.data_in1 = Record(channel_layout)
-               self.data_in2 = Record(channel_layout)
-
-               self.valid_o = Signal()
-               self.de = Signal()
-               self.hsync = Signal()
-               self.vsync = Signal()
-               self.r = Signal(8)
-               self.g = Signal(8)
-               self.b = Signal(8)
-
-               ###
-
-               de = self.data_in0.de
-               de_r = Signal()
-               c = self.data_in0.c
-               c_polarity = Signal(2)
-               c_out = Signal(2)
-
-               self.comb += [
-                       self.de.eq(de_r),
-                       self.hsync.eq(c_out[0]),
-                       self.vsync.eq(c_out[1])
-               ]
-
-               self.sync.pix += [
-                       self.valid_o.eq(self.valid_i),
-                       self.r.eq(self.data_in2.d),
-                       self.g.eq(self.data_in1.d),
-                       self.b.eq(self.data_in0.d),
-
-                       de_r.eq(de),
-                       If(de_r & ~de,
-                               c_polarity.eq(c),
-                               c_out.eq(0)
-                       ).Else(
-                               c_out.eq(c ^ c_polarity)
-                       )
-               ]
diff --git a/top.py b/top.py
index 6a41c507c9f59bfb09abef5b8179252cb14e179d..f3ed0b94d3c8f5b86035e8a00a6bb44d37849649 100644 (file)
--- a/top.py
+++ b/top.py
@@ -92,6 +92,7 @@ class SoC(Module):
                self.submodules.asmicon = asmicon.ASMIcon(sdram_phy, sdram_geom, sdram_timing)
                asmiport_wb = self.asmicon.hub.get_port()
                asmiport_fb = self.asmicon.hub.get_port(3)
+               asmiport_dvi0 = self.asmicon.hub.get_port(2)
                self.asmicon.finalize()
                
                #
@@ -141,8 +142,8 @@ class SoC(Module):
                self.submodules.timer0 = timer.Timer()
                self.submodules.fb = framebuffer.Framebuffer(platform.request("vga"), asmiport_fb)
                self.submodules.asmiprobe = asmiprobe.ASMIprobe(self.asmicon.hub)
-               self.submodules.dvisampler0 = dvisampler.DVISampler(platform.request("dvi_in", 0))
-               self.submodules.dvisampler1 = dvisampler.DVISampler(platform.request("dvi_in", 1))
+               self.submodules.dvisampler0 = dvisampler.DVISampler(platform.request("dvi_in", 0), asmiport_dvi0)
+               #self.submodules.dvisampler1 = dvisampler.DVISampler(platform.request("dvi_in", 1))
 
                self.submodules.csrbankarray = csrgen.BankArray(self,
                        lambda name, memory: self.csr_map[name if memory is None else name + "_" + memory.name_override])