-- --------------------------------------------------------------------------- -- IrDA Fuse - A digital fuse to protect high current pulsed IR LED -- -- --------------------------------------------------------------------------- -- -- File : 'irdafuse.vhd' -- Author : Lars Larsson -- -- Date : November 29, 1998 -- -- Description : The fuse locks the TXD signal to '0' if it is '1' for more -- than 85 us or if the duty cycle of TXD reaches 1:4 (25%). A -- constant LIMIT defines a fuse look threshold time -- -- t[s] = (LIMIT+1) / clk[Hz]. -- -- With a clock frequency of 16 MHz and LIMIT = 1360 the -- threshold time is about 85 us. A revival signal unlocks -- the fuse after a latency phase of 1:5 for DUTY=3. -- -- This design has been used in a FPGA course to protect -- IrDA transceivers (HP HSDL-1100 # 018) from student's -- and educator's IrDA encoder FPGA designs. -- -- -- Hint : File 'components.vhd' (package components) is required. -- -- --------------------------------------------------------------------------- -- -- Copyright (C) 1998 Lars Larsson, Dept. of Computer Science -- University of Hamburg -- Vogt-Koelln-Str. 30 -- D - 22041 Hamburg, Germany -- larsson@informatik.uni-hamburg.de -- http://tech-www.informatik.uni-hamburg.de/~larsson -- -- This program is free software; you can redistribute it and/or modify it -- under the terms of the GNU General Public License as published by the -- Free Software Foundation; either version 2 of the License, or (at your -- option) any later version. -- -- This program is distributed in the hope that it will be useful, but -- WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -- for more details. -- -- You should have received a copy of the GNU General Public License along -- with this program; if not, write to the Free Software Foundation, Inc., -- 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -- -- --------------------------------------------------------------------------- library ieee; use ieee.std_logic_1164.all; use work.components.all; -- entity írdafuse is -- REALLY BAD :-( ERROR CAUSED BY THE í CHARACTER !!! entity irdafuse is port( clk : in std_ulogic; -- clock = 16 MHz nrst : in std_ulogic; -- *reset txdin : in std_ulogic; -- IrDA TXD signal (high active) txdout : out std_ulogic; -- fused IrDA TXD signal alive : out std_ulogic; -- assumed that infrared emitter diode is ok (GREEN LED) killed : out std_ulogic; -- fuse locked, IR LED would have been killed (RED LED) revival : in std_ulogic -- revive fused IrDA signal, with a pull up resistor R, -- it unlocks automatically after resting state ); end irdafuse; architecture behavior of irdafuse is type state_type is ( cool, ouch ); -- cool : irdafuse is transparent to TXD and feels cool enough -- ouch : fuse locked, infrared diode protected constant LIMIT : integer := 1360; -- LIMIT defines a fuse look threshold time t[s]. It is in -- seconds given by t[s] = (LIMIT+1) / clk[Hz] = 85.05 us constant DUTY : integer := 3; -- DUTY defines duty cycle 1:n threshold with LIMIT = (n-1) -- For duty cycle 1:n threshold with (n-1) = 1:4 signal clr_s, cin_s, up_s, mincount_s, maxcount_s : std_ulogic; signal current_state, next_state : state_type; signal cnt_s : integer range 0 to LIMIT; signal div_s : integer range 0 to DUTY; begin clr_s <= '0'; -- synchronous clear signal not used yet sync_p: process ( nrst, clk, txdin ) -- synchronize txdin signal for internal use begin if (nrst='0') then up_s <= '0'; elsif (clk'event and clk='1') then up_s <= txdin; -- count down slowly while TXDin = '0' and end if; -- count up fast while TXDin = '1' end process; div_p: process ( nrst, clk, up_s ) -- divide clk and generate carry signal for begin -- the counter process cnt_p if (nrst='0') then div_s <= 0; elsif (clk'event and clk='1') then if (div_s/=DUTY) then -- definition of duty cycle 1:4 (1:(3+1)) with DUTY=3 div_s <= div_s + 1; -- (3:16 < 1:5 < 1:4 but 1:4 required for PPM) else div_s <= 0; end if; end if; end process; up_p: process ( up_s, div_s ) begin if (up_s='1') then cin_s <= '1'; -- cin_s always '1' for fast up count elsif (div_s/=DUTY) then cin_s <= '0'; -- cin_s = '1' each 1/(3+1) clock for slow down count else cin_s <= '1'; end if; end process; cnt_p: process ( nrst, clk, clr_s, cin_s, up_s ) -- synchronous up/down counter with synchronous clear and carry in -- LIMIT defines a fuse look threshold time t = (LIMIT+1)/clk[Hz] -- counter stops down count at 0 and stops up count at LIMIT begin -- up count is faster than down count - see cin_s @ div_p: process if (nrst='0') then cnt_s <= 0; elsif (clk'event and clk='1') then if (clr_s = '1') then -- if clear = '1' then clear counter cnt_s <= 0; elsif (cin_s='1') then -- if carry in = '1' then count up/down if (up_s='1') then -- if up_s = '1' then count up if (cnt_s/=LIMIT) then -- if count < LIMIT then count up cnt_s <= cnt_s + 1; end if; else -- if up_s = '0' then count down if (cnt_s/=0) then -- if count > 0 then count down cnt_s <= cnt_s - 1; end if; end if; end if; end if; end process; cmp_p: process (cnt_s) -- counter comparator to check limits (0,LIMIT) begin if (cnt_s=LIMIT) then maxcount_s <= '1'; else maxcount_s <= '0'; end if; if (cnt_s=0) then mincount_s <= '1'; else mincount_s <= '0'; end if; end process; reg_p: process ( nrst, clk ) begin if (nrst='0') then current_state <= cool; elsif (clk'event and clk='1') then current_state <= next_state; end if; end process; fuse_p: process ( current_state,maxcount_s,mincount_s,txdin,revival,clr_s,nrst ) -- fuse process state diagram begin -- depends on up/down counter case current_state is when cool => txdout <= txdin and (not clr_s) and nrst; killed <= '0'; alive <= '1'; -- feed through if (maxcount_s='0') then next_state <= cool; else next_state <= ouch; end if; when ouch => txdout <= '0'; killed <= '1'; alive <= '0'; -- lock fuse and switch infrared -- transmitter diode off (TXD='0') if (mincount_s='0') then next_state <= ouch; elsif (revival='1') then next_state <= cool; else next_state <= ouch; end if; when others => txdout <= '0'; killed <= '1'; alive <= '0'; -- to secure the design next_state <= cool; -- WARNING : (mincount_s='1' AND maxcount_s='1') would results in an -- oscillation between both states : cool <-> ouch on any raising_edge(clk) -- and this would result in a IR LED killing oscillation of the TDXOUT !!! end case; end process; end behavior; -- -----------------------------------------------------------------------------