def implement_fsm(states): stnames = ["S" + str(i) for i in range(len(states))] fsm = FSM(*stnames) lans = _LowerAbstractNextState(fsm, states, stnames) for i, state in enumerate(states): actions = lans.visit(state) fsm.act(getattr(fsm, stnames[i]), *actions) return fsm
def __init__(self, plat): neopixel_gpio = [('neopixel', 0, Subsignal('tx', Pins('PMOD:0')), IOStandard('LVCMOS33'))] plat.add_extension(neopixel_gpio) neopixel_pads = plat.request('neopixel') leds = plat.request('user_led') serial_pads = plat.request('serial') self.submodules.uart = UART(serial_pads, baud_rate=115200, clk_freq=12000000) self.submodules.restrider = Restrider() data = Signal(8) self.submodules.uart_fsm = FSM() self.uart_fsm.act( 'RX', If( self.uart.rx_ready, self.uart.rx_ack.eq(1), NextValue(data, self.uart.rx_data), NextState('INGEST'), )) self.comb += self.restrider.data_in.eq(data) self.uart_fsm.act( 'INGEST', self.restrider.latch_data.eq(1), NextState('RX'), ) N_PIXELS = 8 self.submodules.fifo = SyncFIFOBuffered(24, N_PIXELS) pixel_data = Signal(24) self.submodules.slurp_fsm = FSM() self.slurp_fsm.act( 'IDLE', self.fifo.we.eq(0), If( self.restrider.done, self.restrider.out_read_ack.eq(1), NextValue(pixel_data, self.restrider.data_out), NextState('CHUNK'), )) self.comb += self.fifo.din.eq(pixel_data) self.slurp_fsm.act( 'CHUNK', If( self.fifo.writable, self.fifo.we.eq(1), ), NextState('IDLE'), ) self.submodules.neopixels = WS2812Controller(neopixel_pads, self.fifo, 12000000) self.comb += self.neopixels.write_en.eq(self.fifo.level == N_PIXELS)
def __init__(self): self.underflow = CSR() self.error_channel = CSRStatus(24) self.error_timestamp = CSRStatus(64) self.error_address = CSRStatus(16) self.sink = stream.Endpoint(record_layout) self.cri = cri.Interface() self.busy = Signal() # # # underflow_trigger = Signal() self.sync += [ If(underflow_trigger, self.underflow.w.eq(1), self.error_channel.status.eq(self.sink.channel), self.error_timestamp.status.eq(self.sink.timestamp), self.error_address.status.eq(self.sink.address)), If(self.underflow.re, self.underflow.w.eq(0)) ] self.comb += [ self.cri.chan_sel.eq(self.sink.channel), self.cri.timestamp.eq(self.sink.timestamp), self.cri.o_address.eq(self.sink.address), self.cri.o_data.eq(self.sink.data) ] fsm = FSM(reset_state="IDLE") self.submodules += fsm fsm.act( "IDLE", If( ~self.underflow.w, If( self.sink.stb, If( self.sink.eop, # last packet contains dummy data, discard it self.sink.ack.eq(1)).Else(NextState("WRITE")))).Else( # discard all data until errors are acked self.sink.ack.eq(1))) fsm.act("WRITE", self.busy.eq(1), self.cri.cmd.eq(cri.commands["write"]), NextState("CHECK_STATE")) fsm.act( "CHECK_STATE", self.busy.eq(1), If(self.cri.o_status == 0, self.sink.ack.eq(1), NextState("IDLE")), If(self.cri.o_status[1], NextState("UNDERFLOW"))) fsm.act("UNDERFLOW", self.busy.eq(1), underflow_trigger.eq(1), self.sink.ack.eq(1), NextState("IDLE"))
def __init__(self): self.busy = Signal() self.sink = Sink(CMD_REC) self.source = Source([('d',8), ('last',1)]) sm = FSM(reset_state="IDLE") self.submodules += sm self.comb += [ self.source.stb.eq(0), self.source.payload.last.eq(0) ] ssum = Signal(8) token_next = Record(CMD_REC) token = Record(CMD_REC) self.comb += token_next.eq(token) self.sync += token.eq(token_next) sm.act("IDLE", If(self.sink.stb, self.sink.ack.eq(1), token_next.eq(self.sink.payload), NextState('c0'))) _outs = [ 0x55, Cat(token.a[8:14], 0, token.wr), token.a[0:8], token.d, ssum ] s = _outs[0] for i in _outs[1:-1]: s = s + i self.sync += ssum.eq(s) for c, v in enumerate(_outs): _last = 1 if c == len(_outs) - 1 else 0 _next = "IDLE" if _last else "c%d" % (c + 1) sm.act("c%d" % c, self.source.stb.eq(1), self.source.payload.d.eq(v), self.source.payload.last.eq(_last), If(self.source.ack, NextState(_next) ))
def __init__(self, sink_description, source_description, header): self.sink = sink = stream.Endpoint(sink_description) self.source = source = stream.Endpoint(source_description) self.header = Signal(header.length * 8) # # # dw = len(self.sink.data) header_reg = Signal(header.length * 8, reset_less=True) header_words = (header.length * 8) // dw load = Signal() shift = Signal() counter = Signal(max=max(header_words, 2)) counter_reset = Signal() counter_ce = Signal() self.sync += \ If(counter_reset, counter.eq(0) ).Elif(counter_ce, counter.eq(counter + 1) ) self.comb += header.encode(sink, self.header) if header_words == 1: self.sync += [If(load, header_reg.eq(self.header))] else: self.sync += [ If(load, header_reg.eq(self.header)).Elif( shift, header_reg.eq(Cat(header_reg[dw:], Signal(dw)))) ] fsm = FSM(reset_state="IDLE") self.submodules += fsm if header_words == 1: idle_next_state = "COPY" else: idle_next_state = "SEND_HEADER" fsm.act( "IDLE", sink.ready.eq(1), counter_reset.eq(1), If( sink.valid, sink.ready.eq(0), source.valid.eq(1), source.last.eq(0), source.data.eq(self.header[:dw]), If(source.valid & source.ready, load.eq(1), NextState(idle_next_state)))) if header_words != 1: fsm.act( "SEND_HEADER", source.valid.eq(1), source.last.eq(0), source.data.eq(header_reg[dw:2 * dw]), If(source.valid & source.ready, shift.eq(1), counter_ce.eq(1), If(counter == header_words - 2, NextState("COPY")))) if hasattr(sink, "error"): self.comb += source.error.eq(sink.error) fsm.act( "COPY", source.valid.eq(sink.valid), source.last.eq(sink.last), source.data.eq(sink.data), If(source.valid & source.ready, sink.ready.eq(1), If(source.last, NextState("IDLE"))))
def __init__(self, stream_slicer): self.source = stream.Endpoint(record_layout) self.end_marker_found = Signal() self.flush = Signal() hdrlen = (layout_len(record_layout) - 512)//8 record_raw = Record(record_layout) self.comb += [ record_raw.raw_bits().eq(stream_slicer.source), self.source.channel.eq(record_raw.channel), self.source.timestamp.eq(record_raw.timestamp), self.source.address.eq(record_raw.address), Case(record_raw.length, {hdrlen+i: self.source.data.eq(record_raw.data[:i*8]) for i in range(1, 512//8+1)}), ] fsm = FSM(reset_state="FLOWING") self.submodules += fsm fsm.act("FLOWING", If(stream_slicer.source_stb, If(record_raw.length == 0, NextState("END_MARKER_FOUND") ).Else( self.source.stb.eq(1) ) ), If(self.source.ack, stream_slicer.source_consume.eq(record_raw.length) ) ) fsm.act("END_MARKER_FOUND", self.end_marker_found.eq(1), If(self.flush, stream_slicer.flush.eq(1), NextState("WAIT_FLUSH") ) ) fsm.act("WAIT_FLUSH", If(stream_slicer.flush_done, NextState("SEND_EOP") ) ) fsm.act("SEND_EOP", self.source.eop.eq(1), self.source.stb.eq(1), If(self.source.ack, NextState("FLOWING")) )
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) self.submodules += crc ratio = crc.width // dw error = Signal() fifo = InsertReset(SyncFIFO(layout, ratio + 1)) self.submodules += fifo fsm = FSM(reset_state="RESET") self.submodules += fsm fifo_in = Signal() fifo_out = Signal() fifo_full = Signal() self.comb += [ fifo_full.eq(fifo.fifo.level == ratio), fifo_in.eq(sink.stb & (~fifo_full | fifo_out)), fifo_out.eq(source.stb & source.ack), Record.connect(sink, fifo.sink), fifo.sink.stb.eq(fifo_in), self.sink.ack.eq(fifo_in), source.stb.eq(sink.stb & fifo_full), source.sop.eq(fifo.source.sop), source.eop.eq(sink.eop), fifo.source.ack.eq(fifo_out), source.payload.eq(fifo.source.payload), source.error.eq(sink.error | crc.error), ] fsm.act( "RESET", crc.reset.eq(1), fifo.reset.eq(1), NextState("IDLE"), ) fsm.act( "IDLE", crc.data.eq(sink.data), If(sink.stb & sink.sop & sink.ack, crc.ce.eq(1), NextState("COPY"))) fsm.act( "COPY", crc.data.eq(sink.data), If(sink.stb & sink.ack, crc.ce.eq(1), If(sink.eop, NextState("RESET")))) self.comb += self.busy.eq(~fsm.ongoing("IDLE"))
def __init__(self, wishbone, lasmim): ### # Control FSM self.submodules.fsm = fsm = FSM(reset_state="IDLE") fsm.act("IDLE", If(wishbone.cyc & wishbone.stb, NextState("REQUEST"))) fsm.act( "REQUEST", lasmim.stb.eq(1), lasmim.we.eq(wishbone.we), If( lasmim.req_ack, If(wishbone.we, NextState("WRITE_DATA")).Else(NextState("READ_DATA")))) fsm.act( "WRITE_DATA", If(lasmim.dat_w_ack, lasmim.dat_we.eq(wishbone.sel), wishbone.ack.eq(1), NextState("IDLE"))) fsm.act("READ_DATA", If(lasmim.dat_r_ack, wishbone.ack.eq(1), NextState("IDLE"))) # Address / Datapath self.comb += [ lasmim.adr.eq(wishbone.adr), If( lasmim.dat_w_ack, lasmim.dat_w.eq(wishbone.dat_w), ), wishbone.dat_r.eq(lasmim.dat_r) ]
def __init__(self, base, data=300, idle=1000): self.source = Source([('d', 8), ('last', 1)]) self.submodules.dummy = FSM() dummy_count = Signal(max=max(idle, data)) dummy_count_next = Signal(max=max(idle, data)) self.sync += dummy_count.eq(dummy_count_next) self.comb += dummy_count_next.eq(dummy_count) self.dummy.act("S0", self.source.payload.d.eq(base + 0), self.source.stb.eq(1), dummy_count_next.eq(0), If(self.source.ack, NextState("S1"))) self.dummy.act("S1", self.source.payload.d.eq(base + 1), self.source.stb.eq(1), If(self.source.ack, NextState("S2"))) self.dummy.act( "S2", self.source.payload.d.eq(dummy_count[0:8]), self.source.stb.eq(1), If( self.source.ack, If(dummy_count != data, dummy_count_next.eq(dummy_count_next + 1)).Else( dummy_count_next.eq(0), self.source.payload.last.eq(1), NextState("S3")))) self.dummy.act( "S3", If(dummy_count != idle, dummy_count_next.eq(dummy_count_next + 1)).Else( dummy_count_next.eq(0), NextState("S0")))
def __init__(self): self.ctrl = Signal() self.data = Signal() self.status = Signal(8) self.submodules.dut = FSM() self.dut.act( "IDLE", If(self.ctrl, NextState("START") ) ) self.dut.act( "START", If( self.data, NextState("SET-STATUS-LOW") ).Else( NextState("SET-STATUS") ) ) self.dut.act( "SET-STATUS", NextValue(self.status, 0xaa), NextState("IDLE") ) self.dut.act( "SET-STATUS-LOW", NextValue(self.status[:4], 0xb), NextState("IDLE") )
def __init__(self, syncword): self.sink = stream.Endpoint([ ("data", 8), ]) self.source = stream.Endpoint([ ("data", 8), ]) ### self.submodules.fsm = FSM(reset_state="DATA") self.fsm.act( "DATA", self.source.payload.data.eq(self.sink.payload.data), self.source.stb.eq(self.sink.stb), self.sink.ack.eq(self.source.ack), If( self.sink.stb & self.sink.ack & self.sink.eop, NextState("SYNC"), ), ) self.fsm.act( "SYNC", self.source.payload.data.eq(syncword), self.source.stb.eq(1), self.sink.ack.eq(0), If( self.source.stb & self.source.ack, NextState("DATA"), ), )
def __init__(self, update, counts, rtlink_i): self.gate = Signal(len(counts)) # # # gate = Signal(len(counts)) sentinel = 2**(len(rtlink_i.data) - 1) fsm = ClockDomainsRenamer("rio")(FSM()) self.submodules += fsm fsm.act("INIT", rtlink_i.data.eq(sentinel), If(update & (self.gate != 0), NextValue(gate, self.gate), rtlink_i.stb.eq(1), NextState(0) ) ) for n, count in enumerate(counts): last = n == len(counts)-1 fsm.act(n, rtlink_i.data.eq(count), rtlink_i.stb.eq(gate[n]), NextState("INIT" if last else n+1) )
def __init__(self, sys_clk_freq): self.qpll_reset = Signal() self.qpll_lock = Signal() self.tx_reset = Signal() self.done = Signal() # Handle async signals qpll_reset = Signal() tx_reset = Signal() self.sync += [ self.qpll_reset.eq(qpll_reset), self.tx_reset.eq(tx_reset) ] self.qpll_reset.attr.add("no_retiming") self.tx_reset.attr.add("no_retiming") qpll_lock = Signal() self.specials += MultiReg(self.qpll_lock, qpll_lock) # After configuration, transceiver resets have to stay low for # at least 500ns. # See https://www.xilinx.com/support/answers/43482.html timer_max = ceil(500e-9*sys_clk_freq) timer = Signal(max=timer_max+1) tick = Signal() self.sync += [ tick.eq(0), If(timer == timer_max, tick.eq(1), timer.eq(0) ).Else( timer.eq(timer + 1) ) ] fsm = FSM() self.submodules += fsm fsm.act("WAIT", If(tick, NextState("QPLL_RESET")) ) fsm.act("QPLL_RESET", tx_reset.eq(1), qpll_reset.eq(1), If(tick, NextState("WAIT_QPLL_LOCK")) ) fsm.act("WAIT_QPLL_LOCK", tx_reset.eq(1), If(qpll_lock & tick, NextState("DONE")) ) fsm.act("DONE", self.done.eq(1) )
def __init__(self, in_size, out_size, granularity): g = granularity self.sink = stream.Endpoint([("data", in_size * g)]) self.source = Signal(out_size * g) self.source_stb = Signal() self.source_consume = Signal(max=out_size + 1) self.flush = Signal() self.flush_done = Signal() # # # # worst-case buffer space required (when loading): # <data being shifted out> <new incoming word> buf_size = out_size - 1 + in_size buf = Signal(buf_size * g) self.comb += self.source.eq(buf[:out_size * g]) level = Signal(max=buf_size + 1) next_level = Signal(max=buf_size + 1) self.sync += level.eq(next_level) self.comb += next_level.eq(level) load_buf = Signal() shift_buf = Signal() self.sync += [ If( load_buf, Case( level, { i: buf[i * g:(i + in_size) * g].eq( _reverse_bytes(self.sink.data, g)) for i in range(out_size) })), If( shift_buf, Case(self.source_consume, {i: buf.eq(buf[i * g:]) for i in range(out_size)})), ] fsm = FSM(reset_state="FETCH") self.submodules += fsm fsm.act("FETCH", self.sink.ack.eq(1), load_buf.eq(1), If(self.sink.stb, next_level.eq(level + in_size)), If(next_level >= out_size, NextState("OUTPUT"))) fsm.act("OUTPUT", self.source_stb.eq(1), shift_buf.eq(1), next_level.eq(level - self.source_consume), If(next_level < out_size, NextState("FETCH")), If(self.flush, NextState("FLUSH"))) fsm.act( "FLUSH", next_level.eq(0), self.sink.ack.eq(1), If(self.sink.stb & self.sink.eop, self.flush_done.eq(1), NextState("FETCH")))
def __init__(self): self.s = Signal() myfsm = FSM() self.submodules += myfsm myfsm.act("FOO", self.s.eq(1), NextState("BAR")) myfsm.act("BAR", self.s.eq(0), NextState("FOO")) self.be = myfsm.before_entering("FOO") self.ae = myfsm.after_entering("FOO") self.bl = myfsm.before_leaving("FOO") self.al = myfsm.after_leaving("FOO")
def __init__(self, has_completion=True): self.cmd = Endpoint(CMD_REC) self.sink = self.cmd if has_completion: self.completion = Endpoint(CMD_REC) self.source = self.completion self.master = Interface() self.busy = Signal() self.comb += [ self.cmd.ack.eq(0) ] samp_comp = Signal() if has_completion: self.sync += If(self.cmd.ack, self.completion.payload.a.eq(self.cmd.payload.a), self.completion.payload.wr.eq(self.cmd.payload.wr), If(self.cmd.payload.wr, self.completion.payload.d.eq(self.master.dat_w)) ) self.sync += If(samp_comp & ~self.completion.payload.wr, self.completion.payload.d.eq(self.master.dat_r)) fsm = FSM() fsm.act("IDLE", If(self.cmd.stb, self.cmd.ack.eq(1), self.master.we.eq(self.cmd.payload.wr), self.master.adr.eq(self.cmd.payload.a), self.master.dat_w.eq(self.cmd.payload.d), NextState("READ"))) fsm.act("READ", samp_comp.eq(1), NextState("WAIT")) if has_completion: fsm.act("WAIT", self.completion.stb.eq(1), If(self.completion.ack, NextState("IDLE"))) else: fsm.act("WAIT", NextState("IDLE")) self.submodules += fsm
def __init__(self, pins, out_fifo, in_fifo, period_cyc): jtag_oe = Signal(len(pins)) jtag_o = Signal(len(pins)) jtag_i = Signal(len(pins)) self.comb += [ Cat(pin.oe for pin in pins).eq(jtag_oe), Cat(pin.o for pin in pins).eq(jtag_o), ] self.specials += MultiReg(Cat(pin.i for pin in pins), jtag_i) timer = Signal(max=period_cyc) cmd = Signal(8) self.submodules.fsm = FSM(reset_state="RECV-COMMAND") self.fsm.act("RECV-COMMAND", If(out_fifo.readable, out_fifo.re.eq(1), NextValue(cmd, out_fifo.dout), If(out_fifo.dout == CMD_W, NextValue(timer, period_cyc - 1), NextState("WAIT") ).Elif(out_fifo.dout == CMD_I, NextState("INPUT") ).Else( NextState("RECV-DATA") ) ) ) self.fsm.act("RECV-DATA", If(out_fifo.readable, out_fifo.re.eq(1), If(cmd == CMD_OE, NextValue(jtag_oe, out_fifo.dout) ).Elif(cmd == CMD_O, NextValue(jtag_o, out_fifo.dout) ).Elif(cmd == CMD_L, NextValue(jtag_o, ~out_fifo.dout & jtag_o) ).Elif(cmd == CMD_H, NextValue(jtag_o, out_fifo.dout | jtag_o) ), NextState("RECV-COMMAND") ) ) self.fsm.act("WAIT", If(timer == 0, NextState("RECV-COMMAND") ).Else( NextValue(timer, timer - 1) ) ) self.fsm.act("INPUT", If(in_fifo.writable, in_fifo.we.eq(1), in_fifo.din.eq(jtag_i), NextState("RECV-COMMAND") ) )
def __init__(self, mem_depth=4 * (1 << 10)): # XC3S500E: 20x18bx1024 self.specials.mem = Memory(width=16, depth=mem_depth) self.specials.read = read = self.mem.get_port() self.source = Source(line_layout) self.arm = Signal() self.start = Signal() self.frame = Signal(3) ### adr = Signal.like(read.adr) inc = Signal() lp = self.source.payload raw = Signal.like(lp.raw_bits()) self.comb += lp.raw_bits().eq(raw) lpa = Array([ raw[i:i + flen(read.dat_r)] for i in range(0, flen(raw), flen(read.dat_r)) ]) data_read = Signal.like(lp.header.length) self.submodules.fsm = fsm = FSM(reset_state="JUMP") fsm.act("JUMP", read.adr.eq(self.frame), If(self.start, NextState("FRAME"))) fsm.act( "FRAME", read.adr.eq(read.dat_r), inc.eq(1), If(read.dat_r == 0, NextState("JUMP")).Else(NextState("HEADER"))) fsm.act("HEADER", read.adr.eq(adr), inc.eq(1), NextState("LINE")) fsm.act( "LINE", read.adr.eq(adr), If(data_read == lp.header.length, NextState("STB")).Else(inc.eq(1), )) fsm.act( "STB", read.adr.eq(adr), self.source.stb.eq(1), If(self.source.ack, inc.eq(1), If(lp.header.end, NextState("JUMP")).Else(NextState("HEADER"))), If(~self.arm, NextState("JUMP"))) self.sync += [ If( inc, adr.eq(read.adr + 1), ), If( fsm.ongoing("HEADER"), raw.eq(read.dat_r), data_read.eq(1), ), If( fsm.ongoing("LINE"), lpa[data_read].eq(read.dat_r), data_read.eq(data_read + 1), ) ]
def __init__(self, clock_pads, pads): self._reset = CSRStorage() # # # self.clock_domains.cd_eth_rx = ClockDomain() self.clock_domains.cd_eth_tx = ClockDomain() # RX dcm_reset = Signal() dcm_locked = Signal() timer = WaitTimer(1024) fsm = FSM(reset_state="DCM_RESET") self.submodules += timer, fsm fsm.act("DCM_RESET", dcm_reset.eq(1), timer.wait.eq(1), If(timer.done, timer.wait.eq(0), NextState("DCM_WAIT"))) fsm.act("DCM_WAIT", timer.wait.eq(1), If(timer.done, NextState("DCM_CHECK_LOCK"))) fsm.act("DCM_CHECK_LOCK", If(~dcm_locked, NextState("DCM_RESET"))) clk90_rx = Signal() clk0_rx = Signal() clk0_rx_bufg = Signal() self.specials += Instance("DCM", i_CLKIN=clock_pads.rx, i_CLKFB=clk0_rx_bufg, o_CLK0=clk0_rx, o_CLK90=clk90_rx, o_LOCKED=dcm_locked, i_PSEN=0, i_PSCLK=0, i_PSINCDEC=0, i_RST=dcm_reset) self.specials += Instance("BUFG", i_I=clk0_rx, o_O=clk0_rx_bufg) self.specials += Instance("BUFG", i_I=clk90_rx, o_O=self.cd_eth_rx.clk) # TX self.specials += DDROutput(1, 0, clock_pads.tx, ClockSignal("eth_tx")) self.specials += Instance("BUFG", i_I=self.cd_eth_rx.clk, o_O=self.cd_eth_tx.clk) # Reset reset = self._reset.storage self.comb += pads.rst_n.eq(~reset) self.specials += [ AsyncResetSynchronizer(self.cd_eth_tx, reset), AsyncResetSynchronizer(self.cd_eth_rx, reset), ]
def __init__(self, we_bit=28, sel_bits=slice(24, 28)): super(Wishbone, self).__init__() self.bus = bus = wishbone.Interface() ### start = Signal() read = Signal() self.sync += [ If( start, self.bus.adr.eq(self.dout.payload.addr), self.bus.dat_w.eq(self.dout.payload.data), ), If( read, self.din.payload.data.eq(self.bus.dat_r), ) ] self.comb += [ self.dout.ack.eq(1), self.din.payload.addr.eq(self.bus.adr), self.bus.cyc.eq(self.bus.stb), self.bus.we.eq(self.bus.adr[we_bit]), ] if sel_bits is not None: self.comb += self.bus.sel.eq(self.bus.adr[sel_bits]) else: self.bus.sel.reset = 0b1111 self.submodules.fsm = fsm = FSM() fsm.act("IDLE", If( self.dout.stb, start.eq(1), NextState("BUS"), )) fsm.act( "BUS", self.bus.stb.eq(1), If( self.bus.ack, If( self.bus.we, NextState("IDLE"), ).Else( read.eq(1), NextState("QUEUE"), ), )) fsm.act("QUEUE", self.din.stb.eq(1), If( self.din.ack, NextState("IDLE"), ))
def __init__(self, cycle_bits, data_bits, def_end_cycle=20): # I/O signals self.d = Signal() self.clk = Signal() # control signals self.pds = Signal() self.pdi = Signal(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 self.fsm = FSM() self.start_action = [NextState("TRANSFER_DATA")] self.end_action = [NextState("WAIT_DATA")] # registers self._pos_end_cycle = CSRStorage(cycle_bits, reset=def_end_cycle) self._pos_data = CSRStorage(cycle_bits, reset=0) ### # cycle counter and events cycle_counter = Signal(cycle_bits) self.cycle_counter_reset = Signal() self.comb += self.eoc.eq(cycle_counter == self._pos_end_cycle.storage) self.sync += If(self.eoc | self.cycle_counter_reset, cycle_counter.eq(0)).Else( cycle_counter.eq(cycle_counter + 1) ) self.comb += [ self.ev_clk_high.eq(cycle_counter == (self._pos_end_cycle.storage >> 1)), self.ev_clk_low.eq(cycle_counter == self._pos_end_cycle.storage), self.ev_data.eq(cycle_counter == self._pos_data.storage), ] # data sr = Signal(data_bits) self.sr_load = Signal() self.sr_shift = Signal() self.remaining_data = Signal(max=data_bits + 1) self.sync += If(self.sr_load, sr.eq(self.pdi), self.remaining_data.eq(data_bits)).Elif( self.sr_shift, sr.eq(sr[1:]), self.d.eq(sr[0]), self.remaining_data.eq(self.remaining_data - 1) ) # clock clk_p = Signal() self.sync += [If(self.clk_high, clk_p.eq(1)).Elif(self.clk_low, clk_p.eq(0)), self.clk.eq(clk_p)]
def __init__(self): self._size = CSRStorage(8, reset=8) self._cfg = CSRStorage(1, reset=0) self.source = Endpoint([('d', 8), ('last', 1)]) START_BYTE = 0xAA self.lfsr_state = Signal(17) self.lfsr_state_next = Signal(17) self.sync += If(~self._cfg.storage[0], self.lfsr_state.eq(1)).Else( self.lfsr_state.eq(self.lfsr_state_next)) self.bytecount = Signal(8) self.bytecount_next = Signal(8) self.comb += [ self.lfsr_state_next.eq(self.lfsr_state), self.bytecount_next.eq(self.bytecount), self.source.payload.last.eq(0) ] self.sync += self.bytecount.eq(self.bytecount_next) self.submodules.fsm = FSM() self.fsm.act("IDLE", If(self._cfg.storage[0], NextState("SEND_HEAD"))) self.fsm.act("SEND_HEAD", self.source.payload.d.eq(0xAA), self.source.stb.eq(1), If(self.source.ack, NextState("SEND_SIZE"))) self.fsm.act( "SEND_SIZE", self.source.payload.d.eq(self._size.storage), self.source.stb.eq(1), If(self.source.ack, self.bytecount_next.eq(0), NextState("SEND_DATA")), ) self.fsm.act( "SEND_DATA", self.source.payload.d.eq(self.lfsr_state), self.source.stb.eq(1), If(self.bytecount + 1 == self._size.storage, self.source.payload.last.eq(1)), If( self.source.ack, self.lfsr_state_next.eq( Cat( self.lfsr_state[16] ^ self.lfsr_state[14] ^ self.lfsr_state[13] ^ self.lfsr_state[11], self.lfsr_state)), self.bytecount_next.eq(self.bytecount + 1), If(self.bytecount + 1 == self._size.storage, NextState("IDLE"))))
def __init__(self): self.busy=Signal() self.sink = Sink([('d',8)]) self.source = Source(CMD_REC) sm = FSM(reset_state="IDLE") self.submodules += sm # Basic checksum token = self.source.payload token_next = Record(CMD_REC) self.sync += token.eq(token_next) self.comb += token_next.eq(token) sm.act("IDLE", self.sink.ack.eq(1), If(self.sink.stb, If(self.sink.payload.d == 0x55, NextState("ADRH") ))) def parse_state(st, to, *update): sm.act(st, self.sink.ack.eq(1), If(self.sink.stb, NextState(to), *update )) parse_state('ADRH', 'ADRL', token_next.wr.eq(self.sink.payload.d[7]), token_next.a[8:14].eq(self.sink.payload.d[:6])) parse_state('ADRL', 'DATA', token_next.a[0:8].eq(self.sink.payload.d)), parse_state('DATA', 'CKSUM', token_next.d.eq(self.sink.payload.d)), sm.act("CKSUM", self.sink.ack.eq(1), If(self.sink.stb, NextState('ISSUE') ) ) sm.act("ISSUE", self.source.stb.eq(1), If(self.source.ack, NextState('IDLE')))
def __init__(self, port, depth): self.sink = Sink(dmatpl(depth)) self.source = Source(D_LAST) self.busy = Signal() self.pos = Signal(max=depth, reset=0) self.pos_next = Signal(max=depth, reset=0) self.ct = Signal(max=depth, reset=0) self.ct_next = Signal(max=depth) self.comb += [ self.ct_next.eq(self.ct), self.pos_next.eq(self.pos), port.adr.eq(self.pos_next), ] self.sync += [ self.pos.eq(self.pos_next), self.ct.eq(self.ct_next) ] self.submodules.fsm = FSM() self.fsm.act("IDLE", self.busy.eq(0), If(self.sink.stb, self.busy.eq(1), self.sink.ack.eq(1), self.pos_next.eq(self.sink.payload.start), self.ct_next.eq(self.sink.payload.count-1), NextState('d'), ) ) self.fsm.act("d", self.busy.eq(1), self.source.stb.eq(1), self.source.payload.d.eq(port.dat_r), If(self.ct == 0, self.source.payload.last.eq(1)), If(self.source.ack, If(self.ct, _inc(self.pos, depth, self.pos_next), self.ct_next.eq(self.ct - 1), ).Else( NextState("IDLE") ) ) )
def __init__(self, bus_wishbone=None, bus_csr=None): if bus_wishbone is None: bus_wishbone = wishbone.Interface() self.wishbone = bus_wishbone if bus_csr is None: bus_csr = csr_bus.Interface() self.csr = bus_csr self.ack = Signal() self.en = Signal() # # # self.comb += [ self.csr.dat_w.eq(self.wishbone.dat_w), self.wishbone.dat_r.eq(self.csr.dat_r) ] count = Signal(8) fsm = FSM(reset_state="WRITE-READ") self.submodules += fsm fsm.act( "WRITE-READ", If( self.wishbone.cyc & self.wishbone.stb, self.csr.adr.eq(self.wishbone.adr), self.csr.we.eq(self.wishbone.we), self.en.eq(1), NextState("ACK"), )) fsm.act( "ACK", If(self.wishbone.we | self.ack, self.wishbone.ack.eq(1), NextState("WRITE-READ")))
def __init__(self, sys_clk_freq): self.qpll_reset = Signal() self.qpll_lock = Signal() self.tx_reset = Signal() self.done = Signal() # Handle async signals qpll_reset = Signal() tx_reset = Signal() self.sync += [ self.qpll_reset.eq(qpll_reset), self.tx_reset.eq(tx_reset) ] self.qpll_reset.attr.add("no_retiming") self.tx_reset.attr.add("no_retiming") qpll_lock = Signal() self.specials += MultiReg(self.qpll_lock, qpll_lock) # After configuration, transceiver resets have to stay low for # at least 500ns. # See https://www.xilinx.com/support/answers/43482.html timer_max = ceil(500e-9 * sys_clk_freq) timer = Signal(max=timer_max + 1) tick = Signal() self.sync += [ tick.eq(0), If(timer == timer_max, tick.eq(1), timer.eq(0)).Else(timer.eq(timer + 1)) ] fsm = FSM() self.submodules += fsm fsm.act("WAIT", If(tick, NextState("QPLL_RESET"))) fsm.act("QPLL_RESET", tx_reset.eq(1), qpll_reset.eq(1), If(tick, NextState("WAIT_QPLL_LOCK"))) fsm.act("WAIT_QPLL_LOCK", tx_reset.eq(1), If(qpll_lock & tick, NextState("DONE"))) fsm.act("DONE", self.done.eq(1))
def __init__(self, data_width=44, trigger_id_width=0, length=128): self.data_in = Signal(data_width) self.we = Signal() self.pretrigger = Signal(max=length - 1) self.posttrigger = Signal(max=length - 1) self.trigger = Signal() # trigger_id will be optimized out if not required self.trigger_id = Signal(max(trigger_id_width, 1)) # Trigger ID will be embedded into output data self.data_out = Signal(data_width + trigger_id_width) self.stb_out = Signal() # # # buffer = Memory(data_width + trigger_id_width, length) wr_port = buffer.get_port(write_capable=True) rd_port = buffer.get_port(has_re=True) self.specials += [buffer, wr_port, rd_port] self.wr_ptr = wr_ptr = Signal.like(wr_port.adr) self.rd_ptr = rd_ptr = Signal.like(rd_port.adr) trigger_id_d = Signal.like(self.trigger_id) readout_cnt = Signal(max=length - 1) readout_fsm = FSM("IDLE") self.submodules += readout_fsm readout_fsm.act( "IDLE", If(self.trigger == 1, NextState("READOUT"), NextValue(trigger_id_d, self.trigger_id), NextValue(rd_port.re, 1), NextValue(readout_cnt, self.pretrigger + self.posttrigger + 1)).Else( NextValue(rd_port.re, 0))) readout_fsm.act( "READOUT", If(readout_cnt != 0, NextValue(readout_cnt, readout_cnt - 1), NextValue(rd_port.re, 1), NextValue(self.stb_out, 1)).Else(NextState("IDLE"), NextValue(rd_port.re, 0), NextValue(self.stb_out, 0))) self.comb += [ wr_port.we.eq(self.we), wr_port.adr.eq(wr_ptr), # Will be truncated from left (MSB) wr_port.dat_w.eq(Cat(self.data_in, trigger_id_d)), rd_port.adr.eq(rd_ptr), self.data_out.eq(rd_port.dat_r) ] self.sync += [ If(self.we, rd_ptr.eq(wr_ptr - self.pretrigger), wr_ptr.eq(wr_ptr + 1)) ]
def __init__(self, pads): self.source = source = Source(eth_description(8)) ### sop = source.sop set_sop = Signal() clr_sop = Signal() self.sync += \ If(clr_sop, sop.eq(0) ).Elif(set_sop, sop.eq(1) ) lo = Signal(4) hi = Signal(4) load_nibble = Signal(2) self.sync += \ If(load_nibble[0], lo.eq(pads.rx_data) ).Elif(load_nibble[1], hi.eq(pads.rx_data) ) self.comb += [ source.d.eq(Cat(lo, hi)) ] fsm = FSM(reset_state="IDLE") self.submodules += fsm fsm.act("IDLE", set_sop.eq(1), If(pads.dv, load_nibble.eq(0b01), NextState("LOAD_HI") ) ) fsm.act("LOAD_LO", source.stb.eq(1), If(pads.dv, clr_sop.eq(1), load_nibble.eq(0b01), NextState("LOAD_HI") ).Else( source.eop.eq(1), NextState("IDLE") ) ) fsm.act("LOAD_HI", load_nibble.eq(0b10), NextState("LOAD_LO") )
def __init__(self, max_size, buffered=True): self.sink = sink = Sink(descriptor_layout()) if buffered: self.submodules.buffer = Buffer(descriptor_layout(True)) source = self.buffer.d self.source = self.buffer.q else: self.source = source = Source(descriptor_layout(True)) # # # offset = Signal(32) clr_offset = Signal() inc_offset = Signal() self.sync += \ If(clr_offset, offset.eq(0) ).Elif(inc_offset, offset.eq(offset + max_size) ) user_id = Signal(8) self.sync += \ If(sink.stb & sink.ack, user_id.eq(user_id+1) ) fsm = FSM(reset_state="IDLE") self.submodules += fsm length = Signal(16) update_length = Signal() self.sync += If(update_length, length.eq(sink.length)) fsm.act( "IDLE", sink.ack.eq(1), clr_offset.eq(1), If(sink.stb, update_length.eq(1), sink.ack.eq(0), NextState("RUN"))) fsm.act( "RUN", source.stb.eq(1), source.address.eq(sink.address + offset), source.user_id.eq(user_id), If((length - offset) > max_size, source.length.eq(max_size), inc_offset.eq(source.ack)).Else( source.length.eq(length - offset), If(source.ack, NextState("ACK")))) fsm.act("ACK", sink.ack.eq(1), NextState("IDLE"))
def __init__(self, maxlen=65536, data_width=256): self.sink_ctrl = sink_ctrl = stream.Endpoint( self.getControlInterfaceDescriptor(maxlen=maxlen)) self.go = Signal() self.length = Signal(max=maxlen) self.source = source = stream.Endpoint( K2MMPacket.packet_user_description(dw=data_width)) # # # beats = Signal(max=maxlen, reset_less=True) length = Signal.like(sink_ctrl.length) # Status Signal self.busy = busy = Signal() self.sync += busy.eq(sink_ctrl.valid | (sink_ctrl.ready == 0)) # Transition detection _go = Signal.like(self.go) _single_start = Signal() self.sync += _go.eq(self.go) self.comb += _single_start.eq(self.go & ~_go) fsm = FSM(reset_state="IDLE") fsm.act( "IDLE", sink_ctrl.ready.eq(1), If( sink_ctrl.valid | _single_start, NextState("RUN"), NextValue(length, sink_ctrl.length), NextValue(beats, 0), )) _last_sending = Signal() self.comb += _last_sending.eq(beats == length) fsm.act( "RUN", sink_ctrl.ready.eq(0), source.data.eq(Replicate(beats, data_width // len(beats))), source.length.eq((length + 1) * (data_width // 8)), source.pf.eq(1), source.valid.eq(1), source.first.eq(beats == 0), source.last.eq(_last_sending), source.last_be.eq(Replicate(_last_sending, data_width // 8)), If( source.ready == 1, If( _last_sending, NextState("IDLE"), ).Else(NextValue(beats, beats + 1))), ) self.submodules += fsm
def __init__(self, crc_class, layout): self.sink = sink = Sink(layout, True) self.source = source = Source(layout, True) self.busy = Signal() ### dw = flen(sink.d) self.submodules.crc = crc_class(dw) self.submodules.fsm = fsm = FSM(reset_state="IDLE") fsm.act("IDLE", self.crc.reset.eq(1), sink.ack.eq(1), If(sink.stb & sink.sop, sink.ack.eq(0), NextState("COPY"), ) ) fsm.act("COPY", self.crc.ce.eq(sink.stb & source.ack), self.crc.d.eq(sink.d), Record.connect(sink, source), source.eop.eq(0), If(sink.stb & sink.eop & source.ack, NextState("INSERT"), ) ) ratio = self.crc.width//dw cnt = Signal(max=ratio, reset=ratio-1) cnt_done = Signal() fsm.act("INSERT", source.stb.eq(1), chooser(self.crc.value, cnt, source.d, 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) ) self.comb += self.busy.eq(~fsm.ongoing("IDLE"))
def __init__(self, pads, params): self.params = p = params self.data = [ Signal(p.width, reset_less=True) for i in range(p.channels) ] # data to be output, MSB first self.start = Signal() # start transfer self.done = Signal() # transfer complete, next transfer can be # started ### assert p.clk >= 1 cnt = Signal(max=max(2, p.clk), reset_less=True) cnt_done = Signal() cnt_next = Signal() self.comb += cnt_done.eq(cnt == 0) self.sync += [ If(cnt_done, If(cnt_next, cnt.eq(p.clk - 1))).Else(cnt.eq(cnt - 1)) ] for i, d in enumerate(self.data): self.comb += getattr(pads, "mosi{}".format(i)).eq( d[-1]) # mosi = MSB of d bits = Signal(max=p.width + 1, reset_less=True) self.submodules.fsm = fsm = CEInserter()(FSM("IDLE")) self.comb += fsm.ce.eq(cnt_done) fsm.act("IDLE", self.done.eq(1), pads.cs_n.eq(1), If(self.start, cnt_next.eq(1), NextState("SETUP"))) fsm.act("SETUP", cnt_next.eq(1), If(bits == 0, NextState("IDLE")).Else(NextState("HOLD"))) fsm.act("HOLD", cnt_next.eq(1), pads.clk.eq(1), NextState("SETUP")) self.sync += [ If( fsm.ce, If( fsm.before_leaving("HOLD"), bits.eq(bits - 1), [d[1:].eq(d) for d in self.data] # shift d = d << 1 ), If(fsm.ongoing("IDLE"), bits.eq(p.width))) ]
def __init__(self, dw): self.sink = sink = Sink(tlp_raw_layout(dw)) self.source = source = Source(phy_layout(dw)) ### fsm = FSM(reset_state="HEADER1") self.submodules += fsm sink_dat_r = Signal(dw) sink_eop_r = Signal() self.sync += \ If(sink.stb & sink.ack, sink_dat_r.eq(sink.dat), sink_eop_r.eq(sink.eop) ) fsm.act( "HEADER1", sink.ack.eq(1), If(sink.stb & sink.sop, sink.ack.eq(0), source.stb.eq(1), source.sop.eq(1), source.eop.eq(0), source.dat.eq(sink.header[:64]), source.be.eq(0xff), If( source.stb & source.ack, NextState("HEADER2"), ))) fsm.act( "HEADER2", source.stb.eq(1), source.sop.eq(0), source.eop.eq(sink.eop), source.dat.eq(Cat(sink.header[64:96], reverse_bytes(sink.dat[:32]))), source.be.eq(Cat(Signal(4, reset=0xf), freversed(sink.be[:4]))), If(source.stb & source.ack, sink.ack.eq(1), If(source.eop, NextState("HEADER1")).Else(NextState("COPY")))) fsm.act( "COPY", source.stb.eq(sink.stb | sink_eop_r), source.sop.eq(0), source.eop.eq(sink_eop_r), source.dat.eq( Cat(reverse_bytes(sink_dat_r[32:64]), reverse_bytes(sink.dat[:32]))), If(sink_eop_r, source.be.eq(0x0f)).Else(source.be.eq(0xff)), If(source.stb & source.ack, sink.ack.eq(~sink_eop_r), If(source.eop, NextState("HEADER1"))))
def __init__(self): self.counter = Signal(8) myfsm = FSM() self.submodules += myfsm self.sync += self.counter.eq(self.counter + 1) self.sync += If(self.counter > 235, myfsm.act("COAST", If(self.counter == 240, NextState("IDLE")) )) myfsm.act("IDLE", If(self.counter == 10, NextState("START")) ) myfsm.act("START", If(self.counter == 100, NextState("RUNNING")) ) myfsm.act("RUNNING", If(self.counter == 200, NextState("COAST")) )
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 __init__(self, crc_class, layout): self.sink = sink = Sink(layout, True) self.source = source = Source(layout, True) self.busy = Signal() ### dw = flen(sink.d) self.submodules.crc = crc_class(dw) fsm = FSM(reset_state="RESET_CRC") self.submodules += fsm fsm.act("RESET_CRC", sink.ack.eq(0), self.crc.reset.eq(1), NextState("IDLE") ) fsm.act("IDLE", sink.ack.eq(sink.stb), If(sink.stb & sink.sop, Record.connect(sink, source), self.crc.ce.eq(sink.ack), self.crc.d.eq(sink.d), NextState("COPY") ) ) fsm.act("COPY", Record.connect(sink, source), self.crc.ce.eq(sink.stb & sink.ack), self.crc.d.eq(sink.d), source.error.eq(sink.eop & self.crc.error), If(sink.stb & sink.ack & sink.eop, NextState("RESET_CRC") ) ) self.comb += self.busy.eq(~fsm.ongoing("IDLE"))
def __init__(self, a, ba, tRP, tREFI, tRFC): self.req = Signal() self.ack = Signal() # 1st command 1 cycle after assertion of ack self.cmd = CommandRequest(a, ba) ### # Refresh sequence generator: # PRECHARGE ALL --(tRP)--> AUTO REFRESH --(tRFC)--> done seq_start = Signal() seq_done = Signal() self.sync += [ self.cmd.a.eq(2**10), self.cmd.ba.eq(0), self.cmd.cas_n.eq(1), self.cmd.ras_n.eq(1), self.cmd.we_n.eq(1), seq_done.eq(0) ] self.sync += timeline( seq_start, [(1, [self.cmd.ras_n.eq(0), self.cmd.we_n.eq(0)]), (1 + tRP, [self.cmd.cas_n.eq(0), self.cmd.ras_n.eq(0)]), (1 + tRP + tRFC, [seq_done.eq(1)])]) # Periodic refresh counter counter = Signal(max=tREFI) start = Signal() self.sync += [ start.eq(0), If(counter == 0, start.eq(1), counter.eq(tREFI - 1)).Else(counter.eq(counter - 1)) ] # Control FSM fsm = FSM() self.submodules += fsm fsm.act("IDLE", If(start, NextState("WAIT_GRANT"))) fsm.act("WAIT_GRANT", self.req.eq(1), If(self.ack, seq_start.eq(1), NextState("WAIT_SEQ"))) fsm.act("WAIT_SEQ", self.req.eq(1), If(seq_done, NextState("IDLE")))
def __init__(self, pads): self.sink = sink = Sink(eth_description(8)) ### tx_en_r = Signal() tx_data_r = Signal(4) self.sync += [ pads.tx_er.eq(0), pads.tx_en.eq(tx_en_r), pads.tx_data.eq(tx_data_r), ] fsm = FSM(reset_state="IDLE") self.submodules += fsm fsm.act("IDLE", sink.ack.eq(1), If(sink.stb & sink.sop, sink.ack.eq(0), NextState("SEND_LO") ) ) fsm.act("SEND_LO", tx_data_r.eq(sink.d[0:4]), tx_en_r.eq(1), NextState("SEND_HI") ) fsm.act("SEND_HI", tx_data_r.eq(sink.d[4:8]), tx_en_r.eq(1), sink.ack.eq(1), If(sink.stb & sink.eop, NextState("IDLE") ).Else( NextState("SEND_LO") ) )
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, 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): self.s = Signal() myfsm = FSM("FOO", "BAR") self.submodules += myfsm myfsm.act(myfsm.FOO, self.s.eq(1), myfsm.next_state(myfsm.BAR)) myfsm.act(myfsm.BAR, self.s.eq(0), myfsm.next_state(myfsm.FOO))
def __init__(self, geom_settings, timing_settings, address_align, bankn, req): self.refresh_req = Signal() self.refresh_gnt = Signal() self.cmd = CommandRequestRW(geom_settings.mux_a, geom_settings.bank_a) ### # Request FIFO self.submodules.req_fifo = SyncFIFO([("we", 1), ("adr", flen(req.adr))], timing_settings.req_queue_size) self.comb += [ self.req_fifo.din.we.eq(req.we), self.req_fifo.din.adr.eq(req.adr), self.req_fifo.we.eq(req.stb), req.req_ack.eq(self.req_fifo.writable), self.req_fifo.re.eq(req.dat_ack), req.lock.eq(self.req_fifo.readable), ] reqf = self.req_fifo.dout slicer = _AddressSlicer(geom_settings.col_a, address_align) # Row tracking has_openrow = Signal() openrow = Signal(geom_settings.row_a) hit = Signal() self.comb += hit.eq(openrow == slicer.row(reqf.adr)) track_open = Signal() track_close = Signal() self.sync += [ If(track_open, has_openrow.eq(1), openrow.eq(slicer.row(reqf.adr))), If(track_close, has_openrow.eq(0)), ] # Address generation s_row_adr = Signal() self.comb += [ self.cmd.ba.eq(bankn), If(s_row_adr, self.cmd.a.eq(slicer.row(reqf.adr))).Else(self.cmd.a.eq(slicer.col(reqf.adr))), ] # Respect write-to-precharge specification precharge_ok = Signal() t_unsafe_precharge = 2 + timing_settings.tWR - 1 unsafe_precharge_count = Signal(max=t_unsafe_precharge + 1) self.comb += precharge_ok.eq(unsafe_precharge_count == 0) self.sync += [ If(self.cmd.stb & self.cmd.ack & self.cmd.is_write, unsafe_precharge_count.eq(t_unsafe_precharge)).Elif( ~precharge_ok, unsafe_precharge_count.eq(unsafe_precharge_count - 1) ) ] # Control and command generation FSM fsm = FSM() self.submodules += fsm fsm.act( "REGULAR", If(self.refresh_req, NextState("REFRESH")).Elif( self.req_fifo.readable, If( has_openrow, If( hit, # NB: write-to-read specification is enforced by multiplexer self.cmd.stb.eq(1), req.dat_ack.eq(self.cmd.ack), self.cmd.is_read.eq(~reqf.we), self.cmd.is_write.eq(reqf.we), self.cmd.cas_n.eq(0), self.cmd.we_n.eq(~reqf.we), ).Else(NextState("PRECHARGE")), ).Else(NextState("ACTIVATE")), ), ) fsm.act( "PRECHARGE", # Notes: # 1. we are presenting the column address, A10 is always low # 2. since we always go to the ACTIVATE state, we do not need # to assert track_close. If( precharge_ok, self.cmd.stb.eq(1), If(self.cmd.ack, NextState("TRP")), self.cmd.ras_n.eq(0), self.cmd.we_n.eq(0), self.cmd.is_cmd.eq(1), ), ) fsm.act( "ACTIVATE", s_row_adr.eq(1), track_open.eq(1), self.cmd.stb.eq(1), self.cmd.is_cmd.eq(1), If(self.cmd.ack, NextState("TRCD")), self.cmd.ras_n.eq(0), ) fsm.act( "REFRESH", self.refresh_gnt.eq(precharge_ok), track_close.eq(1), self.cmd.is_cmd.eq(1), If(~self.refresh_req, NextState("REGULAR")), ) fsm.delayed_enter("TRP", "ACTIVATE", timing_settings.tRP - 1) fsm.delayed_enter("TRCD", "REGULAR", timing_settings.tRCD - 1)
def __init__(self, lasmim, nslots): bus_aw = lasmim.aw bus_dw = lasmim.dw alignment_bits = bits_for(bus_dw//8) - 1 fifo_word_width = 24*bus_dw//32 self.frame = Sink([("sof", 1), ("pixels", fifo_word_width)]) self._r_frame_size = CSRStorage(bus_aw + alignment_bits, alignment_bits=alignment_bits) self.submodules._slot_array = _SlotArray(nslots, bus_aw, alignment_bits) self.ev = self._slot_array.ev ### # address generator + maximum memory word count to prevent DMA buffer overrun reset_words = Signal() count_word = Signal() last_word = Signal() current_address = Signal(bus_aw) mwords_remaining = Signal(bus_aw) self.comb += [ self._slot_array.address_reached.eq(current_address), last_word.eq(mwords_remaining == 1) ] self.sync += [ If(reset_words, current_address.eq(self._slot_array.address), mwords_remaining.eq(self._r_frame_size.storage) ).Elif(count_word, current_address.eq(current_address + 1), mwords_remaining.eq(mwords_remaining - 1) ) ] # 24bpp -> 32bpp memory_word = Signal(bus_dw) pixbits = [] for i in range(bus_dw//32): for j in range(3): b = (i*3+j)*8 pixbits.append(self.frame.payload.pixels[b+6:b+8]) pixbits.append(self.frame.payload.pixels[b:b+8]) pixbits.append(0) pixbits.append(0) self.comb += memory_word.eq(Cat(*pixbits)) # bus accessor self.submodules._bus_accessor = dma_lasmi.Writer(lasmim) self.comb += [ self._bus_accessor.address_data.payload.a.eq(current_address), self._bus_accessor.address_data.payload.d.eq(memory_word) ] # control FSM fsm = FSM() self.submodules += fsm fsm.act("WAIT_SOF", reset_words.eq(1), self.frame.ack.eq(~self._slot_array.address_valid | ~self.frame.payload.sof), If(self._slot_array.address_valid & self.frame.payload.sof & self.frame.stb, NextState("TRANSFER_PIXELS")) ) fsm.act("TRANSFER_PIXELS", self.frame.ack.eq(self._bus_accessor.address_data.ack), If(self.frame.stb, self._bus_accessor.address_data.stb.eq(1), If(self._bus_accessor.address_data.ack, count_word.eq(1), If(last_word, NextState("EOF")) ) ) ) fsm.act("EOF", If(~self._bus_accessor.busy, self._slot_array.address_done.eq(1), NextState("WAIT_SOF") ) )
def __init__(self, clock_pads, pads): self._reset = CSRStorage() # # # self.clock_domains.cd_eth_rx = ClockDomain() self.clock_domains.cd_eth_tx = ClockDomain() # RX dcm_reset = Signal() dcm_locked = Signal() timer = WaitTimer(1024) fsm = FSM(reset_state="DCM_RESET") self.submodules += timer, fsm fsm.act("DCM_RESET", dcm_reset.eq(1), timer.wait.eq(1), If(timer.done, timer.wait.eq(0), NextState("DCM_WAIT") ) ) fsm.act("DCM_WAIT", timer.wait.eq(1), If(timer.done, NextState("DCM_CHECK_LOCK") ) ) fsm.act("DCM_CHECK_LOCK", If(~dcm_locked, NextState("DCM_RESET") ) ) clk90_rx = Signal() clk0_rx = Signal() clk0_rx_bufg = Signal() self.specials += Instance("DCM", i_CLKIN=clock_pads.rx, i_CLKFB=clk0_rx_bufg, o_CLK0=clk0_rx, o_CLK90=clk90_rx, o_LOCKED=dcm_locked, i_PSEN=0, i_PSCLK=0, i_PSINCDEC=0, i_RST=dcm_reset ) self.specials += Instance("BUFG", i_I=clk0_rx, o_O=clk0_rx_bufg) self.specials += Instance("BUFG", i_I=clk90_rx, o_O=self.cd_eth_rx.clk) # TX self.specials += DDROutput(1, 0, clock_pads.tx, ClockSignal("eth_tx")) self.specials += Instance("BUFG", i_I=self.cd_eth_rx.clk, o_O=self.cd_eth_tx.clk) # Reset reset = self._reset.storage self.comb += pads.rst_n.eq(~reset) self.specials += [ AsyncResetSynchronizer(self.cd_eth_tx, reset), AsyncResetSynchronizer(self.cd_eth_rx, reset), ]
def __init__(self, rx0, tx0, rx1, tx1, rd_port, wr_port, c_pci_data_width=32, wordsize=32, ptrsize=64, npagesincache=4, pagesize=4096): self.cmd_rx = rx0 self.cmd_tx = tx0 self.data_rx = rx1 self.data_tx = tx1 self.rd_port = rd_port self.wr_port = wr_port self.virt_addr = Signal(ptrsize) self.page_addr = Signal(log2_int(npagesincache)) self.send_req = Signal() self.fetch_req = Signal() self.req_complete = Signal() ## # fix start signals cmd_rx_start_prev = Signal() data_rx_start_prev = Signal() self.sync += cmd_rx_start_prev.eq(self.cmd_rx.start), data_rx_start_prev.eq(self.data_rx.start) cmd_rx_transaction_requested = Signal() data_rx_transaction_requested = Signal() cmd_rx_transaction_ack = Signal() data_rx_transaction_ack = Signal() self.sync += If(cmd_rx_transaction_ack, cmd_rx_transaction_requested.eq(0)).Elif(~cmd_rx_transaction_requested & (self.cmd_rx.start == 1) & (cmd_rx_start_prev == 0), cmd_rx_transaction_requested.eq(1)) self.sync += If(data_rx_transaction_ack, data_rx_transaction_requested.eq(0)).Elif(~data_rx_transaction_requested & (self.data_rx.start == 1) & (data_rx_start_prev == 0), data_rx_transaction_requested.eq(1)) # constant definitions memorywidth = max(c_pci_data_width, wordsize) memorysize = npagesincache*pagesize*8//memorywidth pcie_word_adr_nbits = log2_int(memorywidth//32) num_tx_off = log2_int(c_pci_data_width//32) num_tx_per_word = max(1, wordsize//c_pci_data_width) words_per_line = c_pci_data_width//wordsize if c_pci_data_width > wordsize else wordsize//c_pci_data_width page_adr_nbits = log2_int(npagesincache) line_adr_nbits = log2_int(pagesize*8//memorywidth) word_adr_nbits = log2_int(words_per_line) byte_adr_nbits = log2_int(wordsize//8) word_adr_off = byte_adr_nbits line_adr_off = log2_int(memorywidth//8) page_tag_off = line_adr_nbits + line_adr_off page_tag_nbits = ptrsize - page_tag_off # variables virt_addr_internal = Signal(ptrsize) page_addr_internal = Signal(ptrsize) rxcount = Signal(32) txcount = Signal(32) wordcount = Signal(32) rlen = Signal(32) # state machine that controls page cache fsm = FSM() self.submodules += fsm fsm.act("IDLE", #0 #reset internal registers NextValue(rxcount, 0), NextValue(txcount, 0), NextValue(wordcount, 0), NextValue(rlen, 0), self.req_complete.eq(1), If(self.send_req, NextValue(virt_addr_internal, self.virt_addr), NextValue(page_addr_internal, self.page_addr), NextState("TX_DIRTY_PAGE_INIT") ).Elif(self.fetch_req, NextValue(virt_addr_internal, self.virt_addr), NextValue(page_addr_internal, self.page_addr), NextState("TX_PAGE_FETCH_CMD") ) ) fsm.act("REQ_COMPLETE", self.req_complete.eq(1), NextState("IDLE") ) # page send fsm.act("TX_DIRTY_PAGE_INIT", #4 self.data_tx.start.eq(1), self.data_tx.len.eq(pagesize//4), self.data_tx.last.eq(1), NextValue(txcount, c_pci_data_width//32), NextValue(wordcount, 0), If(self.data_tx.ack, rd_port.adr.eq(0), rd_port.adr[-page_adr_nbits:].eq(page_addr_internal), rd_port.re.eq(1), NextState("TX_DIRTY_PAGE") ) ) fsm.act("TX_DIRTY_PAGE", #5 self.data_tx.start.eq(1), self.data_tx.len.eq(pagesize//4), self.data_tx.last.eq(1), self.data_tx.data_valid.eq(1), self.data_tx.data.eq(rd_port.dat_r) if c_pci_data_width >= wordsize else [If(i == wordcount[:word_adr_nbits], self.data_tx.data.eq(rd_port.dat_r[i*c_pci_data_width:(i+1)*c_pci_data_width])) for i in range(num_tx_per_word)], If(self.data_tx.data_ren, NextValue(txcount, txcount + c_pci_data_width//32), NextValue(wordcount, wordcount + 1), If(txcount < (pagesize//4), rd_port.adr[0: line_adr_nbits].eq(txcount[pcie_word_adr_nbits:pcie_word_adr_nbits + line_adr_nbits]), rd_port.adr[-page_adr_nbits:].eq(page_addr_internal), rd_port.re.eq(1) ).Else( NextState("TX_WRITEBACK_CMD") ) ) ) page_writeback_cmd = Signal(128) self.comb += page_writeback_cmd[64:128].eq(0x61B061B061B061B0), page_writeback_cmd[page_tag_off:64].eq(virt_addr_internal[page_tag_off:64]) fsm.act("TX_WRITEBACK_CMD", #2 self.cmd_tx.start.eq(1), self.cmd_tx.len.eq(4), self.cmd_tx.last.eq(1), If(self.cmd_tx.ack, NextState("TX_WRITEBACK_CMD0") ) ) for i in range(128//c_pci_data_width): fsm.act("TX_WRITEBACK_CMD" + str(i), #3 self.cmd_tx.start.eq(1), self.cmd_tx.len.eq(4), self.cmd_tx.last.eq(1), self.cmd_tx.data.eq(page_writeback_cmd[i*c_pci_data_width:(i+1)*c_pci_data_width]), self.cmd_tx.data_valid.eq(1), If(self.cmd_tx.data_ren, NextState("TX_WRITEBACK_CMD" + str(i+1)) if i+1 < 128//c_pci_data_width else NextState("REQ_COMPLETE") ) ) # page fetch page_fetch_cmd = Signal(128) self.comb += page_fetch_cmd[64: 128].eq(0x6E706E706E706E70), page_fetch_cmd[page_tag_off: 64].eq(virt_addr_internal[page_tag_off:]) fsm.act("TX_PAGE_FETCH_CMD", #6 self.cmd_tx.start.eq(1), self.cmd_tx.len.eq(4), self.cmd_tx.last.eq(1), If(self.cmd_tx.ack, NextState("TX_PAGE_FETCH_CMD0") ) ) for i in range(128//c_pci_data_width): fsm.act("TX_PAGE_FETCH_CMD" + str(i), #7 self.cmd_tx.start.eq(1), self.cmd_tx.len.eq(4), self.cmd_tx.last.eq(1), self.cmd_tx.data.eq(page_fetch_cmd[i*c_pci_data_width:(i+1)*c_pci_data_width]), self.cmd_tx.data_valid.eq(1), If(self.cmd_tx.data_ren, NextState("TX_PAGE_FETCH_CMD" + str(i+1)) if i+1 < 128//c_pci_data_width else NextState("RX_WAIT") ) ) fsm.act("RX_WAIT", #8 NextValue(rxcount, 0), If(data_rx_transaction_requested, NextValue(rlen, self.data_rx.len), NextState("RX_PAGE") ) ) fsm.act("RX_PAGE", #9 self.data_rx.ack.eq(1), data_rx_transaction_ack.eq(1), wr_port.dat_w.eq(Cat([self.data_rx.data for i in range(num_tx_per_word)])), wr_port.adr[0:line_adr_nbits].eq(rxcount[pcie_word_adr_nbits: pcie_word_adr_nbits + line_adr_nbits]), wr_port.adr[-page_adr_nbits:].eq(page_addr_internal), If(self.data_rx.data_valid, self.data_rx.data_ren.eq(1), [wr_port.we[i].eq(1) for i in range(c_pci_data_width//wordsize)] if c_pci_data_width >= wordsize else wr_port.we.eq(1 << rxcount[num_tx_off: num_tx_off + word_adr_nbits]), NextValue(rxcount, rxcount + c_pci_data_width//32), If((rxcount >= (pagesize*8 - c_pci_data_width)//32) | (rxcount >= rlen - c_pci_data_width//32), NextState("REQ_COMPLETE") ) ) )
def __init__(self, ulpi_bus, ulpi_reg): ulpi_data_out = Signal(8) ulpi_data_tristate = Signal() ulpi_data_next = Signal(8) ulpi_data_tristate_next = Signal() ulpi_stp_next = Signal() ulpi_state_rx = Signal() ulpi_state_rrd = Signal() self.data_out_source = Endpoint(ULPI_DATA_D) RegWriteReqR = Signal() RegReadReqR = Signal() RegWriteReq = Signal() RegReadReq = Signal() RegReadAckSet = Signal() RegWriteAckSet = Signal() # register the reg read/write requests self.sync += RegReadReqR.eq(ulpi_reg.rreq) self.sync += RegWriteReqR.eq(ulpi_reg.wreq) # signal when read/write is requested but not done self.comb += RegReadReq.eq(RegReadReqR & ~ulpi_reg.rack) v = (RegReadReqR & ~ulpi_reg.rack) self.comb += RegWriteReq.eq(RegWriteReqR & ~ulpi_reg.wack) # ack logic: set ack=0 when req=0, set ack=1 when access done self.sync += If(~RegReadReqR, ulpi_reg.rack.eq(0) ).Elif(RegReadAckSet, ulpi_reg.rack.eq(1)) self.sync += If(~RegWriteReqR, ulpi_reg.wack.eq(0) ).Elif(RegWriteAckSet, ulpi_reg.wack.eq(1)) exp = If(~RegWriteReqR, ulpi_reg.wack.eq(0)).Elif(RegWriteAckSet, ulpi_reg.wack.eq(1)) # output data if required by state self.comb += ulpi_bus.stp.eq(ulpi_stp_next) self.comb += ulpi_data_out.eq(ulpi_data_next) self.comb += ulpi_data_tristate.eq(ulpi_data_tristate_next) self.comb += ulpi_bus.do.eq(ulpi_data_out) self.comb += ulpi_bus.doe.eq(~ulpi_data_tristate) # capture RX data at the end of RX, but only if no turnaround was requested # We also support "stuffing" data, to indicate conditions such as: # - Simultaneous DIR + NXT assertion # (the spec doesn't require an RXCMD - DIR+NXT asserting may be the' # only SOP signal) # - End-of-packet # (Packets may end without an RXCMD, unless an error occurs) ulpi_rx_stuff = Signal() ulpi_rx_stuff_d = Signal(8) self.sync += self.data_out_source.stb.eq(1) self.sync += If(ulpi_rx_stuff, self.data_out_source.payload.d.eq(ulpi_rx_stuff_d), self.data_out_source.payload.rxcmd.eq(1) ).Elif(ulpi_state_rx & ulpi_bus.dir, If(~ulpi_bus.nxt, self.data_out_source.payload.d.eq(ulpi_bus.di & RXCMD_MASK), self.data_out_source.payload.rxcmd.eq(1) ).Else( self.data_out_source.payload.d.eq(ulpi_bus.di), self.data_out_source.payload.rxcmd.eq(0) ) ).Else( self.data_out_source.payload.d.eq(RXCMD_MAGIC_NOP), self.data_out_source.payload.rxcmd.eq(1) ) # capture register reads at the end of RRD self.sync += If(ulpi_state_rrd,ulpi_reg.rdata.eq(ulpi_bus.di)) fsm = FSM() self.submodules += fsm fsm.act("IDLE", ulpi_data_next.eq(0x00), # NOOP ulpi_data_tristate_next.eq(0), ulpi_stp_next.eq(0), If(~ulpi_bus.dir & ~ulpi_bus.nxt & ~(RegWriteReq | RegReadReq), NextState("IDLE") ).Elif(ulpi_bus.dir, # TA, and then either RXCMD or Data NextState("RX"), ulpi_data_tristate_next.eq(1), # If dir & nxt, we're starting a packet, so stuff a custom SOP If(ulpi_bus.nxt, ulpi_rx_stuff.eq(1), ulpi_rx_stuff_d.eq(RXCMD_MAGIC_SOP) ) ).Elif(RegWriteReq, NextState("RW0"), ulpi_data_next.eq(0x80 | ulpi_reg.waddr), # REGW ulpi_data_tristate_next.eq(0), ulpi_stp_next.eq(0) ).Elif(RegReadReq, NextState("RR0"), ulpi_data_next.eq(0xC0 | ulpi_reg.raddr), # REGR ulpi_data_tristate_next.eq(0), ulpi_stp_next.eq(0) ).Else( NextState("ERROR") )) fsm.act("RX", If(ulpi_bus.dir, # stay in RX NextState("RX"), ulpi_state_rx.eq(1), ulpi_data_tristate_next.eq(1) ).Else( # TA back to idle # Stuff an EOP on return to idle ulpi_rx_stuff.eq(1), ulpi_rx_stuff_d.eq(RXCMD_MAGIC_EOP), ulpi_data_tristate_next.eq(0), NextState("IDLE") )) fsm.act("RW0", If(ulpi_bus.dir, NextState("RX"), ulpi_data_tristate_next.eq(1), ).Elif(~ulpi_bus.dir, ulpi_data_next.eq(0x80 | ulpi_reg.waddr), # REGW ulpi_data_tristate_next.eq(0), ulpi_stp_next.eq(0), If(ulpi_bus.nxt, NextState("RWD")).Else(NextState("RW0")), ).Else( NextState("ERROR") )) fsm.act("RWD", If(ulpi_bus.dir, NextState("RX"), ulpi_data_tristate_next.eq(1) ).Elif(~ulpi_bus.dir & ulpi_bus.nxt, NextState("RWS"), ulpi_data_next.eq(ulpi_reg.wdata), ulpi_data_tristate_next.eq(0), ulpi_stp_next.eq(0) ).Else( NextState("ERROR") ), ) fsm.act("RWS", If(~ulpi_bus.dir, NextState("IDLE"), ulpi_data_next.eq(0x00), # NOOP ulpi_data_tristate_next.eq(0), ulpi_stp_next.eq(1), RegWriteAckSet.eq(1) ).Elif(ulpi_bus.dir, NextState("RX"), ulpi_data_tristate_next.eq(1), ), ) fsm.act("RR0", If(~ulpi_bus.dir, ulpi_data_next.eq(0xC0 | ulpi_reg.raddr), # REGR NextState("RR1") ).Elif(ulpi_bus.dir, NextState("RX"), RegWriteAckSet.eq(1) ).Else( NextState("ERROR") )) fsm.act("RR1", If(~ulpi_bus.dir & ulpi_bus.nxt, # PHY accepts REGR ulpi_data_tristate_next.eq(1), # TA NextState("RR2") ).Elif(~ulpi_bus.dir & ~ulpi_bus.nxt, # PHY delays REGR ulpi_data_next.eq(0xC0 | ulpi_reg.raddr), # REGR NextState("RR1") ).Elif(ulpi_bus.dir, NextState("RX"), RegWriteAckSet.eq(1) ).Else( NextState("ERROR") )) fsm.act("RR2", ulpi_data_tristate_next.eq(1), If(~ulpi_bus.nxt, # REGR continue NextState("RRD") ).Elif(ulpi_bus.dir, # PHY indicates RX NextState("RX"), RegWriteAckSet.eq(1) ).Else( NextState("ERROR") )) fsm.act("RRD", If(ulpi_bus.dir & ~ulpi_bus.nxt, NextState("IDLE"), RegReadAckSet.eq(1), ulpi_state_rrd.eq(1), ).Elif(ulpi_bus.dir & ulpi_bus.nxt, NextState("RX"), RegWriteAckSet.eq(1) ).Else( NextState("ERROR") ), ulpi_data_tristate_next.eq(1), ) fsm.act("ERROR", NextState("IDLE"))
def __init__(self, ulpi_reg): ReadAddress = Signal(6) write_fsm = FSM() self.submodules += write_fsm def delay_clocks(v, d): for i in range(d): n = Signal() self.sync += n.eq(v) v = n return v ulpi_reg_wack = delay_clocks(ulpi_reg.wack, 2) ulpi_reg_rack = delay_clocks(ulpi_reg.rack, 2) write_fsm.delayed_enter("RESET", "WRITE_HS_SNOOP", 16) write_fsm.act("WRITE_HS_SNOOP", ulpi_reg.waddr.eq(0x4), ulpi_reg.wdata.eq(0x48), ulpi_reg.wreq.eq(1), If(ulpi_reg_wack, NextState("WRITE_IDLE"))) write_fsm.act("WRITE_IDLE", ulpi_reg.wreq.eq(0)) read_fsm = FSM() self.submodules += read_fsm read_fsm.delayed_enter("RESET", "READ_REG", 16) read_fsm.act("READ_REG", ulpi_reg.raddr.eq(ReadAddress), ulpi_reg.rreq.eq(1), If(ulpi_reg_rack, NextState("READ_ACK"))) self.sync += If(ulpi_reg_rack & ulpi_reg.rreq, ReadAddress.eq(ReadAddress + 1)) read_fsm.act("READ_ACK", ulpi_reg.rreq.eq(0), If(~ulpi_reg_rack, NextState("READ_WAIT"))) read_fsm.delayed_enter("READ_WAIT", "READ_REG", 16)
def __init__(self, ulpi_bus): self.ulpi_bus = ulpi_bus fsm = FSM() self.submodules += fsm self.WantRx = Signal() self.RxByte = Signal(8) self.RxCmd = Signal() self.NextCycleRx = Signal() self.RegWriteValid = Signal() self.RegAddrW = Signal(6) self.RegDataW = Signal(8) self.RegRead = Signal() self.RegAddrR = Signal(6) self.RegDataR = Signal(8) self.StateTX = Signal() SetRegAddrR = Signal() SetRegAddrW = Signal() SetRegDataW = Signal() fsm.act("TXCMD", If(self.WantRx, NextState("TA1") ).Elif(ulpi_bus.do[6:8] == 0b10, NextState("RW0") # REGW ).Elif(ulpi_bus.do[6:8] == 0b11, NextState("RR0") # REGR ).Else(NextState("TXCMD"), ulpi_bus.dir.eq(0), self.StateTX.eq(1) )) fsm.act("TA1", NextState("RX"), ulpi_bus.dir.eq(1), self.NextCycleRx.eq(1) ) fsm.act("RX", If(self.WantRx, NextState("RX"), ulpi_bus.dir.eq(1), ulpi_bus.di.eq(self.RxByte), ulpi_bus.nxt.eq(self.RxCmd), self.NextCycleRx.eq(1) ).Else(NextState("TA2") )) fsm.act("TA2", NextState("TXCMD"), ulpi_bus.dir.eq(0) ) fsm.act("RW0", If(self.WantRx, NextState("TA1") ).Else( NextState("RW1"), ulpi_bus.dir.eq(0), ulpi_bus.nxt.eq(1), SetRegAddrW.eq(1) )) fsm.act("RW1", NextState("RW2"), ulpi_bus.dir.eq(0), ulpi_bus.nxt.eq(1), SetRegDataW.eq(1) ) fsm.act("RW2", NextState("TXCMD"), self.RegWriteValid.eq(ulpi_bus.stp)) fsm.act("RR0", If(self.WantRx, NextState("TA1") ).Else( NextState("RR1"), SetRegAddrR.eq(1), ulpi_bus.nxt.eq(1), )) fsm.act("RR1", ulpi_bus.dir.eq(1), If(self.WantRx, NextState("RX"), ulpi_bus.nxt.eq(1), # indicating abort ).Else( NextState("RRD") )) fsm.act("RRD", ulpi_bus.dir.eq(1), ulpi_bus.di.eq(self.RegDataR), NextState("TA2" )) self.sync += If(SetRegAddrR, self.RegAddrR.eq(ulpi_bus.do[0:6])) self.sync += self.RegRead.eq(SetRegAddrR) self.sync += If(SetRegAddrW, self.RegAddrW.eq(ulpi_bus.do[0:6])) self.sync += If(SetRegDataW, self.RegDataW.eq(ulpi_bus.do))
from migen.fhdl.structure import * from migen.fhdl import verilog from migen.genlib.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 __init__(self, a, ba, tRP, tREFI, tRFC): self.req = Signal() self.ack = Signal() # 1st command 1 cycle after assertion of ack self.cmd = CommandRequest(a, ba) ### # Refresh sequence generator: # PRECHARGE ALL --(tRP)--> AUTO REFRESH --(tRFC)--> done seq_start = Signal() seq_done = Signal() self.sync += [ self.cmd.a.eq(2**10), self.cmd.ba.eq(0), self.cmd.cas_n.eq(1), self.cmd.ras_n.eq(1), self.cmd.we_n.eq(1), seq_done.eq(0) ] self.sync += timeline(seq_start, [ (1, [ self.cmd.ras_n.eq(0), self.cmd.we_n.eq(0) ]), (1+tRP, [ self.cmd.cas_n.eq(0), self.cmd.ras_n.eq(0) ]), (1+tRP+tRFC, [ seq_done.eq(1) ]) ]) # Periodic refresh counter counter = Signal(max=tREFI) start = Signal() self.sync += [ start.eq(0), If(counter == 0, start.eq(1), counter.eq(tREFI - 1) ).Else( counter.eq(counter - 1) ) ] # Control FSM fsm = FSM() self.submodules += fsm fsm.act("IDLE", If(start, NextState("WAIT_GRANT"))) fsm.act("WAIT_GRANT", self.req.eq(1), If(self.ack, seq_start.eq(1), NextState("WAIT_SEQ") ) ) fsm.act("WAIT_SEQ", self.req.eq(1), If(seq_done, NextState("IDLE")) )
def __init__(self, sink_description, source_description, header): self.sink = sink = Sink(sink_description) self.source = source = Source(source_description) self.header = Signal(header.length*8) # # # dw = flen(self.sink.data) header_reg = Signal(header.length*8) header_words = (header.length*8)//dw load = Signal() shift = Signal() counter = Counter(max=max(header_words, 2)) self.submodules += counter self.comb += header.encode(sink, self.header) if header_words == 1: self.sync += [ If(load, header_reg.eq(self.header) ) ] else: self.sync += [ If(load, header_reg.eq(self.header) ).Elif(shift, header_reg.eq(Cat(header_reg[dw:], Signal(dw))) ) ] fsm = FSM(reset_state="IDLE") self.submodules += fsm if header_words == 1: idle_next_state = "COPY" else: idle_next_state = "SEND_HEADER" fsm.act("IDLE", sink.ack.eq(1), counter.reset.eq(1), If(sink.stb & sink.sop, sink.ack.eq(0), source.stb.eq(1), source.sop.eq(1), source.eop.eq(0), source.data.eq(self.header[:dw]), If(source.stb & source.ack, load.eq(1), NextState(idle_next_state) ) ) ) if header_words != 1: fsm.act("SEND_HEADER", source.stb.eq(1), source.sop.eq(0), source.eop.eq(0), source.data.eq(header_reg[dw:2*dw]), If(source.stb & source.ack, shift.eq(1), counter.ce.eq(1), If(counter.value == header_words-2, NextState("COPY") ) ) ) fsm.act("COPY", source.stb.eq(sink.stb), source.sop.eq(0), source.eop.eq(sink.eop), source.data.eq(sink.data), source.error.eq(sink.error), If(source.stb & source.ack, sink.ack.eq(1), If(source.eop, NextState("IDLE") ) ) )
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, sink_description, source_description, header): self.sink = sink = Sink(sink_description) self.source = source = Source(source_description) self.header = Signal(header.length*8) # # # dw = flen(sink.data) header_words = (header.length*8)//dw shift = Signal() counter = Counter(max=max(header_words, 2)) self.submodules += counter if header_words == 1: self.sync += \ If(shift, self.header.eq(sink.data) ) else: self.sync += \ If(shift, self.header.eq(Cat(self.header[dw:], sink.data)) ) fsm = FSM(reset_state="IDLE") self.submodules += fsm if header_words == 1: idle_next_state = "COPY" else: idle_next_state = "RECEIVE_HEADER" fsm.act("IDLE", sink.ack.eq(1), counter.reset.eq(1), If(sink.stb, shift.eq(1), NextState(idle_next_state) ) ) if header_words != 1: fsm.act("RECEIVE_HEADER", sink.ack.eq(1), If(sink.stb, counter.ce.eq(1), shift.eq(1), If(counter.value == header_words-2, NextState("COPY") ) ) ) no_payload = Signal() self.sync += \ If(fsm.before_entering("COPY"), source.sop.eq(1), no_payload.eq(sink.eop) ).Elif(source.stb & source.ack, source.sop.eq(0) ) self.comb += [ source.eop.eq(sink.eop | no_payload), source.data.eq(sink.data), source.error.eq(sink.error), header.decode(self.header, source) ] fsm.act("COPY", sink.ack.eq(source.ack), source.stb.eq(sink.stb | no_payload), If(source.stb & source.ack & source.eop, NextState("IDLE") ) )
def __init__(self, phy_settings, geom_settings, timing_settings, bank_machines, refresher, dfi, lasmic): assert(phy_settings.nphases == len(dfi.phases)) # Command choosing requests = [bm.cmd for bm in bank_machines] choose_cmd = _CommandChooser(requests) choose_req = _CommandChooser(requests) self.comb += [ choose_cmd.want_reads.eq(0), choose_cmd.want_writes.eq(0) ] if phy_settings.nphases == 1: self.comb += [ choose_cmd.want_cmds.eq(1), choose_req.want_cmds.eq(1) ] self.submodules += choose_cmd, choose_req # Command steering nop = CommandRequest(geom_settings.mux_a, geom_settings.bank_a) commands = [nop, choose_cmd.cmd, choose_req.cmd, refresher.cmd] # nop must be 1st (STEER_NOP, STEER_CMD, STEER_REQ, STEER_REFRESH) = range(4) steerer = _Steerer(commands, dfi) self.submodules += steerer # Read/write turnaround read_available = Signal() write_available = Signal() self.comb += [ read_available.eq(optree("|", [req.stb & req.is_read for req in requests])), write_available.eq(optree("|", [req.stb & req.is_write for req in requests])) ] def anti_starvation(timeout): en = Signal() max_time = Signal() if timeout: t = timeout - 1 time = Signal(max=t+1) self.comb += max_time.eq(time == 0) self.sync += If(~en, time.eq(t) ).Elif(~max_time, time.eq(time - 1) ) else: self.comb += max_time.eq(0) return en, max_time read_time_en, max_read_time = anti_starvation(timing_settings.read_time) write_time_en, max_write_time = anti_starvation(timing_settings.write_time) # Refresh self.comb += [bm.refresh_req.eq(refresher.req) for bm in bank_machines] go_to_refresh = Signal() self.comb += go_to_refresh.eq(optree("&", [bm.refresh_gnt for bm in bank_machines])) # Datapath all_rddata = [p.rddata for p in dfi.phases] all_wrdata = [p.wrdata for p in dfi.phases] all_wrdata_mask = [p.wrdata_mask for p in dfi.phases] self.comb += [ lasmic.dat_r.eq(Cat(*all_rddata)), Cat(*all_wrdata).eq(lasmic.dat_w), Cat(*all_wrdata_mask).eq(~lasmic.dat_we) ] # Control FSM fsm = FSM() self.submodules += fsm def steerer_sel(steerer, phy_settings, r_w_n): r = [] for i in range(phy_settings.nphases): s = steerer.sel[i].eq(STEER_NOP) if r_w_n == "read": if i == phy_settings.rdphase: s = steerer.sel[i].eq(STEER_REQ) elif i == phy_settings.rdcmdphase: s = steerer.sel[i].eq(STEER_CMD) elif r_w_n == "write": if i == phy_settings.wrphase: s = steerer.sel[i].eq(STEER_REQ) elif i == phy_settings.wrcmdphase: s = steerer.sel[i].eq(STEER_CMD) else: raise ValueError r.append(s) return r fsm.act("READ", read_time_en.eq(1), choose_req.want_reads.eq(1), choose_cmd.cmd.ack.eq(1), choose_req.cmd.ack.eq(1), steerer_sel(steerer, phy_settings, "read"), If(write_available, # TODO: switch only after several cycles of ~read_available? If(~read_available | max_read_time, NextState("RTW")) ), If(go_to_refresh, NextState("REFRESH")) ) fsm.act("WRITE", write_time_en.eq(1), choose_req.want_writes.eq(1), choose_cmd.cmd.ack.eq(1), choose_req.cmd.ack.eq(1), steerer_sel(steerer, phy_settings, "write"), If(read_available, If(~write_available | max_write_time, NextState("WTR")) ), If(go_to_refresh, NextState("REFRESH")) ) fsm.act("REFRESH", steerer.sel[0].eq(STEER_REFRESH), If(~refresher.req, NextState("READ")) ) fsm.delayed_enter("RTW", "WRITE", phy_settings.read_latency-1) # FIXME: reduce this, actual limit is around (cl+1)/nphases fsm.delayed_enter("WTR", "READ", timing_settings.tWTR-1) # FIXME: workaround for zero-delay loop simulation problem with Icarus Verilog fsm.finalize() self.comb += refresher.ack.eq(fsm.state == fsm.encoding["REFRESH"]) self.submodules.bandwidth = Bandwidth(choose_req.cmd)
def __init__(self, lasmim, nslots): bus_aw = lasmim.aw bus_dw = lasmim.dw alignment_bits = bits_for(bus_dw//8) - 1 # debug print("LASMI Bus Address Width : {}".format(bus_aw)) print("LASMI Bus Data Width : {}".format(bus_dw)) fifo_word_width = bus_dw self.frame = Sink([("sof", 1), ("pixels", fifo_word_width)]) self._frame_size = CSRStorage(bus_aw + alignment_bits, alignment_bits=alignment_bits) self.submodules._slot_array = _SlotArray(nslots, bus_aw, alignment_bits) self.ev = self._slot_array.ev ### # address generator + maximum memory word count to prevent DMA buffer overrun reset_words = Signal() count_word = Signal() last_word = Signal() current_address = Signal(bus_aw) mwords_remaining = Signal(bus_aw) self.comb += [ self._slot_array.address_reached.eq(current_address), last_word.eq(mwords_remaining == 1) ] self.sync += [ If(reset_words, current_address.eq(self._slot_array.address), mwords_remaining.eq(self._frame_size.storage) #Initially there was no division by 4 ).Elif(count_word, current_address.eq(current_address + 1), mwords_remaining.eq(mwords_remaining - 1) ) ] memory_word = Signal(bus_dw) pixbits = [] for i in range(bus_dw//16): #was initially 16 pixbits.append(self.frame.pixels) self.comb += memory_word.eq(Cat(*pixbits)) # bus accessor self.submodules._bus_accessor = dma_lasmi.Writer(lasmim) self.comb += [ self._bus_accessor.address_data.a.eq(current_address), self._bus_accessor.address_data.d.eq(memory_word) ] # control FSM fsm = FSM() self.submodules += fsm fsm.act("WAIT_SOF", reset_words.eq(1), self.frame.ack.eq(~self._slot_array.address_valid | ~self.frame.sof), If(self._slot_array.address_valid & self.frame.sof & self.frame.stb, NextState("TRANSFER_PIXELS")) ) fsm.act("TRANSFER_PIXELS", self.frame.ack.eq(self._bus_accessor.address_data.ack), If(self.frame.stb, self._bus_accessor.address_data.stb.eq(1), If(self._bus_accessor.address_data.ack, count_word.eq(1), If(last_word, NextState("EOF")) ) ) ) fsm.act("EOF", If(~self._bus_accessor.busy, self._slot_array.address_done.eq(1), NextState("WAIT_SOF") ) )