----------------------------------------------------------------------------------
-- Company: 
-- Engineer:    Jason M Blevins
-- 
-- Create Date: 01/05/2026 11:59:12 AM
-- Design Name: 
-- Module Name: eth_flowctrl_tx - 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;
--library UNISIM;
--use UNISIM.VComponents.all;

entity eth_flowctrl_tx is
  Port (
    clk                 : in STD_LOGIC;
    resetn              : in STD_LOGIC;
    prog_full_manual    : in STD_LOGIC;
    data_cnt            : in STD_LOGIC_VECTOR(31 downto 0);
    prog_full_on        : in STD_LOGIC_VECTOR(31 downto 0);
    prog_full_off       : in STD_LOGIC_VECTOR(31 downto 0);
    ctl_tx_resend_pause : out STD_LOGIC;
    ctl_tx_pause_req    : out STD_LOGIC_VECTOR (8 downto 0);
    tx_pause_cnt        : out std_logic_vector(31 downto 0)
    );
end eth_flowctrl_tx;

architecture behavioral of eth_flowctrl_tx is

  signal cnt              : unsigned(3 downto 0);
  signal cnt_r            : unsigned(3 downto 0) := (others => '0');
  signal tx_pause_cnt_i   : unsigned(31 downto 0);
  signal tx_pause_cnt_r   : unsigned(31 downto 0) := (others => '0');
  type state_type is (s0, s1, s2, s3);
  signal state            : state_type;
  signal state_r          : state_type := s0;
  signal resend_pause     : std_logic;
  signal pause_req        : std_logic_vector(8 downto 0);
  signal resend_pause_r   : std_logic := '0';
  signal pause_req_r      : std_logic_vector(8 downto 0) := (others => '0');
  signal prog_full_r      : std_logic := '0';

begin

  ctl_tx_resend_pause <= resend_pause_r;
  ctl_tx_pause_req    <= pause_req_r;
  tx_pause_cnt        <= std_logic_vector(tx_pause_cnt_r);

  process(clk)
  begin
    if(rising_edge(clk))then 
      if(resetn = '0')then
        resend_pause_r  <= '0';
        pause_req_r     <= (others => '0');
        state_r         <= s0;
        cnt_r           <= (others => '0');
        prog_full_r     <= '0';
        tx_pause_cnt_r  <= (others => '0');
      else
        resend_pause_r  <= resend_pause;
        pause_req_r     <= pause_req;
        state_r         <= state;
        cnt_r           <= cnt;
        tx_pause_cnt_r  <= tx_pause_cnt_i;
        if(unsigned(data_cnt) > unsigned(prog_full_on) or prog_full_manual = '1')then
          prog_full_r <= '1';
        elsif (unsigned(data_cnt) <= unsigned(prog_full_off) and prog_full_manual = '0')then
          prog_full_r <= '0';
        end if;         
      end if;
    end if;
  end process;

  process(state_r, cnt_r, prog_full_r, resend_pause_r, pause_req_r, tx_pause_cnt_r)
  begin
    -- defaults
    state           <= state_r;
    cnt             <= cnt_r;
    resend_pause    <= resend_pause_r;
    pause_req       <= pause_req_r;
    tx_pause_cnt_i  <= tx_pause_cnt_r;
  
    case state_r is
      when s0 =>
        if(prog_full_r = '1')then
          state           <= s1;
          tx_pause_cnt_i  <= tx_pause_cnt_r +1;
        end if;

      when s1 =>
        pause_req <= "100000000";
        cnt <= cnt_r +1;
        if(cnt_r = 15)then
          state <= s2;
        end if;

      when s2 =>
        if(prog_full_r = '0')then
          state           <= s3;
          tx_pause_cnt_i  <= tx_pause_cnt_r +1;
        end if;

      when s3 =>
        pause_req     <= (others => '0');
        cnt           <= cnt_r +1;
        if(cnt_r = 0)then
          resend_pause  <= '1';
        else
          resend_pause  <= '0';
        end if;
        if(cnt_r = 15)then
          state <= s0;
        end if;

      when others =>
    end case;

  end process;  


end behavioral;
