mirror of
https://github.com/Polprzewodnikowy/SummerCart64.git
synced 2024-11-23 06:19:16 +01:00
754 lines
22 KiB
Systemverilog
754 lines
22 KiB
Systemverilog
|
module mcu_top (
|
||
|
input clk,
|
||
|
input reset,
|
||
|
|
||
|
usb_scb.controller usb_scb,
|
||
|
dma_scb.controller usb_dma_scb,
|
||
|
sd_scb.controller sd_scb,
|
||
|
dma_scb.controller sd_dma_scb,
|
||
|
n64_scb.controller n64_scb,
|
||
|
flash_scb.controller flash_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_FLASHRAM_READ,
|
||
|
CMD_EEPROM_READ,
|
||
|
CMD_EEPROM_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;
|
||
|
|
||
|
n64_scb.eeprom_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 (n64_scb.eeprom_write) begin
|
||
|
n64_scb.eeprom_address <= n64_scb.eeprom_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
|
||
|
|
||
|
if (cmd == CMD_FLASHRAM_READ) begin
|
||
|
n64_scb.flashram_buffer_address <= rdata[6:1];
|
||
|
counter <= {1'b0, rdata[0]};
|
||
|
end
|
||
|
|
||
|
if ((cmd == CMD_EEPROM_READ) || (cmd == CMD_EEPROM_WRITE)) begin
|
||
|
n64_scb.eeprom_address <= {rdata, 3'd0};
|
||
|
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
|
||
|
|
||
|
if (cmd == CMD_FLASHRAM_READ) begin
|
||
|
if (counter[0]) begin
|
||
|
n64_scb.flashram_buffer_address <= n64_scb.flashram_buffer_address + 1'd1;
|
||
|
end
|
||
|
end
|
||
|
|
||
|
if (cmd == CMD_EEPROM_READ) begin
|
||
|
n64_scb.eeprom_address <= n64_scb.eeprom_address + 1'd1;
|
||
|
end
|
||
|
|
||
|
if (cmd == CMD_EEPROM_WRITE) begin
|
||
|
n64_scb.eeprom_write <= 1'b1;
|
||
|
n64_scb.eeprom_wdata <= rdata;
|
||
|
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
|
||
|
|
||
|
CMD_FLASHRAM_READ: begin
|
||
|
case (counter[0])
|
||
|
1'd0: wdata = n64_scb.flashram_buffer_rdata[15:8];
|
||
|
1'd1: wdata = n64_scb.flashram_buffer_rdata[7:0];
|
||
|
endcase
|
||
|
end
|
||
|
|
||
|
CMD_EEPROM_READ: begin
|
||
|
wdata = n64_scb.eeprom_rdata;
|
||
|
end
|
||
|
|
||
|
CMD_EEPROM_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_STATUS,
|
||
|
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_VERSION,
|
||
|
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_address_e;
|
||
|
|
||
|
logic bootloader_skip;
|
||
|
|
||
|
assign n64_scb.cfg_version = 32'h53437632;
|
||
|
|
||
|
|
||
|
// Register read logic
|
||
|
|
||
|
always_ff @(posedge clk) begin
|
||
|
if (reg_read) begin
|
||
|
reg_rdata <= 32'd0;
|
||
|
|
||
|
case (address)
|
||
|
REG_STATUS: begin
|
||
|
reg_rdata <= {
|
||
|
24'd0,
|
||
|
sd_det_ff[2],
|
||
|
~fifo_bus.tx_full,
|
||
|
~fifo_bus.rx_empty,
|
||
|
n64_scb.flashram_pending,
|
||
|
n64_scb.cfg_pending,
|
||
|
usb_dma_scb.busy,
|
||
|
usb_scb.reset_pending,
|
||
|
button_ff[2]
|
||
|
};
|
||
|
end
|
||
|
|
||
|
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 <= {
|
||
|
28'd0,
|
||
|
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 <= {
|
||
|
22'd0,
|
||
|
n64_scb.eeprom_16k_mode,
|
||
|
n64_scb.eeprom_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 <= {
|
||
|
24'd0,
|
||
|
n64_scb.cfg_cmd
|
||
|
};
|
||
|
end
|
||
|
|
||
|
REG_CFG_VERSION: begin
|
||
|
reg_rdata <= n64_scb.cfg_version;
|
||
|
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 <= {
|
||
|
31'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 <= {
|
||
|
30'd0,
|
||
|
sd_scb.clock_mode
|
||
|
};
|
||
|
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
|
||
|
endcase
|
||
|
end
|
||
|
end
|
||
|
|
||
|
|
||
|
// Register write logic
|
||
|
|
||
|
logic [31:0] reg_buffer;
|
||
|
|
||
|
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_dma_scb.start <= 1'b0;
|
||
|
sd_dma_scb.stop <= 1'b0;
|
||
|
|
||
|
n64_scb.cfg_done <= 1'b0;
|
||
|
n64_scb.cfg_irq <= 1'b0;
|
||
|
|
||
|
n64_scb.flashram_done <= 1'b0;
|
||
|
|
||
|
n64_scb.rtc_done <= 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 (reset) begin
|
||
|
mcu_int <= 1'b0;
|
||
|
sd_scb.clock_mode <= 2'd0;
|
||
|
n64_scb.eeprom_16k_mode <= 1'b0;
|
||
|
n64_scb.eeprom_enabled <= 1'b0;
|
||
|
n64_scb.dd_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;
|
||
|
end else if (reg_write) begin
|
||
|
case (address)
|
||
|
REG_STATUS: begin end
|
||
|
|
||
|
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.eeprom_16k_mode,
|
||
|
n64_scb.eeprom_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[9: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[2:0];
|
||
|
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
|
||
|
reg_buffer <= reg_wdata;
|
||
|
end
|
||
|
|
||
|
REG_RTC_TIME_1: begin
|
||
|
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];
|
||
|
n64_scb.rtc_wdata[28:26] <= reg_buffer[26:24];
|
||
|
n64_scb.rtc_wdata[19:14] <= reg_buffer[21:16];
|
||
|
n64_scb.rtc_wdata[13:7] <= reg_buffer[14:8];
|
||
|
n64_scb.rtc_wdata[6:0] <= reg_buffer[6:0];
|
||
|
end
|
||
|
|
||
|
REG_SD_SCR: begin
|
||
|
sd_scb.clock_mode <= reg_wdata[1: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
|
||
|
endcase
|
||
|
end
|
||
|
end
|
||
|
|
||
|
endmodule
|