Commit 4415494c authored by Ille, Ondrej, Ing.'s avatar Ille, Ondrej, Ing.

Merge branch '9-rx-buffer-unit-test' into 'master'

Resolve "RX buffer unit test"

Closes #9

See merge request illeondr/CAN_FD_IP_Core!103
parents e4cbc488 6e95d74e
...@@ -142,6 +142,9 @@ ...@@ -142,6 +142,9 @@
-- 2. Separated "write_raw_increment" to "write_raw_intent" and -- 2. Separated "write_raw_increment" to "write_raw_intent" and
-- "write_raw_OK" which is valid only when there is enough -- "write_raw_OK" which is valid only when there is enough
-- space in the buffer and overrun did not occur before! -- space in the buffer and overrun did not occur before!
-- 7.6.2018 Changed detection of buffer full to equality of
-- "read_pointer" and "write_pointer_raw" and nonzero amount
-- of frames stored.
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
Library ieee; Library ieee;
...@@ -349,13 +352,13 @@ entity rxBuffer is ...@@ -349,13 +352,13 @@ entity rxBuffer is
-- RX Buffer is empty (no frame is stored in it) -- RX Buffer is empty (no frame is stored in it)
signal rx_empty_int : std_logic; signal rx_empty_int : std_logic;
-- Internal number of free memory words. Updated during the frame after
-- each word is stored!
signal rx_mem_free_raw : natural range 0 to buff_size;
-- Number of free memory words available to SW after frame was committed. -- Number of free memory words available to SW after frame was committed.
signal rx_mem_free_int : natural range 0 to buff_size; signal rx_mem_free_int : natural range 0 to buff_size;
-- Number of free memory words calculated during frame storing, before
-- commit.
signal rx_mem_free_raw : natural range 0 to buff_size;
-- Indicator of at least one free word in RX FIFO! -- Indicator of at least one free word in RX FIFO!
signal is_free_word : boolean; signal is_free_word : boolean;
...@@ -386,6 +389,11 @@ entity rxBuffer is ...@@ -386,6 +389,11 @@ entity rxBuffer is
-- if "data_overrun" did not occur during the frame! -- if "data_overrun" did not occur during the frame!
signal commit_rx_frame : std_logic; signal commit_rx_frame : std_logic;
-- 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;
-- Indicates that read occurred, and that it is valid (there is something -- Indicates that read occurred, and that it is valid (there is something
-- to read), thus read pointer can be incremented. -- to read), thus read pointer can be incremented.
signal read_increment : boolean; signal read_increment : boolean;
...@@ -483,7 +491,8 @@ begin ...@@ -483,7 +491,8 @@ begin
false; false;
write_extra_ts <= true when ((rx_fsm = rxb_store_end_ts_low) or write_extra_ts <= true when ((rx_fsm = rxb_store_end_ts_low) or
(rx_fsm = rxb_store_end_ts_high)) (rx_fsm = rxb_store_end_ts_high)) and
(data_overrun_int = '0')
else else
false; false;
...@@ -498,13 +507,18 @@ begin ...@@ -498,13 +507,18 @@ begin
false; false;
---------------------------------------------------------------------------- ----------------------------------------------------------------------------
-- Store of the memory can be executed only if there is at least one -- Store of new word can be executed only if there is space in the buffer.
-- free word in the memory! -- 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!
---------------------------------------------------------------------------- ----------------------------------------------------------------------------
is_free_word <= false when (rx_mem_free_raw = 0) else is_free_word <= false when (read_pointer = write_pointer_raw and
message_count > 0)
else
true; true;
---------------------------------------------------------------------------- ----------------------------------------------------------------------------
-- Overrun condition. Following conditions must be met: -- Overrun condition. Following conditions must be met:
-- 1. FSM wants to write to memory either to the position of -- 1. FSM wants to write to memory either to the position of
...@@ -512,12 +526,8 @@ begin ...@@ -512,12 +526,8 @@ begin
-- words which were already written, thus there is no need to watch -- words which were already written, thus there is no need to watch
-- for overrun! -- for overrun!
-- 2. There is no free word in the memory remaining! -- 2. There is no free word in the memory remaining!
-- 3. There is no read intent from SW. If there is read intent, and no
-- space in the buffer, data can be stored to the position which is
-- just being read!
---------------------------------------------------------------------------- ----------------------------------------------------------------------------
overrun_condition <= true when (write_raw_intent and overrun_condition <= true when (write_raw_intent and
(read_increment = false) and
(is_free_word = false)) (is_free_word = false))
else else
false; false;
...@@ -614,8 +624,7 @@ begin ...@@ -614,8 +624,7 @@ begin
timestamp_capture <= (OTHERS => '0'); timestamp_capture <= (OTHERS => '0');
elsif (rising_edge(clk_sys)) then elsif (rising_edge(clk_sys)) then
timestamp_capture <= timestamp_capture;
if ((drv_rtsopt = RTS_END and rec_message_valid = '1') or if ((drv_rtsopt = RTS_END and rec_message_valid = '1') or
(drv_rtsopt = RTS_BEG and sof_pulse = '1')) (drv_rtsopt = RTS_BEG and sof_pulse = '1'))
then then
...@@ -644,40 +653,41 @@ begin ...@@ -644,40 +653,41 @@ begin
message_count <= message_count; message_count <= message_count;
read_frame_counter <= read_frame_counter; read_frame_counter <= read_frame_counter;
-- Start the counter only if there is something to read! --------------------------------------------------------------------
-- Reading frame by user when there is active read and there is
-- something to read
--------------------------------------------------------------------
if (read_increment) then if (read_increment) then
----------------------------------------------------------------
-- During the read of FRAME_FORMAT word store the length -- During the read of FRAME_FORMAT word store the length
-- of the frame to "read_frame_counter", thus we know how much -- of the frame to "read_frame_counter", thus we know how much
-- we have to read before decrementing the "message_count". -- we have to read before decrementing the "message_count".
----------------------------------------------------------------
if (read_frame_counter = 0) then if (read_frame_counter = 0) then
read_frame_counter <= read_frame_counter <=
to_integer(unsigned(memory(read_pointer) to_integer(unsigned(memory(read_pointer)
(RWCNT_H downto RWCNT_L))); (RWCNT_H downto RWCNT_L)));
-- The last word is read during decrement from 1 to 0. We can
-- decrease number of frames then, NOT earlier! If decremented
-- earlier, reading of last frame would get stuck, since
-- read_pointer in memory access is incremented only with
-- non-zero message count! If "commit_frame_counter" is '1' we
-- don't decrement since new frame has arrived at the same
-- moment as reading has finished!
elsif (read_frame_counter = 1) then
if (commit_rx_frame = '0') then
message_count <= message_count - 1;
end if;
read_frame_counter <= read_frame_counter - 1;
-- Just count down during the read of all remaining words...
else else
if (commit_rx_frame = '1') then read_frame_counter <= read_frame_counter - 1;
message_count <= message_count + 1; end if;
end if; end if;
read_frame_counter <= read_frame_counter - 1;
--------------------------------------------------------------------
-- 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!
--------------------------------------------------------------------
if (read_increment and (read_frame_counter = 1)) then
if (commit_rx_frame = '0') then
message_count <= message_count - 1;
end if; end if;
elsif (commit_rx_frame = '1') then elsif (commit_rx_frame = '1') then
message_count <= message_count + 1; message_count <= message_count + 1;
end if; end if;
end if; end if;
...@@ -746,8 +756,11 @@ begin ...@@ -746,8 +756,11 @@ begin
-- Store first TIMESTAMP_U_W from beginning of frame. -- Store first TIMESTAMP_U_W from beginning of frame.
-------------------------------------------------------------------- --------------------------------------------------------------------
when rxb_store_beg_ts_high => when rxb_store_beg_ts_high =>
rx_fsm <= rxb_store_data; if (rec_abort = '1') then
rx_fsm <= rxb_idle;
else
rx_fsm <= rxb_store_data;
end if;
-------------------------------------------------------------------- --------------------------------------------------------------------
-- Store DATA_W. If error ocurrs, abort the storing. If storing is -- Store DATA_W. If error ocurrs, abort the storing. If storing is
...@@ -794,16 +807,22 @@ begin ...@@ -794,16 +807,22 @@ begin
commit_proc : process(res_n, clk_sys) commit_proc : process(res_n, clk_sys)
begin begin
if (res_n = ACT_RESET) then if (res_n = ACT_RESET) then
commit_rx_frame <= '0'; commit_rx_frame <= '0';
commit_overrun_abort <= '0';
elsif (rising_edge(clk_sys)) then elsif (rising_edge(clk_sys)) then
if (((rec_message_valid = '1' and drv_rtsopt = RTS_BEG) or if (((rec_message_valid = '1' and drv_rtsopt = RTS_BEG) or
(rx_fsm = rxb_store_end_ts_high)) and (data_overrun_int = '0')) (rx_fsm = rxb_store_end_ts_high)))
then then
commit_rx_frame <= '1'; if (data_overrun_int = '0') then
commit_rx_frame <= '1';
else
commit_overrun_abort <= '1';
end if;
else else
commit_rx_frame <= '0'; commit_rx_frame <= '0';
commit_overrun_abort <= '0';
end if; end if;
end if; end if;
...@@ -827,8 +846,8 @@ begin ...@@ -827,8 +846,8 @@ begin
write_pointer_raw <= 0; write_pointer_raw <= 0;
write_pointer_extra_ts <= 0; write_pointer_extra_ts <= 0;
rx_mem_free_raw <= buff_size;
rx_mem_free_int <= buff_size; rx_mem_free_int <= buff_size;
rx_mem_free_raw <= buff_size;
elsif (rising_edge(clk_sys)) then elsif (rising_edge(clk_sys)) then
...@@ -839,25 +858,31 @@ begin ...@@ -839,25 +858,31 @@ begin
read_pointer <= (read_pointer + 1) mod buff_size; read_pointer <= (read_pointer + 1) mod buff_size;
end if; end if;
-------------------------------------------------------------------- --------------------------------------------------------------------
-- Commiting "write_pointer_raw", resetting or incrementing during -- Loading "write_pointer_raw" to "write_pointer" when frame is
-- write... -- committed.
-------------------------------------------------------------------- --------------------------------------------------------------------
if (commit_rx_frame = '1') then if (commit_rx_frame = '1') then
write_pointer <= write_pointer_raw; write_pointer <= write_pointer_raw;
end if;
elsif (rec_abort = '1' or overrun_condition) then
write_pointer_raw <= write_pointer;
elsif (write_raw_OK) then --------------------------------------------------------------------
-- Updating "write_pointer_raw":
-- 1. Increment when word is written to memory.
-- 2. Reset when "rec_abort" is active (Error frame) or
-- frame finished and overrun occurred meanwhile. Reset to
-- value of last commited write pointer.
--------------------------------------------------------------------
if (write_raw_OK) then
write_pointer_raw <= (write_pointer_raw + 1) mod buff_size; write_pointer_raw <= (write_pointer_raw + 1) mod buff_size;
elsif (rec_abort = '1' or commit_overrun_abort = '1') then
write_pointer_raw <= write_pointer;
else else
write_pointer_raw <= write_pointer_raw; write_pointer_raw <= write_pointer_raw;
end if; end if;
-------------------------------------------------------------------- --------------------------------------------------------------------
-- Setting extra write pointer for write of timestamp from end of -- Setting extra write pointer for write of timestamp from end of
-- frame... -- frame...
...@@ -877,30 +902,36 @@ begin ...@@ -877,30 +902,36 @@ begin
-------------------------------------------------------------------- --------------------------------------------------------------------
-- Calculating free memory. The same way as write_pointer_raw. -- Calculate free memory internally (raw)
-- Free memory for the user is available only after the commit!
-- However, here we must consider also reads!
-------------------------------------------------------------------- --------------------------------------------------------------------
if (commit_rx_frame = '1') then if (read_increment) then
if (read_increment) then if (rec_abort = '1' or commit_overrun_abort = '1') then
rx_mem_free_int <= rx_mem_free_raw + 1;
else
rx_mem_free_int <= rx_mem_free_raw;
end if;
elsif (rec_abort = '1') then
if (read_increment) then
rx_mem_free_raw <= rx_mem_free_int + 1; rx_mem_free_raw <= rx_mem_free_int + 1;
else elsif (not write_raw_OK) then
rx_mem_free_raw <= rx_mem_free_raw + 1;
end if;
else
if (rec_abort = '1' or commit_overrun_abort = '1') then
rx_mem_free_raw <= rx_mem_free_int; rx_mem_free_raw <= rx_mem_free_int;
elsif (write_raw_OK) then
rx_mem_free_raw <= rx_mem_free_raw - 1;
end if; end if;
end if;
elsif (write_raw_OK and (not read_increment)) then --------------------------------------------------------------------
rx_mem_free_raw <= rx_mem_free_raw - 1; -- Calculate free memory for user:
-- 1. Increment when user reads the frame.
elsif read_increment then -- 2. Load RAW value when comitt occurs
rx_mem_free_int <= rx_mem_free_int + 1; --------------------------------------------------------------------
rx_mem_free_raw <= rx_mem_free_raw + 1; if (read_increment) then
if (commit_rx_frame = '1') then
rx_mem_free_int <= rx_mem_free_raw + 1;
else
rx_mem_free_int <= rx_mem_free_int + 1;
end if;
elsif (commit_rx_frame = '1') then
rx_mem_free_int <= rx_mem_free_raw;
end if; end if;
end if; end if;
...@@ -977,7 +1008,7 @@ begin ...@@ -977,7 +1008,7 @@ begin
-- Assertions -- Assertions
---------------------------------------------------------------------------- ----------------------------------------------------------------------------
---------------------------------------------------------------------------- ----------------------------------------------------------------------------
---------------------------------------------------------------------------- ----------------------------------------------------------------------------
-- RX Buffer size can be only powers of 2. Since modulo arithmetics is used -- RX Buffer size can be only powers of 2. Since modulo arithmetics is used
...@@ -1090,4 +1121,27 @@ begin ...@@ -1090,4 +1121,27 @@ begin
-- pragma translate_on -- pragma translate_on
end process; end process;
----------------------------------------------------------------------------
-- Checking consistency of "mem_free" calculation.
-- If buffer is idle (no storing is in progress), and message_count is 0,
-- then the buffer should be completely empty, thus, mem_free should be
-- equal to size of buffer.
----------------------------------------------------------------------------
--mem_free_calc_process : process(clk_sys)
--begin
-- pragma translate_off
-- if (rising_edge(clk_sys) and now /= 0 fs) then
-- if (rx_fsm = rxb_idle and message_count = 0 and rx_mem_free_int /=
-- buff_size and commit_rx_frame = '0')
-- then
-- report "Buffer should be empty, but 'rx_mem_free_raw' is " &
-- "not equal to 'buff_size'" severity error;
-- end if;
--
-- end if;
-- pragma translate_on
-- end process;
end architecture; end architecture;
...@@ -2105,6 +2105,7 @@ package body CANtestLib is ...@@ -2105,6 +2105,7 @@ package body CANtestLib is
-- Generate random data -- Generate random data
-- Unused bytes of data can be set to 0 -- Unused bytes of data can be set to 0
frame.data := (OTHERS => (OTHERS => '0'));
if (frame.data_length > 0) then if (frame.data_length > 0) then
for i in 0 to frame.data_length - 1 loop for i in 0 to frame.data_length - 1 loop
rand_logic_vect_v(rand_ctr, data_byte, 0.5); rand_logic_vect_v(rand_ctr, data_byte, 0.5);
......
...@@ -115,10 +115,11 @@ architecture rx_buf_unit_test of CAN_test is ...@@ -115,10 +115,11 @@ architecture rx_buf_unit_test of CAN_test is
signal rx_read_buff : std_logic_vector(31 downto 0); signal rx_read_buff : std_logic_vector(31 downto 0);
-- Driving bus aliases -- Driving bus aliases
signal drv_rtsopt : std_logic := RTS_BEG; signal drv_rtsopt : std_logic := RTS_END;
signal drv_read_start : std_logic := '0'; signal drv_read_start : std_logic := '0';
signal drv_clr_ovr : std_logic := '0';
---------------------------------------------------------------------------- ----------------------------------------------------------------------------
-- Test specific signals -- Test specific signals
---------------------------------------------------------------------------- ----------------------------------------------------------------------------
...@@ -138,6 +139,9 @@ architecture rx_buf_unit_test of CAN_test is ...@@ -138,6 +139,9 @@ architecture rx_buf_unit_test of CAN_test is
signal exit_imm_d_2 : boolean := false; signal exit_imm_d_2 : boolean := false;
signal exit_imm_d_3 : boolean := false; signal exit_imm_d_3 : boolean := false;
-- Additional random counter
signal rand_ctr_3 : natural range 0 to RAND_POOL_SIZE := 0;
---------------------------------------------------------------------------- ----------------------------------------------------------------------------
-- Memory declarations for memories where data are read out -- Memory declarations for memories where data are read out
---------------------------------------------------------------------------- ----------------------------------------------------------------------------
...@@ -216,7 +220,7 @@ architecture rx_buf_unit_test of CAN_test is ...@@ -216,7 +220,7 @@ architecture rx_buf_unit_test of CAN_test is
wait for 0 ns; wait for 0 ns;
end loop; end loop;
end if; end if;
-- At the end we need to move one more time -- At the end we need to move one more time
-- in_pointer <= in_pointer+1; -- in_pointer <= in_pointer+1;
wait for 0 ns; wait for 0 ns;
...@@ -283,6 +287,9 @@ architecture rx_buf_unit_test of CAN_test is ...@@ -283,6 +287,9 @@ architecture rx_buf_unit_test of CAN_test is
signal rec_abort :out std_logic; signal rec_abort :out std_logic;
signal rec_message_valid :out std_logic; signal rec_message_valid :out std_logic;
signal drv_rtsopt :in std_logic;
signal drv_clr_ovr :inout std_logic;
signal memory :inout eval_mem_test; signal memory :inout eval_mem_test;
signal in_pointer :inout natural; signal in_pointer :inout natural;
signal timestamp :in std_logic_vector(63 downto 0); signal timestamp :in std_logic_vector(63 downto 0);
...@@ -291,14 +298,34 @@ architecture rx_buf_unit_test of CAN_test is ...@@ -291,14 +298,34 @@ architecture rx_buf_unit_test of CAN_test is
variable CAN_frame : SW_CAN_frame_type; variable CAN_frame : SW_CAN_frame_type;
variable stored_ts : std_logic_vector(63 downto 0); variable stored_ts : std_logic_vector(63 downto 0);
variable rand_val : natural; variable rand_val : natural;
variable abort_present : boolean; variable abort_present : boolean := false;
variable id_out : std_logic_vector(28 downto 0); variable id_out : std_logic_vector(28 downto 0);
begin begin
CAN_generate_frame(rand_ctr, CAN_frame); CAN_generate_frame(rand_ctr, CAN_frame);
stored_ts := (OTHERS => '0'); stored_ts := (OTHERS => '0');
------------------------------------------------------------------------
-- Initiate frame storing by clearing possible overrun from before.
-- It might have happened that Overrun was generated at the same time
-- as there was intent abort. In that case, the frame was aborted,
-- overrun was not cleared and stayed till next frame. Storing of
-- next frame then evaluated overrun as present and did not store the
-- frame to input memory!
------------------------------------------------------------------------
drv_clr_ovr <= '1';
wait until rising_edge(clk_sys);
drv_clr_ovr <= '0';
wait for 1 ns;
-- Check that overrun was cleared
if (rx_data_overrun = '1') then
log("Overrun not cleared!", error_l, log_level);
end if;
------------------------------------------------------------------------
-- Initiate Frame by SOF pulse and store timestamp! -- Initiate Frame by SOF pulse and store timestamp!
------------------------------------------------------------------------
sof_pulse <= '1'; sof_pulse <= '1';
if (drv_rtsopt = RTS_BEG) then if (drv_rtsopt = RTS_BEG) then
stored_ts := std_logic_vector(to_unsigned( stored_ts := std_logic_vector(to_unsigned(
...@@ -308,16 +335,20 @@ architecture rx_buf_unit_test of CAN_test is ...@@ -308,16 +335,20 @@ architecture rx_buf_unit_test of CAN_test is
sof_pulse <= '0'; sof_pulse <= '0';
wait until rising_edge(clk_sys); wait until rising_edge(clk_sys);
------------------------------------------------------------------------
-- Wait Random time (to emulate CAN ID). No real need to emulate real -- Wait Random time (to emulate CAN ID). No real need to emulate real
-- length of Identifier! Emulate random error also during this time, -- length of Identifier! Emulate random error also during this time,
-- error frame may come also before any storing started and can not FUCK -- error frame may come also before any storing started and can not FUCK
-- UP the buffer. -- UP the buffer.
------------------------------------------------------------------------
wait_rand_cycles(rand_ctr, clk_sys, 10, 50); wait_rand_cycles(rand_ctr, clk_sys, 10, 50);
generate_random_abort(rand_ctr, rec_abort, clk_sys, abort_present, 0.1, generate_random_abort(rand_ctr, rec_abort, clk_sys, abort_present, 0.1,
log_level); log_level);
if (abort_present) then if (abort_present) then
wait until rising_edge(clk_sys);
wait until rising_edge(clk_sys);
return; return;
end if; end if;
...@@ -332,6 +363,7 @@ architecture rx_buf_unit_test of CAN_test is ...@@ -332,6 +363,7 @@ architecture rx_buf_unit_test of CAN_test is
rec_brs <= CAN_frame.brs; rec_brs <= CAN_frame.brs;
rec_esi <= CAN_frame.esi; rec_esi <= CAN_frame.esi;
rec_rtr <= CAN_frame.rtr; rec_rtr <= CAN_frame.rtr;
log("Storing metadata", info_l, log_level); log("Storing metadata", info_l, log_level);
wait until rising_edge(clk_sys); wait until rising_edge(clk_sys);
...@@ -341,13 +373,15 @@ architecture rx_buf_unit_test of CAN_test is ...@@ -341,13 +373,15 @@ architecture rx_buf_unit_test of CAN_test is
store_metadata <= '0'; store_metadata <= '0';
wait until rising_edge(clk_sys); wait until rising_edge(clk_sys);
------------------------------------------------------------------------
-- Store data words -- Store data words
------------------------------------------------------------------------
if (CAN_frame.data_length > 0) then if (CAN_frame.data_length > 0) then
for i in 0 to ((CAN_frame.data_length - 1) / 4) loop