...
  View open merge request
Commits (11)
--------------------------------------------------------------------------------
--
-- CTU CAN FD IP Core
-- Copyright (C) 2015-2018
--
-- Authors:
-- Ondrej Ille <ondrej.ille@gmail.com>
-- Martin Jerabek <martin.jerabek01@gmail.com>
--
-- Project advisors:
-- Jiri Novak <jnovak@fel.cvut.cz>
-- Pavel Pisa <pisa@cmp.felk.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/)
--
-- 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
-- Component is furnished to do so, subject to the following conditions:
--
-- The above copyright notice and this permission notice shall be included in
-- all copies or substantial portions of the Component.
--
-- 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
-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-- FROM, OUT OF OR IN CONNECTION WITH THE COMPONENT OR THE USE OR OTHER DEALINGS
-- IN THE COMPONENT.
--
-- 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
-- protocol license from Bosch.
--
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
-- Purpose:
-- The aim here is to test whether TX arbitrator selects a frame from TXT
-- Buffer with the highest priority and sends it, in case of more TXT Buffers
-- in "READY" state.
--
-- Test sequence:
-- 1. Generate and set random priorities to TX buffers.
-- 2. Sort the priorities by size (highest priority first)
-- 3. Generate CAN frame for each TX buffer
-- 4. Give set ready command to all buffers at the same time
-- 5. Wait until all frames are received on the second node
-- 6. Check if all frames were received in correct order.
--
--------------------------------------------------------------------------------
-- Revision History:
-- 24.3.2019 Created file
-- 31.3.2019 Test completed.
--------------------------------------------------------------------------------
context work.ctu_can_synth_context;
context work.ctu_can_test_context;
use lib.pkg_feature_exec_dispath.all;
package txt_buffer_priority_feature is
procedure txt_buffer_priority_feature_exec(
variable o : out feature_outputs_t;
signal so : out feature_signal_outputs_t;
signal rand_ctr : inout natural range 0 to RAND_POOL_SIZE;
signal iout : in instance_outputs_arr_t;
signal mem_bus : inout mem_bus_arr_t;
signal bus_level : in std_logic
);
end package;
package body txt_buffer_priority_feature is
procedure txt_buffer_priority_feature_exec(
variable o : out feature_outputs_t;
signal so : out feature_signal_outputs_t;
signal rand_ctr : inout natural range 0 to RAND_POOL_SIZE;
signal iout : in instance_outputs_arr_t;
signal mem_bus : inout mem_bus_arr_t;
signal bus_level : in std_logic
) is
type CAN_frame_array_type is array (1 to 4) of SW_CAN_frame_type;
type priority_array_type is array (1 to 4) of natural range 0 to 8;
variable data : std_logic_vector(31 downto 0) :=
(OTHERS => '0');
variable address : std_logic_vector(11 downto 0) :=
(OTHERS => '0');
variable ID_1 : natural := 1; -- Transmiter
variable ID_2 : natural := 2; -- Receiver
variable CAN_frame_array_tx : CAN_frame_array_type;
variable CAN_frame_array_rx : CAN_frame_array_type;
variable priority_array : priority_array_type;
variable priority_value_tmp : natural range 0 to 8;
variable priority_value_max : natural range 0 to 8;
variable priority_index_max : natural range 0 to 8;
variable frame_equal : boolean := false;
variable tmp_int : natural := 0;
begin
o.outcome := true;
-- Generate random priorities and write it to the Priority register
for j in 1 to 4 loop
rand_int_v(rand_ctr, 7, tmp_int); -- Get random number
priority_array(j) := tmp_int; -- Priority of TXT Buffer N
wait for 0 ns; -- Wait to 'refresh' random generator
-- Write generated priority to the register
CAN_configure_tx_priority(j, priority_array(j), ID_1, mem_bus(1));
end loop;
-- Sorting buffer priorities - descending. First generate frame to buffer
-- with the highest priority. In each iteration find unfulfilled buffer with
-- the highest available priority and insert new frame to it .
for j in 1 to 4 loop
priority_value_tmp := 0; -- Init value for each iteration.
priority_value_max := 0; -- Init value for each iteration.
-- Find unused buffer with the highest priority (used buffer = priority 8)
for i in 1 to 4 loop
-- Use only ">" in this statement because documenntion says
-- "If two buffers have equal priorities, the one with lower index is selected"
if((priority_array(i) > priority_value_max) AND
(priority_array(i) /= 8)) then
priority_value_max := priority_array(i); -- The highest priority found
priority_index_max := i; -- Index of buffer with the highest priority
end if;
end loop;
-- Print buffer number with its priority value.
info("[" & Integer'image(j) & "] Priority " &
Integer'image(priority_array(priority_index_max)) & " in buffer " &
Integer'image(priority_index_max) & ".");
-- Mark buffer as used
priority_array(priority_index_max) := 8;
-- Generate CAN frame
CAN_generate_frame(rand_ctr, CAN_frame_array_tx(j));
CAN_print_frame_simple(CAN_frame_array_tx(j));
-- Insert the frame for transmittion
CAN_insert_TX_frame(CAN_frame_array_tx(j), priority_index_max, ID_1, mem_bus(1));
end loop;
info("Note: higher priority value -> higher priority");
-- Atomic set ready command
send_TXT_buf_cmd(buf_set_ready, "1111", ID_1, mem_bus(1));
info("Set ready command done.");
-- Wait until all four frames are sent
CAN_wait_frame_sent(ID_1, mem_bus(1));
CAN_wait_frame_sent(ID_1, mem_bus(1));
CAN_wait_frame_sent(ID_1, mem_bus(1));
CAN_wait_frame_sent(ID_1, mem_bus(1));
-- Read all frames on the second node
for i in 1 to 4 loop
info("Read Frame " & Integer'image(i) & ":");
CAN_read_frame(CAN_frame_array_rx(i), ID_2, mem_bus(2));
end loop;
-- Generate some debug logs.
info("TX frames (highest priority first)");
for i in 1 to 4 loop
CAN_print_frame_simple(CAN_frame_array_tx(i));
end loop;
info("RX frames (in order of receive):");
for i in 1 to 4 loop
CAN_print_frame_simple(CAN_frame_array_rx(i));
end loop;
-- Eval results
for i in 1 to 4 loop
CAN_compare_frames(CAN_frame_array_tx(i), CAN_frame_array_rx(i), false, frame_equal);
if(frame_equal = false) then
info("FRAMES NOT EQUAL:");
CAN_print_frame(CAN_frame_array_rx(i));
CAN_print_frame(CAN_frame_array_tx(i));
o.outcome := false;
exit;
end if;
-- check_false(frame_equal = true, "FRAMES ARE DIFFERENT!");
end loop;
info("Test successful.");
end procedure;
end package body;
......@@ -252,13 +252,13 @@ package CANtestLib is
-- SSP (Secondary Sampling Point) configuration options
type SSP_set_command_type is (
ssp_measured,
ssp_meas_n_offset,
ssp_offset
ssp_measured, -- Use only TRV_DELAY
ssp_meas_n_offset, -- Use TRV_DELAY + fixed offset given by user
ssp_offset -- Use only offset given by user
);
-- Use only TRV_DELAY
-- Use TRV_DELAY + fixed offset given by user
-- Use only offset given by user
----------------------------------------------------------------------------
......@@ -1184,6 +1184,9 @@ package CANtestLib is
procedure CAN_print_frame(
constant frame : in SW_CAN_frame_type
);
procedure CAN_print_frame_simple(
constant frame : in SW_CAN_frame_type
);
----------------------------------------------------------------------------
......@@ -1430,6 +1433,22 @@ package CANtestLib is
);
----------------------------------------------------------------------------
-- Give command to selected TXT Buffers in one bus access.
--
-- Arguments:
-- cmd Command to give to TXT Buffer.
-- buf_vector Bit vector with TXT Buffers which should receive
-- the command (eg. "1001" = command for buffers 1 and 4.)
-- ID Index of CTU CAN FD Core instance.
-- mem_bus Avalon memory bus to execute the access on.
----------------------------------------------------------------------------
procedure send_TXT_buf_cmd(
constant cmd : in SW_TXT_Buffer_command_type;
constant buf_vector : in std_logic_vector(3 downto 0);
constant ID : in natural range 0 to 15;
signal mem_bus : inout Avalon_mem_type
);
----------------------------------------------------------------------------
-- Read state of TXT Buffer.
--
......@@ -1828,6 +1847,24 @@ package CANtestLib is
constant ID : in natural range 0 to 15;
signal mem_bus : inout Avalon_mem_type
);
----------------------------------------------------------------------------
-- Configure priority of the TXT Buffers in TX Arbitrator. Higher priority
-- value signals that buffer is selected earlier for transmission.
--
-- Arguments:
-- buff_number Select required buffer.
-- priority Value between 0 and 7, details in datasheet.
-- ID Index of CTU CAN FD Core instance.
-- mem_bus Avalon memory bus to execute the access on.
----------------------------------------------------------------------------
procedure CAN_configure_tx_priority(
constant buff_number : in natural range 1 to 4;
variable priority : in natural range 0 to 7;
constant ID : in natural range 0 to 15;
signal mem_bus : inout Avalon_mem_type
);
----------------------------------------------------------------------------
----------------------------------------------------------------------------
......@@ -3097,6 +3134,24 @@ package body CANtestLib is
end if;
info(str_msg);
end procedure;
procedure CAN_print_frame_simple(
constant frame : in SW_CAN_frame_type
)is
variable data_byte : std_logic_vector(7 downto 0);
variable str_msg : string(1 to 512) := (OTHERS => ' ');
begin
str_msg(1 to 10) := "CAN Frame:";
-- Identifier
str_msg(11 to 18) := " ID : 0x";
str_msg(19 to 26) :=
to_hstring(std_logic_vector(to_unsigned(frame.identifier, 32)));
info(str_msg);
end procedure;
procedure CAN_compare_frames(
......@@ -3666,6 +3721,50 @@ package body CANtestLib is
-- Give the command
CAN_write(data, TX_COMMAND_ADR, ID, mem_bus);
end procedure;
-- constant buf_vector : in std_logic_vector(7 downto 0); No
procedure send_TXT_buf_cmd(
constant cmd : in SW_TXT_Buffer_command_type;
constant buf_vector : in std_logic_vector(3 downto 0);
constant ID : in natural range 0 to 15;
signal mem_bus : inout Avalon_mem_type
)is
variable data : std_logic_vector(31 downto 0)
:= (OTHERS => '0');
begin
-- Set active command bit in TX_COMMAND register based on input command
data(TXCE_IND) := '0';
data(TXCR_IND) := '0';
data(TXCA_IND) := '0';
if (cmd = buf_set_empty) then
data(TXCE_IND) := '1';
elsif (cmd = buf_set_ready) then
data(TXCR_IND) := '1';
elsif (cmd = buf_set_abort) then
data(TXCA_IND) := '1';
end if;
-- Set index of Buffer on which the command should be executed.
for i in 0 to 3 loop
if(buf_vector(i) = '1') then
data(i + TXB1_IND) := '1';
end if;
end loop;
-- Give the command
CAN_write(data, TX_COMMAND_ADR, ID, mem_bus);
end procedure;
procedure get_tx_buf_state(
......@@ -4474,6 +4573,43 @@ package body CANtestLib is
CAN_write(data, SSP_CFG_ADR, ID, mem_bus, BIT_16);
end procedure;
procedure CAN_configure_tx_priority(
constant buff_number : in natural range 1 to 4;
variable priority : in natural range 0 to 7;
constant ID : in natural range 0 to 15;
signal mem_bus : inout Avalon_mem_type
) is
variable data : std_logic_vector(31 downto 0) :=
(OTHERS => '0');
variable address : std_logic_vector(11 downto 0) :=
(OTHERS => '0');
begin
-- Read current register value to variable
address := TX_PRIORITY_ADR;
CAN_read(data, address, ID, mem_bus, BIT_16);
info("Read 'TX_PRIORITY_ADR': 0x" & to_hstring(data) & ".");
-- Select buffer and modify appropriate bits in the register
case buff_number is
when 1 =>
data (2 downto 0) := std_logic_vector(to_unsigned(priority, 3));
when 2 =>
data (6 downto 4) := std_logic_vector(to_unsigned(priority, 3));
when 3 =>
data (10 downto 8) := std_logic_vector(to_unsigned(priority, 3));
when 4 =>
data (14 downto 12) := std_logic_vector(to_unsigned(priority, 3));
when others =>
error("Unsupported TX buffer number.");
end case;
-- Write back new value and exit procedure
info("Write 'TX_PRIORITY_ADR': 0x" & to_hstring(data) & ".");
address := TX_PRIORITY_ADR;
CAN_write(data, address, ID, mem_bus, BIT_16);
end procedure;
end package body;
......
......@@ -75,6 +75,8 @@ feature:
timestamp_registers:
txt_buffer_hazard:
iterations: 1
txt_buffer_priority:
iterations: 5
reference:
default:
<<: *default
......
......@@ -104,6 +104,8 @@ feature:
timestamp_registers:
txt_buffer_hazard:
iterations: 1
txt_buffer_priority:
iterations: 5
sanity:
default:
<<: *default
......