-------------------------------------------------------------------------
-- 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_flash_wb IS
END tb_spi_flash_wb;

ARCHITECTURE behavior OF tb_spi_flash_wb IS 

	constant CLK_PERIOD		: time := 20 ns;

	signal CLK				: std_logic := '1';
	signal RST				: std_logic := '1';
	signal CYC_I			: STD_LOGIC := '0';
	signal STB_I			: STD_LOGIC := '0';
	signal SEL_I			: unsigned(3 downto 0) := "1111";
	signal WE_I				: STD_LOGIC := '0';
	signal ACK_O			: STD_LOGIC;
	signal SRDY_O			: STD_LOGIC;
	signal MRDY_I			: STD_LOGIC := '1';
	signal ADDR_I			: unsigned(31 downto 0) := (others => '0');
	signal DAT_I			: unsigned(31 downto 0) := (others => '0');
	signal DAT_O			: unsigned(31 downto 0);
	signal INT_O			: STD_LOGIC;

	signal mosi				: STD_LOGIC;
	signal miso				: STD_LOGIC := '0';
	signal mst_clk			: STD_LOGIC;
	signal mso				: STD_LOGIC;
	signal mso_n			: STD_LOGIC;
	signal HOLDNeg			: STD_LOGIC := '1';
	signal WPNeg			: STD_LOGIC := '1';

BEGIN

	mso_n				<= not mso;
	HOLDNeg				<= '1';
	WPNeg				<= '1';
	
uut : entity work.spi_flash_wb
	GENERIC MAP
	(
		FLASH_ADDR_BITS	=> 24,
		CACHE_ADDR_BITS	=> 6
	)
	PORT MAP
	(
		CLK_I			=> CLK,
		RST_I			=> RST,
		CYC_I			=> CYC_I,
		STB_I			=> STB_I,
		SEL_I			=> SEL_I,
		WE_I			=> WE_I,
		ACK_O			=> ACK_O,
		SRDY_O			=> SRDY_O,
		MRDY_I			=> MRDY_I,
		ADDR_I			=> ADDR_I,
		DAT_I			=> DAT_I,
		DAT_O			=> DAT_O,
		INT_O			=> INT_O,
		spi_hold		=> '0',
		spi_clk			=> mst_clk,
		spi_ss			=> mso,
		spi_miso		=> miso,
		spi_mosi		=> mosi
		
	);

inst_spi_slave: entity work.S25fl064k
	GENERIC MAP
	(	
		UserPreload		=> TRUE,
		mem_file_name	=> "tb_spi_flash_wb.mem",
		screg_file_name	=> "none"
		
	)
    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;

-- Master
STIMULUS: process


	begin

		wait for 600*CLK_PERIOD;
		RST <= '0';
		wait for 600*CLK_PERIOD;

		wait until rising_edge(CLK);
		ADDR_I	<= X"0100_0000";
		STB_I	<= '1';
		CYC_I	<= '1';
		wait until rising_edge(CLK) and SRDY_O = '1';
		STB_I	<= '0';
		wait until rising_edge(CLK) and ACK_O = '1';
		CYC_I	<= '0';
		
		wait for 10*CLK_PERIOD;
		wait until rising_edge(CLK);
		ADDR_I	<= X"0000_0000";
		STB_I	<= '1';
		CYC_I	<= '1';
		wait until rising_edge(CLK) and SRDY_O = '1';
		STB_I	<= '0';
		wait until rising_edge(CLK) and ACK_O = '1';
		CYC_I	<= '0';
		
		wait for 10*CLK_PERIOD;
		wait until rising_edge(CLK);
		ADDR_I	<= X"0000_0004";
		STB_I	<= '1';
		CYC_I	<= '1';
		wait until rising_edge(CLK) and SRDY_O = '1';
		STB_I	<= '0';
		wait until rising_edge(CLK) and ACK_O = '1';
		CYC_I	<= '0';

		wait for 10*CLK_PERIOD;
		wait until rising_edge(CLK);
		ADDR_I	<= X"0000_0100";
		STB_I	<= '1';
		CYC_I	<= '1';
		wait until rising_edge(CLK) and SRDY_O = '1';
		STB_I	<= '0';
		wait until rising_edge(CLK) and ACK_O = '1';
		CYC_I	<= '0';

		wait for 10*CLK_PERIOD;
		CYC_I	<= '1';

		for i in 0 to 63 loop
			ADDR_I	<= to_unsigned(4*i, 32);
			STB_I	<= '1';
			wait until rising_edge(CLK) and SRDY_O = '1';
			STB_I	<= '0';
			wait until rising_edge(CLK) and ACK_O = '1';
			
		end loop;
		wait for 10*CLK_PERIOD;
		CYC_I	<= '1';

		wait; 
	
	end process;
	
END;
