Added test package and guide into documentation
This commit is contained in:
4
documentation/CAN_testdata/data_read.tdf
Normal file
4
documentation/CAN_testdata/data_read.tdf
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
20
|
||||||
|
21
|
||||||
|
22
|
||||||
|
23
|
||||||
5
documentation/CAN_testdata/data_send.tdf
Normal file
5
documentation/CAN_testdata/data_send.tdf
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
10 10101010
|
||||||
|
11 11000010
|
||||||
|
12 10101010
|
||||||
|
13 00001111
|
||||||
|
1 00000001
|
||||||
6
documentation/CAN_testdata/default_setup.tdf
Normal file
6
documentation/CAN_testdata/default_setup.tdf
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
4 00000000
|
||||||
|
5 11111111
|
||||||
|
6 10000000
|
||||||
|
7 01001000
|
||||||
|
8 00000010
|
||||||
|
0 11111110
|
||||||
@@ -32,3 +32,133 @@ lookuptable_ptr:
|
|||||||
ld32 rZ,rX // load from pointer with offset
|
ld32 rZ,rX // load from pointer with offset
|
||||||
//...
|
//...
|
||||||
\end{asm}
|
\end{asm}
|
||||||
|
|
||||||
|
\clearpage
|
||||||
|
\section{How to test a design using the CAN test package}
|
||||||
|
%Designs that use a CAN controller as a peripheral device, are often complex and therefor hard to debug.
|
||||||
|
%This is especially true, if providing valid input data via the CAN bus is necessary in order to verify correct behavior.
|
||||||
|
The platform includes a foreign CAN controller IP component.
|
||||||
|
To ease integration and testing, a test package is provided with the platform source code.
|
||||||
|
With its help, input data and behavior of a CAN network can be modeled more easily.
|
||||||
|
|
||||||
|
The test package is located in \verb=can_tp.vhd= and a application demonstration is given as a testbench in \verb=can_demo_tb.vhd= in the testbench directory.
|
||||||
|
|
||||||
|
In this guide, two approaches on verifying a design are presented.
|
||||||
|
|
||||||
|
%In those situations, the need for tools occurs, that reliably provide input data and model the behavior of a CAN network,
|
||||||
|
%connected to the designs CAN interface.
|
||||||
|
%The CAN test package is a collection of VHDL functions and procedures that implement such tools.
|
||||||
|
%And this guide will explain their proper use.
|
||||||
|
|
||||||
|
%There are two basic approaches, recommended by this guide, on how to do so.
|
||||||
|
%They are described in the two following parts.
|
||||||
|
%The third part gives some hints on how to use these methods in a test bench.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
\subsection{Simulating a CAN transmission}
|
||||||
|
The first approach focuses on generating CAN transmissions, that can be used as input for the design under test. This is achieved by unsing the procedure \verb=simulate_can_transmission= (Listing ~\ref{lst:interface_01}), which is configurable to any data and timing, your CAN interface uses. The user has not to worry about bit stuffing, crc and error detection.
|
||||||
|
|
||||||
|
The \verb=id= and \verb=data= parameters are bit vectors (\verb=std_logic_vector=) that specify the CAN ID and DATA bits of the message.
|
||||||
|
|
||||||
|
The actual length of the data part is configurable by the \verb=datasize= parameter. It is an integer specifying the amount of Bytes of the \verb=data= parameter, that will be included in the CAN transmission. The rest of \verb=data= will simply be ignored.
|
||||||
|
|
||||||
|
The timing is controlled by the \verb=t_bit= parameter, which is of VDHL type time.
|
||||||
|
It stands for the correct overall length of one CAN symbol (this value has to be calculated from the timing configuration of the tested CAN controller).
|
||||||
|
|
||||||
|
The \verb=rx= and \verb=tx= signals have to be connected to a simulated CAN bus. See Section ~\ref{subsec:int_tb} for more information. The signal \verb=tx= is the actual output of the procedure.
|
||||||
|
|
||||||
|
The \verb=test_result= parameter is a diagnostic output of an enumeration type that shows whether the transmission was successful, a CAN error occurs, the arbitration is lost or whether the tested CAN controller is not acknowledging the transmission.
|
||||||
|
|
||||||
|
\begin{vhdl}[Interface]{lst:interface_01}
|
||||||
|
procedure simulate_can_transmission(
|
||||||
|
constant id : in std_logic_vector(10 downto 0);
|
||||||
|
constant data : in std_logic_vector (0 to 63);
|
||||||
|
constant datasize : in integer;
|
||||||
|
constant t_bit : in time;
|
||||||
|
signal rx : in std_logic;
|
||||||
|
signal tx : inout std_logic;
|
||||||
|
signal test_result : out rx_check_result)
|
||||||
|
\end{vhdl}
|
||||||
|
|
||||||
|
\subsection{Creating a test network}
|
||||||
|
While the first approach is limited to transmitting can messages, this one aims at providing one or more fully functioning can nodes in a test network. Each node is implemented by an instantiation of \verb=can_vhdl_top=, but instead of steering them with a LT16soc design, functions of the can test package will do the job:
|
||||||
|
|
||||||
|
If a certain register in a CAN node should be written to, the procedure \verb=can_wb_write_reg= (Listing ~\ref{lst:interface_02}) comes in handy. Its parameter signals \verb=wbs_in= and \verb=wbs_out= must be connected to the CAN controller's Wishbone interface. The parameter \verb=addr= is an integer specifying the target register of the write and the parameter data is a bit vector containing the data. And finally a clock signal \verb=clk= is needed as input, in order to write to the CAN controller. (This must be the same clock used for operating the CAN node.)
|
||||||
|
|
||||||
|
\begin{vhdl}[Interface]{lst:interface_02}
|
||||||
|
procedure can_wb_write_reg(
|
||||||
|
signal wbs_in : out wb_slv_in_type;
|
||||||
|
signal wbs_out : in wb_slv_out_type;
|
||||||
|
constant addr : integer;
|
||||||
|
constant data : in std_logic_vector(7 downto 0);
|
||||||
|
signal clk : in std_logic)
|
||||||
|
\end{vhdl}
|
||||||
|
|
||||||
|
For extracting certain register contents, the procedure \verb=can_wb_read_reg= (Listing ~\ref{lst:interface_03}) is provided. It is used with the same parameters like \verb=can_wb_write_reg=, except a data input bit vector. Instead, a data output signal is provided, to access the read register contents.
|
||||||
|
|
||||||
|
\begin{vhdl}[Interface]{lst:interface_03}
|
||||||
|
procedure can_wb_read_reg(
|
||||||
|
signal wbs_in : out wb_slv_in_type;
|
||||||
|
signal wbs_out : in wb_slv_out_type;
|
||||||
|
constant addr : integer;
|
||||||
|
signal data : out std_logic_vector(7 downto 0);
|
||||||
|
signal clk : in std_logic)
|
||||||
|
\end{vhdl}
|
||||||
|
|
||||||
|
If successive writes are needed, the procedure \verb=write_regs_from_file= (Listing ~\ref{lst:interface_04}) is a convenient way to do this. The first Parameter is a path to a text file. Each line in the file stands for a CAN register, that should be written, and consits of a integer for the desired target register number and eight binary digits ('0' or '1') for the data. Both numbers are separated by one SPACE. See ~\ref{lst:default_setup} for an example.
|
||||||
|
|
||||||
|
\begin{vhdl}[Interface]{lst:interface_04}
|
||||||
|
procedure write_regs_from_file(
|
||||||
|
constant filename : in string;
|
||||||
|
signal wbs_in : out wb_slv_in_type;
|
||||||
|
signal wbs_out : in wb_slv_out_type;
|
||||||
|
signal clk : in std_logic)
|
||||||
|
\end{vhdl}
|
||||||
|
|
||||||
|
Successive reading can be done in a similar way with \verb=read_regs_with_fileaddr= (Listing ~\ref{lst:interface_05}). Here, the data part in each line of the file is ignored. If the registers written to should be read, the same file can be used. The parameter \verb=out_filename= determines an additional file, that is used to store the read register contents.
|
||||||
|
|
||||||
|
\begin{vhdl}[Interface]{lst:interface_05}
|
||||||
|
procedure read_regs_with_fileaddr(
|
||||||
|
constant filename : in string;
|
||||||
|
constant out_filename : in string;
|
||||||
|
signal wbs_in : out wb_slv_in_type;
|
||||||
|
signal wbs_out : in wb_slv_out_type;
|
||||||
|
signal clk : in std_logic)
|
||||||
|
\end{vhdl}
|
||||||
|
|
||||||
|
|
||||||
|
\subsection{Integrating the approaches in a test bench}
|
||||||
|
\label{subsec:int_tb}
|
||||||
|
In order to use the two presented approaches in a test bench, some details have to be considered:
|
||||||
|
|
||||||
|
\begin{itemize}
|
||||||
|
\item Connecting CAN nodes or transmitting custom messages requires the simulation of a CAN network. A VHDL design that does exactly this is provided: \verb=phys_can_sim= (Listing ~\ref{lst:interface_06}). The individual tx and rx signals of the connected can nodes are merged into two vectors. Thier size is determind by the generic parameter \verb=peer_num=, which should be equal to the number of clients connected to the CAN network.
|
||||||
|
\item When using the \verb=simulate_can_transmission= procedure, the \verb=tx= signal is only handled while the procedure is working. For all other times the signal has to be assigned manually.
|
||||||
|
\item When simulating the test bench with ISim, the relative file path in \verb=write_regs_from_file= and \verb=read_regs_with_fileaddr= has its root in the project folder. An example file, containing initialization data for a can node is shown in Listing ~\ref{lst:default_setup}.
|
||||||
|
\item When instantiating \verb=can_vhdl_top= (a CAN node without a lt16soc), do not forget to initialize its \verb=wbs_in= port signal porperly. This can be done by assigning the constant \verb=wbs_in_default= from the CAN test package to it.
|
||||||
|
\item A demo test bench using all the mechanics described in the two approaches is provided: \verb=can_demo_tb=.
|
||||||
|
\end{itemize}
|
||||||
|
|
||||||
|
|
||||||
|
\begin{vhdl}[Interface]{lst:interface_06}
|
||||||
|
entity phys_can_sim
|
||||||
|
generic(
|
||||||
|
peer_num : integer );
|
||||||
|
port(
|
||||||
|
rst : in std_logic;
|
||||||
|
rx_vector : out std_logic_vector(peer_num - 1 downto 0);
|
||||||
|
tx_vector : in std_logic_vector(peer_num - 1 downto 0) );
|
||||||
|
end entity phys_can_sim;
|
||||||
|
\end{vhdl}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
\begin{vhdl}[default\_setup.tdf]{lst:default_setup}
|
||||||
|
4 00000000
|
||||||
|
5 11111111
|
||||||
|
6 10000000
|
||||||
|
7 01001000
|
||||||
|
8 00000010
|
||||||
|
0 11111110
|
||||||
|
\end{vhdl}
|
||||||
|
|||||||
@@ -8,7 +8,18 @@ use ieee.std_logic_textio.all;
|
|||||||
package can_tp is
|
package can_tp is
|
||||||
|
|
||||||
type rx_check_result is (success, can_error, arbitration_lost, no_ack);
|
type rx_check_result is (success, can_error, arbitration_lost, no_ack);
|
||||||
|
|
||||||
|
constant wbs_in_default : wb_slv_in_type := (
|
||||||
|
(others=>'-'), -- adr
|
||||||
|
(others=>'-'), -- dat
|
||||||
|
'-', -- we
|
||||||
|
(others => '-'), -- sel
|
||||||
|
'0', -- stb
|
||||||
|
'0', -- cyc
|
||||||
|
"000", -- cti
|
||||||
|
"00" -- bte
|
||||||
|
);
|
||||||
|
|
||||||
procedure can_wb_write_reg(
|
procedure can_wb_write_reg(
|
||||||
signal wbs_in : out wb_slv_in_type;
|
signal wbs_in : out wb_slv_in_type;
|
||||||
signal wbs_out : in wb_slv_out_type;
|
signal wbs_out : in wb_slv_out_type;
|
||||||
@@ -22,14 +33,28 @@ package can_tp is
|
|||||||
constant addr : in integer;
|
constant addr : in integer;
|
||||||
signal clk : in std_logic);
|
signal clk : in std_logic);
|
||||||
|
|
||||||
|
procedure can_wb_read_reg(
|
||||||
|
signal wbs_in : out wb_slv_in_type;
|
||||||
|
signal wbs_out : in wb_slv_out_type;
|
||||||
|
constant addr : in integer;
|
||||||
|
signal data : out std_logic_vector(7 downto 0);
|
||||||
|
signal clk : in std_logic);
|
||||||
|
|
||||||
procedure write_regs_from_file(
|
procedure write_regs_from_file(
|
||||||
constant filename : in string;
|
constant filename : in string;
|
||||||
signal wbs_in : out wb_slv_in_type;
|
signal wbs_in : out wb_slv_in_type;
|
||||||
signal wbs_out : in wb_slv_out_type;
|
signal wbs_out : in wb_slv_out_type;
|
||||||
signal clk : in std_logic);
|
signal clk : in std_logic);
|
||||||
|
|
||||||
|
-- procedure read_regs_with_fileaddr(
|
||||||
|
-- constant filename : in string;
|
||||||
|
-- signal wbs_in : out wb_slv_in_type;
|
||||||
|
-- signal wbs_out : in wb_slv_out_type;
|
||||||
|
-- signal clk : in std_logic);
|
||||||
|
|
||||||
procedure read_regs_with_fileaddr(
|
procedure read_regs_with_fileaddr(
|
||||||
constant filename : in string;
|
constant filename : in string;
|
||||||
|
constant out_filename : in string;
|
||||||
signal wbs_in : out wb_slv_in_type;
|
signal wbs_in : out wb_slv_in_type;
|
||||||
signal wbs_out : in wb_slv_out_type;
|
signal wbs_out : in wb_slv_out_type;
|
||||||
signal clk : in std_logic);
|
signal clk : in std_logic);
|
||||||
@@ -46,6 +71,11 @@ package can_tp is
|
|||||||
constant data : std_logic_vector(7 downto 0)
|
constant data : std_logic_vector(7 downto 0)
|
||||||
) return std_logic_vector;
|
) return std_logic_vector;
|
||||||
|
|
||||||
|
function canwb2data(
|
||||||
|
constant data_in : std_logic_vector(63 downto 0);
|
||||||
|
constant sel : std_logic_vector(3 downto 0)
|
||||||
|
) return std_logic_vector;
|
||||||
|
|
||||||
function can_crc(
|
function can_crc(
|
||||||
constant data: in std_logic_vector(0 to 63);
|
constant data: in std_logic_vector(0 to 63);
|
||||||
constant datasize: in integer)return std_logic_vector;
|
constant datasize: in integer)return std_logic_vector;
|
||||||
@@ -119,7 +149,23 @@ package body can_tp is
|
|||||||
return wbcan_data;
|
return wbcan_data;
|
||||||
end data2canwb;
|
end data2canwb;
|
||||||
|
|
||||||
--does a asynchronous wb-single-write-handshake and writes to an register of the can controller
|
function canwb2data(
|
||||||
|
constant data_in : std_logic_vector(31 downto 0);
|
||||||
|
constant sel : std_logic_vector(3 downto 0)
|
||||||
|
) return std_logic_vector is
|
||||||
|
variable data_out : std_logic_vector(7 downto 0);
|
||||||
|
begin
|
||||||
|
case sel is
|
||||||
|
when "1000" => data_out := data_in (31 downto 24);
|
||||||
|
when "0100" => data_out := data_in(23 downto 16);
|
||||||
|
when "0010" => data_out := data_in(15 downto 8);
|
||||||
|
when "0001" => data_out := data_in(7 downto 0);
|
||||||
|
when others => data_out := "0000"; -- should not occour
|
||||||
|
end case;
|
||||||
|
return data_out;
|
||||||
|
end canwb2data;
|
||||||
|
|
||||||
|
--does a synchronous wb-single-write-handshake with waitstates and writes to an register of the can controller
|
||||||
procedure can_wb_write_reg(
|
procedure can_wb_write_reg(
|
||||||
signal wbs_in : out wb_slv_in_type;
|
signal wbs_in : out wb_slv_in_type;
|
||||||
signal wbs_out : in wb_slv_out_type;
|
signal wbs_out : in wb_slv_out_type;
|
||||||
@@ -169,6 +215,18 @@ package body can_tp is
|
|||||||
wbs_in.dat <= (others=>'-');
|
wbs_in.dat <= (others=>'-');
|
||||||
wbs_in.adr <= (others=>'-');
|
wbs_in.adr <= (others=>'-');
|
||||||
|
|
||||||
|
end can_wb_read_reg;
|
||||||
|
|
||||||
|
|
||||||
|
procedure can_wb_read_reg(
|
||||||
|
signal wbs_in : out wb_slv_in_type;
|
||||||
|
signal wbs_out : in wb_slv_out_type;
|
||||||
|
constant addr : integer;
|
||||||
|
signal data : out std_logic_vector(7 downto 0);
|
||||||
|
signal clk : in std_logic) is
|
||||||
|
begin
|
||||||
|
can_wb_read_reg(wbs_in, wbs_out, addr, clk);
|
||||||
|
data <= canwb2data(wbs_out.dat, canint2sel(addr));
|
||||||
end can_wb_read_reg;
|
end can_wb_read_reg;
|
||||||
|
|
||||||
|
|
||||||
@@ -190,25 +248,57 @@ package body can_tp is
|
|||||||
can_wb_write_reg(wbs_in, wbs_out, addr, data, clk);
|
can_wb_write_reg(wbs_in, wbs_out, addr, data, clk);
|
||||||
wait for 50 ns;
|
wait for 50 ns;
|
||||||
end loop;
|
end loop;
|
||||||
|
file_close(sourcefile);
|
||||||
end procedure write_regs_from_file;
|
end procedure write_regs_from_file;
|
||||||
|
|
||||||
|
|
||||||
|
-- procedure read_regs_with_fileaddr(
|
||||||
|
-- constant filename : in string;
|
||||||
|
-- signal wbs_in : out wb_slv_in_type;
|
||||||
|
-- signal wbs_out : in wb_slv_out_type;
|
||||||
|
-- signal clk : in std_logic) is
|
||||||
|
--
|
||||||
|
-- file sourcefile : text open read_mode is filename;
|
||||||
|
-- variable input_line : line;
|
||||||
|
-- variable output_line : line;
|
||||||
|
-- variable addr : integer;
|
||||||
|
-- begin
|
||||||
|
-- while not endfile(sourcefile) loop
|
||||||
|
-- readline(sourcefile, input_line); --read line
|
||||||
|
-- read(input_line, addr); --read addr of register
|
||||||
|
-- can_wb_read_reg(wbs_in, wbs_out, addr, clk);
|
||||||
|
-- wait for 50 ns;
|
||||||
|
-- end loop;
|
||||||
|
-- file_close(sourcefile);
|
||||||
|
-- end procedure read_regs_with_fileaddr;
|
||||||
|
|
||||||
|
|
||||||
procedure read_regs_with_fileaddr(
|
procedure read_regs_with_fileaddr(
|
||||||
constant filename : in string;
|
constant filename : in string;
|
||||||
|
constant out_filename : in string;
|
||||||
signal wbs_in : out wb_slv_in_type;
|
signal wbs_in : out wb_slv_in_type;
|
||||||
signal wbs_out : in wb_slv_out_type;
|
signal wbs_out : in wb_slv_out_type;
|
||||||
signal clk : in std_logic) is
|
signal clk : in std_logic) is
|
||||||
|
|
||||||
file sourcefile : text open read_mode is filename;
|
file sourcefile : text open read_mode is filename;
|
||||||
|
file targetfile : text open write_mode is out_filename;
|
||||||
variable input_line : line;
|
variable input_line : line;
|
||||||
|
variable output_line : line;
|
||||||
variable addr : integer;
|
variable addr : integer;
|
||||||
begin
|
begin
|
||||||
while not endfile(sourcefile) loop
|
while not endfile(sourcefile) loop
|
||||||
readline(sourcefile, input_line); --read line
|
readline(sourcefile, input_line); --read line
|
||||||
read(input_line, addr); --read addr of register
|
read(input_line, addr); --read addr of register
|
||||||
can_wb_read_reg(wbs_in, wbs_out, addr, clk);
|
can_wb_read_reg(wbs_in, wbs_out, addr, clk);
|
||||||
|
--wait for 1 ns;
|
||||||
|
write(output_line,addr);
|
||||||
|
write(output_line, ' ' );
|
||||||
|
write(output_line,canwb2data(wbs_out.dat, canint2sel(addr)));
|
||||||
|
writeline(targetfile,output_line);
|
||||||
wait for 50 ns;
|
wait for 50 ns;
|
||||||
end loop;
|
end loop;
|
||||||
|
file_close(sourcefile);
|
||||||
|
file_close(targetfile);
|
||||||
end procedure read_regs_with_fileaddr;
|
end procedure read_regs_with_fileaddr;
|
||||||
|
|
||||||
function can_crc(
|
function can_crc(
|
||||||
|
|||||||
@@ -1086,8 +1086,8 @@ package body wb_tp is
|
|||||||
msto.dat <= enc_wb_dat(adr(1 downto 0),size,writedata);
|
msto.dat <= enc_wb_dat(adr(1 downto 0),size,writedata);
|
||||||
|
|
||||||
wait until rising_edge(clk);
|
wait until rising_edge(clk);
|
||||||
wait until slvo.ack = '1' for 1 ps;
|
wait until slvo.ack = '1' for 100 ns;
|
||||||
assert slvo.ack = '1' report "Slave did not ACK the write properly";
|
assert slvo.ack = '1' report "Slave did not ACK the write properly within 10 wait states";
|
||||||
|
|
||||||
wait until rising_edge(clk);
|
wait until rising_edge(clk);
|
||||||
|
|
||||||
@@ -1180,8 +1180,8 @@ package body wb_tp is
|
|||||||
msto.adr <= adr;
|
msto.adr <= adr;
|
||||||
|
|
||||||
wait until rising_edge(clk);
|
wait until rising_edge(clk);
|
||||||
wait until slvo.ack='1' for 1 ps;
|
wait until slvo.ack='1' for 100 ns;
|
||||||
assert slvo.ack='1' report "Slave did not ACK the read properly";
|
assert slvo.ack='1' report "Slave did not ACK the read properly within 10 wait states";
|
||||||
if slvo.ack='1' then
|
if slvo.ack='1' then
|
||||||
readdata <= dec_wb_dat(sel,slvo.dat);
|
readdata <= dec_wb_dat(sel,slvo.dat);
|
||||||
else
|
else
|
||||||
|
|||||||
195
soc/testbench/can_demo_tb.vhd
Normal file
195
soc/testbench/can_demo_tb.vhd
Normal file
@@ -0,0 +1,195 @@
|
|||||||
|
|
||||||
|
library ieee;
|
||||||
|
use ieee.std_logic_1164.all;
|
||||||
|
use ieee.numeric_std.all;
|
||||||
|
|
||||||
|
library work;
|
||||||
|
use work.wishbone.all;
|
||||||
|
use work.can_tp.all;
|
||||||
|
use work.config.all;
|
||||||
|
|
||||||
|
entity can_demo_tb is
|
||||||
|
end entity can_demo_tb;
|
||||||
|
|
||||||
|
architecture RTL of can_demo_tb is
|
||||||
|
|
||||||
|
|
||||||
|
component can_vhdl_top is
|
||||||
|
generic(
|
||||||
|
memaddr : generic_addr_type;
|
||||||
|
addrmask : generic_mask_type
|
||||||
|
);
|
||||||
|
port(
|
||||||
|
clk : in std_logic;
|
||||||
|
rstn : in std_logic;
|
||||||
|
wbs_i : in wb_slv_in_type;
|
||||||
|
wbs_o : out wb_slv_out_type;
|
||||||
|
rx_i : in std_logic;
|
||||||
|
tx_o : out std_logic;
|
||||||
|
irq_on : out std_logic
|
||||||
|
);
|
||||||
|
end component can_vhdl_top;
|
||||||
|
|
||||||
|
|
||||||
|
component phys_can_sim
|
||||||
|
generic(
|
||||||
|
peer_num : integer );
|
||||||
|
port(
|
||||||
|
rst : in std_logic;
|
||||||
|
rx_vector : out std_logic_vector(peer_num - 1 downto 0);
|
||||||
|
tx_vector : in std_logic_vector(peer_num - 1 downto 0) );
|
||||||
|
end component phys_can_sim;
|
||||||
|
|
||||||
|
|
||||||
|
-- management signal
|
||||||
|
signal clk : std_logic := '0';
|
||||||
|
signal rst : std_logic := '1';
|
||||||
|
signal test_result: rx_check_result;
|
||||||
|
--signal tx_frame: std_logic_vector(0 to 108);
|
||||||
|
|
||||||
|
-- signals to/from controller 1
|
||||||
|
signal wbs_i1 : wb_slv_in_type := wbs_in_default;
|
||||||
|
signal wbs_o1 : wb_slv_out_type;
|
||||||
|
signal irq_on1 : std_logic;
|
||||||
|
signal data_out : std_logic_vector(7 downto 0) := (others => '0');
|
||||||
|
|
||||||
|
-- signals to/from controller 2
|
||||||
|
signal wbs_i2 : wb_slv_in_type:= wbs_in_default;
|
||||||
|
signal wbs_o2 : wb_slv_out_type;
|
||||||
|
signal irq_on2 : std_logic;
|
||||||
|
|
||||||
|
--signals can interconnect
|
||||||
|
constant peer_num_inst : integer := 3;
|
||||||
|
signal rx_vector : std_logic_vector(peer_num_inst - 1 downto 0);
|
||||||
|
signal tx_vector : std_logic_vector(peer_num_inst - 1 downto 0);
|
||||||
|
|
||||||
|
begin
|
||||||
|
|
||||||
|
|
||||||
|
can_inst_1 : component can_vhdl_top
|
||||||
|
generic map(
|
||||||
|
memaddr=>CFG_BADR_MEM,
|
||||||
|
addrmask=>CFG_MADR_FULL
|
||||||
|
)
|
||||||
|
port map(
|
||||||
|
clk => clk,
|
||||||
|
rstn => rst,
|
||||||
|
wbs_i => wbs_i1,
|
||||||
|
wbs_o => wbs_o1,
|
||||||
|
rx_i => rx_vector(0),
|
||||||
|
tx_o => tx_vector(0),
|
||||||
|
irq_on => irq_on1);
|
||||||
|
|
||||||
|
can_inst_2 : component can_vhdl_top
|
||||||
|
generic map(
|
||||||
|
memaddr=>CFG_BADR_MEM,
|
||||||
|
addrmask=>CFG_MADR_FULL
|
||||||
|
)
|
||||||
|
port map(
|
||||||
|
clk => clk,
|
||||||
|
rstn => rst,
|
||||||
|
wbs_i => wbs_i2,
|
||||||
|
wbs_o => wbs_o2,
|
||||||
|
rx_i => rx_vector(1),
|
||||||
|
tx_o => tx_vector(1),
|
||||||
|
irq_on => irq_on2);
|
||||||
|
|
||||||
|
can_interconnect : component phys_can_sim
|
||||||
|
generic map( peer_num => peer_num_inst)
|
||||||
|
port map( rst => rst,
|
||||||
|
rx_vector => rx_vector,
|
||||||
|
tx_vector => tx_vector);
|
||||||
|
|
||||||
|
-- stimuli
|
||||||
|
stimuli: process is
|
||||||
|
begin
|
||||||
|
report "begin stimuli" severity warning;
|
||||||
|
--this tx line is used manually
|
||||||
|
tx_vector(2) <= '1';
|
||||||
|
|
||||||
|
wait for 40 ns;
|
||||||
|
rst <= '0';
|
||||||
|
|
||||||
|
|
||||||
|
--setup both can nodes
|
||||||
|
write_regs_from_file( "./testdata/default_setup.tdf", wbs_i1, wbs_o1, clk);
|
||||||
|
--wait for 1000 ns;
|
||||||
|
write_regs_from_file( "./testdata/default_setup.tdf", wbs_i2, wbs_o2, clk);
|
||||||
|
|
||||||
|
wait for 1000 ns;
|
||||||
|
--setup and execute a 2 byte transmission in controller 1
|
||||||
|
write_regs_from_file( "./testdata/data_send.tdf", wbs_i1, wbs_o1, clk);
|
||||||
|
tx_vector(2) <= tx_vector(1);
|
||||||
|
|
||||||
|
--manual ack by copying controler 2's ack
|
||||||
|
wait on tx_vector(1);
|
||||||
|
tx_vector(2) <= '0';
|
||||||
|
wait for 300 ns;
|
||||||
|
tx_vector(2) <= '1';
|
||||||
|
|
||||||
|
wait on irq_on2;
|
||||||
|
|
||||||
|
--read status register of controller 1
|
||||||
|
can_wb_read_reg(wbs_i1, wbs_o1, 2, data_out ,clk);
|
||||||
|
--read from controller 2's read buffer
|
||||||
|
--read_regs_with_fileaddr("./testdata/data_read.tdf", wbs_i2, wbs_o2, clk);
|
||||||
|
read_regs_with_fileaddr("./testdata/data_read.tdf", "./results/read_data0.tdf", wbs_i2, wbs_o2, clk);
|
||||||
|
|
||||||
|
wait for 1200 ns;
|
||||||
|
--release receive buffer of controller 2
|
||||||
|
can_wb_write_reg(wbs_i2, wbs_o2, 1, "00000100", clk);
|
||||||
|
|
||||||
|
wait for 1200 ns;
|
||||||
|
|
||||||
|
--manually transmit a 2 byte message on tx line 2 (tx_vector(2))
|
||||||
|
simulate_can_transmission("11100010111", x"770F000000000000", 2, 300 ns, rx_vector(2), tx_vector(2), test_result);
|
||||||
|
tx_vector(2) <= '1';
|
||||||
|
|
||||||
|
wait on irq_on2;
|
||||||
|
|
||||||
|
--read from both receive buffers
|
||||||
|
read_regs_with_fileaddr("./testdata/data_read.tdf", "./results/read_data1.tdf", wbs_i1, wbs_o1, clk);
|
||||||
|
read_regs_with_fileaddr("./testdata/data_read.tdf", "./results/read_data2.tdf", wbs_i2, wbs_o2, clk);
|
||||||
|
wait for 2400 ns;
|
||||||
|
--release both receive buffers
|
||||||
|
can_wb_write_reg(wbs_i1, wbs_o1, 1, "00000100", clk);
|
||||||
|
can_wb_write_reg(wbs_i2, wbs_o2, 1, "00000100", clk);
|
||||||
|
|
||||||
|
wait for 1200 ns;
|
||||||
|
report "end stimuli" severity failure;
|
||||||
|
wait;
|
||||||
|
|
||||||
|
end process stimuli;
|
||||||
|
|
||||||
|
|
||||||
|
-- clock generation
|
||||||
|
clock : process is
|
||||||
|
begin
|
||||||
|
clk <= not clk;
|
||||||
|
wait for 10 ns / 2;
|
||||||
|
end process clock;
|
||||||
|
|
||||||
|
-- input files used in this testbench:
|
||||||
|
--
|
||||||
|
-- default_setup.tdf:
|
||||||
|
-- 4 00000000
|
||||||
|
-- 5 11111111
|
||||||
|
-- 6 10000000
|
||||||
|
-- 7 01001000
|
||||||
|
-- 8 00000010
|
||||||
|
-- 0 11111110
|
||||||
|
--
|
||||||
|
-- data_send.tdf:
|
||||||
|
-- 10 10101010
|
||||||
|
-- 11 11000010
|
||||||
|
-- 12 10101010
|
||||||
|
-- 13 00001111
|
||||||
|
-- 1 00000001
|
||||||
|
--
|
||||||
|
-- data_read.tdf:
|
||||||
|
-- 20
|
||||||
|
-- 21
|
||||||
|
-- 22
|
||||||
|
-- 23
|
||||||
|
|
||||||
|
end architecture RTL;
|
||||||
@@ -1,128 +0,0 @@
|
|||||||
|
|
||||||
library ieee;
|
|
||||||
use ieee.std_logic_1164.all;
|
|
||||||
use ieee.numeric_std.all;
|
|
||||||
use work.wishbone.all;
|
|
||||||
use work.can_tp.all;
|
|
||||||
|
|
||||||
entity can_tx_sim_tb is
|
|
||||||
end entity can_tx_sim_tb;
|
|
||||||
|
|
||||||
architecture RTL of can_tx_sim_tb is
|
|
||||||
|
|
||||||
|
|
||||||
component can_vhdl_top is
|
|
||||||
generic(
|
|
||||||
memaddr : generic_addr_type;
|
|
||||||
addrmask : generic_mask_type;
|
|
||||||
);
|
|
||||||
port(
|
|
||||||
clk : in std_logic;
|
|
||||||
rstn : in std_logic;
|
|
||||||
wbs_i : in wb_slv_in_type;
|
|
||||||
wbs_o : out wb_slv_out_type;
|
|
||||||
rx_i : in std_logic;
|
|
||||||
tx_o : out std_logic;
|
|
||||||
irq_on : out std_logic
|
|
||||||
);
|
|
||||||
end component can_vhdl_top;
|
|
||||||
|
|
||||||
|
|
||||||
component phys_can_sim
|
|
||||||
generic(
|
|
||||||
peer_num : integer );
|
|
||||||
port(
|
|
||||||
rst : in std_logic;
|
|
||||||
rx_vector : out std_logic_vector(peer_num - 1 downto 0);
|
|
||||||
tx_vector : in std_logic_vector(peer_num - 1 downto 0) );
|
|
||||||
end component phys_can_sim;
|
|
||||||
|
|
||||||
|
|
||||||
-- management signal
|
|
||||||
signal clk : std_logic := '0';
|
|
||||||
signal rst : std_logic := '1';
|
|
||||||
signal test_result: rx_check_result;
|
|
||||||
signal tx_frame: std_logic_vector(0 to 108);
|
|
||||||
|
|
||||||
-- signals main controller
|
|
||||||
signal wbs_i : wb_slv_in_type;
|
|
||||||
signal wbs_o : wb_slv_out_type;
|
|
||||||
signal irq_on : std_logic;
|
|
||||||
|
|
||||||
|
|
||||||
--signals can interconnect
|
|
||||||
constant peer_num_inst : integer := 2;
|
|
||||||
signal rx_vector : std_logic_vector(peer_num_inst - 1 downto 0);
|
|
||||||
signal tx_vector : std_logic_vector(peer_num_inst - 1 downto 0);
|
|
||||||
|
|
||||||
begin
|
|
||||||
|
|
||||||
|
|
||||||
can_inst_main : component can_vhdl_top
|
|
||||||
generic map(
|
|
||||||
memaddr=>CFG_BADR_MEM,
|
|
||||||
addrmask=>CFG_MADR_FULL
|
|
||||||
)
|
|
||||||
port map(
|
|
||||||
clk => clk,
|
|
||||||
rstn => rst,
|
|
||||||
wbs_i => wbs_i,
|
|
||||||
wbs_o => wbs_o,
|
|
||||||
rx_i => rx_vector(0),
|
|
||||||
tx_o => tx_vector(0),
|
|
||||||
irq_on => irq_on);
|
|
||||||
|
|
||||||
can_interconnect : component phys_can_sim
|
|
||||||
generic map( peer_num => peer_num_inst)
|
|
||||||
port map( rst => rst,
|
|
||||||
rx_vector => rx_vector,
|
|
||||||
tx_vector => tx_vector);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
-- stimuli
|
|
||||||
stimuli: process is
|
|
||||||
--variable data : std_logic_vector (7 downto 0);
|
|
||||||
--variable addr : integer;
|
|
||||||
begin
|
|
||||||
wait for 10 ns;
|
|
||||||
rst <= '1';
|
|
||||||
wait for 40 ns;
|
|
||||||
rst <= '0';
|
|
||||||
|
|
||||||
tx_vector(1) <= '1';
|
|
||||||
write_regs_from_file( "./testdata/default_setup.tdf", wbs_i, wbs_o, clk);
|
|
||||||
wait for 8400 ns;
|
|
||||||
simulate_can_transmission("10101010111", x"770F0F0F00000000", 1, 300 ns, rx_vector(1), tx_vector(1), test_result);
|
|
||||||
wait for 2400 ns;
|
|
||||||
simulate_can_transmission("11100010111", x"770F0F0F00000000", 3, 300 ns, rx_vector(1), tx_vector(1), test_result);
|
|
||||||
wait for 8400 ns;
|
|
||||||
simulate_can_transmission("00000000011", x"770F0F0F00000000", 5, 300 ns, rx_vector(1), tx_vector(1), test_result);
|
|
||||||
wait for 8400 ns;
|
|
||||||
simulate_can_transmission("10111110011", x"770F0F0F00000000", 8, 300 ns, rx_vector(1), tx_vector(1), test_result);
|
|
||||||
tx_vector(1) <= '1';
|
|
||||||
wait;
|
|
||||||
|
|
||||||
report "end stimuli" severity warning;
|
|
||||||
|
|
||||||
end process stimuli;
|
|
||||||
|
|
||||||
sub_programm_test: process is
|
|
||||||
|
|
||||||
begin
|
|
||||||
tx_frame <= buildframe("00000000000", x"770F0F0F00000000", 1);
|
|
||||||
wait;
|
|
||||||
end process;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
-- clock generation
|
|
||||||
clock : process is
|
|
||||||
begin
|
|
||||||
clk <= not clk;
|
|
||||||
wait for 10 ns / 2;
|
|
||||||
end process clock;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
end architecture RTL;
|
|
||||||
47
soc/testbench/phys_can_sim.vhd
Normal file
47
soc/testbench/phys_can_sim.vhd
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
library ieee;
|
||||||
|
use ieee.std_logic_1164.all;
|
||||||
|
|
||||||
|
entity phys_can_sim is
|
||||||
|
generic(
|
||||||
|
peer_num : integer --number of can participants connected to the bus
|
||||||
|
);
|
||||||
|
port(
|
||||||
|
rst : in std_logic;
|
||||||
|
|
||||||
|
rx_vector : out std_logic_vector(peer_num - 1 downto 0); --vector containing all rx_signals
|
||||||
|
tx_vector : in std_logic_vector(peer_num - 1 downto 0) --vector containing all tx_signals
|
||||||
|
);
|
||||||
|
end entity;
|
||||||
|
|
||||||
|
architecture behav of phys_can_sim is
|
||||||
|
|
||||||
|
|
||||||
|
begin
|
||||||
|
|
||||||
|
|
||||||
|
process(tx_vector, rst)
|
||||||
|
|
||||||
|
variable value : std_logic := '1';
|
||||||
|
variable i : integer;
|
||||||
|
|
||||||
|
begin
|
||||||
|
if rst = '1' then
|
||||||
|
rx_vector <= (others => '1');
|
||||||
|
else
|
||||||
|
value := '1';
|
||||||
|
for i in 0 to peer_num - 1 loop
|
||||||
|
value := value and tx_vector(i);
|
||||||
|
end loop;
|
||||||
|
if value = '1' then
|
||||||
|
|
||||||
|
rx_vector <= (others => '1');
|
||||||
|
else
|
||||||
|
rx_vector <= (others => '0');
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
end process;
|
||||||
|
|
||||||
|
|
||||||
|
end architecture;
|
||||||
|
|
||||||
|
--TODO: physical transmission delay simulation if needed (in a later simulation stage)
|
||||||
BIN
warmup2.pdf
BIN
warmup2.pdf
Binary file not shown.
Reference in New Issue
Block a user