Reverse-engineering the flag circuits in the 8085 processor

Processors all have status flags to keep track of conditions such as a zero value, a carry, or a negative value. Whenever you write a loop or conditional, these flags ultimately are in control. But how are these flags implemented in the chip's silicon? I've reverse-engineered the flag circuits in the 8085 microprocessor and explain what is really going on.

The photograph below is a highly magnified image of the 8085's silicon, showing the relevant parts of the chip. In the upper-left, the arithmetic logic unit (ALU) performs 8-bit arithmetic operations. The status flag circuitry is below the ALU and the flags are connected to the data bus (indicated in blue). To the right of the ALU, the control PLA decodes the instructions into control lines that control the operations of the ALU and flag circuits.

Photograph of the 8085 chip showing the location of the ALU, flags, and registers.

The 8085 has seven status flags.
  • Bit 7 is the sign flag, indicating a negative two's-complement value, which is simply a byte with the top bit set.
  • Bit 6 is the zero flag, indicating a value that is all zeros.
  • Bit 5 is the undocumented K (or X5) flag, indicating either a carry from the 16-bit incrementer/decrementer or the result of a signed comparison. See my article on the undocumented K and V flags.
  • Bit 4 is the auxiliary carry, indicating a carry out of the 4 low-order bits. This is typically used for BCD (binary-coded decimal) arithmetic.
  • Bit 3 is unused and set to 0. Interestingly, a fairly large transistor drives the data bus line to 0 when reading the flags, so this unused flag bit doesn't come for free.
  • Bit 2 is the parity flag, which is set if the result has an even number of 1 bits.
  • Bit 1 is the undocumented signed overflow flag V (details).
  • Bit 0 is the carry flag.

The image below zooms in on the flag silicon, showing individual transistors. The large transistors labeled with the flag name drive the flag value onto the data bus. From the data bus, the flag values control the results of conditional jumps, calls, and returns. The complex circuits above these transistors compute and store the flag values.

The silicon that implements the flags in the 8085 microprocessor.

The schematic below shows the flag circuit that is implemented in the silicon above.

Schematic of the flag storage in the 8085 microprocessor.

Schematic of the flag storage in the 8085 microprocessor.

Each flag bit has a latch and control lines to write a value to the latch. Most flags are updated by the same arithmetic instructions and controlled by the arith_to_flags control line. The carry flag is affected by additional instructions and has its own control line. The undocumented K and V flags are updated in different circumstances and have their own control lines.

The bus_to_flags control loads the flags from the data bus for the POP PSW instruction, while the flags_to_bus control sends the flag values over the data bus for the PUSH PSW instruction or for conditional branches.

The circuitry to compute most flag values is straightforward. The sign flag is set based on bit 7 of the result. The auxiliary carry flag is set on the carry out of bit 3. The K and V flags are set based on the top two bits (details). The zero flag is normally set from the alu_zero signal that indicates all bits are zero.

The zero flag has support for multi-byte zero: at each step it can AND the existing zero flag with the current ALU zero value, so the zero flag will be set if both bytes are zero. This is only used for the (undocumented) DSUB 16-bit subtract instruction. Strangely, this circuit is also activated for the 16-bit DAD instructions, but the result is not stored in the flag.

If you look at the chip photograph at the top of the article, the flags are arranged in apparently-random order, not in their bit order as you might expect. Presumably the layout used is more efficient. Also notice that the carry flag C is off to the right of the ALU. Because of the complexity of the carry logic, which will be discussed next, the circuitry wouldn't fit under the ALU with the rest of the flag logic.

The carry logic

The schematic below shows the circuit for the carry flag. The logic for carry is more complex than for the other flags because carry is used in a variety of ways.

Schematic of the carry circuitry in the 8085 microprocessor.

Schematic of the carry circuitry in the 8085 microprocessor.

The value stored in the carry flag

The top part of the circuit computes carry_result, the value stored in the carry flag. This value has several different meanings depending on the instruction:
  • For arithmetic operations, the carry flag is loaded with the value generated by the ALU. That is, alu_carry_7 (the high-order carry from bit 7 of the ALU) is used. (See Inside the ALU of the 8085 microprocessor for details on how this is computed.)
  • For DAA (decimal adjust accumulator), the carry flag is set if the high-order digit is >= 10. This value is alu_hi_ge_10, which is selected by the daa control line.
  • For CMC (complement carry), the carry flag value is complemented. To compute this, the previous carry flag value c_flag is selected by use_carry_flag and complemented by the xor_carry_result control line.
  • For ARHL/RAR/RRC (rotate right operations), bit 0 of the rotated value goes into the carry. In the circuit, reg_act_0 (the low-order bit in the undocumented ACT (accumulator temp) register) is selected by the alu_shift_right control line.
The xor_carry_result control inverts the carry value in a few cases. For subtraction and comparison, it flips the carry bit to be the borrow bit. For STC (set carry), the xor_carry_result control forces the carry to 1. For AND operations, it forces the carry to 0.

Generating the carry input signal

The middle part of the circuit selects the appropriate carry_in value that is supplied to the ALU.
  • The first option is to set the carry in to either 0 or 1, by using carry_in_0 and optionally xor_carry_in. This is used for most instructions.
  • The next option is to use the current carry flag value as an input for additions or subtractions (allowing multi-byte arithmetic). For subtraction, this is inverted to convert borrow to carry; the xor_carry_in control does this.
  • The final option uses the carry latch to temporarily hold the carry for the undocumented LDHI and LDSI instructions. These instructions add a constant to a 16-bit register pair, so they need to add the carry from of the low-order sum to the high-order byte. The carry latch temporarily holds the carry, and this value is selected by the use_latched_carry control line. You might wonder why not just use the normal carry flag; the LDHI and LDSI instructions are designed to leave the carry flag unchanged, so they need somewhere else to temporarily store the carry. The surprising conclusion that Intel deliberately included circuitry in the 8085 specifically to support these undocumented instructions, and then decided not to support these instructions. (In contrast, the 6502's unsupported instructions are just random consequences of unsupported opcodes.)

    Generating the shift_right input signal

    Each bit of the ALU has a shift right input. For most of the bits, the input comes from the bit to the left, but the high-order bit uses different inputs depending on the instruction. The bottom circuit in the schematic below generates the shift right input for the ALU. This circuit has two simple options.
    • Normally the carry flag is fed into shift_right_in. For the ARHL and RAR instructions, this causes the carry flag to go into the high-order bit.
    • For the RRC and RLC instructions (rotate A left/right), the rotate_carry control selects bit 0 as the shift right input.

    Conclusions

    By reverse-engineering the 8085, we can see how the flag circuits in the 8085 actually works at the gate and silicon level. One interesting feature is the circuitry to implement undocumented instructions and flags. Another interesting feature is the complexity of the carry flag compared to the other flags.

    This information is based on the 8085 reverse-engineering done by the visual 6502 team. This team dissolves chips in acid to remove the packaging and then takes many close-up photographs of the die inside. Pavel Zima converted these photographs into mask layer images, generated a transistor net from the layers, and wrote a transistor-level 8085 simulator.

    Footnotes on rotate

    I recommend you skip this section, but there are few confusing things about the rotate logic that I wanted to write down.

    For some reason the rotate operations are named very strangely in the 8080 and 8085. RRC is the "rotate accumulator right" instruction and RAR is the "rotate accumulator right through carry" instruction. Based on the abbreviations, the names seem reversed. The left rotates RLC and RAL are similar. The Z-80 processor has a similar RRC instruction, but calls it "rotate right circular", making the abbreviation slightly less nonsensical.

    Bit 0 of ACT is fed into shift_right_in for both RRC and RLC. However, this input is just ignored for RLC since the rotation is the other direction, so I assume this is just a result of the control logic treating RRC and RLC the same.)

    To reduce the control circuitry, the rotate_carry and use_latched_carry control lines are actually the same control line since the instructions that use them don't conflict. In other words, there is just one control line, but it has two distinct functions.

  • Twelve tips for using the Rigol DS1052E Oscilloscope

    In this article I share a few tips I've learned about using the Rigol DS1052E oscilloscope.

    The Rigol DS1052E digital oscilloscope.

    The Rigol DS1052E digital oscilloscope.

    Push the knobs

    The knobs all have convenient actions if you push them: pushing Vertical Position or Horizontal Position centers the trace vertically or horizontally. Pushing Tigger Level sets it to zero. Pushing Scale sets it to fine adjust mode.

    Long Memory

    If you don't use Long Memory, you're wasting most of the capacity of the oscilloscope. Long Memory stores 64 times as much data, so you can really zoom in on the waveform. To enable Long Memory, push the Acquire menu button, then select MemDepth to set Long Mem. There's additional documentation here.

    The Long Memory depth option of the Rigol DS1052E oscilloscope.

    The Long Memory depth option of the Rigol DS1052E oscilloscope.

    Use zoom

    Once you've recorded a waveform, you can pan across it using the horizontal position knob - the waveform window indicator at the very top of the screen shows where you are. In mid-range settings, however, the pan range is fairly limited (about a factor of 5) compared to how deep you can zoom with the horizontal scale knob (about a factor of 1000 with Long Memory). Note: zoom works best with Single triggering; if you use Auto or Norm triggering and hit Run/Stop, sometimes the detailed data isn't in memory and zoom doesn't show more than is on the display.

    Pushing the horizontal scale knob turns on the cool zoom mode, which lets you see the trace and a zoomed-in version at the same time, letting you zoom and pan.

    The zoom feature of the Rigol DS1052E oscilloscope.

    The zoom feature of the Rigol DS1052E oscilloscope.

    Using the menus

    Most of the menu buttons are in the group of 6 at the top. However, there's also a trigger menu button under the trigger knob and a time base menu under the horizontal position knob. This is in addition to the four vertical menu buttons: CH1, CH2, MATH, and REF. Among other things, the time base menu lets you select X-Y mode.

    The menus hide about 1/6 of the display, so close the menu when you're done: push the round Menu On/Off button or push a menu button a second time.

    Don't press Auto

    The Auto button is right next to the Run/Stop button, so you might think it will set the trigger to Auto Sweep. Instead this button sets the controls to seemingly-random values to aotomatically display your traces. This is good if you're totally lost, but more likely to wipe out the settings you want.

    Screenshots

    Some oscilloscopes make screenshots easy, but the Rigol is more complicated. To take a screenshot on the Rigol, plug a USB drive into the front panel, then hit the Storage menu button, select Bit map under Storage, select External, New File, and Save. This will save NewFile0.bmp to your flash drive. (It's much easier to rename the file on your computer than on the oscilloscope.)

    An alternative is to run the slightly clunky UltraScope software on your computer, which gives you access to the oscilloscope via USB. You can download "UltraScope for DS1000E" from the Rigol Software Applications page; although it has a PDF icon, it's actually a Zip file with the software.

    Built-in help

    If you hold down a button or knob for three seconds, the oscilloscope displays a help screen explaining its action. (I was surprised when I discovered this by accident.)

    The built-in help feature of the Rigol DS1052E oscilloscope is triggered by holding down a button or knob.

    The built-in help feature of the Rigol DS1052E oscilloscope is triggered by holding down a button or knob.

    Triggering

    The three trigger sweep modes are Auto, Normal, and Single. Auto will keep displaying traces until you hit Run/Stop. Normal will display a trace every time the trigger condition is satisfied. Single will display a single trace when triggered and then stop. Auto is the way to see a waveform without worrying about triggering. But if you want a nice, stable waveform, set up the trigger and use Normal. Also make sure you're triggering from the right channel - the oscilloscope likes to default to using Channel 2 as the trigger.

    Controlling the channels

    If you've used an oscilloscope with separate controls for each channel, you may expect the knobs near CH1 to control channel 1, and the knobs near CH2 to control channel 2. Instead, if you hit CH1, the knobs control channel 1's scale and position, while if you hit CH2, Math, or Ref, the same knobs control that channel's scale and position. Make sure you're controlling the trace you think you're controlling.

    Use the colored probe rings

    Maybe this is too obvious to mention, but putting matching colored rings on both ends of the oscilloscope probes lets you easily tell which probe goes with which channel.

    Label oscilloscope probes with colored rings that match the trace colors.

    Label oscilloscope probes with colored rings that match the trace colors.

    Cursors

    The cursors are very handy to measure voltages, times between two points, frequency, etc. (The Measure mode provides lots of automated measurements, but often doesn't measure what you want.) Manual mode lets you position two cursors (either vertical or horizontal), and the positions and difference are displayed. Track lets you position a cursor along the waveform, and a voltage cursor automatically tracks the waveform. Both time and voltage values are displayed. Auto mode is the mode you should use with Measure, in order to see what the measurements mean.

    A tracking cursor puts X-Y lines on the waveform and gives measurements.

    A tracking cursor puts X-Y lines on the waveform and gives measurements.

    Finding the manual

    Search for DS1000E (not DS1052E) to find the user's guide and other documentation.

    Conclusions

    I'm glad I bought the Rigol DS1052E - it performs very well for a low-price ($329) oscilloscope. (If money is no object, there's Agilent's $439,000 Infiniium oscilloscope. :-) I hope you find these tips useful. If you have any additional oscilloscope tips, please leave a comment.

    The Mili universal car/wall USB charger, tested in the lab

    I received a Mili universal USB charger for review from Mobile Fun. This interesting charger has some features that make it my current favorite travel charger. It runs off both wall power and car accessory power. It comes with swappable plugs for Europe, UK, US, or Australia, and runs on 120 or 240 volts. It has two USB outputs - I thought this was pointless until I discovered how useful it is in car trips if two people can charge at the same time. In addition, one of the ports provides 10 watts for charging tablets (when plugged into AC). The charger also lights up - red indicates charging, and green indicates the devices are charged.

    The charger has a few disadvantages. It is a bit expensive with a list price of $49. Measuring about 2 3/4 inches by 2 1/4 inches, it's much larger than Apple's super-compact inch-cube charger - although it has much more functionality. Finally, due to the design, it ends up blocking both outlets when you plug it into the wall.

    In the remainder of this article, I test the performance of the charger both in the car and with AC power. To summarize, the power quality is excellent in the car, but has more noise than the average charger when plugged into the wall.

    The Mili charger with adapters for different countries.

    The Mili charger with adapters for different countries.

    The label shows that when connected to AC, the charger is rated as 2.1A for output 1 and 1A for output 2; that is, it is designed to power an iPad from output 1 and a phone from output 2. When plugged in to a car accessory outlet, it is only rated to provide 1 amp, so charging a tablet will be slower. In the measurements below, I find that the charger's power exceeds these ratings when plugged into the wall, which is good, but provides a bit less than the expected one amp when plugged into a car output, which may make charging slower.

    Label from the Mili charger.

    Label from the Mili charger.

    Apple devices can reject "wrong" chargers with the error "Charging is not supported with this accessory"; Apple uses special proprietary voltages on the USB data pins to distinguish different types of chargers (details). I measured these voltages on the Mili charger and verified that it is configured to appear as an Apple 2A charger on ouput 1, and an Apple 1A charger on output 2.

    Cars: a hostile electrical environment

    You might expect to find 12 volts at your car's accessory outlet, but what comes out can be surprisingly noisy and variable. This voltage will have spikes from the ignition system as well as very large transients due to starting, malfunctions, or jump starting. A car charger must handle this hostile voltage input, and make sure the output to your device is smooth.

    Test setup to measure charger performance in a car.

    Test setup to measure charger performance in a car.
    I measured the voltage in my car to see what happens in a real-world environment using the setup illustrated above. The Mili charger is plugged in just to the left of the gear shift. Above it is the USB interface board, which is connected to the oscilloscope on the dash.

    Car voltage drops and rises when the car is started. Car voltage at idle showing ignition spikes.

    Car voltage drops and rises when the car is started (left). Car voltage at idle showing ignition spikes (right).

    The oscilloscope trace (yellow) on the left shows the large voltage fluctuations when I started the car. At the very left, with the ignition off, the battery provides about 12.5 volts. The starter pulls the voltage down to 8.88 volts until the engine starts. The voltage gradually rises over 6 seconds, settling around 14 volts.

    On the right, zooming in shows that while the car is idling, the accessory output has 1/2 volt spikes every 28 milliseconds, due to the ignition firing. Note the voltage on the left is much noisier with the car running than on battery - the line on the left is thin, and the line on the right is thick.

    Performance of the Mili charger in a car

    The Mili charger has a plug that folds out from the side for use in a car. While this makes the charger larger than a dedicated wall charger, having a charger that works both in the car and with AC is more convenient than I expected, especially when traveling.

    The Mili USB charger with car adapter.

    The Mili USB charger with car adapter.
    I looked at the output of the Mili charger while starting the car, to see if the large voltage fluctuations shown above affected the charger's output. The Mili output remained steady, which is good. I also didn't see any of the ignition spikes in the output from the Mili charger. This indicates that the Mili charger does a good job of filtering out noise from the automotive environment.

    I tested the Mili charger with inputs from 0 to 30 volts. 30 volts may seem excessive, but jump-starts often use 24 volts, and car electrical failures can result in a 120 volt "load dump". Fortunately, the Mili survived 30 volts just fine (unlike some other chargers I'm testing). The image below shows that the Mili generates a stable output voltage (horizontal line) for inputs from 7 volts to 30 volts. This is a good thing, showing that the Mili won't overload your phone even if your car is providing too much voltage. As expected, the Mili can't produce the full output voltage if the input voltage is too low (left side of the graph).

    Output voltage (Y axis) of the Mili charger as the input ranges from 0 to 30 volts (X axis).

    Output voltage (Y axis) of the Mili charger as the input ranges from 0 to 30 volts (X axis).

    The oscilloscope displays below show the output and frequency spectrum with 12V DC input and a 5W load. The power quality is very good - the yellow line is thin and has very few spikes. The high frequency spectrum (orange) shows a spike at the switching frequency, but overall the power quality is among the best of chargers I've looked at.

    High frequency spectrum of the Mili charger with 12V input. Low frequency spectrum of the Mili charger on 12V input.

    High frequency spectrum (left) and Low frequency spectrum (right) of the Mili charger on 12V input.

    Next, I measured the voltage the charger can provide under increasing load (details). The horizontal line shows the voltage drops from about 5 volts to 4.5 volts as the load increases. The vertical line shows the charger maxes out around .9 amps with less than the expected 5 volts. This is slightly less than the rated 1 amp the charger is supposed to provide. Both USB outputs provide the same current when plugged into a car outlet.

    Voltage vs Current for the Mili charger with 12V input.

    Voltage vs Current for the Mili charger with 12V input.

    Charger performance with wall input

    I also examined the performance of the Mili charger when plugged into the wall (120V AC). One minor annoyance with using the Mili as a wall charger is that due to the position of the USB ports, both wall outlets are blocked either by the charger or USB cables.

    The Mili charger.

    The Mili charger.

    The images below show the voltage the charger can provide under increasing load (details). When plugged into the wall, the two USB outputs provide different maximum currents, unlike when plugged into a car outlet. Output 1 (the high current output) is on the left, and output 2 (the low current output) is on the right. Output 1 reaches about 2.45A before the voltage starts dropping, well above the 2.1A rating. The line for output 1 gets fairly wide above 1A, showing the voltage is not too stable. The line also slopes downwards to the right, indicating the voltage drops somewhat as the load increases. Output 2 reaches about 1.1A before the light starts flashing and the power drops and climbs (the curved lines). This graph shows strange behavior under overload that I haven't seen in other chargers. The lines are all fairly wide, showing the voltage is

    Voltage vs current for the Mili charger (output 1) with 120V AC input. Voltage vs current for the Mili charger (output 2) with 120V AC input.

    Voltage vs current for the Mili charger (output 1 left, output 2 right) with 120V AC input.
    I looked at the voltage output along with the high frequency and low frequency spectrums (below), to examine the quality of the power outputs. The yellow line is much wider than when plugged into the car outlet, showing a lot more noise in the output. The large orange spike in the middle of the high frequency spectrum shows that a lot of the charger's switching noise is appearing on the output. Compared to other chargers, the power quality is lower than average. On the positive side, the flat low-frequency spectrum shows the charger is very good at eliminating ripple due to the 60 Hz power lines.

    High frequency spectrum of the Mili charger with 120V AC input. Low frequency spectrum of the Mili charger with 120V AC input.

    High frequency (left) and low frequency (right) spectrum of the Mili charger with 120V AC input.

    Conclusions

    The Mili charger is convenient for travel because it has plugs for multiple countries, works as an auto charger, and has dual outputs. The power quality is very good in the car, but not so good with AC power. This charger is my favorite charger now - while I'd like to tear it apart and examine the circuit inside, I like it too much to destroy it. Hopefully if you get one you'll like it too. And if you found this interesting, check out my detailed analysis of a dozen chargers in the lab.

    Thanks to Mili, Mobile Fun, and Mihnea for providing me with the charger and patiently waiting for the review.

    Teardown and exploration of Apple's Magsafe connector

    Have you ever wondered what's inside a Mac's Magsafe connector? What controls the light? How does the Mac know what kind of charger it is? This article looks inside the Magsafe connector and answers those questions.

    The Magsafe connector (introduced by Apple in 2006) is very convenient. It snaps on magnetically and disconnects if you pull on it. In addition it is symmetrical so you don't need to worry about what side is up. A small LED on the connector changes color to indicate the charging status.

    The picture below shows the newer Magsafe 2 connector, which is slimmer. Note how the pins are arranged symmetrically; this allows the connector to be plugged in with either side on top. The charger and computer communicate through the adapter sense pin (also called the charge control pin), which this article will explain in detail below. The two ground pins are slightly longer than the others so they make contact first when you plug in the connector (the same as USB).

    The pins of a Magsafe 2 connector. The pins are arranged symmetrically, so the connector can be plugged in either way.

    The pins of a Magsafe 2 connector. The pins are arranged symmetrically, so the connector can be plugged in either way.

    Magsafe connector teardown

    I had a Magsafe cable that malfunctioned, burning the power pins as you can see in the photo below, so I figured I'd tear it down and see what's inside. The connector below is an older Magsafe; notice the slightly different shape compared to the Magsafe 2 above. Also note that the middle adapter sense pin is much smaller than the pins, unlike the Magsafe 2.

    A Magsafe connector with burnt pins.

    Removing the outer plastic shell reveals a block of soft waxy plastic, maybe polyethylene, that helps diffuse the light from the LEDs and protects the circuit underneath.

    A Magsafe connector with the plastic case removed. In front is the metal holder of the pins. Behind it is the circuit board encased in plastic. The power cable exits from the back.

    Cutting through the soft plastic block reveals a circuit board, protected by a thin clear plastic coating. The charger wires are soldered onto the back of this board. Only two wires - power and ground - go to the charger unit. There is no data communication via the adapter sense pin with the charger unit itself.

    After removing more plastic, the circuit board inside a Magsafe connector is visible. The power cable is soldered onto the board.

    Disassembling the connector shows the spring-loaded "Pogo pins" that form the physical connection to the Mac. The plastic pieces hold the pins in place. The block of metal on the left is not magnetized, but is attracted by the strong magnet in the Mac's connector.

    The spring-loaded 'pogo pins' inside a Magsafe connector.

    The circuit board inside the Magsafe connector is very small, as you can see below. In the middle are two LEDs, orange/red and green. Two identical LEDs are on the other side. The tiny chip on the left is a DS2413 1-Wire Dual Channel Addressable Switch. This chip has two functions. It switches the status LEDs on and off (that's the "dual channel switch" part). It also provides the ID value to the Mac indicating the charger specifications and serial number.

    The circuit board inside a Magsafe connector is very small. There are two LEDs on each side. The chip is a DS2413 1-Wire switch.

    The chip uses the 1-Wire protocol, which is a clever system for connecting low-speed devices through a single wire (plus ground). The 1-Wire system is convenient here since the Mac can communicate with the Magsafe through the single adapter sense pin.

    Understanding the charger's ID code

    You can easily pull up the charger information on a Mac (Go to "About this Mac", "More Info...", "System Report...", "Power"), but much of the information is puzzling. The wattage and serial number make sense, but what about the ID, Revision, and Family? It turns out that these are part of the 1-Wire protocol used by the chip inside the connector.

    Every chip in the 1-Wire family has a unique 64-bit ID that is individually laser-programmed into the chip. In the 1-Wire standard, the 64-bit ID consists of an 8-bit family code identifying the type of 1-Wire device, a 48-bit unique serial number, and an 8-bit non-cryptographic CRC checksum that verifies the ID number is correct. Companies (such as Apple) can customize the ID numbers: the top 12 bits of the serial number are used as a customer ID, the next 12 bits are data specified by the customer, and the remaining 24 bits are the serial number.

    With this information, the Mac's AC charger information now makes sense and the diagram below shows how the 64-bit ID maps onto the charger information. The ID field 100 is the customer ID indicating Apple. The wattage and revision are in the 12 bits of customer data (hex 3C is 60 decimal, indicating 60 watts). The Family code BA is the 1-Wire family code for the DS2413 chip. Thus, much of the AC charger information presented by the Mac is actually low-level information about the 1-Wire chip.

    The 1-Wire chip inside a Magsafe connector has a 64-bit ID code. This ID maps directly onto the charger properties displayed under 'About this Mac'.

    The 1-Wire chip inside a Magsafe connector has a 64-bit ID code. This ID maps directly onto the charger properties displayed under 'About this Mac'.

    There are a few complications as the diagram below shows. Later chargers use the family code 85 for some reason. This doesn't indicate an 85 watt charger. It also doesn't indicate the family of the 1-Wire device, so it may be an arbitrary number. For Magsafe 2 chargers, the customer ID is 7A1 for a 45 watt charger, 921 for a 60 watt charger, and AA1 for an 85 watt charger. It's strange to use separate customer IDs for the different models. Even stranger, for an 85 watt charger the wattage field in the ID contains 60 (3C hex) not 85, even though 85 watts shows up on the info screen. The Revision is also dropped from the info screen for later chargers.

    In a Magsafe 2 connector, the 64-bit ID maps onto the charger properties displayed under 'About this Mac'. For some reason, the 'Customer data' gives a lower wattage.

    In a Magsafe 2 connector, the 64-bit ID maps onto the charger properties displayed under 'About this Mac'. For some reason, the 'Customer data' gives a lower wattage.

    How to read the ID number

    It's very easy to read the ID number from a Magsafe connector using an Arduino board and a single 2K pullup resistor, along with Paul Stoffregen's Arduino 1-Wire library and a simple Arduino program.

    The circuit to access a 1-Wire chip from an Arduino is trivial - just a 2K pullup resistor.

    The circuit to access a 1-Wire chip from an Arduino is trivial - just a 2K pullup resistor.

    Touching the ground wire to an outer ground pin of the Magsafe connector and the data wire to the inner adapter sense pin will let the Arduino immediately read and display the 64-bit ID number. The charger does not need to be plugged in to the wall - and in fact I recommend not plugging it in - since one interesting feature of the 1-Wire protocol is the device can power itself parasitically off the data wire, without a separate power source.

    The 64-bit ID can be read out of a Magsafe connector by probing the outer pin with ground, and the middle pin with the 1-Wire data line.

    The 64-bit ID can be read out of a Magsafe connector by probing the outer pin with ground, and the middle pin with the 1-Wire data line.

    To make things more convenient, the serial number can be displayed on an LCD display. The circuit looks complicated, but it's just a tangle of wires connecting the LCD display. Using a simple program, the 64-bit ID number is displayed on the bottom line of the display. The top line is a legend indicating the components of the code: "cc" CRC check, "id." customer id, "ww" wattage, "r" revision, "serial" serial number, and "ff" family. The number below corresponds to an 85 watt charger (55 hex = 85 decimal).

    A 1-Wire ID reader with LCD display. Touching the wires to the contacts of the Magsafe connector displays the ID code on the bottom line of the display. The top line indicates the components of the code: CRC check, customer id, wattage, revision, serial number, and family.

    A 1-Wire ID reader with LCD display. Touching the wires to the contacts of the Magsafe connector displays the ID code on the bottom line of the display. The top line indicates the components of the code: CRC check, customer id, wattage, revision, serial number, and family.

    Controlling the Magsafe status light

    The Mac controls the status light in the Magsafe connector by sending commands through the adapter sense pin to the 1-Wire DS2413 switch IC to turn the two pairs of LEDs on or off. By sending the appropriate commands to the IC through the adapter sense pin, an Arduino can control the LEDs as desired.

    The picture below demonstrates the setup. The same simple resistor circuit as before is used to communicate with the chip, along with a simple Arduino program that sends commands via the 1-Wire protocol. These commands are described in the DS2413 datasheet but should be obvious from the program code.

    I used a cable removed from a dead charger for simplicity. The LEDs are normally powered by the charger's voltage, which I simulated with two 9-volt batteries. To hook the Arduino to the connector, this time I used a Mac DC input board that I got on eBay; this is the board in a Mac that the Magsafe connector plugs into. The only purpose of the board here is to give me a safer way to attach the wires than poking at the pins.

    The connector contains a pair of orange/red LEDs and a pair of green LEDs, which can be switched on and off independently. When both pairs are lit, the resulting color is yellow. Thus, the connector can display three colors. The Arduino program cycles through the three colors and off, as you can see from the pictures above.

    The charger startup process

    When the Magsafe connector is plugged into a Mac, a lot more happens than you might expect. I believe the following steps take place:
    1. The charger provides a very low current (about 100 µA) 6 volt signal on the power pins (3 volts for Magsafe 2).
    2. When the Magsafe connector is plugged into the Mac, the Mac applies a resistive load (e.g. 39.41KΩ), pulling the power input low to about 1.7 volts.
    3. The charger detects the power input has been pulled low, but not too low. (A short or a significant load will not enable the charger.) After exactly one second, the charger switches to full voltage (14.85 to 20 volts depending on model and wattage). There's a 16-bit microprocessor inside the charger to control this and other charger functions.
    4. The Mac detects the full voltage on the power input and reads the charger ID using the 1-Wire protocol.
    5. If the Mac is happy with the charger ID, it switches the power input to the internal power conversion circuit and starts using the input power. The Mac switches on the appropriate LED on the connector using the 1-Wire protocol.

    This process explains why there is a delay of a second after you connect the charger before the light turns on and the computer indicates the battery is charging. It also explains why if you measure the charger output with a voltmeter, you don't find much voltage.

    The complex sequence of steps provides more safety than a typical charger. Because the charger is providing extremeley low current at first, there is less risk of shorting something out while attaching the connector. Since the charger waits a full second before powering up, the Magsafe connector is likely to be firmly attached by the time full power is applied. The safety feature are not foolproof, though, as the burnt-up connector I tore apart shows.

    Don't try this at home

    Warning: I recommend you don't try any of these experiments. 85 watts is enough to do lots of damage: blow out your Mac's DC input board, send flames out of a component, blow fuses, or vaporize PC traces, and that's just the things I've had happen to me. The Mac and charger both have various protection mechanisms, but they won't take care of everything. Poking at your charger while it's plugged in is a high-risk activity.

    Reading your charger's ID by probing the pins while it's not plugged in is considerably safer, but I can't guarantee it. If you mess up your charger, computer or Arduino you're on your own.

    Conclusions

    There's more to the Magsafe charger connector than you might expect. The center pin of the connector - the adapter sense pin - controls a tiny chip that both identifies the charger and controls the status LED. It is part of a complex interaction between the charger and the Mac. Using an Arduino microcontroller, this chip can be accessed and controlled using the 1-Wire protocol. Is this useful? Not really, but hopefully you found it interesting.

    Tenma 72-7740 multimeter: review and teardown

    The Tenma 72-7740 digital multimeter is a multimeter in the $70 price range. Overall, it's a nice, solidly-build meter and it has performed well for me. I received this DMM from Newark element14 for review; in this article I describe its functionality followed by a teardown.

    What you get

    What comes in the box with the Tenma 72-7740 DMM: temperature probe, battery, alligator clips, and probes.

    The DMM comes with a temperature probe, battery, alligator clips, and test probes. Note that the test probes have very short metal tips, unlike the long tips on most probes. The alligator clip probes are a nice addition. My biggest complaint with the DMM is the temperature probes connections are soldered with no strain relief so I worry the wires will break off.

    The DMM also comes with a pocket-sized 36 page operating manual - a real, physical manual on paper, not a PDF file like most products these days. The DMM doesn't really need a manual - functions work pretty much as you'd expect - but it's nice to have the manual.

    Specifications

    The DMM is autoranging with maximum reading of 3999. It is full-size (177mm × 85mm × 40mm), not a pocket DMM, and has a built-in stand. The LCD display is large and clear and has a backlight, which is nice if I ever end up using the meter in the dark. It has 10MΩ input impedance and maximum voltages of 1000V DC and 750V AC. The top current range is 10A.

    The DMM also includes capacitance, diode, temperature, frequency, and duty cycle measurements. The top capacitance range (100µF) can take up to 15 seconds to get a measurement, so be patient with those big electrolytics. The lowest capacitance range is 40 nF with 10pF resolution claimed. The DMM also has a continuity buzzer, although I find the sound crackles a bit. The temperature readings are only in °C; I know using Fahrenheit makes me a bad person, but that's what I need to check my appliances. The temperature range is -40°C to 1000°C. The upper range is hotter than I need, but since I sometimes go outside below -40°C my multimeter should be able to handle it too.

    Buttons provide hold and relative mode. The meter goes into sleep mode after 30 minutes.

    I don't have the equipment to measure the accuracy of the DMM myself, so I'm going off the published values. The specification for DC voltage accuracy is a reasonable ±0.8%; the considerably more expensive Fluke 177 has ±0.09% accuracy, so you get what you pay for.

    The function knob has 7 positions: V, resistance/capacitance/diode/continuity, Hertz, °C, µA, mA, and A. The blue function button switches between AC and DC or switches among resistance, capacitance, diode, and continuity.

    There are a few functions found in more advanced multimeters that aren't found here: min/max measurement, RS-232 support, °F, a 4nF capacitance scale, and an analog bar graph.

    For full specifications, see the specification chart.

    Tenma 72-7740 digital multimeter measuring 60Hz line frequency

    Tenma 72-7740 digital multimeter measuring 60Hz line frequency

    Teardown

    Of course I was interested in what was inside the multimeter and opened it up. The instruction manual describes how to remove the screws under the feet. The force required to pry the case apart made me a little nervous, but it snapped open without breaking anything. Note that the case must also be opened in this way to replace the fuses - they are not accessible from the battery compartment. Unfortunately I tend to blow fuses a lot measuring charger performance, but this may motivate me to be more careful.

    Inside the Tenma 72-7740 DMM, showing the foil shield, the two fuses, and the thick wire for high-current measurements.

    A foil shield covers most of the circuit board, with holes for some adjustments. Near the bottom is a thick wavy wire, which is the precision resistor used for the high-current measurements, a fraction of an ohm. There's nothing particularly interesting directly under the foil shield; almost all the components are on the other side.

    Removing the circuit board and flipping it over shows the circuitry. The large LCD display is at the top, with the pushbuttons below. The most visually striking part of the board is the round circuitry for the function knob, which I will explain in more detail below. To the left are three precision (blue) resistors for mA and µA measurement. Below are 5 diodes which I believe are for input protection. The large black cylinder in the lower right appears to be a spark gap to protect the input from high voltages - the DMM is rated to 1000V DC overload protection. Below it is a large yellow PTC resistor to protect from input overloads. The 8-pin IC is a STMicroelectronics TL062C low power J-FET dual op amp.

    The circuit board for the Tenma 72-7740 DMM.

    The circuit board for the Tenma 72-7740 DMM.
    Underneath the LCD is the 100-pin controller IC and a bunch of SMD components. The Semico CS7721CN chip powers the Tenma 72-7740 DMM. I wasn't expecting that a DMM chip would need 100 pins, but that seems to be common. I couldn't find a datasheet for this specific chip, but datasheets for other similar chips (such as the Fortune FS9721 and Cyrustek ES51982) give an idea of how digital multimeters works. The chip has signal inputs for the different functions (voltage, current, resistance, frequency, capacitance, etc.) The four blue precision resistors below the chip divide the input by powers of 10 as appropriate. Six mode pins are connected to the function selector switch to select the appropriate function, as will be displayed below. The function pushbuttons are also connected to the IC. About 17 pins from the IC drive the LCD segments. The crystal provides accurate timing, which is critical for the accuracy of the dual-slope analog-to-digital converter that measures the input.

    The 100-pin Semico CS7721CN chip powers the Tenma 72-7740 DMM.

    The 100-pin Semico CS7721CN chip powers the Tenma 72-7740 DMM.

    How the function selector switch works

    Rotary switches have always been mysterious to me. The pattern on the circuit board seems to be made up of random lines rather than any obvious switch contacts, and looks as much like an Aztec symbol as a switch. So I figured it was time to dive in and figure out how it works.

    The selector knob has 7 positions, rotating a bit under 180 degrees in total. Looking at the back of the selector knob, you can see six independent sliders for six separate switching circuits. Each slider has two peaks in the middle, which bridge two contacts on the circuit board. Note that the two outermost sliders are offset 90 degrees from the others. Since the knob turns a bit under 180°, the sliders n

    The function knob rotates through seven positions and has six independent contacts.

    The following diagram shows how the switches work. Each of the six colored semi-circular rings is associated with one of the sliders. The seven lines inside each semicircle indicate the seven possible positions of the associated slider. The most counterclockwise position in each ring is the V setting, followed by Ω, Hz, °C, µA, mA, and A. If there are two traces lined up with the slider, the slider will connect the two traces.

    This diagram shows the structure of the function switch on the Tenma 72-7740. Each color shows one of the six independent switches, with lines for the seven possible positions. In highlighted positions, a pair of contacts is closed.

    One surprise is that many of the traces don't actually form a circuit. The highlighted positions in the diagram are active positions that close two contacts, but the other positions don't form a connection. In particular, the red ring is only active in one position, and the blue ring in two positions. Many positions have the same circuit trace on both ends of the line, which means the switch does nothing and the trace is unnecessary. My guess is that the redundant metal is there because metal-on-metal is lower friction than metal-on-circuit-board.

    The white, cyan, and blue rings ground various combinations of "mode" pins on the IC to select the function. The left half of the purple ring directs the µAmA°C input to the appropriate circuit based on the function. The right half of the purple ring directs the HzVΩ input appropriately. The red ring has a connection only for the °C setting. The orange ring makes connections for Ω, °C, and A.

    Conclusion

    The 72-7740 DMM is a solid meter that gets the job done and I have only minor complaints. It currently sells for about $70. Inexplicably, the next model up, the 7745, is cheaper despite having true RMS and a serial RS-232 output. The model down, the 7735 is a good deal at about half the price; it also has RS-232, although it lacks temperature measurement, the backlight, and sleep mode.

    The Tenma 72-7740 DMM in the box.

    The Tenma 72-7740 DMM in the box.

    Thanks to Newark element14 for giving me this digital multimeter free for review. (Newark element14 consists of the merger of the well-known Newark electronics distributor and the element14 online electronics community into a single global brand.)

    Wealth distribution in the United States

    Today's Forbes billionaires list inspired me to visualize the wealth inequality in the United States. Use the Forbes list and other sources, I've created a graph that shows wealth distribution in the United States. It turns out that if you put Bill Gates on a linear graph of wealth, pretty much the entire US population is crammed into a one-pixel bar around 0.

    This graph shows the wealth distribution in red. Note that the visible red line is one pixel wide and disappears everywhere else - this is the key point: essentially the entire US population is in that first bar. The graph is drawn with the scale of 1 pixel = $100 million in the X axis, and 1 pixel = 1 million people in the Y axis. Away from the origin, the red line is invisible - less than 1/1000 of a pixel tall since so few people have more than $100 million dollars. It's striking just how much money Bill Gates has; even $100 million is negligible in comparison.

    Since the median US household wealth is about $100,000, half the population is crammed into a microscopic red line 1/1000 of a pixel wide. (The line would be narrower than the wavelength of light so it would be literally invisible). And it turns out the 1-pixel-wide red line isn't just the "99%", but the 99.999%. I hypothesize this is why even many millionaires don't feel rich.

    Wealth inequality among billionaires

    Much has been written about inequality in the US between the rich and the poor, but it turns out there is also huge inequality among the ranks of billionaires. Looking at the 1.9 trillion dollars held by US billionaires, it turns out that the top 20% of billionaires have 59% of this wealth, while the bottom 20% of billionaires have less than 6%. So even among billionaires, most of the money is skewed to the top. (I originally pointed this out in Forbes in 1998, and the billionaire inequality has grown slightly since then.)

    Sources

    The billionaire data is from Forbes billionaires list 2013. Median wealth is from Wikipedia. Also Measuring the Top 1% by Wealth, Not Income and More millionaires despite tough times. Wealth data has a lot of sources of error including people vs households, what gets counted, and changing time periods, but I've tried to make this graph as accurate as possible. I should also mention that wealth and income are two very different things; this post looks strictly at wealth.

    The 8085's register file reverse engineered

    On the surface, a microprocessor's registers seem like simple storage, but not in the 8085 microprocessor. Reverse-engineering the 8085 reveals many interesting tricks that make the registers fast and compact. The picture below shows that the registers and associated control circuitry occupy a large fraction of the chip, so efficiency is important. Each bit is implemented with a surprisingly compact circuit. The instruction set is designed to make register accesses efficient. An indirection trick allows quick register exchanges. Many register operations use the unexpected but efficient data path of going through the ALU.

    While the 8085's register complement is tiny compared to current processors, it has a solid register set by 1977 standards - about twice as many registers as the 6502. The 8085 has a 16-bit program counter, a 16-bit stack pointer, 16-bit BC, DE, and HL register pairs, and the 8-bit accumulator. The 8085 also has little-known hidden registers that are invisible to the programmer but used internally: the WZ register pair, and two 8-bit registers for the ALU: ACT and TMP.

    Photograph of the 8085 chip showing components relevant to register operations.

    Photograph of the 8085 chip showing components relevant to register operations.

    The register file is in the lower left quadrant of the chip. It contains the 6 register pairs and associated circuitry. Underneath the registers is the 16-bit address latch and increment/decrement circuit. The register file is controlled by a set of control lines on the right, which are driven by register control logic circuits and the register control PLA. The current instruction is loaded into the instruction register (upper right) via the data bus. In the upper left is the 8-bit arithmetic-logic unit (ALU), with the accumulator and two temporary registers (ACT and TMP).

    The 8085 has only 40 pins (visible around the edge of the image) to communicate with the outside world, a tiny number compared to current microprocessors with more than 1000 pins. For memory accesses, the 8085 reads or writes 8 bits of data using a 16-bit memory address (for a maximum of 64K of memory). In the image above, memory addresses flow through the 16-bit address bus (abus) provides memory addresses, while data flows through the chip over the 8-bit data bus (dbus). The 8 A pins handle half of the address, while the 8 AD pins are used both for the other half of the address and for data (at different times). This frees up pins for other uses, but makes computers using the 8085 slightly more complicated. In comparison, the 6502 is more straightforward, with separate pins for address and data.

    Overall architecture of the register file

    The diagram below shows the implementation of the 8085 register file in the same layout as on the actual chip. The 8-bit data bus is at the top, and the 16-bit address bus is at the bottom. The register control lines are on the right.

    In the middle are the registers, arranged as pairs of 8-bit registers. Note that the registers are arranged "backwards" with the high-order bit on the right and the low-order bit on the left. The 16-bit program counter and stack pointer are first. Next is the WZ temporary register, and underneath it the BC register pair. The HL and DE register pairs are at the bottom - these registers do not have fixed locations, but can swap roles during execution. A 16-bit register bus (regbus) provides access to the registers.

    Underneath the registers is the address latch, which holds a 16-bit value that is written to the address bus. This value is also the input to the 16-bit increment/decrement circuit. The output of the incrementer/decrementer can be written back to the registers.

    The triangles indicate tri-state buffers, basically switches that control the flow of data. Buffers containing a + are amplifiers to boost the weak signals from the registers. Buffers containing a S are superbuffers, that provide extra current to send data across the long data bus.

    Architecture diagram of the 8085 register file, as it is implemented on the chip. The register file is connected to the data bus at top, and address bus at bottom. The control lines are along the right.

    Architecture diagram of the 8085 register file, as it is implemented on the chip. The register file is connected to the data bus at top, and address bus at bottom. The control lines are along the right.

    The picture below zooms in on the chip image above, showing the register file in detail. The components in silicon exactly map onto the diagram above. Note the repeated patterns for the 16-bit circuits. The large transistors used as high-current drivers are clearly visible. The transistors in each bit of register storage are much smaller.

    A closeup of the 8085 microprocessor, showing the details of the register file and the locations of the major components.

    A closeup of the 8085 microprocessor, showing the details of the register file and the locations of the major components.

    Storing bits in the register file

    The implementation of the 8085 registers is unusual in several ways. The registers don't have explicit read and write modes; instead the register will be overwritten if there is a stronger signal on the bus. Instead of having a bus with one wire for each bit, the 8085 uses a sort of differential bus, with two wires for each bit: one wire transmits the value, and the other transmits the complement of the value.

    Each bit consists of two inverters in a feedback loop, with pass transistors to connect the inverters to the bus. An unusual feature of this is the lack of any circuit to break the feedback loop when modifying the register (unlike the 6502). Instead, the 8085 uses a "might makes right" technique - if a stronger signal is written to the bus, it will overwrite a register connected to the bus. The transistors driving the register bus are about twice as large as the transistors in the inverters, so they can forcibly overwrite the inverter loop.

    One consequence of this register implementation is that a register can't be copied directly to another register, since there's nothing to distinguish the source register from the destination register - each register could potentially damage the other's bits. To get around this, the 8085 uses an interesting trick - copies are actually done through the ALU, as will be explained later.

    One bit of a register in the 8085 register file. Each bit is stored in two inverters in a feedback loop. The register bus uses two lines of opposite polarity for each bit. Access to the register is controlled by the reg_rw control line, which connects the inverters to the bus, allowing the value to be read or written.

    One bit of a register in the 8085 register file. Each bit is stored in two inverters in a feedback loop. The register bus uses two lines of opposite polarity for each bit. Access to the register is controlled by the reg_rw control line, which connects the inverters to the bus, allowing the value to be read or written.
    The image below zooms in on the chip closer, showing the silicon for six individual register bits. The schematic for one bit is overlaid, as are some of the metal lines providing power, ground, and the register bus. Each bit consists of two transistors for the inverters, two depletion pullup transistors for the inverters (shown as resistors), and two pass transistors connecting the bit to the register bus. The pink regions are transistors, with the green strips the gates (details).

    Detail of the 8085 chip showing six bits in the 8085's register file. Bit 2 of the stack pointer is shown with schematic. The two transistors form two inverters in a feedback loop. The light blue lines are the metal layer wires connected to bit 2. The program counter is in the upper half of the image.

    Detail of the 8085 chip showing six bits in the 8085's register file. Bit 2 of the stack pointer is shown with schematic. The two transistors form two inverters in a feedback loop. The light blue lines are the metal layer wires connected to bit 2. The program counter is in the upper half of the image.

    To read a register, an amplifier circuit is used to boost the signal from the differential register bus to write it to the dbus or address latch. I assume this is a tradeoff to make the register file smaller. Each inverter pair can be made as small as possible, but then requires amplification to produce a signal strong enough for use elsewhere in the chip. The amplification circuit that drives the data bus is more complex than I'd expect, probably because of the extra power to drive the bus (details and schematic).

    The incrementer/decrementer

    The 16-bit incrementer/decrementer at the bottom of the register file is used for multiple purposes. It increments the program counter as instructions execute, increments and decrements the stack pointer as needed, and supports the 16-bit increment and decrement instructions.

    An interesting feature of the incrementer is it also supports incrementing by 2, which is used to quickly skip over the two byte address in a call or jump not taken. This allows these operations to complete faster on the 8085 than the 8080.

    Two bits of the 16-bit increment/decrement circuit in the 8085. Odd bits and even bits use a different circuit for efficiency. The carry out from even bits is complemented.

    Two bits of the 16-bit increment/decrement circuit in the 8085. Odd bits and even bits use a different circuit for efficiency. The carry out from even bits is complemented.

    The incrementer/decrementer is implemented by a chain of adders with ripple carry - the carry from each bit flows into the adder for the next bit. (The above schematic shows two bits, and is repeated 8 times in the full circuit.) The DREG_INC and DREG_DEC control lines select increment or decrement. One performance trick is that alternating bits are implemented with different circuits and the carry out of even bits is inverted. This avoids the inverters that would otherwise be needed to flip the carry back to its regular state. This saves space, but even more importantly it speeds up carry propagation. Because the carry has to propagate bit-by-bit through all 16 bits to generate the final result, adding an inverter to each bit would slow it down significantly. The carry out is used to compute the undocumented K flag value (details).

    In comparison, the 6502 has a 16-bit incrementer (no decrement) used exclusively by the program counter. To reduce the carry propagation speed, this incrementer uses a carry-skip. That is, the carry out of the low-order byte is immediately generated and fed into the high-order byte. Thus the carries only need to propagate through 8-bits, the two bytes working in parallel. (The carry is easily generated by ANDing together the low-order bits. If they are all 1, there will be a carry into the high-order byte.)

    The WZ Temporary registers

    The WZ register pair in the 8085 is used for temporary storage, but is invisible to the programmer. Internally, the WZ register pair is implemented like the other register pairs.

    The primary use of WZ is to hold operands from a two or three byte instruction until it can be used. The WZ registers are used to hold 16-bit addresses for LDA, STA, LHLD, JMP, CALL, and RST instructions. The registers hold the port for IN and OUT. The WZ register pair can also temporarily hold information read from memory. The registers hold the address popped off the stack for RET. For XTHL, the registers hold the value from the stack.

    Register decoding and the instruction set

    The instruction set of the 8085 is organized so an instruction can be quickly and easily decoded to determine the instruction to use. The underlying structure for most 8085 instructions is the octal bit pattern bbDDDSSS, where destination bits DDD and/or source bits SSS select the register usage. The move (MOV) instructions follow this structure. Other instructions (e.g. INR) use just the DDD bits to select the register, while math instructions use the three SSS bits. Some instructions only use DDD or SSS, and some instructions operate on register pairs so they don't use the lowest bit. This instruction pattern is visible if the instructions are arranged in an instruction table according to their octal values.

    The three bits select the register as follows:

    D2D1D0Register
    000B
    001C
    010D
    011E
    100H
    101L
    110M
    111A

    M indicates a memory operation and is treated as a pseudo-register in the instruction set. Some instructions (e.g. INX) use the top two bits to select a register pair: BC, DE, HL, or "special" (stack pointer or accumulator). Note that in the table above the low-order bit selects a register out of a register pair.

    This instruction set structure allows simple logic to control the registers. A multiplexer pulls out the right group of three bits, depending on the instruction and the cycle in the instruction (link to schematic). These three bits are then used to pick the specific register control lines to activate at each step.

    The registers are controlled by about 18 control lines that affect the movement of data and the operation of the incremented/decrementer. The following table summarizes the control lines.

    /RREG_RDReads the right-hand side register bus onto the data bus.
    This implements the multiplexing of 16-bit registers onto the 8-bit data bus.
    /LREG_RDReads the left-hand side register bus onto the data bus.
    LREG_WRWrites the data bus to the left-hand side register bus.
    This implements the demultiplexing of the 8-bit data bus to the 16-bit registers.
    RREG_WRWrites the data bus to the right-hand side register bus.
    REG_PC_RWConnects the PC to the register bus.
    REG_SP_RWConnects the SP to the register bus.
    REG_WZ_RWConnects the WZ register pair to the register bus.
    REG_BC_RWConnects the BC register pair to the register bus.
    REG_HL_RWConnects the HL (DE) register pair to the register bus.
    REG_DE_RWConnects the DE (HL) register pair to the register bus.
    DREG_WRWrites the output of the incrementer/decrementer to the register bus.
    DREG_RDReads the register bus into the address latch.
    /DREG_RDInverted DREG_RD.
    DREG_DECIncrementer/decrementer performs decrement.
    DREG_INCIncrementer/decrementer performs increment.
    CARRY_OUTThe carry/borrow out from the incrementer/decrementer.
    DREG_CNTIncrement/decrement by 1.
    DREG_CNT2Increment/decrement by 2.

    The first step in register control is the register control PLA, which generates 19 control signals based on the instruction type and the cycle step. The register control logic (between the register file and the PLA) mixes in the register selection bits as appropriate (and a few other inputs) to generate the register control lines listed above.

    For instance, REG_BC_RW control line is activated if the PLA indicates a register access and the register bits are 00x. The RREG_RD control line is activated for a single-register read instruction if the register bits are xx0, and LREG_RD is activated if the bits are xx1. Both control lines are activated at the same time if the PLA indicates a register pair read.

    The DE/HL exchange trick

    The XCHG instruction exchanges the contents of the HL register pair with the contents of the DE register pair in a single M-cycle. You might wonder how the registers can be exchanged so quickly. It turns out that this instruction is implemented with a trick - an extra level of indirection.

    Although most 8085 architecture diagrams label one register pair as DE and another as HL, this isn't exactly true. In fact, the 8085 has two register pairs and either one can be the DE or HL pair. A status flip flop keeps track of which pair is DE and which is HL. As Pavel Zima figured out, the XCHG instruction doesn't move any data; it simply toggles the flip flop. The data remains in the same place, but the DE register is now HL and vice versa. Thus, the XCHG instruction is completed quickly. The consequence is every use of DE or HL uses this flip flop to determine which register to access (link to schematic).

    Using the ALU to move registers

    You wouldn't expect the ALU (arithmetic-logic unit) to take part in a register-to-register move, but it happens in the 8085. Many register operations take advantage of the ALU's temporary registers.

    The ALU doesn't directly operate on the accumulator and input register. Instead, the accumulator is copied to the ACT (Accumulator Temporary) register and the other input is copied to the TMP register. This way, the result can be written to the accumulator without the race condition that would occur if the accumulator were an input and output at the same time.

    For register moves, the source value is copied to the TMP register, the ACT register is set to 0, and the ALU performs an OR operation (ALU details), writing the result (i.e. the source value) to the dbus. This result can then be stored to the register file during a later cycle.

    The register file in action

    The step-by-step operation of the register file is surprisingly complex. One complication is that the register file and buses must handle stepping the program counter, fetching the instruction, and performing any register moves, without interference. A second complication is that register moves go through the ALU as described above.

    Stepping through an operation in detail will show the complexity of the register operations. The following shows the data flow for a MOV B,E instruction, which copies the contents of the E register into the B register.

    To understand this table, a bit of background on 8085 instruction timing. An instruction cycle is broken down into one or more M (machine) cycles, where an 8-bit memory access can be done in one M cycle. Each M cycle is broken down into several T-states, where each T-state corresponds to one clock cycle. Each clock cycle has a low phase and a high phase.

    The single-byte register-to-register MOV instruction takes one M cycle (M1), 4 T cycles, or 8 clock phases. Each clock phase is a separate line in the table. To make things more complicated, the activity for an instruction isn't entirely within its own instruction cycle. To improve performance, the 8085 uses simple pipelining, where the M1 opcode fetch of the next instruction overlaps with completion of the previous instruction.

    The MOV B, E instruction (which copies the E register to the B register) is illustrated in the table below. The PC is copied to the incrementer latch at the end of the previous operation, and then is written to the address pins during the T1 cycle. The PC is updated with the incremented value at the end of the T2 cycle.

    The instruction opcode is fetched in the T3 cycle, and at this point execution can start on the instruction. It's not until the T1 cycle of the next instruction that the register file swings into action. The E register is written to the dbus at the end of the T1 cycle. Then the ALU's TMP register is loaded from the dbus. The ALU's other argument, the ACT register is 0 at this point, and the ALU is configured to perform an OR operation. At the end of the (next instruction's) T3 cycle, the result of the ALU operation (i.e. the E register) is stored in the B register via the dbus. Meanwhile, the next instruction is getting fetched (grayed out).

    CycleT/clockPC actionRegister action
    T4/0
    T4/1PC → inc latch
    M1
    opcode fetch
    T1/0inc latch → address pins
    T1/1inc latch → address pins
    T2/0
    T2/1inc → PC
    T3/0data pins → dbus → instruction reg
    T3/1
    T4/0
    T4/1PC → inc latch
    M1
    opcode fetch
    T1/0inc latch → address pins
    T1/1inc latch → address pinsE reg → dbus
    T2/0dbus → TMP reg
    T2/1inc → PC
    T3/0data pins → dbus → instruction reg
    T3/1ALU → dbus → B reg

    Each step in the table above is activated by the appropriate register control lines. For instance, in T2/1, the PC is updated by triggering the reg_pc_rw and dreg_wr lines.

    Conclusion

    The 8085 has a complex register set, and it uses some interesting tricks to reduce the size of the chip and to optimize some operations. The register set is much harder to understand than I expected, but with careful examination it reveals its secrets.

    Credits: The chip images are from visual6502.org. The visual6502 team did the hard work of dissolving chips in acid to remove the packaging and then taking many close-up photographs of the die inside. Pavel Zima converted these photographs into mask layer images, a transistor net, an 8085 simulator, and register file schematics (top, bottom).

    See discussion at Hacker News. Thanks for visiting!