def __init__(self, pins, roi_engine_count=16, res_width=12, count_shift=0): self.config = rtlink.Interface( rtlink.OInterface(res_width, bits_for(4*roi_engine_count-1))) self.gate_data = rtlink.Interface( rtlink.OInterface(roi_engine_count), rtlink.IInterface(1+ROI.count_len(res_width, count_shift), timestamped=False)) self.submodules.deserializer = deserializer_7series.Deserializer(pins) self.submodules.frequency_counter = FrequencyCounter() self.submodules.parser = Parser(res_width) self.comb += self.parser.cl.eq(self.deserializer.q) self.roi_engines = [ROI(self.parser.pix, count_shift) for _ in range(roi_engine_count)] self.submodules += self.roi_engines self.submodules.synchronizer = Synchronizer(self.roi_engines) self.submodules.serializer = Serializer(self.synchronizer.update, self.synchronizer.counts, self.gate_data.i) for n, roi_engine in enumerate(self.roi_engines): for offset, target in enumerate([roi_engine.cfg.x0, roi_engine.cfg.y0, roi_engine.cfg.x1, roi_engine.cfg.y1]): roi_boundary = Signal.like(target) roi_boundary.attr.add("no_retiming") self.sync.rtio += If(self.config.o.stb & (self.config.o.address == 4*n+offset), roi_boundary.eq(self.config.o.data)) self.specials += MultiReg(roi_boundary, target, "cl") self.sync.rio += If(self.gate_data.o.stb, self.serializer.gate.eq(self.gate_data.o.data))
def __init__(self, *args, **kwargs): _ChannelPHY.__init__(self, *args, **kwargs) self.phys = [] cfg = self.i[0] rl = rtlink.Interface(rtlink.OInterface( data_width=len(cfg.data), address_width=len(cfg.addr), enable_replace=False)) self.comb += [ cfg.stb.eq(rl.o.stb), rl.o.busy.eq(~cfg.ack), cfg.data.eq(rl.o.data), cfg.addr.eq(rl.o.address), ] self.phys.append(_Phy(rl, [], [])) for i in self.i[1:]: rl = rtlink.Interface(rtlink.OInterface(len(i.payload), delay=-i.latency)) self.comb += [ i.stb.eq(rl.o.stb), rl.o.busy.eq(~i.ack), i.payload.raw_bits().eq(rl.o.data), ] # TODO probes, overrides self.phys.append(_Phy(rl, [], [])) self.phys_named = dict(zip(self.i_names, self.phys))
def __init__(self, o_width, i_width): self.rtlink = rtlink.Interface( rtlink.OInterface(o_width), rtlink.IInterface(i_width, timestamped=True)) self.received_data = Signal(o_width) self.sync.rio_phy += If(self.rtlink.o.stb, self.received_data.eq(self.rtlink.o.data))
def __init__(self, pad, pad_n=None): self.rtlink = rtlink.Interface(rtlink.OInterface(2, 2), rtlink.IInterface(1)) self.overrides = [] self.probes = [] # # # sensitivity = Signal(2) sample = Signal() self.sync.rio += [ sample.eq(0), If(self.rtlink.o.stb & self.rtlink.o.address[1], sensitivity.eq(self.rtlink.o.data), If(self.rtlink.o.address[0], sample.eq(1))) ] i = Signal() i_d = Signal(reset_less=True) pad_i = Signal() if pad_n is None: self.comb += pad_i.eq(pad) else: self.specials += DifferentialInput(pad, pad_n, pad_i) self.specials += MultiReg(pad_i, i, "rio_phy") self.sync.rio_phy += i_d.eq(i) self.comb += [ self.rtlink.i.stb.eq(sample | (sensitivity[0] & (i & ~i_d)) | (sensitivity[1] & (~i & i_d))), self.rtlink.i.data.eq(i) ] self.probes += [i]
def __init__(self, pad, pad_n=None, ftw_width=24, dci=False): self.rtlink = rtlink.Interface(rtlink.OInterface(ftw_width)) # # # pad_o = Signal() if pad_n is None: self.comb += pad.eq(pad_o) else: self.specials += DifferentialOutput(pad_o, pad, pad_n) ftw = Signal(ftw_width) acc = Signal(ftw_width) self.sync.rio += If(self.rtlink.o.stb, ftw.eq(self.rtlink.o.data)) self.sync.rio_phy += [ acc.eq(acc + ftw), # rtlink takes precedence over regular acc increments If( self.rtlink.o.stb, If( self.rtlink.o.data != 0, # known phase on frequency write: at rising edge acc.eq(2**(ftw_width - 1))).Else( # set output to 0 on stop acc.eq(0))), pad_o.eq(acc[-1]) ]
def __init__(self, address_width, wb=None): if wb is None: wb = wishbone.Interface() self.wb = wb self.rtlink = rtlink.Interface( rtlink.OInterface(flen(wb.dat_w), address_width + 1, suppress_nop=False), rtlink.IInterface(flen(wb.dat_r), timestamped=False)) # # # active = Signal() self.sync.rio += [ If(self.rtlink.o.stb, active.eq(1), wb.adr.eq(self.rtlink.o.address[:address_width]), wb.we.eq(~self.rtlink.o.address[address_width]), wb.dat_w.eq(self.rtlink.o.data), wb.sel.eq(2**flen(wb.sel) - 1)), If(wb.ack, active.eq(0)) ] self.comb += [ self.rtlink.o.busy.eq(active), wb.cyc.eq(active), wb.stb.eq(active), self.rtlink.i.stb.eq(wb.ack & ~wb.we), self.rtlink.i.data.eq(wb.dat_r) ]
def __init__(self, pad): self.rtlink = rtlink.Interface( rtlink.OInterface(2, 2), rtlink.IInterface(1)) self.overrides = [] self.probes = [] # # # sensitivity = Signal(2) sample = Signal() self.sync.rio += [ sample.eq(0), If(self.rtlink.o.stb & self.rtlink.o.address[1], sensitivity.eq(self.rtlink.o.data), If(self.rtlink.o.address[0], sample.eq(1)) ) ] i = Signal() i_d = Signal() self.specials += MultiReg(pad, i, "rio_phy") self.sync.rio_phy += i_d.eq(i) self.comb += [ self.rtlink.i.stb.eq( sample | (sensitivity[0] & ( i & ~i_d)) | (sensitivity[1] & (~i & i_d)) ), self.rtlink.i.data.eq(i) ] self.probes += [i]
def __init__(self, regs): self.rtlink = rtlink.Interface( rtlink.OInterface(data_width=32, address_width=4, enable_replace=True)) self.sync.rtio += [ If(self.rtlink.o.stb, Array(regs)[self.rtlink.o.address].eq(self.rtlink.o.data)) ]
def __init__(self, pad): self.rtlink = rtlink.Interface( rtlink.OInterface(2, 2), rtlink.IInterface(1)) override_en = Signal() override_o = Signal() override_oe = Signal() self.overrides = [override_en, override_o, override_oe] self.probes = [] # # # ts = TSTriple() self.specials += ts.get_tristate(pad) sensitivity = Signal(2) o_k = Signal() oe_k = Signal() self.sync.rio_phy += [ If(self.rtlink.o.stb, If(self.rtlink.o.address == 0, o_k.eq(self.rtlink.o.data[0])), If(self.rtlink.o.address == 1, oe_k.eq(self.rtlink.o.data[0])), ), If(override_en, ts.o.eq(override_o), ts.oe.eq(override_oe) ).Else( ts.o.eq(o_k), ts.oe.eq(oe_k) ) ] sample = Signal() self.sync.rio += [ sample.eq(0), If(self.rtlink.o.stb & self.rtlink.o.address[1], sensitivity.eq(self.rtlink.o.data), If(self.rtlink.o.address[0], sample.eq(1)) ) ] i = Signal() i_d = Signal() self.specials += MultiReg(ts.i, i, "rio_phy") self.sync.rio_phy += i_d.eq(i) self.comb += [ self.rtlink.i.stb.eq( sample | (sensitivity[0] & ( i & ~i_d)) | (sensitivity[1] & (~i & i_d)) ), self.rtlink.i.data.eq(i) ] self.probes += [i, ts.oe]
def __init__(self, serdes): serdes_width = len(serdes.o) assert len(serdes.i) == serdes_width self.rtlink = rtlink.Interface( rtlink.OInterface(2, 2, fine_ts_width=log2_int(serdes_width)), rtlink.IInterface(1, fine_ts_width=log2_int(serdes_width))) self.probes = [serdes.i[-1], serdes.oe] override_en = Signal() override_o = Signal() override_oe = Signal() self.overrides = [override_en, override_o, override_oe] # # # # Output self.submodules += _SerdesDriver(serdes_o=serdes.o, stb=self.rtlink.o.stb & (self.rtlink.o.address == 0), data=self.rtlink.o.data[0], fine_ts=self.rtlink.o.fine_ts, override_en=override_en, override_o=override_o) oe_k = Signal() self.sync.rio_phy += [ If(self.rtlink.o.stb & (self.rtlink.o.address == 1), oe_k.eq(self.rtlink.o.data[0])), If(override_en, serdes.oe.eq(override_oe)).Else(serdes.oe.eq(oe_k)) ] # Input sensitivity = Signal(2) sample = Signal() self.sync.rio += [ sample.eq(0), If(self.rtlink.o.stb & self.rtlink.o.address[1], sensitivity.eq(self.rtlink.o.data), If(self.rtlink.o.address[0], sample.eq(1))) ] i = serdes.i[-1] i_d = Signal() self.sync.rio_phy += [ i_d.eq(i), self.rtlink.i.stb.eq(sample | (sensitivity[0] & (i & ~i_d)) | (sensitivity[1] & (~i & i_d))), self.rtlink.i.data.eq(i), ] pe = PriorityEncoder(serdes_width) self.submodules += pe self.comb += pe.i.eq(serdes.i ^ Replicate(i_d, serdes_width)) self.sync.rio_phy += self.rtlink.i.fine_ts.eq(pe.o)
def __init__(self, pad): self.rtlink = rtlink.Interface(rtlink.OInterface(2, 2), rtlink.IInterface(1)) override_en = Signal() override_o = Signal() override_oe = Signal() self.overrides = [override_en, override_o, override_oe] self.probes = [] # Output enable, for interfacing to external buffers. self.oe = Signal() # Registered copy of the input state, in the rio_phy clock domain. self.input_state = Signal() # # # ts = TSTriple() self.specials += ts.get_tristate(pad) sensitivity = Signal(2) o_k = Signal() oe_k = Signal() self.oe.attr.add("no_retiming") self.sync.rio_phy += [ If( self.rtlink.o.stb, If(self.rtlink.o.address == 0, o_k.eq(self.rtlink.o.data[0])), If(self.rtlink.o.address == 1, oe_k.eq(self.rtlink.o.data[0])), ), If(override_en, ts.o.eq(override_o), self.oe.eq(override_oe)).Else(ts.o.eq(o_k), self.oe.eq(oe_k)) ] self.comb += ts.oe.eq(self.oe) sample = Signal() self.sync.rio += [ sample.eq(0), If(self.rtlink.o.stb & self.rtlink.o.address[1], sensitivity.eq(self.rtlink.o.data), If(self.rtlink.o.address[0], sample.eq(1))) ] i = Signal() i_d = Signal() self.specials += MultiReg(ts.i, i, "rio_phy") self.sync.rio_phy += i_d.eq(i) self.comb += [ self.rtlink.i.stb.eq(sample | (sensitivity[0] & (i & ~i_d)) | (sensitivity[1] & (~i & i_d))), self.rtlink.i.data.eq(i), self.input_state.eq(i) ] self.probes += [i, ts.oe]
def __init__(self, regs, name, identifier=None): self.name = name self.regs = regs data_width = max([x[1] for x in regs]) self.rtlink = rtlink.Interface( rtlink.OInterface(data_width=data_width, address_width=len(regs).bit_length() + 1), rtlink.IInterface(data_width=data_width, timestamped=False)) write_enable = self.rtlink.o.address[0] address = self.rtlink.o.address[1:] data_signals_list = [] for idx, r in enumerate(regs): if len(r) > 2: reset_value = r[2] else: reset_value = 0 if len(r) > 3: mode = r[3] else: mode = "rw" signal = Signal(bits_sign=r[1], name=r[0], reset=reset_value) setattr(self, r[0], signal) data_signals_list.append(signal) if mode == "rw": ld_signal_name = r[0] + "_ld" setattr(self, ld_signal_name, Signal(bits_sign=1, name=ld_signal_name)) ld_signal = getattr(self, ld_signal_name) self.sync.rio_phy += [ ld_signal.eq(0), If(self.rtlink.o.stb & write_enable & (address == idx), signal.eq(self.rtlink.o.data), ld_signal.eq(1)) ] data_signals = Array(data_signals_list) self.sync.rio_phy += [ self.rtlink.i.stb.eq(0), If(self.rtlink.o.stb & ~write_enable, self.rtlink.i.stb.eq(1), self.rtlink.i.data.eq(data_signals[address])) ] if identifier is not None: self.add_rtio_channels(channel=Channel.from_phy(self), device_id=identifier, module="elhep_cores.coredevice.rtlink_csr", class_name="RtlinkCsr", arguments={"regs": regs})
def __init__(self, ctrl): self.rtlink = rtlink.Interface( rtlink.OInterface(len(ctrl.profile) + 2)) # # # self.comb += [ctrl.stb.eq(self.rtlink.o.stb), self.rtlink.o.busy.eq(0)] self.sync.rio_phy += [ If( self.rtlink.o.stb, Cat(ctrl.en_out, ctrl.en_iir, ctrl.profile).eq(self.rtlink.o.data)) ]
def __init__(self, pad): self.rtlink = rtlink.Interface(rtlink.OInterface(1)) self.probes = [pad] override_en = Signal() override_o = Signal() self.overrides = [override_en, override_o] # # # pad_k = Signal() self.sync.rio_phy += [ If(self.rtlink.o.stb, pad_k.eq(self.rtlink.o.data)), If(override_en, pad.eq(override_o)).Else(pad.eq(pad_k)) ]
def __init__(self, *args, **kwargs): _ChannelPHY.__init__(self, *args, **kwargs) self.phys = [] for i in self.i: rl = rtlink.Interface(rtlink.OInterface(len(i.payload), delay=-i.latency)) self.comb += [ i.stb.eq(rl.o.stb), rl.o.busy.eq(~i.ack), i.payload.raw_bits().eq(rl.o.data), ] # TODO probes, overrides self.phys.append(_Phy(rl, [], [])) self.phys_named = dict(zip(self.i_names, self.phys))
def __init__(self, serdes): self.rtlink = rtlink.Interface( rtlink.OInterface(1, fine_ts_width=log2_int(len(serdes.o)))) self.probes = [serdes.o[-1]] override_en = Signal() override_o = Signal() self.overrides = [override_en, override_o] # # # self.submodules += _SerdesDriver(serdes.o, self.rtlink.o.stb, self.rtlink.o.data, self.rtlink.o.fine_ts, override_en, override_o)
def __init__(self): self.rtlink = rtlink.Interface(rtlink.OInterface(1), rtlink.IInterface(1)) self.overrides = [] self.probes = [] # # # counter = Signal(2) trigger = Signal() self.sync += [ Cat(counter, trigger).eq(counter + 1), self.rtlink.i.stb.eq(0), If(trigger, self.rtlink.i.stb.eq(1), self.rtlink.i.data.eq(~self.rtlink.i.data)) ]
def _add_rtlink(self): # Address 0: enabled # Address 1: pulse length # Address 2: mask mask_adr_no = (len(self.mask) + 31) // 32 adr_width = len(Signal(max=mask_adr_no + 1)) + 2 self.rtlink = rtlink.Interface( rtlink.OInterface(data_width=32, address_width=adr_width), rtlink.IInterface(data_width=32, timestamped=False)) self.rtlink_address = rtlink_address = Signal.like( self.rtlink.o.address) self.rtlink_wen = rtlink_wen = Signal() self.comb += [ rtlink_address.eq(self.rtlink.o.address[1:]), rtlink_wen.eq(self.rtlink.o.address[0]), ] mask_array = self.signal_to_array(self.mask) self.sync.rio_phy += [ self.rtlink.i.stb.eq(0), If( self.rtlink.o.stb, # Write If(rtlink_wen & (rtlink_address == 0), self.enabled.eq(self.rtlink.o.data[0])).Elif( rtlink_wen & (rtlink_address == 1), self.pulse_length.eq(self.rtlink.o.data)).Elif( rtlink_wen & (rtlink_address >= 2), mask_array[rtlink_address - 2].eq( self.rtlink.o.data)). # Readout Elif(~rtlink_wen & (rtlink_address == 0), self.rtlink.i.data.eq(self.enabled), self.rtlink.i.stb.eq(1)).Elif( ~rtlink_wen & (rtlink_address == 1), self.rtlink.i.data.eq(self.pulse_length), self.rtlink.i.stb.eq(1)).Elif( ~rtlink_wen & (rtlink_address >= 2), self.rtlink.i.data.eq(mask_array[rtlink_address - 2]), self.rtlink.i.stb.eq(1))) ]
def __init__(self, pad, pad_n=None): self.rtlink = rtlink.Interface(rtlink.OInterface(1)) pad_o = Signal(reset_less=True) self.probes = [pad_o] override_en = Signal() override_o = Signal() self.overrides = [override_en, override_o] # # # pad_k = Signal() self.sync.rio_phy += [ If(self.rtlink.o.stb, pad_k.eq(self.rtlink.o.data)), If(override_en, pad_o.eq(override_o)).Else(pad_o.eq(pad_k)) ] if pad_n is None: self.comb += pad.eq(pad_o) else: self.specials += DifferentialOutput(pad_o, pad, pad_n)
def __init__(self, pad, ftw_width=24): self.rtlink = rtlink.Interface(rtlink.OInterface(ftw_width)) # # # ftw = Signal(ftw_width) acc = Signal(ftw_width) self.sync.rio += If(self.rtlink.o.stb, ftw.eq(self.rtlink.o.data)) self.sync.rio_phy += [ acc.eq(acc + ftw), # rtlink takes precedence over regular acc increments If( self.rtlink.o.stb, If( self.rtlink.o.data != 0, # known phase on frequency write: at rising edge acc.eq(2**(ftw_width - 1))).Else( # set output to 0 on stop acc.eq(0))), pad.eq(acc[-1]) ]
def __init__(self, data, treshold_length=4, name="baseline_trigger"): self.rtlink = rtlink.Interface(rtlink.OInterface(data_width=len(data))) # # # regs = [("offset_level", len(data))] csr = RtLinkCSR(regs, "baseline_trigger_generator") self.submodules.csr = csr trigger_level_sys = Signal.like(data) cdc = BusSynchronizer(len(data), "rio_phy", "sys") self.submodules += cdc self.comb += [ cdc.i.eq(self.csr.offset_level), trigger_level_sys.eq(cdc.o) ] super().__init__(data, trigger_level_sys, treshold_length, name)
def __init__(self, servo): self.rtlink = rtlink.Interface( rtlink.OInterface(data_width=32, address_width=8, enable_replace=False), rtlink.IInterface(data_width=32)) ### # reg addresses - starts with R/!W cases = { # control/config reg - rst, afe, dac_clr 0x00: servo.ctrl[:4].eq(self.rtlink.o.data), # enable channels 0x01: servo.ctrl[4:6].eq(self.rtlink.o.data), # enable ADC AFE X10 gain 0x02: servo.ctrl[6:].eq(self.rtlink.o.data), # set dac 0x03: servo.mode.eq(self.rtlink.o.data[-2:]), servo.dac_data.eq(self.rtlink.o.data[:-2]) # init/status reg 0x04: servo.init, # adc data 0x05: servo.adc_data, } input_data = Signal(32, reset_less=True) self.sync.rio_phy += [ If(self.rtlink.o.stb & ~self.rtlink.o.address[-1], Case(self.rtlink.o.address[:-1], cases) ), If(self.rtlink.i.stb, input_data.eq(Case(self.rtlink.o.address[:-1], cases)) ) ] self.comb += [ self.rtlink.i.stb.eq(self.rtlink.o.stb & self.rtlink.o.address[-1]), self.rtlink.i.data.eq(input_data), ]
def __init__(self, address_width, wb=None, rtio_enable_replace=False, write_only=False): if wb is None: wb = wishbone.Interface() self.wb = wb self.rtlink = rtlink.Interface( rtlink.OInterface(len(wb.dat_w), address_width + 1 if not write_only else address_width, enable_replace=rtio_enable_replace), rtlink.IInterface(len(wb.dat_r), timestamped=False) if not write_only else None) # # # active = Signal() self.sync.rio += [ If( self.rtlink.o.stb, active.eq(1), wb.adr.eq(self.rtlink.o.address[:address_width]), wb.we.eq(~self.rtlink.o.address[address_width] if not write_only else 1), wb.dat_w.eq(self.rtlink.o.data), wb.sel.eq(2**len(wb.sel) - 1)), If(wb.ack, active.eq(0)) ] self.comb += [ self.rtlink.o.busy.eq(active), wb.cyc.eq(active), wb.stb.eq(active), ] if not write_only: self.comb += [ self.rtlink.i.stb.eq(wb.ack & ~wb.we), self.rtlink.i.data.eq(wb.dat_r) ]
def __init__(self, name="sw_trigger", identifier=None): super().__init__(name) # Outputs self.trigger = Signal() # CD: rio_phy self.register_trigger(self.trigger, "trigger", ClockDomain("rio_phy")) # Interface - rtlink self.rtlink = rtlink_iface = rtlink.Interface( rtlink.OInterface(data_width=1)) self.sync.rio_phy += [ self.trigger.eq(0), If(rtlink_iface.o.stb, self.trigger.eq(1)) ] if identifier is not None: self.add_rtio_channels( channel=Channel.from_phy(self), device_id=identifier, module="elhep_cores.coredevice.trigger_generators", class_name="RtioTriggerGenerator")
def __init__(self): self.interface = rtlink.Interface(rtlink.OInterface(32)) self.probes = [] self.overrides = []
def __init__(self, pins, pins_n): self.rtlink = rtlink.Interface( rtlink.OInterface(data_width=8, address_width=8, enable_replace=False), rtlink.IInterface(data_width=10)) # share a CosSinGen LUT between the two channels self.submodules.ch0 = DDSChannel() self.submodules.ch1 = DDSChannel(share_lut=self.ch0.dds.cs.lut) n_channels = 2 n_samples = 8 n_bits = 14 body = Signal(n_samples * n_channels * 2 * n_bits, reset_less=True) self.sync.rio_phy += [ If( self.ch0.dds.valid, # & self.ch1.dds.valid, # recent:ch0:i as low order in body Cat(body).eq( Cat(self.ch0.dds.o.i[2:], self.ch0.dds.o.q[2:], self.ch1.dds.o.i[2:], self.ch1.dds.o.q[2:], body)), ), ] self.submodules.serializer = SerDes(n_data=8, t_clk=8, d_clk=0b00001111, n_frame=10, n_crc=6, poly=0x2f) self.submodules.intf = SerInterface(pins, pins_n) self.comb += [ Cat(self.intf.data[:-1]).eq(Cat(self.serializer.data[:-1])), self.serializer.data[-1].eq(self.intf.data[-1]), ] header = Record([("we", 1), ("addr", 7), ("data", 8), ("type", 4)]) assert len(Cat(header.raw_bits(), body)) == \ len(self.serializer.payload) self.comb += self.serializer.payload.eq(Cat(header.raw_bits(), body)) re_dly = Signal(3) # stage, send, respond self.sync.rtio += [ header.type.eq(1), # body type is baseband data If( self.serializer.stb, self.ch0.dds.stb.eq(1), # synchronize self.ch1.dds.stb.eq(1), # synchronize header.we.eq(0), re_dly.eq(re_dly[1:]), ), If( self.rtlink.o.stb, re_dly[-1].eq(~self.rtlink.o.address[-1]), header.we.eq(self.rtlink.o.address[-1]), header.addr.eq(self.rtlink.o.address), header.data.eq(self.rtlink.o.data), ), self.rtlink.i.stb.eq(re_dly[0] & self.serializer.stb), self.rtlink.i.data.eq(self.serializer.readback), ]
def __init__(self, core_link_pads, output_pads, passthrough_sigs, input_phys, simulate=False): """ core_link_pads: EEM pads for inter-Kasli link output_pads: pads for 4 output signals (422sigma, 1092, 422 ps trigger, aux) passthrough_sigs: signals from output phys, connected to output_pads when core not running input_phys: serdes phys for 5 inputs – APD0-3 and 422ps trigger in """ event_counter_width = 14 self.rtlink = rtlink.Interface( rtlink.OInterface( data_width=32, address_width=6, enable_replace=False), rtlink.IInterface( data_width=max(14, event_counter_width), timestamped=True) ) # # # self.submodules.core = ClockDomainsRenamer("rio")(EntanglerCore( core_link_pads, output_pads, passthrough_sigs, input_phys, event_counter_width, simulate=simulate)) read_en = self.rtlink.o.address[5] write_timings = Signal() write_patterns = Signal() self.comb += [ self.rtlink.o.busy.eq(0), write_timings.eq(self.rtlink.o.address[3:6] == 1), write_patterns.eq(self.rtlink.o.address[3:6] == 2), ] output_t_starts = [seq.m_start for seq in self.core.sequencers] output_t_ends = [seq.m_stop for seq in self.core.sequencers] output_t_starts += [gater.gate_start for gater in self.core.apd_gaters] output_t_ends += [gater.gate_stop for gater in self.core.apd_gaters] write_timing_cases = {} for i in range(len(output_t_starts)): write_timing_cases[i] = [output_t_starts[i].eq(self.rtlink.o.data[:16]), output_t_ends[i].eq(self.rtlink.o.data[16:])] # Write timeout counter and start core running self.comb += [ self.core.msm.time_remaining_buf.eq(self.rtlink.o.data), self.core.msm.run_stb.eq( (self.rtlink.o.address==1) & self.rtlink.o.stb ) ] self.sync.rio += [ If(write_timings & self.rtlink.o.stb, Case(self.rtlink.o.address[:3], write_timing_cases) ), If(write_patterns & self.rtlink.o.stb, Cat( *Array(p.patterns for p in self.core.pattern_counters)[ self.rtlink.o.address[:3]]).eq(self.rtlink.o.data) ), If((self.rtlink.o.address == 0) & self.rtlink.o.stb, # Write config self.core.enable.eq(self.rtlink.o.data[0]), self.core.msm.standalone.eq(self.rtlink.o.data[2]), ), If((self.rtlink.o.address == 2) & self.rtlink.o.stb, # Write cycle length self.core.msm.m_end.eq(self.rtlink.o.data[:10]) ), If((self.rtlink.o.address == 3) & self.rtlink.o.stb, # Write herald patterns and enables *[ self.core.heralder.patterns[i].eq( self.rtlink.o.data[4 * i:4 * (i + 1)]) for i in range(4) ], self.core.heralder.pattern_ens.eq(self.rtlink.o.data[16:20]) ), ] # Write is_master bit in rio_phy reset domain to not break 422ps trigger # forwarding on core.reset(). self.sync.rio_phy += If((self.rtlink.o.address == 0) & self.rtlink.o.stb, self.core.msm.is_master.eq(self.rtlink.o.data[1]) ) read = Signal() read_counters = Signal() read_timestamps = Signal() read_addr = Signal(3) # Input timestamps are [apd0, apd1, apd2, apd3, ref] input_timestamps = [gater.sig_ts for gater in self.core.apd_gaters] input_timestamps.append(self.core.apd_gaters[0].ref_ts) cases = {} timing_data = Signal(14) for i, ts in enumerate(input_timestamps): cases[i] = [timing_data.eq(ts)] self.comb += Case(read_addr, cases) self.sync.rio += [ If(read, read.eq(0) ), If(self.rtlink.o.stb, read.eq(read_en), read_counters.eq(self.rtlink.o.address[3:5] == 0b10), read_timestamps.eq(self.rtlink.o.address[3:5] == 0b01), read_addr.eq(self.rtlink.o.address[:3]), ) ] status = Signal(3) self.comb += status.eq(Cat(self.core.msm.ready, self.core.msm.success, self.core.msm.timeout)) reg_data = Signal(event_counter_width) cases = {} cases[0] = [reg_data.eq(status)] cases[1] = [reg_data.eq(self.core.msm.cycles_completed)] cases[2] = [reg_data.eq(self.core.msm.time_remaining)] cases[3] = [reg_data.eq(self.core.triggers_received)] self.comb += Case(read_addr, cases) counter_data = Signal(event_counter_width) self.comb += Case(read_addr, {i: [counter_data.eq(c.counter)] for i, c in enumerate(self.core.counters)}) # Generate an input event if we have a read request RTIO Output event, or if the # core has finished. If the core is finished output the herald match, or 0x3fff # on timeout. # # Simultaneous read requests and core-done events are not currently handled, but # are easy to avoid in the client code. self.comb += [ self.rtlink.i.stb.eq(read | self.core.enable & self.core.msm.done_stb), self.rtlink.i.data.eq( Mux(self.core.enable & self.core.msm.done_stb, Mux(self.core.msm.success, self.core.heralder.matches, 0x3fff), Mux(read_counters, counter_data, Mux(read_timestamps, timing_data, reg_data) ) ) ) ]
def __init__(self, width): self.rtlink = rtlink.Interface(rtlink.OInterface(width)) self.received_data = Signal(width) self.sync.rio_phy += If(self.rtlink.o.stb, self.received_data.eq(self.rtlink.o.data))
def __init__(self, pads, pads_n=None): to_rio_phy = ClockDomainsRenamer("rio_phy") if pads_n is None: interface = SPIInterface(pads) else: interface = SPIInterfaceXC7Diff(pads, pads_n) interface = to_rio_phy(interface) spi = to_rio_phy(SPIMachine(data_width=32, div_width=8)) self.submodules += interface, spi self.rtlink = rtlink.Interface( rtlink.OInterface(len(spi.reg.pdo), address_width=1, enable_replace=False), rtlink.IInterface(len(spi.reg.pdi), timestamped=False)) ### config = Record([ ("offline", 1), ("end", 1), ("input", 1), ("cs_polarity", 1), ("clk_polarity", 1), ("clk_phase", 1), ("lsb_first", 1), ("half_duplex", 1), ("length", 5), ("padding", 3), ("div", 8), ("cs", 8), ]) assert len(config) == len(spi.reg.pdo) == len(spi.reg.pdi) == 32 config.offline.reset = 1 config.end.reset = 1 read = Signal() self.sync.rio += [ If(self.rtlink.i.stb, read.eq(0)), If( self.rtlink.o.stb & spi.writable, If(self.rtlink.o.address, config.raw_bits().eq(self.rtlink.o.data)).Else( read.eq(config.input))), ] self.comb += [ spi.length.eq(config.length), spi.end.eq(config.end), spi.cg.div.eq(config.div), spi.clk_phase.eq(config.clk_phase), spi.reg.lsb_first.eq(config.lsb_first), interface.half_duplex.eq(config.half_duplex), interface.cs.eq(config.cs), interface.cs_polarity.eq( Replicate(config.cs_polarity, len(interface.cs_polarity))), interface.clk_polarity.eq(config.clk_polarity), interface.offline.eq(config.offline), interface.cs_next.eq(spi.cs_next), interface.clk_next.eq(spi.clk_next), interface.ce.eq(spi.ce), interface.sample.eq(spi.reg.sample), spi.reg.sdi.eq(interface.sdi), interface.sdo.eq(spi.reg.sdo), spi.load.eq(self.rtlink.o.stb & spi.writable & ~self.rtlink.o.address), spi.reg.pdo.eq(self.rtlink.o.data), self.rtlink.o.busy.eq(~spi.writable), self.rtlink.i.stb.eq(spi.readable & read), self.rtlink.i.data.eq(spi.reg.pdi) ] self.probes = []
def __init__(self, w, servo): m_coeff = servo.iir.m_coeff.get_port(write_capable=True, mode=READ_FIRST, we_granularity=w.coeff, clock_domain="rio") assert len(m_coeff.we) == 2 m_state = servo.iir.m_state.get_port( write_capable=True, # mode=READ_FIRST, clock_domain="rio") self.specials += m_state, m_coeff # just expose the w.coeff (18) MSBs of state assert w.state >= w.coeff # ensure that we can split the coefficient storage correctly assert len(m_coeff.dat_w) == 2 * w.coeff # ensure that the DDS word data fits into the coefficient mem assert w.coeff >= w.word # coeff, profile, channel, 2 mems, rw # this exceeds the 8-bit RTIO address, so we move the extra ("overflow") # address bits into data. internal_address_width = 3 + w.profile + w.channel + 1 + 1 rtlink_address_width = min(8, internal_address_width) overflow_address_width = internal_address_width - rtlink_address_width self.rtlink = rtlink.Interface( rtlink.OInterface(data_width=overflow_address_width + w.coeff, address_width=rtlink_address_width, enable_replace=False), rtlink.IInterface(data_width=w.coeff, timestamped=False)) # # # config = Signal(w.coeff, reset=0) status = Signal(w.coeff) pad = Signal(6) self.comb += [ Cat(servo.start).eq(config), status.eq( Cat(servo.start, servo.done, pad, [_.clip for _ in servo.iir.ctrl])) ] assert len(self.rtlink.o.address) + len( self.rtlink.o.data) - w.coeff == ( 1 + # we 1 + # state_sel 1 + # high_coeff len(m_coeff.adr)) # ensure that we can fit config/status into the state address space assert len(self.rtlink.o.address) + len( self.rtlink.o.data) - w.coeff >= ( 1 + # we 1 + # state_sel 1 + # config_sel len(m_state.adr)) internal_address = Signal(internal_address_width) self.comb += internal_address.eq( Cat(self.rtlink.o.address, self.rtlink.o.data[w.coeff:])) coeff_data = Signal(w.coeff) self.comb += coeff_data.eq(self.rtlink.o.data[:w.coeff]) we = internal_address[-1] state_sel = internal_address[-2] config_sel = internal_address[-3] high_coeff = internal_address[0] self.comb += [ self.rtlink.o.busy.eq(0), m_coeff.adr.eq(internal_address[1:]), m_coeff.dat_w.eq(Cat(coeff_data, coeff_data)), m_coeff.we[0].eq(self.rtlink.o.stb & ~high_coeff & we & ~state_sel), m_coeff.we[1].eq(self.rtlink.o.stb & high_coeff & we & ~state_sel), m_state.adr.eq(internal_address), m_state.dat_w[w.state - w.coeff:].eq(self.rtlink.o.data), m_state.we.eq(self.rtlink.o.stb & we & state_sel & ~config_sel), ] read = Signal() read_state = Signal() read_high = Signal() read_config = Signal() self.sync.rio += [ If(read, read.eq(0)), If( self.rtlink.o.stb, read.eq(~we), read_state.eq(state_sel), read_high.eq(high_coeff), read_config.eq(config_sel), ) ] self.sync.rio_phy += [ If(self.rtlink.o.stb & we & state_sel & config_sel, config.eq(self.rtlink.o.data)), If(read & read_config & read_state, [_.clip.eq(0) for _ in servo.iir.ctrl]) ] self.comb += [ self.rtlink.i.stb.eq(read), self.rtlink.i.data.eq( Mux( read_state, Mux(read_config, status, m_state.dat_r[w.state - w.coeff:]), Mux(read_high, m_coeff.dat_r[w.coeff:], m_coeff.dat_r[:w.coeff]))) ]