Exemplo n.º 1
0
    def __init__(self):

        self._cfg = CSRStorage(8)
        self._stat = CSRStatus(8)

        self.sink = Sink(ULPI_DATA)
        self.source = Source([("d", 8), ("last", 1)])

        latch_d = Signal()
        latched = Signal(8)
        self.sync += If(latch_d, latched.eq(self.sink.payload.d))

        self.submodules.fsm = FSM()
        self.fsm.act("IDLE",
                self.sink.ack.eq(1),
                If(self.sink.stb & self._cfg.storage[0],
                    latch_d.eq(1),
                    If(self.sink.payload.rxcmd, NextState("RXCMD")
                     ).Else(NextState("UDATA"))))

        self.fsm.act("RXCMD",
                self.source.payload.d.eq(0xAC),
                self.source.stb.eq(1),
                If(self.source.ack,
                    NextState("SENDB"))
                )
        self.fsm.act("UDATA",
                self.source.payload.d.eq(0xAD),
                self.source.stb.eq(1),
                If(self.source.ack,
                    NextState("SENDB"))
                )

        self.fsm.act("SENDB",
                self.source.payload.d.eq(latched),
                self.source.payload.last.eq(1),
                self.source.stb.eq(1),
                If(self.source.ack,
                    NextState("IDLE")))
Exemplo n.º 2
0
    def __init__(self, pads, dummy=15, div=2, with_bitbang=True):
        """
        Simple SPI flash, e.g. N25Q128 on the LX9 Microboard.

        Supports multi-bit pseudo-parallel reads (aka Dual or Quad I/O Fast
        Read). Only supports mode0 (cpol=0, cpha=0).
        Optionally supports software bitbanging (for write, erase, or other commands).
        """
        self.bus = bus = wishbone.Interface()
        spi_width = flen(pads.dq)
        if with_bitbang:
            self.bitbang = CSRStorage(4)
            self.miso = CSRStatus()
            self.bitbang_en = CSRStorage()

        ###

        cs_n = Signal(reset=1)
        clk = Signal()
        dq_oe = Signal()
        wbone_width = flen(bus.dat_r)


        read_cmd_params = {
            4: (_format_cmd(_QIOFR, 4), 4*8),
            2: (_format_cmd(_DIOFR, 2), 2*8),
            1: (_format_cmd(_FAST_READ, 1), 1*8)
        }
        read_cmd, cmd_width = read_cmd_params[spi_width]
        addr_width = 24

        pads.cs_n.reset = 1

        dq = TSTriple(spi_width)
        self.specials.dq = dq.get_tristate(pads.dq)

        sr = Signal(max(cmd_width, addr_width, wbone_width))
        dqs = Replicate(1, spi_width-1)

        self.comb += bus.dat_r.eq(sr)

        hw_read_logic = [
            pads.clk.eq(clk),
            pads.cs_n.eq(cs_n),
            dq.o.eq(sr[-spi_width:]),
            dq.oe.eq(dq_oe)
        ]

        if with_bitbang:
            bitbang_logic = [
                pads.clk.eq(self.bitbang.storage[1]),
                pads.cs_n.eq(self.bitbang.storage[2]),
                dq.o.eq(Cat(self.bitbang.storage[0], dqs)),
                If(self.bitbang.storage[3],
                    dq.oe.eq(0)
                ).Else(
                    dq.oe.eq(1)
                ),
                If(self.bitbang.storage[1],
                    self.miso.status.eq(dq.i[1])
                )
            ]

            self.comb += \
                If(self.bitbang_en.storage,
                    bitbang_logic
                ).Else(
                    hw_read_logic
                )
        else:
            self.comb += hw_read_logic

        if div < 2:
            raise ValueError("Unsupported value \'{}\' for div parameter for SpiFlash core".format(div))
        else:
            i = Signal(max=div)
            dqi = Signal(spi_width)
            self.sync += [
                If(i == div//2 - 1,
                    clk.eq(1),
                    dqi.eq(dq.i),
                ),
                If(i == div - 1,
                    i.eq(0),
                    clk.eq(0),
                    sr.eq(Cat(dqi, sr[:-spi_width]))
                ).Else(
                    i.eq(i + 1),
                ),
            ]

        # spi is byte-addressed, prefix by zeros
        z = Replicate(0, log2_int(wbone_width//8))

        seq = [
            (cmd_width//spi_width*div,
                [dq_oe.eq(1), cs_n.eq(0), sr[-cmd_width:].eq(read_cmd)]),
            (addr_width//spi_width*div,
                [sr[-addr_width:].eq(Cat(z, bus.adr))]),
            ((dummy + wbone_width//spi_width)*div,
                [dq_oe.eq(0)]),
            (1,
                [bus.ack.eq(1), cs_n.eq(1)]),
            (div, # tSHSL!
                [bus.ack.eq(0)]),
            (0,
                []),
        ]

        # accumulate timeline deltas
        t, tseq = 0, []
        for dt, a in seq:
            tseq.append((t, a))
            t += dt

        self.sync += timeline(bus.cyc & bus.stb & (i == div - 1), tseq)
Exemplo n.º 3
0
    def __init__(self,
                 mem_or_size,
                 address,
                 read_only=None,
                 init=None,
                 bus=None):
        if bus is None:
            bus = Interface()
        self.bus = bus
        data_width = flen(self.bus.dat_w)
        if isinstance(mem_or_size, Memory):
            mem = mem_or_size
        else:
            mem = Memory(data_width,
                         mem_or_size // (data_width // 8),
                         init=init)
        csrw_per_memw = (mem.width + data_width - 1) // data_width
        word_bits = log2_int(csrw_per_memw)
        page_bits = log2_int((mem.depth * csrw_per_memw + 511) // 512, False)
        if page_bits:
            self._page = CSRStorage(page_bits,
                                    name=mem.name_override + "_page")
        else:
            self._page = None
        if read_only is None:
            if hasattr(mem, "bus_read_only"):
                read_only = mem.bus_read_only
            else:
                read_only = False

        ###

        port = mem.get_port(write_capable=not read_only)
        self.specials += mem, port

        sel = Signal()
        sel_r = Signal()
        self.sync += sel_r.eq(sel)
        self.comb += sel.eq(self.bus.adr[9:] == address)

        if word_bits:
            word_index = Signal(word_bits)
            word_expanded = Signal(csrw_per_memw * data_width)
            self.sync += word_index.eq(self.bus.adr[:word_bits])
            self.comb += [
                word_expanded.eq(port.dat_r),
                If(
                    sel_r,
                    chooser(word_expanded,
                            word_index,
                            self.bus.dat_r,
                            n=csrw_per_memw,
                            reverse=True))
            ]
            if not read_only:
                wregs = []
                for i in range(csrw_per_memw - 1):
                    wreg = Signal(data_width)
                    self.sync += If(
                        sel & self.bus.we & (self.bus.adr[:word_bits] == i),
                        wreg.eq(self.bus.dat_w))
                    wregs.append(wreg)
                memword_chunks = [self.bus.dat_w] + list(reversed(wregs))
                self.comb += [
                    port.we.eq(sel & self.bus.we
                               & (self.bus.adr[:word_bits] == csrw_per_memw -
                                  1)),
                    port.dat_w.eq(Cat(*memword_chunks))
                ]
        else:
            self.comb += If(sel_r, self.bus.dat_r.eq(port.dat_r))
            if not read_only:
                self.comb += [
                    port.we.eq(sel & self.bus.we),
                    port.dat_w.eq(self.bus.dat_w)
                ]

        if self._page is None:
            self.comb += port.adr.eq(self.bus.adr[word_bits:word_bits +
                                                  flen(port.adr)])
        else:
            pv = self._page.storage
            self.comb += port.adr.eq(
                Cat(
                    self.bus.adr[word_bits:word_bits + flen(port.adr) -
                                 flen(pv)], pv))
Exemplo n.º 4
0
    def __init__(self, pads, default=_default_edid):
        self._hpd_notif = CSRStatus()
        self._hpd_en = CSRStorage()
        self.specials.mem = Memory(8, 128, init=default)

        ###

        # HPD
        if hasattr(pads, "hpd_notif"):
            self.specials += MultiReg(pads.hpd_notif, self._hpd_notif.status)
        else:
            self.comb += self._hpd_notif.status.eq(1)
        if hasattr(pads, "hpd_en"):
            self.comb += pads.hpd_en.eq(self._hpd_en.storage)

        # EDID
        scl_raw = Signal()
        sda_i = Signal()
        sda_raw = Signal()
        sda_drv = Signal()
        _sda_drv_reg = Signal()
        _sda_i_async = Signal()
        self.sync += _sda_drv_reg.eq(sda_drv)
        self.specials += [
            MultiReg(pads.scl, scl_raw),
            Tristate(pads.sda, 0, _sda_drv_reg, _sda_i_async),
            MultiReg(_sda_i_async, sda_raw)
        ]

        # for debug
        self.scl = scl_raw
        self.sda_i = sda_i
        self.sda_o = Signal()
        self.comb += self.sda_o.eq(~_sda_drv_reg)
        self.sda_oe = _sda_drv_reg

        scl_i = Signal()
        samp_count = Signal(6)
        samp_carry = Signal()
        self.sync += [
            Cat(samp_count, samp_carry).eq(samp_count + 1),
            If(samp_carry,
                scl_i.eq(scl_raw),
                sda_i.eq(sda_raw)
            )
        ]

        scl_r = Signal()
        sda_r = Signal()
        scl_rising = Signal()
        sda_rising = Signal()
        sda_falling = Signal()
        self.sync += [
            scl_r.eq(scl_i),
            sda_r.eq(sda_i)
        ]
        self.comb += [
            scl_rising.eq(scl_i & ~scl_r),
            sda_rising.eq(sda_i & ~sda_r),
            sda_falling.eq(~sda_i & sda_r)
        ]

        start = Signal()
        self.comb += start.eq(scl_i & sda_falling)

        din = Signal(8)
        counter = Signal(max=9)
        self.sync += [
            If(start, counter.eq(0)),
            If(scl_rising,
                If(counter == 8,
                    counter.eq(0)
                ).Else(
                    counter.eq(counter + 1),
                    din.eq(Cat(sda_i, din[:7]))
                )
            )
        ]

        self.din = din
        self.counter = counter

        is_read = Signal()
        update_is_read = Signal()
        self.sync += If(update_is_read, is_read.eq(din[0]))

        offset_counter = Signal(max=128)
        oc_load = Signal()
        oc_inc = Signal()
        self.sync += [
            If(oc_load,
                offset_counter.eq(din)
            ).Elif(oc_inc,
                offset_counter.eq(offset_counter + 1)
            )
        ]
        rdport = self.mem.get_port()
        self.specials += rdport
        self.comb += rdport.adr.eq(offset_counter)
        data_bit = Signal()

        zero_drv = Signal()
        data_drv = Signal()
        self.comb += If(zero_drv, sda_drv.eq(1)).Elif(data_drv, sda_drv.eq(~data_bit))

        data_drv_en = Signal()
        data_drv_stop = Signal()
        self.sync += If(data_drv_en, data_drv.eq(1)).Elif(data_drv_stop, data_drv.eq(0))
        self.sync += If(data_drv_en, chooser(rdport.dat_r, counter, data_bit, 8, reverse=True))

        self.submodules.fsm = fsm = FSM()

        fsm.act("WAIT_START")
        fsm.act("RCV_ADDRESS",
            If(counter == 8,
                If(din[1:] == 0x50,
                    update_is_read.eq(1),
                    NextState("ACK_ADDRESS0")
                ).Else(
                    NextState("WAIT_START")
                )
            )
        )
        fsm.act("ACK_ADDRESS0",
            If(~scl_i, NextState("ACK_ADDRESS1"))
        )
        fsm.act("ACK_ADDRESS1",
            zero_drv.eq(1),
            If(scl_i, NextState("ACK_ADDRESS2"))
        )
        fsm.act("ACK_ADDRESS2",
            zero_drv.eq(1),
            If(~scl_i,
                If(is_read,
                    NextState("READ")
                ).Else(
                    NextState("RCV_OFFSET")
                )
            )
        )

        fsm.act("RCV_OFFSET",
            If(counter == 8,
                oc_load.eq(1),
                NextState("ACK_OFFSET0")
            )
        )
        fsm.act("ACK_OFFSET0",
            If(~scl_i, NextState("ACK_OFFSET1"))
        )
        fsm.act("ACK_OFFSET1",
            zero_drv.eq(1),
            If(scl_i, NextState("ACK_OFFSET2"))
        )
        fsm.act("ACK_OFFSET2",
            zero_drv.eq(1),
            If(~scl_i, NextState("RCV_ADDRESS"))
        )

        fsm.act("READ",
            If(~scl_i,
                If(counter == 8,
                    data_drv_stop.eq(1),
                    NextState("ACK_READ")
                ).Else(
                    data_drv_en.eq(1)
                )
            )
        )
        fsm.act("ACK_READ",
            If(scl_rising,
                oc_inc.eq(1),
                If(sda_i,
                    NextState("WAIT_START")
                ).Else(
                    NextState("READ")
                )
            )
        )

        for state in fsm.actions.keys():
            fsm.act(state, If(start, NextState("RCV_ADDRESS")))
            fsm.act(state, If(~self._hpd_en.storage, NextState("WAIT_START")))
Exemplo n.º 5
0
    def __init__(self):
        super(CycleControl, self).__init__()
        time_width = ventilator_layout[0][1]

        self._start = CSR()
        self._prohibit = CSRStorage()
        self._clear = CSR()
        self._run = CSRStatus()
        self._cycle = CSRStatus(time_width)
        self._update = CSR()

        self.have_out = Signal()
        self.have_in = Signal()
        self.cycle = Signal(time_width)
        self.run = Signal()

        ###

        start_in = Signal()
        start_out = Signal()
        prohibit_underflow = Signal()
        stop_once = Signal()

        clear_force = Signal()
        clear_force0 = Signal()

        stop = Signal()
        start = Signal()
        clear = Signal()

        run0 = Signal()

        self.comb += [
            self._run.status.eq(run0),
            start.eq(self._start.re | (start_out & self.have_out)),
            stop.eq(self._prohibit.storage
                    | (prohibit_underflow & ~self.have_out)),
            clear.eq(self._clear.re | clear_force | clear_force0),
            If(
                stop,
                self.run.eq(0),
            ).Elif(
                start,
                self.run.eq(1),
            ).Else(self.run.eq(run0), ),
        ]

        self.comb += [
            self.dout.ack.eq(1),
            self.din.payload.addr.eq(self.dout.payload.addr),
            self.din.payload.data.eq(self.dout.payload.data),
            If(
                self.dout.stb,
                Case(
                    self.dout.payload.addr[:8], {
                        0x00: self.din.stb.eq(1),
                        0x04: stop_once.eq(1),
                        0x05: clear_force.eq(self.dout.payload.data),
                    }),
            )
        ]

        self.sync += [
            If(
                self.dout.stb,
                Case(
                    self.dout.payload.addr[:8], {
                        0x01: start_in.eq(self.dout.payload.data),
                        0x02: start_out.eq(self.dout.payload.data),
                        0x03: prohibit_underflow.eq(self.dout.payload.data),
                        0x05: clear_force0.eq(self.dout.payload.data),
                    }),
            ),
            If(
                stop_once,
                run0.eq(0),
            ).Elif(
                start_in & self.have_in,
                run0.eq(1),
            ).Else(run0.eq(self.run), ),
            If(
                clear,
                self.cycle.eq(0),
            ).Elif(
                self.run,
                self.cycle.eq(self.cycle + 1),
            ),
            If(
                self._update.re,
                self._cycle.status.eq(self.cycle),
            ),
        ]
Exemplo n.º 6
0
    def __init__(self, slaves, depth=256, bus=None, with_wishbone=True):
        time_width, addr_width, data_width = [_[1] for _ in ventilator_layout]

        self.submodules.ctrl = CycleControl()

        self.submodules.ev = ev = EventManager()
        ev.in_readable = EventSourceLevel()
        ev.out_overflow = EventSourceProcess()
        ev.in_overflow = EventSourceLevel()
        ev.out_readable = EventSourceProcess()
        ev.stopped = EventSourceProcess()
        ev.started = EventSourceProcess()
        ev.finalize()

        self._in_time = CSRStatus(time_width)
        self._in_addr = CSRStatus(addr_width)
        self._in_data = CSRStatus(data_width)
        self._in_next = CSR()
        self._in_flush = CSR()

        self._out_time = CSRStorage(time_width, write_from_dev=with_wishbone)
        self._out_addr = CSRStorage(addr_width, write_from_dev=with_wishbone)
        self._out_data = CSRStorage(data_width, write_from_dev=with_wishbone)
        self._out_next = CSR()
        self._out_flush = CSR()

        self.busy = Signal()

        ###

        if with_wishbone:
            if bus is None:
                bus = wishbone.Interface()
            self.bus = bus

        slaves = [(self.ctrl, 0x00000000, 0xffffff00)] + slaves

        self.submodules.in_fifo = in_fifo = SyncFIFOBuffered(
            ventilator_layout, depth)
        self.submodules.out_fifo = out_fifo = SyncFIFOBuffered(
            ventilator_layout, depth)
        self.submodules.enc = PriorityEncoder(len(slaves))

        wb_in_next = Signal()
        wb_out_next = Signal()
        out_request = Signal()
        in_request = Signal()

        # CSRs and Events
        self.comb += [
            ev.in_readable.trigger.eq(in_fifo.readable),
            ev.out_overflow.trigger.eq(~out_fifo.writable),
            ev.in_overflow.trigger.eq(~in_fifo.writable),
            ev.out_readable.trigger.eq(out_fifo.readable),
            ev.started.trigger.eq(~self.ctrl.run),
            ev.stopped.trigger.eq(self.ctrl.run),
            self.ctrl.have_in.eq(~self.enc.n),
            self.ctrl.have_out.eq(out_fifo.readable),
            self._in_time.status.eq(in_fifo.dout.time),
            self._in_addr.status.eq(in_fifo.dout.addr),
            self._in_data.status.eq(in_fifo.dout.data),
            in_fifo.re.eq(self._in_next.re | wb_in_next),
            in_fifo.flush.eq(self._in_flush.re),
            out_fifo.din.time.eq(self._out_time.storage),
            out_fifo.din.addr.eq(self._out_addr.storage),
            out_fifo.din.data.eq(self._out_data.storage),
            out_fifo.we.eq(self._out_next.re | wb_out_next),
            out_fifo.flush.eq(self._out_flush.re),
        ]

        # din dout strobing
        self.comb += [
            # TODO: 0 <= diff <= plausibility range
            out_request.eq(out_fifo.readable & self.ctrl.run
                           & (self.ctrl.cycle == out_fifo.dout.time)),
            # ignore in_fifo.writable
            in_request.eq(~self.enc.n & self.ctrl.run),
            self.busy.eq(out_request | in_request),
        ]

        # to slaves
        addrs = []
        datas = []
        stbs = []
        acks = []
        for i, (slave, prefix, mask) in enumerate(slaves):
            prefix &= mask
            source = Source(slave_layout)
            sink = Sink(slave_layout)
            self.comb += [
                source.connect(slave.dout),
                sink.connect(slave.din),
            ]
            sel = Signal()
            acks.append(sel & source.ack)
            addrs.append(prefix | (sink.payload.addr & (~mask & 0xffffffff)))
            datas.append(sink.payload.data)
            stbs.append(sink.stb)
            self.comb += [
                sel.eq(out_fifo.dout.addr & mask == prefix),
                source.payload.addr.eq(out_fifo.dout.addr),
                source.payload.data.eq(out_fifo.dout.data),
                source.stb.eq(sel & out_request),
                sink.ack.eq((self.enc.o == i) & in_request),
            ]
        self.comb += out_fifo.re.eq(out_request & optree("|", acks))

        # from slaves
        self.comb += [
            self.enc.i.eq(Cat(stbs)),
            in_fifo.din.time.eq(self.ctrl.cycle),
            in_fifo.din.addr.eq(Array(addrs)[self.enc.o]),
            in_fifo.din.data.eq(Array(datas)[self.enc.o]),
            in_fifo.we.eq(in_request),
        ]

        # optional high throughput wishbone access
        if with_wishbone:
            self.comb += [
                self._out_time.dat_w.eq(bus.dat_w),
                self._out_addr.dat_w.eq(bus.dat_w),
                self._out_data.dat_w.eq(bus.dat_w),
                If(
                    bus.cyc & bus.stb,
                    If(
                        bus.we,
                        Case(
                            bus.adr[:4], {
                                0x5: wb_in_next.eq(1),
                                0x6: self._out_time.we.eq(1),
                                0x7: self._out_addr.we.eq(1),
                                0x8: self._out_data.we.eq(1),
                                0x9: wb_out_next.eq(1),
                            }),
                    ),
                    Case(
                        bus.adr[:4], {
                            0x0: bus.dat_r.eq(self.ctrl.cycle),
                            0x1: bus.dat_r.eq(self.ev.status.w),
                            0x2: bus.dat_r.eq(in_fifo.dout.time),
                            0x3: bus.dat_r.eq(in_fifo.dout.addr),
                            0x4: bus.dat_r.eq(in_fifo.dout.data),
                        }),
                )
            ]
            self.sync += bus.ack.eq(bus.cyc & bus.stb & ~bus.ack)
Exemplo n.º 7
0
    def __init__(self, depth):
        self._cfg = CSRStorage(1)

        debug_signals = 1

        storage = Memory(8, depth)
        self.specials += storage

        wrport = storage.get_port(write_capable=True)
        self.specials += wrport
        rdport = storage.get_port(async_read=False)
        self.specials += rdport

        self.submodules.consumer = Consumer(rdport, depth)
        self.submodules.producer = Producer(wrport, depth, self.consumer.pos,
                                            self._cfg.storage[0])

        self.sink = self.producer.ulpi_sink
        self.comb += self.consumer.sink.connect(self.producer.out_addr)
        self.source = self.consumer.source

        # Debug signals for state tracing
        if debug_signals:
            self._cons_lo = CSRStatus(8)
            self._cons_hi = CSRStatus(8)
            self._prod_lo = CSRStatus(8)
            self._prod_hi = CSRStatus(8)
            self._prod_hd_lo = CSRStatus(8)
            self._prod_hd_hi = CSRStatus(8)
            self._size_lo = CSRStatus(8)
            self._size_hi = CSRStatus(8)

            self._prod_state = CSRStatus(8)
            self._cons_status = CSRStatus(8)

            self._last_start_lo = CSRStatus(8)
            self._last_start_hi = CSRStatus(8)
            self._last_count_lo = CSRStatus(8)
            self._last_count_hi = CSRStatus(8)
            self._last_pw_lo = CSRStatus(8)
            self._last_pw_hi = CSRStatus(8)

            self.sync += [
                self._cons_lo.status.eq(self.consumer.pos[:8]),
                self._cons_hi.status.eq(self.consumer.pos[8:]),
                self._prod_lo.status.eq(self.producer.produce_write.v[:8]),
                self._prod_hi.status.eq(self.producer.produce_write.v[8:]),
                self._prod_hd_lo.status.eq(self.producer.produce_header.v[:8]),
                self._prod_hd_hi.status.eq(self.producer.produce_header.v[8:]),
                self._size_lo.status.eq(self.producer.size.v[:8]),
                self._size_hi.status.eq(self.producer.size.v[8:]),
                self._cons_status.status[0].eq(self.consumer.busy),
                #self._prod_state.status.eq(self.producer.fsm.state),
                If(
                    self.producer.out_addr.stb & self.producer.out_addr.ack,
                    self._last_start_lo.status.eq(
                        self.producer.out_addr.payload.start[:8]),
                    self._last_start_hi.status.eq(
                        self.producer.out_addr.payload.start[8:]),
                    self._last_count_lo.status.eq(
                        self.producer.out_addr.payload.count[:8]),
                    self._last_count_hi.status.eq(
                        self.producer.out_addr.payload.count[8:]),
                    self._last_pw_lo.status.eq(
                        self.producer.produce_write.v[:8]),
                    self._last_pw_hi.status.eq(
                        self.producer.produce_write.v[8:]),
                )
            ]