File: /__w/ctu-can-regression/ctu-can-regression/src/tx_arbitrator/tx_arbitrator_fsm.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: -- TX arbitrator FSM.
71: --
72: -- Purpose:
73: -- Controls selection of CAN frame, comparison of its timestamp and Loading
74: -- CAN frame metadata to output. When selected TXT Buffer is changed, selection
75: -- process is restarted. When LOCK command from CAN Core is issued, locks TXT
76: -- Buffer for transmission.
77: -- Each FSM state lasts two clock cycles (wait state is inserted), to give
78: -- time to TXT Buffer RAM for data read.
79: --------------------------------------------------------------------------------
80:
81: Library ieee;
82: use ieee.std_logic_1164.all;
83: use ieee.numeric_std.ALL;
84: use ieee.math_real.ALL;
85:
86: Library ctu_can_fd_rtl;
87: use ctu_can_fd_rtl.can_constants_pkg.all;
88: use ctu_can_fd_rtl.can_types_pkg.all;
89:
90: use ctu_can_fd_rtl.CAN_FD_register_map.all;
91: use ctu_can_fd_rtl.CAN_FD_frame_format.all;
92:
93: entity tx_arbitrator_fsm is
94: port (
95: -------------------------------------------------------------------------------------------
96: -- Clock and Asynchronous reset
97: -------------------------------------------------------------------------------------------
98: clk_sys : in std_logic;
99: res_n : in std_logic;
100:
101: -------------------------------------------------------------------------------------------
102: -- Priority decoder interface
103: -------------------------------------------------------------------------------------------
104: -- TXT Buffer is valid and selected for transmission
105: select_buf_avail : in std_logic;
106:
107: -- Priority decoder output has changed. TXT Arbitrator FSM has to restart selection process.
108: select_index_changed : in std_logic;
109:
110: -------------------------------------------------------------------------------------------
111: -- Timestamp comparison interface
112: -------------------------------------------------------------------------------------------
113: timestamp_valid : in std_logic;
114:
115: -------------------------------------------------------------------------------------------
116: -- CAN Core Interface
117: -------------------------------------------------------------------------------------------
118: -- HW Commands from CAN Core for manipulation with TXT Buffers
119: txtb_hw_cmd_lock : in std_logic;
120: txtb_hw_cmd_unlock : in std_logic;
121:
122: -------------------------------------------------------------------------------------------
123: -- Parity mismatch on currently validated TXT Buffer
124: -------------------------------------------------------------------------------------------
125: txtb_parity_mismatch_vld : in std_logic;
126:
127: -------------------------------------------------------------------------------------------
128: -- TX Arbitrator FSM outputs
129: -------------------------------------------------------------------------------------------
130: -- Load Timestamp lower word to metadata pointer
131: load_ts_lw_addr : out std_logic;
132:
133: -- Load Timestamp upper word to metadata pointer
134: load_ts_uw_addr : out std_logic;
135:
136: -- Load Frame format word to metadata pointer
137: load_ffmt_w_addr : out std_logic;
138:
139: -- Load identifier word to metadata pointer
140: load_ident_w_addr : out std_logic;
141:
142: -- Load frame test word to metadata pointer
143: load_frame_test_w_addr : out std_logic;
144:
145: -- Clock enable for TXT Buffer RAM
146: txtb_meta_clk_en : out std_logic;
147:
148: -- Store timestamp lower word
149: store_ts_l_w : out std_logic;
150:
151: -- Commit double buffers to output registers
152: commit_dbl_bufs : out std_logic;
153:
154: -- Store frame test word to double buffer registers
155: buffer_frame_test_w : out std_logic;
156:
157: -- Store metadata (Frame format word) to double buffer registers.
158: buffer_md_w : out std_logic;
159:
160: -- Signals that TX Arbitrator is locked (CAN Core is transmitting from TXT
161: -- Buffer)
162: tx_arb_locked : out std_logic;
163:
164: -- Store last locked TXT Buffer index
165: store_last_txtb_index : out std_logic;
166:
167: -- Set valid selected buffer on TX Arbitrator output.
168: frame_valid_com_set : out std_logic;
169:
170: -- Clear valid selected buffer on TX Arbitrator output.
171: frame_valid_com_clear : out std_logic;
172:
173: -- TXT Buffer output data are valid
174: tx_arb_parity_check_valid : out std_logic
175: );
176: end entity;
177:
178: architecture rtl of tx_arbitrator_fsm is
179:
180: -- TX Arbitrator FSM state
181: signal curr_state : t_tx_arb_state;
182: signal next_state : t_tx_arb_state;
183: signal tx_arb_fsm_ce : std_logic;
184:
185: -- Wait state DFF
186: signal fsm_wait_state_d : std_logic;
187: signal fsm_wait_state_q : std_logic;
188:
189: -- Parity error in TXT Buffer being validated
190: signal parity_error_vld : std_logic;
191:
192: begin
193:
194: parity_error_vld <= '1' when (txtb_parity_mismatch_vld = '1' and fsm_wait_state_q = '0')
195: else
196: '0';
197:
198: -----------------------------------------------------------------------------------------------
199: -- Next state process
200: -----------------------------------------------------------------------------------------------
201: tx_arb_fsm_proc : process(curr_state, select_buf_avail, select_index_changed,
202: timestamp_valid, fsm_wait_state_q, parity_error_vld, txtb_hw_cmd_unlock, txtb_hw_cmd_lock)
203: begin
204: -- Keeping signals values to avoid latch inference
205: next_state <= curr_state;
206:
207: case curr_state is
208:
209: -------------------------------------------------------------------------------------------
210: -- No TXT Buffer is available, or was just unlocked after transmission
211: -------------------------------------------------------------------------------------------
212: when s_arb_idle =>
213: if (select_buf_avail = '1') then
214: next_state <= s_arb_sel_low_ts;
215: end if;
216:
217: -------------------------------------------------------------------------------------------
218: -- Read Low timestamp word of Selected TXT buffer.
219: -------------------------------------------------------------------------------------------
220: when s_arb_sel_low_ts =>
221: if (txtb_hw_cmd_lock = '1') then
222: next_state <= s_arb_locked;
223: elsif (select_buf_avail = '0' or parity_error_vld = '1') then
224: next_state <= s_arb_idle;
225: elsif (select_index_changed = '1') then
226: next_state <= s_arb_sel_low_ts;
227: elsif (fsm_wait_state_q = '0') then
228: next_state <= s_arb_sel_upp_ts;
229: end if;
230:
231: -------------------------------------------------------------------------------------------
232: -- Read Upper timestamp word of Selected TXT Buffer. Perform Timestamp comparison (Lower
233: -- word is in capture register). When Timestamp elapses -> proceed with validation!
234: -------------------------------------------------------------------------------------------
235: when s_arb_sel_upp_ts =>
236: if (txtb_hw_cmd_lock = '1') then
237: next_state <= s_arb_locked;
238: elsif (select_buf_avail = '0' or parity_error_vld = '1') then
239: next_state <= s_arb_idle;
240: elsif (select_index_changed = '1') then
241: next_state <= s_arb_sel_low_ts;
242: elsif (fsm_wait_state_q = '0') then
243: if (timestamp_valid = '1') then
244: next_state <= s_arb_sel_ftw;
245: end if;
246: end if;
247:
248: -------------------------------------------------------------------------------------------
249: -- Read FRAME_TEST_W from Selected TXT Buffer.
250: -------------------------------------------------------------------------------------------
251: when s_arb_sel_ftw =>
252: if (txtb_hw_cmd_lock = '1') then
253: next_state <= s_arb_locked;
254:
255: -- Note: Parity error is not detected in FRAME_FORMAT_W
256: elsif (select_buf_avail = '0') then
257: next_state <= s_arb_idle;
258: elsif (select_index_changed = '1') then
259: next_state <= s_arb_sel_low_ts;
260: elsif (fsm_wait_state_q = '0') then
261: next_state <= s_arb_sel_ffw;
262: end if;
263:
264: -------------------------------------------------------------------------------------------
265: -- Read Frame format word.
266: -------------------------------------------------------------------------------------------
267: when s_arb_sel_ffw =>
268: if (txtb_hw_cmd_lock = '1') then
269: next_state <= s_arb_locked;
270: elsif (select_buf_avail = '0' or parity_error_vld = '1') then
271: next_state <= s_arb_idle;
272: elsif (select_index_changed = '1') then
273: next_state <= s_arb_sel_low_ts;
274: elsif (fsm_wait_state_q = '0') then
275: next_state <= s_arb_sel_idw;
276: end if;
277:
278: -------------------------------------------------------------------------------------------
279: -- Read identifier word.
280: -------------------------------------------------------------------------------------------
281: when s_arb_sel_idw =>
282: if (txtb_hw_cmd_lock = '1') then
283: next_state <= s_arb_locked;
284: elsif (select_buf_avail = '0' or parity_error_vld = '1') then
285: next_state <= s_arb_idle;
286: elsif (select_index_changed = '1') then
287: next_state <= s_arb_sel_low_ts;
288: elsif (fsm_wait_state_q = '0') then
289: next_state <= s_arb_validated;
290: end if;
291:
292: -------------------------------------------------------------------------------------------
293: -- TXT Buffer is validated!
294: -------------------------------------------------------------------------------------------
295: when s_arb_validated =>
296: if (txtb_hw_cmd_lock = '1') then
297: next_state <= s_arb_locked;
298: elsif (select_buf_avail = '0') then
299: next_state <= s_arb_idle;
300: elsif (select_index_changed = '1') then
301: next_state <= s_arb_sel_low_ts;
302: end if;
303:
304: -------------------------------------------------------------------------------------------
305: -- Finishing the transmission = unlocking the buffer
306: -------------------------------------------------------------------------------------------
307: when s_arb_locked =>
308: if (txtb_hw_cmd_unlock = '1') then
309: next_state <= s_arb_idle;
310: end if;
311:
312: end case;
313: end process;
314:
315:
316: -----------------------------------------------------------------------------------------------
317: -- TX Arbitrator FSM outputs
318: -----------------------------------------------------------------------------------------------
319: tx_arb_fsm_out_proc : process(curr_state, fsm_wait_state_q, timestamp_valid, txtb_hw_cmd_lock,
320: select_index_changed, select_buf_avail, parity_error_vld, txtb_hw_cmd_unlock)
321: begin
322:
323: -- By default all outputs are inactive
324: load_ts_lw_addr <= '0';
325: load_ts_uw_addr <= '0';
326: load_ffmt_w_addr <= '0';
327: load_ident_w_addr <= '0';
328: load_frame_test_w_addr <= '0';
329:
330: -- By default, clocks for memories are gated
331: txtb_meta_clk_en <= '0';
332:
333: store_ts_l_w <= '0';
334: commit_dbl_bufs <= '0';
335: buffer_frame_test_w <= '0';
336:
337: buffer_md_w <= '0';
338: tx_arb_locked <= '0';
339: frame_valid_com_set <= '0';
340: frame_valid_com_clear <= '0';
341: store_last_txtb_index <= '0';
342:
343: fsm_wait_state_d <= '0';
344:
345: tx_arb_parity_check_valid <= '0';
346:
347: case curr_state is
348:
349: -------------------------------------------------------------------------------------------
350: -- No TXT Buffer is available, or was just unlocked after transmission
351: -------------------------------------------------------------------------------------------
352: when s_arb_idle =>
353: if (select_buf_avail = '1') then
354: fsm_wait_state_d <= '1';
355: load_ts_lw_addr <= '1';
356: end if;
357:
358: -------------------------------------------------------------------------------------------
359: -- Read Low timestamp word of Selected TXT buffer.
360: -------------------------------------------------------------------------------------------
361: when s_arb_sel_low_ts =>
362: txtb_meta_clk_en <= '1';
363:
364: if (txtb_hw_cmd_lock = '1') then
365: store_last_txtb_index <= '1';
366:
367: elsif (select_buf_avail = '0') then
368: frame_valid_com_clear <= '1';
369:
370: elsif (select_index_changed = '1') then
371: fsm_wait_state_d <= '1';
372: load_ts_lw_addr <= '1';
373:
374: elsif (fsm_wait_state_q = '0') then
375: fsm_wait_state_d <= '1';
376: load_ts_uw_addr <= '1';
377: store_ts_l_w <= '1';
378: tx_arb_parity_check_valid <= '1';
379: end if;
380:
381: -------------------------------------------------------------------------------------------
382: -- Read Upper timestamp word of Selected TXT Buffer. Perform Timestamp comparison (Lower
383: -- word is in capture register). When Timestamp elapses -> proceed with validation!
384: -------------------------------------------------------------------------------------------
385: when s_arb_sel_upp_ts =>
386: txtb_meta_clk_en <= '1';
387:
388: if (txtb_hw_cmd_lock = '1') then
389: store_last_txtb_index <= '1';
390:
391: elsif (select_buf_avail = '0') then
392: frame_valid_com_clear <= '1';
393:
394: elsif (select_index_changed = '1') then
395: fsm_wait_state_d <= '1';
396: load_ts_lw_addr <= '1';
397:
398: elsif (fsm_wait_state_q = '0') then
399: if (timestamp_valid = '1') then
400: fsm_wait_state_d <= '1';
401: load_frame_test_w_addr <= '1';
402: end if;
403: tx_arb_parity_check_valid <= '1';
404: end if;
405:
406: -------------------------------------------------------------------------------------------
407: -- Read Frame test word
408: -------------------------------------------------------------------------------------------
409: when s_arb_sel_ftw =>
410: txtb_meta_clk_en <= '1';
411:
412: if (txtb_hw_cmd_lock = '1') then
413: store_last_txtb_index <= '1';
414:
415: elsif (select_buf_avail = '0') then
416: frame_valid_com_clear <= '1';
417:
418: elsif (select_index_changed = '1') then
419: fsm_wait_state_d <= '1';
420: load_ts_lw_addr <= '1';
421:
422: elsif (fsm_wait_state_q = '0') then
423: fsm_wait_state_d <= '1';
424: buffer_frame_test_w <= '1';
425: load_ffmt_w_addr <= '1';
426: end if;
427:
428: -------------------------------------------------------------------------------------------
429: -- Read Frame format word.
430: -------------------------------------------------------------------------------------------
431: when s_arb_sel_ffw =>
432: txtb_meta_clk_en <= '1';
433:
434: if (txtb_hw_cmd_lock = '1') then
435: store_last_txtb_index <= '1';
436:
437: elsif (select_buf_avail = '0') then
438: frame_valid_com_clear <= '1';
439:
440: elsif (select_index_changed = '1') then
441: fsm_wait_state_d <= '1';
442: load_ts_lw_addr <= '1';
443:
444: elsif (fsm_wait_state_q = '0') then
445: fsm_wait_state_d <= '1';
446: load_ident_w_addr <= '1';
447: buffer_md_w <= '1';
448: tx_arb_parity_check_valid <= '1';
449: end if;
450:
451: -------------------------------------------------------------------------------------------
452: -- Read identifier word.
453: -------------------------------------------------------------------------------------------
454: when s_arb_sel_idw =>
455: txtb_meta_clk_en <= '1';
456:
457: if (txtb_hw_cmd_lock = '1') then
458: store_last_txtb_index <= '1';
459:
460: elsif (select_buf_avail = '0') then
461: frame_valid_com_clear <= '1';
462:
463: elsif (select_index_changed = '1') then
464: fsm_wait_state_d <= '1';
465: load_ts_lw_addr <= '1';
466:
467: elsif (fsm_wait_state_q = '0') then
468: if (parity_error_vld = '0') then
469: commit_dbl_bufs <= '1';
470: frame_valid_com_set <= '1';
471: end if;
472:
473: tx_arb_parity_check_valid <= '1';
474: end if;
475:
476: -------------------------------------------------------------------------------------------
477: -- TXT Buffer is validated!
478: -------------------------------------------------------------------------------------------
479: when s_arb_validated =>
480: if (txtb_hw_cmd_lock = '1') then
481: store_last_txtb_index <= '1';
482:
483: elsif (select_buf_avail = '0') then
484: frame_valid_com_clear <= '1';
485:
486: elsif (select_index_changed = '1') then
487: fsm_wait_state_d <= '1';
488: load_ts_lw_addr <= '1';
489: end if;
490:
491: -------------------------------------------------------------------------------------------
492: -- Finishing the transmission = unlocking the buffer
493: -------------------------------------------------------------------------------------------
494: when s_arb_locked =>
495: tx_arb_locked <= '1';
496:
497: if (txtb_hw_cmd_unlock = '1') then
498: frame_valid_com_clear <= '1';
499: end if;
500:
501: end case;
502: end process;
503:
504:
505: -----------------------------------------------------------------------------------------------
506: -- State register
507: -----------------------------------------------------------------------------------------------
508: tx_arb_fsm_state_reg : process(clk_sys, res_n)
509: begin
510: if (res_n = '0') then
511: curr_state <= s_arb_idle;
512: elsif (rising_edge(clk_sys)) then
513: if (tx_arb_fsm_ce = '1') then
514: curr_state <= next_state;
515: end if;
516: end if;
517: end process;
518:
519: -- State transition enable
520: tx_arb_fsm_ce <= '1' when (curr_state /= next_state) else
521: '0';
522:
523:
524: -----------------------------------------------------------------------------------------------
525: -- Wait state DFF. Wait state inserted when next state must last two clock cycles!
526: -----------------------------------------------------------------------------------------------
527: fsm_wait_state_proc : process(clk_sys, res_n)
528: begin
529: if (res_n = '0') then
530: fsm_wait_state_q <= '1';
531: elsif (rising_edge(clk_sys)) then
532: fsm_wait_state_q <= fsm_wait_state_d;
533: end if;
534: end process;
535:
536: -----------------------------------------------------------------------------------------------
537: -- Assertions
538: -----------------------------------------------------------------------------------------------
539:
540: -- psl default clock is rising_edge(clk_sys);
541:
542: -- psl tx_arb_no_lock_when_idle_asrt : assert never
543: -- (curr_state = s_arb_idle and txtb_hw_cmd_lock = '1');
544:
545: -- psl tx_arb_no_lock_when_locked_asrt : assert never
546: -- (curr_state = s_arb_locked and txtb_hw_cmd_lock = '1');
547:
548: end architecture;