Belle II KLM Scint Firmware  1
b2tt_8b10b.vhd
1 ------------------------------------------------------------------------
2 -- b2tt_8b10b.vhd --- 8b10b encoder (b2tt_en8b10b) and decoder (b2tt_de8b10b)
3 --
4 -- 20030624 data part is confirmed to work with a FPGA setup
5 -- (code: ftest_en v0.10)
6 -- 20110102 rewritten
7 -- based on http://en.wikipedia.org/wiki/8b/10b_encoding
8 -- 20130411 renamed from b2tt_8b10b to tt_8b10b
9 -- 20130507 renamed back to b2tt_8b10b from tt_8b10b
10 -- 20130522 fixed err[4]
11 -- 20131101 no more std_logic_arith
12 --
13 -- eout bit 9 is first transmitted, bit 0 is last transmitted
14 -- ein bit 9 is first received, bit 0 is last received
15 --
16 -- Mikihiko Nakao, KEK IPNS
17 ------------------------------------------------------------------------
18 
19 library ieee;
20 use ieee.std_logic_1164.all;
21 use ieee.std_logic_unsigned.all;
22 use ieee.numeric_std.all;
23 
24 entity b2tt_en8b10b is
25  port (
26  reset : in std_logic;
27  clock : in std_logic;
28  en : in std_logic;
29  isk : in std_logic;
30  din : in std_logic_vector(7 downto 0);
31  eout : out std_logic_vector(9 downto 0);
32  validk : out std_logic;
33  rdnext : out std_logic;
34  rd6psav : out std_logic;
35  rd4psav : out std_logic );
36 
37 end b2tt_en8b10b;
38 
39 architecture implementation of b2tt_en8b10b is
40 
41  alias din5 : std_logic_vector(4 downto 0) is din(4 downto 0);
42  alias din3 : std_logic_vector(2 downto 0) is din(7 downto 5);
43 
44  signal eout6 : std_logic_vector(5 downto 0) := "111111";
45  signal eout6m : std_logic_vector(5 downto 0) := "111111";
46  signal eout6p : std_logic_vector(5 downto 0) := "111111";
47  signal eout4 : std_logic_vector(3 downto 0) := "1111";
48  signal eout4m : std_logic_vector(3 downto 0) := "1111";
49  signal eout4p : std_logic_vector(3 downto 0) := "1111";
50 
51  signal rd6p : std_logic := '0';
52  signal rd4p : std_logic := '0';
53  signal rdplus : std_logic := '1';
54 
55 begin
56  -- 5b6b table for RD-
57  eout6m <=
58  "100111" when din5 = "00000" else -- D0.x
59  "011101" when din5 = "00001" else -- D1.x
60  "101101" when din5 = "00010" else -- D2.x
61  "110001" when din5 = "00011" else -- D3.x
62  "110101" when din5 = "00100" else -- D4.x
63  "101001" when din5 = "00101" else -- D5.x
64  "011001" when din5 = "00110" else -- D6.x
65  "111000" when din5 = "00111" else -- D7.x
66  "111001" when din5 = "01000" else -- D8.x
67  "100101" when din5 = "01001" else -- D9.x
68  "010101" when din5 = "01010" else -- D10.x
69  "110100" when din5 = "01011" else -- D11.x
70  "001101" when din5 = "01100" else -- D12.x
71  "101100" when din5 = "01101" else -- D13.x
72  "011100" when din5 = "01110" else -- D14.x
73  "010111" when din5 = "01111" else -- D15.x
74  "011011" when din5 = "10000" else -- D16.x
75  "100011" when din5 = "10001" else -- D17.x
76  "010011" when din5 = "10010" else -- D18.x
77  "110010" when din5 = "10011" else -- D19.x
78  "001011" when din5 = "10100" else -- D20.x
79  "101010" when din5 = "10101" else -- D21.x
80  "011010" when din5 = "10110" else -- D22.x
81  "111010" when din5 = "10111" else -- D23.x and K23.7
82  "110011" when din5 = "11000" else -- D24.x
83  "100110" when din5 = "11001" else -- D25.x
84  "010110" when din5 = "11010" else -- D26.x
85  "110110" when din5 = "11011" else -- D27.x and K27.7
86  "001111" when din5 = "11100" and isk = '1' else -- K28.x
87  "001110" when din5 = "11100" and isk = '0' else -- D28.x
88  "101110" when din5 = "11101" else -- D29.x and K29.7
89  "011110" when din5 = "11110" else -- D30.x and K30.7
90  "101011"; -- D31.x
91 
92  -- RD+ table from RD- table
93  -- RD+ = RD- if equal number of 0 and 1 else not RD-.
94 
95  -- following have unequal number of 0 and 1:
96  -- K28, (note D28 has equal number of 0 and 1)
97  -- D0, D8, D16, D24 (lowest 3-bit 000)
98  -- D7, D15, D23, D31 (lowest 3-bit 111)
99  -- D1, D2, D4, (only one 1 in din5)
100  -- D27, D29, D30 (only one 0 in din5) */
101  rd6p <= rdplus;
102  eout6p <= not eout6m when
103  ((isk = '1' and din5 = "11100") or
104  din5(2 downto 0) = "000" or
105  din5(2 downto 0) = "111" or
106  (din5(4 downto 3) = "00"
107  and (din5(2) xor din5(1) xor din5(0)) = '1'
108  and (din5(2) and din5(1) and din5(0)) = '0') or
109  (din5(4 downto 3) = "11"
110  and (din5(2) xor din5(1) xor din5(0)) = '0'
111  and (din5(2) or din5(1) or din5(0)) = '1')) else
112  eout6m;
113 
114  rd4p <= not rd6p when
115  ((isk = '1' and din5 = "11100") or
116  din5(2 downto 0) = "000" or
117  (din5(2 downto 0) = "111" and din5(4 downto 3) /= "00") or
118  (din5(4 downto 3) = "00"
119  and (din5(2) xor din5(1) xor din5(0)) = '1'
120  and (din5(2) and din5(1) and din5(0)) = '0') or
121  (din5(4 downto 3) = "11"
122  and (din5(2) xor din5(1) xor din5(0)) = '0'
123  and (din5(2) or din5(1) or din5(0)) = '1')) else
124  rd6p;
125 
126  -- 3b4b RD+ table
127  -- RD+ table is the same for D and K, but RD- is not
128  eout4p <= "0100" when din3 = "000" else
129  "1001" when din3 = "001" else
130  "0101" when din3 = "010" else
131  "0011" when din3 = "011" else
132  "0010" when din3 = "100" else
133  "1010" when din3 = "101" else
134  "0110" when din3 = "110" else
135  -- alternative RD+ for D11.7, D13.7, D24.7 and Kxx.7
136  "1000" when isk = '1'
137  or din5 = "01011" or din5 = "01101" or din5 = "01110" else
138  "0001";
139 
140  -- 3b4b RD- table
141  -- following have unequal number of 0 and 1:
142  -- Dxx.0, Dxx.4, Dxx.7, K28.0, K28.4, Kxx.7
143  -- alternative RD- for D17.7, D18.7, D20.7 and Kxx.7
144  -- alternative RD- for D11.7, D13.7, D14.7 and Kxx.7
145  eout4m <= not eout4p when din3 = "000" or din3 = "100" else
146  "0111" when din3 = "111" and (isk = '1' or
147  din5 = "10001" or din5 = "10010" or din5 = "10100") else
148  "1110" when din3 = "111" else
149  not eout4p when isk = '1' or din3 = "011" else
150  eout4p;
151 
152  eout6 <= eout6m when rd6p = '0' else eout6p;
153  eout4 <= eout4m when rd4p = '0' else eout4p;
154  eout <= eout6 & eout4;
155 
156  process(clock)
157  begin
158  if clock'event and clock = '1' then
159  if reset = '1' then
160  rdplus <= '1';
161  validk <= '1';
162 
163  elsif en = '1' then
164 
165  -- valid K character check
166  if isk = '1' then
167  if din5 = "11100" then
168  validk <= '1';
169  elsif din3 = "111" and din5(4) = '1' and
170  (din5(3) xor din5(2) xor din5(1) xor din5(0)) = '1' and
171  ((din5(3) and din5(2)) or (din5(1) and din5(0))) = '1' then
172  validk <= '1';
173  else
174  validk <= '0';
175  end if;
176  else
177  validk <= '1';
178  end if;
179 
180  -- RD for the next cycle
181  if din3 = "000" or din3 = "100" or din3 = "111" then
182  rdplus <= not rd4p;
183  else
184  rdplus <= rd4p;
185  end if;
186  rd6psav <= rd6p;
187  rd4psav <= rd4p;
188  end if;
189  end if;
190  end process;
191 
192  -- output
193  rdnext <= rdplus; -- for debug
194 
195 end implementation;
196 ------------------------------------------------------------------------
197 library IEEE;
198 use IEEE.STD_LOGIC_1164.ALL;
199 use IEEE.STD_LOGIC_ARITH.ALL;
200 use IEEE.STD_LOGIC_UNSIGNED.ALL;
201 
202 entity b2tt_de8b10b is
203  port (
204  reset : in std_logic;
205  clock : in std_logic;
206  en : in std_logic;
207  ein : in std_logic_vector(9 downto 0);
208  dout : out std_logic_vector(7 downto 0);
209  isk : out std_logic;
210  err : out std_logic_vector(4 downto 0);
211  rdp : out std_logic );
212 
213 end b2tt_de8b10b;
214 
215 architecture implementation of b2tt_de8b10b is
216 
217  signal rdplus : std_logic := '1';
218  signal dout3 : std_logic_vector (2 downto 0) := "000";
219  signal dout5 : std_logic_vector (4 downto 0) := "00000";
220  alias ein4 : std_logic_vector (3 downto 0) is ein(3 downto 0);
221  alias ein6 : std_logic_vector (5 downto 0) is ein(9 downto 4);
222  signal rd_defined : std_logic := '0';
223  signal bad_ein4 : std_logic := '0';
224  signal bad_ein6 : std_logic := '0';
225  signal bad_rd4 : std_logic := '0';
226  signal bad_rd6 : std_logic := '0';
227  signal expect_rd4m : std_logic := '0';
228  signal expect_rd4p : std_logic := '0';
229  signal expect_rd6m : std_logic := '0';
230  signal expect_rd6p : std_logic := '0';
231  signal rd6flip : std_logic := '0';
232  signal rd4flip : std_logic := '0';
233  signal rd4p : std_logic := '0';
234 
235 begin
236 
237  -- 3b4b table
238  dout3 <= "000" when ein4 = "1011" or ein4 = "0100" else
239  "001" when ein4 = "1001" and ein6 /= "110000" else
240  "001" when ein4 = "0110" and ein6 = "110000" else
241  "010" when ein4 = "0101" and ein6 /= "110000" else
242  "010" when ein4 = "1010" and ein6 = "110000" else
243  "011" when ein4 = "1100" or ein4 = "0011" else
244  "100" when ein4 = "1101" or ein4 = "0010" else
245  "101" when ein4 = "1010" and ein6 /= "110000" else
246  "101" when ein4 = "0101" and ein6 = "110000" else
247  "110" when ein4 = "0110" and ein6 /= "110000" else
248  "110" when ein4 = "1001" and ein6 = "110000" else
249  "111";
250 
251  -- invalid 3b4b
252  bad_ein4 <= '1' when ein4 = "0000" or ein4 = "1111" else '0';
253 
254  -- 5b6b table
255  dout5 <= "00000" when ein6 = "100111" or ein6 = "011000" else
256  "00001" when ein6 = "011101" or ein6 = "100010" else
257  "00010" when ein6 = "101101" or ein6 = "010010" else
258  "00011" when ein6 = "110001" else
259  "00100" when ein6 = "110101" or ein6 = "001010" else
260  "00101" when ein6 = "101001" else
261  "00110" when ein6 = "011001" else
262  "00111" when ein6 = "111000" or ein6 = "000111" else
263  "01000" when ein6 = "111001" or ein6 = "000110" else
264  "01001" when ein6 = "100101" else
265  "01010" when ein6 = "010101" else
266  "01011" when ein6 = "110100" else
267  "01100" when ein6 = "001101" else
268  "01101" when ein6 = "101100" else
269  "01110" when ein6 = "011100" else
270  "01111" when ein6 = "010111" or ein6 = "101000" else
271  "10000" when ein6 = "011011" or ein6 = "100100" else
272  "10001" when ein6 = "100011" else
273  "10010" when ein6 = "010011" else
274  "10011" when ein6 = "110010" else
275  "10100" when ein6 = "001011" else
276  "10101" when ein6 = "101010" else
277  "10110" when ein6 = "011010" else
278  "10111" when ein6 = "111010" or ein6 = "000101" else
279  "11000" when ein6 = "110011" or ein6 = "001100" else
280  "11001" when ein6 = "100110" else
281  "11010" when ein6 = "010110" else
282  "11011" when ein6 = "110110" or ein6 = "001001" else
283  "11100" when ein6 = "001110" else
284  "11101" when ein6 = "101110" or ein6 = "010001" else
285  "11110" when ein6 = "011110" or ein6 = "100001" else
286  "11100" when ein6 = "001111" or ein6 = "110000" else
287  "11111";
288 
289 
290  -- invalid 5b6b - all 0, five 0 or 000011 and comlements
291  bad_ein6 <= '1' when
292  ein6 = "000000" or ein6 = "111111" or
293  ein6 = "000001" or ein6 = "000010" or ein6 = "000100" or
294  ein6 = "001000" or ein6 = "010000" or ein6 = "100000" or
295  ein6 = "111110" or ein6 = "111101" or ein6 = "111011" or
296  ein6 = "110111" or ein6 = "101111" or ein6 = "011111" or
297  ein6 = "000011" or ein6 = "111100" else
298  '0';
299 
300  -- must be rd- to receive 11xx or yy11 with yy /= 00,
301  -- must be rd+ to receive 00xx or yy00 with yy /= 11
302  expect_rd4m <= (ein4(3) and ein4(2)) or
303  ((ein4(3) or ein4(2)) and ein4(1) and ein4(0));
304  expect_rd4p <= not ((ein4(3) or ein4(2)) and
305  ((ein4(3) and ein4(2)) or ein4(1) or ein4(0)));
306  -- must be RD- if 111aaa or bb1111 or
307  -- xxyyzz with all xx,yy,zz /= 00 and one of them = 11,
308  -- must be RD+ if xxyyzz with all xx,yy,zz /= 11 and one of them = 00
309  expect_rd6m <=
310  (ein6(5) and ein6(4) and ein6(3)) or -- 111aaa
311  (ein6(3) and ein6(2) and ein6(1) and ein6(0)) or -- bb1111
312  (ein6(5) and ein6(4) and ein6(1) and ein6(0)) or -- 11cc11
313  ((ein6(5) or ein6(4)) and -- all xx,yy,zz /= 00
314  (ein6(3) or ein6(2)) and (ein6(1) or ein6(0)) and
315  ((ein6(5) and ein6(4)) or -- one of xx,yy,zz = 11
316  (ein6(3) and ein6(2)) or (ein6(1) and ein6(0))));
317  expect_rd6p <= not (
318  (ein6(5) or ein6(4) or ein6(3)) and -- ! 000aaa
319  (ein6(3) or ein6(2) or ein6(1) or ein6(0)) and -- ! bb0000
320  (ein6(5) or ein6(4) or ein6(1) or ein6(0)) and -- ! 00cc00
321  ((ein6(5) and ein6(4)) or -- ! all xx,yy,zz /= 11
322  (ein6(3) and ein6(2)) or (ein6(1) and ein6(0)) or
323  ((ein6(5) or ein6(4)) and -- ! one of xx,yy,zz = 00
324  (ein6(3) or ein6(2)) and (ein6(1) or ein6(0)))));
325 
326  -- RD flips after 6b with even (2 or 4) number of 0s/1s
327  -- and after 4b with odd (1 or 3) number of 0s/1s,
328  -- since there's no 6b with 0,1,5,6 0s/1s and no 4b with 0,4 0s/1s
329  rd6flip <=
330  not (ein6(5) xor ein6(4) xor ein6(3) xor ein6(2) xor ein6(1) xor ein6(0));
331  rd4flip <= ein4(3) xor ein4(2) xor ein4(1) xor ein4(0);
332 
333  -- next RD
334  rd4p <= not rd6flip when expect_rd6p = '1' else
335  rd6flip when expect_rd6m = '1' else
336  rdplus;
337 
338  -- K character (K23,K27,K29,K30)
339  -- RD+ ein6(1:0) = 01 and only one 1 in din(5:2)
340  -- RD- ein6(1:0) = 10 and only one 0 in din(5:2)
341  isk <= '1' when ein6 = "001111" or ein6 = "110000" else
342  (ein6(0) xor ein6(1)) and -- ein6(1:0) = 01 or 10
343  (ein6(5) xor ein6(4) xor ein6(3) xor ein6(2)) and -- ein6(5:2) odd
344  (((ein6(5) or ein6(4)) and (ein6(3) or ein6(2))) xor ein6(0)) and
345  (ein4(3) xor ein4(2)) and -- 0111 or 1000
346  (ein4(3) xor ein4(1)) and
347  (not (ein4(1) xor ein4(0)));
348 
349  -- check valid RD
350  bad_rd6 <= rd_defined and
351  ((rdplus and expect_rd6m) or ((not rdplus) and expect_rd6p));
352  bad_rd4 <= (rd_defined) and
353  ((rd4p and expect_rd4m) or ((not rd4p) and expect_rd4p));
354 
355  dout <= dout3 & dout5;
356 
357  -- process
358  process(clock)
359  begin
360  if clock = '1' and clock'event then
361  if reset = '1' then
362  elsif en = '1' then
363  if expect_rd4p = '1' then
364  rdplus <= not rd4flip;
365  elsif expect_rd4m = '1' then
366  rdplus <= rd4flip;
367  else
368  rdplus <= rd4p;
369  end if;
370 
371  if (bad_rd4 or bad_rd6 or bad_ein6 or bad_ein4) = '1' then
372  rd_defined <= '0';
373  else
374  rd_defined <= '1';
375  end if;
376  err <= (not rd_defined) & bad_rd4 & bad_rd6 & bad_ein6 & bad_ein4;
377  end if;
378  end if;
379  end process;
380 
381  -- out signal
382  rdp <= rdplus;
383 
384 end implementation;