def __init__(self, crc_class, layout): self.sink = sink = stream.Endpoint(layout) self.source = source = stream.Endpoint(layout) self.busy = Signal() # # # dw = len(sink.data) crc = crc_class(dw) fsm = FSM(reset_state="IDLE") self.submodules += crc, fsm fsm.act("IDLE", crc.reset.eq(1), sink.ready.eq(1), If(sink.valid, sink.ready.eq(0), NextState("COPY"), ) ) fsm.act("COPY", crc.ce.eq(sink.valid & source.ready), crc.data.eq(sink.data), sink.connect(source), source.last.eq(0), If(sink.valid & sink.last & source.ready, NextState("INSERT"), ) ) ratio = crc.width//dw if ratio > 1: cnt = Signal(max=ratio, reset=ratio-1) cnt_done = Signal() fsm.act("INSERT", source.valid.eq(1), chooser(crc.value, cnt, source.data, reverse=True), If(cnt_done, source.last.eq(1), If(source.ready, NextState("IDLE")) ) ) self.comb += cnt_done.eq(cnt == 0) self.sync += \ If(fsm.ongoing("IDLE"), cnt.eq(cnt.reset) ).Elif(fsm.ongoing("INSERT") & ~cnt_done, cnt.eq(cnt - source.ready) ) else: fsm.act("INSERT", source.valid.eq(1), source.last.eq(1), source.data.eq(crc.value), If(source.ready, NextState("IDLE")) ) self.comb += self.busy.eq(~fsm.ongoing("IDLE"))
def __init__(self, crc_class, layout): self.sink = sink = Sink(layout) self.source = source = Source(layout) self.busy = Signal() # # # dw = flen(sink.data) crc = crc_class(dw) fsm = FSM(reset_state="IDLE") self.submodules += crc, fsm fsm.act("IDLE", crc.reset.eq(1), sink.ack.eq(1), If(sink.stb & sink.sop, sink.ack.eq(0), NextState("COPY"), ) ) fsm.act("COPY", crc.ce.eq(sink.stb & source.ack), crc.data.eq(sink.data), Record.connect(sink, source), source.eop.eq(0), If(sink.stb & sink.eop & source.ack, NextState("INSERT"), ) ) ratio = crc.width//dw if ratio > 1: cnt = Signal(max=ratio, reset=ratio-1) cnt_done = Signal() fsm.act("INSERT", source.stb.eq(1), chooser(crc.value, cnt, source.data, reverse=True), If(cnt_done, source.eop.eq(1), If(source.ack, NextState("IDLE")) ) ) self.comb += cnt_done.eq(cnt == 0) self.sync += \ If(fsm.ongoing("IDLE"), cnt.eq(cnt.reset) ).Elif(fsm.ongoing("INSERT") & ~cnt_done, cnt.eq(cnt - source.ack) ) else: fsm.act("INSERT", source.stb.eq(1), source.eop.eq(1), source.data.eq(crc.value), If(source.ack, NextState("IDLE")) ) self.comb += self.busy.eq(~fsm.ongoing("IDLE"))
def __init__(self, phy, mem, syncWord=0x42): self.o_done = Signal() self.o_tx = Signal() self.i_trig = Signal() ### self.specials.p = p = mem.get_port(write_capable=False) dataByte = Signal(8) wordIndMax = mem.depth - 1 byteIndMax = ceil(mem.width / 8) - 1 print("MemoryDumper: byteIndMax={} wordIndMax={}".format( byteIndMax, wordIndMax)) byteInd = Signal(max=byteIndMax + 1) byteInd_ce = Signal() # Pulse to increment byte / addr pointer is_last_byte = Signal() # Latches high when last byte was sent self.sync += [ # Logic for incrementing data pointers: byteInd / p.adr If( byteInd_ce, If( byteInd >= byteIndMax, byteInd.eq(0), If(p.adr >= wordIndMax, is_last_byte.eq(1), p.adr.eq(0)).Else(p.adr.eq(p.adr + 1), )).Else( byteInd.eq(byteInd + 1))), self.o_done.eq(0), byteInd_ce.eq(0) ] self.submodules.fsm = fsm = FSM() fsm.act("IDLE", If(self.i_trig, NextState("SYNC"))) fsm.act("SYNC", phy.sink.valid.eq(1), phy.sink.data.eq(syncWord), NextState("WAIT")) fsm.act("SEND", phy.sink.valid.eq(1), phy.sink.data.eq(dataByte), NextValue(byteInd_ce, 1), NextState("WAIT")) fsm.act( "WAIT", If( phy.sink.ready, If(is_last_byte, NextState("IDLE"), NextValue(self.o_done, 1), NextValue(is_last_byte, 0)).Else(NextState("SEND")))) self.comb += [ chooser( # Selects one byte of the dat_r word p.dat_r, byteInd, dataByte, n=ceil(mem.width / 8), reverse=True) ]
def __init__(self, dw): self.sink = stream.Endpoint(eth_phy_layout(dw)) self.source = stream.Endpoint(eth_phy_layout(dw)) # # # preamble = Signal(64, reset=eth_preamble) cnt_max = (64//dw)-1 cnt = Signal(max=cnt_max+1) clr_cnt = Signal() inc_cnt = Signal() self.sync += \ If(clr_cnt, cnt.eq(0) ).Elif(inc_cnt, cnt.eq(cnt+1) ) fsm = FSM(reset_state="IDLE") self.submodules += fsm fsm.act("IDLE", self.sink.ack.eq(1), clr_cnt.eq(1), If(self.sink.stb, self.sink.ack.eq(0), NextState("INSERT"), ) ) fsm.act("INSERT", self.source.stb.eq(1), chooser(preamble, cnt, self.source.data), If(cnt == cnt_max, If(self.source.ack, NextState("COPY")) ).Else( inc_cnt.eq(self.source.ack) ) ) self.comb += [ self.source.data.eq(self.sink.data), self.source.last_be.eq(self.sink.last_be) ] fsm.act("COPY", self.sink.connect(self.source, omit=set(["data", "last_be"])), If(self.sink.stb & self.sink.eop & self.source.ack, NextState("IDLE"), ) )
def __init__(self, d_w): self.sink = Sink(eth_description(d_w)) self.source = Source(eth_description(d_w)) ### preamble = Signal(64, reset=eth_preamble) cnt_max = (64//d_w)-1 cnt = Signal(max=cnt_max+1) clr_cnt = Signal() inc_cnt = Signal() self.sync += \ If(clr_cnt, cnt.eq(0) ).Elif(inc_cnt, cnt.eq(cnt+1) ) fsm = FSM(reset_state="IDLE") self.submodules += fsm fsm.act("IDLE", self.sink.ack.eq(1), clr_cnt.eq(1), If(self.sink.stb & self.sink.sop, self.sink.ack.eq(0), NextState("INSERT"), ) ) fsm.act("INSERT", self.source.stb.eq(1), self.source.sop.eq(cnt==0), chooser(preamble, cnt, self.source.d), If(cnt == cnt_max, If(self.source.ack, NextState("COPY")) ).Else( inc_cnt.eq(self.source.ack) ) ) fsm.act("COPY", Record.connect(self.sink, self.source), self.source.sop.eq(0), If(self.sink.stb & self.sink.eop & self.source.ack, NextState("IDLE"), ) )
def get_fragment(self): port = self.mem.get_port(write_capable=not self.read_only, we_granularity=data_width if not self.read_only and self.word_bits else 0) sel = Signal() sel_r = Signal() sync = [sel_r.eq(sel)] comb = [sel.eq(self.bus.adr[9:] == self.address)] if self.word_bits: word_index = Signal(self.word_bits) word_expanded = Signal(self.csrw_per_memw*data_width) sync.append(word_index.eq(self.bus.adr[:self.word_bits])) comb += [ word_expanded.eq(port.dat_r), If(sel_r, chooser(word_expanded, word_index, self.bus.dat_r, n=self.csrw_per_memw, reverse=True) ) ] if not self.read_only: comb += [ If(sel & self.bus.we, port.we.eq((1 << self.word_bits) >> self.bus.adr[:self.word_bits])), port.dat_w.eq(Replicate(self.bus.dat_w, self.csrw_per_memw)) ] else: comb += [ If(sel_r, self.bus.dat_r.eq(port.dat_r) ) ] if not self.read_only: comb += [ port.we.eq(sel & self.bus.we), port.dat_w.eq(self.bus.dat_w) ] if self._page is None: comb.append(port.adr.eq(self.bus.adr[self.word_bits:len(port.adr)])) else: pv = self._page.field.r comb.append(port.adr.eq(Cat(self.bus.adr[self.word_bits:len(port.adr)-len(pv)], pv))) return Fragment(comb, sync, specials={self.mem})
def __init__(self, pads, default=_default_edid): self.specials.mem = Memory(8, 128, init=default) ### scl_raw = Signal() sda_i = Signal() sda_drv = Signal() _sda_drv_reg = Signal() _sda_i_async = Signal() self.sync += _sda_drv_reg.eq(sda_drv) self.specials += [ MultiReg(pads.scl, scl_raw), Tristate(pads.sda, 0, _sda_drv_reg, _sda_i_async), MultiReg(_sda_i_async, sda_i) ] scl_i = Signal() samp_count = Signal(6) samp_carry = Signal() self.sync += [ Cat(samp_count, samp_carry).eq(samp_count + 1), If(samp_carry, scl_i.eq(scl_raw)) ] scl_r = Signal() sda_r = Signal() scl_rising = Signal() sda_rising = Signal() sda_falling = Signal() self.sync += [ scl_r.eq(scl_i), sda_r.eq(sda_i) ] self.comb += [ scl_rising.eq(scl_i & ~scl_r), sda_rising.eq(sda_i & ~sda_r), sda_falling.eq(~sda_i & sda_r) ] start = Signal() self.comb += start.eq(scl_i & sda_falling) din = Signal(8) counter = Signal(max=9) self.sync += [ If(start, counter.eq(0)), If(scl_rising, If(counter == 8, counter.eq(0) ).Else( counter.eq(counter + 1), din.eq(Cat(sda_i, din[:7])) ) ) ] is_read = Signal() update_is_read = Signal() self.sync += If(update_is_read, is_read.eq(din[0])) offset_counter = Signal(max=128) oc_load = Signal() oc_inc = Signal() self.sync += [ If(oc_load, offset_counter.eq(din) ).Elif(oc_inc, offset_counter.eq(offset_counter + 1) ) ] rdport = self.mem.get_port() self.comb += rdport.adr.eq(offset_counter) data_bit = Signal() zero_drv = Signal() data_drv = Signal() self.comb += If(zero_drv, sda_drv.eq(1)).Elif(data_drv, sda_drv.eq(~data_bit)) data_drv_en = Signal() data_drv_stop = Signal() self.sync += If(data_drv_en, data_drv.eq(1)).Elif(data_drv_stop, data_drv.eq(0)) self.sync += If(data_drv_en, chooser(rdport.dat_r, counter, data_bit, 8, reverse=True)) states = ["WAIT_START", "RCV_ADDRESS", "ACK_ADDRESS0", "ACK_ADDRESS1", "ACK_ADDRESS2", "RCV_OFFSET", "ACK_OFFSET0", "ACK_OFFSET1", "ACK_OFFSET2", "READ", "ACK_READ"] fsm = FSM(*states) self.submodules += fsm fsm.act(fsm.RCV_ADDRESS, If(counter == 8, If(din[1:] == 0x50, update_is_read.eq(1), fsm.next_state(fsm.ACK_ADDRESS0) ).Else( fsm.next_state(fsm.WAIT_START) ) ) ) fsm.act(fsm.ACK_ADDRESS0, If(~scl_i, fsm.next_state(fsm.ACK_ADDRESS1)) ) fsm.act(fsm.ACK_ADDRESS1, zero_drv.eq(1), If(scl_i, fsm.next_state(fsm.ACK_ADDRESS2)) ) fsm.act(fsm.ACK_ADDRESS2, zero_drv.eq(1), If(~scl_i, If(is_read, fsm.next_state(fsm.READ) ).Else( fsm.next_state(fsm.RCV_OFFSET) ) ) ) fsm.act(fsm.RCV_OFFSET, If(counter == 8, oc_load.eq(1), fsm.next_state(fsm.ACK_OFFSET0) ) ) fsm.act(fsm.ACK_OFFSET0, If(~scl_i, fsm.next_state(fsm.ACK_OFFSET1)) ) fsm.act(fsm.ACK_OFFSET1, zero_drv.eq(1), If(scl_i, fsm.next_state(fsm.ACK_OFFSET2)) ) fsm.act(fsm.ACK_OFFSET2, zero_drv.eq(1), If(~scl_i, fsm.next_state(fsm.RCV_ADDRESS)) ) fsm.act(fsm.READ, If(~scl_i, If(counter == 8, data_drv_stop.eq(1), fsm.next_state(fsm.ACK_READ) ).Else( data_drv_en.eq(1) ) ) ) fsm.act(fsm.ACK_READ, If(scl_rising, oc_inc.eq(1), If(sda_i, fsm.next_state(fsm.WAIT_START) ).Else( fsm.next_state(fsm.READ) ) ) ) for state in states: fsm.act(getattr(fsm, state), If(start, fsm.next_state(fsm.RCV_ADDRESS)))
def __init__(self, pads): STATUS_FULL = 1 STATUS_EMPTY = 2 self.shift_reg = shift_reg = CSRStorage(8, write_from_dev=True) self.status = status = CSRStorage(2, reset=STATUS_EMPTY, write_from_dev=True) self.slave_addr = slave_addr = CSRStorage(7) self.pads = pads ### scl_raw = Signal() sda_i = Signal() sda_raw = Signal() sda_drv = Signal() scl_drv = Signal() _sda_drv_reg = Signal() self._sda_i_async = _sda_i_async = Signal() self._scl_i_async = _scl_i_async = Signal() _scl_drv_reg = Signal() self.sync += _sda_drv_reg.eq(sda_drv) self.sync += _scl_drv_reg.eq(scl_drv) self.specials += [ Tristate(pads.sda, 0, _sda_drv_reg, _sda_i_async), Tristate(pads.scl, 0, _scl_drv_reg, _scl_i_async), MultiReg(_scl_i_async, scl_raw), MultiReg(_sda_i_async, sda_raw), ] # for debug self.scl = scl_raw self.sda_i = sda_i self.sda_o = Signal() self.comb += self.sda_o.eq(~_sda_drv_reg) self.sda_oe = _sda_drv_reg shift_reg_full = Signal() shift_reg_empty = Signal() scl_i = Signal() samp_count = Signal(3) samp_carry = Signal() self.sync += [ Cat(samp_count, samp_carry).eq(samp_count + 1), If(samp_carry, scl_i.eq(scl_raw), sda_i.eq(sda_raw) ) ] scl_r = Signal() sda_r = Signal() scl_rising = Signal() scl_falling = Signal() sda_rising = Signal() sda_falling = Signal() self.sync += [ scl_r.eq(scl_i), sda_r.eq(sda_i) ] self.comb += [ shift_reg_full.eq(status.storage[0]), shift_reg_empty.eq(status.storage[1]), scl_rising.eq(scl_i & ~scl_r), scl_falling.eq(~scl_i & scl_r), sda_rising.eq(sda_i & ~sda_r), sda_falling.eq(~sda_i & sda_r) ] start = Signal() self.comb += start.eq(scl_i & sda_falling) din = Signal(8) counter = Signal(max=9) counter_reset = Signal() self.sync += [ If(start | counter_reset, counter.eq(0)), If(scl_rising, If(counter == 8, counter.eq(0) ).Else( counter.eq(counter + 1), din.eq(Cat(sda_i, din[:7])) ) ) ] self.din = din self.counter = counter is_read = Signal() update_is_read = Signal() self.sync += If(update_is_read, is_read.eq(din[0])) data_bit = Signal() zero_drv = Signal() data_drv = Signal() pause_drv = Signal() self.comb += scl_drv.eq(pause_drv) self.comb += If(zero_drv, sda_drv.eq(1)).Elif(data_drv, sda_drv.eq(~data_bit)) data_drv_en = Signal() data_drv_stop = Signal() self.sync += If(data_drv_en, data_drv.eq(1)).Elif(data_drv_stop, data_drv.eq(0)) self.sync += If(data_drv_en, chooser(shift_reg.storage, counter, data_bit, 8, reverse=True)) self.submodules.fsm = fsm = FSM() fsm.act("WAIT_START", data_drv_stop.eq(1), ) fsm.act("RCV_ADDRESS", data_drv_stop.eq(1), If(counter == 8, If(din[1:] == slave_addr.storage, update_is_read.eq(1), NextState("ACK_ADDRESS0"), ).Else( NextState("WAIT_START"), ) ) ) fsm.act("ACK_ADDRESS0", counter_reset.eq(1), If(~scl_i, NextState("ACK_ADDRESS1")), ) fsm.act("ACK_ADDRESS1", counter_reset.eq(1), zero_drv.eq(1), If(scl_i, NextState("ACK_ADDRESS2")), ) fsm.act("ACK_ADDRESS2", counter_reset.eq(1), zero_drv.eq(1), If(~scl_i, NextState("PAUSE") ) ) fsm.act("PAUSE", counter_reset.eq(1), pause_drv.eq(1), If(~shift_reg_empty & is_read, counter_reset.eq(1), NextState("DO_READ"), ).Elif(~shift_reg_full & ~is_read, NextState("DO_WRITE"), ) ) fsm.act("DO_READ", If(~scl_i, If(counter == 8, data_drv_stop.eq(1), status.we.eq(1), status.dat_w.eq(STATUS_EMPTY), NextState("ACK_READ0"), ).Else( data_drv_en.eq(1), ) ) ) fsm.act("ACK_READ0", counter_reset.eq(1), If(scl_rising, If(sda_i, NextState("WAIT_START"), ).Else( NextState("ACK_READ1"), ) ) ) fsm.act("ACK_READ1", counter_reset.eq(1), If(scl_falling, NextState("PAUSE"), ) ) fsm.act("DO_WRITE", If(counter == 8, shift_reg.dat_w.eq(din), shift_reg.we.eq(1), NextState("ACK_WRITE0"), ) ) fsm.act("ACK_WRITE0", counter_reset.eq(1), If(~scl_i, NextState("ACK_WRITE1")), ) fsm.act("ACK_WRITE1", counter_reset.eq(1), zero_drv.eq(1), If(scl_i, NextState("ACK_WRITE2")), ) fsm.act("ACK_WRITE2", counter_reset.eq(1), zero_drv.eq(1), If(~scl_i, NextState("PAUSE"), status.we.eq(1), status.dat_w.eq(STATUS_FULL), ) ) for state in fsm.actions.keys(): fsm.act(state, If(start, NextState("RCV_ADDRESS"))) for state in fsm.actions.keys(): fsm.act(state, If(self.slave_addr.re, NextState("WAIT_START")))
def __init__(self, phy, clk_freq): self.wishbone = wishbone.Interface() # # # byte_counter = Counter(3) word_counter = Counter(8) self.submodules += byte_counter, word_counter cmd = Signal(8) cmd_ce = Signal() length = Signal(8) length_ce = Signal() address = Signal(32) address_ce = Signal() data = Signal(32) rx_data_ce = Signal() tx_data_ce = Signal() self.sync += [ If(cmd_ce, cmd.eq(phy.source.data)), If(length_ce, length.eq(phy.source.data)), If(address_ce, address.eq(Cat(phy.source.data, address[0:24]))), If(rx_data_ce, data.eq(Cat(phy.source.data, data[0:24]))).Elif(tx_data_ce, data.eq(self.wishbone.dat_r)), ] fsm = InsertReset(FSM(reset_state="IDLE")) timer = WaitTimer(clk_freq // 10) self.submodules += fsm, timer self.comb += [fsm.reset.eq(timer.done), phy.source.ack.eq(1)] fsm.act( "IDLE", If( phy.source.stb, cmd_ce.eq(1), If( (phy.source.data == self.cmds["write"]) | (phy.source.data == self.cmds["read"]), NextState("RECEIVE_LENGTH"), ), byte_counter.reset.eq(1), word_counter.reset.eq(1), ), ) fsm.act("RECEIVE_LENGTH", If(phy.source.stb, length_ce.eq(1), NextState("RECEIVE_ADDRESS"))) fsm.act( "RECEIVE_ADDRESS", If( phy.source.stb, address_ce.eq(1), byte_counter.ce.eq(1), If( byte_counter.value == 3, If(cmd == self.cmds["write"], NextState("RECEIVE_DATA")).Elif( cmd == self.cmds["read"], NextState("READ_DATA") ), byte_counter.reset.eq(1), ), ), ) fsm.act( "RECEIVE_DATA", If( phy.source.stb, rx_data_ce.eq(1), byte_counter.ce.eq(1), If(byte_counter.value == 3, NextState("WRITE_DATA"), byte_counter.reset.eq(1)), ), ) self.comb += [ self.wishbone.adr.eq(address + word_counter.value), self.wishbone.dat_w.eq(data), self.wishbone.sel.eq(2 ** flen(self.wishbone.sel) - 1), ] fsm.act( "WRITE_DATA", self.wishbone.stb.eq(1), self.wishbone.we.eq(1), self.wishbone.cyc.eq(1), If( self.wishbone.ack, word_counter.ce.eq(1), If(word_counter.value == (length - 1), NextState("IDLE")).Else(NextState("RECEIVE_DATA")), ), ) fsm.act( "READ_DATA", self.wishbone.stb.eq(1), self.wishbone.we.eq(0), self.wishbone.cyc.eq(1), If(self.wishbone.ack, tx_data_ce.eq(1), NextState("SEND_DATA")), ) self.comb += chooser(data, byte_counter.value, phy.sink.data, n=4, reverse=True) fsm.act( "SEND_DATA", phy.sink.stb.eq(1), If( phy.sink.ack, byte_counter.ce.eq(1), If( byte_counter.value == 3, word_counter.ce.eq(1), If(word_counter.value == (length - 1), NextState("IDLE")).Else( NextState("READ_DATA"), byte_counter.reset.eq(1) ), ), ), ) self.comb += timer.wait.eq(~fsm.ongoing("IDLE")) if phy.sink.description.packetized: self.comb += [ phy.sink.sop.eq((byte_counter.value == 0) & (word_counter.value == 0)), phy.sink.eop.eq((byte_counter.value == 3) & (word_counter.value == (length - 1))), ] if hasattr(phy.sink, "length"): self.comb += phy.sink.length.eq(4 * length)
def __init__(self, dw_i, dw_o): self.wishbone_i = Interface(dw_i) self.wishbone_o = Interface(dw_o) self.ratio = dw_i//dw_o ### rst = Signal() # generate internal write and read ack write_ack = Signal() read_ack = Signal() ack = Signal() self.comb += [ ack.eq(self.wishbone_o.cyc & self.wishbone_o.stb & self.wishbone_o.ack), write_ack.eq(ack & self.wishbone_o.we), read_ack.eq(ack & ~self.wishbone_o.we) ] # accesses counter logic cnt = Signal(max=self.ratio) self.sync += If(rst, cnt.eq(0)).Elif(ack, cnt.eq(cnt + 1)) # read data path dat_r = Signal(dw_i) self.sync += If(ack, dat_r.eq(Cat(self.wishbone_o.dat_r, dat_r[:dw_i-dw_o]))) # write data path dat_w = Signal(dw_i) self.comb += dat_w.eq(self.wishbone_i.dat_w) # errors generation err = Signal() self.sync += If(ack, err.eq(self.wishbone_o.err)) # direct connection of wishbone_i --> wishbone_o signals for name, size, direction in self.wishbone_i.layout: if direction == DIR_M_TO_S and name not in ["adr", "dat_w"]: self.comb += getattr(self.wishbone_o, name).eq(getattr(self.wishbone_i, name)) # adaptation of adr & dat signals self.comb += [ self.wishbone_o.adr[0:flen(cnt)].eq(cnt), self.wishbone_o.adr[flen(cnt):].eq(self.wishbone_i.adr) ] self.comb += chooser(dat_w, cnt, self.wishbone_o.dat_w, reverse=True) # fsm fsm = FSM(reset_state="IDLE") self.submodules += fsm fsm.act("IDLE", If(write_ack, NextState("WRITE_ADAPT")), If(read_ack, NextState("READ_ADAPT")) ) fsm.act("WRITE_ADAPT", If(write_ack & (cnt == self.ratio-1), NextState("IDLE"), rst.eq(1), self.wishbone_i.err.eq(err | self.wishbone_o.err), self.wishbone_i.ack.eq(1), ) ) master_i_dat_r = Signal(dw_i) self.comb += master_i_dat_r.eq(Cat(self.wishbone_o.dat_r, dat_r[:dw_i-dw_o])) fsm.act("READ_ADAPT", If(read_ack & (cnt == self.ratio-1), NextState("IDLE"), rst.eq(1), self.wishbone_i.err.eq(err | self.wishbone_o.err), self.wishbone_i.ack.eq(1), self.wishbone_i.dat_r.eq(master_i_dat_r) ) )
def __init__(self, d_w): self.sink = Sink(eth_description(d_w)) self.source = Source(eth_description(d_w)) ### preamble = Signal(64, reset=eth_preamble) cnt_max = (64//d_w) - 1 cnt = Signal(max=cnt_max+1) clr_cnt = Signal() inc_cnt = Signal() self.sync += \ If(clr_cnt, cnt.eq(0) ).Elif(inc_cnt, cnt.eq(cnt+1) ) discard = Signal() clr_discard = Signal() set_discard = Signal() self.sync += \ If(clr_discard, discard.eq(0) ).Elif(set_discard, discard.eq(1) ) sop = Signal() clr_sop = Signal() set_sop = Signal() self.sync += \ If(clr_sop, sop.eq(0) ).Elif(set_sop, sop.eq(1) ) ref = Signal(d_w) match = Signal() self.comb += [ chooser(preamble, cnt, ref), match.eq(self.sink.d == ref) ] fsm = FSM(reset_state="IDLE") self.submodules += fsm fsm.act("IDLE", self.sink.ack.eq(1), clr_cnt.eq(1), clr_discard.eq(1), If(self.sink.stb & self.sink.sop, clr_cnt.eq(0), inc_cnt.eq(1), clr_discard.eq(0), set_discard.eq(~match), NextState("CHECK"), ) ) fsm.act("CHECK", self.sink.ack.eq(1), If(self.sink.stb, set_discard.eq(~match), If(cnt == cnt_max, If(discard | (~match), NextState("IDLE") ).Else( set_sop.eq(1), NextState("COPY") ) ).Else( inc_cnt.eq(1) ) ) ) fsm.act("COPY", Record.connect(self.sink, self.source), self.source.sop.eq(sop), clr_sop.eq(self.source.stb & self.source.ack), If(self.source.stb & self.source.eop & self.source.ack, NextState("IDLE"), ) )
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_mem = Memory(adw, 2**linebits) data_port = data_mem.get_port(write_capable=True, we_granularity=8) write_from_asmi = Signal() write_to_asmi = Signal() adr_offset_r = Signal(offsetbits) comb += [ data_port.adr.eq(adr_line), If(write_from_asmi, data_port.dat_w.eq(self.asmiport.dat_r), data_port.we.eq(Replicate(1, adw//8)) ).Else( data_port.dat_w.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_port.we, 2**offsetbits, reverse=True) ) ), If(write_to_asmi, self.asmiport.dat_w.eq(data_port.dat_r)), self.asmiport.dat_wm.eq(0), chooser(data_port.dat_r, adr_offset_r, self.wishbone.dat_r, reverse=True) ] sync += [ adr_offset_r.eq(adr_offset) ] # 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) tag_do = Record(tag_layout) tag_di = Record(tag_layout) comb += [ tag_do.raw_bits().eq(tag_port.dat_r), tag_port.dat_w.eq(tag_di.raw_bits()) ] comb += [ tag_port.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_port.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_port.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, specials={data_mem, tag_mem}) \ + fsm.get_fragment()
def __init__(self, pads, default=_default_edid): self._hpd_notif = CSRStatus() self._hpd_en = CSRStorage() self.specials.mem = Memory(8, 128, init=default) ### # HPD if hasattr(pads, "hpd_notif"): self.specials += MultiReg(pads.hpd_notif, self._hpd_notif.status) else: self.comb += self._hpd_notif.status.eq(1) if hasattr(pads, "hpd_en"): self.comb += pads.hpd_en.eq(self._hpd_en.storage) # EDID scl_raw = Signal() sda_i = Signal() sda_raw = Signal() sda_drv = Signal() _sda_drv_reg = Signal() _sda_i_async = Signal() self.sync += _sda_drv_reg.eq(sda_drv) self.specials += [ MultiReg(pads.scl, scl_raw), Tristate(pads.sda, 0, _sda_drv_reg, _sda_i_async), MultiReg(_sda_i_async, sda_raw) ] # for debug self.scl = scl_raw self.sda_i = sda_i self.sda_o = Signal() self.comb += self.sda_o.eq(~_sda_drv_reg) self.sda_oe = _sda_drv_reg scl_i = Signal() samp_count = Signal(6) samp_carry = Signal() self.sync += [ Cat(samp_count, samp_carry).eq(samp_count + 1), If(samp_carry, scl_i.eq(scl_raw), sda_i.eq(sda_raw) ) ] scl_r = Signal() sda_r = Signal() scl_rising = Signal() sda_rising = Signal() sda_falling = Signal() self.sync += [ scl_r.eq(scl_i), sda_r.eq(sda_i) ] self.comb += [ scl_rising.eq(scl_i & ~scl_r), sda_rising.eq(sda_i & ~sda_r), sda_falling.eq(~sda_i & sda_r) ] start = Signal() self.comb += start.eq(scl_i & sda_falling) din = Signal(8) counter = Signal(max=9) self.sync += [ If(start, counter.eq(0)), If(scl_rising, If(counter == 8, counter.eq(0) ).Else( counter.eq(counter + 1), din.eq(Cat(sda_i, din[:7])) ) ) ] self.din = din self.counter = counter is_read = Signal() update_is_read = Signal() self.sync += If(update_is_read, is_read.eq(din[0])) offset_counter = Signal(max=128) oc_load = Signal() oc_inc = Signal() self.sync += [ If(oc_load, offset_counter.eq(din) ).Elif(oc_inc, offset_counter.eq(offset_counter + 1) ) ] rdport = self.mem.get_port() self.specials += rdport self.comb += rdport.adr.eq(offset_counter) data_bit = Signal() zero_drv = Signal() data_drv = Signal() self.comb += If(zero_drv, sda_drv.eq(1)).Elif(data_drv, sda_drv.eq(~data_bit)) data_drv_en = Signal() data_drv_stop = Signal() self.sync += If(data_drv_en, data_drv.eq(1)).Elif(data_drv_stop, data_drv.eq(0)) self.sync += If(data_drv_en, chooser(rdport.dat_r, counter, data_bit, 8, reverse=True)) self.submodules.fsm = fsm = FSM() fsm.act("WAIT_START") fsm.act("RCV_ADDRESS", If(counter == 8, If(din[1:] == 0x50, update_is_read.eq(1), NextState("ACK_ADDRESS0") ).Else( NextState("WAIT_START") ) ) ) fsm.act("ACK_ADDRESS0", If(~scl_i, NextState("ACK_ADDRESS1")) ) fsm.act("ACK_ADDRESS1", zero_drv.eq(1), If(scl_i, NextState("ACK_ADDRESS2")) ) fsm.act("ACK_ADDRESS2", zero_drv.eq(1), If(~scl_i, If(is_read, NextState("READ") ).Else( NextState("RCV_OFFSET") ) ) ) fsm.act("RCV_OFFSET", If(counter == 8, oc_load.eq(1), NextState("ACK_OFFSET0") ) ) fsm.act("ACK_OFFSET0", If(~scl_i, NextState("ACK_OFFSET1")) ) fsm.act("ACK_OFFSET1", zero_drv.eq(1), If(scl_i, NextState("ACK_OFFSET2")) ) fsm.act("ACK_OFFSET2", zero_drv.eq(1), If(~scl_i, NextState("RCV_ADDRESS")) ) fsm.act("READ", If(~scl_i, If(counter == 8, data_drv_stop.eq(1), NextState("ACK_READ") ).Else( data_drv_en.eq(1) ) ) ) fsm.act("ACK_READ", If(scl_rising, oc_inc.eq(1), If(sda_i, NextState("WAIT_START") ).Else( NextState("READ") ) ) ) for state in fsm.actions.keys(): fsm.act(state, If(start, NextState("RCV_ADDRESS"))) fsm.act(state, If(~self._hpd_en.storage, NextState("WAIT_START")))
def __init__(self, pads, default=_default_edid): self._hpd_notif = CSRStatus() self._hpd_en = CSRStorage() mem_size = len(default) assert mem_size % 128 == 0 self.specials.mem = Memory(8, mem_size, init=default) # # # # HPD if hasattr(pads, "hpd_notif"): if hasattr(getattr(pads, "hpd_notif"), "inverted"): hpd_notif_n = Signal() self.comb += hpd_notif_n.eq(~pads.hpd_notif) self.specials += MultiReg(hpd_notif_n, self._hpd_notif.status) else: self.specials += MultiReg(pads.hpd_notif, self._hpd_notif.status) else: self.comb += self._hpd_notif.status.eq(1) if hasattr(pads, "hpd_en"): self.comb += pads.hpd_en.eq(self._hpd_en.storage) # EDID scl_raw = Signal() sda_i = Signal() sda_raw = Signal() sda_drv = Signal() _sda_drv_reg = Signal() _sda_i_async = Signal() self.sync += _sda_drv_reg.eq(sda_drv) pad_scl = getattr(pads, "scl") if hasattr(pad_scl, "inverted"): self.specials += MultiReg(~pads.scl, scl_raw) else: self.specials += MultiReg(pads.scl, scl_raw) if hasattr(pads, "sda_pu") and hasattr(pads, "sda_pd"): pad_sda = getattr(pads, "sda") if hasattr(pad_sda, "inverted"): self.specials += MultiReg(~pads.sda, sda_raw) else: self.specials += MultiReg(pads.sda, sda_raw) self.comb += [ pads.sda_pu.eq(0), pads.sda_pd.eq(_sda_drv_reg), ] else: self.specials += [ Tristate(pads.sda, 0, _sda_drv_reg, _sda_i_async), MultiReg(_sda_i_async, sda_raw), ] # for debug self.scl = scl_raw self.sda_i = sda_i self.sda_o = Signal() self.comb += self.sda_o.eq(~_sda_drv_reg) self.sda_oe = _sda_drv_reg scl_i = Signal() samp_count = Signal(6) samp_carry = Signal() self.sync += [ Cat(samp_count, samp_carry).eq(samp_count + 1), If(samp_carry, scl_i.eq(scl_raw), sda_i.eq(sda_raw)) ] scl_r = Signal() sda_r = Signal() scl_rising = Signal() sda_rising = Signal() sda_falling = Signal() self.sync += [scl_r.eq(scl_i), sda_r.eq(sda_i)] self.comb += [ scl_rising.eq(scl_i & ~scl_r), sda_rising.eq(sda_i & ~sda_r), sda_falling.eq(~sda_i & sda_r) ] start = Signal() self.comb += start.eq(scl_i & sda_falling) din = Signal(8) counter = Signal(max=9) self.sync += [ If(start, counter.eq(0)), If( scl_rising, If(counter == 8, counter.eq(0)).Else(counter.eq(counter + 1), din.eq(Cat(sda_i, din[:7])))) ] self.din = din self.counter = counter is_read = Signal() update_is_read = Signal() self.sync += If(update_is_read, is_read.eq(din[0])) offset_counter = Signal(max=mem_size) oc_load = Signal() oc_inc = Signal() self.sync += \ If(oc_load, offset_counter.eq(din) ).Elif(oc_inc, offset_counter.eq(offset_counter + 1) ) rdport = self.mem.get_port() self.specials += rdport self.comb += rdport.adr.eq(offset_counter) data_bit = Signal() zero_drv = Signal() data_drv = Signal() self.comb += \ If(zero_drv, sda_drv.eq(1) ).Elif(data_drv, sda_drv.eq(~data_bit) ) data_drv_en = Signal() data_drv_stop = Signal() self.sync += \ If(data_drv_en, data_drv.eq(1) ).Elif(data_drv_stop, data_drv.eq(0) ) self.sync += \ If(data_drv_en, chooser(rdport.dat_r, counter, data_bit, 8, reverse=True) ) self.submodules.fsm = fsm = FSM() fsm.act("WAIT_START") fsm.act( "RCV_ADDRESS", If( counter == 8, If(din[1:] == 0x50, update_is_read.eq(1), NextState("ACK_ADDRESS0")).Else(NextState("WAIT_START")))) fsm.act("ACK_ADDRESS0", If(~scl_i, NextState("ACK_ADDRESS1"))) fsm.act("ACK_ADDRESS1", zero_drv.eq(1), If(scl_i, NextState("ACK_ADDRESS2"))) fsm.act( "ACK_ADDRESS2", zero_drv.eq(1), If(~scl_i, If(is_read, NextState("READ")).Else(NextState("RCV_OFFSET")))) fsm.act("RCV_OFFSET", If(counter == 8, oc_load.eq(1), NextState("ACK_OFFSET0"))) fsm.act("ACK_OFFSET0", If(~scl_i, NextState("ACK_OFFSET1"))) fsm.act("ACK_OFFSET1", zero_drv.eq(1), If(scl_i, NextState("ACK_OFFSET2"))) fsm.act("ACK_OFFSET2", zero_drv.eq(1), If(~scl_i, NextState("RCV_ADDRESS"))) fsm.act( "READ", If( ~scl_i, If(counter == 8, data_drv_stop.eq(1), NextState("ACK_READ")).Else(data_drv_en.eq(1)))) fsm.act( "ACK_READ", If(scl_rising, oc_inc.eq(1), If(sda_i, NextState("WAIT_START")).Else(NextState("READ")))) for state in fsm.actions.keys(): fsm.act(state, If(start, NextState("RCV_ADDRESS"))) if hasattr(pads, "hpd_en"): fsm.act(state, If(~self._hpd_en.storage, NextState("WAIT_START")))
def __init__(self, mem_or_size, address, read_only=None, init=None, bus=None): if isinstance(mem_or_size, Memory): mem = mem_or_size else: mem = Memory(data_width, mem_or_size//(data_width//8), init=init) csrw_per_memw = (mem.width + data_width - 1)//data_width word_bits = log2_int(csrw_per_memw) page_bits = log2_int((mem.depth*csrw_per_memw + 511)//512, False) if page_bits: self._page = CSRStorage(page_bits, name=mem.name_override + "_page") else: self._page = None if read_only is None: if hasattr(mem, "bus_read_only"): read_only = mem.bus_read_only else: read_only = False if bus is None: bus = Interface() self.bus = bus ### port = mem.get_port(write_capable=not read_only) self.specials += mem, port sel = Signal() sel_r = Signal() self.sync += sel_r.eq(sel) self.comb += sel.eq(self.bus.adr[9:] == address) if word_bits: word_index = Signal(word_bits) word_expanded = Signal(csrw_per_memw*data_width) self.sync += word_index.eq(self.bus.adr[:word_bits]) self.comb += [ word_expanded.eq(port.dat_r), If(sel_r, chooser(word_expanded, word_index, self.bus.dat_r, n=csrw_per_memw, reverse=True) ) ] if not read_only: wregs = [] for i in range(csrw_per_memw-1): wreg = Signal(data_width) self.sync += If(sel & self.bus.we & (self.bus.adr[:word_bits] == i), wreg.eq(self.bus.dat_w)) wregs.append(wreg) memword_chunks = [self.bus.dat_w] + list(reversed(wregs)) self.comb += [ port.we.eq(sel & self.bus.we & (self.bus.adr[:word_bits] == csrw_per_memw - 1)), port.dat_w.eq(Cat(*memword_chunks)) ] else: self.comb += If(sel_r, self.bus.dat_r.eq(port.dat_r)) if not read_only: self.comb += [ port.we.eq(sel & self.bus.we), port.dat_w.eq(self.bus.dat_w) ] if self._page is None: self.comb += port.adr.eq(self.bus.adr[word_bits:word_bits+flen(port.adr)]) else: pv = self._page.storage self.comb += port.adr.eq(Cat(self.bus.adr[word_bits:word_bits+flen(port.adr)-flen(pv)], pv))
def __init__(self, mem_or_size, address, read_only=None, bus=None): if isinstance(mem_or_size, Memory): mem = mem_or_size else: mem = Memory(data_width, mem_or_size//(data_width//8)) if mem.width > data_width: csrw_per_memw = (mem.width + data_width - 1)//data_width word_bits = bits_for(csrw_per_memw-1) else: csrw_per_memw = 1 word_bits = 0 page_bits = _compute_page_bits(mem.depth + word_bits) if page_bits: self._page = CSRStorage(page_bits, name=mem.name_override + "_page") else: self._page = None if read_only is None: if hasattr(mem, "bus_read_only"): read_only = mem.bus_read_only else: read_only = False if bus is None: bus = Interface() self.bus = bus ### self.specials += mem port = mem.get_port(write_capable=not read_only, we_granularity=data_width if not read_only and word_bits else 0) sel = Signal() sel_r = Signal() self.sync += sel_r.eq(sel) self.comb += sel.eq(self.bus.adr[9:] == address) if word_bits: word_index = Signal(word_bits) word_expanded = Signal(csrw_per_memw*data_width) self.sync += word_index.eq(self.bus.adr[:word_bits]) self.comb += [ word_expanded.eq(port.dat_r), If(sel_r, chooser(word_expanded, word_index, self.bus.dat_r, n=csrw_per_memw, reverse=True) ) ] if not read_only: self.comb += [ If(sel & self.bus.we, port.we.eq((1 << word_bits) >> self.bus.adr[:self.word_bits])), port.dat_w.eq(Replicate(self.bus.dat_w, csrw_per_memw)) ] else: self.comb += If(sel_r, self.bus.dat_r.eq(port.dat_r)) if not read_only: self.comb += [ port.we.eq(sel & self.bus.we), port.dat_w.eq(self.bus.dat_w) ] if self._page is None: self.comb += port.adr.eq(self.bus.adr[word_bits:len(port.adr)]) else: pv = self._page.storage self.comb += port.adr.eq(Cat(self.bus.adr[word_bits:len(port.adr)-len(pv)], pv))
def __init__(self): self.sink = sink = Sink(EndpointDescription([("data", 128)], packetized=True)) self.source = source = Source(EndpointDescription([("data", 16)], packetized=True)) # # # # mem mem = Memory(128, 16) write_port = mem.get_port(write_capable=True) read_port = mem.get_port(async_read=True) self.specials += mem, write_port, read_port write_sel = Signal() write_swap = Signal() read_sel = Signal(reset=1) read_swap = Signal() self.sync += [ If(write_swap, write_sel.eq(~write_sel) ), If(read_swap, read_sel.eq(~read_sel) ) ] # write path v_write_clr = Signal() v_write_inc = Signal() v_write = Signal(3) self.sync += \ If(v_write_clr, v_write.eq(0) ).Elif(v_write_inc, v_write.eq(v_write + 1) ) self.comb += [ write_port.adr.eq(v_write), write_port.adr[-1].eq(write_sel), write_port.dat_w.eq(sink.data), write_port.we.eq(sink.stb & sink.ack) ] self.submodules.write_fsm = write_fsm = FSM(reset_state="IDLE") write_fsm.act("IDLE", v_write_clr.eq(1), If(write_sel != read_sel, NextState("WRITE") ) ) write_fsm.act("WRITE", sink.ack.eq(1), If(sink.stb, If(v_write == 7, write_swap.eq(1), NextState("IDLE") ).Else( v_write_inc.eq(1) ) ) ) # read path h_read_clr = Signal() h_read_inc = Signal() h_read = Signal(3) self.sync += \ If(h_read_clr, h_read.eq(0) ).Elif(h_read_inc, h_read.eq(h_read + 1) ) v_read_clr = Signal() v_read_inc = Signal() v_read = Signal(3) self.sync += \ If(v_read_clr, v_read.eq(0) ).Elif(v_read_inc, v_read.eq(v_read + 1) ) self.comb += [ read_port.adr.eq(v_read), read_port.adr[-1].eq(read_sel), chooser(read_port.dat_r, h_read, source.data, reverse=True) ] self.submodules.read_fsm = read_fsm = FSM(reset_state="IDLE") read_fsm.act("IDLE", h_read_clr.eq(1), v_read_clr.eq(1), If(read_sel == write_sel, read_swap.eq(1), NextState("READ") ) ) read_fsm.act("READ", source.stb.eq(1), source.sop.eq((h_read == 0) & (v_read == 0)), source.eop.eq((h_read == 7) & (v_read == 7)), If(source.ack, If(h_read == 7, h_read_clr.eq(1), If(v_read == 7, NextState("IDLE") ).Else( v_read_inc.eq(1) ) ).Else( h_read_inc.eq(1) ) ) )
def __init__(self, dw): self.sink = stream.Endpoint(eth_phy_description(dw)) self.source = stream.Endpoint(eth_phy_description(dw)) # # # preamble = Signal(64, reset=eth_preamble) cnt_max = (64//dw) - 1 cnt = Signal(max=cnt_max+1) clr_cnt = Signal() inc_cnt = Signal() self.sync += \ If(clr_cnt, cnt.eq(0) ).Elif(inc_cnt, cnt.eq(cnt+1) ) discard = Signal() clr_discard = Signal() set_discard = Signal() self.sync += \ If(clr_discard, discard.eq(0) ).Elif(set_discard, discard.eq(1) ) ref = Signal(dw) match = Signal() self.comb += [ chooser(preamble, cnt, ref), match.eq(self.sink.data == ref) ] fsm = FSM(reset_state="IDLE") self.submodules += fsm fsm.act("IDLE", self.sink.ack.eq(1), clr_cnt.eq(1), clr_discard.eq(1), If(self.sink.stb, clr_cnt.eq(0), inc_cnt.eq(1), clr_discard.eq(0), set_discard.eq(~match), NextState("CHECK"), ) ) fsm.act("CHECK", self.sink.ack.eq(1), If(self.sink.stb, set_discard.eq(~match), If(cnt == cnt_max, If(discard | (~match), NextState("IDLE") ).Else( NextState("COPY") ) ).Else( inc_cnt.eq(1) ) ) ) self.comb += [ self.source.data.eq(self.sink.data), self.source.last_be.eq(self.sink.last_be) ] fsm.act("COPY", self.sink.connect(self.source, leave_out=set(["data", "last_be"])), If(self.source.stb & self.source.eop & self.source.ack, NextState("IDLE"), ) )
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") ) )
def __init__(self, cachesize, lasmim): self.wishbone = wishbone.Interface() ### if lasmim.dw <= 32: raise ValueError("LASMI data width must be strictly larger than 32") if (lasmim.dw % 32) != 0: raise ValueError("LASMI data width must be a multiple of 32") # Split address: # TAG | LINE NUMBER | LINE OFFSET offsetbits = log2_int(lasmim.dw//32) 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() adr_offset_r = Signal(offsetbits) 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//32)), 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) ] self.sync += adr_offset_r.eq(adr_offset) # 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("IDLE", "TEST_HIT", "EVICT_REQUEST", "EVICT_WAIT_DATA_ACK", "EVICT_DATA", "REFILL_WRTAG", "REFILL_REQUEST", "REFILL_WAIT_DATA_ACK", "REFILL_DATA", delayed_enters=[ ("EVICT_DATAD", "EVICT_DATA", lasmim.write_latency-1), ("REFILL_DATAD", "REFILL_DATA", lasmim.read_latency-1) ]) self.submodules += fsm 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_port.we.eq(1) ), fsm.next_state(fsm.IDLE) ).Else( If(tag_do.dirty, fsm.next_state(fsm.EVICT_REQUEST) ).Else( fsm.next_state(fsm.REFILL_WRTAG) ) ) ) fsm.act(fsm.EVICT_REQUEST, lasmim.stb.eq(1), lasmim.we.eq(1), If(lasmim.req_ack, fsm.next_state(fsm.EVICT_WAIT_DATA_ACK)) ) fsm.act(fsm.EVICT_WAIT_DATA_ACK, If(lasmim.dat_ack, fsm.next_state(fsm.EVICT_DATAD)) ) fsm.act(fsm.EVICT_DATA, write_to_lasmi.eq(1), fsm.next_state(fsm.REFILL_WRTAG) ) fsm.act(fsm.REFILL_WRTAG, # Write the tag first to set the LASMI address tag_port.we.eq(1), fsm.next_state(fsm.REFILL_REQUEST) ) fsm.act(fsm.REFILL_REQUEST, lasmim.stb.eq(1), If(lasmim.req_ack, fsm.next_state(fsm.REFILL_WAIT_DATA_ACK)) ) fsm.act(fsm.REFILL_WAIT_DATA_ACK, If(lasmim.dat_ack, fsm.next_state(fsm.REFILL_DATAD)) ) fsm.act(fsm.REFILL_DATA, write_from_lasmi.eq(1), fsm.next_state(fsm.TEST_HIT) )
def __init__(self, cachesize, master, slave): self._size = CSRStatus(8, reset=log2_int(cachesize)) self.master = master self.slave = slave ### dw_from = flen(master.dat_r) dw_to = flen(slave.dat_r) if dw_to > dw_from and (dw_to % dw_from) != 0: raise ValueError("Slave data width must be a multiple of {dw}".format(dw=dw_from)) if dw_to < dw_from and (dw_from % dw_to) != 0: raise ValueError("Master data width must be a multiple of {dw}".format(dw=dw_to)) # Split address: # TAG | LINE NUMBER | LINE OFFSET offsetbits = log2_int(max(dw_to//dw_from, 1)) addressbits = flen(slave.adr) + offsetbits linebits = log2_int(cachesize) - offsetbits tagbits = addressbits - linebits wordbits = log2_int(max(dw_from//dw_to, 1)) adr_offset, adr_line, adr_tag = split(master.adr, offsetbits, linebits, tagbits) word = Signal(wordbits) if wordbits else None # Data memory data_mem = Memory(dw_to*2**wordbits, 2**linebits) data_port = data_mem.get_port(write_capable=True, we_granularity=8) self.specials += data_mem, data_port write_from_slave = 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_slave, displacer(slave.dat_r, word, data_port.dat_w), displacer(Replicate(1, dw_to//8), word, data_port.we) ).Else( data_port.dat_w.eq(Replicate(master.dat_w, max(dw_to//dw_from, 1))), If(master.cyc & master.stb & master.we & master.ack, displacer(master.sel, adr_offset, data_port.we, 2**offsetbits, reverse=True) ) ), chooser(data_port.dat_r, word, slave.dat_w), slave.sel.eq(2**(dw_to//8)-1), chooser(data_port.dat_r, adr_offset_r, master.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 += slave.adr.eq(Cat(word, adr_line, tag_do.tag)) else: self.comb += slave.adr.eq(Cat(adr_line, tag_do.tag)) # slave 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 self.submodules.fsm = fsm = FSM(reset_state="IDLE") fsm.act("IDLE", If(master.cyc & master.stb, NextState("TEST_HIT") ) ) fsm.act("TEST_HIT", word_clr.eq(1), If(tag_do.tag == adr_tag, master.ack.eq(1), If(master.we, tag_di.dirty.eq(1), tag_port.we.eq(1) ), NextState("IDLE") ).Else( If(tag_do.dirty, NextState("EVICT") ).Else( NextState("REFILL_WRTAG") ) ) ) fsm.act("EVICT", slave.stb.eq(1), slave.cyc.eq(1), slave.we.eq(1), If(slave.ack, word_inc.eq(1), If(word_is_last(word), NextState("REFILL_WRTAG") ) ) ) fsm.act("REFILL_WRTAG", # Write the tag first to set the slave address tag_port.we.eq(1), word_clr.eq(1), NextState("REFILL") ) fsm.act("REFILL", slave.stb.eq(1), slave.cyc.eq(1), slave.we.eq(0), If(slave.ack, write_from_slave.eq(1), word_inc.eq(1), If(word_is_last(word), NextState("TEST_HIT"), ).Else( NextState("REFILL") ) ) )
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") )