File: /__w/ctu-can-regression/ctu-can-regression/src/rx_buffer/rx_buffer.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: -- RX Buffer
71: --
72: -- Purpose:
73: -- Stores RX CAN frame during its reception into RX Buffer RAM. Controlled by
74: -- Protocol control FSM. RX Frame is read word by word from Memory registers.
75: -- RX Buffer is continously stored as it is being received. At the end of frame
76: -- it is committed to memory, and becomes available to the user. If Overrun
77: -- or Release receive Buffer occured meanwhile, frame is reverted.
78: --------------------------------------------------------------------------------
79:
80: Library ieee;
81: use ieee.std_logic_1164.all;
82: use ieee.numeric_std.ALL;
83: use ieee.math_real.ALL;
84:
85: Library ctu_can_fd_rtl;
86: use ctu_can_fd_rtl.can_constants_pkg.all;
87: use ctu_can_fd_rtl.can_types_pkg.all;
88:
89: use ctu_can_fd_rtl.CAN_FD_register_map.all;
90: use ctu_can_fd_rtl.CAN_FD_frame_format.all;
91:
92: use ctu_can_fd_rtl.can_registers_pkg.all;
93:
94: entity rx_buffer is
95: generic (
96: -- RX Buffer size
97: G_RX_BUFF_SIZE : natural range 32 to 4096;
98:
99: -- Width of RX Buffer pointers
100: G_RX_BUFF_PTR_WIDTH : natural range 5 to 12;
101:
102: -- Width of RX Buffer frame counter
103: G_RX_BUF_FRAME_CNT_WIDTH : natural range 3 to 11;
104:
105: -- Add parity to RX Buffer RAM
106: G_SUP_PARITY : boolean;
107:
108: -- Reset RX Buffer RAM
109: G_RESET_RX_BUF_RAM : boolean;
110:
111: -- Technology type
112: G_TECHNOLOGY : natural
113: );
114: port (
115: -------------------------------------------------------------------------------------------
116: -- Clocks and Asynchronous reset
117: -------------------------------------------------------------------------------------------
118: clk_sys : in std_logic;
119: res_n : in std_logic;
120:
121: -------------------------------------------------------------------------------------------
122: -- DFT support
123: -------------------------------------------------------------------------------------------
124: scan_enable : in std_logic;
125:
126: -------------------------------------------------------------------------------------------
127: -- Metadata from CAN Core
128: -------------------------------------------------------------------------------------------
129: -- Frame Identifier
130: rec_ident : in std_logic_vector(28 downto 0);
131:
132: -- Data length code
133: rec_dlc : in std_logic_vector(3 downto 0);
134:
135: -- Recieved identifier type (0-BASE Format, 1-Extended Format);
136: rec_ident_type : in std_logic;
137:
138: -- Recieved frame type (0-Normal CAN, 1- CAN FD)
139: rec_frame_type : in std_logic;
140:
141: -- Received Loopback frame
142: rec_lbpf : in std_logic;
143:
144: -- Recieved frame is RTR Frame(0-No, 1-Yes)
145: rec_is_rtr : in std_logic;
146:
147: -- Whenever frame was recieved with BIT Rate shift
148: rec_brs : in std_logic;
149:
150: -- Recieved error state indicator
151: rec_esi : in std_logic;
152:
153: -- Received identifier is valid
154: rec_ivld : in std_logic;
155:
156: -------------------------------------------------------------------------------------------
157: -- Control signals from CAN Core which control storing of CAN Frame. (Filtered by Frame
158: -- Filters)
159: -------------------------------------------------------------------------------------------
160: -- After control field of CAN frame, metadata are valid and can be stored. This command
161: -- starts the RX FSM for storing.
162: store_metadata_f : in std_logic;
163:
164: -- Signal that one word of data can be stored (TX_DATA_X_W). This signal is active when 4
165: -- bytes were received or data reception has finished on 4 byte unaligned number of frames!
166: -- (Thus allowing to store also data which are not 4 byte aligned!
167: store_data_f : in std_logic;
168:
169: -- Data word which should be stored when "store_data" is active!
170: store_data_word : in std_logic_vector(31 downto 0);
171:
172: -- Received frame valid (commit RX Frame)
173: rec_valid_f : in std_logic;
174:
175: -- Abort storing of RX Frame to RX Buffer.
176: rec_abort_f : in std_logic;
177:
178: -- Signals start of frame. If timestamp on RX frame should be captured in the beginning of
179: -- the frame, this pulse captures the timestamp!
180: sof_pulse : in std_logic;
181:
182: -- Error code capture registers
183: err_capt_err_type : in std_logic_vector(2 downto 0);
184: err_capt_err_pos : in std_logic_vector(3 downto 0);
185: err_capt_err_erp : in std_logic;
186:
187: -------------------------------------------------------------------------------------------
188: -- Status signals of RX buffer
189: -------------------------------------------------------------------------------------------
190: -- Signal whenever buffer is full (no free memory words)
191: rx_full : out std_logic;
192:
193: -- Signal whenever buffer is empty (no frame (message) is stored)
194: rx_empty : out std_logic;
195:
196: -- Number of frames (messages) stored in recieve buffer
197: rx_frame_count : out std_logic_vector(G_RX_BUF_FRAME_CNT_WIDTH - 1 downto 0);
198:
199: -- Number of free 32 bit wide words
200: rx_mem_free : out std_logic_vector(G_RX_BUFF_PTR_WIDTH downto 0);
201:
202: -- Position of read pointer
203: rx_read_pointer : out std_logic_vector(G_RX_BUFF_PTR_WIDTH - 1 downto 0);
204:
205: -- Position of write pointer
206: rx_write_pointer : out std_logic_vector(G_RX_BUFF_PTR_WIDTH - 1 downto 0);
207:
208: -- Overrun occurred, data were discarded!
209: -- (This is a flag and persists until it is cleared by SW).
210: rx_data_overrun : out std_logic;
211:
212: -- Middle of frame indication
213: rx_mof : out std_logic;
214:
215: -- RX Buffer Parity error
216: -- (This is a flag and persists until it is cleared by SW).
217: rx_parity_error : out std_logic;
218:
219: -- Actually loaded data for reading
220: rxb_port_b_data_out : out std_logic_vector(31 downto 0);
221:
222: -------------------------------------------------------------------------------------------
223: -- External timestamp input
224: -------------------------------------------------------------------------------------------
225: timestamp : in std_logic_vector(63 downto 0);
226:
227: -------------------------------------------------------------------------------------------
228: -- TX Arbitrator interface
229: -------------------------------------------------------------------------------------------
230: -- TXT Buffer index that is:
231: -- - Currently validated (when no transmission is in progress)
232: -- - Used for transmission (when transmission is in progress)
233: curr_txtb_index : in std_logic_vector(2 downto 0);
234:
235: -------------------------------------------------------------------------------------------
236: -- Memory registers interface
237: -------------------------------------------------------------------------------------------
238: mr_mode_rxbam : in std_logic;
239: mr_command_cdo : in std_logic;
240: mr_command_crxpe : in std_logic;
241: mr_command_rrb : in std_logic;
242: mr_command_rxrpmv : in std_logic;
243: mr_rx_data_read : in std_logic;
244: mr_rx_settings_rtsop : in std_logic;
245: mr_settings_pchke : in std_logic;
246: mr_mode_erfm : in std_logic;
247:
248: -- Memory testability
249: mr_tst_control_tmaena : in std_logic;
250: mr_tst_control_twrstb : in std_logic;
251: mr_tst_dest_tst_addr : in std_logic_vector(15 downto 0);
252: mr_tst_dest_tst_mtgt : in std_logic_vector(3 downto 0);
253: mr_tst_wdata_tst_wdata : in std_logic_vector(31 downto 0);
254:
255: mr_tst_rdata_tst_rdata : out std_logic_vector(31 downto 0)
256: );
257: end entity;
258:
259: architecture rtl of rx_buffer is
260:
261: -----------------------------------------------------------------------------------------------
262: -- FIFO Memory - Pointers
263: -----------------------------------------------------------------------------------------------
264:
265: -- Read Pointer (access from SW)
266: signal read_pointer : std_logic_vector(G_RX_BUFF_PTR_WIDTH - 1 downto 0);
267:
268: -- Read pointer incremented by 1 (combinationally)
269: signal read_pointer_inc_1 : std_logic_vector(G_RX_BUFF_PTR_WIDTH - 1 downto 0);
270:
271: -- Write pointer (committed, available to SW, after frame was stored)
272: signal write_pointer : std_logic_vector(G_RX_BUFF_PTR_WIDTH - 1 downto 0);
273:
274: -- Write pointer RAW. Changing during frame, as frame is continously stored
275: -- to the buffer. When frame is sucesfully received, it is updated to
276: -- write pointer!
277: signal write_pointer_raw : std_logic_vector(G_RX_BUFF_PTR_WIDTH - 1 downto 0);
278:
279: -- Timestamp write pointer which is used for storing timestamp at the end of
280: -- data frame!
281: signal write_pointer_ts : std_logic_vector(G_RX_BUFF_PTR_WIDTH - 1 downto 0);
282:
283: -- Number of free memory words available to SW after frame was committed.
284: signal rx_mem_free_i : std_logic_vector(G_RX_BUFF_PTR_WIDTH downto 0);
285:
286: -- RX Buffer mem free
287: constant C_RX_BUF_MEM_FREE_ZEROES : std_logic_vector(G_RX_BUFF_PTR_WIDTH downto 0) :=
288: (others => '0');
289: constant C_RX_BUF_PTR_ZEROES : std_logic_vector(G_RX_BUFF_PTR_WIDTH - 1 downto 0) :=
290: (others => '0');
291:
292: -----------------------------------------------------------------------------------------------
293: -- FIFO Memory - Free words, Overrun status
294: -----------------------------------------------------------------------------------------------
295:
296: -- Data overrun flag. Recieved message was lost, because there was not enough space in FIFO
297: -- during storing! Available for SW!
298: signal data_overrun_flg : std_logic;
299:
300: -- Internal data overrun flag. This flag is not available to SW, but it is restarted
301: -- automatically at the beginning of each new frame reception! This allows to accept next frames
302: -- when overrun occurred on previous ones!
303: signal data_overrun_i : std_logic;
304:
305: -- Combinationally decoded overrun condition. Active when there is intention to store word to
306: -- the memory, but there is not enough free space!
307: signal overrun_condition : std_logic;
308:
309: -- RX Buffer is empty (no frame is stored in it)
310: signal rx_empty_i : std_logic;
311:
312: -- Indicator of at least one free word in RX FIFO!
313: signal is_free_word : std_logic;
314:
315: -- Number of frames currently stored in RX Buffer. Smallest frame length stored is 4
316: -- (FRAME_FORMAT + IDENTIFIER + 2 * TIMESTAMP). Since we need to store 0 and also
317: -- G_RX_BUFF_SIZE / 4 values we need one value more than can fit into G_RX_BUFF_SIZE / 4 width
318: -- counter. Use one bit wider counter.
319: signal frame_count : unsigned(G_RX_BUF_FRAME_CNT_WIDTH - 1 downto 0);
320:
321: -- Frame read counter. When whole frame is read, number of frames must be decremented.
322: signal read_counter_d : unsigned(4 downto 0);
323: signal read_counter_q : unsigned(4 downto 0);
324:
325:
326: -----------------------------------------------------------------------------------------------
327: -- FIFO Memory - Commands which manipulate pointers, or indicate intent to write or read from
328: -- the memory.
329: -----------------------------------------------------------------------------------------------
330:
331: -- When commit of RX Frame is signalled by CAN Core (rec_valid) "commit_rx_frame" is set to
332: -- indicate that frame was sucesfully stored. Note that "rec_valid" is not enough to indicate
333: -- that frame was stored sucesfully! If frame storing fails at some point due to lack of memory
334: -- in FIFO, Protocol control will still finish the frame and provide "rec_valid"! Thus RX FSM
335: -- sets "commit_rx_frame" only if "data_overrun" did not occur during the frame!
336: signal commit_rx_frame : std_logic;
337:
338: -- When overrun occurred at any point in the frame and some word was not stored, frame can not
339: -- be committed, and write_pointer must be moved back to last committed value!
340: signal commit_overrun_abort : std_logic;
341:
342: -- Indicates that read occurred, and that it is valid (there is something to read), thus read
343: -- pointer can be incremented.
344: signal read_increment : std_logic;
345:
346: -- Indicates that "write_raw_intent" is OK (no overrun) and data can be truly written to the
347: -- memory and raw pointer can be updated!
348: signal write_raw_OK : std_logic;
349:
350:
351: -----------------------------------------------------------------------------------------------
352: -- RX Buffer FSM outputs
353: -----------------------------------------------------------------------------------------------
354:
355: -- Indicates that FSM is in a state which would like to perform write of a word to RX Buffer
356: -- memory!
357: signal write_raw_intent : std_logic;
358:
359: -- Indicates that FSM is in one of states for writing timestamp
360: signal select_ts_wptr : std_logic;
361:
362: -- Intend to commit RX frame
363: signal commit_intent : std_logic;
364:
365: -- Data write selector
366: signal data_selector : std_logic_vector(4 downto 0);
367:
368: -- Signals that write pointer should be stored to timestamp write pointer
369: signal store_ts_wr_ptr : std_logic;
370:
371: -- Increment timestamp write pointer
372: signal inc_ts_wr_ptr : std_logic;
373:
374: -- Restart overrun flag upon start of new frame
375: signal reset_overrun_flag : std_logic;
376:
377: -- Trying to read from RX Buffer FIFO
378: signal read_attempt : std_logic;
379:
380: -- Error frame being logged
381: signal rec_erf : std_logic;
382:
383: -----------------------------------------------------------------------------------------------
384: -- RX FSM, Timestamp capturing, combinationally decoded words
385: -----------------------------------------------------------------------------------------------
386:
387: -- Combinationally decoded size of the frame (without Frame format word) from received DLC (the
388: -- size is in 32-bit words).
389: signal rwcnt_com : natural range 0 to 31;
390:
391: -- Combinational decoded frame format word from metadata.
392: signal frame_form_w : std_logic_vector(27 downto 0);
393:
394: -- Internal timestamp captured for storing. Captured either in the beginning or end of frame.
395: signal timestamp_capture : std_logic_vector(63 downto 0);
396:
397: -- Clock enable signal for timestamp capture register
398: signal timestamp_capture_ce : std_logic;
399:
400:
401: -----------------------------------------------------------------------------------------------
402: -- RAM wrapper signals
403: -----------------------------------------------------------------------------------------------
404: signal rxb_port_a_write : std_logic;
405: signal rxb_port_a_address : std_logic_vector(G_RX_BUFF_PTR_WIDTH - 1 downto 0);
406: signal rxb_port_a_data_in : std_logic_vector(31 downto 0);
407:
408: signal rxb_port_b_address : std_logic_vector(G_RX_BUFF_PTR_WIDTH - 1 downto 0);
409: signal rxb_port_b_data_out_i : std_logic_vector(31 downto 0);
410:
411: -----------------------------------------------------------------------------------------------
412: -- Common reset signal
413: -----------------------------------------------------------------------------------------------
414: signal rx_buf_res_n_d : std_logic;
415: signal rx_buf_res_n_q_scan : std_logic;
416:
417: -----------------------------------------------------------------------------------------------
418: -- Clock gating for memory
419: -----------------------------------------------------------------------------------------------
420: signal rx_buf_ram_clk_en : std_logic;
421: signal clk_ram : std_logic;
422:
423: -----------------------------------------------------------------------------------------------
424: -- Parity error detection
425: -----------------------------------------------------------------------------------------------
426: signal rx_parity_mismatch_comb : std_logic;
427:
428: begin
429:
430: -----------------------------------------------------------------------------------------------
431: -- Common reset signal. Whole buffer can be reset by two ways:
432: -- 1. Asynchronous reset - res_n
433: -- 2. Release Receive Buffer command.
434: -----------------------------------------------------------------------------------------------
435: rx_buf_res_n_d <= '0' when (mr_command_rrb = '1' or res_n = '0')
436: else
437: '1';
438:
439: -----------------------------------------------------------------------------------------------
440: -- Register reset to avoid glitches
441: -----------------------------------------------------------------------------------------------
442: rst_reg_inst : entity ctu_can_fd_rtl.rst_reg
443: generic map (
444: G_RESET_POLARITY => '0'
445: )
446: port map (
447: -- Clock and Reset
448: clk => clk_sys, -- IN
449: arst => res_n, -- IN
450:
451: -- Flip flop input / output
452: d => rx_buf_res_n_d, -- IN
453: q => rx_buf_res_n_q_scan, -- OUT
454:
455: -- Scan mode control
456: scan_enable => scan_enable -- IN
457: );
458:
459: -----------------------------------------------------------------------------------------------
460: -- RX Buffer FSM component
461: -----------------------------------------------------------------------------------------------
462: rx_buffer_fsm_inst : entity ctu_can_fd_rtl.rx_buffer_fsm
463: port map (
464: clk_sys => clk_sys, -- IN
465: res_n => res_n, -- IN
466:
467: mr_mode_erfm => mr_mode_erfm, -- IN
468:
469: store_metadata_f => store_metadata_f, -- IN
470: store_data_f => store_data_f, -- IN
471: rec_valid_f => rec_valid_f, -- IN
472: rec_abort_f => rec_abort_f, -- IN
473: rec_erf => rec_erf, -- OUT
474:
475: write_raw_intent => write_raw_intent, -- OUT
476: select_ts_wptr => select_ts_wptr, -- OUT
477: commit_intent => commit_intent, -- OUT
478: data_selector => data_selector, -- OUT
479: store_ts_wr_ptr => store_ts_wr_ptr, -- OUT
480: inc_ts_wr_ptr => inc_ts_wr_ptr, -- OUT
481: reset_overrun_flag => reset_overrun_flag -- OUT
482: );
483:
484:
485: -----------------------------------------------------------------------------------------------
486: -- RX Buffer Memory pointers
487: -----------------------------------------------------------------------------------------------
488: rx_buffer_pointers_inst : entity ctu_can_fd_rtl.rx_buffer_pointers
489: generic map (
490: G_RX_BUFF_SIZE => G_RX_BUFF_SIZE,
491: G_RX_BUFF_PTR_WIDTH => G_RX_BUFF_PTR_WIDTH
492: )
493: port map (
494: clk_sys => clk_sys, -- IN
495: rx_buf_res_n_q_scan => rx_buf_res_n_q_scan, -- IN
496:
497: rec_abort_f => rec_abort_f, -- IN
498: commit_rx_frame => commit_rx_frame, -- IN
499: write_raw_OK => write_raw_OK, -- IN
500: commit_overrun_abort => commit_overrun_abort, -- IN
501: store_ts_wr_ptr => store_ts_wr_ptr, -- IN
502: inc_ts_wr_ptr => inc_ts_wr_ptr, -- IN
503: read_increment => read_increment, -- IN
504:
505: read_pointer => read_pointer, -- OUT
506: read_pointer_inc_1 => read_pointer_inc_1, -- OUT
507: write_pointer => write_pointer, -- OUT
508: write_pointer_raw => write_pointer_raw, -- OUT
509: write_pointer_ts => write_pointer_ts, -- OUT
510: rx_mem_free_i => rx_mem_free_i -- OUT
511: );
512:
513: -----------------------------------------------------------------------------------------------
514: -- Memory data which are written depend on state of the FSM
515: -----------------------------------------------------------------------------------------------
516: with data_selector select rxb_port_a_data_in <=
517: "0000" & frame_form_w when "00001",
518: "000" & rec_ident when "00010",
519: store_data_word when "00100",
520: timestamp_capture(31 downto 0) when "01000",
521: timestamp_capture(63 downto 32) when "10000",
522: (others => '0') when others;
523:
524: -----------------------------------------------------------------------------------------------
525: -- Signalling that read which came is valid (there is sth to read)
526: -----------------------------------------------------------------------------------------------
527: read_attempt <= mr_rx_data_read when (mr_mode_rxbam = RXBAM_ENABLED)
528: else
529: mr_command_rxrpmv;
530:
531: read_increment <= '1' when (read_attempt = '1' and rx_empty_i = '0')
532: else
533: '0';
534:
535: -----------------------------------------------------------------------------------------------
536: -- Signalling that FSM may progress with the write (there is enough space in the buffer, nor
537: -- any previous data were lost due to overrun)
538: -----------------------------------------------------------------------------------------------
539: write_raw_OK <= '1' when (write_raw_intent = '1' and overrun_condition = '0' and
540: data_overrun_i = '0')
541: else
542: '0';
543:
544: -----------------------------------------------------------------------------------------------
545: -- Store of new word can be executed only if there is space in the buffer. We don't need exact
546: -- amount of words. We only need to know if there is space! When "read_pointer" and
547: -- "write_pointer_raw" are equal, then memory is either empty, or full! If there is no frame
548: -- stored and pointers are equal, then memory is empty! If there is at least one frame and
549: -- pointers are equal, then memory must be full!
550: -----------------------------------------------------------------------------------------------
551: is_free_word <= '0' when (read_pointer = write_pointer_raw and frame_count > 0)
552: else
553: '1';
554:
555: -----------------------------------------------------------------------------------------------
556: -- Overrun condition. Following conditions must be met:
557: -- 1. FSM wants to write to memory either to the position of "write_pointer_raw". Note that
558: -- "write_pointer_ts" writes to words which were already written, thus there is no need to
559: -- watch for overrun!
560: -- 2. There is no free word in the memory remaining!
561: -----------------------------------------------------------------------------------------------
562: overrun_condition <= '1' when (write_raw_intent = '1' and is_free_word = '0')
563: else
564: '0';
565:
566:
567: -----------------------------------------------------------------------------------------------
568: -- When buffer is empty the word on address of read pointer is not valid, provide zeroes
569: -- instead. This guarantees that zeroes are read even if memory content is not defined ater
570: -- power-up!
571: -----------------------------------------------------------------------------------------------
572: rxb_port_b_data_out <= rxb_port_b_data_out_i when (rx_empty_i = '0')
573: else
574: (others => '0');
575:
576:
577: -----------------------------------------------------------------------------------------------
578: -- Receive data size (in words) decoder
579: -----------------------------------------------------------------------------------------------
580: with rec_dlc select rwcnt_com <=
581: 3 when "0000", --Zero bits
582: 4 when "0001", --1 byte
583: 4 when "0010", --2 bytes
584: 4 when "0011", --3 bytes
585: 4 when "0100", --4 bytes
586: 5 when "0101", --5 bytes
587: 5 when "0110", --6 bytes
588: 5 when "0111", --7 bytes
589: 5 when "1000", --8 bytes
590: 6 when "1001", --12 bytes
591: 7 when "1010", --16 bytes
592: 8 when "1011", --20 bytes
593: 9 when "1100", --24 bytes
594: 11 when "1101", --32 bytes
595: 15 when "1110", --48 bytes
596: 19 when others; --64 bytes
597:
598:
599: -----------------------------------------------------------------------------------------------
600: -- Frame format word assignment
601: -----------------------------------------------------------------------------------------------
602: frame_form_w(DLC_H downto DLC_L) <= rec_dlc;
603: frame_form_w(ERF_IND) <= rec_erf;
604: frame_form_w(RTR_IND) <= rec_is_rtr;
605: frame_form_w(IDE_IND) <= rec_ident_type;
606: frame_form_w(FDF_IND) <= rec_frame_type;
607: frame_form_w(LBPF_IND) <= rec_lbpf;
608: frame_form_w(BRS_IND) <= rec_brs;
609: frame_form_w(ESI_RSV_IND) <= rec_esi;
610: frame_form_w(IVLD_IND) <= rec_ivld;
611:
612: -----------------------------------------------------------------------------------------------
613: -- RWCNT (Read word count is calculated like so:
614: -- 1. For RTR Frames or Error Frames -> 3 (Only ID + 2 Timestamp words)
615: -- 2. For Normal CAN Frames with DLC > 8 max. 8 bytes -> RWCNT = 5
616: -- 3. Otherwise Number of data bytes is matching Received DLC!
617: -----------------------------------------------------------------------------------------------
618: frame_form_w(RWCNT_H downto RWCNT_L) <=
619: "00011" when (rec_is_rtr = RTR_FRAME or rec_erf = ERFM_ENABLED) else
620: "00101" when ((rec_frame_type = NORMAL_CAN) and (rec_dlc(3) = '1')) else
621: std_logic_vector(to_unsigned(rwcnt_com, (RWCNT_H - RWCNT_L + 1)));
622:
623: -- Store Error code capture when this is Error frame
624: frame_form_w(ERF_POS_H downto ERF_POS_L) <= err_capt_err_pos when (rec_erf = '1')
625: else
626: (others => '0');
627:
628: frame_form_w(ERF_TYPE_H downto ERF_TYPE_L) <= err_capt_err_type when (rec_erf = '1')
629: else
630: (others => '0');
631:
632: frame_form_w(ERF_ERP_IND) <= err_capt_err_erp when (rec_erf = '1')
633: else
634: '0';
635:
636: -- Store TXT Buffer index when this is Loopback frame
637: frame_form_w(LBTBI_H downto LBTBI_L) <= curr_txtb_index when (rec_lbpf = LBPF_LOOPBACK)
638: else
639: (others => '0');
640:
641: -----------------------------------------------------------------------------------------------
642: -- Capturing timestamp:
643: -- 1. At the beginning of frame (based on SW configuration)
644: -- 2. At the end of frame (based on SW configuration)
645: -- 3. When error frame occurs, and it shall be logged in RX Buffer.
646: -----------------------------------------------------------------------------------------------
647: timestamp_capture_ce <= '1' when (mr_rx_settings_rtsop = RTS_END and rec_valid_f = '1')
648: else
649: '1' when (mr_rx_settings_rtsop = RTS_BEG and sof_pulse = '1')
650: else
651: '1' when (mr_mode_erfm = ERFM_ENABLED and rec_abort_f = '1')
652: else
653: '0';
654:
655: capt_ts_proc : process(clk_sys, res_n)
656: begin
657: if (res_n = '0') then
658: timestamp_capture <= (others => '0');
659: elsif (rising_edge(clk_sys)) then
660: if (timestamp_capture_ce = '1') then
661: timestamp_capture <= timestamp;
662: end if;
663: end if;
664: end process;
665:
666:
667: -----------------------------------------------------------------------------------------------
668: -- Reading counter (read_counter_q) which is loaded by RWCNT during read of frame format word.
669: -- Then each next read decreases the counter. When read counter reaches zero, message count is
670: -- decreased. If "commit_rx_frame" comes, "frame_count" is incremented. If both occur at the
671: -- same time , "frame_count" does not change.
672: -----------------------------------------------------------------------------------------------
673:
674: -----------------------------------------------------------------------------------------------
675: -- During the read of FRAME_FORMAT word store the length of the frame to "read_counter", thus
676: -- we know how much we have to read before decrementing the "frame_count".
677: -----------------------------------------------------------------------------------------------
678: read_counter_d <= read_counter_q - 1 when (read_counter_q > "00000")
679: else
680: unsigned(rxb_port_b_data_out_i(RWCNT_H downto RWCNT_L));
681:
682: read_frame_proc : process(clk_sys, rx_buf_res_n_q_scan)
683: begin
684: if (rx_buf_res_n_q_scan = '0') then
685: read_counter_q <= (others => '0');
686: elsif (rising_edge(clk_sys)) then
687: -- Reading frame by user when there is active read and there is
688: -- something to read
689: if (read_increment = '1') then
690: read_counter_q <= read_counter_d;
691: end if;
692: end if;
693: end process;
694:
695:
696: -----------------------------------------------------------------------------------------------
697: -- Manipulation of "frame_count". When last word is read from frame (read_counter_q = 1 and
698: -- read_increment), "frame_count" is decreased, when new frame is committed, message count is
699: -- increased. If both at the same time, no change since one frame is added, next is removed!
700: -----------------------------------------------------------------------------------------------
701: frame_count_ctr_proc : process(clk_sys, rx_buf_res_n_q_scan)
702: begin
703: if (rx_buf_res_n_q_scan = '0') then
704: frame_count <= (others => '0');
705: elsif (rising_edge(clk_sys)) then
706:
707: -- Read of last word, but no new commit
708: if ((read_increment = '1') and (read_counter_q = "00001")) then
709: if (commit_rx_frame = '0') then
710: frame_count <= frame_count - 1;
711: end if;
712:
713: -- Commit of new frame
714: elsif (commit_rx_frame = '1') then
715: frame_count <= frame_count + 1;
716: end if;
717:
718: end if;
719: end process;
720:
721:
722: -----------------------------------------------------------------------------------------------
723: -- Commit RX Frame when last word was written and overrun did not occur! This can be either
724: -- from "rxb_store_data" state or "rxb_store_end_ts_high"
725: -----------------------------------------------------------------------------------------------
726: commit_proc : process(clk_sys, rx_buf_res_n_q_scan)
727: begin
728: if (rx_buf_res_n_q_scan = '0') then
729: commit_rx_frame <= '0';
730: commit_overrun_abort <= '0';
731:
732: elsif (rising_edge(clk_sys)) then
733:
734: if (commit_intent = '1') then
735: if (data_overrun_i = '0') then
736: commit_rx_frame <= '1';
737: else
738: commit_overrun_abort <= '1';
739: end if;
740: else
741: commit_rx_frame <= '0';
742: commit_overrun_abort <= '0';
743: end if;
744:
745: end if;
746: end process;
747:
748:
749: -----------------------------------------------------------------------------------------------
750: -- Calculation of data overrun flag for user. If FSM would like to write to the memory, and
751: -- there is not enough free space, data overrun flag will be set, and no further writes will
752: -- be executed. Data Overrun flag can be cleared from Memory registers.
753: -----------------------------------------------------------------------------------------------
754: sw_dor_proc : process(clk_sys, rx_buf_res_n_q_scan)
755: begin
756: if (rx_buf_res_n_q_scan = '0') then
757: data_overrun_flg <= '0';
758: elsif (rising_edge(clk_sys)) then
759:
760: -- SW overrun flag -> Cleared from SW!
761: if (mr_command_cdo = '1') then
762: data_overrun_flg <= '0';
763: elsif (overrun_condition = '1') then
764: data_overrun_flg <= '1';
765: else
766: data_overrun_flg <= data_overrun_flg;
767: end if;
768:
769: end if;
770: end process;
771:
772: -----------------------------------------------------------------------------------------------
773: -- Internal data overrun flag. This will be set by two conditions:
774: -- 1. When FSM attempts to write to full RAM.
775: -- 2. When RRB command is issued and frame storing is in progress! If such situation occurs,
776: -- pointers are erased RX Buffer FSM is erased, while Protocol control continues storing
777: -- the frame (increments Raw write pointer). Commiting such a frame would result in
778: -- inconsistent state of RX Buffer. So if RRB during storing occurs, all pointers are
779: -- erased, RX Buffer FSM keeps storing, and overrun flag is set. At the end of storing,
780: -- flag is erased and raw write pointer is reverted to commited pointer (which is zero
781: -- because it was erased).
782: --
783: -- Cleared at the end of frame storing! Note that this register can't be reset by RRB, only
784: -- by res_n!
785: -----------------------------------------------------------------------------------------------
786: internal_dor_proc : process(clk_sys, res_n)
787: begin
788: if (res_n = '0') then
789: data_overrun_i <= '0';
790: elsif (rising_edge(clk_sys)) then
791: if (overrun_condition = '1' or mr_command_rrb = '1') then
792: data_overrun_i <= '1';
793: elsif (reset_overrun_flag = '1') then
794: data_overrun_i <= '0';
795: else
796: data_overrun_i <= data_overrun_i;
797: end if;
798: end if;
799: end process;
800:
801: -----------------------------------------------------------------------------------------------
802: -- Clock gating for RAM. Enable when:
803: -- 1. CAN Core is writing
804: -- 2. Reading occurs from register map.
805: -- 3. Permanently when Memory testing is enabled, or in scan mode
806: -----------------------------------------------------------------------------------------------
807: rx_buf_ram_clk_en <= '1' when (rxb_port_a_write = '1' or read_attempt = '1')
808: else
809: '1' when (mr_tst_control_tmaena = '1')
810: else
811: '0';
812:
813: clk_gate_rx_buffer_ram_comp : entity ctu_can_fd_rtl.clk_gate
814: generic map(
815: G_TECHNOLOGY => G_TECHNOLOGY
816: )
817: port map(
818: clk_in => clk_sys, -- IN
819: clk_en => rx_buf_ram_clk_en, -- IN
820: scan_enable => scan_enable, -- IN
821:
822: clk_out => clk_ram -- OUT
823: );
824:
825: -----------------------------------------------------------------------------------------------
826: -- RAM Memory of RX Buffer
827: -----------------------------------------------------------------------------------------------
828: rx_buffer_ram_inst : entity ctu_can_fd_rtl.rx_buffer_ram
829: generic map(
830: G_RX_BUFF_SIZE => G_RX_BUFF_SIZE,
831: G_RX_BUFF_PTR_WIDTH => G_RX_BUFF_PTR_WIDTH,
832: G_SUP_PARITY => G_SUP_PARITY,
833: G_RESET_RX_BUF_RAM => G_RESET_RX_BUF_RAM
834: )
835: port map(
836: -- Clocks and Asynchronous reset
837: clk_sys => clk_ram, -- IN
838: res_n => res_n, -- IN
839:
840: -- Memory testability
841: mr_tst_control_tmaena => mr_tst_control_tmaena, -- IN
842: mr_tst_control_twrstb => mr_tst_control_twrstb, -- IN
843: mr_tst_dest_tst_addr => mr_tst_dest_tst_addr, -- IN
844: mr_tst_dest_tst_mtgt => mr_tst_dest_tst_mtgt, -- IN
845: mr_tst_wdata_tst_wdata => mr_tst_wdata_tst_wdata, -- IN
846:
847: mr_tst_rdata_tst_rdata => mr_tst_rdata_tst_rdata, -- OUT
848:
849: -- Port A - Write (from CAN Core)
850: rxb_port_a_address => rxb_port_a_address, -- IN
851: rxb_port_a_data_in => rxb_port_a_data_in, -- IN
852: rxb_port_a_write => rxb_port_a_write, -- IN
853:
854: -- Port B - Read (from Memory registers)
855: rxb_port_b_address => rxb_port_b_address, -- IN
856: rxb_port_b_data_out => rxb_port_b_data_out_i, -- OUT
857:
858: -- Parity error detection
859: parity_mismatch => rx_parity_mismatch_comb -- OUT
860: );
861:
862: -- Memory written either on regular write or timestamp write
863: rxb_port_a_write <= '1' when (write_raw_OK = '1' or
864: (select_ts_wptr = '1' and data_overrun_i = '0'))
865: else
866: '0';
867:
868: -----------------------------------------------------------------------------------------------
869: -- Memory write address is multiplexed between "write_pointer_raw" for regular writes and
870: -- "write_pointer_ts" for writes of timestamp!
871: -----------------------------------------------------------------------------------------------
872: rxb_port_a_address <= write_pointer_ts when (select_ts_wptr = '1')
873: else
874: write_pointer_raw;
875:
876: -----------------------------------------------------------------------------------------------
877: -- RAM read address is given by read pointers. If no transaction for read of RX DATA is in
878: -- progress, read pointer is given by its real value. During transaction, Incremented Read
879: -- pointer is chosen to avoid one clock cycle delay caused by increment on read pointer.
880: -----------------------------------------------------------------------------------------------
881: rxb_port_b_address <= read_pointer_inc_1 when (read_increment = '1')
882: else
883: read_pointer;
884:
885:
886: -----------------------------------------------------------------------------------------------
887: -- RX buffer middle of frame
888: -----------------------------------------------------------------------------------------------
889: rx_mof <= '0' when (read_counter_q = "00000")
890: else
891: '1';
892:
893: -----------------------------------------------------------------------------------------------
894: -- Parity error flag
895: -- Set when reading RX Buffer RAM. When read is in porgress is set, then RX Buffer RAM already
896: -- has read data available on output, therefore, RX parity error detection is valid!
897: -----------------------------------------------------------------------------------------------
898: parity_flag_proc : process(res_n, clk_sys)
899: begin
900: if (res_n = '0') then
901: rx_parity_error <= '0';
902: elsif (rising_edge(clk_sys)) then
903: if (read_attempt = '1' and rx_parity_mismatch_comb = '1' and mr_settings_pchke = '1')
904: then
905: rx_parity_error <= '1';
906: elsif (mr_command_crxpe = '1') then
907: rx_parity_error <= '0';
908: end if;
909: end if;
910: end process;
911:
912:
913: -----------------------------------------------------------------------------------------------
914: -- Propagating status registers on output
915: -----------------------------------------------------------------------------------------------
916: rx_read_pointer <= read_pointer;
917: rx_write_pointer <= write_pointer;
918: rx_data_overrun <= data_overrun_flg;
919:
920: rx_empty_i <= '1' when (frame_count = 0)
921: else
922: '0';
923:
924: rx_full <= '1' when (rx_mem_free_i = C_RX_BUF_MEM_FREE_ZEROES)
925: else
926: '0';
927:
928: rx_frame_count <= std_logic_vector(frame_count);
929: rx_mem_free <= rx_mem_free_i;
930: rx_empty <= rx_empty_i;
931:
932:
933: -----------------------------------------------------------------------------------------------
934: -----------------------------------------------------------------------------------------------
935: -- Assertions
936: -----------------------------------------------------------------------------------------------
937: -----------------------------------------------------------------------------------------------
938:
939: -- pragma translate_off
940:
941: -----------------------------------------------------------------------------------------------
942: -- RX Buffer size can be only powers of 2. Since modulo arithmetics is used on memory pointers,
943: -- using non power of 2 value would result in increased logic usage!
944: -----------------------------------------------------------------------------------------------
945:
946: -- coverage off
947: assert ((G_RX_BUFF_SIZE = 32) or
948: (G_RX_BUFF_SIZE = 64) or
949: (G_RX_BUFF_SIZE = 128) or
950: (G_RX_BUFF_SIZE = 256) or
951: (G_RX_BUFF_SIZE = 512) or
952: (G_RX_BUFF_SIZE = 1024) or
953: (G_RX_BUFF_SIZE = 2048) or
954: (G_RX_BUFF_SIZE = 4096))
955: report "Unsupported RX Buffer size! RX Buffer must be power of 2!"
956: severity failure;
957: -- coverage on
958:
959:
960: -----------------------------------------------------------------------------------------------
961: -- Storing sequence is like so:
962: -- 1. Store metadata.
963: -- 2. Store data "n" times, n = ceil(data_length / 4). De-facto RWCNT field contains number of
964: -- remaining words (apart from FRAME_FORMAT_W). Thus, RWCNT - 3 = number of expected data
965: -- words.
966: -- 3. Get "rec_abort" or "rec_valid" command.
967: --
968: -- This process verifies that "rec_data" command comes expected number of times (RWCNT - 3).
969: -- This verifies consistency of storing protocol by CAN Core, as well as RWCNT field!
970: -----------------------------------------------------------------------------------------------
971: -- coverage off
972: rwcnt_assert_proc : process(clk_sys)
973: variable exp_data_stores : natural := 0;
974: variable act_data_stores : natural := 0;
975: begin
976: if (rising_edge(clk_sys) and now /= 0 fs) then
977:
978: -- Calculate number of expected "store_data" commands from CAN Core.
979: if (rec_abort_f = '1') then
980: exp_data_stores := 0;
981: act_data_stores := 0;
982:
983: elsif (store_metadata_f = '1') then
984:
985: exp_data_stores := to_integer(unsigned(frame_form_w(RWCNT_H downto RWCNT_L))) - 3;
986: act_data_stores := 0;
987: end if;
988:
989: -- Count actual number of "store_data" commands.
990: if (store_data_f = '1') then
991: act_data_stores := act_data_stores + 1;
992: end if;
993:
994: -- Check when frame was received that proper number of "store_data"
995: -- commands did arrive.
996: if (rec_valid_f = '1' and
997: act_data_stores /= exp_data_stores)
998: then
999: report "'store_data' count corrupted by CAN Core! " &
1000: "Expected: " & integer'image(exp_data_stores) &
1001: " Actual: " & integer'image(act_data_stores)
1002: severity error;
1003: end if;
1004: end if;
1005: end process;
1006: -- coverage on
1007:
1008: -- pragma translate_on
1009:
1010:
1011: -- psl default clock is rising_edge(clk_sys);
1012:
1013: -- psl read_counter_lt_rwcnt_asrt : assert never
1014: -- (read_counter_q > 19)
1015: -- report "Read counter higher than longest RWCNT!";
1016:
1017: -----------------------------------------------------------------------------------------------
1018: -- "reset_overrun_flag = '1'" only in "s_rxb_idle" state. Therefore we can
1019: -- use this signal to check that FSM is in s_rxb_idle state!
1020: -----------------------------------------------------------------------------------------------
1021:
1022: -- psl sof_pulse_asrt_asrt : assert never
1023: -- (sof_pulse = '1' and reset_overrun_flag = '0')
1024: -- report "RX Buffer: SOF pulse should come when RX Buffer is idle!";
1025:
1026: end architecture;