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, 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, reset_less=True) 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.ready.eq(1), clr_cnt.eq(1), If(self.sink.valid, self.sink.ready.eq(0), NextState("INSERT"), ) ) fsm.act("INSERT", self.source.valid.eq(1), chooser(preamble, cnt, self.source.data), If(cnt == cnt_max, If(self.source.ready, NextState("COPY")) ).Else( inc_cnt.eq(self.source.ready) ) ) 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.valid & self.sink.last & self.source.ready, NextState("IDLE"), ) )
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) ) fsm = FSM(reset_state="IDLE") self.submodules += fsm fsm.act("IDLE", self.sink.ready.eq(1), clr_cnt.eq(1), If(self.sink.valid, self.sink.ready.eq(0), NextState("INSERT"), ) ) fsm.act("INSERT", self.source.valid.eq(1), chooser(preamble, cnt, self.source.data), If(cnt == cnt_max, If(self.source.ready, NextState("COPY")) ).Else( inc_cnt.eq(self.source.ready) ) ) 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.sink.valid & self.sink.last & self.source.ready, NextState("IDLE"), ) )
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, cachesize, master, slave): self.master = master self.slave = slave ### dw_from = len(master.dat_r) dw_to = len(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 = len(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): self.sink = sink = stream.Endpoint([("data", 128)]) self.source = source = stream.Endpoint([("data", 16)]) # # # # 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.valid & sink.ready) ] 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.ready.eq(1), If(sink.valid, 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.valid.eq(1), source.last.eq((h_read == 7) & (v_read == 7)), If(source.ready, 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, 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, phy, clk_freq): self.wishbone = wishbone.Interface() # # # byte_counter = Signal(3) byte_counter_reset = Signal() byte_counter_ce = Signal() self.sync += If(byte_counter_reset, byte_counter.eq(0)).Elif(byte_counter_ce, byte_counter.eq(byte_counter + 1)) word_counter = Signal(3) word_counter_reset = Signal() word_counter_ce = Signal() self.sync += If(word_counter_reset, word_counter.eq(0)).Elif(word_counter_ce, word_counter.eq(word_counter + 1)) 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 = ResetInserter()(FSM(reset_state="IDLE")) timer = WaitTimer(clk_freq // 10) self.submodules += fsm, timer self.comb += [fsm.reset.eq(timer.done), phy.source.ready.eq(1)] fsm.act( "IDLE", If( phy.source.valid, 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.valid, length_ce.eq(1), NextState("RECEIVE_ADDRESS"))) fsm.act( "RECEIVE_ADDRESS", If( phy.source.valid, address_ce.eq(1), byte_counter_ce.eq(1), If( byte_counter == 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.valid, rx_data_ce.eq(1), byte_counter_ce.eq(1), If(byte_counter == 3, NextState("WRITE_DATA"), byte_counter_reset.eq(1)), ), ) self.comb += [ self.wishbone.adr.eq(address + word_counter), self.wishbone.dat_w.eq(data), self.wishbone.sel.eq(2 ** len(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 == (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, phy.sink.data, n=4, reverse=True) fsm.act( "SEND_DATA", phy.sink.valid.eq(1), If( phy.sink.ready, byte_counter_ce.eq(1), If( byte_counter == 3, word_counter_ce.eq(1), If(word_counter == (length - 1), NextState("IDLE")).Else( NextState("READ_DATA"), byte_counter_reset.eq(1) ), ), ), ) self.comb += timer.wait.eq(~fsm.ongoing("IDLE")) self.comb += phy.sink.last.eq((byte_counter == 3) & (word_counter == length - 1)) if hasattr(phy.sink, "length"): self.comb += phy.sink.length.eq(4 * length)
def __init__(self, cachesize, master, slave): self.master = master self.slave = slave ### dw_from = len(master.dat_r) dw_to = len(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 = len(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, mem_or_size, address, read_only=None, init=None, bus=None): if bus is None: bus = Interface() self.bus = bus data_width = len(self.bus.dat_w) 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 ### 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 + len(port.adr)]) else: pv = self._page.storage self.comb += port.adr.eq( Cat( self.bus.adr[word_bits:word_bits + len(port.adr) - len(pv)], pv))
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.ready.eq(1), clr_cnt.eq(1), clr_discard.eq(1), If(self.sink.valid, clr_cnt.eq(0), inc_cnt.eq(1), clr_discard.eq(0), set_discard.eq(~match), NextState("CHECK"), ) ) fsm.act("CHECK", self.sink.ready.eq(1), If(self.sink.valid, 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.valid & self.source.last & self.source.ready, NextState("IDLE"), ) )
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"): 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) 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 bus is None: bus = Interface() self.bus = bus data_width = len(self.bus.dat_w) 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 ### 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+len(port.adr)]) else: pv = self._page.storage self.comb += port.adr.eq(Cat(self.bus.adr[word_bits:word_bits+len(port.adr)-len(pv)], pv))
def __init__(self, phy, clk_freq): self.wishbone = wishbone.Interface() # # # byte_counter = Signal(3) byte_counter_reset = Signal() byte_counter_ce = Signal() self.sync += \ If(byte_counter_reset, byte_counter.eq(0) ).Elif(byte_counter_ce, byte_counter.eq(byte_counter + 1) ) word_counter = Signal(3) word_counter_reset = Signal() word_counter_ce = Signal() self.sync += \ If(word_counter_reset, word_counter.eq(0) ).Elif(word_counter_ce, word_counter.eq(word_counter + 1) ) 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 = ResetInserter()(FSM(reset_state="IDLE")) timer = WaitTimer(clk_freq // 10) self.submodules += fsm, timer self.comb += [fsm.reset.eq(timer.done), phy.source.ready.eq(1)] fsm.act( "IDLE", If( phy.source.valid, 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.valid, length_ce.eq(1), NextState("RECEIVE_ADDRESS"))) fsm.act( "RECEIVE_ADDRESS", If( phy.source.valid, address_ce.eq(1), byte_counter_ce.eq(1), If( byte_counter == 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.valid, rx_data_ce.eq(1), byte_counter_ce.eq(1), If(byte_counter == 3, NextState("WRITE_DATA"), byte_counter_reset.eq(1)))) self.comb += [ self.wishbone.adr.eq(address + word_counter), self.wishbone.dat_w.eq(data), self.wishbone.sel.eq(2**len(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 == (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, phy.sink.data, n=4, reverse=True) fsm.act( "SEND_DATA", phy.sink.valid.eq(1), If( phy.sink.ready, byte_counter_ce.eq(1), If( byte_counter == 3, word_counter_ce.eq(1), If(word_counter == (length - 1), NextState("IDLE")).Else(NextState("READ_DATA"), byte_counter_reset.eq(1))))) self.comb += timer.wait.eq(~fsm.ongoing("IDLE")) self.comb += phy.sink.last.eq((byte_counter == 3) & (word_counter == length - 1)) if hasattr(phy.sink, "length"): self.comb += phy.sink.length.eq(4 * length)
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.ready.eq(1), clr_cnt.eq(1), clr_discard.eq(1), If(self.sink.valid, clr_cnt.eq(0), inc_cnt.eq(1), clr_discard.eq(0), set_discard.eq(~match), NextState("CHECK"), ) ) fsm.act("CHECK", self.sink.ready.eq(1), If(self.sink.valid, 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, omit=set(["data", "last_be"])), If(self.source.valid & self.source.last & self.source.ready, NextState("IDLE"), ) )
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) ### 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.comb += [ pads.scl.w.eq(0), pads.scl.oe.eq(_scl_drv_reg), _scl_i_async.eq(pads.scl.r), pads.sda.w.eq(0), pads.sda.oe.eq(_sda_drv_reg), _sda_i_async.eq(pads.sda.r), ] self.specials += [ 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")))