OpenCores
URL https://opencores.org/ocsvn/powersupplysequencer/powersupplysequencer/trunk

Subversion Repositories powersupplysequencer

[/] [powersupplysequencer/] [vhdl/] [msi/] [PowerSequencer/] [PowerSequencer.vhd] - Rev 2

Compare with Previous | Blame | View Log

-- PowerSequencerSlice
 
-- (c) 2009.. Gerhard Hoffmann  opencores@hoffmann-hochfrequenz.de
-- Published under BSD license
-- V1.0  first published version
--
-- CLK can be any clock you like. RST must be synchronous to it. 
-- Other inputs are synchronized internally unless generated by same type of slice.
--
-- A high clock of, say 200 MHz will produce a lot of logic for the watchdog counter
-- to time the millisecond events that happen in power supplies. 
-- A few KHz should be optimum.
--
-- Ena_chain_async = '1' initiates a power up sequence. It will run to completion for the whole system,
-- unless some supply fails.  In case of supply failure, an ordered retreat is made. 
-- The supply that comes up last will go down first.
-- Pulling ena_chain_async low switches all power supplies off, stage by stage.
--
-- The generic "ticks" determines the number of clock ticks we are willing to wait 
-- until supply_good_async comes up after supply_ena is activated for a given supply.
--
-- Do not forget PullDown resistors on supply_ena if the sequencer itself is, for example, 
-- in a FPGA that is not yet operational at the very first beginning.
 
 
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.numeric_std.all;
 
 
 
entity PowerSequencer is
  generic (
    ticks:            natural;  -- clock ticks we are willing to wait until a power supply has to be operational  
    last_in_chain:    boolean := false
  );
 
  port (
    clk:               in  std_logic;
    rst:               in  std_logic;
 
    ena_chain_async:   in  std_logic; -- enable this slice ( and the following ones if possible)
    fail_chain_out:    out std_logic; -- we've got a problem ( or one of the following slices)
    pu_chain_out:      out std_logic; -- power up status of _this_ slice and its slaves
 
    ena_next:          out std_logic; -- cascade output to next slice
    fail_chain_in:     in  std_logic; -- a cascaded slice has a problem
    pu_chain_in:       in  std_logic; -- power up status of our slaves
 
    supply_ena:        out std_logic; -- enable to the power supplies controlled by this slice
    supply_good_async: in  std_logic  -- power good from the supplies controlled by this slice
  );
end PowerSequencer;
 
 
 
 
 
architecture rtl of PowerSequencer is
 
  type ps_state is ( 
    s_idle, 
    s_powerup_trigger,
    s_do_powerup, 
    s_check, 
    s_ena_next,
    s_operating,
    s_retreat_trigger,
    s_retreat,
    s_complain
  );
 
  signal current_state: ps_state;
 
  signal ena_chain:     std_logic;
  signal supply_good:   std_logic;
 
  signal timer_do:      std_logic;
  signal timer_done:    std_logic;
 
begin
 
 
 
u_synchronizer: process(clk) is
begin
  if rising_edge(clk)
  then 
    ena_chain   <= ena_chain_async;
    supply_good <= supply_good_async;
  end if;
end process u_synchronizer;
 
 
 
u_statemachine: process(clk) is
begin
 
  if rising_edge(clk)
  then
 
    if rst = '1'
    then
      supply_ena      <= '0';
      timer_do        <= '0';
      fail_chain_out  <= '0';
      ena_next        <= '0';
      pu_chain_out    <= '0';
 
      current_state   <= s_idle;
 
    else 
      case current_state is
 
 
        when s_idle =>            -- reset / idle state
        supply_ena      <= '0';
        timer_do        <= '0';
        fail_chain_out  <= '0';
        ena_next        <= '0';
        pu_chain_out    <= '0';
 
        if ena_chain = '1'
        then
          current_state <= s_powerup_trigger;
        end if;
 
 
      when s_powerup_trigger =>    -- waking up
        supply_ena    <= '1';
        timer_do      <= '1';
 
        current_state <= s_do_powerup;
 
 
 
      when s_do_powerup =>    -- we stay here for one timer cycle to allow OUR
        timer_do   <= '0';    -- power supply to build up the voltage.
 
        if timer_done = '1'
        then
          current_state <= s_check;
        end if;
 
 
 
      when s_check =>             -- check wether our supply has come up as expected
        if (supply_good = '1') and (ena_chain = '1')
        then
          ena_next      <= '1';
          current_state <= s_ena_next;
        else
          current_state <= s_retreat_trigger;
        end if;
 
 
 
      when s_ena_next =>          -- ok, enable rest of chain
 
          if (pu_chain_in = '1')  or last_in_chain
          then
            pu_chain_out   <= '1';
            current_state  <= s_operating; 
          elsif (fail_chain_in = '1')
          then
            fail_chain_out <= '1';   -- fail must be communicated on the spot for data saving attempts
            current_state  <= s_operating;  -- looks wrong only at first sight. don't panic. 
          end if;
 
 
 
      when s_operating =>         -- normal operation, but watch our supply and the slaves
 
        if (fail_chain_in = '1') or (supply_good = '0')
        then
            fail_chain_out  <= '1';   -- fail must be communicated on the spot for data saving attempts
        end if; 
 
        if ((ena_chain = '0') or (supply_good = '0'))      -- propagate SwitchOff if there is one
        then
          ena_next  <= '0';
        end if;                  
 
        if    ((    last_in_chain and (ena_chain = '0'))
           or  (not last_in_chain and (pu_chain_in = '0')))
        then
          current_state  <= s_retreat_trigger; 
        else
          -- normal operation all day long
          null;    
        end if;
 
 
 
 
      when s_retreat_trigger =>      -- start power down sequence
        supply_ena    <= '0';
        timer_do      <= '1';
 
        current_state <= s_retreat;
 
 
 
      when s_retreat =>     -- We stay here for one timer cycle to allow OUR
        timer_do  <= '0';   -- Power supply to drain
 
        if (timer_done = '1')
        then
          if (ena_chain = '1') -- don't complain if the user doesn't want the power anyway
          then
            current_state <= s_complain;  -- switchoff because of failure
            fail_chain_out <= '1';
          else
            current_state  <= s_idle;      -- normal switchoff
          end if;
        end if;
 
 
 
      when s_complain =>   -- keep error status until switched off
 
        fail_chain_out  <= '1';
        if (ena_chain = '0')
        then
          current_state <= s_idle;
        end if;
 
 
 
      when others =>    -- whatever surprises the chosen state encoding might provide
        current_state <= s_idle;
 
 
      end case;
    end if;  -- not reset
  end if; -- rising_edge(clk)
end process u_statemachine;
 
 
 
uti: entity work.retrigg_timer
 
  generic  map(
    ticks    => ticks
    )
 
  port map (
    clk     => clk,
    rst     => rst,
    do      => timer_do,
    done    => timer_done,
    running => open
  );
 
 
 
end architecture rtl;
 
 
 
 

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2020 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.