Created
May 18, 2022 06:25
-
-
Save imuguruza/9d347bcb641aa9bab0856d5de4ba7e0f to your computer and use it in GitHub Desktop.
SPI Salve TB
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
-------------------------------------------------------------------------------- | |
-- PROJECT: SPI MASTER AND SLAVE FOR FPGA | |
-------------------------------------------------------------------------------- | |
-- AUTHORS: Jakub Cabal <jakubcabal@gmail.com> | |
-- LICENSE: The MIT License, please read LICENSE file | |
-- WEBSITE: https://github.com/jakubcabal/spi-fpga | |
-------------------------------------------------------------------------------- | |
-- modified by imuguruza | |
----------------------------------------- | |
--/ HEADER 16x bits /-- SPI 16x bits chunk 1 | |
----------------------------------------- | |
--/ MSB..MSB-16 DATA 16xbits /-- SPI 16x bits chunk 2 | |
----------------------------------------- | |
--/ 7..0 DATA 8xbits | CRC | EMPTY 7x bits /-- SPI 16x bits chunk 3 | |
----------------------------------------- | |
library IEEE; | |
use IEEE.STD_LOGIC_1164.ALL; | |
use IEEE.NUMERIC_STD.ALL; | |
use IEEE.MATH_REAL.ALL; | |
entity TOP_TB is | |
Generic ( | |
CLK_FREQ : natural := 50e6; -- system clock frequency in Hz | |
SPI_FREQ : natural := 1e6; -- spi clock frequency in Hz | |
TRANS_COUNT : natural := 1e4; -- number of test transaction | |
DATA_SIZE : integer := 24; --number of data bits in message | |
SPI_DATA_SIZE : integer := 16 --number of data bits in message | |
); | |
end entity; | |
architecture SIM of TOP_TB is | |
constant CLK_PERIOD : time := 1 ns * integer(real(1e9)/real(CLK_FREQ)); | |
constant SPI_PERIOD : time := 1 ns * integer(real(1e9)/real(SPI_FREQ)); | |
constant FRAME_HEADER_WIDTH : INTEGER := 16; -- HEADER SIZE, 16 bits | |
constant FRAME_HEADER_AND_DATA_WIDTH : INTEGER := DATA_SIZE + FRAME_HEADER_WIDTH; | |
constant MESSAGE_HEADER : std_logic_vector (FRAME_HEADER_WIDTH - 1 DOWNTO 0) := x"CAFE"; | |
signal CLK : std_logic; | |
signal RST : std_logic; | |
signal sclk : std_logic := '0'; | |
signal cs_n : std_logic := '1'; | |
signal mosi : std_logic; | |
signal miso : std_logic := '0'; | |
signal dummy_miso : std_logic := '0'; | |
signal spi_mdi : std_logic_vector(SPI_DATA_SIZE-1 downto 0); | |
signal spi_mdo : std_logic_vector(SPI_DATA_SIZE-1 downto 0); | |
signal data : std_logic_vector(DATA_SIZE-1 downto 0); | |
signal sim_done : std_logic := '0'; | |
signal FRAME_HEADER_AND_DATA : std_logic_vector(FRAME_HEADER_AND_DATA_WIDTH-1 downto 0); | |
signal DATA_M_2_S : std_logic_vector (DATA_SIZE-1 DOWNTO 0); | |
signal CRC : std_logic; | |
procedure CALCULATE_CRC ( | |
signal MESSAGE : in std_logic_vector ((FRAME_HEADER_WIDTH + DATA_SIZE) - 1 DOWNTO 0); | |
signal CRC_VAL : out std_logic | |
) is | |
begin | |
for i in 0 to FRAME_HEADER_WIDTH + DATA_SIZE - 2 loop | |
CRC_VAL <= MESSAGE ( (FRAME_HEADER_WIDTH + DATA_SIZE) - 1 - i) | |
xor MESSAGE ( (FRAME_HEADER_WIDTH + DATA_SIZE) - 2 - i); | |
end loop; | |
end procedure; | |
procedure SPI_MASTER ( | |
constant SPI_PER : time; | |
signal SMM_MDI : out std_logic_vector(SPI_DATA_SIZE-1 downto 0); | |
signal SMM_MDO : in std_logic_vector(SPI_DATA_SIZE-1 downto 0); | |
signal SMM_SCLK : out std_logic; | |
signal SMM_CS_N : out std_logic; | |
signal SMM_MOSI : out std_logic; | |
signal SMM_MISO : in std_logic | |
) is | |
begin | |
SMM_CS_N <= '0'; | |
for i in 0 to (SPI_DATA_SIZE-1) loop | |
SMM_SCLK <= '0'; | |
SMM_MOSI <= SMM_MDO(SPI_DATA_SIZE-1-i); | |
wait for SPI_PER/2; | |
SMM_SCLK <= '1'; | |
SMM_MDI(SPI_DATA_SIZE-1-i) <= SMM_MISO; | |
wait for SPI_PER/2; | |
end loop; | |
SMM_SCLK <= '0'; | |
wait for SPI_PER/2; | |
SMM_CS_N <= '1'; | |
end procedure; | |
begin | |
dut : entity work.TOP | |
generic map ( | |
DATA_SIZE => DATA_SIZE | |
) | |
port map ( | |
i_clk => CLK, | |
i_reset => RST, | |
-- SPI MASTER INTERFACE | |
i_sclk => sclk, | |
i_cs_n => cs_n, | |
i_mosi => mosi, | |
o_miso => miso, | |
----------- | |
o_data => data | |
); | |
clk_gen_p : process | |
begin | |
CLK <= '0'; | |
wait for CLK_PERIOD/2; | |
CLK <= '1'; | |
wait for CLK_PERIOD/2; | |
if (sim_done = '1') then | |
wait; | |
end if; | |
end process; | |
rst_gen_p : process | |
begin | |
report "======== SIMULATION START! ========"; | |
RST <= '1'; | |
wait for CLK_PERIOD*3; | |
RST <= '0'; | |
wait; | |
end process; | |
-- ------------------------------------------------------------------------- | |
-- DUT TEST | |
-- ------------------------------------------------------------------------- | |
test : process | |
begin | |
wait until RST = '0'; | |
spi_mdo <= x"0000"; | |
spi_mdi <= x"0000"; | |
wait for CLK_PERIOD*10; | |
-- compose frame header and data and crc | |
DATA_M_2_S <= x"A0A0A0"; | |
wait for CLK_PERIOD*10; | |
FRAME_HEADER_AND_DATA <= JEMA_MESSAGE_HEADER & DATA_M_2_S; | |
wait for CLK_PERIOD*10; | |
CALCULATE_CRC(FRAME_HEADER_AND_DATA, CRC); | |
wait for CLK_PERIOD*10; | |
report "======== Sending frame with data x'A0A0A0'... ========"; | |
-- send chunk 1 | |
spi_mdo <= MESSAGE_HEADER; | |
wait for CLK_PERIOD*10; | |
SPI_MASTER(SPI_PERIOD, spi_mdi, spi_mdo, sclk, cs_n, mosi, dummy_miso); | |
wait for CLK_PERIOD*10; | |
-- send chunk 2 | |
spi_mdo <= DATA_M_2_S(23 DOWNTO 8); | |
wait for CLK_PERIOD*10; | |
SPI_MASTER(SPI_PERIOD, spi_mdi, spi_mdo, sclk, cs_n, mosi, dummy_miso); | |
wait for CLK_PERIOD*10; | |
-- send chunk 3, with 0 empty fields | |
spi_mdo <= DATA_M_2_S(7 DOWNTO 0) & CRC & "0000000"; | |
wait for CLK_PERIOD*10; | |
SPI_MASTER(SPI_PERIOD, spi_mdi, spi_mdo, sclk, cs_n, mosi, dummy_miso); | |
wait for CLK_PERIOD*10; | |
-- Check data out of DUT | |
if (data /= DATA_M_2_S ) then | |
report "======== Data out not expected, error! ========"; | |
else | |
report "======== Data out expected, ok! ========"; | |
end if; | |
-- compose frame header and data and crc | |
DATA_M_2_S <= x"0F0F0F"; | |
wait for CLK_PERIOD; | |
FRAME_HEADER_AND_DATA <= MESSAGE_HEADER & DATA_M_2_S; | |
wait for CLK_PERIOD; | |
CALCULATE_CRC(FRAME_HEADER_AND_DATA, CRC); | |
wait for CLK_PERIOD; | |
report "======== Sending frame with data x'0F0F0F'... ========"; | |
-- send chunk 1 | |
spi_mdo <= MESSAGE_HEADER; | |
wait for CLK_PERIOD; | |
SPI_MASTER(SPI_PERIOD, spi_mdi, spi_mdo, sclk, cs_n, mosi, dummy_miso); | |
wait for CLK_PERIOD*5; | |
-- send chunk 2 | |
spi_mdo <= DATA_M_2_S(23 DOWNTO 8); | |
wait for CLK_PERIOD; | |
SPI_MASTER(SPI_PERIOD, spi_mdi, spi_mdo, sclk, cs_n, mosi, dummy_miso); | |
wait for CLK_PERIOD*5; | |
-- send chunk 3, with 0 empty fields | |
spi_mdo <= DATA_M_2_S(7 DOWNTO 0) & CRC & "0000000"; | |
wait for CLK_PERIOD; | |
SPI_MASTER(SPI_PERIOD, spi_mdi, spi_mdo, sclk, cs_n, mosi, dummy_miso); | |
wait for CLK_PERIOD*5; | |
-- Check data out of DUT | |
if (data /= DATA_M_2_S ) then | |
report "======== Data out not expected, error! ========"; | |
else | |
report "======== Data out expected, ok! ========"; | |
end if; | |
------------------------------------------------------------------------------- | |
DATA_M_2_S <= x"0B0B0B"; | |
wait for CLK_PERIOD; | |
FRAME_HEADER_AND_DATA <= MESSAGE_HEADER & DATA_M_2_S; | |
wait for CLK_PERIOD; | |
CALCULATE_CRC(FRAME_HEADER_AND_DATA, CRC); | |
wait for CLK_PERIOD; | |
report "======== Sending frame with data x'0B0B0B' with wrong CRC... ========"; | |
-- send chunk 1 | |
spi_mdo <= MESSAGE_HEADER; | |
wait for CLK_PERIOD; | |
SPI_MASTER(SPI_PERIOD, spi_mdi, spi_mdo, sclk, cs_n, mosi, dummy_miso); | |
wait for CLK_PERIOD*5; | |
-- send chunk 2 | |
spi_mdo <= DATA_M_2_S(23 DOWNTO 8); | |
wait for CLK_PERIOD; | |
SPI_MASTER(SPI_PERIOD, spi_mdi, spi_mdo, sclk, cs_n, mosi, dummy_miso); | |
wait for CLK_PERIOD*5; | |
-- send chunk 3, with 0 empty fields | |
spi_mdo <= DATA_M_2_S(7 DOWNTO 0) & not CRC & "0000000"; | |
wait for CLK_PERIOD; | |
SPI_MASTER(SPI_PERIOD, spi_mdi, spi_mdo, sclk, cs_n, mosi, dummy_miso); | |
wait for CLK_PERIOD*5; | |
-- Check data out of DUT | |
if (data /= x"0F0F0F" ) then | |
report "======== Data out not expected, error! ========"; | |
else | |
report "======== Data out expected, ok! ========"; | |
end if; | |
------------------------------------------------------------------------------- | |
------------------------------------------------------------------------------- | |
DATA_M_2_S <= x"0B0B0B"; | |
wait for CLK_PERIOD; | |
FRAME_HEADER_AND_DATA <= MESSAGE_HEADER & DATA_M_2_S; | |
wait for CLK_PERIOD; | |
CALCULATE_CRC(FRAME_HEADER_AND_DATA, CRC); | |
wait for CLK_PERIOD; | |
report "======== Sending frame with data x'0C0C0C' with wrong Header... ========"; | |
-- send chunk 1 | |
spi_mdo <= x"EFAC"; | |
wait for CLK_PERIOD; | |
SPI_MASTER(SPI_PERIOD, spi_mdi, spi_mdo, sclk, cs_n, mosi, dummy_miso); | |
wait for CLK_PERIOD*5; | |
-- send chunk 2 | |
spi_mdo <= DATA_M_2_S(23 DOWNTO 8); | |
wait for CLK_PERIOD; | |
SPI_MASTER(SPI_PERIOD, spi_mdi, spi_mdo, sclk, cs_n, mosi, dummy_miso); | |
wait for CLK_PERIOD*5; | |
-- send chunk 3, with 0 empty fields | |
spi_mdo <= DATA_M_2_S(7 DOWNTO 0) & CRC & "0000000"; | |
wait for CLK_PERIOD; | |
SPI_MASTER(SPI_PERIOD, spi_mdi, spi_mdo, sclk, cs_n, mosi, dummy_miso); | |
wait for CLK_PERIOD*5; | |
-- Check data out of DUT | |
if (data /= x"0F0F0F" ) then | |
report "======== Data out not expected, error! ========"; | |
else | |
report "======== Data out expected, ok! ========"; | |
end if; | |
------------------------------------------------------------------------------- | |
------------------------------------------------------------------------------- | |
DATA_M_2_S <= x"0B0B0B"; | |
wait for CLK_PERIOD; | |
FRAME_HEADER_AND_DATA <= MESSAGE_HEADER & DATA_M_2_S; | |
wait for CLK_PERIOD; | |
CALCULATE_CRC(FRAME_HEADER_AND_DATA, CRC); | |
wait for CLK_PERIOD; | |
report "======== Sending frame with data x'0B0B0B' with different message tail... ========"; | |
-- send chunk 1 | |
spi_mdo <= MESSAGE_HEADER; | |
wait for CLK_PERIOD; | |
SPI_MASTER(SPI_PERIOD, spi_mdi, spi_mdo, sclk, cs_n, mosi, dummy_miso); | |
wait for CLK_PERIOD*5; | |
-- send chunk 2 | |
spi_mdo <= DATA_M_2_S(23 DOWNTO 8); | |
wait for CLK_PERIOD; | |
SPI_MASTER(SPI_PERIOD, spi_mdi, spi_mdo, sclk, cs_n, mosi, dummy_miso); | |
wait for CLK_PERIOD*5; | |
-- send chunk 3, with 0 empty fields | |
spi_mdo <= DATA_M_2_S(7 DOWNTO 0) & CRC & "1010101"; | |
wait for CLK_PERIOD; | |
SPI_MASTER(SPI_PERIOD, spi_mdi, spi_mdo, sclk, cs_n, mosi, dummy_miso); | |
wait for CLK_PERIOD*5; | |
-- Check data out of DUT | |
if (data /= DATA_M_2_S ) then | |
report "======== Data out not expected, error! ========"; | |
else | |
report "======== Data out expected, ok! ========"; | |
end if; | |
------------------------------------------------------------------------------- | |
report "======== SIMULATION SUCCESSFULLY COMPLETED! ========"; | |
sim_done <= '1'; | |
wait for CLK_PERIOD*10; | |
end process; | |
end architecture; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment