Пример #1
0
    def __init__(self, fifo, asynchronous=False, auto_flush=True):
        _FIFOInterface.__init__(self, fifo.width, fifo.depth)

        self.submodules.fifo = fifo

        self.dout = fifo.dout
        self.re = fifo.re
        self.readable = fifo.readable
        self.din = fifo.din
        self.we = fifo.we
        self.writable = fifo.writable

        self.flush = Signal(reset=auto_flush)
        if asynchronous:
            self._flush_s = Signal()
            self.specials += MultiReg(self.flush,
                                      self._flush_s,
                                      reset=auto_flush)
        else:
            self._flush_s = self.flush

        self.flushed = Signal()
        self.queued = Signal()
        self._pending = Signal()
        self.sync += [
            If(self.flushed, self._pending.eq(0)).Elif(self.readable & self.re,
                                                       self._pending.eq(1)),
            self.queued.eq(self._flush_s & self._pending)
        ]
Пример #2
0
    def __init__(self, fifo, overflow_depth=2):
        _FIFOInterface.__init__(self, fifo.width, fifo.depth)

        self.submodules.fifo = fifo
        self.submodules.overflow = overflow = SyncFIFO(fifo.width,
                                                       overflow_depth)

        self.dout = fifo.dout
        self.re = fifo.re
        self.readable = fifo.readable

        ###

        self.comb += [
            If(overflow.readable, fifo.din.eq(overflow.dout), fifo.we.eq(1),
               overflow.re.eq(fifo.writable)),
            If(fifo.writable & ~overflow.readable, fifo.din.eq(self.din),
               fifo.we.eq(self.we), self.writable.eq(fifo.writable)).Else(
                   overflow.din.eq(self.din), overflow.we.eq(self.we),
                   self.writable.eq(overflow.writable))
        ]
Пример #3
0
    def __init__(self, sdram, clk_out, clk_sample,
                 databits, rowbits, colbits, bankbits,
                 inbuf, outbuf, burst,
                 tRESET, tCL, tRP, tRFC, tRCD, tREFI):
        _FIFOInterface.__init__(self, databits, None)

        addrbits = rowbits + colbits + bankbits
        assert sdram.dq.nbits == databits
        colabits = colbits if colbits <= 10 else colbits + 1
        max_col = Replicate(1, colbits)
        assert sdram.a.nbits >= colabits
        assert sdram.a.nbits >= rowbits
        assert sdram.ba.nbits == bankbits
        dqmbits = max(databits // 8, 1)
        assert sdram.dqm.nbits == dqmbits
        assert burst <= 1<<colbits

        # DQ handling, tristate, and sampling
        dq = TSTriple(databits)
        self.specials += dq.get_tristate(sdram.dq)
        dq_r = Signal(databits)
        self.clock_domains.cd_sample = ClockDomain(reset_less=True)
        self.comb += self.cd_sample.clk.eq(clk_sample)
        self.sync.sample += dq_r.eq(dq.i)

        # Signals used for driving SDRAM control signals
        # These are not registers, they are functions of the current FSM state.
        # However, the reset state actually determines the default value for
        # states where they are not explicitly assigned. For example, cmd is
        # INHIBIT at reset (because the FSM is in RESET state at reset and that
        # sets cmd to INHIBIT), but it's NOP for every other state where it
        # isn't assigned.
        cmd = Signal(4, reset=NOP)
        dqm = Signal()
        ba = Signal(bankbits)
        a = Signal(max(colabits, rowbits))
        cke = Signal()
        self.comb += [
            sdram.dqm.eq(Replicate(dqm, dqmbits)),
            sdram.cs_n.eq(cmd[3]),
            sdram.ras_n.eq(cmd[2]),
            sdram.cas_n.eq(cmd[1]),
            sdram.we_n.eq(cmd[0]),
            sdram.clk.eq(clk_out),
            sdram.ba.eq(ba),
            sdram.a.eq(a),
            sdram.cke.eq(cke),
        ]

        # Counter to time reset cycle of the SDRAM
        # We enable CKE on the first cycle after system reset, then wait tRESET
        reset_ctr = Signal(max=tRESET+1)
        self.sync += [
            cke.eq(1),
            reset_ctr.eq(reset_ctr + 1)
        ]

        # Counter to time refresh intervals
        # Note that this can go higher than tREFI, since we might be in the
        # middle of a burst, but long-term refresh cycles will be issued often
        # enough to meet refresh timing.
        refresh_interval = tREFI - 2  # A bit of leeway for safety
        refresh_ctr = Signal(max=(refresh_interval + 2*burst + 128))
        self.sync += If(cmd == AUTO_REFRESH,
                        If(refresh_ctr > refresh_interval,
                           refresh_ctr.eq(refresh_ctr - refresh_interval)
                        ).Else(
                           refresh_ctr.eq(0))
                     ).Else(
                        refresh_ctr.eq(refresh_ctr + 1))

        tMRD = 3  # JEDEC spec, Micron only needs 2
        # Mode: Full page burst mode, burst write
        mode = 0b0000000111 | (tCL << 4)

        # FIFOs
        fifo_in = RenameClockDomains(AsyncFIFO(databits, inbuf),
                                     {"read": "sys"})
        fifo_out = RenameClockDomains(AsyncFIFO(databits, outbuf),
                                      {"write": "sys"})
        self.submodules += [fifo_in, fifo_out]
        self.comb += [
            # Wire up FIFO ports to module interface
            self.writable.eq(fifo_in.writable),
            fifo_in.din.eq(self.din_bits),
            fifo_in.we.eq(self.we),
            self.readable.eq(fifo_out.readable),
            fifo_out.re.eq(self.re),
            self.dout_bits.eq(fifo_out.dout),
        ]

        # short circuit FIFOs for testing
        #self.comb += [
            #fifo_out.din.eq(fifo_in.dout),
            #fifo_out.we.eq(fifo_in.readable),
            #fifo_in.re.eq(fifo_out.writable),
        #]

        # SDRAM FIFO pointer regs
        write_ptr = Signal(addrbits)
        read_ptr = Signal(addrbits)
        read_ptr_shadow = Signal(addrbits)

        def delay_clocks(v, d):
            for i in range(d):
                n = Signal()
                self.sync += n.eq(v)
                v = n
            return v

        # Read cycle state signals
        issuing_read = Signal()
        # Reads come back tCL clocks later
        returning_read = delay_clocks(issuing_read, tCL)
        can_read = Signal()
        can_continue_read = Signal()
        kill_read = Signal()
        self.comb += [
            can_read.eq((write_ptr != read_ptr) & fifo_out.writable),
            can_continue_read.eq((write_ptr != read_ptr_shadow + 1) &
                                 fifo_out.writable &
                                 (read_ptr_shadow[:colbits] != max_col) &
                                 ~kill_read),

            fifo_out.din.eq(dq_r),
            fifo_out.we.eq(returning_read & ~kill_read),
        ]
        self.sync += [
            # Increment read pointer when data is written to output FIFO
            If(fifo_out.we & fifo_out.writable,
               read_ptr.eq(read_ptr + 1)),
            # Keep a shadow read pointer for issuing reads. Increment it
            # while a read is being issued, but reset it to the true read
            # otherwise (which might be different if a read was killed).
            If(~issuing_read,
               read_ptr_shadow.eq(read_ptr),
            ).Else(
               read_ptr_shadow.eq(read_ptr_shadow + 1),
            ),
            # If the output FIFO becomes full, kill the current read
            If(returning_read & ~fifo_out.writable,
               kill_read.eq(1)
            ).Elif(~returning_read,
               kill_read.eq(0)
            ),
        ]

        # Write state signals
        issuing_write = Signal()
        can_write = Signal()
        can_continue_write = Signal()
        self.comb += [
            can_write.eq((write_ptr + 1 != read_ptr) & fifo_in.readable),
            can_continue_write.eq((write_ptr + 2 != read_ptr) &
                                  fifo_in.readable &
                                  (write_ptr[:colbits] != max_col)),

            dq.o.eq(fifo_in.dout),
            dq.oe.eq(issuing_write),
            fifo_in.re.eq(issuing_write),
        ]
        self.sync += [
            # Increment write pointer when data is read from input FIFO
            If(fifo_in.re & fifo_in.readable,
               write_ptr.eq(write_ptr + 1)),
        ]

        # Address generation
        def split(addr):
            col = addr[:colbits]
            if colbits > 10:
                col = Cat(col[:10],0,col[10:])
            return col, addr[colbits:colbits+rowbits], addr[colbits+rowbits:]

        r_col, r_row, r_bank = split(read_ptr)
        w_col, w_row, w_bank = split(write_ptr)

        # Finite state machine driving the controller
        fsm = self.submodules.fsm = FSM(reset_state="RESET")

        # Initialization sequence
        fsm.act("RESET",
                cmd.eq(INHIBIT),
                If(reset_ctr == tRESET, NextState("INIT_IDLE")))
        fsm.delayed_enter("INIT_IDLE", "INIT_PRECHARGE", 5)
        fsm.act("INIT_PRECHARGE", cmd.eq(PRECHARGE), a[10].eq(1))
        fsm.delayed_enter("INIT_PRECHARGE", "INIT_REFRESH1", tRP)
        fsm.act("INIT_REFRESH1", cmd.eq(AUTO_REFRESH))
        fsm.delayed_enter("INIT_REFRESH1", "INIT_REFRESH2", tRFC)
        fsm.act("INIT_REFRESH2", cmd.eq(AUTO_REFRESH))
        fsm.delayed_enter("INIT_REFRESH2", "INIT_MODE", tRFC)
        fsm.act("INIT_MODE", cmd.eq(LOAD_MODE), a.eq(mode))
        fsm.delayed_enter("INIT_MODE", "IDLE", tMRD)

        # Main loop
        fsm.act("IDLE", If(refresh_ctr >= refresh_interval,
                           NextState("REFRESH")
                        ).Elif(can_write,
                           NextState("WRITE_ACTIVE")
                        ).Elif(can_read,
                           NextState("READ_ACTIVE")
                        ))
        # REFRESH
        fsm.act("REFRESH", cmd.eq(AUTO_REFRESH))
        fsm.delayed_enter("REFRESH", "IDLE", tRFC)

        # WRITE
        fsm.act("WRITE_ACTIVE", cmd.eq(ACTIVE), ba.eq(w_bank), a.eq(w_row))
        fsm.delayed_enter("WRITE_ACTIVE", "WRITE", tRCD)
        fsm.act("WRITE", cmd.eq(WRITE), ba.eq(w_bank), a.eq(w_col),
                issuing_write.eq(1), dqm.eq(~fifo_in.readable),
                If(can_continue_write,
                   NextState("WRITING")
                ).Else(
                   If(can_read,
                      NextState("PRECHARGE_AND_READ")
                   ).Else(
                      NextState("PRECHARGE")
                   )))
        fsm.act("WRITING", issuing_write.eq(1), dqm.eq(~fifo_in.readable),
                If(~can_continue_write,
                   If(can_read,
                      NextState("PRECHARGE_AND_READ")
                   ).Else(
                      NextState("PRECHARGE")
                   )))
        fsm.act("PRECHARGE_AND_READ", cmd.eq(PRECHARGE), a[10].eq(1)),
        fsm.delayed_enter("PRECHARGE_AND_READ", "READ_ACTIVE", tRP)

        # READ
        fsm.act("READ_ACTIVE", cmd.eq(ACTIVE), ba.eq(r_bank), a.eq(r_row))
        fsm.delayed_enter("READ_ACTIVE", "READ", tRCD)
        fsm.act("READ", cmd.eq(READ), ba.eq(r_bank), a.eq(r_col),
                issuing_read.eq(1),
                If(can_continue_read,
                   NextState("READING")
                ).Else(
                   NextState("PRECHARGE")))
        fsm.act("READING", issuing_read.eq(1),
                If(~can_continue_read,
                   NextState("PRECHARGE")))
        fsm.act("PRECHARGE", cmd.eq(PRECHARGE), a[10].eq(1)),
        fsm.delayed_enter("PRECHARGE", "IDLE", tRP)
Пример #4
0
    def __init__(
        self,
        sdram,
        clk_out,
        clk_sample,
        databits,
        rowbits,
        colbits,
        bankbits,
        inbuf,
        outbuf,
        burst,
        tRESET,
        tCL,
        tRP,
        tRFC,
        tRCD,
        tREFI,
    ):
        _FIFOInterface.__init__(self, databits, None)

        addrbits = rowbits + colbits + bankbits
        assert sdram.dq.nbits == databits
        colabits = colbits if colbits <= 10 else colbits + 1
        max_col = Replicate(1, colbits)
        assert sdram.a.nbits >= colabits
        assert sdram.a.nbits >= rowbits
        assert sdram.ba.nbits == bankbits
        dqmbits = max(databits // 8, 1)
        assert sdram.dqm.nbits == dqmbits
        assert burst <= 1 << colbits

        # DQ handling, tristate, and sampling
        dq = TSTriple(databits)
        self.specials += dq.get_tristate(sdram.dq)
        dq_r = Signal(databits)
        self.clock_domains.cd_sample = ClockDomain(reset_less=True)
        self.comb += self.cd_sample.clk.eq(clk_sample)
        self.sync.sample += dq_r.eq(dq.i)

        # Signals used for driving SDRAM control signals
        # These are not registers, they are functions of the current FSM state.
        # However, the reset state actually determines the default value for
        # states where they are not explicitly assigned. For example, cmd is
        # INHIBIT at reset (because the FSM is in RESET state at reset and that
        # sets cmd to INHIBIT), but it's NOP for every other state where it
        # isn't assigned.
        cmd = Signal(4, reset=NOP)
        dqm = Signal()
        ba = Signal(bankbits)
        a = Signal(max(colabits, rowbits))
        cke = Signal()
        self.comb += [
            sdram.dqm.eq(Replicate(dqm, dqmbits)),
            sdram.cs_n.eq(cmd[3]),
            sdram.ras_n.eq(cmd[2]),
            sdram.cas_n.eq(cmd[1]),
            sdram.we_n.eq(cmd[0]),
            sdram.clk.eq(clk_out),
            sdram.ba.eq(ba),
            sdram.a.eq(a),
            sdram.cke.eq(cke),
        ]

        # Counter to time reset cycle of the SDRAM
        # We enable CKE on the first cycle after system reset, then wait tRESET
        reset_ctr = Signal(max=tRESET + 1)
        self.sync += [cke.eq(1), reset_ctr.eq(reset_ctr + 1)]

        # Counter to time refresh intervals
        # Note that this can go higher than tREFI, since we might be in the
        # middle of a burst, but long-term refresh cycles will be issued often
        # enough to meet refresh timing.
        refresh_interval = tREFI - 2  # A bit of leeway for safety
        refresh_ctr = Signal(max=(refresh_interval + 2 * burst + 128))
        self.sync += If(
            cmd == AUTO_REFRESH,
            If(refresh_ctr > refresh_interval, refresh_ctr.eq(refresh_ctr - refresh_interval)).Else(refresh_ctr.eq(0)),
        ).Else(refresh_ctr.eq(refresh_ctr + 1))

        tMRD = 3  # JEDEC spec, Micron only needs 2
        # Mode: Full page burst mode, burst write
        mode = 0b0000000111 | (tCL << 4)

        # FIFOs
        fifo_in = RenameClockDomains(AsyncFIFO(databits, inbuf), {"read": "sys"})
        fifo_out = RenameClockDomains(AsyncFIFO(databits, outbuf), {"write": "sys"})
        self.submodules += [fifo_in, fifo_out]
        self.comb += [
            # Wire up FIFO ports to module interface
            self.writable.eq(fifo_in.writable),
            fifo_in.din.eq(self.din_bits),
            fifo_in.we.eq(self.we),
            self.readable.eq(fifo_out.readable),
            fifo_out.re.eq(self.re),
            self.dout_bits.eq(fifo_out.dout),
        ]

        # short circuit FIFOs for testing
        # self.comb += [
        # fifo_out.din.eq(fifo_in.dout),
        # fifo_out.we.eq(fifo_in.readable),
        # fifo_in.re.eq(fifo_out.writable),
        # ]

        # SDRAM FIFO pointer regs
        write_ptr = Signal(addrbits)
        read_ptr = Signal(addrbits)
        read_ptr_shadow = Signal(addrbits)

        def delay_clocks(v, d):
            for i in range(d):
                n = Signal()
                self.sync += n.eq(v)
                v = n
            return v

        # Read cycle state signals
        issuing_read = Signal()
        # Reads come back tCL clocks later
        returning_read = delay_clocks(issuing_read, tCL)
        can_read = Signal()
        can_continue_read = Signal()
        kill_read = Signal()
        self.comb += [
            can_read.eq((write_ptr != read_ptr) & fifo_out.writable),
            can_continue_read.eq(
                (write_ptr != read_ptr_shadow + 1)
                & fifo_out.writable
                & (read_ptr_shadow[:colbits] != max_col)
                & ~kill_read
            ),
            fifo_out.din.eq(dq_r),
            fifo_out.we.eq(returning_read & ~kill_read),
        ]
        self.sync += [
            # Increment read pointer when data is written to output FIFO
            If(fifo_out.we & fifo_out.writable, read_ptr.eq(read_ptr + 1)),
            # Keep a shadow read pointer for issuing reads. Increment it
            # while a read is being issued, but reset it to the true read
            # otherwise (which might be different if a read was killed).
            If(~issuing_read, read_ptr_shadow.eq(read_ptr)).Else(read_ptr_shadow.eq(read_ptr_shadow + 1)),
            # If the output FIFO becomes full, kill the current read
            If(returning_read & ~fifo_out.writable, kill_read.eq(1)).Elif(~returning_read, kill_read.eq(0)),
        ]

        # Write state signals
        issuing_write = Signal()
        can_write = Signal()
        can_continue_write = Signal()
        self.comb += [
            can_write.eq((write_ptr + 1 != read_ptr) & fifo_in.readable),
            can_continue_write.eq((write_ptr + 2 != read_ptr) & fifo_in.readable & (write_ptr[:colbits] != max_col)),
            dq.o.eq(fifo_in.dout),
            dq.oe.eq(issuing_write),
            fifo_in.re.eq(issuing_write),
        ]
        self.sync += [
            # Increment write pointer when data is read from input FIFO
            If(fifo_in.re & fifo_in.readable, write_ptr.eq(write_ptr + 1))
        ]

        # Address generation
        def split(addr):
            col = addr[:colbits]
            if colbits > 10:
                col = Cat(col[:10], 0, col[10:])
            return col, addr[colbits : colbits + rowbits], addr[colbits + rowbits :]

        r_col, r_row, r_bank = split(read_ptr)
        w_col, w_row, w_bank = split(write_ptr)

        # Finite state machine driving the controller
        fsm = self.submodules.fsm = FSM(reset_state="RESET")

        # Initialization sequence
        fsm.act("RESET", cmd.eq(INHIBIT), If(reset_ctr == tRESET, NextState("INIT_IDLE")))
        fsm.delayed_enter("INIT_IDLE", "INIT_PRECHARGE", 5)
        fsm.act("INIT_PRECHARGE", cmd.eq(PRECHARGE), a[10].eq(1))
        fsm.delayed_enter("INIT_PRECHARGE", "INIT_REFRESH1", tRP)
        fsm.act("INIT_REFRESH1", cmd.eq(AUTO_REFRESH))
        fsm.delayed_enter("INIT_REFRESH1", "INIT_REFRESH2", tRFC)
        fsm.act("INIT_REFRESH2", cmd.eq(AUTO_REFRESH))
        fsm.delayed_enter("INIT_REFRESH2", "INIT_MODE", tRFC)
        fsm.act("INIT_MODE", cmd.eq(LOAD_MODE), a.eq(mode))
        fsm.delayed_enter("INIT_MODE", "IDLE", tMRD)

        # Main loop
        fsm.act(
            "IDLE",
            If(refresh_ctr >= refresh_interval, NextState("REFRESH"))
            .Elif(can_write, NextState("WRITE_ACTIVE"))
            .Elif(can_read, NextState("READ_ACTIVE")),
        )
        # REFRESH
        fsm.act("REFRESH", cmd.eq(AUTO_REFRESH))
        fsm.delayed_enter("REFRESH", "IDLE", tRFC)

        # WRITE
        fsm.act("WRITE_ACTIVE", cmd.eq(ACTIVE), ba.eq(w_bank), a.eq(w_row))
        fsm.delayed_enter("WRITE_ACTIVE", "WRITE", tRCD)
        fsm.act(
            "WRITE",
            cmd.eq(WRITE),
            ba.eq(w_bank),
            a.eq(w_col),
            issuing_write.eq(1),
            dqm.eq(~fifo_in.readable),
            If(can_continue_write, NextState("WRITING")).Else(
                If(can_read, NextState("PRECHARGE_AND_READ")).Else(NextState("PRECHARGE"))
            ),
        )
        fsm.act(
            "WRITING",
            issuing_write.eq(1),
            dqm.eq(~fifo_in.readable),
            If(~can_continue_write, If(can_read, NextState("PRECHARGE_AND_READ")).Else(NextState("PRECHARGE"))),
        )
        fsm.act("PRECHARGE_AND_READ", cmd.eq(PRECHARGE), a[10].eq(1)),
        fsm.delayed_enter("PRECHARGE_AND_READ", "READ_ACTIVE", tRP)

        # READ
        fsm.act("READ_ACTIVE", cmd.eq(ACTIVE), ba.eq(r_bank), a.eq(r_row))
        fsm.delayed_enter("READ_ACTIVE", "READ", tRCD)
        fsm.act(
            "READ",
            cmd.eq(READ),
            ba.eq(r_bank),
            a.eq(r_col),
            issuing_read.eq(1),
            If(can_continue_read, NextState("READING")).Else(NextState("PRECHARGE")),
        )
        fsm.act("READING", issuing_read.eq(1), If(~can_continue_read, NextState("PRECHARGE")))
        fsm.act("PRECHARGE", cmd.eq(PRECHARGE), a[10].eq(1)),
        fsm.delayed_enter("PRECHARGE", "IDLE", tRP)