Belle II KLM Scint Firmware  1
b2tt_encode.vhd
1 ------------------------------------------------------------------------
2 --
3 -- b2tt_encode.vhd -- TT-link encoder for Belle2link frontend
4 --
5 -- Mikihiko Nakao, KEK IPNS
6 --
7 -- 20130528 first version
8 -- 20131002 oddr is separated out
9 -- 20131101 no more std_logic_arith
10 -- 20131126 hold "err" until runreset
11 -- 20150406 ttup error study
12 -- 20150406 fix busy 1 -> 0 -> 0 -> 1 sequence
13 -- 20150330 b2tt_enoctet fully rewritten
14 -- 20150611 err is not bsy, signal renamed: busyup -> bsyup etc
15 -- 20170628 disparity fix for embedded bsyup/bsydn
16 --
17 -- eout bit 9 is first transmitted, bit 0 is last transmitted
18 -- ein bit 9 is first received, bit 0 is last received
19 --
20 ------------------------------------------------------------------------
21 
22 ------------------------------------------------------------------------
23 -- b2tt_encounter
24 ------------------------------------------------------------------------
25 library ieee;
26 use ieee.std_logic_1164.all;
27 use ieee.std_logic_unsigned.all;
28 use ieee.numeric_std.all;
29 
30 entity b2tt_encounter is
31  port (
32  clock : in std_logic;
33  frame : in std_logic;
34  staframe : out std_logic;
35  cntbit2 : out std_logic_vector (2 downto 0);
36  cntoctet : out std_logic_vector (3 downto 0);
37  cntpacket : out std_logic_vector (7 downto 0) );
38 end b2tt_encounter;
39 ------------------------------------------------------------------------
40 architecture implementation of b2tt_encounter is
41  signal sta_frame : std_logic := '0';
42  signal cnt_bit2 : std_logic_vector (2 downto 0) := "101";
43  signal cnt_octet : std_logic_vector (3 downto 0) := "0000";
44  signal cnt_packet : std_logic_vector (7 downto 0) := x"00";
45 begin
46  proc: process (clock)
47  begin
48  if clock'event and clock = '1' then
49 
50  -- sta_frame
51  if frame = '1' then
52  if cnt_bit2 = 4 and cnt_octet = 15 and cnt_packet = 255 then
53  sta_frame <= '1';
54  else
55  sta_frame <= '0';
56  end if;
57  end if;
58 
59  -- cnt_bit2
60  if frame = '1' or cnt_bit2 = 4 then
61  cnt_bit2 <= "000";
62  else
63  cnt_bit2 <= cnt_bit2 + 1;
64  end if;
65 
66  -- cnt_octet
67  if frame = '1' then
68  cnt_octet <= x"0";
69  elsif cnt_bit2 = 4 then
70  cnt_octet <= cnt_octet + 1;
71  end if;
72 
73  -- cnt_packet
74  if frame = '1' then
75  cnt_packet <= x"00";
76  elsif cnt_bit2 = 4 and cnt_octet = 15 then
77  cnt_packet <= cnt_packet + 1;
78  end if;
79 
80  end if;
81  end process;
82 
83  -- out
84  staframe <= sta_frame;
85  cntbit2 <= cnt_bit2;
86  cntoctet <= cnt_octet;
87  cntpacket <= cnt_packet;
88 
89 end implementation;
90 ------------------------------------------------------------------------
91 -- b2tt_enoctet
92 ------------------------------------------------------------------------
93 library ieee;
94 use ieee.std_logic_1164.all;
95 use ieee.std_logic_unsigned.all;
96 use ieee.numeric_std.all;
97 library work;
98 use work.b2tt_symbols.all;
99 
100 entity b2tt_enoctet is
101  port (
102  clock : in std_logic;
103  inbsy : in std_logic;
104  cntbit2 : in std_logic_vector (2 downto 0);
105  cntoctet : in std_logic_vector (3 downto 0);
106  payload : in std_logic_vector (111 downto 0); -- 14 bytes
107  octet : out std_logic_vector (7 downto 0);
108  isk : out std_logic );
109 end b2tt_enoctet;
110 ------------------------------------------------------------------------
111 architecture implementation of b2tt_enoctet is
112  signal buf_payload : std_logic_vector (111 downto 0) := (others => '0');
113  signal cnt_enoctet : std_logic_vector (3 downto 0) := (others => '0');
114  signal sta_crc8 : std_logic_vector (7 downto 0) := x"00";
115  subtype byte_t is std_logic_vector (7 downto 0);
116 
117  -- from crc8.vhd and comlib.vhd of
118  -- http://opencores.org/project,w11
119  -- 0x4d (x8 + x6 + x3 + x2 + 1) [ shr 1 makes 0xa6 ]
120  function crc8_update
121  ( crc: in byte_t; data: in byte_t ) return byte_t is
122  variable t : byte_t := (others => '0');
123  variable n : byte_t := (others => '0');
124  begin
125  t := data xor crc;
126  n(0) := t(5) xor t(4) xor t(2) xor t(0);
127  n(1) := t(6) xor t(5) xor t(3) xor t(1);
128  n(2) := t(7) xor t(6) xor t(5) xor t(0);
129  n(3) := t(7) xor t(6) xor t(5) xor t(4) xor t(2) xor t(1) xor t(0);
130  n(4) := t(7) xor t(6) xor t(5) xor t(3) xor t(2) xor t(1);
131  n(5) := t(7) xor t(6) xor t(4) xor t(3) xor t(2);
132  n(6) := t(7) xor t(3) xor t(2) xor t(0);
133  n(7) := t(4) xor t(3) xor t(1);
134  return n;
135  end function crc8_update;
136 
137 begin
138  proc: process (clock)
139  begin
140  if clock'event and clock = '1' then
141  -- cnt_datoctet
142  if cntbit2 /= 2 then
143  -- nothing
144  elsif cntoctet = 15 then
145  cnt_enoctet <= (others => '0');
146  elsif inbsy = '0' then
147  cnt_enoctet <= cnt_enoctet + 1;
148  end if;
149 
150  -- buf_payload
151  if cntbit2 /= 2 then
152  -- nothing
153  elsif cnt_enoctet = 0 then
154  buf_payload <= payload;
155  elsif inbsy = '0' then
156  buf_payload <= buf_payload(103 downto 0) & x"00";
157  end if;
158 
159  -- sta_crc8
160  -- this code doesn't care about inbsy, but it will not be
161  -- sent anyway if inbsy occurs
162  if cntbit2 /= 2 then
163  -- nothing
164  elsif cnt_enoctet = 0 then
165  sta_crc8 <= (others => '0');
166  else
167  sta_crc8 <= crc8_update(sta_crc8, buf_payload(111 downto 104));
168  end if;
169 
170  -- octet/isk (data to encode)
171  if cntbit2 /= 2 then
172  -- nothing
173  elsif cnt_enoctet = 0 then
174  octet <= K28_1;
175  isk <= '1';
176  elsif cnt_enoctet = 15 then
177  octet <= sta_crc8;
178  isk <= '0';
179  elsif inbsy = '0' then
180  octet <= buf_payload(111 downto 104);
181  isk <= '0';
182  end if;
183  end if;
184  end process;
185 end implementation;
186 ------------------------------------------------------------------------
187 -- b2tt_enbit2
188 ------------------------------------------------------------------------
189 library ieee;
190 use ieee.std_logic_1164.all;
191 use ieee.std_logic_unsigned.all;
192 use ieee.numeric_std.all;
193 
194 entity b2tt_enbit2 is
195  port (
196  clock : in std_logic;
197  errreset : in std_logic;
198  cntbit2 : in std_logic_vector (2 downto 0);
199  octet : in std_logic_vector (7 downto 0);
200  isk : in std_logic;
201  bsyin : in std_logic;
202  --errin : in std_logic;
203  inbsy : out std_logic;
204  bsyup : out std_logic; -- for debug
205  bsydn : out std_logic; -- for debug
206  bit2 : out std_logic_vector (1 downto 0);
207  validk : out std_logic;
208  rdnext : out std_logic;
209  rd6p : out std_logic;
210  rd4p : out std_logic );
211 end b2tt_enbit2;
212 ------------------------------------------------------------------------
213 architecture implementation of b2tt_enbit2 is
214  signal sig_en : std_logic := '0';
215  signal buf_10b : std_logic_vector (9 downto 0) := "0000000000";
216  signal seq_10b : std_logic_vector (7 downto 0) := "00000000";
217  signal seq_bsy : std_logic_vector (1 downto 0) := "00";
218  --signal seq_err : std_logic_vector (1 downto 0) := "00";
219  --signal sta_err : std_logic := '0';
220  signal sig_bsyup : std_logic := '0';
221  signal sig_bsydn : std_logic := '0';
222  signal cnt_k285 : std_logic_vector (2 downto 0) := "000";
223  signal seq_k285 : std_logic_vector (7 downto 0) := "00000000";
224 begin
225  -- in
226  sig_bsyup <= '1' when seq_bsy = "01" and cnt_k285 = 0 else '0';
227  sig_bsydn <= '1' when seq_bsy = "10" and cnt_k285 = 0 else '0';
228  sig_en <= '1' when cntbit2 = 3 and
229  sig_bsyup = '0' and sig_bsydn = '0' and cnt_k285 = 0 else '0';
230  --sig_bsydn <= '1' when seq_bsy = "10" and cnt_k285 = 0
231  -- and sta_err = '0' else '0';
232  map_en8b10b: entity work.b2tt_en8b10b
233  port map (
234  reset => '0',
235  clock => clock,
236  en => sig_en,
237  isk => isk,
238  din => octet,
239  eout => buf_10b, -- out/async
240  validk => validk, -- out
241  rdnext => rdnext, -- out
242  rd6psav => rd6p, -- out
243  rd4psav => rd4p ); -- out
244 
245  proc: process (clock)
246  begin
247  if clock'event and clock = '1' then
248 
249  -- seq_bsy to detect busy up/down
250  if errreset = '1' then
251  seq_bsy <= "00";
252  elsif cnt_k285 = 0 then
253  seq_bsy <= seq_bsy(0) & bsyin;
254  else
255  seq_bsy <= seq_bsy(0) & seq_bsy(0); -- 2017.0623.0621
256  end if;
257 
258  -- seq_k285, cnt_k285 (to intercept the bit stream with K28.5)
259  -- inbsy (to suspend other tasks for 5 clocks of K28.5 sending)
260  -- seq_10b (bit 7..0 of 8b10b data, bit 9..8 directly goes to bit2)
261  if sig_bsyup = '1' then
262  seq_k285 <= "00000101";
263  cnt_k285 <= "100";
264  inbsy <= '1';
265  bsyup <= '1';
266  elsif sig_bsydn = '1' then
267  seq_k285 <= "11111010";
268  cnt_k285 <= "100";
269  inbsy <= '1';
270  bsydn <= '1';
271  elsif cnt_k285 /= 0 then
272  cnt_k285 <= cnt_k285 - 1;
273  seq_k285 <= seq_k285(5 downto 0) & "00";
274  inbsy <= '1';
275  elsif cntbit2 = 3 then
276  seq_10b <= buf_10b(7 downto 0);
277  inbsy <= '0';
278  bsyup <= '0';
279  bsydn <= '0';
280  else
281  seq_10b <= seq_10b(5 downto 0) & "00";
282  inbsy <= '0';
283  bsyup <= '0';
284  bsydn <= '0';
285  end if;
286 
287  end if;
288  end process;
289 
290  -- out (partially async)
291  -- busy-begin: K28.5+ 1100000101
292  -- busy-end: K28.5- 0011111010
293  bit2 <= "11" when seq_bsy = "01" and cnt_k285 = 0 else
294  "00" when seq_bsy = "10" and cnt_k285 = 0 else
295  seq_k285(7 downto 6) when cnt_k285 /= 0 else
296  buf_10b(9 downto 8) when cntbit2 = 3 else -- async
297  seq_10b(7 downto 6);
298 
299 end implementation;
300 ------------------------------------------------------------------------
301 -- b2tt_encode
302 ------------------------------------------------------------------------
303 library ieee;
304 use ieee.std_logic_1164.all;
305 use ieee.std_logic_unsigned.all;
306 use ieee.numeric_std.all;
307 
308 entity b2tt_encode is
309  generic (
310  constant FLIPACK : std_logic := '0' );
311  port (
312  clock : in std_logic;
313  invclock : in std_logic;
314  frame : in std_logic;
315  errreset : in std_logic;
316  bsyin : in std_logic;
317  --errin : in std_logic;
318  payload : in std_logic_vector (111 downto 0);
319  fillsig : out std_logic;
320  ackp : out std_logic;
321  ackn : out std_logic;
322  cntbit2 : out std_logic_vector (2 downto 0);
323  cntoctet : out std_logic_vector (3 downto 0);
324  isk : out std_logic;
325  octet : out std_logic_vector (7 downto 0);
326  bsyup : out std_logic;
327  bsydn : out std_logic;
328  bit2 : out std_logic_vector (1 downto 0) );
329 end b2tt_encode;
330 ------------------------------------------------------------------------
331 architecture implementation of b2tt_encode is
332  signal sta_frame : std_logic := '0';
333  signal sig_inbsy : std_logic := '0';
334  signal cnt_bit2 : std_logic_vector (2 downto 0) := "101";
335  signal cnt_octet : std_logic_vector (3 downto 0) := "0000";
336  signal cnt_packet : std_logic_vector (7 downto 0) := x"00";
337  signal sig_bit2 : std_logic_vector (1 downto 0) := "00";
338  signal buf_isk : std_logic := '0';
339  signal buf_octet : std_logic_vector (7 downto 0) := x"00";
340  signal buf_rdnext : std_logic := '0';
341  signal buf_rd6p : std_logic := '0';
342  signal buf_rd4p : std_logic := '0';
343  signal sig_validk : std_logic := '0';
344 begin
345 
346  map_co: entity work.b2tt_encounter
347  port map (
348  clock => clock,
349  frame => frame,
350  staframe => sta_frame, -- out
351  cntbit2 => cnt_bit2, -- out
352  cntoctet => cnt_octet, -- out
353  cntpacket => cnt_packet ); -- out
354 
355  map_oc: entity work.b2tt_enoctet
356  port map (
357  clock => clock,
358  inbsy => sig_inbsy,
359  cntbit2 => cnt_bit2,
360  cntoctet => cnt_octet,
361  payload => payload,
362  octet => buf_octet, -- out
363  isk => buf_isk ); -- out
364 
365  map_b2: entity work.b2tt_enbit2
366  port map (
367  clock => clock,
368  errreset => errreset,
369  cntbit2 => cnt_bit2,
370  octet => buf_octet,
371  isk => buf_isk,
372  bsyin => bsyin,
373  --errin => errin,
374  inbsy => sig_inbsy, -- out
375  bsyup => bsyup, -- out
376  bsydn => bsydn, -- out
377  bit2 => sig_bit2, -- out/async
378  validk => sig_validk, -- out/async
379  rdnext => buf_rdnext, -- out
380  rd6p => buf_rd6p, -- out
381  rd4p => buf_rd4p ); -- out
382 
383  map_od: entity work.b2tt_oddr
384  generic map (
385  FLIPOUT => FLIPACK )
386  port map (
387  clock => clock,
388  invclock => invclock,
389  mask => '0', -- for ftsw only
390  bit2 => sig_bit2,
391  outp => ackp, -- out
392  outn => ackn ); -- out
393 
394  -- async-out
395  bit2 <= sig_bit2;
396 
397  -- out
398  octet <= buf_octet;
399  isk <= buf_isk;
400  cntbit2 <= cnt_bit2;
401  cntoctet <= cnt_octet;
402  fillsig <= '1' when cnt_bit2 = 4 and cnt_octet = 15 else '0';
403 
404 end implementation;