]> rtime.felk.cvut.cz Git - fpga/rpi-motor-control.git/blobdiff - pmsm-control/rpi_pmsm_control.vhdl
Correct typo in rpi-mc-1 mapping to Ti AM437x based RICO board.
[fpga/rpi-motor-control.git] / pmsm-control / rpi_pmsm_control.vhdl
index 9e606752b9089f3cb78bea2ffd76d23e0c6ce2cc..e900e8de60cc7a8df12c0dc0f9e2d21cac982305 100644 (file)
@@ -1,13 +1,22 @@
 --
--- * LXPWR slave part *
---  common sioreg & common counter for several ADC&PWM blocks
+-- * Raspberry Pi BLDC/PMSM motor control design for RPi-MI-1 board *
+-- The toplevel component file
 --
--- part of LXPWR motion control board (c) PiKRON Ltd
--- idea by Pavel Pisa PiKRON Ltd <pisa@cmp.felk.cvut.cz>
--- code by Marek Peca <mp@duch.cz>
--- 01/2013
+-- (c) 2015 Martin Prudek <prudemar@fel.cvut.cz>
+-- Czech Technical University in Prague
 --
--- license: GNU GPLv3
+-- Project supervision and original project idea
+-- idea by Pavel Pisa <pisa@cmp.felk.cvut.cz>
+--
+-- Related RPi-MI-1 hardware is designed by Petr Porazil,
+-- PiKRON Ltd  <http://www.pikron.com>
+--
+-- VHDL design reuses some components and concepts from
+-- LXPWR motion power stage board and LX_RoCoN system
+-- developed at PiKRON Ltd with base code implemented
+-- by Marek Peca <hefaistos@gmail.com>
+--
+-- license: GNU LGPL and GPLv3+
 --
 
 library ieee;
@@ -15,35 +24,35 @@ use ieee.std_logic_1164.all;
 use ieee.numeric_std.all;
 use work.util.all;
 
-entity rpi_mc_simple_dc is
+entity rpi_pmsm_control is
 generic(
        pwm_width : natural:=11
        );
 port (
        gpio2: in std_logic; -- SDA
        gpio3: in std_logic; -- SCL
-       gpio4: in std_logic; -- CLK
+       gpio4: in std_logic; -- CLK           (gpio_clk)
        gpio14: in std_logic; -- Tx
        gpio15: in std_logic; -- Rx
-       gpio17: in std_logic; -- RTS
-       gpio18: in std_logic; -- PWM0/PCMCLK
-       gpio27: in std_logic; -- SD1DAT3
-       gpio22: in std_logic; -- SD1CLK
-       gpio23: in std_logic; -- SD1CMD
-       gpio24: in std_logic; -- SD1DAT0
-       gpio10: in std_logic; -- SPI0MOSI
-       gpio9: out std_logic; -- SPI0MISO
-       gpio25: in std_logic; -- SD1DAT1
-       gpio11: in std_logic; -- SPI0SCLK
+       gpio17: inout std_logic; -- RTS       (irc_i)
+       gpio18: in std_logic; -- PWM0/PCMCLK  (pwm_in/pwm1)
+       gpio27: inout std_logic; -- SD1DAT3   (irc_b)
+       gpio22: in std_logic; -- SD1CLK       (pwm_dir_in/pwm1_en)
+       gpio23: inout std_logic; -- SD1CMD    (irc_a)
+       gpio24: inout std_logic; -- SD1DAT0   (irc_a)
+       gpio10: in std_logic; -- SPI0MOSI     (spi_mosi)
+       gpio9: out std_logic; -- SPI0MISO     (spi_miso)
+       gpio25: inout std_logic; -- SD1DAT1   (irc_b)
+       gpio11: in std_logic; -- SPI0SCLK     (spi_clk)
        gpio8: in std_logic; -- SPI0CE0
-       gpio7: in std_logic; -- SPI0CE1
+       gpio7: in std_logic; -- SPI0CE1       (spi_ce)
        gpio5: in std_logic; -- GPCLK1
        gpio6: in std_logic; -- GPCLK2
-       gpio12: in std_logic; -- PWM0
-       gpio13: in std_logic; -- PWM1
-       gpio19: in std_logic; -- PWM1/SPI1MISO/PCMFS
+       gpio12: in std_logic; -- PWM0         (pwm3)
+       gpio13: in std_logic; -- PWM1         (pwm2)
+       gpio19: in std_logic; -- PWM1/SPI1MISO/PCMFS (pwm2_en)
        gpio16: in std_logic; -- SPI1CE2
-       gpio26: in std_logic; -- SD1DAT2
+       gpio26: in std_logic; -- SD1DAT2      (pwm3_en)
        gpio20: in std_logic; -- SPI1MOSI/PCMDIN/GPCLK0
        gpio21: in std_logic; -- SPI1SCLK/PCMDOUT/GPCLK1
        --
@@ -85,21 +94,22 @@ port (
        -- Unused terminal to keep design tools silent
        dummy_unused : out std_logic
 );
-end rpi_mc_simple_dc;
+end rpi_pmsm_control;
 
 
-architecture behavioral of rpi_mc_simple_dc is
+architecture behavioral of rpi_pmsm_control is
        attribute syn_noprune :boolean;
        attribute syn_preserve :boolean;
        attribute syn_keep :boolean;
        attribute syn_hier :boolean;
+
        -- Actel lib
-       -- component pll50to200
-       --   port (
-       --     powerdown, clka: in std_logic;
-       --     lock, gla: out std_logic
-       --   );
-       -- end component;
+       component pll50to200
+               port (
+                       powerdown, clka: in std_logic;
+                       lock, gla: out std_logic
+               );
+       end component;
        
        component CLKINT
                port (A: in std_logic; Y: out std_logic);
@@ -133,36 +143,81 @@ architecture behavioral of rpi_mc_simple_dc is
        );
        end component;
        
-       component div8 is
-       port (
-               --reset: in std_logic;
-               clk_in: in std_logic;
-               clk_out: out std_logic
+       --frequency division by 12
+       component cnt_div is
+       generic (
+               cnt_width_g : natural := 4
+       );
+       port
+       (
+               clk_i     : in std_logic;                               --clk to divide
+               en_i      : in std_logic;                               --enable bit?
+               reset_i   : in std_logic;                               --asynch. reset
+               ratio_i   : in std_logic_vector(cnt_width_g-1 downto 0);--initial value
+               q_out_o   : out std_logic                               --generates puls when counter underflows
        );
        end component;
        
        component adc_reader is
        port (
                clk: in std_logic;                                      --input clk
+               divided_clk : in std_logic;                             --divided clk - value suitable to sourcing voltage
                adc_reset: in std_logic;
                adc_miso: in std_logic;                                 --spi master in slave out
                adc_channels: out std_logic_vector (35 downto 0);       --consistent data of 3 channels
                adc_sclk: out std_logic;                                --spi clk
                adc_scs: out std_logic;                                 --spi slave select
-               adc_mosi: out std_logic                                 --spi master out slave in
+               adc_mosi: out std_logic;                                --spi master out slave in
+               measur_count: out std_logic_vector(8 downto 0)          --number of accumulated measurments
+       
+       );
+       end component;
        
+       component dff3 is
+       port(
+               clk_i   : in std_logic;
+               d_i     : in std_logic;
+               q_o     : out std_logic
        );
        end component;
        
+       --resetovatelna delicka
+       component div128 is
+       port (
+               clk_in: in std_logic;
+               rst: in std_logic;
+               fail_safe: out std_logic
+       );
+       end component;
+       
+       component div256 is
+       port (
+               clk_in: in std_logic;
+               div256: out std_logic
+       );
+       end component;
        
-       signal adc_reset : std_logic;
-       signal adc_channels: std_logic_vector(35 downto 0);
        
+       signal adc_channels: std_logic_vector(71 downto 0);
+       signal adc_m_count: std_logic_vector(8 downto 0);
+
+       --clock signals for logic and master fail monitoring
+       signal gpio_clk: std_logic;
+       signal pll_clkin, pll_clkout, pll_lock: std_logic;
+       signal clkmon_dly1, clkmon_dly2: std_logic;
+       signal clkmon_fail, clkmon_fail_next: std_logic;
+       signal clkmon_wdg: integer range 0 to 6;
+       signal reset_sync, reset_async: std_logic;
+       signal failsafe, next_failsafe: std_logic;
+
+       --RPi SPI interface signals named aliases
+       signal spi_clk, spi_ce, spi_mosi, spi_miso : std_logic;
        signal spiclk_old: std_logic_vector(1 downto 0); --pro detekci hrany SPI hodin
+
        --signal pwm_in, pwm_dir_in: std_logic;
-       signal gpio_clk: std_logic;
        signal dat_reg : STD_LOGIC_VECTOR (127 downto 0); --shift register for spi
        signal position: std_logic_vector(31 downto 0); --pozice z qcounteru
+       signal index_position: std_logic_vector(11 downto 0);           --pozice irc_i
        signal ce0_old: std_logic_vector(1 downto 0);
        
        --pwm signals
@@ -173,16 +228,37 @@ architecture behavioral of rpi_mc_simple_dc is
        
        signal pwm_match: pwm_res_type;                                 --point of reversion of pwm output, 0 to 2047
        signal pwm_count: std_logic_vector (pwm_width-1 downto 0);      --counter, 0 to 2047
+       signal pwm_sync_at_next: std_logic;
        signal pwm_sync: std_logic;
        signal pwm_en_p: std_logic_vector(1 to 3);
        signal pwm_en_n: std_logic_vector(1 to 3);
+       signal pwm_sig: std_logic_vector(1 to 3);
+       signal shdn_sig: std_logic_vector (1 to 3);
        
        signal income_data_valid: std_logic;
+       signal spi_timout_pulse: std_logic;
        
-       signal clk_3M1: std_logic;
-       
+       signal clk_4M17: std_logic;
+
+       -- irc signals processing
+       signal irc_i_prev: std_logic;
+
+       -- function configuration options
+       -- direct IRC channel A, B and I output to RPi/SoC
+       signal fnccfg_direct_irc: std_logic;
+       -- direct 3 phase PWM output
+       signal fnccfg_direct_3ph_pwm: std_logic;
+       -- PWM1 and PWM2 controlled by PWM input and direction
+       signal fnccfg_pwm12_by_pwm_and_dir: std_logic;
        
+       --filetered irc signals
+       signal irc_a_dff3: std_logic;
+       signal irc_b_dff3: std_logic;
        
+       --16k3 clk signal
+       signal clk_16k3: std_logic;
+       --detekce prichazejicich prikazu po SPI
+
        --  attribute syn_noprune of gpio2 : signal is true;
        --  attribute syn_preserve of gpio2 : signal is true;
        --  attribute syn_keep of gpio2 : signal is true;
@@ -198,13 +274,23 @@ begin
                y => gpio_clk
        );
        
+       pll: pll50to200
+       port map (
+               powerdown => '1',
+               clka => pll_clkin,
+               gla => pll_clkout,
+               lock => pll_lock);
+
+       reset_async <= not pll_lock or clkmon_fail;
+
+       pll_clkin <= gpio_clk;
        
        qcount: qcounter
        port map (
                clock => gpio_clk,
                reset => '0',
-               a0 => irc_a,
-               b0 => irc_b,
+               a0 => irc_a_dff3,
+               b0 => irc_b_dff3,
                qcount => position,
                a_rise => open,
                a_fall => open,
@@ -222,8 +308,8 @@ begin
                port map (
                        clock => gpio_clk,                              --50 Mhz clk from gpclk on raspberry
                        sync => pwm_sync,                               --counter restarts
-                       data_valid => income_data_valid,                        
-                       failsafe => '0',
+                       data_valid => pwm_sync_at_next,                 
+                       failsafe => failsafe,
                        --
                        -- pwm config bits & match word
                        --
@@ -232,80 +318,174 @@ begin
                        match => pwm_match(i),
                        count => pwm_count,
                        -- outputs
-                       out_p => pwm(i),                                --positive signal
-                       out_n => shdn(i)                                --reverse signal is in shutdown mode
+                       out_p => pwm_sig(i),                            --positive signal
+                       out_n => shdn_sig(i)                            --reverse signal is in shutdown mode
                );
        end generate;
        
        
-       div8_map: div8 
+       div12_map: cnt_div
+       generic map (
+               cnt_width_g => 4
+       )
        port map(
-               --reset => income_data_valid,
-               clk_in => gpio_clk,
-               clk_out => clk_3M1
+               clk_i  => gpio_clk,
+               en_i   =>'1',
+               reset_i   =>'0',
+               ratio_i   =>"1101", --POZN.: counter detekuje cnt<=1
+               q_out_o   =>clk_4M17
        );
-       
-       adc_reader_map: adc_reader 
+
+       clk_16k3_div: cnt_div
+       generic map (
+               cnt_width_g => 8
+       )
+       port map(
+               clk_i  => gpio_clk,
+               en_i   => clk_4M17,
+               reset_i   => '0',
+               ratio_i   => "11111111",
+               q_out_o   => clk_16k3
+       );
+
+       spi_timeout_div : cnt_div
+       generic map (
+               cnt_width_g => 7
+       )
        port map(
-               clk =>clk_3M1,
-               adc_reset => adc_reset,
+               clk_i  => gpio_clk,
+               en_i   => clk_16k3,
+               reset_i   => income_data_valid,
+               ratio_i   => "1111111",
+               q_out_o   => spi_timout_pulse
+       );
+
+       -- ADC needs 3.2 MHz clk when powered from +5V Vcc
+       --           2.0 MHz clk when +2.7V Vcc
+       -- on the input is 4.17Mhz,but this frequency is divided inside adc_reader by 2 to 2.08 Mhz,
+       --        while we use +3.3V Vcc
+       adc_reader_map: adc_reader
+       port map(
+               clk => gpio_clk,
+               divided_clk => clk_4M17,
+               adc_reset => income_data_valid, --reset at each SPI cycle,TODO: replace with PLL reset
                adc_miso => adc_miso,
                adc_channels => adc_channels,
                adc_sclk => adc_sclk,
                adc_scs => adc_scs,
-               adc_mosi => adc_mosi
+               adc_mosi => adc_mosi,
+               measur_count => adc_m_count
                
        );
-
        
+       dff3_a: dff3
+       port map(       
+               clk_i => gpio_clk,
+               d_i   => irc_a,
+               q_o   => irc_a_dff3
+       );
        
-       --   pll: pll50to200
-       --     port map (
-       --       powerdown => '1',
-       --       clka => pll_clkin,
-       --       gla => pll_clkout,
-       --       lock => pll_lock);
-       -- --  reset <= not pll_lock;
-       --   reset <= '0';                         -- TODO: apply reset for good failsafe
-                                           -- upon power-on
-       --   clock <= clkm;
-
-       dummy_unused <= gpio2 and gpio3  and gpio4 and
+       dff3_b: dff3
+       port map(       
+               clk_i => gpio_clk,
+               d_i   => irc_b,
+               q_o   => irc_b_dff3
+       );
+
+       dummy_unused <= gpio2 and gpio3 and
                gpio5 and gpio6 and
                gpio12 and gpio13 and gpio14 and
                gpio15 and gpio16 and gpio19 and
                gpio20 and gpio21 and gpio26 and
                stat(1) and stat(2) and stat(3) and
                hal_in(1) and hal_in(2) and hal_in(3) and
-               irc_i and power_stat and 
-               adc_miso and 
+               irc_i and power_stat and
+               adc_miso and
                rs485_rxd and
                can_rx and can_tx and
-               dip_sw(1) and dip_sw(2) and dip_sw(3) and
                irc_a and irc_b and
                gpio17 and gpio18 and gpio27 and gpio22 and gpio23 and gpio24 and gpio25 and
-               gpio8  and gpio11 and gpio7 and gpio10 and
+               gpio8  and
                ext_scs1 and ext_scs2 and ext_miso and ext_mosi and ext_sclk and ext_scs0;
+
+       fnccfg_direct_irc <= not dip_sw(1);
+       fnccfg_direct_3ph_pwm <= not dip_sw(2) and dip_sw(3);
+       fnccfg_pwm12_by_pwm_and_dir <= not dip_sw(2) and not dip_sw(3);
                        
        rs485_txd <= '1';
        rs485_dir <= '0';
 
+       spi_clk <= gpio11;
+       spi_ce <= gpio7;
+       spi_mosi <= gpio10;
+       gpio9 <= spi_miso;
 
-       --shdn(1) <= '0';
-       --shdn(2) <= '1';
-       --shdn(3) <= '0';
+       irc_direct_output_selection: process(fnccfg_direct_irc, irc_a, irc_b, irc_i)
+       begin
+               if fnccfg_direct_irc = '1' then
+                       gpio23 <= irc_a;
+                       gpio24 <= irc_a;
+                       gpio27 <= irc_b;
+                       gpio25 <= irc_b;
+                       gpio17 <= irc_i;
+               else
+                       gpio23 <= 'Z';
+                       gpio24 <= 'Z';
+                       gpio27 <= 'Z';
+                       gpio25 <= 'Z';
+                       gpio17 <= 'Z';
+               end if;
+       end process;
 
-       --pwm(1) <= '0';
-       --pwm(2) <= '0';
-       --pwm(3) <= '0';
-       
-               
+       pwm_output_selection: process(pwm_sig, shdn_sig,
+               fnccfg_direct_3ph_pwm, fnccfg_pwm12_by_pwm_and_dir,
+               fnccfg_pwm12_by_pwm_and_dir, gpio12, gpio13, gpio18, gpio19,
+               gpio22, gpio26)
+       begin
+               if fnccfg_direct_3ph_pwm = '1' then
+                       pwm(1) <= gpio18;
+                       pwm(2) <= gpio13;
+                       pwm(3) <= gpio12;
+                       shdn(1) <= not gpio22;
+                       shdn(2) <= not gpio19;
+                       shdn(3) <= not gpio26;
+               elsif fnccfg_pwm12_by_pwm_and_dir = '1' then
+                       -- pwm(1) <= pwm_in and not pwm_dir_in;
+                       pwm(1) <= gpio18 and not gpio22;
+                       -- pwm(2) <= pwm_in and pwm_dir_in;;
+                       pwm(2) <= gpio18 and gpio22;
+                       pwm(3) <= '0';
+                       shdn(1) <= '0';
+                       shdn(2) <= '0';
+                       shdn(3) <= '1';
+               else
+                       pwm <= pwm_sig;
+                       shdn <= shdn_sig;
+               end if;
+       end process;
+
+       process
+       begin
+               wait until (gpio_clk'event and gpio_clk='1');
+               if irc_i_prev = '0' and irc_i = '1' then
+                       index_position(11 downto 0)<=position(11 downto 0);
+               end if;
+               irc_i_prev<=irc_i;
+       end process;
        
        process
        begin
                wait until (gpio_clk'event and gpio_clk='1');
-               IF(pwm_count = pwm_period) THEN                         
-               --end of period reached
+               IF pwm_count = std_logic_vector(unsigned(pwm_period) - 1) THEN                          
+                       --end of period nearly reached
+                       --fetch new pwm match data
+                       pwm_sync_at_next <= '1';
+               else
+                       pwm_sync_at_next <= '0';
+               end if;
+               
+               if pwm_sync_at_next='1' then
+                       --end of period reached
                        pwm_count <= (others=>'0');      --reset counter
                        pwm_sync <= '1';                                -- inform PWM logic about new period start
                ELSE                                                    --end of period not reached
@@ -320,50 +500,98 @@ begin
                wait until (gpio_clk'event and gpio_clk='1');
                
                --SCLK edge detection
-               spiclk_old(0)<=gpio11;
+               spiclk_old(0)<=spi_clk;
                spiclk_old(1)<=spiclk_old(0);
                
                --SS edge detection
-               ce0_old(0)<=gpio7;
+               ce0_old(0)<=spi_ce;
                ce0_old(1)<=ce0_old(0);
                
                if (spiclk_old="01") then --rising edge, faze cteni
-                       if (gpio7 = '0') then             -- SPI CS must be selected
+                       if (spi_ce = '0') then             -- SPI CS must be selected
                                -- shift serial data into dat_reg on each rising edge
                                -- of SCK, MSB first
-                               dat_reg(127 downto 0) <= dat_reg(126 downto 0) & gpio10;
+                               dat_reg(127 downto 0) <= dat_reg(126 downto 0) & spi_mosi;
                                end if;
                elsif (spiclk_old="10" ) then --falling edge, faze zapisu
-                       if (gpio7 = '0') then
-                               gpio9 <= dat_reg(127); --zapisujeme nejdriv MSB
+                       if (spi_ce = '0') then
+                               spi_miso <= dat_reg(127); --zapisujeme nejdriv MSB
                        end if;
                end if;
                
-                       
+
+               if (ce0_old = "10" ) then
+                       income_data_valid <= '1';
+               else
+                       income_data_valid <= '0';
+               end if;
+
                --sestupna hrana SS, pripravime data pro prenos
-               if (ce0_old = "10" ) then 
-                       income_data_valid<='0';
+               if (ce0_old = "10" ) then
                        dat_reg(127 downto 96) <= position(31 downto 0); --pozice
                        dat_reg(95 downto 93) <= hal_in(1 to 3); --halovy sondy
-                       dat_reg(92 downto 90) <= pwm_en_p(1 to 3); --enable positive
-                       dat_reg(89 downto 87) <= pwm_en_n(1 to 3); --shutdown
-                       dat_reg(86 downto 81) <= pwm_match(1)(10 downto 5); --6 MSb of PWM1
-                       dat_reg(80 downto 74) <= pwm_match(2)(10 downto 4); --7 MSb of PWM2
-                       dat_reg(73 downto 68) <= pwm_match(3)(10 downto 5); --6 MSb of PWM3
-                       dat_reg(67 downto 32) <= adc_channels(35 downto 0); --current mesurments
-                       adc_reset<='0'; --remove reset flag, and wait on its rising edge
+                       dat_reg(92 downto 81) <= index_position(11 downto 0);   --position of irc_i
+                       dat_reg(80 downto 72) <=adc_m_count(8 downto 0);        --count of measurments
+                       --data order schould be: ch2 downto ch0 downto ch1
+                       dat_reg(71 downto 0) <= adc_channels(71 downto 0);      --current mesurments
+                       spi_miso <= position(31);               --prepare the first bit on SE activation
                elsif (ce0_old = "01") then --rising edge of SS, we should read the data
-                       adc_reset<='1';
                        pwm_en_p(1 to 3)<=dat_reg(126 downto 124);
                        pwm_en_n(1 to 3)<=dat_reg(123 downto 121);
-                       --11 bit pwm TODO: make it generic
-                       pwm_match(1)(pwm_width-1 downto 0)<=dat_reg(66 downto 56);
-                       pwm_match(2)(pwm_width-1 downto 0)<=dat_reg(55 downto 45);
-                       -- 12 + 11 Unused
-                       pwm_match(3)(pwm_width-1 downto 0)<=dat_reg(42 downto 32);
-                       income_data_valid<='1';
+                       --usable for up to 16-bit PWM duty cycle resolution (pwm_width):
+                       pwm_match(1)(pwm_width-1 downto 0)<=dat_reg(pwm_width+31 downto 32);
+                       pwm_match(2)(pwm_width-1 downto 0)<=dat_reg(pwm_width+15 downto 16);
+                       pwm_match(3)(pwm_width-1 downto 0)<=dat_reg(pwm_width-1 downto 0);
                end if;
        end process;
-                       
+
+       clock_monitor: process (pll_clkout, gpio_clk, clkmon_dly1, clkmon_wdg, clkmon_fail_next)
+       begin
+               if pll_clkout'event and pll_clkout = '1' then
+                       clkmon_dly1 <= gpio_clk;
+                       clkmon_dly2 <= clkmon_dly1;
+                       if clkmon_dly1 = '0' and clkmon_dly2 = '1' then
+                               clkmon_wdg <= 6;
+                               clkmon_fail_next <= '0';
+                       elsif clkmon_wdg > 0 then
+                               clkmon_wdg <= clkmon_wdg - 1;
+                               clkmon_fail_next <= '0';
+                       else
+                               clkmon_wdg <= 0;
+                               clkmon_fail_next <= '1';
+                       end if;
+                       clkmon_fail <= clkmon_fail_next;
+               end if;
+       end process;
+
+       failsafe_spi_monitor: process (failsafe, spi_timout_pulse, income_data_valid)
+       begin
+               -- the failasfe signal from communication block if CRC is used
+               -- or simple watchdog for SPI communication
+               if income_data_valid = '1' then
+                       next_failsafe <= '0';
+               elsif spi_timout_pulse = '1' then
+                       next_failsafe <= '1';
+               else
+                       next_failsafe <= failsafe;
+               end if;
+       end process;
+
+       async_rst: process (gpio_clk, reset_async, reset_sync)
+       begin
+               if reset_async = '1' then
+                       failsafe <= '1';
+               elsif gpio_clk'event and gpio_clk = '1' then
+                       failsafe <= next_failsafe or reset_sync;
+               end if;
+       end process;
+
+       sync_rst: process (gpio_clk, reset_async)
+       begin
+               if gpio_clk'event and gpio_clk = '1' then
+                       reset_sync <= reset_async;
+               end if;
+       end process;
+
 end behavioral;