VHDL coding tips and tricks: Combinatorial Frequency Multiplier Circuit in VHDL

Thursday, April 1, 2010

Combinatorial Frequency Multiplier Circuit in VHDL

     This article is about frequency multiplier in VHDL.Frequency multiplier??? Did you mean Frequency divider?No,you heard me right,I mean multiplier.And the interesting thing is that this is a combinational circuit which doubles the frequency applied to it.The digital circuit for this is given below:
Now analyse the above circuit.Assume a practical NOT gate instead of an ideal one.Then you can see the following timing diagram:


As you can see, because of the delay in the NOT gate the "notclk" signal is not an exact invert of the clk signal.After the XOR operation you will get the "output" signal as shown above.If you analyse the frequency of the output signal it is double that of clk signal.But the duty cycle of the output signal is not 50%.

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?
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.

7 comments:

  1. This is a very useful blog, keep up the good work.
    Thanks
    A Masters Student in the US

    ReplyDelete
  2. 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.

    Xilinx 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.

    ReplyDelete
  3. @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.
    But from a learner's point of view it is good to try out something new than just learn the theory.

    ReplyDelete
  4. Hi. Have you tried adding 2 NOT ports to increase delay before going into the xor to try make the duty cycle correct?

    ReplyDelete
  5. @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.
    Anyway 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.

    ReplyDelete
  6. 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