Counters

There are several applications for counters in a CPU core. The Program Counter and the stack controllers are examples. The counter is specialized for its application since it may need to count up or down and may need the capability of loading a preset value. In any case, it is desirable to have fast updates.

Although there is a single-chip 4-bit counter in SCE, it has limitations that make it unsuitable for counters that need to be able to have a value loaded or which count in a non-standard sequence. An advantage to them however, is that they have a dedicated reset input. they are also as fast as possible in this environment (1 tic).

In SCE, the memory bank is useful as the core of a counter. It operates on 4 bit values and may be programmed to count up or down, by 1 or 2 or even have a non-linear count sequence. All these functions may be programmed into a single bank where the function performed is determined by the value of the 2nd input as a function select input.

There are many ways to implement a counter in this environment and I will explore a few in this article. You may notice that there are many similarities between a counter and an adder. Once you think about it, a counter is simply a specific case of an adder. Examples of the applications for counters in a CPU will also be explored below.

=Small Counter= The smallest 'normal' counter is of course the single-chip 4-bit counter. However, it will only count by 1. If you need a small (4-bit) counter with a different sequence, or with selectable sequences, this circuit is the smallest and fastest available. The count is advanced at every valid function input code. Usually the valid codes represent 'count up' and 'count down'. The function code must return to '0' after each count. The counting bank must be programmed so that when the code is '0' the output simply reflects the input. The trigger bank must be programmed with all '0's for this function code value.

Since there is no discrete reset input, an additional function code should be programmed to always output a '0'. This reset code may be set such as when both UP AND DN are active. Note that there is no provision for carry or borrow so it is limited to 16 states (or counts).

=Full-featured Counter=

This is a loadable counter that can be connected to a data bus. The main counter section is made of the blocks "C/B", "+/-" and "Lin". The rest of the lower half of the diagram are used to load a new value in the counter. The remaining AND gate at the top is an output enable so the data bus can read the counter.

Counter Operation
The C/B block computes whether a carry or borrow is required and sends the result to the next higher stage. The +/- block computes the next value for the counter, depending on the current count (L) input and the function (H) input. This makes a state machine which can count through any sequence at any length up to 16 steps. For the counter, it simply counts up or down according to the bits of the function input. With 4 possible function bits it can perform any necessary function such as +2, -2. It may be programmed so a certain pattern will reset it to '0'.

The output of the +/- block passes through the AND gate which is enabled in normal operation, and to the input of the Lin block. This is a latch so its output won't change until the clock input goes high. After the count is settled, the clock input goes high and sets the new current value of the counter. The count is settled a minimum of 2 tics after either 'up' or 'down' are enabled for this 4-bit counter, or 3 for an 8-bit counter, etc. Conversely, if the function input is held steady, the clock input may be repeatedly pulsed immediately after the count is settled.

When a new value is to be loaded into the counter, the load enable signal goes high (the other function signals are ignored), then the clock input can activate 2 tics later to set the new value.

Loadable 16-bit Counter
The above circuit can be expanded to 16-bits. The following circuit is an example. The total delay from function code change to a valid, latched output is 5 tics.

Compared to the previous circuit, the functions of the discrete gates are being taken up by memory banks. In particular, the input select - the AND gates and the INVerter are replaced with 2 banks. We can then feed the function code directly into the bank and let the bank do any decoding we need. Also, the Output Enable AND gate in the top left corner is not included. It may be needed in the final design, depending on where this counter is connected.

This circuit can count up or down (even by other than one) and be preset. A total of 16 functions could be implemented. Usually Reset, Load, +1, +2, +0, -1, -2 are sufficient.

Operation
This is essentially an expanded version of the previous circuit with the changes stated above and a few more. There is no clock input to control the latch. Instead, the latch control is generated internally to allow all functions to be initiated by a single function code input. Also, the load control is incorporated into the function code (a single hex signal).

As long as the function code is "Idle", no change is called for and the counter will stay in its current state as long as needed. The 'count' input enable is activated but the +/- banks simply pass it through. The Dec bank does not output a latch signal so the current value just stays as it is.

When the function calls for a 'count' (any), the 'Count' input enables are activated and the counter banks begin computing the new value. The 'Dec' bank outputs an 'F' in time to latch the first hex digit. The OR gates latch the next stages as they are calculated. (A delayed, common latch control was tried but something in SCE caused the delay time to become excessive so a chained latch was devised.) The new, latched value is ready to be read 5 tics after the function code activates. (The function code input must be held steady at least this long.)

If the 'reset' code is presented, all input enables are disabled and the +/- banks output a steady '0' which is latched and becomes the current counter value ('0000').

If the 'load' code is presented, the preset input enables are activated, allowing the new value to the +/- banks. These banks will simply pass this value on to the latches so the load value is latched and becomes the current counter value.

Programming the Banks
The memory banks implement the function denoted by the code input. As an example, the memory programs listed below implement these functions: 0 (8) = Idle 1 (9) = +1 2 (A) = -1 5 (D) = +2 6 (E) = -2 8 (4) = Load Preset F (7) = Reset (load '0000') To reduce bit needs, ignore the high bit by using the code listed AND the one in parens.

We will assume the layout and connections as shown in the schematic. All function codes are connected to the High-order input while the parameter is connected to the Low-order input. This makes defining the program for the banks easier.

Input Enables
There are two sets of input selects (or Enables) - the count feedback input and the preset input. The preset input is only active for the function code '8'. According to the schematic, the function is input to the H order input, so all other lines in the bank must be '0 and the line for an '8' is filled in linearly. That is, it's "0123456789ABCDEF", so the output simply follows the input but ONLY when the function code = '8'.

The other set of input selects enables the current count to be the input. The same (linear) function must be entered for all function codes that are "counts", i.e., codes = '1', '2', '5' and '6'. The idle code also has this input enabled.

+/-
These are the banks that do the 'counting'. They each have a function input in addition to the counter value input. When the function input says to +1, the bank is programmed to output (1 + the current value). The other functions are programmed similarly. For example, a -1 function line will look like: "F0123456789ABCDE". If the parameter is '0', the bank outputs 'F', etc. When the function is '8', the +/- banks just follow the input, like the input enables. When it is 'F', these banks force all '0's for output, resetting the counter.

C/B
These banks compute whether a carry or borrow is required from the next higher stage. Each line must be programmed uniquely for the function it is assigned to. For example, when we want to +1 and the current value is 'F', we will send a carry (+1) to the next stage. When we want to -2, a borrow (-1) must be sent if the current value is either '0' or '1' because both will need to borrow from the higher stage.

Note that the 'codes' sent to the next stage do NOT have to be the same as the function input codes. The programs listed DO have them the same but this is only so the first-stage C/B bank may be programmed the same as the higher-order ones.

Lat
These are latches and only follow the input value, just like the input enables. Only the connection is different. Since there is nothing connected to the High-order input, it is always '0' and we only need to program the '0' line. It is programmed with the linear function, like the enables. The difference is that with the clock input connected, the output does not change until the clock signal activates. This gives the "latch" function.

Enc
This single bank just converts the various function codes into a single, binary value. When the function is 'Idle', it outputs a '0'. For any other code, it outputs an 'F'. Thus, the first line is "0FFFFFFFFFFFFFFF". No other line matters since there is nothing connected to the High-order input.

The programs:
The final memory bank programs are listed here so they can be copy/pasted easily. The entire 256 entry is given for completeness.

Ena (Load)

Ena (Count)

+/-

C/B

Lat

Enc

=Counter Applications=

Stack Controllers
The stack controller spends the greatest majority of effort simply counting up and down by 1. On occasion it is reset to '0'. So the stacks will benefit greatly by using a fast counter. The fastest 4-bit counter is of course, the single-chip counter. However it does not chain directly if you need to count UP and DN.

Furthermore, the stack controllers will be driven by signals from the instruction decoder/sequencer and will benefit from not requiring a separate clock input. When the 'INC' or 'DEC' signal is activated, the result needs to be available as soon as possible.

In this case, the 4-bit counter may be used with external detection of the overflow conditions (carry and borrow). This circuit provides those needs in the shortest time - just 3 tics for a 2 stage (8-bit) counter.

Program Counter
The program counter also needs a very fast counter. However the demands on this counter are much greater than with a stack controller. The PC must not only be fast but it is 16 bits wide (in this design), must be loadable (possibly from various sources) and may need to count by 2. These requirements preclude the use of the single-chip counter.

=other=