def elaborate(self, platform): # For virtual platforms just use a regular counter if platform is None: m = Module() counter = Signal(2) domain = getattr(m.d, self.indomain) domain += counter.eq(counter + 1) m.domains += ClockDomain(self.outdomain, reset_less=True) m.d.comb += ClockSignal(self.outdomain).eq(counter[1]) return m m = Module() clkin = Signal() # Buffered output of input clock, into PLL clkfbout = Signal() # Unbuffered feedback out of PLL clkfbout_buf = Signal() # Buffered feedback into PLL clkout = Signal() # Unbuffered output from PLL div4clk = Signal() # Buffered output of output clock m.submodules.clockdiv = Instance("PLLE2_ADV", p_BANDWIDTH="OPTIMIZED", p_COMPENSATION="ZHOLD", p_STARTUP_WAIT="FALSE", p_DIVCLK_DIVIDE=1, p_CLKFBOUT_MULT=4, p_CLKFBOUT_PHASE=0.000, p_CLKOUT0_DIVIDE=16, p_CLKOUT0_PHASE=0.000, p_CLKOUT0_DUTY_CYCLE=0.500, p_CLKIN1_PERIOD=4.000, o_CLKFBOUT=clkfbout, o_CLKOUT0=clkout, i_CLKFBIN=clkfbout_buf, i_CLKIN1=clkin, i_CLKIN2=0, i_CLKINSEL=1, i_DADDR=0, i_DCLK=0, i_DEN=0, i_DI=0, i_DWE=0, i_PWRDWN=0, i_RST=0) m.submodules.inbuf = Instance("BUFG", i_I=ClockSignal(self.indomain), o_O=clkin) m.submodules.outbuf = Instance("BUFG", i_I=clkout, o_O=div4clk) m.submodules.clockfb = Instance("BUFG", i_I=clkfbout, o_O=clkfbout_buf) m.domains += ClockDomain(self.outdomain, reset_less=True) m.d.comb += ClockSignal(self.outdomain).eq(div4clk) return m
def elaborate(self, platform): m = Module() for i, val in enumerate(self._clocks): if val is not None: clk, freq = val unbuf = Signal(name='pl_clk{}_unbuf'.format(i)) platform.add_clock_constraint(unbuf, freq) m.d.comb += unbuf.eq(self._ports[self.CLK][i]) buf = Instance('BUFG_PS', i_I=unbuf, o_O=clk) m.submodules['clk{}_buffer'.format(i)] = buf for i, rst in enumerate(self._resets): if rst is not None: m.d.comb += rst.eq(~self._ports['EMIOGPIOO'][-1 - i]) for i, irq in enumerate(self._irqs): if irq is not None: m.d.comb += self._ports[self.IRQ[i // 8]][i % 8].eq(irq) ps_i = Instance( 'PS8', a_DONT_TOUCH="true", **self._get_instance_ports(), ) m.submodules.ps_i = ps_i return m
def elaborate(self, platform): # For virtual platforms just alias the clocks if platform is None: m = Module() m.d.comb += self.clk120.eq(self.clk125) return m m = Module() clkin = Signal() # Buffered output of input clock, into PLL clkfbout = Signal() # Unbuffered feedback out of PLL clkfbout_buf = Signal() # Buffered feedback into PLL clkout = Signal() # Unbuffered output from PLL # VCO = inclk * clkfbout_mult / divclk_divide # = 125MHz * 48 / 5 # = 1200MHz # out = VCO / CLKOUT0_DIVIDE # = 1200MHz / 10 # = 120MHz m.submodules.clockdiv = Instance("PLLE2_ADV", p_BANDWIDTH="LOW", p_COMPENSATION="BUFIN", p_STARTUP_WAIT="FALSE", p_DIVCLK_DIVIDE=5, p_CLKFBOUT_MULT=48, p_CLKFBOUT_PHASE=0.000, p_CLKOUT0_DIVIDE=10, p_CLKOUT0_PHASE=0.000, p_CLKOUT0_DUTY_CYCLE=0.500, p_CLKIN1_PERIOD=8.000, o_CLKFBOUT=clkfbout, o_CLKOUT0=clkout, i_CLKFBIN=clkfbout_buf, i_CLKIN1=clkin, i_CLKIN2=0, i_CLKINSEL=1, i_DADDR=0, i_DCLK=0, i_DEN=0, i_DI=0, i_DWE=0, i_PWRDWN=0, i_RST=0) m.submodules.inbuf = Instance("BUFG", i_I=self.clk125, o_O=clkin) m.submodules.outbuf = Instance("BUFG", i_I=clkout, o_O=self.clk120) m.submodules.clockfb = Instance("BUFG", i_I=clkfbout, o_O=clkfbout_buf) return m
def elaborate(self, platform): m = Module() # Create our domains... m.domains.usb = ClockDomain() m.domains.usb_io = ClockDomain() m.domains.fast = ClockDomain() # ... and create our 12 MHz USB clock. m.submodules.pll = Instance( "SB_PLL40_CORE", i_REFERENCECLK=ClockSignal("sync"), i_RESETB=Const(1), i_BYPASS=Const(0), o_PLLOUTCORE=ClockSignal("usb"), # Create a 24 MHz PLL clock... p_FEEDBACK_PATH="SIMPLE", p_DIVR=0, p_DIVF=15, p_DIVQ=5, p_FILTER_RANGE=4, # ... and divide it by half to get 12 MHz. p_PLLOUT_SELECT="GENCLK_HALF") # We'll use our 48MHz clock for everything _except_ the usb_io domain... m.d.comb += [ ClockSignal("usb_io").eq(ClockSignal("sync")), ClockSignal("fast").eq(ClockSignal("sync")) ] return m
def elaborate(self, platform): m = Module() # Create our domains... m.domains.sync = ClockDomain() m.domains.usb = ClockDomain() m.domains.usb_io = ClockDomain() m.domains.fast = ClockDomain() # ... create our 48 MHz IO and 12 MHz USB clock... m.submodules.pll = Instance( "SB_PLL40_2F_CORE", i_REFERENCECLK=platform.request(platform.default_clk), i_RESETB=Const(1), i_BYPASS=Const(0), o_PLLOUTCOREA=ClockSignal("sync"), o_PLLOUTCOREB=ClockSignal("usb"), # Create a 48 MHz PLL clock... p_FEEDBACK_PATH="SIMPLE", p_PLLOUT_SELECT_PORTA="GENCLK", p_PLLOUT_SELECT_PORTB="SHIFTREG_0deg", p_DIVR=0, p_DIVF=47, p_DIVQ=4, p_FILTER_RANGE=1, ) # We'll use our 48MHz clock for everything _except_ the usb domain... m.d.comb += [ ClockSignal("usb_io").eq(ClockSignal("sync")), ClockSignal("fast").eq(ClockSignal("sync")) ] return m
def _generate_wide_incrementer(m, platform, adder_input): """ Attempts to create an optimal wide-incrementer for counters. Yosys on certain platforms (ice40 UltraPlus) doesn't currently use hardware resources effectively for wide adders. We'll manually instantiate the relevant resources to get rid of an 18-bit carry chain; avoiding a long critical path. Parameters: platform -- The platform we're working with. adder_input -- The input to our incrementer. """ # If this isn't an iCE40 UltraPlus, let Yosys do its thing. if (not platform) or not platform.device.startswith('iCE40UP'): return adder_input + 1 # Otherwise, we'll create a DSP adder itself. output = Signal.like(adder_input) m.submodules += Instance('SB_MAC16', # Hook up our inputs and outputs. # A = upper bits of input; B = lower bits of input i_A = adder_input[16:], i_B = adder_input[0:16], o_O = output, p_TOPADDSUB_UPPERINPUT =0b1, # Use as a normal adder p_TOPADDSUB_CARRYSELECT=0b11, # Connect our top and bottom adders together. p_BOTADDSUB_UPPERINPUT =0b1, # Use as a normal adder. p_BOTADDSUB_CARRYSELECT=0b01 # Always increment. ) return output
def elaborate(self, platform): m = Module() # Get the SDRAM pins dir_dict = { "a": "-", "ba": "-", "cke": "-", "clk": "-", "clk_en": "-", "dq": "-", "dqm": "-", "cas": "-", "cs": "-", "ras": "-", "we": "-", } sdram = platform.request("sdram", dir=dir_dict) # Create the controller m.submodules.ctrl = ctrl = Sdram() m.d.comb += [ # Set the chip output pins sdram.a.eq(ctrl.sd_addr), sdram.dqm.eq(ctrl.sd_dqm), sdram.ba.eq(ctrl.sd_ba), sdram.cs.eq(ctrl.sd_cs), sdram.we.eq(ctrl.sd_we), sdram.ras.eq(ctrl.sd_ras), sdram.cas.eq(ctrl.sd_cas), sdram.clk_en.eq(1), sdram.clk.eq(ClockSignal("sdram_clk")), # Set the controller input pins ctrl.init.eq(self.init), ctrl.din.eq(self.data_in), ctrl.addr.eq(self.address), ctrl.we.eq(self.req_write), ctrl.oe.eq(self.req_read), ctrl.sync.eq(self.sync), ctrl.ds.eq(C(0b11, 2)), # Set output pins self.data_out.eq(ctrl.dout) ] # Set dq to input or output depending on sd_data_dir for i in range(16): dq_io = Instance("BB", io_B=sdram.dq[i], i_T=~ctrl.sd_data_dir, i_I=ctrl.sd_data_out[i], o_O=ctrl.sd_data_in[i]) m.submodules += dq_io return m
def elaborate(self, platform): args = {f"p_{key.upper()}": val for (key, val) in self.params.items()} for port, (dirn, shape) in self.ports.items(): if port.lower() in self.ports_used: args[f"{dirn}_{port}"] = self.ports_used[port.lower()] elif self.defaults and port in self.defaults: args[f"{dirn}_{port}"] = self.defaults[port] elif port in self.required_ports: raise ValueError(f"{self.itype}: Required port {port} missing") return Instance(self.itype, **args)
def elaborate(self, platform: Platform) -> Module: m = Module() for ip_name in self._ips.keys(): args = getattr(self, ip_name) try: inst = Instance(ip_name, **args) setattr(m.submodules, ip_name, inst) except TypeError: error(f"couldn't create instance of {ip_name} " f"using args: {args}") return m
def elaborate(self, platform): m = Module() locked = Signal() # Create our domains... m.domains.sync = ClockDomain() m.domains.usb = ClockDomain() m.domains.usb_io = ClockDomain() m.domains.fast = ClockDomain() # ... create our 48 MHz IO and 12 MHz USB clock... clk48 = Signal() clk12 = Signal() m.submodules.pll = Instance("SB_PLL40_2F_CORE", i_REFERENCECLK = platform.request(platform.default_clk), i_RESETB = Const(1), i_BYPASS = Const(0), o_PLLOUTCOREA = clk48, o_PLLOUTCOREB = clk12, o_LOCK = locked, # Create a 48 MHz PLL clock... p_FEEDBACK_PATH = "SIMPLE", p_PLLOUT_SELECT_PORTA = "GENCLK", p_PLLOUT_SELECT_PORTB = "SHIFTREG_0deg", p_DIVR = 0, p_DIVF = 47, p_DIVQ = 4, p_FILTER_RANGE = 1, ) # ... and constrain them to their new frequencies. platform.add_clock_constraint(clk48, 48e6) platform.add_clock_constraint(clk12, 12e6) # We'll use our 48MHz clock for everything _except_ the usb domain... m.d.comb += [ ClockSignal("usb") .eq(clk12), ClockSignal("sync") .eq(clk48), ClockSignal("usb_io") .eq(clk48), ClockSignal("fast") .eq(clk48), ResetSignal("usb") .eq(~locked), ResetSignal("sync") .eq(~locked), ResetSignal("usb_io") .eq(~locked), ResetSignal("fast") .eq(~locked) ] return m
def elaborate(self, platform): m = Module() m.submodules.demoaxi_i = Instance( 'demoaxi', p_C_S_AXI_DATA_WIDTH=self.data_w, p_C_S_AXI_ADDR_WIDTH=self.addr_w, i_S_AXI_ACLK=ClockSignal(self.domain), i_S_AXI_ARESETN=~ResetSignal(self.domain), **get_ports_for_instance(self.axilite, prefix='S_AXI_'), ) if isinstance(platform, Platform): for d in self.DEPENDENCIES: add_verilog_file(platform, d) return m
def elaborate(self, platform): m = Module() import os dir_path = os.path.dirname(os.path.realpath(__file__)) with open(dir_path + "/sdram_controller.v") as f: platform.add_file("sdram_controller.v", f.read()) dir_dict = { "a": "-", "ba": "-", "cke": "-", "clk": "-", "clk_en": "-", "dq": "-", "dqm": "-", "cas": "-", "cs": "-", "ras": "-", "we": "-", } sdram = platform.request("sdram", dir=dir_dict) m.submodules += Instance( "sdram_controller", i_CLOCK_50=ClockSignal("compute"), i_CLOCK_100=ClockSignal("sdram"), i_CLOCK_100_del_3ns=ClockSignal("sdram_180_deg"), i_rst=ResetSignal("sdram"), i_address=self.address, i_req_read=self.req_read, i_req_write=self.req_write, i_data_in=self.data_in, o_data_out=self.data_out, o_data_valid=self.data_valid, o_write_complete=self.write_complete, o_DRAM_ADDR=sdram.a, o_DRAM_BA=sdram.ba, o_DRAM_CKE=sdram.clk_en, o_DRAM_CLK=sdram.clk, io_DRAM_DQ=sdram.dq, o_DRAM_DQM=sdram.dqm, o_DRAM_CAS_N=sdram.cas, o_DRAM_CS_N=sdram.cs, o_DRAM_RAS_N=sdram.ras, o_DRAM_WE_N=sdram.we) return m
def elaborate(self, platform): m = Module() locked = Signal() # Create our domains... m.domains.sync = ClockDomain() m.domains.pol = ClockDomain() # clocks 50 MHz circuit # 1 MHz update frequency motor clk50 = Signal() # clk1 = Signal() # details see iCE40 sysCLOCK PLL Design and Usage # settings comment out are for SB_PLL40_2F_CORE m.submodules.pll = \ Instance("SB_PLL40_CORE", i_REFERENCECLK=platform.request(platform.default_clk), i_RESETB=Const(1), # i_BYPASS=Const(0), o_PLLOUTGLOBAL=clk50, o_LOCK=locked, # Create a 50 MHz PLL clock... p_FEEDBACK_PATH="SIMPLE", # internally generated PLL # p_PLLOUT_SELECT_PORTA="GENCLK", # p_PLLOUT_SELECT_PORTB="SHIFTREG_0deg", p_DIVR=0, p_DIVF=7, p_DIVQ=4, p_FILTER_RANGE=5, ) # ... and constrain them to their new frequencies. platform.add_clock_constraint(clk50, 50e6) # platform.add_clock_constraint(clk1, 1e6) # We'll use our 50MHz clock for everything _except_ the polynomal # which create ticks for the motors m.d.comb += [ # ClockSignal("pol").eq(clk1), ClockSignal("sync").eq(clk50), # ResetSignal("pol").eq(~locked), ResetSignal("sync").eq(~locked), ] return m
def elaborate(self, platform): m = Module() # Create our domains... m.domains.sync = ClockDomain() m.domains.usb = ClockDomain() m.domains.usb_io = ClockDomain() m.domains.fast = ClockDomain() # ... ensure our clock is never instantiated with a Global buffer. platform.lookup(platform.default_clk).attrs['GLOBAL'] = False # ... create our 48 MHz IO and 12 MHz USB clocks... clk48 = Signal() clk12 = Signal() m.submodules.pll = Instance( "SB_PLL40_2F_PAD", i_PACKAGEPIN=platform.request(platform.default_clk, dir="i"), i_RESETB=Const(1), i_BYPASS=Const(0), o_PLLOUTGLOBALA=clk48, o_PLLOUTGLOBALB=clk12, # Create a 48 MHz PLL clock... p_FEEDBACK_PATH="SIMPLE", p_PLLOUT_SELECT_PORTA="GENCLK", p_PLLOUT_SELECT_PORTB="SHIFTREG_0deg", p_DIVR=0, p_DIVF=63, p_DIVQ=4, p_FILTER_RANGE=1, ) # ... and constrain them to their new frequencies. platform.add_clock_constraint(clk48, 48e6) platform.add_clock_constraint(clk12, 12e6) # We'll use our 48MHz clock for everything _except_ the usb domain... m.d.comb += [ ClockSignal("usb_io").eq(clk48), ClockSignal("fast").eq(clk48), ClockSignal("sync").eq(clk48), ClockSignal("usb").eq(clk12) ] return m
def delay(m, signal, interval, *, out=None): """ Creates a delayed copy of a given I/O signal. Currently only works at the FPGA's I/O boundary, and only on ECP5s. Parameters: signal -- The signal to be delayed. Must be either an I/O signal connected directly to a platform resource. delay -- Delay, in arbitrary units. These units will vary from unit to unit, but seem to be around 300ps on most ECP5 FPGAs. On ECP5s, maxes out at 127. out -- The signal to received the delayed signal; or None ot have a signal created for you. Returns: delayed -- The delayed signal. Will be equivalent to 'out' if provided; or a new signal otherwise. """ # If we're not being passed our output signal, create one. if out is None: out = Signal.like(signal) # If we have more than one signal, call this function on each # of the subsignals. if len(signal) > 1: # If we have a vector of signals, but a integer delay, # convert that integer to a vector of same-valued delays. if isinstance(interval, int): interval = [interval] * len(signal) return Cat( delay(m, s, d, out=o) for s, d, o in zip(signal, interval, out)) # # Base case: create a delayed version of the relevant signal. # m.submodules += Instance("DELAYG", i_A=signal, o_Z=out, p_DEL_VALUE=interval) return out
def elaborate(self, platform: Platform) -> Module: m = Module() instance_args = {} for internal_name, ports in _group_by_internal_name(self._ports): # Ports must be groupped to allow connecting # multiple ports into one, wider port # # ext_name1[7:6] ---\ # ext_name2[5:4] ----*-- internal_name[7:0] # [fillers] ---/ # ext_name3[1:0] ---/ # Ports must be sorted. # The order of concatentation is : Cat(a,b,c) == cba ports_sorted = sorted(ports, key=lambda p: p.bounds[2]) prefix = port_direction_to_prefix(ports_sorted[0].direction) # fill the empty slices in the list with Signals # the list is iterated starting from last position # in order not to change indices # or mess up when en alement is inserted for i in range(len(ports_sorted) - 2, -1, -1): port1 = ports_sorted[i] port2 = ports_sorted[i + 1] if (isinstance(port1, WrapperPort) and isinstance(port2, WrapperPort)): diff = port2.bounds[3] - port1.bounds[2] - 1 if diff > 0: ports_sorted = (ports_sorted[:i + 1] + [Signal(diff)] + ports_sorted[i + 1:]) diff = ports_sorted[0].bounds[3] # insert signal in front, if the first doesn't start from 0 if diff > 0: ports_sorted = [Signal(diff)] + ports_sorted instance_args[prefix + internal_name] = Cat(*ports_sorted) instance_args = {**instance_args, **self._parameters} m.submodules.ip = Instance(self.ip_name, **instance_args) return m
def elaborate(self, platform): m = Module() if platform is not None: # platform.default_clk_frequency is in Hz coeff = self._calc_freq_coefficients( platform.default_clk_frequency / 1_000_000, self.freq_out) # clk_pin = platform.request(platform.default_clk) lock = Signal() pll = Instance( "SB_PLL40_CORE", p_FEEDBACK_PATH='SIMPLE', p_DIVR=coeff.divr, p_DIVF=coeff.divf, p_DIVQ=coeff.divq, p_FILTER_RANGE=0b001, p_DELAY_ADJUSTMENT_MODE_FEEDBACK='FIXED', p_FDA_FEEDBACK=0b0000, p_DELAY_ADJUSTMENT_MODE_RELATIVE='FIXED', p_FDA_RELATIVE=0b0000, p_SHIFTREG_DIV_MODE=0b00, p_PLLOUT_SELECT='GENCLK', p_ENABLE_ICEGATE=0b0, i_REFERENCECLK=ClockSignal(), o_PLLOUTCORE=ClockSignal(self.domain_name), i_RESETB=ResetSignal(), i_BYPASS=Const(0), o_LOCK=lock, ) rs = ResetSynchronizer(~lock, domain=self.domain_name) m.submodules += [pll, rs] m.domains += ClockDomain(self.domain_name) return m
def elaborate(self, platform): m = Module() # Get the ECP5 block that's responsible for driving the MCLK pin, # and drive it using our SCK line. user_mclk = Instance('USRMCLK', i_USRMCLKI=self.sck, i_USRMCLKTS=0) m.submodules += user_mclk # Connect up each of our other signals. m.d.comb += [ self.bus.sdi .eq(self.sdi), self.sdo .eq(self.bus.sdo) ] if self.use_cs: m.d.comb += [ self.bus.cs.o.eq(self.cs), self.bus.cs.oe.eq(1) ] else: m.d.comb += self.bus.cs.oe.eq(0) return m
def elaborate(self, platform): m = Module() # Create our clock domains. m.domains.fast = ClockDomain() m.domains.sync = ClockDomain() m.domains.usb = ClockDomain() m.domains.clkref = ClockDomain() # Grab our clock and global reset signals. clk_16m384 = platform.request(platform.default_clk) # reset = platform.request(platform.default_rst) # Generate the clocks we need for our PLL. feedback = Signal() locked = Signal() m.submodules.pll = Instance( "EHXPLLL", i_CLKI=clk_16m384, o_CLKOP=ClockSignal("fast"), o_CLKOS=ClockSignal("sync"), # Status. o_LOCK=locked, i_CLKFB=ClockSignal("fast"), # Control signals. i_RST=0, i_STDBY=0, # i_CLKINTFB = 0, i_PHASESEL0=0, i_PHASESEL1=0, i_PHASEDIR=1, i_PHASESTEP=1, i_PHASELOADREG=1, i_PLLWAKESYNC=0, i_ENCLKOP=0, i_ENCLKOS=0, i_ENCLKOS2=0, i_ENCLKOS3=0, p_PLLRST_ENA="DISABLED", p_INTFB_WAKE="DISABLED", p_STDBY_ENABLE="DISABLED", p_DPHASE_SOURCE="DISABLED", p_CLKI_DIV=1, p_CLKOP_ENABLE="ENABLED", p_CLKOP_DIV=4, p_CLKOP_CPHASE=1, p_CLKOP_FPHASE=0, # p_CLKOP_TRIM_DELAY = 0, # p_CLKOP_TRIM_POL = "FALLING", p_CLKOS_ENABLE="ENABLED", p_CLKOS_DIV=8, p_CLKOS_CPHASE=1, p_CLKOS_FPHASE=0, # p_CLKOS_TRIM_DELAY = 0, # p_CLKOS_TRIM_POL = "FALLING", p_FEEDBK_PATH="CLKOP", p_CLKFB_DIV=12, p_CLKOS3_FPHASE=0, p_CLKOS3_CPHASE=0, p_CLKOS2_FPHASE=0, p_CLKOS2_CPHASE=0, p_PLL_LOCK_MODE=0, p_OUTDIVIDER_MUXD="DIVD", p_CLKOS3_ENABLE="DISABLED", p_OUTDIVIDER_MUXC="DIVC", p_CLKOS2_ENABLE="DISABLED", p_OUTDIVIDER_MUXB="DIVB", p_OUTDIVIDER_MUXA="DIVA", p_CLKOS3_DIV=1, p_CLKOS2_DIV=1, # Synthesis attributes. a_FREQUENCY_PIN_CLKI="16.384000", a_FREQUENCY_PIN_CLKOP="196.608000", a_FREQUENCY_PIN_CLKOS="98.304000", a_ICP_CURRENT="12", a_LPF_RESISTOR="8", a_MFG_ENABLE_FILTEROPAMP="1", a_MFG_GMCREF_SEL="2", ) m.d.comb += [ ClockSignal("clkref").eq(clk_16m384), ResetSignal("sync").eq(~locked), ResetSignal("fast").eq(~locked), # ResetSignal("framer").eq(0), ] return m
def elaborate(self, platform): """ """ m = Module() # pins ft_clkout_i = platform.request("ft_clkout_i") ft_wr_n_o = platform.request("ft_wr_n_o") ft_txe_n_i = platform.request("ft_txe_n_i") ft_suspend_n_i = platform.request("ft_suspend_n_i") ft_oe_n_o = platform.request("ft_oe_n_o") ft_rd_n_o = platform.request("ft_rd_n_o") ft_siwua_n_o = platform.request("ft_siwua_n_o") ft_data_io = platform.request("ft_data_io") adc_d_i = platform.request("adc_d_i") adc_oe_o = platform.request("adc_oe_o") adc_shdn_o = platform.request("adc_shdn_o") ext1 = platform.request("ext1") pa_en_n_o = platform.request("pa_en_n_o") mix_en_n_o = platform.request("mix_en_n_o") # signals clk80 = Signal() pll_fb = Signal() chan_a = Signal(self.ADC_WIDTH) chan_b = Signal(self.ADC_WIDTH) lsb = Signal() lock = Signal(RAW_STATE) sample_ctr = Signal(range(self.DECIMATE * self.FFT_LEN)) sample_ctr_max = Const(self.DECIMATE * self.FFT_LEN - 1) cons_done = Signal() cons_done_clk80_dom = Signal() send_start = Signal() send_stop = Signal() wait_prod = Signal() lock_ftclk_dom = Signal() lock_ftclk_dom_last = Signal() # clock domains clk40_neg = ClockDomain("clk40_neg", clk_edge="neg") m.domains.clk40_neg = clk40_neg m.d.comb += ClockSignal("clk40_neg").eq(ClockSignal("sync")) m.domains += ClockDomain("clk60") m.d.comb += ClockSignal("clk60").eq(ft_clkout_i.i) m.domains += ClockDomain("clk80") m.d.comb += ClockSignal("clk80").eq(clk80) # ======================== submodules ======================== # PLL m.submodules += Instance( "PLLE2_BASE", ("p", "CLKFBOUT_MULT", 24), ("p", "DIVCLK_DIVIDE", 1), ("p", "CLKOUT0_DIVIDE", 12), ("p", "CLKIN1_PERIOD", 25), ("o", "CLKOUT0", clk80), ("i", "CLKIN1", ClockSignal("sync")), ("i", "RST", 0), ("o", "CLKFBOUT", pll_fb), ("i", "CLKFBIN", pll_fb), ) # ADC m.submodules.ltc2292 = ltc2292 = LTC2292( posedge_domain="sync", negedge_domain="clk40_neg" ) m.d.comb += [ ltc2292.di.eq(adc_d_i.i), chan_a.eq(ltc2292.dao), chan_b.eq(ltc2292.dbo), ] # FIFO m.submodules.fifo = fifo = AsyncFIFO( width=self.USB_WIDTH, depth=self.DECIMATE * self.FFT_LEN * 2, r_domain="clk60", w_domain="clk80", ) with m.If(lsb): m.d.comb += fifo.w_data.eq(chan_a[: self.USB_WIDTH]) with m.Else(): m.d.comb += fifo.w_data.eq( Cat( chan_a[self.USB_WIDTH :], Const(0, 2 * self.USB_WIDTH - self.ADC_WIDTH), ) ) # consumption done sync m.submodules.cons_done_sync = cons_done_sync = FFSynchronizer( i=cons_done, o=cons_done_clk80_dom, o_domain="clk80" ) # lock synch m.submodules.lock_sync = lock_sync = FFSynchronizer( i=lock, o=lock_ftclk_dom, o_domain="clk60" ) # =========================== logic ========================== m.d.comb += [ pa_en_n_o.o.eq(1), mix_en_n_o.o.eq(1), adc_oe_o.o.eq(0b01), adc_shdn_o.o.eq(0b00), ext1.o[0].eq(0b0), ext1.o[3].eq(lock), ext1.o[1].eq(0b0), ext1.o[4].eq(fifo.r_en), ext1.o[2].eq(0b0), ext1.o[5].eq(fifo.w_en), ] # write clock domain with m.If(lock == RAW_STATE.PROD): with m.If(sample_ctr == sample_ctr_max): m.d.clk80 += [ lock.eq(RAW_STATE.CONS), sample_ctr.eq(0), lsb.eq(0), ] with m.Else(): with m.If(lsb): m.d.clk80 += sample_ctr.eq(sample_ctr + 1) m.d.clk80 += lsb.eq(~lsb) with m.Else(): with m.If(cons_done_clk80_dom): m.d.clk80 += [ lock.eq(RAW_STATE.PROD), sample_ctr.eq(0), lsb.eq(0), ] with m.Switch(lock): with m.Case(RAW_STATE.PROD): m.d.comb += fifo.w_en.eq(1) with m.Case(RAW_STATE.CONS): m.d.comb += fifo.w_en.eq(0) # read clock domain m.d.clk60 += lock_ftclk_dom_last.eq(lock_ftclk_dom) with m.If(lock_ftclk_dom == RAW_STATE.CONS & ~wait_prod): with m.If(~fifo.r_rdy): m.d.clk60 += wait_prod.eq(1) with m.Elif(lock_ftclk_dom == RAW_STATE.CONS): m.d.clk60 += wait_prod.eq(1) with m.Else(): m.d.clk60 += wait_prod.eq(0) m.d.comb += [ ft_oe_n_o.o.eq(1), ft_rd_n_o.o.eq(1), ft_siwua_n_o.o.eq(1), ] with m.Switch(lock_ftclk_dom): with m.Case(RAW_STATE.PROD): m.d.comb += [ send_start.eq(0), send_stop.eq(0), ft_data_io.o.eq(0), ft_wr_n_o.o.eq(1), fifo.r_en.eq(0), ] with m.Case(RAW_STATE.CONS): with m.If(lock_ftclk_dom_last == RAW_STATE.PROD): m.d.comb += send_start.eq(1) with m.Else(): m.d.comb += send_start.eq(0) with m.If(~fifo.r_rdy): m.d.comb += [send_stop.eq(1), cons_done.eq(1)] with m.Else(): m.d.comb += [send_stop.eq(0), cons_done.eq(0)] with m.If(send_start): m.d.comb += [ ft_data_io.o.eq(self.START_FLAG), ft_wr_n_o.o.eq(ft_txe_n_i.i), fifo.r_en.eq(1), ] with m.Elif(send_stop): m.d.comb += [ ft_data_io.o.eq(self.STOP_FLAG), ft_wr_n_o.o.eq(ft_txe_n_i.i), fifo.r_en.eq(0), ] with m.Else(): with m.If(wait_prod): m.d.comb += [ ft_data_io.o.eq(0), ft_wr_n_o.o.eq(1), fifo.r_en.eq(0), ] with m.Else(): m.d.comb += [ ft_data_io.o.eq(fifo.r_data), ft_wr_n_o.o.eq(~(~ft_txe_n_i.i & fifo.r_en)), fifo.r_en.eq(~ft_txe_n_i.i & fifo.r_rdy), ] return m
def elaborate(self, platform): m = Module() # Create clock out signals self.clk = {cfg.cd_name: Signal() for cfg in self.clock_config} self._pll_lock = Signal() # Create our clock domains. for cfg in self.clock_config: m.domains += ClockDomain(cfg.cd_name) m.d.comb += ClockSignal(domain=cfg.cd_name).eq( self.clk[cfg.cd_name]) m.d.comb += ResetSignal(cfg.cd_name).eq(~self._pll_lock), # Grab our input clock clock_name = self.clock_name if self.clock_name else platform.default_clk try: self.clkin_frequency = platform.lookup( clock_name).clock.frequency / 1e6 input_clock_pin = platform.request(clock_name) except: input_clock_pin = ClockSignal(clock_name) # TODO: Make this nicer, remove clock_signal_freq self.clkin_frequency = self.clock_signal_freq / 1e6 # Calculate configuration parameters params = self.calc_pll_params(self.clkin_frequency, self.clock_config[0].freq) if len(self.clock_config) > 1: self.generate_secondary_output(params, 0, self.clock_config[1].freq, self.clock_config[1].phase) if len(self.clock_config) > 2: self.generate_secondary_output(params, 1, self.clock_config[2].freq, self.clock_config[2].phase) if len(self.clock_config) > 3: self.generate_secondary_output(params, 2, self.clock_config[3].freq, self.clock_config[3].phase) for i, p in enumerate([ params, params["secondary"][0], params["secondary"][1], params["secondary"][2] ]): if p["error"] > 0: logger.warning( "ClockDomain {} has an error of {:.3f} MHz ({} instead of {})" .format(self.clock_config[i].cd_name, p["error"], p["freq"], p["freq_requested"])) if not self.skip_checks: assert (p["error"] <= self.clock_config[i].error) m.submodules.pll = Instance( "EHXPLLL", # Clock in. i_CLKI=input_clock_pin, # Generated clock outputs. o_CLKOP=self.clk[self.clock_config[0].cd_name], o_CLKOS=self.clk[self.clock_config[1].cd_name] if len(self.clock_config) > 1 else Signal(), o_CLKOS2=self.clk[self.clock_config[2].cd_name] if len(self.clock_config) > 2 else Signal(), o_CLKOS3=self.clk[self.clock_config[3].cd_name] if len(self.clock_config) > 3 else Signal(), # Status. o_LOCK=self._pll_lock, # PLL parameters... p_PLLRST_ENA="DISABLED", p_INTFB_WAKE="DISABLED", p_STDBY_ENABLE="DISABLED", p_DPHASE_SOURCE="DISABLED", p_OUTDIVIDER_MUXA="DIVA", p_OUTDIVIDER_MUXB="DIVB", p_OUTDIVIDER_MUXC="DIVC", p_OUTDIVIDER_MUXD="DIVD", p_CLKI_DIV=params["refclk_div"], p_CLKOP_ENABLE="ENABLED", p_CLKOP_DIV=params["output_div"], p_CLKOP_CPHASE=params["primary_cphase"], p_CLKOP_FPHASE=0, p_CLKOS_ENABLE="ENABLED" if params["secondary"][0]["enabled"] else "DISABLED", p_CLKOS_FPHASE=params["secondary"][0]["fphase"], p_CLKOS_CPHASE=params["secondary"][0]["cphase"], p_CLKOS_DIV=params["secondary"][0]["div"], p_CLKOS2_ENABLE="ENABLED" if params["secondary"][1]["enabled"] else "DISABLED", p_CLKOS2_FPHASE=params["secondary"][1]["fphase"], p_CLKOS2_CPHASE=params["secondary"][1]["cphase"], p_CLKOS2_DIV=params["secondary"][1]["div"], p_CLKOS3_ENABLE="ENABLED" if params["secondary"][2]["enabled"] else "DISABLED", p_CLKOS3_FPHASE=params["secondary"][2]["fphase"], p_CLKOS3_CPHASE=params["secondary"][2]["cphase"], p_CLKOS3_DIV=params["secondary"][2]["div"], p_FEEDBK_PATH="CLKOP", # TODO: external feedback p_CLKFB_DIV=params["feedback_div"], # Internal feedback. i_CLKFB=self.clk[self.clock_config[0].cd_name], # TODO: Reset i_RST=0, # TODO: Standby i_STDBY=0, # TODO: Dynamic mode i_PHASESEL0=0, i_PHASESEL1=0, i_PHASEDIR=0, i_PHASESTEP=0, i_PHASELOADREG=0, i_PLLWAKESYNC=0, # Output Enables. i_ENCLKOP=0, i_ENCLKOS=0, i_ENCLKOS2=0, i_ENCLKOS3=0, # Synthesis attributes. a_FREQUENCY_PIN_CLKI=str(self.clkin_frequency), a_FREQUENCY_PIN_CLKOP=str(self.clock_config[0].freq), a_FREQUENCY_PIN_CLKOS=str(self.clock_config[1].freq) if len(self.clock_config) > 1 else "0", a_FREQUENCY_PIN_CLKOS2=str(self.clock_config[2].freq) if len(self.clock_config) > 2 else "0", a_FREQUENCY_PIN_CLKOS3=str(self.clock_config[3].freq) if len(self.clock_config) > 3 else "0", a_ICP_CURRENT="12", a_LPF_RESISTOR="8", a_MFG_ENABLE_FILTEROPAMP="1", a_MFG_GMCREF_SEL="2", ) return m
def elaborate(self, platform): m = Module() # Grab our default input clock. input_clock = platform.request(platform.default_clk, dir="i") # Create our domains; but don't do anything else for them, for now. m.domains.sync = ClockDomain() m.domains.usb = ClockDomain() m.domains.usb_io = ClockDomain() m.domains.fast = ClockDomain() m.submodules.pll = Instance( "EHXPLLL", # Clock in. i_CLKI=input_clock, # Generated clock outputs. o_CLKOP=ClockSignal("sync"), o_CLKOS=ClockSignal("usb"), # Status. #o_LOCK=self._pll_lock, # PLL parameters... p_PLLRST_ENA="DISABLED", p_INTFB_WAKE="DISABLED", p_STDBY_ENABLE="DISABLED", p_DPHASE_SOURCE="DISABLED", p_CLKOS3_FPHASE=0, p_CLKOS3_CPHASE=0, p_CLKOS2_FPHASE=0, p_CLKOS2_CPHASE=7, p_CLKOS_FPHASE=0, p_CLKOS_CPHASE=5, p_CLKOP_FPHASE=0, p_CLKOP_CPHASE=5, p_PLL_LOCK_MODE=0, p_CLKOS_TRIM_DELAY="0", p_CLKOS_TRIM_POL="FALLING", p_CLKOP_TRIM_DELAY="0", p_CLKOP_TRIM_POL="FALLING", p_OUTDIVIDER_MUXD="DIVD", p_CLKOS3_ENABLE="DISABLED", p_OUTDIVIDER_MUXC="DIVC", p_CLKOS2_ENABLE="DISABLED", p_OUTDIVIDER_MUXB="DIVB", p_CLKOS_ENABLE="ENABLED", p_OUTDIVIDER_MUXA="DIVA", p_CLKOP_ENABLE="ENABLED", p_CLKOS3_DIV=1, p_CLKOS2_DIV=8, p_CLKOS_DIV=48, p_CLKOP_DIV=12, p_CLKFB_DIV=1, p_CLKI_DIV=1, p_FEEDBK_PATH="CLKOP", # Internal feedback. i_CLKFB=ClockSignal("sync"), # Control signals. i_RST=0, i_PHASESEL0=0, i_PHASESEL1=0, i_PHASEDIR=1, i_PHASESTEP=1, i_PHASELOADREG=1, i_STDBY=0, i_PLLWAKESYNC=0, # Output Enables. i_ENCLKOP=0, i_ENCLKOS=0, i_ENCLKOS2=0, i_ENCLKOS3=0, # Synthesis attributes. a_FREQUENCY_PIN_CLKI="48.000000", a_FREQUENCY_PIN_CLKOS="48.000000", a_FREQUENCY_PIN_CLKOP="12.000000", a_ICP_CURRENT="12", a_LPF_RESISTOR="8") # We'll use our 48MHz clock for everything _except_ the usb domain... m.d.comb += [ ClockSignal("usb_io").eq(ClockSignal("sync")), ClockSignal("fast").eq(ClockSignal("sync")) ] return m
def elaborate(self, platform): m = Instance("OSCH", p_NOM_FREQ=self._freq_str, i_STDBY=Const(0), o_OSC=self.out) return m
def create_submodules(self, m, platform): self._pll_lock = Signal() # Figure out our platform's clock frequencies -- grab the platform's # defaults, and then override any with our local, caller-provided copies. new_clock_frequencies = platform.DEFAULT_CLOCK_FREQUENCIES_MHZ.copy() if self.clock_frequencies: new_clock_frequencies.update(self.clock_frequencies) self.clock_frequencies = new_clock_frequencies # Use the provided clock name for our input; or the default clock # if no name was provided. clock_name = self.clock_name if self.clock_name else platform.default_clk # Create absolute-frequency copies of our PLL outputs. # We'll use the generate_ methods below to select which domains # apply to which components. self._clk_240MHz = Signal() self._clk_120MHz = Signal() self._clk_60MHz = Signal() self._clock_options = { 60: self._clk_60MHz, 120: self._clk_120MHz, 240: self._clk_240MHz } # Grab our input clock # For debugging: if our clock name is "OSCG", allow using the internal # oscillator. This is mostly useful for debugging. if clock_name == "OSCG": logging.warning( "Using FPGA-internal oscillator for an approximately 62MHz.") logging.warning("USB communication won't work for f_OSC != 60MHz.") input_clock = Signal() m.submodules += Instance("OSCG", p_DIV=self.OSCG_DIV, o_OSC=input_clock) else: input_clock = platform.request(clock_name) # Instantiate the ECP5 PLL. # These constants generated by Clarity Designer; which will # ideally be replaced by an open-source component. # (see https://github.com/SymbiFlow/prjtrellis/issues/34.) m.submodules.pll = Instance( "EHXPLLL", # Clock in. i_CLKI=input_clock, # Generated clock outputs. o_CLKOP=self._clk_240MHz, o_CLKOS=self._clk_120MHz, o_CLKOS2=self._clk_60MHz, # Status. o_LOCK=self._pll_lock, # PLL parameters... p_PLLRST_ENA="DISABLED", p_INTFB_WAKE="DISABLED", p_STDBY_ENABLE="DISABLED", p_DPHASE_SOURCE="DISABLED", p_CLKOS3_FPHASE=0, p_CLKOS3_CPHASE=0, p_CLKOS2_FPHASE=0, p_CLKOS2_CPHASE=7, p_CLKOS_FPHASE=0, p_CLKOS_CPHASE=3, p_CLKOP_FPHASE=0, p_CLKOP_CPHASE=1, p_PLL_LOCK_MODE=0, p_CLKOS_TRIM_DELAY="0", p_CLKOS_TRIM_POL="FALLING", p_CLKOP_TRIM_DELAY="0", p_CLKOP_TRIM_POL="FALLING", p_OUTDIVIDER_MUXD="DIVD", p_CLKOS3_ENABLE="DISABLED", p_OUTDIVIDER_MUXC="DIVC", p_CLKOS2_ENABLE="ENABLED", p_OUTDIVIDER_MUXB="DIVB", p_CLKOS_ENABLE="ENABLED", p_OUTDIVIDER_MUXA="DIVA", p_CLKOP_ENABLE="ENABLED", p_CLKOS3_DIV=1, p_CLKOS2_DIV=8, p_CLKOS_DIV=4, p_CLKOP_DIV=2, p_CLKFB_DIV=4, p_CLKI_DIV=1, p_FEEDBK_PATH="CLKOP", # Internal feedback. i_CLKFB=self._clk_240MHz, # Control signals. i_RST=0, i_PHASESEL0=0, i_PHASESEL1=0, i_PHASEDIR=0, i_PHASESTEP=0, i_PHASELOADREG=0, i_STDBY=0, i_PLLWAKESYNC=0, # Output Enables. i_ENCLKOP=0, i_ENCLKOS=0, i_ENCLKOS2=0, i_ENCLKOS3=0, # Synthesis attributes. a_FREQUENCY_PIN_CLKI="60.000000", a_FREQUENCY_PIN_CLKOS2="60.000000", a_FREQUENCY_PIN_CLKOS="120.000000", a_FREQUENCY_PIN_CLKOP="240.000000", a_ICP_CURRENT="9", a_LPF_RESISTOR="8") # Set up our global resets so the system is kept fully in reset until # our core PLL is fully stable. This prevents us from internally clock # glitching ourselves before our PLL is locked. :) m.d.comb += [ ResetSignal("sync").eq(~self._pll_lock), ResetSignal("fast").eq(~self._pll_lock), ]
def elaborate(self, platform): if platform is not None: platform.add_file("picorv32.v", open("picorv32.v", "r")) if not os.path.exists("build"): os.makedirs("build") subprocess.run( [ "cargo", "objcopy", "--release", "--", "-O", "binary", "../build/app.bin" ], cwd="app", ).check_returncode() with open("build/app.bin", "rb") as f: b = bytearray(f.read()) b.extend([0] * (4 - (len(b) % 4))) app = np.frombuffer(b, dtype='<u4').tolist() # MEM_SIZE = 256 # words RAM_SIZE = 256 # words init = ([0] * RAM_SIZE) + app MEM_SIZE = len(init) mem = Memory( width=32, depth=MEM_SIZE, init=init, ) resetn = Signal() mem_valid = Signal() mem_ready = Signal() mem_addr = Signal(32) mem_wdata = Signal(32) mem_wstrb = Signal(4) mem_rdata = Signal(32) m = Module() m.d.comb += resetn.eq(~ResetSignal()) m.submodules.picorv32 = Instance( "picorv32", p_ENABLE_COUNTERS=0, p_LATCHED_MEM_RDATA=1, p_TWO_STAGE_SHIFT=0, p_TWO_CYCLE_ALU=1, p_CATCH_MISALIGN=0, p_CATCH_ILLINSN=0, p_COMPRESSED_ISA=1, p_ENABLE_MUL=1, p_PROGADDR_RESET=1024, p_PROGADDR_IRQ=1024 + 0x10, i_clk=ClockSignal(), i_resetn=resetn, o_mem_valid=mem_valid, i_mem_ready=mem_ready, o_mem_addr=mem_addr, o_mem_wdata=mem_wdata, o_mem_wstrb=mem_wstrb, i_mem_rdata=mem_rdata, ) m.submodules.read_port = read_port = mem.read_port(transparent=False) m.submodules.write_port = write_port = mem.write_port(granularity=8) m.d.sync += mem_ready.eq(0) m.d.comb += [ read_port.addr.eq(mem_addr >> 2), mem_rdata.eq(read_port.data), read_port.en.eq((~mem_wstrb).bool()), write_port.addr.eq(mem_addr >> 2), write_port.data.eq(mem_wdata), write_port.en.eq(mem_wstrb), ] with m.If(resetn & mem_valid & ~mem_ready): with m.If((mem_addr >> 2) < MEM_SIZE): m.d.sync += mem_ready.eq(1) for mapping in self.memory_mappings: if mapping.writing_enabled: with m.If(mem_wstrb.bool() & (mem_addr == mapping.addr)): if mapping.write is not None: mapping.write(m, mem_wdata) else: m.d.sync += [ mapping.signal.eq(mem_wdata), mem_ready.eq(1), ] if mapping.read: with m.If((~mem_wstrb).bool() & (mem_addr == mapping.addr)): m.d.comb += mem_rdata.eq(mapping.signal) m.d.sync += mem_ready.eq(1) if not mapping.read and not (mapping.write or mapping.writing_enabled): print(mapping.addr) print("mapping doesn't specify read or write", file=sys.stderr) return m