예제 #1
0
파일: ulpi.py 프로젝트: zozo123/ov_ftdi
	def __init__(self, ulpi_reg):
		
		ReadAddress = Signal(6)
		
		write_fsm = FSM()
		self.submodules += write_fsm
		
		def delay_clocks(v, d):
			for i in range(d):
				n = Signal()
				self.sync += n.eq(v)
				v = n
			return v
		
		ulpi_reg_wack = delay_clocks(ulpi_reg.wack, 2)
		ulpi_reg_rack = delay_clocks(ulpi_reg.rack, 2)
		
		write_fsm.delayed_enter("RESET", "WRITE_HS_SNOOP", 16)

		write_fsm.act("WRITE_HS_SNOOP",
			ulpi_reg.waddr.eq(0x4),
			ulpi_reg.wdata.eq(0x48),
			ulpi_reg.wreq.eq(1),
			If(ulpi_reg_wack, NextState("WRITE_IDLE")))
		
		write_fsm.act("WRITE_IDLE",
			ulpi_reg.wreq.eq(0))
		
		read_fsm = FSM()
		self.submodules += read_fsm

		read_fsm.delayed_enter("RESET", "READ_REG", 16)
		
		read_fsm.act("READ_REG",
			ulpi_reg.raddr.eq(ReadAddress),
			ulpi_reg.rreq.eq(1),
			If(ulpi_reg_rack, NextState("READ_ACK")))
		
		self.sync += If(ulpi_reg_rack & ulpi_reg.rreq, ReadAddress.eq(ReadAddress + 1))
		
		read_fsm.act("READ_ACK",
			ulpi_reg.rreq.eq(0),
			If(~ulpi_reg_rack, NextState("READ_WAIT")))
		
		read_fsm.delayed_enter("READ_WAIT", "READ_REG", 16)
예제 #2
0
파일: ulpi.py 프로젝트: openvizsla/ov_ftdi
	def __init__(self, ulpi_reg):
		
		ReadAddress = Signal(6)
		
		write_fsm = FSM()
		self.submodules += write_fsm
		
		def delay_clocks(v, d):
			for i in range(d):
				n = Signal()
				self.sync += n.eq(v)
				v = n
			return v
		
		ulpi_reg_wack = delay_clocks(ulpi_reg.wack, 2)
		ulpi_reg_rack = delay_clocks(ulpi_reg.rack, 2)
		
		write_fsm.delayed_enter("RESET", "WRITE_HS_SNOOP", 16)

		write_fsm.act("WRITE_HS_SNOOP",
			ulpi_reg.waddr.eq(0x4),
			ulpi_reg.wdata.eq(0x48),
			ulpi_reg.wreq.eq(1),
			If(ulpi_reg_wack, NextState("WRITE_IDLE")))
		
		write_fsm.act("WRITE_IDLE",
			ulpi_reg.wreq.eq(0))
		
		read_fsm = FSM()
		self.submodules += read_fsm

		read_fsm.delayed_enter("RESET", "READ_REG", 16)
		
		read_fsm.act("READ_REG",
			ulpi_reg.raddr.eq(ReadAddress),
			ulpi_reg.rreq.eq(1),
			If(ulpi_reg_rack, NextState("READ_ACK")))
		
		self.sync += If(ulpi_reg_rack & ulpi_reg.rreq, ReadAddress.eq(ReadAddress + 1))
		
		read_fsm.act("READ_ACK",
			ulpi_reg.rreq.eq(0),
			If(~ulpi_reg_rack, NextState("READ_WAIT")))
		
		read_fsm.delayed_enter("READ_WAIT", "READ_REG", 16)
예제 #3
0
파일: multiplexer.py 프로젝트: RP7/misoc
	def __init__(self, phy_settings, geom_settings, timing_settings, bank_machines, refresher, dfi, lasmic):
		assert(phy_settings.nphases == len(dfi.phases))
	
		# Command choosing
		requests = [bm.cmd for bm in bank_machines]
		choose_cmd = _CommandChooser(requests)
		choose_req = _CommandChooser(requests)
		self.comb += [
			choose_cmd.want_reads.eq(0),
			choose_cmd.want_writes.eq(0)
		]
		if phy_settings.nphases == 1:
			self.comb += [
				choose_cmd.want_cmds.eq(1),
				choose_req.want_cmds.eq(1)
			]	
		self.submodules += choose_cmd, choose_req
		
		# Command steering
		nop = CommandRequest(geom_settings.mux_a, geom_settings.bank_a)
		commands = [nop, choose_cmd.cmd, choose_req.cmd, refresher.cmd] # nop must be 1st
		(STEER_NOP, STEER_CMD, STEER_REQ, STEER_REFRESH) = range(4)
		steerer = _Steerer(commands, dfi)
		self.submodules += steerer
		
		# Read/write turnaround
		read_available = Signal()
		write_available = Signal()
		self.comb += [
			read_available.eq(optree("|", [req.stb & req.is_read for req in requests])),
			write_available.eq(optree("|", [req.stb & req.is_write for req in requests]))
		]
		
		def anti_starvation(timeout):
			en = Signal()
			max_time = Signal()
			if timeout:
				t = timeout - 1
				time = Signal(max=t+1)
				self.comb += max_time.eq(time == 0)
				self.sync += If(~en,
						time.eq(t)
					).Elif(~max_time,
						time.eq(time - 1)
					)
			else:
				self.comb += max_time.eq(0)
			return en, max_time
		read_time_en, max_read_time = anti_starvation(timing_settings.read_time)
		write_time_en, max_write_time = anti_starvation(timing_settings.write_time)
		
		# Refresh
		self.comb += [bm.refresh_req.eq(refresher.req) for bm in bank_machines]
		go_to_refresh = Signal()
		self.comb += go_to_refresh.eq(optree("&", [bm.refresh_gnt for bm in bank_machines]))
		
		# Datapath
		all_rddata = [p.rddata for p in dfi.phases]
		all_wrdata = [p.wrdata for p in dfi.phases]
		all_wrdata_mask = [p.wrdata_mask for p in dfi.phases]
		self.comb += [
			lasmic.dat_r.eq(Cat(*all_rddata)),
			Cat(*all_wrdata).eq(lasmic.dat_w),
			Cat(*all_wrdata_mask).eq(~lasmic.dat_we)
		]
		
		# Control FSM
		fsm = FSM()
		self.submodules += fsm
		
		def steerer_sel(steerer, phy_settings, r_w_n):
			r = []
			for i in range(phy_settings.nphases):
				s = steerer.sel[i].eq(STEER_NOP)
				if r_w_n == "read":
					if i == phy_settings.rdphase:
						s = steerer.sel[i].eq(STEER_REQ)
					elif i == phy_settings.rdcmdphase:
						s = steerer.sel[i].eq(STEER_CMD)
				elif r_w_n == "write":
					if i == phy_settings.wrphase:
						s = steerer.sel[i].eq(STEER_REQ)
					elif i == phy_settings.wrcmdphase:
						s = steerer.sel[i].eq(STEER_CMD)
				else:
					raise ValueError
				r.append(s)
			return r

		fsm.act("READ",
			read_time_en.eq(1),
			choose_req.want_reads.eq(1),
			choose_cmd.cmd.ack.eq(1),
			choose_req.cmd.ack.eq(1),
			steerer_sel(steerer, phy_settings, "read"),
			If(write_available,
				# TODO: switch only after several cycles of ~read_available?
				If(~read_available | max_read_time, NextState("RTW"))
			),
			If(go_to_refresh, NextState("REFRESH"))
		)
		fsm.act("WRITE",
			write_time_en.eq(1),
			choose_req.want_writes.eq(1),
			choose_cmd.cmd.ack.eq(1),
			choose_req.cmd.ack.eq(1),
			steerer_sel(steerer, phy_settings, "write"),
			If(read_available,
				If(~write_available | max_write_time, NextState("WTR"))
			),
			If(go_to_refresh, NextState("REFRESH"))
		)
		fsm.act("REFRESH",
			steerer.sel[0].eq(STEER_REFRESH),
			If(~refresher.req, NextState("READ"))
		)
		fsm.delayed_enter("RTW", "WRITE", phy_settings.read_latency-1) # FIXME: reduce this, actual limit is around (cl+1)/nphases
		fsm.delayed_enter("WTR", "READ", timing_settings.tWTR-1)
		# FIXME: workaround for zero-delay loop simulation problem with Icarus Verilog
		fsm.finalize()
		self.comb += refresher.ack.eq(fsm.state == fsm.encoding["REFRESH"])

		self.submodules.bandwidth = Bandwidth(choose_req.cmd)
예제 #4
0
파일: bankmachine.py 프로젝트: RP7/misoc
    def __init__(self, geom_settings, timing_settings, address_align, bankn, req):
        self.refresh_req = Signal()
        self.refresh_gnt = Signal()
        self.cmd = CommandRequestRW(geom_settings.mux_a, geom_settings.bank_a)

        ###

        # Request FIFO
        self.submodules.req_fifo = SyncFIFO([("we", 1), ("adr", flen(req.adr))], timing_settings.req_queue_size)
        self.comb += [
            self.req_fifo.din.we.eq(req.we),
            self.req_fifo.din.adr.eq(req.adr),
            self.req_fifo.we.eq(req.stb),
            req.req_ack.eq(self.req_fifo.writable),
            self.req_fifo.re.eq(req.dat_ack),
            req.lock.eq(self.req_fifo.readable),
        ]
        reqf = self.req_fifo.dout

        slicer = _AddressSlicer(geom_settings.col_a, address_align)

        # Row tracking
        has_openrow = Signal()
        openrow = Signal(geom_settings.row_a)
        hit = Signal()
        self.comb += hit.eq(openrow == slicer.row(reqf.adr))
        track_open = Signal()
        track_close = Signal()
        self.sync += [
            If(track_open, has_openrow.eq(1), openrow.eq(slicer.row(reqf.adr))),
            If(track_close, has_openrow.eq(0)),
        ]

        # Address generation
        s_row_adr = Signal()
        self.comb += [
            self.cmd.ba.eq(bankn),
            If(s_row_adr, self.cmd.a.eq(slicer.row(reqf.adr))).Else(self.cmd.a.eq(slicer.col(reqf.adr))),
        ]

        # Respect write-to-precharge specification
        precharge_ok = Signal()
        t_unsafe_precharge = 2 + timing_settings.tWR - 1
        unsafe_precharge_count = Signal(max=t_unsafe_precharge + 1)
        self.comb += precharge_ok.eq(unsafe_precharge_count == 0)
        self.sync += [
            If(self.cmd.stb & self.cmd.ack & self.cmd.is_write, unsafe_precharge_count.eq(t_unsafe_precharge)).Elif(
                ~precharge_ok, unsafe_precharge_count.eq(unsafe_precharge_count - 1)
            )
        ]

        # Control and command generation FSM
        fsm = FSM()
        self.submodules += fsm
        fsm.act(
            "REGULAR",
            If(self.refresh_req, NextState("REFRESH")).Elif(
                self.req_fifo.readable,
                If(
                    has_openrow,
                    If(
                        hit,
                        # NB: write-to-read specification is enforced by multiplexer
                        self.cmd.stb.eq(1),
                        req.dat_ack.eq(self.cmd.ack),
                        self.cmd.is_read.eq(~reqf.we),
                        self.cmd.is_write.eq(reqf.we),
                        self.cmd.cas_n.eq(0),
                        self.cmd.we_n.eq(~reqf.we),
                    ).Else(NextState("PRECHARGE")),
                ).Else(NextState("ACTIVATE")),
            ),
        )
        fsm.act(
            "PRECHARGE",
            # Notes:
            # 1. we are presenting the column address, A10 is always low
            # 2. since we always go to the ACTIVATE state, we do not need
            # to assert track_close.
            If(
                precharge_ok,
                self.cmd.stb.eq(1),
                If(self.cmd.ack, NextState("TRP")),
                self.cmd.ras_n.eq(0),
                self.cmd.we_n.eq(0),
                self.cmd.is_cmd.eq(1),
            ),
        )
        fsm.act(
            "ACTIVATE",
            s_row_adr.eq(1),
            track_open.eq(1),
            self.cmd.stb.eq(1),
            self.cmd.is_cmd.eq(1),
            If(self.cmd.ack, NextState("TRCD")),
            self.cmd.ras_n.eq(0),
        )
        fsm.act(
            "REFRESH",
            self.refresh_gnt.eq(precharge_ok),
            track_close.eq(1),
            self.cmd.is_cmd.eq(1),
            If(~self.refresh_req, NextState("REGULAR")),
        )
        fsm.delayed_enter("TRP", "ACTIVATE", timing_settings.tRP - 1)
        fsm.delayed_enter("TRCD", "REGULAR", timing_settings.tRCD - 1)
예제 #5
0
	def __init__(self, cachesize, lasmim):
		self.wishbone = wishbone.Interface()

		###

		data_width = flen(self.wishbone.dat_r)
		if lasmim.dw > data_width and (lasmim.dw % data_width) != 0:
			raise ValueError("LASMI data width must be a multiple of {dw}".format(dw=data_width))
		if lasmim.dw < data_width and (data_width % lasmim.dw) != 0:
			raise ValueError("WISHBONE data width must be a multiple of {dw}".format(dw=lasmim.dw))

		# Split address:
		# TAG | LINE NUMBER | LINE OFFSET
		offsetbits = log2_int(max(lasmim.dw//data_width, 1))
		addressbits = lasmim.aw + offsetbits
		linebits = log2_int(cachesize) - offsetbits
		tagbits = addressbits - linebits
		wordbits = data_width//lasmim.dw
		adr_offset, adr_line, adr_tag = split(self.wishbone.adr, offsetbits, linebits, tagbits)
		word = Signal(wordbits) if wordbits else None
		
		# Data memory
		data_mem = Memory(lasmim.dw*2**wordbits, 2**linebits)
		data_port = data_mem.get_port(write_capable=True, we_granularity=8)
		self.specials += data_mem, data_port
		
		write_from_lasmi = Signal()
		write_to_lasmi = Signal()
		if adr_offset is None:
			adr_offset_r = None
		else:
			adr_offset_r = Signal(offsetbits)
			self.sync += adr_offset_r.eq(adr_offset)

		self.comb += [
			data_port.adr.eq(adr_line),
			If(write_from_lasmi,
				displacer(lasmim.dat_r, word, data_port.dat_w),
				displacer(Replicate(1, lasmim.dw//8), word, data_port.we)
			).Else(
				data_port.dat_w.eq(Replicate(self.wishbone.dat_w, max(lasmim.dw//data_width, 1))),
				If(self.wishbone.cyc & self.wishbone.stb & self.wishbone.we & self.wishbone.ack,
					displacer(self.wishbone.sel, adr_offset, data_port.we, 2**offsetbits, reverse=True)
				)
			),
			If(write_to_lasmi, 
				chooser(data_port.dat_r, word, lasmim.dat_w),
				lasmim.dat_we.eq(2**(lasmim.dw//8)-1)
			),
			chooser(data_port.dat_r, adr_offset_r, self.wishbone.dat_r, reverse=True)
		]

		
		# Tag memory
		tag_layout = [("tag", tagbits), ("dirty", 1)]
		tag_mem = Memory(layout_len(tag_layout), 2**linebits)
		tag_port = tag_mem.get_port(write_capable=True)
		self.specials += tag_mem, tag_port
		tag_do = Record(tag_layout)
		tag_di = Record(tag_layout)
		self.comb += [
			tag_do.raw_bits().eq(tag_port.dat_r),
			tag_port.dat_w.eq(tag_di.raw_bits())
		]
			
		self.comb += [
			tag_port.adr.eq(adr_line),
			tag_di.tag.eq(adr_tag)
		]
		if word is not None:
			self.comb += lasmim.adr.eq(Cat(word, adr_line, tag_do.tag))
		else:
			self.comb += lasmim.adr.eq(Cat(adr_line, tag_do.tag))		
			
		# Lasmim word computation, word_clr and word_inc will be simplified
		# at synthesis when wordbits=0
		word_clr = Signal()
		word_inc = Signal()
		if word is not None:
			self.sync += \
				If(word_clr,
					word.eq(0),
				).Elif(word_inc,
					word.eq(word+1)
				)

		def word_is_last(word):
			if word is not None:
				return word == 2**wordbits-1
			else:
				return 1

		# Control FSM
		assert(lasmim.write_latency >= 1 and lasmim.read_latency >= 1)
		fsm = FSM(reset_state="IDLE")
		self.submodules += fsm
		
		fsm.delayed_enter("EVICT_DATAD", "EVICT_DATA", lasmim.write_latency-1)
		fsm.delayed_enter("REFILL_DATAD", "REFILL_DATA", lasmim.read_latency-1)

		fsm.act("IDLE",
			If(self.wishbone.cyc & self.wishbone.stb, NextState("TEST_HIT"))
		)
		fsm.act("TEST_HIT",
			word_clr.eq(1),
			If(tag_do.tag == adr_tag,
				self.wishbone.ack.eq(1),
				If(self.wishbone.we,
					tag_di.dirty.eq(1),
					tag_port.we.eq(1)
				),
				NextState("IDLE")
			).Else(
				If(tag_do.dirty,
					NextState("EVICT_REQUEST")
				).Else(
					NextState("REFILL_WRTAG")
				)
			)
		)
		
		fsm.act("EVICT_REQUEST",
			lasmim.stb.eq(1),
			lasmim.we.eq(1),
			If(lasmim.req_ack, NextState("EVICT_WAIT_DATA_ACK"))
		)
		fsm.act("EVICT_WAIT_DATA_ACK",
			If(lasmim.dat_ack, NextState("EVICT_DATAD"))
		)
		fsm.act("EVICT_DATA",
			write_to_lasmi.eq(1),
			word_inc.eq(1),
			If(word_is_last(word),
				NextState("REFILL_WRTAG"),
			).Else(
				NextState("EVICT_REQUEST")
			)
		)
		
		fsm.act("REFILL_WRTAG",
			# Write the tag first to set the LASMI address
			tag_port.we.eq(1),
			word_clr.eq(1),
			NextState("REFILL_REQUEST")
		)
		fsm.act("REFILL_REQUEST",
			lasmim.stb.eq(1),
			If(lasmim.req_ack, NextState("REFILL_WAIT_DATA_ACK"))
		)
		fsm.act("REFILL_WAIT_DATA_ACK",
			If(lasmim.dat_ack, NextState("REFILL_DATAD"))
		)
		fsm.act("REFILL_DATA",
			write_from_lasmi.eq(1),
			word_inc.eq(1),
			If(word_is_last(word),
				NextState("TEST_HIT"),
			).Else(
				NextState("REFILL_REQUEST")
			)
		)
예제 #6
0
    def __init__(self, cachesize, lasmim):
        self.wishbone = wishbone.Interface()

        ###

        data_width = flen(self.wishbone.dat_r)
        if lasmim.dw > data_width and (lasmim.dw % data_width) != 0:
            raise ValueError(
                "LASMI data width must be a multiple of {dw}".format(
                    dw=data_width))
        if lasmim.dw < data_width and (data_width % lasmim.dw) != 0:
            raise ValueError(
                "WISHBONE data width must be a multiple of {dw}".format(
                    dw=lasmim.dw))

        # Split address:
        # TAG | LINE NUMBER | LINE OFFSET
        offsetbits = log2_int(max(lasmim.dw // data_width, 1))
        addressbits = lasmim.aw + offsetbits
        linebits = log2_int(cachesize) - offsetbits
        tagbits = addressbits - linebits
        wordbits = log2_int(max(data_width // lasmim.dw, 1))
        adr_offset, adr_line, adr_tag = split(self.wishbone.adr, offsetbits,
                                              linebits, tagbits)
        word = Signal(wordbits) if wordbits else None

        # Data memory
        data_mem = Memory(lasmim.dw * 2**wordbits, 2**linebits)
        data_port = data_mem.get_port(write_capable=True, we_granularity=8)
        self.specials += data_mem, data_port

        write_from_lasmi = Signal()
        write_to_lasmi = Signal()
        if adr_offset is None:
            adr_offset_r = None
        else:
            adr_offset_r = Signal(offsetbits)
            self.sync += adr_offset_r.eq(adr_offset)

        self.comb += [
            data_port.adr.eq(adr_line),
            If(write_from_lasmi, displacer(lasmim.dat_r, word,
                                           data_port.dat_w),
               displacer(Replicate(1, lasmim.dw // 8), word,
                         data_port.we)).Else(
                             data_port.dat_w.eq(
                                 Replicate(self.wishbone.dat_w,
                                           max(lasmim.dw // data_width, 1))),
                             If(
                                 self.wishbone.cyc & self.wishbone.stb
                                 & self.wishbone.we & self.wishbone.ack,
                                 displacer(self.wishbone.sel,
                                           adr_offset,
                                           data_port.we,
                                           2**offsetbits,
                                           reverse=True))),
            If(write_to_lasmi, chooser(data_port.dat_r, word, lasmim.dat_w),
               lasmim.dat_we.eq(2**(lasmim.dw // 8) - 1)),
            chooser(data_port.dat_r,
                    adr_offset_r,
                    self.wishbone.dat_r,
                    reverse=True)
        ]

        # Tag memory
        tag_layout = [("tag", tagbits), ("dirty", 1)]
        tag_mem = Memory(layout_len(tag_layout), 2**linebits)
        tag_port = tag_mem.get_port(write_capable=True)
        self.specials += tag_mem, tag_port
        tag_do = Record(tag_layout)
        tag_di = Record(tag_layout)
        self.comb += [
            tag_do.raw_bits().eq(tag_port.dat_r),
            tag_port.dat_w.eq(tag_di.raw_bits())
        ]

        self.comb += [tag_port.adr.eq(adr_line), tag_di.tag.eq(adr_tag)]
        if word is not None:
            self.comb += lasmim.adr.eq(Cat(word, adr_line, tag_do.tag))
        else:
            self.comb += lasmim.adr.eq(Cat(adr_line, tag_do.tag))

        # Lasmim word computation, word_clr and word_inc will be simplified
        # at synthesis when wordbits=0
        word_clr = Signal()
        word_inc = Signal()
        if word is not None:
            self.sync += \
             If(word_clr,
              word.eq(0),
             ).Elif(word_inc,
              word.eq(word+1)
             )

        def word_is_last(word):
            if word is not None:
                return word == 2**wordbits - 1
            else:
                return 1

        # Control FSM
        assert (lasmim.write_latency >= 1 and lasmim.read_latency >= 1)
        fsm = FSM(reset_state="IDLE")
        self.submodules += fsm

        fsm.delayed_enter("EVICT_DATAD", "EVICT_DATA",
                          lasmim.write_latency - 1)
        fsm.delayed_enter("REFILL_DATAD", "REFILL_DATA",
                          lasmim.read_latency - 1)

        fsm.act(
            "IDLE",
            If(self.wishbone.cyc & self.wishbone.stb, NextState("TEST_HIT")))
        fsm.act(
            "TEST_HIT", word_clr.eq(1),
            If(tag_do.tag == adr_tag, self.wishbone.ack.eq(1),
               If(self.wishbone.we, tag_di.dirty.eq(1), tag_port.we.eq(1)),
               NextState("IDLE")).Else(
                   If(tag_do.dirty, NextState("EVICT_REQUEST")).Else(
                       NextState("REFILL_WRTAG"))))

        fsm.act("EVICT_REQUEST", lasmim.stb.eq(1), lasmim.we.eq(1),
                If(lasmim.req_ack, NextState("EVICT_WAIT_DATA_ACK")))
        fsm.act("EVICT_WAIT_DATA_ACK",
                If(lasmim.dat_ack, NextState("EVICT_DATAD")))
        fsm.act(
            "EVICT_DATA", write_to_lasmi.eq(1), word_inc.eq(1),
            If(
                word_is_last(word),
                NextState("REFILL_WRTAG"),
            ).Else(NextState("EVICT_REQUEST")))

        fsm.act(
            "REFILL_WRTAG",
            # Write the tag first to set the LASMI address
            tag_port.we.eq(1),
            word_clr.eq(1),
            NextState("REFILL_REQUEST"))
        fsm.act("REFILL_REQUEST", lasmim.stb.eq(1),
                If(lasmim.req_ack, NextState("REFILL_WAIT_DATA_ACK")))
        fsm.act("REFILL_WAIT_DATA_ACK",
                If(lasmim.dat_ack, NextState("REFILL_DATAD")))
        fsm.act(
            "REFILL_DATA", write_from_lasmi.eq(1), word_inc.eq(1),
            If(
                word_is_last(word),
                NextState("TEST_HIT"),
            ).Else(NextState("REFILL_REQUEST")))
예제 #7
0
    def __init__(self, geom_settings, timing_settings, controller_settings,
                 address_align, bankn, req):
        self.refresh_req = Signal()
        self.refresh_gnt = Signal()
        self.cmd = CommandRequestRW(geom_settings.addressbits,
                                    geom_settings.bankbits)

        ###

        # Request FIFO
        layout = [("we", 1), ("adr", len(req.adr))]
        req_in = Record(layout)
        reqf = Record(layout)
        self.submodules.req_fifo = SyncFIFO(layout_len(layout),
                                            controller_settings.req_queue_size)
        self.comb += [
            self.req_fifo.din.eq(req_in.raw_bits()),
            reqf.raw_bits().eq(self.req_fifo.dout)
        ]
        self.comb += [
            req_in.we.eq(req.we),
            req_in.adr.eq(req.adr),
            self.req_fifo.we.eq(req.stb),
            req.req_ack.eq(self.req_fifo.writable),
            self.req_fifo.re.eq(req.dat_w_ack | req.dat_r_ack),
            req.lock.eq(self.req_fifo.readable)
        ]

        slicer = _AddressSlicer(geom_settings.colbits, address_align)

        # Row tracking
        has_openrow = Signal()
        openrow = Signal(geom_settings.rowbits)
        hit = Signal()
        self.comb += hit.eq(openrow == slicer.row(reqf.adr))
        track_open = Signal()
        track_close = Signal()
        self.sync += [
            If(track_open, has_openrow.eq(1),
               openrow.eq(slicer.row(reqf.adr))),
            If(track_close, has_openrow.eq(0))
        ]

        # Address generation
        s_row_adr = Signal()
        self.comb += [
            self.cmd.ba.eq(bankn),
            If(s_row_adr, self.cmd.a.eq(slicer.row(reqf.adr))).Else(
                self.cmd.a.eq(slicer.col(reqf.adr)))
        ]

        # Respect write-to-precharge specification
        precharge_ok = Signal()
        t_unsafe_precharge = 2 + timing_settings.tWR - 1
        unsafe_precharge_count = Signal(max=t_unsafe_precharge + 1)
        self.comb += precharge_ok.eq(unsafe_precharge_count == 0)
        self.sync += [
            If(self.cmd.stb & self.cmd.ack & self.cmd.is_write,
               unsafe_precharge_count.eq(t_unsafe_precharge)).Elif(
                   ~precharge_ok,
                   unsafe_precharge_count.eq(unsafe_precharge_count - 1))
        ]

        # Control and command generation FSM
        fsm = FSM()
        self.submodules += fsm
        fsm.act(
            "REGULAR",
            If(self.refresh_req, NextState("REFRESH")).Elif(
                self.req_fifo.readable,
                If(
                    has_openrow,
                    If(
                        hit,
                        # NB: write-to-read specification is enforced by multiplexer
                        self.cmd.stb.eq(1),
                        req.dat_w_ack.eq(self.cmd.ack & reqf.we),
                        req.dat_r_ack.eq(self.cmd.ack & ~reqf.we),
                        self.cmd.is_read.eq(~reqf.we),
                        self.cmd.is_write.eq(reqf.we),
                        self.cmd.cas_n.eq(0),
                        self.cmd.we_n.eq(~reqf.we)).Else(
                            NextState("PRECHARGE"))).Else(
                                NextState("ACTIVATE"))))
        fsm.act(
            "PRECHARGE",
            # Notes:
            # 1. we are presenting the column address, A10 is always low
            # 2. since we always go to the ACTIVATE state, we do not need
            # to assert track_close.
            If(precharge_ok, self.cmd.stb.eq(1),
               If(self.cmd.ack, NextState("TRP")), self.cmd.ras_n.eq(0),
               self.cmd.we_n.eq(0), self.cmd.is_cmd.eq(1)))
        fsm.act("ACTIVATE", s_row_adr.eq(1), track_open.eq(1),
                self.cmd.stb.eq(1), self.cmd.is_cmd.eq(1),
                If(self.cmd.ack, NextState("TRCD")), self.cmd.ras_n.eq(0))
        fsm.act("REFRESH", self.refresh_gnt.eq(precharge_ok),
                track_close.eq(1), self.cmd.is_cmd.eq(1),
                If(~self.refresh_req, NextState("REGULAR")))
        fsm.delayed_enter("TRP", "ACTIVATE", timing_settings.tRP - 1)
        fsm.delayed_enter("TRCD", "REGULAR", timing_settings.tRCD - 1)
예제 #8
0
파일: __init__.py 프로젝트: benyjsun/misoc
	def __init__(self, phy_settings, geom_settings, timing_settings):
		if phy_settings.memtype in ["SDR"]:
			burst_length = phy_settings.nphases*1 # command multiplication*SDR
		elif phy_settings.memtype in ["DDR", "LPDDR", "DDR2", "DDR3"]:
			burst_length = phy_settings.nphases*2 # command multiplication*DDR
		address_align = log2_int(burst_length)

		nbanks = range(2**geom_settings.bank_a)
		A10_ENABLED = 0
		COLUMN      = 1
		ROW         = 2
		rdphase = phy_settings.rdphase
		wrphase = phy_settings.wrphase

		self.dfi = dfi = dfibus.Interface(geom_settings.mux_a,
			geom_settings.bank_a,
			phy_settings.dfi_d,
			phy_settings.nphases)

		self.bus = bus = wishbone.Interface(data_width=phy_settings.nphases*flen(dfi.phases[rdphase].rddata))
		slicer = _AddressSlicer(geom_settings.col_a, geom_settings.bank_a, geom_settings.row_a, address_align)
		refresh_req = Signal()
		refresh_ack = Signal()
		refresh_counter = Signal(max=timing_settings.tREFI+1)
		hit = Signal()
		row_open = Signal()
		row_closeall = Signal()
		addr_sel = Signal(max=3, reset=A10_ENABLED)
		has_curbank_openrow = Signal()

		# Extra bit means row is active when asserted
		self.openrow = openrow = Array(Signal(geom_settings.row_a + 1) for b in nbanks)

		self.comb += [
			hit.eq(openrow[slicer.bank(bus.adr)] == Cat(slicer.row(bus.adr), 1)),
			has_curbank_openrow.eq(openrow[slicer.bank(bus.adr)][-1]),
			bus.dat_r.eq(Cat(phase.rddata for phase in dfi.phases)),
			Cat(phase.wrdata for phase in dfi.phases).eq(bus.dat_w),
			Cat(phase.wrdata_mask for phase in dfi.phases).eq(~bus.sel),
		]

		for phase in dfi.phases:
			self.comb += [
				phase.cke.eq(1),
				phase.cs_n.eq(0),
				phase.address.eq(Array([2**10, slicer.col(bus.adr), slicer.row(bus.adr)])[addr_sel]),
				phase.bank.eq(slicer.bank(bus.adr))
			]

		for b in nbanks:
			self.sync += [
				If(row_open & (b == slicer.bank(bus.adr)),
					openrow[b].eq(Cat(slicer.row(bus.adr), 1)),
				),
				If(row_closeall,
					openrow[b][-1].eq(0)
				)
			]

		self.sync += [
			If(refresh_ack,
				refresh_req.eq(0)
			),
			If(refresh_counter == 0,
				refresh_counter.eq(timing_settings.tREFI),
				refresh_req.eq(1)
			).Else(
				refresh_counter.eq(refresh_counter - 1)
			)
		]

		fsm = FSM()
		self.submodules += fsm
		fsm.act("IDLE",
			If(refresh_req,
				NextState("PRECHARGEALL")
			).Elif(bus.stb & bus.cyc,
				If(hit & bus.we,
					NextState("WRITE")
				),
				If(hit & ~bus.we,
					NextState("READ")
				),
				If(has_curbank_openrow & ~hit,
					NextState("PRECHARGE")
				),
				If(~has_curbank_openrow,
					NextState("ACTIVATE")
				),
			)
		)
		fsm.act("READ",
			# We output Column bits at address pins so A10 is 0
			# to disable row Auto-Precharge
			dfi.phases[rdphase].ras_n.eq(1),
			dfi.phases[rdphase].cas_n.eq(0),
			dfi.phases[rdphase].we_n.eq(1),
			dfi.phases[rdphase].rddata_en.eq(1),
			addr_sel.eq(COLUMN),
			NextState("READ-WAIT-ACK"),
		)
		fsm.act("READ-WAIT-ACK",
			If(dfi.phases[rdphase].rddata_valid,
				NextState("IDLE"),
				bus.ack.eq(1)
			).Else(
				NextState("READ-WAIT-ACK")
			)
		)
		fsm.act("WRITE",
			dfi.phases[wrphase].ras_n.eq(1),
			dfi.phases[wrphase].cas_n.eq(0),
			dfi.phases[wrphase].we_n.eq(0),
			dfi.phases[wrphase].wrdata_en.eq(1),
			addr_sel.eq(COLUMN),
			bus.ack.eq(1),
			NextState("IDLE")
		)
		fsm.act("PRECHARGEALL",
			row_closeall.eq(1),
			dfi.phases[rdphase].ras_n.eq(0),
			dfi.phases[rdphase].cas_n.eq(1),
			dfi.phases[rdphase].we_n.eq(0),
			addr_sel.eq(A10_ENABLED),
			NextState("PRE-REFRESH")
		)
		fsm.act("PRECHARGE",
			# Notes:
			# 1. we are presenting the column address so that A10 is low
			# 2. since we always go to the ACTIVATE state, we do not need
			# to assert row_close because it will be reopen right after.
			NextState("TRP"),
			addr_sel.eq(COLUMN),
			dfi.phases[rdphase].ras_n.eq(0),
			dfi.phases[rdphase].cas_n.eq(1),
			dfi.phases[rdphase].we_n.eq(0)
		)
		fsm.act("ACTIVATE",
			row_open.eq(1),
			NextState("TRCD"),
			dfi.phases[rdphase].ras_n.eq(0),
			dfi.phases[rdphase].cas_n.eq(1),
			dfi.phases[rdphase].we_n.eq(1),
			addr_sel.eq(ROW)
		)
		fsm.act("REFRESH",
			refresh_ack.eq(1),
			dfi.phases[rdphase].ras_n.eq(0),
			dfi.phases[rdphase].cas_n.eq(0),
			dfi.phases[rdphase].we_n.eq(1),
			NextState("POST-REFRESH")
		)
		fsm.delayed_enter("TRP", "ACTIVATE", timing_settings.tRP-1)
		fsm.delayed_enter("PRE-REFRESH", "REFRESH", timing_settings.tRP-1)
		fsm.delayed_enter("TRCD", "IDLE", timing_settings.tRCD-1)
		fsm.delayed_enter("POST-REFRESH", "IDLE", timing_settings.tRFC-1)
예제 #9
0
    def __init__(self, phy_settings, geom_settings, timing_settings, controller_settings, bank_machines, refresher, dfi, lasmic):
        assert(phy_settings.nphases == len(dfi.phases))
        self.phy_settings = phy_settings

        # Command choosing
        requests = [bm.cmd for bm in bank_machines]
        self.submodules.choose_cmd = choose_cmd = _CommandChooser(requests)
        self.submodules.choose_req = choose_req = _CommandChooser(requests)
        self.comb += [
            choose_cmd.want_reads.eq(0),
            choose_cmd.want_writes.eq(0)
        ]
        if phy_settings.nphases == 1:
            self.comb += [
                choose_cmd.want_cmds.eq(1),
                choose_req.want_cmds.eq(1)
            ]

        # Command steering
        nop = CommandRequest(geom_settings.addressbits, geom_settings.bankbits)
        commands = [nop, choose_cmd.cmd, choose_req.cmd, refresher.cmd]  # nop must be 1st
        (STEER_NOP, STEER_CMD, STEER_REQ, STEER_REFRESH) = range(4)
        steerer = _Steerer(commands, dfi)
        self.submodules += steerer

        # Read/write turnaround
        read_available = Signal()
        write_available = Signal()
        self.comb += [
            read_available.eq(reduce(or_, [req.stb & req.is_read for req in requests])),
            write_available.eq(reduce(or_, [req.stb & req.is_write for req in requests]))
        ]

        def anti_starvation(timeout):
            en = Signal()
            max_time = Signal()
            if timeout:
                t = timeout - 1
                time = Signal(max=t+1)
                self.comb += max_time.eq(time == 0)
                self.sync += If(~en,
                        time.eq(t)
                    ).Elif(~max_time,
                        time.eq(time - 1)
                    )
            else:
                self.comb += max_time.eq(0)
            return en, max_time
        read_time_en, max_read_time = anti_starvation(controller_settings.read_time)
        write_time_en, max_write_time = anti_starvation(controller_settings.write_time)

        # Refresh
        self.comb += [bm.refresh_req.eq(refresher.req) for bm in bank_machines]
        go_to_refresh = Signal()
        self.comb += go_to_refresh.eq(reduce(and_, [bm.refresh_gnt for bm in bank_machines]))

        # Datapath
        all_rddata = [p.rddata for p in dfi.phases]
        all_wrdata = [p.wrdata for p in dfi.phases]
        all_wrdata_mask = [p.wrdata_mask for p in dfi.phases]
        self.comb += [
            lasmic.dat_r.eq(Cat(*all_rddata)),
            Cat(*all_wrdata).eq(lasmic.dat_w),
            Cat(*all_wrdata_mask).eq(~lasmic.dat_we)
        ]

        # Control FSM
        fsm = FSM()
        self.submodules += fsm

        def steerer_sel(steerer, phy_settings, r_w_n):
            r = []
            for i in range(phy_settings.nphases):
                s = steerer.sel[i].eq(STEER_NOP)
                if r_w_n == "read":
                    if i == phy_settings.rdphase:
                        s = steerer.sel[i].eq(STEER_REQ)
                    elif i == phy_settings.rdcmdphase:
                        s = steerer.sel[i].eq(STEER_CMD)
                elif r_w_n == "write":
                    if i == phy_settings.wrphase:
                        s = steerer.sel[i].eq(STEER_REQ)
                    elif i == phy_settings.wrcmdphase:
                        s = steerer.sel[i].eq(STEER_CMD)
                else:
                    raise ValueError
                r.append(s)
            return r

        fsm.act("READ",
            read_time_en.eq(1),
            choose_req.want_reads.eq(1),
            choose_cmd.cmd.ack.eq(1),
            choose_req.cmd.ack.eq(1),
            steerer_sel(steerer, phy_settings, "read"),
            If(write_available,
                # TODO: switch only after several cycles of ~read_available?
                If(~read_available | max_read_time, NextState("RTW"))
            ),
            If(go_to_refresh, NextState("REFRESH"))
        )
        fsm.act("WRITE",
            write_time_en.eq(1),
            choose_req.want_writes.eq(1),
            choose_cmd.cmd.ack.eq(1),
            choose_req.cmd.ack.eq(1),
            steerer_sel(steerer, phy_settings, "write"),
            If(read_available,
                If(~write_available | max_write_time, NextState("WTR"))
            ),
            If(go_to_refresh, NextState("REFRESH"))
        )
        fsm.act("REFRESH",
            steerer.sel[0].eq(STEER_REFRESH),
            refresher.ack.eq(1),
            If(~refresher.req, NextState("READ"))
        )
        fsm.delayed_enter("RTW", "WRITE", phy_settings.read_latency-1)  # FIXME: reduce this, actual limit is around (cl+1)/nphases
        fsm.delayed_enter("WTR", "READ", timing_settings.tWTR-1)
예제 #10
0
	def __init__(self, cachesize, lasmim, wbm=None):
		if wbm is None:
			wbm = wishbone.Interface()
		self.wishbone = wbm

		###

		data_width = flen(self.wishbone.dat_r)
		if lasmim.dw < data_width:
			raise ValueError("LASMI data width must be >= {dw}".format(dw=data_width))
		if (lasmim.dw % data_width) != 0:
			raise ValueError("LASMI data width must be a multiple of {dw}".format(dw=data_width))

		# Split address:
		# TAG | LINE NUMBER | LINE OFFSET
		offsetbits = log2_int(lasmim.dw//data_width)
		addressbits = lasmim.aw + offsetbits
		linebits = log2_int(cachesize) - offsetbits
		tagbits = addressbits - linebits
		adr_offset, adr_line, adr_tag = split(self.wishbone.adr, offsetbits, linebits, tagbits)
		
		# Data memory
		data_mem = Memory(lasmim.dw, 2**linebits)
		data_port = data_mem.get_port(write_capable=True, we_granularity=8)
		self.specials += data_mem, data_port
		
		write_from_lasmi = Signal()
		write_to_lasmi = Signal()
		if adr_offset is None:
			adr_offset_r = None
		else:
			adr_offset_r = Signal(offsetbits)
			self.sync += adr_offset_r.eq(adr_offset)

		self.comb += [
			data_port.adr.eq(adr_line),
			If(write_from_lasmi,
				data_port.dat_w.eq(lasmim.dat_r),
				data_port.we.eq(Replicate(1, lasmim.dw//8))
			).Else(
				data_port.dat_w.eq(Replicate(self.wishbone.dat_w, lasmim.dw//data_width)),
				If(self.wishbone.cyc & self.wishbone.stb & self.wishbone.we & self.wishbone.ack,
					displacer(self.wishbone.sel, adr_offset, data_port.we, 2**offsetbits, reverse=True)
				)
			),
			If(write_to_lasmi, 
				lasmim.dat_w.eq(data_port.dat_r),
				lasmim.dat_we.eq(2**(lasmim.dw//8)-1)
			),
			chooser(data_port.dat_r, adr_offset_r, self.wishbone.dat_r, reverse=True)
		]

		
		# Tag memory
		tag_layout = [("tag", tagbits), ("dirty", 1)]
		tag_mem = Memory(layout_len(tag_layout), 2**linebits)
		tag_port = tag_mem.get_port(write_capable=True)
		self.specials += tag_mem, tag_port
		tag_do = Record(tag_layout)
		tag_di = Record(tag_layout)
		self.comb += [
			tag_do.raw_bits().eq(tag_port.dat_r),
			tag_port.dat_w.eq(tag_di.raw_bits())
		]
			
		self.comb += [
			tag_port.adr.eq(adr_line),
			tag_di.tag.eq(adr_tag),
			lasmim.adr.eq(Cat(adr_line, tag_do.tag))
		]
		
		# Control FSM
		assert(lasmim.write_latency >= 1 and lasmim.read_latency >= 1)
		fsm = FSM()
		self.submodules += fsm
		
		fsm.delayed_enter("EVICT_DATAD", "EVICT_DATA", lasmim.write_latency-1)
		fsm.delayed_enter("REFILL_DATAD", "REFILL_DATA", lasmim.read_latency-1)

		fsm.act("IDLE",
			If(self.wishbone.cyc & self.wishbone.stb, NextState("TEST_HIT"))
		)
		fsm.act("TEST_HIT",
			If(tag_do.tag == adr_tag,
				self.wishbone.ack.eq(1),
				If(self.wishbone.we,
					tag_di.dirty.eq(1),
					tag_port.we.eq(1)
				),
				NextState("IDLE")
			).Else(
				If(tag_do.dirty,
					NextState("EVICT_REQUEST")
				).Else(
					NextState("REFILL_WRTAG")
				)
			)
		)
		
		fsm.act("EVICT_REQUEST",
			lasmim.stb.eq(1),
			lasmim.we.eq(1),
			If(lasmim.req_ack, NextState("EVICT_WAIT_DATA_ACK"))
		)
		fsm.act("EVICT_WAIT_DATA_ACK",
			If(lasmim.dat_ack, NextState("EVICT_DATAD"))
		)
		fsm.act("EVICT_DATA",
			write_to_lasmi.eq(1),
			NextState("REFILL_WRTAG")
		)
		
		fsm.act("REFILL_WRTAG",
			# Write the tag first to set the LASMI address
			tag_port.we.eq(1),
			NextState("REFILL_REQUEST")
		)
		fsm.act("REFILL_REQUEST",
			lasmim.stb.eq(1),
			If(lasmim.req_ack, NextState("REFILL_WAIT_DATA_ACK"))
		)
		fsm.act("REFILL_WAIT_DATA_ACK",
			If(lasmim.dat_ack, NextState("REFILL_DATAD"))
		)
		fsm.act("REFILL_DATA",
			write_from_lasmi.eq(1),
			NextState("TEST_HIT")
		)