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

entity ABC_to_dq_v1_0 is
	generic (
		-- Users to add parameters here

		-- User parameters ends
		-- Do not modify the parameters beyond this line


		-- Parameters of Axi Slave Bus Interface S00_AXI
		C_S00_AXI_DATA_WIDTH	: integer	:= 32;
		C_S00_AXI_ADDR_WIDTH	: integer	:= 4
	);
	port (
		-- Users to add ports here
        sync_in : in std_logic;
        clk : in std_logic;
        a : in std_logic_vector (15 downto 0);
        b : in std_logic_vector (15 downto 0);
        angle : in std_logic_vector (15 downto 0);
        d : out std_logic_vector (15 downto 0);
        q : out std_logic_vector (15 downto 0);
        sin : out std_logic_vector (15 downto 0);
        cos : out std_logic_vector (15 downto 0);
        sync_out : out std_logic;
		-- User ports ends
		-- Do not modify the ports beyond this line


		-- Ports of Axi Slave Bus Interface S00_AXI
		s00_axi_aclk	: in std_logic;
		s00_axi_aresetn	: in std_logic;
		s00_axi_awaddr	: in std_logic_vector(C_S00_AXI_ADDR_WIDTH-1 downto 0);
		s00_axi_awprot	: in std_logic_vector(2 downto 0);
		s00_axi_awvalid	: in std_logic;
		s00_axi_awready	: out std_logic;
		s00_axi_wdata	: in std_logic_vector(C_S00_AXI_DATA_WIDTH-1 downto 0);
		s00_axi_wstrb	: in std_logic_vector((C_S00_AXI_DATA_WIDTH/8)-1 downto 0);
		s00_axi_wvalid	: in std_logic;
		s00_axi_wready	: out std_logic;
		s00_axi_bresp	: out std_logic_vector(1 downto 0);
		s00_axi_bvalid	: out std_logic;
		s00_axi_bready	: in std_logic;
		s00_axi_araddr	: in std_logic_vector(C_S00_AXI_ADDR_WIDTH-1 downto 0);
		s00_axi_arprot	: in std_logic_vector(2 downto 0);
		s00_axi_arvalid	: in std_logic;
		s00_axi_arready	: out std_logic;
		s00_axi_rdata	: out std_logic_vector(C_S00_AXI_DATA_WIDTH-1 downto 0);
		s00_axi_rresp	: out std_logic_vector(1 downto 0);
		s00_axi_rvalid	: out std_logic;
		s00_axi_rready	: in std_logic
	);
end ABC_to_dq_v1_0;

architecture arch_imp of ABC_to_dq_v1_0 is

    signal sync_d1 : std_logic;
    
    signal a_signal : signed (15 downto 0);
    signal b_signal : signed (15 downto 0);
    signal d_signal : signed (15 downto 0);
    signal q_signal : signed (15 downto 0);
    signal alfa : signed (15 downto 0);
    signal beta : signed (15 downto 0);
    signal trig_sin : signed (15 downto 0);
    signal trig_cos : signed (15 downto 0);
    signal sin_signal : signed (15 downto 0);
    signal cos_signal : signed (15 downto 0);
    signal angle_signal : unsigned (15 downto 0);
    
    signal AXI_DATA0 : std_logic_vector (C_S00_AXI_DATA_WIDTH-1 downto 0);
    signal AXI_DATA1 : std_logic_vector (C_S00_AXI_DATA_WIDTH-1 downto 0);
    signal AXI_DATA2 : std_logic_vector (C_S00_AXI_DATA_WIDTH-1 downto 0);
    signal AXI_DATA3 : std_logic_vector (C_S00_AXI_DATA_WIDTH-1 downto 0);
    
	-- component declaration
	component ABC_to_dq_v1_0_S00_AXI is
		generic (
		C_S_AXI_DATA_WIDTH	: integer	:= 32;
		C_S_AXI_ADDR_WIDTH	: integer	:= 4
		);
		port (
		AXI_DATA0 : in std_logic_vector (C_S_AXI_DATA_WIDTH-1 downto 0);
        AXI_DATA1 : in std_logic_vector (C_S_AXI_DATA_WIDTH-1 downto 0);
        AXI_DATA2 : in std_logic_vector (C_S_AXI_DATA_WIDTH-1 downto 0);
        AXI_DATA3 : in std_logic_vector (C_S_AXI_DATA_WIDTH-1 downto 0);
		S_AXI_ACLK	: in std_logic;
		S_AXI_ARESETN	: in std_logic;
		S_AXI_AWADDR	: in std_logic_vector(C_S_AXI_ADDR_WIDTH-1 downto 0);
		S_AXI_AWPROT	: in std_logic_vector(2 downto 0);
		S_AXI_AWVALID	: in std_logic;
		S_AXI_AWREADY	: out std_logic;
		S_AXI_WDATA	: in std_logic_vector(C_S_AXI_DATA_WIDTH-1 downto 0);
		S_AXI_WSTRB	: in std_logic_vector((C_S_AXI_DATA_WIDTH/8)-1 downto 0);
		S_AXI_WVALID	: in std_logic;
		S_AXI_WREADY	: out std_logic;
		S_AXI_BRESP	: out std_logic_vector(1 downto 0);
		S_AXI_BVALID	: out std_logic;
		S_AXI_BREADY	: in std_logic;
		S_AXI_ARADDR	: in std_logic_vector(C_S_AXI_ADDR_WIDTH-1 downto 0);
		S_AXI_ARPROT	: in std_logic_vector(2 downto 0);
		S_AXI_ARVALID	: in std_logic;
		S_AXI_ARREADY	: out std_logic;
		S_AXI_RDATA	: out std_logic_vector(C_S_AXI_DATA_WIDTH-1 downto 0);
		S_AXI_RRESP	: out std_logic_vector(1 downto 0);
		S_AXI_RVALID	: out std_logic;
		S_AXI_RREADY	: in std_logic
		);
	end component ABC_to_dq_v1_0_S00_AXI;
	
	component Triginometric is
        port (
            sync_in : in std_logic;
            clk : in std_logic;
            angle : in unsigned (15 downto 0);
            sin : out signed (15 downto 0);
            cos : out signed (15 downto 0);
            sync_out : out std_logic
        );
    end component;
    
    component Clarc_transformation is    
        port (
            a : in signed (15 downto 0);
            b : in signed (15 downto 0);
            alfa : out signed (15 downto 0);
            beta : out signed (15 downto 0)
        );
    end component;
    
    component Park_transformation is
        Port (
            alfa : in signed (15 downto 0); 
            beta : in signed (15 downto 0); 
            sin : in signed (15 downto 0);
            cos : in signed (15 downto 0);
            d : out signed (15 downto 0); 
            q : out signed (15 downto 0) 
        );
    end component;

begin

-- Instantiation of Axi Bus Interface S00_AXI
ABC_to_dq_v1_0_S00_AXI_inst : ABC_to_dq_v1_0_S00_AXI
	generic map (
		C_S_AXI_DATA_WIDTH	=> C_S00_AXI_DATA_WIDTH,
		C_S_AXI_ADDR_WIDTH	=> C_S00_AXI_ADDR_WIDTH
	)
	port map (
	    AXI_DATA0 => AXI_DATA0,
        AXI_DATA1 => AXI_DATA1,
        AXI_DATA2 => AXI_DATA2,
        AXI_DATA3 => AXI_DATA3,
		S_AXI_ACLK	=> s00_axi_aclk,
		S_AXI_ARESETN	=> s00_axi_aresetn,
		S_AXI_AWADDR	=> s00_axi_awaddr,
		S_AXI_AWPROT	=> s00_axi_awprot,
		S_AXI_AWVALID	=> s00_axi_awvalid,
		S_AXI_AWREADY	=> s00_axi_awready,
		S_AXI_WDATA	=> s00_axi_wdata,
		S_AXI_WSTRB	=> s00_axi_wstrb,
		S_AXI_WVALID	=> s00_axi_wvalid,
		S_AXI_WREADY	=> s00_axi_wready,
		S_AXI_BRESP	=> s00_axi_bresp,
		S_AXI_BVALID	=> s00_axi_bvalid,
		S_AXI_BREADY	=> s00_axi_bready,
		S_AXI_ARADDR	=> s00_axi_araddr,
		S_AXI_ARPROT	=> s00_axi_arprot,
		S_AXI_ARVALID	=> s00_axi_arvalid,
		S_AXI_ARREADY	=> s00_axi_arready,
		S_AXI_RDATA	=> s00_axi_rdata,
		S_AXI_RRESP	=> s00_axi_rresp,
		S_AXI_RVALID	=> s00_axi_rvalid,
		S_AXI_RREADY	=> s00_axi_rready
	);

	-- Add user logic here
	trigon_inst: Triginometric
        port map (
            sync_in => sync_in,
            clk => clk,
            angle => angle_signal,
            sin => trig_sin,
            cos => trig_cos,
            sync_out => sync_d1
        );
        
    clark_inst : Clarc_transformation    
        port map (
            a => a_signal,
            b => b_signal,
            alfa => alfa,
            beta => beta
        );
        
    park_inst : Park_transformation
        port map (
            alfa => alfa,
            beta => beta,
            sin => trig_sin,
            cos => trig_cos,
            d => d_signal, 
            q => q_signal 
        );      
	
	angle_signal <= unsigned(angle);
	a_signal <= signed(a);
	b_signal <= signed(b);
	
    process (clk) begin 
        if (clk'event and clk='1') then
            if (sync_d1='1') then
                d <= std_logic_vector(d_signal);
                q <= std_logic_vector(q_signal);
                sin_signal <= trig_sin;
                cos_signal <= trig_cos;
                sin <= std_logic_vector(trig_sin);
                cos <= std_logic_vector(trig_cos);
                AXI_DATA0 <= std_logic_vector(resize(d_signal,C_S00_AXI_DATA_WIDTH));
                AXI_DATA1 <= std_logic_vector(resize(q_signal,C_S00_AXI_DATA_WIDTH));
                AXI_DATA2 <= std_logic_vector(resize(sin_signal,C_S00_AXI_DATA_WIDTH));
                AXI_DATA3 <= std_logic_vector(resize(cos_signal,C_S00_AXI_DATA_WIDTH));
                sync_out <= '1';
            else
                sync_out <= '0';     
            end if;    
        end if;  
    end process;
	-- User logic ends

end arch_imp;
