Example #1
0
File: fsm.py Project: Jwomers/migen
def implement_fsm(states):
	stnames = ["S" + str(i) for i in range(len(states))]
	fsm = FSM(*stnames)
	lans = _LowerAbstractNextState(fsm, states, stnames)
	for i, state in enumerate(states):
		actions = lans.visit(state)
		fsm.act(getattr(fsm, stnames[i]), *actions)
	return fsm
Example #2
0
	def __init__(self, cycle_bits, data_bits, extra_fsm_states=[]):
		self.cycle_bits = cycle_bits
		self.data_bits = data_bits
		
		# I/O signals
		self.d = Signal()
		self.clk = Signal()
		
		# control signals
		self.pds = Signal()
		self.pdi = Signal(self.data_bits)
		
		self.clk_high = Signal()
		self.clk_low = Signal()
		
		self.eoc = Signal()
		self.ev_clk_high = Signal()
		self.ev_clk_low = Signal()
		self.ev_data = Signal()
		
		# FSM
		fsm_states = ["WAIT_DATA", "TRANSFER_DATA"] + extra_fsm_states
		self.fsm = FSM(*fsm_states)
		self.start_action = [self.fsm.next_state(self.fsm.TRANSFER_DATA)]
		self.end_action = [self.fsm.next_state(self.fsm.WAIT_DATA)]
		
		# registers
		self._pos_end_cycle = RegisterField("pos_end_cycle", self.cycle_bits, reset=20)
		self._pos_data = RegisterField("pos_data", self.cycle_bits, reset=0)
Example #3
0
from migen.fhdl.structure import *
from migen.fhdl import verilog
from migen.corelogic.fsm import FSM

s = Signal()
myfsm = FSM("FOO", "BAR")
myfsm.act(myfsm.FOO, s.eq(1), myfsm.next_state(myfsm.BAR))
myfsm.act(myfsm.BAR, s.eq(0), myfsm.next_state(myfsm.FOO))
print(verilog.convert(myfsm.get_fragment(), {s}))
Example #4
0
	def get_fragment(self):
		comb = []
		sync = []
		
		aaw = self.asmiport.hub.aw
		adw = self.asmiport.hub.dw
		
		# Split address:
		# TAG | LINE NUMBER | LINE OFFSET
		offsetbits = _log2_int(adw//32)
		addressbits = aaw + offsetbits
		linebits = _log2_int(self.cachesize) - offsetbits
		tagbits = aaw - linebits
		adr_offset, adr_line, adr_tag = split(self.wishbone.adr, offsetbits, linebits, tagbits)
		
		# Data memory
		data_adr = Signal(BV(linebits))
		data_do = Signal(BV(adw))
		data_di = Signal(BV(adw))
		data_we = Signal(BV(adw//8))
		data_port = MemoryPort(data_adr, data_do, data_we, data_di, we_granularity=8)
		data_mem = Memory(adw, 2**linebits, data_port)
		
		write_from_asmi = Signal()
		write_to_asmi = Signal()
		adr_offset_r = Signal(BV(offsetbits))
		comb += [
			data_adr.eq(adr_line),
			If(write_from_asmi,
				data_di.eq(self.asmiport.dat_r),
				data_we.eq(Replicate(1, adw//8))
			).Else(
				data_di.eq(Replicate(self.wishbone.dat_w, adw//32)),
				If(self.wishbone.cyc & self.wishbone.stb & self.wishbone.we & self.wishbone.ack,
					displacer(self.wishbone.sel, adr_offset, data_we, 2**offsetbits, reverse=True)
				)
			),
			If(write_to_asmi,
				self.asmiport.dat_w.eq(data_do),
				self.asmiport.dat_wm.eq(Replicate(1, adw//8))
			),
			chooser(data_do, adr_offset_r, self.wishbone.dat_r, reverse=True)
		]
		sync += [
			adr_offset_r.eq(adr_offset)
		]
		
		# Tag memory
		tag_layout = [("tag", BV(linebits)), ("dirty", BV(1))]
		tag_do = Record(tag_layout)
		tag_do_raw = tag_do.to_signal(comb, False)
		tag_di = Record(tag_layout)
		tag_di_raw = tag_di.to_signal(comb, True)
		
		tag_adr = Signal(BV(linebits))
		tag_we = Signal()
		tag_port = MemoryPort(tag_adr, tag_do_raw, tag_we, tag_di_raw)
		tag_mem = Memory(tagbits+1, 2**linebits, tag_port)
		
		comb += [
			tag_adr.eq(adr_line),
			tag_di.tag.eq(adr_tag),
			self.asmiport.adr.eq(Cat(adr_line, tag_do.tag))
		]
		
		# Control FSM
		write_to_asmi_pre = Signal()
		sync.append(write_to_asmi.eq(write_to_asmi_pre))
		
		fsm = FSM("IDLE", "TEST_HIT",
			"EVICT_ISSUE", "EVICT_WAIT",
			"REFILL_WRTAG", "REFILL_ISSUE", "REFILL_WAIT", "REFILL_COMPLETE")
		
		fsm.act(fsm.IDLE,
			If(self.wishbone.cyc & self.wishbone.stb, fsm.next_state(fsm.TEST_HIT))
		)
		fsm.act(fsm.TEST_HIT,
			If(tag_do.tag == adr_tag,
				self.wishbone.ack.eq(1),
				If(self.wishbone.we,
					tag_di.dirty.eq(1),
					tag_we.eq(1)
				),
				fsm.next_state(fsm.IDLE)
			).Else(
				If(tag_do.dirty,
					fsm.next_state(fsm.EVICT_ISSUE)
				).Else(
					fsm.next_state(fsm.REFILL_WRTAG)
				)
			)
		)
		
		fsm.act(fsm.EVICT_ISSUE,
			self.asmiport.stb.eq(1),
			self.asmiport.we.eq(1),
			If(self.asmiport.ack, fsm.next_state(fsm.EVICT_WAIT))
		)
		fsm.act(fsm.EVICT_WAIT,
			# Data is actually sampled by the memory controller in the next state.
			# But since the data memory has one cycle latency, it gets the data
			# at the address given during this cycle.
			If(self.asmiport.get_call_expression(),
				write_to_asmi_pre.eq(1),
				fsm.next_state(fsm.REFILL_WRTAG)
			)
		)
		
		fsm.act(fsm.REFILL_WRTAG,
			# Write the tag first to set the ASMI address
			tag_we.eq(1),
			fsm.next_state(fsm.REFILL_ISSUE)
		)
		fsm.act(fsm.REFILL_ISSUE,
			self.asmiport.stb.eq(1),
			If(self.asmiport.ack, fsm.next_state(fsm.REFILL_WAIT))
		)
		fsm.act(fsm.REFILL_WAIT,
			If(self.asmiport.get_call_expression(), fsm.next_state(fsm.REFILL_COMPLETE))
		)
		fsm.act(fsm.REFILL_COMPLETE,
			write_from_asmi.eq(1),
			fsm.next_state(fsm.TEST_HIT)
		)
		
		return Fragment(comb, sync, memories=[data_mem, tag_mem]) \
			+ fsm.get_fragment()
Example #5
0
    def get_fragment(self):
        comb = []
        sync = []

        aaw = self.asmiport.hub.aw
        adw = self.asmiport.hub.dw

        # Split address:
        # TAG | LINE NUMBER | LINE OFFSET
        offsetbits = log2_int(adw // 32)
        addressbits = aaw + offsetbits
        linebits = log2_int(self.cachesize) - offsetbits
        tagbits = addressbits - linebits
        adr_offset, adr_line, adr_tag = split(self.wishbone.adr, offsetbits,
                                              linebits, tagbits)

        # Data memory
        data_adr = Signal(BV(linebits))
        data_do = Signal(BV(adw))
        data_di = Signal(BV(adw))
        data_we = Signal(BV(adw // 8))
        data_port = MemoryPort(data_adr,
                               data_do,
                               data_we,
                               data_di,
                               we_granularity=8)
        data_mem = Memory(adw, 2**linebits, data_port)

        write_from_asmi = Signal()
        write_to_asmi = Signal()
        adr_offset_r = Signal(BV(offsetbits))
        comb += [
            data_adr.eq(adr_line),
            If(write_from_asmi, data_di.eq(self.asmiport.dat_r),
               data_we.eq(Replicate(1, adw // 8))).Else(
                   data_di.eq(Replicate(self.wishbone.dat_w, adw // 32)),
                   If(
                       self.wishbone.cyc & self.wishbone.stb & self.wishbone.we
                       & self.wishbone.ack,
                       displacer(self.wishbone.sel,
                                 adr_offset,
                                 data_we,
                                 2**offsetbits,
                                 reverse=True))),
            If(write_to_asmi, self.asmiport.dat_w.eq(data_do)),
            self.asmiport.dat_wm.eq(0),
            chooser(data_do, adr_offset_r, self.wishbone.dat_r, reverse=True)
        ]
        sync += [adr_offset_r.eq(adr_offset)]

        # Tag memory
        tag_layout = [("tag", BV(tagbits)), ("dirty", BV(1))]
        tag_do = Record(tag_layout)
        tag_do_raw = tag_do.to_signal(comb, False)
        tag_di = Record(tag_layout)
        tag_di_raw = tag_di.to_signal(comb, True)

        tag_adr = Signal(BV(linebits))
        tag_we = Signal()
        tag_port = MemoryPort(tag_adr, tag_do_raw, tag_we, tag_di_raw)
        tag_mem = Memory(tagbits + 1, 2**linebits, tag_port)

        comb += [
            tag_adr.eq(adr_line),
            tag_di.tag.eq(adr_tag),
            self.asmiport.adr.eq(Cat(adr_line, tag_do.tag))
        ]

        # Control FSM
        write_to_asmi_pre = Signal()
        sync.append(write_to_asmi.eq(write_to_asmi_pre))

        fsm = FSM("IDLE", "TEST_HIT", "EVICT_ISSUE", "EVICT_WAIT",
                  "REFILL_WRTAG", "REFILL_ISSUE", "REFILL_WAIT",
                  "REFILL_COMPLETE")

        fsm.act(
            fsm.IDLE,
            If(self.wishbone.cyc & self.wishbone.stb,
               fsm.next_state(fsm.TEST_HIT)))
        fsm.act(
            fsm.TEST_HIT,
            If(tag_do.tag == adr_tag, self.wishbone.ack.eq(1),
               If(self.wishbone.we, tag_di.dirty.eq(1), tag_we.eq(1)),
               fsm.next_state(fsm.IDLE)).Else(
                   If(tag_do.dirty, fsm.next_state(fsm.EVICT_ISSUE)).Else(
                       fsm.next_state(fsm.REFILL_WRTAG))))

        fsm.act(fsm.EVICT_ISSUE, self.asmiport.stb.eq(1),
                self.asmiport.we.eq(1),
                If(self.asmiport.ack, fsm.next_state(fsm.EVICT_WAIT)))
        fsm.act(
            fsm.EVICT_WAIT,
            # Data is actually sampled by the memory controller in the next state.
            # But since the data memory has one cycle latency, it gets the data
            # at the address given during this cycle.
            If(self.asmiport.get_call_expression(), write_to_asmi_pre.eq(1),
               fsm.next_state(fsm.REFILL_WRTAG)))

        fsm.act(
            fsm.REFILL_WRTAG,
            # Write the tag first to set the ASMI address
            tag_we.eq(1),
            fsm.next_state(fsm.REFILL_ISSUE))
        fsm.act(fsm.REFILL_ISSUE, self.asmiport.stb.eq(1),
                If(self.asmiport.ack, fsm.next_state(fsm.REFILL_WAIT)))
        fsm.act(
            fsm.REFILL_WAIT,
            If(self.asmiport.get_call_expression(),
               fsm.next_state(fsm.REFILL_COMPLETE)))
        fsm.act(fsm.REFILL_COMPLETE, write_from_asmi.eq(1),
                fsm.next_state(fsm.TEST_HIT))

        return Fragment(comb, sync, memories=[data_mem, tag_mem]) \
         + fsm.get_fragment()
	def get_fragment(self):
		# memory
		mem = Memory(self.width, self.depth)
		mem_ports = [mem.get_port(write_capable=True, has_re=True) 
			for i in range(self.spc)]
		
		# address generator
		adr_reset = Signal()
		adr_inc_1 = Signal()
		adr_inc_mult = Signal()
		sync = []
		for n, port in enumerate(mem_ports):
			v_mem_a = Signal(bits_for(self.depth-1)+1, variable=True)
			sync += [
				v_mem_a.eq(port.adr),
				If(adr_reset,
					v_mem_a.eq(n*self._mult.field.r)
				).Elif(adr_inc_1,
					v_mem_a.eq(v_mem_a + self.spc)
				).Elif(adr_inc_mult,
					v_mem_a.eq(v_mem_a + self.spc*self._mult.field.r)
				),
				If(v_mem_a >= self._size.field.r,
					v_mem_a.eq(v_mem_a - self._size.field.r)
				),
				port.adr.eq(v_mem_a)
			]
		
		# glue
		mem_re = Signal()
		mem_we = Signal()
		mem_dat_ws = [port.dat_w for port in mem_ports]
		data_in_rs = [r.field.r for r in self._data_ins]
		comb = [
			Cat(*mem_dat_ws).eq(Cat(*data_in_rs)),
			self._busy.field.w.eq(self.busy)
		]
		for i, port in enumerate(mem_ports):
			comb += [
				port.re.eq(mem_re),
				port.we.eq(mem_we),
				getattr(self.token("sample"), "value" + str(i)).eq(port.dat_r)
			]
		
		# control
		fsm = FSM("IDLE", "LOAD", "FLUSH", "PLAYBACK")
		fsm.act(fsm.IDLE,
			self.busy.eq(0),
			adr_reset.eq(1),
			If(self._mode.field.r == MODE_LOAD, fsm.next_state(fsm.LOAD)),
			If(self._mode.field.r == MODE_PLAYBACK, fsm.next_state(fsm.FLUSH))
		)
		fsm.act(fsm.LOAD,
			self.busy.eq(0),
			If(self._shift_data.re,
				mem_we.eq(1),
				adr_inc_1.eq(1)
			),
			If(self._mode.field.r != MODE_LOAD, fsm.next_state(fsm.IDLE))
		)
		fsm.act(fsm.FLUSH,
			self.busy.eq(1),
			mem_re.eq(1),
			adr_inc_mult.eq(1),
			fsm.next_state(fsm.PLAYBACK)
		)
		fsm.act(fsm.PLAYBACK,
			self.busy.eq(1),
			self.endpoints["sample"].stb.eq(1),
			If(self.endpoints["sample"].ack,
				adr_inc_mult.eq(1),
				mem_re.eq(1),
				If(self._mode.field.r != MODE_PLAYBACK, fsm.next_state(fsm.IDLE))
			)
		)
		
		return fsm.get_fragment() \
			+ Fragment(comb, sync, memories=[mem])
Example #7
0
class SerialDataWriter:
	def __init__(self, cycle_bits, data_bits, extra_fsm_states=[]):
		self.cycle_bits = cycle_bits
		self.data_bits = data_bits
		
		# I/O signals
		self.d = Signal()
		self.clk = Signal()
		
		# control signals
		self.pds = Signal()
		self.pdi = Signal(self.data_bits)
		
		self.clk_high = Signal()
		self.clk_low = Signal()
		
		self.eoc = Signal()
		self.ev_clk_high = Signal()
		self.ev_clk_low = Signal()
		self.ev_data = Signal()
		
		# FSM
		fsm_states = ["WAIT_DATA", "TRANSFER_DATA"] + extra_fsm_states
		self.fsm = FSM(*fsm_states)
		self.start_action = [self.fsm.next_state(self.fsm.TRANSFER_DATA)]
		self.end_action = [self.fsm.next_state(self.fsm.WAIT_DATA)]
		
		# registers
		self._pos_end_cycle = RegisterField("pos_end_cycle", self.cycle_bits, reset=20)
		self._pos_data = RegisterField("pos_data", self.cycle_bits, reset=0)
	
	def get_registers(self):
		return [self._pos_end_cycle, self._pos_data]
	
	def get_fragment(self):
		# cycle counter and events
		cycle_counter = Signal(self.cycle_bits)
		cycle_counter_reset = Signal()
		comb = [
			self.eoc.eq(cycle_counter == self._pos_end_cycle.field.r)
		]
		sync = [
			If(self.eoc | cycle_counter_reset,
				cycle_counter.eq(0)
			).Else(
				cycle_counter.eq(cycle_counter + 1)
			)
		]
		
		comb += [
			self.ev_clk_high.eq(cycle_counter == (self._pos_end_cycle.field.r >> 1)),
			self.ev_clk_low.eq(cycle_counter == self._pos_end_cycle.field.r),
			self.ev_data.eq(cycle_counter == self._pos_data.field.r)
		]
		
		# data
		sr = Signal(self.data_bits)
		sr_load = Signal()
		sr_shift = Signal()
		remaining_data = Signal(max=self.data_bits+1)
		sync += [
			If(sr_load,
				sr.eq(self.pdi),
				remaining_data.eq(self.data_bits)
			).Elif(sr_shift,
				sr.eq(sr[1:]),
				self.d.eq(sr[0]),
				remaining_data.eq(remaining_data-1)
			)
		]
		
		# clock
		clk_p = Signal()
		sync += [
			If(self.clk_high,
				clk_p.eq(1)
			).Elif(self.clk_low,
				clk_p.eq(0)
			),
			self.clk.eq(clk_p)
		]
		
		# control FSM
		self.fsm.act(self.fsm.WAIT_DATA,
			cycle_counter_reset.eq(1),
			sr_load.eq(1),
			If(self.pds,
				*self.start_action
			)
		)
		self.fsm.act(self.fsm.TRANSFER_DATA,
			self.clk_high.eq(self.ev_clk_high),
			self.clk_low.eq(self.ev_clk_low),
			sr_shift.eq(self.ev_data),
			If(self.eoc & (remaining_data == 0),
				*self.end_action
			)
		)
		
		return Fragment(comb, sync) + self.fsm.get_fragment()