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) ]
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)) ]
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)
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)