-- Do not edit.  Generated by cheby 1.5.dev0 using these options:
--  -i lpdc_mdio_regs.cheby --gen-hdl lpdc_mdio_regs.vhd
-- Generated on Mon Apr 24 15:04:26 2023 by twl


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

package lpdc_mdio_regs_pkg is
  type t_lpdc_regs_master_out is record
    CTRL_tx_sw_reset : std_logic;
    CTRL_tx_enable   : std_logic;
    CTRL_rx_enable   : std_logic;
    CTRL_rx_sw_reset : std_logic;
    CTRL_qpll_sw_reset : std_logic;
    CTRL_txusrpll_reset : std_logic;
    CTRL_comma_target_pos : std_logic_vector(7 downto 0);
    CTRL_dmtd_clk_sel : std_logic_vector(1 downto 0);
  end record t_lpdc_regs_master_out;
  subtype t_lpdc_regs_slave_in is t_lpdc_regs_master_out;

  type t_lpdc_regs_slave_out is record
    STAT_qpll_locked : std_logic;
    STAT_link_up     : std_logic;
    STAT_link_aligned : std_logic;
    STAT_tx_rst_done : std_logic;
    STAT_txusrpll_locked : std_logic;
    STAT_rx_rst_done : std_logic;
    STAT_comma_current_pos : std_logic_vector(7 downto 0);
    STAT_comma_pos_valid : std_logic;
  end record t_lpdc_regs_slave_out;
  subtype t_lpdc_regs_master_in is t_lpdc_regs_slave_out;

end lpdc_mdio_regs_pkg;

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

entity lpdc_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
    lpdc_regs_i          : in    t_lpdc_regs_master_in;
    lpdc_regs_o          : out   t_lpdc_regs_master_out;

    -- Xilinx DRP registers, specific to the transceiver
    drp_regs_i           : in    t_wishbone_master_in;
    drp_regs_o           : out   t_wishbone_master_out
  );
end lpdc_mdio_regs;

architecture syn of lpdc_mdio_regs is
  signal adr_int                        : std_logic_vector(12 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 CTRL_tx_sw_reset_reg           : std_logic;
  signal CTRL_tx_enable_reg             : std_logic;
  signal CTRL_rx_enable_reg             : std_logic;
  signal CTRL_rx_sw_reset_reg           : std_logic;
  signal CTRL_qpll_sw_reset_reg         : std_logic;
  signal CTRL_txusrpll_reset_reg        : std_logic;
  signal CTRL_comma_target_pos_reg      : std_logic_vector(7 downto 0);
  signal CTRL_dmtd_clk_sel_reg          : std_logic_vector(1 downto 0);
  signal CTRL_wreq                      : std_logic;
  signal CTRL_wack                      : std_logic;
  signal drp_regs_re                    : std_logic;
  signal drp_regs_we                    : std_logic;
  signal drp_regs_wt                    : std_logic;
  signal drp_regs_rt                    : std_logic;
  signal drp_regs_tr                    : std_logic;
  signal drp_regs_wack                  : std_logic;
  signal drp_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(12 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(12 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 CTRL
  lpdc_regs_o.CTRL_tx_sw_reset <= CTRL_tx_sw_reset_reg;
  lpdc_regs_o.CTRL_tx_enable <= CTRL_tx_enable_reg;
  lpdc_regs_o.CTRL_rx_enable <= CTRL_rx_enable_reg;
  lpdc_regs_o.CTRL_rx_sw_reset <= CTRL_rx_sw_reset_reg;
  lpdc_regs_o.CTRL_qpll_sw_reset <= CTRL_qpll_sw_reset_reg;
  lpdc_regs_o.CTRL_txusrpll_reset <= CTRL_txusrpll_reset_reg;
  lpdc_regs_o.CTRL_comma_target_pos <= CTRL_comma_target_pos_reg;
  lpdc_regs_o.CTRL_dmtd_clk_sel <= CTRL_dmtd_clk_sel_reg;
  process (clk_i) begin
    if rising_edge(clk_i) then
      if rst_n_i = '0' then
        CTRL_tx_sw_reset_reg <= '0';
        CTRL_tx_enable_reg <= '0';
        CTRL_rx_enable_reg <= '0';
        CTRL_rx_sw_reset_reg <= '0';
        CTRL_qpll_sw_reset_reg <= '0';
        CTRL_txusrpll_reset_reg <= '0';
        CTRL_comma_target_pos_reg <= "00000000";
        CTRL_dmtd_clk_sel_reg <= "00";
        CTRL_wack <= '0';
      else
        if CTRL_wreq = '1' then
          CTRL_tx_sw_reset_reg <= wr_dat_d0(0);
          CTRL_tx_enable_reg <= wr_dat_d0(1);
          CTRL_rx_enable_reg <= wr_dat_d0(2);
          CTRL_rx_sw_reset_reg <= wr_dat_d0(3);
          CTRL_qpll_sw_reset_reg <= wr_dat_d0(4);
          CTRL_txusrpll_reset_reg <= wr_dat_d0(5);
          CTRL_comma_target_pos_reg <= wr_dat_d0(13 downto 6);
          CTRL_dmtd_clk_sel_reg <= wr_dat_d0(15 downto 14);
        end if;
        CTRL_wack <= CTRL_wreq;
      end if;
    end if;
  end process;

  -- Register STAT

  -- Interface drp_regs
  drp_regs_tr <= drp_regs_wt or drp_regs_rt;
  process (clk_i) begin
    if rising_edge(clk_i) then
      if rst_n_i = '0' then
        drp_regs_rt <= '0';
        drp_regs_wt <= '0';
      else
        drp_regs_rt <= (drp_regs_rt or drp_regs_re) and not drp_regs_rack;
        drp_regs_wt <= (drp_regs_wt or drp_regs_we) and not drp_regs_wack;
      end if;
    end if;
  end process;
  drp_regs_o.cyc <= drp_regs_tr;
  drp_regs_o.stb <= drp_regs_tr;
  drp_regs_wack <= drp_regs_i.ack and drp_regs_wt;
  drp_regs_rack <= drp_regs_i.ack and drp_regs_rt;
  drp_regs_o.adr <= ((19 downto 0 => '0') & adr_int(11 downto 2)) & (1 downto 0 => '0');
  drp_regs_o.sel <= wr_sel_d0;
  drp_regs_o.we <= drp_regs_wt;
  drp_regs_o.dat <= wr_dat_d0;

  -- Process for write requests.
  process (wr_adr_d0, wr_req_d0, CTRL_wack, drp_regs_wack) begin
    CTRL_wreq <= '0';
    drp_regs_we <= '0';
    case wr_adr_d0(12 downto 12) is
    when "0" =>
      case wr_adr_d0(11 downto 2) is
      when "0000000000" =>
        -- Reg CTRL
        CTRL_wreq <= wr_req_d0;
        wr_ack_int <= CTRL_wack;
      when "0000000001" =>
        -- Reg STAT
        wr_ack_int <= wr_req_d0;
      when others =>
        wr_ack_int <= wr_req_d0;
      end case;
    when "1" =>
      -- Submap drp_regs
      drp_regs_we <= wr_req_d0;
      wr_ack_int <= drp_regs_wack;
    when others =>
      wr_ack_int <= wr_req_d0;
    end case;
  end process;

  -- Process for read requests.
  process (adr_int, rd_req_int, CTRL_tx_sw_reset_reg, CTRL_tx_enable_reg,
           CTRL_rx_enable_reg, CTRL_rx_sw_reset_reg, CTRL_qpll_sw_reset_reg,
           CTRL_txusrpll_reset_reg, CTRL_comma_target_pos_reg,
           CTRL_dmtd_clk_sel_reg, lpdc_regs_i.STAT_qpll_locked,
           lpdc_regs_i.STAT_link_up, lpdc_regs_i.STAT_link_aligned,
           lpdc_regs_i.STAT_tx_rst_done, lpdc_regs_i.STAT_txusrpll_locked,
           lpdc_regs_i.STAT_rx_rst_done, lpdc_regs_i.STAT_comma_current_pos,
           lpdc_regs_i.STAT_comma_pos_valid, drp_regs_i.dat, drp_regs_rack) begin
    -- By default ack read requests
    rd_dat_d0 <= (others => 'X');
    drp_regs_re <= '0';
    case adr_int(12 downto 12) is
    when "0" =>
      case adr_int(11 downto 2) is
      when "0000000000" =>
        -- Reg CTRL
        rd_ack_d0 <= rd_req_int;
        rd_dat_d0(0) <= CTRL_tx_sw_reset_reg;
        rd_dat_d0(1) <= CTRL_tx_enable_reg;
        rd_dat_d0(2) <= CTRL_rx_enable_reg;
        rd_dat_d0(3) <= CTRL_rx_sw_reset_reg;
        rd_dat_d0(4) <= CTRL_qpll_sw_reset_reg;
        rd_dat_d0(5) <= CTRL_txusrpll_reset_reg;
        rd_dat_d0(13 downto 6) <= CTRL_comma_target_pos_reg;
        rd_dat_d0(15 downto 14) <= CTRL_dmtd_clk_sel_reg;
        rd_dat_d0(31 downto 16) <= (others => '0');
      when "0000000001" =>
        -- Reg STAT
        rd_ack_d0 <= rd_req_int;
        rd_dat_d0(0) <= lpdc_regs_i.STAT_qpll_locked;
        rd_dat_d0(1) <= lpdc_regs_i.STAT_link_up;
        rd_dat_d0(2) <= lpdc_regs_i.STAT_link_aligned;
        rd_dat_d0(3) <= lpdc_regs_i.STAT_tx_rst_done;
        rd_dat_d0(4) <= lpdc_regs_i.STAT_txusrpll_locked;
        rd_dat_d0(5) <= lpdc_regs_i.STAT_rx_rst_done;
        rd_dat_d0(6) <= '0';
        rd_dat_d0(14 downto 7) <= lpdc_regs_i.STAT_comma_current_pos;
        rd_dat_d0(15) <= lpdc_regs_i.STAT_comma_pos_valid;
        rd_dat_d0(31 downto 16) <= (others => '0');
      when others =>
        rd_ack_d0 <= rd_req_int;
      end case;
    when "1" =>
      -- Submap drp_regs
      drp_regs_re <= rd_req_int;
      rd_dat_d0 <= drp_regs_i.dat;
      rd_ack_d0 <= drp_regs_rack;
    when others =>
      rd_ack_d0 <= rd_req_int;
    end case;
  end process;
end syn;
