----------------------------------------------------------------------------------
-- Company: University of Connecticut
-- Engineer: Igor Senderovich
-- 
-- Create Date:    04:14:41 10/01/2007 
-- Design Name: 
-- Module Name:    WriteDpacket - behavioral 
-- Description:    Assembles D-type packet - reports DAC values
----------------------------------------------------------------------------------

library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_arith.all;
use IEEE.std_logic_unsigned.all;

library FPGA_BasicComp;
use FPGA_BasicComp.BasicComp.all;

library FPGA_BasicComp;
use FPGA_BasicComp.BasicComp.all;

entity WriteDpacket is
    port ( Clk : in  std_logic;
	   Go : in std_logic;
	   Done : out std_logic;
	   LocStamp : in std_logic_vector (7 downto 0);
	   RAM_EN : out std_logic;
	   RAM_ADDR_tri : out std_logic_vector (9 downto 0);
	   RAM_WE_tri : out std_logic_vector (1 downto 0);
	   RAM_DI_tri : out std_logic_vector (15 downto 0);
	   RAM_DO : in std_logic_vector (15 downto 0);
	   TxRx_Go : out std_logic;
	   TxRx_Rd_tri : out std_logic;
	   TxRx_A_tri : out std_logic_vector (7 downto 0);
	   TxRx_D_tri : out std_logic_vector (7 downto 0);
	   TxRx_Q : in std_logic_vector (7 downto 0);
	   TxRx_Done : in std_logic);
end WriteDpacket;

architecture behavioral of WriteDpacket is
	
	type stage_t is (S0,S1,S2,S3,S4,S5,S6,S7,S8,S9);
	signal stage : stage_t := S0;

	signal counter_2b : std_logic_vector (1 downto 0);
	signal counter_6b : std_logic_vector (5 downto 0);
	signal buffer_addr : std_logic_vector (7 downto 0);
	signal Done_reg : std_logic := '0';
	signal RAM_EN_reg : std_logic := '0';
	signal RAM_ADDR_reg : std_logic_vector (9 downto 0) := (others => '0');
	signal RAM_WE_reg : std_logic_vector (1 downto 0) := (others => '0');
	signal RAM_DI_reg : std_logic_vector (15 downto 0) := (others => '0');
	signal TxRx_Go_reg : std_logic := '0';
	signal TxRx_Rd_reg : std_logic := '0';
	signal TxRx_A_reg : std_logic_vector (7 downto 0) := (others => '0');
	signal TxRx_D_reg : std_logic_vector (7 downto 0) := (others => '0');
begin
	RAM_EN <= RAM_EN_reg;
	RAM_ADDR_tri <= RAM_ADDR_reg when (RAM_EN_reg = '1') else (others => 'Z');
	RAM_WE_tri <= RAM_WE_reg when (RAM_EN_reg = '1') else (others => 'Z');
	RAM_DI_tri <= RAM_DI_reg when (RAM_EN_reg = '1') else (others => 'Z');

	TxRx_Go <= TxRx_Go_reg;
	TxRx_Rd_tri <= TxRx_Rd_reg when (TxRx_Go_reg = '1') else 'Z';
	TxRx_A_tri <= TxRx_A_reg when (TxRx_Go_reg = '1') else (others => 'Z');
	TxRx_D_tri <= TxRx_D_reg when (TxRx_Go_reg = '1') else (others => 'Z');

	Sequencer : process (Clk) is
		variable op_complete_var : std_logic;
	begin
		if rising_edge(Clk) then
			stage <= stage;
			Done_reg <= '0';
			counter_2b <= (others => '0');
			counter_6b <= (others => '0');
			buffer_addr <= (others => '0');
			-- disable the RAM when not in use
			RAM_EN_reg <= '0';
			RAM_ADDR_reg <= (others => '0');
			RAM_WE_reg <= (others => '0');
			RAM_DI_reg <= (others => '0');
			-- disable the MuxIntel bus when not in use
			TxRx_Go_reg <= '0';
			TxRx_Rd_reg <= '0';
			TxRx_A_reg <= (others => '0');
			TxRx_D_reg <= (others => '0');
			op_complete_var := TxRx_Go_reg and TxRx_Done;

			case stage is
			    when S0 =>
				if (Go = '1') then
					stage <= S1;
				end if;

			-------------------------------------------------------
			-- Write the first 4 bytes into the transmit buffer.
			-- 	2 bytes - packet payload length (0x0042)
			-- 	2 bytes - packet identifier (LocStamp & 0x44)
			-------------------------------------------------------

			    when S1 =>
				buffer_addr <= X"0c";
				counter_2b <= "00";
				stage <= S2;
			    when S2 =>
				TxRx_A_reg <= X"08";
				TxRx_D_reg <= X"00";
				TxRx_Rd_reg <= '0';
				TxRx_Go_reg <= not TxRx_Done;
				buffer_addr <= buffer_addr;
				counter_2b <= counter_2b;
				if (op_complete_var = '1') then
					stage <= S3;
				end if;
			    when S3 =>
				TxRx_A_reg <= X"09";
				TxRx_D_reg <= buffer_addr(7 downto 0);
				TxRx_Rd_reg <= '0';
				TxRx_Go_reg <= not TxRx_Done;
				buffer_addr <= buffer_addr;
				counter_2b <= counter_2b;
				if (op_complete_var = '1') then
					stage <= S4;
				end if;
			    when S4 =>
				TxRx_A_reg <= X"04";
				case counter_2b is
				    when "00" =>
					TxRx_D_reg <= X"00";
				    when "01" =>
					TxRx_D_reg <= X"42";
				    when "10" =>
					TxRx_D_reg <= LocStamp;
				    when others =>
					TxRx_D_reg <= X"44";
				end case;
				TxRx_Rd_reg <= '0';
				TxRx_Go_reg <= not TxRx_Done;
				buffer_addr <= buffer_addr;
				counter_2b <= counter_2b;
				if (op_complete_var = '1') then
					buffer_addr <= buffer_addr + '1';
					counter_2b <= counter_2b + '1';
					if (counter_2b = "11") then
						stage <= S5;
 					else 
						stage <= S2;
					end if;
				end if;

			-------------------------------------------------------
			-- Follow this with the 32 2-byte DAC values from RAM
			-------------------------------------------------------

			    when S5 =>
				RAM_EN_reg <= '1';
				RAM_ADDR_reg <= "00010" & counter_6b(5 downto 1);
				TxRx_A_reg <= X"09";
				TxRx_D_reg <= buffer_addr(7 downto 0);
				TxRx_Rd_reg <= '0';
				TxRx_Go_reg <= not TxRx_Done;
				buffer_addr <= buffer_addr;
				counter_6b <= counter_6b;
				if (op_complete_var = '1') then
					stage <= S6;
				end if;
			    when S6 =>
				RAM_EN_reg <= '1';
				RAM_ADDR_reg <= RAM_ADDR_reg;
				-- RAM_DO is valid at the first clock in S6 because the
				-- RAM_ADDR and RAM_EN lines were set up in S5.
				TxRx_A_reg <= X"04";
				if (buffer_addr(0) = '0') then
					TxRx_D_reg <= RAM_DO(15 downto 8);
				else
					TxRx_D_reg <= RAM_DO(7 downto 0);
				end if;
				TxRx_Rd_reg <= '0';
				TxRx_Go_reg <= not TxRx_Done;
				buffer_addr <= buffer_addr;
				counter_6b <= counter_6b;
				if (op_complete_var = '1') then
					buffer_addr <= buffer_addr + 1;
					counter_6b <= counter_6b + 1;
					if (counter_6b = X"3F") then
						stage <= S7;
					else 
						stage <= S5;
					end if;
				end if;

			-------------------------------------------------------
			-- Pad to 84 bytes by setting TXENDH:TXENDL to 0x004F 
			-- and letting the chip append the final 4-byte CRC.
			-------------------------------------------------------

			    when S7 =>
				TxRx_A_reg <= X"57";
				TxRx_D_reg <= X"00";
				TxRx_Rd_reg <= '0';
				TxRx_Go_reg <= not TxRx_Done;
				if (op_complete_var = '1') then
					stage <= S8;
				end if;
			    when S8 =>
				TxRx_A_reg <= X"58";
				TxRx_D_reg <= X"4F";
				TxRx_Rd_reg <= '0';
				TxRx_Go_reg <= not TxRx_Done;
				if (op_complete_var = '1') then
					stage <= S9;
				end if;
			    when S9 =>
				if (Go = '1') then
					Done_reg <= '1';
				else
					stage <= S0;
				end if;
			end case;

		else
			stage <= stage;
			Done_reg <= Done_reg;
			counter_2b <= counter_2b;
			counter_6b <= counter_6b;
			buffer_addr <= buffer_addr;
			RAM_EN_reg <= RAM_EN_reg;
			RAM_ADDR_reg <= RAM_ADDR_reg;
			RAM_WE_reg <= RAM_WE_reg;
			RAM_DI_reg <= RAM_DI_reg;
			TxRx_Go_reg <= TxRx_Go_reg;
			TxRx_Rd_reg <= TxRx_Rd_reg;
			TxRx_A_reg <= TxRx_A_reg;
			TxRx_D_reg <= TxRx_D_reg;
		end if;
	end process;

	Done <= Done_reg;

end behavioral;
