-------------------------------------------------------------------------
-- Project: JCPU, a portable 8-bit RISC CPU written in VHDL
-- This file: cpu_embedded using cpu_core and rom
--
-- Copyright (C) 2007 J. Ahrensfeld
--
-- This program is free software: you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation, either version 3 of the License, or
-- (at your option) any later version.
--
-- This program 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 General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program.  If not, see <http://www.gnu.org/licenses/>.
--
-- 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.fifo_ctrl_pkg.all;
use work.sdram_config.all;
use work.sdram_types.all;

entity tb_sdram_ctrl_frontend is
end;

architecture struct of tb_sdram_ctrl_frontend is

	-- Number of user data words for simulation
	constant CLK_PERIOD		: time := 10 ns;
	constant BURST_LEN		: natural := 2;

	signal rst				: std_logic := '1';  
	signal clk				: std_logic := '0';  
	signal rst_out			: std_logic;  
	signal clk_out			: std_logic;  
	signal clk_fb			: std_logic;  
	signal part_clk_p		: std_logic;  
	signal part_clk_n		: std_logic;  
	signal part_cke			: std_logic;  
	signal part_cs_n		: std_logic;  
	signal part_we_n		: std_logic;  
	signal part_ras_n		: std_logic;  
	signal part_cas_n		: std_logic;  
	signal part_ba			: unsigned(DDR_BANK_WIDTH-1 downto 0) := (others => '0');
	signal part_dm			: unsigned(DDR_DM_WIDTH-1 downto 0) := (others => '0');
	signal part_dqs			: unsigned(DDR_DQS_WIDTH-1 downto 0) := (others => '0');
	signal part_addr		: unsigned(DDR_ADDR_WIDTH-1 downto 0) := (others => '0');
	signal part_data		: unsigned(DDR_DATA_WIDTH-1 downto 0) := (others => '0');

	signal addr				: user_addr_t := (others => '0');
	signal r_wn				: std_logic := '0';
	signal en				: std_logic := '0';
	signal busy				: std_logic;
	signal din				: unsigned(2*DDR_DATA_WIDTH-1 downto 0) := (others => '0');
	signal be				: unsigned(2*DDR_DM_WIDTH-1 downto 0) := "1111";
	signal dout				: unsigned(2*DDR_DATA_WIDTH-1 downto 0) := (others => '0');
	signal dout_vld			: std_logic;
	signal dout_re			: std_logic;
	signal dout_reg			: unsigned(2*DDR_DATA_WIDTH-1 downto 0) := (others => '0');

begin 
   
	clk_fb	<= part_clk_p after 1 ns;

	-- DDR SDRAM Controller Core
	inst_sdram_ctrl_frontend : entity work.sdram_ctrl_frontend
	Generic map
	(
		BL 				=> BURST_LEN,
		read_phaseshift => 0,
		f_sysclk 		=> 100E6,
		fifo_depth		=> 4
	)
	Port map
	(
	
		sys_rst_in			=> rst,
		sys_clk_in			=> clk,

		sys_rst_out			=> rst_out,
		sys_clk_out			=> clk_out,
		sys_clk_fb			=> clk_fb,
		
		busy				=> busy,
		en					=> en,
		r_wn				=> r_wn,
		be					=> be,
		addr				=> addr,
		din					=> din,
		dout				=> dout,
		dout_re				=> dout_re,
		dout_vld			=> dout_vld,
		
		-- SDRAM signals
		sd_clk_p			=> part_clk_p,
		sd_clk_n			=> part_clk_n,
		sd_cke				=> part_cke,
		sd_cs_n				=> part_cs_n,
		sd_cas_n			=> part_cas_n,
		sd_ras_n			=> part_ras_n,
		sd_we_n				=> part_we_n,
		sd_addr				=> part_addr,
		sd_ba				=> part_ba,
		sd_dm				=> part_dm,
		sd_dqs				=> part_dqs,
		sd_data				=> part_data
		
	);
   
   -- MICRON DDR SDRAM Simulation Model
   i_mt46v16m16_0 : entity work.mt46v16m16 
      port map (
         dq    => std_logic_vector(part_data),
         dqs   => std_logic_vector(part_dqs),
         addr  => std_logic_vector(part_addr),
         ba    => std_logic_vector(part_ba),
         clk   => part_clk_p,
         clk_n => part_clk_n,
         cke   => part_cke,
         cs_n  => part_cs_n,
         ras_n => part_ras_n,
         cas_n => part_cas_n,
         we_n  => part_we_n,
         dm    => std_logic_vector(part_dm)
	);

CLK_GEN: process
	begin
		wait for CLK_PERIOD/2;
		clk <= not clk;
	end process;

read_register:
	process(clk_out)
	begin
		if rising_edge(clk_out) then
			if dout_vld = '1' then
				dout_reg	<= dout;
			end if;
		end if;
	end process;
		
------------------------------------------------------------------------------------------
	dout_re	<= dout_vld;
	
	process
	begin
         
	-- Write MAX_WORDS to DDR SDRAM Controller
	wait for 4*CLK_PERIOD;
	rst <= '0';

	wait for 4*CLK_PERIOD;
	wait until rising_edge(clk_out) and rst_out='0';

	for i in 0 to 999 loop

		en		<= '1';
		r_wn	<= '0';
		din		<= to_unsigned(i, 32);
		addr	<= to_unsigned(2*i, 24);
		wait until rising_edge(clk_out) and busy = '0';
	end loop;	

	for i in 0 to 999 loop
		en		<= '1';
		r_wn	<= '1';
		din		<= to_unsigned(i, 32);
		addr	<= to_unsigned(2*i, 24);
		wait until rising_edge(clk_out) and busy = '0';
	end loop;	

	en		<= '1';
	r_wn	<= '0';
	din		<= X"01020304";
	addr	<= X"000000";

	wait until rising_edge(clk_out) and busy = '0';
	en		<= '1';
	r_wn	<= '0';
	din		<= X"05060708";
	addr	<= X"000002";

	wait until rising_edge(clk_out) and busy = '0';
	en		<= '1';
	r_wn	<= '0';
	din		<= X"00001111";
	addr	<= X"000004";

	wait until rising_edge(clk_out) and busy = '0';
	en		<= '1';
	r_wn	<= '0';
	din		<= X"22223333";
	addr	<= X"000006";

	wait until rising_edge(clk_out) and busy = '0';
	en		<= '1';
	r_wn	<= '0';
	din		<= X"44445555";
	addr	<= X"000008";

	wait until rising_edge(clk_out) and busy = '0';
	en		<= '1';
	r_wn	<= '0';
	din		<= X"66667777";
	addr	<= X"00000a";

	wait until rising_edge(clk_out) and busy = '0';
	en		<= '1';
	r_wn	<= '0';
	din		<= X"88889999";
	addr	<= X"00000c";

	wait until rising_edge(clk_out) and busy = '0';
	en		<= '1';
	r_wn	<= '0';
	din		<= X"AAAABBBB";
	addr	<= X"00000e";

	wait until rising_edge(clk_out) and busy = '0';
	en		<= '1';
	r_wn	<= '0';
	din		<= X"CCCCDDDD";
	addr	<= X"000010";

	wait until rising_edge(clk_out) and busy = '0';
	en		<= '1';
	r_wn	<= '0';
	din		<= X"EEEEFFFF";
	addr	<= X"000012";

	wait until rising_edge(clk_out) and busy = '0';
	en		<= '1';
	r_wn	<= '0';
	din		<= X"FFFFFFFF";
	addr	<= X"000014";

	wait until rising_edge(clk_out) and busy = '0';
	en		<= '1';
	r_wn	<= '1';
	addr	<= X"000014";

	wait until rising_edge(clk_out) and busy = '0';
	en		<= '1';
	r_wn	<= '0';
	din		<= X"87CCCCCC";
	be		<= "1000";
	addr	<= X"000014";

	wait until rising_edge(clk_out) and busy = '0';
	en		<= '1';
	r_wn	<= '1';
	addr	<= X"000014";

	wait until rising_edge(clk_out) and busy = '0';
	en		<= '1';
	r_wn	<= '0';
	din		<= X"CC65CCCC";
	be		<= "0100";
	addr	<= X"000014";

	wait until rising_edge(clk_out) and busy = '0';
	en		<= '1';
	r_wn	<= '1';
	addr	<= X"000014";

	wait until rising_edge(clk_out) and busy = '0';
	en		<= '1';
	r_wn	<= '0';
	din		<= X"CCCC43CC";
	be		<= "0010";
	addr	<= X"000014";

	wait until rising_edge(clk_out) and busy = '0';
	en		<= '1';
	r_wn	<= '1';
	addr	<= X"000014";

	wait until rising_edge(clk_out) and busy = '0';
	en		<= '1';
	r_wn	<= '0';
	din		<= X"89ABCDEF";
	addr	<= X"000016";

	wait until rising_edge(clk_out) and busy = '0';
	en		<= '1';
	r_wn	<= '0';
	din		<= X"CCCCCC21";
	be		<= "0001";
	addr	<= X"000014";

	wait until rising_edge(clk_out) and busy = '0';
	en		<= '1';
	r_wn	<= '1';
	addr	<= X"000014";

	wait until rising_edge(clk_out) and busy = '0';
	en		<= '1';
	r_wn	<= '0';
	din		<= X"55555555";
	be		<= "1010";
	addr	<= X"000014";

	wait until rising_edge(clk_out) and busy = '0';
	en		<= '1';
	r_wn	<= '1';
	addr	<= X"000014";

	wait until rising_edge(clk_out) and busy = '0';
	en		<= '1';
	r_wn	<= '0';
	din		<= X"AAAAAAAA";
	be		<= "0101";
	addr	<= X"000014";

	wait until rising_edge(clk_out) and busy = '0';
	en		<= '1';
	r_wn	<= '1';
	addr	<= X"000014";

	wait until rising_edge(clk_out) and busy = '0';
	be		<= "1111";
	en		<= '1';
	r_wn	<= '0';
	din		<= X"11223344";
	addr	<= X"000018";

	wait until rising_edge(clk_out) and busy = '0';
	r_wn	<= '1';
	addr 	<= X"000010";

	wait until rising_edge(clk_out) and busy = '0';
	en		<= '1';
	r_wn	<= '0';
	din 	<= X"55667788";
	addr	<= X"00001a";

	wait until rising_edge(clk_out) and busy = '0';
	en		<= '1';
	r_wn	<= '0';
	din <= X"99990000";
	addr <= X"00001c";

	wait until rising_edge(clk_out) and busy = '0';
	en		<= '1';
	r_wn	<= '0';
	din 	<= X"AAAA5555";
	addr 	<= X"000020";

	wait until rising_edge(clk_out) and busy = '0';
	r_wn	<= '1';
	addr 	<= X"000000";

	wait until rising_edge(clk_out) and busy = '0';
	r_wn	<= '1';
	addr 	<= X"000018";

	wait until rising_edge(clk_out) and busy = '0';
	r_wn	<= '1';
	addr 	<= X"00001A";

	wait until rising_edge(clk_out) and busy = '0';
	r_wn	<= '1';
	addr	 <= X"00001C";

	wait until rising_edge(clk_out) and busy = '0';
	r_wn	<= '1';
	addr 	<= X"000020";

	wait until rising_edge(clk_out) and busy = '0';
	en <= '0';

	wait;
	
	end process;
	
end architecture struct;
