-- Do not edit.  Generated by cheby 1.5.dev0 using these options:
--  -i ep_mdio_regs.cheby --gen-hdl ep_mdio_regs.vhd
-- Generated on Mon May 08 17:28:22 2023 by twl


library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.wishbone_pkg.all;

package ep_mdio_regs_pkg is
  type t_mdio_regs_master_out is record
    MCR_uni_en       : std_logic;
    MCR_anrestart    : std_logic;
    MCR_pdown        : std_logic;
    MCR_anenable     : std_logic;
    MCR_loopback     : std_logic;
    MCR_reset        : std_logic;
    MSR_rd           : std_logic;
    ADVERTISE_PAUSE  : std_logic_vector(1 downto 0);
    ADVERTISE_RFAULT : std_logic_vector(1 downto 0);
    WR_SPEC_TX_CAL   : std_logic;
    WR_SPEC_RX_CAL_STAT : std_logic;
    WR_SPEC_CAL_CRST : std_logic;
    WR_SPEC_BSLIDE   : std_logic_vector(4 downto 0);
    ECTRL_lpbck_vec  : std_logic_vector(2 downto 0);
    ECTRL_sfp_tx_fault : std_logic;
    ECTRL_sfp_loss   : std_logic;
    ECTRL_sfp_tx_disable : std_logic;
    ECTRL_tx_prbs_sel : std_logic_vector(2 downto 0);
  end record t_mdio_regs_master_out;
  subtype t_mdio_regs_slave_in is t_mdio_regs_master_out;

  type t_mdio_regs_slave_out is record
    MSR_LSTATUS      : std_logic;
    MSR_RFAULT       : std_logic;
    MSR_anegcomplete : std_logic;
    LPA_FULL         : std_logic;
    LPA_HALF         : std_logic;
    LPA_PAUSE        : std_logic_vector(1 downto 0);
    LPA_RFAULT       : std_logic_vector(1 downto 0);
    LPA_LPACK        : std_logic;
    LPA_NPAGE        : std_logic;
    WR_SPEC_RX_CAL_STAT : std_logic;
    WR_SPEC_BSLIDE   : std_logic_vector(4 downto 0);
    ECTRL_sfp_tx_fault : std_logic;
    ECTRL_sfp_loss   : std_logic;
  end record t_mdio_regs_slave_out;
  subtype t_mdio_regs_master_in is t_mdio_regs_slave_out;

end ep_mdio_regs_pkg;

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.wishbone_pkg.all;
use work.ep_mdio_regs_pkg.all;

entity ep_mdio_regs is
  port (
    rst_n_i              : in    std_logic;
    clk_i                : in    std_logic;
    wb_i                 : in    t_wishbone_slave_in;
    wb_o                 : out   t_wishbone_slave_out;
    -- Wires and registers
    mdio_regs_i          : in    t_mdio_regs_master_in;
    mdio_regs_o          : out   t_mdio_regs_master_out;

    -- Custom PHY-specific registers.
    phy_specific_regs_i  : in    t_wishbone_master_in;
    phy_specific_regs_o  : out   t_wishbone_master_out
  );
end ep_mdio_regs;

architecture syn of ep_mdio_regs is
  signal adr_int                        : std_logic_vector(13 downto 2);
  signal rd_req_int                     : std_logic;
  signal wr_req_int                     : std_logic;
  signal rd_ack_int                     : std_logic;
  signal wr_ack_int                     : std_logic;
  signal wb_en                          : std_logic;
  signal ack_int                        : std_logic;
  signal wb_rip                         : std_logic;
  signal wb_wip                         : std_logic;
  signal MCR_uni_en_reg                 : std_logic;
  signal MCR_anrestart_reg              : std_logic;
  signal MCR_pdown_reg                  : std_logic;
  signal MCR_anenable_reg               : std_logic;
  signal MCR_loopback_reg               : std_logic;
  signal MCR_reset_reg                  : std_logic;
  signal MCR_wreq                       : std_logic;
  signal MCR_wack                       : std_logic;
  signal ADVERTISE_PAUSE_reg            : std_logic_vector(1 downto 0);
  signal ADVERTISE_RFAULT_reg           : std_logic_vector(1 downto 0);
  signal ADVERTISE_wreq                 : std_logic;
  signal ADVERTISE_wack                 : std_logic;
  signal WR_SPEC_TX_CAL_reg             : std_logic;
  signal WR_SPEC_CAL_CRST_reg           : std_logic;
  signal WR_SPEC_wreq                   : std_logic;
  signal WR_SPEC_wack                   : std_logic;
  signal ECTRL_lpbck_vec_reg            : std_logic_vector(2 downto 0);
  signal ECTRL_sfp_tx_disable_reg       : std_logic;
  signal ECTRL_tx_prbs_sel_reg          : std_logic_vector(2 downto 0);
  signal ECTRL_wreq                     : std_logic;
  signal ECTRL_wack                     : std_logic;
  signal phy_specific_regs_re           : std_logic;
  signal phy_specific_regs_we           : std_logic;
  signal phy_specific_regs_wt           : std_logic;
  signal phy_specific_regs_rt           : std_logic;
  signal phy_specific_regs_tr           : std_logic;
  signal phy_specific_regs_wack         : std_logic;
  signal phy_specific_regs_rack         : std_logic;
  signal rd_ack_d0                      : std_logic;
  signal rd_dat_d0                      : std_logic_vector(31 downto 0);
  signal wr_req_d0                      : std_logic;
  signal wr_adr_d0                      : std_logic_vector(13 downto 2);
  signal wr_dat_d0                      : std_logic_vector(31 downto 0);
  signal wr_sel_d0                      : std_logic_vector(3 downto 0);
begin

  -- WB decode signals
  adr_int <= wb_i.adr(13 downto 2);
  wb_en <= wb_i.cyc and wb_i.stb;

  process (clk_i) begin
    if rising_edge(clk_i) then
      if rst_n_i = '0' then
        wb_rip <= '0';
      else
        wb_rip <= (wb_rip or (wb_en and not wb_i.we)) and not rd_ack_int;
      end if;
    end if;
  end process;
  rd_req_int <= (wb_en and not wb_i.we) and not wb_rip;

  process (clk_i) begin
    if rising_edge(clk_i) then
      if rst_n_i = '0' then
        wb_wip <= '0';
      else
        wb_wip <= (wb_wip or (wb_en and wb_i.we)) and not wr_ack_int;
      end if;
    end if;
  end process;
  wr_req_int <= (wb_en and wb_i.we) and not wb_wip;

  ack_int <= rd_ack_int or wr_ack_int;
  wb_o.ack <= ack_int;
  wb_o.stall <= not ack_int and wb_en;
  wb_o.rty <= '0';
  wb_o.err <= '0';

  -- pipelining for wr-in+rd-out
  process (clk_i) begin
    if rising_edge(clk_i) then
      if rst_n_i = '0' then
        rd_ack_int <= '0';
        wr_req_d0 <= '0';
      else
        rd_ack_int <= rd_ack_d0;
        wb_o.dat <= rd_dat_d0;
        wr_req_d0 <= wr_req_int;
        wr_adr_d0 <= adr_int;
        wr_dat_d0 <= wb_i.dat;
        wr_sel_d0 <= wb_i.sel;
      end if;
    end if;
  end process;

  -- Register MCR
  mdio_regs_o.MCR_uni_en <= MCR_uni_en_reg;
  mdio_regs_o.MCR_anrestart <= MCR_anrestart_reg;
  mdio_regs_o.MCR_pdown <= MCR_pdown_reg;
  mdio_regs_o.MCR_anenable <= MCR_anenable_reg;
  mdio_regs_o.MCR_loopback <= MCR_loopback_reg;
  mdio_regs_o.MCR_reset <= MCR_reset_reg;
  process (clk_i) begin
    if rising_edge(clk_i) then
      if rst_n_i = '0' then
        MCR_uni_en_reg <= '0';
        MCR_anrestart_reg <= '0';
        MCR_pdown_reg <= '0';
        MCR_anenable_reg <= '0';
        MCR_loopback_reg <= '0';
        MCR_reset_reg <= '0';
        MCR_wack <= '0';
      else
        if MCR_wreq = '1' then
          MCR_uni_en_reg <= wr_dat_d0(5);
          MCR_anrestart_reg <= wr_dat_d0(9);
          MCR_pdown_reg <= wr_dat_d0(11);
          MCR_anenable_reg <= wr_dat_d0(12);
          MCR_loopback_reg <= wr_dat_d0(14);
          MCR_reset_reg <= wr_dat_d0(15);
        else
          MCR_anrestart_reg <= '0';
          MCR_reset_reg <= '0';
        end if;
        MCR_wack <= MCR_wreq;
      end if;
    end if;
  end process;

  -- Register MSR

  -- Register PHYSID1

  -- Register PHYSID2

  -- Register ADVERTISE
  mdio_regs_o.ADVERTISE_PAUSE <= ADVERTISE_PAUSE_reg;
  mdio_regs_o.ADVERTISE_RFAULT <= ADVERTISE_RFAULT_reg;
  process (clk_i) begin
    if rising_edge(clk_i) then
      if rst_n_i = '0' then
        ADVERTISE_PAUSE_reg <= "00";
        ADVERTISE_RFAULT_reg <= "00";
        ADVERTISE_wack <= '0';
      else
        if ADVERTISE_wreq = '1' then
          ADVERTISE_PAUSE_reg <= wr_dat_d0(8 downto 7);
          ADVERTISE_RFAULT_reg <= wr_dat_d0(13 downto 12);
        end if;
        ADVERTISE_wack <= ADVERTISE_wreq;
      end if;
    end if;
  end process;

  -- Register LPA

  -- Register EXPANSION

  -- Register ESTATUS

  -- Register WR_SPEC
  mdio_regs_o.WR_SPEC_TX_CAL <= WR_SPEC_TX_CAL_reg;
  mdio_regs_o.WR_SPEC_RX_CAL_STAT <= wr_dat_d0(1);
  mdio_regs_o.WR_SPEC_CAL_CRST <= WR_SPEC_CAL_CRST_reg;
  mdio_regs_o.WR_SPEC_BSLIDE <= wr_dat_d0(8 downto 4);
  process (clk_i) begin
    if rising_edge(clk_i) then
      if rst_n_i = '0' then
        WR_SPEC_TX_CAL_reg <= '0';
        WR_SPEC_CAL_CRST_reg <= '0';
        WR_SPEC_wack <= '0';
      else
        if WR_SPEC_wreq = '1' then
          WR_SPEC_TX_CAL_reg <= wr_dat_d0(0);
          WR_SPEC_CAL_CRST_reg <= wr_dat_d0(2);
        else
          WR_SPEC_CAL_CRST_reg <= '0';
        end if;
        WR_SPEC_wack <= WR_SPEC_wreq;
      end if;
    end if;
  end process;

  -- Register ECTRL
  mdio_regs_o.ECTRL_lpbck_vec <= ECTRL_lpbck_vec_reg;
  mdio_regs_o.ECTRL_sfp_tx_fault <= wr_dat_d0(3);
  mdio_regs_o.ECTRL_sfp_loss <= wr_dat_d0(4);
  mdio_regs_o.ECTRL_sfp_tx_disable <= ECTRL_sfp_tx_disable_reg;
  mdio_regs_o.ECTRL_tx_prbs_sel <= ECTRL_tx_prbs_sel_reg;
  process (clk_i) begin
    if rising_edge(clk_i) then
      if rst_n_i = '0' then
        ECTRL_lpbck_vec_reg <= "000";
        ECTRL_sfp_tx_disable_reg <= '0';
        ECTRL_tx_prbs_sel_reg <= "000";
        ECTRL_wack <= '0';
      else
        if ECTRL_wreq = '1' then
          ECTRL_lpbck_vec_reg <= wr_dat_d0(2 downto 0);
          ECTRL_sfp_tx_disable_reg <= wr_dat_d0(5);
          ECTRL_tx_prbs_sel_reg <= wr_dat_d0(10 downto 8);
        end if;
        ECTRL_wack <= ECTRL_wreq;
      end if;
    end if;
  end process;

  -- Interface phy_specific_regs
  phy_specific_regs_tr <= phy_specific_regs_wt or phy_specific_regs_rt;
  process (clk_i) begin
    if rising_edge(clk_i) then
      if rst_n_i = '0' then
        phy_specific_regs_rt <= '0';
        phy_specific_regs_wt <= '0';
      else
        phy_specific_regs_rt <= (phy_specific_regs_rt or phy_specific_regs_re) and not phy_specific_regs_rack;
        phy_specific_regs_wt <= (phy_specific_regs_wt or phy_specific_regs_we) and not phy_specific_regs_wack;
      end if;
    end if;
  end process;
  phy_specific_regs_o.cyc <= phy_specific_regs_tr;
  phy_specific_regs_o.stb <= phy_specific_regs_tr;
  phy_specific_regs_wack <= phy_specific_regs_i.ack and phy_specific_regs_wt;
  phy_specific_regs_rack <= phy_specific_regs_i.ack and phy_specific_regs_rt;
  phy_specific_regs_o.adr <= ((18 downto 0 => '0') & adr_int(12 downto 2)) & (1 downto 0 => '0');
  phy_specific_regs_o.sel <= wr_sel_d0;
  phy_specific_regs_o.we <= phy_specific_regs_wt;
  phy_specific_regs_o.dat <= wr_dat_d0;

  -- Process for write requests.
  process (wr_adr_d0, wr_req_d0, MCR_wack, ADVERTISE_wack, WR_SPEC_wack, ECTRL_wack,
           phy_specific_regs_wack) begin
    MCR_wreq <= '0';
    ADVERTISE_wreq <= '0';
    WR_SPEC_wreq <= '0';
    ECTRL_wreq <= '0';
    phy_specific_regs_we <= '0';
    case wr_adr_d0(13 downto 13) is
    when "0" =>
      case wr_adr_d0(12 downto 2) is
      when "00000000000" =>
        -- Reg MCR
        MCR_wreq <= wr_req_d0;
        wr_ack_int <= MCR_wack;
      when "00000000001" =>
        -- Reg MSR
        wr_ack_int <= wr_req_d0;
      when "00000000010" =>
        -- Reg PHYSID1
        wr_ack_int <= wr_req_d0;
      when "00000000011" =>
        -- Reg PHYSID2
        wr_ack_int <= wr_req_d0;
      when "00000000100" =>
        -- Reg ADVERTISE
        ADVERTISE_wreq <= wr_req_d0;
        wr_ack_int <= ADVERTISE_wack;
      when "00000000101" =>
        -- Reg LPA
        wr_ack_int <= wr_req_d0;
      when "00000000110" =>
        -- Reg EXPANSION
        wr_ack_int <= wr_req_d0;
      when "00000001111" =>
        -- Reg ESTATUS
        wr_ack_int <= wr_req_d0;
      when "00000010000" =>
        -- Reg WR_SPEC
        WR_SPEC_wreq <= wr_req_d0;
        wr_ack_int <= WR_SPEC_wack;
      when "00000010001" =>
        -- Reg ECTRL
        ECTRL_wreq <= wr_req_d0;
        wr_ack_int <= ECTRL_wack;
      when others =>
        wr_ack_int <= wr_req_d0;
      end case;
    when "1" =>
      -- Submap phy_specific_regs
      phy_specific_regs_we <= wr_req_d0;
      wr_ack_int <= phy_specific_regs_wack;
    when others =>
      wr_ack_int <= wr_req_d0;
    end case;
  end process;

  -- Process for read requests.
  process (adr_int, rd_req_int, MCR_uni_en_reg, MCR_pdown_reg, MCR_anenable_reg,
           MCR_loopback_reg, mdio_regs_i.MSR_LSTATUS, mdio_regs_i.MSR_RFAULT,
           mdio_regs_i.MSR_anegcomplete, ADVERTISE_PAUSE_reg,
           ADVERTISE_RFAULT_reg, mdio_regs_i.LPA_FULL, mdio_regs_i.LPA_HALF,
           mdio_regs_i.LPA_PAUSE, mdio_regs_i.LPA_RFAULT,
           mdio_regs_i.LPA_LPACK, mdio_regs_i.LPA_NPAGE, WR_SPEC_TX_CAL_reg,
           mdio_regs_i.WR_SPEC_RX_CAL_STAT, mdio_regs_i.WR_SPEC_BSLIDE,
           ECTRL_lpbck_vec_reg, mdio_regs_i.ECTRL_sfp_tx_fault,
           mdio_regs_i.ECTRL_sfp_loss, ECTRL_sfp_tx_disable_reg,
           ECTRL_tx_prbs_sel_reg, phy_specific_regs_i.dat,
           phy_specific_regs_rack) begin
    -- By default ack read requests
    rd_dat_d0 <= (others => 'X');
    mdio_regs_o.MSR_rd <= '0';
    phy_specific_regs_re <= '0';
    case adr_int(13 downto 13) is
    when "0" =>
      case adr_int(12 downto 2) is
      when "00000000000" =>
        -- Reg MCR
        rd_ack_d0 <= rd_req_int;
        rd_dat_d0(4 downto 0) <= "00000";
        rd_dat_d0(5) <= MCR_uni_en_reg;
        rd_dat_d0(6) <= '1';
        rd_dat_d0(7) <= '0';
        rd_dat_d0(8) <= '1';
        rd_dat_d0(9) <= '0';
        rd_dat_d0(10) <= '0';
        rd_dat_d0(11) <= MCR_pdown_reg;
        rd_dat_d0(12) <= MCR_anenable_reg;
        rd_dat_d0(13) <= '0';
        rd_dat_d0(14) <= MCR_loopback_reg;
        rd_dat_d0(15) <= '0';
        rd_dat_d0(31 downto 16) <= (others => '0');
      when "00000000001" =>
        -- Reg MSR
        mdio_regs_o.MSR_rd <= rd_req_int;
        rd_ack_d0 <= rd_req_int;
        rd_dat_d0(0) <= '0';
        rd_dat_d0(1) <= '0';
        rd_dat_d0(2) <= mdio_regs_i.MSR_LSTATUS;
        rd_dat_d0(3) <= '1';
        rd_dat_d0(4) <= mdio_regs_i.MSR_RFAULT;
        rd_dat_d0(5) <= mdio_regs_i.MSR_anegcomplete;
        rd_dat_d0(6) <= '0';
        rd_dat_d0(7) <= '1';
        rd_dat_d0(8) <= '1';
        rd_dat_d0(9) <= '0';
        rd_dat_d0(10) <= '0';
        rd_dat_d0(11) <= '0';
        rd_dat_d0(12) <= '0';
        rd_dat_d0(13) <= '0';
        rd_dat_d0(14) <= '0';
        rd_dat_d0(15) <= '0';
        rd_dat_d0(31 downto 16) <= (others => '0');
      when "00000000010" =>
        -- Reg PHYSID1
        rd_ack_d0 <= rd_req_int;
        rd_dat_d0(15 downto 0) <= "0000000000000000";
        rd_dat_d0(31 downto 16) <= (others => '0');
      when "00000000011" =>
        -- Reg PHYSID2
        rd_ack_d0 <= rd_req_int;
        rd_dat_d0(3 downto 0) <= "0000";
        rd_dat_d0(9 downto 4) <= "000000";
        rd_dat_d0(15 downto 10) <= "000000";
        rd_dat_d0(31 downto 16) <= (others => '0');
      when "00000000100" =>
        -- Reg ADVERTISE
        rd_ack_d0 <= rd_req_int;
        rd_dat_d0(4 downto 0) <= "00000";
        rd_dat_d0(5) <= '1';
        rd_dat_d0(6) <= '0';
        rd_dat_d0(8 downto 7) <= ADVERTISE_PAUSE_reg;
        rd_dat_d0(11 downto 9) <= "000";
        rd_dat_d0(13 downto 12) <= ADVERTISE_RFAULT_reg;
        rd_dat_d0(14) <= '0';
        rd_dat_d0(15) <= '0';
        rd_dat_d0(31 downto 16) <= (others => '0');
      when "00000000101" =>
        -- Reg LPA
        rd_ack_d0 <= rd_req_int;
        rd_dat_d0(4 downto 0) <= "00000";
        rd_dat_d0(5) <= mdio_regs_i.LPA_FULL;
        rd_dat_d0(6) <= mdio_regs_i.LPA_HALF;
        rd_dat_d0(8 downto 7) <= mdio_regs_i.LPA_PAUSE;
        rd_dat_d0(11 downto 9) <= "000";
        rd_dat_d0(13 downto 12) <= mdio_regs_i.LPA_RFAULT;
        rd_dat_d0(14) <= mdio_regs_i.LPA_LPACK;
        rd_dat_d0(15) <= mdio_regs_i.LPA_NPAGE;
        rd_dat_d0(31 downto 16) <= (others => '0');
      when "00000000110" =>
        -- Reg EXPANSION
        rd_ack_d0 <= rd_req_int;
        rd_dat_d0(0) <= '0';
        rd_dat_d0(1) <= '0';
        rd_dat_d0(2) <= '0';
        rd_dat_d0(15 downto 3) <= "0000000000000";
        rd_dat_d0(31 downto 16) <= (others => '0');
      when "00000001111" =>
        -- Reg ESTATUS
        rd_ack_d0 <= rd_req_int;
        rd_dat_d0(11 downto 0) <= "000000000000";
        rd_dat_d0(12) <= '0';
        rd_dat_d0(13) <= '0';
        rd_dat_d0(14) <= '0';
        rd_dat_d0(15) <= '1';
        rd_dat_d0(31 downto 16) <= (others => '0');
      when "00000010000" =>
        -- Reg WR_SPEC
        rd_ack_d0 <= rd_req_int;
        rd_dat_d0(0) <= WR_SPEC_TX_CAL_reg;
        rd_dat_d0(1) <= mdio_regs_i.WR_SPEC_RX_CAL_STAT;
        rd_dat_d0(2) <= '0';
        rd_dat_d0(3) <= '0';
        rd_dat_d0(8 downto 4) <= mdio_regs_i.WR_SPEC_BSLIDE;
        rd_dat_d0(31 downto 9) <= (others => '0');
      when "00000010001" =>
        -- Reg ECTRL
        rd_ack_d0 <= rd_req_int;
        rd_dat_d0(2 downto 0) <= ECTRL_lpbck_vec_reg;
        rd_dat_d0(3) <= mdio_regs_i.ECTRL_sfp_tx_fault;
        rd_dat_d0(4) <= mdio_regs_i.ECTRL_sfp_loss;
        rd_dat_d0(5) <= ECTRL_sfp_tx_disable_reg;
        rd_dat_d0(7 downto 6) <= (others => '0');
        rd_dat_d0(10 downto 8) <= ECTRL_tx_prbs_sel_reg;
        rd_dat_d0(31 downto 11) <= (others => '0');
      when others =>
        rd_ack_d0 <= rd_req_int;
      end case;
    when "1" =>
      -- Submap phy_specific_regs
      phy_specific_regs_re <= rd_req_int;
      rd_dat_d0 <= phy_specific_regs_i.dat;
      rd_ack_d0 <= phy_specific_regs_rack;
    when others =>
      rd_ack_d0 <= rd_req_int;
    end case;
  end process;
end syn;
