Magic‐1 Complete Technical Specification - retrotruestory/M1DEV GitHub Wiki
- Microcode Organization: 4096 × 56-bit words organized as 8 AM27S191 2K×8 PROMs
-
Microcode Word Layout:
- Bits 55-48: ALU operation control and condition selection
- Bits 47-40: Register file control (load enables, select lines)
- Bits 39-32: Bus control signals (enables, multiplexer selects)
- Bits 31-24: Memory interface control (RD, WR, MREQ, etc.)
- Bits 23-16: Next address calculation control
- Bits 15-0: Next microaddress or immediate field
- Primary Oscillator: 4.0 MHz crystal oscillator (HC-49/U package)
- Clock Divider Network: 74HC4040 ripple counter
-
Two-Phase Clock:
- CLK_S (System clock): 2.0 MHz, 50% duty cycle
- CLKM (Microcode clock): 2.0 MHz, 180° phase shift from CLK_S
-
Critical Timing Parameters:
- tCYC: 500ns (clock cycle time)
- tRISE: <15ns (clock rise time)
- tFALL: <15ns (clock fall time)
- tHOLD: 35ns (minimum hold time for register inputs)
- tSETUP: 45ns (minimum setup time for register inputs)
- Register Technology: 74F374 Octal D-type flip-flops
-
Register Arrangement:
- Four 74F374 chips per 16-bit register
- Load enables decoded via 74F138 3-to-8 decoders
- Output enables controlled by microcode
-
Special Register Implementations:
- FLAGS: 74F273 with individual bit set/clear capability
- PC: Dedicated 74F193 up/down counters with parallel load
- MAR: 74F377 with optional increment via 74F283 adders
- State Encoding: 3-bit state using 74F164 shift register
- State Transition Logic: Implemented with 74F151 multiplexers
-
Critical States:
- S0: Instruction fetch
- S1: Operand fetch
- S2: ALU operation
- S3: Memory access
- S4: Register writeback
- S5-S7: Extension states for multi-cycle operations
Upper Nibble | 0x | 1x | 2x | 3x | 4x | 5x | 6x | 7x | 8x | 9x | Ax | Bx | Cx | Dx | Ex | Fx |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | nop | clr | not | neg | inc | dec | asr | asl | lsr | rol | ror | jmp | jsr | rts | load | store |
1 | add | sub | mul | div | mod | and | or | xor | ldcnd | stcnd | test | cmp | swp | ext | push | pop |
2 | addi | subi | muli | divi | modi | andi | ori | xori | ldi | sti | biti | cmpi | ldx | stx | pushf | popf |
3 | jz | jnz | jc | jnc | jn | jp | jv | jnv | jo | jno | js | jns | jge | jl | jg | jle |
4 | addx | subx | mulx | divx | modx | andx | orx | xorx | ldax | stax | ldcx | stcx | tst | sta | lda | ldcl |
5 | tbit | sbit | cbit | wait | trap | reti | cli | sti | extb | extw | leas | movs | seq | clrc | setc | halt |
6 | addsp | subsp | ldsp | stsp | addc | subc | rrc | rlc | ldhi | ldsi | ldxi | stsi | stxi | ldai | stai | extli |
7 | ldil | stil | tstl | cmpl | xchg | bitv | mvsp | mvps | tlbp | tlbr | tlbwi | tlbwr | ldtlbl | ldtlbh | sttlbl | sttlbh |
8-F | Region-specific extended opcodes, implementation-defined |
Format 1 (Basic Operations):
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| Opcode | Register/Mode |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
Format 2 (Immediate Operations):
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| Opcode | Register/Mode | 16-bit Immediate Value |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
Format 3 (Extended Operations):
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| Opcode | Dst Reg | Src Reg | 16-bit Immediate Value |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
Mode | Binary | Meaning | Effective Address Calculation |
---|---|---|---|
000 | 0000xxxx | Register Direct | EA = Rx |
001 | 0001xxxx | Register Indirect | EA = [Rx] |
010 | 0010xxxx | Register Indirect with Post-increment | EA = [Rx], Rx += (size) |
011 | 0011xxxx | Register Indirect with Pre-decrement | Rx -= (size), EA = [Rx] |
100 | 0100xxxx | Indexed with 8-bit offset | EA = [Rx + sign_extend(imm8)] |
101 | 0101xxxx | Indexed with 16-bit offset | EA = [Rx + imm16] |
110 | 0110xxxx | PC-relative with 16-bit offset | EA = [PC + imm16] |
111 | 0111xxxx | Absolute 16-bit address | EA = [imm16] |
- TLB Entry Storage: Implemented with 74189 64-bit RAM ICs
-
Content-Addressable Compare Logic:
- 74F85 4-bit magnitude comparators in cascade
- 74F521 8-bit identity comparators for tag comparison
-
TLB Entry Format (32 bits per entry):
31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | Tag |G |V | ASIDs | PFN |D |C |W |R | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- Tag: VPN (Virtual Page Number)
- G: Global bit
- V: Valid bit
- ASIDs: Address Space ID
- PFN: Physical Frame Number
- D: Dirty bit
- C: Cacheable bit
- W: Writable bit
- R: Readable bit
-
Page Directory: 16 entries × 16 bits
- Bits 15-12: Flags (Valid, Writable, User, Reserved)
- Bits 11-0: Physical address of page table (4KB aligned)
-
Page Table: 32 entries × 16 bits per process
- Bits 15-12: Flags (Valid, Writable, User, Cacheable)
- Bits 11-0: Physical page number
- Extract VPN: VA[15:11]
- Extract Page Offset: VA[10:0]
-
Check TLB Match:
- Compare VPN with all TLB tags
- Check Valid bit and permissions
-
On TLB Miss:
- Calculate PTE address: PTBase + (VPN × 2)
- Read PTE from memory
- Check permissions
- Install in TLB
- Construct Physical Address: (PFN × 2048) | Offset
-
Permission Bits:
- R: Page readable
- W: Page writable
- U: User accessible (when 0, supervisor only)
- C: Cacheable
-
Exception Conditions:
- Access user page while in supervisor mode: Protection fault
- Write to read-only page: Protection fault
- Access to invalid page: Page fault
- TLB miss with invalid PTE: Page fault
- Organization: Direct-mapped
- Size: 1KB (512 entries × 16 bits)
- Line Size: 2 bytes (single instruction)
- Tag Bits: 8 bits
- Index Bits: 9 bits
-
Address Mapping:
- Tag: VA[15:9]
- Index: VA[8:1]
- Word Select: VA[0]
-
Cache Line Format:
31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ |V | Tag | Data Word | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- Organization: 2-way set associative
- Size: 2KB (512 entries × 2 ways × 16 bits)
- Line Size: 2 bytes
- Tag Bits: 7 bits
- Index Bits: 8 bits
- Replacement Policy: LRU (Least Recently Used)
- Write Policy: Write-through with no-write allocate
-
Line Format (per way):
31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ |V |D |L | Tag | Data Word | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- V: Valid bit
- D: Dirty bit
- L: LRU bit
- Address: 0xFFB0
-
Bit Layout:
- Bit 0: IC_EN (Instruction Cache Enable)
- Bit 1: DC_EN (Data Cache Enable)
- Bit 2: IC_INV (Invalidate Instruction Cache)
- Bit 3: DC_INV (Invalidate Data Cache)
- Bit 4: DC_WB (Data Cache Write Back, triggers write-back of dirty lines)
- Bits 5-15: Reserved
- Address Bus (A[21:0]): 22-bit multiplexed address bus
- Data Bus (D[15:0]): 16-bit bidirectional data bus
-
Control Signals:
- /RD: Read strobe (active low)
- /WR: Write strobe (active low)
- /MREQ: Memory request (active low)
- /IORQ: I/O request (active low)
- /WAIT: Wait state request (active low)
- /INT: Interrupt request (active low)
- /NMI: Non-maskable interrupt (active low)
- /RESET: System reset (active low)
- /BUSRQ: Bus request for DMA (active low)
- /BUSACK: Bus acknowledge for DMA (active low)
-
Memory Read Cycle Timing:
- Assert address on A[21:0]
- Assert /MREQ
- Assert /RD after tAD (address setup time) = 50ns
- Wait minimum tRD (read access time) = 200ns
- Sample data bus
- Deassert /RD
- Deassert /MREQ
- Deassert address bus
-
Memory Write Cycle Timing:
- Assert address on A[21:0]
- Assert /MREQ
- Drive data on D[15:0]
- Assert /WR after tAD (address setup time) = 50ns
- Hold for tWP (write pulse width) = 150ns
- Deassert /WR
- Hold data for tDH (data hold time) = 25ns
- Deassert /MREQ
- Deassert address bus
- Insertion Method: External devices pull /WAIT low
- Maximum Wait Cycles: 7 (controlled by timeout counter)
- Wait State Logic: Implemented with 74LS164 shift register and 74LS02 NOR gates
Vector | Priority | Type | Description |
---|---|---|---|
0x00 | - | RESET | System reset |
0x04 | 1 (High) | NMI | Non-maskable interrupt |
0x08 | 2 | TLB | TLB miss exception |
0x0C | 3 | PAGEF | Page fault |
0x10 | 4 | PROT | Protection fault |
0x14 | 5 | BUS | Bus error |
0x18 | 6 | ILL | Illegal instruction |
0x1C | 7 | PRIV | Privileged instruction |
0x20 | 8 | DIV | Divide by zero |
0x24 | 9 | OVFL | Arithmetic overflow |
0x28 | 10 | TIMER | Timer interrupt |
0x2C | 11 | UART | UART interrupt |
0x30 | 12 (Low) | USER | User interrupt |
Address | Register | Description |
---|---|---|
0xFFA0 | INT_PEND | Interrupt pending register |
0xFFA2 | INT_MASK | Interrupt mask register |
0xFFA4 | INT_PRI | Interrupt priority register |
0xFFA6 | INT_VEC | Interrupt vector register |
-
Hardware Actions:
- Device asserts /INT line
- CPU completes current instruction
- CPU samples interrupt controller to get vector
- Hardware pushes PC, FLAGS onto stack
- FLAGS.I cleared (interrupts disabled)
- PC set to vector address
-
Software Handler Actions:
- Push registers
- Handle interrupt
- Clear interrupt source
- Restore registers
- Execute RETI (Return from Interrupt)
-
RETI Instruction Sequence:
- Pop FLAGS from stack
- Pop PC from stack
- Resume execution at return address
Address | Register | Access | Description |
---|---|---|---|
0xE000 | TX/RX | R/W | Transmit/Receive Buffer |
0xE001 | IER | R/W | Interrupt Enable Register |
0xE002 | IIR | R | Interrupt Identification |
0xE002 | FCR | W | FIFO Control Register |
0xE003 | LCR | R/W | Line Control Register |
0xE004 | MCR | R/W | Modem Control Register |
0xE005 | LSR | R | Line Status Register |
0xE006 | MSR | R | Modem Status Register |
0xE007 | SCR | R/W | Scratch Register |
UART Initialization Sequence:
; Initialize UART at 9600 baud, 8N1
ldi #0x80 ; Set DLAB bit
sta 0xE003 ; Write to LCR
ldi #0x0C ; Divisor value for 9600 baud (LSB)
sta 0xE000 ; Write to DLL
ldi #0x00 ; Divisor value (MSB)
sta 0xE001 ; Write to DLM
ldi #0x03 ; 8N1 format
sta 0xE003 ; Write to LCR
ldi #0x07 ; Enable FIFOs, reset, trigger level 14
sta 0xE002 ; Write to FCR
ldi #0x0B ; RTS, DTR, enable interrupts
sta 0xE004 ; Write to MCR
ldi #0x01 ; Enable RX interrupts
sta 0xE001 ; Write to IER
Address | Register | Access | Description |
---|---|---|---|
0xE010 | TMR0_CNT | R/W | Timer 0 Counter |
0xE012 | TMR0_CTRL | R/W | Timer 0 Control |
0xE014 | TMR1_CNT | R/W | Timer 1 Counter |
0xE016 | TMR1_CTRL | R/W | Timer 1 Control |
Timer Control Register Bits:
- Bit 0: Enable (1=enabled, 0=disabled)
- Bit 1: Mode (0=one-shot, 1=auto-reload)
- Bit 2: Interrupt Enable
- Bit 3: Prescaler Select bit 0
- Bit 4: Prescaler Select bit 1
- Bits 5-15: Reserved
Prescaler Values:
- 00: Divide by 1
- 01: Divide by 16
- 10: Divide by 256
- 11: Divide by 1024
Address | Register | Access | Description |
---|---|---|---|
0xE020 | CF_DATA | R/W | Data Register (16-bit) |
0xE022 | CF_ERROR | R | Error Register |
0xE023 | CF_FEAT | W | Feature Register |
0xE024 | CF_COUNT | R/W | Sector Count |
0xE026 | CF_LBA0 | R/W | LBA Low |
0xE028 | CF_LBA1 | R/W | LBA Mid |
0xE02A | CF_LBA2 | R/W | LBA High |
0xE02C | CF_SELECT | R/W | Drive/Head Register |
0xE02E | CF_STATUS | R | Status Register |
0xE02E | CF_CMD | W | Command Register |
CF Card Read Sequence:
; Read sector #1234 into memory at $4000
ldi #0x00 ; LBA mode, Drive 0
sta 0xE02C ; Write to SELECT
ldi #0x01 ; Sector count = 1
sta 0xE024 ; Write to COUNT
ldi #0xD2 ; LBA bits 7-0 (0x04D2 = 1234)
sta 0xE026 ; Write to LBA0
ldi #0x04 ; LBA bits 15-8
sta 0xE028 ; Write to LBA1
ldi #0x00 ; LBA bits 23-16
sta 0xE02A ; Write to LBA2
ldi #0x20 ; READ SECTOR(S) command
sta 0xE02E ; Write to CMD
wait_rdy:
lda 0xE02E ; Read STATUS
biti #0x08 ; Test DRQ bit
jz wait_rdy ; Loop until ready
ldi #0x00 ; Initialize counter
ldx #0x4000 ; Destination address
rd_loop:
lda 0xE020 ; Read data word
sta (X)+ ; Store and advance
addi #1 ; Increment counter
cmpi #256 ; 256 words = 512 bytes
jnz rd_loop ; Continue until done
Address | Size | Contents |
---|---|---|
0x0000 | 2B | Reset Vector (PC initial value) |
0x0002 | 2B | Initial Stack Pointer |
0x0004 | 28B | Interrupt Vectors |
0x0020 | 32B | ROM Configuration Data |
0x0040 | 64B | System Information Table |
0x0080 | 128B | Boot Parameter Block |
0x0100 | 256B | CF Card Driver |
0x0200 | 512B | Boot Menu Code |
0x0400 | 1KB | Main Boot Loader |
0x0800 | 1KB | ROM Monitor |
0x0C00 | 1KB | Hardware Test Routines |
Address Range | Size | Purpose | Features |
---|---|---|---|
0x0000-0x1FFF | 8KB | Boot ROM | Read-only, shadowed after boot |
0x2000-0x3FFF | 8KB | System RAM | Used for vectors, system data |
0x4000-0x7FFF | 16KB | Kernel RAM | OS kernel resides here |
0x8000-0xDFFF | 24KB | User RAM | Application code and data |
0xE000-0xEFFF | 4KB | I/O Space | Memory-mapped devices |
0xF000-0xF7FF | 2KB | Video RAM | Text mode display buffer |
0xF800-0xFBFF | 1KB | System Variables | OS maintained variables |
0xFC00-0xFFFF | 1KB | Stack Area | System and interrupt stack |
+--------+
| 74F163 |
| PC |
+--------+ |Counter | +--------+
| PROM | +--------+ | 74F377 |
| 27S181 |<-+ +->| μAddr |
|(μcode) | | ALU | |Register|
+--------+ | Control | +--------+
| +----------+ |
v v
+--------+ +--------+ +--------+
| Inst | | ALU | | Next |
| Decode |->| Ops |<-| μAddr |
| Logic | | Logic | | Logic |
+--------+ +--------+ +--------+
^ ^ ^
| | |
v v v
+-----------------------------------+
| Control Bus |
+-----------------------------------+
^ ^ ^
| | |
+--------+ +--------+ +--------+
| Timing | | Flag | | 74F138 |
| Logic | | Logic | | Decode |
+--------+ +--------+ +--------+
+--------+ +--------+
| 74F283 | | 74F283 |
| Adder | | Adder |
+--------+ +--------+
A B A B
| | | |
v v v v
+--------+ +--------+ +--------+
| Misc | | 74F381 | | 74F381 |
| Logic | | ALU | | ALU |
+--------+ +--------+ +--------+
| | |
v v v
+------------------------------------+
| Result Bus |
+------------------------------------+
|
v
+--------+
| 74F377 |
| Z |
|Register|
+--------+
+--------+ +--------+ +--------+
| MAR | | MBR | | Memory |
|Register|---->|Register|<--->| Chips |
+--------+ +--------+ +--------+
| | |
v v v
+------------------------------------+
| Address/Data Bus |
+------------------------------------+
| | |
v v v
+--------+ +--------+ +--------+
| Address| | Data | | Memory |
| Decode | | Buffer | | Control|
+--------+ +--------+ +--------+
F0: PC → MAR, PC + 2 → PC // Fetch opcode
F1: MEM[MAR] → IR // Load instruction
F2: Decode IR // Decode add instruction
E0: A → L-bus, R[IR.7-4] → R-bus // Load operands
E1: L-bus + R-bus → Z-bus // Perform addition
E2: Z-bus → A, Set flags // Store result and set flags
E3: Next instruction // Done
F0: PC → MAR, PC + 2 → PC // Fetch opcode
F1: MEM[MAR] → IR // Load instruction
F2: PC → MAR, PC + 2 → PC // Fetch offset
F3: MEM[MAR] → TEMP // Store offset
E0: R[IR.7-4] + TEMP → MAR // Calculate effective address
E1: MEM[MAR] → MBR // Read memory
E2: MBR → A, Next instruction // Load to accumulator
F0: PC → MAR, PC + 2 → PC // Fetch opcode
F1: MEM[MAR] → IR // Load instruction
F2: PC → MAR, PC + 2 → PC F0: PC → MAR, PC + 2 → PC // Fetch opcode
F1: MEM[MAR] → IR // Load instruction
F2: PC → MAR, PC + 2 → PC
Similar code found with 2 license types