ROM
"Could you tell me a bit more about ROM and how it is designed internally? I suppose that it cannot be built from D latches like RAM." Even though the answer is probably not that important, I found the answer interesting so I am posting it.
Grok:
Your question about how ROM (Read-Only Memory) is designed internally, and why it can’t be built from D latches like RAM, is a great one! It shows you’re diving deep into the nuts and bolts of your 4-bit processor project. Since you’re considering a ROM-based instruction decoder to store control signals (based on T-states and opcodes), understanding ROM’s internal design will help clarify how it fits into your system and why it’s distinct from RAM. I’ll explain ROM’s purpose, contrast it with RAM, dive into its internal architecture (focusing on mask ROM, PROM, EPROM, and EEPROM for context), and address why D latches aren’t used. I’ll keep it concise yet detailed, tying it to your project where possible, and avoid speculative details since you’ve asked for a factual rundown.
What is ROM?
ROM is a type of non-volatile memory that stores fixed data, readable during operation but not typically writable (or only writable under special conditions, unlike RAM). In your case, the ROM will store control signals for each T-state and opcode combination, acting as a lookup table for your instruction decoder.
Key Traits:
- Read-Only (Mostly): Data is preset (e.g., programmed into an EEPROM) and read via address lines (T-state + opcode → signals).
- Non-Volatile: Retains data without power, unlike your RAM (volatile, loses data when powered off).
- Use in Your Project: A ROM (e.g., 256 × 16 bits) maps 8-bit addresses to 16-bit control signals.
Contrast with RAM:
- RAM (e.g., 74LS189): Volatile, read/write, stores program/data (e.g., opcodes at 0000–0111, data at 1000–1111). Uses D latches/flip-flops to hold bits dynamically.
- ROM: Non-volatile, read-only (or rarely writable), stores fixed control logic. Doesn’t use latches, as data is physically encoded.
Why ROM Can’t Use D Latches Like RAM?
Your intuition is correct—ROM doesn’t rely on D latches (or flip-flops) like RAM does. Here’s why:
- RAM’s Design (e.g., 74LS189):
- Storage: Each bit is stored in a memory cell, typically a D latch or SRAM cell (cross-coupled inverters forming a flip-flop, ~6 transistors in CMOS).
- Dynamic: Latches hold state as long as power is on, changeable via writes.
- Your: 16 locations × 4 bits, each bit a latch, volatile (loses data without VCC).
- ROM’s Design:
- Storage: Bits are hardwired or programmed into the physical structure (e.g., metal connections, fuses, or charge traps), not stored dynamically in latches.
- Operation:
- Address selects a word (row), and the ROM outputs predefined bits (e.g. one for each control signal).
- No write circuitry (except in PROM/EPROM/EEPROM, which use special programming).
- Fixed Data: No need for latches, as bits are encoded permanently (or semi-permanently in EEPROM).
- Why No Latches?
- Purpose: ROM stores immutable data (your control signals), so dynamic storage (latches) is unnecessary and power-hungry.
- Volatility: Latches lose data without power, defeating ROM’s non-volatile goal.
- Complexity: Latches need write logic and refresh (in DRAM), while ROM uses simpler, static structures (e.g., diodes, transistors).
- Density: ROM’s matrix design (below) packs more bits than latch-based SRAM, critical for larger memories.
In short, D latches are ideal for RAM’s read/write needs but overkill for ROM’s fixed, read-only data. ROM uses physical or programmable structures to encode 1s and 0s directly.
Internal Design of ROM
ROM’s internal architecture depends on its type (mask ROM, PROM, EPROM, EEPROM), but all share a decoder-matrix structure. I’ll explain the general design and focus on EEPROM, with notes on others for context.
1. Basic ROM Structure
A ROM is organized as:
- Address Decoder: Converts input address (e.g., 8 bits, A7–A0) into a selected word line (one of 256 rows).
- Memory Array: A grid where each row (word) stores a data word.
- Output Lines: Data bits (D0–D15) driven by the selected row’s contents.
2. ROM Types and Their Storage
Here’s how different ROMs encode bits in the memory array, explaining why latches aren’t used:
- Mask ROM:
- Design: Bits are fixed during manufacturing.
- Storage: Uses a diode matrix or transistor matrix.
- Diode Matrix:
- Grid of word lines (rows) and bit lines (columns).
- A diode at an intersection (row i, column j) encodes a 1; no diode encodes a 0.
- Transistor Matrix: NMOS/PMOS transistors act as switches (1 = transistor present, 0 = absent).
- Diode Matrix:
- Use Case: Not for you (fixed at fab), but shows ROM’s static nature.
- PROM (Programmable ROM):
- Design: One-time programmable by user.
- Storage: Fusible links (e.g., nichrome fuses).
- Each intersection has a fuse (initially 1).
- Programming: Blow fuses (apply high current) to set 0s.
- Use Case: Rare now, less practical than EEPROM for your project.
- EPROM (Erasable PROM):
- Design: Reprogrammable via UV erasure.
- Storage: Floating-gate MOSFETs.
- Each bit is a MOSFET with a floating gate (no connection to external circuit).
- 1 (Erased): No charge on gate, transistor conducts (bit line pulled low).
- 0 (Programmed): High voltage (e.g., 25V) traps electrons on gate, blocking conduction (bit line stays high).
- Programming: Apply high voltage to select rows/columns, setting 0s.
- Erasure: UV light removes charge, resetting to 1s.
- Use Case: Viable, but needs UV programmer/eraser.
- EEPROM (Electrically Erasable PROM):
- Design: Reprogrammable electrically, ideal for your ROM (256 × 16 bits).
- Storage: Floating-gate MOSFETs with tunneling.
- Similar to EPROM, but adds a thin oxide layer for Fowler-Nordheim tunneling.
- 1: No charge, transistor conducts.
- 0: Charge trapped via tunneling (high voltage, ~12V).
- Programming: Apply voltage to set 0s, reverse to erase to 1s, byte-by-byte.
- Use Case: Perfect for you.
-end-
My Summary
In the previous entry, Grok suggested that we use a ROM (an EEPROM more specifically) to "store control signals for the instruction decoder". Grok suggests that we use a "256 x 16 ROM". This means that it has 256 addresses, where each address can store 16 bits, bit 0 to bit 15:
We simply set an address, say 0110 1100 on the input pins and the 16 output pins will hold a 0 or a 1 depending on how we have programmed the ROM. The ROM really acts as a "look-up table". The actual data held by the ROM will be the "control signals", but not sure precisely how yet - will get back to this.
Here is a example of an EEPROM, ATMELs AT28C64B:
This EEPROM has a 13 bit address (13 of the pins are input pins A0-A12), with a total of 2^13 = 8192 addresses, way more than we need right now. This is not a problem though. We use only A0-A7 and set the 5 highest pins, A8-A12, to 0.
AT28C64B stores only 8 bits at each address (it has 8 output pins). The simplest solution is to use two of these, one for the first 8 data bits and one for the remaining 8 data bits. In addition to the 21 address and data pins, it has pins to control if we are writing data to the ROM or reading data from the ROM.
ACEL ROM
I created a 256 x 16 ROM in ACEL, called "ROM256x16". To "program" this ROM, we define a variable called "data" (you can name it whatever you want):
uint16_t data[256] = {"data at A=0", "data at A=1", "data at A=2",...};
"data" is an array of 256 "uint16_t", where "uint16_t" means 16 bits. This is precisely what we need to program the ROM. For example, if we do
uint16_t data[256] = {0b0000000000000000, 0b1000000000000011};
then all bits at address 0 will be set to 0. At address 1, bit 0 (left-most bit) will be set to 1, bit 14 and bit 15 will be set to 1, and the rest to 0. Since we have not defined any data for address 2 and onwards, they will all be set to 0 (all bits 0).
Now, programming RAM by typing each individual bit is not the best way. Instead, we break up the sixteen binary bits into four groups of four bits each. For example,
1000 0000 0000 0011
Each group of four binary digits is then converted to a single hex digit (see entry 9):
1000 0000 0000 0011 = 8003 in hex
An equivalent, but simpler way of programming RAM is as follows (where the "x" indicates hex)
uint16_t data[256] = {0x0000, 0x8003};
Conversion between hex and binary is super simple. You can program the ROM using decimal numbers as well, but the conversion between binary and decimal is "messy". Using a converter, for example Windows Calculator, we see that 1000 0000 0000 0011 is 32771 in decimal.
Therefore, we can also write
uint16_t data[256] = {0, 32771};
Finally, we initialize the chip "ROM256x16" with the data.
auto* rom = new ROM256x16(data);
You can test it on Wokwi, project "256 x 16 ROM".
Next, let's figure out how to use the ROM to store control signals... in the next entry.
No comments:
Post a Comment