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