From ce5287491abebec6cc0c963a73254aa4c134307e Mon Sep 17 00:00:00 2001 From: Pavel Pisa Date: Tue, 14 Feb 2017 19:25:50 +0100 Subject: [PATCH] microzed_apo: Servo outputs aequipped by PWM generators PWM. Signed-off-by: Pavel Pisa --- system/ip/servo_led_ps2_1.0/component.xml | 58 +++++++- system/ip/servo_led_ps2_1.0/hdl/cnt_div.vhdl | 62 ++++++++ .../ip/servo_led_ps2_1.0/hdl/pulse_gen.vhdl | 68 +++++++++ .../hdl/servo_led_ps2_v1_0.vhd | 132 +++++++++++++++++- .../hdl/servo_led_ps2_v1_0_S00_AXI.vhd | 16 ++- 5 files changed, 326 insertions(+), 10 deletions(-) create mode 100644 system/ip/servo_led_ps2_1.0/hdl/cnt_div.vhdl create mode 100644 system/ip/servo_led_ps2_1.0/hdl/pulse_gen.vhdl diff --git a/system/ip/servo_led_ps2_1.0/component.xml b/system/ip/servo_led_ps2_1.0/component.xml index ef01082..d1aa5cb 100644 --- a/system/ip/servo_led_ps2_1.0/component.xml +++ b/system/ip/servo_led_ps2_1.0/component.xml @@ -263,6 +263,12 @@ xilinx_vhdlsynthesis_view_fileset + + + viewChecksum + c00197f5 + + xilinx_vhdlbehavioralsimulation @@ -273,6 +279,12 @@ xilinx_vhdlbehavioralsimulation_view_fileset + + + viewChecksum + c00197f5 + + xilinx_softwaredriver @@ -281,6 +293,12 @@ xilinx_softwaredriver_view_fileset + + + viewChecksum + 244fe9e0 + + xilinx_xpgui @@ -289,6 +307,12 @@ xilinx_xpgui_view_fileset + + + viewChecksum + fd592ead + + bd_tcl @@ -297,6 +321,12 @@ bd_tcl_view_fileset + + + viewChecksum + 45a2f450 + + @@ -695,10 +725,18 @@ hdl/servo_led_ps2_v1_0_S00_AXI.vhd vhdlSource + + hdl/cnt_div.vhdl + vhdlSource + + + hdl/pulse_gen.vhdl + vhdlSource + hdl/servo_led_ps2_v1_0.vhd vhdlSource - CHECKSUM_71876159 + CHECKSUM_e1033dbf @@ -707,6 +745,14 @@ hdl/servo_led_ps2_v1_0_S00_AXI.vhd vhdlSource + + hdl/cnt_div.vhdl + vhdlSource + + + hdl/pulse_gen.vhdl + vhdlSource + hdl/servo_led_ps2_v1_0.vhd vhdlSource @@ -827,14 +873,20 @@ AXI_Peripheral servo_led_ps2_v1.0 - 1 - 2017-01-23T13:46:18Z + 2 + 2017-02-14T18:17:16Z /home/pi/fpga/zynq/canbech-sw/system/ip/servo_led_ps2_1.0 2016.1 + + + + + + diff --git a/system/ip/servo_led_ps2_1.0/hdl/cnt_div.vhdl b/system/ip/servo_led_ps2_1.0/hdl/cnt_div.vhdl new file mode 100644 index 0000000..e65e562 --- /dev/null +++ b/system/ip/servo_led_ps2_1.0/hdl/cnt_div.vhdl @@ -0,0 +1,62 @@ +-- +-- * Counter - divider * +-- +-- part of LXPWR motion control board (c) PiKRON Ltd +-- idea by Pavel Pisa PiKRON Ltd +-- +-- license: BSD +-- +-- This file is used in "RPI PMS motor control" as frequency divider - divides by 6 + +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +entity 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 cnt_div; + +architecture behavioral of cnt_div is + signal cnt_val_s : natural range 0 to (2**cnt_width_g - 1); --counter value before DFF + signal cnt_val_r : natural range 0 to (2**cnt_width_g - 1); --counter value after DFF +begin + +comb: process (reset_i, en_i, ratio_i, cnt_val_r) + begin + if reset_i = '1' then --reset detection + cnt_val_s <= to_integer(unsigned(ratio_i)); --set initial value + q_out_o <= '0'; --reset output + else + if en_i = '0' then --stop-state + cnt_val_s <= cnt_val_r; --hold the value + q_out_o <= '0'; --reset output + else + if cnt_val_r <= 1 then --counter underflows + cnt_val_s <= to_integer(unsigned(ratio_i)); --set initial value + q_out_o <= '1'; --set output + else + cnt_val_s <= cnt_val_r - 1; --decrement counter + q_out_o <= '0'; --reset output + end if; + end if; + end if; + end process; + +seq: process + begin + wait until clk_i'event and clk_i = '1'; + cnt_val_r <= cnt_val_s; + end process; + +end behavioral; + diff --git a/system/ip/servo_led_ps2_1.0/hdl/pulse_gen.vhdl b/system/ip/servo_led_ps2_1.0/hdl/pulse_gen.vhdl new file mode 100644 index 0000000..e682b45 --- /dev/null +++ b/system/ip/servo_led_ps2_1.0/hdl/pulse_gen.vhdl @@ -0,0 +1,68 @@ +-- +-- * pulse generator * +-- +-- based on code from LXPWR motion control board (c) PiKRON Ltd +-- idea by Pavel Pisa PiKRON Ltd +-- +-- license: BSD +-- + +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +entity pulse_gen is + generic ( + duration_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 + trigger_i : in std_logic; --start to generate pulse + duration_i : in std_logic_vector(duration_width_g-1 downto 0);--duration/interval of the pulse + q_out_o : out std_logic --generates pulse for given duration + ); +end pulse_gen; + +architecture behavioral of pulse_gen is + signal cnt_val_s : natural range 0 to (2**duration_width_g - 1); --counter value before DFF + signal cnt_val_r : natural range 0 to (2**duration_width_g - 1); --counter value after DFF +begin + +comb: process (reset_i, en_i, duration_i, trigger_i, cnt_val_r) + begin + if reset_i = '1' then --reset detection + cnt_val_s <= 0; --set defined value + q_out_o <= '0'; --reset output + else + if en_i = '0' then --stop-state + cnt_val_s <= cnt_val_r; --hold the value + else + if trigger_i = '1' then --trigger pulse generator + if to_integer(unsigned(duration_i)) = 0 then + q_out_o <= '0'; + else + q_out_o <= '1'; + end if; + cnt_val_s <= to_integer(unsigned(duration_i)); --set initial value + elsif cnt_val_r = 0 then --pulse finished + cnt_val_s <= cnt_val_r; + q_out_o <= '0'; --set output + else + cnt_val_s <= cnt_val_r - 1; --decrement counter + q_out_o <= '1'; --reset output + end if; + end if; + end if; + end process; + +seq: process + begin + wait until clk_i'event and clk_i = '1'; + cnt_val_r <= cnt_val_s; + end process; + +end behavioral; + diff --git a/system/ip/servo_led_ps2_1.0/hdl/servo_led_ps2_v1_0.vhd b/system/ip/servo_led_ps2_1.0/hdl/servo_led_ps2_v1_0.vhd index d331942..097e1a4 100644 --- a/system/ip/servo_led_ps2_1.0/hdl/servo_led_ps2_v1_0.vhd +++ b/system/ip/servo_led_ps2_1.0/hdl/servo_led_ps2_v1_0.vhd @@ -54,11 +54,17 @@ architecture arch_imp of servo_led_ps2_v1_0 is -- component declaration component servo_led_ps2_v1_0_S00_AXI is generic ( + servo_pwm_width : integer := 24; C_S_AXI_DATA_WIDTH : integer := 32; C_S_AXI_ADDR_WIDTH : integer := 5 ); port ( S_REG0 : out std_logic_vector(C_S_AXI_DATA_WIDTH-1 downto 0); + servo_pwm_period: out std_logic_vector(servo_pwm_width-1 downto 0); + servo1_pwm_duty: out std_logic_vector(servo_pwm_width-1 downto 0); + servo2_pwm_duty: out std_logic_vector(servo_pwm_width-1 downto 0); + servo3_pwm_duty: out std_logic_vector(servo_pwm_width-1 downto 0); + servo4_pwm_duty: out std_logic_vector(servo_pwm_width-1 downto 0); S_AXI_ACLK : in std_logic; S_AXI_ARESETN : in std_logic; @@ -84,18 +90,69 @@ architecture arch_imp of servo_led_ps2_v1_0 is ); end component servo_led_ps2_v1_0_S00_AXI; - signal s_reg0 : std_logic_vector(32-1 downto 0); + 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 pulse_gen is + generic ( + duration_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 + trigger_i : in std_logic; --start to generate pulse + duration_i : in std_logic_vector(duration_width_g-1 downto 0);--duration/interval of the pulse + q_out_o : out std_logic --generates pulse for given duration + ); + end component; + + constant servo_pwm_width : integer := 24; + + signal servo_pwm_period: std_logic_vector(servo_pwm_width-1 downto 0); + signal servo1_pwm_duty: std_logic_vector(servo_pwm_width-1 downto 0); + signal servo2_pwm_duty: std_logic_vector(servo_pwm_width-1 downto 0); + signal servo3_pwm_duty: std_logic_vector(servo_pwm_width-1 downto 0); + signal servo4_pwm_duty: std_logic_vector(servo_pwm_width-1 downto 0); + signal fsm_clk : std_logic; + signal fsm_rst : std_logic; + + signal pwm_cycle_start : std_logic; + + signal s_reg0 : std_logic_vector(32-1 downto 0); + + signal servo1_pwm: std_logic; + signal servo2_pwm: std_logic; + signal servo3_pwm: std_logic; + signal servo4_pwm: std_logic; begin -- Instantiation of Axi Bus Interface S00_AXI servo_led_ps2_v1_0_S00_AXI_inst : servo_led_ps2_v1_0_S00_AXI generic map ( + servo_pwm_width => servo_pwm_width, C_S_AXI_DATA_WIDTH => C_S00_AXI_DATA_WIDTH, C_S_AXI_ADDR_WIDTH => C_S00_AXI_ADDR_WIDTH ) port map ( S_REG0 => s_reg0, + servo_pwm_period => servo_pwm_period, + servo1_pwm_duty => servo1_pwm_duty, + servo2_pwm_duty => servo2_pwm_duty, + servo3_pwm_duty => servo3_pwm_duty, + servo4_pwm_duty => servo4_pwm_duty, S_AXI_ACLK => s00_axi_aclk, S_AXI_ARESETN => s00_axi_aresetn, @@ -121,11 +178,78 @@ servo_led_ps2_v1_0_S00_AXI_inst : servo_led_ps2_v1_0_S00_AXI ); -- Add user logic here +cnt_div_inst: cnt_div + generic map ( + cnt_width_g => servo_pwm_width + ) + port map ( + clk_i => fsm_clk, + en_i => '1', + reset_i => fsm_rst, + ratio_i =>servo_pwm_period, + q_out_o => pwm_cycle_start + ); + +servo1_pwm_inst: pulse_gen + generic map ( + duration_width_g => servo_pwm_width + ) + port map ( + clk_i => fsm_clk, + en_i => '1', + reset_i => fsm_rst, + trigger_i => pwm_cycle_start, + duration_i => servo1_pwm_duty, + q_out_o => servo1_pwm + ); + +servo2_pwm_inst: pulse_gen + generic map ( + duration_width_g => servo_pwm_width + ) + port map ( + clk_i => fsm_clk, + en_i => '1', + reset_i => fsm_rst, + trigger_i => pwm_cycle_start, + duration_i => servo2_pwm_duty, + q_out_o => servo1_pwm + ); + +servo3_pwm_inst: pulse_gen + generic map ( + duration_width_g => servo_pwm_width + ) + port map ( + clk_i => fsm_clk, + en_i => '1', + reset_i => fsm_rst, + trigger_i => pwm_cycle_start, + duration_i => servo3_pwm_duty, + q_out_o => servo1_pwm + ); + +servo4_pwm_inst: pulse_gen + generic map ( + duration_width_g => servo_pwm_width + ) + port map ( + clk_i => fsm_clk, + en_i => '1', + reset_i => fsm_rst, + trigger_i => pwm_cycle_start, + duration_i => servo4_pwm_duty, + q_out_o => servo1_pwm + ); - SERVO1 <= s_reg0(0); - SERVO2 <= s_reg0(1); - SERVO3 <= s_reg0(2); + SERVO1 <= s_reg0(0) xor servo1_pwm; + SERVO2 <= s_reg0(1) xor servo2_pwm; + SERVO3 <= s_reg0(2) xor servo3_pwm; + SERVO4 <= s_reg0(3) xor servo4_pwm when s_reg0(8) = '1' + else 'Z'; + fsm_clk <= s00_axi_aclk; + fsm_rst <= not s00_axi_aresetn; -- User logic ends end arch_imp; diff --git a/system/ip/servo_led_ps2_1.0/hdl/servo_led_ps2_v1_0_S00_AXI.vhd b/system/ip/servo_led_ps2_1.0/hdl/servo_led_ps2_v1_0_S00_AXI.vhd index 4b51b8d..1bdda75 100644 --- a/system/ip/servo_led_ps2_1.0/hdl/servo_led_ps2_v1_0_S00_AXI.vhd +++ b/system/ip/servo_led_ps2_1.0/hdl/servo_led_ps2_v1_0_S00_AXI.vhd @@ -5,7 +5,7 @@ use ieee.numeric_std.all; entity servo_led_ps2_v1_0_S00_AXI is generic ( -- Users to add parameters here - + servo_pwm_width : integer := 24; -- User parameters ends -- Do not modify the parameters beyond this line @@ -17,6 +17,12 @@ entity servo_led_ps2_v1_0_S00_AXI is port ( -- Users to add ports here S_REG0 : out std_logic_vector(C_S_AXI_DATA_WIDTH-1 downto 0); + + servo_pwm_period: out std_logic_vector(servo_pwm_width-1 downto 0); + servo1_pwm_duty: out std_logic_vector(servo_pwm_width-1 downto 0); + servo2_pwm_duty: out std_logic_vector(servo_pwm_width-1 downto 0); + servo3_pwm_duty: out std_logic_vector(servo_pwm_width-1 downto 0); + servo4_pwm_duty: out std_logic_vector(servo_pwm_width-1 downto 0); -- User ports ends -- Do not modify the ports beyond this line @@ -123,9 +129,13 @@ architecture arch_imp of servo_led_ps2_v1_0_S00_AXI is begin - -- User dignals + -- User signals S_REG0 <= slv_reg0; - + servo_pwm_period <= slv_reg3(servo_pwm_width-1 downto 0); + servo1_pwm_duty <= slv_reg4(servo_pwm_width-1 downto 0); + servo2_pwm_duty <= slv_reg5(servo_pwm_width-1 downto 0); + servo3_pwm_duty <= slv_reg6(servo_pwm_width-1 downto 0); + servo4_pwm_duty <= slv_reg7(servo_pwm_width-1 downto 0); -- I/O Connections assignments S_AXI_AWREADY <= axi_awready; -- 2.39.2