Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import argparse
- from nmigen import *
- from nmigen.build import Platform
- from nmigen_boards.ulx3s import *
- from blink import Blink
- from vga2dvi import VGA2DVI
- from vga import VGA
- from ecp5pll import ECP5PLL
- # modes tested on lenovo monitor
- # 640x400 @50Hz
- # 640x400 @60Hz
- # 640x480 @50Hz
- # 640x480 @60Hz
- # 720x576 @50Hz
- # 720x576 @60Hz
- # 800x480 @60Hz
- # 800x600 @60Hz
- # 1024x768 @60Hz
- # 1280x768 @60Hz
- # 1366x768 @60Hz
- # 1280x1024 @60Hz
- # 1920x1080 @30Hz
- # 1920x1080 @50Hz overclock 540MHz
- # 1920x1200 @50Hz overclock 600MHz
- class TopVGATest(Elaboratable):
- def __init__(self,
- x=640, # pixels
- y=480, # pixels
- f=60, # Hz (60, 50, 30)
- xadjustf=0, # adjust -3..3 if no picture
- yadjustf=0, # or to fine-tune f
- ddr=True): # False: SDR, True: DDR
- self.i_btn = Signal(7)
- self.o_led = Signal(8)
- self.o_gpdi_dp = Signal(4)
- self.o_user_programn = Signal()
- self.o_wifi_gpio0 = Signal()
- # Configuration
- self.x = x
- self.y = y
- self.f = f
- self.xadjustf = xadjustf
- self.yadjustf = yadjustf
- self.ddr = ddr
- def find_next_f(self, f):
- next_f = 0
- if (f < 25e6):
- next_f = 25e6
- elif (f > 27e6):
- next_f = 27e6
- elif (f > 40e6):
- next_f = 40e6
- elif (f > 50e6):
- next_f = 50e6
- elif (f > 54e6):
- next_f = 54e6
- elif (f > 60e6):
- next_f = 60e6
- elif (f > 65e6):
- next_f = 65e6
- elif (f > 75e6):
- next_f = 75e6
- elif (f > 80e6):
- next_f = 80e6
- elif (f > 100e6):
- next_f = 100e6
- elif (f > 108e6):
- next_f = 108e6
- elif (f > 120e6):
- next_f = 120e6
- return next_f
- def elaborate(self, platform: Platform) -> Module:
- m = Module()
- if platform:
- clk_in = platform.request(platform.default_clk, dir='-')[0]
- # Constants
- xminblank = self.x // 64 # Initial estimate
- yminblank = self.y // 64 # for minimal blank space
- min_pixel_f = self.f * (self.x + xminblank) * (self.y * yminblank)
- pixel_f = self.find_next_f(min_pixel_f)
- yframe = self.y + yminblank
- xframe = pixel_f // (self.f * yframe)
- xblank = xframe - self.x
- yblank = yframe - self.y
- hsync_front_porch = xblank // 3
- hsync_pulse_width = xblank // 3
- hsync_back_porch = xblank - hsync_pulse_width - hsync_front_porch + self.xadjustf
- vsync_front_porch = yblank // 3
- vsync_pulse_width = yblank // 3
- vsync_back_porch = yblank - vsync_pulse_width - vsync_front_porch + self.yadjustf
- # o_wifi_gpio0 = 1 keeps board from rebooting
- # Hold btn0 to let ESP32 take control of the board.
- m.d.comb += self.o_wifi_gpio0.eq(self.i_btn[0])
- # Press btn0 to exit this bitstream.
- R_delay_reload = Signal(20, reset=0)
- with m.If(R_delay_reload[19] == 0):
- m.d.sync += R_delay_reload.eq(R_delay_reload + 1)
- m.d.comb += self.o_user_programn.eq(self.i_btn[0] | ~R_delay_reload[19])
- # Clock generator.
- m.domains.sync = cd_sync = ClockDomain("sync")
- m.domains.pixel = cd_pixel = ClockDomain("pixel")
- m.domains.shift = cd_shift = ClockDomain("shift")
- m.submodules.ecp5pll = pll = ECP5PLL()
- pll.register_clkin(clk_in, platform.default_clk_frequency)
- pll.create_clkout(cd_sync, platform.default_clk_frequency)
- pll.create_clkout(cd_shift, pixel_f)
- pll.create_clkout(cd_pixel, pixel_f * 5.0 * (1.0 if self.ddr else 2.0))
- # VGA signal generator.
- vga_r = Signal(8)
- vga_g = Signal(8)
- vga_b = Signal(8)
- vga_hsync = Signal()
- vga_vsync = Signal()
- vga_blank = Signal()
- m.submodules.vga = vga = VGA(
- resolution_x = self.x,
- hsync_front_porch = hsync_front_porch,
- hsync_pulse = hsync_pulse_width,
- hsync_back_porch = hsync_back_porch,
- resolution_y = self.y,
- vsync_front_porch = vsync_front_porch,
- vsync_pulse = vsync_pulse_width,
- vsync_back_porch = vsync_back_porch,
- bits_x = 11,
- bits_y = 11
- )
- m.d.comb += [
- vga.i_clk_en.eq(1),
- vga.i_test_picture.eq(1),
- vga.i_r.eq(0),
- vga.i_g.eq(0),
- vga.i_b.eq(0),
- vga_r.eq(vga.o_vga_r),
- vga_g.eq(vga.o_vga_g),
- vga_b.eq(vga.o_vga_b),
- vga_hsync.eq(vga.o_vga_hsync),
- vga_vsync.eq(vga.o_vga_vsync),
- vga_blank.eq(vga.o_vga_blank),
- ]
- # VGA to digital video converter.
- tmds = [Signal(2) for i in range(4)]
- m.submodules.vga2dvid = vga2dvid = VGA2DVI()
- m.d.comb += [
- vga2dvid.i_red.eq(vga_r),
- vga2dvid.i_green.eq(vga_g),
- vga2dvid.i_blue.eq(vga_b),
- vga2dvid.i_hsync.eq(vga_hsync),
- vga2dvid.i_vsync.eq(vga_vsync),
- vga2dvid.i_blank.eq(vga_blank),
- tmds[3].eq(vga2dvid.o_clk),
- tmds[2].eq(vga2dvid.o_red),
- tmds[1].eq(vga2dvid.o_green),
- tmds[0].eq(vga2dvid.o_blue),
- ]
- # LED blinky
- counter_width = 28
- countblink = Signal(8)
- m.submodules.blink = blink = Blink(counter_width)
- m.d.comb += [
- countblink.eq(blink.o_led),
- self.o_led[6:8].eq(countblink[6:8]),
- self.o_led[0].eq(vga_vsync),
- self.o_led[1].eq(vga_hsync),
- self.o_led[2].eq(vga_blank),
- ]
- # if (self.ddr):
- # # Vendor specific DDR modules.
- # # Convert SDR 2-bit input to DDR clocked 1-bit output (single-ended)
- # # onboard GPDI.
- # m.submodules.ddr0_clock = ODDRX1F()
- # m.submodules.ddr0_red = ODDRX1F()
- # m.submodules.ddr0_green = ODDRX1F()
- # m.submodules.ddr0_blue = ODDRX1F()
- # else:
- m.d.comb += [
- self.o_gpdi_dp[3].eq(tmds[3][0]),
- self.o_gpdi_dp[2].eq(tmds[2][0]),
- self.o_gpdi_dp[1].eq(tmds[1][0]),
- self.o_gpdi_dp[0].eq(tmds[0][0]),
- ]
- return m
- if __name__ == "__main__":
- variants = {
- '12F': ULX3S_12F_Platform,
- '25F': ULX3S_25F_Platform,
- '45F': ULX3S_45F_Platform,
- '85F': ULX3S_85F_Platform
- }
- # Figure out which FPGA variant we want to target...
- parser = argparse.ArgumentParser()
- parser.add_argument('variant', choices=variants.keys())
- args = parser.parse_args()
- #platform = variants[args.variant]
- platform = ULX3S_85F_Platform
- m = Module()
- m.submodules.top = top = TopVGATest(ddr=False)
- #leds = platform.request("led", 0)
- #btns = platform.request("button", 0)
- btns = [platform.request("button_pwr"),
- platform.request("button_fire", 0),
- platform.request("button_fire", 1),
- platform.request("button_up"),
- platform.request("button_down"),
- platform.request("button_left"),
- platform.request("button_right")]
- for i in range(len(btns)):
- m.d.comb += top.i_btn[i].eq(btns[i])
- platform().build(m, do_program=False)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement