soc/cores/video: Add initial (and simple) VideoFrameBuffer core.
This commit is contained in:
parent
24fb153fa1
commit
ccc8916995
|
@ -13,6 +13,8 @@ from migen.genlib.cdc import MultiReg
|
||||||
from litex.soc.interconnect.csr import *
|
from litex.soc.interconnect.csr import *
|
||||||
from litex.soc.interconnect import stream
|
from litex.soc.interconnect import stream
|
||||||
|
|
||||||
|
from litedram.frontend.dma import LiteDRAMDMAReader
|
||||||
|
|
||||||
# Video Constants ----------------------------------------------------------------------------------
|
# Video Constants ----------------------------------------------------------------------------------
|
||||||
|
|
||||||
hbits = 12
|
hbits = 12
|
||||||
|
@ -229,7 +231,7 @@ class VideoTimingGenerator(Module, AutoCSR):
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
# Patterns -----------------------------------------------------------------------------------------
|
# Video Patterns -----------------------------------------------------------------------------------
|
||||||
|
|
||||||
class ColorBarsPattern(Module):
|
class ColorBarsPattern(Module):
|
||||||
"""Color Bars Pattern"""
|
"""Color Bars Pattern"""
|
||||||
|
@ -551,6 +553,51 @@ class VideoTerminal(Module):
|
||||||
source.b.eq(0x00)
|
source.b.eq(0x00)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Video FrameBuffer --------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
class VideoFrameBuffer(Module, AutoCSR):
|
||||||
|
"""Video FrameBuffer"""
|
||||||
|
def __init__(self, dram_port, hres=640, vres=480, base=0x00000000, clock_domain="sys"):
|
||||||
|
self.vtg_sink = vtg_sink = stream.Endpoint(video_timing_layout)
|
||||||
|
self.source = source = stream.Endpoint(video_data_layout)
|
||||||
|
|
||||||
|
# # #
|
||||||
|
|
||||||
|
# Video DMA.
|
||||||
|
self.submodules.dma = LiteDRAMDMAReader(dram_port, fifo_depth=2048, fifo_buffered=True) # FIXME: Adjust/Expose.
|
||||||
|
self.dma.add_csr(
|
||||||
|
default_base = base,
|
||||||
|
default_length = hres*vres*32//8, # 32-bit RGB-444
|
||||||
|
default_start = 1,
|
||||||
|
default_loop = 1
|
||||||
|
)
|
||||||
|
|
||||||
|
# FIXME: Make sure it will work for all DRAM's data-width/all Video resolutions.
|
||||||
|
|
||||||
|
# Video Data-Width Converter.
|
||||||
|
self.submodules.conv = stream.Converter(dram_port.data_width, 32)
|
||||||
|
self.comb += self.dma.source.connect(self.conv.sink)
|
||||||
|
|
||||||
|
# Video CDC.
|
||||||
|
self.submodules.cdc = stream.ClockDomainCrossing([("data", 32)], cd_from="sys", cd_to=clock_domain)
|
||||||
|
self.comb += self.conv.source.connect(self.cdc.sink)
|
||||||
|
|
||||||
|
# Video Generation.
|
||||||
|
self.comb += [
|
||||||
|
vtg_sink.ready.eq(1),
|
||||||
|
If(vtg_sink.valid & vtg_sink.de,
|
||||||
|
source.valid.eq(self.cdc.source.valid),
|
||||||
|
vtg_sink.ready.eq(source.ready),
|
||||||
|
self.cdc.source.ready.eq(source.ready)
|
||||||
|
),
|
||||||
|
source.de.eq(vtg_sink.de),
|
||||||
|
source.hsync.eq(vtg_sink.hsync),
|
||||||
|
source.vsync.eq(vtg_sink.vsync),
|
||||||
|
source.r.eq(self.cdc.source.data[ 0: 8]),
|
||||||
|
source.g.eq(self.cdc.source.data[ 8:16]),
|
||||||
|
source.b.eq(self.cdc.source.data[16:24]),
|
||||||
|
]
|
||||||
|
|
||||||
# Video PHYs ---------------------------------------------------------------------------------------
|
# Video PHYs ---------------------------------------------------------------------------------------
|
||||||
|
|
||||||
class VideoDVIPHY(Module):
|
class VideoDVIPHY(Module):
|
||||||
|
|
|
@ -18,7 +18,7 @@ from litex.soc.cores.identifier import Identifier
|
||||||
from litex.soc.cores.timer import Timer
|
from litex.soc.cores.timer import Timer
|
||||||
from litex.soc.cores.spi_flash import SpiFlash
|
from litex.soc.cores.spi_flash import SpiFlash
|
||||||
from litex.soc.cores.spi import SPIMaster
|
from litex.soc.cores.spi import SPIMaster
|
||||||
from litex.soc.cores.video import VideoTimingGenerator, VideoTerminal
|
from litex.soc.cores.video import VideoTimingGenerator, VideoTerminal, VideoFrameBuffer
|
||||||
|
|
||||||
from litex.soc.interconnect.csr import *
|
from litex.soc.interconnect.csr import *
|
||||||
from litex.soc.interconnect.csr_eventmanager import *
|
from litex.soc.interconnect.csr_eventmanager import *
|
||||||
|
@ -1639,7 +1639,7 @@ class LiteXSoC(SoC):
|
||||||
vres = int(timings.split("@")[0].split("x")[1]),
|
vres = int(timings.split("@")[0].split("x")[1]),
|
||||||
)
|
)
|
||||||
vt = ClockDomainsRenamer(clock_domain)(vt)
|
vt = ClockDomainsRenamer(clock_domain)(vt)
|
||||||
self.submodules.video_terminal_vt = vt
|
self.submodules.video_terminal = vt
|
||||||
|
|
||||||
# Connect Video Timing Generator to Video Terminal.
|
# Connect Video Timing Generator to Video Terminal.
|
||||||
self.comb += vtg.source.connect(vt.vtg_sink)
|
self.comb += vtg.source.connect(vt.vtg_sink)
|
||||||
|
@ -1655,3 +1655,26 @@ class LiteXSoC(SoC):
|
||||||
|
|
||||||
# Connect Video Terminal to Video PHY.
|
# Connect Video Terminal to Video PHY.
|
||||||
self.comb += vt.source.connect(phy.sink)
|
self.comb += vt.source.connect(phy.sink)
|
||||||
|
|
||||||
|
# Add Video Framebuffer ------------------------------------------------------------------------
|
||||||
|
def add_video_framebuffer(self, name="video_framebuffer", phy=None, timings="800x600@60Hz", clock_domain="sys"):
|
||||||
|
# Video Timing Generator.
|
||||||
|
vtg = VideoTimingGenerator(default_video_timings=timings)
|
||||||
|
vtg = ClockDomainsRenamer(clock_domain)(vtg)
|
||||||
|
self.submodules.video_framebuffer_vtg = vtg
|
||||||
|
self.add_csr("video_framebuffer_vtg")
|
||||||
|
|
||||||
|
# Video FrameBuffer.
|
||||||
|
vfb = VideoFrameBuffer(self.sdram.crossbar.get_port(),
|
||||||
|
hres = int(timings.split("@")[0].split("x")[0]),
|
||||||
|
vres = int(timings.split("@")[0].split("x")[1]),
|
||||||
|
clock_domain = "vga"
|
||||||
|
)
|
||||||
|
self.submodules.video_framebuffer = vfb
|
||||||
|
self.add_csr("video_framebuffer")
|
||||||
|
|
||||||
|
# Connect Video Timing Generator to Video FrameBuffer.
|
||||||
|
self.comb += vtg.source.connect(vfb.vtg_sink)
|
||||||
|
|
||||||
|
# Connect Video FrameBuffer to Video PHY.
|
||||||
|
self.comb += vfb.source.connect(phy.sink)
|
||||||
|
|
Loading…
Reference in New Issue