Intel® Quartus® Prime Software
Intel® Quartus® Prime Design Software, Design Entry, Synthesis, Simulation, Verification, Timing Analysis, System Design (Platform Designer, formerly Qsys)
17257 Discussions

Best approach for creating clock sources please?

Altera_Forum
Honored Contributor II
2,329 Views

Hello again and more inane questions from yours truly! 

 

I have a design which relies on many different clock sources: A lot of inter-dependent timing going on. 

 

What therefore is the best (or 'proper') approach to creating many different clocking sources (from the same basic clock source input of course). 

 

I know it is not 'good practice' to gate clocks to create another clock which is then used to clock say a latch or a register etc. 

 

So, what is considered a good / acceptable clock source? The output of a state machine perhaps? The output of a counter? 

 

Any guidelines / comments / suggestions much appreciated! 

 

I include below VHDL of something I have written that creates an 8MHz clock from my 24MHz source: 

proc_8MHz : PROCESS (nPowerSettleDelay, M24MHz) BEGIN IF nPowerSettleDelay='0' THEN uM8MHz <= '1'; u_nM8MHz <= '0'; Next_State <= State_1; ELSIF RISING_EDGE(M24MHz) THEN CASE Next_State IS WHEN State_1 => Next_State <= State_2; uM8MHz <= '1'; -- 1 u_nM8MHz <= '0'; -- 0 WHEN State_2 => Next_State <= State_3; uM8MHz <= '0'; -- 0 u_nM8MHz <= '1'; -- 1 WHEN State_3 => Next_State <= State_1; uM8MHz <= '0'; -- 0 u_nM8MHz <= '0'; -- 0 END CASE; END IF; END PROCESS proc_8MHz;  

 

Is it 'safe' then to use either the uM8MHz or the nM8MHz signal as clock sources? 

 

Cheers again all, 

 

Andy
0 Kudos
12 Replies
Altera_Forum
Honored Contributor II
1,634 Views

 

--- Quote Start ---  

 

I know it is not 'good practice' to gate clocks to create another clock which is then used to clock say a latch or a register etc. 

 

So, what is considered a good / acceptable clock source? The output of a state machine perhaps? The output of a counter? 

 

--- Quote End ---  

 

 

The only good clock is either a real clock or the output of a PLL, thats it. A state machine output and counter output are the same thing - a register, and these are bad. Using logic to create a clock is bad. 

 

For what you are doing, you want clock enables. Ie. the enable is high for one clock in a number of clocks, and you clock all your logic using the same system clock. And then your logic looks like this: 

 

process(clk) begin if rising_edge(clk) then cnt <= cnt + 1; div_by_2 <= cnt (0); if cnt(1 downto 0) = "00" then div_by_4 <= '1'; else div_by_4 <= '0'; end if; if div_by_2 then --stuff happens at half the system clock end if; if div_by_4 then --stuff happens at 1/4 of the system clock end if; --etc end if; end process;
0 Kudos
Altera_Forum
Honored Contributor II
1,634 Views

Riiiiight. 

 

So, reading into your kind response, in effect I can see that basically everything that is clock event driven should therefore be in ONE big process? I had often wondered what exactly was meant by 'clock enables' - not quite the same as an enable pin on an IC as I had thought of it. 

 

Now I am wondering how to rewire 2,000 lines of my VHDL code to suit this approach (and if it is worth it TBH). LOL. Having said that, what I have written so far is 95% complete and seems to work, all be it with some issues that need sorting out. Like most 'code' the closer one gets to completion, the more difficult the bugs become. 

 

Thank you again Mr. Tricky 

 

Andy
0 Kudos
Altera_Forum
Honored Contributor II
1,634 Views

It doesnt have to be one big process. Remember, its all about the logic, not the code. So one big process or several separate processes can map to the same hardware. 

But the theory is the same. Use the same system clock for all of your processes and have clock enables as appropriate. The same enable can go to many processes.
0 Kudos
Altera_Forum
Honored Contributor II
1,634 Views

OK, good my friend. 

 

If you can please, can you show me an example of such inter-process clock enabling (of for example different clock 'sources / frequencies'). Such an example will quickly open my mind up to exactly the right approach! ;) 

 

Many thanks yet again for your help. 

 

Andy
0 Kudos
Altera_Forum
Honored Contributor II
1,634 Views

The following code: 

 

signal cnt : unsigned(2 downto 0) := "000"; signal div_by_2, div_by_4, div_by_8 : std_logic; process(clk) begin if rising_edge(clk) then cnt <= cnt + 1; div_by_2 <= cnt(0); if cnt(1 downto 0) = 0 then div_by_4 <= '1'; else div_by_4 <= '0'; end if; if cnt = 0 then div_by_8 <= '1'; else div_by_8 <= '0'; end if; if div_by_2 then --do something every 2 clocks end if; if div_by_4 then -- do something every 4 clocks end if; if div_by_8 then -- do something every 8 clocks end if; end if; end if;  

 

Is functionally the same as, and will produce the same hardware as this code: 

 

process(clk) begin if rising_edge(clk) then cnt <= cnt + 1; end if; end process; process(clk) begin if rising_edge(clk) then div_by_2 <= cnt(0); end if; end if; process(clk) begin if rising_edge(clk) then if cnt(1 downto 0) = 0 then div_by_4 <= '1'; else div_by_4 <= '0'; end if; end if; end if; process(clk) begin if rising_edge(clk) then if cnt = 0 then div_by_8 <= '1'; else div_by_8 <= '0'; end if; end if; end if process(clk) begin if rising_edge(clk) then if div_by_2 then --do something every 2 clocks end if; end if; end if; process(clk) begin if rising_edge(clk) then if div_by_4 then -- do something every 4 clocks end if; end if; end if; process(clk) begin if rising_edge(clk) then if div_by_8 then -- do something every 8 clocks end if; end if; end if;
0 Kudos
Altera_Forum
Honored Contributor II
1,634 Views

Yes, just the answer I was looking for! Spot on. :) 

 

So, going back to my original post, could I rewrite it as below to suit what I need to achieve? 

 

--The main clock source for everything is running at 24MHz --Create an 8MHz & n8Mhz clock enable proc_8MHz : PROCESS (nPowerSettleDelay, M24MHz) BEGIN IF nPowerSettleDelay='0' THEN en_uM8MHz <= '1'; en_u_nM8MHz <= '0'; Next_State <= State_1; ELSIF RISING_EDGE(M24MHz) THEN CASE Next_State IS WHEN State_1 => Next_State <= State_2; en_uM8MHz <= '1'; -- 1 en_u_nM8MHz <= '0'; -- 0 WHEN State_2 => Next_State <= State_3; en_uM8MHz <= '0'; -- 0 en_u_nM8MHz <= '1'; -- 1 WHEN State_3 => Next_State <= State_1; en_uM8MHz <= '0'; -- 0 en_u_nM8MHz <= '0'; -- 0 END CASE; END IF; END PROCESS proc_8MHz; --Do something that is @ 8MHz proc_DoSomething_8MHz : PROCESS(M24MHz) BEGIN IF RISING_EDGE(M24MHz) THEN IF en_uM8MHz THEN --do something every @ 8MHz END IF; END IF; END PROCESS proc_DoSomething_8MHz; --Do something that is @ /8MHz proc_DoSomething_n8MHz : PROCESS(M24MHz) BEGIN IF RISING_EDGE(M24MHz) THEN IF en_u_nM8MHz THEN --do something every @ /8MHz END IF; END IF; END PROCESS proc_DoSomething_n8MHz;  

 

Thanks Tricky, 

 

Andy
0 Kudos
Altera_Forum
Honored Contributor II
1,634 Views

Taking for example my last post, I have created an 8MHz clock enable based on my common 24MHz clock source. 

 

When the enable is true, any process such as: 

proc_8MHz_freq : PROCESS (M24MHz) BEGIN IF RISING_EDGE(M24MHz) THEN IF en_uM8MHz='1' THEN --some_counter + 1 END IF; END IF; END PROCESS proc_8MHz_freq;  

 

Here, some_counter will +1, not a frequency of 8MHz, rather it will see a bust of M24MHz clocks for the 8MHz enable period. This is obvious and not what I want to have happen with some_counter. 

 

Is there an elegant way to better create the en_uM8MHz enable signal such that only ONE clocking event drives some_counter? 

 

Thanks again, 

 

Andy
0 Kudos
Altera_Forum
Honored Contributor II
1,634 Views

how is the enabled generated? it should not be a 4 clock wide pulse, but a 1 clock wide pulse every 4 clocks.

0 Kudos
Altera_Forum
Honored Contributor II
1,634 Views

Generated as per post# 7, but I see what you are saying...

0 Kudos
Altera_Forum
Honored Contributor II
1,634 Views

If your enable is longer than a single clock cycle, there must be something wrong somewhere. 

With the posted code snippets, assuming the 24HMz clock is constant, the some_counter signal should only increment once every 3 clocks. 

Are you simulating this design? have you got a testbench? are you tracing back the cause of these "bursts"
0 Kudos
Altera_Forum
Honored Contributor II
1,634 Views

The clock source is constant and a 'true' clock. 

I think maybe I am implementing the enable signal incorrectly.... 

 

proc_Counters : PROCESS(IN_RESETn, M24MHz) BEGIN IF IN_RESETn='0' THEN usg_Counter_7_0 <= (OTHERS => '0'); ELSIF RISING_EDGE(M24MHz) THEN IF en_uM8MHz ='1' THEN IF usg_Counter_7_0 = usg_MAXCOUNT THEN --Reset the counter... usg_Counter_7_0 <= (OTHERS => '0'); ELSE --... or increment the counter usg_Counter_7_0 <= usg_Counter_7_0 + 1; END IF; END IF; END IF; END PROCESS proc_Counters;  

 

Yes in my sim, I see the counter increasing in bursts.
0 Kudos
Altera_Forum
Honored Contributor II
1,634 Views

Sorry, yes the en_uM8MHz signal is high for 3 M24MHz clocks. Hence the source of the bursts.

0 Kudos
Reply