Monday, June 7, 2010

Synchronous Digital Logic implemented in Reason 4

Updated - Digital Logic in Reason: Updated Flipflop & Counter

Correction - FF pass-through outputs are CV Out3 and CV Out4 (not 2 & 3) for clock and reset respectively. The diagram is incorrect for version 0.0.1.

This is the sort of post where you either understand what I'm talking about, immediately realise the huge implications and your brain explodes, or you don't know what I'm talking about, in which case none of this will make much sense.

Late last year, I spent a considerable amount of time working on an idea. I wanted to see how far I could get implementing some sort of "digital logic" with Reason4 devices. You know, the sorts of things that make computers and electronics work. I wanted to use CV as a kind of "voltage" and create both combinational logic gates (e.g. AND, XOR) as well as sequential logic (flipflops) so that I can combine them to create various complex devices such as finite state machines or digital adders. This is the sort of thing that electronics engineers like myself think about...

I had grand plans for this stuff, but time ran out for now. Therefore I'd like to post what I have to date so that people can pick this up and run with it if they think it's interesting.

I did manage to get things working quite nicely - I believe basic finite state machines are definitely possible and to prove this I created one of the most simple of all - a counter. Behold, my 16-bit digital synchronous counter implemented entirely with Reason devices!

This design is based on the standard synchronous counter implemented with D-type flipflops, as described here.


In order to achieve this, I had to design a suite of simpler devices such as AND and XOR gates, as well as synchronous elements such as a clock generator and a flipflop.

I set myself some goals:

  1. each device must compose of no more than a single Thor instance. No combinators allowed because I wanted to put groups of these devices inside combinators without messing around with combi programming.
  2. ensure the devices are designed to run at the fastest Reason CV oscillator rate - 250 Hz. Not very fast really, but fast enough for what I want to do.
  3. ensure that the flipflops act as registers, not latches. The output should only change on the 'clock edge'.
An important question I had to resolve is whether to use unipolar (0-127) or bipolar (-64 to 63) CV signals as representations of digital logic levels. After a lot of messing around with unipolar CV, I eventually gave up and tried bipolar CV instead. It was much easier and this is what I'm now using. If anyone is interested, here are some unipolar combinational logic gates, but I failed to construct a reasonable flipflop.

Bipolar input signals need to be specially constructed, so I designed a bipolar signal source and bipolar clock generator to produce the right CV signals.

I'm not going to go into the intricacies of the combinational logic devices, but here is an interactive testbench (RNS). Click the Thor buttons labeled A, B, C and D to generate logical input signals...

then select your function from the Function Select combi (only choose one at a time!).

You should see the result in the Outputs combi. Some devices incorporate multiple gates, and are named as such - e.g. AND2. In this case, inputs A & B correspond to output W, and C &D correspond to output Y. For the NOT4 device, A corresponds to W, B to X, C to Y and D to Z.

You should be able to verify these basic logic operations pretty easily with this testbench.

The flipflop (FF) is a much more interesting device, and is the fundamental building block for synchronous logic. I won't go into the details of an ideal D-type flipflop, but one characteristic that is crucial is that the output only changes on the rising clock edge (i.e. when the clock transitions from low to high, in this case).

This testbench shows a single flipflop in operation. The clock is running at about 1 Hz and you can hear and see this in the Monitor combi. You can change the clock rate with knob 1 on the Inputs combi. You'll also see four buttons:

  1. reset - used to set the FF into a known state - set the button for at least one clock cycle, then unset it. It is a synchronous reset.
  2. data - the input signal that the FF will sample on the rising clock edge and hold.
  3. enable - used to turn the clock on or off. This version of the clock generator does not implement this correctly.
  4. beep - simply for audio feedback, turn it off if you prefer.

Below, the MONITOR combi shows four button-lights. The "FF Output" is the critical signal, and it should change to whatever "data" is set to, but only when the clock goes from low to high (i.e. just as the CLOCK button lights up).

The FF has 3 inputs on the back panel:
  1. ROTARY 1: incoming data that will be sampled and held on the rising clock edge.
  2. CV In1: the clock signal - a bipolar CV signal in the shape of a square wave.
  3. CV In2: the reset signal - active high, synchronous, sets the FF output to low.
The FF has several outputs:
  1. CV Out1: the sampled and held output.
  2. CV Out3: simply a pass-through for the clock for chaining FFs together.
  3. CV Out4: simply a pass-through for the reset for chaining FFs together.
  4. Audio Out4: this is for an optional 'beep' sound that helps debug the FF operation. You can leave this disconnected.

Correction - pass-through outputs are CV Out3 and CV Out4 (not 2 & 3) for clock and reset respectively. The diagram above is incorrect.

NOTE: when you save a Thor patch, it does not save any rear-panel cables. For the FF to operate correctly, you must connect AUDIO OUTPUT 1 to AUDIO INPUT 1 with a single cable.

This FF works by using a little trick to store state information. The incoming data value is used to set the transpose level of the Step Sequencer. However Thor will only remember this value when the Step Sequencer is triggered by the clock incoming on CV In1 going high. If we stopped here, there would be a problem. The FF output must only change when the clock edge rises, so it must not be transparent to changes on the data input when the clock is high. I forget exactly how I solved this, but I end up converted the stored value (transposed note value) into an audio signal, passing it out of the Thor via a very small delay, taking it straight back in again and converting it to an output CV value. This also creates a very short propagation delay that prevents the FF output from changing simultaneously with the clock edge - if it did, then downstream FFs would see their input value change too soon and that would be bad as it would make all FFs transparent on the clock edge.

Then I simply took the FF and combinational devices and connected them to create 4-bit counter combinators.

By chaining four of these in series, via the carry bit, I created a 16-bit counter. I had to add a FF in-between 4-bit counter to buffer the signal and ensure the first FF in the next 4-bit counter would sample accurately - probably an issue with the way Reason handles CV internally in large networks. This does add extra clock cycles unfortunately, but there may be a cleaner way to buffer between these counters.

The BV512 vocoder display is used to display the 16-bit value - you can see the least-significant-bit on the far right, and the most-significant-bit on the far left. It takes some time to reach its maximum value before rolling back over to zero.

This was a very interesting little project and I was immensely satisfied to create a functioning 16-bit counter. Unfortunately other things came up and I lacked the time or energy to take this further, but I envisioned the following projects using these components:
  1. a simple finite state machine that can change CV values in response to events - essentially a way for things to change over time in a programmatic way. One example might be a CV signal that changes after a number of events have occurred.
  2. a multiplexer design that allows the selection of multiple incoming CV signals so that only one (or a set of several for multi-input muxes) passes through at a time. This would allow programmatic selection of various control signals in real-time.
  3. hundreds of other little ideas spinning around inside my head.

I also learned a valuable lesson - in future, when creating many, many different devices with different functions, keep a log! That way you know what these things all are when you look at them again six months later. Sigh.

One final note. It is known by some that if you have a NAND gate (negated-and), you can implement any combinational logic function with just NAND gates. I've provided a NOT and an AND gate; the NAND should be trivial. Good luck!

RNS files in this post:
You can pull the device patches directly from those files - I do not plan to publish individual patches separately.

One last comment - although my demonstrations use Thor buttons in a combi for visual feedback, this is for illustrative purposes only. It's important that the "digital" CV signals sit on the rails - i.e. -64 and +63, or whatever the equivalent scaling is. The Thor buttons in a combi are only on when the signal is at the top rail, but off for all other values. To properly debug any use of these devices, I recommend using the CV Monitor instead of "Thor buttons", and ensuring that the relevant Delay display is either "1" or "2000" and nothing in-between, otherwise these errors will propagate and eventually cause problems.

The examples in this article require Reason 4 or newer.


  1. As an Eletrical Engineer and Reason user myself, I can only say: Cooool

  2. I have to check this stuff out later tonight when I get Home :D

    Good to see you posting articles again on your blog btw ;)

  3. @Mikael - thanks for your comment - I have some more things planned in this area so stay tuned.

    @Hydlide - thanks for your encouraging comment. It's hard to find the time these days, but every now and again I get a flurry of ideas and the motivation to write about them.

  4. Oh jeez. Ok that's pretty cool.
    As an FPGA-toolsmaker by day, and Reason-user by weekend... :)

  5. Very cool. I currently have these files open and trying to wrap my head around them(I'm not an engineer). Take a look at this post, you might find it interesting..

    Actually I'm hoping you have a better way of doing what I did. It's basically a knob movement monitor that translates knob movement into CV, independent of min/max programming.

    What I'd really like to find is a way to capture the velocity of a knob movement, ie if I move a knob quickly, the CV is higher than a slow movement. At any rate, I think it represents another dimension in Combi programming. Sent it to Robb last week. I'm hoping someone can take the idea further.

  6. @polycube - I've got to do something intellectually challenging at some point in my week :-P

    @danreneer - I took a look at your post, it sounds very interesting. I have some ideas on this to think about this weekend.

  7. I'm a Mechatronic engineering student and producer using Reason. Just finished a subject on digital logic where i had to implement some basic state machines etc. on a CPLD. I wish i had the time to play with this idea in reason myself, alas i do not at the moment. Very interesting stuff tho. Thanks for posting. Good to know someone else spends hours on things just because they are interesting!

  8. @DJ - thanks for your comment, glad you found it interesting :) Feel free to drop by this site again for more of this stuff in the future, time permitting.