-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathibm_8b_10b_encoder.adb
292 lines (267 loc) · 10.3 KB
/
ibm_8b_10b_encoder.adb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
--Copyright (c) 2019 Alex Tsantilis under the MIT License
package body IBM_8b_10b_Encoder is
type Encoder_Entry is
record
RD_Neg_Val: Ten_Bits;
RD_Pos_Val: Ten_Bits;
RD_Changes: Boolean;
end record;
type Decoder_Entry is
record
Key: Ten_Bits := 0;
Value: Byte := 0;
end record;
type Decoder_Table is array(Natural range 0 .. 255) of Decoder_Entry;
Encoder_Table: array(Byte) of Encoder_Entry;
Decoder_Table_RD_Neg: Decoder_Table;
Decoder_Table_RD_Pos: Decoder_Table;
procedure Encode( B: in Byte;
T: out Ten_Bits;
RD: in out Running_Disp) is
begin
case RD is
when Neg_1 => T := Encoder_Table(B).RD_Neg_Val;
case Encoder_Table(B).RD_Changes is
when False => RD := Neg_1;
when True => RD := Pos_1;
end case;
when Pos_1 => T := Encoder_Table(B).RD_Pos_Val;
case Encoder_Table(B).RD_Changes is
when False => RD := Pos_1;
when True => RD := Neg_1;
end case;
end case;
end Encode;
function Compute_Hash_Index(K: Ten_Bits;
Table_Size: Natural) return Natural is
begin
return Natural(K) mod Table_Size;
end Compute_Hash_Index;
procedure Insert( Table: in out Decoder_Table;
Key: in Ten_Bits;
Value: in Byte;
Success: out Boolean ) is
I: Natural := 0;
Idx, Idx_Modded: Natural;
begin
Success := False;
Idx := Compute_Hash_Index(Key, Table'Length);
Idx_Modded := Idx;
loop
if Table(Idx_Modded).Key = 0 or Table(Idx_Modded).Key = Key then
Table(Idx_Modded).Key := Key;
Table(Idx_Modded).Value := Value;
Success := True;
else
I := I + 1;
--Note: this variant of the quadratic probing algorithm
--is most effective with tables with 2^n entries, where
--n is any positive integer. Coincidentally, this works
--perfectly for our encoding table. :D
Idx_Modded := (Idx + (I + I**2)/2) mod Table'Length;
end if;
exit when Success or I >= Table'Length;
end loop;
end Insert;
procedure Find_Entry( Table: in Decoder_Table;
Key: in Ten_Bits;
Value: out Byte;
Success: out Boolean) is
I: Natural := 0;
Idx, Idx_Modded: Natural;
begin
Success := False;
Idx := Compute_Hash_Index(Key, Table'Length);
Idx_Modded := Idx;
loop
if Table(Idx_Modded).Key = Key then
Value := Table(Idx_Modded).Value;
Success := True;
else
I := I + 1;
Idx_Modded := (Idx + (I + I**2)/2) mod Table'Length;
end if;
exit when Success or I >= Table'Length;
end loop;
end Find_Entry;
--To verify that Running Disparity is being preserved, use this version.
procedure Decode( T: in Ten_Bits;
B: out Byte;
RD: in out Running_Disp;
Success: out Boolean) is
begin
case RD is
when Neg_1 =>
Find_Entry(Decoder_Table_RD_Neg, T, B, Success);
case Encoder_Table(B).RD_Changes is
when False => RD := Neg_1;
when True => RD := Pos_1;
end case;
when Pos_1 =>
Find_Entry(Decoder_Table_RD_Pos, T, B, Success);
case Encoder_Table(B).RD_Changes is
when False => RD := Pos_1;
when True => RD := Neg_1;
end case;
end case;
end Decode;
procedure Decode( T: in Ten_Bits;
B: out Byte;
Success: out Boolean) is
begin
Find_Entry(Decoder_Table_RD_Neg, T, B, Success);
if not Success then
Find_Entry(Decoder_Table_RD_Pos, T, B, Success);
end if;
end Decode;
begin
declare
--8 to 10 bit encoding table construction necessities (all are temporary)
Table_5to6_Bits: array(Byte range 0 .. 31, 0 .. 1) of Ten_Bits :=
((2#111001#, 2#000110#),
(2#101110#, 2#010001#),
(2#101101#, 2#010010#),
(2#100011#, 2#100011#),
(2#101011#, 2#010100#),
(2#100101#, 2#100101#),
(2#100110#, 2#100110#),
(2#000111#, 2#111000#),
(2#100111#, 2#011000#),
(2#101001#, 2#101001#),
(2#101010#, 2#101010#),
(2#001011#, 2#001011#),
(2#101100#, 2#101100#),
(2#001101#, 2#001101#),
(2#001110#, 2#001110#),
(2#111010#, 2#000101#),
(2#110110#, 2#001001#),
(2#110001#, 2#110001#),
(2#110010#, 2#110010#),
(2#010011#, 2#010011#),
(2#110100#, 2#110100#),
(2#010101#, 2#010101#),
(2#010110#, 2#010110#),
(2#010111#, 2#101000#),
(2#110011#, 2#001100#),
(2#011001#, 2#011001#),
(2#011010#, 2#011010#),
(2#011011#, 2#100100#),
(2#011100#, 2#011100#),
(2#011101#, 2#100010#),
(2#011110#, 2#100001#),
(2#110101#, 2#001010#));
Table_3to4_Bits: array(Byte range 0 .. 7, 0 .. 3) of Ten_Bits :=
--RD -1, RD +1
((2#1101#, 2#0010#, -1, -1),
(2#1001#, 2#1001#, -1, -1),
(2#1010#, 2#1010#, -1, -1),
(2#0011#, 2#1100#, -1, -1),
(2#1011#, 2#0100#, -1, -1),
(2#0101#, 2#0101#, -1, -1),
(2#0110#, 2#0110#, -1, -1),
--||---Primary----|||---Alternate---||
--RD -1 , RD +1 | RD -1 , RD +1
(2#0111#, 2#1000#, 2#1110#, 2#0001#));
NO : Boolean := False;
YES : Boolean := True;
Changes_Running_Disp: array(Byte range 0 .. 31) of Boolean :=
(
NO ,
NO ,
NO ,
YES,
NO ,
YES,
YES,
YES,
NO ,
YES,
YES,
YES,
YES,
YES,
YES,
NO ,
NO ,
YES,
YES,
YES,
YES,
YES,
YES,
NO ,
NO ,
YES,
YES,
NO ,
YES,
NO ,
NO ,
NO
);
Old_Right, Old_Left: Byte := 0;
Encoded_Left_Pos, Encoded_Left_Neg,
Encoded_Right_Pos, Encoded_Right_Neg: Ten_Bits := 0;
RD_Change_Idx: Byte;
Insertion_Error: exception;
begin
for I in Byte range 0 .. 255 loop
Old_Right := I and 2#000_11111#;
Old_Left := (I and 2#111_00000#) / 2**5;
--Encoding the right 5 bits is easy, but encoding the left
--3 bits requires following a very specific pattern...
Encoded_Right_Neg := Table_5to6_Bits(Old_Right, 0);
Encoded_Right_Pos := Table_5to6_Bits(Old_Right, 1);
if Old_Left < 2#111# then
--when the encoding of the right bits is the same regardless
--of the running disparity (7 is an exception because it has
--equal 0s and 1s), the 5 bit encoding for (-) RD is paired with
--the 3 bit encoding for (-) RD, and (+) with (+)
if Encoded_Right_Neg = Encoded_Right_Pos or Old_Right = 7 then
Encoded_Left_Neg := Table_3to4_Bits(Old_Left, 0);
Encoded_Left_Pos := Table_3to4_Bits(Old_Left, 1);
else
Encoded_Left_Neg := Table_3to4_Bits(Old_Left, 1);
Encoded_Left_Pos := Table_3to4_Bits(Old_Left, 0);
end if;
--when the 3 left bits to encode are "111", there are unique
--circumstances where an alternate output needs to be used
else
if Encoded_Right_Neg = Encoded_Right_Pos or Old_Right = 7 then
if Old_Right /= 17 and Old_Right /= 18 and Old_Right /= 20 then
Encoded_Left_Neg := Table_3to4_Bits(Old_Left, 0);
else
Encoded_Left_Neg := Table_3to4_Bits(Old_Left, 2);
end if;
if Old_Right /= 11 and Old_Right /= 13 and Old_Right /= 14 then
Encoded_Left_Pos := Table_3to4_Bits(Old_Left, 1);
else
Encoded_Left_Pos := Table_3to4_Bits(Old_Left, 3);
end if;
else
Encoded_Left_Neg := Table_3to4_Bits(Old_Left, 1);
Encoded_Left_Pos := Table_3to4_Bits(Old_Left, 0);
end if;
end if;
RD_Change_Idx := I mod 32;
declare
E: Encoder_Entry;
Check: Boolean;
begin
--Add an entry to the encoding table...
E.RD_Neg_Val := (Encoded_Left_Neg * 2**6) or Encoded_Right_Neg;
E.RD_Pos_Val := (Encoded_Left_Pos * 2**6) or Encoded_Right_Pos;
if Old_Left = 2#000# or Old_Left = 2#100# or Old_Left = 2#111# then
E.RD_Changes := Changes_Running_Disp(RD_Change_Idx);
else
E.RD_Changes := not Changes_Running_Disp(RD_Change_Idx);
end if;
Encoder_Table(I) := E;
--...and add the flipped keys and values to the decoding tables
Insert(Decoder_Table_RD_Neg, E.RD_Neg_Val, I, Check);
Insert(Decoder_Table_RD_Pos, E.RD_Pos_Val, I, Check);
if not Check then raise Insertion_Error; end if;
end;
end loop;
end;
end IBM_8b_10b_Encoder;