Exemplo n.º 1
0
    def __init__(self, platform, sys_clk_freq):
        self.reset = CSR()

        self.clock_domains.cd_sys = ClockDomain()
        self.clock_domains.cd_sys4x = ClockDomain(reset_less=True)
        self.clock_domains.cd_sys4x_dqs = ClockDomain(reset_less=True)
        self.clock_domains.cd_clk200 = ClockDomain()
        self.clock_domains.cd_clk100 = ClockDomain()
        self.clock_domains.cd_eth = ClockDomain()

        clk50 = platform.request("clk50")
        platform.add_period_constraint(clk50, period_ns(50e6))

        soft_reset = Signal()
        self.sync += timeline(self.reset.re, [(1024, [soft_reset.eq(1)])])

        self.submodules.pll = pll = S7PLL()
        pll.register_clkin(clk50, 50e6)
        pll.create_clkout(self.cd_sys, sys_clk_freq)
        pll.create_clkout(self.cd_sys4x, 4*sys_clk_freq)
        pll.create_clkout(self.cd_sys4x_dqs, 4*sys_clk_freq, phase=90)
        pll.create_clkout(self.cd_clk200, 200e6)
        pll.create_clkout(self.cd_clk100, 100e6)
        pll.create_clkout(self.cd_eth, 50e6)

        self.submodules.idelayctrl = S7IDELAYCTRL(self.cd_clk200)
Exemplo n.º 2
0
    def __init__(self, cmd, trp, trfc):
        self.start = Signal()
        self.done = Signal()

        # # #

        self.sync += [
            cmd.a.eq(2**10),
            cmd.ba.eq(0),
            cmd.cas.eq(0),
            cmd.ras.eq(0),
            cmd.we.eq(0),
        ]
        self.sync += [
            self.done.eq(0),
            # Wait start
            timeline(
                self.start,
                [
                    # Precharge All
                    (0, [cmd.ras.eq(1), cmd.we.eq(1)]),
                    # Auto Refresh after tRP
                    (trp, [cmd.cas.eq(1), cmd.ras.eq(1)]),
                    # Done after tRP + tRFC
                    (trp + trfc, [self.done.eq(1)])
                ])
        ]
Exemplo n.º 3
0
    def __init__(self):
        # Pins
        self.o_nCS = Signal(
            reset=1)  # A conversion process begins on the falling edge of CS.
        self.i_SDATA = Signal()  # The output words are clocked out of this pin
        self.o_SCLK = Signal()  # guaranteed performance at 20 MHz

        # Samples
        self.o_dat = Signal(12)
        self.o_valid = Signal()  # Single cycle pulse when o_dat is valid
        self.i_trig = Signal(
        )  # Start a conversion (can be hardwired to 1 for continuous mode)

        ###

        self.peekReg = CSR(size=12)
        shiftReg = Signal(12)
        self.comb += [
            self.o_SCLK.eq(ClockSignal()),
            self.peekReg.w.eq(self.o_dat)
        ]
        self.sync += [
            self.o_valid.eq(0),
            shiftReg.eq(Cat(self.i_SDATA, shiftReg[:-1])),
            timeline(self.i_trig,
                     [(0, [self.o_nCS.eq(0), shiftReg.eq(0)]),
                      (16, [
                          self.o_nCS.eq(1),
                          self.o_dat.eq(shiftReg),
                          self.o_valid.eq(1)
                      ])])
        ]
Exemplo n.º 4
0
    def __init__(self, with_csr=True, simulation=False):
        self.addr = Signal(5)
        self.data = Signal(32)
        self.send = Signal()
        self.done = Signal()

        # # #

        # Create slow icap clk (sys_clk/16) ---------------------------------------------------------
        self.clock_domains.cd_icap = ClockDomain()
        icap_clk_counter = Signal(4)
        self.sync += icap_clk_counter.eq(icap_clk_counter + 1)
        self.sync += self.cd_icap.clk.eq(icap_clk_counter[3])

        # Resynchronize send pulse to icap domain ---------------------------------------------------
        ps_send = PulseSynchronizer("sys", "icap")
        self.submodules += ps_send
        self.comb += ps_send.i.eq(self.send)

        # Generate icap bitstream write sequence
        self._csib = _csib = Signal(reset=1)
        self._i = _i = Signal(32)
        _addr = self.addr << 13
        _data = self.data
        self.sync.icap += [
            _i.eq(0xffffffff),  # dummy
            timeline(
                ps_send.o,
                [
                    (1, [_csib.eq(1), self.done.eq(0)]),
                    (2, [_csib.eq(0), _i.eq(0x20000000)]),  # noop
                    (3, [_csib.eq(0), _i.eq(0xaa995566)]),  # sync word
                    (4, [_csib.eq(0), _i.eq(0x20000000)]),  # noop
                    (5, [_csib.eq(0), _i.eq(0x20000000)]),  # noop
                    (6, [_csib.eq(0), _i.eq(0x30000001 | _addr)
                         ]),  # write command
                    (7, [_csib.eq(0), _i.eq(_data)]),  # write value
                    (8, [_csib.eq(0), _i.eq(0x20000000)]),  # noop
                    (9, [_csib.eq(0), _i.eq(0x20000000)]),  # noop
                    (10, [_csib.eq(0), _i.eq(0x30008001)
                          ]),  # write to cmd register
                    (11, [_csib.eq(0), _i.eq(0x0000000d)]),  # desync command
                    (12, [_csib.eq(0), _i.eq(0x20000000)]),  # noop
                    (13, [_csib.eq(0), _i.eq(0x20000000)]),  # noop
                    (14, [_csib.eq(1), self.done.eq(1)]),
                ])
        ]

        # ICAP instance
        if not simulation:
            self.specials += [
                Instance(
                    "ICAPE2",
                    p_ICAP_WIDTH="X32",
                    i_CLK=ClockSignal("icap"),
                    i_CSIB=_csib,
                    i_RDWRB=0,
                    i_I=Cat(*[_i[8 * i:8 * (i + 1)][::-1] for i in range(4)]),
                )
            ]
Exemplo n.º 5
0
    def __init__(self, cmd, trp, trfc):
        self.start = Signal()
        self.done = Signal()

        # # #

        self.sync += [
            cmd.a.eq(2**10),
            cmd.ba.eq(0),
            cmd.cas.eq(0),
            cmd.ras.eq(0),
            cmd.we.eq(0),
        ]
        self.sync += [
            self.done.eq(0),
            # Wait start
            timeline(
                self.start,
                [
                    # Precharge all
                    (1, [cmd.ras.eq(1), cmd.we.eq(1)]),
                    # Wait tRP then Auto Refresh
                    (1 + trp, [cmd.cas.eq(1), cmd.ras.eq(1)]),
                    # Wait tRFC then done
                    (1 + trp + trfc, [self.done.eq(1)])
                ])
        ]
Exemplo n.º 6
0
    def __init__(self, settings):
        # 1st command 1 cycle after assertion of ready
        self.cmd = cmd = stream.Endpoint(cmd_request_rw_layout(settings.geom.addressbits,
                                                               settings.geom.bankbits))

        # # #

        # Refresh sequence generator:
        # PRECHARGE ALL --(tRP)--> AUTO REFRESH --(tRFC)--> done
        seq_start = Signal()
        seq_done = Signal()
        self.sync += [
            cmd.a.eq(2**10),
            cmd.ba.eq(0),
            cmd.cas.eq(0),
            cmd.ras.eq(0),
            cmd.we.eq(0),
            seq_done.eq(0)
        ]
        self.sync += timeline(seq_start, [
            (1, [
                cmd.ras.eq(1),
                cmd.we.eq(1)
            ]),
            (1+settings.timing.tRP, [
                cmd.cas.eq(1),
                cmd.ras.eq(1)
            ]),
            (1+settings.timing.tRP+settings.timing.tRFC, [
                seq_done.eq(1)
            ])
        ])

        # Periodic refresh counter
        self.submodules.timer = WaitTimer(settings.timing.tREFI)
        self.comb += self.timer.wait.eq(settings.with_refresh & ~self.timer.done)

        # Control FSM
        self.submodules.fsm = fsm = FSM()
        fsm.act("IDLE",
            If(self.timer.done,
                NextState("WAIT_GRANT")
            )
        )
        fsm.act("WAIT_GRANT",
            cmd.valid.eq(1),
            If(cmd.ready,
                seq_start.eq(1),
                NextState("WAIT_SEQ")
            )
        )
        fsm.act("WAIT_SEQ",
            If(seq_done,
                cmd.last.eq(1),
                NextState("IDLE")
            ).Else(
                cmd.valid.eq(1)
            )
        )
Exemplo n.º 7
0
    def __init__(self):
        self.pause = Signal()
        self.stop = Signal()
        self.delay = Signal()
        self.reset = Signal()

        # # #

        new_lock = Signal()
        update = Signal()
        stop = Signal()
        freeze = Signal()
        pause = Signal()
        reset = Signal()

        # DDRDLLA instance -------------------------------------------------------------------------
        _lock = Signal()
        delay = Signal()
        self.specials += Instance("DDRDLLA",
                                  i_RST=ResetSignal("init"),
                                  i_CLK=ClockSignal("sys2x"),
                                  i_UDDCNTLN=~update,
                                  i_FREEZE=freeze,
                                  o_DDRDEL=delay,
                                  o_LOCK=_lock)
        lock = Signal()
        lock_d = Signal()
        self.specials += MultiReg(_lock, lock, "init")
        self.sync.init += lock_d.eq(lock)
        self.comb += new_lock.eq(lock & ~lock_d)

        # DDRDLLA/DDQBUFM/ECLK initialization sequence ---------------------------------------------
        t = 8  # in cycles
        self.sync.init += [
            # Wait DDRDLLA Lock
            timeline(
                new_lock,
                [
                    (1 * t, [freeze.eq(1)]),  # Freeze DDRDLLA
                    (2 * t, [stop.eq(1)]),  # Stop ECLK domain
                    (3 * t, [reset.eq(1)]),  # Reset ECLK domain
                    (4 * t, [reset.eq(0)]),  # Release ECLK domain reset
                    (5 * t, [stop.eq(0)]),  # Release ECLK domain stop
                    (6 * t, [freeze.eq(0)]),  # Release DDRDLLA freeze
                    (7 * t, [pause.eq(1)]),  # Pause DQSBUFM
                    (8 * t, [update.eq(1)]),  # Update DDRDLLA
                    (9 * t, [update.eq(0)]),  # Release DDRDMMA update
                    (10 * t, [pause.eq(0)]),  # Release DQSBUFM pause
                ])
        ]

        # ------------------------------------------------------------------------------------------
        self.comb += [
            self.pause.eq(pause),
            self.stop.eq(stop),
            self.delay.eq(delay),
            self.reset.eq(reset),
        ]
Exemplo n.º 8
0
	def get_fragment(self):
		sync = [
			self.csr.we.eq(0),
			self.csr.dat_w.eq(self.wishbone.dat_w[:csr.data_width]),
			self.csr.adr.eq(self.wishbone.adr[:14]),
			self.wishbone.dat_r.eq(self.csr.dat_r)
		]
		sync += timeline(self.wishbone.cyc & self.wishbone.stb, [
			(1, [self.csr.we.eq(self.wishbone.we)]),
			(2, [self.wishbone.ack.eq(1)]),
			(3, [self.wishbone.ack.eq(0)])
		])
		return Fragment(sync=sync)
Exemplo n.º 9
0
    def __init__(self, cmd, trp, trfc):
        self.start = Signal()
        self.done = Signal()

        # # #

        self.sync += [
            cmd.a.eq(0),
            cmd.ba.eq(0),
            cmd.cas.eq(0),
            cmd.ras.eq(0),
            cmd.we.eq(0),
            self.done.eq(0),
            # Wait start
            timeline(
                self.start,
                [
                    # Precharge All
                    (0, [
                        cmd.a.eq(2**10),
                        cmd.ba.eq(0),
                        cmd.cas.eq(0),
                        cmd.ras.eq(1),
                        cmd.we.eq(1)
                    ]),
                    # Auto Refresh after tRP
                    (
                        trp,
                        [
                            cmd.a.eq(
                                2**10
                            ),  # all banks in LPDDR4/DDR5, ignored in other memories
                            cmd.ba.eq(0),
                            cmd.cas.eq(1),
                            cmd.ras.eq(1),
                            cmd.we.eq(0),
                        ]),
                    # Done after tRP + tRFC
                    (trp + trfc, [
                        cmd.a.eq(0),
                        cmd.ba.eq(0),
                        cmd.cas.eq(0),
                        cmd.ras.eq(0),
                        cmd.we.eq(0),
                        self.done.eq(1),
                    ]),
                ])
        ]
Exemplo n.º 10
0
    def __init__(self, platform):
        self.clock_domains.cd_sys = ClockDomain("sys")
        self.clock_domains.cd_clk125 = ClockDomain("clk125")

        # soft reset generaton
        self._soft_rst = CSR()
        soft_rst = Signal()
        # trigger soft reset 1us after CSR access to terminate
        # Wishbone access when reseting from PCIe
        self.sync += [
            timeline(self._soft_rst.re & self._soft_rst.r, [(125, [soft_rst.eq(1)])]),
        ]

        # sys_clk / sys_rst (from PCIe)
        self.comb += self.cd_sys.clk.eq(self.cd_clk125.clk)
        self.specials += AsyncResetSynchronizer(self.cd_sys, self.cd_clk125.rst | soft_rst)
Exemplo n.º 11
0
    def __init__(self, pads, clk=10.):
        self.source = do = Endpoint(bus_layout)
        self.busy = Signal()

        # t_RDLl_Dv = 50 ns (setup)
        # t_RDLh_Di = 0ns (hold)
        # t_RDLl_RDLh = 50 ns (redundant, <= r_RDLl_Dv)
        # t_RDLh_RXFLh = 25ns (from FT245R) (redundant, <= t_RDLh_RDLl)
        # t_RXFLh_RXFLl = 80ns (from FT245R)
        # t_RDLh_RDLl = 50ns + t_RXh_RXl (we understand this as a
        #    conditional addition)

        # we read every t_hold + t_precharge + t_setup + 2 cycles
        # can only sustain 1MByte/s anyway at full speed USB
        # stb implicitly needs to be acked within a read cycle
        #clk /= 4 # slow it down
        t_latch = int(ceil(50 / clk)) + 2  # t_RDLl_Dv + slave skew
        t_drop = t_latch + 2  # slave skew
        t_refill = t_drop + int(ceil(50 / clk))  # t_RDLh_RDLl

        reading = Signal()
        rxfl = Signal()
        rd_in = Signal()
        # proxy rxfl to slaves, drive rdl
        self.comb += [
            pads.rdl.eq(~pads.g1_out),
            self.busy.eq(~do.stb | do.ack)
        ]
        self.specials += [
            MultiReg(pads.rxfl, rxfl),
            MultiReg(pads.g1_in, rd_in),
        ]
        self.sync += [
            If(
                ~reading & ~rd_in,
                pads.g1_out.eq(~rxfl),
            ),
            do.stb.eq(do.stb & ~do.ack),
            timeline(rd_in, [
                (0, [reading.eq(1)]),
                (t_latch, [do.stb.eq(1),
                           do.payload.data.eq(pads.data)]),
                (t_drop, [pads.g1_out.eq(0)]),
                (t_refill, [reading.eq(0)]),
            ])
        ]
Exemplo n.º 12
0
	def __init__(self):
		self.wishbone = wishbone.Interface()
		self.csr = csr.Interface()
	
		###

		self.sync += [
			self.csr.we.eq(0),
			self.csr.dat_w.eq(self.wishbone.dat_w[:csr.data_width]),
			self.csr.adr.eq(self.wishbone.adr[:14]),
			self.wishbone.dat_r.eq(self.csr.dat_r)
		]
		self.sync += timeline(self.wishbone.cyc & self.wishbone.stb, [
			(1, [self.csr.we.eq(self.wishbone.we)]),
			(2, [self.wishbone.ack.eq(1)]),
			(3, [self.wishbone.ack.eq(0)])
		])
Exemplo n.º 13
0
    def __init__(self, pads, clk=10.):
        self.source = do = Endpoint(bus_layout)
        self.busy = Signal()

        # t_RDLl_Dv = 50 ns (setup)
        # t_RDLh_Di = 0ns (hold)
        # t_RDLl_RDLh = 50 ns (redundant, <= r_RDLl_Dv)
        # t_RDLh_RXFLh = 25ns (from FT245R) (redundant, <= t_RDLh_RDLl)
        # t_RXFLh_RXFLl = 80ns (from FT245R)
        # t_RDLh_RDLl = 50ns + t_RXh_RXl (we understand this as a
        #    conditional addition)

        # we read every t_hold + t_precharge + t_setup + 2 cycles
        # can only sustain 1MByte/s anyway at full speed USB
        # stb implicitly needs to be acked within a read cycle
        #clk /= 4 # slow it down
        t_latch = int(ceil(50/clk)) + 2 # t_RDLl_Dv + slave skew
        t_drop = t_latch + 2  # slave skew
        t_refill = t_drop + int(ceil(50/clk))  # t_RDLh_RDLl

        reading = Signal()
        rxfl = Signal()
        rd_in = Signal()
        # proxy rxfl to slaves, drive rdl
        self.comb += [
                pads.rdl.eq(~pads.g1_out),
                self.busy.eq(~do.stb | do.ack)
        ]
        self.specials += [
            MultiReg(pads.rxfl, rxfl),
            MultiReg(pads.g1_in, rd_in),
        ]
        self.sync += [
                If(~reading & ~rd_in,
                   pads.g1_out.eq(~rxfl),
                ),
                do.stb.eq(do.stb & ~do.ack),
                timeline(rd_in, [
                    (0, [reading.eq(1)]),
                    (t_latch, [do.stb.eq(1), do.payload.data.eq(pads.data)]),
                    (t_drop, [pads.g1_out.eq(0)]),
                    (t_refill, [reading.eq(0)]),
                ])
        ]
Exemplo n.º 14
0
	def __init__(self, pads, rd_timing):
		self.bus = wishbone.Interface()
	
		###

		adr_width = len(pads.adr) + 1
		self.comb += [pads.oe_n.eq(0), pads.we_n.eq(1),
			pads.ce_n.eq(0)]
		self.sync += timeline(self.bus.cyc & self.bus.stb, [
			(0, [pads.adr.eq(Cat(0, self.bus.adr[:adr_width-2]))]),
			(rd_timing, [
				self.bus.dat_r[16:].eq(pads.d),
				pads.adr.eq(Cat(1, self.bus.adr[:adr_width-2]))]),
			(2*rd_timing, [
				self.bus.dat_r[:16].eq(pads.d),
				self.bus.ack.eq(1)]),
			(2*rd_timing + 1, [
				self.bus.ack.eq(0)])
		])
Exemplo n.º 15
0
    def __init__(self, a, ba, tRP, tREFI, tRFC):
        self.req = Signal()
        self.ack = Signal()  # 1st command 1 cycle after assertion of ack
        self.cmd = CommandRequest(a, ba)

        ###

        # Refresh sequence generator:
        # PRECHARGE ALL --(tRP)--> AUTO REFRESH --(tRFC)--> done
        seq_start = Signal()
        seq_done = Signal()
        self.sync += [
            self.cmd.a.eq(2**10),
            self.cmd.ba.eq(0),
            self.cmd.cas_n.eq(1),
            self.cmd.ras_n.eq(1),
            self.cmd.we_n.eq(1),
            seq_done.eq(0)
        ]
        self.sync += timeline(
            seq_start, [(1, [self.cmd.ras_n.eq(0),
                             self.cmd.we_n.eq(0)]),
                        (1 + tRP, [self.cmd.cas_n.eq(0),
                                   self.cmd.ras_n.eq(0)]),
                        (1 + tRP + tRFC, [seq_done.eq(1)])])

        # Periodic refresh counter
        counter = Signal(max=tREFI)
        start = Signal()
        self.sync += [
            start.eq(0),
            If(counter == 0, start.eq(1),
               counter.eq(tREFI - 1)).Else(counter.eq(counter - 1))
        ]

        # Control FSM
        fsm = FSM()
        self.submodules += fsm
        fsm.act("IDLE", If(start, NextState("WAIT_GRANT")))
        fsm.act("WAIT_GRANT", self.req.eq(1),
                If(self.ack, seq_start.eq(1), NextState("WAIT_SEQ")))
        fsm.act("WAIT_SEQ", self.req.eq(1), If(seq_done, NextState("IDLE")))
Exemplo n.º 16
0
    def __init__(self, bus_wishbone=None, bus_csr=None):
        if bus_wishbone is None:
            bus_wishbone = wishbone.Interface()
        self.wishbone = bus_wishbone
        if bus_csr is None:
            bus_csr = csr_bus.Interface()
        self.csr = bus_csr

        ###

        self.sync += [
            self.csr.we.eq(0),
            self.csr.dat_w.eq(self.wishbone.dat_w),
            self.csr.adr.eq(self.wishbone.adr),
            self.wishbone.dat_r.eq(self.csr.dat_r)
        ]
        self.sync += timeline(self.wishbone.cyc & self.wishbone.stb,
                              [(1, [self.csr.we.eq(self.wishbone.we)]),
                               (2, [self.wishbone.ack.eq(1)]),
                               (3, [self.wishbone.ack.eq(0)])])
Exemplo n.º 17
0
Arquivo: dma.py Projeto: olofk/misoc
    def __init__(self, platform):
        self.clock_domains.cd_sys = ClockDomain("sys")
        self.clock_domains.cd_clk125 = ClockDomain("clk125")

        # soft reset generaton
        self._soft_rst = CSR()
        soft_rst = Signal()
        # trigger soft reset 1us after CSR access to terminate
        # Wishbone access when reseting from PCIe
        self.sync += [
            timeline(self._soft_rst.re & self._soft_rst.r, [(125, [soft_rst.eq(1)])]),
        ]

        # sys_clk / sys_rst (from PCIe)
        self.comb += self.cd_sys.clk.eq(self.cd_clk125.clk)
        self.specials += AsyncResetSynchronizer(self.cd_sys, self.cd_clk125.rst | soft_rst)

        # scratch register
        self._scratch = CSR(32)
        self.sync += If(self._scratch.re, self._scratch.w.eq(self._scratch.r))
Exemplo n.º 18
0
    def __init__(self, bus_wishbone=None, bus_csr=None):
        if bus_wishbone is None:
            bus_wishbone = wishbone.Interface()
        self.wishbone = bus_wishbone
        if bus_csr is None:
            bus_csr = csr.Interface()
        self.csr = bus_csr

        ###

        self.sync += [
            self.csr.we.eq(0),
            self.csr.dat_w.eq(self.wishbone.dat_w),
            self.csr.adr.eq(self.wishbone.adr),
            self.wishbone.dat_r.eq(self.csr.dat_r)
        ]
        self.sync += timeline(self.wishbone.cyc & self.wishbone.stb, [
            (1, [self.csr.we.eq(self.wishbone.we)]),
            (2, [self.wishbone.ack.eq(1)]),
            (3, [self.wishbone.ack.eq(0)])
        ])
Exemplo n.º 19
0
    def __init__(self, cmd, trp, tzqcs):
        self.start = Signal()
        self.done = Signal()

        # # #

        self.sync += [
            # Note: Don't set cmd to 0 since already done in RefreshExecuter
            self.done.eq(0),
            # Wait start
            timeline(
                self.start,
                [
                    # Precharge All
                    (0, [
                        cmd.a.eq(2**10),
                        cmd.ba.eq(0),
                        cmd.cas.eq(0),
                        cmd.ras.eq(1),
                        cmd.we.eq(1)
                    ]),
                    # ZQ Short Calibration after tRP
                    (trp, [
                        cmd.a.eq(0),
                        cmd.ba.eq(0),
                        cmd.cas.eq(0),
                        cmd.ras.eq(0),
                        cmd.we.eq(1),
                    ]),
                    # Done after tRP + tZQCS
                    (trp + tzqcs, [
                        cmd.a.eq(0),
                        cmd.ba.eq(0),
                        cmd.cas.eq(0),
                        cmd.ras.eq(0),
                        cmd.we.eq(0),
                        self.done.eq(1)
                    ]),
                ])
        ]
Exemplo n.º 20
0
    def __init__(self, bus_wishbone=None, bus_csr=None, wb_bus_dw=32):
        if bus_wishbone is None:
            bus_wishbone = wishbone.Interface(data_width=wb_bus_dw,
                                              adr_width=32 -
                                              log2_int(wb_bus_dw // 8))
        self.wishbone = bus_wishbone
        if bus_csr is None:
            bus_csr = csr_bus.Interface()
        self.csr = bus_csr

        ###

        self.sync += [
            self.csr.we.eq(0),
            self.csr.dat_w.eq(self.wishbone.dat_w),
            self.csr.adr.eq(self.wishbone.adr),
            self.wishbone.dat_r.eq(self.csr.dat_r)
        ]
        self.sync += timeline(self.wishbone.cyc & self.wishbone.stb,
                              [(1, [self.csr.we.eq(self.wishbone.we)]),
                               (2, [self.wishbone.ack.eq(1)]),
                               (3, [self.wishbone.ack.eq(0)])])
Exemplo n.º 21
0
    def __init__(self,
                 pads,
                 dummy=15,
                 div=2,
                 with_bitbang=True,
                 endianness="big"):
        """
        Simple SPI flash.
        Supports multi-bit pseudo-parallel reads (aka Dual or Quad I/O Fast
        Read). Only supports mode3 (cpol=1, cpha=1).
        """
        SpiFlashCommon.__init__(self, pads)
        self.bus = bus = wishbone.Interface()
        spi_width = len(pads.dq)
        max_transfer_size = 8 * 8
        assert spi_width >= 2

        if with_bitbang:
            self.bitbang = CSRStorage(
                4,
                reset_less=True,
                fields=[
                    CSRField(
                        "mosi",
                        description=
                        "Output value for MOSI pin, valid whenever ``dir`` is ``0``."
                    ),
                    CSRField("clk",
                             description="Output value for SPI CLK pin."),
                    CSRField("cs_n",
                             description="Output value for SPI CSn pin."),
                    CSRField(
                        "dir",
                        description=
                        "Sets the direction for *ALL* SPI data pins except CLK and CSn.",
                        values=[
                            ("0", "OUT", "SPI pins are all output"),
                            ("1", "IN", "SPI pins are all input"),
                        ])
                ],
                description="""
                Bitbang controls for SPI output.  Only standard 1x SPI is supported, and as
                a result all four wires are ganged together.  This means that it is only possible
                to perform half-duplex operations, using this SPI core.
            """)
            self.miso = CSRStatus(description="Incoming value of MISO signal.")
            self.bitbang_en = CSRStorage(
                description=
                "Write a ``1`` here to disable memory-mapped mode and enable bitbang mode."
            )

        queue = self.queue = CSRStatus(4)
        in_len = self.in_len = CSRStorage(4)
        out_len = self.out_len = CSRStorage(4)
        in_left = self.in_left = Signal(max=2**8)
        out_left = self.out_left = Signal(max=2**8)
        self.quad_transfer = Signal(reset=0)
        spi_in = self.spi_in = CSRStorage(max_transfer_size)
        spi_out = self.spi_out = CSRStatus(max_transfer_size)

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

        cmd_width = 8
        addr_width = 24

        dq = TSTriple(spi_width)

        sr = Signal(max(cmd_width, addr_width, wbone_width))
        if endianness == "big":
            self.comb += bus.dat_r.eq(sr)
        else:
            self.comb += bus.dat_r.eq(reverse_bytes(sr))

        self.specials.dq0 = Tristate(pads.dq[0],
                                     o=dq.o[0],
                                     i=dq.i[0],
                                     oe=dq.oe)
        self.specials.dq1 = Tristate(pads.dq[1],
                                     o=dq.o[1],
                                     i=dq.i[1],
                                     oe=dq.oe)
        if with_bitbang:
            # Keep DQ2,DQ3 as outputs during bitbang, this ensures they activate ~WP or ~HOLD functions
            self.specials.dq2 = Tristate(pads.dq[2],
                                         o=dq.o[2],
                                         i=dq.i[2],
                                         oe=(dq.oe | self.bitbang_en.storage))
            self.specials.dq3 = Tristate(pads.dq[3],
                                         o=dq.o[3],
                                         i=dq.i[3],
                                         oe=(dq.oe | self.bitbang_en.storage))
        else:
            self.specials.dq2 = Tristate(pads.dq[2],
                                         o=dq.o[2],
                                         i=dq.i[2],
                                         oe=dq.oe)
            self.specials.dq3 = Tristate(pads.dq[3],
                                         o=dq.o[3],
                                         i=dq.i[3],
                                         oe=dq.oe)

        sr = Signal(max(cmd_width, addr_width, wbone_width, max_transfer_size))

        if endianness == "big":
            self.comb += bus.dat_r.eq(sr[:wbone_width])
        else:
            self.comb += bus.dat_r.eq(reverse_bytes(sr[:wbone_width]))
        hw_read_logic_single = [
            pads.clk.eq(clk),
            pads.cs_n.eq(cs_n),
            dq.o.eq(sr[-spi_width:]),
            dq.oe.eq(dq_oe)
        ]
        hw_read_logic_quad = [
            pads.clk.eq(clk),
            pads.cs_n.eq(cs_n),
            dq.o.eq(Cat(sr[-1:], Replicate(1, 3))),
            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]),

                # In Dual/Quad mode, no single data pin is consistently
                # an input or output thanks to dual/quad reads, so we need a bit
                # to swap direction of the pins. Aside from this additional bit,
                # bitbang mode is identical for Single/Dual/Quad; dq[0] is mosi
                # and dq[1] is miso, meaning remaining data pin values don't
                # appear in CSR registers.
                If(self.bitbang.storage[3], dq.oe.eq(0)).Else(dq.oe.eq(1)),
                If(
                    self.bitbang.
                    storage[1],  # CPOL=0/CPHA=0 or CPOL=1/CPHA=1 only.
                    self.miso.status.eq(dq.i[1])),
                dq.o.eq(
                    Cat(self.bitbang.storage[0], Replicate(1, spi_width - 1)))
            ]

            self.comb += [
                If(self.bitbang_en.storage, bitbang_logic).Elif(
                    self.quad_transfer,
                    hw_read_logic_single).Else(hw_read_logic_quad)
            ]

        else:
            self.comb += [
                If(self.quad_transfer,
                   hw_read_logic_single).Else(hw_read_logic_quad)
            ]

        if div < 2:
            raise ValueError(
                "Unsupported value \'{}\' for div parameter for SpiFlash core".
                format(div))

        # spi is byte-addressed, prefix by zeros
        z = Replicate(0, log2_int(wbone_width // 8))
        i = Signal(max=div)
        dqi = Signal(spi_width)

        # SPI or memmap mode
        self.mode = Signal()

        self.sync += [
            If(
                i == div // 2 - 1,
                clk.eq(1),
                dqi.eq(dq.i),
            ),
            If(
                i == div - 1, i.eq(0), clk.eq(0),
                If(self.quad_transfer, sr.eq(Cat(dqi, sr[:-spi_width]))).Else(
                    sr.eq(Cat(dqi[1], sr[:-1])))).Else(i.eq(i + 1), ),
        ]

        read_seq = [
            (4 * cmd_width // spi_width * div, [
                dq_oe.eq(1),
                cs_n.eq(0), sr[-cmd_width:].eq(_QIOFR),
                self.quad_transfer.eq(0)
            ]),
            (addr_width // spi_width * div,
             [sr[-addr_width:].eq(Cat(z, bus.adr)),
              self.quad_transfer.eq(1)]),
            ((1 + 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, [queue.status[0].eq(0)]),
        ]

        write_seq = [
            (4 * cmd_width // spi_width * div, [
                dq_oe.eq(1),
                cs_n.eq(0), sr[-cmd_width:].eq(_QIOPP),
                self.quad_transfer.eq(0)
            ]),
            (addr_width // spi_width * div,
             [sr[-addr_width:].eq(Cat(z, bus.adr)),
              self.quad_transfer.eq(1)]),
            ((wbone_width // spi_width) * div,
             [sr[-wbone_width:].eq(reverse_bytes(bus.dat_w))]),
            (1, [bus.ack.eq(1), cs_n.eq(1)]),
            (div, [bus.ack.eq(0)]),
            (0, [queue.status[1].eq(0)]),
        ]

        # prepare spi transfer
        self.sync += If(
            self.out_len.re & (self.out_len.storage != 0)
            & self.en_quad.storage[0],
            self.out_left.eq(Cat(1, self.out_len.storage)))

        self.sync += If(self.out_len.re & (self.out_len.storage == 0),
                        self.out_left.eq(0))
        self.sync += If(
            self.out_len.re & (self.out_len.storage != 0)
            & ~self.en_quad.storage[0],
            self.out_left.eq(Cat(1, Replicate(0, 2), self.out_len.storage)))
        self.sync += If(
            self.in_len.re & (self.in_len.storage != 0)
            & ~self.en_quad.storage[0], [
                queue.status[2].eq(1),
                self.in_left.eq(Cat(Replicate(0, 3), in_len.storage)),
                self.quad_transfer.eq(0)
            ])

        # write data to sr
        self.sync += If(
            queue.status[2] & (i == div - 1) & ~self.en_quad.storage[0],
            sr[-max_transfer_size:].eq(self.spi_in.storage),
            queue.status[2].eq(0), queue.status[3].eq(1), cs_n.eq(0),
            dq_oe.eq(1))

        # count spi to slave transfer cycles
        self.sync += If(queue.status[3] & (self.in_left > 0) & (i == div - 1),
                        self.in_left.eq(self.in_left - 1), dq_oe.eq(1))
        # count spi to master transfer cycles
        self.sync += If(
            queue.status[3] & (self.in_left < 1) & (self.out_left > 0) &
            (i == div - 1), self.out_left.eq(self.out_left - 1), dq_oe.eq(0))

        #end transmision and read data from sr
        self.sync += If(
            ~self.in_len.re & (in_left < 1) & (out_left < 1) & queue.status[3],
            queue.status[3].eq(0), cs_n.eq(1),
            If(self.out_len.storage == 1,
               self.spi_out.status.eq(Cat(Replicate(0, 8 * 7), sr))).Elif(
                   self.out_len.storage == 2,
                   self.spi_out.status.eq(Cat(Replicate(0, 8 * 6), sr))).Elif(
                       self.out_len.storage == 3,
                       self.spi_out.status.eq(Cat(Replicate(
                           0, 8 * 5), sr))).Elif(
                               self.out_len.storage == 4,
                               self.spi_out.status.eq(
                                   Cat(Replicate(0, 8 * 4), sr))).Elif(
                                       self.out_len.storage == 5,
                                       self.spi_out.status.eq(
                                           Cat(Replicate(0, 8 * 3), sr))).
            Elif(
                self.out_len.storage == 6,
                self.spi_out.status.eq(Cat(Replicate(0, 8 * 2), sr))).Elif(
                    self.out_len.storage == 7,
                    self.spi_out.status.eq(Cat(Replicate(0, 8 * 1), sr))).Else(
                        self.spi_out.status.eq(sr)))

        # detect mem map access
        self.sync += If(~self.mode & bus.cyc & bus.stb & ~bus.we,
                        queue.status[0].eq(1))
        self.sync += If(~self.mode & bus.cyc & bus.stb & bus.we,
                        queue.status[1].eq(1))

        self.sync += timeline(
            queue.status[0] & ~self.en_quad.storage[0] & (i == div - 1),
            accumulate_timeline_deltas(read_seq))
        self.sync += timeline(
            queue.status[1] & ~self.en_quad.storage[0] & (i == div - 1),
            accumulate_timeline_deltas(write_seq))
Exemplo n.º 22
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.º 23
0
    def __init__(self,
                 pads,
                 dummy=15,
                 div=2,
                 with_bitbang=True,
                 endianness="big"):
        """
        Simple SPI flash.
        Supports multi-bit pseudo-parallel reads (aka Dual or Quad I/O Fast
        Read). Only supports mode0 (cpol=0, cpha=0).
        """
        self.bus = bus = wishbone.Interface()
        spi_width = len(pads.dq)
        assert spi_width >= 2

        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 = len(bus.dat_r)

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

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

        sr = Signal(max(cmd_width, addr_width, wbone_width))
        if endianness == "big":
            self.comb += bus.dat_r.eq(sr)
        else:
            self.comb += bus.dat_r.eq(reverse_bytes(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]),

                # In Dual/Quad mode, no single data pin is consistently
                # an input or output thanks to dual/quad reads, so we need a bit
                # to swap direction of the pins. Aside from this additional bit,
                # bitbang mode is identical for Single/Dual/Quad; dq[0] is mosi
                # and dq[1] is miso, meaning remaining data pin values don't
                # appear in CSR registers.
                If(self.bitbang.storage[3], dq.oe.eq(0)).Else(dq.oe.eq(1)),
                If(
                    self.bitbang.
                    storage[1],  # CPOL=0/CPHA=0 or CPOL=1/CPHA=1 only.
                    self.miso.status.eq(dq.i[1])),
                dq.o.eq(
                    Cat(self.bitbang.storage[0], Replicate(1, spi_width - 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.º 24
0
    def __init__(self,
                 pads,
                 dummy=15,
                 div=2,
                 with_bitbang=True,
                 endianness="big"):
        """
        Simple SPI flash.
        Supports 1-bit reads. Only supports mode0 (cpol=0, cpha=0).
        """
        self.bus = bus = wishbone.Interface()

        if with_bitbang:
            self.bitbang = CSRStorage(4)
            self.miso = CSRStatus()
            self.bitbang_en = CSRStorage()

        # # #

        if hasattr(pads, "wp"):
            self.comb += pads.wp.eq(1)

        if hasattr(pads, "hold"):
            self.comb += pads.hold.eq(1)

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

        read_cmd = _FAST_READ
        cmd_width = 8
        addr_width = 24

        sr = Signal(max(cmd_width, addr_width, wbone_width))
        if endianness == "big":
            self.comb += bus.dat_r.eq(sr)
        else:
            self.comb += bus.dat_r.eq(reverse_bytes(sr))

        hw_read_logic = [
            pads.clk.eq(clk),
            pads.cs_n.eq(cs_n),
            pads.mosi.eq(sr[-1:])
        ]

        if with_bitbang:
            bitbang_logic = [
                pads.clk.eq(self.bitbang.storage[1]),
                pads.cs_n.eq(self.bitbang.storage[2]),
                If(
                    self.bitbang.
                    storage[1],  # CPOL=0/CPHA=0 or CPOL=1/CPHA=1 only.
                    self.miso.status.eq(pads.miso)),
                pads.mosi.eq(self.bitbang.storage[0])
            ]

            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)
            miso = Signal()
            self.sync += [
                If(
                    i == div // 2 - 1,
                    clk.eq(1),
                    miso.eq(pads.miso),
                ),
                If(i == div - 1, i.eq(0), clk.eq(0),
                   sr.eq(Cat(miso, sr[:-1]))).Else(i.eq(i + 1), ),
            ]

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

        seq = [
            (cmd_width * div, [cs_n.eq(0), sr[-cmd_width:].eq(read_cmd)]),
            (addr_width * div, [sr[-addr_width:].eq(Cat(z, bus.adr))]),
            ((dummy + wbone_width) * div, []),
            (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.º 25
0
    def __init__(self, pads):
        self.pads = pads
        self.bus  = bus = wishbone.Interface()

        # # #

        clk       = Signal()
        clk_phase = Signal(2)
        cs        = Signal()
        ca        = Signal(48)
        sr        = Signal(48)
        dq        = self.add_tristate(pads.dq) if not hasattr(pads.dq, "oe") else pads.dq
        rwds      = self.add_tristate(pads.rwds) if not hasattr(pads.rwds, "oe") else pads.rwds

        # Drive rst_n, cs_n, clk from internal signals ---------------------------------------------
        if hasattr(pads, "rst_n"):
            self.comb += pads.rst_n.eq(1)
        self.comb += pads.cs_n[0].eq(~cs)
        assert len(pads.cs_n) <= 2
        if len(pads.cs_n) == 2:
            self.comb += pads.cs_n[1].eq(1)
        if hasattr(pads, "clk"):
            self.comb += pads.clk.eq(clk)
        else:
            self.specials += DifferentialOutput(clk, pads.clk_p, pads.clk_n)

        # Clock Generation (sys_clk/4) -------------------------------------------------------------
        self.sync += clk_phase.eq(clk_phase + 1)
        cases = {}
        cases[1] = clk.eq(cs) # Set pads clk on 90° (if cs is set)
        cases[3] = clk.eq(0)  # Clear pads clk on 270°
        self.sync += Case(clk_phase, cases)

        # Data Shift Register (for write and read) -------------------------------------------------
        dqi = Signal(8)
        self.sync += dqi.eq(dq.i) # Sample on 90° and 270°
        cases = {}
        cases[0] = sr.eq(Cat(dqi, sr[:-8])) # Shift on 0°
        cases[2] = sr.eq(Cat(dqi, sr[:-8])) # Shift on 180°
        self.sync += Case(clk_phase, cases)
        self.comb += [
            bus.dat_r.eq(sr), # To Wisbone
            dq.o.eq(sr[-8:]), # 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
        ]

        # Sequencer --------------------------------------------------------------------------------
        dt_seq = [
            # DT,  Action
            (3,    []),
            (12,   [cs.eq(1), dq.oe.eq(1), sr.eq(ca)]),    # Command: 6 clk
            (44,   [dq.oe.eq(0)]),                         # Latency(default): 2*6 clk
            (2,    [dq.oe.eq(self.bus.we),                 # Write/Read data byte: 2 clk
                    sr[:16].eq(0),
                    sr[16:].eq(self.bus.dat_w),
                    rwds.oe.eq(self.bus.we),
                    rwds.o.eq(~bus.sel[0])]),
            (2,    [rwds.o.eq(~bus.sel[1])]),              # Write/Read data byte: 2 clk
            (2,    [rwds.o.eq(~bus.sel[2])]),              # Write/Read data byte: 2 clk
            (2,    [rwds.o.eq(~bus.sel[3])]),              # Write/Read data byte: 2 clk
            (2,    [cs.eq(0), rwds.oe.eq(0), dq.oe.eq(0)]),
            (1,    [bus.ack.eq(1)]),
            (1,    [bus.ack.eq(0)]),
            (0,    []),
        ]
        # Convert delta-time sequencer to time sequencer
        t_seq = []
        t_seq_start = (clk_phase == 1)
        t = 0
        for dt, a in dt_seq:
            t_seq.append((t, a))
            t += dt
        self.sync += timeline(bus.cyc & bus.stb & t_seq_start, t_seq)
Exemplo n.º 26
0
    def __init__(self,
                 pads,
                 dummy=15,
                 div=2,
                 with_bitbang=True,
                 endianness="big"):
        """
        Simple memory-mapped SPI flash.
        Supports 1-bit reads. Only supports mode3 (cpol=1, cpha=1).
        """
        SpiFlashCommon.__init__(self, pads)
        self.bus = bus = wishbone.Interface()

        if with_bitbang:
            self.bitbang = CSRStorage(
                4,
                fields=[
                    CSRField("mosi",
                             description="Output value for SPI MOSI pin."),
                    CSRField("clk",
                             description="Output value for SPI CLK pin."),
                    CSRField("cs_n",
                             description="Output value for SPI CSn pin."),
                    CSRField("dir", description="Unused in this design.")
                ],
                description="""Bitbang controls for SPI output.""")
            self.miso = CSRStatus(description="Incoming value of MISO pin.")
            self.bitbang_en = CSRStorage(
                description=
                "Write a ``1`` here to disable memory-mapped mode and enable bitbang mode."
            )

        # # #

        if hasattr(pads, "wp"):
            self.comb += pads.wp.eq(1)

        if hasattr(pads, "hold"):
            self.comb += pads.hold.eq(1)

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

        read_cmd = _FAST_READ
        cmd_width = 8
        addr_width = 24

        sr = Signal(max(cmd_width, addr_width, wbone_width))
        if endianness == "big":
            self.comb += bus.dat_r.eq(sr)
        else:
            self.comb += bus.dat_r.eq(reverse_bytes(sr))

        hw_read_logic = [
            pads.clk.eq(clk),
            pads.cs_n.eq(cs_n),
            pads.mosi.eq(sr[-1:])
        ]

        if with_bitbang:
            bitbang_logic = [
                pads.clk.eq(self.bitbang.storage[1]),
                pads.cs_n.eq(self.bitbang.storage[2]),
                If(
                    self.bitbang.
                    storage[1],  # CPOL=0/CPHA=0 or CPOL=1/CPHA=1 only.
                    self.miso.status.eq(pads.miso)),
                pads.mosi.eq(self.bitbang.storage[0])
            ]

            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)
            miso = Signal()
            self.sync += [
                If(
                    i == div // 2 - 1,
                    clk.eq(1),
                    miso.eq(pads.miso),
                ),
                If(i == div - 1, i.eq(0), clk.eq(0),
                   sr.eq(Cat(miso, sr[:-1]))).Else(i.eq(i + 1), ),
            ]

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

        seq = [
            (cmd_width * div, [cs_n.eq(0), sr[-cmd_width:].eq(read_cmd)]),
            (addr_width * div, [sr[-addr_width:].eq(Cat(z, bus.adr))]),
            ((dummy + wbone_width) * div, []),
            (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.º 27
0
    def __init__(self, pads):
        """
        HyperRAM simple core for LiteX
        This core should always just work on any FPGA platorm it is fully vendor neutral
        No configuration, no software setup, ready after poweron, fixed latency        
        
        """
        HyperMemporyCommon.__init__(self, pads)

        if hasattr(pads, "rst_n"):
            self.comb += pads.rst_n.eq(1)
        if hasattr(pads, "cs1_n"):
            self.comb += pads.cs1_n.eq(1)

        # Tristate pads
        dq = TSTriple(8)
        self.specials.dq = dq.get_tristate(pads.dq)
        rwds = TSTriple(1)
        self.specials.rwds = rwds.get_tristate(pads.rwds)

        # Wishbone
        self.bus = bus = wishbone.Interface()
        sr = Signal(48)

        dq_oe = Signal(reset=0)
        rwds_oe = Signal(reset=0)
        cs_int = Signal(reset=1)

        self.comb += [
            bus.dat_r.eq(sr),
            dq.oe.eq(dq_oe),
            dq.o.eq(sr[-8:]),
            rwds.oe.eq(rwds_oe),
            pads.cs0_n.eq(cs_int)
        ]

        # we generate complementaty clk out for emulated differential output
        clk_p = Signal(1)
        clk_n = Signal(1)

        self.comb += pads.clk.eq(clk_p)
        # if negative is defined drive complementary clock out
        if hasattr(pads, "clk_n"):
            self.comb += pads.clk_n.eq(clk_n)
        # 1 sys clock delay needed to adjust input timings?
        dqi = Signal(8)
        self.sync += [dqi.eq(dq.i)]
        # hyper RAM clock generator and 48 bit byte shifter
        i = Signal(max=4)
        self.sync += [
            If(
                i == 0,
                sr.eq(Cat(dqi, sr[:-8])),
            ),
            If(
                i == 1,
                clk_p.eq(~cs_int),  # 1
                clk_n.eq(cs_int)  # 0
            ),
            If(i == 2, sr.eq(Cat(dqi, sr[:-8]))),
            If(
                i == 3,
                i.eq(0),
                clk_p.eq(0),  # 1
                clk_n.eq(1)  # 0
            ).Else(i.eq(i + 1))
        ]
        # signals to use CA or data to write
        CA = Signal(48)
        # combine bits to create CA bytes
        self.comb += [
            CA[47].eq(~self.bus.we),
            CA[45].eq(1),
            CA[16:35].eq(self.bus.adr[2:21]),
            CA[1:3].eq(self.bus.adr[0:2]),
            CA[0].eq(0),
        ]
        z = Replicate(0, 16)
        seq = [
            (3, []),
            (12, [cs_int.eq(0), dq_oe.eq(1),
                  sr.eq(CA)]),  # 6 clock edges for command transmit
            (44, [dq_oe.eq(0)]),  # 6+6 latency default
            (2, [
                dq_oe.eq(self.bus.we),
                rwds_oe.eq(self.bus.we),
                rwds.o.eq(~bus.sel[0]),
                sr.eq(Cat(z, self.bus.dat_w))
            ]),  # 4 edges to write data
            (2, [rwds.o.eq(~bus.sel[1])]),  # 4 edges to write data
            (2, [rwds.o.eq(~bus.sel[2])]),  # 4 edges to write data
            (2, [rwds.o.eq(~bus.sel[3])]),  # 4 edges to write data
            (2, [cs_int.eq(1), rwds_oe.eq(0),
                 dq_oe.eq(0)]),
            (1, [bus.ack.eq(1)]),  # is 1 also OK?
            (1, [bus.ack.eq(0)]),  #
            (0, []),
        ]

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

        self.sync += timeline(bus.cyc & bus.stb & (i == 1), tseq)
Exemplo n.º 28
0
    def __init__(self, simulation=False):
        self.addr = CSRStorage(5, description="ICAP Write Address.")
        self.data = CSRStorage(32, description="ICAP Write Data.")
        self.send = CSRStorage(
            description=
            "ICAP Control.\n\n Write ``1`` send a write command to the ICAP.")
        self.done = CSRStatus(
            reset=1,
            description=
            "ICAP Status.\n\n Write command done when read as ``1``.")

        # # #

        # Create slow icap clk (sys_clk/16) ---------------------------------------------------------
        self.clock_domains.cd_icap = ClockDomain()
        icap_clk_counter = Signal(4)
        self.sync += icap_clk_counter.eq(icap_clk_counter + 1)
        self.sync += self.cd_icap.clk.eq(icap_clk_counter[3])

        # Resynchronize send pulse to icap domain ---------------------------------------------------
        ps_send = PulseSynchronizer("sys", "icap")
        self.submodules += ps_send
        self.comb += [ps_send.i.eq(self.send.re)]

        # Generate icap bitstream write sequence
        self._csib = _csib = Signal(reset=1)
        self._i = _i = Signal(32)
        _addr = self.addr.storage << 13
        _data = self.data.storage
        self.sync.icap += [
            _i.eq(0xffffffff),  # dummy
            timeline(
                ps_send.o,
                [
                    (1, [_csib.eq(1), self.done.status.eq(0)]),
                    (2, [_csib.eq(0), _i.eq(0x20000000)]),  # noop
                    (3, [_csib.eq(0), _i.eq(0xaa995566)]),  # sync word
                    (4, [_csib.eq(0), _i.eq(0x20000000)]),  # noop
                    (5, [_csib.eq(0), _i.eq(0x20000000)]),  # noop
                    (6, [_csib.eq(0), _i.eq(0x30000001 | _addr)
                         ]),  # write command
                    (7, [_csib.eq(0), _i.eq(_data)]),  # write value
                    (8, [_csib.eq(0), _i.eq(0x20000000)]),  # noop
                    (9, [_csib.eq(0), _i.eq(0x20000000)]),  # noop
                    (10, [_csib.eq(0), _i.eq(0x30008001)
                          ]),  # write to cmd register
                    (11, [_csib.eq(0), _i.eq(0x0000000d)]),  # desync command
                    (12, [_csib.eq(0), _i.eq(0x20000000)]),  # noop
                    (13, [_csib.eq(0), _i.eq(0x20000000)]),  # noop
                    (14, [_csib.eq(1), self.done.status.eq(1)]),
                ])
        ]

        # ICAP instance
        if not simulation:
            self.specials += [
                Instance(
                    "ICAPE2",
                    p_ICAP_WIDTH="X32",
                    i_CLK=ClockSignal("icap"),
                    i_CSIB=_csib,
                    i_RDWRB=0,
                    i_I=Cat(*[_i[8 * i:8 * (i + 1)][::-1] for i in range(4)]),
                )
            ]
Exemplo n.º 29
0
    def __init__(self, pads, exclude):
        """
        BBIO simple core for LiteX
        TODO expose seladr, input mux out, and write enable, and value to external IP cores     
        This would "connect" the last access BBIO pin to external time multipexed IP's
        TODO can we update the .h files from here?         
        """
        bbioCommon.__init__(self, pads, exclude)

        bbio_width = len(pads)
        #
        bbio_o = Signal(bbio_width)
        bbio_oe = Signal(bbio_width)
        bbio_i = Signal(bbio_width)
        # create single pin tristate buffers
        for b in range(bbio_width):
            self.submodules += bbioSinglePin(pads, b, bbio_i[b], bbio_o[b],
                                             bbio_oe[b])

        # Wishbone
        self.bus = bus = wishbone.Interface()

        #
        sel = Signal(bbio_width)
        inbit = Signal(1)

        # todo: dynamic address width calc to optimize the decode logic
        addr_width = 12
        # 1024 IO max?
        # expose sel address to external IP Cores
        seladr = Signal(10)

        # 10 bits of address = 1024 pins max
        #        self.comb += seladr.eq(self.bus.adr[:10])

        # address decoder
        for b in range(bbio_width):
            self.comb += sel[b].eq(seladr == b)

        self.comb += inbit.eq((bbio_i & sel) != 0)

        # Read bit
        rdbus = Signal(32)
        self.comb += [rdbus[0].eq(inbit), bus.dat_r.eq(rdbus)]

        # process output
        # todo. multiplex them to external IP core use
        outbit = Signal(1)
        oebit = Signal(1)
        wren = Signal(1)

        # PINAPI 1.0 compatible: 0 = drive 0, 1 drive 1, 3 = HiZ
        self.comb += outbit.eq(bus.dat_w[0])
        self.comb += oebit.eq(~bus.dat_w[1])

        # write enables
        #        self.comb += wren.eq(self.bus.stb & self.bus.cyc & self.bus.we)

        for b in range(bbio_width):
            self.sync += If(wren & sel[b], bbio_o[b].eq(outbit),
                            bbio_oe[b].eq(oebit))

        # todo optimize 1 cycle away?
        seq = [
            (1, [
                bus.ack.eq(0),
                seladr.eq(self.bus.adr[:10]),
                wren.eq(self.bus.we)
            ]),  # latch IO address and wren bit
            (1, [bus.ack.eq(1), wren.eq(0)
                 ]),  # ack transfer, clear wren, KEEP select address!
            (1, [bus.ack.eq(0)]),  # done
            (0, []),
        ]

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

        self.sync += timeline(bus.cyc & bus.stb, tseq)
Exemplo n.º 30
0
    def __init__(self, S=8, D=2, INITIAL_IDELAY=15, clock_regions=[0, 1]):
        """
        S = serialization factor (bits per frame)
        D = number of parallel lanes
        clock_regions:
            list of D integers specifying how to assign the lvds_data input
            pins to specific clock regions.
            Each clock_region will be treated as a separate clock domain,
            having its own BUFR, BUFIO, FIFO and reset sync. logic
            Example for 3 signals, where the last one is in a separate region:
            clock_regions = [0, 0, 1]
        """
        self.CLOCK_REGIONS = Counter(clock_regions)  # = {0: 2, 1: 1}

        # LVDS DDR bit clock
        self.dco_p = Signal()
        self.dco_n = Signal()

        # data (+frame) lanes
        self.lvds_data_p = Signal(D)
        self.lvds_data_n = Signal(D)

        # Pulse to rotate bits (sys clock domain)
        # Will be synchronized to all clock regions and applied to all ISERDES
        self.bitslip = Signal()

        # IDELAY control for DCO clock input
        # on sys clock domain
        self.id_inc = Signal()
        self.id_dec = Signal()
        self.id_value = Signal(5)

        # parallel data out, S-bit serdes on D-lanes
        # on `sample` clock domain
        self.data_outs = [Signal(S) for i in range(D)]

        ###

        # recovered ADC sampling clock
        self.clock_domains.cd_sample = ClockDomain("sample")
        self.init_running = Signal(reset=1)

        self.iserdes_default = {
            "p_DATA_WIDTH": S,
            "p_DATA_RATE": "DDR",
            "p_SERDES_MODE": "MASTER",
            "p_INTERFACE_TYPE": "NETWORKING",
            "p_NUM_CE": 1,
            "p_IOBDELAY": "NONE",
            "i_DDLY": 0,
            "i_CE1": 1,
            "i_CE2": 1,
            "i_DYNCLKDIVSEL": 0,
            "i_DYNCLKSEL": 0
        }

        # -------------------------------------------------
        #  DCO input clock --> IDELAYE2 --> BUFMRCE
        # -------------------------------------------------
        dco = Signal()
        dco_delay = Signal()
        dco_delay_2 = Signal()
        id_CE = Signal()
        self.comb += id_CE.eq(self.id_inc ^ self.id_dec)
        self.specials += DifferentialInput(self.dco_p, self.dco_n, dco)
        self.specials += Instance("IDELAYE2",
                                  p_DELAY_SRC="IDATAIN",
                                  p_HIGH_PERFORMANCE_MODE="TRUE",
                                  p_REFCLK_FREQUENCY=200.0,
                                  p_IDELAY_TYPE="VARIABLE",
                                  p_IDELAY_VALUE=INITIAL_IDELAY,
                                  i_C=ClockSignal("sys"),
                                  i_LD=ResetSignal("sys"),
                                  i_INC=self.id_inc,
                                  i_CE=id_CE,
                                  i_LDPIPEEN=0,
                                  i_CINVCTRL=0,
                                  i_CNTVALUEIN=Constant(0, 5),
                                  i_DATAIN=0,
                                  i_REGRST=0,
                                  i_IDATAIN=dco,
                                  o_DATAOUT=dco_delay,
                                  o_CNTVALUEOUT=self.id_value)

        bufmr_ce = Signal()
        bufr_clr = Signal(reset=1)
        self.specials += Instance("BUFMRCE",
                                  i_CE=bufmr_ce,
                                  i_I=dco_delay,
                                  o_O=dco_delay_2)

        # -------------------------------------------------
        #  Reset sequence
        # -------------------------------------------------
        # Sample clock domain will reset on sys clock reset.
        # ... which will also trigger the init sequence below
        #
        # synchronize BUFR dividers on sys_clk reset
        # a symptom of screwing this up is:
        #   * different number of bitslips are required
        #     for ISERDES in different clock regions
        #
        # __Note:__
        # The sequence suggested in [1] releases `bufr_clr` last,
        # which for me did not align the BUFR dividers reliably.
        # However releasing `bufmr_ce` last did the tick.
        # Error in the Xilinx documentation?
        #
        # [1] UG472 p. 110 `BUFR Alignment`
        self.sync.sys += timeline(
            self.init_running,
            [
                # Shut down sample_clk at BUFMRCE, clear regional dividers ...
                (0, [bufr_clr.eq(1), bufmr_ce.eq(0)]),
                (4, [bufr_clr.eq(0)]),
                # Re-enable regional clocks
                (8, [bufmr_ce.eq(1)]),
                # Regional clocks are running and synced,
                # release `cd_sample` reset
                (16, [self.init_running.eq(0)])
            ])
        # Only release all resets on sample_clk domain after step 16
        self.specials += AsyncResetSynchronizer(self.cd_sample,
                                                self.init_running)

        # -------------------------------------------------
        #  generate a separate CD for each clock region
        # -------------------------------------------------
        # each one having its own BUFR, BUFIO and reset sync.
        r_ioclks = {}  # Regional IO clocks driven by BUFIO
        r_clks = {}  # Regional fabric clocks driven by BUFR
        r_bitslips = {}  # Regional bitslip pulses

        for cr_i, cr_n in self.CLOCK_REGIONS.items():
            print(f"Clock region: {cr_i}, inputs: {cr_n}")

            # regional buffer for the fast IO clock
            ioclk = Signal()
            self.specials += Instance("BUFIO", i_I=dco_delay_2, o_O=ioclk)

            # regional clock domain for ISERDES output + interface fabric
            cd_name = f'bufr_{cr_i}'
            cd = ClockDomain(cd_name)
            self.clock_domains += cd
            self.specials += Instance(
                "BUFR",
                p_BUFR_DIVIDE=str(S // 2),  # div by 2 due to DDR
                i_I=dco_delay_2,
                i_CE=1,
                i_CLR=bufr_clr,
                o_O=cd.clk)

            # Releasing global `sample` reset releases local `bufr_N` reset
            AsyncResetSynchronizer(cd, ResetSignal('sample'))

            # Move bitslip pulse into regional CD
            ps = PulseSynchronizer('sys', cd_name)
            self.submodules += ps
            self.comb += ps.i.eq(self.bitslip)

            # Collect all region specific items in dicts
            r_ioclks[cr_i] = ioclk
            r_clks[cr_i] = cd.clk
            r_bitslips[cr_i] = ps.o

        # Make last regional clock available to rest of the design
        # Note that the output of the BUFG is not phase matched with the
        # output of the BUFR. I'll use elastic buffers to move over the data
        # TODO get sample clock from IBUFDS --> MMCM --> BUFG ???
        # The BUFG cell BUFG_1 I pin is driven by a BUFR cell BUFR_1. For 7-Series devices, this is not a recommended clock topology. Please analyze your clock network and remove the BUFR to BUFG cascade.
        self.specials += Instance("BUFG",
                                  i_I=cd.clk,
                                  o_O=ClockSignal("sample"))

        # -------------------------------------------------
        #  Generate an IDERDES for each data lane
        # -------------------------------------------------
        r_dos = defaultdict(list)  # Regional data-outs, key = clock region
        for d_p, d_n, c_reg in zip(self.lvds_data_p, self.lvds_data_n,
                                   clock_regions):
            d_i = Signal()
            self.specials += DifferentialInput(d_p, d_n, d_i)

            # Collect parallel output data
            do = Signal(S)

            self.specials += Instance("ISERDESE2",
                                      **self.iserdes_default,
                                      i_CLK=r_ioclks[c_reg],
                                      i_CLKB=~r_ioclks[c_reg],
                                      i_CLKDIV=r_clks[c_reg],
                                      i_D=d_i,
                                      i_BITSLIP=r_bitslips[c_reg],
                                      i_RST=ResetSignal(cd_name),
                                      o_Q1=do[0],
                                      o_Q2=do[1],
                                      o_Q3=do[2],
                                      o_Q4=do[3],
                                      o_Q5=do[4],
                                      o_Q6=do[5],
                                      o_Q7=do[6],
                                      o_Q8=do[7])

            r_dos[c_reg].append(do)

        # -------------------------------------------------
        #  Generate elastic-buffer for each clock region
        # -------------------------------------------------
        fifo_outs = []
        for cr_i, r_dos in r_dos.items():
            dos = Cat(r_dos)

            cd_name = f'bufr_{cr_i}'
            ebuf_name = f'ebuf_{cr_i}'

            # Regional FIFO
            ebuf = ElasticBuffer(len(dos), 2, cd_name, 'sample')
            setattr(self.submodules, ebuf_name, ebuf)
            self.comb += ebuf.din.eq(dos)
            fifo_outs.append(ebuf.dout)

        self.comb += Cat(self.data_outs).eq(Cat(fifo_outs))
Exemplo n.º 31
0
    def __init__(self,
                 S,
                 D,
                 MIRROR_BITS,
                 BITSLIPS,
                 idelay_overrides={},
                 iserdes_overrides={}):
        """
        Generates all logic necessary for the data lanes, calibration
        and phase detection / adjustment
        Does not do anything related to clocking.
        Inherit and add you own clock.
        """
        # LVDS DDR bit clock
        self.dco_p = Signal()
        self.dco_n = Signal()

        # data lanes
        self.lvds_data_p = Signal(D)
        self.lvds_data_n = Signal(D)

        # Control signals (on sample clock domain)
        self.bitslip = Signal()  # Pulse to rotate

        # Phase detector readout (on sample clock domain)
        # input for number of sample clock cycles to integrate
        self.pd_int_period = Signal(32, reset=2**23)
        # outputs integrated Phase detector values (int32)
        self.pd_int_phases = [Signal((32, True)) for i in range(D)]
        # input to enable auto increment / decrement IDELAY based on PD value
        self.id_auto_control = Signal()

        # Idelay control inputs (on sample clock domain)
        self.id_mux = Signal(max=D + 1)  # select a LVDS lane
        self.id_inc = Signal(1)
        self.id_dec = Signal(1)

        # parallel data out, S-bit serdes on D-lanes (on sample clock domain)
        self.data_outs = [Signal(S) for i in range(D)]

        # Async Reset for clock generation and `sample` clock domain
        self.reset = Signal(reset=1)

        ###

        # Common internal signals which must be driven by child
        self.clock_domains.sample = ClockDomain(
            "sample")  # received ADC sample clock
        self.ioclk_p = Signal()
        self.ioclk_n = Signal()
        self.serdesstrobe = Signal()

        # -----------------------------
        #  IDELAY calibration
        # -----------------------------
        self.idelay_rst = Signal()
        self.idelay_cal_m = Signal()
        self.idelay_cal_s = Signal()
        # High when IDELAY initialization complete
        self.initial_tl_done = Signal()
        bitslip_initial = Signal()
        self.sync.sample += [
            self.idelay_cal_m.eq(0),
            self.idelay_cal_s.eq(0),
            self.idelay_rst.eq(0),
            bitslip_initial.eq(0)
        ]
        # Initially calibrate and reset all IDELAY2s
        tl = [
            (20, [self.idelay_cal_m.eq(1),
                  self.idelay_cal_s.eq(1)]),
            (40, [self.idelay_rst.eq(1)]),
            (60, [self.initial_tl_done.eq(1)]),
            # Add initial bitslips starting from clk 100. Have I gone too far?
            *zip([100 + i * 10 for i in range(BITSLIPS)],
                 [[bitslip_initial.eq(1)]] * BITSLIPS)
        ]
        # print(tl)
        self.sync.sample += timeline(~self.initial_tl_done, tl)
        # Periodically re-calibrate all slave IDELAY2s
        self.sync.sample += timeline(
            self.initial_tl_done,
            [(2**26, [self.idelay_cal_s.eq(1)])  # every 0.54 s at 125 MHz
             ])

        # Accumulator regs for phase detector
        pd_int_accus = [Signal.like(s) for s in self.pd_int_phases]
        pd_int_cnt = Signal(32)
        self.sync.sample += [
            If(
                pd_int_cnt >= self.pd_int_period,
                pd_int_cnt.eq(0),
            ).Elif(
                self.
                initial_tl_done,  # only start counting when idelays are calibrated
                pd_int_cnt.eq(pd_int_cnt + 1))
        ]

        # -----------------------------
        #  Default block parameters
        # -----------------------------
        self.idelay_default = {
            "p_SIM_TAPDELAY_VALUE": 49,
            "p_IDELAY_VALUE": 0,  # A faire: make CSR
            "p_IDELAY2_VALUE": 0,
            "p_ODELAY_VALUE": 0,
            "p_IDELAY_MODE": "NORMAL",
            "p_COUNTER_WRAPAROUND": "WRAPAROUND",
            "p_DELAY_SRC": "IDATAIN",
            "i_T": 1,
            "i_ODATAIN": 0,
            "i_IOCLK0": self.ioclk_p,
            "i_IOCLK1": self.ioclk_n,
            "i_CLK": ClockSignal("sample"),
            "i_RST": self.idelay_rst
        }
        self.idelay_default.update(idelay_overrides)
        self.iserdes_default = {
            "p_DATA_WIDTH": S,
            "p_BITSLIP_ENABLE": "TRUE",
            "p_INTERFACE_TYPE": "RETIMED",
            "i_CE0": 1,
            "i_CLK0": self.ioclk_p,
            "i_CLK1": self.ioclk_n,
            "i_IOCE": self.serdesstrobe,
            "i_RST": ~self.initial_tl_done,
            "i_CLKDIV": ClockSignal("sample"),
            "i_BITSLIP": self.bitslip | bitslip_initial
        }
        self.iserdes_default.update(iserdes_overrides)

        for i in range(D):
            lvds_data = Signal()
            lvds_data_m = Signal()
            lvds_data_s = Signal()
            id_CE = Signal()
            id_INC = Signal()
            # -------------------------------------
            #  Idelay control (auto / manual)
            # -------------------------------------
            self.sync.sample += [
                # Mux the IDELAY control inputs
                If(
                    self.id_auto_control,
                    id_CE.
                    eq((pd_int_cnt == 1) &
                       # Adjust IDELAYS at end of each accumulator cycle
                       (self.pd_int_phases[i] != 0)
                       # Adjust IDELAYs when consistently early / late
                       # during _all_ accumulator cycles
                       # ((self.pd_int_phases[i] >= self.pd_int_period) |
                       # (self.pd_int_phases[i] <= -self.pd_int_period))
                       ),
                    id_INC.eq(self.pd_int_phases[i] < 0)).Else(
                        id_CE.eq((self.id_mux == i)
                                 & (self.id_inc ^ self.id_dec)),
                        id_INC.eq(self.id_inc))
            ]
            self.specials += DifferentialInput(self.lvds_data_p[i],
                                               self.lvds_data_n[i], lvds_data)
            self.specials += Instance("IODELAY2",
                                      p_SERDES_MODE="MASTER",
                                      p_IDELAY_TYPE="DIFF_PHASE_DETECTOR",
                                      i_IDATAIN=lvds_data,
                                      i_CAL=self.idelay_cal_m,
                                      i_CE=id_CE,
                                      i_INC=id_INC,
                                      o_DATAOUT=lvds_data_m,
                                      **self.idelay_default)
            self.specials += Instance("IODELAY2",
                                      p_SERDES_MODE="SLAVE",
                                      p_IDELAY_TYPE="DIFF_PHASE_DETECTOR",
                                      i_IDATAIN=lvds_data,
                                      i_CAL=self.idelay_cal_s,
                                      i_CE=id_CE,
                                      i_INC=id_INC,
                                      o_DATAOUT=lvds_data_s,
                                      **self.idelay_default)
            cascade_up = Signal()
            cascade_down = Signal()
            tempData = Signal(8)
            pdValid = Signal()
            pdInc = Signal()
            pdAcc = pd_int_accus[i]
            self.specials += Instance(
                "ISERDES2",
                p_SERDES_MODE="MASTER",
                i_D=lvds_data_m,
                i_SHIFTIN=cascade_up,
                o_Q4=tempData[7],
                o_Q3=tempData[6],
                o_Q2=tempData[5],
                o_Q1=tempData[4],
                o_SHIFTOUT=cascade_down,
                # The phase detector outputs
                o_VALID=pdValid,
                o_INCDEC=pdInc,
                **self.iserdes_default)
            # Accumulate increment / decrement pulses
            self.sync.sample += [
                If(
                    pd_int_cnt >= self.pd_int_period,
                    # Latch accumulator value into output registers
                    self.pd_int_phases[i].eq(pdAcc),
                    # Reset accumulators
                    pdAcc.eq(0)).Elif(
                        pdValid & self.initial_tl_done,
                        # Accumulate
                        If(pdInc,
                           pdAcc.eq(pdAcc - 1)).Else(pdAcc.eq(pdAcc + 1)))
            ]
            self.specials += Instance("ISERDES2",
                                      p_SERDES_MODE="SLAVE",
                                      i_D=lvds_data_s,
                                      i_SHIFTIN=cascade_down,
                                      o_Q4=tempData[3],
                                      o_Q3=tempData[2],
                                      o_Q2=tempData[1],
                                      o_Q1=tempData[0],
                                      o_SHIFTOUT=cascade_up,
                                      **self.iserdes_default)
            if MIRROR_BITS:
                self.comb += self.data_outs[i].eq(tempData[::-1])
            else:
                self.comb += self.data_outs[i].eq(tempData)
Exemplo n.º 32
0
    def __init__(self,
                 pads,
                 dummy=15,
                 div=2,
                 with_bitbang=True,
                 endianness="big"):
        """
        Simple SPI flash.
        Supports multi-bit pseudo-parallel reads (aka Dual or Quad I/O Fast
        Read). Only supports mode3 (cpol=1, cpha=1).
        """
        SpiFlashCommon.__init__(self, pads)
        self.bus = bus = wishbone.Interface()
        spi_width = len(pads.dq)
        assert spi_width >= 2

        if with_bitbang:
            self.bitbang = CSRStorage(
                4,
                fields=[
                    CSRField(
                        "mosi",
                        description=
                        "Output value for MOSI pin, valid whenever ``dir`` is ``0``."
                    ),
                    CSRField("clk",
                             description="Output value for SPI CLK pin."),
                    CSRField("cs_n",
                             description="Output value for SPI CSn pin."),
                    CSRField(
                        "dir",
                        description=
                        "Sets the direction for *ALL* SPI data pins except CLK and CSn.",
                        values=[
                            ("0", "OUT", "SPI pins are all output"),
                            ("1", "IN", "SPI pins are all input"),
                        ])
                ],
                description="""
                Bitbang controls for SPI output.  Only standard 1x SPI is supported, and as
                a result all four wires are ganged together.  This means that it is only possible
                to perform half-duplex operations, using this SPI core.
            """)
            self.miso = CSRStatus(description="Incoming value of MISO signal.")
            self.bitbang_en = CSRStorage(
                description=
                "Write a ``1`` here to disable memory-mapped mode and enable bitbang mode."
            )

        # # #

        cs_n = Signal(reset=1)
        clk = Signal()
        dq_oe = Signal()
        wbone_width = len(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

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

        sr = Signal(max(cmd_width, addr_width, wbone_width))
        if endianness == "big":
            self.comb += bus.dat_r.eq(sr)
        else:
            self.comb += bus.dat_r.eq(reverse_bytes(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]),

                # In Dual/Quad mode, no single data pin is consistently
                # an input or output thanks to dual/quad reads, so we need a bit
                # to swap direction of the pins. Aside from this additional bit,
                # bitbang mode is identical for Single/Dual/Quad; dq[0] is mosi
                # and dq[1] is miso, meaning remaining data pin values don't
                # appear in CSR registers.
                If(self.bitbang.storage[3], dq.oe.eq(0)).Else(dq.oe.eq(1)),
                If(
                    self.bitbang.
                    storage[1],  # CPOL=0/CPHA=0 or CPOL=1/CPHA=1 only.
                    self.miso.status.eq(dq.i[1])),
                dq.o.eq(
                    Cat(self.bitbang.storage[0], Replicate(1, spi_width - 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.º 33
0
    def __init__(self, pads, dummy=15, div=2, endianness="big"):
        """
        Simple SPI flash.
        Supports 1-bit reads. Only supports mode0 (cpol=0, cpha=0).
        """
        self.bus = bus = wishbone.Interface()

        # # #

        if hasattr(pads, "wp"):
            self.comb += pads.wp.eq(1)

        if hasattr(pads, "hold"):
            self.comb += pads.hold.eq(1)

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

        read_cmd = _FAST_READ
        cmd_width = 8
        addr_width = 24

        sr = Signal(max(cmd_width, addr_width, wbone_width))
        if endianness == "big":
            self.comb += bus.dat_r.eq(sr)
        else:
            self.comb += bus.dat_r.eq(reverse_bytes(sr))

        self.comb += [
            pads.clk.eq(clk),
            pads.cs_n.eq(cs_n),
            pads.mosi.eq(sr[-1:])
        ]

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

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

        seq = [
            (cmd_width*div,
                [cs_n.eq(0), sr[-cmd_width:].eq(read_cmd)]),
            (addr_width*div,
                [sr[-addr_width:].eq(Cat(z, bus.adr))]),
            ((dummy + wbone_width)*div,
                []),
            (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)
    def __init__(self, pads, dummy=15, div=2, endianness="big"):
        """
        Simple SPI flash.
        Supports multi-bit pseudo-parallel reads (aka Dual or Quad I/O Fast
        Read). Only supports mode0 (cpol=0, cpha=0).
        """
        self.bus = bus = wishbone.Interface()
        spi_width = len(pads.dq)
        assert spi_width >= 2

        # # #

        cs_n = Signal(reset=1)
        clk = Signal()
        dq_oe = Signal()
        wbone_width = len(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

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

        sr = Signal(max(cmd_width, addr_width, wbone_width))
        if endianness == "big":
            self.comb += bus.dat_r.eq(sr)
        else:
            self.comb += bus.dat_r.eq(reverse_bytes(sr))

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

        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.º 35
0
	def __init__(self, pads, cmd=0xfffefeff, cmd_width=32, addr_width=24,
			dummy=15, div=2):
		"""
		Simple read-only 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).

		`cmd` is the read instruction. Since everything is transmitted on all
		dq lines (cmd, adr and data), extend/interleave cmd to full pads.dq
		width even if dq1-dq3 are don't care during the command phase:
		For example, for N25Q128, 0xeb is the quad i/o fast read, and
		extended to 4 bits (dq1,dq2,dq3 high) is: 0xfffefeff
		"""
		self.bus = bus = wishbone.Interface()

		##

		wbone_width = flen(bus.dat_r)
		spi_width = flen(pads.dq)

		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))
		self.comb += [
			bus.dat_r.eq(sr),
			dq.o.eq(sr[-spi_width:]),
		]

		if div == 1:
			i = 0
			self.comb += pads.clk.eq(~ClockSignal())
			self.sync += sr.eq(Cat(dq.i, sr[:-spi_width]))
		else:
			i = Signal(max=div)
			dqi = Signal(spi_width)
			self.sync += [
				If(i == div//2 - 1,
					pads.clk.eq(1),
					dqi.eq(dq.i),
				),
				If(i == div - 1,
					i.eq(0),
					pads.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), pads.cs_n.eq(0), sr[-cmd_width:].eq(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), pads.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.º 36
0
    def __init__(self, a, ba, tRP, tREFI, tRFC):
        self.req = Signal()
        self.ack = Signal()  # 1st command 1 cycle after assertion of ack
        self.cmd = CommandRequest(a, ba)

        ###

        # Refresh sequence generator:
        # PRECHARGE ALL --(tRP)--> AUTO REFRESH --(tRFC)--> done
        seq_start = Signal()
        seq_done = Signal()
        self.sync += [
            self.cmd.a.eq(2**10),
            self.cmd.ba.eq(0),
            self.cmd.cas_n.eq(1),
            self.cmd.ras_n.eq(1),
            self.cmd.we_n.eq(1),
            seq_done.eq(0)
        ]
        self.sync += timeline(seq_start, [
            (1, [
                self.cmd.ras_n.eq(0),
                self.cmd.we_n.eq(0)
            ]),
            (1+tRP, [
                self.cmd.cas_n.eq(0),
                self.cmd.ras_n.eq(0)
            ]),
            (1+tRP+tRFC, [
                seq_done.eq(1)
            ])
        ])

        # Periodic refresh counter
        counter = Signal(max=tREFI)
        start = Signal()
        self.sync += [
            start.eq(0),
            If(counter == 0,
                start.eq(1),
                counter.eq(tREFI - 1)
            ).Else(
                counter.eq(counter - 1)
            )
        ]

        # Control FSM
        fsm = FSM()
        self.submodules += fsm
        fsm.act("IDLE", If(start, NextState("WAIT_GRANT")))
        fsm.act("WAIT_GRANT",
            self.req.eq(1),
            If(self.ack,
                seq_start.eq(1),
                NextState("WAIT_SEQ")
            )
        )
        fsm.act("WAIT_SEQ",
            self.req.eq(1),
            If(seq_done, NextState("IDLE"))
        )
Exemplo n.º 37
0
    def __init__(self, pads, dummy=5, div=2, endianness="big"):
        """
        Simple SPI flash.
        Supports multi-bit pseudo-parallel reads (aka Dual or Quad I/O Fast
        Read). Only supports mode0 (cpol=0, cpha=0).
        """
        self.bus = bus = wishbone.Interface()
        spi_width = len(pads.dq)
        assert spi_width >= 2

        # # #

        cs_n = Signal(reset=1)
        clk = Signal()
        dq_oe = Signal()
        wbone_width = len(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]
        write_cmd_params = {
            4: _format_cmd(_QIOW, 4),
            1: _format_cmd(_WRITE, 1),
        }
        write_cmd = write_cmd_params[spi_width]
        write_stage = Signal()  # 0 during address stage, 1 during write stage
        addr_width = 24

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

        sr = Signal(max(cmd_width, addr_width, wbone_width))
        if endianness == "big":
            self.comb += bus.dat_r.eq(sr)
        else:
            self.comb += bus.dat_r.eq(reverse_bytes(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)
        ]

        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)
            dqo = 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),
                    If(
                        bus.we & write_stage,
                        # If we're writing, reuse the `dat_r` lines
                        # as a temporary buffer to shift out the data.
                        sr.eq(Cat(Signal(spi_width), sr[:-spi_width])),
                    ).Else(sr.eq(Cat(dqi,
                                     sr[:-spi_width])))).Else(i.eq(i + 1), ),
            ]

        # spi is byte-addressed, prefixed by zeroes
        z = Replicate(0, log2_int(wbone_width // 8))
        seq = [
            # Send the `read_cmd` out the port, reusing the
            # Wishbone `rx` line as a temporary buffer
            (cmd_width // spi_width * div,
             [dq_oe.eq(1),
              cs_n.eq(0), sr[-cmd_width:].eq(read_cmd)]),
            # Write the address out the port, again by reusing the
            # Wishbone `rx` line as a temporary buffer
            (addr_width // spi_width * div,
             [sr[-addr_width:].eq(Cat(z, bus.adr))]),
            # Wait for 8 clock cycles for the read to appear
            ((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, rd_tseq = 0, []
        for dt, a in seq:
            rd_tseq.append((t, a))
            t += dt

        addr_stage = Signal()
        seq = [
            # Send the `write_cmd` out the port
            (cmd_width // spi_width * div, [
                dq_oe.eq(1),
                cs_n.eq(0), sr[-cmd_width:].eq(write_cmd),
                write_stage.eq(0),
                addr_stage.eq(0)
            ]),
            # Write the address out the port, again by reusing the
            # Wishbone `rx` line as a temporary buffer
            (addr_width // spi_width * div,
             [sr[-addr_width:].eq(Cat(z, bus.adr)),
              addr_stage.eq(1)]),
            # Immediately write the data out
            (1, [write_stage.eq(1), sr.eq(bus.dat_w)]),
            ((wbone_width // spi_width) * div, []),
            (1, [bus.ack.eq(1), cs_n.eq(1),
                 dq_oe.eq(0)]),
            (
                div,  # tSHSL!
                [
                    bus.ack.eq(0),
                ]),
            (0, []),
        ]

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

        self.sync += [
            timeline(bus.cyc & bus.stb & ~bus.we & (i == div - 1), rd_tseq),
            timeline(bus.cyc & bus.stb & bus.we & (i == div - 1), wr_tseq),
        ]
Exemplo n.º 38
0
    def __init__(self, order=1, mode="pipelined",
                 width=25, coeff_width=18,
                 shift=16, intermediate_width=None):
        Filter.__init__(self, width)
        assert mode in ("pipelined", "iterative")
        if intermediate_width is None:
            intermediate_width = width + coeff_width
            # + bits_for(2*(order + 1))

        self.z0 = CSRStorage(intermediate_width - shift, reset=0)
        self.shift = CSRConstant(shift)
        self.width = CSRConstant(coeff_width)
        self.interval = CSRConstant(0, 8)
        self.latency = CSRConstant(0, 8)
        self.order = CSRConstant(order, 8)
        self.iterative = CSRConstant(mode == "iterative", 1)

        self.c = c = {}
        for i in "ab":
            for j in range(order + 1):
                name = "%s%i" % (i, j)
                if name == "a0":
                    continue
                ci = Signal((coeff_width, True), name=name)
                rci = CSRStorage(len(ci), name=name)
                self.sync += ci.eq(rci.storage)
                c[name] = ci
                setattr(self, "r_" + name, rci)

        ###

        z = Signal((intermediate_width, True), name="z0r")
        self.sync += z.eq(self.z0.storage << shift)

        y_lim = Signal.like(self.y)
        y_next = Signal.like(z)
        y_over = y_next[shift+width-1:]
        y_pat = Signal.like(y_over, reset=-1)
        y = Signal.like(self.y)
        railed = Signal()
        self.comb += [
            railed.eq(~((y_over == y_pat) | (y_over == ~y_pat))),
            If(railed,
                y_lim.eq(self.y)
            ).Else(
                y_lim.eq(y_next[shift:])
            )
        ]
        self.sync += [
            self.error.eq(railed),
            self.y.eq(y_lim),
            If(self.clear,
                y.eq(0)
            ).Elif(~self.hold,
                y.eq(y_lim)
            )
        ]

        if mode == "pipelined":
            r = [("b%i" % i, self.x) for i in reversed(range(order + 1))]
            r += [("a%i" % i, y) for i in reversed(range(1, order + 1))]
            for coeff, signal in r:
                zr = Signal.like(z)
                self.sync += zr.eq(z)
                z = Signal.like(zr)
                self.comb += z.eq(zr + signal*c[coeff])
            self.comb += y_next.eq(z)
            self.latency.value = Constant(order + 1)
            self.interval.value = Constant(1)

        elif mode == "iterative":
            ma = Signal.like(self.y)
            mb = Signal.like(c["a1"])
            mm = Signal.like(z)
            mc = Signal.like(z)
            mp = Signal.like(z)
            self.sync += mm.eq(ma*mb), mc.eq(mp)
            self.comb += mp.eq(mm + mc)
            steps = []
            x = [self.x] + [Signal.like(self.x) for i in range(order + 1)]
            for i in reversed(range(order + 1)):
                steps.append([
                    x[i + 1].eq(x[i]), ma.eq(x[i]), mb.eq(c["b%i" % i])
                ])
            y = [None, y] + [Signal.like(y) for i in range(1, order + 1)]
            for i in reversed(range(1, order + 1)):
                steps.append([
                    y[i + 1].eq(y[i]), ma.eq(y[i]), mb.eq(c["a%i" % i])
                ])
            steps[1].append(mc.eq(z))
            latency = order + 4
            if order == 1:
                steps.append([])
                latency += 1
            self.latency.value = Constant(latency)
            steps[int(order > 1)].append(y_next.eq(mp))
            self.sync += timeline(1, list(enumerate(steps)))
            self.interval.value = Constant(len(steps))

        else:
            raise ValueError
Exemplo n.º 39
0
    def __init__(self, pads):
        """
        MFIO simple core for LiteX
        
        """
        mfioCommon.__init__(self, pads)

        mfio_width = len(pads)
        #
        mfio_o = Signal(mfio_width)
        mfio_oe = Signal(mfio_width)
        mfio_i = Signal(mfio_width)
        # create single pin tristate buffers
        for b in range(mfio_width):
            self.submodules += mfioSinglePin(pads, b, mfio_i[b], mfio_o[b],
                                             mfio_oe[b])

        # Wishbone
        self.bus = bus = wishbone.Interface()

        #
        sel = Signal(mfio_width)
        inbit = Signal(1)

        # todo: dynamic address width calc to optimize the decode logic
        addr_width = 12
        # 1024 IO max
        seladr = Signal(10)

        # 10 bits of address = 1024 pins max
        self.comb += seladr.eq(self.bus.adr[:10])

        # address decoder
        for b in range(mfio_width):
            self.comb += sel[b].eq(seladr == b)

        self.comb += inbit.eq((mfio_i & sel) != 0)

        # Read bit
        rdbus = Signal(32)
        self.comb += [rdbus[0].eq(inbit), bus.dat_r.eq(rdbus)]

        # process output
        outbit = Signal(1)
        oebit = Signal(1)
        wren = Signal(1)

        # PINAPI 1.0 compatible: 0 = drive 0, 1 drive 1, 3 = HiZ
        self.comb += outbit.eq(bus.dat_w[0])
        self.comb += oebit.eq(~bus.dat_w[1])

        # write enable
        self.comb += wren.eq(self.bus.stb & self.bus.cyc & self.bus.we)

        for b in range(mfio_width):
            self.sync += If(wren & sel[b], mfio_o[b].eq(outbit),
                            mfio_oe[b].eq(oebit))

        seq = [
            (1, [bus.ack.eq(1)]),  #
            (1, [bus.ack.eq(0)]),  #
            (0, []),
        ]

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

        self.sync += timeline(bus.cyc & bus.stb, tseq)