Using the Logic Modules

 

by Jim Clark

Introduction

Complex Logic Functions

The Nord Modular provides only the most basic logic functions - AND, OR, XOR, and NOT (or Inversion). Fortunately, one can make any Boolean function (logic function) out of AND gates and NOT gates alone.

Flipflops, Counters and Other Sequential Elements

Flipflops

Clavia does not include a flipflop module, but we can make one using the sample-hold module. This is shown in the following patch, which implements a "toggle" flipflop. On each rising clock transition the output of the flipflop alternates, or "toggles", between high and low values. In the patch pressing the C4 key alternately turns the sound on, and then off. This toggling action is very useful in a wide variety of control tasks, and is also very useful in making so-called "noodles" or auto-play patches.

Figure 1. A toggle flipflop made using sample-hold modules (R. Hordijk).

One can use the sample/hold feedback approach to make a so-called "D" flipflop (D is for "data"). A D-flipflop merely holds the value of its input when the clock goes high. Now this seems to be the exact operation performed by the sample/hold modules. So why do we need to do anything else? Well there is a small problem, one that is actually quite prevalent whenever you try to emulate parallel or concurrent systems (such as analog synthesizers), in which every thing happens at the same time, with digital systems where only a few things (or only one thing) happen at a time. In the Nord Modular, on a single DSP slot, operations are executed one at a time. This means that the outputs of some modules are actually computed before the outputs of others. Normally the order in which computations are done does not matter. But sometimes it does, and in obtaining the proper functioning of a D-flipflop is one of these times. To see this, consider a string of sample/hold modules, intended to emulate a string of D-flipflops. Such strings are referred to as shift registers and are very useful. So encountering such a situation is not unlikely. Now consider two adjacent sample/hold modules, where the output of one feeds into the input of the other. Suppose that the operation is synchronous, which means that every unit should change state at the same time, usually in response to a clock signal transition. So let both the of sample inputs of these two sample/hold modules be connected to the same clock signal. Let the output of both sample/hold modules be initially zero, and let the input to the first be connected to a high signal. Now, what will happen when a rising transition of the clock signal is received? Well, the answer depends on the order of the computations! If the second sample/hold module is computed first, everything will be OK. After all the computations are done, the output of the first sample/hold will be high, and the output of the second will remain low. But if the order of the computation is reversed, the answer will be "wrong". Look carefully. If we compute the output of the first sample/hold first, it will sample its input, which is high, and therefore set its value to be high. Now we compute the output of the second sample hold, but its input is now high, since we have already computed the first module's output! Thus the output of the second sample/hold module will also be high. This behaviour is bad for two reasons. First is that sometimes we get the wrong answer. But worse still, we can't say for sure when designing the patch whether we will get the right answer or not, since we have no control over the order of computation.

But we can design circuits that are insensitive to the order of computation. We can use pairs of sample-hold modules that are clocked with different signals, out of phase relative to each other. This dual-phase clocking allows us to control when things happen. The resulting circuit is called a "Master-Slave" D-flipflop. The master is the first of the two sample/holds in the pair, and the slave is the second, which merely follows the lead of the master. A master-slave D-flipflop is shown in the following patch.

Figure 2. A master-slave flipflop made using sample-hold modules (J. Clark).

The patch shown above exhibits two different ways of clocking the flipflop from a single clock signal. The first way is to clock the first sample/hold module with the clock signal, and clock the second with the inverse of the clock signal. This has the drawback that the clock signal has to go high and then low again before the input value appears at the output of the second sample/hold module. In many situations, especially those in which the clock signal is a regular periodic signal, this will cause no problem. In some situations, it may be a long indeterminate time before the clocking signal goes low. For example, in the above patch, to get a new value latched into the D-flipflop one has to first press the C4 key and then release it. It might be a long time before you release the key. It would be preferable if the value could be stored in the flipflop whenever you press on the key. In this case the second clocking technique may be better. In this technique the clock signal is used to clock the first sample/hold as before, but is also fed into a positive edge delay module to generate a slightly delayed version of the clock signal. This delayed pulse is used to clock the second sample/hold module. This will guarantee that the first sample/hold module is clocked before the second. The delay time is set to the minimum non-zero value of 1 millisecond. If the clock rate is faster than 1KHz, this delay value will be too long and the second sample/hold will never be clocked. In this case an audio-rate delay line would have to be used. This is an expensive solution, however, so in such high speed situations it is better to use the first clocking technique and merely use an audio inverter to invert the clock signal.

Counters

Counters are useful for many musical tasks. There are many different ways to construct counters in the Nord Modular. Which way is best depends on the application. Many sequencing tasks require counters, and for these the ready-made sequencer modules fit the bill. The control and note sequencer modules are very good for general purpose counter design as well. They are easy to use and involve merely setting the levels of the sequence step values to the desired count values. For example, if you wanted to count repeatedly in the sequence 1,2,4,5,1,2,... you could take a control sequencer and set the loop period to 4 and set the first four levels to 1,2,4 and 5. Voila! Instant counter.

Using the sequencer modules as counters is an easy solution, but sometimes one needs more flexibility. Often one requires a "binary" output from the counter, where the count value is not in a "voltage" but rather represented as a multiple-bit digital word. One could use a "digital to analog converter" to convert a voltage level from a sequencer module into a digital word, but this would be inefficient. There are more straightforward techniques. One could implement a binary counter directly using toggle flipflops, or even D-flipflops, but unless you need to process audio-rate signals it is more efficient to use ClkDiv modules.

Counters can be made with sample/hold modules feeding back to themselves through summing (or mixing) modules. The output of the sample/hold is added to a set value (say 1 or -1, for example) and the sum fed back to the sample/hold input. When the sample/hold is triggered, the new count value is loaded. This technique is used in the patch shown below, an absolutely delightful classic created by Keith Crosley:

Figure 3. A patch simulating a wind-up toy. It contains many different uses of the logic modules (K. Crosley).

In this patch, an "Up/Down" counter (one which can either count up or count down) is formed from the sample/hold module labelled "Spring Tensi.." and the summing modules labelled "+1" and "-1". Which of these summing modules gets fed back to the sample/hold input determines whether the counter counts up or counts down. The selection of this feedback is done by the crossfade module labelled "+/- Control", under the direction of the "Unwinder" signal derived from the Squarewave LFO module labelled "Unwind Rate". When the phase of the squarewave output of this LFO is high, the input to the sample/hold comes from the "-1" summing module, turning the counter into a down counter. When the LFO waveform is in its low phase the counter is an up counter. This part is simple enough. The counter alternates between being an up counter and a down counter following the squarewave output of the "Unwind Rate" LFO. The actual clocking of the counter, on the other hand, is somewhat more complicated.

Asynchronous Elements

Although most synth programmers are comfortable with sequential logic elements such as counters, much of music cannot be tied to a rigid clock. In fact, it is better to think of an electronic musical instrument that is involved in a performance as an Event-Driven system. In such a system, what drives transitions from one state to the next is not the transitions of a clock signal, but the occurence of an Event, usually generated externally to the system. For example, events can be created by the pressing of a key on the keyboard of a synthesizer, or the striking of a drumstick on an electronic drum pad. As you are no doubt aware, even when playing music such as Bach, where a very precise periodic rhythm is desired, the events produced by human performers are by no means periodic. Some players are much better than others, of course, but then there is the drummer from your neighborhood garage band. Some music is arrhythmic. Some music has the timing of its events derived from the environment. In all of these cases, musical events essentially occur asynchronously, that is to say, they occur independently of a periodic clock.

Asynchronous systems have been studied extensively by computer engineers and many useful basic building blocks have been developed. One of these building blocks is the "C-element". A C-element can be thought of as an "AND-gate" for events. An event is generated on the output of the C-element only after an event has been received on both of the inputs. Thus, the C-element acts as a synchronizer - if an event occurs on one of the inputs, the C-element will wait until an event occurs on the other input before changing the output. A C-element can be made in the Nord-Modular as shown in the following figure:

Figure 4. Implementing a C-element using Nord Modular modules (J. Clark).

C-elements are often used in control mechanisms for various asynchronous operations. One example that is useful in music applications is the asynchronous FIFO (first-in-first-out) buffer. In an asynchronous FIFO events arrive (asynchronously) and stored in the buffer, and then read out asynchronously. Think of the FIFO as a tube in which one can insert balls in one end and can remove them out the other end. Clearly the first ball in will be the first one out. There is no need to put balls in at the same time you take them out, nor do you have to do the insertion or removal at regular time intervals. Of course, if the rate of insertion events is greater than the rate of removal events, events will tend to pile up in the FIFO, which might then overflow at some point.

The following diagram shows how such an asynchronous buffer can be made out of C-elements.

Figure 5. A 16-element asynchronous buffer made using C-elements.

The following patch shows an implementation of an asynchronous buffer on the Nord Modular. The input events come from the keyboard module, and hence are generated by the external world, perhaps by a garage band drummer, and therefore not guaranteed to be periodic. The output events are generated by a clock. Therefore this patch has the effect of making the possibly irregular input events into a nice smooth sequence (as long as the input events come in as fast, or faster, than the output events, otherwise the outputs will stop). Of course, one can just as easily do the opposite, where a regular sequence of events is input to the buffer, while the readout events are irregular.

Figure 6. The 16-element asynchronous buffer Nord Modular patch (J. Clark).

Arpeggiation

Constructing an arpeggiator in the Nord Modular (or in any modular, for that matter) is deceptively difficult. It might seem that one just needs to throw together some sample/holds and be done with it, but things are not that simple. The main problem is that the order in which notes are played in an arpeggiaton is usually in order of pitch, rather than in order of being played. This means one can not just store the sequence of notes (e.g in sample/hold modules) as they are played. Instead one must scan the notes that are being played, in pitch order. This scanning must be done continually, as notes can be played or released at any time.

I will describe one particular implementation bit by bit. The patch is loosely based on the Korg Mono/Poly arpeggiator. It works by quickly scanning one octave of key detectors once during each arpeggiation cycle.

Let us start by looking at the part of the patch that scans the octave of keys. Twelve note-detect modules are used to detect the pressing of each of the twelve keys in the octave. Each of these modules outputs a high logic level when the corresponding key is pressed (based on NOTE-ON commands in the MIDI stream input to the Nord Modular). We use a counter to scan through each of the note-detect modules one by one. The scan counter is implemented with a set of ClkDiv modules. The outputs of the ClkDiv modules are passed through XOR gates which permits the scanning to be either upwards or downwards. The XOR gates either invert the counter outputs or leave them unchanged. The effect of inverting the counter outputs is to have the counter count downwards instead of upwards. The counter bits are used to control a 12-input multiplexer. A multiplexer is a circuit which selects one of a set of inputs and passes that signal to the output. So here, the scan counter selects which of the twelve NoteDetect module outputs to examine. The multiplexer is implemented on the Nord Modular with a set of CrossFader modules acting as binary analog switches. An expensive solution perhaps, but in the absence of voltage-controlled switches on the Nord Modular, the best we can do.

Figure 7. The portion of the arpeggiator patch that implements the scanning of one octave of keys (J. Clark).

When the scan detects a key down (i.e. when the output of the scan multiplexer goes high), the scan is halted until the arpeggiator clock goes low, at which point the scan is restarted and searches for the next key that is down. The envelope generators are triggered on the rising edge of the arpeggiator clock. Let's pause here and look at an example. Suppose there are three keys pressed, say the C#, F, and A keys of the octave we are scanning. Suppose the scan counter is counting up (we will look at up/down counting in a bit) from 0, which corresponds to note C of the octave. The output of the scan multiplexer will be low until the scan count reaches the count selecting the NoteDetector tuned to C#. Then the output of the multiplexer will go high. At this point the scan is stopped. Therefore the multiplexer output will stay high. The desired operation of an arpeggiator is to progress from one note to the next at times specified by some arpeggiation clock. Thus we restart the scan when we see the next rising edge of the arpeggiator clock. At this point the scan will continue until the next key that is down is found, in this case the F key. Then the scan stops again until the next rising edge of the arpeggiator clock. You might complain that there will be a bit of timing irregularity caused by the fact that there will be some time elapsed after the rising of the arpeggiator clock to the detection of the next key. So there will be a slight delay in the setting of the pitch to the new value from when the envelope generators were triggered by the arpeggiator clock. And you would be right, but the scan clock frequency is set to be quite high, so that this time delay is very small and unnoticeable in practice, and at worst adds a bit of pitch modulation.

The key scanning process is the difficult and tricky part of the arpeggiator design. The rest of the arpeggiator patch is just adding in the bells and whistles which make arpeggiators so much fun. As mentioned earlier, this arpeggiator is based on the one found on the Korg Mono/Poly synthesizer, which had a number of different modes of operation. The different features of the Nord Modulator implementation are as follows:

* The arpeggiation direction can be either UP, DOWN, or UP/DOWN. The direction is set by the XOR gates acting the output of the scan counter. In the UP/DOWN mode the input to the XOR gate is toggled (alternated between high and low values) at the end of each 1 octave scan. This toggling is implemented by a ClkDiv module acting on the Most Significant Bit of the scan counter. LogicProc3 is an XOR gate which combines the UP/DOWN toggle signal with the output of the "Up or Down" switch, which selects whether the direction is UP or DOWN when UP/DOWN mode is not active (i.e. when the "Up and Down" switch is off).

* The arpeggiation pattern can be repeated in higher octaves. Either 1, 2 or 3 octave jumps can be selected. To see how this works, one should first understand how the pitch is determined. The scan count at the time when the scanning is stopped is converted to a pitch value by a "digital-to-analog" converter, consisting of four multiplier modules feeding a mixer. The multipliers multiply the counter bits by values of 1,2,4, and 8, and these products are added together to complete the conversion, and then fed into one of the pitch inputs of the master oscillator. In addition to this pitch value, another pitch input of the master oscillator is fed by an offset signal corresponding to the octave jumps. The octave offets are values of 0,12,24 or 36, depending on the octave jump setting. The time at which octave jumps are triggered is determined by the state of a counter (implemented by the ClkDiv module titled OctRpt in the patch). This selects the output of the octave jumps 1-4 switch. The period of this counter is set by knob 7. It determines the number of notes between jumps from one octave to the other. Interesting patterns can be obtained by setting this period to something different than the number of keys pressed.

In addition to the octave jumps, one can repeat notes within the arpeggiation pattern. The number of repeats of a note is set by a clock divider (the module entitled NoteRpt in the patch) placed in front of the scan counter. This counter has the effect of pausing the scan count until a given number of arpeggiator clock cycles have passed, thereby resulting in the repetition of notes. * There is a ping-pong pan mode which merely alternates successive notes between the left and right outputs, giving the classic ping-pong effect.