----------------------------------------------------------------------------------
-- Company: 
-- Engineer: 
-- 
-- Create Date:    19:55:49 04/08/2007 
-- Design Name: 
-- Module Name:    sipo - Behavioral 
-- Project Name: 
-- Target Devices: 
-- Tool versions: 
-- Description: 
--
-- Dependencies: 
--
-- Revision: 
-- Revision 0.01 - File Created
-- Additional Comments: 
--
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;

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

entity sipo is
Generic ( width : integer := 8 );
Port (
	rst		: in  STD_LOGIC;
	clk		: in  STD_LOGIC;
	srdyo	: out STD_LOGIC;
	sdi		: in  STD_LOGIC;
	ssi		: in  STD_LOGIC;
	prdyi	: in  STD_LOGIC;
	pvo		: out STD_LOGIC;
	pdo		: out UNSIGNED (width-1 downto 0)
	);
end sipo;

architecture Behavioral of sipo is

type sstate_t is (reset, idle, ready, sync, active);

constant idle_pol : std_logic := '0';
signal reg : UNSIGNED (width-1 downto 0);
signal pvalid, shift_en, counter_srst, counter_rdy : std_logic;
signal sstate, sstate_next : sstate_t;

begin

par_out:
process (rst, clk, sdi, reg, shift_en, pvalid)
begin
	if rst = '1' then
		reg <= (others => idle_pol);
		pvo <= '0';
	elsif rising_edge(clk) then
		if shift_en = '1' then
			reg <= reg(width-2 downto 0) & sdi;
		end if;	
		pvo <= pvalid;
	end if;
	pdo <= reg;
end process;

counter:
process (rst, clk, counter_srst)
variable counter : integer range 0 to width-1;
begin
	if rst = '1' then
		counter_rdy <= '0';
	elsif rising_edge(clk) then
		if counter_srst = '1' then
			counter := width-4;
			counter_rdy <= '0';
		elsif counter /= 0 then	
			counter := counter - 1;
		else	
			counter_rdy <= '1';
		end if;	
	end if;
end process;

ser_sm:
process (rst, clk, ssi, sstate, counter_rdy, prdyi)
begin
	sstate_next <= sstate;
	shift_en <= '1';
	pvalid <= '0';
	counter_srst <= ssi;
	srdyo <= '0';
	
	case sstate is
	when reset =>
		sstate_next <= idle;
	when idle =>
		sstate_next <= ready;
	when ready =>	
		srdyo <= prdyi;
		if ssi = '1' then
			sstate_next <= active;
		end if;	
	when active =>	
		if counter_rdy = '1' then
			sstate_next <= sync;
		end if;	
	when sync =>	
		pvalid <= '1';
		sstate_next <= idle;
	when others =>	
		sstate_next <= idle;
		
	end case;
end process;
	
state_proc:
process (rst, clk, sstate_next)
begin
	if rst = '1' then
		sstate <= reset;
	elsif rising_edge(clk) then
		sstate <= sstate_next;
	end if;
end process;


end Behavioral;

