1
0
Fork 0

pipeline GW: add voter for duplicate char

This commit is contained in:
morgan 2024-10-09 12:12:14 +08:00
parent 61df5113a2
commit 24a16a3a5b
1 changed files with 43 additions and 10 deletions

View File

@ -301,6 +301,25 @@ class RX_Debug_Buffer(Module,AutoCSR):
self.dout_valid.status.eq(buf_out.source.stb), 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() @FullMemoryWE()
class CXP_Data_Packet_Decode(Module): class CXP_Data_Packet_Decode(Module):
def __init__(self): def __init__(self):
@ -313,7 +332,6 @@ class CXP_Data_Packet_Decode(Module):
# DEBUG: remove debug # DEBUG: remove debug
# TODO: decode all packet type here # TODO: decode all packet type here
# TODO: data&event -> memory
# TODO: heartbeat # TODO: heartbeat
type = { type = {
"data_stream": 0x01, "data_stream": 0x01,
@ -331,10 +349,23 @@ class CXP_Data_Packet_Decode(Module):
self.submodules.fsm = fsm = FSM(reset_state="IDLE") 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", fsm.act("IDLE",
self.sink.ack.eq(1), self.sink.ack.eq(1),
# TODO: add error correction? If((self.sink.stb & (voter.char == KCode["pak_start"]) & (voter.k == 1)),
If((self.sink.stb & (self.sink.data == Replicate(KCode["pak_start"], 4)) & (self.sink.k == 0b1111)),
NextState("DECODE"), NextState("DECODE"),
) )
) )
@ -345,9 +376,9 @@ class CXP_Data_Packet_Decode(Module):
fsm.act("DECODE", fsm.act("DECODE",
self.sink.ack.eq(1), self.sink.ack.eq(1),
If(self.sink.stb, 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["data_stream"]: NextState("STREAMING"),
type["control_ack_no_tag"]:[ type["control_ack_no_tag"]:[
NextValue(addr, addr.reset), NextValue(addr, addr.reset),
@ -384,7 +415,7 @@ class CXP_Data_Packet_Decode(Module):
fsm.act("VERIFY_TEST_PATTERN", fsm.act("VERIFY_TEST_PATTERN",
self.sink.ack.eq(1), self.sink.ack.eq(1),
If(self.sink.stb, 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"), NextState("IDLE"),
).Else( ).Else(
If(((self.sink.data != Cat(cnt, cnt+1, cnt+2, cnt+3))), 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 # For stream data packet
fsm.act("STREAMING", 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 # discard K29,7
self.sink.ack.eq(1), self.sink.ack.eq(1),
NextState("IDLE") NextState("IDLE")
@ -429,7 +460,7 @@ class CXP_Data_Packet_Decode(Module):
mem_port.we.eq(0), mem_port.we.eq(0),
self.sink.ack.eq(1), self.sink.ack.eq(1),
If(self.sink.stb, 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"), NextState("MOVE_BUFFER_PTR"),
).Else( ).Else(
mem_port.we.eq(1), 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.fsm = fsm = FSM(reset_state="COPY")
self.submodules.voter = voter = Duplicate_Majority_Voter(self.sink.data, self.sink.k)
fsm.act("COPY", 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 # discard K28,6
self.sink.ack.eq(1), self.sink.ack.eq(1),
NextState("CHECK_ACK") NextState("CHECK_ACK")
@ -483,7 +516,7 @@ class CXP_Trig_Ack_Checker(Module, AutoCSR):
NextState("COPY"), NextState("COPY"),
# discard the word after K28,6 # discard the word after K28,6
self.sink.ack.eq(1), 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), self.ack.eq(1),
) )
) )