Add 16-bits, RGB565 FB support in simple-framebuffer
This commit is contained in:
parent
47e4a1b437
commit
bf004d48e9
|
@ -606,11 +606,13 @@ class VideoTerminal(Module):
|
||||||
|
|
||||||
class VideoFrameBuffer(Module, AutoCSR):
|
class VideoFrameBuffer(Module, AutoCSR):
|
||||||
"""Video FrameBuffer"""
|
"""Video FrameBuffer"""
|
||||||
def __init__(self, dram_port, hres=800, vres=600, base=0x00000000, fifo_depth=65536, clock_domain="sys", clock_faster_than_sys=False):
|
def __init__(self, dram_port, hres=800, vres=600, base=0x00000000, fifo_depth=65536, clock_domain="sys", clock_faster_than_sys=False, depth=32):
|
||||||
self.vtg_sink = vtg_sink = stream.Endpoint(video_timing_layout)
|
self.vtg_sink = vtg_sink = stream.Endpoint(video_timing_layout)
|
||||||
self.source = source = stream.Endpoint(video_data_layout)
|
self.source = source = stream.Endpoint(video_data_layout)
|
||||||
self.underflow = Signal()
|
self.underflow = Signal()
|
||||||
|
|
||||||
|
assert((depth == 32) or (depth == 16))
|
||||||
|
|
||||||
# # #
|
# # #
|
||||||
|
|
||||||
# Video DMA.
|
# Video DMA.
|
||||||
|
@ -618,29 +620,29 @@ class VideoFrameBuffer(Module, AutoCSR):
|
||||||
self.submodules.dma = LiteDRAMDMAReader(dram_port, fifo_depth=fifo_depth//(dram_port.data_width//8), fifo_buffered=True)
|
self.submodules.dma = LiteDRAMDMAReader(dram_port, fifo_depth=fifo_depth//(dram_port.data_width//8), fifo_buffered=True)
|
||||||
self.dma.add_csr(
|
self.dma.add_csr(
|
||||||
default_base = base,
|
default_base = base,
|
||||||
default_length = hres*vres*32//8, # 32-bit RGB-444
|
default_length = hres*vres*depth//8, # 32-bit RGB-888 or 16-bit RGB-565
|
||||||
default_enable = 0,
|
default_enable = 0,
|
||||||
default_loop = 1
|
default_loop = 1
|
||||||
)
|
)
|
||||||
|
|
||||||
# If DRAM Data Width > 32-bit and Video clock is faster than sys_clk:
|
# If DRAM Data Width > depth and Video clock is faster than sys_clk:
|
||||||
if (dram_port.data_width > 32) and clock_faster_than_sys:
|
if (dram_port.data_width > depth) and clock_faster_than_sys:
|
||||||
# Do Clock Domain Crossing first...
|
# Do Clock Domain Crossing first...
|
||||||
self.submodules.cdc = stream.ClockDomainCrossing([("data", dram_port.data_width)], cd_from="sys", cd_to=clock_domain)
|
self.submodules.cdc = stream.ClockDomainCrossing([("data", dram_port.data_width)], cd_from="sys", cd_to=clock_domain)
|
||||||
self.comb += self.dma.source.connect(self.cdc.sink)
|
self.comb += self.dma.source.connect(self.cdc.sink)
|
||||||
# ... and then Data-Width Conversion.
|
# ... and then Data-Width Conversion.
|
||||||
self.submodules.conv = stream.Converter(dram_port.data_width, 32)
|
self.submodules.conv = stream.Converter(dram_port.data_width, depth)
|
||||||
self.comb += self.cdc.source.connect(self.conv.sink)
|
self.comb += self.cdc.source.connect(self.conv.sink)
|
||||||
video_pipe_source = self.conv.source
|
video_pipe_source = self.conv.source
|
||||||
# Elsif DRAM Data Widt < 32-bit or Video clock is slower than sys_clk:
|
# Elsif DRAM Data Width <= depth or Video clock is slower than sys_clk:
|
||||||
else:
|
else:
|
||||||
# Do Data-Width Conversion first...
|
# Do Data-Width Conversion first...
|
||||||
self.submodules.conv = stream.Converter(dram_port.data_width, 32)
|
self.submodules.conv = stream.Converter(dram_port.data_width, depth)
|
||||||
self.comb += self.dma.source.connect(self.conv.sink)
|
self.comb += self.dma.source.connect(self.conv.sink)
|
||||||
# ... and then Clock Domain Crossing.
|
# ... and then Clock Domain Crossing.
|
||||||
self.submodules.cdc = stream.ClockDomainCrossing([("data", 32)], cd_from="sys", cd_to=clock_domain)
|
self.submodules.cdc = stream.ClockDomainCrossing([("data", depth)], cd_from="sys", cd_to=clock_domain)
|
||||||
self.comb += self.conv.source.connect(self.cdc.sink)
|
self.comb += self.conv.source.connect(self.cdc.sink)
|
||||||
self.comb += If(dram_port.data_width < 32, # FIXME.
|
self.comb += If((dram_port.data_width < depth) and (depth == 32), # FIXME.
|
||||||
self.cdc.sink.data[ 0: 8].eq(self.conv.source.data[16:24]),
|
self.cdc.sink.data[ 0: 8].eq(self.conv.source.data[16:24]),
|
||||||
self.cdc.sink.data[16:24].eq(self.conv.source.data[ 0: 8]),
|
self.cdc.sink.data[16:24].eq(self.conv.source.data[ 0: 8]),
|
||||||
)
|
)
|
||||||
|
@ -655,9 +657,15 @@ class VideoFrameBuffer(Module, AutoCSR):
|
||||||
|
|
||||||
),
|
),
|
||||||
vtg_sink.connect(source, keep={"de", "hsync", "vsync"}),
|
vtg_sink.connect(source, keep={"de", "hsync", "vsync"}),
|
||||||
source.r.eq(video_pipe_source.data[16:24]),
|
If(depth == 32,
|
||||||
source.g.eq(video_pipe_source.data[ 8:16]),
|
source.r.eq(video_pipe_source.data[16:24]),
|
||||||
source.b.eq(video_pipe_source.data[ 0: 8]),
|
source.g.eq(video_pipe_source.data[ 8:16]),
|
||||||
|
source.b.eq(video_pipe_source.data[ 0: 8]),
|
||||||
|
).Else( # depth == 16
|
||||||
|
source.r.eq(Cat(Signal(3, reset = 0), video_pipe_source.data[ 0: 5])),
|
||||||
|
source.g.eq(Cat(Signal(2, reset = 0), video_pipe_source.data[ 5:11])),
|
||||||
|
source.b.eq(Cat(Signal(3, reset = 0), video_pipe_source.data[11:16])),
|
||||||
|
)
|
||||||
]
|
]
|
||||||
|
|
||||||
# Underflow.
|
# Underflow.
|
||||||
|
|
|
@ -1784,7 +1784,7 @@ class LiteXSoC(SoC):
|
||||||
self.comb += vt.source.connect(phy if isinstance(phy, stream.Endpoint) else phy.sink)
|
self.comb += vt.source.connect(phy if isinstance(phy, stream.Endpoint) else phy.sink)
|
||||||
|
|
||||||
# Add Video Framebuffer ------------------------------------------------------------------------
|
# Add Video Framebuffer ------------------------------------------------------------------------
|
||||||
def add_video_framebuffer(self, name="video_framebuffer", phy=None, timings="800x600@60Hz", clock_domain="sys"):
|
def add_video_framebuffer(self, name="video_framebuffer", phy=None, timings="800x600@60Hz", clock_domain="sys", depth=32):
|
||||||
# Imports.
|
# Imports.
|
||||||
from litex.soc.cores.video import VideoTimingGenerator, VideoFrameBuffer
|
from litex.soc.cores.video import VideoTimingGenerator, VideoFrameBuffer
|
||||||
|
|
||||||
|
@ -1803,7 +1803,8 @@ class LiteXSoC(SoC):
|
||||||
vres = vres,
|
vres = vres,
|
||||||
base = base,
|
base = base,
|
||||||
clock_domain = clock_domain,
|
clock_domain = clock_domain,
|
||||||
clock_faster_than_sys = vtg.video_timings["pix_clk"] > self.sys_clk_freq
|
clock_faster_than_sys = vtg.video_timings["pix_clk"] > self.sys_clk_freq,
|
||||||
|
depth = depth
|
||||||
)
|
)
|
||||||
setattr(self.submodules, name, vfb)
|
setattr(self.submodules, name, vfb)
|
||||||
|
|
||||||
|
@ -1817,3 +1818,5 @@ class LiteXSoC(SoC):
|
||||||
self.add_constant("VIDEO_FRAMEBUFFER_BASE", base)
|
self.add_constant("VIDEO_FRAMEBUFFER_BASE", base)
|
||||||
self.add_constant("VIDEO_FRAMEBUFFER_HRES", hres)
|
self.add_constant("VIDEO_FRAMEBUFFER_HRES", hres)
|
||||||
self.add_constant("VIDEO_FRAMEBUFFER_VRES", vres)
|
self.add_constant("VIDEO_FRAMEBUFFER_VRES", vres)
|
||||||
|
self.add_constant("VIDEO_FRAMEBUFFER_DEPTH", depth)
|
||||||
|
|
||||||
|
|
|
@ -211,7 +211,7 @@ def generate_dts(d, initrd_start=None, initrd_size=None, initrd=None, root_devic
|
||||||
}};
|
}};
|
||||||
""".format(
|
""".format(
|
||||||
framebuffer_base = d["constants"]["video_framebuffer_base"],
|
framebuffer_base = d["constants"]["video_framebuffer_base"],
|
||||||
framebuffer_size = (d["constants"]["video_framebuffer_hres"] * d["constants"]["video_framebuffer_vres"] * 4))
|
framebuffer_size = (d["constants"]["video_framebuffer_hres"] * d["constants"]["video_framebuffer_vres"] * (d["constants"]["video_framebuffer_depth"]//8)))
|
||||||
|
|
||||||
dts += """
|
dts += """
|
||||||
};
|
};
|
||||||
|
@ -491,6 +491,10 @@ def generate_dts(d, initrd_start=None, initrd_size=None, initrd=None, root_devic
|
||||||
framebuffer_base = d["constants"]["video_framebuffer_base"]
|
framebuffer_base = d["constants"]["video_framebuffer_base"]
|
||||||
framebuffer_width = d["constants"]["video_framebuffer_hres"]
|
framebuffer_width = d["constants"]["video_framebuffer_hres"]
|
||||||
framebuffer_height = d["constants"]["video_framebuffer_vres"]
|
framebuffer_height = d["constants"]["video_framebuffer_vres"]
|
||||||
|
framebuffer_depth = d["constants"]["video_framebuffer_depth"]
|
||||||
|
framebuffer_format = "a8b8g8r8"
|
||||||
|
if (framebuffer_depth == 16):
|
||||||
|
framebuffer_format = "r5g6b5"
|
||||||
dts += """
|
dts += """
|
||||||
framebuffer0: framebuffer@{framebuffer_base:x} {{
|
framebuffer0: framebuffer@{framebuffer_base:x} {{
|
||||||
compatible = "simple-framebuffer";
|
compatible = "simple-framebuffer";
|
||||||
|
@ -498,14 +502,15 @@ def generate_dts(d, initrd_start=None, initrd_size=None, initrd=None, root_devic
|
||||||
width = <{framebuffer_width}>;
|
width = <{framebuffer_width}>;
|
||||||
height = <{framebuffer_height}>;
|
height = <{framebuffer_height}>;
|
||||||
stride = <{framebuffer_stride}>;
|
stride = <{framebuffer_stride}>;
|
||||||
format = "a8b8g8r8";
|
format = "{framebuffer_format}";
|
||||||
}};
|
}};
|
||||||
""".format(
|
""".format(
|
||||||
framebuffer_base = framebuffer_base,
|
framebuffer_base = framebuffer_base,
|
||||||
framebuffer_width = framebuffer_width,
|
framebuffer_width = framebuffer_width,
|
||||||
framebuffer_height = framebuffer_height,
|
framebuffer_height = framebuffer_height,
|
||||||
framebuffer_size = framebuffer_width * framebuffer_height * 4,
|
framebuffer_size = framebuffer_width * framebuffer_height * (framebuffer_depth//8),
|
||||||
framebuffer_stride = framebuffer_width * 4)
|
framebuffer_stride = framebuffer_width * (framebuffer_depth//8),
|
||||||
|
framebuffer_format = framebuffer_format)
|
||||||
|
|
||||||
# ICAP Bitstream -------------------------------------------------------------------------------
|
# ICAP Bitstream -------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue