--------------------------------------------------------------------------------
-- Company: 
-- Engineer:
--
-- Create Date:    21:52:19 10/22/05
-- Design Name:    
-- Module Name:    oneshot - Behavioral
-- Project Name:   
-- Target Device:  
-- Tool versions:  
-- Description:
--
-- Dependencies:
-- 
-- Revision:
-- Revision 0.01 - File Created
-- Additional Comments:
-- 
-----------------------------------------------------------------------
-- $Header: D:\usr\cvsroot/VHDL/lib/misc/oneshot.vhd,v 1.1 2008/08/23 08:20:29 Jens Exp $
-----------------------------------------------------------------------
-- Component Template
--
--	COMPONENT oneshot
--	GENERIC (mode : integer);
--	PORT(
--		rst : IN std_logic;
--		clk : IN std_logic;
--		input : IN std_logic;          
--		output : OUT std_logic
--		);
--	END COMPONENT;
--
-- Instantation Template
--
--	oneshot_int: oneshot 
--	GENERIC MAP (
--		mode => 1)		
--	PORT MAP(
--		rst => ,
--		clk => ,
--		input => ,
--		output => 
--	);
--
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

---- Uncomment the following library declaration if instantiating
---- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;

entity oneshot is
    Generic ( mode : integer range 0 to 2 := 1);
    Port ( rst : in std_logic;
           clk : in std_logic;
           input : in std_logic;
           output : out std_logic);
end oneshot;

architecture Behavioral of oneshot is

type shot_state_t is (shot_pos_st, shot_neg_st, release_pos_st, release_neg_st);

signal shot_cs : shot_state_t;
signal shot_ns : shot_state_t;

begin

mode_0:
if mode = 0 generate
begin
	shot_clk: process(rst, clk, shot_ns, input)
	begin
		if (rst = '1') then
			if (input = '1') then
				shot_cs <= release_pos_st;
			else
				shot_cs <= release_neg_st;
			end if;
		else
			if rising_edge(clk) then
				shot_cs <= shot_ns;
			end if;
		end if;
	end process;

	shot_in: process(rst, clk, input, shot_cs)
	begin
		shot_ns <= shot_cs;
		case shot_cs is
			when release_pos_st =>
				if (input = '0') then
					shot_ns <= shot_neg_st;
				end if;
			when shot_neg_st =>
				shot_ns <= release_neg_st;
			when release_neg_st =>
				if (input = '1') then
					shot_ns <= release_pos_st;
				end if;
			when others => null;
		end case;
	end process;

	shot_out: process(shot_cs)
	begin
		output   <= '0';
		case shot_cs is
			when shot_pos_st =>
				output   <= '1';
			when shot_neg_st =>
				output   <= '1';
			when others => null;
		end case;
	end process;
end generate;

mode_1:
if mode = 1 generate
begin
	shot_clk: process(rst, clk, shot_ns, input)
	begin
		if (rst = '1') then
			if (input = '1') then
				shot_cs <= release_pos_st;
			else
				shot_cs <= release_neg_st;
			end if;
		else
			if rising_edge(clk) then
				shot_cs <= shot_ns;
			end if;
		end if;
	end process;

	shot_in: process(rst, clk, input, shot_cs)
	begin
		shot_ns <= shot_cs;
		case shot_cs is
			when shot_pos_st =>
				shot_ns <= release_pos_st;
			when release_pos_st =>
				if (input = '0') then
					shot_ns <= release_neg_st;
				end if;
			when release_neg_st =>
				if (input = '1') then
					shot_ns <= shot_pos_st;
				end if;
			when others => null;
		end case;
	end process;

	shot_out: process(shot_cs)
	begin
		output   <= '0';
		case shot_cs is
			when shot_pos_st =>
				output   <= '1';
			when shot_neg_st =>
				output   <= '1';
			when others => null;
		end case;
	end process;
end generate;

mode_2:
if mode = 2 generate
begin
	shot_clk: process(rst, clk, shot_ns, input)
	begin
		if (rst = '1') then
			if (input = '1') then
				shot_cs <= release_pos_st;
			else
				shot_cs <= release_neg_st;
			end if;
		else
			if rising_edge(clk) then
				shot_cs <= shot_ns;
			end if;
		end if;
	end process;

	shot_in: process(rst, clk, input, shot_cs)
	begin
		shot_ns <= shot_cs;
		case shot_cs is
			when shot_pos_st =>
				shot_ns <= release_pos_st;
			when release_pos_st =>
				if (input = '0') then
					shot_ns <= shot_neg_st;
				end if;
			when shot_neg_st =>
				shot_ns <= release_neg_st;
			when release_neg_st =>
				if (input = '1') then
					shot_ns <= shot_pos_st;
				end if;
		end case;
	end process;

	shot_out: process(shot_cs)
	begin
		output   <= '0';
		case shot_cs is
			when shot_pos_st =>
				output   <= '1';
			when shot_neg_st =>
				output   <= '1';
			when others => null;
		end case;
	end process;
end generate;

			

end Behavioral;
