diff --git a/src/gateware/cxp_pipeline.py b/src/gateware/cxp_pipeline.py index cabcdd6..00363c7 100644 --- a/src/gateware/cxp_pipeline.py +++ b/src/gateware/cxp_pipeline.py @@ -301,6 +301,25 @@ class RX_Debug_Buffer(Module,AutoCSR): self.dout_valid.status.eq(buf_out.source.stb), ] +class Duplicate_Majority_Voter(Module): + def __init__(self, data, k): + assert data.nbits == 32 + assert k.nbits == 4 + + # Section 9.2.2.1 (CXP-001-2021) + # decoder should immune to single bit errors when handling duplicated characters + self.char = Signal(char_width) + self.k = Signal() + + a, a_k = data[:8], k[0] + b, b_k = data[8:16], k[1] + c, c_k = data[16:24], k[2] + d, d_k = data[24:], k[3] + self.comb += [ + self.char.eq(a&b&c | a&b&d | a&c&d | b&c&d), + self.k.eq(a_k&b_k&c_k | a_k&b_k&d_k | a_k&c_k&d_k | b_k&c_k&d_k), + ] + @FullMemoryWE() class CXP_Data_Packet_Decode(Module): def __init__(self): @@ -313,7 +332,6 @@ class CXP_Data_Packet_Decode(Module): # DEBUG: remove debug # TODO: decode all packet type here - # TODO: data&event -> memory # TODO: heartbeat type = { "data_stream": 0x01, @@ -331,10 +349,23 @@ class CXP_Data_Packet_Decode(Module): self.submodules.fsm = fsm = FSM(reset_state="IDLE") + self.submodules.voter = voter = Duplicate_Majority_Voter(self.sink.data, self.sink.k) + + # # Section 9.2.2.1 (CXP-001-2021) + # # decoder should immune to single bit errors when handling duplicated characters + # char_majority = Signal(char_width) + # k_majority = Signal() + # a, b, c, d = self.sink.data[:8], self.sink.data[8:16], self.sink.data[16:24], self.sink.data[24:] + # a_k, b_k, c_k, d_k = self.sink.k[0], self.sink.k[1], self.sink.k[2], self.sink.k[3] + # self.comb += [ + # char_majority.eq(a&b&c | a&b&d | a&c&d | b&c&d), + # k_majority.eq(a_k&b_k&c_k | a_k&b_k&d_k | a_k&c_k&d_k | b_k&c_k&d_k), + # ] + + fsm.act("IDLE", self.sink.ack.eq(1), - # TODO: add error correction? - If((self.sink.stb & (self.sink.data == Replicate(KCode["pak_start"], 4)) & (self.sink.k == 0b1111)), + If((self.sink.stb & (voter.char == KCode["pak_start"]) & (voter.k == 1)), NextState("DECODE"), ) ) @@ -345,9 +376,9 @@ class CXP_Data_Packet_Decode(Module): fsm.act("DECODE", self.sink.ack.eq(1), If(self.sink.stb, - NextValue(self.packet_type, self.sink.data[:8]), + NextValue(self.packet_type, voter.char), - Case(self.sink.data[:8],{ + Case(voter.char, { type["data_stream"]: NextState("STREAMING"), type["control_ack_no_tag"]:[ NextValue(addr, addr.reset), @@ -384,7 +415,7 @@ class CXP_Data_Packet_Decode(Module): fsm.act("VERIFY_TEST_PATTERN", self.sink.ack.eq(1), If(self.sink.stb, - If(((self.sink.data == Replicate(KCode["pak_end"], 4)) & (self.sink.k == 0b1111)), + If(((voter.char == KCode["pak_end"]) & (voter.k == 1)), NextState("IDLE"), ).Else( If(((self.sink.data != Cat(cnt, cnt+1, cnt+2, cnt+3))), @@ -402,7 +433,7 @@ class CXP_Data_Packet_Decode(Module): # For stream data packet fsm.act("STREAMING", - If((self.sink.stb & (self.sink.data == Replicate(KCode["pak_end"], 4)) & (self.sink.k == 0b1111)), + If((self.sink.stb & (voter.char == KCode["pak_end"]) & (voter.k == 1)), # discard K29,7 self.sink.ack.eq(1), NextState("IDLE") @@ -429,7 +460,7 @@ class CXP_Data_Packet_Decode(Module): mem_port.we.eq(0), self.sink.ack.eq(1), If(self.sink.stb, - If(((self.sink.data == Replicate(KCode["pak_end"], 4)) & (self.sink.k == 0b1111)), + If(((voter.char == KCode["pak_end"]) & (voter.k == 1)), NextState("MOVE_BUFFER_PTR"), ).Else( mem_port.we.eq(1), @@ -468,8 +499,10 @@ class CXP_Trig_Ack_Checker(Module, AutoCSR): self.submodules.fsm = fsm = FSM(reset_state="COPY") + self.submodules.voter = voter = Duplicate_Majority_Voter(self.sink.data, self.sink.k) + fsm.act("COPY", - If((self.sink.stb & (self.sink.data == Replicate(KCode["io_ack"], 4)) & (self.sink.k == 0b1111)), + If((self.sink.stb & (voter.char == KCode["io_ack"]) & (voter.k == 1)), # discard K28,6 self.sink.ack.eq(1), NextState("CHECK_ACK") @@ -483,7 +516,7 @@ class CXP_Trig_Ack_Checker(Module, AutoCSR): NextState("COPY"), # discard the word after K28,6 self.sink.ack.eq(1), - If(self.sink.data == Replicate(C(0x01, char_width), 4), + If((voter.char == 0x01) & (voter.k == 0), self.ack.eq(1), ) )