Sense amplifier revisited

Introduction

I’ve described my design for the sense amplifier in the core memory before. Here, I will revisit the subject and try to design a sense amp from scratch, while understanding more how it works. Join me on this journey of discovery, if you – just like me – are a little ignorant about differential amplifiers and the like.

A simple differential amplifier

Let’s start at the beginning! The simplest form of a differential amplifier can be the following:

I’m using a symmetrical +/-12V supply (V+ and V-), but that, as many other things in the design is rather arbitrary. The basic operation is as follows: we have a current source at the bottom, I1. This forces 5mA through the two branches of the differential amplifier. The current through R14/Q1/R1 and R13/Q2/R2 will sum up to 5mA. Always. The only thing that the transistors have control over is the ratio between the two currents.

So, to begin with, if both inputs (INA and INB) are at the same potential, then there is no difference between the operating points of the two transistors. Consequently, there can be no difference between the currents flowing through the two branches. They are 2.5mA each. This 2.5mA will drop 6V on R14 (and R13), so the outputs (CA and CB) are both sitting at 6V. This is independent of what the actual voltage at INA and INB are, as long as they are equal. The common component of INA and INB is erased from the output: the amplifier has infinite common mode rejection.

The common mode output voltage is:

Vcm_out = V+ – Rt*I1 / 2

If now we introduce a difference between INA and INB (let’s say that INA is higher), the current will re-balance itself. More current will flow through Q1 than Q2, consequently the voltage at CA will drop and the voltage at CB will rise. By how much? Well, that’s where R1 and R2 comes in the picture. Let’s for a minute forget about the Vbe drop of a transistors, and assume that the base and the emitter are at the same potential. This is an approximation of course, but will simplify what follows and is good enough for a basic understanding. So, the emitter of Q1 is at the same potential as INA. The same goes for Q2 and INB.

Let’s name things a little: let’s call the voltage at the common node of R1 and R2 (the top end of the current source) Vc. With that, the current flowing through R1 is:

I1 = (INA-Vc)/Rfb

Similarly, the current through R2 is:

I2 = (INB-Vc)/Rfb

Now, these currents flow through R14 and R13 respectively, dropping some voltages. So, the output voltages become:

CA = V+ – Rt*I1 = V+ – (INA-Vc)*Rt/Rfb

CB = V+ – Rt*I2 = V+ – (INB-Vc)*Rt/Rfb

With these, the differential output voltage can be written as:

Vdiff_out = CB-CA = (INA-INB)*Rt/Rfb

From this, we can see that the differential gain of our amplifier is Rt/Rfb. With the values, I have set, it’s 80.

Now, there are several approximations in this calculation: Vbe is non zero, some of the emitter current comes from the base, it doesn’t purely flow through the emitter, all of these things are temperature dependent, etc. In simulation, the differential gain sits between 50 and 60:

Let’s now look at the common mode behavior. We’ve said that the common mode rejection is infinite. That is of course only true as long as the components in the two branches of the amplifier are truly identical. Even ignoring that, there is an obvious problem: the emitters of the two transistors have to sit at a potential higher than V-, and (in a pure common mode input scenario) will have to sit below 6V or so. As the common mode input changes (again, ignoring Vbe for now), the emitter voltages also are the same as the common mode input. So, we should assume that the common mode input voltage range is somewhere between V- and 6V in this case. This is more or less validated by the simulation:

You see how the common mode output voltage starts deviating from 6V as the input common mode goes beyond it. What you don’t see is the limitation around -12V, because the current source is ideal and it actually can drop to negative voltages.

So, we can say the following:

  1. The common mode output set-point is determined by the current source and Rt
  2. The gain is determined by the ratio of Rt and Rfb
  3. The input voltage range is determined by – on the low end – V- and – on the high end – by the common mode output voltage
  4. Realistic component models deviate from this ideal model, reducing gain and making it temperature dependent

Another thing to notice is that we can’t really set this amplifier up to have 0V common mode output: this is because of point #3 above: that would severely limit input voltage range. So, how do deal with that?

Two-stage diff-amp

My idea right now is to add a second, complementer stage to the amplifier. This will have opposite behavior, but now need to only worry about a single common-mode input voltage set-point: the output of stage-1. It would also increase gain quite a bit. So, let’s see how it would work!

I set the common mode output to ~0V on the second stage and the gain to ~1. So, what does the transfer function look like now?

Pretty neat! The gain further reduced somewhat and the common mode offset isn’t exactly 0, but close enough, I think.

There’s a problem though: if you look at the common-mode equation above, you see that it depends on the supply voltage. That’s unavoidable if you want the output common-mode to be zero, but maybe it’s more important to be supply-independent? To do that, we need to operate the second stage from ground, instead of V-.

Another change to make is to equalize the gain between the stages. The idea is that higher gain results in lower bandwidth (we’ll come back to that in a minute), so we should have as low gain in each stage as possible, while leaving the overall gain unchanged. Lastly, in order to minimize temperature-dependence in the design, I need to set the current to be identical in the two stages. I ended up parametrizing a lot of things in the simulation so I can easily adjust and experiment with various things. This is how it looks after all of these changes:

The DC transfer function is as follows:

You can see almost no temperature dependency (in fact, you have to take my word for it that this is a temperature sweep from -25 to 125C), but you can also see rather limited output swing: we can only go down to 0 (well, d’uh) and only up to about twice the common-mode output. This is not necessarily a problem for my application, but worth keeping in mind.

You can also see that the output common-mode only depends on the settings for the second stage (again, d’uh), but the common-mode output of the first stage does play a role: the second stage can’t operate beyond the common mode of the first stage: you will quickly drive the second stage into saturation. You can see that, if I try to set the second-stage common mode output to 5.5V:

Again, not a problem for me, here, but there are limitations, especially since the first stage common mode output does depend on the supply voltage level.

Frequency response

Yes, frequency response. But before looking that, we have to settle on the gain we actually need from the amplifier!

For the core memory sense amplifier application, we need to be able to detect a ~30mV differential input pulse. On the output, I will have a common-collector stage as the comparator (I think at least), so I want the differential output to be able to clearly turn the comparator on for such an input. That means an output voltage of about 0.6V (one Vbe drop). So, that would make a gain of 20. However, I also want the threshold to be adjustable, which means extra gain headroom. I settled for a gain of 40, which you see above.

Let’s look at the (normalized) frequency response:

The -3dB point is at around 4.3MHz. Not stellar. Can we improve on this?

As it turns out, we can. By adding an emitter follower stage between the two differential pairs, we can greatly improve the bandwidth to about 27MHz:

In fact, for some reason the gain increased by 3dB that I can’t really explain (other than the vague notion that stage 2 loaded stage 1 down, but that’s not really satisfactory an answer). At any rate, adjusting for that, one sees close to 30MHz of bandwidth:

The price to pay for it is the gain being somewhat temperature-dependent and some rather minimal peaking around the corner frequency.

Is this good enough though? I believe so. A 30MHz bandwidth corresponds to about 12ns rise-time (according to this article). That’s plenty fast, though I should validate it with the real core memory once I have actual HW.

Now, let’s look at another parameter, we can change: the current through the differential stages. Intuition would say that higher currents would increase bandwidth, the rationale being that we have more “oomph” so to say to charge and discharge any stray capacitors that limit our agility. In this run, I’m changing the current sources from 5mA to 20mA:

We can certainly trade power for bandwidth, however the peaking gets worse and worse. In fact, I tend to think that a somewhat lower bandwidth and lower power consumption might be a better tradeoff. A 7mA current setting allows for 23MHz of bandwidth (15ns rise-time) and a power consumption of only 250mW. It also results in an almost completely flat frequency response:

From diff amp to sense amp

Let’s take stock of where we are at this point:

We have a differential amplifier with a gain of 40, an output offset of 0.6V, a rise time of 15ns and power consumption of 250mW. Its input-referenced differential range is 30mV, after which it saturates.

Now, to get from this circuit to a sense amp, we need to do two things: we need to generate the absolute value of the output voltage and the threshold it at a programmable level. The first thing is easy: use a pair of emitter followers that dump their output onto the same load resistor: this effectively selects the larger of the two output values (as the other transistor simply turns off). We have to be careful about temperature dependency, so we need another emitter-follower to remove it. In fact, I will do a variation of this, where I start with PNP followers, and a single NPN to undo the temperature effects:

This will select the minimum (instead of the maximum) of the two outputs (OA and OB), so the DC transfer function looks like this:

Here, I have to explain something else: when I first plotted this curve, I realized that I want the ~30mV case to sit at the 0.6V threshold. That means that the common mode offset should be twice of that, 1.2V. That’s why the peak is at that level and that’s why the input range changed to +/-60mV.

Notice that we have to run these emitter followers between the positive and negative supplies, otherwise our 0.6V (or 1.2V) offset would not be sufficient to get a linear response out of them.

Now, we can threshold this with a high-gain NPN stage:

And get something that starts to resemble a sense amplifier:

Now, the problem is that the threshold voltage is temperature dependent, so we have a rather wide detection range. We can fix that by removing the temperature compensation of the output:

The downside of this is that the common mode offset is now back to about 0.6V with it’s associated input swing reduction.

Notice how the bottom of the ‘tub’ is at almost 0V. That tells me that Q10 enters saturation, which might be a speed issue, once we start looking at time-domain responses. I’ll stow that away for later. At this point we still have bigger fish to fry.

Real life current sources

Next, let’s remove the last non-realistic part of our design: the current sources. These so far have been ideal ones, but of course that’s not something that DigiKey carries.

We need real current sources. The canonical way of dealing with these is using current mirrors.

The problem with them is this: the reference current is normally set by a resistor. A resistor towards a supply voltage:

Now, the reference current is (V+ – Vbe)/R_ref. Clearly, dependent on the voltage supply. If I used this reference current as the current for the differential stages, their common-mode offset would depend on the voltage supply. Not ideal. At all. And if that’s not what I want to do, I’m back to square one: I need a current source (in place of R_ref).

Not exactly square one though. All I need is a stable voltage reference. A Zener diode can do the trick. However, there are secondary problems: the Zener voltage itself is temperature as well as bias current dependent and the current mirrors Vbe drop also is temperature dependent. To compensate these things, a slightly more complex circuit is needed:

Here, Q12 offsets the Vbe drop of Q11 and the resistors R10 and R_iset are adjusted to cancel out most of the remaining temperature dependency. The result is that the current over R_load is precise to about 0.1%:

That is, at lest up to 100C. After that, the curve goes crazy, I’m not sure if I can trust the models at that point. At any rate, if I can boil water on this thing, without breaking, that’s good enough for me.

The trouble with it though that the potential on ‘top’ depends on V+ not just on the zener voltage. That’s because the resistor values R10 and R_iset are very close to each other. In other words, I have excellent temperature dependency, but very bad supply dependency, which was the reason to have zener to begin with. So, let’s see a different structure, courtesy of this article:

You see a similar compensation technique: Q2 adds to the zener reference drop the same amount as Q1 will take up. R1 sets the bias current for the Zener, but now Q1 draws almost no current away from that node, making it much less dependent on supply voltage. This keeps the emitter voltage a constant step away from V+, thus the current through R2 should be constant as well. At least in theory. As you can see, practice is quite a bit different:

Here the various lines correspond to various supply voltages between 8 and 16V. The dependency on supply voltage comes from the Vbe drop of Q2 as well as the Zener being current-dependent: as the supply voltage changes, the bias current through the zener changes, which in turn changes Vbe as well as the zener drop. Not by much, but it adds up to about 100mV. Since the zener voltage is set at 6.2V though, that’s close to a 2% change. This directly translates to a 2% change in current set-point. Now, realistically, I shouldn’t expect a 100% change in supply voltage (from 8V to 16). More like 10%.

The temperature dependency however is rather poor: close to 10% and that’s just up to 100C. The simplest fix seems to be to change the zener voltage and through it its temperature coefficient. As it turns out, a 4.7V zener neatly cancels out the temperature dependency of the Vbe difference between Q1 and Q2, leaving us with only about 3uA of temperature variability. So, let’s plot the current curves over temperature for the min/typ/max supply settings of 10/12/14V:

As it turns out, at the extreme edges of the supply range, we see about 12uA temperature dependence, at nominal, we only see the 3uA. The dependency on supply voltage is much more pronounced, about 80uA from the two edges. Given, that the set-point current is 7mA, this means that we have about 1% accuracy, dominated by supply voltage. Temperature plays only a 0.2% role, much less if the supply voltage is closer to nominal.

I’m not happy with 1% accuracy, but maybe that’s acceptable. Let’s move on though. Let’s say that this is the current source I’m going to use. At least for the second stage. The first stage is much less sensitive to the current setting because it’s common mode output will be removed by the second stage. Maybe a single resistor is sufficient?

Replacing the first current source with a simple resistor, I see almost no dependency on the supply voltage, which is not surprising, but still reassuring:

So, on to the second current source. Let’s replace that with our contraption from above:

The DC sweep is … interesting: the circuit doesn’t work at all below 11V, but is very stable above. Even up to 22V:

Honestly, that’s an easy fix: the 12V was a rather arbitrary supply voltage anyways, if it needs to be higher, well, be it.

By the way: you can see how the supply voltage ends up not affecting the threshold voltage almost at all. So, all this trepidation about the current supply stability was for nothing (much). It works.

Adjusting threshold voltage

Now, to the fun stuff! How to adjust the threshold voltage? We have essentially two knobs: we can adjust the gain or the common mode offset. The first depends on tightly matched resistors, so adjusting that is a no-go. But the offset depends exclusively on the current through the second amplifier stage. And that is set by R19. Let’s do this: change the power supply to 15V and then vary R19 to see how the threshold voltage moves!

OK, this is pretty neat. Going below 20mV threshold is a struggle (the current through the stage is dropping to about 2mA), but if I need to, at that point, I can change the gain to something different. Going above 60mV is also a struggle (again, the current becomes really high, around 16mA). This is a close to a 4:1 range. That’s enough. Once I have real HW, I can see what the pulses I need to detect actually look like and I can set the gain such that it sits at the center of this 4:1 range.

What needs to happen then is this: I have to have a ~300 fixed resistor in series with a ~2k trimmer in place of R19 in the final design. Or maybe, because the behavior is inversely proportional to R19, it should be a parallel configuration? I’ll have to think about that.

Dynamic performance

We only briefly looked at how this circuit behaves over time and even then, only in the frequency domain. So, let’s switch gears and look at how it would work in the time domain!

Well, in one word: poorly.

This is what I alluded to way way up towards the top: the comparator transistor, Q10 goes into saturation and doesn’t have time to recover. So, let’s fix that with the usual Schottky trick…

Much better. The output voltages could be nicer, but at least the responses are sharp and well defined. The circuit now looks like this:

To deal with the non-ideal output, let’s add an inverter stage: this will clean a lot of the imperfections up:

With the schematic being:

Common mode behavior

While common mode rejection in general is hard to simulate as it is chiefly a function of component mismatches, there’s one thing we can look at: what transients should we expect to see if we abruptly change the common mode on the input?

For this test, I drove both inputs with the same, 6V pulse train:

What you don’t see, but have to believe me on, is that OA and OB still moves in tandem, that is, no common-mode-to-differential conversion is talking place. However the output common mode does jump around a little as the input common mode changes. The transient takes about 50ns to settle on OA and OB and the amplitude is rather large at around 200mV.

The subsequent stage converts this pulse into a single-ended signal as you can see on ‘sense_out’, but luckily it’s not quick enough to follow it: the amplitude is reduced and the whole transient is shortened. This short wiggle is not enough to kick the output into changing (the amplitude alone should still be able to do it), so it is in effect benign. This, again you have to believe me as I’m not showing the final output trace.

The whole argument holds up across temperature as well with slight variations in exact curve shapes and offsets but no change in outcome.

Another thing that works in our favor is the rise- and fall-time of the common-mode change: in the simulation I’m using a very aggressive 1ns setting. Almost immediate. In reality, the common mode change is the result of the current ramp on the X and Y select wires coupling through the core rings as tiny transformers. I’m lucky if I can keep the rise and fall times of the current at 50ns. Changing the simulation to this more gentle excitation, the signal on OA and OB reduces in amplitude significantly to about 20mV. The transient on sense_out is not detectable and of course the output is still stable.

In closing

By looking at the response more closely, we can deduce the following:

  • The minimum pulse with on the input to get a reliably detection from the output is 90ns.
  • The detection delay is 55ns
  • The detection precision (over temperature) is better than 2mV.

Overall the design uses 13 transistors, one zener and one diodes plus a grab-bag of resistors. This is compared to my old design (based on the Motorola sense amplifier) that used 19 transistors, 4 diodes and no zeners. So, this is a cheaper design, with similar, or at least acceptable performance. It does need a higher operating voltage of +15V (the negative can stay at -12 or something similar, it’s not that important).

I think the most important learning from this exercise is that I much better understand how these circuits work, what tradeoffs to take into account and what performance to expect from them.

What’s left is that I need to undo all the automation and write in the various component values. After that, I can start looking into tweaking them to reduce the number of different resistors needed. This is important: I will replicate this circuit many times, fewer kinds of components not only reduces cost (higher volume for the remaining ones), but simplifies “inventory management” and assembly.

But all of that will have to wait for another day. Till then, sleep well, if you are not already…