Пример #1
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"))
Пример #2
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"),
        )
Пример #3
0
    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)