diff --git a/litex/soc/cores/video.py b/litex/soc/cores/video.py index 33b819c47..0d6401c4b 100644 --- a/litex/soc/cores/video.py +++ b/litex/soc/cores/video.py @@ -606,11 +606,13 @@ class VideoTerminal(Module): class VideoFrameBuffer(Module, AutoCSR): """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.source = source = stream.Endpoint(video_data_layout) self.underflow = Signal() + assert((depth == 32) or (depth == 16)) + # # # # 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.dma.add_csr( 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_loop = 1 ) - # If DRAM Data Width > 32-bit and Video clock is faster than sys_clk: - if (dram_port.data_width > 32) and clock_faster_than_sys: + # If DRAM Data Width > depth and Video clock is faster than sys_clk: + if (dram_port.data_width > depth) and clock_faster_than_sys: # Do Clock Domain Crossing first... 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) # ... 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) 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: # 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) # ... 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 += 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[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"}), - source.r.eq(video_pipe_source.data[16:24]), - source.g.eq(video_pipe_source.data[ 8:16]), - source.b.eq(video_pipe_source.data[ 0: 8]), + If(depth == 32, + source.r.eq(video_pipe_source.data[16:24]), + 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. diff --git a/litex/soc/integration/soc.py b/litex/soc/integration/soc.py index 8798fb071..d99a526ef 100644 --- a/litex/soc/integration/soc.py +++ b/litex/soc/integration/soc.py @@ -1784,7 +1784,7 @@ class LiteXSoC(SoC): self.comb += vt.source.connect(phy if isinstance(phy, stream.Endpoint) else phy.sink) # 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. from litex.soc.cores.video import VideoTimingGenerator, VideoFrameBuffer @@ -1803,7 +1803,8 @@ class LiteXSoC(SoC): vres = vres, base = base, 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) @@ -1817,3 +1818,5 @@ class LiteXSoC(SoC): self.add_constant("VIDEO_FRAMEBUFFER_BASE", base) self.add_constant("VIDEO_FRAMEBUFFER_HRES", hres) self.add_constant("VIDEO_FRAMEBUFFER_VRES", vres) + self.add_constant("VIDEO_FRAMEBUFFER_DEPTH", depth) + diff --git a/litex/tools/litex_json2dts_linux.py b/litex/tools/litex_json2dts_linux.py index 85e6430d2..4d548ebd6 100755 --- a/litex/tools/litex_json2dts_linux.py +++ b/litex/tools/litex_json2dts_linux.py @@ -211,7 +211,7 @@ def generate_dts(d, initrd_start=None, initrd_size=None, initrd=None, root_devic }}; """.format( 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 += """ }; @@ -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_width = d["constants"]["video_framebuffer_hres"] 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 += """ framebuffer0: framebuffer@{framebuffer_base:x} {{ compatible = "simple-framebuffer"; @@ -498,14 +502,15 @@ def generate_dts(d, initrd_start=None, initrd_size=None, initrd=None, root_devic width = <{framebuffer_width}>; height = <{framebuffer_height}>; stride = <{framebuffer_stride}>; - format = "a8b8g8r8"; + format = "{framebuffer_format}"; }}; """.format( framebuffer_base = framebuffer_base, framebuffer_width = framebuffer_width, framebuffer_height = framebuffer_height, - framebuffer_size = framebuffer_width * framebuffer_height * 4, - framebuffer_stride = framebuffer_width * 4) + framebuffer_size = framebuffer_width * framebuffer_height * (framebuffer_depth//8), + framebuffer_stride = framebuffer_width * (framebuffer_depth//8), + framebuffer_format = framebuffer_format) # ICAP Bitstream -------------------------------------------------------------------------------