A single pair of memory commands — open a row, close the array, open a second row — is one primitive with one timing dial, and it opens a fixed, predictable family of rows: the two rows it names plus their relatives at fixed address offsets (here 4, 16, 64 and 512), a family wired into the chip's row decoder and identical every time. At copy timing the first row's content spreads across that whole family at once — a real, measured multi-row copy (DRAM's own RowClone, run here on purpose), and the reason the weights are laid out to keep operands off one another's families. At vote timing nothing is imported: the family's rows are counted, and their bit-by-bit majority wins. One primitive, one dial — copy spreads, vote counts. This page shows where the line between them sits, why the family is exactly the rows it is, and how, when a copy lands on a vote's operands, a wrong answer becomes something you can predict down to the byte.
Every row in a DRAM chip has a numeric address. To open a row, the chip feeds that address into a decoder — a small tree of logic that lights up one wordline, the wire connecting a row of storage cells to the chip's sense circuitry. The decoder never sees the address as one number. It splits it into two parts — which block of rows (the upper bits) and which position inside the block (the lower ten bits) — and the position's ten bits arrive pre-grouped in six bundles. On the dies this page measures, the bundles are:
| bundle | wires |
|---|---|
| bit 9 | 2 — one per value (0, 1) |
| bits 8-7 | 4 — one per value (00, 01, 10, 11) |
| bits 6-5 | 4 |
| bits 4-3 | 4 |
| bits 2-1 | 4 |
| bit 0 | 2 |
Asking for a row turns on exactly one wire in every bundle — the wire for that row's value — and a row opens only when all six of its wires are on. Normally that selects exactly one row, and the wires are released when the activation completes. Hold that picture: everything later on this page follows from it.
The whole story is a single sequence of four commands to the memory:
ACT opens a row; PRE ("precharge") closes the array again. Two timing knobs shape what happens:
Shorten these and the array never fully settles between the two activations: the second ACT can open its row while the first is still driving the shared wires. That overlap is the source of both behaviours below. It is not a defect — it is exactly the mechanism SiMRA's Multi-RowCopy uses on purpose (credited in full at the end).
This is the one object to understand on the page. Move the needle along the first hold, counted in command slots, and watch what the same command pair does to the same three rows.
Read it off the dial. At the operating point (0–1 slots) the pair resolves a majority vote — every participating row ends holding the winning value. One extra slot of hold and the sense amplifiers land undecided: a tie. Three or more slots and the pair has become a copy — the first-opened row (the source) is written into the others. Same four commands; the timing alone picks the physics.
The other knob — the gap after PRE, before the second ACT — controls a different line: whether the pair copies into a single destination row or into many. A clean copy into one destination row needs the array fully closed, which takes at least 4 slots (6.0 ns). Below that, the copy spreads across a whole set of neighbours.
First-hit-wins. The standard SiMRA calibration scans this gap upward from 1 slot and stops at the first value that clones successfully — which is 1 slot, inside multi-row territory. So a calibrated "RowClone" is already a multi-row operation: it copies into the neighbour set too. That is not a reliability choice; it is simply where a first-hit search happens to stop. Production keeps this short timing on purpose (see §7).
"Majority vote" means exactly what it says: for each bit position, the result takes whichever value appears in more of the rows. Here are three one-byte values and the majority they produce — the only place on the page where bits are shown one at a time. Everywhere else, bytes are written in hex.
A 1 1 1 1 0 0 0 0 F0 B 1 1 0 0 1 1 0 0 CC C 1 0 1 0 1 0 1 0 AA ─────────────── MAJ 1 1 1 0 1 0 0 0 E8
Each column of the bottom row is the majority of the three above it: MAJ(F0, CC, AA) = E8. In the demo the operand rows hold F0 (call it A), CC (B) or AA (C); a well-timed vote turns all of them into E8.
A majority of three does more than break ties — it is a small logic gate in disguise. Pin one of the three inputs to all-zeros, and the majority of the other two can only come out 1 when both of them are 1: that is their AND. Pin that same input to all-ones instead, and the vote tips the moment either of the other two is 1: their OR. One primitive, one input held to a fixed 0 or 1, and the same majority delivers AND or OR on demand — which is why a bare majority vote is enough to build logic inside the memory.
A held input has a third setting, too — the one this work calls frac, short for fractional charge. A cell need not sit fully at 0 or fully at 1: it can be parked deliberately partway between the two, at a level the sense amplifier reads as neither. Dropped into a vote as a reference the other rows are judged against, such a partly-charged row acts as a bias — a known thumb on the scale that tilts a close majority the chosen way.
The same trick runs with five rows instead of three — a five-input majority, or MAJ5. It matters because it completes the adder: to add three bits, the carry-out is simply the majority of the three, MAJ3(a, b, c), and the sum bit is the five-input majority of those same three together with two copies of the inverted carry, MAJ5(a, b, c, NOT carry, NOT carry). Majority alone — three rows and five rows — gives a full adder, the primitive every running total is built from.
Wider votes exist as well — seven-input and nine-input majorities — but the workhorse for adding up many bits at once is not an ever-larger vote; it is the popcount, which simply counts how many of the rows hold a 1.
One last thing about that count. The worked example votes over three distinct values, but on silicon the vote runs across sixteen rows, not three — and the reason is margin, not bookkeeping. A sense amplifier decides each bit from a tiny difference in charge on the shared wire; with only three rows leaning on it, that difference is small enough that the amplifier can resolve it the wrong way. Pile more rows holding the same value onto the same wire and the difference grows, giving the amplifier room to settle on the right answer. So the real vote deliberately spreads each value across many rows — which sixteen, and why exactly those, follows from the address wiring the next section lays out.
The pair opens more rows than the two it names, and exactly which ones follows from §1's six-bundle picture — walked through here on this page's real pair. One warning first: do not compare the two row numbers bit by bit. Written as one number, block and position smear together and mislead. Split first, the way the chip does:
38424 = block 38400 + position 24 38988 = block 38400 + position 588
Same block — that is what lets them interact at all. From here on, only the two positions matter.
Write both positions in their six bundles and compare, bundle by bundle:
position bit 9 | 8-7 | 6-5 | 4-3 | 2-1 | 0 24 0 | 00 | 00 | 11 | 00 | 0 588 1 | 00 | 10 | 01 | 10 | 0 DIFF | same | DIFF | DIFF | DIFF | same
Four bundles differ. Now add §2's mechanism: the second activation arrives before the first is released, so nothing gets un-lit. Watch one differing bundle up close:
bundle 6-5 wire 00 wire 01 wire 10 wire 11 24 asks (value 00) ON off off off 588 arrives (10) ON off ON off ↑ never released
Two of that bundle's four wires end up on — the two values somebody asked for. The values nobody asked for stay dark. The same happens in every differing bundle; the matching bundles hold one lit wire, shared. Count the lit wires and multiply — a row opens only when all six of its wires are on, so every bundle contributes its lit-wire count as a factor:
wires lit 2 | 1 | 2 | 2 | 2 | 1 → 2·1·2·2·2·1 = 16 rows open
Rows opened = the product of lit wires per bundle. That product is the whole rule. Here it is 16, and adding the block back turns the sixteen mixes into row numbers:
These sixteen are, digit for digit, the row family in the calibration file — and the pair 38424/38988 is the calibrated activation pair precisely because it differs in four bundles: it is the pair that opens the whole family. The four rows shaded amber sit one single bundle-swap from the source; they matter in §6:
| neighbour row | reached from the source by |
|---|---|
| 38408 | swapping bundle 4-3 (−16) |
| 38428 | swapping bundle 2-1 (+4) |
| 38488 | swapping bundle 6-5 (+64) |
| 38936 | swapping bit 9 (+512) |
Any other pair mixes only what it lights. Activate 38408 with 38412 (positions 8 and 12 — one differing bundle) and 2¹ = 2 rows open: those two, nothing else. That is also what a clean copy is: a pair differing in exactly one bundle — one source, one destination. And the rule counts bundles, not bits: positions 8 and 14 differ in two bits, but both sit in the 2-1 bundle (00 against 11) — still just 2 rows, and the in-between values 01 and 10 can never open, because no activation lit their wires. Bits inside a bundle cannot be mixed.
Sixteen is a choice, not a ceiling. A pair differing in five bundles opens 32 — measured, and the product rule holds without exception — and all six would open 64, the most any pair can reach. Production calibrates 16-row families deliberately: bigger sets open just fine, but opening is not voting, and sixteen is where the vote is reliable on these chips — with the four differing bundles chosen one per bundle, so every mix is addressable.
Now the payoff. Take the 16-row family, load it with A, B and C so the honest majority is E8, and fire one well-timed vote. Layout: A on 6 rows (including both opened rows), B on 6, C on 4 — the worst tally at any bit is 6-against-10, so the honest answer wins by at least four votes and no single row can change it.
Every operand row ends holding E8. The vote is destructive: it writes the result back into all 16 rows. That is normal.
| address | role | value |
|---|
Change one thing. Before the vote, use the copy regime to place the source F0 onto its four nearest neighbours — the four rows from §5, one bundle-swap each, holding C. This is a targeted copy, not the whole-family flood the dial shows at deep copy timing: each neighbour is filled by its own small source-to-neighbour copy, so exactly those four flip and the other eleven rows stay put. Read the group back in the freeze-frame between the deposits and the vote — the four neighbours now hold F0 byte-for-byte, everything else is untouched. Now fire the same well-timed vote:
| address | role | value |
|---|
Ten rows now hold F0 and six hold CC, so the vote returns F0 — not the honest E8 — and, being destructive, writes that F0 back into all 16 rows. The machine is not glitching; it is faithfully voting, over an operand set quietly rewritten first. And because it is a vote, the wrong answer arrives exactly when the count says it should:
| k | tally at the contested bits | result |
|---|---|---|
| 0, 1 | 6+k against 10−k → honest side wins | E8 correct |
| 2 | 8 against 8 | tie — undecided |
| 3, 4 | 9 against 7, then 10 against 6 | F0 wrong |
A blanket copy would ignore k; a random glitch would not track a vote count. The flip at k = 3 is the signature of a genuine majority computed over substituted operands.
One honesty note. A raw vote is analog — repeated in the same session it agrees to within a fraction of a percent of the cells. The copy deposits, by contrast, are exact: every one of the 8 192 bytes matches the source. The tables show the logical result.
The bad case looks like a trap, and left unmanaged it is one. But the very same coupling is a free one-to-many copy: fire the pair once and the source lands in its whole family at no extra cost. Whether that is a hazard or a gift is decided by where you put your data, not by the timing.
This is why the short "dirty" calibration timing from §3 is kept on purpose. Widening the gap would suppress the extra deposits — but those extra deposits are free copies. Keep the short timing; make the spread harmless by placement. For the production throughput numbers and the wall model behind them, see the peer doc.
The multi-row co-activation itself — one command pair opening a lattice of rows and driving them to the source's value — is SiMRA's own Multi-RowCopy. What this page adds is the address algebra — that the opened rows are exactly the family the pair's differing bundles span (the coset), the product rule (the selection law) for how many open, and the consequence that a majority vote can run, silently, over a substituted operand set.
The candidate selection is byte-identical across our two SK hynix modules (two different part numbers), and a Micron die reproduces the same physics with a different grouping.