File: /__w/ctu-can-regression/ctu-can-regression/src/prescaler/bit_segment_meter.vhd
0: --------------------------------------------------------------------------------
1: --
2: -- CTU CAN FD IP Core
3: -- Copyright (C) 2021-2023 Ondrej Ille
4: -- Copyright (C) 2023- Logic Design Services Ltd.s
5: --
6: -- Permission is hereby granted, free of charge, to any person obtaining a copy
7: -- of this VHDL component and associated documentation files (the "Component"),
8: -- to use, copy, modify, merge, publish, distribute the Component for
9: -- non-commercial purposes. Using the Component for commercial purposes is
10: -- forbidden unless previously agreed with Copyright holder.
11: --
12: -- The above copyright notice and this permission notice shall be included in
13: -- all copies or substantial portions of the Component.
14: --
15: -- THE COMPONENT IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16: -- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17: -- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18: -- AUTHORS OR COPYRIGHTHOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19: -- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20: -- FROM, OUT OF OR IN CONNECTION WITH THE COMPONENT OR THE USE OR OTHER DEALINGS
21: -- IN THE COMPONENT.
22: --
23: -- The CAN protocol is developed by Robert Bosch GmbH and protected by patents.
24: -- Anybody who wants to implement this IP core on silicon has to obtain a CAN
25: -- protocol license from Bosch.
26: --
27: -- -------------------------------------------------------------------------------
28: --
29: -- CTU CAN FD IP Core
30: -- Copyright (C) 2015-2020 MIT License
31: --
32: -- Authors:
33: -- Ondrej Ille <ondrej.ille@gmail.com>
34: -- Martin Jerabek <martin.jerabek01@gmail.com>
35: --
36: -- Project advisors:
37: -- Jiri Novak <jnovak@fel.cvut.cz>
38: -- Pavel Pisa <pisa@cmp.felk.cvut.cz>
39: --
40: -- Department of Measurement (http://meas.fel.cvut.cz/)
41: -- Faculty of Electrical Engineering (http://www.fel.cvut.cz)
42: -- Czech Technical University (http://www.cvut.cz/)
43: --
44: -- Permission is hereby granted, free of charge, to any person obtaining a copy
45: -- of this VHDL component and associated documentation files (the "Component"),
46: -- to deal in the Component without restriction, including without limitation
47: -- the rights to use, copy, modify, merge, publish, distribute, sublicense,
48: -- and/or sell copies of the Component, and to permit persons to whom the
49: -- Component is furnished to do so, subject to the following conditions:
50: --
51: -- The above copyright notice and this permission notice shall be included in
52: -- all copies or substantial portions of the Component.
53: --
54: -- THE COMPONENT IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
55: -- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
56: -- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
57: -- AUTHORS OR COPYRIGHTHOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
58: -- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
59: -- FROM, OUT OF OR IN CONNECTION WITH THE COMPONENT OR THE USE OR OTHER DEALINGS
60: -- IN THE COMPONENT.
61: --
62: -- The CAN protocol is developed by Robert Bosch GmbH and protected by patents.
63: -- Anybody who wants to implement this IP core on silicon has to obtain a CAN
64: -- protocol license from Bosch.
65: --
66: --------------------------------------------------------------------------------
67:
68: --------------------------------------------------------------------------------
69: -- Module:
70: -- Bit segment meter.
71: --
72: -- Purpose:
73: -- This module measures segment length (TSEG1 or TSEG2) with respect to
74: -- Re-synchronisation. Expected segment length is loaded upon the end of
75: -- previous segment. Upon Resynchronisation, new length of segment is loaded
76: -- (shortened or lengthened). End of segment is requested when Segment counter
77: -- reaches expected length of segment.
78: --
79: -- To cover immediate re-synchronisation in PH2, where Bit should end
80: -- immediately, there is special "immediate" resynchronisation implemented.
81: -- This re-synchronisation signals end of segment in the same clock cycle.
82: --
83: -- Re-synchronisation data-path is depicted in following diagrams:
84: --
85: -- TSEG1 +-+
86: -- +---->+ +
87: -- | +
88: -- | +---+ +-+ Expected
89: -- TSEG2 | + +----->+ + segment
90: -- +---->+ + | | + +-----+ length
91: -- +-+ +-+---+ | +--->D Q+-------->
92: -- | | | + | |
93: -- | +/- +->+ + | |
94: -- SJW +-+ | | +-+ | ENA |
95: -- +---->+ + +-+---+ +--+--+
96: -- | + ^ ^
97: -- Bit | +---+ +-+--+
98: -- Counter| + | OR |
99: -- +---->+ + ++--++
100: -- +-+ Segment End ^ |
101: -- +---------------+ |
102: -- Resynchronisation |
103: -- +------------------+
104: -- valid
105: --
106: -- In this first part, Expected length of segment is calculated. Note that
107: -- upon end of segment either TSEG1 or TSEG2 is loaded to measure duration
108: -- of next segment (TSEG1 or TSEG2) mux, its output is then selected to D
109: -- input of Expected segment length register.
110: -- Re-synchronisation can be broken down to following parts:
111: -- 1. Phase error > 0 (TSEG1) and Phase err > SJW.
112: -- 2. Phase error > 0 (TSEG1) and Phase err < SJW.
113: -- 3. Phase error < 0 (TSEG2) and Phase err > SJW.
114: -- 4. Phase error < 0 (TSEG2) and Phase err < SJW.
115: -- Following values are loaded to expected segment length in these cases:
116: -- 1. TSEG1 + SJW (TSEG1 prolonged by SJW)
117: -- 2. TSEG1 + Segment Counter (in this case value in Segment counter
118: -- is equal to phase error).
119: -- 3. TSEG2 - SJW (TSEG1 is shortened by SJW).
120: -- 4. This case is not handled here, since this requires immediate
121: -- end of segment in acutal Time quanta. If Time quanta is 1 this
122: -- needs to be in current cycle and we can't afford 1 clock cycle
123: -- delay of "expected segment length" register. This is handled
124: -- by immediate segment exit described further.
125: --
126: -- If Hard synchronisation occured, Length of TSEG1 - 1 is loaded to expected
127: -- segment length register.
128: --
129: -- Calculation oh phase error and Detection of immediate segment exit
130: -- is shown in following diagram:
131: --
132: -- Synchronisation jump width
133: -- +--------------------------------+ Phase error more
134: -- Bit | than SJW
135: -- Counter +-+ v |---------------------->
136: -- +---------->+ + Phase +--+--+ |
137: -- | | + error | | | +-----+
138: -- | +-----+ | +------>+ > +----->+ | Immediate
139: -- +-----+->+ | | + | | | | exit
140: -- TSEG2 | +->+ + +-----+ +--->+ AND +--------->
141: -- +------->+ - | +-+ Is TSEG2? | | |
142: -- 1 | | +------------+ +->+ |
143: -- +------->| | Resynchronisation | +-----+
144: -- +-----+ +-------------------+
145: -- valid
146: --
147: -- Phase error detection functions like so:
148: -- 1. In TSEG1, phase error is given just by value of Bit counter
149: -- 2. In TSEG2, phase error = TSEG2 - Bit Counter.
150: --
151: -- Phase error is compared with SJW to find out whether Phase error > SJW
152: -- or not. This signal is then used to drive muxes in diagram nr. 1.
153: -- Immediate segment end is detected when Phase error <= SJW and at the same
154: -- time we are in TSEG2 and re-synchronisation occurs.
155: --
156: -- End of segment request is depicted in following diagram:
157: --
158: -- Immediate exit +----+
159: -- +-------------->+ |
160: -- Bit | | Segment end request
161: -- Counter +---+ | OR +---------------------->
162: -- +------->+ | | |
163: -- | = +->+ |
164: -- +------->+ | +----+
165: -- Expected +---+
166: -- segment
167: -- length
168: --
169: -- End of segment request provides a request to finish current Bit time
170: -- segment either due to Immediate Re-synchronisation or Reaching expected
171: -- length of segment (nominal or post-resynchronisation).
172: --
173: -- All three above described diagrams create a single re-synchronisation
174: -- datapath.
175: --
176: -- All data-path inputs are unsigned (direct code)!!
177: --
178: --------------------------------------------------------------------------------
179:
180: Library ieee;
181: use ieee.std_logic_1164.all;
182: use ieee.numeric_std.ALL;
183:
184: Library ctu_can_fd_rtl;
185: use ctu_can_fd_rtl.can_constants_pkg.all;
186: use ctu_can_fd_rtl.can_types_pkg.all;
187:
188: use ctu_can_fd_rtl.CAN_FD_register_map.all;
189: use ctu_can_fd_rtl.CAN_FD_frame_format.all;
190:
191: entity bit_segment_meter is
192: generic (
193: -- SJW width
194: G_SJW_WIDTH : natural;
195:
196: -- TSEG1 width
197: G_TSEG1_WIDTH : natural;
198:
199: -- TSEG2 width
200: G_TSEG2_WIDTH : natural;
201:
202: -- Bit counter width
203: G_BT_WIDTH : natural
204: );
205: port (
206: -------------------------------------------------------------------------------------------
207: -- Clock and Asynchronous reset
208: -------------------------------------------------------------------------------------------
209: clk_sys : in std_logic;
210: res_n : in std_logic;
211:
212: -------------------------------------------------------------------------------------------
213: -- Control interface
214: -------------------------------------------------------------------------------------------
215: -- There is a valid re-synchronisation edge.
216: resync_edge_valid : in std_logic;
217:
218: -------------------------------------------------------------------------------------------
219: -- Bit Time FSM interface
220: -------------------------------------------------------------------------------------------
221: -- Bit time is in SYNC, PROP or PH1
222: is_tseg1 : in std_logic;
223:
224: -- Bit time is in PH2
225: is_tseg2 : in std_logic;
226:
227: -------------------------------------------------------------------------------------------
228: -- Bit Time config capture interface
229: -------------------------------------------------------------------------------------------
230: -- Time segment 1 (SYNC + PROP + PH1)
231: tseg_1 : in std_logic_vector(G_TSEG1_WIDTH - 1 downto 0);
232:
233: -- Time segment 2 (PH2)
234: tseg_2 : in std_logic_vector(G_TSEG2_WIDTH - 1 downto 0);
235:
236: -- Synchronisation Jump Width
237: sjw : in std_logic_vector(G_SJW_WIDTH - 1 downto 0);
238:
239: -- Circuit operation has started -> load expected segment length reg.
240: start_edge : in std_logic;
241:
242: -------------------------------------------------------------------------------------------
243: -- Bit Time counter interface
244: -------------------------------------------------------------------------------------------
245: -- Bit time counter
246: segm_counter : in std_logic_vector(G_BT_WIDTH - 1 downto 0);
247:
248: -------------------------------------------------------------------------------------------
249: -- End of segment detector
250: -------------------------------------------------------------------------------------------
251: -- End of segment (either TSEG1 or TSEG2)
252: segm_end : in std_logic;
253:
254: -- Hard synchronisation valid
255: h_sync_valid : in std_logic;
256:
257: -------------------------------------------------------------------------------------------
258: -- Output interface (signalling end of segment)
259: -------------------------------------------------------------------------------------------
260: -- End of segment request
261: exit_segm_req : out std_logic
262: );
263: end entity;
264:
265: architecture rtl of bit_segment_meter is
266:
267: function max (
268: a : natural;
269: b : natural)
270: return natural is
271: begin
272: if (a > b) then
273: return a;
274: else
275: return b;
276: end if;
277: end function max;
278:
279: -----------------------------------------------------------------------------------------------
280: -- Internal constants, calculation of data-path widths.
281: -----------------------------------------------------------------------------------------------
282: constant C_BS_WIDTH : natural := max(G_TSEG1_WIDTH, G_TSEG2_WIDTH);
283: constant C_EXT_WIDTH : natural := max(G_BT_WIDTH, G_SJW_WIDTH);
284: constant C_EXP_WIDTH : natural := max(C_BS_WIDTH, C_EXT_WIDTH) + 1;
285:
286: constant C_E_WIDTH : natural := max(G_BT_WIDTH, G_TSEG2_WIDTH);
287: constant C_E_SJW_WIDTH : natural := max(C_E_WIDTH, G_SJW_WIDTH);
288:
289: -- Selector between TSEG1 and TSEG2
290: signal sel_tseg1 : std_logic;
291:
292: -- Length of TSEG1 or TSEG2 (without resynchronisation)
293: signal basic_segm_length : unsigned(C_BS_WIDTH - 1 downto 0);
294:
295: -- Length which should be added to the basic segment length (positive only)
296: signal segm_extension : unsigned(C_EXT_WIDTH - 1 downto 0);
297:
298: -- Base length of segment +/- segment extension
299: signal segm_ext_add : unsigned(C_EXP_WIDTH - 1 downto 0);
300: signal segm_ext_sub : unsigned(C_EXP_WIDTH - 1 downto 0);
301:
302: -- Expected segment length register
303: signal exp_seg_length_d : unsigned(C_EXP_WIDTH - 1 downto 0);
304: signal exp_seg_length_q : unsigned(C_EXP_WIDTH - 1 downto 0);
305: signal exp_seg_length_ce : std_logic;
306:
307: -- Expected length of segment after re-synchronisation
308: signal sync_segm_length : unsigned(C_EXP_WIDTH - 1 downto 0);
309:
310: -- Negative phase error (in PH2)
311: signal neg_phase_err : unsigned(C_E_WIDTH - 1 downto 0);
312:
313: -- Phase error
314: signal phase_err : unsigned(C_E_WIDTH - 1 downto 0);
315:
316: -- Phase error higher than SJW
317: signal phase_err_mt_sjw : std_logic;
318: signal phase_err_eq_sjw : std_logic;
319:
320: -- Exit PH2 immediately
321: signal exit_ph2_immediate : std_logic;
322:
323: -- Regular exit of Bit segment
324: signal exit_segm_regular : std_logic;
325:
326: -- Regular exit for TSEG1, TSEG2
327: signal exit_segm_regular_tseg1 : std_logic;
328: signal exit_segm_regular_tseg2 : std_logic;
329:
330: -- SJW more than 0
331: signal sjw_mt_zero : std_logic;
332:
333: -- Choose basic segment length
334: signal use_basic_segm_length : std_logic;
335:
336: -- Phase error = SJW + 1 -> Used for immediate segment end in case of negative resync,
337: -- since at point where edge is evaluated, bit time should be ended!
338: signal phase_err_sjw_by_one : std_logic;
339:
340: -- Shorten following Tseg1 by 1 due to negative resync with Phase err <= SJW
341: signal shorten_tseg1_after_tseg2 : std_logic;
342:
343: begin
344:
345: -----------------------------------------------------------------------------------------------
346: -----------------------------------------------------------------------------------------------
347: -- Re-synchronisation data-path
348: -----------------------------------------------------------------------------------------------
349: -----------------------------------------------------------------------------------------------
350: sel_tseg1 <= '1' when (h_sync_valid = '1' or start_edge = '1' or shorten_tseg1_after_tseg2 = '1') or
351: (segm_end = '1' and is_tseg2 = '1') or
352: (segm_end = '0' and is_tseg1 = '1') else
353: '0';
354:
355: basic_segm_length <=
356: resize(unsigned(tseg_1), C_BS_WIDTH) when (sel_tseg1 = '1') else
357: resize(unsigned(tseg_2), C_BS_WIDTH);
358:
359: segm_extension <=
360: to_unsigned(1, C_EXT_WIDTH) when (h_sync_valid = '1' or
361: shorten_tseg1_after_tseg2 = '1') else
362: resize(unsigned(sjw), C_EXT_WIDTH) when (phase_err_mt_sjw = '1') else
363: resize(unsigned(segm_counter), C_EXT_WIDTH);
364:
365: segm_ext_add <= resize(basic_segm_length, C_EXP_WIDTH) +
366: resize(segm_extension, C_EXP_WIDTH);
367:
368: segm_ext_sub <= resize(basic_segm_length, C_EXP_WIDTH) -
369: resize(segm_extension, C_EXP_WIDTH);
370:
371: sync_segm_length <= segm_ext_sub when (is_tseg2 = '1' or h_sync_valid = '1' or
372: exit_ph2_immediate = '1')
373: else
374: segm_ext_add;
375:
376: -----------------------------------------------------------------------------------------------
377: -- Use basic segment length:
378: -- 1. Circuit start
379: -- 2. Segment end, but not due to hard-sync. When segment end due to hard sync occurs, we must
380: -- take TSEG1 - 1 which is calculated in synced segment length! This also applies when there
381: -- is negative resync. due to Phase error <= SJW.
382: -----------------------------------------------------------------------------------------------
383: use_basic_segm_length <= '1' when (start_edge = '1') or
384: (segm_end = '1' and h_sync_valid = '0' and
385: shorten_tseg1_after_tseg2 = '0')
386: else
387: '0';
388:
389: -----------------------------------------------------------------------------------------------
390: -- Expected length of segment register. Load:
391: -- 1. Nominal length of next segment
392: -- 2. Value post-synchronisation.
393: -----------------------------------------------------------------------------------------------
394: exp_seg_length_d <=
395: resize(basic_segm_length, C_EXP_WIDTH) when (use_basic_segm_length = '1')
396: else
397: resize(sync_segm_length, C_EXP_WIDTH);
398:
399: exp_seg_length_ce <= '1' when (segm_end = '1' or resync_edge_valid = '1' or
400: h_sync_valid = '1' or start_edge = '1')
401: else
402: '0';
403:
404: exp_seg_length_proc : process(res_n, clk_sys)
405: begin
406: if (res_n = '0') then
407: exp_seg_length_q <= (others => '1');
408: elsif (rising_edge(clk_sys)) then
409: if (exp_seg_length_ce = '1') then
410: exp_seg_length_q <= exp_seg_length_d;
411: end if;
412: end if;
413: end process;
414:
415: -----------------------------------------------------------------------------------------------
416: -- Phase error calculation:
417: -- 1. For TSEG2: TSEG2 - Bit Time counter - 1
418: -- 2. For TSEG1: Only Bit Time counter
419: --
420: -- Note that subtraction in unsigned type is safe here since segm_counter is never higher than
421: -- tseg_2 in tseg_2. If we are in tseg_1 neg_phase err underflows, but we don't care since we
422: -- don't use it then!
423: -----------------------------------------------------------------------------------------------
424: neg_phase_err <= resize(unsigned(tseg_2), C_E_WIDTH) -
425: resize(unsigned(segm_counter), C_E_WIDTH);
426:
427: phase_err <= resize(neg_phase_err, C_E_WIDTH) when (is_tseg2 = '1') else
428: resize(unsigned(segm_counter), C_E_WIDTH);
429:
430: phase_err_mt_sjw <= '1' when (resize(phase_err, C_E_SJW_WIDTH) >
431: resize(unsigned(sjw), C_E_SJW_WIDTH))
432: else
433: '0';
434:
435: phase_err_eq_sjw <= '1' when (resize(phase_err, C_E_SJW_WIDTH) =
436: resize(unsigned(sjw), C_E_SJW_WIDTH))
437: else
438: '0';
439:
440: phase_err_sjw_by_one <= '1' when (resize(phase_err, C_E_SJW_WIDTH) =
441: (resize(unsigned(sjw), C_E_SJW_WIDTH) +
442: to_unsigned(1, C_E_SJW_WIDTH)))
443: else
444: '0';
445:
446: sjw_mt_zero <= '1' when (unsigned(sjw) > 0) else
447: '0';
448:
449: -----------------------------------------------------------------------------------------------
450: -- Immediate exit occurs during PH2 when resync edge occurs.
451: -- This occurs in two cases:
452: -- 1. Phase error <= SJW. Also, consecutive TSEG1 is shortened.
453: -- 2. Phase error = SJW + 1. In this case immediate end also occurs, because at the end of TQ
454: -- we flip to Phase error of 5 and we must shorten TSEG2 by SJW. In this case consecutive
455: -- TSEG1 is NOT shortened!
456: -----------------------------------------------------------------------------------------------
457: exit_ph2_immediate <= '1' when ((phase_err_mt_sjw = '0' or phase_err_sjw_by_one = '1') and
458: is_tseg2 = '1' and resync_edge_valid = '1')
459: else
460: '0';
461:
462:
463: -----------------------------------------------------------------------------------------------
464: -- When negative resynchronisation occurs due to Phase error <= SJW, we exit immediately! But
465: -- we also exit immediately when Phase error
466: -----------------------------------------------------------------------------------------------
467: shorten_tseg1_after_tseg2 <= '1' when (exit_ph2_immediate = '1' and phase_err_sjw_by_one = '0')
468: else
469: '0';
470:
471: -----------------------------------------------------------------------------------------------
472: -- Regular end occurs when Bit time counter reaches expected length of segment.
473: -----------------------------------------------------------------------------------------------
474: exit_segm_regular <= '1' when (resize(unsigned(segm_counter), C_EXP_WIDTH) >=
475: resize(unsigned(exp_seg_length_q) - 1, C_EXP_WIDTH))
476: else
477: '0';
478:
479:
480: -----------------------------------------------------------------------------------------------
481: -- TSEG1 is finished when Bit time counter reached value, but not when resync-edge is there at
482: -- the same time! If we did not consider resync edge, we would ignore resync edge which arrives
483: -- just at the same clock cycle as bit time!
484: -----------------------------------------------------------------------------------------------
485: exit_segm_regular_tseg1 <= '0' when (is_tseg1 = '1' and resync_edge_valid = '1' and
486: sjw_mt_zero = '1')
487: else
488: '1' when (is_tseg1 = '1' and exit_segm_regular = '1')
489: else
490: '0';
491:
492: -----------------------------------------------------------------------------------------------
493: -- TSEG2 is finished when Bit time counter reached expected value!
494: -----------------------------------------------------------------------------------------------
495: exit_segm_regular_tseg2 <= '1' when (is_tseg2 = '1' and exit_segm_regular = '1')
496: else
497: '0';
498:
499: -----------------------------------------------------------------------------------------------
500: -- Capture request to end of segment. Re-synchronisation is not Time Quanta aligned, so we must
501: -- capture the flag.
502: -- 1. Immediate exit of PH2.
503: -- 2. PH2, regular segment exit.
504: -- 3. PROP or PH1 regular segment exit.
505: -----------------------------------------------------------------------------------------------
506: exit_segm_req <= '1' when (exit_ph2_immediate = '1') or
507: (exit_segm_regular_tseg1 = '1' or exit_segm_regular_tseg2 = '1')
508: else
509: '0';
510:
511: end architecture rtl;