dvisampler: mostly working, very basic and slightly buggy DMA
This commit is contained in:
parent
f82a16f3a3
commit
e2d15b169a
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
]
|
|
@ -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)]
|
||||
|
|
|
@ -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)
|
||||
]
|
|
@ -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()
|
|
@ -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)
|
|
@ -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)
|
||||
)
|
||||
]
|
5
top.py
5
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])
|
||||
|
|
Loading…
Reference in New Issue