Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
  • 3 commits
  • 11 files changed
  • 0 commit comments
  • 1 contributor
View
2  build.py
@@ -18,8 +18,6 @@ def main():
""", clk50=platform.lookup_request("clk50"))
platform.add_platform_command("""
-INST "m1crg/pll" LOC="PLL_ADV_X0Y1";
-INST "m1crg/vga_clock_gen" LOC="DCM_X0Y6";
INST "m1crg/wr_bufpll" LOC = "BUFPLL_X0Y2";
INST "m1crg/rd_bufpll" LOC = "BUFPLL_X0Y3";
View
54 milkymist/dvisampler/__init__.py
@@ -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.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 @@ def __init__(self, pads):
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 @@ def __init__(self, pads):
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)
View
148 milkymist/dvisampler/analysis.py
@@ -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
1  milkymist/dvisampler/common.py
@@ -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)]
View
46 milkymist/dvisampler/debug.py
@@ -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
48 milkymist/dvisampler/dma.py
@@ -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
49 milkymist/dvisampler/resdetection.py
@@ -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
49 milkymist/dvisampler/syncpol.py
@@ -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)
- )
- ]
View
17 software/videomixer/main.c
@@ -3,10 +3,12 @@
#include <irq.h>
#include <uart.h>
+#include <console.h>
#include <hw/csr.h>
#include <hw/flags.h>
static int d0, d1, d2;
+static unsigned int framebuffer[640*480] __attribute__((aligned(16)));
static void print_status(void)
{
@@ -22,6 +24,17 @@ static void print_status(void)
dvisampler0_resdetection_vres_read());
}
+static void capture_fb(void)
+{
+ dvisampler0_dma_base_write((unsigned int)framebuffer);
+ dvisampler0_dma_length_write(sizeof(framebuffer));
+ dvisampler0_dma_shoot_write(1);
+
+ printf("waiting for DMA...");
+ while(dvisampler0_dma_busy_read());
+ printf("done\n");
+}
+
static void calibrate_delays(void)
{
dvisampler0_data0_cap_dly_ctl_write(DVISAMPLER_DELAY_CAL);
@@ -119,6 +132,8 @@ static void vmix(void)
adjust_phase();
counter = 0;
}
+ if(readchar_nonblock() && (readchar() == 'c'))
+ capture_fb();
}
printf("PLL unlocked\n");
}
@@ -132,6 +147,8 @@ int main(void)
puts("Minimal video mixer software built "__DATE__" "__TIME__"\n");
+ fb_base_write((unsigned int)framebuffer);
+ fb_enable_write(1);
vmix();
return 0;
View
5 top.py
@@ -92,6 +92,7 @@ def __init__(self, platform):
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 @@ def __init__(self, platform):
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])
View
10 verilog/m1crg/m1crg.v
@@ -209,6 +209,12 @@ BUFG bufg_x1(
.O(sys_clk)
);
+wire clk50g;
+BUFG bufg_50(
+ .I(pllout4),
+ .O(clk50g)
+);
+
wire clk2x_off;
BUFG bufg_x2_offclk(
.I(pllout5),
@@ -253,7 +259,7 @@ ODDR2 #(
* Ethernet PHY
*/
-always @(posedge pllout4)
+always @(posedge clk50g)
eth_phy_clk_pad <= ~eth_phy_clk_pad;
/* Let the synthesizer insert the appropriate buffers */
@@ -277,7 +283,7 @@ DCM_CLKGEN #(
.CLKFX180(),
.CLKFXDV(),
.STATUS(),
- .CLKIN(pllout4),
+ .CLKIN(clk50g),
.FREEZEDCM(1'b0),
.PROGCLK(vga_progclk),
.PROGDATA(vga_progdata),

No commit comments for this range

Something went wrong with that request. Please try again.