Exemplo n.º 1
0
    def __init__(self, clk_freq, baud_rate):
        self.submodules.rxcore = RX(clk_freq, baud_rate)
        self.submodules.fifo = SyncFIFO(8, 1024)
        self.comb += [self.fifo.din.eq(self.rxcore.data)]
        self.submodules.fsm = FSM(reset_state='IDLE')
        self.fsm.act(
            'IDLE',
            If(
                self.rxcore.ready,
                If(
                    self.fifo.writable,
                    self.fifo.we.eq(1),
                ),
                self.rxcore.ack.eq(1),
                NextState('READING'),
            ).Else(self.fifo.we.eq(0), ))
        self.fsm.act(
            'READING',
            self.fifo.we.eq(0),
            self.rxcore.ack.eq(0),
            If(
                ~self.rxcore.ready,
                NextState('IDLE'),
            ),
        )
        self.dout = self.fifo.dout
        self.re = self.fifo.re
        self.readable = self.fifo.readable
        self.rx = self.rxcore.rx

        self.io = {self.dout, self.re, self.readable, self.rx}
Exemplo n.º 2
0
    def __init__(self):
        self.cfu_bus = Record(cfu_bus_minimized_layout)
        self.cfu_cen = Signal()
        self.cpu_cen = Signal()

        self.submodules.fsm = fsm = FSM(reset_state="CPU_ENABLED")

        fsm.act(
            "CPU_ENABLED",
            self.cpu_cen.eq(1),
            self.cfu_cen.eq(0),

            # If CPU has prepared a command, enable CFU
            If(
                self.cfu_bus.cmd.valid,
                self.cfu_cen.eq(1),
                NextState("CFU_ENABLED"),
            ))

        fsm.act(
            "CFU_ENABLED",
            self.cfu_cen.eq(1),
            self.cpu_cen.eq(1),

            # Disable CPU if CFU is calculating response
            If(
                ~self.cfu_bus.rsp.valid & ~self.cfu_bus.cmd.valid,
                self.cpu_cen.eq(0),

                # Enable CPU and disable CFU if CPU received a response and has no next command
                If(
                    self.cfu_bus.cmd.ready,
                    self.cpu_cen.eq(1),
                    NextState("CPU_ENABLED"),
                )))
Exemplo n.º 3
0
    def __init__(self, clk_freq, baud_rate):
        self.data = Signal(8)
        self.ready = Signal()
        self.ack = Signal()
        self.error = Signal()
        self.rx = Signal(reset=1)

        divisor = clk_freq // baud_rate

        rx_counter = Signal(max=divisor)
        self.rx_strobe = Signal()
        self.comb += self.rx_strobe.eq(rx_counter == 0)
        self.sync += \
                If(rx_counter == 0,
                    rx_counter.eq(divisor - 1)
                ).Else(
                    rx_counter.eq(rx_counter - 1)
                )

        self.rx_bitno = Signal(3)
        self.submodules.rx_fsm = FSM(reset_state='IDLE')
        self.rx_fsm.act(
            'IDLE',
            If(~self.rx, NextValue(rx_counter, divisor // 2),
               NextState('START')))
        self.rx_fsm.act('START', If(self.rx_strobe, NextState('DATA')))
        self.rx_fsm.act(
            'DATA',
            If(self.rx_strobe,
               NextValue(self.data, Cat(self.data[1:8], self.rx)),
               NextValue(self.rx_bitno, self.rx_bitno + 1),
               If(self.rx_bitno == 7, NextState('STOP'))))
        self.rx_fsm.act(
            'STOP',
            If(self.rx_strobe,
               If(~self.rx, NextState('ERROR')).Else(NextState('FULL'), )))
        self.rx_fsm.act(
            'FULL', self.ready.eq(1),
            If(self.ack, NextState('IDLE')).Elif(~self.rx, NextState('ERROR')))
        self.rx_fsm.act('ERROR', self.error.eq(1))
Exemplo n.º 4
0
    def migen_body(self, template):

        inp = template.add_pa_in_port('inp', DOptional(DInt()))
        trigger = template.add_pa_in_port('trigger', DOptional(DInt()))
        out = template.add_pa_out_port('out', DInt())

        # Declare input and output ports always happy to receive/transmit data
        self.comb += (
            inp.ready.eq(1),
            trigger.ready.eq(1),
            out.ready.eq(1),
        )

        commander_fsm = FSM(reset_state="IDLE")
        self.submodules.commander_fsm = commander_fsm

        commander_fsm.act("IDLE", If(inp.valid == 1, NextState("LOADING")))

        commander_fsm.act(
            "LOADING",
            If(trigger.valid & trigger.data == 1, NextState("RETURN")).Else(
                NextValue(out.data, out.data + inp.data), ))

        commander_fsm.act("RETURN", NextValue(out.valid, 1), NextState("IDLE"))
Exemplo n.º 5
0
    def migen_body(self, template):
        # creation of input/output ports
        angle = template.add_pa_in_port(
            'angle',
            dl.DOptional(dl.DRaw(dl.DUInt(dl.DSize(ANGLE_MEMORY_WIDTH))))
        )

        hal_command = template.add_pa_out_port('hal_command',
                                               dl.DUInt(dl.DSize(32)))
        shot_completed = template.add_pa_out_port('shot_completed',
                                               dl.DBool())
        # set up  internal signals
        _rotation_command = Signal(32)

        self.comb += (
            # declare input/output ports always happy to receive/transmit data
            angle.ready.eq(1)
        )

        # define finite state machine for triggering HAL command sequences
        self.submodules.commander_fsm = \
            commander_fsm = FSM(reset_state="STATE_PREPARATION")

        # waits for angle signal before kicking off HAL sequence
        commander_fsm.act(
            "STATE_PREPARATION",
            NextValue(shot_completed.valid, 0),
            If(
                angle.valid == 1,
                NextValue(
                    _rotation_command,
                    dl.lib.command_creator("RX", argument=angle.data)
                ),
                NextValue(hal_command.valid, 1),
                NextValue(
                    hal_command.data,
                    dl.lib.command_creator("STATE_PREPARATION")
                ),
                NextState("ROTATION")
            ).Else(
                NextValue(hal_command.valid, 0),
                NextState("STATE_PREPARATION")
            )
        )

        # align HAL command to rotation
        commander_fsm.act(
            "ROTATION",
            NextValue(hal_command.valid, 1),
            NextValue(hal_command.data, _rotation_command),
            NextValue(shot_completed.valid, 0),
            NextState("STATE_MEASURE")
        )

        # align HAL command to state measure
        commander_fsm.act(
            "STATE_MEASURE",
            NextValue(hal_command.valid, 1),
            NextValue(hal_command.data,
                      dl.lib.command_creator("STATE_MEASURE")),
            NextValue(shot_completed.valid, 1),
            NextValue(shot_completed.data, 1),
            NextState("STATE_PREPARATION")
        )
Exemplo n.º 6
0
    def migen_body(self, template):
        # creation of input/output ports
        shot_completed = template.add_pa_in_port('shot_completed',
                                              dl.DOptional(dl.DBool()))
        hal_result = template.add_pa_in_port(
            'hal_result',
            dl.DOptional(dl.DUInt(dl.DSize(32)))
        )

        agg_result = template.add_pa_out_port('agg_result',
                                              dl.DInt(dl.DSize(32)))
        # Completed is currently returning a simple 0/1 value but we make space
        # for an error code to be returned e.g. 255, 0b11111111 can be in the
        # future used to represent an error.
        completed = template.add_pa_out_port('completed', dl.DInt(dl.DSize(8)))
        next_angle = template.add_pa_out_port(
            'next_angle',
            dl.DRaw(dl.DUInt(dl.DSize(ANGLE_MEMORY_WIDTH)))
        )

        # generate a ROM of 10-bit angle values
        angles = generate_angles(RESOLUTION)

        self.specials.angle_memory = angle_memory = Memory(
            ANGLE_MEMORY_WIDTH, len(angles), init=angles, name="ANGLE_ROM"
        )
        angle_rom_port = angle_memory.get_port(write_capable=False)
        self.specials += angle_rom_port

        # set up internal signals
        _shots_counter = Signal(32)
        _high_hal_results = Signal(32)
        _reset_high_hal = Signal(1)
        _angle_rom_index = Signal(RESOLUTION+1)

        self.comb += (
            # declare input/output ports always happy to receive/transmit data
            hal_result.ready.eq(1),
            shot_completed.ready.eq(1),

            # align angle ROM address with ROM index signal
            angle_rom_port.adr.eq(_angle_rom_index),
        )

        # define finite state machine for triggering angle and result signals
        self.submodules.rabi_aggregator_fsm = \
            rabi_aggregator_fsm = FSM(reset_state="IDLE")

        # Logic to accumulate measurements
        self.sync += (
            If (_reset_high_hal == 1,
                _high_hal_results.eq(0)
            ).Else (
                If (hal_result.valid == 1,
                    If ((hal_result.data &
                        dl.lib.Masks.MEASUREMENTS.value) == 1,
                        _high_hal_results.eq(_high_hal_results + 1)
                    )
                )
            )
        )

        # waits for the experiment to be kicked off

        rabi_aggregator_fsm.act(
            "IDLE",
            NextValue(agg_result.valid, 0),
            NextValue(next_angle.valid, 0),
            NextValue(completed.valid, 0),
            NextValue(_shots_counter, 0),
            NextValue(_reset_high_hal, 1),
            NextState("DO_SHOTS")
        )

        rabi_aggregator_fsm.act(
            "DO_SHOTS",
            NextValue(agg_result.valid, 0),
            NextValue(_reset_high_hal, 0),
            If (_shots_counter == REPETITIONS,
                NextState("CHECK_IF_COMPLETE"),
                NextValue(_angle_rom_index, _angle_rom_index + 1),
                NextValue(agg_result.data, _high_hal_results),
                NextValue(agg_result.valid, 1),
                NextValue(_reset_high_hal, 1),
             ).Else (
                NextValue(next_angle.data, angle_rom_port.dat_r),
                NextValue(next_angle.valid, 1),
                NextState("WAIT_SHOT")
            )
        )

        rabi_aggregator_fsm.act(
            "WAIT_SHOT",
            NextValue(next_angle.valid, 0),
            If ((shot_completed.valid == 1) & (shot_completed.data == 1),
                NextValue(_shots_counter, _shots_counter + 1),
                NextState("DO_SHOTS"),
            )
        )

        rabi_aggregator_fsm.act(
            "CHECK_IF_COMPLETE",
            NextState("IDLE"),
            NextValue(agg_result.valid, 0),
            If(_angle_rom_index == 2 ** RESOLUTION,
                NextValue(completed.data, 1),
                NextValue(completed.valid, 1),
            )
        )
Exemplo n.º 7
0
    def migen_body(self, template):

        _TIME_RES = 32
        # Node inputs
        self.time_in = template.add_pa_in_port('time_in',
                                               dl.Optional(dl.UInt()))

        # Node outputs
        self.time_out = template.add_pa_out_port('time_out', dl.UInt())
        self.counter_reset = template.add_pa_out_port('counter_reset',
                                                      dl.Int())

        # Internal signals
        self.pmt_reg = Signal(_TIME_RES)
        self.rf_reg = Signal(_TIME_RES)
        self.pmt_trig = Signal(1)
        self.rf_trig = Signal(1)

        self.submodules.fsm = FSM(reset_state="RESET_COUNTER")

        self.sync += [
            If(
                self.pmt_trig,
                self.pmt_reg.eq(self.time_in.data),
            ).Elif(self.fsm.ongoing("RESET_COUNTER"),
                   self.pmt_reg.eq(0)).Else(self.pmt_reg.eq(self.pmt_reg)),
            If(
                self.rf_trig,
                self.rf_reg.eq(self.time_in.data),
            ).Elif(self.fsm.ongoing("RESET_COUNTER"),
                   self.rf_reg.eq(0)).Else(self.rf_reg.eq(self.rf_reg))
        ]
        """FSM
        The FSM is used to control the readouts from the HPTDC chip and
        generate a time signal for the accumulator

        RESET_COUNTER
        This is the dinitial state of the FSM at the start of the experiment.
        It resets the "coarse counter" of the HPTDC chip to establish a TO
        time reference.

        WAIT_FOR_PMT
        This state holds until the PMT timestamp is available at the HPTDC
        chip readout (first data_ready sync pulse)

        WAIT_FOR_RF
        This state holds until the RMT timestamp is available at the HPTDC
        chip readout (second data_ready sync pulse)

        SEND_TIME
        In this state, the difference between t_PMT and t_RF is derived and
        sent to the accumulator.

        WAIT_ACC_LATENCY
        This state is used to wait for any delays on inter-node communication
        """

        self.fsm.act(
            "RESET_COUNTER",
            self.pmt_trig.eq(0),
            self.rf_trig.eq(0),
            self.time_in.ready.eq(1),
            self.counter_reset.data.eq(1),  # reset counters
            self.counter_reset.valid.eq(1),
            NextState("WAIT_FOR_PMT"))

        self.fsm.act(
            "WAIT_FOR_PMT", self.counter_reset.data.eq(0),
            self.time_in.ready.eq(1),
            If(self.time_in.valid, self.pmt_trig.eq(1),
               NextState("WAIT_FOR_RF")))

        self.fsm.act(
            "WAIT_FOR_RF", self.time_in.ready.eq(1),
            If(self.time_in.valid, self.rf_trig.eq(1), NextState("SEND_TIME")))

        self.fsm.act("SEND_TIME", self.time_in.ready.eq(1),
                     self.time_out.data.eq(self.rf_reg - self.pmt_reg),
                     self.time_out.valid.eq(1), NextState("WAIT_ACC_LATENCY"))

        self.fsm.act("WAIT_ACC_LATENCY",
                     If(self.time_in.valid == 0, NextState("RESET_COUNTER")))
Exemplo n.º 8
0
    def __init__(self, pads):
        self.pads = pads
        self.bus = bus = Interface(adr_width=22)

        self.dly_io = delayf_pins()
        self.dly_clk = delayf_pins()

        # # #

        clk = Signal()
        cs = Signal()
        ca = Signal(48)
        sr_in = Signal(64)
        sr_out = Signal(64)
        sr_rwds_in = Signal(8)
        sr_rwds_out = Signal(8)

        timeout_counter = Signal(6)

        self.submodules.phy = phy = HyperBusPHY(pads)

        self.comb += [
            phy.dly_io.eq(self.dly_io),
            phy.dly_clk.eq(self.dly_clk),
        ]

        # Drive rst_n, from internal signals ---------------------------------------------
        if hasattr(pads, "rst_n"):
            self.comb += pads.rst_n.eq(1)

        self.comb += [phy.cs.eq(~cs), phy.clk_enable.eq(clk)]

        # Data In/Out Shift Registers -------------------------------------------------
        self.sync += [
            sr_out.eq(Cat(Signal(32), sr_out[:32])),
            sr_in.eq(Cat(phy.dq.i, sr_in[:32])),
            sr_rwds_in.eq(Cat(phy.rwds.i, sr_rwds_in[:4])),
            sr_rwds_out.eq(Cat(phy.rwds.i, sr_rwds_out[:4])),
        ]

        self.comb += [
            bus.dat_r.eq(Cat(phy.dq.i[-16:], sr_in[:16])),  # To Wishbone
            phy.dq.o.eq(sr_out[-32:]),  # To HyperRAM
            phy.rwds.o.eq(sr_rwds_out[-4:])  # To HyperRAM
        ]

        # Command generation -----------------------------------------------------------------------
        self.comb += [
            ca[47].eq(~self.bus.we),  # R/W#
            ca[45].eq(1),  # Burst Type (Linear)
            ca[16:35].eq(self.bus.adr[2:21]),  # Row & Upper Column Address
            ca[1:3].eq(self.bus.adr[0:2]),  # Lower Column Address
            ca[0].eq(0),  # Lower Column Address
        ]

        # FSM Sequencer --------------------------------------------------------------------------------
        self.submodules.fsm = fsm = FSM(reset_state="IDLE")
        fsm.act("IDLE",
                If(bus.cyc & bus.stb, NextValue(cs, 1), NextState("CA-SEND")))
        fsm.act("CA-SEND", NextValue(clk, 1), NextValue(phy.dq.oe, 1),
                NextValue(sr_out, Cat(Signal(16), ca)), NextState("CA-WAIT"))
        fsm.act("CA-WAIT", NextValue(timeout_counter, 0), NextState("LATENCY"))
        fsm.act("LATENCY", NextValue(phy.dq.oe, 0), NextState("LATENCY-WAIT"))

        fsm.delayed_enter("LATENCY-WAIT", "READ-WRITE-SETUP", 3)

        fsm.act("READ-WRITE-SETUP", NextValue(phy.dq.oe, self.bus.we),
                NextValue(phy.rwds.oe, self.bus.we), NextState("READ-WRITE"))
        fsm.act(
            "READ-WRITE",
            NextState("READ-ACK"),
            If(
                self.bus.we,
                NextValue(phy.dq.oe, 1),  # Write Cycle
                NextValue(sr_out[:32], 0),
                NextValue(sr_out[32:], self.bus.dat_w),
                NextValue(sr_rwds_out[:4], 0),
                NextValue(sr_rwds_out[4:], ~bus.sel[0:4]),
                bus.ack.eq(1),  # Get next byte
                NextState("CLK-OFF"),
                If(
                    bus.cti == 0b010,
                    NextState("READ-WRITE"),
                )))

        fsm.act(
            "READ-ACK", NextValue(timeout_counter, timeout_counter + 1),
            If(phy.rwds.i[3], NextValue(timeout_counter, 0), bus.ack.eq(1),
               If(bus.cti != 0b010, NextValue(clk, 0), NextState("CLEANUP"))),
            If(~self.bus.cyc | (timeout_counter > 20), NextState("CLK-OFF")))

        fsm.act("CLK-OFF", NextValue(clk, 0), NextState("CLEANUP"))
        fsm.act("CLEANUP", NextValue(cs, 0), NextValue(phy.rwds.oe, 0),
                NextValue(phy.dq.oe, 0), NextState("HOLD-WAIT"))
        fsm.act("HOLD-WAIT", NextValue(sr_out, 0), NextValue(sr_rwds_out, 0),
                NextState("WAIT"))
        fsm.delayed_enter("WAIT", "IDLE", 10)

        # Signals that can be an ILA for debugging
        self.dbg = [
            bus,
            sr_out,
            sr_in,
            sr_rwds_in,
            sr_rwds_out,
            cs,
            clk,
            phy.dq.i,
            phy.dq.o,
            phy.dq.oe,
            phy.rwds.i,
            phy.rwds.o,
            phy.rwds.oe,
        ]
Exemplo n.º 9
0
    def __init__(self, counter_width=10):
        """Define the state machine logic for running the input & output sequences."""
        self.m = Signal(counter_width)  # Global cycle-relative time.
        self.time_remaining = Signal(
            32)  # Clock cycles remaining before timeout
        self.time_remaining_buf = Signal(32)
        self.cycles_completed = Signal(
            14
        )  # How many iterations of the loop have completed since last start

        self.run_stb = Signal(
        )  # Pulsed to start core running until timeout or success
        self.done_stb = (
            Signal())  # Pulsed when core has finished (on timeout or success)
        self.running = Signal()  # Asserted on run_stb, cleared on done_stb

        self.timeout = Signal()
        self.success = Signal()

        self.ready = Signal()

        self.herald = Signal()

        self.is_master = Signal()
        self.standalone = Signal(
        )  # Ignore state of partner for single-device testing.
        self.act_as_master = Signal()
        self.comb += self.act_as_master.eq(self.is_master | self.standalone)

        self.trigger_out = Signal()  # Trigger to slave

        # Unregistered inputs from master
        self.trigger_in_raw = Signal()
        self.success_in_raw = Signal()
        self.timeout_in_raw = Signal()

        # Unregistered input from slave
        self.slave_ready_raw = Signal()

        self.m_end = Signal(
            counter_width)  # Number of clock cycles to run main loop for

        # Asserted while the entangler is idling, waiting for the entanglement cycle to
        # start.
        self.cycle_starting = Signal()

        self.cycle_ending = Signal()

        # # #

        self.comb += self.cycle_ending.eq(self.m == self.m_end)

        self.trigger_in = Signal()
        self.success_in = Signal()
        self.slave_ready = Signal()
        self.timeout_in = Signal()
        self.sync += [
            self.trigger_in.eq(self.trigger_in_raw),
            self.success_in.eq(self.success_in_raw),
            self.slave_ready.eq(self.slave_ready_raw),
            self.timeout_in.eq(self.timeout_in_raw),
        ]

        self.sync += [
            If(self.run_stb, self.running.eq(1)),
            If(self.done_stb, self.running.eq(0)),
        ]

        # The core times out if time_remaining countdown reaches zero, or,
        # if we are a slave, if the master has timed out.
        # This is required to ensure the slave syncs with the master
        self.comb += self.timeout.eq((self.time_remaining == 0)
                                     | (~self.act_as_master & self.timeout_in))

        self.sync += [
            If(self.run_stb,
               self.time_remaining.eq(self.time_remaining_buf)).Else(
                   If(~self.timeout,
                      self.time_remaining.eq(self.time_remaining - 1)))
        ]

        done = Signal()
        done_d = Signal()
        finishing = Signal()
        self.comb += finishing.eq(~self.run_stb & self.running
                                  & (self.timeout | self.success))
        # Done asserted at the at the end of the successful / timedout cycle
        self.comb += done.eq(finishing & self.cycle_starting)
        self.comb += self.done_stb.eq(done & ~done_d)

        # Ready asserted when run_stb is pulsed, and cleared on success or timeout
        self.sync += [
            If(
                self.run_stb,
                self.ready.eq(1),
                self.cycles_completed.eq(0),
                self.success.eq(0),
            ),
            done_d.eq(done),
            If(finishing, self.ready.eq(0)),
        ]

        fsm = FSM()
        self.submodules += fsm

        fsm.act(
            "IDLE",
            self.cycle_starting.eq(1),
            If(
                self.act_as_master,
                If(
                    ~finishing & self.ready &
                    (self.slave_ready | self.standalone),
                    NextState("TRIGGER_SLAVE"),
                ),
            ).Else(
                If(~finishing & self.ready & self.trigger_in,
                   NextState("COUNTER"))),
            NextValue(self.m, 0),
            self.trigger_out.eq(0),
        )
        fsm.act("TRIGGER_SLAVE", NextState("TRIGGER_SLAVE2"),
                self.trigger_out.eq(1))
        fsm.act("TRIGGER_SLAVE2", NextState("COUNTER"), self.trigger_out.eq(1))
        fsm.act(
            "COUNTER",
            NextValue(self.m, self.m + 1),
            If(
                self.cycle_ending,
                NextValue(self.cycles_completed, self.cycles_completed + 1),
                If(
                    self.act_as_master,
                    If(self.herald, NextValue(self.success, 1)),
                    NextState("IDLE"),
                ).Else(NextState("SLAVE_SUCCESS_WAIT")),
            ),
            self.trigger_out.eq(0),
        )
        fsm.act("SLAVE_SUCCESS_WAIT", NextState("SLAVE_SUCCESS_CHECK"))
        fsm.act(
            "SLAVE_SUCCESS_CHECK",  # On slave, checking if master broadcast success
            If(self.success_in, NextValue(self.success, 1)),
            NextState("IDLE"),
        )
Exemplo n.º 10
0
    def __init__(self, clk_freq, baud_rate):
        divisor = clk_freq // baud_rate

        self.submodules.fifo = SyncFIFO(8, 1024)

        self.din = self.fifo.din
        self.we = self.fifo.we
        self.writable = self.fifo.writable
        self.tx = Signal()
        self.io = {self.din, self.we, self.fifo.writable, self.tx}

        # strobe_counter counts down from divisor to 0, resets automatically
        # or when strobe-start is asserted.
        strobe_counter = Signal(max=divisor)
        strobe_start = Signal()
        strobe = Signal()
        self.comb += strobe.eq(strobe_counter == 0)
        self.sync += (If(
            strobe | strobe_start,
            strobe_counter.eq(divisor - 1),
        ).Else(strobe_counter.eq(strobe_counter - 1)))

        # Main bit sender FSM.
        bit_counter = Signal(max=8)
        tx_data = Signal(8)
        self.submodules.fsm = FSM(reset_state='IDLE')
        self.fsm.act(
            'IDLE',
            If(
                self.fifo.readable,
                NextState('START'),
                NextValue(tx_data, self.fifo.dout),
            ))
        self.fsm.act(
            'START',
            If(
                strobe,
                NextState('DATA'),
                NextValue(bit_counter, 0),
            ),
        )
        self.fsm.act(
            'DATA',
            If(
                strobe,
                If(
                    bit_counter == 7,
                    NextState('STOP'),
                ).Else(NextValue(bit_counter, bit_counter + 1))))
        self.fsm.act(
            'STOP',
            If(
                strobe,
                NextState('IDLE'),
            ),
        )

        self.comb += [
            # FIFO readout.
            self.fifo.re.eq(self.fsm.ongoing('IDLE')),
            # Keep resetting the counter when in IDLE.
            strobe_start.eq(self.fsm.ongoing('IDLE')),
            # TX line logic.
            If(
                self.fsm.ongoing('START'),
                self.tx.eq(0),
            ).Elif(
                self.fsm.ongoing('DATA'),
                self.tx.eq((tx_data >> bit_counter) & 1),
            ).Else(self.tx.eq(1), )
        ]
Exemplo n.º 11
0
    def migen_body(self, template):
        # Node Inputs
        # Two inputs, a command and parameters.
        self.DAC_command = template.add_pa_in_port('DAC_command',
                                                   dl.DOptional(dl.DInt()))
        self.DAC_param = template.add_pa_in_port('DAC_param',
                                                 dl.DOptional(dl.DInt()))

        # Node Outputs
        # Returns the node status upon request
        self.DAC_controller_status = template.add_pa_out_port(
            'DAC_controller_status', dl.DInt())
        # Data to be returned to accumulator eg DAC voltage
        self.DAC_return_data = template.add_pa_out_port(
            'DAC_return_data', dl.DInt())

        # Internal signals.
        #####
        # How long to wait for the DAC voltage to settle after a new
        # voltage is set
        self.v_settle_count = Signal(10)
        # Tracks the current status of this node
        self.node_status_internal = Signal(8)
        # 10 bit voltage
        self.DAC_voltage = Signal(10)

        # If self.v_settle_count is not zero it means we've updated the voltage
        # and are waiting for it to settle before initiating more data
        # collection
        self.sync += If(self.v_settle_count != 0,
                        self.v_settle_count.eq(self.v_settle_count - 1))

        # If the DAC_command is a request of node status immediately return
        # present value of node status
        self.comb += If(
            self.DAC_command.data == DAC_STATUS,
            self.DAC_controller_status.data.eq(self.node_status_internal),
            self.DAC_controller_status.valid.eq(1))
        """FSM
        The state machine is used to handle the different commands. These will
        likely involve further communication with the SPI drives to the DAC

        IDLE
        This is the default hold state. It stays here while there is nothing to
        do. When recieving a command the state is then changed appropriately.

        DAC_READ_VOLTAGE
        This state returns the current DAC voltage. This is stored locally in
        DAC_voltage, however, in a real implementation this state would read
        the voltage directly from the DAC IC and return this value.

        DAC_SET_VOLTAGE
        This state sets DAC_voltage equal to the value sent in DAC_param. In a
        real implementation this state would pass the correct set of SPI
        commands to set the DAC voltage.

        SETTLE_HOLD
        This state is used as a hold time after the DAC voltage is written. We
        can assume there is a none zero settle time for the new electrode
        voltage to be set and any oscillations to settle. The time in this hold
        state is set by the self.v_settle_count value, set when moving from
        DAC_SET_VOLTAGE. Once self.cnt reaches 0 then the FSM moves back to
        IDLE. While in this state a poll of the DAC_STATUS will return _BUSY
        """

        self.submodules.DAC_fsm = FSM(reset_state="IDLE")

        self.DAC_fsm.act(
            "IDLE", NextValue(self.DAC_command.ready, 1),
            NextValue(self.DAC_param.ready, 1),
            NextValue(self.DAC_return_data.valid, 0),
            If(self.DAC_command.data == DAC_GET_VOLTAGE,
               NextValue(self.node_status_internal, BUSY),
               NextState("DAC_READ_VOLTAGE")).Elif(
                   self.DAC_command.data == DAC_SET_VOLTAGE,
                   NextValue(self.DAC_voltage, self.DAC_param.data),
                   NextValue(self.node_status_internal, BUSY),
                   NextState("DAC_SET_VOLTAGE")))

        self.DAC_fsm.act(
            "DAC_READ_VOLTAGE",
            NextValue(self.DAC_return_data.data, self.DAC_voltage),
            NextValue(self.DAC_return_data.valid, 1),
            NextValue(self.node_status_internal, READY), NextState("IDLE"))

        self.DAC_fsm.act("DAC_SET_VOLTAGE",
                         NextValue(self.node_status_internal, BUSY),
                         NextValue(self.v_settle_count, 0x1),
                         NextState("SETTLE_HOLD"))

        self.DAC_fsm.act(
            "SETTLE_HOLD",
            If(self.v_settle_count == 0,
               NextValue(self.node_status_internal, READY), NextState("IDLE")))
Exemplo n.º 12
0
Arquivo: c2.py Projeto: a1k0n/litex-c2
    def __init__(self, c2):

        txwidth = 13
        txlen = Signal(max=txwidth + 1)
        txbuf = Signal(txwidth)
        rxbuf = Signal(8)
        rxlen = Signal(4)

        waitlen = Signal(7)
        rfull = Signal()
        readerror = Signal()

        reset_count = Signal(max=961)

        self._cmd = CSRStorage(8)
        self._stat = CSRStatus(8)
        self._rxbuf = CSRStatus(8)
        self.comb += self._rxbuf.status.eq(rxbuf)
        self._txdat = CSRStorage(8)

        c2d = TSTriple()
        c2ck = Signal(reset=1)
        self.comb += c2.c2ck.eq(c2ck)
        self.specials += c2d.get_tristate(c2.c2d)

        self._pwcon = CSRStorage(8, reset=1)
        self._glitchoff = CSRStorage(32)
        self._glitchlen = CSRStorage(8)
        glitchout = Signal()
        glitchmode = Signal()
        glitchtmr = Signal(32)
        self.comb += c2.power.eq(self._pwcon.storage[0] & glitchout)
        self.sync += If(self._pwcon.storage[1], self._pwcon.storage[1].eq(0),
                        glitchmode.eq(0),
                        glitchtmr.eq(self._glitchoff.storage))
        self.sync += If(glitchtmr == 0, glitchout.eq(1)).Else(
            glitchtmr.eq(glitchtmr - 1), glitchout.eq(~glitchmode),
            If(
                glitchtmr == 1,
                If(glitchmode == 0, glitchtmr[:8].eq(self._glitchlen.storage),
                   glitchmode.eq(1))))

        # when rxbuf is read, reset the buffer full flag
        self.sync += If(self._rxbuf.we, rfull.eq(0))

        fsm = FSM(reset_state="IDLE")
        self.submodules.fsm = fsm

        fsm.act(
            "IDLE",
            c2d.oe.eq(0),
            NextValue(c2ck, 1),
            If(
                self._cmd.storage == 1,  # data read
                NextValue(self._cmd.storage, 0),
                NextValue(txbuf, 1),  # start(1), data read (00), length (00)
                NextValue(txlen, 5),
                NextValue(rxlen, 8),
                NextValue(readerror, 0),
                NextValue(waitlen, 127),
                NextState("TX")).Elif(
                    self._cmd.storage == 2,  # address write
                    NextValue(self._cmd.storage, 0),
                    # start (1), address write (11), address
                    NextValue(txbuf, (self._txdat.storage << 3) | 7),
                    NextValue(txlen, 11),
                    NextValue(rxlen, 0),
                    NextValue(waitlen, 0),
                    NextState("TX")).Elif(
                        self._cmd.storage == 3,  # address read
                        NextValue(self._cmd.storage, 0),
                        NextValue(waitlen, 0),
                        NextValue(txbuf, 5),  # start (1), address read (01)
                        NextValue(txlen, 3),
                        NextValue(waitlen, 0),  # no wait
                        NextValue(rxlen, 8),  # read 8 bits
                        NextValue(readerror, 0),
                        NextState("TX")).Elif(
                            self._cmd.storage == 4,  # data write
                            NextValue(self._cmd.storage, 0),
                            NextValue(waitlen, 0),
                            # start (1), data write (10), length (00), data
                            NextValue(txbuf, (self._txdat.storage << 5) | 3),
                            NextValue(txlen, 13),
                            NextValue(waitlen, 127),  # wait at the end
                            NextValue(rxlen, 0),  # no read
                            NextState("TX")).Elif(
                                self._cmd.storage == 5,  # reset
                                NextValue(self._cmd.storage, 0),
                                NextValue(reset_count, 960),  # 20us at 48MHz
                                NextValue(c2ck, 0),
                                NextState("RESET")))

        fsm.act(
            "RESET",  # 20us reset line low
            NextValue(c2ck, 0),
            If(
                reset_count == 0,
                NextValue(reset_count, 96),  # 2us at 48MHz
                NextState("RESET2")).Else(
                    NextValue(reset_count, reset_count - 1), ))

        fsm.act(
            "RESET2",  # 2us reset line high
            NextValue(c2ck, 1),
            If(reset_count == 0,
               NextState("IDLE")).Else(NextValue(reset_count,
                                                 reset_count - 1), ))

        fsm.act(
            "TX",
            # clk initially 1 here
            c2d.oe.eq(1),
            If(
                txlen == 0,
                If(
                    waitlen != 0,
                    NextState("WAIT"),
                ).Elif(
                    rxlen != 0,
                    NextState("RX"),
                ).Else(NextState("STOP")), NextValue(c2ck, 0)).
            Else(
                If(
                    c2ck == 1,  # clock is high, about to drop the next bit
                    NextValue(c2d.o, txbuf[0]),
                    NextValue(txbuf, txbuf[1:])).
                Else(
                    # clock is low, about to raise it and potentially advance to the next state
                    NextValue(txlen, txlen - 1)),
                NextValue(c2ck, ~c2ck)))

        fsm.act(
            "WAIT",
            # must enter state with c2ck already at 0
            c2d.oe.eq(0),
            If((c2ck == 1) & (c2d.i == 1),
               If(rxlen != 0, NextState("RX")).Else(NextState("STOP")),
               NextValue(c2ck, 0)).Else(
                   If(waitlen == 0, NextValue(readerror, 1),
                      NextState("IDLE")).Else(NextValue(waitlen, waitlen - 1),
                                              NextValue(c2ck, ~c2ck))))

        fsm.act(
            "RX",
            # must enter state with c2ck already at 0
            c2d.oe.eq(0),
            If(
                c2ck == 1,  # clock is high, shift in bit as it falls
                NextValue(rxbuf, Cat(rxbuf[1:], c2d.i)),
                If(rxlen == 1, NextValue(rfull, 1), NextState("STOP")),
                NextValue(c2ck, 0),
                NextValue(rxlen, rxlen - 1),
            ).Else(NextValue(c2ck, 1)))

        fsm.act(
            "STOP",
            # must enter state with c2ck already at 0
            c2d.oe.eq(0),
            If(
                c2ck == 1,  # stop done
                NextState("IDLE")).Else(NextValue(c2ck, 1)))

        # status register byte:
        # |  7  |  6   | 5 | 4 |  3   |  2 |  1 |  0   |
        # | ERR | RRDY | . | . | WAIT | RX | TX | IDLE |
        self.comb += self._stat.status.eq(
            fsm.ongoing("IDLE") | (fsm.ongoing("TX") << 1)
            | (fsm.ongoing("RX") << 2) | (fsm.ongoing("WAIT") << 3)
            | (rfull << 6) | (readerror << 7))

        # for debugging, expose internals
        self._txlen = CSRStatus(5)
        self._txbuf = CSRStatus(12)
        self._rxlen = CSRStatus(4)
        self._waitlen = CSRStatus(7)

        self.comb += self._txlen.status.eq(txlen)
        self.comb += self._txbuf.status.eq(txbuf)
        self.comb += self._rxlen.status.eq(rxlen)
        self.comb += self._waitlen.status.eq(waitlen)
Exemplo n.º 13
0
    def __init__(self, dw=8):
        self.UDP_FRAG_MTU = UDP_FRAG_MTU = 1472 - 8  # The -8 is because of FRAGMENTER header
        self.sink = sink = stream.Endpoint([("data", dw), ("length", 32)])
        self.source = source = stream.Endpoint(eth_udp_user_description(dw))
        self.packetizer = packetizer = UDPFragmenterPacketizer()
        self.submodules += packetizer

        self.mf = mf = Signal(reset=0)  # mf == More Fragments
        self.fragment_offset = fragment_offset = Signal(32, reset=0)
        self.identification = identification = Signal(16, reset=0)
        self.fragment_id = fragment_id = Signal(32, reset=0)

        self.comb += [
            sink.connect(packetizer.sink, omit={"length"}),
            packetizer.sink.total_fragmets.eq(identification),
            packetizer.sink.fragment_id.eq(fragment_id),
            packetizer.source.connect(source),
        ]

        ww = dw // 8

        # counter logic ;)
        self.foo_counter = counter = Signal(32)
        counter_reset = Signal()
        counter_ce = Signal()
        self.sync += \
            If(counter_reset,
                counter.eq(0)
            ).Elif(counter_ce,
                counter.eq(counter + ww)
            )
        bytes_in_fragment = Signal(16, reset=0)

        self.submodules.fsm = fsm = FSM(reset_state="IDLE")
        fsm.act(
            "IDLE",
            sink.ready.eq(packetizer.sink.ready),
            If(
                sink.valid,
                If(
                    sink.length < UDP_FRAG_MTU,
                    sink.connect(packetizer.sink, omit={"length"}),
                    # TODO
                    source.length.eq(sink.length)).Else(
                        sink.ready.eq(0), source.length.eq(UDP_FRAG_MTU + 8),
                        counter_reset.eq(1), NextValue(mf, 1),
                        NextValue(fragment_offset, 0),
                        NextValue(fragment_id, 0),
                        NextValue(identification, identification + 1),
                        NextValue(bytes_in_fragment, UDP_FRAG_MTU),
                        NextState("FRAGMENTED_PACKET_SEND"))))

        fsm.act(
            "FRAGMENTED_PACKET_SEND",
            sink.connect(packetizer.sink, omit={"length"}),
            packetizer.sink.length.eq(bytes_in_fragment),
            source.length.eq(bytes_in_fragment + 8),
            If(sink.valid & packetizer.sink.ready, counter_ce.eq(1)),
            If(
                counter == (bytes_in_fragment - ww),
                NextValue(fragment_offset,
                          fragment_offset + (bytes_in_fragment >> 3)),
                packetizer.sink.last.eq(1),
                If(((fragment_offset << 3) + counter + ww) == sink.length,
                   NextValue(fragment_offset, 0),
                   NextState("IDLE")).Else(counter_ce.eq(0),
                                           NextState("NEXT_FRAGMENT"))))

        fsm.act(
            "NEXT_FRAGMENT", counter_ce.eq(0), sink.ready.eq(0),
            packetizer.sink.valid.eq(0),
            packetizer.sink.length.eq(bytes_in_fragment),
            source.length.eq(bytes_in_fragment + 8), counter_reset.eq(1),
            If(
                (sink.length - (fragment_offset << 3)) > UDP_FRAG_MTU,
                NextValue(bytes_in_fragment, UDP_FRAG_MTU),
            ).Else(
                NextValue(bytes_in_fragment,
                          sink.length - (fragment_offset << 3)),
                NextValue(mf, 0),
            ), NextValue(fragment_id, fragment_id + 1),
            NextState("FRAGMENTED_PACKET_SEND"))