Include in PMSM design to implement safe behavior when external clocks are not present.
authorPavel Pisa <ppisa@pikron.com>
Fri, 1 May 2015 14:59:49 +0000 (16:59 +0200)
committerPavel Pisa <ppisa@pikron.com>
Fri, 1 May 2015 14:59:49 +0000 (16:59 +0200)
The PLL is configured to synthesize 200 MHz clock from 50 MHz input.
The clock monitor holds PWM outputs low if the external clocks are
not present. The reference lost is recognized 6 in 8 cycles
of 200 MHz synthesized clock as well.

Signed-off-by: Pavel Pisa <ppisa@pikron.com>
pmsm-control/pll50to200.vhd [new file with mode: 0644]
pmsm-control/rpi_pmsm_control.sdc [new file with mode: 0644]
pmsm-control/rpi_pmsm_control.vhdl

diff --git a/pmsm-control/pll50to200.vhd b/pmsm-control/pll50to200.vhd
new file mode 100644 (file)
index 0000000..3f110ad
--- /dev/null
@@ -0,0 +1,124 @@
+-- Version: 9.1 9.1.0.18
+
+library ieee;
+use ieee.std_logic_1164.all;
+library igloo;
+use igloo.all;
+
+entity pll50to200 is
+    port(POWERDOWN, CLKA : in std_logic;  LOCK, GLA : out
+        std_logic) ;
+end pll50to200;
+
+
+architecture DEF_ARCH of  pll50to200 is
+
+    component PLL
+    generic (VCOFREQUENCY:real := 0.0);
+
+        port(CLKA, EXTFB, POWERDOWN : in std_logic := 'U'; GLA,
+        LOCK, GLB, YB, GLC, YC : out std_logic;  OADIV0, OADIV1,
+        OADIV2, OADIV3, OADIV4, OAMUX0, OAMUX1, OAMUX2, DLYGLA0,
+        DLYGLA1, DLYGLA2, DLYGLA3, DLYGLA4, OBDIV0, OBDIV1,
+        OBDIV2, OBDIV3, OBDIV4, OBMUX0, OBMUX1, OBMUX2, DLYYB0,
+        DLYYB1, DLYYB2, DLYYB3, DLYYB4, DLYGLB0, DLYGLB1, DLYGLB2,
+        DLYGLB3, DLYGLB4, OCDIV0, OCDIV1, OCDIV2, OCDIV3, OCDIV4,
+        OCMUX0, OCMUX1, OCMUX2, DLYYC0, DLYYC1, DLYYC2, DLYYC3,
+        DLYYC4, DLYGLC0, DLYGLC1, DLYGLC2, DLYGLC3, DLYGLC4,
+        FINDIV0, FINDIV1, FINDIV2, FINDIV3, FINDIV4, FINDIV5,
+        FINDIV6, FBDIV0, FBDIV1, FBDIV2, FBDIV3, FBDIV4, FBDIV5,
+        FBDIV6, FBDLY0, FBDLY1, FBDLY2, FBDLY3, FBDLY4, FBSEL0,
+        FBSEL1, XDLYSEL, VCOSEL0, VCOSEL1, VCOSEL2 : in std_logic :=
+        'U') ;
+    end component;
+
+    component VCC
+        port( Y : out std_logic);
+    end component;
+
+    component GND
+        port( Y : out std_logic);
+    end component;
+
+    signal VCC_1_net, GND_1_net : std_logic ;
+    begin
+
+    VCC_2_net : VCC port map(Y => VCC_1_net);
+    GND_2_net : GND port map(Y => GND_1_net);
+    Core : PLL
+      generic map(VCOFREQUENCY => 200.000)
+
+      port map(CLKA => CLKA, EXTFB => GND_1_net, POWERDOWN =>
+        POWERDOWN, GLA => GLA, LOCK => LOCK, GLB => OPEN , YB =>
+        OPEN , GLC => OPEN , YC => OPEN , OADIV0 => GND_1_net,
+        OADIV1 => GND_1_net, OADIV2 => GND_1_net, OADIV3 =>
+        GND_1_net, OADIV4 => GND_1_net, OAMUX0 => GND_1_net,
+        OAMUX1 => GND_1_net, OAMUX2 => VCC_1_net, DLYGLA0 =>
+        GND_1_net, DLYGLA1 => GND_1_net, DLYGLA2 => GND_1_net,
+        DLYGLA3 => GND_1_net, DLYGLA4 => GND_1_net, OBDIV0 =>
+        GND_1_net, OBDIV1 => GND_1_net, OBDIV2 => GND_1_net,
+        OBDIV3 => GND_1_net, OBDIV4 => GND_1_net, OBMUX0 =>
+        GND_1_net, OBMUX1 => GND_1_net, OBMUX2 => GND_1_net,
+        DLYYB0 => GND_1_net, DLYYB1 => GND_1_net, DLYYB2 =>
+        GND_1_net, DLYYB3 => GND_1_net, DLYYB4 => GND_1_net,
+        DLYGLB0 => GND_1_net, DLYGLB1 => GND_1_net, DLYGLB2 =>
+        GND_1_net, DLYGLB3 => GND_1_net, DLYGLB4 => GND_1_net,
+        OCDIV0 => GND_1_net, OCDIV1 => GND_1_net, OCDIV2 =>
+        GND_1_net, OCDIV3 => GND_1_net, OCDIV4 => GND_1_net,
+        OCMUX0 => GND_1_net, OCMUX1 => GND_1_net, OCMUX2 =>
+        GND_1_net, DLYYC0 => GND_1_net, DLYYC1 => GND_1_net,
+        DLYYC2 => GND_1_net, DLYYC3 => GND_1_net, DLYYC4 =>
+        GND_1_net, DLYGLC0 => GND_1_net, DLYGLC1 => GND_1_net,
+        DLYGLC2 => GND_1_net, DLYGLC3 => GND_1_net, DLYGLC4 =>
+        GND_1_net, FINDIV0 => VCC_1_net, FINDIV1 => GND_1_net,
+        FINDIV2 => GND_1_net, FINDIV3 => VCC_1_net, FINDIV4 =>
+        GND_1_net, FINDIV5 => GND_1_net, FINDIV6 => GND_1_net,
+        FBDIV0 => VCC_1_net, FBDIV1 => VCC_1_net, FBDIV2 =>
+        VCC_1_net, FBDIV3 => GND_1_net, FBDIV4 => GND_1_net,
+        FBDIV5 => VCC_1_net, FBDIV6 => GND_1_net, FBDLY0 =>
+        GND_1_net, FBDLY1 => GND_1_net, FBDLY2 => GND_1_net,
+        FBDLY3 => GND_1_net, FBDLY4 => GND_1_net, FBSEL0 =>
+        VCC_1_net, FBSEL1 => GND_1_net, XDLYSEL => GND_1_net,
+        VCOSEL0 => VCC_1_net, VCOSEL1 => VCC_1_net, VCOSEL2 =>
+        VCC_1_net);
+end DEF_ARCH;
+
+-- _Disclaimer: Please leave the following comments in the file, they are for internal purposes only._
+
+
+-- _GEN_File_Contents_
+
+-- Version:9.1.0.18
+-- ACTGENU_CALL:1
+-- BATCH:T
+-- FAM:IGLOO
+-- OUTFORMAT:VHDL
+-- LPMTYPE:LPM_PLL_STATIC
+-- LPM_HINT:NONE
+-- INSERT_PAD:NO
+-- INSERT_IOREG:NO
+-- GEN_BHV_VHDL_VAL:F
+-- GEN_BHV_VERILOG_VAL:F
+-- MGNTIMER:F
+-- MGNCMPL:T
+-- DESDIR:/tmp/igloo/pll50to200
+-- GEN_BEHV_MODULE:F
+-- SMARTGEN_DIE:IS4X4M1LP
+-- SMARTGEN_PACKAGE:vq100
+-- AGENIII_IS_SUBPROJECT_LIBERO:F
+-- FIN:50.000000
+-- CLKASRC:0
+-- FBDLY:1
+-- FBMUX:1
+-- XDLYSEL:0
+-- PRIMFREQ:200.000000
+-- PPHASESHIFT:0
+-- DLYAVAL:1
+-- OAMUX:4
+-- POWERDOWN_POLARITY:0
+-- LOCK_POLARITY:1
+-- LOCK_CTL:1
+-- VOLTAGE:1.5
+
+-- _End_Comments_
+
diff --git a/pmsm-control/rpi_pmsm_control.sdc b/pmsm-control/rpi_pmsm_control.sdc
new file mode 100644 (file)
index 0000000..7670b71
--- /dev/null
@@ -0,0 +1,16 @@
+
+# create_clock -name name -period period_value [-waveform edge_list] source
+create_clock -name {gpio_clk} -period 20 -waveform {0 10} {p:gpio4}
+
+#create_clock -name {pll_clkout} -period 5 -waveform {0 2.5} {n:pll_clkout}
+
+# create_generated_clock -name {name -source reference_pin [-divide_by divide_factor] \
+#   [-multiply_by multiply_factor] [-invert] source -pll_output pll_feedback_clock \
+#   -pll_feedback pll_feedback_input
+
+create_generated_clock -name {pll_clkout} \
+  -multiply_by 4 \
+  -source {n:gpio_clk} \
+  {n:pll_clkout}
+
+# set_false_path -through {n:clkmon_fail}
index 4829beb..c3f8416 100644 (file)
@@ -93,13 +93,14 @@ architecture behavioral of rpi_pmsm_control is
        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);
@@ -159,10 +160,18 @@ architecture behavioral of rpi_pmsm_control is
        signal adc_reset : std_logic;
        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;
+
        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
@@ -202,6 +211,19 @@ begin
                y => gpio_clk
        );
        
+       pll: pll50to200
+       port map (
+               powerdown => '1',
+               clka => pll_clkin,
+               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;
        
        qcount: qcounter
        port map (
@@ -227,7 +249,7 @@ begin
                        clock => gpio_clk,                              --50 Mhz clk from gpclk on raspberry
                        sync => pwm_sync,                               --counter restarts
                        data_valid => income_data_valid,                        
-                       failsafe => '0',
+                       failsafe => failsafe,
                        --
                        -- pwm config bits & match word
                        --
@@ -266,19 +288,6 @@ begin
                
        );
 
-       
-       
-       --   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
                gpio5 and gpio6 and
                gpio12 and gpio13 and gpio14 and
@@ -372,6 +381,41 @@ begin
                        income_data_valid<='1';
                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;
+
+       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;