-- WARNING: Do NOT edit the input and output ports in this file in a text
-- editor if you plan to continue editing the block that represents it in
-- the Block Editor! File corruption is VERY likely to occur.

-- Copyright (C) 1991-2004 Altera Corporation
-- Any  megafunction  design,  and related netlist (encrypted  or  decrypted),
-- support information,  device programming or simulation file,  and any other
-- associated  documentation or information  provided by  Altera  or a partner
-- under  Altera's   Megafunction   Partnership   Program  may  be  used  only
-- to program  PLD  devices (but not masked  PLD  devices) from  Altera.   Any
-- other  use  of such  megafunction  design,  netlist,  support  information,
-- device programming or simulation file,  or any other  related documentation
-- or information  is prohibited  for  any  other purpose,  including, but not
-- limited to  modification,  reverse engineering,  de-compiling, or use  with
-- any other  silicon devices,  unless such use is  explicitly  licensed under
-- a separate agreement with  Altera  or a megafunction partner.  Title to the
-- intellectual property,  including patents,  copyrights,  trademarks,  trade
-- secrets,  or maskworks,  embodied in any such megafunction design, netlist,
-- support  information,  device programming or simulation file,  or any other
-- related documentation or information provided by  Altera  or a megafunction
-- partner, remains with Altera, the megafunction partner, or their respective
-- licensors. No other licenses, including any licenses needed under any third
-- party's intellectual property, are provided herein.


-- Generated by Quartus II Version 4.1 (Build Build 208 09/10/2004)
-- Created on Sat Nov 13 01:28:56 2004

library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;

USE ieee.std_logic_arith.all  ; 
USE ieee.numeric_std.ALL;

--  Entity Declaration

ENTITY PCI_SLAVE IS
	-- {{ALTERA_IO_BEGIN}} DO NOT REMOVE THIS LINE!
	PORT
	(	--global clk and reset
		CLK : IN STD_LOGIC;
		RESET : IN STD_LOGIC;
		-- RW register access port
		REGS_RW_DAT_READ 	: IN STD_LOGIC_VECTOR(31 downto 0);
		REGS_RW_DAT_WRITE 	: OUT STD_LOGIC_VECTOR(31 downto 0);
		REGS_RW_ADDR 		: OUT STD_LOGIC_VECTOR(4 downto 0);
		REGS_RW_WREN 		: OUT STD_LOGIC;
		--read only register access port
		REGS_R_DAT_READ 	: IN STD_LOGIC_VECTOR(31 downto 0);
		REGS_R_ADDR  		: OUT STD_LOGIC_VECTOR(4 downto 0);
		-- dual port read-write ram acess
		DPRAM0_RW_DAT_READ 	: IN STD_LOGIC_VECTOR(31 downto 0);
		DPRAM0_RW_DAT_WRITE : OUT STD_LOGIC_VECTOR(31 downto 0);
		DPRAM0_RW_ADDR 		: OUT STD_LOGIC_VECTOR(6 downto 0);
		DPRAM0_RW_WREN 		: OUT STD_LOGIC;
		-- dual port result ram acess
		DPRAM1_R_DAT_READ 	: IN STD_LOGIC_VECTOR(31 downto 0);
		DPRAM1_R_ADDR 		: OUT STD_LOGIC_VECTOR(6 downto 0);
		-- analyser DPRAM2 access
		DPRAM2_R_DATA 		: IN STD_LOGIC_VECTOR(31 downto 0);
		DPRAM2_R_ADDR 		: OUT STD_LOGIC_VECTOR(10 downto 0);
		-- analyser DPRAM3 access
		DPRAM3_R_DATA 		: IN STD_LOGIC_VECTOR(31 downto 0);
		DPRAM3_R_ADDR 		: OUT STD_LOGIC_VECTOR(10 downto 0);
		DPRAM_ADDR_RST		: IN STD_LOGIC;
		--PCI-like lines
		PCI_FRAMEn 			: IN STD_LOGIC;
		PCI_BEn 			: IN STD_LOGIC_VECTOR(1 downto 0);
		PCI_IRDYn 			: IN STD_LOGIC;
		PCI_TRDYn 			: buffer STD_LOGIC;
		PCI_INTn 			: OUT STD_LOGIC;
		PCI_AD 				: INOUT STD_LOGIC_VECTOR(15 downto 0);
		--interrupt in
		INT_IN				: IN STD_LOGIC;
		--test lines		
		TEST1				: OUT STD_LOGIC_VECTOR(31 downto 0);
		TEST2				: OUT STD_LOGIC_VECTOR(31 downto 0)
	);
	-- {{ALTERA_IO_END}} DO NOT REMOVE THIS LINE!
	
END PCI_SLAVE;


--  Architecture Body

ARCHITECTURE PCI_SLAVE_architecture OF PCI_SLAVE IS


TYPE STATE_TYPE IS (
		IDLE,
		write_dat_MSB,
		write_dat_LSB,
		deselect,
		set_trdy,
		read_dat_MSB,
		read_dat_LSB
		);


SIGNAL state: STATE_TYPE;
SIGNAL  	count_enable,
			count_enable_main, 
			header_end,
			latch_base_address,
			load_counter,
			force_count,
			latch_MSB,
			dpram_count_enable   : std_logic; 

signal		regs_rw_sel,
			regs_r_sel,
			dpram0_sel,
			dpram1_sel,
			dpram2_sel,
			dpram3_sel,
			write_en		: std_logic; 
	
	
	
signal		dpram_addr_count : std_logic_vector(10 downto 0);			  
signal		addr_count : std_logic_vector(15 downto 0);
signal      mem_sel : std_logic_vector(1 downto 0);
signal      base_ad : std_logic_vector(15 downto 0);
signal      dat_MSB : std_logic_vector(15 downto 0);
signal		mem_data_wr, mem_data_rd : std_logic_vector(31 downto 0);


BEGIN



---***********************************************************************************************************************************************
---***********************************************		PCI SLAVE state machine			********************************************************
---***********************************************************************************************************************************************


PROCESS (clk,reset)
BEGIN
if reset='1'then
	state<=IDLE;
elsif clk'EVENT AND clk = '1' THEN
	CASE state IS
		WHEN IDLE =>
			if PCI_FRAMEn = '0' and PCI_BEn = "11" then
				state <= write_dat_MSB;
			elsif PCI_FRAMEn = '0' and PCI_BEn = "01" then
				state <= set_trdy;
			else
				state <= IDLE;
			end if;		


			

		WHEN write_dat_MSB =>
			if PCI_FRAMEn = '1' then
				state <= deselect;
			elsif PCI_IRDYn = '0' and PCI_BEn(1) = '0' then 
				state <= write_dat_LSB;
			end if;	
				
		WHEN write_dat_LSB =>
			if PCI_FRAMEn = '1' then
				state <= deselect;
			elsif PCI_IRDYn = '0' and PCI_BEn(0) = '0' then  
				state <= write_dat_MSB;
			end if;	
				
				
		WHEN deselect =>
			state <= IDLE;
		
					
		WHEN set_trdy =>
			if PCI_FRAMEn = '1' then
				state <= deselect;
			elsif PCI_IRDYn = '0' and PCI_BEn(1) = '0' then 
				state <= read_dat_MSB;
			end if;		

		WHEN read_dat_MSB =>	
			if PCI_FRAMEn = '1' then
				state <= deselect;
			elsif PCI_IRDYn = '0' then 
				state <= read_dat_LSB;
			end if;		
			
		WHEN read_dat_LSB =>	
			if PCI_FRAMEn = '1' then
				state <= deselect;
			else
				state <= set_trdy;
			end if;		
			
		WHEN others =>
				state <= IDLE;
	
END CASE;
END IF;
END PROCESS;

---***********************************************************************************************************************************************
---***********************************************************************************************************************************************
-----------     state machine output signals assignments
---***********************************************************************************************************************************************
---***********************************************************************************************************************************************




WITH state SELECT

 PCI_TRDYn 		<= 			'1' 		when 		IDLE,
							'0'     	when		write_dat_MSB,
							'0'     	when		write_dat_LSB,
							'1' 		when		deselect,
							'1'  		when		set_trdy,
							'0' 		when		read_dat_MSB,
							'0' 		when		read_dat_LSB,
							'1' 		when        others;

	
WITH state SELECT
PCI_AD 			<=  	mem_data_rd(15 downto 0)	when	read_dat_LSB,
						mem_data_rd(31 downto 16)	when	read_dat_MSB,
					  	(others => 'Z')				when 	others;


with state select
count_enable_main	<= 		'0' 		when 		IDLE,
							'0'     	when		write_dat_MSB,
							'1'     	when		write_dat_LSB,
							'0' 		when		deselect,
							'0'  		when		set_trdy,
							'0' 		when		read_dat_MSB,
							'1' 		when		read_dat_LSB,
							'0' 		when        others;
with state select
load_counter		<= 		'1' 		when 		IDLE,
							'0' 		when        others;
with state select
latch_base_address	<= 		'1' 		when 		IDLE,
							'0' 		when        others;
							
										
						
with state select
write_en			<= 		'1' 		when 		write_dat_LSB,
							'0' 		when        others;						
							
---***********************************************************************************************************************************************
-----------     address counter
---***********************************************************************************************************************************************


count_enable <= count_enable_main and (not PCI_TRDYn) and (not PCI_IRDYn)  and (not PCI_BEn(0));

process(clk,reset)
begin
if reset = '1' then
	addr_count <= (others => '0');	
elsif clk'event and clk = '1' then
	if load_counter = '1' then
		addr_count(15 downto 0) <= PCI_AD(15 downto 0);
	elsif count_enable = '1' then
		addr_count <= addr_count+1;
	end if;	
end if;
end process;

process(clk)
begin
if clk'event and clk = '1' then
	if latch_base_address = '1' then
		base_ad(15 downto 0) <= PCI_AD(15 downto 0);
	end if;	
end if;
end process;

---***********************************************************************************************************************************************
-----------    analyser DPRAM address coutner
---***********************************************************************************************************************************************
	
	dpram_count_enable	<= count_enable_main and (not PCI_TRDYn) and (not PCI_IRDYn)  and (not PCI_BEn(0)) and ( dpram2_sel or dpram3_sel);
	
process(clk,reset,DPRAM_ADDR_RST)
begin
if reset = '1' or DPRAM_ADDR_RST = '1' then
	dpram_addr_count <= (others => '0');	
elsif clk'event and clk = '1' then
	if dpram_count_enable = '1' then
		dpram_addr_count <= dpram_addr_count+1;
	end if;	
end if;
end process;

---***********************************************************************************************************************************************
----- memory select address decoder
---***********************************************************************************************************************************************
																			-- number of 32 bit location!!!   	--ADDRESS
	regs_rw_sel <= '1' when base_ad(15 downto 7) = std_logic_vector(to_unsigned(0,9)) else '0'; --0x0000 	  	--0x0000
	regs_r_sel  <= '1' when base_ad(15 downto 7) = std_logic_vector(to_unsigned(1,9)) else '0';	--0x0080		--0x0200
	dpram0_sel  <= '1' when base_ad(15 downto 7) = std_logic_vector(to_unsigned(2,9)) else '0';	--0x0100		--0x0400
	dpram1_sel  <= '1' when base_ad(15 downto 7) = std_logic_vector(to_unsigned(3,9)) else '0';	--0x0180		--0x0600
	dpram2_sel  <= '1' when base_ad(15 downto 7) = std_logic_vector(to_unsigned(4,9)) else '0';	--0x0200		--0x0800
	dpram3_sel  <= '1' when base_ad(15 downto 7) = std_logic_vector(to_unsigned(5,9)) else '0';	--0x0280		--0x0A00


---***********************************************************************************************************************************************
-----------    RAM write enables generation
---***********************************************************************************************************************************************
 						
REGS_RW_WREN  <=	 regs_rw_sel and (not PCI_TRDYn) and (not PCI_IRDYn) and write_en;
DPRAM0_RW_WREN <=	dpram0_sel	and (not PCI_TRDYn) and (not PCI_IRDYn) and write_en;

---***********************************************************************************************************************************************
-----------    RAM address generation
---***********************************************************************************************************************************************

REGS_RW_ADDR <= addr_count(4 downto 0);
REGS_R_ADDR <= addr_count(4 downto 0);
DPRAM0_RW_ADDR <= addr_count(6 downto 0);
DPRAM1_R_ADDR <= addr_count(6 downto 0);
DPRAM2_R_ADDR <= dpram_addr_count;
DPRAM3_R_ADDR <= dpram_addr_count;

---***********************************************************************************************************************************************
-----------    RAM data assignment
---***********************************************************************************************************************************************
latch_MSB <= '1' when PCI_IRDYn = '0' and PCI_TRDYn = '0' and state = write_dat_MSB else '0' ;

--latches MSB of PCI transfer to form 32 bit memory word
process(clk)
begin
if clk'event and clk = '1' then
	if latch_MSB = '1' then
		dat_MSB(15 downto 0) <= PCI_AD(15 downto 0);
	end if;	
end if;
end process;

mem_data_wr<= dat_MSB & PCI_AD; -- compose final memory data 
REGS_RW_DAT_WRITE <= mem_data_wr;
DPRAM0_RW_DAT_WRITE <= mem_data_wr;

---***********************************************************************************************************************************************
-----------    RAM data out assignment
---***********************************************************************************************************************************************

 	 
mem_data_rd <= 	REGS_RW_DAT_READ 	when regs_rw_sel = '1' 	else
				REGS_R_DAT_READ 	when regs_r_sel  = '1' 	else
				DPRAM0_RW_DAT_READ 	when dpram0_sel = '1' 	else
				DPRAM1_R_DAT_READ 	when dpram1_sel = '1' 	else
				DPRAM2_R_DATA 		when dpram2_sel = '1' 	else 
				DPRAM3_R_DATA 		when dpram3_sel = '1' 	else
				x"00000000" ;
			     




PCI_INTn <= not INT_IN;

		
TEST1(7 downto 0) <= latch_MSB & write_en & addr_count(5 downto 0);
TEST1(31 downto 8) <= (others => '0');
TEST2 <= mem_data_wr;

END PCI_SLAVE_architecture;
