-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
--
-- Copyright 2025 VLSI Solution Oy
-- SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1
--
-- Licensed under the Solderpad Hardware License v 2.1 (the "License");
-- you may not use this file except in compliance with the License, or,
-- at your option, the Apache License version 2.0.
-- You may obtain a copy of the License at
--
--    https://solderpad.org/licenses/SHL-2.1/
--
-- Unless required by applicable law or agreed to in writing, any work
-- distributed under the License is distributed on an "AS IS" BASIS,
-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-- See the License for the specific language governing permissions and
-- limitations under the License.
--
-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
--
--  uart_pkg.vhd
--  V1.1
--
--
-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -


library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;

package uart_pkg is

  subtype sl_t      is std_logic;
  subtype slv_t     is std_logic_vector;

  subtype slv_15_00 is std_logic_vector(15 downto 0);
  subtype slv_15_08 is std_logic_vector(15 downto 8);
  subtype slv_09_00 is std_logic_vector(9  downto 0);
  subtype slv_07_00 is std_logic_vector(7  downto 0);
  subtype slv_06_00 is std_logic_vector(6  downto 0);
  subtype slv_04_00 is std_logic_vector(4  downto 0);
  subtype slv_02_00 is std_logic_vector(2  downto 0);
  subtype slv_03_00 is std_logic_vector(3  downto 0);
  subtype slv_01_00 is std_logic_vector(1  downto 0);
  subtype slv_03_01 is std_logic_vector(3  downto 1);
  
  --  register addresses
  constant UART_REG_RB   : slv_02_00 := "000";  -- d0  - receiver buffer
  constant UART_REG_TR   : slv_02_00 := "000";  -- d0  - transmitter
  constant UART_REG_IE   : slv_02_00 := "001";  -- d1  - interrupt enable
  constant UART_REG_II   : slv_02_00 := "010";  -- d2  - inter identification
  constant UART_REG_FC   : slv_02_00 := "010";  -- d2  - FIFO control
  constant UART_REG_LC   : slv_02_00 := "011";  -- d3  - line Control
  constant UART_REG_MC   : slv_02_00 := "100";  -- d4  - modem control
  constant UART_REG_LS   : slv_02_00 := "101";  -- d5  - line status
  constant UART_REG_MS   : slv_02_00 := "110";  -- d6  - modem status
  constant UART_REG_SR   : slv_02_00 := "111";  -- d7  - scratch register
  constant UART_REG_DL1  : slv_02_00 := "000";  -- d0  - divisor latch bytes 1-2
  constant UART_REG_DL2  : slv_02_00 := "001";  -- d1

  --  interrupt enable register bits
  constant UART_IE_RDA   : natural := 0;   -- received data available interrupt
  constant UART_IE_THRE  : natural := 1;   -- transmitter holding register
                                           -- empty interrupt
  constant UART_IE_RLS   : natural := 2;   -- receiver line status interrupt
  constant UART_IE_MS    : natural := 3;   -- modem status interrupt

  --  interrupt identification register bits
  constant UART_II_IP    : natural   := 0;      -- interrupt pending when 0
  constant UART_II_II    : slv_03_01 := "000";  -- inter identification

  --  interrupt identification values for bits 3:1
  constant UART_II_RLS   : slv_02_00 := "011";  -- d3  - receiver line status
  constant UART_II_RDA   : slv_02_00 := "010";  -- d2  - receiver data available
  constant UART_II_TI    : slv_02_00 := "110";  -- d6  - timeout indication
  constant UART_II_THRE  : slv_02_00 := "001";  -- d1  - transmitter holding
                                                --         register empty
  constant UART_II_MS    : slv_02_00 := "000";  -- d0  - modem Status

  --  FIFO control register bits
  constant UART_FC_TL    : slv_01_00 := "00";   -- trigger level

  --  FIFO trigger level values
  constant UART_FC_1     : slv_01_00 := "00";   -- d0
  constant UART_FC_4     : slv_01_00 := "01";   -- d1
  constant UART_FC_8     : slv_01_00 := "10";   -- d2
  constant UART_FC_14    : slv_01_00 := "11";   -- d3

  --  Line control register bits
  constant UART_LC_BITS  : slv_01_00 := "00";   -- bits in character
  constant UART_LC_SB    : natural := 2;        -- stop bits
  constant UART_LC_PE    : natural := 3;        -- parity enable
  constant UART_LC_EP    : natural := 4;        -- even parity
  constant UART_LC_SP    : natural := 5;        -- stick parity
  constant UART_LC_BC    : natural := 6;        -- break control
  constant UART_LC_DL    : natural := 7;        -- divisor latch access bit

  --  modem control register bits
  constant UART_MC_DTR   : natural := 0;
  constant UART_MC_RTS   : natural := 1;
  constant UART_MC_OUT1  : natural := 2;
  constant UART_MC_OUT2  : natural := 3;
  constant UART_MC_LB    : natural := 4;        -- loopback mode

  --  line status register bits
  constant UART_LS_DR    : natural := 0;        -- data ready
  constant UART_LS_OE    : natural := 1;        -- overrun error
  constant UART_LS_PE    : natural := 2;        -- parity error
  constant UART_LS_FE    : natural := 3;        -- framing error
  constant UART_LS_BI    : natural := 4;        -- break interrupt
  constant UART_LS_TFE   : natural := 5;        -- transmit FIFO is empty
  constant UART_LS_TE    : natural := 6;        -- transmitter empty indicator
  constant UART_LS_EI    : natural := 7;        -- error indicator

  --  modem status register bits
  constant UART_MS_DCTS  : natural := 0;        -- delta signals
  constant UART_MS_DDSR  : natural := 1;
  constant UART_MS_TERI  : natural := 2;
  constant UART_MS_DDCD  : natural := 3;
  constant UART_MS_CCTS  : natural := 4;        -- complement signals
  constant UART_MS_CDSR  : natural := 5;
  constant UART_MS_CRI   : natural := 6;
  constant UART_MS_CDCD  : natural := 7;


  --  All activity on the WISHBONE is recorded
  constant VERBOSE_WB          : std_logic := '0';
  --  details about the lsr (line status register)
  constant VERBOSE_LINE_STATUS : std_logic := '0';
  --  64/1024 packets are sent
  constant FAST_TEST           : std_logic := '1';


  function to_uint  (arg1 : slv_t)                return natural;

  -- increment unsigned
  function inc1u    (svec : slv_t)                return slv_t;
  -- decrement unsigned
  function dec1u    (svec : slv_t)                return slv_t;

  -- equal
  function eq       (svec1, svec2 : slv_t)        return std_logic;


  -- return or of all bits in vector
  function not_zero (svec : slv_t)                return std_logic;


  -- return xor of all bits in vector and parity bit
  function xor_bits (svec : slv_t; parity : sl_t) return std_logic;

  function log2     (arg1 : natural)              return natural;

end uart_pkg;


package body uart_pkg is

  
  -- - - - - - - - - - - - - - - - - - - - - - -
  -- return std_logic_vector as unsigned integer
  -- - - - - - - - - - - - - - - - - - - - - - -
  function to_uint (arg1 : slv_t) return natural is
    variable result: natural;
  begin
    return to_integer(unsigned(arg1));    -- POSITIVE integer, i.e. natural
  end function to_uint;


  -- - - - - - - - - - - - - - - - - - - - - - -
  -- increment unsigned std_logic_vector by one
  -- - - - - - - - - - - - - - - - - - - - - - -
  function inc1u ( svec : slv_t ) return slv_t is
  begin
    return (slv_t(unsigned(svec) + 1));
  end function inc1u;
  -- - - - - - - - - - - - - - - - - - - - - - -
  -- decrement unsigned std_logic_vector by one
  -- - - - - - - - - - - - - - - - - - - - - - -
  function dec1u ( svec : slv_t ) return slv_t is
  begin
    return (slv_t(unsigned(svec) - 1));
  end function dec1u;


  -- - - - - - - - - - - - - - - - - - - - -
  -- return '1' if std_logic_vectors match
  -- - - - - - - - - - - - - - - - - - - - -
  function eq (svec1, svec2 : slv_t) return std_logic is
    variable result_v : std_logic;
  begin
    result_v := '0';
    if (svec1 = svec2) then
      result_v := '1';
    end if;
    return result_v;
  end;


  -- - - - - - - - - - - - - - - - - - - - -
  -- return or of all bits in vector
  -- - - - - - - - - - - - - - - - - - - - -
  function not_zero (svec : slv_t) return std_logic is
  begin
    if (unsigned(svec) = 0) then
      return '0';
    else
      return '1';
    end if;
  end;


  -- - - - - - - - - - - - - - - - - - - - - - - - -
  -- return xor of all bits in vector and parity bit
  -- - - - - - - - - - - - - - - - - - - - - - - - -
  function xor_bits (svec : slv_t; parity : sl_t) return std_logic is
    variable result_v : std_logic;
  begin
    result_v := '0';
    for ii in svec'range loop
      result_v := result_v xor svec(ii);
    end loop;
    result_v := result_v xor parity;
    return result_v;
  end;

    -- - - - - - - - - - - - - - - - - - - - -
  -- return log2 of argument
  -- - - - - - - - - - - - - - - - - - - - -
  function log2 (arg1 : natural) return natural is
    variable result: natural;
  begin
    result := 0;
    while 2 ** result < arg1 loop
      result := result + 1;
    end loop;
    if (result < 1) then
      result := 1;
    end if;
    return result;
  end function log2;


end uart_pkg;
