rx_buffer.vhd 44.7 KB
Newer Older
Ille, Ondrej, Ing.'s avatar
Ille, Ondrej, Ing. committed
1
--------------------------------------------------------------------------------
Ille, Ondrej, Ing.'s avatar
Ille, Ondrej, Ing. committed
2
-- 
Ille, Ondrej, Ing.'s avatar
Ille, Ondrej, Ing. committed
3
-- CTU CAN FD IP Core
4
-- Copyright (C) 2015-2018
Ille, Ondrej, Ing.'s avatar
Ille, Ondrej, Ing. committed
5
-- 
6 7
-- Authors:
--     Ondrej Ille <ondrej.ille@gmail.com>
8
--     Martin Jerabek <martin.jerabek01@gmail.com>
9 10
-- 
-- Project advisors: 
Ille, Ondrej, Ing.'s avatar
Ille, Ondrej, Ing. committed
11 12
-- 	Jiri Novak <jnovak@fel.cvut.cz>
-- 	Pavel Pisa <pisa@cmp.felk.cvut.cz>
13
-- 
Ille, Ondrej, Ing.'s avatar
Ille, Ondrej, Ing. committed
14 15 16 17
-- Department of Measurement         (http://meas.fel.cvut.cz/)
-- Faculty of Electrical Engineering (http://www.fel.cvut.cz)
-- Czech Technical University        (http://www.cvut.cz/)
-- 
18 19 20 21 22
-- Permission is hereby granted, free of charge, to any person obtaining a copy
-- of this VHDL component and associated documentation files (the "Component"),
-- to deal in the Component without restriction, including without limitation
-- the rights to use, copy, modify, merge, publish, distribute, sublicense,
-- and/or sell copies of the Component, and to permit persons to whom the
Ille, Ondrej, Ing.'s avatar
Ille, Ondrej, Ing. committed
23 24
-- Component is furnished to do so, subject to the following conditions:
-- 
25
-- The above copyright notice and this permission notice shall be included in
Ille, Ondrej, Ing.'s avatar
Ille, Ondrej, Ing. committed
26 27
-- all copies or substantial portions of the Component.
-- 
28 29 30 31
-- THE COMPONENT IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-- AUTHORS OR COPYRIGHTHOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
32
-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
33
-- FROM, OUT OF OR IN CONNECTION WITH THE COMPONENT OR THE USE OR OTHER DEALINGS
Ille, Ondrej, Ing.'s avatar
Ille, Ondrej, Ing. committed
34 35
-- IN THE COMPONENT.
-- 
36 37
-- The CAN protocol is developed by Robert Bosch GmbH and protected by patents.
-- Anybody who wants to implement this IP core on silicon has to obtain a CAN
38
-- protocol license from Bosch.
Ille, Ondrej, Ing.'s avatar
Ille, Ondrej, Ing. committed
39
-- 
40 41 42 43 44 45 46 47 48 49
--------------------------------------------------------------------------------

--------------------------------------------------------------------------------
-- Purpose:
--  Recieve buffer for messages. RAM memory type of N*32 bit words. Reading of 
--  data from registers done word by word. In registers reading implemented in 
--  the way that one read moves to the next word. Storing the message into the
--  buffer is sequential operation started with valid rec_message_valid for one
--  clock cycle. In following up to 20 clock cycles recieved data has to be va-
--  lid to be fully stored
50
--
51 52 53 54 55 56
--  Note:This is guaranteed from CAN Core. rec_message_valid is active in the 
--  end of EOF field. Intermission field follows with 11 bit times (minimum 55 
--  clock cycles) where recieved data are not changed, only overload condition 
--  may be signallised!
--------------------------------------------------------------------------------
-- Revision History:
57
--    July 2015   Created file
Ille, Ondrej, Ing.'s avatar
Ille, Ondrej, Ing. committed
58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87
--    18.12.2015  RX Buffer inference from Flip-flops changed to native SRAM me-
--                mory on FPGA. Dual port memory used for this purpose (sync 
--                write and async read). Memory is automatically recongized by
--                synthetizer. Erase of buffer needed to be removed, because 
--                SRAM cant be erased all at once, due to this SRAM wasnt in-
--                ferred before. To achieve "erase like" behaviour simple work-
--                around was implemented. Additional vector "memory_valid" is 
--                kept. This vector is erased at once (FF based) and when write
--                into memory is performed this bit is set to logic '1' for app-
--                ropriate field. Async read returns data from memory when valid
--                bit is set, and all zeroes if it is not. Due to this, from user
--                point of view memory acts as erased after initialization.
--                Due to this  "RAM initialiser" IP function or State machine
--                does not have to be used. Memory is thus available directly
--                after async reset.
--                Disadvantage is that one memory vector of the same size as 
--                memory need to be kept!
--    2.6.2016    Added data_size set to 0 at start time to avoid possible 
--                storing of invalid frame
--    3.6.2016    1.Bug fix of mem_free variable. Variable was decreased by frame
--                  size at arrival of new frame! This is not expected behaviour
--                  since it takes up to 20 clock cycles to store the frame and 
--                  mem_free is now reduced by one with each word stored!
--                2.Detected and fixed incorrect behaviour during data overrun! 
--                  Wrong setting of copy_counter caused part of the frame to be
--                  stored during data_overrun
--    21.6.2016   Added limit of 512 to the RX Buffer size! Thisway it is comp-
--                liant with memory map width of readable size
--    22.6.2016   1.Added RTR frame detection. Any RTR frame is recieved no data
--                  words are stored!!!
88
--                2.Added rec_esi bit stored into the buffer!
Ille, Ondrej, Ing.'s avatar
Ille, Ondrej, Ing. committed
89 90 91 92 93
--    15.7.2016   Changed handling of moving to next word in RX buffer RX_DATA.
--                Falling edge detection removed Now memory registers set 
--                "drv_read_start" only for ONE clock cycle per each access. So
--                it is enough to check whether signal is active! Thisway it is
--                not necessary to add empty clock cycles between consecutive
94
--                reads from RX_DATA register!
Ille, Ondrej, Ing.'s avatar
Ille, Ondrej, Ing. committed
95 96 97 98
--    29.11.2017  Changed hadnling of received data. "rec_data_in" replaced by 
--                "rec_dram_word" and "rec_dram_addr" as part of resource opti-
--                mizations. Data are not available in parallel at input of the
--                RX buffer but addressed in internal RAM of Protocol control.
99 100 101 102 103
--    09.02.2018  1. Fixed data_size upper range threshold from 32 to 31.
--                2. Added "frame_form_w" to assign it with generated indices
--                3. Added combinational decoder on received DLC to frame
--                   length in words (without frame_format word) into new signal
--                   "data_size_comb".
104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131
--    19.02.2018  Removed memory valid vector. Output word is 0 only if
--                memory is completely empty.
--    20.02.2018  1. Implemented process for counting frames "read_frame_proc".
--                   It stores size of the frame at the first read and decrements
--                   it until 1. At transition from 1 to 0, message counter is
--                   decremented.
--                2. Added commit_rx_frame which will be active for one clock
--                   cycle when frame storing finished. This is preparation for
--                   continous storing of the frame during reception, instead
--                   of storing it at once at the end.
--                3. Changed read handling. Read is allowed to proceed (increment
--                   read pointer) only if new message counter is non-zero. This
--                   guarantees that frame is fully stored (again preparation
--                   for later) at the time of first read. IT also keeps the 
--                   read pointer in sync with frame counting process from p.1.
--                4. Since "rx_empty" will be used for detection of frame in the
--                   buffer, its now driven by non-zero message counter instead
--                   of non-zero amount of stored words. Non-zero amount of
--                   stored words would indicate that buffer is not empty even
--                   if the frame was not committed yet! We dont want to signal
--                   it since storing of the rest of the words (in case of con-
--                   tinous storing during reception) might take longer than
--                   reading the words out! Thus we would end up in a situation
--                   where buffer is marked as non-empty but, SW cant read whole
--                   frame from it! This is undesirable.
--                5. Removed "message_mark" signal and original "message_counter"
--                   variable in memory access process due to beiing obsolete
--                   with new implementation of message counter.
132 133
--                6. Increased maximal buffer depth to 4096, resized output
--                   vectors accordingly.
134 135 136
--    22.02.2018  1. Removed obsolete "drv_ovr_rx".
--                2. Added configurable capturing of timestamp on beginning or
--                   end of the frame.
137 138 139 140 141 142 143 144 145 146 147 148
--    11.5.2018   1. Changed storing of frame to last during the whole frame.
--                2. Added FSM for control of storing
--                3. Added "write_pointer_raw" and "write_pointer_extra_ts" to
--                   execute writes of timestamp at the end of the frame.
--                4. Commit operation moves "raw" pointer to real pointer. Data
--                   overrun restarts "raw" pointer to value of committed
--                   pointer.
--    19.5.2018   1. Added assertion for number of "store_data" commands during
--                   storing of CAN Frame.
--                2. Separated "write_raw_increment" to "write_raw_intent" and
--                   "write_raw_OK" which is valid only when there is enough
--                   space in the buffer and overrun did not occur before!
149 150 151
--    7.6.2018    Changed detection of buffer full to equality of 
--                "read_pointer" and "write_pointer_raw" and nonzero amount
--                of frames stored.
152 153 154
--   10.7.2018    Changed decoding of RWCNT field. Added exception for CAN 
--                frames with DLC higher than 8, to store only 8 bytes (2 data
--                words).
155 156 157
--   31.8.2018    Changed reading of RAM to be synchronous to achieve BRAM
--                inferrence on Xilinx! Added register "read_mem_word" to which
--                RAM word is read.
158 159
--  15.12.2018    1. Moved RX Buffer FSM to separate entity.
--                2. Moved handling of memory pointers to separate entity
Ille, Ondrej, Ing.'s avatar
Ille, Ondrej, Ing. committed
160
--------------------------------------------------------------------------------
161

162
context work.ctu_can_synth_context;
163

164
entity rx_buffer is
165
    generic(
166

167 168 169 170 171 172 173 174 175 176 177 178
        -- Only 2^k are allowed as buff_size. Memory adressing is in modular 
        -- arithmetic, synthesis of modulo by number other than 2^k might not
        -- play nicely (will consume lot of LUTs)!!
        buff_size                   :       natural range 32 to 4096 := 32
    );
    port(
        ------------------------------------------------------------------------
        -- Clocks and reset 
        ------------------------------------------------------------------------
        signal clk_sys              :in     std_logic; --System clock
        signal res_n                :in     std_logic; --Async. reset
        
179

180 181 182
        ------------------------------------------------------------------------
        -- Metadata from CAN Core (provided discrete)
        ------------------------------------------------------------------------
183
        
184 185
        -- Message Identifier
        signal rec_ident_in         :in     std_logic_vector(28 downto 0);
186
        
187 188
        -- Data length code
        signal rec_dlc_in           :in     std_logic_vector(3 downto 0);
189
        
190 191
        -- Recieved identifier type (0-BASE Format, 1-Extended Format);
        signal rec_ident_type_in    :in     std_logic;
192
        
193 194
        -- Recieved frame type (0-Normal CAN, 1- CAN FD)
        signal rec_frame_type_in    :in     std_logic;
195
        
196 197
        -- Recieved frame is RTR Frame(0-No, 1-Yes)
        signal rec_is_rtr           :in     std_logic;
198
        
199 200 201 202 203 204 205
        -- Whenever frame was recieved with BIT Rate shift 
        signal rec_brs              :in     std_logic;

        -- Recieved error state indicator
        signal rec_esi              :in     std_logic;


Ille, Ondrej, Ing.'s avatar
Ille, Ondrej, Ing. committed
206
        ------------------------------------------------------------------------
207
        -- Control signals from CAN Core which control storing of CAN Frame.
Ille, Ondrej, Ing.'s avatar
Ille, Ondrej, Ing. committed
208
        ------------------------------------------------------------------------
209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226

        -- After control field of CAN frame, metadata are valid and can be stored.
        -- This command starts the RX FSM for storing.
        signal store_metadata       :in     std_logic;
       
        -- Signal that one word of data can be stored (TX_DATA_X_W). This signal
        -- is active when 4 bytes were received or data reception has finished 
        -- on 4 byte unaligned number of frames! (Thus allowing to store also
        -- data which are not 4 byte aligned!
        signal store_data           :in     std_logic;

        -- Data word which should be stored when "store_data" is active!
        signal store_data_word      :in     std_logic_vector(31 downto 0);

        -- When frame reception is succesfull, in the end of EOF field, CAN Core
        -- gives acknowledge by this signal. This means that frame was received
        -- OK, and Error frame can no longer occur in it.
        signal rec_message_valid    :in     std_logic;
227
        
228 229 230 231 232 233 234 235 236 237 238 239 240
        -- If error frame occurred, CAN Core activates this signal.
        -- "write_pointer_raw" will be restarted to last committed value in
        -- "write_pointer".
        signal rec_abort            :in     std_logic;

        -- Signals start of frame. If timestamp on RX frame should be captured
        -- in the beginning of the frame, this pulse captures the timestamp!
        signal sof_pulse            :in     std_logic;


        ------------------------------------
        -- Status signals of recieve buffer
        ------------------------------------
241
        
242 243
        -- Actual size of synthetised message buffer (in 32 bit words)
        signal rx_buf_size          :out    std_logic_vector(12 downto 0);
244
        
245 246
        -- Signal whenever buffer is full (no free memory words)
        signal rx_full              :out    std_logic;
247
        
248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280
        -- Signal whenever buffer is empty (no frame (message) is stored)
        signal rx_empty             :out    std_logic;
        
        -- Number of frames (messages) stored in recieve buffer
        signal rx_message_count     :out    std_logic_vector(10 downto 0);
        
        -- Number of free 32 bit wide words
        signal rx_mem_free          :out    std_logic_vector(12 downto 0);
        
        -- Position of read pointer
        signal rx_read_pointer_pos  :out    std_logic_vector(11 downto 0);
        
        -- Position of write pointer
        signal rx_write_pointer_pos :out    std_logic_vector(11 downto 0);
        
        -- Overrun occurred, data were discarded!
        -- (This is a flag and persists until it is cleared by SW)! 
        signal rx_data_overrun      :out    std_logic;
        
        -- External timestamp input
        signal timestamp            :in     std_logic_vector(63 downto 0);


        ------------------------------------
        -- User registers interface
        ------------------------------------
        
        -- Actually loaded data for reading
        signal rx_read_buff         :out    std_logic_vector(31 downto 0);
        
        -- Driving bus from registers
        signal drv_bus              :in     std_logic_vector(1023 downto 0)
    );
281 282 283 284
end entity;


architecture rtl of rx_buffer is
285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306

    ----------------------------------------------------------------------------
    ----------------------------------------------------------------------------
    -- Driving bus signal aliases
    ----------------------------------------------------------------------------
    ----------------------------------------------------------------------------

    -- Erase command from driving registers. Resets FIFO pointers!
    signal drv_erase_rx             :       std_logic;

    -- Command to load increase the reading pointer
    signal drv_read_start           :       std_logic;

    -- Clear data OverRun Flag
    signal drv_clr_ovr              :       std_logic;

    -- Receive Timestamp options
    signal drv_rtsopt               :       std_logic;


    ----------------------------------------------------------------------------
    ----------------------------------------------------------------------------
307
    -- FIFO  Memory - Pointers
308 309 310 311 312 313
    ----------------------------------------------------------------------------
    ----------------------------------------------------------------------------

    -- Read Pointer (access from SW)
    signal read_pointer             :       natural range 0 to buff_size - 1;

314 315 316
    -- Read pointer incremented by 1 (combinationally)
    signal read_pointer_inc_1       :       natural range 0 to buff_size - 1;

317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335
    -- Write pointer (committed, available to SW, after frame was stored)
    signal write_pointer            :       natural range 0 to buff_size - 1;

    -- Write pointer RAW. Changing during frame, as frame is continously stored
    -- to the buffer. When frame is sucesfully received, it is updated to
    -- write pointer!
    signal write_pointer_raw        :       natural range 0 to buff_size - 1;

    -- Extra write pointer which is used for storing timestamp at the end of
    -- data frame!
    signal write_pointer_extra_ts   :       natural range 0 to buff_size - 1;

    -- Final pointer to memory. "write_pointer_raw" and 
    -- "write_pointer_extra_ts" are multiplexed based on RX FSM! 
    signal memory_write_pointer     :       natural range 0 to buff_size - 1;

    -- Data that will be written to the RX Buffer memory!
    signal memory_write_data        :       std_logic_vector(31 downto 0);

336
    -- Number of free memory words available to SW after frame was committed.
Ille, Ondrej, Ing.'s avatar
Ille, Ondrej, Ing. committed
337
    signal rx_mem_free_int          :       natural range -1 to buff_size + 1;
338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390

    ----------------------------------------------------------------------------
    ----------------------------------------------------------------------------
    -- FIFO  Memory - Free words, Overrun status
    ----------------------------------------------------------------------------
    ----------------------------------------------------------------------------

    -- Data overrun flag. Recieved message was lost, because there was not
    -- enough space in FIFO during storing! Available for SW!
    signal data_overrun_r           :       std_logic;

    -- Internal data overrun flag. This flag is not available to SW, but it
    -- is restarted automatically at the beginning of each new frame reception!
    -- This allows to accept next frames when overrun occurred on previous ones!
    signal data_overrun_int         :       std_logic;

    -- Combinationally decoded overrun condition. Active when there is intention
    -- to store word to the memory, but there is not enough free space! 
    signal overrun_condition        :       boolean;

     -- RX Buffer is empty (no frame is stored in it)
    signal rx_empty_int             :       std_logic;

    -- Indicator of at least one free word in RX FIFO!
    signal is_free_word             :       boolean;

    -- Number of frames currently stored in RX Buffer. Smallest frame length
    -- stored is 4 (FRAME_FORMAT +  IDENTIFIER + 2 * TIMESTAMP). Since we need
    -- to store 0 and also buff_size / 4 values we need one value more than can
    -- fit into buff_size / 4 width counter. Use one bit wider counter.
    signal message_count            :       natural range 0 to (buff_size / 2) - 1; 

    -- Counter for reading the frame. When whole frame is read,
    -- number of frames must be decremented.
    signal read_frame_counter       :       natural range 0 to 31;


    ----------------------------------------------------------------------------
    ----------------------------------------------------------------------------
    -- FIFO  Memory - Commands which manipulate pointers, or indicate intent
    --  to write or read from the memory.
    ----------------------------------------------------------------------------
    ----------------------------------------------------------------------------

    -- When commit of RX Frame is signalled by CAN Core (rec_message_valid)
    -- "commit_rx_frame" is set to indicate that frame was sucesfully
    -- stored. Note that "rec_message_valid" is not enough to indicate that
    -- frame was stored sucesfully! If frame storing fails at some point due
    -- to lack of memory in FIFO, Protocol control will still finish the frame
    -- and provide "rec_message_valid"! Thus RX FSM sets "commit_rx_frame" only
    -- if "data_overrun" did not occur during the frame!
    signal commit_rx_frame          :       std_logic;

391 392 393 394 395
    -- When overrun occurred at any point in the frame and some word was not
    -- stored, frame can not be committed, and write_pointer must be moved
    -- back to last committed value!
    signal commit_overrun_abort     :       std_logic;

396 397
    -- Indicates that read occurred, and that it is valid (there is something
    -- to read), thus read pointer can be incremented.
398
    signal read_increment           :       std_logic;
399 400 401

    -- Indicates that "write_raw_intent" is OK (no overrun) and data can be
    -- truly written to the memory and raw pointer can be updated!
402 403 404 405 406 407 408 409 410 411 412 413
    signal write_raw_OK             :       std_logic;


    ----------------------------------------------------------------------------
    ----------------------------------------------------------------------------
    -- RX Buffer FSM outputs
    ----------------------------------------------------------------------------
    ----------------------------------------------------------------------------

    -- Indicates that FSM is in a state which would like to perform write of a
    -- word to RX Buffer memory!
    signal write_raw_intent         :       std_logic;
414 415 416

    -- Indicates that FSM is in one of states for writing timestmap from end of
    -- frame to the memory.
417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432
    signal write_extra_ts           :       std_logic;

    -- Storing of extra timestamp is at the end.
    signal store_extra_ts_end       :       std_logic;

    -- Data write selector
    signal data_selector            :       std_logic_vector(6 downto 0);

    -- Signals that write pointer should be stored to extra write pointer
    signal store_extra_wr_ptr       :       std_logic;

    -- Increment extra write pointer
    signal inc_extra_wr_ptr         :       std_logic;

    -- Restart overrun flag upon start of new frame
    signal reset_overrun_flag       :       std_logic;
433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451


    ----------------------------------------------------------------------------
    ----------------------------------------------------------------------------
    -- RX FSM, Timestamp capturing, combinationally decoded words
    ----------------------------------------------------------------------------
    ----------------------------------------------------------------------------

    -- Combinationally decoded size of the frame (without Frame format word)
    -- from received DLC (the size is in 32-bit words).
    signal rwcnt_com                :       natural range 0 to 31;

    -- Combinational decoded frame format word from metadata.
    signal frame_form_w             :       std_logic_vector(31 downto 0);

    -- Internal timestamp captured for storing. Captured either in the
    -- beginning or end of frame. 
    signal timestamp_capture        :       std_logic_vector(63 downto 0);

452

453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470
    ----------------------------------------------------------------------------
    ----------------------------------------------------------------------------
    -- RAM wrapper signals
    ----------------------------------------------------------------------------
    ---------------------------------------------------------------------------
    
    -- Write control signal    
    signal RAM_write                :       std_logic;

    -- Data output from port B     
    signal RAM_data_out             :       std_logic_vector(31 downto 0);

    -- Write address (connected to write pointer)
    signal RAM_write_address        :       std_logic_vector(11 downto 0);

    -- Read address (connected to read pointer)
    signal RAM_read_address         :       std_logic_vector(11 downto 0);

471 472 473 474 475 476 477 478 479
begin

    ----------------------------------------------------------------------------
    -- Driving bus aliases
    ----------------------------------------------------------------------------
    drv_erase_rx          <= drv_bus(DRV_ERASE_RX_INDEX);
    drv_read_start        <= drv_bus(DRV_READ_START_INDEX);
    drv_clr_ovr           <= drv_bus(DRV_CLR_OVR_INDEX);
    drv_rtsopt            <= drv_bus(DRV_RTSOPT_INDEX);
480

481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502

    ----------------------------------------------------------------------------
    -- Propagating status registers on output
    ----------------------------------------------------------------------------
    rx_read_pointer_pos   <= std_logic_vector(to_unsigned(read_pointer, 12));
    rx_write_pointer_pos  <= std_logic_vector(to_unsigned(write_pointer, 12));
    rx_data_overrun       <= data_overrun_r;
    rx_buf_size           <= std_logic_vector(to_unsigned(buff_size, 13));

    rx_empty_int          <= '1' when (message_count = 0)
                                 else
                             '0'; 

    rx_full               <= '1' when (rx_mem_free_int = 0)
                                 else
                             '0';

    rx_message_count      <= std_logic_vector(to_unsigned(message_count, 11)); 
    rx_mem_free           <= std_logic_vector(to_unsigned(rx_mem_free_int, 13));
    rx_empty              <= rx_empty_int;


503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551
    ----------------------------------------------------------------------------
    -- RX Buffer FSM component
    ----------------------------------------------------------------------------
    rx_buffer_fsm_comp : rx_buffer_fsm
    port map(
        clk_sys             => clk_sys,
        res_n               => res_n,
        store_metadata      => store_metadata,
        store_data          => store_data,
        rec_message_valid   => rec_message_valid,
        rec_abort           => rec_abort,
        sof_pulse           => sof_pulse,
        drv_bus             => drv_bus,
        write_raw_intent    => write_raw_intent,
        write_extra_ts      => write_extra_ts,
        store_extra_ts_end  => store_extra_ts_end,
        data_selector       => data_selector,
        store_extra_wr_ptr  => store_extra_wr_ptr,
        inc_extra_wr_ptr    => inc_extra_wr_ptr,
        reset_overrun_flag  => reset_overrun_flag
    );


    ----------------------------------------------------------------------------
    -- RX Buffer Memory pointers
    ----------------------------------------------------------------------------
    rx_buffer_pointers_comp : rx_buffer_pointers
    generic map(
        buff_size               => buff_size
    )
    port map(
        clk_sys                 => clk_sys,
        res_n                   => res_n,
        rec_abort               => rec_abort,
        commit_rx_frame         => commit_rx_frame,
        write_raw_OK            => write_raw_OK,
        commit_overrun_abort    => commit_overrun_abort,
        store_extra_wr_ptr      => store_extra_wr_ptr,
        inc_extra_wr_ptr        => inc_extra_wr_ptr,
        read_increment          => read_increment,
        drv_bus                 => drv_bus,
        read_pointer            => read_pointer,
        read_pointer_inc_1      => read_pointer_inc_1,
        write_pointer           => write_pointer,
        write_pointer_raw       => write_pointer_raw,
        write_pointer_extra_ts  => write_pointer_extra_ts,
        rx_mem_free_int         => rx_mem_free_int
    );

552 553

    ----------------------------------------------------------------------------
554 555 556
    -- Final write pointer is multiplexed between "write_pointer_raw" for
    -- regular writes and "write_pointer_extra_ts" for writes of timestamp
    -- in the end of frame!
557
    ----------------------------------------------------------------------------
558 559 560
    memory_write_pointer   <= write_pointer_extra_ts when (write_extra_ts = '1')
                                                     else
                              write_pointer_raw;
561 562 563


    ----------------------------------------------------------------------------
564
    -- Memory data which are written depend on state of the FSM
565
    ----------------------------------------------------------------------------
566 567 568 569 570 571 572 573 574
    with data_selector select memory_write_data <=
        frame_form_w                     when "0000001",
        "000" & rec_ident_in             when "0000010",
        timestamp_capture(31 downto 0)   when "0000100",
        timestamp_capture(31 downto 0)   when "0001000",
        timestamp_capture(63 downto 32)  when "0010000",
        timestamp_capture(63 downto 32)  when "0100000",
        store_data_word                  when "1000000",
        (OTHERS => '0')                  when others;
575

576 577 578 579 580 581

    ----------------------------------------------------------------------------
    -- Signalling that read which came is valid (there is sth to read)
    ----------------------------------------------------------------------------
    read_increment        <= '1' when (drv_read_start = '1' and
                                        rx_empty_int = '0')
582
                                  else
583 584
                             '0';

585 586 587 588 589

    ----------------------------------------------------------------------------
    -- Signalling that FSM may progress with the write (there is enough space
    -- in the buffer, nor any previous data were lost due to overrun)
    ----------------------------------------------------------------------------
590
    write_raw_OK         <= '1' when (write_raw_intent = '1' and
591 592
                                       overrun_condition = false and
                                       data_overrun_int = '0')
593 594
                                else
                            '0';
595 596

    ----------------------------------------------------------------------------
597 598 599 600 601 602
    -- Store of new word can be executed only if there is space in the buffer.
    -- We don't need exact amount of words. We only need to know if there is
    -- space! When "read_pointer" and "write_pointer_raw" are equal, then 
    -- memory is either empty, or full! If there is no frame stored and pointers
    -- are equal, then memory is empty! If there is at least one frame and
    -- pointers are equal, then memory must be full!
603
    ----------------------------------------------------------------------------
604
    is_free_word          <= false when (read_pointer = write_pointer_raw and
605 606
                                         message_count > 0)
                                   else
607 608 609 610 611 612 613 614 615 616
                             true;

    ----------------------------------------------------------------------------
    -- Overrun condition. Following conditions must be met:
    --  1. FSM wants to write to memory either to the position of
    --      "write_pointer_raw". Note that "write_pointer_extra_ts" writes to
    --      words which were already written, thus there is no need to watch
    --      for overrun!
    --  2. There is no free word in the memory remaining!
    ----------------------------------------------------------------------------
617
    overrun_condition    <= true when (write_raw_intent = '1' and 
618 619 620 621 622 623 624 625 626
                                       (is_free_word = false))
                                 else
                            false;


    ----------------------------------------------------------------------------
    -- When buffer is empty the word on address of read pointer is not valid,
    -- provide zeroes instead
    ----------------------------------------------------------------------------
627 628
    rx_read_buff          <= RAM_data_out when (rx_empty_int = '0')
                                          else
629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660
                             (OTHERS => '0');


    ----------------------------------------------------------------------------
    -- Receive data size (in words) decoder
    ----------------------------------------------------------------------------
    with rec_dlc_in select rwcnt_com <=
        3 when "0000", --Zero bits
        4 when "0001", --1 byte
        4 when "0010", --2 bytes
        4 when "0011", --3 bytes
        4 when "0100", --4 bytes
        5 when "0101", --5 bytes
        5 when "0110", --6 bytes
        5 when "0111", --7 bytes
        5 when "1000", --8 bytes
        6 when "1001", --12 bytes
        7 when "1010", --16 bytes
        8 when "1011", --20 bytes
        9 when "1100", --24 bytes
        11 when "1101", --32 bytes
        15 when "1110", --48 bytes
        19 when "1111", --64 bytes
        0  when others;


    ----------------------------------------------------------------------------
    -- Frame format word assignment
    ----------------------------------------------------------------------------
    frame_form_w(DLC_H downto DLC_L)      <= rec_dlc_in;
    frame_form_w(4)                       <= '0';
    frame_form_w(RTR_IND)                 <= rec_is_rtr;
661 662
    frame_form_w(IDE_IND)                 <= rec_ident_type_in;
    frame_form_w(FDF_IND)                 <= rec_frame_type_in;
663 664
    frame_form_w(TBF_IND)                 <= '1'; -- All frames have the timestamp
    frame_form_w(BRS_IND)                 <= rec_brs;
665 666
    frame_form_w(ESI_RSV_IND)             <= rec_esi;

667 668 669 670 671 672 673 674 675

    ----------------------------------------------------------------------------
    -- RWCNT (Read word count is calculated like so:
    --  1. For RTR Frames -> 3 (Only ID + 2 Timestamp words)
    --  2. For Normal CAN Frames with DLC > 8 max. 8 bytes -> RWCNT = 5
    --  3. Otherwise Number of data bytes is matching Received DLC!
    ----------------------------------------------------------------------------
    frame_form_w(RWCNT_H downto RWCNT_L)  <=
        "00011" when (rec_is_rtr = RTR_FRAME) else
Ille, Ondrej, Ing.'s avatar
Ille, Ondrej, Ing. committed
676
        "00101" when ((rec_frame_type_in = NORMAL_CAN) and (rec_dlc_in(3) = '1')) else
Ille, Ondrej, Ing.'s avatar
Ille, Ondrej, Ing. committed
677
         std_logic_vector(to_unsigned(rwcnt_com, (RWCNT_H - RWCNT_L + 1)));
678 679 680 681 682 683 684 685 686 687 688 689 690 691

    frame_form_w(31 downto 16)            <= (OTHERS => '0');


    ----------------------------------------------------------------------------
    -- Capturing timestamp. Done at the beginning or end of frame based on
    -- SW configuration.
    ----------------------------------------------------------------------------
    capt_ts_proc : process(clk_sys, res_n)
    begin
        if (res_n = ACT_RESET) then
            timestamp_capture       <= (OTHERS => '0');

        elsif (rising_edge(clk_sys)) then
692
            
693 694 695 696 697 698 699 700 701 702
            if ((drv_rtsopt = RTS_END and rec_message_valid = '1') or
                (drv_rtsopt = RTS_BEG and sof_pulse = '1')) 
            then  
                timestamp_capture   <= timestamp;
            end if;
        end if;
    end process;


    ----------------------------------------------------------------------------
703 704 705 706 707
    -- Reading counter (read_frame_counter) which is loaded by RWCNT during read
    -- of frame format word. Then each next read decreases the counter. When 
    -- read counter reaches zero, message count is decreased. If "commit_rx_frame" 
    -- comes, "message_count" is incremented. If both occur at the same time
    -- , "message_count" does not change.
708 709 710 711 712 713 714 715
    ----------------------------------------------------------------------------
    read_frame_proc : process(clk_sys, res_n, drv_erase_rx)
    begin
        if (res_n = ACT_RESET or drv_erase_rx = '1') then
            read_frame_counter           <= 0;

        elsif (rising_edge(clk_sys)) then

716 717 718 719
            --------------------------------------------------------------------
            -- Reading frame by user when there is active read and there is
            -- something to read
            --------------------------------------------------------------------
720
            if (read_increment = '1') then
721

722
                ----------------------------------------------------------------
723 724 725
                -- During the read of FRAME_FORMAT word store the length
                -- of the frame to "read_frame_counter", thus we know how much
                -- we have to read before decrementing the "message_count".
726
                ----------------------------------------------------------------
727 728
                if (read_frame_counter = 0) then
                    read_frame_counter    <=
729
                        to_integer(unsigned(RAM_data_out(RWCNT_H downto
730
                                                            RWCNT_L)));
731
                else
732
                    read_frame_counter <= read_frame_counter - 1;
733
                end if;
734 735
            end if;

736 737 738 739
        end if;    
    end process;


740 741 742 743 744 745 746 747 748 749 750
    ---------------------------------------------------------------------------
    -- Manipulation of "message_count". When last word is read from frame
    -- (read_frame_counter = 1 and read_increment), "message_count" is
    -- decreased, when new frame is committed, message count is increased.
    -- If both at the same time, no change since one frame is added, next is 
    -- removed!
    ---------------------------------------------------------------------------
    message_count_ctr_proc : process(res_n, clk_sys, drv_erase_rx)
    begin
        if (res_n = ACT_RESET or drv_erase_rx = '1') then
            message_count <= 0;
751

752
        elsif (rising_edge(clk_sys)) then
753

754 755 756 757
            -- Read of last word, but no new commit
            if ((read_increment = '1') and (read_frame_counter = 1)) then
                if (commit_rx_frame = '0') then
                    message_count           <= message_count - 1;
758 759
                end if;

760 761 762 763
            -- Commit of new frame
            elsif (commit_rx_frame = '1') then
                message_count               <= message_count + 1;
            end if;
764 765 766

        end if;
    end process;
767
    
768 769 770 771 772

    ----------------------------------------------------------------------------
    -- Commit RX Frame when last word was written and overrun did not occur!
    -- This can be either from "rxb_store_data" state or "rxb_store_end_ts_high"
    ----------------------------------------------------------------------------
773
    commit_proc : process(res_n, clk_sys, drv_erase_rx)
774
    begin
775
        if (res_n = ACT_RESET or drv_erase_rx = '1') then
776 777
            commit_rx_frame       <= '0';
            commit_overrun_abort  <= '0';
778 779 780 781

        elsif (rising_edge(clk_sys)) then

            if (((rec_message_valid = '1' and drv_rtsopt = RTS_BEG) or
782
                 (store_extra_ts_end = '1')))
783
            then
784 785 786 787 788
                if (data_overrun_int = '0') then
                    commit_rx_frame         <= '1';
                else
                    commit_overrun_abort    <= '1';
                end if;
789
            else
790 791
                commit_rx_frame             <= '0';
                commit_overrun_abort        <= '0';
792 793 794 795 796 797 798 799 800 801 802
            end if;

        end if;
    end process;


    ----------------------------------------------------------------------------
    -- Calculation of data overrun flag. If FSM would like to write to the
    -- memory, and there is not enough free space, data overrun flag will be
    -- set, and no further writes will be executed.
    ----------------------------------------------------------------------------
803
    dor_proc : process(res_n, clk_sys, drv_erase_rx)
804 805 806 807 808 809 810 811 812 813
    begin
        if (res_n = ACT_RESET or drv_erase_rx = '1') then
            data_overrun_r      <= '0';
            data_overrun_int    <= '0';

        elsif (rising_edge(clk_sys)) then

            --------------------------------------------------------------------
            -- Internal Data overrun flag -> cleared by new frame!
            --------------------------------------------------------------------
814
            if (reset_overrun_flag = '1') then
815 816 817 818 819 820 821 822 823 824 825 826 827
                data_overrun_int    <= '0';

            elsif (overrun_condition) then
                data_overrun_int    <= '1';
            else
                data_overrun_int    <= data_overrun_int;
            end if;

            --------------------------------------------------------------------
            -- SW overrun flag -> Cleared from SW!
            --------------------------------------------------------------------
            if (drv_clr_ovr = '1') then
                data_overrun_r  <= '0';
828
 
829 830 831 832 833 834 835 836 837 838 839
            elsif (overrun_condition) then
                data_overrun_r  <= '1';
            else
                data_overrun_r  <= data_overrun_r;
            end if;

        end if;
    end process;


    ----------------------------------------------------------------------------
840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859
    -- RAM Memory of RX Buffer
    ----------------------------------------------------------------------------
    rx_buf_RAM : inf_RAM_wrapper 
    generic map (
        word_width           => 32,
        depth                => buff_size,
        address_width        => RAM_write_address'length,
        reset_polarity       => ACT_RESET,
        simulation_reset     => true,
        sync_read            => true
    )
    port map(
        clk_sys              => clk_sys,
        res_n                => res_n,
        addr_A               => RAM_write_address,
        write                => RAM_write, 
        data_in              => memory_write_data,
        addr_B               => RAM_read_address,
        data_out             => RAM_data_out
    );
860

861
    -- Memory written either on regular write or Extra timestamp write
862 863
    RAM_write           <= '1' when (write_raw_OK = '1' or write_extra_ts = '1')
                               else
864
                           '0';
865

866 867 868
    -- Write address is given by write pointer
    RAM_write_address   <= std_logic_vector(to_unsigned(
                            memory_write_pointer, RAM_write_address'length));
869

870

871 872 873 874 875 876 877 878
    ----------------------------------------------------------------------------
    -- RAM read address is given by read pointers. If no transaction for read
    -- of RX DATA is in progress, read pointer is given by its real value.
    -- During transaction, Incremented Read pointer is chosen to avoid one clock
    -- cycle delay caused by increment on read pointer!
    ----------------------------------------------------------------------------
   RAM_read_address <= std_logic_vector(to_unsigned(
                        read_pointer_inc_1, RAM_read_address'length))
879
                       when (read_increment = '1') else
880 881
                       std_logic_vector(to_unsigned(
                        read_pointer, RAM_read_address'length));
882

883 884 885 886 887 888

    ----------------------------------------------------------------------------
    ----------------------------------------------------------------------------
    -- Assertions
    ----------------------------------------------------------------------------
    ----------------------------------------------------------------------------
889

890

891 892 893 894 895 896 897 898 899 900 901 902 903 904
    ----------------------------------------------------------------------------
    -- RX Buffer size can be only powers of 2. Since modulo arithmetics is used
    -- on memory pointers, using non power of 2 value would result in increased
    -- logic usage!
    ----------------------------------------------------------------------------
    assert ((buff_size = 32) or
            (buff_size = 64) or
            (buff_size = 128) or
            (buff_size = 256) or
            (buff_size = 512) or
            (buff_size = 1024) or
            (buff_size = 2048) or
            (buff_size = 4096))
    report "Unsupported RX Buffer size! RX Buffer must be power of 2!"
905
        severity failure;
906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924


    ----------------------------------------------------------------------------
    -- Storing sequence is like so:
    --  1. Store metadata.
    --  2. Store data "n" times, n = ceil(data_length / 4). De-facto RWCNT field
    --     contains number of remaining words (apart from FRAME_FORMAT_W). Thus,
    --     RWCNT - 3 = number of expected data words.
    --  3. Get "rec_abort" or "rec_message_valid" command.
    --
    --  This process verifies that "rec_data" command comes expected number of
    --  times (RWCNT - 3). This verifies consistency of storing protocol by
    --  CAN Core, as well as RWCNT field! 
    ----------------------------------------------------------------------------
    rwcnt_assert_proc : process(clk_sys)
        variable exp_data_stores    : natural := 0;
        variable act_data_stores   : natural := 0;
    begin
        -- pragma translate_off
925
        if (rising_edge(clk_sys) and now /= 0 fs) then
926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958

            -- Calculate number of expected "store_data" commands from CAN Core.
            if (rec_abort = '1') then
                exp_data_stores := 0;
                act_data_stores := 0;

            elsif (store_metadata = '1') then

                exp_data_stores := to_integer(unsigned(
                                    frame_form_w(RWCNT_H downto RWCNT_L))) - 3;
                act_data_stores := 0;
            end if;

            -- Count actual number of "store_data" commands.
            if (store_data = '1') then
                act_data_stores := act_data_stores + 1;
            end if;

            -- Check when frame was received that proper number of "store_data"
            -- commands did arrive.
            if (rec_message_valid = '1' and 
                act_data_stores /= exp_data_stores)
            then
                report "'store_data' count corrupted by CAN Core! " &
                       "Expected: " & integer'image(exp_data_stores) &
                       "  Actual: " & integer'image(act_data_stores)
                severity error;
            end if;
        end if;
        -- pragma translate_on
    end process;

end architecture;