File: /__w/ctu-can-regression/ctu-can-regression/test/main_tb/agents/can_agent/can_agent.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: -- @Purpose:
70: -- CAN Bus agent. Configurable over Vunit Communication library.
71: --
72: -- More on Vunit and its communication library can be found at:
73: --- https://vunit.github.io/documentation.html
74: -- https://vunit.github.io/com/user_guide.html
75: --
76: -- CAN Bus agent is connected to can_tx and can_rx signals of DUT. It drives
77: -- can_rx via driver and it monitors_can_tx via monitor.
78: --
79: -- Driver contains FIFO of items to be driven. Each item contains value and
80: -- a time for which to drive the value. When driving of 1 item finishes it
81: -- is immediately followed by next one until driver FIFO is empty. Driver
82: -- can be started by a command over Communication library (this is intended
83: -- for sending frame by CAN agent), or simultaneously with Monitor (this is
84: -- intended for receiving frame by CAN Agent from DUT).
85: --
86: -- Monitor contains a FIFO of items to be monitored. Each item contains
87: -- value, time and sample period for which to monitor the value. When
88: -- Monitoring of 1 item finishes, it is immediately followed by next one
89: -- until monitor FIFO is empty. Monitor does not check for the value
90: -- constantly, but it samples can_tx output with configurable sampling
91: -- period. If monitored value is not equal to expected value when it is
92: -- sampled, internal mismatch counter is incremented and warning is printed.
93: --
94: -- Monitor can be in one of five states: "Idle", "Waiting for Trigger",
95: -- "Running", "Passed" and "Failed". When it is "Idle", no monitoring is
96: -- progress. When it is started via communication library, it moves to
97: -- "Waiting for Trigger". In this state it waits until trigger event occurs
98: -- (Type of trigger event is also configurable over Communication library)
99: -- and moves to "Running". When it is running, it monitors items from Monitor
100: -- FIFO one after another. After all items were monitored, monitor transfers to
101: -- "Passed" when no mismatch between can_tx and monitored values occured
102: -- during monitoring. Otherwise it transfers to failed.
103: --
104: -- Trigger functionality of monitor is a way how to synchronize its operation
105: -- with driver. Monitor can be configured to start at the same time as
106: -- driver starts.
107: --
108: -- When Monitor operation starts its internal error counter is erased. When
109: -- its ends, succesfull monitoring (no errors) can be checked via
110: -- Communication library.
111: --
112: -------------------------------------------------------------------------------
113: -- MONITORING of an ITEM (examples):
114: --
115: -- Lets suppose that monitor is about to monitor logic 1 for 100 ns with
116: -- sample period of 20 ns. Following figure shows where can_tx will be
117: -- checked:
118: --
119: -- _______________________________________________________
120: -- can_tx _____| |____
121: --
122: -- Check: O O O O
123: -- | | | | | |
124: -- 0ns 20ns 40ns 60 ns 80ns 100ns
125: --
126: -- Note that monitor will NOT execute check of can_tx less than sample_time
127: -- after start of monitoring item, and less than sample time before the end of
128: -- monitoring of an item! This behaviour is intentional!
129: --
130: -- The intention is, to set sample time to value of Time Quanta. This allows
131: -- checking with granularity of time quanta.
132: --
133: -- When DUT is configured e.g with BRP = 4, and Driver is not synchronized
134: -- with DUT, then shift between Driver and DUT can up to 1 TQ! Therefore, the
135: -- value of edge coming from DUT can be floating in range between 0 ns and
136: -- 1 TQ! (DUT does not operate on lower granularity than time quanta).
137: --
138: -------------------------------------------------------------------------------
139: -- API for work with CAN agent is implemented in "can_agent_pkg" package.
140: --
141: --------------------------------------------------------------------------------
142: -- Revision History:
143: -- 25.1.2020 Created file
144: -- 04.2.2021 Adjusted to work without Vunits COM library.
145: --------------------------------------------------------------------------------
146:
147: Library ctu_can_fd_tb;
148: context ctu_can_fd_tb.ieee_context;
149: context ctu_can_fd_tb.tb_common_context;
150:
151: use ctu_can_fd_tb.can_agent_pkg.all;
152: use ctu_can_fd_tb.tb_shared_vars_pkg.all;
153:
154: entity can_agent is
155: generic(
156: G_DRIVER_FIFO_DEPTH : natural := 128;
157: G_MONITOR_FIFO_DEPTH : natural := 128
158: );
159: port (
160: -- CAN bus connections
161: can_tx : in std_logic;
162: can_rx : out std_logic := '1'
163: );
164: end entity;
165:
166: architecture tb of can_agent is
167:
168: type t_driver_fifo_mem is array (0 to G_DRIVER_FIFO_DEPTH - 1) of
169: t_can_driver_entry;
170:
171: type t_monitor_fifo_mem is array (0 to G_MONITOR_FIFO_DEPTH - 1) of
172: t_can_monitor_entry;
173:
174: -- Driver signals
175: signal driver_mem : t_driver_fifo_mem;
176: signal driver_wp : natural := 0;
177: signal driver_rp : natural := 0;
178: signal driver_ena : boolean := false;
179: signal driving_in_progress : boolean := false;
180: signal driver_wait_for_monitor : boolean := false;
181:
182: -- Monitor signals
183: signal monitor_mem : t_monitor_fifo_mem;
184: signal monitor_wp : natural := 0;
185: signal monitor_rp : natural := 0;
186: signal monitor_ena : boolean := false;
187: signal monitor_in_progress : boolean := false;
188: signal monitor_state : t_can_monitor_state := mon_disabled;
189:
190: ---------------------------------------------------------------------------
191: -- Parameters configured over communication library
192: ---------------------------------------------------------------------------
193:
194: -- Driver
195: signal driver_wait_timeout : time := 10 ms;
196: signal driven_item : t_can_driver_entry := (
197: value => 'Z',
198: drive_time => 0 ns,
199: print_msg => false,
200: msg => C_EMPTY_STRING
201: );
202:
203: -- Monitor
204: signal monitor_wait_timeout : time := 10 ms;
205: signal monitored_item : t_can_monitor_entry := (
206: value => 'Z',
207: monitor_time => 0 ns,
208: sample_rate => 0 ns,
209: print_msg => false,
210: msg => C_EMPTY_STRING
211: );
212:
213: signal monitor_trigger : t_can_monitor_trigger := trig_immediately;
214: signal monitor_trig_wait_time : time := 100 ns;
215:
216: -- Debug signal only, shows where can_rx is sampled!
217: signal monitor_sample : std_logic := '0';
218:
219: -- Debug signal only, shows mismatch (by an X)
220: signal monitor_mismatch : std_logic := '0';
221:
222: -- Mismatch counter
223: signal mon_mismatch_ctr : integer := 0;
224:
225: -- Input delay
226: signal mon_input_delay : time := 0 ns;
227:
228: -- can_tx to can_rx feedback
229: signal tx_to_rx_feedback_enable : boolean := false;
230:
231: -- Internal value of can_rx
232: signal can_rx_i : std_logic := '1';
233:
234: begin
235:
236: ---------------------------------------------------------------------------
237: -- Comunication receiver process
238: ---------------------------------------------------------------------------
239: receiver_proc : process
240: variable cmd : integer;
241: variable reply_code : integer;
242: variable push_item : t_can_driver_entry;
243: variable push_mon_item : t_can_monitor_entry;
244: variable tmp : boolean := false;
245: variable tmp_int : integer := 0;
246:
247: procedure driver_fifo_push is
248: begin
249: driver_mem(driver_wp) <= push_item;
250: driver_wp <= (driver_wp + 1) mod G_DRIVER_FIFO_DEPTH;
251: wait for 0 ns;
252: end procedure;
253:
254: procedure monitor_fifo_push is
255: begin
256: monitor_mem(monitor_wp) <= push_mon_item;
257: monitor_wp <= (monitor_wp + 1) mod G_MONITOR_FIFO_DEPTH;
258: wait for 0 ns;
259: end procedure;
260:
261: begin
262: receive_start(default_channel, C_CAN_AGENT_ID);
263:
264: -- Command is sent as message type
265: cmd := com_channel_data.get_msg_code;
266: reply_code := C_REPLY_CODE_OK;
267:
268: case cmd is
269: when CAN_AGNT_CMD_DRIVER_START =>
270: driver_ena <= true;
271:
272: when CAN_AGNT_CMD_DRIVER_STOP =>
273: driver_ena <= false;
274:
275: when CAN_AGNT_CMD_DRIVER_FLUSH =>
276: -- Just move to position of acutally driven item (Read pointer).
277: -- This will efectively stash all written items and only current
278: -- driven item will be finished!
279: driver_wp <= driver_rp;
280:
281: when CAN_AGNT_CMD_DRIVER_GET_PROGRESS =>
282: com_channel_data.set_param(driving_in_progress);
283:
284: when CAN_AGNT_CMD_DRIVER_GET_DRIVEN_VAL =>
285: com_channel_data.set_param(can_rx);
286:
287: when CAN_AGNT_CMD_DRIVER_PUSH_ITEM =>
288: push_item.value := com_channel_data.get_param;
289: push_item.drive_time := com_channel_data.get_param;
290: push_item.print_msg := com_channel_data.get_param;
291: if (push_item.print_msg) then
292: push_item.msg := com_channel_data.get_param;
293: else
294: push_item.msg := (OTHERS => ' ');
295: end if;
296:
297: -- Check for overflow, keep one item empty so that we don't have to
298: -- handle pointers
299: if ((driver_wp + 1) mod G_DRIVER_FIFO_DEPTH = driver_rp) then
300: reply_code := C_REPLY_CODE_ERR;
301: error_m(CAN_AGENT_TAG & "Driver FIFO overflow! -> Skipping");
302: else
303: driver_fifo_push;
304: end if;
305:
306: when CAN_AGNT_CMD_DRIVER_SET_WAIT_TIMEOUT =>
307: driver_wait_timeout <= com_channel_data.get_param;
308:
309: when CAN_AGNT_CMD_DRIVER_WAIT_FINISH =>
310: wait for 0 ns;
311: if (driving_in_progress) then
312: wait until (driving_in_progress = false) for driver_wait_timeout;
313: end if;
314:
315: when CAN_AGNT_CMD_DRIVER_DRIVE_SINGLE_ITEM =>
316: if (not driver_ena) then
317: driver_ena <= true;
318: tmp := true;
319: end if;
320:
321: push_item.value := com_channel_data.get_param;
322: push_item.drive_time := com_channel_data.get_param;
323: push_item.print_msg := com_channel_data.get_param;
324: if (push_item.print_msg) then
325: push_item.msg := com_channel_data.get_param;
326: else
327: push_item.msg := (OTHERS => ' ');
328: end if;
329:
330: if (driver_wp /= driver_rp) then
331: warning_m(CAN_AGENT_TAG &
332: "Driver FIFO not empty, other items will be driven first...");
333: end if;
334:
335: if ((driver_wp + 1) mod G_DRIVER_FIFO_DEPTH = driver_rp) then
336: reply_code := C_REPLY_CODE_ERR;
337: error_m(CAN_AGENT_TAG & "Driver FIFO overflow -> Skipping");
338: else
339: driver_fifo_push;
340: wait until (driver_wp = driver_rp) for driver_wait_timeout;
341:
342: if (driver_wp /= driver_rp) then
343: warning_m(CAN_AGENT_TAG & " Drive_single_item timeout!");
344: end if;
345: end if;
346:
347: -- If driver was previously disabled, put it back into the same state!
348: if (tmp) then
349: driver_ena <= false;
350: end if;
351:
352: when CAN_AGNT_CMD_DRIVER_DRIVE_ALL_ITEMS =>
353: if (not driver_ena) then
354: driver_ena <= true;
355: tmp := true;
356: end if;
357:
358: if (driver_wp = driver_rp) then
359: warning_m(CAN_AGENT_TAG & "Driver FIFO empty, no items will be driven");
360: else
361: wait until (driver_wp = driver_rp) for driver_wait_timeout;
362: end if;
363:
364: if (driver_wp /= driver_rp) then
365: warning_m(CAN_AGENT_TAG & " Drive_all_items timeout!");
366: end if;
367:
368: -- If driver was previously disabled, put it back into the same state!
369: if (tmp) then
370: driver_ena <= false;
371: end if;
372:
373: when CAN_AGNT_CMD_SET_WAIT_FOR_MONITOR =>
374: driver_wait_for_monitor <= com_channel_data.get_param;
375:
376: when CAN_AGNT_CMD_MONITOR_START =>
377: monitor_ena <= true;
378:
379: when CAN_AGNT_CMD_MONITOR_STOP =>
380: monitor_ena <= false;
381:
382: when CAN_AGNT_CMD_MONITOR_FLUSH =>
383: -- Just move to position of acutally driven item (Read pointer).
384: -- This will efectively stash all written items and only current
385: -- driven item will be finished!
386: monitor_wp <= monitor_rp;
387:
388: when CAN_AGNT_CMD_MONITOR_GET_STATE =>
389: com_channel_data.set_param(t_can_monitor_state'pos(monitor_state));
390:
391: when CAN_AGNT_CMD_MONITOR_GET_MONITORED_VAL =>
392: com_channel_data.set_param(monitored_item.value);
393:
394: when CAN_AGNT_CMD_MONITOR_PUSH_ITEM =>
395: push_mon_item.value := com_channel_data.get_param;
396: push_mon_item.monitor_time := com_channel_data.get_param;
397: push_mon_item.print_msg := com_channel_data.get_param;
398: if (push_mon_item.print_msg) then
399: push_mon_item.msg := com_channel_data.get_param;
400: else
401: push_mon_item.msg := (OTHERS => ' ');
402: end if;
403: push_mon_item.sample_rate := com_channel_data.get_param2;
404:
405: monitor_fifo_push;
406:
407: when CAN_AGNT_CMD_MONITOR_SET_WAIT_TIMEOUT =>
408: monitor_wait_timeout <= com_channel_data.get_param;
409:
410: when CAN_AGNT_CMD_MONITOR_WAIT_FINISH =>
411: wait for 0 ns;
412: wait until (monitor_in_progress = false) for monitor_wait_timeout;
413:
414: when CAN_AGNT_CMD_MONITOR_MONITOR_SINGLE_ITEM =>
415: if (not monitor_ena) then
416: monitor_ena <= true;
417: tmp := true;
418: end if;
419:
420: push_mon_item.value := com_channel_data.get_param;
421: push_mon_item.monitor_time := com_channel_data.get_param;
422: push_mon_item.print_msg := com_channel_data.get_param;
423: if (push_mon_item.print_msg) then
424: push_mon_item.msg := com_channel_data.get_param;
425: else
426: push_mon_item.msg := (OTHERS => ' ');
427: end if;
428: push_mon_item.sample_rate := com_channel_data.get_param2;
429:
430: if (monitor_wp /= monitor_rp) then
431: warning_m(CAN_AGENT_TAG &
432: "Monitor FIFO not empty, other items will be monitored first...");
433: end if;
434:
435: if ((monitor_wp + 1) mod G_MONITOR_FIFO_DEPTH = monitor_rp) then
436: reply_code := C_REPLY_CODE_ERR;
437: error_m(CAN_AGENT_TAG & "Monitor FIFO overflow -> Skipping");
438: else
439: monitor_fifo_push;
440: wait until (monitor_wp = monitor_rp) for monitor_wait_timeout;
441:
442: if (monitor_wp /= monitor_rp) then
443: warning_m(CAN_AGENT_TAG & " Monitor_single_item timeout!");
444: end if;
445: end if;
446:
447: -- If monitor was previously disabled, put it back into the same state!
448: if (tmp) then
449: monitor_ena <= false;
450: end if;
451:
452: when CAN_AGNT_CMD_MONITOR_MONITOR_ALL_ITEMS =>
453: if (not monitor_ena) then
454: monitor_ena <= true;
455: tmp := true;
456: end if;
457:
458: if (monitor_wp = monitor_rp) then
459: warning_m(CAN_AGENT_TAG & "Monitor FIFO empty, no items will be driven");
460: else
461: wait until (monitor_wp = monitor_rp) for monitor_wait_timeout;
462: end if;
463:
464: if (monitor_wp /= monitor_rp) then
465: warning_m(CAN_AGENT_TAG & " Monitor_all_items timeout!");
466: end if;
467:
468: -- If monitor was previously disabled, put it back into the same state!
469: if (tmp) then
470: monitor_ena <= false;
471: end if;
472:
473: when CAN_AGNT_CMD_MONITOR_SET_TRIGGER =>
474: tmp_int := com_channel_data.get_param;
475: monitor_trigger <= t_can_monitor_trigger'val(tmp_int);
476:
477: when CAN_AGNT_CMD_MONITOR_GET_TRIGGER =>
478: com_channel_data.set_param(t_can_monitor_trigger'pos(monitor_trigger));
479:
480: when CAN_AGNT_CMD_MONITOR_CHECK_RESULT =>
481: check_m(mon_mismatch_ctr = 0, CAN_AGENT_TAG & "Mismatches in monitor!");
482:
483: when CAN_AGNT_CMD_MONITOR_SET_INPUT_DELAY =>
484: mon_input_delay <= com_channel_data.get_param;
485:
486: when CAN_AGNT_CMD_TX_RX_FEEDBACK_ENABLE =>
487: tx_to_rx_feedback_enable <= true;
488: wait for 0 ns;
489:
490: when CAN_AGNT_CMD_TX_RX_FEEDBACK_DISABLE =>
491: tx_to_rx_feedback_enable <= false;
492: wait for 0 ns;
493:
494: when others =>
495: warning_m(CAN_AGENT_TAG & "Invalid message type: " & integer'image(cmd));
496: reply_code := C_REPLY_CODE_ERR;
497: end case;
498:
499: receive_finish(default_channel, reply_code);
500: end process;
501:
502: ---------------------------------------------------------------------------
503: ---------------------------------------------------------------------------
504: -- Driver process (reading from Driver FIFO)
505: ---------------------------------------------------------------------------
506: ---------------------------------------------------------------------------
507: driver_proc : process
508: begin
509: if (driver_ena) then
510: if (driver_wait_for_monitor = true) then
511: wait until (monitor_state = mon_running);
512: end if;
513: while (true) loop
514: if (not driver_ena) then
515: driving_in_progress <= false;
516: exit;
517: end if;
518:
519: -- There is something in FIFO -> drive it!
520: if (driver_rp /= driver_wp) then
521: driving_in_progress <= true;
522: driven_item <= driver_mem(driver_rp);
523: wait for 0 ns;
524:
525: --debug_m(CAN_AGENT_TAG &
526: -- "Driving: " & std_logic'image(driven_item.value) &
527: -- " for time: " & time'image(driven_item.drive_time));
528: --if (driven_item.print_msg) then
529: -- info_m("Driving item: " & driven_item.msg);
530: --end if;
531:
532: can_rx_i <= driven_item.value;
533: wait for driven_item.drive_time;
534: driver_rp <= (driver_rp + 1) mod G_DRIVER_FIFO_DEPTH;
535: wait for 0 ns;
536: else
537: driving_in_progress <= false;
538: wait until driver_rp /= driver_wp or driver_ena=false;
539: end if;
540: end loop;
541: else
542: driving_in_progress <= false;
543: wait until driver_ena;
544: end if;
545: end process;
546:
547: ---------------------------------------------------------------------------
548: ---------------------------------------------------------------------------
549: -- Monitor process (FSM)
550: ---------------------------------------------------------------------------
551: ---------------------------------------------------------------------------
552: monitor_proc : process
553: variable mon_count : integer := 0;
554: variable monitored_time : time := 0 fs;
555:
556: -----------------------------------------------------------------------
557: -- Comparison procedure for monitor. Simple "=" operator is not enough
558: -- since GHDL might improprely handle don't care values. Also, compare
559: -- is not symmetrical (can_tx is now allowed to have "don't care"
560: -----------------------------------------------------------------------
561: impure function monitor_compare return boolean is
562: begin
563: if (can_tx = 'X' or
564: can_tx = 'U' or
565: can_tx = '-' or
566: can_tx = 'W' or
567: can_tx = 'Z')
568: then
569: return false;
570: end if;
571:
572: if (monitored_item.value = '-' and (can_tx = '1' or can_rx = '0'))
573: then
574: return true;
575: end if;
576:
577: if (can_tx = '0' and monitored_item.value = '0') then
578: return true;
579: elsif (can_tx = '1' and monitored_item.value = '1') then
580: return true;
581: end if;
582:
583: return false;
584: end function;
585:
586: begin
587: case monitor_state is
588: when mon_disabled =>
589: if (monitor_ena) then
590: if (monitor_trigger = trig_immediately) then
591: monitor_state <= mon_running;
592: else
593: monitor_state <= mon_waiting_for_trigger;
594: end if;
595: wait for 0 ns;
596: else
597: wait until monitor_ena;
598: end if;
599:
600: when mon_waiting_for_trigger =>
601: if (monitor_ena = false)then
602: monitor_state <= mon_disabled;
603: wait for 0 ns;
604: else
605: case monitor_trigger is
606: when trig_immediately =>
607: when trig_can_rx_rising_edge =>
608: wait until rising_edge(can_rx) or (monitor_ena = false);
609: when trig_can_rx_falling_edge =>
610: wait until falling_edge(can_rx) or (monitor_ena = false);
611: when trig_can_tx_rising_edge =>
612: wait until rising_edge(can_tx) or (monitor_ena = false);
613: when trig_can_tx_falling_edge =>
614: wait until falling_edge(can_tx) or (monitor_ena = false);
615:
616: when trig_time_elapsed =>
617: wait until (monitor_ena = false) for monitor_trig_wait_time;
618:
619: -- Note: This triggers also when driver is started but its
620: -- FIFO is empty so it does not drive anything!
621: when trig_driver_start =>
622: wait until (driver_ena = true) or (monitor_ena = false);
623:
624: when trig_driver_stop =>
625: wait until (driver_ena = false) or (monitor_ena = false);
626: end case;
627:
628: if (monitor_ena = false) then
629: monitor_state <= mon_disabled;
630: else
631: -- Wait additional monitor delay
632: wait for mon_input_delay;
633:
634: monitor_state <= mon_running;
635: end if;
636: wait for 0 ns;
637: end if;
638:
639: when mon_running =>
640: mon_mismatch_ctr <= 0;
641: while (true) loop
642: if (monitor_ena = false) then
643: monitor_state <= mon_disabled;
644: monitor_in_progress <= false;
645: wait for 0 ns;
646: exit;
647: end if;
648:
649: if (monitor_wp = monitor_rp) then
650:
651: if (mon_mismatch_ctr = 0) then
652: monitor_state <= mon_passed;
653: else
654: monitor_state <= mon_failed;
655: end if;
656: monitor_in_progress <= false;
657: monitor_mismatch <= '0';
658: wait for 0 ns;
659: exit;
660: end if;
661:
662: monitor_in_progress <= true;
663:
664: -- Read value from FIFO and start monitoring it!
665: monitored_item <= monitor_mem(monitor_rp);
666: wait for 0 ns;
667:
668: --debug_m(CAN_AGENT_TAG &
669: -- "Monitoring: " & std_logic'image(monitored_item.value) &
670: -- " for time: " & time'image(monitored_item.monitor_time));
671:
672: --if (monitored_item.print_msg) then
673: -- info_m("Monitoring item: " & monitored_item.msg);
674: --end if;
675:
676: mon_count := monitored_item.monitor_time / monitored_item.sample_rate;
677: monitored_time := 0 ns;
678: debug_m("Number of samples: " & integer'image(mon_count));
679:
680: ------------------------------------------------------------------------
681: -- Monitor until we are not closer than sample rate from the end. This
682: -- will truncate the last sample so that we dont compare too close to
683: -- the end!
684: ------------------------------------------------------------------------
685: while (monitored_time < monitored_item.monitor_time - monitored_item.sample_rate) loop
686: wait for (monitored_item.sample_rate - 1 ps);
687: monitor_sample <= '1';
688: wait for 1 ps;
689: monitor_sample <= '0';
690: wait for 0 ns;
691:
692: if (monitor_compare = false) then
693: monitor_mismatch <= 'X';
694: mon_mismatch_ctr <= mon_mismatch_ctr + 1;
695:
696: warning_m(CAN_AGENT_TAG &
697: "Monitor mismatch! Expected: " &
698: std_logic'image(monitored_item.value) &
699: " Monitored: " & std_logic'image(can_tx));
700: else
701: monitor_mismatch <= '0';
702: end if;
703: monitored_time := monitored_time + monitored_item.sample_rate;
704: end loop;
705:
706: -- We must wait the rest so that monitor item lasts proper time!
707: wait for monitored_item.monitor_time - monitored_time;
708:
709: monitor_mismatch <= '0';
710:
711: monitor_rp <= (monitor_rp + 1) mod G_MONITOR_FIFO_DEPTH;
712: wait for 0 ns;
713: end loop;
714:
715: when mon_passed =>
716: info_m("*****************************************************");
717: info_m (" Monitor sequence PASSED");
718: info_m ("*****************************************************");
719: monitor_state <= mon_disabled;
720: wait for 0 ns;
721:
722: when mon_failed =>
723: info_m ("*****************************************************");
724: info_m (" Monitor sequence FAILED");
725: info_m ("*****************************************************");
726: monitor_state <= mon_disabled;
727: wait for 0 ns;
728:
729: end case;
730: end process;
731:
732: -----------------------------------------------------------------------------
733: -- CAN tx to CAN rx feedback. This corresponds to CAN bus realization!
734: -----------------------------------------------------------------------------
735: can_rx <= can_rx_i when (tx_to_rx_feedback_enable = false) else
736: can_rx_i and can_tx;
737:
738: end architecture;