diff --git a/fw/SummerCart64.qsf b/fw/SummerCart64.qsf index f35482f..8f8edbf 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 = 23:19:06 October 24, 2021 +# Date created = 00:50:07 October 26, 2021 # # -------------------------------------------------------------------------- # # @@ -58,6 +58,7 @@ set_global_assignment -name SYSTEMVERILOG_FILE ../sw/riscv/build/cpu_bootloader. 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_flash.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 @@ -68,7 +69,6 @@ set_global_assignment -name SYSTEMVERILOG_FILE rtl/cpu/cpu_soc.sv set_global_assignment -name SYSTEMVERILOG_FILE rtl/cpu/cpu_uart.sv set_global_assignment -name SYSTEMVERILOG_FILE rtl/cpu/cpu_usb.sv set_global_assignment -name SYSTEMVERILOG_FILE rtl/cpu/cpu_wrapper.sv -set_global_assignment -name SYSTEMVERILOG_FILE rtl/memory/memory_flash.sv 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 @@ -224,7 +224,6 @@ set_global_assignment -name USE_CONFIGURATION_DEVICE OFF # Signal Tap Assignments # ====================== set_global_assignment -name ENABLE_SIGNALTAP ON -set_global_assignment -name USE_SIGNALTAP_FILE output_files/signaltap.stp # Power Estimation Assignments # ============================ diff --git a/fw/rtl/SummerCart64.sv b/fw/rtl/SummerCart64.sv index 0474b97..48eea35 100644 --- a/fw/rtl/SummerCart64.sv +++ b/fw/rtl/SummerCart64.sv @@ -64,6 +64,8 @@ module SummerCart64 ( if_si si (); + if_flash flash (); + system system_inst ( .sys(sys) ); @@ -81,6 +83,7 @@ module SummerCart64 ( .sdram(sdram), .flashram(flashram), .si(si), + .flash(flash), .n64_pi_alel(i_n64_pi_alel), .n64_pi_aleh(i_n64_pi_aleh), @@ -107,6 +110,7 @@ module SummerCart64 ( .sdram(sdram), .flashram(flashram), .si(si), + .flash(flash), .gpio_o(gpio_o), .gpio_i(gpio_i), diff --git a/fw/rtl/cpu/cpu_flash.sv b/fw/rtl/cpu/cpu_flash.sv new file mode 100644 index 0000000..a7c3b6f --- /dev/null +++ b/fw/rtl/cpu/cpu_flash.sv @@ -0,0 +1,61 @@ +interface if_flash (); + + logic request; + logic ack; + logic write; + logic [31:0] address; + logic [31:0] rdata; + logic [31:0] wdata; + + modport cpu ( + output request, + input ack, + output write, + output address, + input rdata, + output wdata + ); + + modport memory ( + input request, + output ack, + input write, + input address, + output rdata, + input wdata + ); + +endinterface + + +module cpu_flash ( + if_system.sys sys, + if_cpu_bus bus, + if_flash.cpu flash +); + + logic request; + + always_comb begin + bus.ack = flash.ack; + bus.rdata = flash.rdata; + flash.request = bus.request || request; + flash.write = &bus.wmask; + flash.address = bus.address; + flash.wdata = bus.wdata; + end + + always_ff @(posedge sys.clk) begin + if (sys.reset) begin + request <= 1'b0; + end else begin + if (bus.request) begin + request <= 1'b1; + end + if (flash.ack) begin + request <= 1'b0; + end + end + end + +endmodule diff --git a/fw/rtl/cpu/cpu_soc.sv b/fw/rtl/cpu/cpu_soc.sv index 5a9303a..69b4050 100644 --- a/fw/rtl/cpu/cpu_soc.sv +++ b/fw/rtl/cpu/cpu_soc.sv @@ -5,6 +5,7 @@ module cpu_soc ( if_sdram.cpu sdram, if_flashram.cpu flashram, if_si.cpu si, + if_flash.cpu flash, input [7:0] gpio_i, output [7:0] gpio_o, @@ -111,4 +112,10 @@ module cpu_soc ( .si(si) ); + cpu_flash cpu_flash_inst ( + .sys(sys), + .bus(bus.at[sc64::ID_CPU_FLASH].device), + .flash(flash) + ); + endmodule diff --git a/fw/rtl/intel/flash/intel_flash.qsys b/fw/rtl/intel/flash/intel_flash.qsys index 9aca588..ffe595d 100644 --- a/fw/rtl/intel/flash/intel_flash.qsys +++ b/fw/rtl/intel/flash/intel_flash.qsys @@ -7,17 +7,17 @@ description="" tags="INTERNAL_COMPONENT=true" categories="System" /> - @@ -41,10 +41,18 @@ - + + + + + + + + + @@ -68,7 +76,7 @@ - Read only,Read only,Hidden,Read only,Read only + Read and write,Read and write,Hidden,Read and write,Read and write $${FILENAME}_onchip_flash_0 ../sw/n64/build/SummerLoader64.hex diff --git a/fw/rtl/memory/memory_flash.sv b/fw/rtl/memory/memory_flash.sv deleted file mode 100644 index 2aefc25..0000000 --- a/fw/rtl/memory/memory_flash.sv +++ /dev/null @@ -1,76 +0,0 @@ -module memory_flash ( - if_system.sys sys, - - input request, - output ack, - input [31:0] address, - output [15:0] rdata -); - - logic flash_enable; - logic flash_request; - logic flash_busy; - logic flash_ack; - logic [31:0] flash_rdata; - - logic dummy_ack; - - always_comb begin - flash_enable = address < 32'h10016800; - - ack = flash_ack | dummy_ack; - - rdata = 16'd0; - if (ack && flash_enable) begin - if (address[1]) rdata = {flash_rdata[23:16], flash_rdata[31:24]}; - else rdata = {flash_rdata[7:0], flash_rdata[15:8]}; - end - end - - typedef enum bit [0:0] { - S_IDLE, - S_WAIT - } e_state; - - e_state state; - - always_ff @(posedge sys.clk) begin - dummy_ack <= 1'b0; - - if (sys.reset) begin - state <= S_IDLE; - flash_request <= 1'b0; - end else begin - case (state) - S_IDLE: begin - if (request) begin - state <= S_WAIT; - flash_request <= flash_enable; - dummy_ack <= !flash_enable; - end - end - - S_WAIT: begin - if (!flash_busy) begin - flash_request <= 1'b0; - end - if (ack) begin - state <= S_IDLE; - end - end - endcase - end - end - - intel_flash intel_flash_inst ( - .clock(sys.clk), - .reset_n(~sys.reset), - .avmm_data_addr(address[31:2]), - .avmm_data_read(flash_request), - .avmm_data_readdata(flash_rdata), - .avmm_data_waitrequest(flash_busy), - .avmm_data_readdatavalid(flash_ack), - .avmm_data_burstcount(2'd1) - ); - -endmodule diff --git a/fw/rtl/n64/n64_bootloader.sv b/fw/rtl/n64/n64_bootloader.sv index 2967a31..8773928 100644 --- a/fw/rtl/n64/n64_bootloader.sv +++ b/fw/rtl/n64/n64_bootloader.sv @@ -1,14 +1,119 @@ module n64_bootloader ( if_system.sys sys, - if_n64_bus bus + if_n64_bus bus, + if_flash.memory flash ); - memory_flash memory_flash_inst ( - .sys(sys), - .request(bus.request), - .ack(bus.ack), - .address(bus.address), - .rdata(bus.rdata) + logic mem_request; + logic csr_ack; + logic data_ack; + logic data_busy; + logic mem_write; + logic [31:0] mem_address; + logic [31:0] csr_rdata; + logic [31:0] data_rdata; + logic [31:0] mem_wdata; + + typedef enum bit [0:0] { + S_IDLE, + S_WAIT + } e_state; + + typedef enum bit [0:0] { + T_N64, + T_CPU + } e_source_request; + + e_state state; + e_source_request source_request; + + always_ff @(posedge sys.clk) begin + csr_ack <= 1'b0; + + if (sys.reset) begin + state <= S_IDLE; + mem_request <= 1'b0; + end else begin + case (state) + S_IDLE: begin + if (bus.request || flash.request) begin + state <= S_WAIT; + mem_request <= 1'b1; + if (bus.request) begin + mem_write <= 1'b0; + mem_address <= bus.address; + mem_wdata <= bus.wdata; + source_request <= T_N64; + end else if (flash.request) begin + mem_write <= flash.write; + mem_address <= flash.address; + mem_wdata <= flash.wdata; + source_request <= T_CPU; + end + end + end + + S_WAIT: begin + if (mem_address[27] && source_request != T_N64 && !csr_ack) begin + mem_request <= 1'b0; + csr_ack <= 1'b1; + end + if ((!mem_address[27] || source_request == T_N64) && !data_busy) begin + mem_request <= 1'b0; + end + if (csr_ack || data_ack) begin + state <= S_IDLE; + end + end + endcase + end + end + + logic csr_or_data; + logic csr_read; + logic csr_write; + logic data_read; + logic data_write; + + always_comb begin + csr_or_data = mem_address[27] && source_request == T_CPU; + csr_read = csr_or_data && mem_request && !mem_write; + csr_write = csr_or_data && mem_request && mem_write; + data_read = !csr_or_data && mem_request && !mem_write; + data_write = !csr_or_data && mem_request && mem_write; + + bus.ack = source_request == T_N64 && data_ack; + bus.rdata = 16'd0; + if (bus.ack && bus.address >= 32'h10000000 && bus.address < 32'h10016800) begin + if (bus.address[1]) bus.rdata = {data_rdata[23:16], data_rdata[31:24]}; + else bus.rdata = {data_rdata[7:0], data_rdata[15:8]}; + end + + flash.ack = source_request == T_CPU && (csr_ack || data_ack); + flash.rdata = 32'd0; + if (flash.ack) begin + flash.rdata = csr_or_data ? csr_rdata : data_rdata; + end + end + + intel_flash intel_flash_inst ( + .clock(sys.clk), + .reset_n(~sys.reset), + + .avmm_csr_addr(mem_address[2]), + .avmm_csr_read(csr_read), + .avmm_csr_writedata(mem_wdata), + .avmm_csr_write(csr_write), + .avmm_csr_readdata(csr_rdata), + + .avmm_data_addr(mem_address[31:2]), + .avmm_data_read(data_read), + .avmm_data_writedata(mem_wdata), + .avmm_data_write(data_write), + .avmm_data_readdata(data_rdata), + .avmm_data_waitrequest(data_busy), + .avmm_data_readdatavalid(data_ack), + .avmm_data_burstcount(2'd1) ); endmodule diff --git a/fw/rtl/n64/n64_soc.sv b/fw/rtl/n64/n64_soc.sv index 1f38904..4e6c5a3 100644 --- a/fw/rtl/n64/n64_soc.sv +++ b/fw/rtl/n64/n64_soc.sv @@ -5,6 +5,7 @@ module n64_soc ( if_sdram.memory sdram, if_flashram.flashram flashram, if_si.si si, + if_flash.memory flash, input n64_pi_alel, input n64_pi_aleh, @@ -63,7 +64,8 @@ module n64_soc ( n64_bootloader n64_bootloader_inst ( .sys(sys), - .bus(bus.at[sc64::ID_N64_BOOTLOADER].device) + .bus(bus.at[sc64::ID_N64_BOOTLOADER].device), + .flash(flash) ); n64_flashram n64_flashram_inst ( diff --git a/fw/rtl/system/sc64.sv b/fw/rtl/system/sc64.sv index 9044d52..e8ddb03 100644 --- a/fw/rtl/system/sc64.sv +++ b/fw/rtl/system/sc64.sv @@ -21,6 +21,7 @@ package sc64; ID_CPU_SDRAM, ID_CPU_FLASHRAM, ID_CPU_SI, + ID_CPU_FLASH, __ID_CPU_END } e_cpu_id; diff --git a/sw/n64/Makefile b/sw/n64/Makefile index e46c4df..8b384cc 100644 --- a/sw/n64/Makefile +++ b/sw/n64/Makefile @@ -13,7 +13,7 @@ $(BUILD_DIR)/$(PROGRAM_NAME).elf: $(src:%.c=$(BUILD_DIR)/%.o) $(PROGRAM_NAME).z64: N64_ROM_TITLE="$(PROGRAM_NAME)" $(BUILD_DIR)/$(PROGRAM_NAME).hex: $(PROGRAM_NAME).z64 - sed 's/\x00*$$//' $(PROGRAM_NAME).z64 > $(BUILD_DIR)/$(PROGRAM_NAME)_stripped.z64 + sed '$$ s/\x00*$$//' $(PROGRAM_NAME).z64 > $(BUILD_DIR)/$(PROGRAM_NAME)_stripped.z64 @if [ $$(stat -L -c %s $(BUILD_DIR)/$(PROGRAM_NAME)_stripped.z64) -gt 92160 ]; then\ echo "\n Error: stripped file size is larger than 90kB thus cannot fit inside FPGA flash.\n"; exit 1;\ fi diff --git a/sw/riscv/src/handlers.c b/sw/riscv/src/handlers.c index a5f2895..9a757f0 100644 --- a/sw/riscv/src/handlers.c +++ b/sw/riscv/src/handlers.c @@ -2,43 +2,18 @@ #include "sys.h" -#define BOOT_UART - - __attribute__ ((naked, section(".bootloader"))) void reset_handler (void) { - register uint32_t length = 0; + io32_t *ram = (io32_t *) &RAM; + io32_t *flash = (io32_t *) (FLASH_BASE + FLASH_IMAGE_OFFSET); -#if defined(BOOT_UART) - volatile uint8_t *pointer = (volatile uint8_t *) &RAM; - for (int i = 0; i < 4; i++) { - while (!(UART->SCR & UART_SCR_RXNE)); - length |= (UART->DR << (i * 8)); + for (int i = 0; i < RAM_SIZE; i += 4) { + *ram++ = *flash++; } -#elif defined(BOOT_N64) - volatile uint32_t *pointer = (volatile uint32_t *) &RAM; - while (!(CFG->SCR & CFG_SCR_CPU_BUSY)); - length = CFG->DATA[0]; - CFG->SCR &= ~(CFG_SCR_CPU_READY); -#endif - while (1) { -#if defined(BOOT_UART) - while (!(UART->SCR & UART_SCR_RXNE)); - *pointer++ = UART->DR; - length = length - 1; -#elif defined(BOOT_N64) - while (!(CFG->SCR & CFG_SCR_CPU_BUSY)); - *pointer++ = CFG->DATA[0]; - CFG->SCR &= ~(CFG_SCR_CPU_READY); - length = length - 4; -#endif - if (length == 0) { - __asm__ volatile ( - "la t0, app_handler \n" - "jalr zero, t0 \n" - ); - } - } + __asm__ volatile ( + "la t0, app_handler \n" + "jalr zero, t0 \n" + ); } diff --git a/sw/riscv/src/sys.h b/sw/riscv/src/sys.h index 8fb9343..87c356e 100644 --- a/sw/riscv/src/sys.h +++ b/sw/riscv/src/sys.h @@ -13,6 +13,7 @@ typedef volatile uint32_t io32_t; #define RAM_BASE (0x00000000UL) #define RAM (*((io32_t *) RAM_BASE)) +#define RAM_SIZE (16 * 1024) #define BOOTLOADER_BASE (0x10000000UL) @@ -153,6 +154,21 @@ typedef volatile struct joybus_regs { #define JOYBUS_SCR_TX_LENGTH_BIT (16) +#define FLASH_BASE (0xB0000000UL) +#define FLASH (*((io32_t *) FLASH_BASE)) + +#define FLASH_IMAGE_OFFSET (0x35800) + + +typedef volatile struct flash_regs { + io32_t SR; + io32_t CR; +} flash_regs_t; + +#define FLASH_SCR_BASE (0xB8000000UL) +#define FLASH_SCR ((flash_regs_t *) FLASH_SCR_BASE) + + void reset_handler (void); void app_handler (void); diff --git a/sw/riscv/src/uart.c b/sw/riscv/src/uart.c index b33d00a..47c1b70 100644 --- a/sw/riscv/src/uart.c +++ b/sw/riscv/src/uart.c @@ -38,7 +38,7 @@ void uart_print_08hex (uint32_t number) { void uart_init (void) { #ifdef DEBUG - uart_print("App ready!\n"); + uart_print("App ready from flash!\n"); #endif } @@ -72,7 +72,8 @@ void process_uart (void) { uart_print_02hex(((uint8_t *) (time))[i]); uart_print(" "); } - uart_print("\r\n"); + uart_print("\n"); + break; } } #endif