1 # This file is Copyright (c) 2018-2019 Florent Kermarrec <florent@enjoy-digital.fr>
7 Hamming codes with additional parity (SECDED):
8 - Single Error Correction
9 - Double Error Detection
12 from functools
import reduce
13 from operator
import xor
17 # Helpers ------------------------------------------------------------------------------------------
21 while (2**m
< (m
+ k
+ 1)):
27 def compute_syndrome_positions(m
):
36 def compute_data_positions(m
):
38 e
= compute_syndrome_positions(m
)
39 for i
in range(1, m
+ 1):
45 def compute_cover_positions(m
, p
):
49 for j
in range(min(p
, m
- i
+ 1)):
54 # SECDED (Single Error Detection, Double Error Detection) ------------------------------------------
57 def place_data(self
, data
, codeword
):
58 d_pos
= compute_data_positions(len(codeword
))
59 for i
, d
in enumerate(d_pos
):
60 self
.comb
+= codeword
[d
-1].eq(data
[i
])
62 def extract_data(self
, codeword
, data
):
63 d_pos
= compute_data_positions(len(codeword
))
64 for i
, d
in enumerate(d_pos
):
65 self
.comb
+= data
[i
].eq(codeword
[d
-1])
67 def compute_syndrome(self
, codeword
, syndrome
):
68 p_pos
= compute_syndrome_positions(len(codeword
))
69 for i
, p
in enumerate(p_pos
):
71 c_pos
= compute_cover_positions(len(codeword
), 2**i
)
74 self
.comb
+= new_pn
.eq(pn ^ codeword
[c
-1])
76 self
.comb
+= syndrome
[i
].eq(pn
)
78 def place_syndrome(self
, syndrome
, codeword
):
79 p_pos
= compute_syndrome_positions(len(codeword
))
80 for i
, p
in enumerate(p_pos
):
81 self
.comb
+= codeword
[p
-1].eq(syndrome
[i
])
83 def compute_parity(self
, codeword
, parity
):
84 self
.comb
+= parity
.eq(reduce(xor
,
85 [codeword
[i
] for i
in range(len(codeword
))]))
87 # ECC Encoder --------------------------------------------------------------------------------------
89 class ECCEncoder(SECDED
, Module
):
90 def __init__(self
, k
):
93 self
.i
= i
= Signal(k
)
94 self
.o
= o
= Signal(n
+ 1)
100 codeword_d
= Signal(n
)
101 codeword_d_p
= Signal(n
)
102 codeword
= Signal(n
+ 1)
104 # place data bits in codeword
105 self
.place_data(i
, codeword_d
)
106 # compute and place syndrome bits
107 self
.compute_syndrome(codeword_d
, syndrome
)
108 self
.comb
+= codeword_d_p
.eq(codeword_d
)
109 self
.place_syndrome(syndrome
, codeword_d_p
)
111 self
.compute_parity(codeword_d_p
, parity
)
112 # output codeword + parity
113 self
.comb
+= o
.eq(Cat(parity
, codeword_d_p
))
115 # ECC Decoder --------------------------------------------------------------------------------------
117 class ECCDecoder(SECDED
, Module
):
118 def __init__(self
, k
):
119 m
, n
= compute_m_n(k
)
121 self
.enable
= Signal()
122 self
.i
= i
= Signal(n
+ 1)
123 self
.o
= o
= Signal(k
)
125 self
.sec
= sec
= Signal()
126 self
.ded
= ded
= Signal()
133 codeword_c
= Signal(n
)
135 # input codeword + parity
136 self
.compute_parity(i
, parity
)
137 self
.comb
+= codeword
.eq(i
[1:])
139 self
.compute_syndrome(codeword
, syndrome
)
140 self
.comb
+= If(~self
.enable
, syndrome
.eq(0))
141 # locate/correct codeword error bit if any and flip it
143 cases
["default"] = codeword_c
.eq(codeword
)
144 for i
in range(1, 2**len(syndrome
)):
145 cases
[i
] = codeword_c
.eq(codeword ^
(1<<(i
-1)))
146 self
.comb
+= Case(syndrome
, cases
)
147 # extract data / status
148 self
.extract_data(codeword_c
, o
)
151 # double error detected
154 # single error corrected