diff --git a/artiq/gateware/rtio/sed/gates.py b/artiq/gateware/rtio/sed/gates.py index 7ed460d0c..8d0f604e4 100644 --- a/artiq/gateware/rtio/sed/gates.py +++ b/artiq/gateware/rtio/sed/gates.py @@ -29,7 +29,10 @@ class Gates(Module): else: self.sync += getattr(output.payload, field).eq(getattr(input.payload, field)) self.sync += output.seqn.eq(input.seqn) - self.comb += output.replace_occured.eq(0) + self.comb += [ + output.replace_occured.eq(0), + output.nondata_replace_occured.eq(0) + ] self.comb += input.re.eq(input.payload.timestamp[fine_ts_width:] == self.coarse_timestamp) self.sync += output.valid.eq(input.re & input.readable) diff --git a/artiq/gateware/rtio/sed/layouts.py b/artiq/gateware/rtio/sed/layouts.py index 35dbbf460..b0a983911 100644 --- a/artiq/gateware/rtio/sed/layouts.py +++ b/artiq/gateware/rtio/sed/layouts.py @@ -69,5 +69,6 @@ def output_network_node(seqn_width, layout_payload): ("valid", 1), ("seqn", seqn_width), ("replace_occured", 1), + ("nondata_replace_occured", 1), ("payload", layout_payload) ] diff --git a/artiq/gateware/rtio/sed/output_driver.py b/artiq/gateware/rtio/sed/output_driver.py index ff7086031..7f26ec58a 100644 --- a/artiq/gateware/rtio/sed/output_driver.py +++ b/artiq/gateware/rtio/sed/output_driver.py @@ -33,10 +33,12 @@ class OutputDriver(Module): en_replaces = [channel.interface.o.enable_replace for channel in channels] for lane_data, on_output in zip(lane_datas, output_network.output): replace_occured_r = Signal() + nondata_replace_occured_r = Signal() self.sync += [ lane_data.valid.eq(on_output.valid), lane_data.payload.eq(on_output.payload), replace_occured_r.eq(on_output.replace_occured), + nondata_replace_occured_r.eq(on_output.nondata_replace_occured) ] en_replaces_rom = Memory(1, len(en_replaces), init=en_replaces) @@ -44,7 +46,7 @@ class OutputDriver(Module): self.specials += en_replaces_rom, en_replaces_rom_port self.comb += [ en_replaces_rom_port.adr.eq(on_output.payload.channel), - lane_data.collision.eq(replace_occured_r & ~en_replaces_rom_port.dat_r) + lane_data.collision.eq(replace_occured_r & (~en_replaces_rom_port.dat_r | nondata_replace_occured_r)) ] self.sync += [ diff --git a/artiq/gateware/rtio/sed/output_network.py b/artiq/gateware/rtio/sed/output_network.py index 05797bdcb..1b57baf9e 100644 --- a/artiq/gateware/rtio/sed/output_network.py +++ b/artiq/gateware/rtio/sed/output_network.py @@ -60,6 +60,13 @@ class OutputNetwork(Module): for _ in range(lane_count)] for node1, node2 in step: + nondata_difference = Signal() + for field, _ in layout_payload: + if field != "data": + f1 = getattr(step_input[node1].payload, field) + f2 = getattr(step_input[node2].payload, field) + self.comb += If(f1 != f2, nondata_difference.eq(1)) + k1 = Cat(step_input[node1].payload.channel, ~step_input[node1].valid) k2 = Cat(step_input[node2].payload.channel, ~step_input[node2].valid) self.sync += [ @@ -72,6 +79,7 @@ class OutputNetwork(Module): step_output[node2].eq(step_input[node2]) ), step_output[node1].replace_occured.eq(1), + step_output[node1].nondata_replace_occured.eq(nondata_difference), step_output[node2].valid.eq(0), ).Elif(k1 < k2, step_output[node1].eq(step_input[node1]),