X-Git-Url: https://rtime.felk.cvut.cz/gitweb/fpga/rpi-motor-control.git/blobdiff_plain/bd18e9490dc33e857c4e857e6efd9be683f6ad21..HEAD:/pmsm-control/rpi_pmsm_control.vhdl diff --git a/pmsm-control/rpi_pmsm_control.vhdl b/pmsm-control/rpi_pmsm_control.vhdl index 27ca4d8..e900e8d 100644 --- a/pmsm-control/rpi_pmsm_control.vhdl +++ b/pmsm-control/rpi_pmsm_control.vhdl @@ -31,28 +31,28 @@ generic( 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 -- @@ -144,10 +144,17 @@ architecture behavioral of rpi_pmsm_control is end component; --frequency division by 12 - component divider is - port ( - clk_in: in std_logic; - div12: out std_logic + 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; @@ -166,6 +173,30 @@ architecture behavioral of rpi_pmsm_control is ); 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_channels: std_logic_vector(71 downto 0); signal adc_m_count: std_logic_vector(8 downto 0); @@ -197,18 +228,37 @@ architecture behavioral of rpi_pmsm_control 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_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; @@ -231,9 +281,6 @@ begin gla => pll_clkout, lock => pll_lock); - -- the failasfe signal from communication block if CRC is used - next_failsafe <= '0'; - reset_async <= not pll_lock or clkmon_fail; pll_clkin <= gpio_clk; @@ -242,8 +289,8 @@ begin 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, @@ -261,7 +308,7 @@ begin port map ( clock => gpio_clk, --50 Mhz clk from gpclk on raspberry sync => pwm_sync, --counter restarts - data_valid => income_data_valid, + data_valid => pwm_sync_at_next, failsafe => failsafe, -- -- pwm config bits & match word @@ -272,23 +319,52 @@ begin count => pwm_count, -- outputs out_p => pwm_sig(i), --positive signal - out_n => shdn(i) --reverse signal is in shutdown mode + out_n => shdn_sig(i) --reverse signal is in shutdown mode ); end generate; - div12_map: divider + div12_map: cnt_div + generic map ( + cnt_width_g => 4 + ) port map( - --reset => income_data_valid, - clk_in => gpio_clk, - div12 => clk_4M17 + clk_i => gpio_clk, + en_i =>'1', + reset_i =>'0', + ratio_i =>"1101", --POZN.: counter detekuje cnt<=1 + q_out_o =>clk_4M17 ); - + + 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_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 + -- while we use +3.3V Vcc + adc_reader_map: adc_reader port map( clk => gpio_clk, divided_clk => clk_4M17, @@ -301,6 +377,20 @@ begin measur_count => adc_m_count ); + + dff3_a: dff3 + port map( + clk_i => gpio_clk, + d_i => irc_a, + q_o => irc_a_dff3 + ); + + 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 @@ -309,15 +399,18 @@ begin 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 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'; @@ -327,11 +420,50 @@ begin spi_mosi <= gpio10; gpio9 <= spi_miso; - pwm(1) <= pwm_sig(1) and dip_sw(1); - pwm(2) <= pwm_sig(2) and dip_sw(2); - pwm(3) <= pwm_sig(3) and dip_sw(3); - - + 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_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'); @@ -344,8 +476,16 @@ begin 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 @@ -379,10 +519,15 @@ begin 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 81) <= index_position(11 downto 0); --position of irc_i @@ -397,7 +542,6 @@ begin 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); - income_data_valid<='1'; end if; end process; @@ -420,6 +564,19 @@ begin 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