Aquí dejo el código en vhdl que he hecho para usarlo con una FPGA o una CPLD. El diseño físico ocupa muy muy poco, sobre el 15% de una XC2C256 que es la que estoy usando. Si le quitamos el retardo inicial de 32ms, se queda en menos del 5%, con lo que valdría para una CPLD XC2C32 (que cuesta sobre 1,5 euros), que es la más pequeña que hay en la serie CoolRunner II de Xilinx.
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity top is
Port ( clk : in STD_LOGIC; -- main clock (50 Mhz)
reset : in STD_LOGIC; -- entrada activa a nivel bajo (BTN0)
btn1 : in STD_LOGIC; -- entrada activa a nivel bajo (BTN1)
pulso : out STD_LOGIC; -- salida activa a nivel alto (???)
led0 : out STD_LOGIC -- salida activa a nivel bajo (LED0)
);
end top;
architecture Behavioral of top is
type state_machine is ( Power_Up_Delay,
Wait_Button,
Pulso1,
Pulso2,
Idle);
signal state : state_machine:= Power_Up_Delay;
signal led : std_logic := '0';
signal delay_count : std_logic_vector(23 downto 0):= (others=>'0');
begin
process(CLK, RESET, BTN1)
begin
if (RESET='0') then
state <= Power_Up_Delay;
delay_count <= (others=>'0');
pulso <= '0'; -- inactivo
led <= '1'; -- apagado
elsif (CLK = '1' and CLK'event) then
case state is
when Power_Up_Delay =>
if (delay_count = X"186A00") then -- espera 32 milisegundos (0x186A00 = 32ms/20ns)
delay_count <= X"186A00";
state <= Wait_Button;
else
state <= Power_Up_delay;
delay_count <= delay_count + 1;
end if;
pulso <= '0'; -- inactivo
led <= '1'; -- apagado
when Wait_Button =>
if (BTN1 = '0') then
state <= Pulso1;
else
state <= Wait_Button;
end if;
delay_count <= (others=>'0');
pulso <= '0'; -- inactivo
led <= '0'; -- encendido
when Pulso1 =>
delay_count <= (others=>'0');
pulso <= '1'; -- activo
led <= '1'; -- apagado
state <= Pulso2;
when Pulso2 =>
delay_count <= (others=>'0');
pulso <= '1'; -- activo
led <= '1'; -- apagado
state <= Idle;
when Idle =>
if (delay_count = X"5F5E10") then -- espera 125 milisegundos (0x5F5E10 = 125ms/20ns)
delay_count <= (others=>'0');
led <= not (led); -- parpadea led0 cada 125 milisegundos
else
delay_count <= delay_count + 1;
end if;
state <= Idle;
pulso <= '0'; -- inactivo
when OTHERS =>
state <= Power_Up_Delay;
delay_count <= (others=>'0');
pulso <= '0'; -- inactivo
led <= '1'; -- apagado
end case;
end if;
end process;
led0 <= led;
end Behavioral;
No incluyo el archivo UCF de definiciones de pines, porque aquí se tiene completa libertad de elegir los pines...
Si alguien tiene alguna duda que pregunte...
Una captura de la simulación donde se ven los 40ns (señal nombrada como "pulso"):
Evidentemente como es una simulación no está probado que funcione el exploit. Ya os contaré cuando la ps3 se deje instalar ubuntu...
PD: Psmaniaco, me cuesta más un lector de CD externo, que un remplazo de la lente de la ps3...
Saludos
EDITO: esto vale para un reloj externo de 50 MHz.