-------------------------------------------------------------------------------
--
-- Title       : registers
-- Design      : flasher
-- Author      : Wayne Radochonski
-- Company     : Home
--
-------------------------------------------------------------------------------
--
-- File        : registers.vhd
-- Generated   : Sun Sep 10 10:06:12 2006
-- From        : interface description file
-- By          : Itf2Vhdl ver. 1.20
--
-------------------------------------------------------------------------------
--
-- Description : 
--
-------------------------------------------------------------------------------

library IEEE;
use IEEE.std_logic_1164.all;  
use work.globals.all;

entity registers is
	 port(
		 clock 			: in 	std_logic;
		 reset 			: in 	std_logic;
		 cs_n 			: in 	std_logic;
		 rd_n 			: in 	std_logic;
		 wr_n 			: in 	std_logic;	   
		 done			: in	std_logic;
		 address 		: in 	std_logic_vector( 5 downto 2);
		 data_in 		: in 	std_logic_vector(15 downto 0);
		 data_out 		: out 	std_logic_vector(15 downto 0);
		 period 		: out 	std_logic_vector(15 downto 0);
		 flash_on 		: out 	std_logic_vector(15 downto 0);
		 flash_off 		: out 	std_logic_vector(15 downto 0);
		 sample_on 		: out 	std_logic_vector(15 downto 0);
		 sample_off 	: out 	std_logic_vector(15 downto 0);
		 flashes 		: out 	std_logic_vector(15 downto 0);
		 full			: out	std_logic;
		 oe				: out	std_logic
	     );
end registers;

architecture synthesis of registers is	

	component dual_rank_synchronizer is
		port (
			clock		: in  std_logic;
			reset		: in  std_logic;
			unsynced_in	: in  std_logic;
			synced_out	: out std_logic
		);
	end component dual_rank_synchronizer;      
	
	component falling_edge_detector is
		port (
			clock      	: in  std_logic;
			reset		: in  std_logic;
			candidate	: in  std_logic;
			detected	: out std_logic
		);
	end component falling_edge_detector;		 
	
	component jk_ff is
		port (
			 clock 		: in 	std_logic;
			 reset 		: in 	std_logic;	
			 enable		: in	std_logic;
			 j 			: in 	std_logic;
			 k 			: in 	std_logic;
			 q_out 		: out 	std_logic
		);
	end component jk_ff; 
	
	signal		period_register 	: std_logic_vector (15 downto 0);
	signal 		flash_on_register	: std_logic_vector (15 downto 0);
	signal 		flash_off_register	: std_logic_vector (15 downto 0);
	signal 		sample_on_register	: std_logic_vector (15 downto 0);
	signal 		sample_off_register	: std_logic_vector (15 downto 0);
	signal 		number_of_flashes	: std_logic_vector (15 downto 0); 		     
	signal		synced_cs_n			: std_logic;
	signal		synced_wr_n			: std_logic;	
	signal		write_pulse			: std_logic;   
	signal		start				: std_logic;
	signal 		empty				: std_logic;
	signal		set_full			: std_logic;
begin				
	
	sync1 : dual_rank_synchronizer
		port map (
		  clock     	=> clock,
		  reset 		=> reset,
		  unsynced_in	=> cs_n,
		  synced_out    => synced_cs_n
		  );	
		  
	sync2 : dual_rank_synchronizer
		port map (
		  clock     	=> clock,
		  reset 		=> reset,
		  unsynced_in	=> wr_n,
		  synced_out    => synced_wr_n
		  );	
		  
	fed1 : falling_edge_detector
		port map (
		  clock     => clock,
		  reset		=> reset,
		  candidate => synced_wr_n,
		  detected  => write_pulse
		  );   
		  
	full_ff : jk_ff
		port map (
		  clock     	=> clock,
		  reset 		=> reset, 
		  enable		=> vdd,
		  j 	     	=> set_full,
		  k      		=> done,
		  q_out     	=> start
		);
		
	register_file : process (clock)
	begin					 
		if rising_edge(clock) then	   
			if reset = '1' then
				period_register 	<= (others => '0');
				flash_on_register  	<= (others => '0');
				flash_off_register  <= (others => '0');
				sample_on_register  <= (others => '0');
				sample_off_register <= (others => '0');
				number_of_flashes	<= (others => '0');		
			elsif (synced_cs_n = '0' and write_pulse = '1') then
				case address is
					when PeriodRegisterAddress  	=> period_register		<= data_in;
					when FlashOnRegisterAddress  	=> flash_on_register	<= data_in;
					when FlashOffRegisterAddress   	=> flash_off_register	<= data_in;
					when SampleOnRegisterAddress   	=> sample_on_register	<= data_in;
					when SampleOffRegisterAddress   => sample_off_register	<= data_in;
					when FlashesRegisterAddress 	=> number_of_flashes	<= data_in;
					when others => null;
				end case;	
			end if;
		end if;
	end process register_file;
		
	data_out_mux : process (address, cs_n, rd_n, empty, period_register, flash_on_register,
						    flash_off_register, sample_on_register, sample_off_register,
							number_of_flashes)
	begin  
		if (cs_n = '0' and rd_n = '0') then
			case address is
				when StatusRegisterAddress		=> data_out <= "000000000000000" & empty;
				when PeriodRegisterAddress  	=> data_out <= period_register;
				when FlashOnRegisterAddress   	=> data_out <= flash_on_register;
				when FlashOffRegisterAddress   	=> data_out <= flash_off_register;
				when SampleOnRegisterAddress   	=> data_out <= sample_on_register;
				when SampleOffRegisterAddress   => data_out <= sample_off_register;
				when FlashesRegisterAddress 	=> data_out <= number_of_flashes;
				when RevisionRegisterAddress => data_out <= ChipRevision;
				when others => data_out <= X"DEAD";
			end case;	 
		else
			data_out <= (others => 'X');
		end if;
	end process data_out_mux;	 
	
	empty		<= not start;
	oe			<= '1' when (synced_cs_n = '0' and rd_n = '0') else '0';
	set_full	<= '1' when (synced_cs_n = '0' and write_pulse = '1' and 
	                         address = CommandRegisterAddress) else '0';
	period 		<= period_register;
	flash_on 	<= flash_on_register;
	flash_off  	<= flash_off_register;
	sample_on  	<= sample_on_register;
	sample_off	<= sample_off_register;
	flashes	 	<= number_of_flashes;			 
	full		<= start;

end synthesis;
