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

Subversion Repositories powerseq

[/] [powerseq/] [trunk/] [example2.vhd] - Rev 2

Compare with Previous | Blame | View Log

----------------------------------------------------------------------------------
-- Engineer: Istvan Nagy
-- Create Date: 10/06/2024 10:10:13 AM
-- License: 0BSD, no restrictions for use, no need to publish modified versions. 
--   The BSD 0-clause license: Copyright (C) 2024 by Istvan Nagy buenoshun@gmail.com 
--   Permission to use, copy, modify, and/or distribute this software for any purpose 
--   with or without fee is hereby granted. THE SOFTWARE IS PROVIDED "AS IS" AND 
--   THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE.
-- Module Name: example - Behavioral
-- Target devices: Michorchip Igloo preferred
-- This code shows how a sequencer is typically used on a complex server motherboard.
--  This code would be instantiated into a FPGA top level VHDL file, that has other
--  logic too, that are not power management related. Signals coming from the X86 and
--  the BMC should be double-flopped on the top-level FPGA code file.
--  Each power domain needs a separate powerseq block instantiated here.
--  On your board the rail assignments will be totally different! Do not reuse as is!
--  For every project this file is to be heavily modified or completely rewritten. This 
--  is not the main reusable open source powerseq code, just an example use case.
-- Synthesis statistics: 2992 LUTs, and 1167 register bits
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
--entity header  ----------------------------------------------------------------
entity example is
    Port ( 
           --System signals for FPGA glue logic
           clk  : in std_logic; --25MHz clock
           reset_n  : in std_logic; --FPGA reset, needs 1ms from standby 3.3V on
           forcepoweron  : in std_logic; --from dip switch, avoid failure response
           pfailure : out std_logic; --assers during failure --1 if one or more railes failed.
           pseqstate_out  : out std_logic_vector(7 downto 0); --we can monitor status through a pin with TopJtag
           ALL_PWR_ON_LED_N	 : out std_logic;
           PWRFAIL_LED_N	 : out std_logic;
           --rails:
            --BMC POWER RAILS	
           VCC_BMC_1V0_ON	 : out std_logic;
           VCC_BMC_1V0_PG	 : in std_logic;
           VCC_BMC_1V5_ON	 : out std_logic;
           VCC_BMC_1V5_PG	 : in std_logic;
            --PCH POWER RAILS CONTROL
           VCC_5V0_ENA	 : out std_logic;
           VCC_5V0_PG	 : in std_logic;
           P1V0_PCH_SBY_EN	 : out std_logic;
           P1V0_PCH_SBY_PG	 : in std_logic;
           P1V8_PCH_SBY_EN	 : out std_logic;
           P1V8_PCH_SBY_PG	 : in std_logic;
           P3V3_S0_EN	 : out std_logic;
           P3V3_S0_PG	 : in std_logic;
           P1V5_PCH_S0_EN	 : out std_logic;
           P1V5_PCH_S0_PG	 : in std_logic;
           P1V0_PCH_S0_EN	 : out std_logic;
           P1V0_PCH_S0_PG	 : in std_logic;
            --CPU POWER RAILS CONTROL
           VCORECPU1_EN	 : out std_logic;
           VCORECPU1_PG	 : in std_logic;
           VCCSA_CPU1_EN	 : out std_logic;
           VCCSA_CPU1_PG	 : in std_logic;
           P1V5_CPU1_EN	 : out std_logic;
           P1V5_CPU1_PG	 : in std_logic;
           P1V05_CPU1_EN	 : out std_logic;
           P1V05_CPU1_PG	 : in std_logic;
           VCORECPU2_EN	 : out std_logic;
           VCORECPU2_PG	 : in std_logic;
           VCCSA_CPU2_EN	 : out std_logic;
           VCCSA_CPU2_PG	 : in std_logic;
           P1V5_CPU2_EN	 : out std_logic;
           P1V5_CPU2_PG	 : in std_logic;
           P1V05_CPU2_EN	 : out std_logic;
           P1V05_CPU2_PG	 : in std_logic;
            --Other device POWER RAILS CONTROL
           PSU_ON	 : out std_logic;
           PSU12V_PG	 : in std_logic;
           P1V8_SSD_EN	 : out std_logic;
           P1V8_SSD_PG	 : in std_logic;
           P1V2_SSD_EN	 : out std_logic;
           P1V2_SSD_PG	 : in std_logic;
            --PCH POWER MANAGEMENT GLUE LOGIC	
           PCH_RSMRST_N	 : out std_logic;
           CPU1_PROCHOT_N	 : in std_logic;
           CPU1_THERMTRIP_N	 : in std_logic;
           CPU1_CATERR_N	 : in std_logic;
           CPU2_PROCHOT_N	 : in std_logic;
           CPU2_THERMTRIP_N	 : in std_logic;
           CPU2_CATERR_N	 : in std_logic;
           CKG_PLL_LOCK	 : in std_logic;
           CKG_CLKEN	 : out std_logic;
           PCH_PWRBTN_N	 : out std_logic;
           PCH_CPUPWRGD	 : out std_logic;
           PCH_DRAMPWRGD	 : out std_logic;
           PCH_PWROK	 : out std_logic;
           PCH_RSTBTN_N	 : out std_logic;
           PCH_SLPS3_N	 : in std_logic;
           PCH_SLPS5_N	 : in std_logic;
           PCH_SLPS4_N	 : in std_logic;
           PCH_SYSPWROK	 : out std_logic;
           PLTRST_N	 : in std_logic;
            --POWER MASTER BMC LOGIC	
           PENA_ALL_BMC	 : in std_logic; --power master ordered the sequence to commence on
           PGD_ALL_BMC	 : out std_logic; --tell the power master that all is on
           BMC_TO_CPU_RST_N	 : in std_logic;
           BMC_RST_N	 : out std_logic; --reset
            --other
           RST_SSD_N	 : out std_logic;
           RST_PCIESLT1_N	 : out std_logic;
           RST_PCIESLT2_N	 : out std_logic;
           RST_PCIESLT3_N	 : out std_logic;
           RST_PCIESLT4_N	 : out std_logic;
           MEMA_THERM_N	 : in std_logic;
           MEMB_THERM_N	 : in std_logic;
           MEMC_THERM_N	 : in std_logic;
           MEMD_THERM_N	 : in std_logic
           );
end example;
 
--architecture start ------------------------------------------------------------
architecture Behavioral of example is
 
-- INTERNAL SIGNALS -------------------------------------------------------------
 
           SIGNAL PSEQ_RAIL_PGa :  std_logic_vector(127 downto 0); --map to rails
           SIGNAL PSEQ_RAIL_ENa :  std_logic_vector(127 downto 0); --map to rails
           SIGNAL failed_railsa :  std_logic_vector(255 downto 0); --bits=1 for failed rails
           SIGNAL tick_outa :  std_logic; --available if needed outside, 1pulse in every several thousand clk
           SIGNAL PSEQ_RAIL_PGb :  std_logic_vector(127 downto 0); --map to rails
           SIGNAL PSEQ_RAIL_ENb :  std_logic_vector(127 downto 0); --map to rails
           SIGNAL failed_railsb :  std_logic_vector(255 downto 0); --bits=1 for failed rails
           SIGNAL pfailurea :  std_logic; 
           SIGNAL pfailureb :  std_logic; 
           SIGNAL tick_outb :  std_logic; --available if needed outside, 1pulse in every several thousand clk
           SIGNAL thermal_na :  std_logic; 
           SIGNAL pseqstate_outa :  std_logic_vector(3 downto 0);
           SIGNAL all_pgooda :  std_logic; 
           SIGNAL all_ona :  std_logic; 
           SIGNAL thermal_nb :  std_logic; 
           SIGNAL pseqstate_outb :  std_logic_vector(3 downto 0);
           SIGNAL all_pgoodb :  std_logic; 
           SIGNAL all_onb :  std_logic; 
           SIGNAL dummy1 :  std_logic; 
           SIGNAL PCH_RSTBTN_N1  :  std_logic;
           SIGNAL x86_state  :  std_logic_vector(2 downto 0);
           SIGNAL delaysig_out1 :  std_logic;
           SIGNAL delaysig_in1  :  std_logic;
           SIGNAL delaycounter1  :  std_logic_vector(19 downto 0); 
           SIGNAL delaysig_out2 :  std_logic;
           SIGNAL delaysig_in2  :  std_logic;
           SIGNAL delaycounter2  :  std_logic_vector(19 downto 0); 
           SIGNAL delaysig_out3 :  std_logic;
           SIGNAL delaysig_in3  :  std_logic;
           SIGNAL delaycounter3  :  std_logic_vector(23 downto 0); 
           SIGNAL delaysig_out4 :  std_logic;
           SIGNAL delaysig_in4  :  std_logic;
           SIGNAL delaycounter4  :  std_logic_vector(19 downto 0); 
           SIGNAL delaysig_out5 :  std_logic;
           SIGNAL delaysig_in5  :  std_logic;
           SIGNAL delaycounter5  :  std_logic_vector(19 downto 0); 
 
 
--------- COMPONENT DECLARATIONS (introducing the IPs) --------------------------
	COMPONENT pseq_3redundant
	PORT(
		clk : IN std_logic;
		reset_n : IN std_logic;
		forcepoweron : IN std_logic;
		PSEQ_RAIL_PG : IN std_logic_vector(127 downto 0);
		thermal_n : IN std_logic;
		all_on : IN std_logic;          
		PSEQ_RAIL_EN : OUT std_logic_vector(127 downto 0);
		failed_rails : OUT std_logic_vector(255 downto 0);
		pfailure : OUT std_logic;
		tick_out : OUT std_logic;
		pseqstate_out : OUT std_logic_vector(3 downto 0);
		all_pgood : OUT std_logic
		);
	END COMPONENT;
 
 
 
--architecture body start -------------------------------------------------------
begin
 
 
--First sequencer for S5 standby power domain rails: #############################
--This just turns on as soon as possible, not controlled
--Trying to follow this sequence:
--1v5_bmc -> 1v0_bmc -> 1v8_pch_sby -> 1v0_pch_sby -> rsmrst
 
	Inst_pseq_3redundanta: pseq_3redundant PORT MAP(
		clk => clk,
		reset_n => reset_n,
		forcepoweron => forcepoweron,
		PSEQ_RAIL_EN => PSEQ_RAIL_ENa,
		PSEQ_RAIL_PG => PSEQ_RAIL_PGa,
		thermal_n => thermal_na,
		failed_rails => failed_railsa,
		pfailure => pfailurea,
		tick_out => tick_outa,
		pseqstate_out => pseqstate_outa,
		all_on => '1', --always on
		all_pgood => dummy1
	);
 
-- Rail assignments:
--enables
VCC_BMC_1V5_ON <= PSEQ_RAIL_ENa(0);
VCC_BMC_1V0_ON <= PSEQ_RAIL_ENa(1);
P1V8_PCH_SBY_EN <= PSEQ_RAIL_ENa(2);
P1V0_PCH_SBY_EN <= PSEQ_RAIL_ENa(3);
delaysig_in1 <= PSEQ_RAIL_ENa(4);
-- <= PSEQ_RAIL_ENa(127 downto 5); unused
--powergood
PSEQ_RAIL_PGa(0) <= VCC_BMC_1V5_PG;
PSEQ_RAIL_PGa(1) <= VCC_BMC_1V0_PG;
PSEQ_RAIL_PGa(2) <= P1V8_PCH_SBY_PG;
PSEQ_RAIL_PGa(3) <= P1V0_PCH_SBY_PG;
PSEQ_RAIL_PGa(4) <= delaysig_out1;
PSEQ_RAIL_PGa(127 downto 5) <= (others => '1'); --unused
 
--system signals for seq 1:
thermal_na <= '1'; --not used in this power domain
 
--simple DELAY1:
process ( reset_n, clk, delaysig_in1 )
   begin
     if ( reset_n='0' or delaysig_in1='0') then
        delaysig_out1 <= '0';
        delaycounter1 <= (others => '0');
     elsif (clk'event and clk='1') then
        if ( delaycounter1 = "01111010000100100000" ) then --after 20msec (40ns clk period)
           delaysig_out1 <= '1';
           delaycounter1 <= delaycounter1; --stop counting
        else
           delaycounter1 <= delaycounter1 +1;
           delaysig_out1 <= '0';
        end if;
     end if; 
   end process;
 
BMC_RST_N <= delaysig_out1; --we can let them know 20ms after all power is good to come out of reset
PCH_RSMRST_N <= delaysig_out1;
 
 
 
--Second sequencer for S0 fully-on power domain rails: #############################
--this one turns on or off as the BMC commands it.
--Trying to follow this sequence:
--12v -> 5v -> 3.3v -> PCH1v5 -> PCH1v0 -> 1v5mem -> drampwrgd -> 1v0cpu -> vcorecpu -> vccsacpu -> 100ms -> pchpwrok -> plllock -> 20ms -> cpupwrgd -> 20ms -> syspwrok
 
	Inst_pseq_3redundantb: pseq_3redundant PORT MAP(
		clk => clk,
		reset_n => reset_n,
		forcepoweron => forcepoweron,
		PSEQ_RAIL_EN => PSEQ_RAIL_ENb,
		PSEQ_RAIL_PG => PSEQ_RAIL_PGb,
		thermal_n => thermal_nb,
		failed_rails => failed_railsb,
		pfailure => pfailureb,
		tick_out => tick_outb,
		pseqstate_out => pseqstate_outb,
		all_on => all_onb,
		all_pgood => all_pgoodb
	);
 
-- Rail assignments:
--enables
PSU_ON <= PSEQ_RAIL_ENb(0);
VCC_5V0_ENA <= PSEQ_RAIL_ENb(1);
P3V3_S0_EN <= PSEQ_RAIL_ENb(2);
P1V5_PCH_S0_EN <= PSEQ_RAIL_ENb(3);
P1V0_PCH_S0_EN <= PSEQ_RAIL_ENb(4);
P1V5_CPU1_EN <= PSEQ_RAIL_ENb(5);
P1V5_CPU2_EN <= PSEQ_RAIL_ENb(6);
PCH_DRAMPWRGD <= PSEQ_RAIL_ENb(7);
VCORECPU1_EN <= PSEQ_RAIL_ENb(8);
VCORECPU2_EN <= PSEQ_RAIL_ENb(9);
VCCSA_CPU1_EN <= PSEQ_RAIL_ENb(10);
VCCSA_CPU2_EN <= PSEQ_RAIL_ENb(11);
delaysig_in3 <= PSEQ_RAIL_ENb(12);
PCH_PWROK <= PSEQ_RAIL_ENb(13);
CKG_CLKEN <= PSEQ_RAIL_ENb(14);
delaysig_in4 <= PSEQ_RAIL_ENb(15);
PCH_CPUPWRGD <= PSEQ_RAIL_ENb(16);
delaysig_in5 <= PSEQ_RAIL_ENb(17);
PCH_SYSPWROK <= PSEQ_RAIL_ENb(18);
-- <= PSEQ_RAIL_ENb(127 downto 19); unused
--powergood
PSEQ_RAIL_PGb(0) <= PSU12V_PG;
PSEQ_RAIL_PGb(1) <= VCC_5V0_PG;
PSEQ_RAIL_PGb(2) <= P3V3_S0_PG;
PSEQ_RAIL_PGb(3) <= P1V5_PCH_S0_PG;
PSEQ_RAIL_PGb(4) <= P1V0_PCH_S0_PG;
PSEQ_RAIL_PGb(5) <= P1V5_CPU1_PG;
PSEQ_RAIL_PGb(6) <= P1V5_CPU2_PG;
PSEQ_RAIL_PGb(7) <= '1';
PSEQ_RAIL_PGb(8) <= VCORECPU1_PG;
PSEQ_RAIL_PGb(9) <= VCORECPU2_PG;
PSEQ_RAIL_PGb(10) <= VCCSA_CPU1_PG;
PSEQ_RAIL_PGb(11) <= VCCSA_CPU2_PG;
PSEQ_RAIL_PGb(12) <= delaysig_out3;
PSEQ_RAIL_PGb(13) <= '1';
PSEQ_RAIL_PGb(14) <= CKG_PLL_LOCK;
PSEQ_RAIL_PGb(15) <= delaysig_out4;
PSEQ_RAIL_PGb(16) <= '1';
PSEQ_RAIL_PGb(17) <= delaysig_out5;
PSEQ_RAIL_PGb(18) <= '1';
PSEQ_RAIL_PGb(127 downto 19) <= (others => '1'); --unused
 
--system signals for seq 2:
thermal_nb <= CPU1_PROCHOT_N AND CPU1_THERMTRIP_N AND CPU1_CATERR_N
          AND CPU2_PROCHOT_N AND CPU2_THERMTRIP_N AND CPU2_CATERR_N
          AND MEMA_THERM_N AND MEMB_THERM_N AND MEMC_THERM_N AND MEMD_THERM_N; --if any of these pulses low, we do a thermal shutdown in S0
 
--simple DELAY3:
process ( reset_n, clk, delaysig_in3 )
   begin
     if ( reset_n='0' or delaysig_in3='0') then
        delaysig_out3 <= '0';
        delaycounter3 <= (others => '0');
     elsif (clk'event and clk='1') then
        if ( delaycounter3 = "001001100010010110100000" ) then --after 100msec (40ns clk period)
           delaysig_out3 <= '1';
           delaycounter3 <= delaycounter3; --stop counting
        else
           delaycounter3 <= delaycounter3 +1;
           delaysig_out3 <= '0';
        end if;
     end if; 
   end process;
 
--simple DELAY4:
process ( reset_n, clk, delaysig_in4 )
   begin
     if ( reset_n='0' or delaysig_in4='0') then
        delaysig_out4 <= '0';
        delaycounter4 <= (others => '0');
     elsif (clk'event and clk='1') then
        if ( delaycounter4 = "01111010000100100000" ) then --after 20msec (40ns clk period)
           delaysig_out4 <= '1';
           delaycounter4 <= delaycounter4; --stop counting
        else
           delaycounter4 <= delaycounter4 +1;
           delaysig_out4 <= '0';
        end if;
     end if; 
   end process;
 
--simple DELAY5:
process ( reset_n, clk, delaysig_in5 )
   begin
     if ( reset_n='0' or delaysig_in5='0') then
        delaysig_out5 <= '0';
        delaycounter5 <= (others => '0');
     elsif (clk'event and clk='1') then
        if ( delaycounter5 = "01111010000100100000" ) then --after 20msec (40ns clk period)
           delaysig_out5 <= '1';
           delaycounter5 <= delaycounter5; --stop counting
        else
           delaycounter5 <= delaycounter5 +1;
           delaysig_out5 <= '0';
        end if;
     end if; 
   end process;
 
 
 
--X86 Chipset power managment Interface #############################
--This handles the powerbutton, as well as talks to the BMC and sequencer2
--Chain: BMC-->thisprocess-->chipset-->seq2-->VRMs
--It does not support sleep states
--BMC Software requires discipline: wait 1sec between turn off and turn on.
    process (reset_n, clk) 
    begin
    if (reset_n='1') then 
       delaysig_in2 <= '0';	
       all_onb <= '0';
       x86_state <= (others => '0');
       PCH_PWRBTN_N <= 'Z';
       PGD_ALL_BMC <= '0';
    else
      if (clk'event and clk = '1') then
                case ( x86_state ) is
 
                when "000" =>   --chipset standby s5    
                    all_onb <= '0';    
                    PGD_ALL_BMC <= '0';
                    if (PENA_ALL_BMC='1') then --BMC ordered power up
                      x86_state <= "001";
                      delaysig_in2 <= '1'; --start 20ms delay
                      PCH_PWRBTN_N <= '0'; --assert power button
                    else
                      delaysig_in2 <= '0';
                      PCH_PWRBTN_N <= 'Z';
                    end if;
 
                when "001" =>   --powerup powerbutton pressing 
                    if (delaysig_out2='1') then --button was pressed for 20ms
                      x86_state <= "010";
                      delaysig_in2 <= '0';
                      PCH_PWRBTN_N <= 'Z'; --release it
                    end if;  	 
 
                when "010" =>   --powerup sequence
                    if (PCH_SLPS3_N='1') then --chipset asserted SLP_S3 high
                      all_onb <= '1'; --start the sequncer2
                    end if;  
                    if (all_pgoodb='1') then --sequncer2 completed up
                      x86_state <= "011";
                    end if;  
 
                when "011" =>   --chipset fully on
                    PGD_ALL_BMC <= '1';
                    if (PENA_ALL_BMC='0') then --BMC turned off the power
                      x86_state <= "100";
                      delaysig_in2 <= '1';
                      PCH_PWRBTN_N <= '0'; --assert power button
                    end if;
 
                when "100" =>   --powerdown powerbutton pressing
                    PGD_ALL_BMC <= '0';
                    if (delaysig_out2='1') then --button was pressed for 20ms
                      x86_state <= "101";
                      delaysig_in2 <= '0';
                      PCH_PWRBTN_N <= 'Z'; --release it
                    end if;  
 
                when "101" =>   --powerdown sequence
                    if (PCH_SLPS3_N='0') then --chipset asserted SLP_S3 low/off
                      all_onb <= '0'; --start the sequncer2 down
                    end if;  
                    if (all_pgoodb='0') then --sequncer2 completed down
                      x86_state <= "000"; --go back to standby
                    end if; 
 
                when others => --error
                      x86_state <= "000"; --go to state 0
                      all_onb <= '0';
                end case;     
       end if;        
    end if;
    end process;
 
--simple DELAY2:
process ( reset_n, clk, delaysig_in2 )
   begin
     if ( reset_n='0' or delaysig_in2='0') then
        delaysig_out2 <= '0';
        delaycounter2 <= (others => '0');
     elsif (clk'event and clk='1') then
        if ( delaycounter2 = "01111010000100100000" ) then --after 20msec (40ns clk period)
           delaysig_out2 <= '1';
           delaycounter2 <= delaycounter2; --stop counting
        else
           delaycounter2 <= delaycounter2 +1;
           delaysig_out2 <= '0';
        end if;
     end if; 
   end process;
 
 
 
-- RESETS AND OTHER STUFF #############################
 
PCH_RSTBTN_N1 <= BMC_TO_CPU_RST_N AND VCORECPU1_PG AND VCORECPU2_PG AND P1V0_PCH_S0_PG AND P3V3_S0_PG;
process ( PCH_RSTBTN_N1 ) --3state buffer
    begin
       if (PCH_RSTBTN_N1='1') then PCH_RSTBTN_N <= 'Z';
       else PCH_RSTBTN_N <= '0';
       end if;
    end process;
 
RST_SSD_N <= PLTRST_N AND P3V3_S0_PG AND P1V8_SSD_PG AND P1V2_SSD_PG;
RST_PCIESLT1_N <= PLTRST_N AND P3V3_S0_PG;
RST_PCIESLT2_N <= PLTRST_N AND P3V3_S0_PG;
RST_PCIESLT3_N <= PLTRST_N AND P3V3_S0_PG;
RST_PCIESLT4_N <= PLTRST_N AND P3V3_S0_PG;
 
 
-- Other stuff:
pseqstate_out(7 downto 4) <= pseqstate_outa;
pseqstate_out(3 downto 0) <= pseqstate_outb;
ALL_PWR_ON_LED_N <= NOT (all_pgooda AND all_pgoodb);
PWRFAIL_LED_N <= NOT (pfailurea OR pfailureb);
pfailure <= pfailurea OR pfailureb;
 
 
--end file ----------------------------------------------------------------------
end Behavioral;
 

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

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