--=================================================================================================
-- File Name                           : plot_mux.vhd


-- Targeted device                     : Microsemi-SoC
-- Author                              : India Solutions Team
--
-- COPYRIGHT 2019 BY MICROSEMI
-- THE INFORMATION CONTAINED IN THIS DOCUMENT IS SUBJECT TO LICENSING RESTRICTIONS FROM MICROSEMI
-- CORP. IF YOU ARE NOT IN POSSESSION OF WRITTEN AUTHORIZATION FROM MICROSEMI FOR USE OF THIS
-- FILE, THEN THE FILE SHOULD BE IMMEDIATELY DESTROYED AND NO BACK-UP OF THE FILE SHOULD BE MADE.
--
--=================================================================================================

--=================================================================================================
-- Libraries
--=================================================================================================
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.NUMERIC_STD.ALL;

--=================================================================================================
-- plot_mux  entity declaration
--=================================================================================================
ENTITY plot_mux IS
GENERIC (
-- Generic list
    -- Specifies the width of constants
    g_CONST_WIDTH                      : INTEGER := 8;

    -- Specifies width of all input and output ports
    g_STD_IO_WIDTH                     : INTEGER RANGE 10 TO 18 := 18
);
PORT (
-- Port list
    -- System reset
    reset_i                            : IN  STD_LOGIC;
    -- System clock
    sys_clk_i                          : IN  STD_LOGIC;

    -- Trigger
    start_i                            : IN  STD_LOGIC;

    -- Data Input specifies the ia input of Clarke module
    ia_i             		           : IN STD_LOGIC_VECTOR(g_STD_IO_WIDTH-1 DOWNTO 0);

    -- Data Input specifies the ib input of Clarke module
    ib_i              	               : IN STD_LOGIC_VECTOR(g_STD_IO_WIDTH-1 DOWNTO 0);

    -- Data Input specifies the ialpha output of Clarke module
    ialpha_i                           : IN STD_LOGIC_VECTOR(g_STD_IO_WIDTH-1 DOWNTO 0);

    -- Data Input specifies the ibeta output of Clarke module
    ibeta_i                            : IN STD_LOGIC_VECTOR(g_STD_IO_WIDTH-1 DOWNTO 0);

    -- Data Input specifies the id output of Park module
    id_i                               : IN STD_LOGIC_VECTOR(g_STD_IO_WIDTH-1 DOWNTO 0);

    -- Data Input specifies the iq output of Park module
    iq_i                               : IN STD_LOGIC_VECTOR(g_STD_IO_WIDTH-1 DOWNTO 0);

    -- Data Input specifies the valpha output of IPark module
    valpha_i                           : IN STD_LOGIC_VECTOR(g_STD_IO_WIDTH-1 DOWNTO 0);

    -- Data Input specifies the vbeta output of IPark module
    vbeta_i                            : IN STD_LOGIC_VECTOR(g_STD_IO_WIDTH-1 DOWNTO 0);

    -- Data Input specifies the output of rate limiter module
	rl_out_i              	           : IN STD_LOGIC_VECTOR(g_STD_IO_WIDTH-1 DOWNTO 0);

    -- Data Input specifies the speed PI output
	speed_pi_out_i                 	   : IN STD_LOGIC_VECTOR(g_STD_IO_WIDTH-1 DOWNTO 0);

    -- Data Input specifies the id PI output
	id_pi_out_i                    	   : IN STD_LOGIC_VECTOR(g_STD_IO_WIDTH-1 DOWNTO 0);

    -- Data Input specifies the iq PI output
	iq_pi_out_i                    	   : IN STD_LOGIC_VECTOR(g_STD_IO_WIDTH-1 DOWNTO 0);

    -- Data Input specifies the ealpha input value
	ealpha_i                       	   : IN STD_LOGIC_VECTOR(g_STD_IO_WIDTH-1 DOWNTO 0);

    -- Data Input specifies the ebeta input value
	ebeta_i                        	   : IN STD_LOGIC_VECTOR(g_STD_IO_WIDTH-1 DOWNTO 0);

    -- Data Input specifies the ealpha filter output value
	ealpha_filter_out_i            	   : IN STD_LOGIC_VECTOR(g_STD_IO_WIDTH-1 DOWNTO 0);

    -- Data Input specifies the ebeta filter output value
	ebeta_filter_out_i             	   : IN STD_LOGIC_VECTOR(g_STD_IO_WIDTH-1 DOWNTO 0);

    -- Data Input specifies the PLL theta input value
	pll_theta_i                    	   : IN STD_LOGIC_VECTOR(g_STD_IO_WIDTH-1 DOWNTO 0);

    -- Data Input specifies the closed loop theta information
	theta_i                        	   : IN STD_LOGIC_VECTOR(g_STD_IO_WIDTH-1 DOWNTO 0);

    -- Data Input specifies the position estimator output
	omega_pi_out_i                 	   : IN STD_LOGIC_VECTOR(g_STD_IO_WIDTH-1 DOWNTO 0);

    -- Data Input specifies the position estimator output
	omega_filter_out_i             	   : IN STD_LOGIC_VECTOR(g_STD_IO_WIDTH-1 DOWNTO 0);

    -- Data Input specifies the ADC output for channel 0
    adc_ch0_val_i                      : IN STD_LOGIC_VECTOR(g_STD_IO_WIDTH-1 DOWNTO 0);

    -- Data Input specifies the ADC output for channel 1
    adc_ch1_val_i                      : IN STD_LOGIC_VECTOR(g_STD_IO_WIDTH-1 DOWNTO 0);

    -- Data Input specifies the ADC output for channel 2
    adc_ch2_val_i                      : IN STD_LOGIC_VECTOR(g_STD_IO_WIDTH-1 DOWNTO 0);

    -- Data Input specifies the ADC output for channel 3
    adc_ch3_val_i                      : IN STD_LOGIC_VECTOR(g_STD_IO_WIDTH-1 DOWNTO 0);

    ch_selection_i                     : IN STD_LOGIC_VECTOR(31 DOWNTO 0);

    fsm_sync_done_o                    : OUT STD_LOGIC;

    channel_a_o                        : OUT STD_LOGIC_VECTOR(15 DOWNTO 0);
                       
    channel_b_o                        : OUT STD_LOGIC_VECTOR(15 DOWNTO 0);
                       
    channel_c_o                        : OUT STD_LOGIC_VECTOR(15 DOWNTO 0);
                       
    channel_d_o                        : OUT STD_LOGIC_VECTOR(15 DOWNTO 0)  
);
END plot_mux;

--=================================================================================================
-- apb3_if architecture body
--=================================================================================================

ARCHITECTURE plot_mux OF plot_mux IS

--=================================================================================================
-- Component declarations
--=================================================================================================
--NA--

--=================================================================================================
-- Synthesis Attributes
--=================================================================================================
--NA--

--=================================================================================================
-- Signal declarations
--=================================================================================================
--ADC Register Addresses
--Plotting
CONSTANT C_IA_REG_ADDR                 : STD_LOGIC_VECTOR(g_CONST_WIDTH-1 DOWNTO 0) := x"00";
CONSTANT C_IB_REG_ADDR                 : STD_LOGIC_VECTOR(g_CONST_WIDTH-1 DOWNTO 0) := x"04";
CONSTANT C_IALPHA_REG_ADDR             : STD_LOGIC_VECTOR(g_CONST_WIDTH-1 DOWNTO 0) := x"08";
CONSTANT C_IBETA_REG_ADDR              : STD_LOGIC_VECTOR(g_CONST_WIDTH-1 DOWNTO 0) := x"0C";
CONSTANT C_ID_PARK_REG_ADDR            : STD_LOGIC_VECTOR(g_CONST_WIDTH-1 DOWNTO 0) := x"10";
CONSTANT C_IQ_PARK_REG_ADDR            : STD_LOGIC_VECTOR(g_CONST_WIDTH-1 DOWNTO 0) := x"14";
CONSTANT C_VALPHA_IPARK_REG_ADDR       : STD_LOGIC_VECTOR(g_CONST_WIDTH-1 DOWNTO 0) := x"18";
CONSTANT C_VBETA_IPARK_REG_ADDR        : STD_LOGIC_VECTOR(g_CONST_WIDTH-1 DOWNTO 0) := x"1C";
CONSTANT C_RATE_LIMITER_OUT_ADDR       : STD_LOGIC_VECTOR(g_CONST_WIDTH-1 DOWNTO 0) := x"20";
CONSTANT C_SPEED_PI_OUT_ADDR           : STD_LOGIC_VECTOR(g_CONST_WIDTH-1 DOWNTO 0) := x"24";
CONSTANT C_ID_PI_OUT_ADDR              : STD_LOGIC_VECTOR(g_CONST_WIDTH-1 DOWNTO 0) := x"28";
CONSTANT C_IQ_PI_OUT_ADDR              : STD_LOGIC_VECTOR(g_CONST_WIDTH-1 DOWNTO 0) := x"2C";
CONSTANT C_SQMNG_THETA_OUT_ADDR        : STD_LOGIC_VECTOR(g_CONST_WIDTH-1 DOWNTO 0) := x"30";
CONSTANT C_CH0_DATA_VAL_ADDR           : STD_LOGIC_VECTOR(g_CONST_WIDTH-1 DOWNTO 0) := x"38";
CONSTANT C_CH1_DATA_VAL_ADDR           : STD_LOGIC_VECTOR(g_CONST_WIDTH-1 DOWNTO 0) := x"3C";
CONSTANT C_CH2_DATA_VAL_ADDR           : STD_LOGIC_VECTOR(g_CONST_WIDTH-1 DOWNTO 0) := x"40";
CONSTANT C_CH3_DATA_VAL_ADDR           : STD_LOGIC_VECTOR(g_CONST_WIDTH-1 DOWNTO 0) := x"44";
--Position Estimator specific plotting
CONSTANT C_EALPHA_OUT_ADDR             : STD_LOGIC_VECTOR(g_CONST_WIDTH-1 DOWNTO 0) := x"50";
CONSTANT C_EBETA_OUT_ADDR              : STD_LOGIC_VECTOR(g_CONST_WIDTH-1 DOWNTO 0) := x"54";
CONSTANT C_EALPHA_FILTER_OUT_ADDR      : STD_LOGIC_VECTOR(g_CONST_WIDTH-1 DOWNTO 0) := x"58";
CONSTANT C_EBETA_FILTER_OUT_ADDR       : STD_LOGIC_VECTOR(g_CONST_WIDTH-1 DOWNTO 0) := x"5C";
CONSTANT C_PLL_THETA_OUT_ADDR          : STD_LOGIC_VECTOR(g_CONST_WIDTH-1 DOWNTO 0) := x"60";
CONSTANT C_OMEGA_PI_OUT_ADDR           : STD_LOGIC_VECTOR(g_CONST_WIDTH-1 DOWNTO 0) := x"64";
CONSTANT C_OMEGA_FILTER_OUT_ADDR       : STD_LOGIC_VECTOR(g_CONST_WIDTH-1 DOWNTO 0) := x"68";

TYPE UART_FSM IS                    	(IDLE,
                                         CH_A_DATA,
                                         CH_B_DATA,
                                         CH_C_DATA,
                                         CH_D_DATA
                                        );
SIGNAL state                           : UART_FSM;
SIGNAL s_done                          : STD_LOGIC;
SIGNAL s_start_dly                     : STD_LOGIC;
SIGNAL s_start_dtc                     : STD_LOGIC;
               
SIGNAL s_selector                      : STD_LOGIC_VECTOR(7 DOWNTO 0);
SIGNAL s_channel_a                     : STD_LOGIC_VECTOR(g_STD_IO_WIDTH-1 DOWNTO 0);
SIGNAL s_channel_b                     : STD_LOGIC_VECTOR(g_STD_IO_WIDTH-1 DOWNTO 0);
SIGNAL s_channel_c                     : STD_LOGIC_VECTOR(g_STD_IO_WIDTH-1 DOWNTO 0);
SIGNAL s_channel_d                     : STD_LOGIC_VECTOR(g_STD_IO_WIDTH-1 DOWNTO 0);
SIGNAL s_mux_out                       : STD_LOGIC_VECTOR(g_STD_IO_WIDTH-1 DOWNTO 0);

BEGIN


--=================================================================================================
-- Top level output port assignments
--=================================================================================================
channel_a_o     <= s_channel_a(17 DOWNTO 2);
channel_b_o     <= s_channel_b(17 DOWNTO 2);
channel_c_o     <= s_channel_c(17 DOWNTO 2);
channel_d_o     <= s_channel_d(17 DOWNTO 2);
fsm_sync_done_o <= s_done;
--=================================================================================================
-- Generate blocks
--=================================================================================================
--NA--

--=================================================================================================
-- Asynchronous blocks
--=================================================================================================
s_start_dtc <= start_i AND NOT(s_start_dly);
--------------------------------------------------------------------------
-- Name       : READ_DECODE_PROC
-- Description: Process implements the APB read operation
--------------------------------------------------------------------------

READ_DECODE_PROC:
    PROCESS (s_selector,ia_i,ib_i,ialpha_i,ibeta_i,id_i,adc_ch0_val_i,adc_ch1_val_i,
             iq_i,valpha_i,vbeta_i,rl_out_i,adc_ch2_val_i,adc_ch3_val_i,
             speed_pi_out_i,id_pi_out_i,iq_pi_out_i,ealpha_i,ebeta_i,ealpha_filter_out_i,
             ebeta_filter_out_i,omega_pi_out_i,pll_theta_i,omega_filter_out_i,theta_i)
    BEGIN
        CASE  s_selector  IS
--------------------
-- C_IA_REG_ADDR
--------------------
            WHEN C_IA_REG_ADDR =>
                s_mux_out               <= ia_i;
--------------------
-- C_IB_REG_ADDR
--------------------
            WHEN C_IB_REG_ADDR =>
                s_mux_out               <= ib_i;
--------------------
-- C_IALPHA_REG_ADDR
--------------------
            WHEN C_IALPHA_REG_ADDR =>
                s_mux_out               <= ialpha_i;
--------------------
-- C_IBETA_REG_ADDR
--------------------
            WHEN C_IBETA_REG_ADDR =>
                s_mux_out               <= ibeta_i;
--------------------
-- C_ID_PARK_REG_ADDR
--------------------
            WHEN C_ID_PARK_REG_ADDR =>
                s_mux_out               <= id_i;
--------------------
-- C_IQ_PARK_REG_ADDR
--------------------

            WHEN C_IQ_PARK_REG_ADDR =>
                s_mux_out               <= iq_i;
--------------------
-- C_VALPHA_IPARK_REG_ADDR
--------------------
            WHEN C_VALPHA_IPARK_REG_ADDR =>
                s_mux_out               <= valpha_i;
--------------------
-- C_VBETA_IPARK_REG_ADDR
--------------------
            WHEN C_VBETA_IPARK_REG_ADDR =>
                s_mux_out               <= vbeta_i;
--------------------
-- C_RATE_LIMITER_OUT_ADDR
--------------------
            WHEN C_RATE_LIMITER_OUT_ADDR =>
                s_mux_out               <= rl_out_i;
--------------------
-- C_SPEED_PI_OUT_ADDR
--------------------
            WHEN C_SPEED_PI_OUT_ADDR =>
                s_mux_out               <= speed_pi_out_i;
--------------------
-- C_ID_PI_OUT_ADDR
--------------------
            WHEN C_ID_PI_OUT_ADDR =>
                s_mux_out               <= id_pi_out_i;
--------------------
-- C_IQ_PI_OUT_ADDR
--------------------
            WHEN C_IQ_PI_OUT_ADDR =>
                s_mux_out               <= iq_pi_out_i;
--------------------
-- C_EALPHA_OUT_ADDR
--------------------
            WHEN C_EALPHA_OUT_ADDR  =>
                s_mux_out               <= ealpha_i;
--------------------
-- C_EBETA_OUT_ADDR
--------------------
            WHEN  C_EBETA_OUT_ADDR=>
                s_mux_out               <= ebeta_i;
--------------------
-- C_EALPHA_FILTER_OUT_ADDR
--------------------
            WHEN  C_EALPHA_FILTER_OUT_ADDR=>
                s_mux_out               <= ealpha_filter_out_i;
--------------------
-- C_EBETA_FILTER_OUT_ADDR
--------------------
            WHEN C_EBETA_FILTER_OUT_ADDR=>
                s_mux_out               <= ebeta_filter_out_i;
--------------------
-- C_OMEGA_PI_OUT_ADDR
--------------------
            WHEN  C_OMEGA_PI_OUT_ADDR=>
                s_mux_out               <= omega_pi_out_i;
--------------------
-- C_PLL_THETA_OUT_ADDR
--------------------
            WHEN C_PLL_THETA_OUT_ADDR  =>
                s_mux_out               <= pll_theta_i;
--------------------
-- C_OMEGA_FILTER_OUT_ADDR
--------------------
            WHEN C_OMEGA_FILTER_OUT_ADDR=>
                s_mux_out               <= omega_filter_out_i;
--------------------
-- C_SQMNG_THETA_OUT_ADDR
--------------------
            WHEN C_SQMNG_THETA_OUT_ADDR =>
                s_mux_out               <= theta_i;
--------------------
-- C_CH0_DATA_VAL_ADDR
--------------------
            WHEN C_CH0_DATA_VAL_ADDR =>
                s_mux_out <= adc_ch0_val_i;
--------------------
-- C_CH1_DATA_VAL_ADDR
--------------------
            WHEN C_CH1_DATA_VAL_ADDR =>
                s_mux_out <= adc_ch1_val_i;
--------------------
-- C_CH2_DATA_VAL_ADDR
--------------------
            WHEN C_CH2_DATA_VAL_ADDR =>
                s_mux_out <= adc_ch2_val_i;
--------------------
-- C_CH3_DATA_VAL_ADDR
--------------------
            WHEN C_CH3_DATA_VAL_ADDR =>
                s_mux_out <= adc_ch3_val_i;
--------------------
-- OTHERS
--------------------
            WHEN OTHERS =>
            s_mux_out <= (OTHERS=>'0');

        END CASE;

    END PROCESS;

--=================================================================================================
-- Synchronous blocks
--=================================================================================================
--------------------------------------------------------------------------
-- Name       : DELAY_PROC
-- Description: This process generates the slave select signal
--------------------------------------------------------------------------
DELAY_PROC:
    PROCESS(reset_i,sys_clk_i)
    BEGIN
        IF (reset_i = '0') THEN
            s_start_dly <= '0';
        ELSIF rising_edge(sys_clk_i) THEN
            s_start_dly <= start_i;
        END IF;
    END PROCESS;
--------------------------------------------------------------------------
-- Name       : FSM_PROC
-- Description: This process implements the UART interface FSM
--------------------------------------------------------------------------
FSM_PROC:
    PROCESS(sys_clk_i,reset_i)
    BEGIN
        IF reset_i = '0' THEN
                s_done          <= '0';
                s_selector      <= (OTHERS => '0');
                s_channel_a     <= (OTHERS => '0');
                s_channel_b     <= (OTHERS => '0');
                s_channel_c     <= (OTHERS => '0');
                s_channel_d     <= (OTHERS => '0');
                state           <= IDLE;
        ELSIF RISING_EDGE(sys_clk_i) THEN
            CASE state IS
------------------
-- IDLE state
------------------
                WHEN IDLE             =>
                    IF (s_start_dtc = '1') THEN
                        s_done <= '0';
                        state               <= CH_A_DATA;
                        s_selector          <= ch_selection_i(7 DOWNTO 0);
                    ELSE
                        s_done <= '1';
                        state               <= IDLE;
                    END IF;
------------------
-- CH_A_DATA state
------------------
                WHEN CH_A_DATA             =>
                        s_selector          <= ch_selection_i(15 DOWNTO 8);
                        state               <= CH_B_DATA;
                        s_channel_a         <= s_mux_out;
------------------
-- CH_B_DATA state
------------------
                WHEN CH_B_DATA             =>
                        s_selector          <= ch_selection_i(23 DOWNTO 16);
                        state               <= CH_C_DATA;
                        s_channel_b         <= s_mux_out;
------------------
-- CH_C_DATA state
------------------
                WHEN CH_C_DATA             =>
                        s_selector          <= ch_selection_i(31 DOWNTO 24);
                        state               <= CH_D_DATA;
                        s_channel_c         <= s_mux_out;
------------------
-- CH_D_DATA state
------------------
                WHEN CH_D_DATA             =>
                        state               <= IDLE;
                        s_channel_d         <= s_mux_out;

--------------------
-- OTHERS state
--------------------
                WHEN OTHERS           =>
                        s_done          <= '0';
                        s_selector      <= (OTHERS => '0');
                        s_channel_a     <= (OTHERS => '0');
                        s_channel_b     <= (OTHERS => '0');
                        s_channel_c     <= (OTHERS => '0');
                        s_channel_d     <= (OTHERS => '0');
                        state           <= IDLE;

            END CASE;
        END IF;
        
    END PROCESS;


--=================================================================================================
-- Component Instantiations
--=================================================================================================
--NA--

END ARCHITECTURE plot_mux;