SRAM address aliasing on an 8051 memory board
An 8051 board carries a 6264 8K×8 SRAM (A0–A12, /CE1, CE2, /OE, /WE) and a 27C256 32K EPROM (A0–A14). The EPROM's /CE is driven from A15 through a gate, so it answers only in 0x8000–0xFFFF. For the SRAM the designer tied /CE1 to GND, drove CE2 from the inverted A15, and left A13 and A14 unconnected. The firmware declares the stack at 0x0100–0x01FF, variables at 0x0020–0x005F, and a 2 KB serial receive buffer at 0x2000. Packets may be up to 1 KB and the receiver has no bounds check. Everything works until a packet exceeds about 256 bytes, after which the unit resets at random. The same firmware image runs on an older board with a 32K SRAM without ever failing. A walking-bit test that writes from 0x2000 upward reads identical data back at 0x0000, 0x4000 and 0x6000. Production would prefer a one-line software change, moving the buffer, to a board respin.
1. From the wiring, explain why the copies appear, state the alias step and the number of distinct 8K blocks, and identify exactly why a packet longer than 256 bytes causes resets.
Read the worked answer
CE2 is the inverse of A15, so the SRAM is selected for every address with A15 = 0, i.e. 0x0000–0x7FFF. But the chip has only 13 address pins: A13 and A14 are not connected, so they are don't-cares to the memory. The 32K window therefore folds into four 8K images with a step of 2^13 = 0x2000:
| Window | Addresses |
|---|---|
| 0 | 0x0000–0x1FFF |
| 1 | 0x2000–0x3FFF |
| 2 | 0x4000–0x5FFF |
| 3 | 0x6000–0x7FFF |
All four are the same 8K of silicon. Address 0x2100 differs from 0x0100 only in A13, so both select the same cell.
The buffer starts at 0x2000 and aliases onto 0x0000. Byte 0 of the buffer lands at 0x0000 and byte 0x100 lands at 0x0100 - the first byte of the stack. Once a packet exceeds 256 bytes the receive pointer overwrites the stack, return addresses are destroyed, and the CPU executes garbage: the random resets. The walking-bit result at 0x0000/0x4000/0x6000 is the same folding seen from the outside.
2. Evaluate the proposed software workaround against adding full address decoding. Give the decoded ranges after the fix and check whether the existing memory map still fits.
Read the worked answer
The workaround cannot be made safe. Every address in 0x0000–0x7FFF aliases onto three others, so whatever offset you choose for the buffer, some other variable is only 0x2000 away and will be hit when the buffer grows. Moving the buffer to 0x3000 merely relocates the collision to 0x1000; there is no address in the window that is free of a victim. The only software-only option is to bound the buffer to 256 bytes and prove that no pointer ever exceeds it - a discipline, not a fix, and it still leaves the stack and variables sharing silicon with unused windows.
Hardware fix: decode A15, A14 and A13 all low. With a 74HC138 using A15 on an active-low enable and A14/A13 as inputs, Y0 is low for 0x0000–0x1FFF only. Connect Y0 to /CE1 and tie CE2 high. The SRAM then occupies exactly 8K at 0x0000–0x1FFF with no mirrors; the EPROM remains 0x8000–0xFFFF.
Capacity check: stack 512 B + buffer 2 KB + variables and scratch ≈ 1 KB gives roughly 3.5 KB, comfortably inside 8 KB. So the fix costs one small logic package and no firmware change beyond keeping the linker map inside 8K.
3. Suppose a wiring error enabled the SRAM and the EPROM at the same time. What would you observe, and how would you prove it on the bench?
Read the worked answer
Both chips would drive D0–D7 simultaneously. Where they disagree, one output pulls high while the other pulls low, and the bus settles at an intermediate level set by the relative output resistances - typically 1.5–3 V instead of a clean 0 or 5 V. The CPU then reads indeterminate data, so the symptom is erratic code execution or an apparent 'corrupted EPROM' rather than a clean failure. Sustained contention also raises supply current noticeably and warms both packages.
Bench proof:
- Scope a data line during a read with a short ground connection; look for intermediate levels and for both /CE pins low in the same cycle.
- Trigger the scope on /CE of the EPROM and check the SRAM's /CE on the second channel; a simultaneous low is conclusive.
- Measure supply current with one /CE lifted; a significant drop confirms contention.
- Cross-check statically with the ohmmeter/multimeter on the address decoder output rather than probing inside a running bus.
Prevention: /OE should be driven by the CPU read strobe, not by the address decoder, so memory only drives the bus during a read and never during a write.