Esempio n. 1
0
def cross_connect(gpio, chains):
    state_names = ["force"] + ["di%i" % i for i in range(len(gpio.i))]
    states = [1, gpio.i]
    signal_names = ["zero"]
    signals = Array([0])

    for n, c in chains:
        for s in c.state_out:
            states.append(s)
            state_names.append("%s_%s" % (n, s.backtrace[-1][0]))
        for s in c.signal_out:
            signals.append(s)
            name = s.backtrace[-1][0]
            signal_names.append("%s_%s" % (n, name))
            sig = CSRStatus(len(s), name=name)
            clr = CSR(name="%s_clr" % name)
            max = CSRStatus(len(s), name="%s_max" % name)
            min = CSRStatus(len(s), name="%s_min" % name)
            # setattr(c, sig.name, sig)
            setattr(c, clr.name, clr)
            setattr(c, max.name, max)
            setattr(c, min.name, min)
            c.comb += sig.status.eq(s)
            c.sync += If(clr.re | (max.status < s), max.status.eq(s))
            c.sync += If(clr.re | (min.status > s), min.status.eq(s))

    states = Cat(states)
    state = Signal(len(states))
    gpio.comb += state.eq(states)
    gpio.state = CSRStatus(len(state))
    gpio.state_clr = CSR()
    gpio.sync += [
        If(
            gpio.state_clr.re,
            gpio.state.status.eq(0),
        ).Else(gpio.state.status.eq(gpio.state.status | state), )
    ]

    # connect gpio output to "doi%i_en"
    for i, s in enumerate(gpio.o):
        csr = CSRStorage(len(state), name="do%i_en" % i)
        setattr(gpio, csr.name, csr)
        gpio.sync += s.eq((state & csr.storage) != 0)

    # connect state ins to "%s_en" and signal ins to "%s_sel"
    for n, c in chains:
        for s in c.state_in:
            csr = CSRStorage(len(state), name="%s_en" % s.backtrace[-1][0])
            setattr(c, csr.name, csr)
            c.sync += s.eq((state & csr.storage) != 0)

        for s in c.signal_in:
            csr = CSRStorage(bits_for(len(signals) - 1),
                             name="%s_sel" % s.backtrace[-1][0])
            setattr(c, csr.name, csr)
            c.sync += s.eq(signals[csr.storage])

    return state_names, signal_names
Esempio n. 2
0
    def connect_everything(self, width, signal_width):
        s = signal_width - width

        combined_error_signal = Signal((signal_width, True))
        self.control_signal = Signal((signal_width, True))

        self.sync += [
            self.chain_a_offset_signed.eq(self.chain_a_offset.storage),
            self.chain_b_offset_signed.eq(self.chain_b_offset.storage),
            self.combined_offset_signed.eq(self.combined_offset.storage),
            self.out_offset_signed.eq(self.out_offset.storage),
        ]

        self.state_in = []
        self.signal_in = []
        self.state_out = []
        self.signal_out = [self.control_signal, combined_error_signal]

        self.comb += [
            combined_error_signal.eq(self.limit_error_signal.y),
            self.control_signal.eq(
                Array([self.limit_fast1.y, self.limit_fast2.y])[
                    self.control_channel.storage
                ]
                << s
            ),
        ]
Esempio n. 3
0
        def __init__(self, hit_channels, time, reset, clock):

            # parameters

            # inputs
            self.hit_channels = hit_channels
            self.reset = reset
            self.clock = clock

            # outputs
            self.time = time

            # internal signals
            self.meta_reg1 = Signal(self.NB_INPUTS)
            self.meta_reg2 = Signal(self.NB_INPUTS)
            self.edge_reg = Signal(self.NB_INPUTS)
            self.edge_detect = Signal(self.NB_INPUTS)
            self.hit_time_regs = Array(
                Signal(TIME_RES) for a in range(self.NB_INPUTS))
            self.time_reg = Signal(TIME_RES)

            ####

            # edge detector with meta-stability removal register chain
            self.sync += [
                self.meta_reg1.eq(self.hit_channels),
                self.meta_reg2.eq(self.meta_reg1),
                self.edge_reg.eq(self.meta_reg2),
            ]

            for i in range(self.NB_INPUTS):
                self.sync += [
                    If(
                        self.edge_detect[i],  # pulse detected
                        self.hit_time_regs[i].eq(
                            self.clock)  # update hit register
                    ).Elif(
                        self.reset.data == 1,
                        self.hit_time_regs[i].eq(0),
                    ).Elif(
                        self.hit_time_regs[i] != 0,  # reset hit register
                        self.hit_time_regs[i].eq(0))
                ]

            self.comb += [
                self.time_reg.eq(self.hit_time_regs[0]
                                 | self.hit_time_regs[1])
            ]
            self.comb += [
                self.reset.ready.eq(1),
                self.time.data.eq(self.time_reg),
                self.edge_detect.eq(~self.edge_reg
                                    & self.meta_reg2),  # edge detection
                # output logic
                If(self.time_reg != 0,
                   self.time.valid.eq(1)).Else(self.time.valid.eq(0))
            ]
Esempio n. 4
0
    def __init__(self, max_decimation):
        self.decimation = Signal(max_decimation)

        self.decimation_counter = Signal(max_decimation)
        self.sync += [self.decimation_counter.eq(self.decimation_counter + 1)]

        self.output = Signal(1)

        self.sync += [
            self.output.eq(Array(self.decimation_counter)[self.decimation])
        ]
Esempio n. 5
0
    def migen_body(self, template):

        # generics
        N_BITS = template.generics["N_BITS"]  # 1-64
        N_INPUTS = template.generics["N_INPUTS"]
        TREE_DEPTH = int(ceil(log2(N_INPUTS)))

        # inputs
        self.d_in = template.add_pa_in_port(
            'd_in', dl.DOptional(dl.DInt(dl.DSize(N_BITS * N_INPUTS))))
        self.cmd = template.add_pa_in_port('cmd', dl.DOptional(dl.DInt()))

        # outputs
        self.d_out = template.add_pa_out_port('d_out', dl.DInt())
        self.err = template.add_pa_out_port('error', dl.DInt())

        # input length correction [need a power of 2 sized tree]
        N_INPUTS_CORR = pow(2, TREE_DEPTH)

        # internals

        # correct the size of the input tree to be a power of 2
        # and register the inputs
        self.d_in_full_reg = Signal(N_INPUTS_CORR * N_BITS)
        self.d_in_valid_reg = Signal(1)
        self.cmd_data_reg = Signal(8)
        self.cmd_valid_reg = Signal(1)

        # register outputs
        self.d_out_data_reg = Signal(N_BITS + TREE_DEPTH)
        self.d_out_valid_reg = Signal(1)
        self.err_data_reg = Signal(1)
        self.err_valid_reg = Signal(1)

        # create the 2D array of data [INPUTS x TREE_DEPTH] to route
        # all the core units in an iterative way. The number of bits is incremented
        # at each stage to account for the carry in additions.
        self.d_pipe = Array(
            Array(Signal(N_BITS + b) for a in range(N_INPUTS_CORR))
            for b in range(TREE_DEPTH + 1))

        # create the 2D array of error signals.
        self.e_pipe = Array(
            Array(Signal(N_BITS) for a in range(N_INPUTS_CORR))
            for b in range(TREE_DEPTH))

        ###

        # correct input vector length to match a power of 2.
        # fill non-provided inputs with 0's (affects mean and minimum)
        self.sync += [
            self.d_in_full_reg.eq(self.d_in.data),
            self.d_in_valid_reg.eq(self.d_in.valid),
            self.cmd_data_reg.eq(self.cmd.data),
            self.cmd_valid_reg.eq(self.cmd.valid)
        ]

        # wiring inputs to the first stage of the tree
        for i in range(N_INPUTS_CORR):
            self.comb += [
                self.d_pipe[0][i].eq(self.d_in_full_reg[N_BITS * i:N_BITS *
                                                        (i + 1)])
            ]

        # instantiation of the core units.
        for j in range(TREE_DEPTH):
            for i in range(int(N_INPUTS_CORR / (pow(2, j + 1)))):
                self.submodules += CoreUnit(self.d_pipe[j][2 * i],
                                            self.d_pipe[j][2 * i + 1],
                                            self.d_pipe[j + 1][i],
                                            self.cmd_data_reg,
                                            self.e_pipe[j][i], N_BITS)

                # error signal propagation. If any of the single units have
                # a high error signal, the error is propagated to the node's output.
                self.comb += [
                    If(self.e_pipe[j][i] == 1, self.err_data_reg.eq(1))
                ]

        self.comb += [
            self.d_in.ready.eq(1),
            self.cmd.ready.eq(1),
            self.d_out_data_reg.eq(self.d_pipe[TREE_DEPTH][0]),
            If(self.d_in_valid_reg, self.err_valid_reg.eq(1),
               self.d_out_valid_reg.eq(1)).Else(self.err_valid_reg.eq(0))
        ]

        self.sync += [
            self.d_out.data.eq(self.d_out_data_reg),
            self.d_out.valid.eq(self.d_out_valid_reg),
            self.err.data.eq(self.err_data_reg),
            self.err.valid.eq(self.err_valid_reg)
        ]
Esempio n. 6
0
    def __init__(self, width=14, N_points=16383, max_delay=16383):
        self.init_submodules(width, N_points, max_delay)
        peak_height_bit, x_data_length_bit = self.init_csr(N_points)
        self.init_inout_signals(width)

        # is the autolock actively trying to detect peaks? This is set to true
        # if lock is requested and once the ramp is at start
        watching = Signal()

        # the following signals are property of the peak that the autolock is
        # trying to detet right now
        self.current_instruction_idx = Signal(
            bits_for(AUTOLOCK_MAX_N_INSTRUCTIONS - 1))
        current_peak_height = Signal((peak_height_bit, True))
        abs_current_peak_height = Signal.like(current_peak_height)
        current_wait_for = Signal(x_data_length_bit)
        self.comb += [
            current_peak_height.eq(
                Array([
                    peak_height.storage for peak_height in self.peak_heights
                ])[self.current_instruction_idx]),
            current_wait_for.eq(
                Array([wait_for.storage for wait_for in self.wait_for
                       ])[self.current_instruction_idx]),
        ]

        # after detecting the last peak, how many cycles have passed?
        waited_for = Signal(bits_for(N_points))
        # after all peaks have been detected, how many cycles have passed?
        final_waited_for = Signal(bits_for(N_points))

        # this is the signal that's used for detecting peaks
        sum_diff = Signal((len(self.sum_diff_calculator.output), True))
        abs_sum_diff = Signal.like(sum_diff)
        self.comb += [
            self.sum_diff_calculator.writing_data_now.eq(
                self.writing_data_now),
            self.sum_diff_calculator.restart.eq(self.at_start),
            self.sum_diff_calculator.input.eq(self.input),
            self.sum_diff_calculator.delay_value.eq(self.time_scale.storage),
            sum_diff.eq(self.sum_diff_calculator.output),
        ]

        # has this signal at the moment the same sign as the peak we are looking
        # for?
        sign_equal = Signal()
        # is this signal higher than the peak we are looking for?
        over_threshold = Signal()
        # since detecting the previous peak, has enough time passed?
        waited_long_enough = Signal()
        # have we detected all peaks (and can turn on the lock)?
        all_instructions_triggered = Signal()

        self.comb += [
            sign_equal.eq((sum_diff > 0) == (current_peak_height > 0)),
            If(sum_diff >= 0,
               abs_sum_diff.eq(sum_diff)).Else(abs_sum_diff.eq(-1 * sum_diff)),
            If(
                current_peak_height >= 0,
                abs_current_peak_height.eq(current_peak_height),
            ).Else(abs_current_peak_height.eq(-1 * current_peak_height)),
            over_threshold.eq(abs_sum_diff >= abs_current_peak_height),
            waited_long_enough.eq(waited_for > current_wait_for),
            all_instructions_triggered.eq(
                self.current_instruction_idx >= self.N_instructions.storage),
            self.turn_on_lock.eq(
                all_instructions_triggered
                & (final_waited_for >= self.final_wait_time.storage)),
        ]

        self.sync += [
            If(
                self.at_start,
                waited_for.eq(0),
                # fpga robust autolock algorithm registeres trigger events delayed.
                # Therefore, we give it a head start for `final_waited_for`
                final_waited_for.eq(ROBUST_AUTOLOCK_FPGA_DELAY),
                self.current_instruction_idx.eq(0),
                If(self.request_lock, watching.eq(1)).Else(watching.eq(0)),
            ).Else(
                # not at start
                If(
                    ~self.request_lock,
                    # disable `watching` if `request_lock` was disabled while
                    # the ramp is running. This is important for slow scan
                    # speeds when disabling the autolock and enabling it again
                    # with different parameters. In this case we want to take
                    # care that we start watching at start.
                    watching.eq(0),
                ),
                If(
                    self.writing_data_now & ~all_instructions_triggered
                    & self.sweep_up,
                    If(
                        watching & sign_equal & over_threshold
                        & waited_long_enough,
                        self.current_instruction_idx.eq(
                            self.current_instruction_idx + 1),
                        waited_for.eq(0),
                    ).Else(waited_for.eq(waited_for + 1)),
                ),
                If(
                    self.writing_data_now & all_instructions_triggered
                    & self.sweep_up,
                    final_waited_for.eq(final_waited_for + 1),
                ),
            ),
        ]

        self.signal_out = []
        self.signal_in = []
        self.state_out = [
            watching,
            self.turn_on_lock,
            sign_equal,
            over_threshold,
            waited_long_enough,
        ]
        self.state_in = []
Esempio n. 7
0
    def __init__(self, width=25):
        self.gpio_trigger = Signal()
        self.sweep_trigger = Signal()

        # when lock is disabled and sweep enabled, acquisition process arms the
        # scope, waits until scope has triggered and reads out the data. Once
        # data is read out, it rearms the acquisition. When robust autolock is
        # looking for a lock point, acquisition process doesn't send any triggers
        # though because it doesn't transmit any data until lock is confirmed.
        # Therefore, autolock turns on "always_arm" mode which automatically
        # rearms scope when it has finished.
        self.automatically_rearm = Signal()

        # this mode is used when the laser is locked. In this case we don't have
        # to sync acquisition with a ramp. Synchronisation with readout takes
        # place by manually rearming after reading out the data.
        self.automatically_trigger = Signal()
        automatic_trigger_signal = Signal()
        self.sync += [
            If(self.automatically_trigger,
                automatic_trigger_signal.eq(~automatic_trigger_signal)
            ).Else(
                automatic_trigger_signal.eq(0)
            )
        ]

        self.external_trigger = CSRStorage(1)
        ext_scope_trigger = Array([self.gpio_trigger, self.sweep_trigger])[
            self.external_trigger.storage
        ]

        self.scope_sys = Record(sys_layout)
        self.asg_sys = Record(sys_layout)

        adc_a = Signal((width, True))
        adc_a_q = Signal((width, True))
        adc_b = Signal((width, True))
        adc_b_q = Signal((width, True))
        dac_a = Signal((width, True))
        dac_b = Signal((width, True))

        self.signal_in = adc_a, adc_b, adc_a_q, adc_b_q
        self.signal_out = dac_a, dac_b
        self.state_in = ()
        self.state_out = ()

        asg_a = Signal((14, True))
        asg_b = Signal((14, True))
        asg_trig = Signal()

        s = width - len(asg_a)
        self.comb += dac_a.eq(asg_a << s), dac_b.eq(asg_b << s)

        # these signals will be connected to autolock which inspects written data
        self.writing_data_now = Signal()
        self.scope_written_data = Signal((14, True))
        self.scope_position = Signal(14)

        self.specials.scope = Instance(
            "red_pitaya_scope",
            i_automatically_rearm_i=self.automatically_rearm,
            i_adc_a_i=adc_a >> s,
            i_adc_b_i=adc_b >> s,
            i_adc_a_q_i=adc_a_q >> s,
            i_adc_b_q_i=adc_b_q >> s,
            # i_adc_a_q_i=0b11111111111111,
            # i_adc_b_q_i=0b11111111111111,
            i_adc_clk_i=ClockSignal(),
            i_adc_rstn_i=~ResetSignal(),
            i_trig_ext_i=ext_scope_trigger | automatic_trigger_signal,
            i_trig_asg_i=asg_trig,
            i_sys_clk_i=self.scope_sys.clk,
            i_sys_rstn_i=self.scope_sys.rstn,
            i_sys_addr_i=self.scope_sys.addr,
            i_sys_wdata_i=self.scope_sys.wdata,
            i_sys_sel_i=self.scope_sys.sel,
            i_sys_wen_i=self.scope_sys.wen,
            i_sys_ren_i=self.scope_sys.ren,
            o_sys_rdata_o=self.scope_sys.rdata,
            o_sys_err_o=self.scope_sys.err,
            o_sys_ack_o=self.scope_sys.ack,
            o_written_data=self.scope_written_data,
            o_scope_position=self.scope_position,
            o_scope_writing_now=self.writing_data_now,
        )
Esempio n. 8
0
    def __init__(self,
                 width=14,
                 signal_width=25,
                 coeff_width=18,
                 mod=None,
                 offset_signal=None):
        self.adc = Signal((width, True))
        # output of in-phase demodulated signal
        self.out_i = Signal((signal_width, True))
        # output of quadrature demodulated signal
        self.out_q = Signal((signal_width, True))

        self.y_tap = CSRStorage(2)
        self.invert = CSRStorage(1)

        self.state_in = []
        self.state_out = []

        x = Signal((signal_width, True))
        dx = Signal((signal_width, True))
        dy = Signal((signal_width, True))

        self.signal_in = dx, dy
        self.signal_out = x, self.out_i, self.out_q

        ###

        self.submodules.demod = Demodulate(width=width)

        ###

        s = signal_width - width

        self.comb += [
            x.eq(self.adc << s),
            self.demod.x.eq(self.adc),
            self.demod.phase.eq(mod.phase),
        ]
        ya = Signal((width + 3, True))
        self.sync += (ya.eq(((dy >> s))), )

        ###

        def init_submodule(name, submodule):
            setattr(self.submodules, name, submodule)

        # iterate over in-phase and quadrature signal
        # both have filters and limits
        for sub_channel_idx in (0, 1):
            x_limit = LimitCSR(width=signal_width, guard=1)
            init_submodule("x_limit_%d" % (sub_channel_idx + 1), x_limit)
            iir_c = Iir(
                width=signal_width,
                coeff_width=coeff_width,
                shift=coeff_width - 2,
                order=1,
            )
            init_submodule("iir_c_%d" % (sub_channel_idx + 1), iir_c)
            iir_d = Iir(
                width=signal_width,
                coeff_width=coeff_width,
                shift=coeff_width - 2,
                order=2,
            )
            init_submodule("iir_d_%d" % (sub_channel_idx + 1), iir_d)
            y_limit = LimitCSR(width=signal_width, guard=3)
            init_submodule("y_limit_%d" % (sub_channel_idx + 1), y_limit)

            self.comb += [
                x_limit.x.eq(
                    ([self.demod.i, self.demod.q][sub_channel_idx] << s) + dx),
                iir_c.x.eq(x_limit.y),
                iir_c.hold.eq(0),
                iir_c.clear.eq(0),
                iir_d.x.eq(iir_c.y),
                iir_d.hold.eq(0),
                iir_d.clear.eq(0),
            ]

            ys = Array([iir_c.x, iir_c.y, iir_d.y])

            self.comb += [
                y_limit.x.eq(
                    Mux(self.invert.storage, -1, 1) *
                    (ys[self.y_tap.storage] + (ya << s) +
                     (offset_signal << s))),
                (self.out_i, self.out_q)[sub_channel_idx].eq(y_limit.y),
            ]