--
-- 4b Symbol Encoder
-- 
-- Matt Warren July 2015
--
--


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

library readout130;
use readout130.pkg_star_flink.all;


entity star_flink_encoder is
  port(
    -- 160 MHz domain
    clk160 : in  std_logic;             -- ser clock
    ser_o  : out std_logic;             -- serial out (160Mb)

    -- 40MHz domain
    bcr_i : in std_logic;
    ls_i  : in std_logic;
    pr_l0id_i : in  std_logic_vector(7 downto 0);
    pr_req_i  : in  std_logic;
    pr_done_o : out std_logic;
    lp_l0id_i : in  std_logic_vector(7 downto 0);
    lp_req_i  : in  std_logic;
    lp_done_o : out std_logic;
    isidle_o : out std_logic;
    symbol_o : out std_logic_vector(3 downto 0);
    -- Infra
    clk : in std_logic;
    rst : in std_logic
    );

-- Declarations

end star_flink_encoder;

---------------------------------------------------------------------------
architecture rtl of star_flink_encoder is

  signal pr_state : std_logic_vector(1 downto 0);
  signal lp_state : std_logic_vector(1 downto 0);

  signal symbol : std_logic_vector(3 downto 0);

  signal sbit_count : integer range 0 to 3 := 0;

  --signal dsymb       : std_logic_vector(3 downto 0);
  --signal dsymb_count : integer;

begin

  -- Encode and output
  --==========================================================================================

  prc_encode : process (clk)
  begin

    if rising_edge(clk) then
      if (rst = '1') then
        isidle_o <= '0';

        pr_state <= "11";
        pr_done_o <= '0';

        lp_state <= "11";
        lp_done_o <= '0';

      else

        -- defaults
        isidle_o <= '0';
        pr_done_o        <= '0';
        lp_done_o        <= '0';

        -- Sync Sigs
        if (bcr_i = '1') and (ls_i = '1') then
          symbol <= sBCRLS;

        elsif (bcr_i = '1') then
          symbol <= sBCR;

        elsif (ls_i = '1') then
          symbol <= sLS;

        -- PR data
        elsif (pr_state = "00") then
           symbol <= data2symb('0' & pr_l0id_i(7 downto 6));
           pr_state <= "01";

        elsif (pr_state = "01") then
           symbol <= data2symb(pr_l0id_i(5 downto 3));
            pr_state <= "10";

        elsif (pr_state = "10") then
          symbol <= data2symb(pr_l0id_i(2 downto 0));
          pr_done_o <= '1';
          pr_state <= "11";

         -- LP data
         elsif (lp_state = "00") then
           symbol <= data2symb('0' & lp_l0id_i(7 downto 6));
           lp_state <= "01";

        elsif (lp_state = "01") then
           symbol <= data2symb(lp_l0id_i(5 downto 3));
            lp_state <= "10";

        elsif (lp_state = "10") then
          symbol <= data2symb(lp_l0id_i(2 downto 0));
          lp_done_o <= '1';
          lp_state <= "11";

        -- PR and LP start     
        elsif (pr_req_i = '1') then
          symbol           <= sPR;
          pr_state        <= "00";

        elsif (lp_req_i = '1') then
          symbol           <= sLP;
          lp_state        <= "00";

        -- Idle  
        else
          symbol   <= sIDLE;
          isidle_o <= '1';

        end if;
      end if;
    end if;
  end process;



-- Toy 160Mb Serialiser (sim only)
--=================================================================================

prc_sbit_counter : process(clk160)
begin
  if rising_edge(clk160) then
    if (rst = '1') then
      sbit_count <= 3; -- choose to ensure words are are aligned with 40MHz period
    else
      if (sbit_count = 0) then
        sbit_count <= 3;
      else
        sbit_count <= sbit_count - 1;

      end if;
    end if;
  end if;
end process;

ser_o    <= symbol(sbit_count) when rising_edge(clk160);
symbol_o <= symbol;


--Debug options to get words aligned
--------------------------------------------------------
--ser_o    <= dsymb(sbit_count); -- when rising_edge(clk160);
--symbol_o <= dsymb;
--prc_debug_symbol : process(clk)
--begin
--  if rising_edge(clk) then
--    if (rst = '1') then
--      dsymb_count <= 0;
--    else
--      if (dsymb_count = 15) then
--        dsymb_count <= 0;
--      else
--        dsymb_count <= dsymb_count + 1;
--      end if;
--    end if;
--  end if;
--  --case dsymb_count is
--  --  when 0      => dsymb <= x"0";
--  --  when 1      => dsymb <= x"0";
--  --  when 2      => dsymb <= x"1";
--  --  when 3      => dsymb <= x"0";
--  --  when 4      => dsymb <= x"0";
--  --  when others => dsymb <= x"0";
--  --end case;
--end process;
--dsymb <= conv_std_logic_vector(dsymb_count,4);




end rtl;