Timer circuits create stable and accurate time bases for processing systems that are not affected by changing processor loads. Consistent periodic signals are required in several situations, including:
- Sampling input signals where phase noise (or jitter) will adversely affect the digitized waveform;
- Reconstituting output signals where phase noise (or jitter) will add unwanted distortion to the output;
- Creating a regular time interval the processor can use to service time sensitive processes (like clock displays);
- Creating periodic waveforms that drive external devices like motors or LEDs;
- Time-stamping input data;
- “Watch dogging” processor operations (watchdog timers are discussed later);
- And creating an accurate, low-overhead time base a processor can access as needed.
Timer circuits run independently from the processors timing system, so their accuracy is not affected by any software processes. Their outputs can be polled by the processor, or they can drive interrupt signals. You can read more about timer circuits in microprocessor systems here: Timers in Microprocessors
ZYNQs timer circuits
ZYNQ includes three timer circuits: a 64-bit global timer that runs continuously from reset; a Triple-Timer-Counter (TTC) module that can measure can create a wide variety of periodic signals; and a watchdog timer that can interrupt and/or reset the processor if errant software prevents it from being properly serviced. All three timer circuits use binary counters to measure time. The global timer’s counter always runs at 1/2 the CPU clock frequency. On the Blackboard, the global timer runs at 333.33MHz, so each new count represents a 3ns interval. The TTC uses a programmable clock generator, so many different count intervals are possible. The watchdog timer can use the processors main clock, or a clock generated in the FPGA. Each of these are discussed in the following sections.
Global Timer
The global timer IP block uses a continuously-running 64-bit counter running at 333.33MHz. After reset and while enabled, the counter will increment every 3ns, rolling over after 1750 years. The counter value can be read directly, and a new count value can be written. Because the counter value is 64 bits, consecutive 32-bit registers are used to read and write the value. Note that because the clock is so fast, the upper 32 bits might change just after the lower 32 bits are read – care should be taken to prevent misreading data in this case (i.e., read the upper 32 bits, then read the lower 32 bits, then read the upper 32 bits again – if the upper 32 bits have not changed, the 64-bit value is correct. If they have changed, read the lower 32 bits again).
A comparator value can be written, and an output signal (called the “event flag”) will be asserted when the counter and comparator values match. Bit 0 of the event flag register can be polled to check for a match, or that bit can drive an interrupt signal. After a compare event, a “1” must be written to the event flag register to clear the bit so it can show future compares.
To allow the global counter to generate periodic events, an auto-increment register can be programmed with a value that will automatically be added to the compare value immediately after a compare is true (bit3 in the configuration register enables this feature). Note that after a compare event, the user must clear the event flag so the next compare event can be regsitered.
Global Timer Registers
GTC_DRX (0x0200/0x0204): Global timer data. 64 bits in two consecutive registers (read/write).
GTC_DR: Global timer data. Returns counter value when read; loads new counter value when written. The counter should be disabled (bit0 in the control register) prior to a write cycle.
GTC_CR (0x0208): Global timer control register (read/write).
PRESCALER: Divides counter (by 2^N); only used for decrementing event (see ARM manual)
AI: Auto-increment mode enable (1 to enable). Causes increment value add to compare value after compare event.
IE: Interrupt enable (1 to enable). Interrupts occur whenever a compare event happens.
CE: Comparator enable – enables comparator output (1 to enable)
EN: Global timer enable signal (1 to enable)
GTC_ISR (0x020C): Global timer interrupt status (read/write).
EF: Event Flag. Automatically set to a 1 when compare output valid. Can be polled or can drive an interrupt. Write a 1 to clear.
GTC_COMPX (0x0210/0x0214): Global timer compare value. 64 bits in two consecutive registers (read/write).
GTC_COMP: Global timer compare data – 64 bits in two consecutive registers.
GTC_AI (0x0218): Global timer auto-increment value. Immediately after a valid compare, the value in this register will automatically be added to the value stored in the compare registers (if auto-increment mode is enabled).
GTC_AI: Auto-increment value used to automatically update global timer compare registers.
ZYNQ’s Triple-Timer Counter IP Block
ZYNQ includes two triple-timer-counter (TTC) IP blocks. Each TTC block contains three independent timer/counters, for a total of six counters. A representation of one such counter is shown below. Each 16-bit timer/counter includes a 16-bit clock prescaler on its clock input, an interval register and comparator to set a regular counting interval, a zero-detect comparator, and three “match” registers/comparators to compare the counter value to a given user-programmed value. The interval and match values can be used to create periodic waveforms, to generate interrupts, and to precisely measure input periodic waveforms.
Each of the six counter modules includes its own 16-bit interval register. The interval register can be programmed with any 16-bit number, and each time the count value equals the value stored in the interval register the counter will reset back to zero and continue counting (a signal/interrupt can be asserted when the count value is 0). If the interval resister contains zero, then the counter will count through the entire 2^16 count range, roll over, and continue counting. Each of the six counter modules also include three match registers. Each time the counter value equals one of the programmed match values, an interrupt can be generated. The first match register (match1) can also be used together with the interval register to create a periodic output waveform (see the PWM section below). The output waveform from each counter module can be polled by software, routed to an output pin, or routed to the FPGA for use by custom IP blocks. The counter can be configured to count up or down by setting the DEC bit in the configuration register.
If the counter is operating in interval mode (by setting bit 1 in the counter configuration register), it increments or decrements continuously between 0 and the value of the Interval register, with the direction of counting determined by the DEC bit (bit 2) of the Counter Control register. Otherwise the counter operates in overflow mode, and increments or decrements continuously between 0 and 0xFFFF (again with the direction of counting determined by the DEC bit of the Counter Control register). In either mode, an interrupt can be generated when the counter equals zero or when it equals one of the values programmed into the match registers.
The input clock to the timer module (PS_Clk) can come from the processor clock, or from the FPGA – the Blackboard is setup to use the 111.111MHz processor clock. The prescaler register divides the input clock by 2^(N+1), where N is the 4-bit prescaler value. The prescaler allows the 111.111MHz input clock to be divided by the first 16 powers of 2 (so, 2, 4, 8,… through 65,636).
Table 1 below shows the configuration registers for TTC0 counter 1; additional instances of these same registers exist for the other two counters in TTC0, as well as the other three in TTC1 (TTC1 offset is 0xF8002000).
TTCO_CLKCNT_X (0x00/04/08): Configuration register TTC input clock (read/write)
CE: Select negative edge of clock (1 to select); only for external clock if external clock selected
CS: Clock source (1 for external clock, 0 for 111MHz processor clock)
PRESCALE: Prescaler for dividing input clock by 2^(N + 1)
EN: Prescale enable (1 to enable use of clock prescale)
TTCO_CNTL_X (0x0C/10/14): Mode configuration (read/write)
PL: Waveform polarity (1 for 1-0 transition on match; 0 for 0-1 transition on match)
OW: Output waveform enable (1 to enable output waveform)
CR: Reset counter (1 to reset). Counter resets/restarts and CR bit automatically cleared
ME: Match Enable (1 to enable). Enables interrupt to be generated when any match occurs
DC: Decrement (1 to cause counter to down count)
IM: Interval mode (1 to enable interval mode; counter reset and interrupts generated at set interval)
OD: Output enable (1 to freeze counter at current setting, 0 to let counter count)
TTCO_CNTVAL_X (0x18/1C/20): Counter value (read only)
CNTVAL: Current counter value
TTCO_INTVAL_X (0x24/28/2C): Interval value (read/write)
INTVAL: Interval value. Maximum value counter will count to before reset
TTCO_MATCH_X (0x30 – 0x50 – 9 regsiters): Match values (three per counter) (read only)
MATCH: Match value. When match enabled, interrupt generated when count value equals match value
TTCO_ISR_X (0x54/58/5C): Interrupt status (read only; clear on read)
EV: Event timer overflow
CO: Counter overflow
M3: Match3 occurred
M2: Match2 occurred
M1: Match1 occurred
I: Interval occured
TTCO_IER_X (0x60/64/68): Interrupt enable (read/write). Write 1 to enable.
EV: Event timer overflow (1 to enable)
CO: Counter overflow (1 to enable)
M3: Match3 occurred (1 to enable)
M2: Match2 occurred (1 to enable)
M1: Match1 occurred (1 to enable)
I: Interval occurred (1 to enable)
TTCO_EVENTCNTL_X (0x6C/70/74): Event control (read/write). Configure input waveform settings.
ED: Event timer disable (0 to disable). When 0, event timer stops on overflow, when 1, not disabled.
EL: Event level (1 to count when input is low, 0 to count when input is high)
EN: Enable event timer (1 to enable)
TTCO_EVENT_X (0x78/7C/80): Event count value (read only).
EVENT: Count value. Value is duration of input waveform high or low time (set by EL bit above).
Using the TTC to generate a PWM signal
Each counter can produce PWM signal using the interval and match1 values: the interval value sets the PWM window frequency, and the match value drives the waveform high or low at a given count value. If the CLK_POL bit (bit 1 of the counter configuration register) is set to a 1, the output waveform will be: driven to a 1 at the start of the interval; driven to 0 when the counter value equals the match1 value; and driven back to 1 when the counter resets to start a new interval. This is illustrated in the figure below. If CLK_POL is 0, then the output waveform will start low, be driven high when the counter equals match1, and then reset back to low to start a new interval.
As an example, setting the 4-bit clock prescaler value to 9 will cause the counter to run at 111.111MHz/1024, or 108KHz. Then setting the interval register to 10000 will cause the counter to reset every 10000 counts, to create a PWM window frequency of 108KHz/10000, or about 10Hz. Then, the PWM duty cycle can be set by programming the match1 register. If CLK_POL is set to 1, then any pulse width between 1 and 2^16 clock periods (about 10us per clock period based on the 10KHz clock) can be set, with the pulse going high at the start of the interval, and back low when the counter equals the match value.
To design a PWM signal for any given application, you must decide what “step size” or time resolution is required for each pulse length (i.e., at what precision can you adjust pulse widths), what PWM period (or window frequency) is required, and how many different pulse lengths per window are needed. These values are related: the PWM period divided by the minimum pulse length gives the number of possible pulses lengths that can be created. The smallest attainable pulse width defines the minimum quantity that the PWM signal can represent; the maximum number of pulses per window defines the maximum quantity the PWM signal can represent, and their ratio defines the dynamic range of the PWM signal (often, a PWM signal must be able to represent a signal with a given dynamic range). In the case of driving a servo motor, if the minimum PWM step size rotates the servo by one degree, and each pulse must be able to attain at least 180 lengths, and the PWM period is 20ms, then given the systems time base, values can be chosen for the main clock divider, the interval time, and the individual pulse widths. Since the main time base and divider ratios are not changeable (they are fixed on Blackboard/ZYNQ), you must choose best-fit values for the main clock divider, interval time, and pulse widths.
A representation of one of the six counters that emphasizes the blocks needed to create a PWM signal is shown below. Blackboard’s hardware configuration file routes the waveform outputs of the three counters in TTC0 to the PWM pins on servo connectors J1, J2, and J3.