One issues you hit as you tackle complex projects in your electronics hobby is the need to run things at different speeds.
As time is the essence of digital logic you'll start to want to explore changing the length of said time periods. Inn fact, logic itself relies on having discrete periods of time in which to switch bits between 1s and 0s.
Clock management is a perfect skill for folks coming from an Arduino background to master: so let's get to it. We're going to show how to divide frequencies using digital logic.
What did you build that required multiple clicks?
In another post, I discussed how I multiplied a clock using only digital logic. I want to impress something on you: don't do that for a production piece of hardware. A real solution requires feedback! (Check out our PLL multiplication post here).
Digital Clock Division Theory: Phase Relationships, and Perfect and Predictable Divided Clocks
While determining the requirements for my recent project, I determined I needed a few clocks.
Folks who have worked with video in the past will probably recognize a few of them - and note that I decided to 'round' things off a little:
- Base: 3.5795454 MHz ( (5*7*9)/(8*11) MHz)
- Pixel: 12.528 MHz (7/2 * Base)
- Other: 25.0568 MHz (7 * Base)
Don't get hung up on the exact numbers. This particular project was a video project, but as long as you determine up front what clocks you need and how much you can 'cheat' you can accomplish similar things.
We'll discuss a bit of the theory, but concentrate more on the practical applications.
Here's the thing: division of a clock is simple compared to multiplication. If you have a nice, 50% duty clock coming into your project, you can easily make other 50% clocks at a slower speed. It's especially simple to divide clocks if you have an even integer divisor.
For our project, we started with a 14.31818 MHz oscillator - .49 cents on eBay, and 4x our Base Clock.
(We prefer full can designs. You can use a crystal with two leads, but getting these things to oscillate properly on your own is harder.)
Methods of Clock Division
Dividing Clocks with the Simple Flip Flop Method
Most sites recommend using normal flip-flops to divide a clock.
You can Google around for more detail, but in our schematic we use a D-Flip-Flop to toggle back and forth between a 1 and a 0 by feeding back the opposite of the data to the input. This effectively divides our clock by 2:
There are 2 'events' every clock cycle - a low to high movement, and a high to low movement. The flip-flops will toggle on every positive - low to high - edge, so you effectively only get one 'event' per clock. Bam, simple division by two, combine a few in fun ways to easily divide by powers of 2 while matching the clock's duty cycle.
Note, too, that you can create very complex methods to divide clocks by non-powers of two. Using and and or gates, you can effectively string together flip flop outputs to match your 50% duty cycle.
Here's a good paper with some examples, from a Xilinx engineer.
Note that for this project, we divide our clock by 4, then 2 (so... 8). We then multiply by 14 to get around dividing by 4 and multiplying by 7. The odd integer created too much chip inflation for our taste.
Dividing Clocks with The Shift Register Method
One part most everyone who has played around with an Arduino has in their parts drawer? The venerable 74**595.
Now, this part is usually used as a "port expander" on an Arduino. Using one pin, you can control as many pins as you need at a slower speed than your system clock.
Here's something else that's pretty cool: what you put into the input comes out of the output at a known rate. By introducing feedback you can divide your original clock.
Using this method you can divide a clock by 2, 4, 6, 8, 10, 12, 14, or 16 by only adding an inverter! Chain a few together and you've got most any clock you need.
(As an added bonus for our project, you can sample any of the outputs to get your desired clock. All of Q0-Q7 in our schematic are running at 3.5795454 MHz, a huge bonus for a video project.
We get 4 phases here - "0 degrees" and 90, 180, and 270. If you started with a 28.6363 MHz clock? You'd make all 8 outputs useful by getting 8 phases!)
Digital Clock Division Practice: Build Our Clock Divisor in the Lab!
I've omitted some parts in this schematic, namely attempting to tie off unused inputs (especially on CMOS parts, see datasheets) and decoupling capacitors on some of the pins. If you follow this project, note that 25 MHz on a breadboard is starting to push the extremes of reliability - so do all you can for reliable operation.
Parts List:
- 14.31818 MHz Oscillator (try eBay)
- 74HC595 Shift Register
- 74F74N D-Type Flip Flops (eBay...)
- 74F14N Schmitt Trigger Inverters (Ditto)
Note: The 74HC595 would be better replaced by a shift register without a latch enable.
Also note we don't particularly care if the clock starts low or high when we power on. We invert the output, which will be a '?' at startup. If you use this concept in a hardware design language, initialize it to either high or low.
Digital Clock Division Bonus! Divide Frequencies in Hardware Design Languages
Our eventual end point for that 25.xxx MHz clock was a CPLD, a "Complex Programmable Logic Device".
In the abstract, a CPLD is a cousin to the Field Programmable Gate Array (FPGA). It has some benefits like instant configuration on power-up and lower power usage and footprint. However, CPLDs generally lack the huge number of resources present day FPGAs offer.They can be programmed with a Hardware Design Language, just like an FPGA.
Here's an example of dividing a 25.0568 MHz clock by 7 in VHDL (merely take 'nots' of each output for 7 more phases!).
-- Define the shift register:
signal PHASE_SHIFTER : unsigned(6 downto 0) := "1111111";
... -- Skip a few lines
process(CLK)
beginif (CLK'event) then
PHASE_SHIFTER <= unsigned(PHASE_SHIFTER (5 downto 0)) & not PHASE_SHIFTER(6);
end if;end process;
(Yes, I'm American. Yes, I learned Verilog first. I just enjoy VHDL more.)
Note: you'll need a CPLD/FPGA family which has flip flops which can clock on both edges to use the above code ("CLK'Event"). I used a 64 macrocell Coolrunner II from Xilinx.
Errata? Comments? Questions on Clock Division?
What methods have you used? See anything wrong with the piece as presented? Did it work for you? What projects have you completed that required clock manipulation?