Forum Discussion
Altera_Forum
Honored Contributor
14 years agoMaking a counter from 50MHz Clock?
Hi,
I know this might be a really silly question but I can't seem to get the theory down into HDL: I want to make a 3579545Hz clock from a 50MHz clock input: i know that --- Quote Start --- 1/3579545 = 2.7936511484001458285899464876123e-7 Multiply that by 1000,000 and get 279.36511484001458285899464876123ns --- Quote End --- :D but how i use this info to make a clock? that's another story. I've tried just using a PLL, but it didnt like my desired output. I'm thinking it was in the wrong format but i don't know for sure. In the megawizard, i told it that my input clock was 50MHz. the output could only be in MHz ps or ns. of course it did not like my desired output saying that tthe requested multiply/div factors were not achievable. could someone please help? P.S. I tried reading the ALTPLL.pdf but it was very hard to do14 Replies
- Altera_Forum
Honored Contributor
--- Quote Start --- Wrong, I am afraid. choose counter of 26 bits (to cover 50 million) and I will add extra bit for overflow protection. I prefer to use variable here so that the count is corrected before it is too late.
--- Quote End --- gooooooooooooooooooodprocess(clk) variable count : unsigned(26 downto 0) := (others => '0'); begin if rising_edge(clk) then if count > 50000000-1 then count := count - 50000000; else count := count + 3579545; end if; my_clk <= std_logic(count(25)); end if; end process; - Altera_Forum
Honored Contributor
Wow. Clever trick. I hope that I can keep enough consistent practice to have tricks like that up my sleeve whenever ready. Thanks!!
- Altera_Forum
Honored Contributor
The "others => '0' is equivalent to writing:
count := "000000000000000000000000000"; -- and I lost how many zeros. The subtraction is not to reset count to zero and you shouldn't. Instead you wrap up and keep difference from zero (count phase). To understand it better take case of generating 21MHz from 50MHz clock. the ratio factorises to 21/50 so: 0, + 21, + 21, + 21, + 21, + 21,... = 0, 21, 42, 63, 84, 105... and with modulo 50 = 0, 21, 42, 13, 34, 5... 0, 0, 1, 0, 1, 0... MSB will togle at 0.5 or more of count value - Altera_Forum
Honored Contributor
Sorry,
Work and school got a bit overwhelming... I'm able to spend a few days working on some VHDL now :) I will try to comment your code to confirm i understand it. --- Quote Start ---
--- Quote End --- thanks for your help!!process(clk) variable count : unsigned(26 downto 0) := (others => '0'); //why others => '0'? begin if rising_edge(clk) then if count > 50000000-1 then count := count - 50000000; //set count to 0 else count := count + 3579545; //very clever "modulo" does it really work as such? end if; my_clk <= std_logic(count(25)); //passes bit 25 and uses as a clock signal end if; end process; - Altera_Forum
Honored Contributor
Refer to my correction of code above. Moreover you can factorise your values of 50MHz and new clock by dividing each by 5 then use modulo 10000000 instead saving few bits on adder.
Notice this adder is a general case for any rate below clock rate and is equivalent to using explicit counters (which are adders anyway) for example to get half clock out of 50000000 then you will say add 25000000 modulo 50000000 then factorise it to the ratio 2:1 hence add 1 modulo 2 which is what we do by just having 1 bit toggle without the hassle of modulo but modulo serves a good generic concept. - Altera_Forum
Honored Contributor
so if bit 25 is set, then this is 3479545? interesting technique. never seen it before. :) I will give that a try thanks!!!
- Altera_Forum
Honored Contributor
please excuse me for a moment, will reply shortly, thanks :)
- Altera_Forum
Honored Contributor
Wrong, I am afraid.
choose counter of 26 bits (to cover 50 million) and I will add extra bit for overflow protection. I prefer to use variable here so that the count is corrected before it is too late.process(clk) variable count : unsigned(26 downto 0) := (others => '0'); begin if rising_edge(clk) then if count > 50000000-1 then count := count - 50000000; else count := count + 3579545; end if; my_clk <= std_logic(count(25)); end if; end process; - Altera_Forum
Honored Contributor
--- Quote Start --- You have it in NCOs hidden there. just use a suitable width adder starting from zero adding 3579545 every system clock and carrying over result after (50 million -1) i.e. if it becomes > (50 million-1) then subtract 50 million from it and keep going nonstop. Then MSB is your rate. The generated clock is correct rate-wise but duty cycle varies. --- Quote End --- so then:
is that what i need to do? (not actual VHDL syntax :) )if ((counter > 49,999,999) AND (counter < 3579545Hz)) counter = counter - 50,000,000 endif; if(counter == 3579545Hz) clk_enable <= "1" else clk_enable <= "0" endif; - Altera_Forum
Honored Contributor
You have it in NCOs hidden there.
just use a suitable width adder starting from zero adding 3579545 every system clock and carrying over result after (50 million -1) i.e. if it becomes > (50 million-1) then subtract 50 million from it and keep going nonstop. Then MSB is your rate. The generated clock is correct rate-wise but duty cycle varies.