File: /__w/ctu-can-regression/ctu-can-regression/src/rx_buffer/rx_buffer_pointers.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 pointers.
71: --
72: -- Purpose:
73: -- Pointers to RX Buffer RAM in RX Buffer and free memory calculation.
74: -- Following pointers are implemented:
75: -- 1. Read pointer
76: -- 2. Write pointer raw
77: -- 3. Write pointer (regular, commited)
78: -- 4. Write pointer for storing timestamp.
79: -- Counters for free memory:
80: -- 1. RX mem free internal for control of storing and overrun
81: -- 2. RX mem free available to user.
82: --------------------------------------------------------------------------------
83:
84: Library ieee;
85: use ieee.std_logic_1164.all;
86: use ieee.numeric_std.ALL;
87: use ieee.math_real.ALL;
88:
89: Library ctu_can_fd_rtl;
90: use ctu_can_fd_rtl.can_constants_pkg.all;
91: use ctu_can_fd_rtl.can_types_pkg.all;
92:
93: use ctu_can_fd_rtl.CAN_FD_register_map.all;
94: use ctu_can_fd_rtl.CAN_FD_frame_format.all;
95:
96: entity rx_buffer_pointers is
97: generic (
98: -- RX Buffer size
99: G_RX_BUFF_SIZE : natural range 32 to 4096;
100:
101: -- Width of RX Buffer pointers
102: G_RX_BUFF_PTR_WIDTH : natural range 5 to 12
103: );
104: port (
105: -------------------------------------------------------------------------------------------
106: -- Clocks and Asynchronous reset
107: -------------------------------------------------------------------------------------------
108: clk_sys : in std_logic;
109: rx_buf_res_n_q_scan : in std_logic;
110:
111: -------------------------------------------------------------------------------------------
112: -- Control signals
113: -------------------------------------------------------------------------------------------
114: -- Abort storing of frame in RX Buffer. Revert to last frame. Raw RX
115: -- pointer will be reverted to internal RX pointers.
116: rec_abort_f : in std_logic;
117:
118: -- Commit RX Frame to RX Buffer. Raw pointer will be stored internal
119: -- RX pointer.
120: commit_rx_frame : in std_logic;
121:
122: -- RX Buffer RAM is being written and there is enough space available.
123: write_raw_OK : in std_logic;
124:
125: -- RX Frame is not commited, write pointer raw should be reverted to
126: -- last stored write_pointer value.
127: commit_overrun_abort : in std_logic;
128:
129: -- RX Buffer FSM signals to store regular write pointer to timestamp
130: -- write pointer
131: store_ts_wr_ptr : in std_logic;
132:
133: -- RX Buffer FSM signals to increment timestamp write pointer
134: inc_ts_wr_ptr : in std_logic;
135:
136: -- RX Buffer RAM is being read by SW
137: read_increment : in std_logic;
138:
139: -------------------------------------------------------------------------------------------
140: -- Status outputs
141: -------------------------------------------------------------------------------------------
142: -- Read Pointer (access from SW)
143: read_pointer : out std_logic_vector(G_RX_BUFF_PTR_WIDTH - 1 downto 0);
144:
145: -- Read pointer incremented by 1 (combinationally)
146: read_pointer_inc_1 : out std_logic_vector(G_RX_BUFF_PTR_WIDTH - 1 downto 0);
147:
148: -- Write pointer (committed, available to SW, after frame was stored)
149: write_pointer : out std_logic_vector(G_RX_BUFF_PTR_WIDTH - 1 downto 0);
150:
151: -- Write pointer RAW. Changing during frame, as frame is continously stored
152: -- to the buffer. When frame is sucesfully received, it is updated to
153: -- write pointer!
154: write_pointer_raw : out std_logic_vector(G_RX_BUFF_PTR_WIDTH - 1 downto 0);
155:
156: -- Timestamp write pointer
157: write_pointer_ts : out std_logic_vector(G_RX_BUFF_PTR_WIDTH - 1 downto 0);
158:
159: -- Number of free memory words available for user
160: rx_mem_free_i : out std_logic_vector(G_RX_BUFF_PTR_WIDTH downto 0)
161: );
162: end entity;
163:
164: architecture rtl of rx_buffer_pointers is
165:
166: -----------------------------------------------------------------------------------------------
167: -- Memory pointers
168: -----------------------------------------------------------------------------------------------
169:
170: signal read_pointer_i : unsigned(G_RX_BUFF_PTR_WIDTH - 1 downto 0);
171: signal read_pointer_inc_1_i : unsigned(G_RX_BUFF_PTR_WIDTH - 1 downto 0);
172: signal write_pointer_i : unsigned(G_RX_BUFF_PTR_WIDTH - 1 downto 0);
173:
174: signal write_pointer_raw_i : unsigned(G_RX_BUFF_PTR_WIDTH - 1 downto 0);
175: signal write_pointer_raw_d : unsigned(G_RX_BUFF_PTR_WIDTH - 1 downto 0);
176: signal write_pointer_raw_ce : std_logic;
177:
178: signal write_pointer_ts_i : unsigned(G_RX_BUFF_PTR_WIDTH - 1 downto 0);
179: signal write_pointer_ts_d : unsigned(G_RX_BUFF_PTR_WIDTH - 1 downto 0);
180: signal write_pointer_ts_ce : std_logic;
181:
182: -----------------------------------------------------------------------------------------------
183: -- Memory free status signals
184: -----------------------------------------------------------------------------------------------
185:
186: -- Width of free memory
187: constant C_FREE_MEM_WIDTH : natural := G_RX_BUFF_PTR_WIDTH + 1;
188:
189: signal rx_mem_free_i_i : unsigned(C_FREE_MEM_WIDTH - 1 downto 0);
190:
191: -- Raw value of number of free memory words.
192: signal rx_mem_free_raw : unsigned(C_FREE_MEM_WIDTH - 1 downto 0);
193:
194: -- Number of free memory words calculated during frame storing before commit
195: -- combinationally incremented by 1.
196: signal rx_mem_free_raw_inc_1 : unsigned(C_FREE_MEM_WIDTH - 1 downto 0);
197:
198: -- Number of free memory words calculated during frame storing before commit
199: -- combinationally decremented by 1.
200: signal rx_mem_free_raw_dec_1 : unsigned(C_FREE_MEM_WIDTH - 1 downto 0);
201:
202: -- Number of free memory words available to SW, combinationally icnremented
203: -- by 1.
204: signal rx_mem_free_i_inc_1 : unsigned(C_FREE_MEM_WIDTH - 1 downto 0);
205:
206: -----------------------------------------------------------------------------------------------
207: -- Auxiliarly signals
208: -----------------------------------------------------------------------------------------------
209: signal abort_applied : std_logic;
210:
211: begin
212:
213: read_pointer <= std_logic_vector(read_pointer_i);
214: read_pointer_inc_1 <= std_logic_vector(read_pointer_inc_1_i);
215: write_pointer <= std_logic_vector(write_pointer_i);
216: write_pointer_raw <= std_logic_vector(write_pointer_raw_i);
217: write_pointer_ts <= std_logic_vector(write_pointer_ts_i);
218: rx_mem_free_i <= std_logic_vector(rx_mem_free_i_i);
219:
220: abort_applied <= '1' when (rec_abort_f = '1' or commit_overrun_abort = '1')
221: else
222: '0';
223:
224: -----------------------------------------------------------------------------------------------
225: -- Read pointer, incremented during read from RX Buffer FIFO. Moving to next word by reading
226: -- (if there is sth to read).
227: -----------------------------------------------------------------------------------------------
228: read_pointer_proc : process(clk_sys, rx_buf_res_n_q_scan)
229: begin
230: if (rx_buf_res_n_q_scan = '0') then
231: read_pointer_i <= (others => '0');
232: elsif (rising_edge(clk_sys)) then
233: if (read_increment = '1') then
234: read_pointer_i <= read_pointer_inc_1_i;
235: end if;
236: end if;
237: end process;
238:
239: -----------------------------------------------------------------------------------------------
240: -- Write pointers available to the user manipulation. Loading "write_pointer_raw_int" to
241: -- "write_pointer_int" when frame is committed.
242: -----------------------------------------------------------------------------------------------
243: write_pointer_proc : process(clk_sys, rx_buf_res_n_q_scan)
244: begin
245: if (rx_buf_res_n_q_scan = '0') then
246: write_pointer_i <= (others => '0');
247: elsif (rising_edge(clk_sys)) then
248: if (commit_rx_frame = '1') then
249: write_pointer_i <= write_pointer_raw_i;
250: end if;
251: end if;
252: end process;
253:
254:
255: -----------------------------------------------------------------------------------------------
256: -- Write pointers raw manipulation:
257: -- 1. Increment when word is written to memory.
258: -- 2. Reset when "rec_abort_f" is active (Error frame) or frame finished and overrun occurred
259: -- meanwhile. Reset to value of last commited write pointer.
260: -----------------------------------------------------------------------------------------------
261: write_pointer_raw_d <= write_pointer_raw_i + 1 when (write_raw_OK = '1')
262: else
263: write_pointer_i;
264:
265: write_pointer_raw_ce <= '1' when (write_raw_OK = '1') else
266: '1' when (rec_abort_f = '1') else
267: '1' when (commit_overrun_abort = '1') else
268: '0';
269:
270: write_pointer_raw_proc : process(clk_sys, rx_buf_res_n_q_scan)
271: begin
272: if (rx_buf_res_n_q_scan = '0') then
273: write_pointer_raw_i <= (others => '0');
274: elsif (rising_edge(clk_sys)) then
275: if (write_pointer_raw_ce = '1') then
276: write_pointer_raw_i <= write_pointer_raw_d;
277: end if;
278: end if;
279: end process;
280:
281:
282: -----------------------------------------------------------------------------------------------
283: -- Timestamp write pointer.
284: -----------------------------------------------------------------------------------------------
285: write_pointer_ts_d <= write_pointer_raw_i when (store_ts_wr_ptr = '1')
286: else
287: write_pointer_ts_i + 1;
288:
289: -- Tick only when it should be incremented or stored
290: write_pointer_ts_ce <= '1' when (store_ts_wr_ptr = '1') else
291: '1' when (inc_ts_wr_ptr = '1') else
292: '0';
293:
294: timestamp_write_ptr_proc : process(clk_sys, rx_buf_res_n_q_scan)
295: begin
296: if (rx_buf_res_n_q_scan = '0') then
297: write_pointer_ts_i <= (others => '0');
298: elsif (rising_edge(clk_sys)) then
299: if (write_pointer_ts_ce = '1') then
300: write_pointer_ts_i <= write_pointer_ts_d;
301: end if;
302: end if;
303: end process;
304:
305:
306: -----------------------------------------------------------------------------------------------
307: -- Calculating amount of free memory.
308: -----------------------------------------------------------------------------------------------
309: mem_free_proc : process(clk_sys, rx_buf_res_n_q_scan)
310: begin
311: if (rx_buf_res_n_q_scan = '0') then
312: rx_mem_free_i_i <= to_unsigned(G_RX_BUFF_SIZE, C_FREE_MEM_WIDTH);
313: rx_mem_free_raw <= to_unsigned(G_RX_BUFF_SIZE, C_FREE_MEM_WIDTH);
314:
315: elsif (rising_edge(clk_sys)) then
316:
317: ---------------------------------------------------------------------------------------
318: -- Calculate free memory internally (raw)
319: ---------------------------------------------------------------------------------------
320: if (read_increment = '1') then
321:
322: -- Read of memory word, and abort at the same time. Revert last commited value of
323: -- read pointer incremented by 1.
324: if (abort_applied = '1') then
325: rx_mem_free_raw <= rx_mem_free_i_inc_1;
326:
327: -- Read of memory word and no write of memory word. Load raw value incremented by 1.
328: elsif (write_raw_OK = '0') then
329: rx_mem_free_raw <= rx_mem_free_raw_inc_1;
330:
331: -- Implicit else: Read increment and write of a word at the same time,
332: -- rx_mem_free_raw remains unchanged.
333: end if;
334:
335: else
336:
337: -- Abort, or abort was previously flaged -> Revert last commited value.
338: if (abort_applied = '1') then
339: rx_mem_free_raw <= rx_mem_free_i_i;
340:
341: -- No read, write only, decrement by 1.
342: elsif (write_raw_OK = '1') then
343: rx_mem_free_raw <= rx_mem_free_raw_dec_1;
344: end if;
345: end if;
346:
347: ---------------------------------------------------------------------------------------
348: -- Calculate free memory for user:
349: -- 1. Increment when user reads the frame.
350: -- 2. Load RAW value when comitt occurs
351: ---------------------------------------------------------------------------------------
352: if (read_increment = '1') then
353: if (commit_rx_frame = '1') then
354: rx_mem_free_i_i <= rx_mem_free_raw_inc_1;
355: else
356: rx_mem_free_i_i <= rx_mem_free_i_inc_1;
357: end if;
358:
359: elsif (commit_rx_frame = '1') then
360: rx_mem_free_i_i <= rx_mem_free_raw;
361: end if;
362:
363: end if;
364: end process;
365:
366:
367: -----------------------------------------------------------------------------------------------
368: -- Calculating incremented value of free memory combinationally
369: -----------------------------------------------------------------------------------------------
370: mem_free_arith_proc : process(rx_mem_free_i_i, rx_mem_free_raw)
371: begin
372: rx_mem_free_i_inc_1 <= rx_mem_free_i_i + 1;
373: rx_mem_free_raw_inc_1 <= rx_mem_free_raw + 1;
374: rx_mem_free_raw_dec_1 <= rx_mem_free_raw - 1;
375: end process;
376:
377: -----------------------------------------------------------------------------------------------
378: -- Calculation of Incremented Read Pointer combinationally. This is used for two things:
379: -- 1. Actual Increment of Read pointer during read of RX_DATA.
380: -- 2. Adressing RX Buffer RAM read side by incremented value to avoid one clock cycle delay on
381: -- "read_pointer_int" and thus allow bursts on read from RX_DATA register!
382: -----------------------------------------------------------------------------------------------
383: read_pointer_inc_proc : process(read_pointer_i)
384: begin
385: read_pointer_inc_1_i <= read_pointer_i + 1;
386: end process;
387:
388: end architecture;