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