flash working with cpu

This commit is contained in:
Polprzewodnikowy 2021-10-26 00:51:58 +02:00
parent b0b1ea309f
commit 5ad902aa10
13 changed files with 239 additions and 136 deletions

View File

@ -19,7 +19,7 @@
# #
# Quartus Prime # Quartus Prime
# Version 20.1.1 Build 720 11/11/2020 SJ Lite Edition # 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_bus.sv
set_global_assignment -name SYSTEMVERILOG_FILE rtl/cpu/cpu_cfg.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_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_flashram.sv
set_global_assignment -name SYSTEMVERILOG_FILE rtl/cpu/cpu_gpio.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_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_uart.sv
set_global_assignment -name SYSTEMVERILOG_FILE rtl/cpu/cpu_usb.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/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/memory/memory_sdram.sv
set_global_assignment -name SYSTEMVERILOG_FILE rtl/n64/n64_bootloader.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_bus.sv
@ -224,7 +224,6 @@ set_global_assignment -name USE_CONFIGURATION_DEVICE OFF
# Signal Tap Assignments # Signal Tap Assignments
# ====================== # ======================
set_global_assignment -name ENABLE_SIGNALTAP ON set_global_assignment -name ENABLE_SIGNALTAP ON
set_global_assignment -name USE_SIGNALTAP_FILE output_files/signaltap.stp
# Power Estimation Assignments # Power Estimation Assignments
# ============================ # ============================

View File

@ -64,6 +64,8 @@ module SummerCart64 (
if_si si (); if_si si ();
if_flash flash ();
system system_inst ( system system_inst (
.sys(sys) .sys(sys)
); );
@ -81,6 +83,7 @@ module SummerCart64 (
.sdram(sdram), .sdram(sdram),
.flashram(flashram), .flashram(flashram),
.si(si), .si(si),
.flash(flash),
.n64_pi_alel(i_n64_pi_alel), .n64_pi_alel(i_n64_pi_alel),
.n64_pi_aleh(i_n64_pi_aleh), .n64_pi_aleh(i_n64_pi_aleh),
@ -107,6 +110,7 @@ module SummerCart64 (
.sdram(sdram), .sdram(sdram),
.flashram(flashram), .flashram(flashram),
.si(si), .si(si),
.flash(flash),
.gpio_o(gpio_o), .gpio_o(gpio_o),
.gpio_i(gpio_i), .gpio_i(gpio_i),

61
fw/rtl/cpu/cpu_flash.sv Normal file
View File

@ -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

View File

@ -5,6 +5,7 @@ module cpu_soc (
if_sdram.cpu sdram, if_sdram.cpu sdram,
if_flashram.cpu flashram, if_flashram.cpu flashram,
if_si.cpu si, if_si.cpu si,
if_flash.cpu flash,
input [7:0] gpio_i, input [7:0] gpio_i,
output [7:0] gpio_o, output [7:0] gpio_o,
@ -111,4 +112,10 @@ module cpu_soc (
.si(si) .si(si)
); );
cpu_flash cpu_flash_inst (
.sys(sys),
.bus(bus.at[sc64::ID_CPU_FLASH].device),
.flash(flash)
);
endmodule endmodule

View File

@ -7,17 +7,17 @@
description="" description=""
tags="INTERNAL_COMPONENT=true" tags="INTERNAL_COMPONENT=true"
categories="System" /> categories="System" />
<parameter name="bonusData"><![CDATA[bonusData <parameter name="bonusData"><![CDATA[bonusData
{ {
element onchip_flash_0 element onchip_flash_0
{ {
datum _sortIndex datum _sortIndex
{ {
value = "0"; value = "0";
type = "int"; type = "int";
} }
} }
} }
]]></parameter> ]]></parameter>
<parameter name="clockCrossingAdapter" value="HANDSHAKE" /> <parameter name="clockCrossingAdapter" value="HANDSHAKE" />
<parameter name="device" value="10M08SCE144C8G" /> <parameter name="device" value="10M08SCE144C8G" />
@ -41,10 +41,18 @@
<interface name="clk" internal="onchip_flash_0.clk" type="clock" dir="end"> <interface name="clk" internal="onchip_flash_0.clk" type="clock" dir="end">
<port name="clock" internal="clock" /> <port name="clock" internal="clock" />
</interface> </interface>
<interface name="csr" internal="onchip_flash_0.csr" /> <interface name="csr" internal="onchip_flash_0.csr" type="avalon" dir="end">
<port name="avmm_csr_addr" internal="avmm_csr_addr" />
<port name="avmm_csr_read" internal="avmm_csr_read" />
<port name="avmm_csr_writedata" internal="avmm_csr_writedata" />
<port name="avmm_csr_write" internal="avmm_csr_write" />
<port name="avmm_csr_readdata" internal="avmm_csr_readdata" />
</interface>
<interface name="data" internal="onchip_flash_0.data" type="avalon" dir="end"> <interface name="data" internal="onchip_flash_0.data" type="avalon" dir="end">
<port name="avmm_data_addr" internal="avmm_data_addr" /> <port name="avmm_data_addr" internal="avmm_data_addr" />
<port name="avmm_data_read" internal="avmm_data_read" /> <port name="avmm_data_read" internal="avmm_data_read" />
<port name="avmm_data_writedata" internal="avmm_data_writedata" />
<port name="avmm_data_write" internal="avmm_data_write" />
<port name="avmm_data_readdata" internal="avmm_data_readdata" /> <port name="avmm_data_readdata" internal="avmm_data_readdata" />
<port name="avmm_data_waitrequest" internal="avmm_data_waitrequest" /> <port name="avmm_data_waitrequest" internal="avmm_data_waitrequest" />
<port name="avmm_data_readdatavalid" internal="avmm_data_readdatavalid" /> <port name="avmm_data_readdatavalid" internal="avmm_data_readdatavalid" />
@ -68,7 +76,7 @@
<parameter name="PART_NAME" value="10M08SCE144C8G" /> <parameter name="PART_NAME" value="10M08SCE144C8G" />
<parameter name="READ_BURST_COUNT" value="2" /> <parameter name="READ_BURST_COUNT" value="2" />
<parameter name="READ_BURST_MODE" value="Incrementing" /> <parameter name="READ_BURST_MODE" value="Incrementing" />
<parameter name="SECTOR_ACCESS_MODE">Read only,Read only,Hidden,Read only,Read only</parameter> <parameter name="SECTOR_ACCESS_MODE">Read and write,Read and write,Hidden,Read and write,Read and write</parameter>
<parameter name="autoInitializationFileName">$${FILENAME}_onchip_flash_0</parameter> <parameter name="autoInitializationFileName">$${FILENAME}_onchip_flash_0</parameter>
<parameter name="initFlashContent" value="true" /> <parameter name="initFlashContent" value="true" />
<parameter name="initializationFileName">../sw/n64/build/SummerLoader64.hex</parameter> <parameter name="initializationFileName">../sw/n64/build/SummerLoader64.hex</parameter>

View File

@ -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

View File

@ -1,14 +1,119 @@
module n64_bootloader ( module n64_bootloader (
if_system.sys sys, if_system.sys sys,
if_n64_bus bus if_n64_bus bus,
if_flash.memory flash
); );
memory_flash memory_flash_inst ( logic mem_request;
.sys(sys), logic csr_ack;
.request(bus.request), logic data_ack;
.ack(bus.ack), logic data_busy;
.address(bus.address), logic mem_write;
.rdata(bus.rdata) 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 endmodule

View File

@ -5,6 +5,7 @@ module n64_soc (
if_sdram.memory sdram, if_sdram.memory sdram,
if_flashram.flashram flashram, if_flashram.flashram flashram,
if_si.si si, if_si.si si,
if_flash.memory flash,
input n64_pi_alel, input n64_pi_alel,
input n64_pi_aleh, input n64_pi_aleh,
@ -63,7 +64,8 @@ module n64_soc (
n64_bootloader n64_bootloader_inst ( n64_bootloader n64_bootloader_inst (
.sys(sys), .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 ( n64_flashram n64_flashram_inst (

View File

@ -21,6 +21,7 @@ package sc64;
ID_CPU_SDRAM, ID_CPU_SDRAM,
ID_CPU_FLASHRAM, ID_CPU_FLASHRAM,
ID_CPU_SI, ID_CPU_SI,
ID_CPU_FLASH,
__ID_CPU_END __ID_CPU_END
} e_cpu_id; } e_cpu_id;

View File

@ -13,7 +13,7 @@ $(BUILD_DIR)/$(PROGRAM_NAME).elf: $(src:%.c=$(BUILD_DIR)/%.o)
$(PROGRAM_NAME).z64: N64_ROM_TITLE="$(PROGRAM_NAME)" $(PROGRAM_NAME).z64: N64_ROM_TITLE="$(PROGRAM_NAME)"
$(BUILD_DIR)/$(PROGRAM_NAME).hex: $(PROGRAM_NAME).z64 $(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\ @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;\ echo "\n Error: stripped file size is larger than 90kB thus cannot fit inside FPGA flash.\n"; exit 1;\
fi fi

View File

@ -2,43 +2,18 @@
#include "sys.h" #include "sys.h"
#define BOOT_UART
__attribute__ ((naked, section(".bootloader"))) void reset_handler (void) { __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) for (int i = 0; i < RAM_SIZE; i += 4) {
volatile uint8_t *pointer = (volatile uint8_t *) &RAM; *ram++ = *flash++;
for (int i = 0; i < 4; i++) {
while (!(UART->SCR & UART_SCR_RXNE));
length |= (UART->DR << (i * 8));
} }
#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) { __asm__ volatile (
#if defined(BOOT_UART) "la t0, app_handler \n"
while (!(UART->SCR & UART_SCR_RXNE)); "jalr zero, t0 \n"
*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"
);
}
}
} }

View File

@ -13,6 +13,7 @@ typedef volatile uint32_t io32_t;
#define RAM_BASE (0x00000000UL) #define RAM_BASE (0x00000000UL)
#define RAM (*((io32_t *) RAM_BASE)) #define RAM (*((io32_t *) RAM_BASE))
#define RAM_SIZE (16 * 1024)
#define BOOTLOADER_BASE (0x10000000UL) #define BOOTLOADER_BASE (0x10000000UL)
@ -153,6 +154,21 @@ typedef volatile struct joybus_regs {
#define JOYBUS_SCR_TX_LENGTH_BIT (16) #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 reset_handler (void);
void app_handler (void); void app_handler (void);

View File

@ -38,7 +38,7 @@ void uart_print_08hex (uint32_t number) {
void uart_init (void) { void uart_init (void) {
#ifdef DEBUG #ifdef DEBUG
uart_print("App ready!\n"); uart_print("App ready from flash!\n");
#endif #endif
} }
@ -72,7 +72,8 @@ void process_uart (void) {
uart_print_02hex(((uint8_t *) (time))[i]); uart_print_02hex(((uint8_t *) (time))[i]);
uart_print(" "); uart_print(" ");
} }
uart_print("\r\n"); uart_print("\n");
break;
} }
} }
#endif #endif