Now analyse the above circuit.Assume a practical NOT gate instead of an ideal one.Then you can see the following timing diagram:
A VHDL code can be written for this code.But since the Xilinx ISE simulator just ignores the gate delays we cannot see the above output in the simulation level.Also for actually applying a delay in hardware you need to use a clock buffer as shown in the code.
--Library declarations
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
Library UNISIM; --for including the Language template "BUFG"
use UNISIM.vcomponents.all;
--------------------------------------------
entity test is
port (clk : in std_logic; --input clock
a : out std_logic; --output signal which changes with "clk" signal
--output signal which changes with "frequency multiplied clock" signal
b : out std_logic
);
end test;
architecture Behavioral of test is
signal c1,O,a2 : std_logic:='0';
signal count,count2 : std_logic_vector(31 downto 0):=(others => '0');
begin
BUFG_inst : BUFG
port map (
O => O, -- Clock buffer output
I => c1 -- Clock buffer input
);
c1<=not clk;
a2 <= clk xor O;
b<=count(28);
a<=count2(28); --original
--counter with modified clock
process(a2)
begin
if(rising_edge(a2)) then
count <= count+'1';
if(count="11111111111111111111111111111111") then
count <=(others =>'0');
end if;
end if;
end process;
--counter with original clock
process(clk)
begin
if(rising_edge(clk)) then
count2 <= count2+'1';
if(count2="11111111111111111111111111111111") then
count2 <=(others =>'0');
end if;
end if;
end process;
end Behavioral;
If you analyse the code ,you can see that I have two counters running at different frequencies.And the actual output signals are the 28th MSB bit of these counter values.Why this extra piece of code is needed?library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
Library UNISIM; --for including the Language template "BUFG"
use UNISIM.vcomponents.all;
--------------------------------------------
entity test is
port (clk : in std_logic; --input clock
a : out std_logic; --output signal which changes with "clk" signal
--output signal which changes with "frequency multiplied clock" signal
b : out std_logic
);
end test;
architecture Behavioral of test is
signal c1,O,a2 : std_logic:='0';
signal count,count2 : std_logic_vector(31 downto 0):=(others => '0');
begin
BUFG_inst : BUFG
port map (
O => O, -- Clock buffer output
I => c1 -- Clock buffer input
);
c1<=not clk;
a2 <= clk xor O;
b<=count(28);
a<=count2(28); --original
--counter with modified clock
process(a2)
begin
if(rising_edge(a2)) then
count <= count+'1';
if(count="11111111111111111111111111111111") then
count <=(others =>'0');
end if;
end if;
end process;
--counter with original clock
process(clk)
begin
if(rising_edge(clk)) then
count2 <= count2+'1';
if(count2="11111111111111111111111111111111") then
count2 <=(others =>'0');
end if;
end if;
end process;
end Behavioral;
As I said the delay in NOT will be neglected in simulation results.So only way to verify your result is to synthesis it and try it in a FPGA board.I tried this code in Virtex 5 FPGA(package : ff136,Device : XC5VSX50T).The clock frequency I gave was 100 MHz.The doubling of the frequency is verified by 2 LED's one running at the input clock and another running at output clock.But at 100 MHz the ON/OFF process of the LED's cannot be seen by the human eyes.So you have to divide both the frequencies by a fixed number.That is why I have chosen a 32 bit counter and used its 28th bit to drive the LED.
When I ran the code I got the following results:
LED1(original clk) LED2(doubled clk)
off off
off on
on off
on on
off off
From the way the LED's are ON/OFF, we can see that the clock actually doubled in frequency!!! And it is acting like a 2-bit counter.
Note :- This kind of circuit is the only possible type of combinatorial circuit for doubling frequency.
This is a very useful blog, keep up the good work.
ReplyDeleteThanks
A Masters Student in the US
This post is dangerously misleading. there is no reason to think this is a "good idea". the only reason it works is because the author is lucky and also running a slow clock.
ReplyDeleteXilinx has several app notes and guides that tell you not to do the above.
I suggest using something like a DCM or PLL. in some cases a BUFR will work. This will avoid the build-dependent runt pulses.
@Chris : This post was written just from a digital point of view.I am not expecting people to use this method in their actual project, for getting a higher frequency.
ReplyDeleteBut from a learner's point of view it is good to try out something new than just learn the theory.
good one..
ReplyDeleteHi. Have you tried adding 2 NOT ports to increase delay before going into the xor to try make the duty cycle correct?
ReplyDelete@vende : No.I havent tried it yet. But the delay in gates is small, so it may not make a huge difference. Also simply adding NOT gates without any buffers between them may not work,since XST may optimize and remove the extra gates.
ReplyDeleteAnyway if you try it please let me know the results.
Also this is just an idea to play with. Dont use it in serious projects to get a higher freq.
Some cheap DIY-friendly FPGAs doesn't have a PLL. If you could multiply the frequency 4x (instead of 2x) then pass the output via a D Flip-flop, with N you'll end up with 2xFrequency and 50% duty cycle. I don't have a real FPGA to test it right now, but sometimes you can save several dollars for external PLL.
ReplyDelete