def __init__(self, cmd=False, data=False, data_width=1, skip_start_bit=False): assert cmd or data self.pads_in = pads_in = stream.Endpoint(_sdpads_layout) self.source = source = stream.Endpoint([("data", 8)]) # # # pads_in_data = pads_in.cmd.i[: data_width] if cmd else pads_in.data.i[: data_width] print(len(pads_in_data)) # Xfer starts when data == 0 start = Signal() run = Signal() self.comb += start.eq(pads_in_data == 0) self.sync += If(pads_in.valid & pads_in.ready, run.eq(start | run)) # Convert data to 8-bit stream converter = stream.Converter(data_width, 8, reverse=True) buf = stream.Buffer([("data", 8)]) self.submodules += converter, buf self.comb += [ converter.sink.valid.eq(pads_in.valid & (run if skip_start_bit else (start | run))), converter.sink.data.eq(pads_in_data), pads_in.ready.eq(converter.sink.ready), converter.source.connect(buf.sink), buf.source.connect(source) ]
def __init__(self, axi, port, buffer_depth): self.cmd_request = Signal() self.cmd_grant = Signal() # # # ashift = log2_int(port.data_width // 8) # Burst to Beat aw_buffer = stream.Buffer( ax_description(axi.address_width, axi.id_width)) self.submodules += aw_buffer self.comb += axi.aw.connect(aw_buffer.sink) aw = stream.Endpoint(ax_description(axi.address_width, axi.id_width)) aw_burst2beat = AXIBurst2Beat(aw_buffer.source, aw) self.submodules.aw_burst2beat = aw_burst2beat # Write Buffer w_buffer = stream.SyncFIFO(w_description(axi.data_width, axi.id_width), buffer_depth, buffered=True) self.submodules.w_buffer = w_buffer # Write ID Buffer & Response id_buffer = stream.SyncFIFO([("id", axi.id_width)], buffer_depth) resp_buffer = stream.SyncFIFO([("id", axi.id_width), ("resp", 2)], buffer_depth) self.submodules += id_buffer, resp_buffer self.comb += [ id_buffer.sink.valid.eq(aw.valid & aw.first & aw.ready), id_buffer.sink.id.eq(aw.id), If( w_buffer.source.valid & w_buffer.source.last & w_buffer.source.ready, resp_buffer.sink.valid.eq(1), resp_buffer.sink.resp.eq(RESP_OKAY), resp_buffer.sink.id.eq(id_buffer.source.id), id_buffer.source.ready.eq(1)), resp_buffer.source.connect(axi.b) ] # Command # Accept and send command to the controller only if: # - Address & Data request are *both* valid. # - Data buffer is not full. self.comb += [ self.cmd_request.eq(aw.valid & axi.w.valid & w_buffer.sink.ready), If( self.cmd_request & self.cmd_grant, port.cmd.valid.eq(1), port.cmd.we.eq(1), port.cmd.addr.eq(aw.addr >> ashift), aw.ready.eq(port.cmd.ready), axi.w.connect(w_buffer.sink, omit={"valid", "ready"}), If(port.cmd.ready, w_buffer.sink.valid.eq(1), axi.w.ready.eq(1))) ] # Write Data self.comb += [ w_buffer.source.connect(port.wdata, omit={"strb", "id"}), port.wdata.we.eq(w_buffer.source.strb) ]
def __init__(self, axi, port, buffer_depth): self.cmd_request = Signal() self.cmd_grant = Signal() # # # ashift = log2_int(port.data_width // 8) # Burst to Beat aw_buffer = stream.Buffer( ax_description(axi.address_width, axi.id_width)) self.comb += axi.aw.connect(aw_buffer.sink) aw = stream.Endpoint(ax_description(axi.address_width, axi.id_width)) aw_burst2beat = LiteDRAMAXIBurst2Beat(aw_buffer.source, aw) self.submodules += aw_buffer, aw_burst2beat # Write Buffer w_buffer = stream.SyncFIFO(w_description(axi.data_width), buffer_depth) self.submodules += w_buffer # Write ID Buffer & Response id_buffer = stream.SyncFIFO([("id", axi.id_width)], buffer_depth) resp_buffer = stream.SyncFIFO([("id", axi.id_width), ("resp", 2)], buffer_depth) self.submodules += id_buffer, resp_buffer self.comb += [ id_buffer.sink.valid.eq(aw.valid & aw.first & aw.ready), id_buffer.sink.id.eq(aw.id), If( w_buffer.source.valid & w_buffer.source.last & w_buffer.source.ready, resp_buffer.sink.valid.eq(1), resp_buffer.sink.resp.eq(resp_types["okay"]), resp_buffer.sink.id.eq(id_buffer.source.id), id_buffer.source.ready.eq(1)), resp_buffer.source.connect(axi.b) ] # Command self.comb += [ # Emits the command only if we have the data If( w_buffer.source.valid, self.cmd_request.eq(aw.valid), If(self.cmd_grant, port.cmd.valid.eq(aw.valid), aw.ready.eq(port.cmd.ready), port.cmd.we.eq(1), port.cmd.addr.eq(aw.addr >> ashift))) ] # Write Data self.comb += [ axi.w.connect(w_buffer.sink), If(id_buffer.source.valid, w_buffer.source.connect(port.wdata, omit={"strb"}), port.wdata.we.eq(w_buffer.source.strb)) ]
def __init__(self, check_ctrl_only=False): self.enable = Signal(reset=1) self.sink = sink = stream.Endpoint([("data", 32), ("ctrl", 4)]) self.source = source = stream.Endpoint([("data", 32), ("ctrl", 4)]) # # # alignment = Signal(2) alignment_d = Signal(2) buf = stream.Buffer([("data", 32), ("ctrl", 4)]) self.submodules += buf self.comb += [ sink.connect(buf.sink), source.valid.eq(sink.valid & buf.source.valid), buf.source.ready.eq(sink.valid & source.ready), ] # Alignment detection for i in reversed(range(4)): self.comb += [ If( sink.valid & sink.ready, If( sink.ctrl[i] & (check_ctrl_only | (sink.data[8 * i:8 * (i + 1)] == COM.value)), alignment.eq(i))) ] self.sync += [ If( sink.valid & sink.ready, If( self.enable, If( (sink.ctrl != 0) & (buf.source.ctrl == 0), alignment_d.eq(alignment), ))), ] # Data selection data = Cat(buf.source.data, sink.data) ctrl = Cat(buf.source.ctrl, sink.ctrl) cases = {} for i in range(4): cases[i] = [ source.data.eq(data[8 * i:]), source.ctrl.eq(ctrl[i:]), ] self.comb += Case(alignment_d, cases)
def __init__(self, dw, cd_ratio): self.sink = stream.Endpoint(core_layout(dw)) self.source = stream.Endpoint(core_layout(dw * cd_ratio)) # # # self.submodules.buffer = stream.Buffer(core_layout(dw)) self.submodules.trigger = FrontendTrigger(dw) self.submodules.subsampler = FrontendSubSampler(dw) self.submodules.converter = stream.StrideConverter( core_layout(dw, 1), core_layout(dw * cd_ratio, cd_ratio)) self.submodules.fifo = ClockDomainsRenamer({ "write": "sys", "read": "new_sys" })(stream.AsyncFIFO(core_layout(dw * cd_ratio, cd_ratio), 8)) self.submodules.pipeline = stream.Pipeline(self.sink, self.buffer, self.trigger, self.subsampler, self.converter, self.fifo, self.source)
def __init__(self, axi, axi_lite): assert axi.data_width == axi_lite.data_width assert axi.address_width == axi_lite.address_width ax_buffer = stream.Buffer( ax_description(axi.address_width, axi.id_width)) ax_burst = stream.Endpoint( ax_description(axi.address_width, axi.id_width)) ax_beat = stream.Endpoint( ax_description(axi.address_width, axi.id_width)) self.comb += ax_burst.connect(ax_buffer.sink) ax_burst2beat = AXIBurst2Beat(ax_buffer.source, ax_beat) self.submodules += ax_buffer, ax_burst2beat _data = Signal(axi.data_width) _cmd_done = Signal() _last_ar_aw_n = Signal() self.submodules.fsm = fsm = FSM(reset_state="IDLE") fsm.act( "IDLE", NextValue(_cmd_done, 0), If( axi.ar.valid & axi.aw.valid, # If last access was a read, do a write If(_last_ar_aw_n, axi.aw.connect(ax_burst), NextValue(_last_ar_aw_n, 0), NextState("WRITE") # If last access was a write, do a read ).Else( axi.ar.connect(ax_burst), NextValue(_last_ar_aw_n, 1), NextState("READ"), )).Elif( axi.ar.valid, axi.ar.connect(ax_burst), NextValue(_last_ar_aw_n, 1), NextState("READ"), ).Elif(axi.aw.valid, axi.aw.connect(ax_burst), NextValue(_last_ar_aw_n, 0), NextState("WRITE"))) fsm.act( "READ", # cmd axi_lite.ar.valid.eq(ax_beat.valid & ~_cmd_done), axi_lite.ar.addr.eq(ax_beat.addr), ax_beat.ready.eq(axi_lite.ar.ready & ~_cmd_done), If( ax_beat.valid & ax_beat.last, If(axi_lite.ar.ready, ax_beat.ready.eq(0), NextValue(_cmd_done, 1))), # data axi.r.valid.eq(axi_lite.r.valid), axi.r.last.eq(_cmd_done), axi.r.resp.eq(RESP_OKAY), axi.r.id.eq(ax_beat.id), axi.r.data.eq(axi_lite.r.data), axi_lite.r.ready.eq(axi.r.ready), # exit If(axi.r.valid & axi.r.last & axi.r.ready, ax_beat.ready.eq(1), NextState("IDLE"))) # always accept write responses self.comb += axi_lite.b.ready.eq(1) fsm.act( "WRITE", # cmd axi_lite.aw.valid.eq(ax_beat.valid & ~_cmd_done), axi_lite.aw.addr.eq(ax_beat.addr), ax_beat.ready.eq(axi_lite.aw.ready & ~_cmd_done), If( ax_beat.valid & ax_beat.last, If(axi_lite.aw.ready, ax_beat.ready.eq(0), NextValue(_cmd_done, 1))), # data axi_lite.w.valid.eq(axi.w.valid), axi_lite.w.data.eq(axi.w.data), axi_lite.w.strb.eq(axi.w.strb), axi.w.ready.eq(axi_lite.w.ready), # exit If(axi.w.valid & axi.w.last & axi.w.ready, NextState("WRITE-RESP"))) fsm.act("WRITE-RESP", axi.b.valid.eq(1), axi.b.resp.eq(RESP_OKAY), axi.b.id.eq(ax_beat.id), If(axi.b.ready, ax_beat.ready.eq(1), NextState("IDLE")))
def __init__(self, clock_domain, mem_size=128): # ********************************************************* # * Interface * # ********************************************************* self.armed = CSRStorage() # Trigger is armed self.trigged = CSRStatus() # Pattern found self.size = CSRStorage(8) # Pattern size - 1 self.enable = Signal() self.trigExt = Signal() self.sink = sink = stream.Endpoint(trigger_layout) self.source = source = stream.Endpoint(trigger_layout) # ********************************************************* # * Signals * # ********************************************************* matches = Signal(8) addr = Signal(log2_int(mem_size)) trig = Signal() _armed = Signal() _trigged = Signal() _size = Signal(8) # ********************************************************* # * CDC * # ********************************************************* self.specials += MultiReg(self.armed.storage, _armed, clock_domain) self.specials += MultiReg(_trigged, self.trigged.status, "sys") self.specials += MultiReg(self.size.storage, _size, clock_domain) # ********************************************************* # * Specials * # ********************************************************* self.specials.mem = Memory(20, mem_size) self.specials.rdport = self.mem.get_port(write_capable=False, async_read=True, clock_domain=clock_domain) # ********************************************************* # * Submodules * # ********************************************************* buf0 = stream.Buffer(trigger_layout) buf1 = stream.Buffer(trigger_layout) self.submodules += ClockDomainsRenamer(clock_domain)(buf0) self.submodules += ClockDomainsRenamer(clock_domain)(buf1) # ********************************************************* # * Combinatorial * # ********************************************************* self.comb += [ sink.connect(buf0.sink), buf0.source.connect(buf1.sink), buf1.source.connect(source, omit={"trig"}), sink.ready.eq(source.ready), self.rdport.adr.eq(addr), source.trig.eq(buf1.source.trig | trig), self.trigExt.eq(trig), ] # ********************************************************* # * FSM * # ********************************************************* fsm = ResetInserter()(FSM(reset_state="IDLE")) self.submodules.fsm = ClockDomainsRenamer(clock_domain)(fsm) fsm.act("IDLE", If(_armed & self.enable, NextValue(addr, 0), NextValue(matches, 0), NextState("FIRST") ), ) fsm.act("FIRST", # If we search "bc1c" we are in this situation: bc1c 1c1c xxxx If((((self.rdport.dat_r[UPPER_BYTE] == buf0.source.data[UPPER_BYTE]) | self.rdport.dat_r[UPPER_DONT_CARE]) & ((self.rdport.dat_r[LOWER_BYTE] == buf0.source.data[LOWER_BYTE]) | self.rdport.dat_r[LOWER_DONT_CARE]) & ((self.rdport.dat_r[UPPER_K] == buf0.source.ctrl[CTRL_UPPER_K])| self.rdport.dat_r[UPPER_DONT_CARE]) & ((self.rdport.dat_r[LOWER_K] == buf0.source.ctrl[CTRL_LOWER_K])| self.rdport.dat_r[LOWER_DONT_CARE]) & ~buf0.source.time & buf0.source.valid), # Full word match NextValue(matches, matches + 1), NextValue(addr, addr + 1), NextState("ALIGNED_CHECK") ).Else( # If we search "bc1c" we are in this situation: xxbc 1c1c 1cxx If((((self.rdport.dat_r[UPPER_BYTE] == buf0.source.data[LOWER_BYTE]) | self.rdport.dat_r[UPPER_DONT_CARE]) & ((self.rdport.dat_r[LOWER_BYTE] == sink.data[UPPER_BYTE]) | self.rdport.dat_r[LOWER_DONT_CARE]) & ((self.rdport.dat_r[UPPER_K] == buf0.source.ctrl[CTRL_LOWER_K])| self.rdport.dat_r[UPPER_DONT_CARE]) & ((self.rdport.dat_r[LOWER_K] == sink.ctrl[CTRL_UPPER_K]) | self.rdport.dat_r[UPPER_DONT_CARE]) & ~buf0.source.time & ~sink.time & buf0.source.valid & sink.valid), # Half word match NextValue(matches, matches + 1), NextValue(addr, addr + 1), NextState("UNALIGNED_CHECK") ) ), If(~self.enable, NextState("IDLE") ) ) fsm.act("ALIGNED_CHECK", If(matches == _size, NextState("DONE"), NextValue(_trigged, 1), trig.eq(1), ).Else( If((((self.rdport.dat_r[UPPER_BYTE] == buf0.source.data[UPPER_BYTE]) | self.rdport.dat_r[UPPER_DONT_CARE]) & ((self.rdport.dat_r[LOWER_BYTE] == buf0.source.data[LOWER_BYTE]) | self.rdport.dat_r[LOWER_DONT_CARE]) & ((self.rdport.dat_r[UPPER_K] == buf0.source.ctrl[CTRL_UPPER_K])| self.rdport.dat_r[UPPER_DONT_CARE]) & ((self.rdport.dat_r[LOWER_K] == buf0.source.ctrl[CTRL_LOWER_K])| self.rdport.dat_r[LOWER_DONT_CARE]) & ~buf0.source.time & buf0.source.valid), NextValue(matches, matches + 1), NextValue(addr, addr + 1), NextState("ALIGNED_CHECK") ).Else( NextValue(matches, 0), NextValue(addr, 0), NextState("FIRST") ) ), If(~self.enable, NextState("IDLE") ) ) fsm.act("UNALIGNED_CHECK", If(matches == _size, NextState("DONE"), NextValue(_trigged, 1), trig.eq(1), ).Else( If((((self.rdport.dat_r[UPPER_BYTE] == buf0.source.data[LOWER_BYTE]) | self.rdport.dat_r[UPPER_DONT_CARE]) & ((self.rdport.dat_r[LOWER_BYTE] == sink.data[UPPER_BYTE]) | self.rdport.dat_r[LOWER_DONT_CARE]) & ((self.rdport.dat_r[UPPER_K] == buf0.source.ctrl[CTRL_LOWER_K])| self.rdport.dat_r[UPPER_DONT_CARE]) & ((self.rdport.dat_r[LOWER_K] == sink.ctrl[CTRL_UPPER_K]) | self.rdport.dat_r[UPPER_DONT_CARE]) & ~buf0.source.time & ~sink.time & buf0.source.valid & sink.valid), # Half word match NextValue(matches, matches + 1), NextValue(addr, addr + 1), NextState("UNALIGNED_CHECK") ).Else( NextValue(matches, 0), NextValue(addr, 0), NextState("FIRST") ) ), If(~self.enable, NextState("IDLE") ) ) fsm.act("DONE", If(_armed == 0, NextState("IDLE"), NextValue(_trigged, 0), ), If(~self.enable, NextState("IDLE") ) )
def __init__(self, n, address_width, address_align, nranks, settings): self.req = req = Record(cmd_layout(address_width)) self.refresh_req = refresh_req = Signal() self.refresh_gnt = refresh_gnt = Signal() a = settings.geom.addressbits ba = settings.geom.bankbits + log2_int(nranks) self.cmd = cmd = stream.Endpoint(cmd_request_rw_layout(a, ba)) # # # auto_precharge = Signal() # Command buffer --------------------------------------------------------------------------- cmd_buffer_layout = [("we", 1), ("addr", len(req.addr))] cmd_buffer_lookahead = stream.SyncFIFO( cmd_buffer_layout, settings.cmd_buffer_depth, buffered=settings.cmd_buffer_buffered) cmd_buffer = stream.Buffer(cmd_buffer_layout) # 1 depth buffer to detect row change self.submodules += cmd_buffer_lookahead, cmd_buffer self.comb += [ req.connect(cmd_buffer_lookahead.sink, keep={"valid", "ready", "we", "addr"}), cmd_buffer_lookahead.source.connect(cmd_buffer.sink), cmd_buffer.source.ready.eq(req.wdata_ready | req.rdata_valid), req.lock.eq(cmd_buffer_lookahead.source.valid | cmd_buffer.source.valid), ] slicer = _AddressSlicer(settings.geom.colbits, address_align) # Row tracking ----------------------------------------------------------------------------- row = Signal(settings.geom.rowbits) row_opened = Signal() row_hit = Signal() row_open = Signal() row_close = Signal() self.comb += row_hit.eq(row == slicer.row(cmd_buffer.source.addr)) self.sync += \ If(row_close, row_opened.eq(0) ).Elif(row_open, row_opened.eq(1), row.eq(slicer.row(cmd_buffer.source.addr)) ) # Address generation ----------------------------------------------------------------------- row_col_n_addr_sel = Signal() self.comb += [ cmd.ba.eq(n), If(row_col_n_addr_sel, cmd.a.eq(slicer.row(cmd_buffer.source.addr)) ).Else( cmd.a.eq((auto_precharge << 10) | slicer.col(cmd_buffer.source.addr)) ) ] # tWTP (write-to-precharge) controller ----------------------------------------------------- write_latency = math.ceil(settings.phy.cwl / settings.phy.nphases) precharge_time = write_latency + settings.timing.tWR + settings.timing.tCCD # AL=0 self.submodules.twtpcon = twtpcon = tXXDController(precharge_time) self.comb += twtpcon.valid.eq(cmd.valid & cmd.ready & cmd.is_write) # tRC (activate-activate) controller ------------------------------------------------------- self.submodules.trccon = trccon = tXXDController(settings.timing.tRC) self.comb += trccon.valid.eq(cmd.valid & cmd.ready & row_open) # tRAS (activate-precharge) controller ----------------------------------------------------- self.submodules.trascon = trascon = tXXDController(settings.timing.tRAS) self.comb += trascon.valid.eq(cmd.valid & cmd.ready & row_open) # Auto Precharge generation ---------------------------------------------------------------- if settings.with_auto_precharge: self.comb += \ If(cmd_buffer_lookahead.source.valid & cmd_buffer.source.valid, If(slicer.row(cmd_buffer_lookahead.source.addr) != slicer.row(cmd_buffer.source.addr), auto_precharge.eq(row_close == 0) ) ) # Control and command generation FSM ------------------------------------------------------- # Note: tRRD, tFAW, tCCD, tWTR timings are enforced by the multiplexer self.submodules.fsm = fsm = FSM() fsm.act("REGULAR", If(refresh_req, NextState("REFRESH") ).Elif(cmd_buffer.source.valid, If(row_opened, If(row_hit, cmd.valid.eq(1), If(cmd_buffer.source.we, req.wdata_ready.eq(cmd.ready), cmd.is_write.eq(1), cmd.we.eq(1), ).Else( req.rdata_valid.eq(cmd.ready), cmd.is_read.eq(1) ), cmd.cas.eq(1), If(cmd.ready & auto_precharge, NextState("AUTOPRECHARGE") ) ).Else( NextState("PRECHARGE") ) ).Else( NextState("ACTIVATE") ) ) ) fsm.act("PRECHARGE", # Note: we are presenting the column address, A10 is always low If(twtpcon.ready & trascon.ready, cmd.valid.eq(1), If(cmd.ready, NextState("TRP") ), cmd.ras.eq(1), cmd.we.eq(1), cmd.is_cmd.eq(1) ), row_close.eq(1) ) fsm.act("AUTOPRECHARGE", If(twtpcon.ready & trascon.ready, NextState("TRP") ), row_close.eq(1) ) fsm.act("ACTIVATE", If(trccon.ready, row_col_n_addr_sel.eq(1), row_open.eq(1), cmd.valid.eq(1), cmd.is_cmd.eq(1), If(cmd.ready, NextState("TRCD") ), cmd.ras.eq(1) ) ) fsm.act("REFRESH", If(twtpcon.ready, refresh_gnt.eq(1), ), row_close.eq(1), cmd.is_cmd.eq(1), If(~refresh_req, NextState("REGULAR") ) ) fsm.delayed_enter("TRP", "ACTIVATE", settings.timing.tRP - 1) fsm.delayed_enter("TRCD", "REGULAR", settings.timing.tRCD - 1)
def __init__(self, port_from, port_to, reverse=False): assert port_from.clock_domain == port_to.clock_domain assert port_from.data_width < port_to.data_width assert port_from.mode == port_to.mode assert port_from.mode == "read" if port_to.data_width % port_from.data_width: raise ValueError("Ratio must be an int") # # # ratio = port_to.data_width//port_from.data_width # cmd cmd_buffer = stream.SyncFIFO([("sel", ratio)], 4) self.submodules += cmd_buffer counter = Signal(max=ratio) counter_ce = Signal() self.sync += \ If(counter_ce, counter.eq(counter + 1) ) self.comb += \ If(port_from.cmd.valid, If(counter == 0, port_to.cmd.valid.eq(1), port_to.cmd.addr.eq(port_from.cmd.addr[log2_int(ratio):]), port_from.cmd.ready.eq(port_to.cmd.ready), counter_ce.eq(port_to.cmd.ready) ).Else( port_from.cmd.ready.eq(1), counter_ce.eq(1) ) ) # TODO: fix sel self.comb += \ If(port_to.cmd.valid & port_to.cmd.ready, cmd_buffer.sink.valid.eq(1), cmd_buffer.sink.sel.eq(2**ratio-1) ) # datapath rdata_buffer = stream.Buffer(port_to.rdata.description) rdata_converter = stream.StrideConverter( port_to.rdata.description, port_from.rdata.description, reverse=reverse) self.submodules += rdata_buffer, rdata_converter rdata_chunk = Signal(ratio, reset=1) rdata_chunk_valid = Signal() self.sync += \ If(rdata_converter.source.valid & rdata_converter.source.ready, rdata_chunk.eq(Cat(rdata_chunk[ratio-1], rdata_chunk[:ratio-1])) ) self.comb += [ port_to.rdata.connect(rdata_buffer.sink), rdata_buffer.source.connect(rdata_converter.sink), rdata_chunk_valid.eq((cmd_buffer.source.sel & rdata_chunk) != 0), If(port_from.flush, rdata_converter.source.ready.eq(1) ).Elif(cmd_buffer.source.valid, If(rdata_chunk_valid, port_from.rdata.valid.eq(rdata_converter.source.valid), port_from.rdata.data.eq(rdata_converter.source.data), rdata_converter.source.ready.eq(port_from.rdata.ready) ).Else( rdata_converter.source.ready.eq(1) ) ), cmd_buffer.source.ready.eq( rdata_converter.source.ready & rdata_chunk[ratio-1]) ]
def __init__(self, hres=800, vres=600, with_csi_interpreter=True): self.enable = Signal(reset=1) self.vtg_sink = vtg_sink = stream.Endpoint(video_timing_layout) self.uart_sink = uart_sink = stream.Endpoint([("data", 8)]) self.source = source = stream.Endpoint(video_data_layout) # # # csi_width = 8 if with_csi_interpreter else 0 # Font Mem. # --------- os.system("wget https://github.com/enjoy-digital/litex/files/6076336/ter-u16b.txt") # FIXME: Store Font in LiteX? os.system("mv ter-u16b.txt ter-u16b.bdf") font = import_bdf_font("ter-u16b.bdf") font_width = 8 font_heigth = 16 font_mem = Memory(width=8, depth=4096, init=font) font_rdport = font_mem.get_port(has_re=True) self.specials += font_mem, font_rdport # Terminal Mem. # ------------- term_colums = 128 # 80 rounded to next power of two. term_lines = math.floor(vres/font_heigth) term_depth = term_colums * term_lines term_init = [ord(c) for c in [" "]*term_colums*term_lines] term_mem = Memory(width=font_width + csi_width, depth=term_depth, init=term_init) term_wrport = term_mem.get_port(write_capable=True) term_rdport = term_mem.get_port(has_re=True) self.specials += term_mem, term_wrport, term_rdport # UART Terminal Fill. # ------------------- # Optional CSI Interpreter. if with_csi_interpreter: self.submodules.csi_interpreter = CSIInterpreter() self.comb += uart_sink.connect(self.csi_interpreter.sink) uart_sink = self.csi_interpreter.source self.comb += term_wrport.dat_w[font_width:].eq(self.csi_interpreter.color) self.submodules.uart_fifo = stream.SyncFIFO([("data", 8)], 8) self.comb += uart_sink.connect(self.uart_fifo.sink) uart_sink = self.uart_fifo.source # UART Reception and Terminal Fill. x_term = term_wrport.adr[:7] y_term = term_wrport.adr[7:] y_term_rollover = Signal() self.submodules.uart_fsm = uart_fsm = FSM(reset_state="RESET") uart_fsm.act("RESET", NextValue(x_term, 0), NextValue(y_term, 0), NextState("CLEAR-XY") ) uart_fsm.act("CLEAR-XY", term_wrport.we.eq(1), term_wrport.dat_w[:font_width].eq(ord(" ")), NextValue(x_term, x_term + 1), If(x_term == (term_colums - 1), NextValue(x_term, 0), NextValue(y_term, y_term + 1), If(y_term == (term_lines - 1), NextValue(y_term, 0), NextState("IDLE") ) ) ) uart_fsm.act("IDLE", If(uart_sink.valid, If(uart_sink.data == ord("\n"), uart_sink.ready.eq(1), # Ack sink. NextState("INCR-Y") ).Elif(uart_sink.data == ord("\r"), uart_sink.ready.eq(1), # Ack sink. NextState("RST-X") ).Else( NextState("WRITE") ) ) ) uart_fsm.act("WRITE", uart_sink.ready.eq(1), term_wrport.we.eq(1), term_wrport.dat_w[:font_width].eq(uart_sink.data), NextState("INCR-X") ) uart_fsm.act("RST-X", NextValue(x_term, 0), NextState("CLEAR-X") ) uart_fsm.act("INCR-X", NextValue(x_term, x_term + 1), NextState("IDLE"), If(x_term == (80 - 1), NextValue(x_term, 0), NextState("INCR-Y") ) ) uart_fsm.act("RST-Y", NextValue(y_term, 0), NextState("CLEAR-X") ) uart_fsm.act("INCR-Y", NextValue(y_term, y_term + 1), NextState("CLEAR-X"), If(y_term == (term_lines - 1), NextValue(y_term_rollover, 1), NextState("RST-Y") ) ) uart_fsm.act("CLEAR-X", NextValue(x_term, x_term + 1), term_wrport.we.eq(1), term_wrport.dat_w[:font_width].eq(ord(" ")), If(x_term == (term_colums - 1), NextValue(x_term, 0), NextState("IDLE") ) ) # Video Generation. # ----------------- ce = (vtg_sink.valid & vtg_sink.ready) # Timing delay line. latency = 2 timing_bufs = [stream.Buffer(video_timing_layout) for i in range(latency)] self.comb += vtg_sink.connect(timing_bufs[0].sink) for i in range(len(timing_bufs) - 1): self.comb += timing_bufs[i].source.connect(timing_bufs[i+1].sink) self.comb += timing_bufs[-1].source.connect(source, keep={"valid", "ready", "last", "de", "hsync", "vsync"}) self.submodules += timing_bufs # Compute X/Y position. x = vtg_sink.hcount[int(math.log2(font_width)):] y = vtg_sink.vcount[int(math.log2(font_heigth)):] y_rollover = Signal(8) self.comb += [ If(~y_term_rollover, y_rollover.eq(y) ).Else( # FIXME: Use Modulo. If((y + y_term + 1) >= term_lines, y_rollover.eq(y + y_term + 1 - term_lines) ).Else( y_rollover.eq(y + y_term + 1) ), ) ] # Get character from Terminal Mem. term_dat_r = Signal(font_width) self.comb += term_rdport.re.eq(ce) self.comb += term_rdport.adr.eq(x + y_rollover*term_colums) self.comb += [ term_dat_r.eq(term_rdport.dat_r[:font_width]), If((x >= 80) | (y >= term_lines), term_dat_r.eq(ord(" ")), # Out of range, generate space. ) ] # Translate character to video data through Font Mem. self.comb += font_rdport.re.eq(ce) self.comb += font_rdport.adr.eq(term_dat_r*font_heigth + timing_bufs[0].source.vcount[:4]) bit = Signal() cases = {} for i in range(font_width): cases[i] = [bit.eq(font_rdport.dat_r[font_width-1-i])] self.comb += Case(timing_bufs[1].source.hcount[:int(math.log2(font_width))], cases) # FIXME: Add Palette. self.comb += [ If(bit, Case(term_rdport.dat_r[font_width:], { 0: [Cat(source.r, source.g, source.b).eq(0xffffff)], 1: [Cat(source.r, source.g, source.b).eq(0x34e289)], }) ).Else( Cat(source.r, source.g, source.b).eq(0x000000), ) ]
def __init__(self, axi, port, buffer_depth): self.cmd_request = Signal() self.cmd_grant = Signal() # # # can_read = Signal() ashift = log2_int(port.data_width // 8) # Burst to Beat ar_buffer = stream.Buffer( ax_description(axi.address_width, axi.id_width)) self.submodules += ar_buffer self.comb += axi.ar.connect(ar_buffer.sink) ar = stream.Endpoint(ax_description(axi.address_width, axi.id_width)) ar_burst2beat = AXIBurst2Beat(ar_buffer.source, ar) self.submodules.ar_burst2beat = ar_burst2beat # Read buffer r_buffer = stream.SyncFIFO(r_description(axi.data_width, axi.id_width), buffer_depth, buffered=True) self.submodules.r_buffer = r_buffer # Read Buffer reservation # - Incremented when data is planned to be queued # - Decremented when data is dequeued r_buffer_queue = Signal() r_buffer_dequeue = Signal() r_buffer_level = Signal(max=buffer_depth + 1) self.comb += [ r_buffer_queue.eq(port.cmd.valid & port.cmd.ready & ~port.cmd.we), r_buffer_dequeue.eq(r_buffer.source.valid & r_buffer.source.ready) ] self.sync += [ If(r_buffer_queue, If(~r_buffer_dequeue, r_buffer_level.eq(r_buffer_level + 1))).Elif( r_buffer_dequeue, r_buffer_level.eq(r_buffer_level - 1)) ] self.comb += can_read.eq(r_buffer_level != buffer_depth) # Read ID Buffer id_buffer = stream.SyncFIFO([("id", axi.id_width)], buffer_depth) self.submodules += id_buffer self.comb += [ id_buffer.sink.valid.eq(ar.valid & ar.ready), id_buffer.sink.last.eq(ar.last), id_buffer.sink.id.eq(ar.id), axi.r.last.eq(id_buffer.source.last), axi.r.id.eq(id_buffer.source.id), id_buffer.source.ready.eq(axi.r.valid & axi.r.ready) ] # Command self.comb += [ self.cmd_request.eq(ar.valid & can_read), If(self.cmd_grant, port.cmd.valid.eq(ar.valid & can_read), ar.ready.eq(port.cmd.ready & can_read), port.cmd.we.eq(0), port.cmd.addr.eq(ar.addr >> ashift)) ] # Read data self.comb += [ port.rdata.connect(r_buffer.sink, omit={"bank"}), r_buffer.source.connect(axi.r, omit={"id", "last"}), axi.r.resp.eq(RESP_OKAY) ]
def __init__(self, cfg): self.pads = pads = _sdpads() self.sink = sink = stream.Endpoint([("data", 8)]) self.source = source = stream.Endpoint([("data", 8), ("status", 3)]) # # # datarfb_reset = Signal() self.submodules.datarfb = SDPHYRFB(pads.data.i, True) self.submodules.cdc = ClockDomainsRenamer({"write": "sd_fb", "read": "sd"})( stream.AsyncFIFO(self.datarfb.source.description, 4) ) self.submodules.buffer = ClockDomainsRenamer("sd")(stream.Buffer(self.datarfb.source.description)) self.comb += self.datarfb.source.connect(self.buffer.sink) dtimeout = Signal(32) read = Signal(10) toread = Signal(10) cnt = Signal(8) self.submodules.fsm = fsm = ClockDomainsRenamer("sd")(FSM(reset_state="IDLE")) fsm.act("IDLE", pads.data.oe.eq(0), pads.clk.eq(1), datarfb_reset.eq(1), self.buffer.source.ready.eq(1), If(sink.valid, NextValue(dtimeout, 0), NextValue(read, 0), # Read 1 block + 8*8 == 64 bits CRC NextValue(toread, cfg.blocksize + 8), NextState("DATA_READSTART") ) ) self.specials += MultiReg(datarfb_reset, self.datarfb.reset, "sd_fb") fsm.act("DATA_READSTART", pads.data.oe.eq(0), pads.clk.eq(1), NextValue(dtimeout, dtimeout + 1), If(self.buffer.source.valid, NextState("DATA_READ") ).Elif(dtimeout > cfg.datatimeout, NextState("TIMEOUT") ) ) fsm.act("DATA_READ", pads.data.oe.eq(0), pads.clk.eq(1), source.valid.eq(self.buffer.source.valid), source.data.eq(self.buffer.source.data), source.status.eq(SDCARD_STREAM_STATUS_OK), source.last.eq(read == (toread - 1)), self.buffer.source.ready.eq(source.ready), If(source.valid & source.ready, NextValue(read, read + 1), If(read == (toread - 1), If(sink.last, NextState("DATA_CLK40") ).Else( sink.ready.eq(1), NextState("DATA_FLUSH") ) ) ) ) fsm.act("DATA_FLUSH", pads.data.oe.eq(0), datarfb_reset.eq(1), self.buffer.source.ready.eq(1), If(cnt < 5, NextValue(cnt, cnt + 1), ).Else( NextValue(cnt, 0), NextState("IDLE") ) ) fsm.act("DATA_CLK40", pads.data.oe.eq(1), pads.data.o.eq(0xf), If(cnt < 40, NextValue(cnt, cnt + 1), pads.clk.eq(1) ).Else( NextValue(cnt, 0), sink.ready.eq(1), NextState("IDLE") ) ) fsm.act("TIMEOUT", source.valid.eq(1), source.data.eq(0), source.status.eq(SDCARD_STREAM_STATUS_TIMEOUT), source.last.eq(1), If(source.valid & source.ready, sink.ready.eq(1), NextState("IDLE") ) )
def __init__(self, n, aw, address_align, settings): self.req = req = Record(cmd_layout(aw)) self.refresh_req = Signal() self.refresh_gnt = Signal() a = settings.geom.addressbits ba = settings.geom.bankbits self.cmd = cmd = stream.Endpoint(cmd_request_rw_layout(a, ba)) # # # # Command buffer cmd_buffer_layout = [("we", 1), ("adr", len(req.adr))] if settings.cmd_buffer_depth < 2: cmd_buffer = stream.Buffer(cmd_buffer_layout) else: cmd_buffer = stream.SyncFIFO(cmd_buffer_layout, settings.cmd_buffer_depth) self.submodules += cmd_buffer self.comb += [ req.connect(cmd_buffer.sink, omit=[ "wdata_valid", "wdata_ready", "rdata_valid", "rdata_ready", "lock" ]), cmd_buffer.source.ready.eq(req.wdata_ready | req.rdata_valid), req.lock.eq(cmd_buffer.source.valid), ] slicer = _AddressSlicer(settings.geom.colbits, address_align) # Row tracking has_openrow = Signal() openrow = Signal(settings.geom.rowbits, reset_less=True) hit = Signal() self.comb += hit.eq(openrow == slicer.row(cmd_buffer.source.adr)) track_open = Signal() track_close = Signal() self.sync += \ If(track_close, has_openrow.eq(0) ).Elif(track_open, has_openrow.eq(1), openrow.eq(slicer.row(cmd_buffer.source.adr)) ) # Address generation sel_row_adr = Signal() self.comb += [ cmd.ba.eq(n), If(sel_row_adr, cmd.a.eq(slicer.row(cmd_buffer.source.adr))).Else( cmd.a.eq(slicer.col(cmd_buffer.source.adr))) ] # Respect write-to-precharge specification precharge_time = 2 + settings.timing.tWR - 1 + 1 self.submodules.precharge_timer = WaitTimer(precharge_time) self.comb += self.precharge_timer.wait.eq(~(cmd.valid & cmd.ready & cmd.is_write)) # Control and command generation FSM self.submodules.fsm = fsm = FSM() fsm.act( "REGULAR", If(self.refresh_req, NextState("REFRESH")).Elif( cmd_buffer.source.valid, If( has_openrow, If( hit, # Note: write-to-read specification is enforced by # multiplexer cmd.valid.eq(1), If( cmd_buffer.source.we, req.wdata_ready.eq(cmd.ready), cmd.is_write.eq(1), cmd.we.eq(1), ).Else(req.rdata_valid.eq(cmd.ready), cmd.is_read.eq(1)), cmd.cas.eq(1)).Else(NextState("PRECHARGE"))).Else( NextState("ACTIVATE")))) fsm.act( "PRECHARGE", # Note: we are presenting the column address, A10 is always low If(self.precharge_timer.done, cmd.valid.eq(1), If(cmd.ready, NextState("TRP")), cmd.ras.eq(1), cmd.we.eq(1), cmd.is_cmd.eq(1)), track_close.eq(1)) fsm.act("ACTIVATE", sel_row_adr.eq(1), track_open.eq(1), cmd.valid.eq(1), cmd.is_cmd.eq(1), If(cmd.ready, NextState("TRCD")), cmd.ras.eq(1)) fsm.act("REFRESH", If( self.precharge_timer.done, self.refresh_gnt.eq(1), ), track_close.eq(1), cmd.is_cmd.eq(1), If(~self.refresh_req, NextState("REGULAR"))) fsm.delayed_enter("TRP", "ACTIVATE", settings.timing.tRP - 1) fsm.delayed_enter("TRCD", "REGULAR", settings.timing.tRCD - 1)
def __init__(self, clock_domain, fifo_size): # ********************************************************* # * Interface * # ********************************************************* self.filterEnable = CSRStorage() self.filterConfig = CSRStorage(32) # Filter configuration self.tlpDllpTimeoutCnt = CSRStorage(32) # Payload size used for error detection self.ts = Signal(32) # Global time stamp self.trigExt = Signal() # Insert a trigger flag self.source = source = stream.Endpoint(trigger_layout) self.sink = sink = stream.Endpoint(descrambler_layout) # ********************************************************* # * Signals * # ********************************************************* _ts = Signal(32) _filterConfig = Signal(32) _tlpDllpTimeoutCnt = Signal(32) _filterEnable = Signal() _trigExt = Signal() trigPending = Signal() clearTrig = Signal() enabledDatas = Signal() self.trigPending = trigPending self._trigExt = _trigExt self.clearTrig = clearTrig skipEnabled = Signal() ftsEnabled = Signal() tlpEnabled = Signal() dllpEnabled = Signal() ts1Enabled = Signal() ts2Enabled = Signal() idleEnabled = Signal() count = Signal(8) insert_ts = Signal() state_after = Signal(4) last_ts = Signal(32) payload_cnt = Signal(32) from_error = Signal() ts_trig = Signal() # ********************************************************* # * CDC * # ********************************************************* self.specials += MultiReg(self.ts, _ts, clock_domain) self.specials += MultiReg(self.filterConfig.storage, _filterConfig, clock_domain) self.specials += MultiReg(self.filterEnable.storage, _filterEnable, clock_domain) self.specials += MultiReg(self.tlpDllpTimeoutCnt.storage, _tlpDllpTimeoutCnt, clock_domain) self.specials += MultiReg(self.trigExt, _trigExt, clock_domain) # ********************************************************* # * Submodules * # ********************************************************* fifo = ResetInserter()(stream.SyncFIFO(filter_fifo_layout, fifo_size)) self.submodules.fifo = ClockDomainsRenamer(clock_domain)(fifo) buf_in = stream.Buffer(descrambler_layout) self.submodules += ClockDomainsRenamer(clock_domain)(buf_in) buf_out = stream.Buffer(filter_fifo_layout) self.submodules += ClockDomainsRenamer(clock_domain)(buf_out) # ********************************************************* # * Combinatorial * # ********************************************************* self.comb += [ sink.connect(buf_in.sink), buf_in.source.connect(fifo.sink, omit={"valid", "ts", "error"}), self.sink.ready.eq(1), fifo.source.connect(buf_out.sink), skipEnabled.eq(_filterConfig[0]), ftsEnabled.eq( _filterConfig[1]), tlpEnabled.eq( _filterConfig[2]), dllpEnabled.eq(_filterConfig[3]), ts1Enabled.eq( _filterConfig[4]), ts2Enabled.eq( _filterConfig[5]), idleEnabled.eq( _filterConfig[6]), ] sync = getattr(self.sync, clock_domain) sync += [ If(_trigExt, trigPending.eq(1)), If(clearTrig, trigPending.eq(0)) ] # ********************************************************* # * FSM * # ********************************************************* fsmWriter = FSM(reset_state="NO_FILTER") self.submodules.fsmWriter = ClockDomainsRenamer(clock_domain)(fsmWriter) fsmReader = FSM(reset_state="NO_FILTER") self.submodules.fsmReader = ClockDomainsRenamer(clock_domain)(fsmReader) # ********************************************************* # * Filter control * # ********************************************************* fsmWriter.act("NO_FILTER", NextValue(fifo.sink.valid, 0), NextValue(buf_out.source.ready, 0), If(_filterEnable, self.fifo.reset.eq(1), NextState("FIND_DELIMITER"), ) ) # ******************************************************************** # * Writing side of the FIFO. * # * All frames are written to the FIFO, software IDLE are removed. * # * A timestamp is added to each symbol to keep track of the timing. * # ******************************************************************** # ********************************************************* # * Detect frames delimiter * # ********************************************************* fsmWriter.act("FIND_DELIMITER", NextValue(fifo.sink.valid, 0), NextValue(fifo.sink.error, 0), # Ordered sets If(sink.osets & (sink.data[8:16] == COM.value), NextValue(fifo.sink.valid, 1), NextValue(fifo.sink.ts, _ts), NextState("ORDERED_SETS"), ), # TLP If((sink.ctrl == 0b10) & (sink.data[8:16] == STP.value), NextValue(fifo.sink.valid, 1), NextValue(fifo.sink.ts, _ts), NextValue(payload_cnt, 0), NextState("TLP"), ), # DLLP If((sink.ctrl == 0b10) & (sink.data[8:16] == SDP.value), NextValue(fifo.sink.valid, 1), NextValue(fifo.sink.ts, _ts), NextValue(payload_cnt, 0), NextState("DLLP"), ), If(~_filterEnable, NextState("NO_FILTER"), ) ) # ********************************************************* # * An ordered set is detected * # ********************************************************* fsmWriter.act("ORDERED_SETS", NextValue(fifo.sink.ts, _ts), NextValue(fifo.sink.error, 0), # We are done If(sink.osets == 0, NextValue(fifo.sink.valid, 0), NextState("FIND_DELIMITER"), ), # It's a nested frame. Get directly to TLP If(sink.ctrl[1] & (sink.data[8:16] == STP.value), NextValue(fifo.sink.valid, 1), NextValue(payload_cnt, 0), NextState("TLP"), ), # It's a nested frame. Get directly to DLLP If(sink.ctrl[1] & (sink.data[8:16] == SDP.value), NextValue(fifo.sink.valid, 1), NextValue(payload_cnt, 0), NextState("DLLP"), ), If(~_filterEnable, NextState("NO_FILTER"), ) ) # ********************************************************* # * An TLP is detected * # ********************************************************* fsmWriter.act("TLP", NextValue(fifo.sink.ts, _ts), NextValue(fifo.sink.error, 0), NextValue(payload_cnt, payload_cnt + 1), # By default, is we have a K symbol before END, that's an error If((sink.ctrl[0] & (sink.data[0:8] != END.value)) | sink.ctrl[1] | (payload_cnt > _tlpDllpTimeoutCnt), NextValue(fifo.sink.error, 1), NextValue(fifo.sink.valid, 1), NextState("FIND_DELIMITER"), ).Else( NextValue(fifo.sink.error, 0), ), If((buf_in.source.ctrl[0]) & (buf_in.source.data[0:8] == END.value), NextValue(fifo.sink.valid, 0), NextValue(fifo.sink.error, 0), NextState("FIND_DELIMITER"), ), If(sink.ctrl[1] & (sink.data[8:16] == STP.value), NextValue(fifo.sink.valid, 1), NextValue(payload_cnt, 0), NextState("TLP"), ), If(sink.ctrl[1] & (sink.data[8:16] == SDP.value), NextValue(fifo.sink.valid, 1), NextValue(payload_cnt, 0), NextState("DLLP"), ), If(sink.osets & (sink.data[8:16] == COM.value), NextValue(fifo.sink.valid, 1), NextState("ORDERED_SETS"), ), If(~_filterEnable, NextState("NO_FILTER"), ) ) # ********************************************************* # * An DLLP is detected * # ********************************************************* fsmWriter.act("DLLP", NextValue(fifo.sink.ts, _ts), NextValue(fifo.sink.error, 0), NextValue(payload_cnt, payload_cnt + 1), # By default, is we have a K symbol before END, that's an error If((sink.ctrl[0] & (sink.data[0:8] != END.value)) | sink.ctrl[1]| (payload_cnt > _tlpDllpTimeoutCnt), NextValue(fifo.sink.error, 1), NextValue(fifo.sink.valid, 1), NextState("FIND_DELIMITER"), ).Else( NextValue(fifo.sink.error, 0), ), If((buf_in.source.ctrl[0]) & (buf_in.source.data[0:8] == END.value), NextValue(fifo.sink.valid, 0), NextValue(fifo.sink.error, 0), NextState("FIND_DELIMITER"), ), If(sink.ctrl[1] & (sink.data[8:16] == STP.value), NextValue(fifo.sink.valid, 1), NextValue(payload_cnt, 0), NextState("TLP"), ), If(sink.ctrl[1] & (sink.data[8:16] == SDP.value), NextValue(fifo.sink.valid, 1), NextValue(payload_cnt, 0), NextState("DLLP"), ), If(sink.osets & (sink.data[8:16] == COM.value), NextValue(fifo.sink.valid, 1), NextState("ORDERED_SETS"), ), If(~_filterEnable, NextState("NO_FILTER"), ) ) # ****************************************************************** # * Reading side of the FIFO. * # * Filtering takes place on the reading side of the FIFO. * # * A timestamp is added to each frame (or frame group) to keep * # * track of the timing. * # ****************************************************************** # ********************************************************* # * Filtering control * # ********************************************************* fsmReader.act("NO_FILTER", NextValue(source.data, sink.data), NextValue(source.ctrl, sink.ctrl), NextValue(source.valid, sink.valid), NextValue(source.time, 0), If(_filterEnable, NextState("FILTER"), ) ) # ********************************************************* # * Frame filtering * # ********************************************************* fsmReader.act("FILTER", NextValue(source.valid, 0), NextValue(source.time, 0), NextValue(buf_out.source.ready, 0), NextValue(from_error, 0), NextValue(source.eof, 0), NextValue(clearTrig, 0), NextValue(source.trig, 0), If(from_error, NextValue(buf_out.source.ready, 1), ), If(buf_out.source.valid, # Don't insert a new timestamp If(last_ts == buf_out.source.ts, insert_ts.eq(0), ).Else( insert_ts.eq(1), NextValue(last_ts, buf_out.source.ts), ), # ---- SKIP ---- If(buf_out.source.osets & (buf_out.source.type == osetsType.SKIP) & (buf_out.source.data[8:16] == COM.value), If(insert_ts, NextValue(source.data, buf_out.source.ts[16:32]), # When this frame is disabled, we need to change last_ts # in order to force ts insertion on the next frame. If(skipEnabled, NextValue(source.valid, 1), NextValue(source.time, 1), ), NextValue(buf_out.source.ready, 0), NextValue(state_after, state.SKIP), NextValue(ts_trig, 0), NextState("TIMESTAMP_LSB"), ).Else( NextValue(count, 0), NextValue(buf_out.source.ready, 1), NextState("SKIP"), ), If(~skipEnabled, NextValue(last_ts, 0)), ), # ---- IDLE ---- If(buf_out.source.osets & (buf_out.source.type == osetsType.IDLE) & (buf_out.source.data[8:16] == COM.value), If(insert_ts, NextValue(source.data, buf_out.source.ts[16:32]), # When this frame is disabled, we need to change last_ts # in order to force ts insertion on the next frame. If(idleEnabled, NextValue(source.valid, 1), NextValue(source.time, 1), ), NextValue(buf_out.source.ready, 0), NextValue(state_after, state.IDLE), NextValue(ts_trig, 0), NextState("TIMESTAMP_LSB"), ).Else( NextValue(count, 0), NextValue(buf_out.source.ready, 1), NextState("IDLE"), ), If(~idleEnabled, NextValue(last_ts, 0)), ), # ---- FTS ---- If(buf_out.source.osets & (buf_out.source.type == osetsType.FTS) & (buf_out.source.data[8:16] == COM.value), If(insert_ts, NextValue(source.data, buf_out.source.ts[16:32]), If(ftsEnabled, NextValue(source.valid, 1), NextValue(source.time, 1), ), NextValue(buf_out.source.ready, 0), NextValue(state_after, state.FTS), NextValue(ts_trig, 0), NextState("TIMESTAMP_LSB"), ).Else( NextValue(count, 0), NextValue(buf_out.source.ready, 1), NextState("FTS"), ), If(~ftsEnabled, NextValue(last_ts, 0)), ), # ---- TS1 ---- If(buf_out.source.osets & (buf_out.source.type == osetsType.TS1) & (buf_out.source.data[8:16] == COM.value), If(insert_ts, NextValue(source.data, buf_out.source.ts[16:32]), If(ts1Enabled, NextValue(source.valid, 1), NextValue(source.time, 1), ), NextValue(buf_out.source.ready, 0), NextValue(state_after, state.TS1), NextValue(ts_trig, 0), NextState("TIMESTAMP_LSB"), ).Else( NextValue(count, 0), NextValue(buf_out.source.ready, 1), NextState("TS1"), ), If(~ts1Enabled, NextValue(last_ts, 0)), ), # ---- TS2 ---- If(buf_out.source.osets & (buf_out.source.type == osetsType.TS2) & (buf_out.source.data[8:16] == COM.value), If(insert_ts, NextValue(source.data, buf_out.source.ts[16:32]), If(ts2Enabled, NextValue(source.valid, 1), NextValue(source.time, 1), ), NextValue(buf_out.source.ready, 0), NextValue(state_after, state.TS2), NextValue(ts_trig, 0), NextState("TIMESTAMP_LSB"), ).Else( NextValue(count, 0), NextValue(buf_out.source.ready, 1), NextState("TS2"), ), If(~ts2Enabled, NextValue(last_ts, 0)), ), # ---- TLP ---- If(buf_out.source.ctrl[1] & (buf_out.source.data[8:16] == STP.value), If(insert_ts, NextValue(source.data, buf_out.source.ts[16:32]), If(tlpEnabled, NextValue(source.valid, 1), NextValue(source.time, 1), ), NextValue(buf_out.source.ready, 0), NextValue(state_after, state.TLP), NextValue(ts_trig, 0), NextState("TIMESTAMP_LSB"), ).Else( NextValue(count, 0), NextValue(buf_out.source.ready, 1), NextState("TLP"), ), If(~tlpEnabled, NextValue(last_ts, 0)), ), # ---- DLLP ---- If(buf_out.source.ctrl[1] & (buf_out.source.data[8:16] == SDP.value), If(insert_ts, NextValue(source.data, buf_out.source.ts[16:32]), If(dllpEnabled, NextValue(source.valid, 1), NextValue(source.time, 1), ), NextValue(buf_out.source.ready, 0), NextValue(state_after, state.DLLP), NextValue(ts_trig, 0), NextState("TIMESTAMP_LSB"), ).Else( NextValue(count, 0), NextValue(buf_out.source.ready, 1), NextState("DLLP"), ), If(~dllpEnabled, NextValue(last_ts, 0)), ), # buf_out.source is not valid ).Else( If(trigPending, NextValue(buf_out.source.ready, 0), NextValue(state_after, state.FILTER), NextState("TIMESTAMP_MSB_TRIG"), ) ), If(~_filterEnable, NextState("NO_FILTER"), ) ) # ********************************************************* # * Insert LSB part of timestamp * # ********************************************************* fsmReader.act("TIMESTAMP_MSB_TRIG", NextValue(source.time, 1), NextValue(source.valid, 1), NextValue(source.data, _ts[16:32]), NextState("TIMESTAMP_LSB"), NextValue(source.trig, 1), NextValue(clearTrig, 1), NextValue(ts_trig, 1), ), # ********************************************************* # * Insert LSB part of timestamp * # ********************************************************* fsmReader.act("TIMESTAMP_LSB", NextValue(source.data, buf_out.source.ts[0:16]), If(ts_trig, NextValue(source.data, _ts[0:16]), NextValue(source.trig, 1), ).Else( NextValue(count, 0), ), NextValue(ts_trig, 0), NextValue(buf_out.source.ready, 1), If((state_after == state.FILTER), NextState("FILTER"), ), If((state_after == state.SKIP), If(skipEnabled, NextValue(source.valid, 1), ), NextState("SKIP"), ), If((state_after == state.IDLE), If(ftsEnabled, NextValue(source.valid, 1), ), NextState("IDLE"), ), If((state_after == state.FTS), If(ftsEnabled, NextValue(source.valid, 1), ), NextState("FTS"), ), If((state_after == state.TS1), If(ts1Enabled, NextValue(source.valid, 1), ), NextState("TS1"), ), If((state_after == state.TS2), If(ts2Enabled, NextValue(source.valid, 1), ), NextState("TS2"), ), If((state_after == state.DLLP), If(dllpEnabled, NextValue(source.valid, 1), ), NextState("DLLP"), ), If((state_after == state.TLP), If(tlpEnabled, NextValue(source.valid, 1), ), NextState("TLP"), ), If(~_filterEnable, NextState("NO_FILTER"), ) ) # ********************************************************* # * Read a SKIP from the FIFO * # ********************************************************* fsmReader.act("SKIP", NextValue(source.data, buf_out.source.data), NextValue(source.ctrl, buf_out.source.ctrl), NextValue(count, count + 1), NextValue(source.valid, 1), NextValue(last_ts, last_ts + 1), NextValue(source.time, 0), NextValue(source.trig, 0), NextValue(source.sof, 0), NextValue(source.eof, 0), If(trigPending, NextValue(buf_out.source.ready, 0), NextValue(state_after, state.SKIP), NextState("TIMESTAMP_MSB_TRIG"), ), If(count == 1, NextValue(buf_out.source.ready, 0), NextValue(source.valid, 0), NextState("FILTER"), ), If(skipEnabled, If(count == 0, NextValue(source.sof, 1)), If(count == 1, NextValue(source.eof, 1)), NextValue(source.valid, 1), ).Else( NextValue(source.valid, 0), ), If(~_filterEnable, NextState("NO_FILTER"), ) ) # ********************************************************* # * Read a IDLE from the FIFO * # ********************************************************* fsmReader.act("IDLE", NextValue(source.data, buf_out.source.data), NextValue(source.ctrl, buf_out.source.ctrl), NextValue(count, count + 1), NextValue(source.valid, 1), NextValue(last_ts, last_ts + 1), NextValue(source.time, 0), NextValue(source.trig, 0), NextValue(source.sof, 0), NextValue(source.eof, 0), If(trigPending, NextValue(buf_out.source.ready, 0), NextValue(state_after, state.IDLE), NextState("TIMESTAMP_MSB_TRIG"), ), If(count == 1, NextValue(buf_out.source.ready, 0), NextValue(source.valid, 0), NextValue(source.sof, 0), NextValue(source.eof, 1), NextState("FILTER"), ), If(idleEnabled, If(count == 0, NextValue(source.sof, 1)), If(count == 1, NextValue(source.eof, 1)), NextValue(source.valid, 1), ).Else( NextValue(source.valid, 0), ), If(~_filterEnable, NextState("NO_FILTER"), ) ) # ********************************************************* # * Read a FTS from the FIFO * # ********************************************************* fsmReader.act("FTS", NextValue(source.data, buf_out.source.data), NextValue(source.ctrl, buf_out.source.ctrl), NextValue(count, count + 1), NextValue(source.valid, 1), NextValue(last_ts, last_ts + 1), NextValue(source.time, 0), NextValue(source.trig, 0), NextValue(source.sof, 0), NextValue(source.eof, 0), If(trigPending, NextValue(buf_out.source.ready, 0), NextValue(state_after, state.FTS), NextState("TIMESTAMP_MSB_TRIG"), ), If(count == 1, NextValue(buf_out.source.ready, 0), NextValue(source.valid, 0), NextValue(source.sof, 0), NextValue(source.eof, 1), NextState("FILTER"), ), If(ftsEnabled, If(count == 0, NextValue(source.sof, 1)), If(count == 1, NextValue(source.eof, 1)), NextValue(source.valid, 1), ).Else( NextValue(source.valid, 0), ), If(~_filterEnable, NextState("NO_FILTER"), ) ) # ********************************************************* # * Read a TS1 from the FIFO * # ********************************************************* fsmReader.act("TS1", NextValue(source.data, buf_out.source.data), NextValue(source.ctrl, buf_out.source.ctrl), NextValue(count, count + 1), NextValue(source.valid, 1), NextValue(last_ts, last_ts + 1), NextValue(source.time, 0), NextValue(source.trig, 0), NextValue(source.sof, 0), NextValue(source.eof, 0), If(trigPending, NextValue(buf_out.source.ready, 0), NextValue(state_after, state.TS1), NextState("TIMESTAMP_MSB_TRIG"), ), If(count == 7, NextValue(buf_out.source.ready, 0), NextValue(source.valid, 0), NextValue(source.sof, 0), NextValue(source.eof, 1), NextState("FILTER"), ), If(ts1Enabled, If(count == 0, NextValue(source.sof, 1)), If(count == 7, NextValue(source.eof, 1)), NextValue(source.valid, 1), ).Else( NextValue(source.valid, 0), ), If(~_filterEnable, NextState("NO_FILTER"), ) ) # ********************************************************* # * Read a TS2 from the FIFO * # ********************************************************* fsmReader.act("TS2", NextValue(source.data, buf_out.source.data), NextValue(source.ctrl, buf_out.source.ctrl), NextValue(count, count + 1), NextValue(source.valid, 1), NextValue(last_ts, last_ts + 1), NextValue(source.time, 0), NextValue(source.trig, 0), NextValue(source.sof, 0), NextValue(source.eof, 0), If(trigPending, NextValue(buf_out.source.ready, 0), NextValue(state_after, state.TS2), NextState("TIMESTAMP_MSB_TRIG"), ), If(count == 7, NextValue(buf_out.source.ready, 0), NextValue(source.valid, 0), NextValue(source.sof, 0), NextValue(source.eof, 1), NextState("FILTER"), ), If(ts2Enabled, If(count == 0, NextValue(source.sof, 1)), If(count == 7, NextValue(source.eof, 1)), NextValue(source.valid, 1), ).Else( NextValue(source.valid, 0), ), If(~_filterEnable, NextState("NO_FILTER"), ) ) # ********************************************************* # * Read a TLP from the FIFO * # ********************************************************* fsmReader.act("TLP", NextValue(source.data, buf_out.source.data), NextValue(source.ctrl, buf_out.source.ctrl), NextValue(count, count + 1), NextValue(source.valid, 1), NextValue(last_ts, last_ts + 1), NextValue(source.time, 0), NextValue(source.trig, 0), NextValue(source.sof, 0), NextValue(source.eof, 0), If(trigPending, NextValue(buf_out.source.ready, 0), NextValue(state_after, state.TLP), NextState("TIMESTAMP_MSB_TRIG"), ), If((buf_out.source.ctrl[0] & (buf_out.source.data[0:8] == END.value)) | fifo.source.error, If(tlpEnabled, NextValue(source.eof, 1)), NextValue(buf_out.source.ready, 0), NextValue(source.valid, 0), NextState("FILTER"), If(fifo.source.error, NextValue(from_error, 1), ), ), If(tlpEnabled, If(count == 0, NextValue(source.sof, 1)), NextValue(source.valid, 1), ).Else( NextValue(source.valid, 0), ), If(~_filterEnable, NextState("NO_FILTER"), ) ) # ********************************************************* # * Read a DLLP from the FIFO * # ********************************************************* fsmReader.act("DLLP", NextValue(source.data, buf_out.source.data), NextValue(source.ctrl, buf_out.source.ctrl), NextValue(count, count + 1), NextValue(source.valid, 1), NextValue(last_ts, last_ts + 1), NextValue(source.time, 0), NextValue(source.trig, 0), NextValue(source.sof, 0), NextValue(source.eof, 0), If(trigPending, NextValue(buf_out.source.ready, 0), NextValue(state_after, state.DLLP), NextState("TIMESTAMP_MSB_TRIG"), ), If((buf_out.source.ctrl[0] & (buf_out.source.data[0:8] == END.value)) | fifo.source.error, If(dllpEnabled, NextValue(source.eof, 1)), NextValue(buf_out.source.ready, 0), NextValue(source.valid, 0), NextState("FILTER"), If(fifo.source.error, NextValue(from_error, 1), ), ), If(dllpEnabled, If(count == 0, NextValue(source.sof, 1)), NextValue(source.valid, 1), ).Else( NextValue(source.valid, 0), ), If(~_filterEnable, NextState("NO_FILTER"), ) )