import "/collections/namedtuple" import "/nmigen/lib/cdc/ResetSynchronizer" import "/nmigen_boards.icebreaker/ICEBreakerPlatform" import "/nmigen_dg/*" import "/subprocess" import "/sys" import "common/pipeline" import "common/to_signed" import "modules/vga/DviController12" import "resources/pmod" run_icepll = current target -> current /= 1e6 # Hz -> MHz target /= 1e6 # Hz -> MHz out = subprocess.run ["icepll", "-i", str current, "-o", str target] capture_output: True check: True get_field = field substring:None -> pipeline out.stdout.decode!.splitlines! bind filter $ x -> x.startswith field if substring => bind filter $ x -> substring in x otherwise => x -> x # nop head str.split tail head (namedtuple "icepll_config" "FEEDBACK FILTER_RANGE DIVR DIVF DIVQ given requested achieved") str$ get_field "FEEDBACK" int$ get_field "FILTER_RANGE" int$ get_field "DIVR" int$ get_field "DIVF" int$ get_field "DIVQ" float$ get_field "F_PLLIN" float$ get_field "F_PLLOUT" "(requested)" float$ get_field "F_PLLOUT" "(achieved)" Top = subclass Elaboratable where elaborate = platform ~> m where with m = Module! => # Configure DVI controller dvi = Submodule$ DviController12 x:800 y:480 fps:60 # setup clock default_clk = platform.request platform.default_clk dir:"-" default_freq = platform.default_clk_frequency default_reset = if platform.default_rst => platform.request platform.default_rst otherwise => Const 1 pll_config = run_icepll default_freq dvi.pix_freq print dvi.timings print pll_config pll_clk, pll_lock = Signal!, Signal! Submodule.pll$ Instance "SB_PLL40_PAD" # "SB_PLL40_CORE" i_PACKAGEPIN : default_clk # i_REFERENCECLK i_BYPASS : (Const 0) i_RESETB : default_reset o_LOCK : pll_lock o_PLLOUTGLOBAL : pll_clk p_FEEDBACK_PATH : pll_config.FEEDBACK p_FILTER_RANGE : pll_config.FILTER_RANGE p_DIVR : pll_config.DIVR p_DIVF : pll_config.DIVF p_DIVQ : pll_config.DIVQ Domains.sync = ClockDomain "sync" Comb$ ClockSignal "sync" :== pll_clk Submodule.rs$ ResetSynchronizer ~pll_lock domain: "sync" # Feed a picture to the DVI controller scroll = Signal 8 period = int (pll_config.achieved / 60) counter = Signal$ range period Sync$ counter :== counter - 1 When (counter==0) $ -> Sync$ counter :== int period Sync$ scroll :== scroll + 1 Sync$ dvi.r :== 0x0 Sync$ dvi.g :== 0x0 Sync$ dvi.b :== 0x0 cx = to_signed dvi.pixel_x - (800//2) cy = to_signed dvi.pixel_y - (480//2) rx = cx*cx ry = cy*cy tx1 = (dvi.pixel_x - scroll) & (1<<5) ty1 = (dvi.pixel_y - scroll) & (1<<5) tx2 = (dvi.pixel_x + scroll) & (1<<6) ty2 = (dvi.pixel_y + scroll + 40) & (1<<6) When rx + ry < 200**2 ,-> Sync$ dvi.r :== 0xF #Sync$ dvi.g :== 0xF Sync$ dvi.b :== 0xF tx1 ^ ty1 ,-> Sync$ dvi.b :== 0xF tx2 ^ ty2 ,-> Sync$ dvi.r :== 0xF Sync$ dvi.g :== 0xF if __name__ == "__main__" => plat = ICEBreakerPlatform! plat.add_resources$ pmod.dvi_12bit 0 plat.add_resources$ plat.break_off_pmod plat.build Top! do_program: ("--flash" in sys.argv) synth_opts: "-dsp"