Last active
October 23, 2017 05:53
-
-
Save adamgreig/b4d6711cbd8bbd3e881c07b0d16f5841 to your computer and use it in GitHub Desktop.
migen lfsr on de0-nano
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from migen import Module, Signal, ClockDomain, Instance | |
from migen.build.platforms import de0nano | |
# Load the DE0-Nano platform and request resources | |
plat = de0nano.Platform() | |
led = plat.request("user_led") | |
pins = plat.request("gpio_0") | |
clk50 = plat.request("clk50") | |
class PLL(Module): | |
"""Helper for instantiating onboard PLLs""" | |
def __init__(self, period_in, name, phase_shift, operation_mode): | |
self.clk_in = Signal() | |
self.clk_out = Signal() | |
self.specials += Instance("ALTPLL", | |
p_bandwidth_type="AUTO", | |
p_clk0_divide_by=1, | |
p_clk0_duty_cycle=50, | |
p_clk0_multiply_by=8, | |
p_clk0_phase_shift="{}".format( | |
str(phase_shift)), | |
p_compensate_clock="CLK0", | |
p_inclk0_input_frequency=int(period_in*1000), | |
p_intended_device_family="Cyclone IV E", | |
p_lpm_hint="CBX_MODULE_PREFIX={}_pll" | |
.format(name), | |
p_lpm_type="altpll", | |
p_operation_mode=operation_mode, | |
i_inclk=self.clk_in, | |
o_clk=self.clk_out, | |
i_areset=0, | |
i_clkena=0x3f, | |
i_clkswitch=0, | |
i_configupdate=0, | |
i_extclkena=0xf, | |
i_fbin=1, | |
i_pfdena=1, | |
i_phasecounterselect=0xf, | |
i_phasestep=1, | |
i_phaseupdown=1, | |
i_pllena=1, | |
i_scanaclr=0, | |
i_scanclk=0, | |
i_scanclkena=1, | |
i_scandata=0, | |
i_scanread=0, | |
i_scanwrite=0) | |
class CRG(Module): | |
"""Manual clock and reset generator, so that we can use the PLL | |
and our custom clock domains. | |
""" | |
def __init__(self, clk50): | |
self.clock_domains.cd_sys = ClockDomain() | |
self.clock_domains.cd_por = ClockDomain(reset_less=True) | |
sys_pll = PLL(20, "sys", 0, "NORMAL") | |
self.submodules += sys_pll | |
self.comb += [ | |
sys_pll.clk_in.eq(clk50), | |
self.cd_sys.clk.eq(sys_pll.clk_out) | |
] | |
# Power on Reset (vendor agnostic) | |
rst_n = Signal() | |
self.sync.por += rst_n.eq(1) | |
self.comb += [ | |
self.cd_por.clk.eq(self.cd_sys.clk), | |
self.cd_sys.rst.eq(~rst_n), | |
] | |
# Make our LFSR module with our custom clocking and reset | |
m = Module() | |
m.submodules.crg = CRG(clk50) | |
# Set up an LFSR clock domain running off a divider | |
counter = Signal(26) | |
m.sync += counter.eq(counter + 1) | |
lfsrclk = counter[1] | |
m.clock_domains.lfsr = ClockDomain("lfsr", reset_less=True) | |
m.comb += m.lfsr.clk.eq(lfsrclk) | |
# The LFSR register itself | |
lfsr = Signal(16, reset=1) | |
m.sync.lfsr += [lfsr[x].eq(lfsr[x+1]) for x in (0, 1, 2, 3, 4, 5, 6, 7, 8, 9)] | |
m.sync.lfsr += lfsr[10].eq(lfsr[11] ^ lfsr[0]) | |
m.sync.lfsr += lfsr[11].eq(lfsr[12]) | |
m.sync.lfsr += lfsr[12].eq(lfsr[13] ^ lfsr[0]) | |
m.sync.lfsr += lfsr[13].eq(lfsr[14] ^ lfsr[0]) | |
m.sync.lfsr += lfsr[14].eq(lfsr[15]) | |
m.sync.lfsr += lfsr[15].eq(lfsr[0]) | |
# Output the LFSR register to the GPIO | |
m.comb += [pins[idx].eq(lfsr[idx]) for idx in range(16)] | |
# Output the LFSR output bit and clock | |
m.comb += pins[23].eq(lfsr[0]) | |
m.comb += pins[22].eq(lfsrclk) | |
# Blink LED off the divider to show activity | |
m.comb += led.eq(counter[25]) | |
# Build this module and then program it onto the FPGA | |
plat.build(m) | |
prog = plat.create_programmer() | |
prog.load_bitstream("build/top.sof") |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment