From 30ff67139b3df6783de63ea572cb3341cde98d0e Mon Sep 17 00:00:00 2001 From: Polprzewodnikowy Date: Sat, 28 Aug 2021 17:57:48 +0200 Subject: [PATCH] flashram fully working --- fw/SummerCart64.qsf | 7 +- fw/cpu/controller/process.c | 50 +++++++-- fw/cpu/controller/sys.h | 38 +++++-- fw/rtl/SummerCart64.sv | 4 + fw/rtl/cpu/cpu_flashram.sv | 77 ++++++++++++++ fw/rtl/cpu/cpu_sdram.sv | 2 +- fw/rtl/cpu/cpu_soc.sv | 7 ++ fw/rtl/memory/memory_sdram.sv | 10 +- fw/rtl/n64/n64_flashram.sv | 185 ++++++++++++++++++++++++++++++++++ fw/rtl/n64/n64_soc.sv | 7 +- fw/rtl/system/sc64.sv | 1 + 11 files changed, 359 insertions(+), 29 deletions(-) create mode 100644 fw/rtl/cpu/cpu_flashram.sv create mode 100644 fw/rtl/n64/n64_flashram.sv diff --git a/fw/SummerCart64.qsf b/fw/SummerCart64.qsf index cd12b94..13d94dd 100644 --- a/fw/SummerCart64.qsf +++ b/fw/SummerCart64.qsf @@ -19,7 +19,7 @@ # # Quartus Prime # Version 20.1.1 Build 720 11/11/2020 SJ Lite Edition -# Date created = 03:59:09 August 28, 2021 +# Date created = 17:57:25 August 28, 2021 # # -------------------------------------------------------------------------- # # @@ -58,6 +58,7 @@ set_global_assignment -name SYSTEMVERILOG_FILE picorv32/picorv32.v set_global_assignment -name SYSTEMVERILOG_FILE rtl/cpu/cpu_bus.sv set_global_assignment -name SYSTEMVERILOG_FILE rtl/cpu/cpu_cfg.sv set_global_assignment -name SYSTEMVERILOG_FILE rtl/cpu/cpu_dma.sv +set_global_assignment -name SYSTEMVERILOG_FILE rtl/cpu/cpu_flashram.sv set_global_assignment -name SYSTEMVERILOG_FILE rtl/cpu/cpu_gpio.sv set_global_assignment -name SYSTEMVERILOG_FILE rtl/cpu/cpu_i2c.sv set_global_assignment -name SYSTEMVERILOG_FILE rtl/cpu/cpu_ram.sv @@ -71,6 +72,7 @@ set_global_assignment -name SYSTEMVERILOG_FILE rtl/memory/memory_sdram.sv set_global_assignment -name SYSTEMVERILOG_FILE rtl/n64/n64_bootloader.sv set_global_assignment -name SYSTEMVERILOG_FILE rtl/n64/n64_bus.sv set_global_assignment -name SYSTEMVERILOG_FILE rtl/n64/n64_cfg.sv +set_global_assignment -name SYSTEMVERILOG_FILE rtl/n64/n64_flashram.sv set_global_assignment -name SYSTEMVERILOG_FILE rtl/n64/n64_pi.sv set_global_assignment -name SYSTEMVERILOG_FILE rtl/n64/n64_pi_fifo.sv set_global_assignment -name SYSTEMVERILOG_FILE rtl/n64/n64_sdram.sv @@ -186,7 +188,7 @@ set_global_assignment -name TIMING_ANALYZER_MULTICORNER_ANALYSIS ON # Compiler Assignments # ==================== -set_global_assignment -name OPTIMIZATION_MODE BALANCED +set_global_assignment -name OPTIMIZATION_MODE "HIGH PERFORMANCE EFFORT" # Analysis & Synthesis Assignments # ================================ @@ -200,6 +202,7 @@ set_global_assignment -name VHDL_INPUT_VERSION VHDL_2008 set_global_assignment -name VHDL_SHOW_LMF_MAPPING_MESSAGES OFF set_global_assignment -name VERILOG_INPUT_VERSION SYSTEMVERILOG_2005 set_global_assignment -name VERILOG_SHOW_LMF_MAPPING_MESSAGES OFF +set_global_assignment -name TOP_LEVEL_ENTITY SummerCart64 # Fitter Assignments # ================== diff --git a/fw/cpu/controller/process.c b/fw/cpu/controller/process.c index 42c4ba0..0a6e128 100644 --- a/fw/cpu/controller/process.c +++ b/fw/cpu/controller/process.c @@ -8,7 +8,7 @@ static const uint8_t err_token[3] = { 'E', 'R', 'R' }; static uint8_t save_type = 0; static uint16_t cic_type = 0xFFFF; static uint8_t tv_type = 0xFF; -static volatile uint32_t *save_pointer = &SDRAM + DEFAULT_SAVE_OFFSET; +static uint32_t *save_pointer = (uint32_t *) (SDRAM_BASE + DEFAULT_SAVE_OFFSET); void process_usb (void); void process_cfg (void); @@ -16,9 +16,13 @@ void process_dd (void); void process_si (void); void process_uart (void); void process_rtc (void); +void process_flashram (void); void cfg_set_save_type (uint8_t type); void cfg_update_config (uint32_t *args); +// void print (const char *text); +// void print_02hex (unsigned char number); + void process (void) { while (1) { process_usb(); @@ -27,6 +31,7 @@ void process (void) { process_si(); process_uart(); process_rtc(); + process_flashram(); } } @@ -189,6 +194,32 @@ void process_rtc (void) { } +void process_flashram (void) { + uint32_t scr = FLASHRAM->SCR; + volatile uint32_t *offset_pointer = save_pointer; + size_t length; + + if (scr & FLASHRAM_OPERATION_PENDING) { + if (scr & FLASHRAM_WRITE_OR_ERASE) { + if (scr & FLASHRAM_SECTOR_OR_ALL) { + length = 128 * 1024; + } else { + offset_pointer += 32 * (scr >> FLASHRAM_SECTOR_BIT); + length = 16 * 1024; + } + for (size_t i = 0; i < (length / 4); i++) { + offset_pointer[i] = 0xFFFFFFFF; + } + } else { + offset_pointer += 32 * (scr >> FLASHRAM_SECTOR_BIT); + for (size_t i = 0; i < 32; i++) { + offset_pointer[i] &= FLASHRAM->BUFFER[i]; + } + } + FLASHRAM->SCR = FLASHRAM_OPERATION_DONE; + } +} + void cfg_update_config (uint32_t *args) { switch (args[0]) { case 0: { @@ -232,36 +263,37 @@ void cfg_update_config (uint32_t *args) { void cfg_set_save_type (uint8_t type) { CFG->SCR &= ~(CFG_SCR_FLASHRAM_EN | CFG_SCR_SRAM_BANKED | CFG_SCR_SRAM_EN); + uint32_t save_offset = 0; switch (type) { case 0: { break; } case 1: { - CFG->SAVE_OFFSET = SDRAM_SIZE - 512; + save_offset = SDRAM_SIZE - 512; break; } case 2: { - CFG->SAVE_OFFSET = SDRAM_SIZE - 2048; + save_offset = SDRAM_SIZE - 2048; break; } case 3: { - CFG->SAVE_OFFSET = SDRAM_SIZE - (32 * 1024); + save_offset = SDRAM_SIZE - (32 * 1024); CFG->SCR |= CFG_SCR_SRAM_EN; break; } case 4: { - CFG->SAVE_OFFSET = SDRAM_SIZE - (256 * 1024); + save_offset = SDRAM_SIZE - (256 * 1024); CFG->SCR |= CFG_SCR_FLASHRAM_EN; break; } case 5: { - CFG->SAVE_OFFSET = SDRAM_SIZE - (3 * 32 * 1024); + save_offset = SDRAM_SIZE - (3 * 32 * 1024); CFG->SCR |= CFG_SCR_SRAM_BANKED | CFG_SCR_SRAM_EN; break; } case 6: { - CFG->SAVE_OFFSET = 0x01618000; + save_offset = 0x01608000; CFG->SCR |= CFG_SCR_FLASHRAM_EN; break; } @@ -270,8 +302,10 @@ void cfg_set_save_type (uint8_t type) { } } - save_pointer = &SDRAM + CFG->SAVE_OFFSET; + save_pointer = (uint32_t *) (SDRAM_BASE + save_offset); save_type = type; + + CFG->SAVE_OFFSET = save_offset; } // void print (const char *text) { diff --git a/fw/cpu/controller/sys.h b/fw/cpu/controller/sys.h index 94b8734..1ed8aba 100644 --- a/fw/cpu/controller/sys.h +++ b/fw/cpu/controller/sys.h @@ -6,19 +6,19 @@ #include -#define DEFAULT_SAVE_OFFSET (0x03FE0000) -#define DEFAULT_DD_OFFSET (0x03BE0000) +#define DEFAULT_SAVE_OFFSET (0x03FE0000UL) +#define DEFAULT_DD_OFFSET (0x03BE0000UL) typedef volatile uint8_t io8_t; typedef volatile uint32_t io32_t; -#define RAM_BASE (0x00000000) +#define RAM_BASE (0x00000000UL) #define RAM (*((io32_t *) RAM_BASE)) -#define BOOTLOADER_BASE (0x10000000) +#define BOOTLOADER_BASE (0x10000000UL) #define BOOTLOADER (*((io32_t *) BOOTLOADER_BASE)) @@ -29,7 +29,7 @@ typedef volatile struct gpio_regs { io8_t __padding; } gpio_regs_t; -#define GPIO_BASE (0x20000000) +#define GPIO_BASE (0x20000000UL) #define GPIO ((gpio_regs_t *) GPIO_BASE) @@ -38,7 +38,7 @@ typedef volatile struct i2c_regs { io32_t DR; } i2c_regs_t; -#define I2C_BASE (0x30000000) +#define I2C_BASE (0x30000000UL) #define I2C ((i2c_regs_t *) I2C_BASE) #define I2C_SCR_START (1 << 0) @@ -55,7 +55,7 @@ typedef volatile struct usb_regs { io8_t __padding[3]; } usb_regs_t; -#define USB_BASE (0x40000000) +#define USB_BASE (0x40000000UL) #define USB ((usb_regs_t *) USB_BASE) #define USB_SCR_RXNE (1 << 0) @@ -70,7 +70,7 @@ typedef volatile struct uart_regs { io8_t __padding[3]; } uart_regs_t; -#define UART_BASE (0x50000000) +#define UART_BASE (0x50000000UL) #define UART ((uart_regs_t *) UART_BASE) #define UART_SCR_RXNE (1 << 0) @@ -83,7 +83,7 @@ typedef volatile struct dma_regs { io32_t ID_LEN; } dma_regs_t; -#define DMA_BASE (0x60000000) +#define DMA_BASE (0x60000000UL) #define DMA ((dma_regs_t *) DMA_BASE) #define DMA_SCR_START (1 << 0) @@ -101,7 +101,7 @@ typedef volatile struct cfg_regs { io32_t DATA[3]; } cfg_regs_t; -#define CFG_BASE (0x70000000) +#define CFG_BASE (0x70000000UL) #define CFG ((cfg_regs_t *) CFG_BASE) #define CFG_SCR_SDRAM_SWITCH (1 << 0) @@ -114,9 +114,25 @@ typedef volatile struct cfg_regs { #define CFG_SCR_CPU_READY (1 << 31) -#define SDRAM_BASE (0x80000000) +#define SDRAM_BASE (0x80000000UL) #define SDRAM (*((io32_t *) SDRAM_BASE)) #define SDRAM_SIZE (64 * 1024 * 1024) +typedef volatile struct flashram_regs { + io32_t SCR; + io32_t __padding[31]; + io32_t BUFFER[32]; +} flashram_regs_t; + +#define FLASHRAM_BASE (0x90000000UL) +#define FLASHRAM ((flashram_regs_t *) FLASHRAM_BASE) + +#define FLASHRAM_OPERATION_PENDING (1 << 0) +#define FLASHRAM_OPERATION_DONE (1 << 1) +#define FLASHRAM_WRITE_OR_ERASE (1 << 2) +#define FLASHRAM_SECTOR_OR_ALL (1 << 3) +#define FLASHRAM_SECTOR_BIT (8) + + #endif diff --git a/fw/rtl/SummerCart64.sv b/fw/rtl/SummerCart64.sv index 8d9112a..ccb416a 100644 --- a/fw/rtl/SummerCart64.sv +++ b/fw/rtl/SummerCart64.sv @@ -60,6 +60,8 @@ module SummerCart64 ( if_sdram sdram (); + if_flashram flashram (); + system system_inst ( .sys(sys) ); @@ -75,6 +77,7 @@ module SummerCart64 ( .cfg(cfg), .dma(dma), .sdram(sdram), + .flashram(flashram), .n64_pi_alel(i_n64_pi_alel), .n64_pi_aleh(i_n64_pi_aleh), @@ -99,6 +102,7 @@ module SummerCart64 ( .cfg(cfg), .dma(dma), .sdram(sdram), + .flashram(flashram), .gpio_o(gpio_o), .gpio_i(gpio_i), diff --git a/fw/rtl/cpu/cpu_flashram.sv b/fw/rtl/cpu/cpu_flashram.sv new file mode 100644 index 0000000..f6eb4b5 --- /dev/null +++ b/fw/rtl/cpu/cpu_flashram.sv @@ -0,0 +1,77 @@ +interface if_flashram (); + + logic [4:0] address; + logic [31:0] rdata; + logic [9:0] sector; + logic operation_pending; + logic write_or_erase; + logic sector_or_all; + logic operation_done; + + modport cpu ( + output address, + input rdata, + input sector, + input operation_pending, + input write_or_erase, + input sector_or_all, + output operation_done + ); + + modport flashram ( + input address, + output rdata, + output sector, + output operation_pending, + output write_or_erase, + output sector_or_all, + input operation_done + ); + +endinterface + + +module cpu_flashram ( + if_system.sys sys, + if_cpu_bus bus, + if_flashram.cpu flashram +); + + always_ff @(posedge sys.clk) begin + bus.ack <= 1'b0; + if (bus.request) begin + bus.ack <= 1'b1; + end + end + + always_comb begin + bus.rdata = 32'd0; + if (bus.ack) begin + bus.rdata = { + 14'd0, + flashram.sector, + 4'd0, + flashram.sector_or_all, + flashram.write_or_erase, + 1'b0, + flashram.operation_pending + }; + if (bus.address[7]) begin + bus.rdata = flashram.rdata; + end + end + + flashram.address = bus.address[6:2]; + end + + always_ff @(posedge sys.clk) begin + flashram.operation_done <= 1'b0; + + if (bus.request) begin + if (!bus.address[5] && bus.wmask[0]) begin + flashram.operation_done <= bus.wdata[1]; + end + end + end + +endmodule diff --git a/fw/rtl/cpu/cpu_sdram.sv b/fw/rtl/cpu/cpu_sdram.sv index b1cd3d5..438d691 100644 --- a/fw/rtl/cpu/cpu_sdram.sv +++ b/fw/rtl/cpu/cpu_sdram.sv @@ -46,7 +46,7 @@ module cpu_sdram ( sdram.write = current_word ? &bus.wmask[3:2] : &bus.wmask[1:0]; sdram.address = {1'b0, bus.address[30:2], current_word, 1'b0}; - sdram.wdata = current_word ? bus.wdata[31:16] : bus.wdata[15:0]; + sdram.wdata = current_word ? bus.wdata[15:0] : bus.wdata[31:16]; end always_ff @(posedge sys.clk) begin diff --git a/fw/rtl/cpu/cpu_soc.sv b/fw/rtl/cpu/cpu_soc.sv index 6acdea5..2889149 100644 --- a/fw/rtl/cpu/cpu_soc.sv +++ b/fw/rtl/cpu/cpu_soc.sv @@ -3,6 +3,7 @@ module cpu_soc ( if_config.cpu cfg, if_dma dma, if_sdram.cpu sdram, + if_flashram.cpu flashram, input [7:0] gpio_i, output [7:0] gpio_o, @@ -97,4 +98,10 @@ module cpu_soc ( .sdram(sdram) ); + cpu_flashram cpu_flashram_inst ( + .sys(sys), + .bus(bus.at[sc64::ID_CPU_FLASHRAM].device), + .flashram(flashram) + ); + endmodule diff --git a/fw/rtl/memory/memory_sdram.sv b/fw/rtl/memory/memory_sdram.sv index 0839dc1..06e3e51 100644 --- a/fw/rtl/memory/memory_sdram.sv +++ b/fw/rtl/memory/memory_sdram.sv @@ -114,20 +114,20 @@ module memory_sdram ( end end - logic [15:0] wait_counter; - logic [15:0] refresh_counter; + logic [13:0] wait_counter; + logic [9:0] refresh_counter; logic pending_refresh; always_ff @(posedge sys.clk) begin if (sys.reset || state != next_state) begin - wait_counter <= 16'd0; + wait_counter <= 14'd0; end else begin wait_counter <= wait_counter + 1'd1; end if (sdram_next_cmd == CMD_REF) begin - refresh_counter <= 16'd0; - end else begin + refresh_counter <= 10'd0; + end else if (refresh_counter < 10'h3FF) begin refresh_counter <= refresh_counter + 1'd1; end end diff --git a/fw/rtl/n64/n64_flashram.sv b/fw/rtl/n64/n64_flashram.sv new file mode 100644 index 0000000..92b0964 --- /dev/null +++ b/fw/rtl/n64/n64_flashram.sv @@ -0,0 +1,185 @@ +module n64_flashram ( + if_system.sys sys, + if_n64_bus bus, + if_config.flashram cfg, + if_flashram.flashram flashram +); + + localparam [31:0] FLASH_TYPE_ID = 32'h1111_8001; + localparam [31:0] FLASH_MODEL_ID = 32'h00C2_001D; + + typedef enum bit [7:0] { + CMD_STATUS_MODE = 8'hD2, + CMD_READID_MODE = 8'hE1, + CMD_READ_MODE = 8'hF0, + CMD_ERASE_SECTOR = 8'h4B, + CMD_ERASE_CHIP = 8'h3C, + CMD_BUFFER_MODE = 8'hB4, + CMD_ERASE_START = 8'h78, + CMD_WRITE_START = 8'hA5 + } e_cmd; + + typedef enum bit [0:0] { + S_IDLE, + S_WAIT + } e_bus_state; + + typedef enum bit [1:0] { + FS_STATUS, + FS_ID, + FS_READ, + FS_BUFFER + } e_flashram_state; + + typedef enum bit [1:0] { + B_WRITE_BUSY, + B_ERASE_BUSY, + B_WRITE_DONE, + B_ERASE_DONE + } e_flashram_status; + + e_bus_state bus_state; + e_flashram_state flashram_state; + logic [3:0] flashram_status; + logic [7:0] flashram_command; + logic flashram_erase_enabled; + + logic [1:0][15:0] write_buffer [0:31]; + logic [1:0] write_buffer_wmask; + + always_comb begin + write_buffer_wmask = 2'b00; + if (bus.request && bus.write && !bus.address[16] && flashram_state == FS_BUFFER) begin + write_buffer_wmask[0] = bus.address[1]; + write_buffer_wmask[1] = !bus.address[1]; + end + end + + always @(posedge sys.clk) begin + flashram.rdata <= {write_buffer[flashram.address][1], write_buffer[flashram.address][0]}; + if (write_buffer_wmask[0]) write_buffer[bus.address[6:2]][0] <= bus.wdata; + if (write_buffer_wmask[1]) write_buffer[bus.address[6:2]][1] <= bus.wdata; + end + + always_comb begin + bus.rdata = 16'd0; + if (bus.ack) begin + if (bus.address[1]) begin + bus.rdata = {12'd0, flashram_status}; + end + if (flashram_state == FS_ID) begin + case (bus.address[2:1]) + 0: bus.rdata = FLASH_TYPE_ID[31:16]; + 1: bus.rdata = FLASH_TYPE_ID[15:0]; + 2: bus.rdata = FLASH_MODEL_ID[31:16]; + 3: bus.rdata = FLASH_MODEL_ID[15:0]; + endcase + end + end + + cfg.flashram_read_mode = flashram_state == FS_READ; + end + + always_ff @(posedge sys.clk) begin + bus.ack <= 1'b0; + + if (sys.reset) begin + bus_state <= S_IDLE; + flashram_state <= FS_STATUS; + flashram_status <= 4'b0000; + flashram_erase_enabled <= 1'b0; + flashram.operation_pending <= 1'b0; + end else begin + if (flashram.operation_done) begin + flashram.operation_pending <= 1'b0; + if (flashram.write_or_erase) begin + flashram_status[B_ERASE_BUSY] <= 1'b0; + flashram_status[B_ERASE_DONE] <= 1'b1; + end else begin + flashram_status[B_WRITE_BUSY] <= 1'b0; + flashram_status[B_WRITE_DONE] <= 1'b1; + end + end + + case (bus_state) + S_IDLE: begin + if (bus.request) begin + bus_state <= S_WAIT; + bus.ack <= 1'b1; + if (bus.write && !flashram.operation_pending) begin + if (bus.address[16]) begin + if (!bus.address[1]) begin + flashram_command <= bus.wdata[15:8]; + end else begin + flashram_erase_enabled <= 1'b0; + + case (flashram_command) + CMD_STATUS_MODE: begin + flashram_state <= FS_STATUS; + end + + CMD_READID_MODE: begin + flashram_state <= FS_ID; + end + + CMD_READ_MODE: begin + flashram_state <= FS_READ; + end + + CMD_ERASE_SECTOR: begin + flashram_state <= FS_STATUS; + flashram_erase_enabled <= 1'b1; + flashram.sector <= bus.wdata[9:0]; + flashram.sector_or_all <= 1'b0; + end + + CMD_ERASE_CHIP: begin + flashram_state <= FS_STATUS; + flashram_erase_enabled <= 1'b1; + flashram.sector <= 10'd0; + flashram.sector_or_all <= 1'b1; + end + + CMD_BUFFER_MODE: begin + flashram_state <= FS_BUFFER; + end + + CMD_ERASE_START: begin + flashram_state <= FS_STATUS; + if (flashram_erase_enabled) begin + flashram_status[B_ERASE_BUSY] <= 1'b1; + flashram_status[B_ERASE_DONE] <= 1'b0; + flashram.operation_pending <= 1'b1; + flashram.write_or_erase <= 1'b1; + end + end + + CMD_WRITE_START: begin + flashram_state <= FS_STATUS; + flashram_status[B_WRITE_BUSY] <= 1'b1; + flashram_status[B_WRITE_DONE] <= 1'b0; + flashram.sector <= bus.wdata[9:0]; + flashram.operation_pending <= 1'b1; + flashram.write_or_erase <= 1'b0; + flashram.sector_or_all <= 1'b0; + end + endcase + end + end else begin + if (flashram_state == FS_STATUS) begin + flashram_status[B_ERASE_DONE] <= bus.wdata[B_ERASE_DONE]; + flashram_status[B_WRITE_DONE] <= bus.wdata[B_WRITE_DONE]; + end + end + end + end + end + + S_WAIT: begin + bus_state <= S_IDLE; + end + endcase + end + end + +endmodule diff --git a/fw/rtl/n64/n64_soc.sv b/fw/rtl/n64/n64_soc.sv index f76d4a3..2c26cb2 100644 --- a/fw/rtl/n64/n64_soc.sv +++ b/fw/rtl/n64/n64_soc.sv @@ -3,6 +3,7 @@ module n64_soc ( if_config cfg, if_dma.memory dma, if_sdram.memory sdram, + if_flashram.flashram flashram, input n64_pi_alel, input n64_pi_aleh, @@ -56,9 +57,11 @@ module n64_soc ( .bus(bus.at[sc64::ID_N64_BOOTLOADER].device) ); - n64_dummy n64_flashram_inst ( + n64_flashram n64_flashram_inst ( .sys(sys), - .bus(bus.at[sc64::ID_N64_FLASHRAM].device) + .bus(bus.at[sc64::ID_N64_FLASHRAM].device), + .cfg(cfg), + .flashram(flashram) ); n64_dummy n64_ddregs_inst ( diff --git a/fw/rtl/system/sc64.sv b/fw/rtl/system/sc64.sv index 71799f4..38d6eea 100644 --- a/fw/rtl/system/sc64.sv +++ b/fw/rtl/system/sc64.sv @@ -19,6 +19,7 @@ package sc64; ID_CPU_DMA, ID_CPU_CFG, ID_CPU_SDRAM, + ID_CPU_FLASHRAM, __ID_CPU_END } e_cpu_id;