module mcu_top (
    input clk,
    input reset,

    n64_scb.controller n64_scb,
    dd_scb.controller dd_scb,
    usb_scb.controller usb_scb,
    dma_scb.controller usb_dma_scb,
    sd_scb.controller sd_scb,
    dma_scb.controller sd_dma_scb,
    flash_scb.controller flash_scb,
    vendor_scb.controller vendor_scb,

    fifo_bus.controller fifo_bus,
    mem_bus.controller mem_bus,

    input sd_det,
    input button,

    output logic mcu_int,
    input mcu_clk,
    input mcu_cs,
    input mcu_mosi,
    output mcu_miso
);

    // Button input synchronization

    logic [2:0] sd_det_ff;
    logic [2:0] button_ff;

    always_ff @(posedge clk) begin
        sd_det_ff <= {sd_det_ff[1:0], sd_det};
        button_ff <= {button_ff[1:0], button};
    end


    // MCU <-> FPGA transport

    logic frame_start;
    logic data_ready;
    logic [7:0] rdata;
    logic [7:0] wdata;

    mcu_spi mcu_spi_inst (
        .clk(clk),
        .reset(reset),

        .frame_start(frame_start),
        .data_ready(data_ready),
        .rx_data(rdata),
        .tx_data(wdata),

        .mcu_clk(mcu_clk),
        .mcu_cs(mcu_cs),
        .mcu_mosi(mcu_mosi),
        .mcu_miso(mcu_miso)
    );


    // Protocol controller

    const bit [7:0] FPGA_ID = 8'h64;

    typedef enum bit [1:0] {
        PHASE_CMD,
        PHASE_ADDRESS,
        PHASE_DATA,
        PHASE_NOP
    } phase_e;

    typedef enum bit [7:0] {
        CMD_IDENTIFY,
        CMD_REG_READ,
        CMD_REG_WRITE,
        CMD_MEM_READ,
        CMD_MEM_WRITE,
        CMD_USB_STATUS,
        CMD_USB_READ,
        CMD_USB_WRITE
    } cmd_e;

    phase_e phase;
    cmd_e cmd;

    logic [1:0] counter;
    logic [7:0] address;

    logic reg_read;
    logic reg_write;
    logic [31:0] reg_rdata;
    logic [31:0] reg_wdata;

    logic mem_read;
    logic mem_write;
    logic [15:0] mem_rdata;
    logic [15:0] mem_wdata;
    logic mem_word_select;

    always_ff @(posedge clk) begin
        fifo_bus.rx_read <= 1'b0;
        fifo_bus.tx_write <= 1'b0;

        reg_read <= 1'b0;
        reg_write <= 1'b0;

        mem_read <= 1'b0;
        mem_write <= 1'b0;

        if (reset) begin
        end else begin
            if (frame_start) begin
                counter <= 2'd0;
                phase <= PHASE_CMD;
            end

            if (reg_read || reg_write || (mem_word_select && (mem_read || mem_write))) begin
                address <= address + 1'd1;
            end

            if (data_ready) begin
                case (phase)
                    PHASE_CMD: begin
                        cmd <= cmd_e'(rdata);
                        phase <= PHASE_ADDRESS;

                        if (rdata == CMD_USB_STATUS) begin
                            phase <= PHASE_NOP;
                        end

                        if (rdata == CMD_USB_READ) begin
                            fifo_bus.rx_read <= 1'b1;
                            phase <= PHASE_DATA;
                        end

                        if (rdata == CMD_USB_WRITE) begin
                            phase <= PHASE_DATA;
                        end
                    end

                    PHASE_ADDRESS: begin
                        address <= rdata;
                        phase <= PHASE_DATA;

                        if (cmd == CMD_REG_READ) begin
                            reg_read <= 1'b1;
                        end

                        if (cmd == CMD_MEM_READ) begin
                            mem_read <= 1'b1;
                            mem_word_select <= 1'b0;
                        end
                    end

                    PHASE_DATA: begin
                        counter <= counter + 1'd1;

                        if (cmd == CMD_REG_READ) begin
                            if (counter == 2'd3) begin
                                reg_read <= 1'd1;
                            end
                        end

                        if (cmd == CMD_REG_WRITE) begin
                            case (counter)
                                2'd0: reg_wdata[7:0] <= rdata;
                                2'd1: reg_wdata[15:8] <= rdata;
                                2'd2: reg_wdata[23:16] <= rdata;
                                2'd3: reg_wdata[31:24] <= rdata;
                            endcase
                            if (counter == 2'd3) begin
                                reg_write <= 1'd1;
                            end
                        end

                        if (cmd == CMD_MEM_READ) begin
                            if (counter[0]) begin
                                mem_read <= 1'b1;
                                mem_word_select <= ~mem_word_select;
                            end
                        end

                        if (cmd == CMD_MEM_WRITE) begin
                            case (counter[0])
                                1'd0: mem_wdata[15:8] <= rdata;
                                1'd1: mem_wdata[7:0] <= rdata;
                            endcase
                            if (counter[0]) begin
                                mem_write <= 1'b1;
                                mem_word_select <= counter[1];
                            end
                        end

                        if (cmd == CMD_USB_READ) begin
                            phase <= PHASE_NOP;
                        end

                        if (cmd == CMD_USB_WRITE) begin
                            fifo_bus.tx_write <= 1'b1;
                            fifo_bus.tx_wdata <= rdata;
                            phase <= PHASE_NOP;
                        end
                    end

                    PHASE_NOP: begin end
                endcase
            end
        end
    end

    always_comb begin
        wdata = 8'h00;

        case (cmd)
            CMD_IDENTIFY: begin
                wdata = FPGA_ID;
            end

            CMD_REG_READ: begin
                case (counter)
                    2'd0: wdata = reg_rdata[7:0];
                    2'd1: wdata = reg_rdata[15:8];
                    2'd2: wdata = reg_rdata[23:16];
                    2'd3: wdata = reg_rdata[31:24];
                endcase
            end

            CMD_REG_WRITE: begin
                wdata = 8'h00;
            end

            CMD_MEM_READ: begin
                case (counter[0])
                    1'd0: wdata = mem_rdata[15:8];
                    1'd1: wdata = mem_rdata[7:0];
                endcase
            end

            CMD_MEM_WRITE: begin
                wdata = 8'h00;
            end

            CMD_USB_STATUS: begin
                wdata = {6'd0, ~fifo_bus.tx_full, ~fifo_bus.rx_empty};
            end

            CMD_USB_READ: begin
                wdata = fifo_bus.rx_rdata;
            end

            CMD_USB_WRITE: begin
                wdata = 8'h00;
            end
        endcase
    end


    // Mem bus controller

    logic [15:0] mem_buffer [0:511];
    
    logic mem_start;
    logic mem_stop;
    logic mem_direction;    
    logic [8:0] mem_length;
    logic [31:0] mem_address;

    logic mem_busy;
    logic mem_stop_pending;
    logic [8:0] mem_counter;

    always_ff @(posedge clk) begin
        if (reset) begin
            mem_busy <= 1'b0;
            mem_stop_pending <= 1'b0;
            mem_bus.request <= 1'b0;
        end else begin
            if (mem_read) begin
                mem_rdata <= mem_buffer[{address, mem_word_select}];
            end

            if (mem_write) begin
                mem_buffer[{address, mem_word_select}] <= mem_wdata;
            end

            if (mem_stop) begin
                mem_stop_pending <= mem_busy;
            end else if (mem_start && !mem_busy) begin
                mem_bus.write <= mem_direction;
                mem_bus.address <= mem_address;
                mem_busy <= 1'b1;
                mem_counter <= 9'd0;
            end

            if (mem_busy) begin
                if (!mem_bus.request) begin
                    mem_bus.request <= 1'b1;
                    mem_bus.wdata <= mem_buffer[mem_counter];
                end

                if (mem_bus.ack) begin
                    mem_bus.request <= 1'b0;
                    mem_bus.address <= mem_bus.address + 2'd2;
                    mem_counter <= mem_counter + 1'd1;
                    if (!mem_bus.write) begin
                        mem_buffer[mem_counter] <= mem_bus.rdata;
                    end
                    if ((mem_counter == mem_length) || mem_stop_pending) begin
                        mem_busy <= 1'b0;
                        mem_stop_pending <= 1'b0;
                    end
                end
            end
        end
    end

    always_comb begin
        mem_bus.wmask = 2'b11;
    end


    // Register list

    typedef enum bit [7:0] {
        REG_MEM_ADDRESS,
        REG_MEM_SCR,
        REG_USB_SCR,
        REG_USB_DMA_ADDRESS,
        REG_USB_DMA_LENGTH,
        REG_USB_DMA_SCR,
        REG_CFG_SCR,
        REG_CFG_DATA_0,
        REG_CFG_DATA_1,
        REG_CFG_CMD,
        REG_CFG_IDENTIFIER,
        REG_FLASHRAM_SCR,
        REG_FLASH_SCR,
        REG_RTC_SCR,
        REG_RTC_TIME_0,
        REG_RTC_TIME_1,
        REG_SD_SCR,
        REG_SD_ARG,
        REG_SD_CMD,
        REG_SD_RSP_0,
        REG_SD_RSP_1,
        REG_SD_RSP_2,
        REG_SD_RSP_3,
        REG_SD_DAT,
        REG_SD_DMA_ADDRESS,
        REG_SD_DMA_LENGTH,
        REG_SD_DMA_SCR,
        REG_DD_SCR,
        REG_DD_CMD_DATA,
        REG_DD_HEAD_TRACK,
        REG_DD_SECTOR_INFO,
        REG_DD_DRIVE_ID,
        REG_SAVE_COUNT,
        REG_VENDOR_SCR,
        REG_VENDOR_DATA,
        REG_DEBUG_0,
        REG_DEBUG_1
    } reg_address_e;

    logic bootloader_skip;

    assign n64_scb.cfg_identifier = 32'h53437632;

    logic dd_bm_ack;


    // Register read logic

    always_ff @(posedge clk) begin
        if (reg_read) begin
            reg_rdata <= 32'd0;

            case (address)
                REG_MEM_ADDRESS: begin
                    reg_rdata <= mem_address;
                end

                REG_MEM_SCR: begin
                    reg_rdata <= {
                        28'd0,
                        mem_busy,
                        3'b000
                    };
                end

                REG_USB_SCR: begin
                    reg_rdata <= {
                        2'd0,
                        usb_scb.pwrsav,
                        usb_scb.reset_state,
                        usb_scb.tx_count,
                        usb_scb.rx_count,
                        2'b00,
                        usb_scb.reset_pending,
                        ~fifo_bus.tx_full,
                        ~fifo_bus.rx_empty,
                        1'b0
                    };
                end

                REG_USB_DMA_ADDRESS: begin
                    reg_rdata <= {
                        5'd0,
                        usb_dma_scb.starting_address
                    };
                end

                REG_USB_DMA_LENGTH: begin
                    reg_rdata <= {
                        5'd0,
                        usb_dma_scb.transfer_length
                    };
                end

                REG_USB_DMA_SCR: begin
                    reg_rdata <= {
                        28'd0,
                        usb_dma_scb.busy,
                        usb_dma_scb.direction,
                        2'b00
                    };
                end

                REG_CFG_SCR: begin
                    reg_rdata <= {
                        ~button_ff[2],
                        19'd0,
                        n64_scb.rom_extended_enabled,
                        n64_scb.eeprom_16k_mode,
                        n64_scb.eeprom_enabled,
                        n64_scb.ddipl_enabled,
                        n64_scb.dd_enabled,
                        n64_scb.flashram_enabled,
                        n64_scb.sram_banked,
                        n64_scb.sram_enabled,
                        n64_scb.rom_shadow_enabled,
                        n64_scb.rom_write_enabled,
                        bootloader_skip,
                        n64_scb.bootloader_enabled
                    };
                end

                REG_CFG_DATA_0: begin
                    reg_rdata <= n64_scb.cfg_rdata[0];
                end

                REG_CFG_DATA_1: begin
                    reg_rdata <= n64_scb.cfg_rdata[1];
                end

                REG_CFG_CMD: begin
                    reg_rdata <= {
                        23'd0,
                        n64_scb.cfg_pending,
                        n64_scb.cfg_cmd
                    };
                end

                REG_CFG_IDENTIFIER: begin
                    reg_rdata <= n64_scb.cfg_identifier;
                end

                REG_FLASHRAM_SCR: begin
                    reg_rdata <= {
                        18'd0,
                        n64_scb.flashram_write_or_erase,
                        n64_scb.flashram_sector_or_all,
                        n64_scb.flashram_sector,
                        n64_scb.flashram_pending,
                        1'b0
                    };
                end

                REG_FLASH_SCR: begin
                    reg_rdata <= {
                        31'd0,
                        flash_scb.erase_pending
                    };
                end

                REG_RTC_SCR: begin
                    reg_rdata <= {
                        24'h525443,
                        7'd0,
                        n64_scb.rtc_pending
                    };
                end

                REG_RTC_TIME_0: begin
                    reg_rdata <= {
                        5'd0, n64_scb.rtc_rdata[28:26],
                        2'd0, n64_scb.rtc_rdata[19:14],
                        1'd0, n64_scb.rtc_rdata[13:7],
                        1'd0, n64_scb.rtc_rdata[6:0]
                    };
                end

                REG_RTC_TIME_1: begin
                    reg_rdata <= {
                        8'd0,
                        n64_scb.rtc_rdata[41:34],
                        3'd0, n64_scb.rtc_rdata[33:29],
                        2'd0, n64_scb.rtc_rdata[25:20]
                    };
                end

                REG_SD_SCR: begin
                    reg_rdata <= {
                        4'd0,
                        sd_scb.tx_count,
                        sd_scb.rx_count,
                        ~sd_det_ff[2],
                        sd_scb.card_busy,
                        sd_scb.cmd_error,
                        sd_scb.cmd_busy,
                        sd_scb.clock_mode
                    };
                end

                REG_SD_ARG: begin
                    reg_rdata <= sd_scb.cmd_arg;
                end

                REG_SD_CMD: begin
                    reg_rdata <= {
                        22'd0,
                        sd_scb.cmd_ignore_crc,
                        sd_scb.cmd_long_response,
                        sd_scb.cmd_reserved_response,
                        sd_scb.cmd_skip_response,
                        sd_scb.cmd_index
                    };
                end

                REG_SD_RSP_0: begin
                    reg_rdata <= sd_scb.cmd_rsp[31:0];
                end

                REG_SD_RSP_1: begin
                    reg_rdata <= sd_scb.cmd_rsp[63:32];
                end

                REG_SD_RSP_2: begin
                    reg_rdata <= sd_scb.cmd_rsp[95:64];
                end

                REG_SD_RSP_3: begin
                    reg_rdata <= sd_scb.cmd_rsp[127:96];
                end

                REG_SD_DAT: begin
                    reg_rdata <= {
                        18'd0,
                        sd_scb.dat_error,
                        sd_scb.dat_busy,
                        12'd0
                    };
                end

                REG_SD_DMA_ADDRESS: begin
                    reg_rdata <= {
                        5'd0,
                        sd_dma_scb.starting_address
                    };
                end

                REG_SD_DMA_LENGTH: begin
                    reg_rdata <= {
                        5'd0,
                        sd_dma_scb.transfer_length
                    };
                end

                REG_SD_DMA_SCR: begin
                    reg_rdata <= {
                        28'd0,
                        sd_dma_scb.busy,
                        sd_dma_scb.direction,
                        2'b00
                    };
                end

                REG_DD_SCR: begin
                    reg_rdata <= {
                        14'd0,
                        dd_bm_ack,
                        dd_scb.bm_micro_error,
                        dd_scb.bm_transfer_c2,
                        dd_scb.bm_transfer_data,
                        dd_scb.bm_transfer_blocks,
                        dd_scb.bm_transfer_mode,
                        1'b0,
                        dd_scb.bm_stop_pending,
                        1'b0,
                        dd_scb.bm_start_pending,
                        dd_scb.disk_changed,
                        dd_scb.disk_inserted,
                        1'b0,
                        dd_scb.bm_pending,
                        1'b0,
                        dd_scb.cmd_pending,
                        1'b0,
                        dd_scb.hard_reset
                    };
                end

                REG_DD_CMD_DATA: begin
                    reg_rdata <= {8'd0, dd_scb.cmd, dd_scb.data};
                end

                REG_DD_HEAD_TRACK: begin
                    reg_rdata <= {18'd0, dd_scb.index_lock, dd_scb.head_track};
                end

                REG_DD_SECTOR_INFO: begin
                    reg_rdata <= {
                        dd_scb.sectors_in_block,
                        dd_scb.sector_size_full,
                        dd_scb.sector_size,
                        dd_scb.sector_num
                    };
                end

                REG_SAVE_COUNT: begin
                    reg_rdata <= {16'd0, n64_scb.save_count};
                end

                REG_VENDOR_SCR: begin
                    reg_rdata <= vendor_scb.control_rdata;
                end

                REG_VENDOR_DATA: begin
                    reg_rdata <= vendor_scb.data_rdata;
                end

                REG_DEBUG_0: begin
                    reg_rdata <= n64_scb.pi_debug[31:0];
                end

                REG_DEBUG_1: begin
                    reg_rdata <= {
                        28'd0,
                        n64_scb.pi_debug[35:32]
                    };
                end
            endcase
        end
    end


    // Register write logic

    always_ff @(posedge clk) begin
        mem_start <= 1'b0;
        mem_stop <= 1'b0;

        usb_scb.write_buffer_flush <= 1'b0;
        usb_scb.reset_ack <= 1'b0;
        usb_scb.fifo_flush <= 1'b0;

        usb_dma_scb.start <= 1'b0;
        usb_dma_scb.stop <= 1'b0;

        sd_scb.cmd_start <= 1'b0;
        sd_scb.dat_fifo_flush <= 1'b0;
        sd_scb.dat_start_write <= 1'b0;
        sd_scb.dat_start_read <= 1'b0;
        sd_scb.dat_stop <= 1'b0;

        sd_dma_scb.start <= 1'b0;
        sd_dma_scb.stop <= 1'b0;

        n64_scb.cfg_done <= 1'b0;
        n64_scb.cfg_error <= 1'b0;
        n64_scb.cfg_irq <= 1'b0;

        n64_scb.flashram_done <= 1'b0;

        n64_scb.rtc_done <= 1'b0;

        dd_scb.hard_reset_clear <= 1'b0;
        dd_scb.cmd_ready <= 1'b0;
        dd_scb.bm_start_clear <= 1'b0;
        dd_scb.bm_stop_clear <= 1'b0;
        dd_scb.bm_clear <= 1'b0;
        dd_scb.bm_ready <= 1'b0;

        vendor_scb.control_valid <= 1'b0;

        if (n64_scb.n64_nmi) begin
            n64_scb.bootloader_enabled <= !bootloader_skip;
        end

        if (flash_scb.erase_done) begin
            flash_scb.erase_pending <= 1'b0;
        end

        if (dd_scb.bm_interrupt_ack) begin
            dd_bm_ack <= 1'b1;
        end

        if (reset) begin
            mcu_int <= 1'b0;
            sd_scb.clock_mode <= 2'd0;
            n64_scb.rom_extended_enabled <= 1'b0;
            n64_scb.eeprom_16k_mode <= 1'b0;
            n64_scb.eeprom_enabled <= 1'b0;
            n64_scb.dd_enabled <= 1'b0;
            n64_scb.ddipl_enabled <= 1'b0;
            n64_scb.flashram_enabled <= 1'b0;
            n64_scb.sram_banked <= 1'b0;
            n64_scb.sram_enabled <= 1'b0;
            n64_scb.rom_shadow_enabled <= 1'b0;
            n64_scb.rom_write_enabled <= 1'b0;
            bootloader_skip <= 1'b0;
            n64_scb.bootloader_enabled <= 1'b1;
            flash_scb.erase_pending <= 1'b0;
            dd_bm_ack <= 1'b0;
            n64_scb.rtc_wdata_valid <= 1'b0;
        end else if (reg_write) begin
            case (address)
                REG_MEM_ADDRESS: begin
                    mem_address <= reg_wdata;
                end

                REG_MEM_SCR: begin
                    {
                        mem_length,
                        mem_direction,
                        mem_stop,
                        mem_start
                    } <= {(reg_wdata[14:5] - 1'd1), reg_wdata[2:0]};
                end

                REG_USB_SCR: begin
                    {
                        usb_scb.write_buffer_flush,
                        usb_scb.reset_ack,
                        usb_scb.fifo_flush
                    } <= {reg_wdata[5:4], reg_wdata[0]};
                end

                REG_USB_DMA_ADDRESS: begin
                    usb_dma_scb.starting_address <= reg_wdata[26:0];
                end

                REG_USB_DMA_LENGTH: begin
                    usb_dma_scb.transfer_length <= reg_wdata[26:0];
                end

                REG_USB_DMA_SCR: begin
                    {
                        usb_dma_scb.direction,
                        usb_dma_scb.stop,
                        usb_dma_scb.start
                    } <= reg_wdata[2:0];
                end

                REG_CFG_SCR: begin
                    {
                        n64_scb.rom_extended_enabled,
                        n64_scb.eeprom_16k_mode,
                        n64_scb.eeprom_enabled,
                        n64_scb.ddipl_enabled,
                        n64_scb.dd_enabled,
                        n64_scb.flashram_enabled,
                        n64_scb.sram_banked,
                        n64_scb.sram_enabled,
                        n64_scb.rom_shadow_enabled,
                        n64_scb.rom_write_enabled,
                        bootloader_skip,
                        n64_scb.bootloader_enabled
                    } <= reg_wdata[11:0];
                end

                REG_CFG_DATA_0: begin
                    n64_scb.cfg_wdata[0] <= reg_wdata;
                end

                REG_CFG_DATA_1: begin
                    n64_scb.cfg_wdata[1] <= reg_wdata;
                end

                REG_CFG_CMD: begin
                    {
                        n64_scb.cfg_irq,
                        n64_scb.cfg_error,
                        n64_scb.cfg_done
                    } <= reg_wdata[11:9];
                end

                REG_FLASHRAM_SCR: begin
                    n64_scb.flashram_done <= reg_wdata[0];
                end

                REG_FLASH_SCR: begin
                    flash_scb.erase_pending <= 1'b1;
                    flash_scb.erase_block <= reg_wdata[23:16];
                end

                REG_RTC_SCR: begin
                    n64_scb.rtc_done <= reg_wdata[1];
                end

                REG_RTC_TIME_0: begin
                    n64_scb.rtc_wdata_valid <= 1'b0;
                    n64_scb.rtc_wdata[28:26] <= reg_wdata[26:24];
                    n64_scb.rtc_wdata[19:14] <= reg_wdata[21:16];
                    n64_scb.rtc_wdata[13:7] <= reg_wdata[14:8];
                    n64_scb.rtc_wdata[6:0] <= reg_wdata[6:0];
                end

                REG_RTC_TIME_1: begin
                    n64_scb.rtc_wdata_valid <= 1'b1;
                    n64_scb.rtc_wdata[41:34] <= reg_wdata[23:16];
                    n64_scb.rtc_wdata[33:29] <= reg_wdata[12:8];
                    n64_scb.rtc_wdata[25:20] <= reg_wdata[5:0];
                end

                REG_SD_SCR: begin
                    sd_scb.clock_mode <= reg_wdata[1:0];
                end

                REG_SD_ARG: begin
                    sd_scb.cmd_arg <= reg_wdata;
                end

                REG_SD_CMD: begin
                    sd_scb.cmd_start <= 1'b1;
                    sd_scb.cmd_ignore_crc <= reg_wdata[9];
                    sd_scb.cmd_long_response <= reg_wdata[8];
                    sd_scb.cmd_reserved_response <= reg_wdata[7];
                    sd_scb.cmd_skip_response <= reg_wdata[6];
                    sd_scb.cmd_index <= reg_wdata[5:0];
                end

                REG_SD_DAT: begin
                    sd_scb.dat_blocks <= reg_wdata[11:4];
                    sd_scb.dat_stop <= reg_wdata[3];
                    sd_scb.dat_start_read <= reg_wdata[2];
                    sd_scb.dat_start_write <= reg_wdata[1];
                    sd_scb.dat_fifo_flush <= reg_wdata[0];
                end

                REG_SD_DMA_ADDRESS: begin
                    sd_dma_scb.starting_address <= reg_wdata[26:0];
                end

                REG_SD_DMA_LENGTH: begin
                    sd_dma_scb.transfer_length <= reg_wdata[26:0];
                end

                REG_SD_DMA_SCR: begin
                    {
                        sd_dma_scb.direction,
                        sd_dma_scb.stop,
                        sd_dma_scb.start
                    } <= reg_wdata[2:0];
                end

                REG_DD_SCR: begin
                    dd_scb.bm_clear <= reg_wdata[19];
                    if (reg_wdata[18]) begin
                        dd_bm_ack <= 1'b0;
                    end
                    dd_scb.bm_micro_error <= reg_wdata[16];
                    dd_scb.bm_transfer_c2 <= reg_wdata[15];
                    dd_scb.bm_transfer_data <= reg_wdata[14];
                    dd_scb.bm_stop_clear <= reg_wdata[11];
                    dd_scb.bm_start_clear <= reg_wdata[9];
                    dd_scb.disk_changed <= reg_wdata[7];
                    dd_scb.disk_inserted <= reg_wdata[6];
                    dd_scb.bm_ready <= reg_wdata[5];
                    dd_scb.cmd_ready <= reg_wdata[3];
                    dd_scb.hard_reset_clear <= reg_wdata[1];
                end

                REG_DD_CMD_DATA: begin
                    dd_scb.cmd_data <= reg_wdata[15:0];
                end

                REG_DD_HEAD_TRACK: begin
                    {dd_scb.index_lock, dd_scb.head_track} <= reg_wdata[13:0];
                end

                REG_DD_DRIVE_ID: begin
                    dd_scb.drive_id <= reg_wdata[15:0];
                end

                REG_VENDOR_SCR: begin
                    vendor_scb.control_valid <= 1'b1;
                    vendor_scb.control_wdata <= reg_wdata;
                end

                REG_VENDOR_DATA: begin
                    vendor_scb.data_wdata <= reg_wdata;
                end
            endcase
        end
    end

endmodule
