dvisampler: mostly working, very basic and slightly buggy DMA

This commit is contained in:
Sebastien Bourdeauducq 2013-05-06 09:58:12 +02:00
parent f82a16f3a3
commit e2d15b169a
8 changed files with 262 additions and 138 deletions

View File

@ -1,8 +1,6 @@
from migen.fhdl.structure import * from migen.fhdl.structure import *
from migen.fhdl.module import Module from migen.fhdl.module import Module
from migen.bank.description import * from migen.bank.description import AutoCSR
from migen.genlib.fifo import AsyncFIFO
from migen.actorlib import structuring, dma_asmi, spi
from milkymist.dvisampler.edid import EDID from milkymist.dvisampler.edid import EDID
from milkymist.dvisampler.clocking import Clocking 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.charsync import CharSync
from milkymist.dvisampler.decoding import Decoding from milkymist.dvisampler.decoding import Decoding
from milkymist.dvisampler.chansync import ChanSync from milkymist.dvisampler.chansync import ChanSync
from milkymist.dvisampler.syncpol import SyncPolarity from milkymist.dvisampler.analysis import SyncPolarity, ResolutionDetection, FrameExtraction
from milkymist.dvisampler.resdetection import ResolutionDetection from milkymist.dvisampler.dma import DMA
class DVISampler(Module, AutoCSR): class DVISampler(Module, AutoCSR):
def __init__(self, pads): def __init__(self, pads, asmiport):
self.submodules.edid = EDID(pads) self.submodules.edid = EDID(pads)
self.submodules.clocking = Clocking(pads) self.submodules.clocking = Clocking(pads)
@ -54,6 +52,8 @@ class DVISampler(Module, AutoCSR):
self.chansync.data_in2.eq(self.data2_decod.output), self.chansync.data_in2.eq(self.data2_decod.output),
] ]
###
self.submodules.syncpol = SyncPolarity() self.submodules.syncpol = SyncPolarity()
self.comb += [ self.comb += [
self.syncpol.valid_i.eq(self.chansync.chan_synced), self.syncpol.valid_i.eq(self.chansync.chan_synced),
@ -64,42 +64,20 @@ class DVISampler(Module, AutoCSR):
self.submodules.resdetection = ResolutionDetection() self.submodules.resdetection = ResolutionDetection()
self.comb += [ self.comb += [
self.resdetection.valid_i.eq(self.syncpol.valid_o),
self.resdetection.de.eq(self.syncpol.de), self.resdetection.de.eq(self.syncpol.de),
self.resdetection.vsync.eq(self.syncpol.vsync) self.resdetection.vsync.eq(self.syncpol.vsync)
] ]
class RawDVISampler(Module, AutoCSR): self.submodules.frame = FrameExtraction()
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.comb += [
self.data0_cap.pad.eq(s), self.frame.valid_i.eq(self.syncpol.valid_o),
self.data0_cap.serdesstrobe.eq(self.clocking.serdesstrobe) 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.submodules.dma = DMA(asmiport)
self.add_submodule(fifo, {"write": "pix", "read": "sys"}) self.comb += self.frame.frame.connect(self.dma.frame)
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)
]

View File

@ -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)
]

View File

@ -1,2 +1,3 @@
control_tokens = [0b1101010100, 0b0010101011, 0b0101010100, 0b1010101011] control_tokens = [0b1101010100, 0b0010101011, 0b0101010100, 0b1010101011]
channel_layout = [("d", 8), ("c", 2), ("de", 1)] channel_layout = [("d", 8), ("c", 2), ("de", 1)]
frame_layout = [("parity", 1), ("r", 8), ("g", 8), ("b", 8)]

View File

@ -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)
]

View File

@ -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()

View File

@ -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)

View File

@ -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
View File

@ -92,6 +92,7 @@ class SoC(Module):
self.submodules.asmicon = asmicon.ASMIcon(sdram_phy, sdram_geom, sdram_timing) self.submodules.asmicon = asmicon.ASMIcon(sdram_phy, sdram_geom, sdram_timing)
asmiport_wb = self.asmicon.hub.get_port() asmiport_wb = self.asmicon.hub.get_port()
asmiport_fb = self.asmicon.hub.get_port(3) asmiport_fb = self.asmicon.hub.get_port(3)
asmiport_dvi0 = self.asmicon.hub.get_port(2)
self.asmicon.finalize() self.asmicon.finalize()
# #
@ -141,8 +142,8 @@ class SoC(Module):
self.submodules.timer0 = timer.Timer() self.submodules.timer0 = timer.Timer()
self.submodules.fb = framebuffer.Framebuffer(platform.request("vga"), asmiport_fb) self.submodules.fb = framebuffer.Framebuffer(platform.request("vga"), asmiport_fb)
self.submodules.asmiprobe = asmiprobe.ASMIprobe(self.asmicon.hub) self.submodules.asmiprobe = asmiprobe.ASMIprobe(self.asmicon.hub)
self.submodules.dvisampler0 = dvisampler.DVISampler(platform.request("dvi_in", 0)) self.submodules.dvisampler0 = dvisampler.DVISampler(platform.request("dvi_in", 0), asmiport_dvi0)
self.submodules.dvisampler1 = dvisampler.DVISampler(platform.request("dvi_in", 1)) #self.submodules.dvisampler1 = dvisampler.DVISampler(platform.request("dvi_in", 1))
self.submodules.csrbankarray = csrgen.BankArray(self, self.submodules.csrbankarray = csrgen.BankArray(self,
lambda name, memory: self.csr_map[name if memory is None else name + "_" + memory.name_override]) lambda name, memory: self.csr_map[name if memory is None else name + "_" + memory.name_override])