Introduction
The first sentence on this page used to be this: “This is hopefully a short topic”. Well, it turned out to be anything but. I spend weeks (weeks!) on this seemingly simple problem:

I have a current source. I have a load. A resistive load at that. I need to somehow turn the current on and off on the load. How to do that?
So, let’s go though some of the problems I had and the solution I came up with!
Inhibit drivers
Actually, before we go there… Lets spend a few moments understanding the application!
In core memories, selection of a particular bit (a core ring) is done through a matrix of selection wires. These so-called X and Y wires are energized by a “half-current”, a current that’s – well – half of the current needed to flip the magnetization of the ferrite core ring. Doing so, even though a whole row and a whole column of core rings in the matrix see some current flowing through them, only a single one sees enough current to flip.
This is the basic concept behind writes in magnetic core memories. A problem arises though when we try to construct multi-bit memories. In those setups all bit-planes are connected in series for both the X and Y selection wires; meaning that now there is one core at the X/Y intersection for every bit-plane. For a 16-bit memory, sixteen of them. Of course we want to write a bit-pattern, not all “1”-s, so somehow we would need to control which of the 16 selected cores would actually flip their fields. We do that, by having a third wire, called the “inhibit wire” threaded through every core. There is one such wire for every bit-plane and snakes through every core of a given bit-plane. During writes, if a “0” is to be written into a bit, the inhibit wire is also energized, but in the opposite direction by a half-current. This subtracts from the total magnetic field inside the cores of that bit-plane, making sure that none sees a strong-enough field to flip their values.
Long story short, in order to get a functional core memory, I need the ability to drive a half-current into a wire at command. In theory this driver is quite a bit simpler than the X and Y select current drivers. There are two important reasons for this:
First, the inhibit current is uni-directional. This means that no H-bridges are needed, not even half bridges. A simple high-side switch should do, which is why the schematic at the top of the article looks so simple. Side-note: high-side so that during sense operation the sense-inhibit wire is not tied to a voltage that saturates the common-mode input of the sense amp.
Second, the length of the wire, and consequently it’s resistance is different from the X/Y select wires: only about 15 ohms for each half.
Here’s how DEC dealt with the problem:

This of course is the circuit for only one of the bit-planes, there are sixteen replicas of this in a PDP-11. They are using their favorite trick of saturating transformers to control the current and transformer base-drive (which we’ll get back to) to get their speed up.
You can also see them connecting the two half of the sense wires in parallel. This parallel loading a current source is not nice: it makes controlling the current in the two halves problematic. If the resistance of the wires isn’t exactly the same it can lead to different currents flowing it the two halves even if they sum up to the same value. This led me down the path of separating the two paths and having independent drivers. That means I actually need 32 inhibit lines drivers but I also can lower the current on each driver to 370mA from the 740mA they have used.
As you can see in the above schematic, DEC didn’t provide any discharge paths for the inductive loads, strengthening my conviction that the load is mostly resistive. Still, I plan on having a Zenner diode solution just in case.
Timing
The inhibit current is there to prevent a core from ever reaching the saturation current that would induce a magnetic field flip. This means that by the time both X and Y currents ramped up to their peak value, so should the inhibit current. What was DECs approach to timing?
It appears that the inhibit current was enabled for 300ns. It also seems that X and Y currents were turned on at the same time for writes (this is different from reads apparently) and were on for 400ns. I gather that all currents were turned on at the same time, but why was inhibit turned of early is a mystery. I honestly probably am reading the timing diagrams incorrectly, this setup makes no sense.
I’m not yet sure I want to make X/Y current timing different between reads and writes. I just want to make sure that by the time X current (the one turned on second) ramps to its full value the inhibit current also settled.
Either way, I intend to use this memory with a 2MHz cycle time, same as DEC. I figure if I can get a ~200ns current pulse with reasonable edges into the load, that should be good enough and worry about exact timing later.
First though
Since we’re building a computer from discrete transistors, let’s look at the simplest circuit that comes to mind: a PNP transistor. I’ve selected an ancient, high-power device for the job: the TIP42C:

The circuit should be fairly obvious, except for D6, so let’s spend some time on it. You see, switching an ideal current source is not really a thing. Current will flow through a current source. An ideal one, at least. It will generate whatever voltage is needed to make that happen. The actual current source I have will max out at a voltage around 20V, the supply voltage. If it can’t generate the requisite current even by putting out that voltage level, the current through it will start to drop. In other words: it’s a current source up to 20V, after which it is a voltage source. The simplest way to model that behavior is to put a 20V zenner in parallel with the current source. This will ensure that the voltage output will be capped at 20V and any extra current that can’t flow through the load will flow through the zenner. Not a real solution, just a model, but good enough.
So how does this switch perform?

In one word: not well. Not well at all. Even if I ignore the fact that the steady-state current is much lower then the set-point of the current source (the rest is flowing through the base), there is enormous over-shoot during turn-off and very poor decay behavior. There’s also a significant turn-on current spike in the negative direction.
Let’s tackle the decay first, because that’s easy. The TIP42C is – to put it simply – a lumbering giant. It’s high-power, but slow. Its transition frequency is a mere 3MHz. So, just for fun, let’s replace it with my go-to PNP transistor, the 2N3906. This is a small-signal device, completely inadequate for the job, but Spice doesn’t care. This little critter has a much high transition frequency of 250MHz:

Much better. So the lesson here is: I need to find a faster power-transistor. I selected the 2db1182q, the same one I ended up with in my current source design. It has a reasonable transition frequency of 110MHz and the current-carrying capability for the purpose. How does it do?

As expected, somewhere in between. Still, at least the edges are nice and clean. But what about the steady-state current? It’s about 250mA, which is to say that the base current is over 100mA. That’s very large. It is controlled by the base resistor, so to lower it, I have to increase the value of R11. My transistor has a hFE of about 110, so, in order to conduct 370mA emitter-current, the base current needs to be about 3mA or higher. Let’s set it to ~4mA, which corresponds to a base resistor of 4.7k:

OK, we clearly have issues. Now the circuit is so slow that it can’t even completely turn off during the 300ns I allow it to have. On the plus side, the steady-state current at least is fixed and the overshoot is gone.
I seem to have arrived at an impasse: Either the switch is too slow to be usable, or has enormous turn-off transients. Both are show-stoppers. I need speed, otherwise currents for subsequent memory operations overlap and I get unreliable operation. I can’t allow overshoots (especially overshoots) on the current as they lead to inadvertent flipping of magnetic cores, thus corrupting memory content. I could try to finesse the value of R11, but I don’t like to play those games: it’s going to be nasty to get it working reliably over temperature and process variations.
So, what to try next?
Second thought
In this day and age, no one in their right mind uses BJTs for power-switching purposes. Everyone uses MOSFETs. Even I used them in my H-bridge designs. So, why not?

I’ve spent a lot of time selecting this particular MOSFET. I’m not going to bore you with the search, but I’ll tell you how I ended up with the search criteria. Before we get there though, let’s see how it’s doing!

Well, to be honest, I was hoping for better. Certainly is better then what I get with BJTs, but similar problems still exist: the current is slow to rise, needing about 120ns to plateau. There is also a large overshoot around the turn-off transient.
So, what is causing the transient? You see every MOSFET has three parasitic capacitors in it:

These capacitors need to charge and discharge when the MOSFET is turned on or off. Let’s start with the ‘off’ state. I this case the gate and the source are at the same potential (20V for us) and the drain is pulled down by the load to 0V. So Cds and Cgd are both charged to 20V, while Cgs is completely discharged.
When we try to turn on the device by lowering the gate to 0V, Cgs needs to charge to -20V. After the transient the source and the drain are at (roughly) the same potential, 20V. So, Cds needs to discharge and Cgd needs to flip it’s charge to -20V.
When capacitors charge change, they conduct some current. So, during the transient all three of these capacitors will conduct. Cds is not all that important, it conducts between the current source and our load, something we want our end-state to be anyways. The current through Cgs has two places to flow: either through the gate or through Cgd. Lets pay attention to the directions though! Both capacitors are charging to a negative voltage, so their current will flow from top to bottom. The shared current part thus is flowing from the current source to the load, again, something we want anyways. The part that flows through the gate is problematic. Let’s put the gate current on the same plot and zoom in on a single pulse:

OK, now we’re getting somewhere: we see that the gate-current is responsible for slow leveling of the current. We also see that quite significant amount of current flows through the gate in both transitions. Which leads us neatly to the turn-off transient:
Here, we try to turn the device off, by yanking the gate voltage back to 20V. As the channel closes, Cds needs to charge up to 20V and Cgs needs to discharge to 0V. Here’s the problem though: until Cgs discharges to a considerable degree it’s voltage (and consequently the gate-source voltage of the MOSFET) will stay above the threshold voltage and keep the device conducting. Only after that, can the transistor start turning off. All this time, we decrease the gate-drain voltage (gate is rising, but the device is still conducting, so the drain remains at 20V). This means that Cgd starts discharging (well, charging from -20 to 0V) as well. In other words, during the off transient, both Cgs and Cgd are changing their charge, which generates currents though them. Some of this manifests as current from our current source to the load, some as gate current. The portion of the gate current that flows towards the drain is added to the current flowing through the load. All this, while the MOSFET is still conducting, so there’s a significant current path from the current source to the load as well. This is the reason for the current overshoot. The current only starts to come off from its high, once the gate voltage reaches the threshold level and the channel starts to get choked off. Then, finally the load current starts dropping, eventually reaching zero.
Now, here’s the rub: there really isn’t much we can do about this. The parasitic capacitances are there. We can’t remove them. To operate the device, we have to apply relatively large voltage swings to the gate. The very operation of the device will introduce large voltage swings on the drain. These voltage swings will cause the parasitic capacitors to charge and discharge. The changing charge on the capacitors will drive these currents. To get the speeds we want, the swings will have to be speedy, which means the currents through these parasitic capacitors is going to be large.
So what can we do? We can try to select transistors with low capacitance values, but that’s about it. There is another problem though: the larger the device physically is (not the package, but the piece of semiconductor within), the lower it’s channel resistance is, but the higher the parasitic capacitance values are. I need low channel resistance to keep power dissipation in check and I need low parasitic capacitance values to keep the transients at bay. Worst: devices with large channel resistances usually come in small packages, things that can’t take high currents. So, even if I was fine with dissipating a bunch of energy on the MOSFET, the device – or rather it’s package – won’t be.
And now I can tell you how I arrived at this particular MOSFET with a rather unruly part number: this device strikes a rather nice balance between channel resistance, low parasitic capacitance values and a large enough package that the thermals close. Yet, it doesn’t work as exemplified by the plots above: I simply can’t live with uncontrolled current spikes in this application.
What did others do?
Now you see where my headache came from in the last few weeks: no matter which way I tried to solve this problem, I ended up at a dead-end: either too-slow-to-be-useful operation or current spikes that are verboten.
Yet, obviously, core memories did work, and worked at these speeds. So, the natural question is how? How did others manage to overcome these problems? I started looking at core memory schematics to collect some design ideas. After a while a pattern emerged. You’ve seen in in the DEC design as well, but here is another representative example, the Data General Nova:

Drive the transistors through transformers. I don’t like that. At all… Google to the rescue, here’s what I have found:
A BJT base drive is actually a bit more involved than a MOSFET gate drive design. The reason is that you have to be careful not to exceed the RBSOA of the BJT. The HFE falls with collector current so you need to drive it harder as the current increases. By driving it hard at low current just increases the switching/storage time so should be avoided. A small transformer placed in the emmiter lead (configured as a CT) will increase the base drive in proportion to the emmiter current and yield better switching performance. It’s called a proportional base drive.
A resistor in series with the base normally has a small capacitor placed across it. This charges up under forward biased conditions and reverse biases the base when the drive is pulled to ground, speeding up the turn-off. For high speed high current switching you have to be really careful to not exceed the RBSOA and even then the long term reliability of the device is questionable. MOSFET’s solved all (most) of these problems.
Here RBSOA I’m guessing refers to the (S)afe (O)perating (A)rea of the the transistor, essentially warning you not to cook it. Translated to plain English: BJTs suck in this role, use MOSFETs. Well, except I know they aren’t working either.
Third thought
So, is my option truly only to use transformers? Before we despair, let’s try to understand the reason for the overshoot. We already did that for the MOSFET case, but what about the BJT setup?
You see, the problem there is very different. Yes, the parasitic capacitors exist as well, but they are much smaller and … wait a minute! A BJT can be thought of as two diodes:

And when these diodes are forward-biased there’s a recovery time to be paid when we try to turn them off. This recovery time is especially long for silicon diodes, which these are. The transistor-terminology for this is “saturation”. When both the B-C and the B-E diodes are forward biased, the transistor enters saturation mode: there is a large current flowing form the collector to the emitter, the voltage drop from collector to emitter is rather low (a few hundred mV), but the price to pay is large recovery time. During this time, we try to reverse bias the B-C diode junction through increased base-current, which – for us – flows through the load but not the current source.
Going back to our circuit:

we now understand the reason for the overshoot and we can even see it in action if we plot the base- and load-currents on the same chart:

So, while the overshoot looks rather similar for BJTs and MOSFETs, the underlying mechanism is quite a bit different. The reason for the BJT spike is that we drive our transistor into saturation. If we could avoid that…
This is the very same problem I faced in my logic circuits. There too, saturation was a problem, though it manifested itself in slow operation not so much in large currents. The solution was to use schottky transistors. So let’s try that:

Except it won’t work here. You see, the diode (D7 above) does indeed prevent the transistor from going into saturation, but it does so by sinking enough current through the emitter-collector-diode-base-drive path to ensure that the collector-base voltage stays at around 0.2V, or whatever the forward voltage of the schottky diode is. The key here is that it increases the base current and that current flows from the emitter (our current source), but doesn’t flow through the load: we’ve introduced an additional current path from the collector through the diode that can divert this extra current from the load. In other words, we end up with a leaky switch that defeats our current source:

We still have a little bit of overshoot (now we’re paying for the recovery of the schottky diode, which is much smaller), but look at the steady-state current: it’s well below 300mA. It should be 370mA.
Fourth thought
Ok, Ok. This didn’t work, but maybe the idea isn’t so crazy: if we can prevent the transistor from entering saturation in some other way, a way without drawing any current from the collector to do so we can solve these problems in another way.
The idea would be to use an emitter-follower to de-couple the circuit that biases the base just the right way and thus drawing the requisite current from the supply of said emitter-follower instead of the collector of the power transistor. Yes, the base-current of an emitter follower is non-zero, but very small. There is a problem though: the emitter-follower introduces a temperature-dependent voltage drop on its output screwing up our reference. So, I’ll need a second emitter follower stage of the complementer kind to cancel it out.
With this two-stage emitter follower I now really reduced the load on the collector of the power stage.
With that, so far we have something like this:

The emitter of Q11 will now mirror the collector voltage of the power stage (Q8). We have to ensure that the base of Q8 never goes below this voltage. How to do that? Well, we can try our schottky diode trick:

Does it work? No, not at all:

The reason for this becomes obvious, if we plot the voltages at the beginning and at the end of the emitter followers:

Our emitter followers are too slow. That’s due to the pull-up resistor (R16) being too large, compared to the currents the diode (D9) needs to conduct.
We could reduce R16, but that in turn would increase the current through Q11, quickly moving it out from its supported power dissipation range. Here’s a different idea: now that we have such an intricate way of mirroring the collector voltage, what if we connect the output of Q11 directly to the base of the power stage and instead muck around with it’s input bias (the base of Q11) to introduce control?
Here’s that idea:

Does this work?

Huh, even worse! Except, if you pay attention to this, there are two things to notice: one, the on-time current is what it should be: 370mA. Two, the turn-off spike, while exists is very short. It’s really the off-time that’s not well-controlled at all.
In the off period we try to turn Q8 off by pulling its base close to its emitter: 20V. The only thing in this circuit that’s doing it is R16. It apparently isn’t doing a kick-ass job. We need to stiffen it somehow, but we can’t really decrease its value too much for the same reasons we couldn’t in the schottky diode variant above. We can, however bypass it during the off-time. Here’s that idea:

Now we rely on Q12 during the off-time and Q11 during the on-time. Does this work?

Yes, yes it does! It finally does!
Let’s take a close look at the overshoot:

It’s pretty bad in amplitude, but it’s really really short: only 2ns start to finish. I can’t believe that an actual circuit, built with real wires and real transistors with rather large physical distances can actually manage a 2ns wide ~300mA high current spike. And even if does, a ferrite bead should take care of it.
The end of the tunnel
This article is getting incredibly long, so I’m going to stop here. What I don’t like about this circuit is that I have to replicate it 32 times. It contains 5 transistors and a three resistors. And I still haven’t accounted for the level-shifters needed to drive it (right now my drive pulse is 20V high, but the logic circuit in my design operates at 3.3V). That too will need to be replicated 32 times. Still, this is the best I could come up with.
I also have to test this with my current source, not just an idealized one. I have to test it through temperature too.
Overall, this has been a wild journey. I would have never thought that that simple question mark at the very top could turn out to be such a bear. But, then again, this is what makes this project fun. Learning.