From 90850e69f4dc01cf6488f6344cfa3e461f5e6d5e Mon Sep 17 00:00:00 2001 From: Pavel Pisa Date: Wed, 26 Jul 2017 20:12:38 +0200 Subject: [PATCH] dcsimpledrv: implemented PWM generator to drive motor into both directions. Signed-off-by: Pavel Pisa --- system/ip/dcsimpledrv_1.0/component.xml | 20 +++-- system/ip/dcsimpledrv_1.0/hdl/bidir_pwm.vhdl | 77 +++++++++++++++++++ .../dcsimpledrv_1.0/hdl/dcsimpledrv_v1_0.vhd | 38 ++++++++- 3 files changed, 127 insertions(+), 8 deletions(-) create mode 100644 system/ip/dcsimpledrv_1.0/hdl/bidir_pwm.vhdl diff --git a/system/ip/dcsimpledrv_1.0/component.xml b/system/ip/dcsimpledrv_1.0/component.xml index caba483..142a6da 100644 --- a/system/ip/dcsimpledrv_1.0/component.xml +++ b/system/ip/dcsimpledrv_1.0/component.xml @@ -266,7 +266,7 @@ viewChecksum - e5b742c7 + cee40dbc @@ -282,7 +282,7 @@ viewChecksum - e5b742c7 + cee40dbc @@ -802,10 +802,14 @@ hdl/dff3.vhdl vhdlSource + + hdl/bidir_pwm.vhdl + vhdlSource + hdl/dcsimpledrv_v1_0.vhd vhdlSource - CHECKSUM_6ad8b1ec + CHECKSUM_7e089523 @@ -826,6 +830,10 @@ hdl/dff3.vhdl vhdlSource + + hdl/bidir_pwm.vhdl + vhdlSource + hdl/dcsimpledrv_v1_0.vhd vhdlSource @@ -946,8 +954,8 @@ AXI_Peripheral dcsimpledrv_v1.0 - 4 - 2017-07-25T17:46:36Z + 5 + 2017-07-26T16:47:18Z /home/pi/fpga/zynq/canbech-sw/system/ip/dcsimpledrv_1.0 @@ -956,7 +964,7 @@ 2016.1 - + diff --git a/system/ip/dcsimpledrv_1.0/hdl/bidir_pwm.vhdl b/system/ip/dcsimpledrv_1.0/hdl/bidir_pwm.vhdl new file mode 100644 index 0000000..920d99a --- /dev/null +++ b/system/ip/dcsimpledrv_1.0/hdl/bidir_pwm.vhdl @@ -0,0 +1,77 @@ +-- +-- * Simple PWM generator for bidirectional DC motor control * +-- The comparisons are not optimized from inequality +-- to simple match to allow asynchronous period and duty +-- changes without need to wait for previously exhaustive +-- set period to finish + +-- (c) 2017 Pavel Pisa +-- +-- license: BSD +-- +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +entity bidir_pwm is +generic ( + pwm_width: integer := 30 +); +port ( + clock: in std_logic; + reset: in std_logic; + pwm_period: in std_logic_vector (pwm_width - 1 downto 0); + pwm_duty: in std_logic_vector (pwm_width - 1 downto 0); + dir_a, dir_b: in std_logic; + pwm_a, pwm_b: out std_logic +); +end bidir_pwm; + +architecture behavioral of bidir_pwm is + signal cnt_val_s : natural range 0 to (2**pwm_width - 1); + signal cnt_val_r : natural range 0 to (2**pwm_width - 1); + + signal pwm_a_gen_s : std_logic; + signal pwm_a_gen_r : std_logic; + signal pwm_b_gen_s : std_logic; + signal pwm_b_gen_r : std_logic; +begin + +comb: process (reset, cnt_val_r, pwm_a_gen_r, pwm_b_gen_r, dir_a, dir_b, pwm_period, pwm_duty) + begin + if reset = '1' then + cnt_val_s <= 0; + pwm_a_gen_s <= '0'; + pwm_b_gen_s <= '0'; + else + if cnt_val_r + 1 >= to_integer(unsigned(pwm_period)) then + cnt_val_s <= 0; + else + cnt_val_s <= cnt_val_r + 1; + end if; + + if to_integer(unsigned(pwm_duty)) <= cnt_val_r then + pwm_a_gen_s <= '0'; + pwm_b_gen_s <= '0'; + elsif cnt_val_r = 0 then + pwm_a_gen_s <= dir_a; + pwm_b_gen_s <= dir_b; + else + pwm_a_gen_s <= pwm_a_gen_r and dir_a; + pwm_b_gen_s <= pwm_b_gen_r and dir_b; + end if; + end if; + end process; + +seq: process + begin + wait until clock'event and clock = '1'; + cnt_val_r <= cnt_val_s; + pwm_a_gen_r <= pwm_a_gen_s; + pwm_b_gen_r <= pwm_b_gen_s; + end process; + + pwm_a <= pwm_a_gen_r and not reset; + pwm_b <= pwm_b_gen_r and not reset; + +end behavioral; diff --git a/system/ip/dcsimpledrv_1.0/hdl/dcsimpledrv_v1_0.vhd b/system/ip/dcsimpledrv_1.0/hdl/dcsimpledrv_v1_0.vhd index 43d3af5..097df97 100644 --- a/system/ip/dcsimpledrv_1.0/hdl/dcsimpledrv_v1_0.vhd +++ b/system/ip/dcsimpledrv_1.0/hdl/dcsimpledrv_v1_0.vhd @@ -123,6 +123,20 @@ architecture arch_imp of dcsimpledrv_v1_0 is ); end component; + component bidir_pwm is + generic ( + pwm_width: integer := 30 + ); + port ( + clock: in std_logic; + reset: in std_logic; + pwm_period: in std_logic_vector (pwm_width - 1 downto 0); + pwm_duty: in std_logic_vector (pwm_width - 1 downto 0); + dir_a, dir_b: in std_logic; + pwm_a, pwm_b: out std_logic + ); + end component; + constant irc_bits_n: natural := 32; signal irc_pos_act: std_logic_vector(irc_bits_n-1 downto 0); @@ -143,6 +157,9 @@ architecture arch_imp of dcsimpledrv_v1_0 is signal pwm_period : std_logic_vector(C_S00_AXI_DATA_WIDTH-1 downto 0); signal pwm_duty : std_logic_vector(C_S00_AXI_DATA_WIDTH-1 downto 0); + signal pwm_reset_rq : std_logic; + signal pwm_a_gen : std_logic; + signal pwm_b_gen : std_logic; begin -- Instantiation of Axi Bus Interface S00_AXI @@ -229,13 +246,30 @@ qcounter_nbit_inst: qcounter_nbit ab_error => open ); +bidir_pwm_inst: bidir_pwm + generic map ( + pwm_width => 30 + ) + port map( + clock => fsm_clk, + reset => pwm_reset_rq, + pwm_period => pwm_period(29 downto 0), + pwm_duty => pwm_duty(29 downto 0), + dir_a => pwm_duty(30), + dir_b => pwm_duty(31), + pwm_a => pwm_a_gen, + pwm_b => pwm_b_gen + ); + fsm_clk <= s00_axi_aclk; fsm_rst <= not s00_axi_aresetn; irc_reset_rq <= irc_reset_bit or fsm_rst; - PWM_A <= pwm_direct_a; - PWM_B <= pwm_direct_b; + pwm_reset_rq <= not pwm_enable or fsm_rst; + + PWM_A <= (pwm_direct_a and not pwm_enable) or pwm_a_gen; + PWM_B <= (pwm_direct_b and not pwm_enable) or pwm_b_gen; IRC_A_MON <= irc_a_dff3; IRC_B_MON <= irc_b_dff3; -- 2.39.2