------------------------------------------------------------------------- -- Project: JCPU, a portable 8-bit RISC CPU written in VHDL -- This file: testbench for system test using Xilinx ML-402 -- Copyright (C) 2007 J. Ahrensfeld -- This library is free software; you can redistribute it and/or -- modify it under the terms of the GNU Lesser General Public -- License as published by the Free Software Foundation; either -- version 2.1 of the License, or (at your option) any later version. -- This library is distributed in the hope that it will be useful, -- but WITHOUT ANY WARRANTY; without even the implied warranty of -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -- Lesser General Public License for more details. -- You should have received a copy of the GNU Lesser General Public -- License along with this library; if not, write to the Free Software -- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -- For questions and ideas, please contact the author at jens@jayfield.org ----------------------------------------------------------------------- LIBRARY ieee; use IEEE.STD_LOGIC_1164.ALL; USE ieee.numeric_std.ALL; use work.spi_types.all; ENTITY tb_spi_master IS END tb_spi_master; ARCHITECTURE behavior OF tb_spi_master IS constant CLK_PERIOD : time := 20 ns; signal CLK : std_logic := '1'; signal RST : std_logic := '1'; signal mst_cmd_vld : STD_LOGIC := '0'; signal mst_cmd_rdy : STD_LOGIC; signal mst_cmd : cmd_t; signal mst_din_vld : STD_LOGIC := '0'; signal mst_din_rdy : STD_LOGIC; signal mst_din : unsigned(31 downto 0) := (others => '0'); signal mst_dout : unsigned(31 downto 0); signal mst_dout_vld : STD_LOGIC; signal mst_dout_re : STD_LOGIC := '0'; signal mst_shift_en : STD_LOGIC := '1'; signal mosi : STD_LOGIC; signal miso : STD_LOGIC := '0'; signal mst_clk : STD_LOGIC; signal ctrl : ctrl_t; signal status : status_t; signal mso : STD_LOGIC; signal mso_n : STD_LOGIC; signal HOLDNeg : STD_LOGIC := '1'; signal WPNeg : STD_LOGIC := '1'; signal mst_rx_data : unsigned(31 downto 0); signal slv_rx_shiftreg : unsigned(31 downto 0) := (others => '0'); signal slv_tx_shiftreg : unsigned(31 downto 0) := (others => '0'); signal slv_rx_valid_pipe : unsigned(31 downto 0) := (others => '0'); signal slv_rx_data : unsigned(31 downto 0) := (others => '0'); signal slv_rx_data_vld : STD_LOGIC; BEGIN ctrl.cpol <= '0'; ctrl.cpha <= '0'; ctrl.msb_first <= '1'; ctrl.clk_div <= X"00"; mso_n <= not mso; HOLDNeg <= '1'; WPNeg <= '1'; inst_spi_master : entity work.spi_master GENERIC MAP ( word_width => 32 ) PORT MAP ( rst => RST, clk => CLK, cmd_vld => mst_cmd_vld, cmd_rdy => mst_cmd_rdy, cmd => mst_cmd, din_vld => mst_din_vld, din_rdy => mst_din_rdy, din => mst_din, dout_re => mst_dout_re, dout_vld => mst_dout_vld, dout => mst_dout, shift_en => mst_shift_en, mosi => mosi, miso => miso, sclk => mst_clk, mso => mso, ctrl => ctrl, status => status ); inst_spi_slave: entity work.S25fl064k PORT MAP ( SCK => mst_clk, -- serial clock input SI => mosi, -- serial data input CSNeg => mso_n, -- chip select input HOLDNeg => HOLDNeg, -- hold input WPNeg => WPNeg, -- write protect input SO => miso -- SO ); CLK_GEN: process begin wait for CLK_PERIOD/2; CLK <= not CLK; end process; mst_dout_re_GEN: process begin wait for 10 us; mst_dout_re <= '1'; wait for CLK_PERIOD; mst_dout_re <= '1'; end process; RX_SLAVE_SIM_SHIFT_REG: process(mst_clk) begin if rising_edge(mst_clk) then slv_rx_data_vld <= '0'; if mso = '1' then if slv_rx_valid_pipe(slv_rx_valid_pipe'left) = '1' then slv_rx_valid_pipe <= (slv_rx_valid_pipe'left downto 1 => '0') & '1'; slv_rx_data_vld <= '1'; else slv_rx_valid_pipe <= slv_rx_valid_pipe(slv_rx_valid_pipe'left-1 downto 0) & '1'; end if; slv_rx_shiftreg <= slv_rx_shiftreg(slv_rx_shiftreg'left-1 downto 0) & mosi; end if; end if; end process; TX_SLAVE_SIM_SHIFT_REG: process(mst_clk) begin if falling_edge(mst_clk) then if slv_rx_data_vld = '1' then slv_tx_shiftreg <= slv_rx_shiftreg; else slv_tx_shiftreg <= slv_tx_shiftreg(slv_tx_shiftreg'left-1 downto 0) & '0'; end if; end if; end process; -- miso <= slv_tx_shiftreg(slv_tx_shiftreg'left); RX_SLAVE_SIM_DATA_REG: process(clk) variable data_vld : unsigned(1 downto 0); begin if mso = '0' then data_vld := "00"; elsif rising_edge(clk) then data_vld(1) := data_vld(0); data_vld(0) := slv_rx_valid_pipe(slv_rx_valid_pipe'left); if data_vld(0) = '1' and data_vld(1) = '0' then slv_rx_data <= slv_rx_shiftreg; end if; end if; end process; MASTER_TX_DATA_REG: process(clk) begin if rising_edge(clk) then if mst_dout_vld = '1' then mst_rx_data <= mst_dout; end if; end if; end process; -- Master STIMULUS: process begin wait for 600*CLK_PERIOD; RST <= '0'; wait for 6*CLK_PERIOD; wait for 600*CLK_PERIOD; wait until rising_edge(CLK); mst_din <= X"9F55AAC1"; mst_din_vld <= '1'; wait until rising_edge(CLK) and mst_din_rdy = '1'; mst_din_vld <= '0'; wait until rising_edge(CLK); mst_cmd <= to_cmd(32, 8); mst_cmd_vld <= '1'; wait until rising_edge(CLK) and mst_cmd_rdy = '1'; mst_cmd_vld <= '0'; -------------------------------------------------------- wait until rising_edge(CLK); mst_din <= X"9F00_0000"; mst_din_vld <= '1'; wait until rising_edge(CLK) and mst_din_rdy = '1'; mst_din_vld <= '0'; wait until rising_edge(CLK); mst_cmd <= to_cmd(32, 8); mst_cmd_vld <= '1'; wait until rising_edge(CLK) and mst_cmd_rdy = '1'; mst_cmd_vld <= '0'; -------------------------------------------------------- wait until rising_edge(CLK); mst_din <= X"9F00_0000"; mst_din_vld <= '1'; wait until rising_edge(CLK) and mst_din_rdy = '1'; mst_din_vld <= '0'; wait until rising_edge(CLK); mst_cmd <= to_cmd(656, 8); mst_cmd_vld <= '1'; wait until rising_edge(CLK) and mst_cmd_rdy = '1'; mst_cmd_vld <= '0'; -------------------------------------------------------- wait until rising_edge(CLK); mst_din <= X"030155C1"; mst_din_vld <= '1'; wait until rising_edge(CLK) and mst_din_rdy = '1'; mst_din_vld <= '0'; wait until rising_edge(CLK); mst_cmd <= to_cmd(64, 32); mst_cmd_vld <= '1'; wait until rising_edge(CLK) and mst_cmd_rdy = '1'; mst_cmd_vld <= '0'; wait for 200*CLK_PERIOD; wait until rising_edge(CLK) and mst_din_rdy = '1'; mst_din <= X"0311FF05"; mst_din_vld <= '1'; wait until rising_edge(CLK) and mst_din_rdy = '1'; mst_din_vld <= '0'; -------------------------------------------------------- mst_din <= X"03000000"; for i in 0 to 16 loop wait until rising_edge(CLK); mst_din_vld <= '1'; wait until rising_edge(CLK) and mst_din_rdy = '1'; mst_din_vld <= '0'; mst_din <= mst_din + 1; wait until rising_edge(CLK); mst_cmd <= to_cmd(64, 32); mst_cmd_vld <= '1'; wait until rising_edge(CLK) and mst_cmd_rdy = '1'; mst_cmd_vld <= '0'; wait until rising_edge(CLK) and mso = '1'; wait until rising_edge(CLK) and mso = '0'; end loop; -------------------------------------------------------- wait until rising_edge(CLK); mst_din <= X"0355AAC1"; mst_din_vld <= '1'; wait until rising_edge(CLK) and mst_din_rdy = '1'; mst_din_vld <= '0'; wait until rising_edge(CLK); mst_cmd <= to_cmd(64, 32); mst_cmd_vld <= '1'; wait until rising_edge(CLK) and mst_cmd_rdy = '1'; mst_cmd_vld <= '0'; -------------------------------------------------------- wait until rising_edge(CLK); mst_din <= X"0355AA00"; mst_din_vld <= '1'; wait until rising_edge(CLK) and mst_din_rdy = '1'; mst_din_vld <= '0'; wait until rising_edge(CLK); mst_cmd <= to_cmd(32, 32); mst_cmd_vld <= '1'; wait until rising_edge(CLK) and mst_cmd_rdy = '1'; mst_cmd_vld <= '0'; -------------------------------------------------------- wait until rising_edge(CLK); mst_din <= X"0311AAC1"; mst_din_vld <= '1'; wait until rising_edge(CLK) and mst_din_rdy = '1'; mst_din_vld <= '0'; wait until rising_edge(CLK); mst_cmd <= to_cmd(24, 32); mst_cmd_vld <= '1'; wait until rising_edge(CLK) and mst_cmd_rdy = '1'; mst_cmd_vld <= '0'; wait; end process; END;