]> rtime.felk.cvut.cz Git - fpga/zynq/canbench-sw.git/commitdiff
microzed_apo: Servo outputs aequipped by PWM generators PWM.
authorPavel Pisa <pisa@cmp.felk.cvut.cz>
Tue, 14 Feb 2017 18:25:50 +0000 (19:25 +0100)
committerPavel Pisa <pisa@cmp.felk.cvut.cz>
Tue, 14 Feb 2017 18:25:50 +0000 (19:25 +0100)
Signed-off-by: Pavel Pisa <pisa@cmp.felk.cvut.cz>
system/ip/servo_led_ps2_1.0/component.xml
system/ip/servo_led_ps2_1.0/hdl/cnt_div.vhdl [new file with mode: 0644]
system/ip/servo_led_ps2_1.0/hdl/pulse_gen.vhdl [new file with mode: 0644]
system/ip/servo_led_ps2_1.0/hdl/servo_led_ps2_v1_0.vhd
system/ip/servo_led_ps2_1.0/hdl/servo_led_ps2_v1_0_S00_AXI.vhd

index ef01082d0e12ee277eb06cff7b4a67427d30f16f..d1aa5cbea2137077e77bc5303001afc725161f1a 100644 (file)
         <spirit:fileSetRef>
           <spirit:localName>xilinx_vhdlsynthesis_view_fileset</spirit:localName>
         </spirit:fileSetRef>
+        <spirit:parameters>
+          <spirit:parameter>
+            <spirit:name>viewChecksum</spirit:name>
+            <spirit:value>c00197f5</spirit:value>
+          </spirit:parameter>
+        </spirit:parameters>
       </spirit:view>
       <spirit:view>
         <spirit:name>xilinx_vhdlbehavioralsimulation</spirit:name>
         <spirit:fileSetRef>
           <spirit:localName>xilinx_vhdlbehavioralsimulation_view_fileset</spirit:localName>
         </spirit:fileSetRef>
+        <spirit:parameters>
+          <spirit:parameter>
+            <spirit:name>viewChecksum</spirit:name>
+            <spirit:value>c00197f5</spirit:value>
+          </spirit:parameter>
+        </spirit:parameters>
       </spirit:view>
       <spirit:view>
         <spirit:name>xilinx_softwaredriver</spirit:name>
         <spirit:fileSetRef>
           <spirit:localName>xilinx_softwaredriver_view_fileset</spirit:localName>
         </spirit:fileSetRef>
+        <spirit:parameters>
+          <spirit:parameter>
+            <spirit:name>viewChecksum</spirit:name>
+            <spirit:value>244fe9e0</spirit:value>
+          </spirit:parameter>
+        </spirit:parameters>
       </spirit:view>
       <spirit:view>
         <spirit:name>xilinx_xpgui</spirit:name>
         <spirit:fileSetRef>
           <spirit:localName>xilinx_xpgui_view_fileset</spirit:localName>
         </spirit:fileSetRef>
+        <spirit:parameters>
+          <spirit:parameter>
+            <spirit:name>viewChecksum</spirit:name>
+            <spirit:value>fd592ead</spirit:value>
+          </spirit:parameter>
+        </spirit:parameters>
       </spirit:view>
       <spirit:view>
         <spirit:name>bd_tcl</spirit:name>
         <spirit:fileSetRef>
           <spirit:localName>bd_tcl_view_fileset</spirit:localName>
         </spirit:fileSetRef>
+        <spirit:parameters>
+          <spirit:parameter>
+            <spirit:name>viewChecksum</spirit:name>
+            <spirit:value>45a2f450</spirit:value>
+          </spirit:parameter>
+        </spirit:parameters>
       </spirit:view>
     </spirit:views>
     <spirit:ports>
         <spirit:name>hdl/servo_led_ps2_v1_0_S00_AXI.vhd</spirit:name>
         <spirit:fileType>vhdlSource</spirit:fileType>
       </spirit:file>
+      <spirit:file>
+        <spirit:name>hdl/cnt_div.vhdl</spirit:name>
+        <spirit:fileType>vhdlSource</spirit:fileType>
+      </spirit:file>
+      <spirit:file>
+        <spirit:name>hdl/pulse_gen.vhdl</spirit:name>
+        <spirit:fileType>vhdlSource</spirit:fileType>
+      </spirit:file>
       <spirit:file>
         <spirit:name>hdl/servo_led_ps2_v1_0.vhd</spirit:name>
         <spirit:fileType>vhdlSource</spirit:fileType>
-        <spirit:userFileType>CHECKSUM_71876159</spirit:userFileType>
+        <spirit:userFileType>CHECKSUM_e1033dbf</spirit:userFileType>
       </spirit:file>
     </spirit:fileSet>
     <spirit:fileSet>
         <spirit:name>hdl/servo_led_ps2_v1_0_S00_AXI.vhd</spirit:name>
         <spirit:fileType>vhdlSource</spirit:fileType>
       </spirit:file>
+      <spirit:file>
+        <spirit:name>hdl/cnt_div.vhdl</spirit:name>
+        <spirit:fileType>vhdlSource</spirit:fileType>
+      </spirit:file>
+      <spirit:file>
+        <spirit:name>hdl/pulse_gen.vhdl</spirit:name>
+        <spirit:fileType>vhdlSource</spirit:fileType>
+      </spirit:file>
       <spirit:file>
         <spirit:name>hdl/servo_led_ps2_v1_0.vhd</spirit:name>
         <spirit:fileType>vhdlSource</spirit:fileType>
         <xilinx:taxonomy>AXI_Peripheral</xilinx:taxonomy>
       </xilinx:taxonomies>
       <xilinx:displayName>servo_led_ps2_v1.0</xilinx:displayName>
-      <xilinx:coreRevision>1</xilinx:coreRevision>
-      <xilinx:coreCreationDateTime>2017-01-23T13:46:18Z</xilinx:coreCreationDateTime>
+      <xilinx:coreRevision>2</xilinx:coreRevision>
+      <xilinx:coreCreationDateTime>2017-02-14T18:17:16Z</xilinx:coreCreationDateTime>
       <xilinx:tags>
         <xilinx:tag xilinx:name="user.org:user:servo_led_ps2:1.0_ARCHIVE_LOCATION">/home/pi/fpga/zynq/canbech-sw/system/ip/servo_led_ps2_1.0</xilinx:tag>
       </xilinx:tags>
     </xilinx:coreExtensions>
     <xilinx:packagingInfo>
       <xilinx:xilinxVersion>2016.1</xilinx:xilinxVersion>
+      <xilinx:checksum xilinx:scope="busInterfaces" xilinx:value="ab027bc6"/>
+      <xilinx:checksum xilinx:scope="memoryMaps" xilinx:value="493665f4"/>
+      <xilinx:checksum xilinx:scope="fileGroups" xilinx:value="b9262cf0"/>
+      <xilinx:checksum xilinx:scope="ports" xilinx:value="99629858"/>
+      <xilinx:checksum xilinx:scope="hdlParameters" xilinx:value="ce3109b2"/>
+      <xilinx:checksum xilinx:scope="parameters" xilinx:value="32fcab1b"/>
     </xilinx:packagingInfo>
   </spirit:vendorExtensions>
 </spirit:component>
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 (file)
index 0000000..e65e562
--- /dev/null
@@ -0,0 +1,62 @@
+--
+-- * Counter - divider *
+--
+-- part of LXPWR motion control board (c) PiKRON Ltd
+-- idea by Pavel Pisa PiKRON Ltd <ppisa@pikron.com>
+--
+-- 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 (file)
index 0000000..e682b45
--- /dev/null
@@ -0,0 +1,68 @@
+--
+-- * pulse generator *
+--
+-- based on code from LXPWR motion control board (c) PiKRON Ltd
+-- idea by Pavel Pisa PiKRON Ltd <ppisa@pikron.com>
+--
+-- 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;
+
index d331942707e12ed5b69cf1509f199973ce81fd4f..097e1a43645daf2c269a27019825062e6a153d41 100644 (file)
@@ -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;
index 4b51b8dac311848eb8bd1e396665d944c770be12..1bdda759a290e266cc24f12a850cfeb350eeea2b 100644 (file)
@@ -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;