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

Subversion Repositories powersupplysequencer

[/] [powersupplysequencer/] [vhdl/] [msi/] [PowerSequencer/] [PowerSequencer.vhd] - Blame information for rev 2

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 dk4xp
-- PowerSequencerSlice
2
 
3
-- (c) 2009.. Gerhard Hoffmann  opencores@hoffmann-hochfrequenz.de
4
-- Published under BSD license
5
-- V1.0  first published version
6
--
7
-- CLK can be any clock you like. RST must be synchronous to it. 
8
-- Other inputs are synchronized internally unless generated by same type of slice.
9
--
10
-- A high clock of, say 200 MHz will produce a lot of logic for the watchdog counter
11
-- to time the millisecond events that happen in power supplies. 
12
-- A few KHz should be optimum.
13
--
14
-- Ena_chain_async = '1' initiates a power up sequence. It will run to completion for the whole system,
15
-- unless some supply fails.  In case of supply failure, an ordered retreat is made. 
16
-- The supply that comes up last will go down first.
17
-- Pulling ena_chain_async low switches all power supplies off, stage by stage.
18
--
19
-- The generic "ticks" determines the number of clock ticks we are willing to wait 
20
-- until supply_good_async comes up after supply_ena is activated for a given supply.
21
--
22
-- Do not forget PullDown resistors on supply_ena if the sequencer itself is, for example, 
23
-- in a FPGA that is not yet operational at the very first beginning.
24
 
25
 
26
library IEEE;
27
use IEEE.STD_LOGIC_1164.ALL;
28
use IEEE.numeric_std.all;
29
 
30
 
31
 
32
entity PowerSequencer is
33
  generic (
34
    ticks:            natural;  -- clock ticks we are willing to wait until a power supply has to be operational  
35
    last_in_chain:    boolean := false
36
  );
37
 
38
  port (
39
    clk:               in  std_logic;
40
    rst:               in  std_logic;
41
 
42
    ena_chain_async:   in  std_logic; -- enable this slice ( and the following ones if possible)
43
    fail_chain_out:    out std_logic; -- we've got a problem ( or one of the following slices)
44
    pu_chain_out:      out std_logic; -- power up status of _this_ slice and its slaves
45
 
46
    ena_next:          out std_logic; -- cascade output to next slice
47
    fail_chain_in:     in  std_logic; -- a cascaded slice has a problem
48
    pu_chain_in:       in  std_logic; -- power up status of our slaves
49
 
50
    supply_ena:        out std_logic; -- enable to the power supplies controlled by this slice
51
    supply_good_async: in  std_logic  -- power good from the supplies controlled by this slice
52
  );
53
end PowerSequencer;
54
 
55
 
56
 
57
 
58
 
59
architecture rtl of PowerSequencer is
60
 
61
  type ps_state is (
62
    s_idle,
63
    s_powerup_trigger,
64
    s_do_powerup,
65
    s_check,
66
    s_ena_next,
67
    s_operating,
68
    s_retreat_trigger,
69
    s_retreat,
70
    s_complain
71
  );
72
 
73
  signal current_state: ps_state;
74
 
75
  signal ena_chain:     std_logic;
76
  signal supply_good:   std_logic;
77
 
78
  signal timer_do:      std_logic;
79
  signal timer_done:    std_logic;
80
 
81
begin
82
 
83
 
84
 
85
u_synchronizer: process(clk) is
86
begin
87
  if rising_edge(clk)
88
  then
89
    ena_chain   <= ena_chain_async;
90
    supply_good <= supply_good_async;
91
  end if;
92
end process u_synchronizer;
93
 
94
 
95
 
96
u_statemachine: process(clk) is
97
begin
98
 
99
  if rising_edge(clk)
100
  then
101
 
102
    if rst = '1'
103
    then
104
      supply_ena      <= '0';
105
      timer_do        <= '0';
106
      fail_chain_out  <= '0';
107
      ena_next        <= '0';
108
      pu_chain_out    <= '0';
109
 
110
      current_state   <= s_idle;
111
 
112
    else
113
      case current_state is
114
 
115
 
116
        when s_idle =>            -- reset / idle state
117
        supply_ena      <= '0';
118
        timer_do        <= '0';
119
        fail_chain_out  <= '0';
120
        ena_next        <= '0';
121
        pu_chain_out    <= '0';
122
 
123
        if ena_chain = '1'
124
        then
125
          current_state <= s_powerup_trigger;
126
        end if;
127
 
128
 
129
      when s_powerup_trigger =>    -- waking up
130
        supply_ena    <= '1';
131
        timer_do      <= '1';
132
 
133
        current_state <= s_do_powerup;
134
 
135
 
136
 
137
      when s_do_powerup =>    -- we stay here for one timer cycle to allow OUR
138
        timer_do   <= '0';    -- power supply to build up the voltage.
139
 
140
        if timer_done = '1'
141
        then
142
          current_state <= s_check;
143
        end if;
144
 
145
 
146
 
147
      when s_check =>             -- check wether our supply has come up as expected
148
        if (supply_good = '1') and (ena_chain = '1')
149
        then
150
          ena_next      <= '1';
151
          current_state <= s_ena_next;
152
        else
153
          current_state <= s_retreat_trigger;
154
        end if;
155
 
156
 
157
 
158
      when s_ena_next =>          -- ok, enable rest of chain
159
 
160
          if (pu_chain_in = '1')  or last_in_chain
161
          then
162
            pu_chain_out   <= '1';
163
            current_state  <= s_operating;
164
          elsif (fail_chain_in = '1')
165
          then
166
            fail_chain_out <= '1';   -- fail must be communicated on the spot for data saving attempts
167
            current_state  <= s_operating;  -- looks wrong only at first sight. don't panic. 
168
          end if;
169
 
170
 
171
 
172
      when s_operating =>         -- normal operation, but watch our supply and the slaves
173
 
174
        if (fail_chain_in = '1') or (supply_good = '0')
175
        then
176
            fail_chain_out  <= '1';   -- fail must be communicated on the spot for data saving attempts
177
        end if;
178
 
179
        if ((ena_chain = '0') or (supply_good = '0'))      -- propagate SwitchOff if there is one
180
        then
181
          ena_next  <= '0';
182
        end if;
183
 
184
        if    ((    last_in_chain and (ena_chain = '0'))
185
           or  (not last_in_chain and (pu_chain_in = '0')))
186
        then
187
          current_state  <= s_retreat_trigger;
188
        else
189
          -- normal operation all day long
190
          null;
191
        end if;
192
 
193
 
194
 
195
 
196
      when s_retreat_trigger =>      -- start power down sequence
197
        supply_ena    <= '0';
198
        timer_do      <= '1';
199
 
200
        current_state <= s_retreat;
201
 
202
 
203
 
204
      when s_retreat =>     -- We stay here for one timer cycle to allow OUR
205
        timer_do  <= '0';   -- Power supply to drain
206
 
207
        if (timer_done = '1')
208
        then
209
          if (ena_chain = '1') -- don't complain if the user doesn't want the power anyway
210
          then
211
            current_state <= s_complain;  -- switchoff because of failure
212
            fail_chain_out <= '1';
213
          else
214
            current_state  <= s_idle;      -- normal switchoff
215
          end if;
216
        end if;
217
 
218
 
219
 
220
      when s_complain =>   -- keep error status until switched off
221
 
222
        fail_chain_out  <= '1';
223
        if (ena_chain = '0')
224
        then
225
          current_state <= s_idle;
226
        end if;
227
 
228
 
229
 
230
      when others =>    -- whatever surprises the chosen state encoding might provide
231
        current_state <= s_idle;
232
 
233
 
234
      end case;
235
    end if;  -- not reset
236
  end if; -- rising_edge(clk)
237
end process u_statemachine;
238
 
239
 
240
 
241
uti: entity work.retrigg_timer
242
 
243
  generic  map(
244
    ticks    => ticks
245
    )
246
 
247
  port map (
248
    clk     => clk,
249
    rst     => rst,
250
    do      => timer_do,
251
    done    => timer_done,
252
    running => open
253
  );
254
 
255
 
256
 
257
end architecture rtl;
258
 
259
 
260
 

powered by: WebSVN 2.1.0

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