VHDL question - making a slower clock from a faster one... - Page 1
Forum section: electronics / projects

author: alank2
author_rank: Super Contributor
timestamp: August 09, 2016, 09:10:30 pm
content: Let's say you have a 50 Mhz clock - can you make a 40 MHz clock from it with VHDL? or will it have to be half or slower?I did this to half a clock:process (clk50M)beginif rising_edge(clk50M) thenclk <= not clk;end if;end process;Could you do something whe nthe clk50M changes (low->high, or high_low) so that something occurs on both transitions? Could that something then be addition into a std_logic_vector that could drop a 50 Mhz clock down close to 40 MHz ? Something like defining a 16 bit one and then using the highest bit for the 40 Mhz clock? If you added 8192 to it each clk50m transition, the top bit would toggle at 50 Mhz , right? 8192*40/50 would be 6553.6, or rounded up to 6554. Would that yield a 40 MHz clock even though it is jittery?

author: Siwastaja
author_rank: Super Contributor
timestamp: August 10, 2016, 06:14:56 am
content: You can only divide by integer (25 MHz, 16.67MHz...), otherwise you need a specialized analog hardware, namely PLL. But practically every device you program with VHDL includes a bunch of PLLs, so learn how to instantiate those on your chip of choice.Of course you could do horribly jittery kludges, but I think the jitter is too much.

author: rstofer
author_rank: Super Contributor
timestamp: August 10, 2016, 01:53:15 pm
content: Most devices have some form of DCM (Digital Clock Manager) which is a very sophisticated phase lock loop. Yes, you can generate 40 MHz from a 50 MHz clock but you'll have to wait for hamster_nz to jump in. I can't recall that I have ever used the gadget. Or, if I did, it was a canned solution to something I was playing with.

author: rstofer
author_rank: Super Contributor
timestamp: August 10, 2016, 03:28:13 pm
content: Wouldn't this thread be better over in the FPGA forum?

author: aandrew
author_rank: Frequent Contributor
timestamp: August 10, 2016, 08:56:18 pm
content: Generally speaking, do not create new clocks in logic. Use the clock hardware within the FPGA to do it for you. Using a signal that is generated from logic as a clock input for another bit of logic is all kinds of janky; the synthesizer now has to route a logic signal around to a clock network and you might have more issues meeting timing since the delays on the general routing fabric aren't as tight as on the clock networks. From one run to the next you may end up with enough of a variation that your logic won't work. Your generated clock will also be more jittery than one generated with hardware designed to generate clocks.Having said that, if you need some kind of slower timing, use clock enables. This helps to keep all your logic tied to your "core" clocks (i.e. no need to worry about clock domain crossing if the logic all uses the same clock) and utilizes the FPGA fabric better, since pretty much every ALM/LUT/LAB/whatever has clock enables just waiting to be used.An example. Let's say you've got logic that you want to run every 100ms. You've got a 24MHz clock. You don't create a 10Hz clock, you generate a 10Hz clock enable and gate the logic that must run every 100ms with the clock enable.Code:-- generates a 1T clock enable pulse every 100msprocess gen_100ms_ce (clk, rst)variable ctr: integer range 0 to 2399999;beginif rst = '1' thenctr := 0;onehundred_ms <= '0';elsif rising_edge(clk) thenif ctr = ctr'high thenonehundred_ms <= '1';ctr := 0;elseonehundred_ms <= '0';ctr := ctr + 1;end if;end if;end process gen_100ms_ce;And now to use it, you still use the normal (fast) clock:Code:-- does something every 100ms, uses a clock enable to gate the logicprocess do_100ms(clk, rst)beginif rising_edge(clk) thenif onehundred_ms = '1' then...end if;end if;end process do_100ms;

author: rstofer
author_rank: Super Contributor
timestamp: August 10, 2016, 10:05:58 pm
content: It seems to me that the approach above works well when the divisor is huge. But getting 40 MHz out of 50 MHz using counters probably doesn't work. You can't even divide by 2.The manual gets to the meat of the situation around page 71:http://www.xilinx.com/support/documentation/user_guides/ug472_7Series_Clocking.pdfThe gist of it might be to multiply the 50 MHz by 8 and divide by 10. There are certain ranges for the VCO so a bit of studying is required.

author: hamster_nz
author_rank: Super Contributor
timestamp: August 11, 2016, 03:08:39 am
content: If you are using Xilinx 7 series, this should work....Code:Library UNISIM;use UNISIM.vcomponents.all;....--------------------------------------------------------- Generate a 40MHz from 50Mhz clock-------------------------------------------------------clocking : PLLE2_BASEgeneric map (BANDWIDTH => "OPTIMIZED",CLKFBOUT_MULT => 24, -- VCO freq is 1.2GHz - needs to be between 800MHz and 1600MHzCLKFBOUT_PHASE => 0.0,CLKIN1_PERIOD => 10.0,-- CLKOUT0_DIVIDE - CLKOUT5_DIVIDE: Divide amount for each CLKOUT (1-128)CLKOUT0_DIVIDE => 30, CLKOUT1_DIVIDE => 16, CLKOUT2_DIVIDE => 16,CLKOUT3_DIVIDE => 16, CLKOUT4_DIVIDE => 16, CLKOUT5_DIVIDE => 16,-- CLKOUT0_DUTY_CYCLE - CLKOUT5_DUTY_CYCLE: Duty cycle for each CLKOUT (0.001-0.999).CLKOUT0_DUTY_CYCLE => 0.5, CLKOUT1_DUTY_CYCLE => 0.5, CLKOUT2_DUTY_CYCLE => 0.5,CLKOUT3_DUTY_CYCLE => 0.5, CLKOUT4_DUTY_CYCLE => 0.5, CLKOUT5_DUTY_CYCLE => 0.5,-- CLKOUT0_PHASE - CLKOUT5_PHASE: Phase offset for each CLKOUT (-360.000-360.000).CLKOUT0_PHASE => 0.0, CLKOUT1_PHASE => 0.0, CLKOUT2_PHASE => 0.0,CLKOUT3_PHASE => 0.0, CLKOUT4_PHASE => 0.0, CLKOUT5_PHASE => 0.0,DIVCLK_DIVIDE => 1,REF_JITTER1 => 0.0,STARTUP_WAIT => "FALSE")port map (CLKIN1 => CLK50MHz,CLKOUT0 => CLK40MHz, CLKOUT1 => open,CLKOUT2 => open, CLKOUT3 => open,CLKOUT4 => open, CLKOUT5 => open,LOCKED => open,PWRDWN => '0',RST => '0',CLKFBOUT => clkfb,CLKFBIN => clkfb);On the latest releases of Vivado you may need to add a clock buffer on the input clock - it doesn't do it automatically during the implementation phase any more.