mirror of
https://github.com/Polprzewodnikowy/SummerCart64.git
synced 2024-11-21 21:49:15 +01:00
[SC64][FW][SW] Added command to reconfigure FPGA from software (#10)
This commit is contained in:
parent
adff845460
commit
d1bf99fdf4
@ -19,7 +19,7 @@
|
||||
#
|
||||
# Quartus Prime
|
||||
# Version 20.1.1 Build 720 11/11/2020 SJ Lite Edition
|
||||
# Date created = 22:44:04 October 26, 2021
|
||||
# Date created = 23:38:22 October 28, 2021
|
||||
#
|
||||
# -------------------------------------------------------------------------- #
|
||||
#
|
||||
@ -46,13 +46,13 @@ set_global_assignment -name LAST_QUARTUS_VERSION "20.1.1 Lite Edition"
|
||||
set_global_assignment -name PROJECT_OUTPUT_DIRECTORY output_files
|
||||
set_global_assignment -name NUM_PARALLEL_PROCESSORS ALL
|
||||
set_global_assignment -name FLOW_ENABLE_POWER_ANALYZER ON
|
||||
set_global_assignment -name QSYS_FILE rtl/intel/config/intel_config.qsys
|
||||
set_global_assignment -name QSYS_FILE rtl/intel/flash/intel_flash.qsys
|
||||
set_global_assignment -name QSYS_FILE rtl/intel/snp/intel_snp.qsys
|
||||
set_global_assignment -name QIP_FILE rtl/intel/fifo/intel_fifo_8.qip
|
||||
set_global_assignment -name QIP_FILE rtl/intel/gpio/intel_gpio_ddro.qip
|
||||
set_global_assignment -name QIP_FILE rtl/intel/pll/intel_pll.qip
|
||||
set_global_assignment -name SDC_FILE SummerCart64.sdc
|
||||
set_global_assignment -name SIGNALTAP_FILE stp.stp
|
||||
set_global_assignment -name SYSTEMVERILOG_FILE cpu/picorv32/picorv32.v
|
||||
set_global_assignment -name SYSTEMVERILOG_FILE ../sw/riscv/build/cpu_bootloader.sv
|
||||
set_global_assignment -name SYSTEMVERILOG_FILE rtl/cpu/cpu_bus.sv
|
||||
@ -85,7 +85,6 @@ set_global_assignment -name SYSTEMVERILOG_FILE rtl/system/config.sv
|
||||
set_global_assignment -name SYSTEMVERILOG_FILE rtl/system/sc64.sv
|
||||
set_global_assignment -name SYSTEMVERILOG_FILE rtl/system/system.sv
|
||||
set_global_assignment -name SYSTEMVERILOG_FILE rtl/usb/usb_ft1248.sv
|
||||
set_global_assignment -name SIGNALTAP_FILE output_files/signaltap.stp
|
||||
|
||||
# Pin & Location Assignments
|
||||
# ==========================
|
||||
@ -190,7 +189,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
|
||||
# ================================
|
||||
@ -221,10 +220,6 @@ set_global_assignment -name ENABLE_OCT_DONE OFF
|
||||
set_global_assignment -name EXTERNAL_FLASH_FALLBACK_ADDRESS 00000000
|
||||
set_global_assignment -name USE_CONFIGURATION_DEVICE OFF
|
||||
|
||||
# Signal Tap Assignments
|
||||
# ======================
|
||||
set_global_assignment -name ENABLE_SIGNALTAP ON
|
||||
|
||||
# Power Estimation Assignments
|
||||
# ============================
|
||||
set_global_assignment -name POWER_PRESET_COOLING_SOLUTION "NO HEAT SINK WITH STILL AIR"
|
||||
@ -303,6 +298,7 @@ set_global_assignment -name OUTPUT_IO_TIMING_FAR_END_VMEAS "HALF SIGNAL SWING" -
|
||||
set_global_assignment -name PARTITION_NETLIST_TYPE SOURCE -section_id Top
|
||||
set_global_assignment -name PARTITION_FITTER_PRESERVATION_LEVEL PLACEMENT_AND_ROUTING -section_id Top
|
||||
set_global_assignment -name PARTITION_COLOR 16764057 -section_id Top
|
||||
set_instance_assignment -name PARTITION_HIERARCHY root_partition -to | -section_id Top
|
||||
|
||||
# end DESIGN_PARTITION(Top)
|
||||
# -------------------------
|
||||
|
@ -10,6 +10,11 @@ create_generated_clock -name sdram_clk -source [get_pins $sdram_pll_clk] [get_po
|
||||
# create_generated_clock -name sd_reg_clk -source [get_pins {sd_interface_inst|sd_clk_inst|o_sd_clk|clk}] -divide_by 2 [get_pins $sd_reg_clk]
|
||||
# create_generated_clock -name sd_clk -source [get_pins $sd_reg_clk] [get_ports {o_sd_clk}]
|
||||
|
||||
create_generated_clock -name config_clk \
|
||||
-source [get_pins {cpu_soc_inst|cpu_cfg_inst|reconfig_clk|clk}] \
|
||||
-divide_by 2 \
|
||||
[get_pins {cpu_soc_inst|cpu_cfg_inst|reconfig_clk|q}]
|
||||
|
||||
create_generated_clock -name flash_se_neg_reg \
|
||||
-source [get_pins -compatibility_mode {*altera_onchip_flash:*onchip_flash_0|altera_onchip_flash_avmm_data_controller:avmm_data_controller|flash_se_neg_reg|clk}] \
|
||||
-divide_by 2 \
|
||||
|
@ -5,6 +5,7 @@ module cpu_cfg (
|
||||
);
|
||||
|
||||
logic skip_bootloader;
|
||||
logic trigger_reconfiguration;
|
||||
|
||||
typedef enum bit [2:0] {
|
||||
R_SCR,
|
||||
@ -13,9 +14,12 @@ module cpu_cfg (
|
||||
R_COMMAND,
|
||||
R_DATA_0,
|
||||
R_DATA_1,
|
||||
R_VERSION
|
||||
R_VERSION,
|
||||
R_RECONFIGURE
|
||||
} e_reg_id;
|
||||
|
||||
const logic [31:0] RECONFIGURE_MAGIC = 32'h52535446;
|
||||
|
||||
always_ff @(posedge sys.clk) begin
|
||||
bus.ack <= 1'b0;
|
||||
if (bus.request) begin
|
||||
@ -47,6 +51,7 @@ module cpu_cfg (
|
||||
R_DATA_0: bus.rdata = cfg.data[0];
|
||||
R_DATA_1: bus.rdata = cfg.data[1];
|
||||
R_VERSION: bus.rdata = sc64::SC64_VER;
|
||||
R_RECONFIGURE: bus.rdata = {31'd0, trigger_reconfiguration};
|
||||
default: bus.rdata = 32'd0;
|
||||
endcase
|
||||
end
|
||||
@ -75,6 +80,7 @@ module cpu_cfg (
|
||||
cfg.dd_offset <= 26'h3BE_0000;
|
||||
cfg.save_offset <= 26'h3FE_0000;
|
||||
skip_bootloader <= 1'b0;
|
||||
trigger_reconfiguration <= 1'b0;
|
||||
end else begin
|
||||
if (sys.n64_soft_reset) begin
|
||||
cfg.sdram_switch <= skip_bootloader;
|
||||
@ -117,9 +123,51 @@ module cpu_cfg (
|
||||
cfg.save_offset <= bus.wdata[25:0];
|
||||
end
|
||||
end
|
||||
|
||||
R_RECONFIGURE: begin
|
||||
if (&bus.wmask && bus.wdata == RECONFIGURE_MAGIC) begin
|
||||
trigger_reconfiguration <= 1'b1;
|
||||
end
|
||||
end
|
||||
endcase
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
logic reconfig_clk;
|
||||
logic reconfig_write;
|
||||
logic [31:0] reconfig_rdata;
|
||||
logic reconfig_write_done;
|
||||
|
||||
const logic [31:0] TRIGGER_RECONFIGURATION = 32'h00000001;
|
||||
|
||||
always_ff @(posedge sys.clk) begin
|
||||
if (sys.reset) begin
|
||||
reconfig_clk <= 1'b0;
|
||||
reconfig_write <= 1'b0;
|
||||
reconfig_write_done <= 1'b0;
|
||||
end else begin
|
||||
reconfig_clk <= ~reconfig_clk;
|
||||
|
||||
if (!reconfig_clk) begin
|
||||
reconfig_write <= 1'b0;
|
||||
|
||||
if (trigger_reconfiguration && !reconfig_write_done) begin
|
||||
reconfig_write <= 1'b1;
|
||||
reconfig_write_done <= 1'b1;
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
intel_config intel_config_inst (
|
||||
.clk(reconfig_clk),
|
||||
.nreset(~sys.reset),
|
||||
.avmm_rcv_address(3'd0),
|
||||
.avmm_rcv_read(1'b0),
|
||||
.avmm_rcv_writedata(TRIGGER_RECONFIGURATION),
|
||||
.avmm_rcv_write(reconfig_write),
|
||||
.avmm_rcv_readdata(reconfig_rdata)
|
||||
);
|
||||
|
||||
endmodule
|
||||
|
67
fw/rtl/intel/config/intel_config.qsys
Normal file
67
fw/rtl/intel/config/intel_config.qsys
Normal file
@ -0,0 +1,67 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<system name="$${FILENAME}">
|
||||
<component
|
||||
name="$${FILENAME}"
|
||||
displayName="$${FILENAME}"
|
||||
version="1.0"
|
||||
description=""
|
||||
tags="INTERNAL_COMPONENT=true"
|
||||
categories="System" />
|
||||
<parameter name="bonusData"><![CDATA[bonusData
|
||||
{
|
||||
element dual_boot_0
|
||||
{
|
||||
datum _sortIndex
|
||||
{
|
||||
value = "0";
|
||||
type = "int";
|
||||
}
|
||||
}
|
||||
}
|
||||
]]></parameter>
|
||||
<parameter name="clockCrossingAdapter" value="HANDSHAKE" />
|
||||
<parameter name="device" value="10M08SCE144C8G" />
|
||||
<parameter name="deviceFamily" value="MAX 10" />
|
||||
<parameter name="deviceSpeedGrade" value="8" />
|
||||
<parameter name="fabricMode" value="QSYS" />
|
||||
<parameter name="generateLegacySim" value="false" />
|
||||
<parameter name="generationId" value="0" />
|
||||
<parameter name="globalResetBus" value="false" />
|
||||
<parameter name="hdlLanguage" value="VERILOG" />
|
||||
<parameter name="hideFromIPCatalog" value="true" />
|
||||
<parameter name="lockedInterfaceDefinition" value="" />
|
||||
<parameter name="maxAdditionalLatency" value="1" />
|
||||
<parameter name="projectName" value="" />
|
||||
<parameter name="sopcBorderPoints" value="false" />
|
||||
<parameter name="systemHash" value="0" />
|
||||
<parameter name="testBenchDutName" value="" />
|
||||
<parameter name="timeStamp" value="0" />
|
||||
<parameter name="useTestBenchNamingPattern" value="false" />
|
||||
<instanceScript></instanceScript>
|
||||
<interface name="avalon" internal="dual_boot_0.avalon" type="avalon" dir="end">
|
||||
<port name="avmm_rcv_address" internal="avmm_rcv_address" />
|
||||
<port name="avmm_rcv_read" internal="avmm_rcv_read" />
|
||||
<port name="avmm_rcv_writedata" internal="avmm_rcv_writedata" />
|
||||
<port name="avmm_rcv_write" internal="avmm_rcv_write" />
|
||||
<port name="avmm_rcv_readdata" internal="avmm_rcv_readdata" />
|
||||
</interface>
|
||||
<interface name="clk" internal="dual_boot_0.clk" type="clock" dir="end">
|
||||
<port name="clk" internal="clk" />
|
||||
</interface>
|
||||
<interface name="nreset" internal="dual_boot_0.nreset" type="reset" dir="end">
|
||||
<port name="nreset" internal="nreset" />
|
||||
</interface>
|
||||
<module
|
||||
name="dual_boot_0"
|
||||
kind="altera_dual_boot"
|
||||
version="20.1"
|
||||
enabled="1"
|
||||
autoexport="1">
|
||||
<parameter name="CLOCK_FREQUENCY" value="50.0" />
|
||||
<parameter name="INTENDED_DEVICE_FAMILY" value="MAX 10" />
|
||||
</module>
|
||||
<interconnectRequirement for="$system" name="qsys_mm.clockCrossingAdapter" value="HANDSHAKE" />
|
||||
<interconnectRequirement for="$system" name="qsys_mm.enableEccProtection" value="FALSE" />
|
||||
<interconnectRequirement for="$system" name="qsys_mm.insertDefaultSlave" value="FALSE" />
|
||||
<interconnectRequirement for="$system" name="qsys_mm.maxAdditionalLatency" value="1" />
|
||||
</system>
|
3
sw/pc/.gitignore
vendored
3
sw/pc/.gitignore
vendored
@ -6,4 +6,5 @@
|
||||
*.z64
|
||||
*.v64
|
||||
*.data
|
||||
*.bak
|
||||
*.bak
|
||||
*.bin
|
||||
|
97
sw/pc/update.py
Normal file
97
sw/pc/update.py
Normal file
@ -0,0 +1,97 @@
|
||||
import os
|
||||
import serial
|
||||
import time
|
||||
import filecmp
|
||||
|
||||
|
||||
|
||||
class SC64:
|
||||
__CFG_ID_FLASH_OPERATION = 10
|
||||
__CFG_ID_RECONFIGURE = 11
|
||||
|
||||
|
||||
def __init__(self, port):
|
||||
self.__serial = serial.Serial(port)
|
||||
|
||||
|
||||
def __query_config(self, query, arg=0):
|
||||
self.__serial.write(b'CMDQ')
|
||||
self.__serial.write(query.to_bytes(4, byteorder='big'))
|
||||
self.__serial.write(arg.to_bytes(4, byteorder='big'))
|
||||
value = self.__serial.read(4)
|
||||
if (self.__serial.read(4).decode() != 'CMPQ'):
|
||||
raise Exception('Bad query response')
|
||||
return int.from_bytes(value, byteorder='big')
|
||||
|
||||
|
||||
def __change_config(self, change, arg=0, ignore_response=False):
|
||||
self.__serial.write(b'CMDC')
|
||||
self.__serial.write(change.to_bytes(4, byteorder='big'))
|
||||
self.__serial.write(arg.to_bytes(4, byteorder='big'))
|
||||
if (not ignore_response and self.__serial.read(4).decode() != 'CMPC'):
|
||||
raise Exception('Bad change response')
|
||||
|
||||
|
||||
def reconfigure(self):
|
||||
magic = self.__query_config(self.__CFG_ID_RECONFIGURE)
|
||||
self.__change_config(self.__CFG_ID_RECONFIGURE, magic, ignore_response=True)
|
||||
time.sleep(1)
|
||||
|
||||
|
||||
def read_flash(self, file):
|
||||
size = self.__query_config(self.__CFG_ID_FLASH_OPERATION)
|
||||
print('Flash size: {:08X}'.format(size))
|
||||
self.__serial.write(b'CMDR')
|
||||
self.__serial.write((0).to_bytes(4, byteorder='big'))
|
||||
self.__serial.write((size).to_bytes(4, byteorder='big'))
|
||||
flash = self.__serial.read(size)
|
||||
response = self.__serial.read(4)
|
||||
if (response.decode() == 'CMPR'):
|
||||
with open(file, 'wb') as f:
|
||||
f.write(flash)
|
||||
else:
|
||||
raise Exception('There was a problem while reading flash data')
|
||||
|
||||
|
||||
def program_flash(self, file):
|
||||
length = os.path.getsize(file)
|
||||
offset = 0
|
||||
with open(file, 'rb') as f:
|
||||
self.__serial.write(b'CMDW')
|
||||
self.__serial.write(offset.to_bytes(4, byteorder='big'))
|
||||
self.__serial.write(length.to_bytes(4, byteorder='big'))
|
||||
self.__serial.write(f.read())
|
||||
response = self.__serial.read(4)
|
||||
if (response.decode() != 'CMPW'):
|
||||
raise Exception('There was a problem while sending flash data')
|
||||
self.__change_config(self.__CFG_ID_FLASH_OPERATION)
|
||||
|
||||
|
||||
|
||||
file = '../../fw/output_files/SC64_update.bin'
|
||||
backup_file = 'SC64_backup.bin'
|
||||
verify_file = 'SC64_update_verify.bin'
|
||||
port = 'COM7'
|
||||
|
||||
sc64 = SC64(port)
|
||||
|
||||
print('Making backup...')
|
||||
sc64.read_flash(backup_file)
|
||||
print('done\n')
|
||||
|
||||
print('Flashing... ')
|
||||
sc64.program_flash(file)
|
||||
print('done\n')
|
||||
|
||||
print('Reconfiguring... ')
|
||||
sc64.reconfigure()
|
||||
print('done\n')
|
||||
|
||||
print('Verifying... ')
|
||||
sc64.read_flash(verify_file)
|
||||
if (filecmp.cmp(file, verify_file)):
|
||||
print('success!\n')
|
||||
else:
|
||||
print('failure.\n')
|
||||
|
||||
print('Update done!')
|
@ -28,6 +28,7 @@ enum cfg_id {
|
||||
CFG_ID_DD_OFFEST,
|
||||
CFG_ID_SKIP_BOOTLOADER,
|
||||
CFG_ID_FLASH_OPERATION,
|
||||
CFG_ID_RECONFIGURE,
|
||||
};
|
||||
|
||||
enum save_type {
|
||||
@ -137,6 +138,14 @@ void cfg_update (uint32_t *args) {
|
||||
case CFG_ID_FLASH_OPERATION:
|
||||
flash_program(args[1]);
|
||||
break;
|
||||
case CFG_ID_RECONFIGURE:
|
||||
if (args[1] == CFG_RECONFIGURE_MAGIC) {
|
||||
CFG->RECONFIGURE = CFG_RECONFIGURE_MAGIC;
|
||||
__asm__ volatile (
|
||||
"ebreak \n"
|
||||
);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -175,6 +184,9 @@ void cfg_query (uint32_t *args) {
|
||||
case CFG_ID_FLASH_OPERATION:
|
||||
args[1] = flash_read(args[1]);
|
||||
break;
|
||||
case CFG_ID_RECONFIGURE:
|
||||
args[1] = CFG_RECONFIGURE_MAGIC;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -96,6 +96,8 @@ typedef volatile struct cfg_regs {
|
||||
io8_t CMD;
|
||||
io8_t __padding[3];
|
||||
io32_t DATA[2];
|
||||
io32_t VERSION;
|
||||
io32_t RECONFIGURE;
|
||||
} cfg_regs_t;
|
||||
|
||||
#define CFG_BASE (0x70000000UL)
|
||||
@ -113,6 +115,8 @@ typedef volatile struct cfg_regs {
|
||||
#define CFG_SCR_CPU_BUSY (1 << 30)
|
||||
#define CFG_SCR_CPU_READY (1 << 31)
|
||||
|
||||
#define CFG_RECONFIGURE_MAGIC (0x52535446)
|
||||
|
||||
|
||||
#define SDRAM_BASE (0x80000000UL)
|
||||
#define SDRAM (*((io32_t *) SDRAM_BASE))
|
||||
|
@ -153,6 +153,33 @@ void usb_debug_reset (void) {
|
||||
}
|
||||
|
||||
|
||||
static bool rx_cmd (uint32_t *data) {
|
||||
static uint8_t current_byte = 0;
|
||||
static uint32_t buffer = 0;
|
||||
uint8_t tmp;
|
||||
|
||||
while (rx_byte(&tmp)) {
|
||||
current_byte += 1;
|
||||
if ((current_byte != 4) && (tmp != (USB_CMD_TOKEN >> (8 * (4 - current_byte)) & 0xFF))) {
|
||||
current_byte = 0;
|
||||
buffer = 0;
|
||||
|
||||
return false;
|
||||
}
|
||||
buffer = (buffer << 8) | tmp;
|
||||
if (current_byte == 4) {
|
||||
current_byte = 0;
|
||||
*data = buffer;
|
||||
buffer = 0;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void usb_init (void) {
|
||||
USB->SCR = USB_SCR_FLUSH_TX | USB_SCR_FLUSH_RX;
|
||||
|
||||
@ -168,7 +195,7 @@ void process_usb (void) {
|
||||
if (p.debug_tx_busy) {
|
||||
p.state = STATE_DEBUG_TX;
|
||||
p.dma_in_progress = false;
|
||||
} else if (rx_word(&p.args[0])) {
|
||||
} else if (rx_cmd(&p.args[0])) {
|
||||
if ((p.args[0] & 0xFFFFFF00) == USB_CMD_TOKEN) {
|
||||
p.cmd = p.args[0] & 0xFF;
|
||||
p.counter = 0;
|
||||
|
Loading…
Reference in New Issue
Block a user