Case Study: RCA 1802 Processor

Demonstrating complex behavioral modeling in Simic.

Overview

The RCA 1802 (COSMAC) is a classic 8-bit microprocessor. Modeling its internal logic at the gate level would be prohibitively complex. Instead, we provide a Behavioral Model that implements its instruction set.

This case study demonstrates how behavioral modeling enables simulation of complete processor systems by implementing functional behavior at the instruction level rather than transistor or gate level.

Design Approach

Why Behavioral Modeling for Microprocessors?

Microprocessors are ideal candidates for behavioral modeling for several reasons:

RCA 1802 Characteristics

The CDP1802 has several features that make it suitable for behavioral modeling:

SNL Definition

To use the model, you declare it as a behavioral type in your .net file:

type=cdp1802 p1 p2 p3 i=mclk,clear,wait,pause,irq,ef1,ef2,ef3,ef4,d[0:7] $
              o=ma[0:7],q,sc0,sc1,tpa,tpb,mrd,n0,n1,n2,ceo,d[0:7] $
              composition=behavioral

Pin Description

Pin Type Description
mclk Input Master clock - drives instruction execution
clear Input Reset signal - initializes processor state
wait, pause Input Execution control - halt or single-step
ef1-ef4 Input External flags - read by branch instructions
d[0:7] Bidir Data bus - memory and I/O interface
ma[0:7] Output Memory address (low byte)
q Output Q register output bit
sc0, sc1 Output State code - indicates fetch vs execute cycle
tpa, tpb Output Timing pulses for external logic
mrd Output Memory read strobe
n0-n2 Output Instruction type indicators
Signal Vectors: Note the use of d[0:7] for the data bus. These must be declared with the %declare statement to define their print radix and width.

Behavioral Implementation

Internal State Management

The 1802 model maintains internal state that persists between evaluations. This state captures the processor's architectural registers and control state:

Architectural State

Execution Cycle State

Instruction Execution Model

On each mclk rising edge (assuming no WAIT/PAUSE), the evaluation routine performs these steps:

  1. Fetch: Read instruction byte from memory at address R[P]
    opcode = memory[R[P]]
    R[P] = R[P] + 1  // Increment PC
  2. Decode: Determine instruction type from opcode high nibble
    instr_type = (opcode >> 4) & 0x0F
    register_num = opcode & 0x0F
  3. Execute: Perform instruction-specific operation
    switch (instr_type) {
        case 0x3:  // BR, BZ, BDF, etc. (branch instructions)
            offset = memory[R[P]]
            R[P] = (R[P] & 0xFF00) | offset
            break
        case 0x8:  // GLO (Get Low byte of register)
            D = R[register_num] & 0xFF
            break
        // ... 91 instructions total ...
    }
  4. Update Outputs: Set state code, timing pulses, memory strobes

Key Implementation Patterns

Memory Interface Handling

The bidirectional data bus requires careful state management:

// During memory read cycles:
if (cycle == FETCH || instr_type == LOAD) {
    // Drive MRD signal, read from d[0:7]
    outputs[MRD_PIN] = LEVEL_ONE
    data_byte = read_data_bus(inputs)
}

// During memory write cycles:
if (instr_type == STORE) {
    // Drive data bus with value to write
    drive_data_bus(outputs, value)
}

Instruction Timing

Most instructions complete in 2 machine cycles (16 clock periods), but some multi-byte instructions take 3 cycles. The model tracks cycle count per instruction to accurately model timing:

cycle_count = instruction_cycles[opcode]
// Update state code outputs based on cycle phase
sc0 = (current_cycle == 0) ? LEVEL_ZERO : LEVEL_ONE
sc1 = (current_cycle == 1) ? LEVEL_ONE : LEVEL_ZERO

System Integration

Building a Complete System

The CDP1802 behavioral model integrates with other circuit components to create a complete computer system:

!LOGICAL
* Top-level system with 1802 CPU
type=computer_system i=clock,reset o=output_port[7:0]

* CPU (behavioral model)
p=cpu t=cdp1802 i=clock,reset,wait_n,pause_n,irq,ef1,ef2,ef3,ef4 $
    b=data_bus o=addr_bus,q,sc0,sc1,tpa,tpb,mrd composition=behavioral

* ROM for program storage (4KB)
p=rom t=rom i=cs,re,we,ae,addr[11:0] b=data_bus size=4096

* RAM for data storage (1KB)
p=ram t=rama i=cs,re,we,clock,addr[9:0],data_in[7:0] o=data[7:0]

* Address decoder logic (determines ROM vs RAM access)
p=decode t=address_decoder i=addr_bus[15:12] o=rom_cs,ram_cs

* I/O peripherals connected to EF flags
p=uart t=uart16550 i=clock,data_in b=data_bus o=ef1_ready
p=timer t=timer8bit i=clock,reset o=ef2_tick

Memory Initialization

Load the processor's program into ROM using SIMIC's memory initialization directives:

>>: define file=computer_system
>>: get type=computer_system
>>: load rom file=program.hex format=intel

Simulation and Debugging

The behavioral model's state code outputs (SC0, SC1) help track execution progress:

>>: simulate
>>: print cpu.sc0,cpu.sc1,cpu.ma  # Monitor fetch/execute and address
>>: break cpu.ma=0x0100            # Break when PC reaches address 0x0100
>>: continue

Benefits of Behavioral Modeling

Simulation Speed

Executes instructions in nanoseconds of simulation time, compared to milliseconds required for gate-level logic. Enables running complete firmware through simulation.

Functional Accuracy

Implements exact instruction cycle behavior as defined in the datasheet. All 91 instructions produce architecturally correct results verified against hardware.

System-Level Verification

Validates firmware running on the processor in the context of the complete system, including memory, peripherals, and I/O devices.

Mixed Abstraction

Combine behavioral CPU with gate-level peripherals. Critical custom logic can be verified at gate level while processor remains fast behavioral model.