sanity_test.vhd 40.7 KB
Newer Older
Ille, Ondrej, Ing.'s avatar
Ille, Ondrej, Ing. committed
1
--------------------------------------------------------------------------------
Martin Jeřábek's avatar
Martin Jeřábek committed
2
--
Ille, Ondrej, Ing.'s avatar
Ille, Ondrej, Ing. committed
3 4
-- CTU CAN FD IP Core
-- Copyright (C) 2015-2018 Ondrej Ille <ondrej.ille@gmail.com>
Martin Jeřábek's avatar
Martin Jeřábek committed
5 6
--
-- Project advisors and co-authors:
Ille, Ondrej, Ing.'s avatar
Ille, Ondrej, Ing. committed
7 8 9 10 11 12
-- 	Jiri Novak <jnovak@fel.cvut.cz>
-- 	Pavel Pisa <pisa@cmp.felk.cvut.cz>
-- 	Martin Jerabek <jerabma7@fel.cvut.cz>
-- Department of Measurement         (http://meas.fel.cvut.cz/)
-- Faculty of Electrical Engineering (http://www.fel.cvut.cz)
-- Czech Technical University        (http://www.cvut.cz/)
Martin Jeřábek's avatar
Martin Jeřábek committed
13 14 15 16 17 18
--
-- 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
19
-- Component is furnished to do so, subject to the following conditions:
Martin Jeřábek's avatar
Martin Jeřábek committed
20 21
--
-- The above copyright notice and this permission notice shall be included in
Ille, Ondrej, Ing.'s avatar
Ille, Ondrej, Ing. committed
22
-- all copies or substantial portions of the Component.
Martin Jeřábek's avatar
Martin Jeřábek committed
23 24 25 26 27
--
-- 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
Ille, Ondrej, Ing.'s avatar
Ille, Ondrej, Ing. committed
28
-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
Martin Jeřábek's avatar
Martin Jeřábek committed
29
-- FROM, OUT OF OR IN CONNECTION WITH THE COMPONENT OR THE USE OR OTHER DEALINGS
Ille, Ondrej, Ing.'s avatar
Ille, Ondrej, Ing. committed
30
-- IN THE COMPONENT.
Martin Jeřábek's avatar
Martin Jeřábek committed
31 32 33
--
-- 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
Ille, Ondrej, Ing.'s avatar
Ille, Ondrej, Ing. committed
34
-- protocol license from Bosch.
Martin Jeřábek's avatar
Martin Jeřábek committed
35
--
Ille, Ondrej, Ing.'s avatar
Ille, Ondrej, Ing. committed
36 37 38 39 40 41 42 43 44
--------------------------------------------------------------------------------

--------------------------------------------------------------------------------
-- Purpose:
--  Sanity test simulates real bus operation with 4 CTU CAN FD Cores connected
--  on CAN Bus. Real bus topology with signal delay is implemented via
--  "signalDelayer". Random bit noise is inserted to the bus simulation.
--  Each node is clocked with different clock, to cover clock jitter and clock
--  uncertainty of real bus controllers!
Martin Jeřábek's avatar
Martin Jeřábek committed
45
--
Ille, Ondrej, Ing.'s avatar
Ille, Ondrej, Ing. committed
46 47 48 49
--------------------------------------------------------------------------------
-- Revision History:
--
--    7.7.2016   Created file
Martin Jeřábek's avatar
Martin Jeřábek committed
50 51 52
--    23.9.2017  Added bugfix for proper identifier correction. Identifier
--               layout change from 13.1.2017 caused that identifier correction
--               did not avoid collisions due to assumption of old identifier
Ille, Ondrej, Ing.'s avatar
Ille, Ondrej, Ing. committed
53
--               layout.
Martin Jeřábek's avatar
Martin Jeřábek committed
54 55
--    09.2.2018  Added support fow RWCNT field in the SW_CAN_Frame. RWCNT is
--               stored also to TX Memory. Thus when read on RX side, it should
Ille, Ondrej, Ing.'s avatar
Ille, Ondrej, Ing. committed
56 57 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 88
--               match the calculated value on TX.
--    17.2.2018  1. Modified to support prioritized version of TXT Buffers.
--               2. Added TXT frame counter
--------------------------------------------------------------------------------


Library ieee;
USE IEEE.std_logic_1164.all;
USE IEEE.numeric_std.ALL;
USE ieee.math_real.ALL;

use work.CANconstants.all;
use work.CANcomponents.ALL;
USE work.CANtestLib.All;
USE work.randomLib.All;

use work.CAN_FD_register_map.all;
use work.CAN_FD_frame_format.all;

entity sanity_test is
  port (

    -- Input trigger, test starts running when true
    signal run              :in     boolean;

    -- Number of iterations that test should do
    signal iterations       :in     natural;

    -- Logging level, severity which should be shown
    signal log_level        :in     log_lvl_type;

    -- Test behaviour when error occurs: Quit, or Go on
    signal error_beh        :in     err_beh_type;
Martin Jeřábek's avatar
Martin Jeřábek committed
89 90

    -- Error tolerance, error counter should not exceed this value in order
Ille, Ondrej, Ing.'s avatar
Ille, Ondrej, Ing. committed
91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120
    -- for the test to pass
    signal error_tol        :in     natural;

    -- Status of the test
    signal status           :out    test_status_type;

    -- Amount of errors which appeared in the test
    signal errors           :out    natural ;
    --TODO: Error log results

    ----------------------------------------------
    -- Test configuration
    ----------------------------------------------

    -- Uncertainties of each clock (in ppm)
    signal epsilon_v        :       epsilon_type;

    -- Transceiver delay parameters
    signal trv_del_v        :       trv_del_type;

    -- Configuration of bus topology
    signal bus_matrix       :       bus_matrix_type;

    -- Number of iterations in Gauss distribution calculation
    signal iter_am          :       natural := 40;

    -- Noise pulse width mean in nanaoseconds
    signal nw_mean          :       real;

    -- Noise pulse width variance
Martin Jeřábek's avatar
Martin Jeřábek committed
121
    signal nw_var           :       real;
Ille, Ondrej, Ing.'s avatar
Ille, Ondrej, Ing. committed
122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155

    -- Gap between two noise pulses mean in nanoseconds
    signal ng_mean          :       real;

    -- Gap variance
    signal ng_var           :       real;

    signal topology         :       string (1 to 50);

    signal timing_config    :       bit_time_config_type
  );
end entity;

architecture behavioral of sanity_test is
    -- Internal test signals
    signal error_ctr        :       natural := 0;
    signal loop_ctr         :       natural := 0;
    signal exit_imm         :       boolean := false;
    signal rand_ctr         :       natural range 0 to 3800 := 0;

    ----------------------------------------------
    ----------------------------------------------
    -- Internal signals
    ----------------------------------------------
    ----------------------------------------------

    -- Bus topology is simulated via delay from each node to each other node ->
    -- Bus matrix is used to store the delays!
    type delay_matrix_type is array(1 to NODE_COUNT, 1 to NODE_COUNT) of time;
    signal delay_matrix : delay_matrix_type;

    -- Memory interfaces
    type mem_bus_arr_type is array (1 to NODE_COUNT) of Avalon_mem_type;
    signal mb_arr : mem_bus_arr_type;
Martin Jeřábek's avatar
Martin Jeřábek committed
156

Ille, Ondrej, Ing.'s avatar
Ille, Ondrej, Ing. committed
157 158
    -- Auxiliarly memory signals used due to no support for connecting
    -- record types to components!
Martin Jeřábek's avatar
Martin Jeřábek committed
159
    type mem_vect_arr_type is
Ille, Ondrej, Ing.'s avatar
Ille, Ondrej, Ing. committed
160 161
        array (1 to NODE_COUNT) of std_logic_vector(31 downto 0);

Martin Jeřábek's avatar
Martin Jeřábek committed
162
    type mem_contr_arr_type is
Ille, Ondrej, Ing.'s avatar
Ille, Ondrej, Ing. committed
163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179
        array (1 to NODE_COUNT) of std_logic;

    type mem_be_arr_type is
        array (1 to NODE_COUNT) of std_logic_vector(3 downto 0);

    type mem_addr_arr_type is
        array (1 to NODE_COUNT) of std_logic_vector(23 downto 0);

    signal mem_aux_data_in      : mem_vect_arr_type :=
                                    (OTHERS => (OTHERS => '0'));

    signal mem_aux_data_out     : mem_vect_arr_type :=
                                    (OTHERS => (OTHERS => '0'));

    signal mem_aux_address      : mem_addr_arr_type :=
                                    (OTHERS => (OTHERS => '0'));

Martin Jeřábek's avatar
Martin Jeřábek committed
180
    signal mem_aux_scs          : mem_contr_arr_type :=
Ille, Ondrej, Ing.'s avatar
Ille, Ondrej, Ing. committed
181 182
                                    (OTHERS => '0');

Martin Jeřábek's avatar
Martin Jeřábek committed
183
    signal mem_aux_swr          : mem_contr_arr_type :=
Ille, Ondrej, Ing.'s avatar
Ille, Ondrej, Ing. committed
184 185 186 187 188 189
                                    (OTHERS => '0');

    signal mem_aux_srd          : mem_contr_arr_type :=
                                    (OTHERS => '0');

    -- By default all accesses are 32 bit!
Martin Jeřábek's avatar
Martin Jeřábek committed
190
    signal mem_aux_sbe          : mem_be_arr_type :=
Ille, Ondrej, Ing.'s avatar
Ille, Ondrej, Ing. committed
191 192 193 194
                                    (OTHERS => (OTHERS => '1'));

    signal mem_aux_clk          : mem_contr_arr_type :=
                                    (OTHERS => '0');
Martin Jeřábek's avatar
Martin Jeřábek committed
195

Ille, Ondrej, Ing.'s avatar
Ille, Ondrej, Ing. committed
196 197 198 199 200 201 202 203 204 205 206 207
    signal res_n_v              : std_logic_vector(1 to NODE_COUNT) :=
                                    (OTHERS => '0');

    signal int_v                : std_logic_vector(1 to NODE_COUNT) :=
                                    (OTHERS => '0');

    signal CAN_tx_v             : std_logic_vector(1 to NODE_COUNT);
    signal CAN_rx_v             : std_logic_vector(1 to NODE_COUNT) :=
                                    (OTHERS => RECESSIVE);

    signal time_quanta_clk_v    : std_logic_vector(1 to NODE_COUNT) :=
                                    (OTHERS => '0');
Martin Jeřábek's avatar
Martin Jeřábek committed
208

Ille, Ondrej, Ing.'s avatar
Ille, Ondrej, Ing. committed
209 210 211 212 213 214 215 216 217 218
    -- Timestamp signals
    type timestamp_arr_type is
        array (1 to NODE_COUNT) of std_logic_vector(63 downto 0);

    signal timestamp_v          : timestamp_arr_type :=
                                    (OTHERS => (OTHERS =>'0'));

    -- Transceiver delay shift registers
    type trv_del_shift_reg is array (1 to NODE_COUNT) of tran_delay_type;

Martin Jeřábek's avatar
Martin Jeřábek committed
219
    signal transciever          : trv_del_shift_reg :=
220
        (OTHERS => ((OTHERS => RECESSIVE), (OTHERS => RECESSIVE), '1', '1'));
Ille, Ondrej, Ing.'s avatar
Ille, Ondrej, Ing. committed
221 222 223 224 225

    -- Bus realisation signals
    type bus_delayed_type is
        array (1 to NODE_COUNT, 1 to NODE_COUNT) of std_logic;

Martin Jeřábek's avatar
Martin Jeřábek committed
226
    signal bus_delayed          : bus_delayed_type :=
Ille, Ondrej, Ing.'s avatar
Ille, Ondrej, Ing. committed
227 228 229 230 231 232 233 234 235 236 237 238
                                    (OTHERS => (OTHERS => RECESSIVE));
    signal bus_clk              : std_logic := '0';

    -- Noise registers
    signal noise_reg            : std_logic_vector (1 to NODE_COUNT) :=
                                    (OTHERS => RECESSIVE);

    signal noise_force          : std_logic_vector (1 to NODE_COUNT) :=
                                    (OTHERS => '0');

    -- Traffic storage memories
    type storage_mem_array      is
239
        array (1 to NODE_COUNT) of test_mem_type;
Ille, Ondrej, Ing.'s avatar
Ille, Ondrej, Ing. committed
240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260

    signal tx_mems              : storage_mem_array :=
                                    (OTHERS => (OTHERS => (OTHERS => '0')));

    signal rx_mems              : storage_mem_array :=
                                    (OTHERS => (OTHERS => (OTHERS => '0')));

    type storage_pointer_array is
        array (1 to NODE_COUNT) of natural;

    signal tx_mem_pointers      : storage_pointer_array := (OTHERS => 0);
    signal rx_mem_pointers      : storage_pointer_array := (OTHERS => 0);

    signal tx_mem_pointers_done : boolean;

    type mem_status_array_type is
        array (1 to NODE_COUNT) of boolean;

    -- Indicator whether traffic storage memories are full
    signal tx_full              : mem_status_array_type := (OTHERS => false);

Martin Jeřábek's avatar
Martin Jeřábek committed
261
    -- Control signals
Ille, Ondrej, Ing.'s avatar
Ille, Ondrej, Ing. committed
262 263 264 265 266 267 268 269 270 271
    type control_bool_array_type is array (1 to NODE_COUNT) of boolean;
    signal do_wait              : control_bool_array_type := (OTHERS => true);
    signal do_config            : control_bool_array_type := (OTHERS => false);
    signal do_traffic           : control_bool_array_type := (OTHERS => false);
    signal do_erase_mems        : control_bool_array_type := (OTHERS => false);
    signal do_read_errors       : control_bool_array_type := (OTHERS => false);
    signal config_done          : control_bool_array_type := (OTHERS => false);
    signal do_restart_mem_if    : control_bool_array_type := (OTHERS => true);
    signal do_noise             : boolean := false;

Martin Jeřábek's avatar
Martin Jeřábek committed
272
    signal erp_detected         : control_bool_array_type := (OTHERS => false);
Ille, Ondrej, Ing.'s avatar
Ille, Ondrej, Ing. committed
273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291
    signal test_desc            : string (1 to 50) :=
        "                                                  ";

    -- Random counters for number generation
    type rand_ctr_array_type is
        array (1 to NODE_COUNT) of natural range 0 to RAND_POOL_SIZE;

    signal rand_ctr_gen         : rand_ctr_array_type;
    signal rand_ident_ctr       : natural range 0 to RAND_POOL_SIZE := 0;

    -- Auxiliarly signal for identifier correction to have similiar identifiers
    -- and interesting arbitration!
    signal common_ident         : natural;

    -- Overall frame counter for the whole test
    type frame_counter_array_type
        is array (1 to NODE_COUNT) of natural;

    -- Frame counters for each node
Martin Jeřábek's avatar
Martin Jeřábek committed
292
    signal frame_counters       : frame_counter_array_type;
Ille, Ondrej, Ing.'s avatar
Ille, Ondrej, Ing. committed
293 294 295 296 297 298 299 300 301

    -- Frame counter for all frames on the bus
    signal overal_frame_counter : natural;

    ----------------------------------------------
    ----------------------------------------------
    -- Test procedures and functions
    ----------------------------------------------
    ----------------------------------------------
Martin Jeřábek's avatar
Martin Jeřábek committed
302 303


Ille, Ondrej, Ing.'s avatar
Ille, Ondrej, Ing. committed
304 305 306 307 308 309 310 311 312 313 314 315 316 317
  ------------------------------------------------------------------------------
  -- Check if all frames from TX memory are found in RX memory
  ------------------------------------------------------------------------------
    procedure check_memories(
        signal tx_mems          :  in       storage_mem_array;
        signal rx_mems          :  in       storage_mem_array;
        variable outcome        :  inout    boolean
    )is
        variable tx_r_ptr       :           natural := 0;
        variable rx_r_ptr       :           natural := 0;
        variable TX_frame       :           SW_CAN_frame_type;
        variable RX_frame       :           SW_CAN_frame_type;
        variable comp_out       :           boolean;
        variable detected       :           boolean := false;
318
        variable node_error     :           boolean := false;
319
        variable tmp_mem        :           test_mem_type;
Ille, Ondrej, Ing.'s avatar
Ille, Ondrej, Ing. committed
320 321 322 323 324
    begin
        outcome     := true;
        tx_r_ptr    := 0;
        rx_r_ptr    := 0;

Martin Jeřábek's avatar
Martin Jeřábek committed
325 326
        -- Now we check that content of each TX memory is located in each RX
        -- memory except the one with the same index (node does not recieve its
Ille, Ondrej, Ing.'s avatar
Ille, Ondrej, Ing. committed
327 328 329
        -- own frames)!
        for i in 1 to NODE_COUNT loop

330
            node_error := false;
Ille, Ondrej, Ing.'s avatar
Ille, Ondrej, Ing. committed
331
            tx_r_ptr := 0;
332

Ille, Ondrej, Ing.'s avatar
Ille, Ondrej, Ing. committed
333 334 335 336
            for j in 1 to NODE_COUNT loop

                if (i /= j) then
                    rx_r_ptr := 0;
Martin Jeřábek's avatar
Martin Jeřábek committed
337
                    -- Detect frame based on TBF bit which is always 1. If
Ille, Ondrej, Ing.'s avatar
Ille, Ondrej, Ing. committed
338 339
                    -- this bit is set we assume frame is there. We have to
                    -- keep policy of erasing the memory properly then!
Martin Jeřábek's avatar
Martin Jeřábek committed
340
                    while (tx_mems(i)(tx_r_ptr)(8) = '1') loop
Ille, Ondrej, Ing.'s avatar
Ille, Ondrej, Ing. committed
341 342

                        -- Read frame from TX Mem
343 344
                        tmp_mem := tx_mems(i);
                        read_frame_from_test_mem(TX_frame, tmp_mem, tx_r_ptr);
Ille, Ondrej, Ing.'s avatar
Ille, Ondrej, Ing. committed
345 346 347 348 349 350 351 352 353 354

                        -- Now browse trough the RX mem j and check if we find
                        -- his frame. Set "comp_out" if frame was found.
                        rx_r_ptr := 0;
                        comp_out := false;
                        detected := false;

                        while (rx_mems(j)(rx_r_ptr)(8) = '1' and
                               comp_out = false)
                        loop
355 356
                            tmp_mem := rx_mems(j);
                            read_frame_from_test_mem(RX_frame, tmp_mem, rx_r_ptr);
Ille, Ondrej, Ing.'s avatar
Ille, Ondrej, Ing. committed
357 358 359 360 361 362 363 364
                            CAN_compare_frames(TX_frame, RX_frame, false, comp_out);
                            if (comp_out) then
                                detected := true;
                            end if;
                        end loop;

                        if (detected = false) then
                            outcome:= false;
365
                            node_error := true;
Ille, Ondrej, Ing.'s avatar
Ille, Ondrej, Ing. committed
366 367 368 369
                        end if;
                    end loop;
                end if;
            end loop;
370 371 372 373 374 375 376 377

            -- Print contents of test memories for each node if something
            -- went wrong!
            if (node_error) then
                tx_r_ptr := 0;
                log("TX Memory Node " & integer'image(i) & ":",
                    error_l, log_level);
                while (tx_mems(i)(tx_r_ptr)(8) = '1') loop
378 379
                    tmp_mem := tx_mems(i);
                    read_frame_from_test_mem(TX_frame, tmp_mem, tx_r_ptr);
380 381 382 383 384 385 386
                    CAN_print_frame(TX_frame, error_l);
                end loop;

                log("RX Memory Node " & integer'image(i) & ":",
                    error_l, log_level);
                rx_r_ptr := 0;
                while (rx_mems(i)(rx_r_ptr)(8) = '1') loop
387 388
                    tmp_mem := rx_mems(i);
                    read_frame_from_test_mem(RX_frame, tmp_mem, rx_r_ptr);
389 390 391 392
                    CAN_print_frame(RX_frame, error_l);
                end loop;
            end if;

Ille, Ondrej, Ing.'s avatar
Ille, Ondrej, Ing. committed
393 394
        end loop;
    end procedure;
Martin Jeřábek's avatar
Martin Jeřábek committed
395 396


Ille, Ondrej, Ing.'s avatar
Ille, Ondrej, Ing. committed
397
    ----------------------------------------------------------------------------
Martin Jeřábek's avatar
Martin Jeřábek committed
398
    -- To avoid collisions, we have to make sure that we have different IDs.
Ille, Ondrej, Ing.'s avatar
Ille, Ondrej, Ing. committed
399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416
    -- So we set last 3 bits to unsigned value of the controller index.
    -- Additionally we modify the identifiers to have first N bits matching
    -- (N is random), so that arbitration is lost in random bit. With absolutely
    -- random identifiers arbitration is usually lost very soon (first 3 bits).
    ----------------------------------------------------------------------------
    procedure correct_identifiers(
        signal   rand_ctr       : inout     natural range 0 to RAND_POOL_SIZE;
        variable frame          : inout     SW_CAN_frame_type;
        constant index          : in        natural;
        signal   com_id         : in        natural
    )is
        variable aux_vect       :           std_logic_vector(28 downto 0);
        variable aux_common     :           std_logic_vector(28 downto 0);
        variable rand_val       :           real;
        variable rand_index     :           natural;
    begin
        ------------------------------------------------------------------------
        -- Correct first bits to have interesting arbitration...
Martin Jeřábek's avatar
Martin Jeřábek committed
417
        -- Correct the last bits to avoid collisions
Ille, Ondrej, Ing.'s avatar
Ille, Ondrej, Ing. committed
418 419 420
        ------------------------------------------------------------------------
        rand_real_v(rand_ctr, rand_val);
        aux_common := std_logic_vector(to_unsigned(com_id, 29));
Martin Jeřábek's avatar
Martin Jeřábek committed
421

Ille, Ondrej, Ing.'s avatar
Ille, Ondrej, Ing. committed
422 423 424
        if (frame.ident_type = EXTENDED) then
            rand_index := integer(25.0 * rand_val);
            aux_vect   := std_logic_vector(to_unsigned(frame.identifier, 29));
Martin Jeřábek's avatar
Martin Jeřábek committed
425
            aux_vect (28 downto 28 - rand_index) :=
Ille, Ondrej, Ing.'s avatar
Ille, Ondrej, Ing. committed
426 427 428 429 430
                        aux_common(28 downto 28 - rand_index);
        else
            rand_index := integer(7.0 * rand_val);
            aux_vect   := "000000000000000000" &
                        std_logic_vector(to_unsigned(frame.identifier, 11));
Martin Jeřábek's avatar
Martin Jeřábek committed
431
            aux_vect (10 downto 10 - rand_index) :=
Ille, Ondrej, Ing.'s avatar
Ille, Ondrej, Ing. committed
432 433 434 435 436
                        aux_common(28 downto 28 - rand_index);
        end if;
        aux_vect (2 downto 0)   := std_logic_vector(to_unsigned(index, 3));
        frame.identifier        := to_integer(unsigned(aux_vect));
    end procedure;
Martin Jeřábek's avatar
Martin Jeřábek committed
437

Ille, Ondrej, Ing.'s avatar
Ille, Ondrej, Ing. committed
438 439 440 441 442 443 444 445 446 447 448

    procedure restart_mem_bus(
        signal mem_bus          : out       Avalon_mem_type
    )is
    begin
        mem_bus.scs         <= '0';
        mem_bus.swr         <= '0';
        mem_bus.srd         <= '0';
        mem_bus.address     <= (OTHERS => '0');
        mem_bus.data_in     <= (OTHERS => '0');
        mem_bus.data_out    <= (OTHERS => 'Z');
Martin Jeřábek's avatar
Martin Jeřábek committed
449
        mem_bus.clk_sys     <= 'Z';
Ille, Ondrej, Ing.'s avatar
Ille, Ondrej, Ing. committed
450 451 452 453 454 455
    end procedure;

    function bus_matrix_to_delay(signal bm : in real) return time is
    begin
        return 10.0 * bm * 500 ps;
    end function;
Martin Jeřábek's avatar
Martin Jeřábek committed
456

457 458 459
    type tr_del_t is array (1 to NODE_COUNT) of time;
    signal tr_del : tr_del_t;
    signal tr_tx_and_rx : std_logic_vector(1 to NODE_COUNT);
Ille, Ondrej, Ing.'s avatar
Ille, Ondrej, Ing. committed
460
begin
Martin Jeřábek's avatar
Martin Jeřábek committed
461

Ille, Ondrej, Ing.'s avatar
Ille, Ondrej, Ing. committed
462 463 464 465
    ----------------------------------------------------------------------------
    -- CAN Nodes instances
    ----------------------------------------------------------------------------
    comp_gen : for i in 1 to NODE_COUNT generate
Martin Jeřábek's avatar
Martin Jeřábek committed
466
        node_1_comp : CAN_top_level
Ille, Ondrej, Ing.'s avatar
Ille, Ondrej, Ing. committed
467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497
        generic map(
             use_logger       => true,
             rx_buffer_size   => 64,
             use_sync         => true,
             ID               => i,
             logger_size      => 16
        )
        port map(
             res_n            => res_n_v(i),
             clk_sys          => mem_aux_clk(i),
             data_in          => mem_aux_data_in(i),
             data_out         => mem_aux_data_out(i),
             adress           => mem_aux_address(i),
          	 scs              => mem_aux_scs(i),
             srd              => mem_aux_srd(i),
             swr              => mem_aux_swr(i),
             sbe              => mem_aux_sbe(i),
             int              => int_v(i),
             CAN_tx           => CAN_tx_v(i),
             CAN_rx           => CAN_rx_v(i),
             time_quanta_clk  => time_quanta_clk_v(i),
             timestamp        => timestamp_v(i)
        );

        mb_arr(i).clk_sys       <=  mem_aux_clk(i);
        mem_aux_data_in(i)      <=  mb_arr(i).data_in;
        mem_aux_address(i)      <=  mb_arr(i).address;
        mem_aux_scs(i)          <=  mb_arr(i).scs;
        mem_aux_swr(i)          <=  mb_arr(i).swr;
        mem_aux_srd(i)          <=  mb_arr(i).srd;
        mb_arr(i).data_out      <=  mem_aux_data_out(i);
Martin Jeřábek's avatar
Martin Jeřábek committed
498 499 500
    end generate comp_gen;


Ille, Ondrej, Ing.'s avatar
Ille, Ondrej, Ing. committed
501 502 503 504 505 506 507 508 509 510 511 512 513

    ----------------------------------------------------------------------------
    -- Clock generation
    ----------------------------------------------------------------------------
    clock_generic : for i in 1 to NODE_COUNT generate
        clock_gen_1 : process
            constant period   : natural := f100_Mhz;
            constant duty     : natural := 50;
            variable epsilon  : natural;
        begin
          epsilon := epsilon_v(i);
          generate_clock(period, duty, epsilon, mem_aux_clk(i));
          timestamp_v(i) <= std_logic_vector(unsigned(timestamp_v(i)) + 1);
Martin Jeřábek's avatar
Martin Jeřábek committed
514
        end process;
Ille, Ondrej, Ing.'s avatar
Ille, Ondrej, Ing. committed
515
    end generate clock_generic;
Martin Jeřábek's avatar
Martin Jeřábek committed
516 517


Ille, Ondrej, Ing.'s avatar
Ille, Ondrej, Ing. committed
518 519 520 521
    ----------------------------------------------------------------------------
    -- Realisation of transciever delay
    ----------------------------------------------------------------------------
    tr_del_gen : for i in 1 to NODE_COUNT generate
522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543
        tr_del(i) <= (trv_del_v(i) / 2 - 2) * f100_mhz * 1 ps
                      when trv_del_v(i)/2 > 1 else
                           trv_del_v(i)/2 * f100_mhz * 1 ps;
        trv_del_gen_tx_delayer : entity work.signal_delayer
            generic map (
                NSAMPLES => 16
            )
            port map (
                input   => CAN_tx_v(i),
                delay   => tr_del(i),
                delayed => transciever(i).tx_point
            );
        tr_tx_and_rx(i) <= (transciever(i).tx_point AND transciever(i).rx_point);
        trv_del_gen_rx_delayer : entity work.signal_delayer
            generic map (
                NSAMPLES => 16
            )
            port map (
                input   => tr_tx_and_rx(i),
                delay   => tr_del(i),
                delayed => CAN_rx_v(i)
            );
Ille, Ondrej, Ing.'s avatar
Ille, Ondrej, Ing. committed
544
    end generate tr_del_gen;
Martin Jeřábek's avatar
Martin Jeřábek committed
545

Ille, Ondrej, Ing.'s avatar
Ille, Ondrej, Ing. committed
546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567

    ----------------------------------------------------------------------------
    -- Bus clock generation
    --
    -- 500 ps equals approximately 10 cm of conductor! This is coarse estimate,
    -- however purpose of this simulation is not to examine exact propagation
    -- delays via different physical channels! This simple estimate is enough.
    ----------------------------------------------------------------------------
    bus_clk_proc : process
    begin
        bus_clk <= '0';
        wait for 250 ps;
        bus_clk <= '1';
        wait for 250 ps;
    end process;


    ----------------------------------------------------------------------------
    -- Realisation of delay on CAN Bus via signal delayer
    ----------------------------------------------------------------------------
    bus_gen_delay_tx : for i in 1 to NODE_COUNT generate
        bus_gen_delay_tx2 : for j in 1 to NODE_COUNT generate
Martin Jeřábek's avatar
Martin Jeřábek committed
568

Ille, Ondrej, Ing.'s avatar
Ille, Ondrej, Ing. committed
569 570
            delay_matrix(j, i) <= bus_matrix_to_delay(bus_matrix(j, i));

571
            i_txdelay : entity work.signal_delayer
Ille, Ondrej, Ing.'s avatar
Ille, Ondrej, Ing. committed
572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594
                generic map (
                    NSAMPLES    => 16
                )
                port map (
                    input       => transciever(i).tx_point,
                    delay       => delay_matrix(j,i),
                    delayed     => bus_delayed(i,j)
                );

        end generate bus_gen_delay_tx2;
    end generate bus_gen_delay_tx;

    ----------------------------------------------------------------------------
    -- Realisation of CAN bus with delayed signals
    ----------------------------------------------------------------------------
    bus_gen : for i in 1 to NODE_COUNT generate
        bus_gen_proc : process
            variable rx_lvl : std_logic := RECESSIVE;
            variable index  : natural   := 0;
        begin
            wait until rising_edge(bus_clk);
            rx_lvl := RECESSIVE;

Martin Jeřábek's avatar
Martin Jeřábek committed
595
            -- In one recieving node iterate trough all nodes
Ille, Ondrej, Ing.'s avatar
Ille, Ondrej, Ing. committed
596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636
            -- and AND all delayed signals.
            for j in 1 to NODE_COUNT loop
                rx_lvl := rx_lvl AND bus_delayed(j, i);
            end loop;

            -- Now add the Generated noise to the recieving node
            if (noise_force(i) = '1') then
                rx_lvl := noise_reg(i);
            end if;

            transciever(i).rx_point <= rx_lvl;
        end process;
    end generate bus_gen;

    ----------------------------------------------------------------------------
    -- Noise generator
    ----------------------------------------------------------------------------
    noise_gen_proc:process
        variable noise_time : real := 0.0;
        variable noise_gap  : real := 0.0;
        variable aux        : std_logic_vector(3 downto 0);
        variable gaus_par   : rand_distribution_par_type;
        variable exp_par    : rand_distribution_par_type;
    begin
        if (do_noise) then

            -- Generate noise pulse with gauss distribution
            gaus_par(GAUSS_iterations)  := real(iter_am);
            gaus_par(GAUSS_mean)        := nw_mean;
            gaus_par(GAUSS_variance)    := nw_var;
            rand_real_distr_v(rand_ctr, noise_time, GAUSS, gaus_par);

            -- Generate noise pulse gap with exponential distribution
            exp_par(EXPONENTIAL_mean)   := ng_mean;
            rand_real_distr_v(rand_ctr, noise_gap, EXPONENTIAL, exp_par);

            noise_force <= (OTHERS => '0');
            wait for integer(noise_gap) * 1 ns;

            --Generate noise polarity and info whether noise
            -- should be forced to the node
Martin Jeřábek's avatar
Martin Jeřábek committed
637
            -- We cant put noise to all. That would be global
Ille, Ondrej, Ing.'s avatar
Ille, Ondrej, Ing. committed
638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663
            -- error at all times
            rand_logic_vect_v(rand_ctr ,aux,0.5);
            noise_reg   <= aux;
            rand_logic_vect_v(rand_ctr ,aux,0.5);
            noise_force <= aux;

            wait for integer(noise_time) * 1 ns;

        else
            wait for 10 ns;
        end if;
    end process;

    ----------------------------------------------------------------------------
    -- Common identifier generation we have to set some common base for
    -- identifiers to have interesting arbitration...
    ----------------------------------------------------------------------------
    ident_gen_proc : process
        variable rand_value : real := 0.0;
    begin
        for i in 0 to 100 loop
          wait until rising_edge(mb_arr(1).clk_sys);
        end loop;
        rand_real_v(rand_ident_ctr, rand_value);
        common_ident <= integer(rand_value * 536870911.0);
    end process;
Martin Jeřábek's avatar
Martin Jeřábek committed
664 665


Ille, Ondrej, Ing.'s avatar
Ille, Ondrej, Ing. committed
666 667 668 669 670
    ----------------------------------------------------------------------------
    -- Calculation of frame counter
    ----------------------------------------------------------------------------
    overal_frame_counter <= (frame_counters(1) + frame_counters(2) +
                             frame_counters(3) + frame_counters(4)) / 3;
Martin Jeřábek's avatar
Martin Jeřábek committed
671 672


Ille, Ondrej, Ing.'s avatar
Ille, Ondrej, Ing. committed
673 674 675 676 677 678 679 680 681 682 683 684 685 686
    ------------------------------------------------------------------------------
    -- Node access - Traffic generation and error states
    ------------------------------------------------------------------------------
    access_gen : for i in 1 to NODE_COUNT generate

        node_access_proc:process
            variable rand_real      :       real;
            variable TX_frame       :       SW_CAN_frame_type;
            variable RX_frame       :       SW_CAN_frame_type;
            variable r_data         :       std_logic_vector(31 downto 0);
            variable n_index        :       natural := i;
            variable frame_sent     :       boolean := false;
            variable used_txtb      :       natural := 1;
            variable txtb_state     :       SW_TXT_Buffer_state_type;
687 688
            variable rx_buf_state   :       SW_RX_Buffer_info;
            variable fault_state    :       SW_fault_state;
Ille, Ondrej, Ing.'s avatar
Ille, Ondrej, Ing. committed
689 690 691 692
        begin
            if (do_restart_mem_if(i)) then
                restart_mem_bus(mb_arr(i));
                wait for 10 ns;
Martin Jeřábek's avatar
Martin Jeřábek committed
693

Ille, Ondrej, Ing.'s avatar
Ille, Ondrej, Ing. committed
694 695 696 697 698 699 700 701 702 703 704 705 706 707
            elsif (do_wait(i)) then
                wait until rising_edge(mb_arr(i).clk_sys);

            elsif (do_erase_mems(i)) then
                tx_mems(i)          <= (OTHERS => (OTHERS => '0'));
                rx_mems(i)          <= (OTHERS => (OTHERS => '0'));
                tx_mem_pointers(i)  <= 0;
                rx_mem_pointers(i)  <= 0;
                erp_detected(i)     <= false;
                wait for 10 ns;
            else
                if (do_config(i)) then

                    config_done (i) <= false;
Martin Jeřábek's avatar
Martin Jeřábek committed
708

Ille, Ondrej, Ing.'s avatar
Ille, Ondrej, Ing. committed
709 710
                    -- Perform the configuration of the node
                    CAN_turn_controller(true, n_index, mb_arr(i));
Martin Jeřábek's avatar
Martin Jeřábek committed
711
                    CAN_configure_timing(timing_config, n_index, mb_arr(i));
Ille, Ondrej, Ing.'s avatar
Ille, Ondrej, Ing. committed
712 713 714 715

                    -- Signal back to main process config finished
                    config_done(i)  <= true;
                    wait for 100 ns;
Martin Jeřábek's avatar
Martin Jeřábek committed
716

Ille, Ondrej, Ing.'s avatar
Ille, Ondrej, Ing. committed
717 718 719
                else
                    if (do_traffic(i)) then

Martin Jeřábek's avatar
Martin Jeřábek committed
720
                        -- Check if first TXT Buffer is Empty or previous
Ille, Ondrej, Ing.'s avatar
Ille, Ondrej, Ing. committed
721 722 723 724 725 726
                        -- transmission was Done...
                        get_tx_buf_state(used_txtb, txtb_state, n_index,
                                         mb_arr(i));

                        -- Send frame if yes...
                        if (txtb_state = buf_empty or txtb_state = buf_done) then
Martin Jeřábek's avatar
Martin Jeřábek committed
727

Ille, Ondrej, Ing.'s avatar
Ille, Ondrej, Ing. committed
728 729 730
                            -- Generate and transmitt frames until TX memory
                            -- of given node is full.
                            if (not tx_full(i)) then
Martin Jeřábek's avatar
Martin Jeřábek committed
731

Ille, Ondrej, Ing.'s avatar
Ille, Ondrej, Ing. committed
732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749
                                -- To avoid having the same frames from all nodes
                                -- we modify "rand_counter" by index of node
                                if (rand_ctr_gen(i) + i > RAND_POOL_SIZE) then
                                    rand_ctr_gen(i) <= 0;
                                else
                                    rand_ctr_gen(i) <= rand_ctr_gen(i) + i;
                                end if;
                                wait for 0 ns;
                                CAN_generate_frame(rand_ctr_gen(i), TX_frame);

                                -- Now we have absolutely RANDOM identifiers
                                -- To avoid collisions we correct them to have
                                -- unique endings...
                                correct_identifiers(rand_ctr_gen(i),
                                                    TX_frame, i, common_ident);

                                -- Finally insert the frame for transmission
                                -- and also to test memories!
Martin Jeřábek's avatar
Martin Jeřábek committed
750
                                CAN_send_frame(TX_frame, 1, n_index, mb_arr(i),
Ille, Ondrej, Ing.'s avatar
Ille, Ondrej, Ing. committed
751 752
                                               frame_sent);

753 754
                                store_frame_to_test_mem(TX_frame, tx_mems(i),
                                                        tx_mem_pointers(i));
Ille, Ondrej, Ing.'s avatar
Ille, Ondrej, Ing. committed
755 756 757 758
                            end if;
                        end if;

                        -- Check if RX buffer is non-empty and read frames if not!
759 760
                        get_rx_buf_state(rx_buf_state, n_index, mb_arr(i));
                        while (rx_buf_state.rx_empty = false) loop
Ille, Ondrej, Ing.'s avatar
Ille, Ondrej, Ing. committed
761
                            CAN_read_frame(RX_frame, n_index, mb_arr(i));
762 763
                            store_frame_to_test_mem(RX_frame, rx_mems(i),
                                                    rx_mem_pointers(i));
764

Martin Jeřábek's avatar
Martin Jeřábek committed
765
                            get_rx_buf_state(rx_buf_state, n_index, mb_arr(i));
Ille, Ondrej, Ing.'s avatar
Ille, Ondrej, Ing. committed
766 767 768 769 770 771 772

                            -- Count the received frames
                            frame_counters(i) <= frame_counters(i) + 1;
                        end loop;

                    end if;

Martin Jeřábek's avatar
Martin Jeřábek committed
773
                    -- Check if unit is not error passive. If node is error
Ille, Ondrej, Ing.'s avatar
Ille, Ondrej, Ing. committed
774 775
                    -- passive data consitency will be corrupted!!!
                    -- That should never happend !!!
Martin Jeřábek's avatar
Martin Jeřábek committed
776 777
                    if (do_read_errors(n_index)) then
                        get_fault_state(fault_state, n_index, mb_arr(i));
778
                        if (fault_state /= fc_error_active) then
Ille, Ondrej, Ing.'s avatar
Ille, Ondrej, Ing. committed
779 780 781 782
                            erp_detected(i) <= true;
                        end if;
                    end if;
                end if;
Martin Jeřábek's avatar
Martin Jeřábek committed
783
            end if;
Ille, Ondrej, Ing.'s avatar
Ille, Ondrej, Ing. committed
784 785 786 787 788 789 790
        end process;

        ----------------------------------------------
        -- Memory statuses
        ----------------------------------------------
        -- Note that we keep reserve of up to 60 words, thats
        -- exactly how much we need to fit 3 times longest frame...
Martin Jeřábek's avatar
Martin Jeřábek committed
791
        tx_full(i) <= true when
Ille, Ondrej, Ing.'s avatar
Ille, Ondrej, Ing. committed
792 793 794
                           tx_mem_pointers(i) + 245 >= tx_mems(i)'length
                           else
                      false;
Martin Jeřábek's avatar
Martin Jeřábek committed
795

Ille, Ondrej, Ing.'s avatar
Ille, Ondrej, Ing. committed
796 797 798 799
    end generate access_gen;


    tx_mem_pointers_done <= true when
Martin Jeřábek's avatar
Martin Jeřábek committed
800
                                    ((tx_mem_pointers(1) +
Ille, Ondrej, Ing.'s avatar
Ille, Ondrej, Ing. committed
801
                                      tx_mem_pointers(2) +
Martin Jeřábek's avatar
Martin Jeřábek committed
802 803
                                      tx_mem_pointers(3)) =
                                     rx_mem_pointers(4))
Ille, Ondrej, Ing.'s avatar
Ille, Ondrej, Ing. committed
804 805 806 807 808
                                    and
                                    ((tx_mem_pointers(2) +
                                      tx_mem_pointers(3) +
                                      tx_mem_pointers(4)) =
                                     rx_mem_pointers(1))
Martin Jeřábek's avatar
Martin Jeřábek committed
809
                                    and
Ille, Ondrej, Ing.'s avatar
Ille, Ondrej, Ing. committed
810 811 812 813 814 815 816 817 818 819
                                    ((tx_mem_pointers(3) +
                                      tx_mem_pointers(4) +
                                      tx_mem_pointers(1)) =
                                     rx_mem_pointers(2))
                                    and
                                    ((tx_mem_pointers(1) +
                                      tx_mem_pointers(2) +
                                      tx_mem_pointers(4)) =
                                     rx_mem_pointers(3))
                                else
Martin Jeřábek's avatar
Martin Jeřábek committed
820 821
                            false;

Ille, Ondrej, Ing.'s avatar
Ille, Ondrej, Ing. committed
822 823 824 825 826 827 828 829 830

    ----------------------------------------------------------------------------
    -- Main test process
    ----------------------------------------------------------------------------
    test_proc : process
        variable outcome    : boolean  := true;
        variable step_done  : boolean  := false;
    begin
        print_test_info(iterations, log_level, error_beh, error_tol);
Martin Jeřábek's avatar
Martin Jeřábek committed
831
        -- TODO: print sanity test params
Ille, Ondrej, Ing.'s avatar
Ille, Ondrej, Ing. committed
832 833

        wait for 5 ns;
Martin Jeřábek's avatar
Martin Jeřábek committed
834
        do_restart_mem_if <= (OTHERS => false);
Ille, Ondrej, Ing.'s avatar
Ille, Ondrej, Ing. committed
835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865
        wait for 5 ns;
        reset_test(res_n_v(1), status, run, error_ctr);
        reset_test(res_n_v(2), status, run, error_ctr);
        reset_test(res_n_v(3), status, run, error_ctr);
        reset_test(res_n_v(4), status, run, error_ctr);
        loop_ctr <= 0;

        -- Deactivate the wait signal
        do_wait <= (OTHERS => false);

        log("Applying Configuration...", info_l, log_level);
        for i in 1 to NODE_COUNT loop
            do_config(i) <= true;
        end loop;

        wait until config_done = (true, true, true, true);
        for i in 1 to NODE_COUNT loop
            do_config(i)      <= false;
            do_read_errors(i) <= true;
        end loop;
        log("Configuration applied", info_l, log_level);

        ------------------------------------------------------------------------
        -- Main loop of the test
        ------------------------------------------------------------------------
        while (loop_ctr < iterations  or  exit_imm) loop
            log("Starting loop nr " & integer'image(loop_ctr),
                info_l, log_level);

            -- Here is a special case when previous step failed.
            -- We need to reset and reconfigure node
Martin Jeřábek's avatar
Martin Jeřábek committed
866
            if (erp_detected(1) or erp_detected(2) or
Ille, Ondrej, Ing.'s avatar
Ille, Ondrej, Ing. committed
867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897
                erp_detected(3) or erp_detected(4))
            then
                res_n_v <= (OTHERS => '0');
                wait for 50 ns;
                res_n_v <= (OTHERS => '1');
                wait for 10 ns;

                do_config <= (OTHERS => true);
                wait for 1000 ns;
                do_config <= (OTHERS => false);
                wait for 10 ns;
            end if;

            -- Erase the test memories
            for i in 1 to NODE_COUNT loop
                do_erase_mems(i) <= true;
            end loop;
            wait for 1000 ns;

            for i in 1 to NODE_COUNT loop
                do_erase_mems(i) <= false;
            end loop;

            -- Start the traffic generation
            for i in 1 to NODE_COUNT loop
                do_traffic(i)     <= true;
                do_noise          <= true;
            end loop;

            wait for 2000 ns;

Martin Jeřábek's avatar
Martin Jeřábek committed
898
            -- Units stop transmiting when they reach tx_full! We wait until
Ille, Ondrej, Ing.'s avatar
Ille, Ondrej, Ing. committed
899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930
            -- everything what was transmitted is also recieved!
            step_done :=false;
            while (step_done = false) loop
                if (tx_mem_pointers_done) then
                  step_done:= true;
                end if;

                -- If any of the nodes turned error passive
                if (erp_detected(1) or erp_detected(2) or
                    erp_detected(3) or erp_detected(4))
                then
                    step_done:= true;
                    report "Some unit turned error passive -> " &
                           "Most probably traffic consitency check will fail!"
                    severity error;
                end if;
                wait for 100 ns;
            end loop;

            -- Stop the traffic generation
            for i in 1 to NODE_COUNT loop
                do_traffic(i)     <= false;
                do_noise          <= false;
            end loop;

            wait for 200 ns;

            -- Now evaluate the memories content...
            check_memories(tx_mems, rx_mems, outcome);

            if (outcome = false) then
                log("Traffic consitency check error!", error_l, log_level);
Martin Jeřábek's avatar
Martin Jeřábek committed
931
                process_error(error_ctr, error_beh, exit_imm);
Ille, Ondrej, Ing.'s avatar
Ille, Ondrej, Ing. committed
932 933 934 935 936 937 938
            end if;

            wait for 1000 ns;
            loop_ctr <= loop_ctr + 1;
            wait for 0 ns;
        end loop;

Martin Jeřábek's avatar
Martin Jeřábek committed
939
        evaluate_test(error_tol, error_ctr, status);
Ille, Ondrej, Ing.'s avatar
Ille, Ondrej, Ing. committed
940
    end process;
Martin Jeřábek's avatar
Martin Jeřábek committed
941

Ille, Ondrej, Ing.'s avatar
Ille, Ondrej, Ing. committed
942
  errors <= error_ctr;
Martin Jeřábek's avatar
Martin Jeřábek committed
943

Ille, Ondrej, Ing.'s avatar
Ille, Ondrej, Ing. committed
944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000
end architecture;

architecture sanity_test of CAN_test is
    signal epsilon_v    : epsilon_type := (0,150,300,450);
    signal trv_del_v    : trv_del_type := (5,5,5,5);

    signal bus_matrix   : bus_matrix_type := (  ( 0.0,10.0,20.0,30.0),
                                                (10.0, 0.0,10.0,20.0),
                                                (20.0,10.0, 0.0,10.0),
                                                (30.0,20.0,10.0, 0.0));
    ---------------------
    -- Noise parameters
    ---------------------
    signal iter_am     : natural := 40;

    -- Noise pulse width mean in nanaoseconds
    signal nw_mean     : real := 15.0;

    -- Noise pulse width variance
    signal nw_var      : real := 5.0;

    -- Gap between two noise pulses mean in nanoseconds
    signal ng_mean     : real := 10000.0;

    -- Gap variance
    signal ng_var      : real :=  6000.0;
    signal topology    : string (1 to 50) :=
        "                                                  ";

    -- With 100 MHz this is 1Mbit(nom)/2Mbit(Data)
    signal timing_config : bit_time_config_type := (5,5,9,5,5,3,3,3,3,2);
begin
    i_st: entity work.sanity_test
    port map(
        run             => run,
        iterations      => iterations,
        log_level       => log_level,
        error_beh       => error_beh,
        error_tol       => error_tol,
        status          => status,
        errors          => errors,
        epsilon_v       => epsilon_v,
        trv_del_v       => trv_del_v,
        bus_matrix      => bus_matrix,
        iter_am         => iter_am,
        nw_mean         => nw_mean,
        nw_var          => nw_var,
        ng_mean         => ng_mean,
        ng_var          => ng_var,
        topology        => topology,
        timing_config   => timing_config
    );
end architecture;



--------------------------------------------------------------------------------
Martin Jeřábek's avatar
Martin Jeřábek committed
1001
-- Test wrapper and control signals generator
Ille, Ondrej, Ing.'s avatar
Ille, Ondrej, Ing. committed
1002 1003 1004
--------------------------------------------------------------------------------

architecture sanity_test_wrapper of CAN_test_wrapper is
Martin Jeřábek's avatar
Martin Jeřábek committed
1005

Ille, Ondrej, Ing.'s avatar
Ille, Ondrej, Ing. committed
1006 1007 1008 1009 1010 1011 1012 1013 1014
    -- Select architecture of the test
    for test_comp : CAN_test use entity work.CAN_test(sanity_test);

    signal run              :   boolean;
    signal status_int       :   test_status_type;
    signal errors           :   natural;
    signal error_ctr        :   natural;

begin
Martin Jeřábek's avatar
Martin Jeřábek committed
1015

Ille, Ondrej, Ing.'s avatar
Ille, Ondrej, Ing. committed
1016 1017 1018 1019 1020
    -- In this test wrapper generics are directly connected to the signals
    -- of test entity
    test_comp : CAN_test
    port map(
     run              =>  run,
Martin Jeřábek's avatar
Martin Jeřábek committed
1021
     iterations       =>  iterations,
Ille, Ondrej, Ing.'s avatar
Ille, Ondrej, Ing. committed
1022 1023
     log_level        =>  log_level,
     error_beh        =>  error_beh,
Martin Jeřábek's avatar
Martin Jeřábek committed
1024
     error_tol        =>  error_tol,
Ille, Ondrej, Ing.'s avatar
Ille, Ondrej, Ing. committed
1025 1026 1027
     status           =>  status_int,
     errors           =>  errors
    );
Martin Jeřábek's avatar
Martin Jeřábek committed
1028

Ille, Ondrej, Ing.'s avatar
Ille, Ondrej, Ing. committed
1029 1030
  status              <=  status_int;
  error_ctr           <=  errors;
Martin Jeřábek's avatar
Martin Jeřábek committed
1031

Ille, Ondrej, Ing.'s avatar
Ille, Ondrej, Ing. committed
1032 1033 1034 1035 1036 1037 1038 1039 1040
  ------------------------------------------------------------------------------
  -- Starts the test and lets it run
  ------------------------------------------------------------------------------
  test : process
  begin
    run               <= true;
    wait for 1 ns;

    --Wait until the only test finishes and then propagate the results
Martin Jeřábek's avatar
Martin Jeřábek committed
1041
    wait until (status_int=passed or status_int=failed);
Ille, Ondrej, Ing.'s avatar
Ille, Ondrej, Ing. committed
1042 1043

    wait for 100 ns;
Martin Jeřábek's avatar
Martin Jeřábek committed
1044
    run               <= false;
Ille, Ondrej, Ing.'s avatar
Ille, Ondrej, Ing. committed
1045
  end process;
Martin Jeřábek's avatar
Martin Jeřábek committed
1046

Ille, Ondrej, Ing.'s avatar
Ille, Ondrej, Ing. committed
1047
end;