Magic‐1 Hardware Initialization Procedure - retrotruestory/M1DEV GitHub Wiki

Magic-1 Hardware Initialization Procedure

Based on the provided Magic-1 source files, here's the hardware initialization procedure sequence:

Magic-1 Hardware Initialization Procedure

1. Initial Reset and Mode Setup

// 1. Initial CPU state after reset:
- Interrupts disabled 
- System mode active
- Paging disabled
- MSW (Machine Status Word) = 0x0000

2. Core System Setup

// From bcrt0.s startup sequence:
_start:
    // Ensure system state
    ld.16   a,0x0000
    copy    msw,a          // Interrupts off, system mode

    // Setup kernel stack
    ld.16   a,stack_start  // stack_start = 0x8000
    copy    sp,a

    // Initialize data pointer
    ld.16   a,dp_start    // dp_start = 0x0000 
    copy    dp,a

3. Device Initialization Sequence

3.1 UART Initialization

void init_uart(t_rs232 *p, unsigned int baud_rate) {
    // Set baud rate
    *p->p_uart_lcr = UART_DLAB_1;
    *p->p_uart_div_lsb = baud_rate & 0xff;
    *p->p_uart_div_msb = (baud_rate >> 8) & 0xff;

    // Configure 8N1 mode
    *p->p_uart_lcr = UART_8N1;

    // Enable FIFO
    *p->p_uart_fcr = (UART_FIFO_ON | UART_FIFO_RESET | UART_FIFO_SIG1);

    // Set modem control
    *p->p_uart_mcr = (UART_DTR | UART_RTS);

    // Clear data
    *p->p_uart_msr;
    *p->p_uart_lsr;
    *p->p_uart_data;

    // Disable interrupts
    *p->p_uart_ier = 0;
}

3.2 RTC Initialization

void init_rtc() {
    unsigned char *p = (unsigned char*) RTC_BASE;
    
    // Disable interrupts
    p[RTC_CE] = RTC_INTERRUPTS_OFF;
    
    // Clear pending interrupts
    p[RTC_CD] = 0;
    
    // Configure clock:
    // - 64ths timing mode
    // - Pulse mode
    // - Enable interrupts (though they're ignored)
    p[RTC_CE] = (RTC_64ths | RTC_PULSE_MODE | RTC_INTERRUPTS_ON);
}

3.3 IDE/Storage Initialization

void ide_reset() {
    // Reset IDE interface
    p = (unsigned char *) CFG_8255;
    *p = WR_IDE_8255;
    
    // Reset control lines
    p = (unsigned char *) IDE_8255_CTL;
    *p = 0;
    
    // Assert reset
    *p = IDE_RESET_LINE;
    // Delay >25us
    // Deassert reset
    *p = 0;
}

void init_ide_info() {
    // Initialize IDE interfaces
    ide_reset();
    
    // Configure master drive
    ide_init(IDE_MASTER, IDE_LBA);
    
    // Configure slave drive
    ide_init(IDE_SLAVE, IDE_LBA);
    
    // Configure CF if present
    cf_init(CF_MASTER, CF_MODE);
}

4. Memory Management Setup

void setup_address_space() {
    // Set up initial page tables
    create_boot_image_address_space(0, FALSE);
    
    // Enable paging
    paging_on();
}

5. Interrupt Vector Setup

_interrupt_vector:
    // Set up interrupt vectors at fixed locations
    defw    unhandled_exception    ; IRQ5 (RTC) 
    defw    unhandled_exception    ; IRQ4 
    defw    unhandled_exception    ; IRQ3 (UART0)
    defw    unhandled_exception    ; IRQ2 (UART1)
    defw    unhandled_exception    ; IRQ1 (IDE)
    defw    unhandled_exception    ; IRQ0
    defw    unhandled_exception    ; DMA
    defw    unhandled_exception    ; SYSCALL

The initialization sequence ensures:

  1. Safe initial CPU state
  2. Working stack and data pointers
  3. Configured I/O devices
  4. Memory management ready
  5. System prepared for OS loading

Based on the Magic-1 specifications, let's implement the hardware initialization sequence in Verilog. This procedure ensures proper reset and initialization of all CPU components.

module magic1_init (
    input wire clk,
    input wire ext_reset_n,
    output reg sys_ready,
    output reg [7:0] init_state
);

    // Initialization states
    localparam [7:0]
        INIT_RESET      = 8'h00,
        INIT_CLOCK      = 8'h01,
        INIT_REGISTERS  = 8'h02,
        INIT_MEMORY     = 8'h03,
        INIT_MMU        = 8'h04,
        INIT_CACHE      = 8'h05,
        INIT_IO         = 8'h06,
        INIT_COMPLETE   = 8'h07;

    // Reset sequence counter
    reg [7:0] reset_counter;
    
    // Initialization sequence
    always @(posedge clk or negedge ext_reset_n) begin
        if (!ext_reset_n) begin
            init_state <= INIT_RESET;
            sys_ready <= 1'b0;
            reset_counter <= 8'h00;
        end else begin
            case (init_state)
                INIT_RESET: begin
                    // Hold reset for 16 cycles
                    if (reset_counter == 8'h0F) begin
                        init_state <= INIT_CLOCK;
                        reset_counter <= 8'h00;
                    end else begin
                        reset_counter <= reset_counter + 1;
                    end
                end
                
                INIT_CLOCK: begin
                    // Initialize clock generation
                    if (reset_counter == 8'h03) begin
                        init_state <= INIT_REGISTERS;
                        reset_counter <= 8'h00;
                    end else begin
                        reset_counter <= reset_counter + 1;
                    end
                end

                INIT_REGISTERS: begin
                    // Clear all registers
                    init_state <= INIT_MEMORY;
                end

                INIT_MEMORY: begin
                    // Initialize memory subsystem
                    init_state <= INIT_MMU;
                end

                INIT_MMU: begin
                    // Setup MMU with default page tables
                    init_state <= INIT_CACHE;
                end

                INIT_CACHE: begin
                    // Invalidate cache
                    init_state <= INIT_IO;
                end

                INIT_IO: begin
                    // Initialize I/O subsystems
                    init_state <= INIT_COMPLETE;
                end

                INIT_COMPLETE: begin
                    sys_ready <= 1'b1;
                end
            endcase
        end
    end

endmodule

To integrate this initialization module with the main system:

module magic1_top (
    input wire ext_clk,
    input wire ext_reset_n,
    // ...other ports...
);

    // System signals
    wire sys_clk;
    wire sys_reset_n;
    wire sys_ready;
    wire [7:0] init_state;

    // Instantiate initialization controller
    magic1_init init_controller (
        .clk(ext_clk),
        .ext_reset_n(ext_reset_n),
        .sys_ready(sys_ready),
        .init_state(init_state)
    );

    // Hold system in reset until initialization complete
    assign sys_reset_n = ext_reset_n & sys_ready;

    // ...rest of system implementation...

endmodule

To test the initialization sequence:

# Compile and run initialization test
cd /testbench
iverilog -g2012 magic1_init_test.v ../rtl/magic1_init.v -o init_test
./init_test

The initialization sequence follows these key steps:

  1. Assert reset for 16 clock cycles
  2. Initialize clock generation
  3. Clear all registers to known state
  4. Initialize memory subsystem
  5. Setup MMU and page tables
  6. Invalidate cache
  7. Initialize I/O subsystems
  8. Signal system ready