From 7e3b8ab3b52dc33e8897cbf908d1470bf226c14b Mon Sep 17 00:00:00 2001 From: Florent Kermarrec Date: Wed, 3 Mar 2021 16:21:04 +0100 Subject: [PATCH] icebreaker: Add optional DVI Video Terminal with new LiteX's VideoOut core. Tested with: ./icebreaker.py --cpu-type=serv --with-video-terminal --build --flash https://twitter.com/enjoy_digital/status/1365324823447171074 --- litex_boards/platforms/icebreaker.py | 13 ++++++++ litex_boards/targets/icebreaker.py | 45 +++++++++++++++++++++------- 2 files changed, 48 insertions(+), 10 deletions(-) diff --git a/litex_boards/platforms/icebreaker.py b/litex_boards/platforms/icebreaker.py index 94d36e9..4f62709 100644 --- a/litex_boards/platforms/icebreaker.py +++ b/litex_boards/platforms/icebreaker.py @@ -83,6 +83,19 @@ break_off_pmod = [ ("user_ledg", 3, Pins("PMOD2:2"), IOStandard("LVCMOS33")) ] +dvi_pmod = [ + ("dvi", 0, + Subsignal("clk", Pins("PMOD1B:1")), + Subsignal("de", Pins("PMOD1B:6")), + Subsignal("hsync", Pins("PMOD1B:3")), + Subsignal("vsync", Pins("PMOD1B:7")), + Subsignal("r", Pins("PMOD1A:5 PMOD1A:1 PMOD1A:4 PMOD1A:0")), + Subsignal("g", Pins("PMOD1A:7 PMOD1A:3 PMOD1A:6 PMOD1A:2")), + Subsignal("b", Pins("PMOD1B:2 PMOD1B:5 PMOD1B:4 PMOD1B:0")), + IOStandard("LVCMOS33"), + ) +] + # Platform ----------------------------------------------------------------------------------------- class Platform(LatticePlatform): diff --git a/litex_boards/targets/icebreaker.py b/litex_boards/targets/icebreaker.py index f56fa5d..5789f8d 100755 --- a/litex_boards/targets/icebreaker.py +++ b/litex_boards/targets/icebreaker.py @@ -32,6 +32,7 @@ from litex.soc.integration.soc_core import * from litex.soc.integration.soc import SoCRegion from litex.soc.integration.builder import * from litex.soc.cores.led import LedChaser +from litex.soc.cores.video import * kB = 1024 mB = 1024*kB @@ -69,7 +70,7 @@ class _CRG(Module): class BaseSoC(SoCCore): mem_map = {**SoCCore.mem_map, **{"spiflash": 0x80000000}} - def __init__(self, bios_flash_offset, sys_clk_freq=int(24e6), **kwargs): + def __init__(self, bios_flash_offset, sys_clk_freq=int(24e6), with_video_terminal=False, **kwargs): platform = icebreaker.Platform() platform.add_extension(icebreaker.break_off_pmod) @@ -77,6 +78,10 @@ class BaseSoC(SoCCore): kwargs["integrated_sram_size"] = 0 kwargs["integrated_rom_size"] = 0 + # Force sys_clk_freq with Video Terminal since iCE40's PLL only has 1 output. + if with_video_terminal: + sys_clk_freq = 40e6 + # Set CPU variant / reset address kwargs["cpu_reset_address"] = self.mem_map["spiflash"] + bios_flash_offset @@ -90,8 +95,8 @@ class BaseSoC(SoCCore): self.submodules.crg = _CRG(platform, sys_clk_freq) # 128KB SPRAM (used as SRAM) --------------------------------------------------------------- - self.submodules.spram = Up5kSPRAM(size=128*kB) - self.bus.add_slave("sram", self.spram.bus, SoCRegion(size=128*kB)) + self.submodules.spram = Up5kSPRAM(size=64*kB) + self.bus.add_slave("sram", self.spram.bus, SoCRegion(size=64*kB)) # SPI Flash -------------------------------------------------------------------------------- self.add_spi_flash(mode="1x", dummy_cycles=8) @@ -103,6 +108,24 @@ class BaseSoC(SoCCore): linker = True) ) + # Video Terminal --------------------------------------------------------------------------- + if with_video_terminal: + self.platform.add_extension(icebreaker.dvi_pmod) + self.submodules.vtg = vtg = VideoTimingGenerator(default_video_timings="800x600@60Hz") + self.add_csr("vtg") + #self.submodules.vgen = vgen = ColorBarsPattern() + self.submodules.vgen = vgen = VideoTerminal(hres=800, vres=600) + self.submodules.vphy = vphy = VideoDVIPHY(platform.request("dvi"), clock_domain="sys") + self.comb += [ + # Connect UART to Video Terminal. + vgen.uart_sink.valid.eq(self.uart.source.valid & self.uart.source.ready), + vgen.uart_sink.data.eq(self.uart.source.data), + # Connect Video Timing Generator to Video Terminal. + vtg.source.connect(vgen.vtg_sink), + # Connect VideoTerminal to VideoDVIPHY. + vgen.source.connect(vphy.sink), + ] + # Leds ------------------------------------------------------------------------------------- self.submodules.leds = LedChaser( pads = platform.request_all("user_led"), @@ -122,18 +145,20 @@ def flash(bios_flash_offset): def main(): parser = argparse.ArgumentParser(description="LiteX SoC on iCEBreaker") - parser.add_argument("--build", action="store_true", help="Build bitstream") - parser.add_argument("--load", action="store_true", help="Load bitstream") - parser.add_argument("--flash", action="store_true", help="Flash Bitstream") - parser.add_argument("--sys-clk-freq", default=24e6, help="System clock frequency (default: 24MHz)") - parser.add_argument("--bios-flash-offset", default=0x40000, help="BIOS offset in SPI Flash (default: 0x40000)") + parser.add_argument("--build", action="store_true", help="Build bitstream") + parser.add_argument("--load", action="store_true", help="Load bitstream") + parser.add_argument("--flash", action="store_true", help="Flash Bitstream") + parser.add_argument("--sys-clk-freq", default=24e6, help="System clock frequency (default: 24MHz)") + parser.add_argument("--bios-flash-offset", default=0x40000, help="BIOS offset in SPI Flash (default: 0x40000)") + parser.add_argument("--with-video-terminal", action="store_true", help="Enable Video Terminal (with DVI PMOD)") builder_args(parser) soc_core_args(parser) args = parser.parse_args() soc = BaseSoC( - bios_flash_offset = args.bios_flash_offset, - sys_clk_freq = int(float(args.sys_clk_freq)), + bios_flash_offset = args.bios_flash_offset, + sys_clk_freq = int(float(args.sys_clk_freq)), + with_video_terminal = args.with_video_terminal, **soc_core_argdict(args) ) builder = Builder(soc, **builder_argdict(args))