mirror of
https://github.com/Polprzewodnikowy/SummerCart64.git
synced 2024-12-25 04:21:56 +01:00
good stopping point
This commit is contained in:
parent
8bde0ccfb2
commit
8493c2edb1
2
build.sh
2
build.sh
@ -86,7 +86,7 @@ build_fpga () {
|
||||
|
||||
pushd fw > /dev/null
|
||||
if [ "$SKIP_FPGA_REBUILD" = true ] && [ -f output_files/SummerCart64.sof ]; then
|
||||
echo Skipping FPGA build
|
||||
quartus_cpf -c SummerCart64.cof
|
||||
else
|
||||
if [ "$DEBUG_ENABLED" = true ]; then
|
||||
quartus_sh --set VERILOG_MACRO="DEBUG" ./SummerCart64.qpf
|
||||
|
@ -19,7 +19,7 @@
|
||||
#
|
||||
# Quartus Prime
|
||||
# Version 21.1.0 Build 842 10/21/2021 SJ Lite Edition
|
||||
# Date created = 13:29:40 November 11, 2021
|
||||
# Date created = 19:00:58 February 02, 2022
|
||||
#
|
||||
# -------------------------------------------------------------------------- #
|
||||
#
|
||||
@ -46,6 +46,7 @@ set_global_assignment -name LAST_QUARTUS_VERSION "21.1.0 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 POST_MODULE_SCRIPT_FILE "quartus_sh:scripts/post_module.tcl"
|
||||
set_global_assignment -name QSYS_FILE rtl/intel/flash/intel_flash.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
|
||||
@ -55,10 +56,8 @@ 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_dd.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
|
||||
set_global_assignment -name SYSTEMVERILOG_FILE rtl/cpu/cpu_ram.sv
|
||||
set_global_assignment -name SYSTEMVERILOG_FILE rtl/cpu/cpu_sdram.sv
|
||||
@ -67,6 +66,7 @@ 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_dma.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
|
||||
@ -83,7 +83,8 @@ 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 POST_MODULE_SCRIPT_FILE "quartus_sh:scripts/post_module.tcl"
|
||||
set_global_assignment -name SYSTEMVERILOG_FILE rtl/vendor/vendor_flash.sv
|
||||
set_global_assignment -name SYSTEMVERILOG_FILE rtl/vendor/vendor_reconfigure.sv
|
||||
|
||||
# Pin & Location Assignments
|
||||
# ==========================
|
||||
@ -164,8 +165,11 @@ set_location_assignment PIN_114 -to o_sd_clk
|
||||
set_location_assignment PIN_118 -to io_sd_cmd
|
||||
set_location_assignment PIN_119 -to io_sd_dat[3]
|
||||
set_location_assignment PIN_120 -to io_sd_dat[2]
|
||||
set_location_assignment PIN_121 -to io_usb_miosi[5]
|
||||
set_location_assignment PIN_122 -to io_usb_miosi[7]
|
||||
set_location_assignment PIN_123 -to o_n64_irq
|
||||
set_location_assignment PIN_138 -to i_usb_pwren
|
||||
set_location_assignment PIN_124 -to io_usb_miosi[6]
|
||||
set_location_assignment PIN_126 -to io_usb_miosi[4]
|
||||
set_location_assignment PIN_140 -to o_usb_cs
|
||||
set_location_assignment PIN_141 -to i_usb_miso
|
||||
|
||||
@ -191,6 +195,7 @@ 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
|
||||
set_global_assignment -name VERILOG_MACRO DEBUG
|
||||
|
||||
# Fitter Assignments
|
||||
# ==================
|
||||
@ -200,7 +205,7 @@ set_global_assignment -name ENABLE_CONFIGURATION_PINS OFF
|
||||
set_global_assignment -name ENABLE_BOOT_SEL_PIN OFF
|
||||
set_global_assignment -name INTERNAL_FLASH_UPDATE_MODE "SINGLE COMP IMAGE"
|
||||
set_global_assignment -name CRC_ERROR_OPEN_DRAIN OFF
|
||||
set_global_assignment -name STRATIX_DEVICE_IO_STANDARD "3.3-V LVTTL"
|
||||
set_global_assignment -name STRATIX_DEVICE_IO_STANDARD "3.0-V LVTTL"
|
||||
|
||||
# Assembler Assignments
|
||||
# =====================
|
||||
@ -226,10 +231,8 @@ set_global_assignment -name OUTPUT_IO_TIMING_FAR_END_VMEAS "HALF SIGNAL SWING" -
|
||||
|
||||
# Pin & Location Assignments
|
||||
# ==========================
|
||||
set_instance_assignment -name FAST_INPUT_REGISTER ON -to io_usb_miosi[*]
|
||||
set_instance_assignment -name FAST_INPUT_REGISTER ON -to i_uart_rxd
|
||||
set_instance_assignment -name FAST_INPUT_REGISTER ON -to io_rtc_sda
|
||||
set_instance_assignment -name FAST_INPUT_REGISTER ON -to io_n64_si_dq
|
||||
set_instance_assignment -name FAST_INPUT_REGISTER ON -to i_n64_nmi
|
||||
set_instance_assignment -name FAST_INPUT_REGISTER ON -to i_n64_reset
|
||||
set_instance_assignment -name FAST_INPUT_REGISTER ON -to i_n64_si_clk
|
||||
@ -239,25 +242,19 @@ set_global_assignment -name OUTPUT_IO_TIMING_FAR_END_VMEAS "HALF SIGNAL SWING" -
|
||||
set_instance_assignment -name FAST_INPUT_REGISTER ON -to i_n64_pi_write
|
||||
set_instance_assignment -name FAST_INPUT_REGISTER ON -to i_n64_pi_alel
|
||||
set_instance_assignment -name FAST_INPUT_REGISTER ON -to io_sdram_dq[*]
|
||||
set_instance_assignment -name FAST_INPUT_REGISTER ON -to io_sd_*
|
||||
set_instance_assignment -name FAST_INPUT_REGISTER ON -to i_usb_pwren
|
||||
set_instance_assignment -name FAST_INPUT_REGISTER ON -to i_usb_miso
|
||||
set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to o_usb_clk
|
||||
set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to io_usb_miosi[*]
|
||||
set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to o_uart_txd
|
||||
set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to o_rtc_scl
|
||||
set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to io_rtc_sda
|
||||
set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to io_n64_pi_ad[*]
|
||||
set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to o_sdram_*
|
||||
set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to o_sdram_cs
|
||||
set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to o_sdram_ras
|
||||
set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to o_sdram_cas
|
||||
set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to o_sdram_we
|
||||
set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to o_sdram_a[*]
|
||||
set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to o_sdram_ba[*]
|
||||
set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to io_sdram_dq[*]
|
||||
set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to o_sd_clk
|
||||
set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to io_sd_*
|
||||
set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to o_usb_cs
|
||||
set_instance_assignment -name FAST_OUTPUT_ENABLE_REGISTER ON -to io_usb_miosi[*]
|
||||
set_instance_assignment -name FAST_OUTPUT_ENABLE_REGISTER ON -to io_n64_pi_ad[*]
|
||||
set_instance_assignment -name FAST_OUTPUT_ENABLE_REGISTER ON -to io_sdram_dq[*]
|
||||
set_instance_assignment -name FAST_OUTPUT_ENABLE_REGISTER ON -to io_sd_*
|
||||
set_instance_assignment -name FAST_OUTPUT_ENABLE_REGISTER ON -to io_rtc_sda
|
||||
|
||||
# Fitter Assignments
|
||||
# ==================
|
||||
@ -272,7 +269,6 @@ set_global_assignment -name OUTPUT_IO_TIMING_FAR_END_VMEAS "HALF SIGNAL SWING" -
|
||||
set_instance_assignment -name WEAK_PULL_UP_RESISTOR ON -to i_n64_pi_write
|
||||
set_instance_assignment -name WEAK_PULL_UP_RESISTOR ON -to i_n64_pi_alel
|
||||
set_instance_assignment -name WEAK_PULL_UP_RESISTOR ON -to o_n64_irq
|
||||
set_instance_assignment -name WEAK_PULL_UP_RESISTOR ON -to i_usb_pwren
|
||||
set_instance_assignment -name WEAK_PULL_UP_RESISTOR ON -to i_usb_miso
|
||||
|
||||
# start DESIGN_PARTITION(Top)
|
||||
|
@ -7,9 +7,9 @@ set sdram_pll_clk {system_inst|intel_pll_inst|altpll_component|auto_generated|pl
|
||||
# set sd_reg_clk {sd_interface_inst|sd_clk_inst|o_sd_clk|q}
|
||||
|
||||
create_generated_clock -name sdram_clk -source [get_pins $sdram_pll_clk] [get_ports {o_sdram_clk}]
|
||||
create_clock -name usb_clk -period 40.0 [get_ports {o_usb_clk}]
|
||||
# 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 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 \
|
||||
@ -30,6 +30,7 @@ set_input_delay -clock [get_clocks {sdram_clk}] -max 5.4 [get_ports $sdram_input
|
||||
set_input_delay -clock [get_clocks {sdram_clk}] -min 2.5 [get_ports $sdram_inputs]
|
||||
|
||||
set_multicycle_path -setup -end 2 -from [get_clocks {sdram_clk}] -to [get_clocks $sys_clk]
|
||||
set_multicycle_path -hold -end 1 -from [get_clocks {sdram_clk}] -to [get_clocks $sys_clk]
|
||||
|
||||
|
||||
# SD card timings
|
||||
@ -48,8 +49,17 @@ set_multicycle_path -setup -end 2 -from [get_clocks {sdram_clk}] -to [get_clocks
|
||||
|
||||
# FT1248 timings
|
||||
|
||||
set_false_path -to [get_ports {o_usb_clk io_usb_miosi[*] o_usb_cs}]
|
||||
set_false_path -from [get_ports {io_usb_miosi[*] i_usb_miso i_usb_pwren}]
|
||||
set_output_delay -clock [get_clocks {usb_clk}] -max 5.0 [get_ports {io_usb_miosi[*] o_usb_cs}]
|
||||
set_output_delay -clock [get_clocks {usb_clk}] -min -5.0 [get_ports {io_usb_miosi[*] o_usb_cs}]
|
||||
|
||||
set_input_delay -clock [get_clocks {usb_clk}] -max 5.0 [get_ports {io_usb_miosi[*] i_usb_miso}]
|
||||
set_input_delay -clock [get_clocks {usb_clk}] -min 5.0 [get_ports {io_usb_miosi[*] i_usb_miso}]
|
||||
|
||||
set_multicycle_path -setup -start 2 -from [get_clocks $sys_clk] -to [get_clocks {usb_clk}]
|
||||
set_multicycle_path -hold -start 3 -from [get_clocks $sys_clk] -to [get_clocks {usb_clk}]
|
||||
|
||||
set_multicycle_path -setup -end 2 -from [get_clocks {usb_clk}] -to [get_clocks $sys_clk]
|
||||
set_multicycle_path -hold -end 3 -from [get_clocks {usb_clk}] -to [get_clocks $sys_clk]
|
||||
|
||||
|
||||
# N64, PI and SI timings
|
||||
|
@ -1 +1 @@
|
||||
Subproject commit f9b1beb4cfd6b382157b54bc8f38c61d5ae7d785
|
||||
Subproject commit f00a88c36eaab478b64ee27d8162e421049bcc66
|
@ -29,8 +29,7 @@ module SummerCart64 (
|
||||
output o_usb_clk,
|
||||
output o_usb_cs,
|
||||
input i_usb_miso,
|
||||
inout [3:0] io_usb_miosi,
|
||||
input i_usb_pwren,
|
||||
inout [7:0] io_usb_miosi,
|
||||
|
||||
input i_uart_rxd,
|
||||
output o_uart_txd,
|
||||
@ -42,10 +41,6 @@ module SummerCart64 (
|
||||
output o_led
|
||||
);
|
||||
|
||||
logic [7:0] gpio_o;
|
||||
logic [7:0] gpio_i;
|
||||
logic [7:0] gpio_oe;
|
||||
|
||||
logic dd_interrupt;
|
||||
|
||||
if_system sys (
|
||||
@ -56,7 +51,7 @@ module SummerCart64 (
|
||||
|
||||
if_config cfg ();
|
||||
|
||||
if_dma dma ();
|
||||
if_memory_dma usb_dma ();
|
||||
|
||||
if_sdram sdram ();
|
||||
|
||||
@ -70,7 +65,6 @@ module SummerCart64 (
|
||||
.dd_interrupt(dd_interrupt)
|
||||
);
|
||||
|
||||
if_cpu_ram cpu_ram ();
|
||||
|
||||
system system_inst (
|
||||
.sys(sys)
|
||||
@ -85,13 +79,12 @@ module SummerCart64 (
|
||||
n64_soc n64_soc_inst (
|
||||
.sys(sys),
|
||||
.cfg(cfg),
|
||||
.dma(dma),
|
||||
.usb_dma(usb_dma),
|
||||
.sdram(sdram),
|
||||
.flashram(flashram),
|
||||
.si(si),
|
||||
.flash(flash),
|
||||
.dd(dd),
|
||||
.cpu_ram(cpu_ram),
|
||||
|
||||
.n64_pi_alel(i_n64_pi_alel),
|
||||
.n64_pi_aleh(i_n64_pi_aleh),
|
||||
@ -114,18 +107,13 @@ module SummerCart64 (
|
||||
cpu_soc cpu_soc_inst (
|
||||
.sys(sys),
|
||||
.cfg(cfg),
|
||||
.dma(dma),
|
||||
.usb_dma(usb_dma),
|
||||
.sdram(sdram),
|
||||
.flashram(flashram),
|
||||
.si(si),
|
||||
.flash(flash),
|
||||
.dd(dd),
|
||||
.cpu_ram(cpu_ram),
|
||||
|
||||
.gpio_o(gpio_o),
|
||||
.gpio_i(gpio_i),
|
||||
.gpio_oe(gpio_oe),
|
||||
|
||||
.i2c_scl(o_rtc_scl),
|
||||
.i2c_sda(io_rtc_sda),
|
||||
|
||||
@ -133,7 +121,6 @@ module SummerCart64 (
|
||||
.usb_cs(o_usb_cs),
|
||||
.usb_miso(i_usb_miso),
|
||||
.usb_miosi(io_usb_miosi),
|
||||
.usb_pwren(i_usb_pwren),
|
||||
|
||||
.uart_rxd(i_uart_rxd),
|
||||
.uart_txd(o_uart_txd),
|
||||
@ -145,14 +132,7 @@ module SummerCart64 (
|
||||
|
||||
always_comb begin
|
||||
o_n64_irq = dd_interrupt ? 1'b0 : 1'bZ;
|
||||
end
|
||||
|
||||
always_comb begin
|
||||
o_led = gpio_oe[0] ? gpio_o[0] : 1'bZ;
|
||||
end
|
||||
|
||||
always_ff @(posedge sys.clk) begin
|
||||
gpio_i <= {4'b0000, i_n64_nmi, i_n64_reset, gpio_o[1:0]};
|
||||
o_led = 1'bZ;
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
@ -1,6 +1,6 @@
|
||||
interface if_cpu_bus ();
|
||||
|
||||
localparam [3:0] NUM_DEVICES = sc64::__ID_CPU_END;
|
||||
interface if_cpu_bus #(
|
||||
parameter bit [3:0] NUM_DEVICES
|
||||
) ();
|
||||
|
||||
logic request;
|
||||
logic ack;
|
||||
|
@ -18,7 +18,8 @@ module cpu_cfg (
|
||||
R_VERSION,
|
||||
R_RECONFIGURE,
|
||||
R_ISV_OFFSET,
|
||||
R_ISV_RD_PTR
|
||||
R_ISV_RD_PTR,
|
||||
R_FLASH
|
||||
} e_reg_id;
|
||||
|
||||
const logic [31:0] RECONFIGURE_MAGIC = 32'h52535446;
|
||||
@ -39,7 +40,10 @@ module cpu_cfg (
|
||||
cfg.cpu_busy,
|
||||
1'b0,
|
||||
cfg.cmd_error,
|
||||
20'd0,
|
||||
2'd0,
|
||||
cfg.flash_erase_busy,
|
||||
1'd0,
|
||||
16'd0,
|
||||
cfg.isv_enabled,
|
||||
skip_bootloader,
|
||||
cfg.flashram_enabled,
|
||||
@ -73,6 +77,10 @@ module cpu_cfg (
|
||||
end
|
||||
|
||||
always_ff @(posedge sys.clk) begin
|
||||
cfg.flash_erase_start <= 1'b0;
|
||||
cfg.flash_wp_enable <= 1'b0;
|
||||
cfg.flash_wp_disable <= 1'b0;
|
||||
|
||||
if (sys.reset) begin
|
||||
cfg.cpu_ready <= 1'b0;
|
||||
cfg.cpu_busy <= 1'b0;
|
||||
@ -95,9 +103,11 @@ module cpu_cfg (
|
||||
cfg.sdram_writable <= 1'b0;
|
||||
isv_current_rd_ptr <= 16'd0;
|
||||
end
|
||||
|
||||
if (cfg.cmd_request) begin
|
||||
cfg.cpu_busy <= 1'b1;
|
||||
end
|
||||
|
||||
if (bus.request) begin
|
||||
case (bus.address[5:2])
|
||||
R_SCR: begin
|
||||
@ -105,8 +115,11 @@ module cpu_cfg (
|
||||
{
|
||||
cfg.cpu_ready,
|
||||
cfg.cpu_busy,
|
||||
cfg.cmd_error
|
||||
} <= {bus.wdata[31:30], bus.wdata[28]};
|
||||
cfg.cmd_error,
|
||||
cfg.flash_wp_disable,
|
||||
cfg.flash_wp_enable,
|
||||
cfg.flash_erase_start
|
||||
} <= {bus.wdata[31:30], bus.wdata[28:26], bus.wdata[24]};
|
||||
end
|
||||
if (bus.wmask[0]) begin
|
||||
{
|
||||
@ -156,31 +169,11 @@ module cpu_cfg (
|
||||
end
|
||||
end
|
||||
|
||||
logic [1:0] ru_clk;
|
||||
logic ru_rconfig;
|
||||
logic ru_regout;
|
||||
vendor_reconfigure vendor_reconfigure_inst (
|
||||
.clk(sys.clk),
|
||||
.reset(sys.reset),
|
||||
|
||||
always_ff @(posedge sys.clk) begin
|
||||
if (sys.reset) begin
|
||||
ru_clk <= 2'd0;
|
||||
ru_rconfig <= 1'b0;
|
||||
end else begin
|
||||
ru_clk <= ru_clk + 1'd1;
|
||||
|
||||
if (ru_clk == 2'd1) begin
|
||||
ru_rconfig <= trigger_reconfiguration;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
fiftyfivenm_rublock fiftyfivenm_rublock_inst (
|
||||
.clk(ru_clk[1]),
|
||||
.shiftnld(1'b0),
|
||||
.captnupdt(1'b0),
|
||||
.regin(1'b0),
|
||||
.rsttimer(1'b0),
|
||||
.rconfig(ru_rconfig),
|
||||
.regout(ru_regout)
|
||||
.trigger_reconfiguration(trigger_reconfiguration)
|
||||
);
|
||||
|
||||
endmodule
|
||||
|
@ -1,222 +0,0 @@
|
||||
interface if_dma ();
|
||||
|
||||
localparam [1:0] NUM_DEVICES = sc64::__ID_DMA_END;
|
||||
|
||||
sc64::e_dma_id id;
|
||||
|
||||
logic rx_empty;
|
||||
logic rx_read;
|
||||
logic [7:0] rx_rdata;
|
||||
logic tx_full;
|
||||
logic tx_write;
|
||||
logic [7:0] tx_wdata;
|
||||
|
||||
logic request;
|
||||
logic ack;
|
||||
logic write;
|
||||
logic [31:0] address;
|
||||
logic [15:0] rdata;
|
||||
logic [15:0] wdata;
|
||||
|
||||
modport controller (
|
||||
output id,
|
||||
|
||||
input rx_empty,
|
||||
output rx_read,
|
||||
input rx_rdata,
|
||||
input tx_full,
|
||||
output tx_write,
|
||||
output tx_wdata,
|
||||
|
||||
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
|
||||
);
|
||||
|
||||
logic [7:0] device_rx_rdata [(NUM_DEVICES - 1):0];
|
||||
logic device_rx_empty [(NUM_DEVICES - 1):0];
|
||||
logic device_tx_full [(NUM_DEVICES - 1):0];
|
||||
|
||||
always_comb begin
|
||||
rx_rdata = 8'd0;
|
||||
rx_empty = 1'b0;
|
||||
tx_full = 1'b0;
|
||||
|
||||
for (integer i = 0; i < NUM_DEVICES; i++) begin
|
||||
rx_rdata = rx_rdata | (id == i[1:0] ? device_rx_rdata[i] : 8'd0);
|
||||
rx_empty = rx_empty | (device_rx_empty[i] && id == i[1:0]);
|
||||
tx_full = tx_full | (device_tx_full[i] && id == i[1:0]);
|
||||
end
|
||||
end
|
||||
|
||||
genvar n;
|
||||
generate
|
||||
for (n = 0; n < NUM_DEVICES; n++) begin : at
|
||||
logic device_selected;
|
||||
logic device_rx_read;
|
||||
logic device_tx_write;
|
||||
|
||||
always_comb begin
|
||||
device_selected = id == n[1:0];
|
||||
device_rx_read = device_selected && rx_read;
|
||||
device_tx_write = device_selected && tx_write;
|
||||
end
|
||||
|
||||
modport device (
|
||||
output .rx_empty(device_rx_empty[n]),
|
||||
input .rx_read(device_rx_read),
|
||||
output .rx_rdata(device_rx_rdata[n]),
|
||||
output .tx_full(device_tx_full[n]),
|
||||
input .tx_write(device_tx_write),
|
||||
input .tx_wdata(tx_wdata)
|
||||
);
|
||||
end
|
||||
endgenerate
|
||||
|
||||
endinterface
|
||||
|
||||
|
||||
module cpu_dma (
|
||||
if_system.sys sys,
|
||||
if_cpu_bus bus,
|
||||
if_dma.controller dma
|
||||
);
|
||||
|
||||
typedef enum bit [2:0] {
|
||||
S_IDLE,
|
||||
S_FETCH,
|
||||
S_TRANSFER
|
||||
} e_state;
|
||||
|
||||
e_state state;
|
||||
logic pending_stop;
|
||||
logic direction;
|
||||
logic [27:0] length;
|
||||
logic [15:0] rdata_buffer;
|
||||
logic byte_counter;
|
||||
|
||||
always_comb begin
|
||||
bus.rdata = 32'd0;
|
||||
if (bus.ack) begin
|
||||
case (bus.address[3:2])
|
||||
0: bus.rdata = {28'd0, state != S_IDLE, direction, 2'b00};
|
||||
1: bus.rdata = dma.address;
|
||||
2: bus.rdata = {2'b00, dma.id, length};
|
||||
default: bus.rdata = 32'd0;
|
||||
endcase
|
||||
end
|
||||
end
|
||||
|
||||
always_ff @(posedge sys.clk) begin
|
||||
bus.ack <= 1'b0;
|
||||
if (bus.request) begin
|
||||
bus.ack <= 1'b1;
|
||||
end
|
||||
|
||||
dma.rx_read <= 1'b0;
|
||||
dma.tx_write <= 1'b0;
|
||||
|
||||
if (sys.reset) begin
|
||||
state <= S_IDLE;
|
||||
pending_stop <= 1'b0;
|
||||
dma.request <= 1'b0;
|
||||
end else begin
|
||||
if (bus.request && bus.address[3:2] == 0 && bus.wmask[0]) begin
|
||||
pending_stop <= bus.wdata[1];
|
||||
end
|
||||
|
||||
case (state)
|
||||
S_IDLE: begin
|
||||
pending_stop <= 1'b0;
|
||||
|
||||
if (bus.request) begin
|
||||
case (bus.address[3:2])
|
||||
0: if (bus.wmask[0]) begin
|
||||
direction <= bus.wdata[2];
|
||||
if (bus.wdata[0]) begin
|
||||
state <= S_FETCH;
|
||||
byte_counter <= 1'b0;
|
||||
end
|
||||
end
|
||||
|
||||
1: if (&bus.wmask) begin
|
||||
dma.address <= bus.wdata;
|
||||
end
|
||||
|
||||
2: if (&bus.wmask) begin
|
||||
{dma.id, length} <= {bus.wdata[29:1], 1'b0};
|
||||
end
|
||||
endcase
|
||||
end
|
||||
end
|
||||
|
||||
S_FETCH: begin
|
||||
if (length != 28'd0 && !pending_stop) begin
|
||||
if (direction) begin
|
||||
if (!dma.rx_empty && !dma.rx_read) begin
|
||||
dma.rx_read <= 1'b1;
|
||||
dma.wdata <= {dma.wdata[7:0], dma.rx_rdata};
|
||||
byte_counter <= ~byte_counter;
|
||||
if (byte_counter) begin
|
||||
state <= S_TRANSFER;
|
||||
dma.request <= 1'b1;
|
||||
dma.write <= 1'b1;
|
||||
end
|
||||
end
|
||||
end else begin
|
||||
dma.request <= 1'b1;
|
||||
dma.write <= 1'b0;
|
||||
if (dma.ack) begin
|
||||
state <= S_TRANSFER;
|
||||
dma.request <= 1'b0;
|
||||
rdata_buffer <= dma.rdata;
|
||||
end
|
||||
end
|
||||
end else begin
|
||||
state <= S_IDLE;
|
||||
end
|
||||
end
|
||||
|
||||
S_TRANSFER: begin
|
||||
if (direction) begin
|
||||
if (dma.ack) begin
|
||||
state <= S_FETCH;
|
||||
dma.request <= 1'b0;
|
||||
dma.address <= dma.address + 2'd2;
|
||||
length <= length - 2'd2;
|
||||
end
|
||||
end else begin
|
||||
if (!dma.tx_full && !dma.tx_write) begin
|
||||
dma.tx_write <= 1'b1;
|
||||
dma.tx_wdata <= byte_counter ? rdata_buffer[7:0] : rdata_buffer[15:8];
|
||||
byte_counter <= ~byte_counter;
|
||||
if (byte_counter) begin
|
||||
state <= S_FETCH;
|
||||
dma.address <= dma.address + 2'd2;
|
||||
length <= length - 2'd2;
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
default: begin
|
||||
state <= S_IDLE;
|
||||
dma.request <= 1'b0;
|
||||
end
|
||||
endcase
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
@ -16,7 +16,7 @@ interface if_flash ();
|
||||
output wdata
|
||||
);
|
||||
|
||||
modport memory (
|
||||
modport flash (
|
||||
input request,
|
||||
output ack,
|
||||
input write,
|
||||
|
@ -1,42 +0,0 @@
|
||||
module cpu_gpio (
|
||||
if_system.sys sys,
|
||||
if_cpu_bus bus,
|
||||
|
||||
input [7:0] gpio_i,
|
||||
output [7:0] gpio_o,
|
||||
output [7:0] gpio_oe
|
||||
);
|
||||
|
||||
logic [1:0][7:0] gpio_i_ff;
|
||||
logic [7:0] gpio_o_value;
|
||||
logic [7:0] gpio_oe_value;
|
||||
|
||||
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 = {8'd0, gpio_oe_value, gpio_i_ff[1], gpio_o_value};
|
||||
end
|
||||
end
|
||||
|
||||
always_ff @(posedge sys.clk) begin
|
||||
gpio_i_ff <= {gpio_i_ff[0], gpio_i};
|
||||
gpio_o <= gpio_o_value;
|
||||
gpio_oe <= gpio_oe_value;
|
||||
|
||||
if (sys.reset) begin
|
||||
gpio_o_value <= 8'd0;
|
||||
gpio_oe_value <= 8'd0;
|
||||
end else if (bus.request) begin
|
||||
if (bus.wmask[0]) gpio_o_value <= bus.wdata[7:0];
|
||||
if (bus.wmask[2]) gpio_oe_value <= bus.wdata[23:16];
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
@ -1,36 +1,10 @@
|
||||
interface if_cpu_ram ();
|
||||
|
||||
logic write;
|
||||
logic [12:0] address;
|
||||
logic [15:0] rdata;
|
||||
logic [15:0] wdata;
|
||||
|
||||
modport cpu (
|
||||
input write,
|
||||
input address,
|
||||
output rdata,
|
||||
input wdata
|
||||
);
|
||||
|
||||
modport external (
|
||||
output write,
|
||||
output address,
|
||||
input rdata,
|
||||
output wdata
|
||||
);
|
||||
|
||||
endinterface
|
||||
|
||||
|
||||
module cpu_ram (
|
||||
if_system.sys sys,
|
||||
if_cpu_bus bus,
|
||||
if_cpu_ram.cpu cpu_ram
|
||||
if_cpu_bus bus
|
||||
);
|
||||
|
||||
logic [3:0][7:0] ram [0:4095];
|
||||
logic [31:0] q_cpu;
|
||||
logic [31:0] q_external;
|
||||
logic [3:0][7:0] ram [0:8191];
|
||||
logic [31:0] q;
|
||||
|
||||
always_ff @(posedge sys.clk) begin
|
||||
bus.ack <= 1'b0;
|
||||
@ -40,33 +14,19 @@ module cpu_ram (
|
||||
end
|
||||
|
||||
always_comb begin
|
||||
cpu_ram.rdata = cpu_ram.address[0] ? q_external[31:16] : q_external[15:0];
|
||||
bus.rdata = 32'd0;
|
||||
if (bus.ack) begin
|
||||
bus.rdata = q_cpu;
|
||||
bus.rdata = q;
|
||||
end
|
||||
end
|
||||
|
||||
always_ff @(posedge sys.clk) begin
|
||||
q_cpu <= ram[bus.address[13:2]];
|
||||
q <= ram[bus.address[14:2]];
|
||||
if (bus.request) begin
|
||||
if (bus.wmask[0]) ram[bus.address[13:2]][0] <= bus.wdata[7:0];
|
||||
if (bus.wmask[1]) ram[bus.address[13:2]][1] <= bus.wdata[15:8];
|
||||
if (bus.wmask[2]) ram[bus.address[13:2]][2] <= bus.wdata[23:16];
|
||||
if (bus.wmask[3]) ram[bus.address[13:2]][3] <= bus.wdata[31:24];
|
||||
end
|
||||
end
|
||||
|
||||
always_ff @(posedge sys.clk) begin
|
||||
q_external <= ram[cpu_ram.address[12:1]];
|
||||
if (cpu_ram.write) begin
|
||||
if (cpu_ram.address[0]) begin
|
||||
ram[cpu_ram.address[12:1]][2] <= cpu_ram.wdata[7:0];
|
||||
ram[cpu_ram.address[12:1]][3] <= cpu_ram.wdata[15:8];
|
||||
end else begin
|
||||
ram[cpu_ram.address[12:1]][0] <= cpu_ram.wdata[7:0];
|
||||
ram[cpu_ram.address[12:1]][1] <= cpu_ram.wdata[15:8];
|
||||
end
|
||||
if (bus.wmask[0]) ram[bus.address[14:2]][0] <= bus.wdata[7:0];
|
||||
if (bus.wmask[1]) ram[bus.address[14:2]][1] <= bus.wdata[15:8];
|
||||
if (bus.wmask[2]) ram[bus.address[14:2]][2] <= bus.wdata[23:16];
|
||||
if (bus.wmask[3]) ram[bus.address[14:2]][3] <= bus.wdata[31:24];
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -1,17 +1,12 @@
|
||||
module cpu_soc (
|
||||
if_system.sys sys,
|
||||
if_config.cpu cfg,
|
||||
if_dma dma,
|
||||
if_memory_dma usb_dma,
|
||||
if_sdram.cpu sdram,
|
||||
if_flashram.cpu flashram,
|
||||
if_si.cpu si,
|
||||
if_flash.cpu flash,
|
||||
if_flash flash,
|
||||
if_dd.cpu dd,
|
||||
if_cpu_ram.cpu cpu_ram,
|
||||
|
||||
input [7:0] gpio_i,
|
||||
output [7:0] gpio_o,
|
||||
output [7:0] gpio_oe,
|
||||
|
||||
output i2c_scl,
|
||||
inout i2c_sda,
|
||||
@ -19,8 +14,7 @@ module cpu_soc (
|
||||
output usb_clk,
|
||||
output usb_cs,
|
||||
input usb_miso,
|
||||
inout [3:0] usb_miosi,
|
||||
input usb_pwren,
|
||||
inout [7:0] usb_miosi,
|
||||
|
||||
input uart_rxd,
|
||||
output uart_txd,
|
||||
@ -30,98 +24,98 @@ module cpu_soc (
|
||||
inout [3:0] sd_dat
|
||||
);
|
||||
|
||||
if_cpu_bus bus ();
|
||||
typedef enum bit [3:0] {
|
||||
DEV_FLASH,
|
||||
DEV_RAM,
|
||||
DEV_CFG,
|
||||
DEV_I2C,
|
||||
DEV_USB,
|
||||
DEV_UART,
|
||||
DEV_DD,
|
||||
DEV_SDRAM,
|
||||
DEV_FLASHRAM,
|
||||
DEV_SI,
|
||||
__NUM_DEVICES
|
||||
} e_bus_id;
|
||||
|
||||
if_cpu_bus #(
|
||||
.NUM_DEVICES(__NUM_DEVICES)
|
||||
) bus ();
|
||||
|
||||
cpu_wrapper cpu_wrapper_inst (
|
||||
.sys(sys),
|
||||
.bus(bus)
|
||||
);
|
||||
|
||||
cpu_ram cpu_ram_inst (
|
||||
.sys(sys),
|
||||
.bus(bus.at[sc64::ID_CPU_RAM].device),
|
||||
.cpu_ram(cpu_ram)
|
||||
);
|
||||
|
||||
cpu_flash cpu_flash_inst (
|
||||
.sys(sys),
|
||||
.bus(bus.at[sc64::ID_CPU_FLASH].device),
|
||||
.bus(bus.at[DEV_FLASH].device),
|
||||
.flash(flash)
|
||||
);
|
||||
|
||||
cpu_gpio cpu_gpio_inst (
|
||||
cpu_ram cpu_ram_inst (
|
||||
.sys(sys),
|
||||
.bus(bus.at[sc64::ID_CPU_GPIO].device),
|
||||
.gpio_i(gpio_i),
|
||||
.gpio_o(gpio_o),
|
||||
.gpio_oe(gpio_oe)
|
||||
.bus(bus.at[DEV_RAM].device)
|
||||
);
|
||||
|
||||
cpu_cfg cpu_cfg_inst (
|
||||
.sys(sys),
|
||||
.bus(bus.at[DEV_CFG].device),
|
||||
.cfg(cfg)
|
||||
);
|
||||
|
||||
cpu_i2c cpu_i2c_inst (
|
||||
.sys(sys),
|
||||
.bus(bus.at[sc64::ID_CPU_I2C].device),
|
||||
.bus(bus.at[DEV_I2C].device),
|
||||
.i2c_scl(i2c_scl),
|
||||
.i2c_sda(i2c_sda)
|
||||
);
|
||||
|
||||
cpu_usb cpu_usb_inst (
|
||||
.sys(sys),
|
||||
.bus(bus.at[sc64::ID_CPU_USB].device),
|
||||
.dma(dma.at[sc64::ID_DMA_USB].device),
|
||||
.bus(bus.at[DEV_USB].device),
|
||||
.dma(usb_dma),
|
||||
.usb_clk(usb_clk),
|
||||
.usb_cs(usb_cs),
|
||||
.usb_miso(usb_miso),
|
||||
.usb_miosi(usb_miosi),
|
||||
.usb_pwren(usb_pwren)
|
||||
.usb_miosi(usb_miosi)
|
||||
);
|
||||
|
||||
generate
|
||||
if (sc64::CPU_HAS_UART) begin
|
||||
cpu_uart cpu_uart_inst (
|
||||
.sys(sys),
|
||||
.bus(bus.at[sc64::ID_CPU_UART].device),
|
||||
.bus(bus.at[DEV_UART].device),
|
||||
.uart_rxd(uart_rxd),
|
||||
.uart_txd(uart_txd)
|
||||
);
|
||||
end
|
||||
endgenerate
|
||||
|
||||
cpu_dma cpu_dma_inst (
|
||||
cpu_dd cpu_dd_inst (
|
||||
.sys(sys),
|
||||
.bus(bus.at[sc64::ID_CPU_DMA].device),
|
||||
.dma(dma)
|
||||
);
|
||||
|
||||
cpu_cfg cpu_cfg_inst (
|
||||
.sys(sys),
|
||||
.bus(bus.at[sc64::ID_CPU_CFG].device),
|
||||
.cfg(cfg)
|
||||
.bus(bus.at[DEV_DD].device),
|
||||
.dd(dd)
|
||||
);
|
||||
|
||||
cpu_sdram cpu_sdram_inst (
|
||||
.sys(sys),
|
||||
.bus(bus.at[sc64::ID_CPU_SDRAM].device),
|
||||
.bus(bus.at[DEV_SDRAM].device),
|
||||
.sdram(sdram)
|
||||
);
|
||||
|
||||
cpu_flashram cpu_flashram_inst (
|
||||
.sys(sys),
|
||||
.bus(bus.at[sc64::ID_CPU_FLASHRAM].device),
|
||||
.bus(bus.at[DEV_FLASHRAM].device),
|
||||
.flashram(flashram)
|
||||
);
|
||||
|
||||
cpu_si cpu_si_inst (
|
||||
.sys(sys),
|
||||
.bus(bus.at[sc64::ID_CPU_SI].device),
|
||||
.bus(bus.at[DEV_SI].device),
|
||||
.si(si)
|
||||
);
|
||||
|
||||
cpu_dd cpu_dd_inst (
|
||||
.sys(sys),
|
||||
.bus(bus.at[sc64::ID_CPU_DD].device),
|
||||
.dd(dd)
|
||||
);
|
||||
|
||||
assign sd_clk = 1'bZ;
|
||||
assign sd_cmd = 1'bZ;
|
||||
assign sd_dat = 4'bZZZZ;
|
||||
|
@ -1,44 +1,27 @@
|
||||
module cpu_usb (
|
||||
if_system sys,
|
||||
if_cpu_bus bus,
|
||||
if_dma dma,
|
||||
if_memory_dma dma,
|
||||
|
||||
output usb_clk,
|
||||
output usb_cs,
|
||||
input usb_miso,
|
||||
inout [3:0] usb_miosi,
|
||||
input usb_pwren
|
||||
inout [7:0] usb_miosi
|
||||
);
|
||||
|
||||
logic rx_flush;
|
||||
logic rx_empty;
|
||||
logic rx_read;
|
||||
logic [7:0] rx_rdata;
|
||||
|
||||
logic tx_flush;
|
||||
logic tx_full;
|
||||
logic tx_write;
|
||||
logic [7:0] tx_wdata;
|
||||
logic usb_enable;
|
||||
logic reset_pending;
|
||||
logic reset_ack;
|
||||
logic write_buffer_flush;
|
||||
|
||||
logic rx_escape_valid;
|
||||
logic rx_escape_ack;
|
||||
logic [7:0] rx_escape;
|
||||
|
||||
logic cpu_rx_read;
|
||||
logic cpu_tx_write;
|
||||
|
||||
logic usb_enabled;
|
||||
logic tx_force;
|
||||
|
||||
always_comb begin
|
||||
dma.rx_empty = rx_empty;
|
||||
rx_read = cpu_rx_read || dma.rx_read;
|
||||
dma.rx_rdata = rx_rdata;
|
||||
|
||||
dma.tx_full = tx_full;
|
||||
tx_write = cpu_tx_write || dma.tx_write;
|
||||
tx_wdata = dma.tx_write ? dma.tx_wdata : bus.wdata[7:0];
|
||||
end
|
||||
typedef enum bit [1:0] {
|
||||
R_SCR,
|
||||
R_DATA,
|
||||
R_ADDR,
|
||||
R_LEN
|
||||
} e_reg_id;
|
||||
|
||||
always_ff @(posedge sys.clk) begin
|
||||
bus.ack <= 1'b0;
|
||||
@ -51,75 +34,93 @@ module cpu_usb (
|
||||
bus.rdata = 32'd0;
|
||||
if (bus.ack) begin
|
||||
case (bus.address[3:2])
|
||||
0: bus.rdata = {25'd0, rx_escape_valid, usb_pwren, usb_enabled, 2'b00, ~tx_full, ~rx_empty};
|
||||
1: bus.rdata = {24'd0, rx_rdata};
|
||||
2: bus.rdata = {24'd0, rx_escape};
|
||||
R_SCR: bus.rdata = {
|
||||
23'd0,
|
||||
dma.busy,
|
||||
1'b0,
|
||||
reset_pending,
|
||||
1'b0,
|
||||
usb_enable,
|
||||
2'b00,
|
||||
~dma.tx_full,
|
||||
~dma.rx_empty
|
||||
};
|
||||
R_DATA: bus.rdata = {24'd0, dma.rx_rdata};
|
||||
default: bus.rdata = 32'd0;
|
||||
endcase
|
||||
end
|
||||
end
|
||||
|
||||
always_ff @(posedge sys.clk) begin
|
||||
dma.start <= 1'b0;
|
||||
dma.stop <= 1'b0;
|
||||
dma.cpu_rx_read <= 1'b0;
|
||||
dma.cpu_tx_write <= 1'b0;
|
||||
rx_flush <= 1'b0;
|
||||
cpu_rx_read <= 1'b0;
|
||||
|
||||
tx_flush <= 1'b0;
|
||||
cpu_tx_write <= 1'b0;
|
||||
|
||||
rx_escape_ack <= 1'b0;
|
||||
tx_force <= 1'b0;
|
||||
reset_ack <= 1'b0;
|
||||
write_buffer_flush <= 1'b0;
|
||||
|
||||
if (sys.reset) begin
|
||||
usb_enabled <= 1'b0;
|
||||
usb_enable <= 1'b0;
|
||||
end else begin
|
||||
if (bus.request) begin
|
||||
case (bus.address[2:2])
|
||||
2'd0: begin
|
||||
if (bus.wmask[1]) begin
|
||||
tx_force <= bus.wdata[8];
|
||||
end
|
||||
if (bus.wmask[0]) begin
|
||||
rx_escape_ack <= bus.wdata[7];
|
||||
{usb_enabled, tx_flush, rx_flush} <= bus.wdata[4:2];
|
||||
end
|
||||
case (bus.address[3:2])
|
||||
R_SCR: if (&bus.wmask) begin
|
||||
{dma.direction, dma.stop, dma.start} <= bus.wdata[11:9];
|
||||
reset_ack <= bus.wdata[7];
|
||||
{write_buffer_flush, usb_enable, tx_flush, rx_flush} <= bus.wdata[5:2];
|
||||
end
|
||||
|
||||
2'd1: begin
|
||||
if (bus.wmask[0]) begin
|
||||
cpu_tx_write <= 1'b1;
|
||||
end else begin
|
||||
cpu_rx_read <= 1'b1;
|
||||
end
|
||||
R_DATA: if (bus.wmask == 4'b0000) begin
|
||||
dma.cpu_rx_read <= 1'b1;
|
||||
end else if (bus.wmask == 4'b0001) begin
|
||||
dma.cpu_tx_write <= 1'b1;
|
||||
dma.cpu_tx_wdata <= bus.wdata[7:0];
|
||||
end
|
||||
|
||||
R_ADDR: if (&bus.wmask) begin
|
||||
dma.starting_address <= bus.wdata;
|
||||
end
|
||||
|
||||
R_LEN: if (&bus.wmask) begin
|
||||
dma.transfer_length <= bus.wdata;
|
||||
end
|
||||
endcase
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
usb_ft1248 usb_ft1248_inst (
|
||||
.sys(sys),
|
||||
memory_dma usb_memory_dma_inst (
|
||||
.clk(sys.clk),
|
||||
.reset(~usb_enable),
|
||||
.dma(dma)
|
||||
);
|
||||
|
||||
.usb_enabled(usb_enabled),
|
||||
.tx_force(tx_force),
|
||||
usb_ft1248 usb_ft1248_inst (
|
||||
.clk(sys.clk),
|
||||
.reset(~usb_enable),
|
||||
|
||||
.usb_clk(usb_clk),
|
||||
.usb_cs(usb_cs),
|
||||
.usb_miso(usb_miso),
|
||||
.usb_miosi(usb_miosi),
|
||||
|
||||
.reset_pending(reset_pending),
|
||||
.reset_ack(reset_ack),
|
||||
.write_buffer_flush(write_buffer_flush),
|
||||
|
||||
.rx_flush(rx_flush),
|
||||
.rx_empty(rx_empty),
|
||||
.rx_read(rx_read),
|
||||
.rx_rdata(rx_rdata),
|
||||
.rx_empty(dma.rx_empty),
|
||||
.rx_almost_empty(dma.rx_almost_empty),
|
||||
.rx_read(dma.rx_read),
|
||||
.rx_rdata(dma.rx_rdata),
|
||||
|
||||
.tx_flush(tx_flush),
|
||||
.tx_full(tx_full),
|
||||
.tx_write(tx_write),
|
||||
.tx_wdata(tx_wdata),
|
||||
|
||||
.rx_escape_valid(rx_escape_valid),
|
||||
.rx_escape_ack(rx_escape_ack),
|
||||
.rx_escape(rx_escape)
|
||||
.tx_full(dma.tx_full),
|
||||
.tx_almost_full(dma.tx_almost_full),
|
||||
.tx_write(dma.tx_write),
|
||||
.tx_wdata(dma.tx_wdata)
|
||||
);
|
||||
|
||||
endmodule
|
||||
|
@ -28,12 +28,29 @@ module cpu_wrapper (
|
||||
end
|
||||
end
|
||||
|
||||
logic trap;
|
||||
logic mem_valid;
|
||||
logic mem_instr;
|
||||
logic [31:0] mem_la_addr;
|
||||
logic [31:0] mem_la_wdata;
|
||||
logic [3:0] mem_la_wstrb;
|
||||
logic pcpi_valid;
|
||||
logic [31:0] pcpi_insn;
|
||||
logic [31:0] pcpi_rs1;
|
||||
logic [31:0] pcpi_rs2;
|
||||
logic [31:0] eoi;
|
||||
logic trace_valid;
|
||||
logic [35:0] trace_data;
|
||||
|
||||
picorv32 #(
|
||||
.ENABLE_COUNTERS(0),
|
||||
.ENABLE_COUNTERS64(0),
|
||||
.TWO_STAGE_SHIFT(0),
|
||||
.TWO_CYCLE_COMPARE(1),
|
||||
.TWO_CYCLE_ALU(1),
|
||||
.CATCH_MISALIGN(0),
|
||||
.CATCH_ILLINSN(0),
|
||||
.PROGADDR_RESET(sc64::CPU_RESET_VECTOR)
|
||||
.PROGADDR_RESET(32'h0001_0000)
|
||||
) cpu_inst (
|
||||
.clk(sys.clk),
|
||||
.resetn(~sys.reset),
|
||||
@ -43,7 +60,26 @@ module cpu_wrapper (
|
||||
.mem_ready(bus.ack),
|
||||
.mem_rdata(bus.rdata),
|
||||
.mem_la_read(mem_la_read),
|
||||
.mem_la_write(mem_la_write)
|
||||
.mem_la_write(mem_la_write),
|
||||
|
||||
.trap(trap),
|
||||
.mem_valid(mem_valid),
|
||||
.mem_instr(mem_instr),
|
||||
.mem_la_addr(mem_la_addr),
|
||||
.mem_la_wdata(mem_la_wdata),
|
||||
.mem_la_wstrb(mem_la_wstrb),
|
||||
.pcpi_valid(pcpi_valid),
|
||||
.pcpi_insn(pcpi_insn),
|
||||
.pcpi_rs1(pcpi_rs1),
|
||||
.pcpi_rs2(pcpi_rs2),
|
||||
.pcpi_wr(1'b0),
|
||||
.pcpi_rd(32'd0),
|
||||
.pcpi_wait(1'b0),
|
||||
.pcpi_ready(1'b0),
|
||||
.irq(32'd0),
|
||||
.eoi(eoi),
|
||||
.trace_valid(trace_valid),
|
||||
.trace_data(trace_data)
|
||||
);
|
||||
|
||||
endmodule
|
||||
|
@ -9,7 +9,7 @@
|
||||
// scfifo
|
||||
//
|
||||
// Simulation Library Files(s):
|
||||
//
|
||||
// altera_mf
|
||||
// ============================================================
|
||||
// ************************************************************
|
||||
// THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE!
|
||||
@ -43,6 +43,8 @@ module intel_fifo_8 (
|
||||
rdreq,
|
||||
sclr,
|
||||
wrreq,
|
||||
almost_empty,
|
||||
almost_full,
|
||||
empty,
|
||||
full,
|
||||
q);
|
||||
@ -52,16 +54,22 @@ module intel_fifo_8 (
|
||||
input rdreq;
|
||||
input sclr;
|
||||
input wrreq;
|
||||
output almost_empty;
|
||||
output almost_full;
|
||||
output empty;
|
||||
output full;
|
||||
output [7:0] q;
|
||||
|
||||
wire sub_wire0;
|
||||
wire sub_wire1;
|
||||
wire [7:0] sub_wire2;
|
||||
wire empty = sub_wire0;
|
||||
wire full = sub_wire1;
|
||||
wire [7:0] q = sub_wire2[7:0];
|
||||
wire sub_wire2;
|
||||
wire sub_wire3;
|
||||
wire [7:0] sub_wire4;
|
||||
wire almost_empty = sub_wire0;
|
||||
wire almost_full = sub_wire1;
|
||||
wire empty = sub_wire2;
|
||||
wire full = sub_wire3;
|
||||
wire [7:0] q = sub_wire4[7:0];
|
||||
|
||||
scfifo scfifo_component (
|
||||
.clock (clock),
|
||||
@ -69,16 +77,18 @@ module intel_fifo_8 (
|
||||
.rdreq (rdreq),
|
||||
.sclr (sclr),
|
||||
.wrreq (wrreq),
|
||||
.empty (sub_wire0),
|
||||
.full (sub_wire1),
|
||||
.q (sub_wire2),
|
||||
.almost_empty (sub_wire0),
|
||||
.almost_full (sub_wire1),
|
||||
.empty (sub_wire2),
|
||||
.full (sub_wire3),
|
||||
.q (sub_wire4),
|
||||
.aclr (),
|
||||
.almost_empty (),
|
||||
.almost_full (),
|
||||
.eccstatus (),
|
||||
.usedw ());
|
||||
defparam
|
||||
scfifo_component.add_ram_output_register = "ON",
|
||||
scfifo_component.add_ram_output_register = "OFF",
|
||||
scfifo_component.almost_empty_value = 2,
|
||||
scfifo_component.almost_full_value = 1023,
|
||||
scfifo_component.intended_device_family = "MAX 10",
|
||||
scfifo_component.lpm_numwords = 1024,
|
||||
scfifo_component.lpm_showahead = "ON",
|
||||
@ -95,10 +105,10 @@ endmodule
|
||||
// ============================================================
|
||||
// CNX file retrieval info
|
||||
// ============================================================
|
||||
// Retrieval info: PRIVATE: AlmostEmpty NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: AlmostEmptyThr NUMERIC "-1"
|
||||
// Retrieval info: PRIVATE: AlmostFull NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: AlmostFullThr NUMERIC "-1"
|
||||
// Retrieval info: PRIVATE: AlmostEmpty NUMERIC "1"
|
||||
// Retrieval info: PRIVATE: AlmostEmptyThr NUMERIC "2"
|
||||
// Retrieval info: PRIVATE: AlmostFull NUMERIC "1"
|
||||
// Retrieval info: PRIVATE: AlmostFullThr NUMERIC "1023"
|
||||
// Retrieval info: PRIVATE: CLOCKS_ARE_SYNCHRONIZED NUMERIC "1"
|
||||
// Retrieval info: PRIVATE: Clock NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: Depth NUMERIC "1024"
|
||||
@ -109,7 +119,7 @@ endmodule
|
||||
// Retrieval info: PRIVATE: LegacyRREQ NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: MAX_DEPTH_BY_9 NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: OVERFLOW_CHECKING NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: Optimize NUMERIC "1"
|
||||
// Retrieval info: PRIVATE: Optimize NUMERIC "2"
|
||||
// Retrieval info: PRIVATE: RAM_BLOCK_TYPE NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: SYNTH_WRAPPER_GEN_POSTFIX STRING "0"
|
||||
// Retrieval info: PRIVATE: UNDERFLOW_CHECKING NUMERIC "0"
|
||||
@ -128,7 +138,9 @@ endmodule
|
||||
// Retrieval info: PRIVATE: wsFull NUMERIC "1"
|
||||
// Retrieval info: PRIVATE: wsUsedW NUMERIC "0"
|
||||
// Retrieval info: LIBRARY: altera_mf altera_mf.altera_mf_components.all
|
||||
// Retrieval info: CONSTANT: ADD_RAM_OUTPUT_REGISTER STRING "ON"
|
||||
// Retrieval info: CONSTANT: ADD_RAM_OUTPUT_REGISTER STRING "OFF"
|
||||
// Retrieval info: CONSTANT: ALMOST_EMPTY_VALUE NUMERIC "2"
|
||||
// Retrieval info: CONSTANT: ALMOST_FULL_VALUE NUMERIC "1023"
|
||||
// Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "MAX 10"
|
||||
// Retrieval info: CONSTANT: LPM_NUMWORDS NUMERIC "1024"
|
||||
// Retrieval info: CONSTANT: LPM_SHOWAHEAD STRING "ON"
|
||||
@ -138,6 +150,8 @@ endmodule
|
||||
// Retrieval info: CONSTANT: OVERFLOW_CHECKING STRING "ON"
|
||||
// Retrieval info: CONSTANT: UNDERFLOW_CHECKING STRING "ON"
|
||||
// Retrieval info: CONSTANT: USE_EAB STRING "ON"
|
||||
// Retrieval info: USED_PORT: almost_empty 0 0 0 0 OUTPUT NODEFVAL "almost_empty"
|
||||
// Retrieval info: USED_PORT: almost_full 0 0 0 0 OUTPUT NODEFVAL "almost_full"
|
||||
// Retrieval info: USED_PORT: clock 0 0 0 0 INPUT NODEFVAL "clock"
|
||||
// Retrieval info: USED_PORT: data 0 0 8 0 INPUT NODEFVAL "data[7..0]"
|
||||
// Retrieval info: USED_PORT: empty 0 0 0 0 OUTPUT NODEFVAL "empty"
|
||||
@ -151,6 +165,8 @@ endmodule
|
||||
// Retrieval info: CONNECT: @rdreq 0 0 0 0 rdreq 0 0 0 0
|
||||
// Retrieval info: CONNECT: @sclr 0 0 0 0 sclr 0 0 0 0
|
||||
// Retrieval info: CONNECT: @wrreq 0 0 0 0 wrreq 0 0 0 0
|
||||
// Retrieval info: CONNECT: almost_empty 0 0 0 0 @almost_empty 0 0 0 0
|
||||
// Retrieval info: CONNECT: almost_full 0 0 0 0 @almost_full 0 0 0 0
|
||||
// Retrieval info: CONNECT: empty 0 0 0 0 @empty 0 0 0 0
|
||||
// Retrieval info: CONNECT: full 0 0 0 0 @full 0 0 0 0
|
||||
// Retrieval info: CONNECT: q 0 0 8 0 @q 0 0 8 0
|
||||
@ -160,3 +176,4 @@ endmodule
|
||||
// Retrieval info: GEN_FILE: TYPE_NORMAL intel_fifo_8.bsf FALSE
|
||||
// Retrieval info: GEN_FILE: TYPE_NORMAL intel_fifo_8_inst.v FALSE
|
||||
// Retrieval info: GEN_FILE: TYPE_NORMAL intel_fifo_8_bb.v FALSE
|
||||
// Retrieval info: LIB_FILE: altera_mf
|
||||
|
@ -9,7 +9,7 @@
|
||||
// altpll
|
||||
//
|
||||
// Simulation Library Files(s):
|
||||
//
|
||||
// altera_mf
|
||||
// ============================================================
|
||||
// ************************************************************
|
||||
// THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE!
|
||||
@ -337,4 +337,5 @@ endmodule
|
||||
// Retrieval info: GEN_FILE: TYPE_NORMAL intel_pll.bsf FALSE
|
||||
// Retrieval info: GEN_FILE: TYPE_NORMAL intel_pll_inst.v FALSE
|
||||
// Retrieval info: GEN_FILE: TYPE_NORMAL intel_pll_bb.v FALSE
|
||||
// Retrieval info: LIB_FILE: altera_mf
|
||||
// Retrieval info: CBX_MODULE_PREFIX: ON
|
||||
|
237
fw/rtl/memory/memory_dma.sv
Normal file
237
fw/rtl/memory/memory_dma.sv
Normal file
@ -0,0 +1,237 @@
|
||||
interface if_memory_dma ();
|
||||
|
||||
logic request;
|
||||
logic ack;
|
||||
logic write;
|
||||
logic [1:0] wmask;
|
||||
logic [31:0] address;
|
||||
logic [15:0] rdata;
|
||||
logic [15:0] wdata;
|
||||
|
||||
logic start;
|
||||
logic stop;
|
||||
logic busy;
|
||||
logic direction;
|
||||
logic [31:0] transfer_length;
|
||||
logic [31:0] starting_address;
|
||||
|
||||
logic dma_rx_read;
|
||||
logic dma_tx_write;
|
||||
logic [7:0] dma_tx_wdata;
|
||||
|
||||
logic cpu_rx_read;
|
||||
logic cpu_tx_write;
|
||||
logic [7:0] cpu_tx_wdata;
|
||||
|
||||
logic rx_empty;
|
||||
logic rx_almost_empty;
|
||||
logic rx_read;
|
||||
logic [7:0] rx_rdata;
|
||||
|
||||
logic tx_full;
|
||||
logic tx_almost_full;
|
||||
logic tx_write;
|
||||
logic [7:0] tx_wdata;
|
||||
|
||||
always_comb begin
|
||||
rx_read = dma_rx_read || cpu_rx_read;
|
||||
tx_write = dma_tx_write || cpu_tx_write;
|
||||
tx_wdata = cpu_tx_write ? cpu_tx_wdata : dma_tx_wdata;
|
||||
end
|
||||
|
||||
modport dma (
|
||||
input start,
|
||||
input stop,
|
||||
output busy,
|
||||
input direction,
|
||||
input transfer_length,
|
||||
input starting_address,
|
||||
|
||||
output request,
|
||||
input ack,
|
||||
output write,
|
||||
output wmask,
|
||||
output address,
|
||||
input rdata,
|
||||
output wdata,
|
||||
|
||||
input rx_empty,
|
||||
input rx_almost_empty,
|
||||
output dma_rx_read,
|
||||
input rx_rdata,
|
||||
|
||||
input tx_full,
|
||||
input tx_almost_full,
|
||||
output dma_tx_write,
|
||||
output dma_tx_wdata
|
||||
);
|
||||
|
||||
modport cpu (
|
||||
output start,
|
||||
output stop,
|
||||
input busy,
|
||||
output direction,
|
||||
output transfer_length,
|
||||
output starting_address,
|
||||
|
||||
input rx_empty,
|
||||
output cpu_rx_read,
|
||||
input rx_rdata,
|
||||
|
||||
input tx_full,
|
||||
output cpu_tx_write,
|
||||
output cpu_tx_wdata
|
||||
);
|
||||
|
||||
modport memory (
|
||||
input request,
|
||||
output ack,
|
||||
input write,
|
||||
input wmask,
|
||||
input address,
|
||||
output rdata,
|
||||
input wdata
|
||||
);
|
||||
|
||||
modport device (
|
||||
output rx_empty,
|
||||
output rx_almost_empty,
|
||||
input rx_read,
|
||||
output rx_rdata,
|
||||
|
||||
output tx_full,
|
||||
output tx_almost_full,
|
||||
input tx_write,
|
||||
input tx_wdata
|
||||
);
|
||||
|
||||
endinterface
|
||||
|
||||
|
||||
module memory_dma (
|
||||
input clk,
|
||||
input reset,
|
||||
if_memory_dma.dma dma
|
||||
);
|
||||
|
||||
typedef enum bit [0:0] {
|
||||
STATE_FETCH,
|
||||
STATE_TRANSFER
|
||||
} e_state;
|
||||
|
||||
logic [31:0] remaining;
|
||||
logic [15:0] data_buffer;
|
||||
logic byte_counter;
|
||||
e_state state;
|
||||
|
||||
always_ff @(posedge clk) begin
|
||||
dma.dma_rx_read <= 1'b0;
|
||||
dma.dma_tx_write <= 1'b0;
|
||||
|
||||
if (dma.dma_rx_read) begin
|
||||
if (dma.address[0] || (remaining == 32'd1)) begin
|
||||
dma.wdata <= {dma.rx_rdata, dma.rx_rdata};
|
||||
end else begin
|
||||
dma.wdata <= {dma.wdata[7:0], dma.rx_rdata};
|
||||
end
|
||||
end
|
||||
|
||||
if (reset) begin
|
||||
dma.busy <= 1'b0;
|
||||
dma.request <= 1'b0;
|
||||
end else begin
|
||||
if (!dma.busy) begin
|
||||
if (dma.start) begin
|
||||
dma.busy <= 1'b1;
|
||||
dma.write <= dma.direction;
|
||||
dma.address <= dma.starting_address;
|
||||
remaining <= dma.transfer_length;
|
||||
byte_counter <= 1'd0;
|
||||
state <= STATE_FETCH;
|
||||
end
|
||||
end else begin
|
||||
if (dma.stop) begin
|
||||
dma.busy <= 1'b0;
|
||||
dma.request <= 1'b0;
|
||||
end else if (remaining != 32'd0) begin
|
||||
if (dma.write) begin
|
||||
case (state)
|
||||
STATE_FETCH: begin
|
||||
if (!dma.rx_empty && !(dma.dma_rx_read && dma.rx_almost_empty)) begin
|
||||
dma.dma_rx_read <= 1'b1;
|
||||
if (dma.address[0]) begin
|
||||
dma.wmask <= 2'b01;
|
||||
state <= STATE_TRANSFER;
|
||||
end else if (remaining == 32'd1) begin
|
||||
dma.wmask <= 2'b10;
|
||||
state <= STATE_TRANSFER;
|
||||
end else begin
|
||||
byte_counter <= byte_counter + 1'd1;
|
||||
if (byte_counter) begin
|
||||
dma.wmask <= 2'b11;
|
||||
state <= STATE_TRANSFER;
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
STATE_TRANSFER: begin
|
||||
dma.request <= 1'b1;
|
||||
if (dma.ack) begin
|
||||
dma.request <= 1'b0;
|
||||
if (dma.wmask != 2'b11) begin
|
||||
dma.address <= dma.address + 1'd1;
|
||||
remaining <= remaining - 1'd1;
|
||||
end else begin
|
||||
dma.address <= dma.address + 2'd2;
|
||||
remaining <= remaining - 2'd2;
|
||||
end
|
||||
state <= STATE_FETCH;
|
||||
end
|
||||
end
|
||||
endcase
|
||||
end else begin
|
||||
case (state)
|
||||
STATE_FETCH: begin
|
||||
dma.request <= 1'b1;
|
||||
if (dma.ack) begin
|
||||
dma.request <= 1'b0;
|
||||
data_buffer <= dma.rdata;
|
||||
state <= STATE_TRANSFER;
|
||||
end
|
||||
end
|
||||
|
||||
STATE_TRANSFER: begin
|
||||
if (!dma.tx_full && !(dma.dma_tx_write && dma.tx_almost_full)) begin
|
||||
dma.dma_tx_write <= 1'b1;
|
||||
if (dma.address[0]) begin
|
||||
dma.address <= dma.address + 1'd1;
|
||||
remaining <= remaining - 1'd1;
|
||||
dma.dma_tx_wdata <= data_buffer[7:0];
|
||||
state <= STATE_FETCH;
|
||||
end else if (remaining == 32'd1) begin
|
||||
dma.address <= dma.address + 1'd1;
|
||||
remaining <= remaining - 1'd1;
|
||||
dma.dma_tx_wdata <= data_buffer[15:8];
|
||||
state <= STATE_FETCH;
|
||||
end else begin
|
||||
dma.dma_tx_wdata <= byte_counter ? data_buffer[7:0] : data_buffer[15:8];
|
||||
byte_counter <= byte_counter + 1'd1;
|
||||
if (byte_counter) begin
|
||||
dma.address <= dma.address + 2'd2;
|
||||
remaining <= remaining - 2'd2;
|
||||
state <= STATE_FETCH;
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
endcase
|
||||
end
|
||||
end else begin
|
||||
dma.busy <= 1'b0;
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
@ -1,20 +1,10 @@
|
||||
module n64_bootloader (
|
||||
if_system.sys sys,
|
||||
if_n64_bus bus,
|
||||
if_flash.memory flash
|
||||
if_config.flash cfg,
|
||||
if_flash.flash flash
|
||||
);
|
||||
|
||||
logic mem_request;
|
||||
logic csr_ack;
|
||||
logic data_ack;
|
||||
logic write_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
|
||||
@ -28,97 +18,77 @@ module n64_bootloader (
|
||||
e_state state;
|
||||
e_source_request source_request;
|
||||
|
||||
always_ff @(posedge sys.clk) begin
|
||||
csr_ack <= 1'b0;
|
||||
write_ack <= 1'b0;
|
||||
logic request;
|
||||
logic ack;
|
||||
logic write;
|
||||
logic [31:0] address;
|
||||
logic [31:0] wdata;
|
||||
logic [31:0] rdata;
|
||||
|
||||
always_ff @(posedge sys.clk) begin
|
||||
if (sys.reset) begin
|
||||
state <= S_IDLE;
|
||||
mem_request <= 1'b0;
|
||||
request <= 1'b0;
|
||||
end else begin
|
||||
case (state)
|
||||
S_IDLE: begin
|
||||
if (bus.request || flash.request) begin
|
||||
state <= S_WAIT;
|
||||
mem_request <= 1'b1;
|
||||
request <= 1'b1;
|
||||
if (bus.request) begin
|
||||
mem_write <= 1'b0;
|
||||
mem_address <= bus.address;
|
||||
mem_wdata <= bus.wdata;
|
||||
write <= 1'b0;
|
||||
address <= bus.address;
|
||||
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;
|
||||
write <= flash.write;
|
||||
address <= flash.address;
|
||||
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 (!mem_address[27] && mem_write && !data_busy && !write_ack) begin
|
||||
write_ack <= 1'b1;
|
||||
end
|
||||
if (csr_ack || data_ack || write_ack) begin
|
||||
if (ack) begin
|
||||
state <= S_IDLE;
|
||||
request <= 1'b0;
|
||||
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.ack = source_request == T_N64 && ack;
|
||||
bus.rdata = 16'd0;
|
||||
if (bus.ack && bus.address < 32'h00010000) 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]};
|
||||
if (bus.address[1]) bus.rdata = {rdata[23:16], rdata[31:24]};
|
||||
else bus.rdata = {rdata[7:0], rdata[15:8]};
|
||||
end
|
||||
|
||||
flash.ack = source_request == T_CPU && (csr_ack || data_ack || write_ack);
|
||||
flash.ack = source_request == T_CPU && ack;
|
||||
flash.rdata = 32'd0;
|
||||
if (flash.ack) begin
|
||||
flash.rdata = csr_or_data ? csr_rdata : data_rdata;
|
||||
flash.rdata = rdata;
|
||||
end
|
||||
end
|
||||
|
||||
intel_flash intel_flash_inst (
|
||||
.clock(sys.clk),
|
||||
.reset_n(~sys.reset),
|
||||
vendor_flash vendor_flash_inst (
|
||||
.clk(sys.clk),
|
||||
.reset(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),
|
||||
.erase_start(cfg.flash_erase_start),
|
||||
.erase_busy(cfg.flash_erase_busy),
|
||||
.wp_enable(cfg.flash_wp_enable),
|
||||
.wp_disable(cfg.flash_wp_disable),
|
||||
|
||||
.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)
|
||||
.request(request),
|
||||
.ack(ack),
|
||||
.write(write),
|
||||
.address(address),
|
||||
.wdata(wdata),
|
||||
.rdata(rdata)
|
||||
);
|
||||
|
||||
endmodule
|
||||
|
@ -1,8 +1,7 @@
|
||||
module n64_cfg (
|
||||
if_system sys,
|
||||
if_n64_bus bus,
|
||||
if_config.n64 cfg,
|
||||
if_cpu_ram.external cpu_ram
|
||||
if_config.n64 cfg
|
||||
);
|
||||
|
||||
typedef enum bit [2:0] {
|
||||
@ -32,10 +31,6 @@ module n64_cfg (
|
||||
logic [31:0] isv_id;
|
||||
|
||||
always_comb begin
|
||||
cpu_ram.write = bus.request && bus.write && (bus.address[15:14] == 2'b01);
|
||||
cpu_ram.address = bus.address[13:1];
|
||||
cpu_ram.wdata = {bus.wdata[7:0], bus.wdata[15:8]};
|
||||
|
||||
bus.rdata = 16'd0;
|
||||
if (bus.ack) begin
|
||||
if (bus.address[15:14] == 2'b00) begin
|
||||
@ -54,14 +49,14 @@ module n64_cfg (
|
||||
R_DATA_1_L: bus.rdata = cfg.data[1][15:0];
|
||||
R_VERSION_H: bus.rdata = sc64::SC64_VER[31:16];
|
||||
R_VERSION_L: bus.rdata = sc64::SC64_VER[15:0];
|
||||
default: bus.rdata = 16'd0;
|
||||
endcase
|
||||
end else if (bus.address[15:14] == 2'b01) begin
|
||||
bus.rdata = {cpu_ram.rdata[7:0], cpu_ram.rdata[15:8]};
|
||||
end else if (bus.address[15:14] == 2'b11) begin
|
||||
case (bus.address[4:1])
|
||||
R_ISV_ID_H: bus.rdata = isv_id[31:16];
|
||||
R_ISV_ID_L: bus.rdata = isv_id[15:0];
|
||||
R_ISV_RD_PTR: bus.rdata = cfg.isv_rd_ptr;
|
||||
default: bus.rdata = 16'd0;
|
||||
endcase
|
||||
end
|
||||
end
|
||||
|
@ -1,7 +1,7 @@
|
||||
module n64_sdram (
|
||||
if_system sys,
|
||||
if_n64_bus bus,
|
||||
if_dma.memory dma,
|
||||
if_memory_dma.memory usb_dma,
|
||||
if_sdram.memory sdram,
|
||||
|
||||
output sdram_cs,
|
||||
@ -20,58 +20,40 @@ module n64_sdram (
|
||||
logic [15:0] mem_rdata;
|
||||
logic [15:0] mem_wdata;
|
||||
|
||||
typedef enum bit [0:0] {
|
||||
S_IDLE,
|
||||
S_WAIT
|
||||
} e_state;
|
||||
|
||||
typedef enum bit [1:0] {
|
||||
T_BUS,
|
||||
T_DMA,
|
||||
T_SDRAM
|
||||
T_SDRAM,
|
||||
T_USB_DMA
|
||||
} e_source_request;
|
||||
|
||||
e_state state;
|
||||
e_source_request source_request;
|
||||
|
||||
always_ff @(posedge sys.clk) begin
|
||||
if (sys.reset) begin
|
||||
state <= S_IDLE;
|
||||
mem_request <= 1'b0;
|
||||
end else begin
|
||||
case (state)
|
||||
S_IDLE: begin
|
||||
if (bus.request) begin
|
||||
state <= S_WAIT;
|
||||
mem_request <= 1'b1;
|
||||
mem_write <= bus.write;
|
||||
mem_address <= bus.address;
|
||||
mem_wdata <= bus.wdata;
|
||||
source_request <= T_BUS;
|
||||
end else if ((!bus.n64_active) && (sdram.request || dma.request)) begin
|
||||
state <= S_WAIT;
|
||||
mem_request <= 1'b1;
|
||||
if (sdram.request) begin
|
||||
mem_write <= sdram.write;
|
||||
mem_address <= sdram.address;
|
||||
mem_wdata <= sdram.wdata;
|
||||
source_request <= T_SDRAM;
|
||||
end else if (dma.request) begin
|
||||
mem_write <= dma.write;
|
||||
mem_address <= dma.address;
|
||||
mem_wdata <= dma.wdata;
|
||||
source_request <= T_DMA;
|
||||
end
|
||||
end
|
||||
if (!mem_request && (bus.request || sdram.request || usb_dma.request)) begin
|
||||
mem_request <= 1'b1;
|
||||
if (bus.request) begin
|
||||
mem_write <= bus.write;
|
||||
mem_address <= bus.address;
|
||||
mem_wdata <= bus.wdata;
|
||||
source_request <= T_BUS;
|
||||
end else if (sdram.request) begin
|
||||
mem_write <= sdram.write;
|
||||
mem_address <= sdram.address;
|
||||
mem_wdata <= sdram.wdata;
|
||||
source_request <= T_SDRAM;
|
||||
end else if (usb_dma.request) begin
|
||||
mem_write <= usb_dma.write;
|
||||
mem_address <= usb_dma.address;
|
||||
mem_wdata <= usb_dma.wdata;
|
||||
source_request <= T_USB_DMA;
|
||||
end
|
||||
|
||||
S_WAIT: begin
|
||||
if (mem_ack) begin
|
||||
state <= S_IDLE;
|
||||
mem_request <= 1'b0;
|
||||
end
|
||||
end
|
||||
endcase
|
||||
end
|
||||
if (mem_ack) begin
|
||||
mem_request <= 1'b0;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@ -79,11 +61,11 @@ module n64_sdram (
|
||||
bus.ack = source_request == T_BUS && mem_ack;
|
||||
bus.rdata = bus.ack ? mem_rdata : 16'd0;
|
||||
|
||||
dma.ack = source_request == T_DMA && mem_ack;
|
||||
dma.rdata = mem_rdata;
|
||||
|
||||
sdram.ack = source_request == T_SDRAM && mem_ack;
|
||||
sdram.rdata = mem_rdata;
|
||||
|
||||
usb_dma.ack = source_request == T_USB_DMA && mem_ack;
|
||||
usb_dma.rdata = mem_rdata;
|
||||
end
|
||||
|
||||
memory_sdram memory_sdram_inst (
|
||||
|
@ -1,13 +1,12 @@
|
||||
module n64_soc (
|
||||
if_system sys,
|
||||
if_config cfg,
|
||||
if_dma.memory dma,
|
||||
if_memory_dma.memory usb_dma,
|
||||
if_sdram.memory sdram,
|
||||
if_flashram.flashram flashram,
|
||||
if_si.si si,
|
||||
if_flash.memory flash,
|
||||
if_flash.flash flash,
|
||||
if_dd dd,
|
||||
if_cpu_ram.external cpu_ram,
|
||||
|
||||
input n64_pi_alel,
|
||||
input n64_pi_aleh,
|
||||
@ -52,7 +51,7 @@ module n64_soc (
|
||||
n64_sdram n64_sdram_inst (
|
||||
.sys(sys),
|
||||
.bus(bus.at[sc64::ID_N64_SDRAM].device),
|
||||
.dma(dma),
|
||||
.usb_dma(usb_dma),
|
||||
.sdram(sdram),
|
||||
|
||||
.sdram_cs(sdram_cs),
|
||||
@ -67,6 +66,7 @@ module n64_soc (
|
||||
n64_bootloader n64_bootloader_inst (
|
||||
.sys(sys),
|
||||
.bus(bus.at[sc64::ID_N64_BOOTLOADER].device),
|
||||
.cfg(cfg),
|
||||
.flash(flash)
|
||||
);
|
||||
|
||||
@ -91,8 +91,7 @@ module n64_soc (
|
||||
n64_cfg n64_cfg_inst (
|
||||
.sys(sys),
|
||||
.bus(bus.at[sc64::ID_N64_CFG].device),
|
||||
.cfg(cfg),
|
||||
.cpu_ram(cpu_ram)
|
||||
.cfg(cfg)
|
||||
);
|
||||
|
||||
endmodule
|
||||
|
@ -20,6 +20,10 @@ interface if_config ();
|
||||
logic [25:0] save_offset;
|
||||
logic [25:0] isv_offset;
|
||||
logic [15:0] isv_rd_ptr;
|
||||
logic flash_erase_start;
|
||||
logic flash_erase_busy;
|
||||
logic flash_wp_enable;
|
||||
logic flash_wp_disable;
|
||||
|
||||
modport pi (
|
||||
input sdram_switch,
|
||||
@ -39,6 +43,13 @@ interface if_config ();
|
||||
output flashram_read_mode
|
||||
);
|
||||
|
||||
modport flash (
|
||||
input flash_erase_start,
|
||||
output flash_erase_busy,
|
||||
input flash_wp_enable,
|
||||
input flash_wp_disable
|
||||
);
|
||||
|
||||
modport n64 (
|
||||
input cpu_ready,
|
||||
input cpu_busy,
|
||||
@ -70,7 +81,11 @@ interface if_config ();
|
||||
output ddipl_offset,
|
||||
output save_offset,
|
||||
output isv_offset,
|
||||
input isv_rd_ptr
|
||||
input isv_rd_ptr,
|
||||
output flash_erase_start,
|
||||
input flash_erase_busy,
|
||||
output flash_wp_enable,
|
||||
output flash_wp_disable
|
||||
);
|
||||
|
||||
endinterface
|
||||
|
@ -9,31 +9,8 @@ package sc64;
|
||||
__ID_N64_END
|
||||
} e_n64_id;
|
||||
|
||||
typedef enum bit [3:0] {
|
||||
ID_CPU_RAM,
|
||||
ID_CPU_FLASH,
|
||||
ID_CPU_GPIO,
|
||||
ID_CPU_I2C,
|
||||
ID_CPU_USB,
|
||||
ID_CPU_UART,
|
||||
ID_CPU_DMA,
|
||||
ID_CPU_CFG,
|
||||
ID_CPU_SDRAM,
|
||||
ID_CPU_FLASHRAM,
|
||||
ID_CPU_SI,
|
||||
ID_CPU_DD,
|
||||
__ID_CPU_END
|
||||
} e_cpu_id;
|
||||
|
||||
typedef enum bit [1:0] {
|
||||
ID_DMA_USB,
|
||||
ID_DMA_SD,
|
||||
__ID_DMA_END
|
||||
} e_dma_id;
|
||||
|
||||
parameter bit [31:0] SC64_VER = 32'h53437632;
|
||||
parameter int CLOCK_FREQUENCY = 32'd100_000_000;
|
||||
parameter bit [31:0] CPU_RESET_VECTOR = {4'(ID_CPU_FLASH), 28'h0010000};
|
||||
parameter int UART_BAUD_RATE = 32'd1_000_000;
|
||||
|
||||
`ifdef DEBUG
|
||||
|
@ -1,280 +1,241 @@
|
||||
module usb_ft1248 (
|
||||
if_system.sys sys,
|
||||
|
||||
input usb_enabled,
|
||||
input tx_force,
|
||||
input clk,
|
||||
input reset,
|
||||
|
||||
output usb_clk,
|
||||
output usb_cs,
|
||||
input usb_miso,
|
||||
inout [3:0] usb_miosi,
|
||||
inout [7:0] usb_miosi,
|
||||
|
||||
output reset_pending,
|
||||
input reset_ack,
|
||||
input write_buffer_flush,
|
||||
|
||||
input rx_flush,
|
||||
output rx_empty,
|
||||
output rx_almost_empty,
|
||||
input rx_read,
|
||||
output [7:0] rx_rdata,
|
||||
|
||||
input tx_flush,
|
||||
output tx_full,
|
||||
output tx_almost_full,
|
||||
input tx_write,
|
||||
input [7:0] tx_wdata,
|
||||
|
||||
output rx_escape_valid,
|
||||
input rx_escape_ack,
|
||||
output [7:0] rx_escape
|
||||
input [7:0] tx_wdata
|
||||
);
|
||||
|
||||
parameter bit [7:0] ESCAPE_CHARACTER = 8'h1B;
|
||||
|
||||
// FIFOs
|
||||
|
||||
logic rx_full;
|
||||
logic rx_almost_full;
|
||||
logic rx_write;
|
||||
logic [7:0] rx_wdata;
|
||||
|
||||
logic tx_empty;
|
||||
logic tx_almost_empty;
|
||||
logic tx_read;
|
||||
logic [7:0] tx_rdata;
|
||||
|
||||
logic rx_wdata_valid;
|
||||
logic rx_escape_active;
|
||||
|
||||
intel_fifo_8 fifo_8_rx_inst (
|
||||
.clock(sys.clk),
|
||||
.sclr(rx_flush || !usb_enabled),
|
||||
.clock(clk),
|
||||
.sclr(reset || rx_flush),
|
||||
|
||||
.empty(rx_empty),
|
||||
.almost_empty(rx_almost_empty),
|
||||
.rdreq(rx_read),
|
||||
.q(rx_rdata),
|
||||
|
||||
.full(rx_full),
|
||||
.almost_full(rx_almost_full),
|
||||
.wrreq(rx_write),
|
||||
.data(rx_wdata)
|
||||
.data(usb_miosi)
|
||||
);
|
||||
|
||||
intel_fifo_8 fifo_8_tx_inst (
|
||||
.clock(sys.clk),
|
||||
.sclr(tx_flush || !usb_enabled),
|
||||
.clock(clk),
|
||||
.sclr(reset || tx_flush),
|
||||
|
||||
.empty(tx_empty),
|
||||
.almost_empty(tx_almost_empty),
|
||||
.rdreq(tx_read),
|
||||
.q(tx_rdata),
|
||||
|
||||
.full(tx_full),
|
||||
.almost_full(tx_almost_full),
|
||||
.wrreq(tx_write),
|
||||
.data(tx_wdata)
|
||||
);
|
||||
|
||||
|
||||
// Escape character detection
|
||||
|
||||
always_comb begin
|
||||
rx_write = 1'b0;
|
||||
if (rx_wdata_valid) begin
|
||||
rx_write = rx_escape_active ? rx_wdata == ESCAPE_CHARACTER : rx_wdata != ESCAPE_CHARACTER;
|
||||
end
|
||||
end
|
||||
|
||||
always_ff @(posedge sys.clk) begin
|
||||
if (sys.reset || !usb_enabled) begin
|
||||
rx_escape_valid <= 1'b0;
|
||||
rx_escape_active <= 1'b0;
|
||||
end else begin
|
||||
if (rx_escape_ack) begin
|
||||
rx_escape_valid <= 1'b0;
|
||||
end
|
||||
|
||||
if (rx_wdata_valid) begin
|
||||
if (!rx_escape_active) begin
|
||||
if (rx_wdata == ESCAPE_CHARACTER) begin
|
||||
rx_escape_active <= 1'b1;
|
||||
end
|
||||
end else begin
|
||||
rx_escape_active <= 1'b0;
|
||||
rx_escape <= rx_wdata;
|
||||
if (rx_wdata != ESCAPE_CHARACTER) begin
|
||||
rx_escape_valid <= 1'b1;
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
// FT1248 interface controller
|
||||
|
||||
typedef enum bit [1:0] {
|
||||
S_TRY_RX,
|
||||
S_TRY_TX,
|
||||
S_COMMAND,
|
||||
S_DATA
|
||||
typedef enum bit [2:0] {
|
||||
STATE_IDLE,
|
||||
STATE_SELECT,
|
||||
STATE_COMMAND,
|
||||
STATE_STATUS,
|
||||
STATE_DATA,
|
||||
STATE_DESELECT
|
||||
} e_state;
|
||||
|
||||
typedef enum bit [7:0] {
|
||||
C_WRITE = 8'h00,
|
||||
C_READ = 8'h04,
|
||||
C_FORCE = 8'h80
|
||||
CMD_WRITE = 8'h00,
|
||||
CMD_READ = 8'h40,
|
||||
CMD_READ_MODEM_STATUS = 8'h20,
|
||||
CMD_WRITE_MODEM_STATUS = 8'h60,
|
||||
CMD_WRITE_BUFFER_FLUSH = 8'h08
|
||||
} e_command;
|
||||
|
||||
typedef enum bit [1:0] {
|
||||
P_PRE_RISING,
|
||||
P_RISING,
|
||||
P_PRE_FALLING,
|
||||
P_FALLING
|
||||
} e_clock_phase;
|
||||
|
||||
logic usb_miosi_oe;
|
||||
logic write_buffer_flush_pending;
|
||||
logic write_modem_status_pending;
|
||||
logic [4:0] modem_status_counter;
|
||||
logic modem_status_read;
|
||||
logic last_reset_status;
|
||||
logic reset_reply;
|
||||
logic [3:0] phase;
|
||||
logic [7:0] usb_cmd;
|
||||
e_state state;
|
||||
|
||||
logic [3:0] clock_phase;
|
||||
|
||||
logic usb_clk_output;
|
||||
logic usb_cs_output;
|
||||
logic [3:0] usb_miosi_input;
|
||||
logic [3:0] usb_miosi_output;
|
||||
logic [3:0] usb_miosi_output_data;
|
||||
logic usb_miosi_output_enable;
|
||||
logic usb_miosi_output_enable_data;
|
||||
logic usb_miso_input;
|
||||
|
||||
logic tx_force_pending;
|
||||
logic is_cmd_write;
|
||||
logic is_cmd_tx_force;
|
||||
logic [1:0] nibble_counter;
|
||||
logic [7:0] tx_buffer;
|
||||
|
||||
always_ff @(posedge sys.clk) begin
|
||||
if (sys.reset || state == S_TRY_RX || state == S_TRY_TX) begin
|
||||
clock_phase <= 4'b0001;
|
||||
end else begin
|
||||
clock_phase <= {clock_phase[2:0], clock_phase[3]};
|
||||
end
|
||||
end
|
||||
|
||||
always_ff @(posedge sys.clk) begin
|
||||
usb_clk <= usb_clk_output;
|
||||
usb_cs <= usb_cs_output;
|
||||
|
||||
usb_miosi_input <= usb_miosi;
|
||||
usb_miosi_output <= usb_miosi_output_data;
|
||||
usb_miosi_output_enable <= usb_miosi_output_enable_data;
|
||||
|
||||
usb_miso_input <= usb_miso;
|
||||
|
||||
tx_buffer <= tx_rdata;
|
||||
end
|
||||
|
||||
always_comb begin
|
||||
usb_miosi = usb_miosi_output_enable ? usb_miosi_output : 4'bZZZZ;
|
||||
end
|
||||
|
||||
always_comb begin
|
||||
case (state)
|
||||
S_COMMAND: begin
|
||||
usb_clk_output = clock_phase[P_PRE_FALLING] || clock_phase[P_FALLING];
|
||||
usb_cs_output = 1'b0;
|
||||
if (is_cmd_tx_force) begin
|
||||
usb_miosi_output_data = nibble_counter[0] ? C_FORCE[3:0] : C_FORCE[7:4];
|
||||
end else if (is_cmd_write) begin
|
||||
usb_miosi_output_data = nibble_counter[0] ? C_WRITE[3:0] : C_WRITE[7:4];
|
||||
end else begin
|
||||
usb_miosi_output_data = nibble_counter[0] ? C_READ[3:0] : C_READ[7:4];
|
||||
usb_miosi = 8'hZZ;
|
||||
if (usb_miosi_oe) begin
|
||||
usb_miosi = 8'h00;
|
||||
if ((state == STATE_COMMAND) || (state == STATE_STATUS)) begin
|
||||
usb_miosi = usb_cmd;
|
||||
end
|
||||
if ((state == STATE_DATA) || (state == STATE_DESELECT)) begin
|
||||
if (usb_cmd == CMD_WRITE) begin
|
||||
usb_miosi = tx_rdata;
|
||||
end
|
||||
if (usb_cmd == CMD_WRITE_MODEM_STATUS) begin
|
||||
usb_miosi = {2'b00, reset_reply, 5'b00000};
|
||||
end
|
||||
usb_miosi_output_enable_data = nibble_counter < 2'd2;
|
||||
end
|
||||
|
||||
S_DATA: begin
|
||||
usb_clk_output = clock_phase[P_PRE_FALLING] || clock_phase[P_FALLING];
|
||||
usb_cs_output = 1'b0;
|
||||
usb_miosi_output_data = nibble_counter[0] ? tx_buffer[7:4] : tx_buffer[3:0];
|
||||
usb_miosi_output_enable_data = is_cmd_write;
|
||||
end
|
||||
|
||||
default: begin
|
||||
usb_clk_output = 1'b0;
|
||||
usb_cs_output = 1'b1;
|
||||
usb_miosi_output_data = 4'hF;
|
||||
usb_miosi_output_enable_data = 1'b0;
|
||||
end
|
||||
endcase
|
||||
end
|
||||
end
|
||||
|
||||
always_ff @(posedge sys.clk) begin
|
||||
rx_wdata_valid <= 1'b0;
|
||||
always_ff @(posedge clk) begin
|
||||
rx_write <= 1'b0;
|
||||
tx_read <= 1'b0;
|
||||
modem_status_read <= 1'b0;
|
||||
phase <= {phase[2:0], phase[3]};
|
||||
|
||||
if (clock_phase[P_RISING]) begin
|
||||
nibble_counter <= nibble_counter + 1'd1;
|
||||
end
|
||||
|
||||
if (sys.reset || !usb_enabled) begin
|
||||
state <= S_TRY_RX;
|
||||
tx_force_pending <= 1'b0;
|
||||
if (reset) begin
|
||||
usb_clk <= 1'b0;
|
||||
usb_cs <= 1'b1;
|
||||
usb_miosi_oe <= 1'b0;
|
||||
reset_pending <= 1'b0;
|
||||
write_buffer_flush_pending <= 1'b0;
|
||||
write_modem_status_pending <= 1'b0;
|
||||
modem_status_counter <= 5'd0;
|
||||
last_reset_status <= 1'b0;
|
||||
reset_reply <= 1'b0;
|
||||
phase <= 4'b0001;
|
||||
state <= STATE_IDLE;
|
||||
end else begin
|
||||
if (tx_force) begin
|
||||
tx_force_pending <= 1'b1;
|
||||
if (write_buffer_flush) begin
|
||||
write_buffer_flush_pending <= 1'b1;
|
||||
end
|
||||
|
||||
if (reset_ack) begin
|
||||
reset_pending <= 1'b0;
|
||||
write_modem_status_pending <= 1'b1;
|
||||
reset_reply <= 1'b1;
|
||||
end
|
||||
|
||||
if (modem_status_read) begin
|
||||
last_reset_status <= usb_miosi[0];
|
||||
if (!last_reset_status && usb_miosi[0]) begin
|
||||
reset_pending <= 1'b1;
|
||||
end
|
||||
if (last_reset_status && !usb_miosi[0]) begin
|
||||
write_modem_status_pending <= 1'b1;
|
||||
reset_reply <= 1'b0;
|
||||
end
|
||||
end
|
||||
|
||||
case (state)
|
||||
S_TRY_RX: begin
|
||||
if (!rx_full && !rx_escape_valid) begin
|
||||
state <= S_COMMAND;
|
||||
is_cmd_write <= 1'b0;
|
||||
is_cmd_tx_force <= 1'b0;
|
||||
nibble_counter <= 2'b11;
|
||||
STATE_IDLE: begin
|
||||
usb_cs <= 1'b0;
|
||||
state <= STATE_SELECT;
|
||||
if (write_modem_status_pending) begin
|
||||
usb_cmd <= CMD_WRITE_MODEM_STATUS;
|
||||
end else if (&modem_status_counter) begin
|
||||
usb_cmd <= CMD_READ_MODEM_STATUS;
|
||||
end else if (!tx_empty) begin
|
||||
usb_cmd <= CMD_WRITE;
|
||||
end else if (write_buffer_flush_pending) begin
|
||||
usb_cmd <= CMD_WRITE_BUFFER_FLUSH;
|
||||
end else if (!rx_full) begin
|
||||
usb_cmd <= CMD_READ;
|
||||
end else begin
|
||||
state <= S_TRY_TX;
|
||||
usb_cs <= 1'b1;
|
||||
modem_status_counter <= modem_status_counter + 1'd1;
|
||||
state <= STATE_IDLE;
|
||||
end
|
||||
end
|
||||
|
||||
S_TRY_TX: begin
|
||||
if (!tx_empty) begin
|
||||
state <= S_COMMAND;
|
||||
is_cmd_write <= 1'b1;
|
||||
is_cmd_tx_force <= 1'b0;
|
||||
nibble_counter <= 2'b11;
|
||||
end else if (tx_force_pending) begin
|
||||
state <= S_COMMAND;
|
||||
tx_force_pending <= 1'b0;
|
||||
is_cmd_write <= 1'b1;
|
||||
is_cmd_tx_force <= 1'b1;
|
||||
nibble_counter <= 2'b11;
|
||||
end else begin
|
||||
state <= S_TRY_RX;
|
||||
STATE_SELECT: begin
|
||||
phase <= 4'b0001;
|
||||
state <= STATE_COMMAND;
|
||||
end
|
||||
|
||||
STATE_COMMAND: begin
|
||||
if (phase[0]) begin
|
||||
usb_clk <= 1'b1;
|
||||
usb_miosi_oe <= 1'b1;
|
||||
end else if (phase[2]) begin
|
||||
usb_clk <= 1'b0;
|
||||
end else if (phase[3]) begin
|
||||
state <= STATE_STATUS;
|
||||
end
|
||||
end
|
||||
|
||||
S_COMMAND: begin
|
||||
if (clock_phase[P_RISING]) begin
|
||||
if (nibble_counter == 2'd2) begin
|
||||
if (usb_miso_input || is_cmd_tx_force) begin
|
||||
state <= is_cmd_write ? S_TRY_RX : S_TRY_TX;
|
||||
end else begin
|
||||
state <= S_DATA;
|
||||
nibble_counter <= 2'd0;
|
||||
STATE_STATUS: begin
|
||||
if (phase[0]) begin
|
||||
usb_clk <= 1'b1;
|
||||
usb_miosi_oe <= 1'b0;
|
||||
end else if (phase[2]) begin
|
||||
usb_clk <= 1'b0;
|
||||
end else if (phase[3]) begin
|
||||
state <= STATE_DATA;
|
||||
end
|
||||
end
|
||||
|
||||
STATE_DATA: begin
|
||||
if (phase[0]) begin
|
||||
usb_clk <= 1'b1;
|
||||
usb_miosi_oe <= (usb_cmd == CMD_WRITE) || (usb_cmd == CMD_WRITE_MODEM_STATUS);
|
||||
end else if (phase[2]) begin
|
||||
usb_clk <= 1'b0;
|
||||
end else if (phase[3]) begin
|
||||
if (usb_miso) begin
|
||||
state <= STATE_DESELECT;
|
||||
end else if (usb_cmd == CMD_WRITE) begin
|
||||
tx_read <= 1'b1;
|
||||
if (tx_almost_empty) begin
|
||||
state <= STATE_DESELECT;
|
||||
end
|
||||
end else if (usb_cmd == CMD_READ) begin
|
||||
rx_write <= 1'b1;
|
||||
if (rx_almost_full) begin
|
||||
state <= STATE_DESELECT;
|
||||
end
|
||||
end else if (usb_cmd == CMD_READ_MODEM_STATUS) begin
|
||||
modem_status_read <= 1'b1;
|
||||
state <= STATE_DESELECT;
|
||||
end else if (usb_cmd == CMD_WRITE_MODEM_STATUS) begin
|
||||
write_modem_status_pending <= 1'b0;
|
||||
state <= STATE_DESELECT;
|
||||
end else if (usb_cmd == CMD_WRITE_BUFFER_FLUSH) begin
|
||||
write_buffer_flush_pending <= 1'b0;
|
||||
state <= STATE_DESELECT;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
S_DATA: begin
|
||||
if (clock_phase[P_FALLING]) begin
|
||||
if (nibble_counter[0]) begin
|
||||
tx_read <= is_cmd_write;
|
||||
end
|
||||
STATE_DESELECT: begin
|
||||
usb_cs <= 1'b1;
|
||||
usb_miosi_oe <= 1'b0;
|
||||
if (phase[1]) begin
|
||||
modem_status_counter <= modem_status_counter + 1'd1;
|
||||
state <= STATE_IDLE;
|
||||
end
|
||||
if (clock_phase[P_RISING]) begin
|
||||
rx_wdata <= {usb_miosi_input, rx_wdata[7:4]};
|
||||
if (nibble_counter[0]) begin
|
||||
rx_wdata_valid <= !is_cmd_write;
|
||||
end
|
||||
if (usb_miso_input || (!is_cmd_write && (rx_full || rx_escape_valid)) || (is_cmd_write && tx_empty)) begin
|
||||
state <= is_cmd_write ? S_TRY_RX : S_TRY_TX;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
default: begin
|
||||
state <= S_TRY_RX;
|
||||
end
|
||||
endcase
|
||||
end
|
||||
|
175
fw/rtl/vendor/vendor_flash.sv
vendored
Normal file
175
fw/rtl/vendor/vendor_flash.sv
vendored
Normal file
@ -0,0 +1,175 @@
|
||||
module vendor_flash (
|
||||
input clk,
|
||||
input reset,
|
||||
|
||||
input erase_start,
|
||||
output erase_busy,
|
||||
input wp_enable,
|
||||
input wp_disable,
|
||||
|
||||
input request,
|
||||
output ack,
|
||||
input write,
|
||||
input [31:0] address,
|
||||
input [31:0] wdata,
|
||||
output [31:0] rdata
|
||||
);
|
||||
|
||||
const int FLASH_SECTORS = 3'd4;
|
||||
|
||||
typedef enum bit [1:0] {
|
||||
STATE_START,
|
||||
STATE_PENDING,
|
||||
STATE_ERASING
|
||||
} e_erase_state;
|
||||
|
||||
typedef enum bit [0:0] {
|
||||
CSR_STATUS = 1'b0,
|
||||
CSR_CONTROL = 1'b1
|
||||
} e_flash_csr;
|
||||
|
||||
typedef enum bit [1:0] {
|
||||
STATUS_IDLE = 2'b00,
|
||||
STATUS_BUSY_ERASE = 2'b01,
|
||||
STATUS_BUSY_WRITE = 2'b10,
|
||||
STATUS_BUSY_READ = 2'b11
|
||||
} e_flash_status;
|
||||
|
||||
logic csr_read;
|
||||
logic csr_write;
|
||||
e_flash_csr csr_address;
|
||||
logic [31:0] csr_wdata;
|
||||
logic [31:0] csr_rdata;
|
||||
|
||||
logic wp_setting;
|
||||
logic [2:0] erase_sector;
|
||||
e_erase_state state;
|
||||
|
||||
always_ff @(posedge clk) begin
|
||||
csr_read <= 1'b0;
|
||||
csr_write <= 1'b0;
|
||||
csr_address <= CSR_STATUS;
|
||||
|
||||
if (reset) begin
|
||||
erase_busy <= 1'b0;
|
||||
wp_setting <= 1'b1;
|
||||
end else if (!erase_busy) begin
|
||||
if (erase_start) begin
|
||||
erase_busy <= 1'b1;
|
||||
erase_sector <= 3'd1;
|
||||
state <= STATE_START;
|
||||
end else if (wp_enable) begin
|
||||
csr_write <= 1'b1;
|
||||
csr_address <= CSR_CONTROL;
|
||||
csr_wdata <= 32'hFFFF_FFFF;
|
||||
wp_setting <= 1'b1;
|
||||
end else if (wp_disable) begin
|
||||
csr_write <= 1'b1;
|
||||
csr_address <= CSR_CONTROL;
|
||||
csr_wdata <= 32'hF07F_FFFF;
|
||||
wp_setting <= 1'b0;
|
||||
end
|
||||
end else begin
|
||||
csr_read <= 1'b1;
|
||||
|
||||
case (state)
|
||||
STATE_START: begin
|
||||
if (csr_read && (csr_rdata[1:0] == STATUS_IDLE)) begin
|
||||
csr_read <= 1'b0;
|
||||
csr_write <= 1'b1;
|
||||
csr_address <= CSR_CONTROL;
|
||||
csr_wdata <= {4'hF, {5{wp_setting}}, erase_sector, 20'hFFFFF};
|
||||
state <= STATE_PENDING;
|
||||
end
|
||||
end
|
||||
|
||||
STATE_PENDING: begin
|
||||
if (csr_read && (csr_rdata[1:0] == STATUS_BUSY_ERASE)) begin
|
||||
state <= STATE_ERASING;
|
||||
end
|
||||
end
|
||||
|
||||
STATE_ERASING: begin
|
||||
if (csr_read && (csr_rdata[1:0] == STATUS_IDLE)) begin
|
||||
if (erase_sector == FLASH_SECTORS) begin
|
||||
erase_busy <= 1'b0;
|
||||
end else begin
|
||||
erase_sector <= erase_sector + 1'd1;
|
||||
state <= STATE_START;
|
||||
end
|
||||
end
|
||||
end
|
||||
endcase
|
||||
end
|
||||
end
|
||||
|
||||
logic data_read;
|
||||
logic data_write;
|
||||
logic data_busy;
|
||||
logic data_ack;
|
||||
logic [15:0] data_address;
|
||||
logic [31:0] data_wdata;
|
||||
logic [31:0] data_rdata;
|
||||
|
||||
logic pending;
|
||||
logic write_ack;
|
||||
|
||||
always_ff @(posedge clk) begin
|
||||
write_ack <= 1'b0;
|
||||
|
||||
if (reset) begin
|
||||
data_read <= 1'b0;
|
||||
data_write <= 1'b0;
|
||||
pending <= 1'b0;
|
||||
end else begin
|
||||
if (request && !pending && !erase_busy) begin
|
||||
pending <= 1'b1;
|
||||
if (write && !wp_setting) begin
|
||||
data_write <= 1'b1;
|
||||
end else begin
|
||||
data_read <= 1'b1;
|
||||
end
|
||||
end
|
||||
|
||||
if (data_read && !data_busy) begin
|
||||
data_read <= 1'b0;
|
||||
end
|
||||
|
||||
if (data_write && !data_busy) begin
|
||||
data_write <= 1'b0;
|
||||
pending <= 1'b0;
|
||||
write_ack <= 1'b1;
|
||||
end
|
||||
|
||||
if (data_ack) begin
|
||||
pending <= 1'b0;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
always_comb begin
|
||||
ack = data_ack || write_ack;
|
||||
data_address = address[17:2];
|
||||
end
|
||||
|
||||
intel_flash intel_flash_inst (
|
||||
.clock(clk),
|
||||
.reset_n(~reset),
|
||||
|
||||
.avmm_csr_read(csr_read),
|
||||
.avmm_csr_write(csr_write),
|
||||
.avmm_csr_addr(csr_address),
|
||||
.avmm_csr_writedata(csr_wdata),
|
||||
.avmm_csr_readdata(csr_rdata),
|
||||
|
||||
.avmm_data_read(data_read),
|
||||
.avmm_data_write(data_write),
|
||||
.avmm_data_waitrequest(data_busy),
|
||||
.avmm_data_readdatavalid(data_ack),
|
||||
.avmm_data_addr(data_address),
|
||||
.avmm_data_writedata(wdata),
|
||||
.avmm_data_readdata(rdata),
|
||||
.avmm_data_burstcount(2'd1)
|
||||
);
|
||||
|
||||
endmodule
|
42
fw/rtl/vendor/vendor_reconfigure.sv
vendored
Normal file
42
fw/rtl/vendor/vendor_reconfigure.sv
vendored
Normal file
@ -0,0 +1,42 @@
|
||||
module vendor_reconfigure (
|
||||
input clk,
|
||||
input reset,
|
||||
|
||||
input trigger_reconfiguration
|
||||
);
|
||||
|
||||
logic [1:0] ru_clk;
|
||||
logic ru_rconfig;
|
||||
logic ru_regout;
|
||||
|
||||
logic pending;
|
||||
|
||||
always_ff @(posedge clk) begin
|
||||
if (reset) begin
|
||||
ru_clk <= 2'd0;
|
||||
ru_rconfig <= 1'b0;
|
||||
pending <= 1'b0;
|
||||
end else begin
|
||||
ru_clk <= ru_clk + 1'd1;
|
||||
|
||||
if (trigger_reconfiguration) begin
|
||||
pending <= 1'b1;
|
||||
end
|
||||
|
||||
if (ru_clk == 2'd1) begin
|
||||
ru_rconfig <= pending;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
fiftyfivenm_rublock fiftyfivenm_rublock_inst (
|
||||
.clk(ru_clk[1]),
|
||||
.shiftnld(1'b0),
|
||||
.captnupdt(1'b0),
|
||||
.regin(1'b0),
|
||||
.rsttimer(1'b0),
|
||||
.rconfig(ru_rconfig),
|
||||
.regout(ru_regout)
|
||||
);
|
||||
|
||||
endmodule
|
@ -229,9 +229,6 @@ typedef struct {
|
||||
io32_t SR_CMD;
|
||||
io32_t DATA[2];
|
||||
io32_t VERSION;
|
||||
io32_t __padding[4092];
|
||||
io32_t CPU_RAM[3840];
|
||||
io32_t BUFFER[256];
|
||||
} sc64_regs_t;
|
||||
|
||||
#define SC64_BASE (0x1FFF0000UL)
|
||||
|
@ -83,7 +83,7 @@ void sc64_set_time (rtc_time_t *t) {
|
||||
}
|
||||
|
||||
static uint32_t sc64_wait_drive_ready (drive_id_t drive) {
|
||||
uint32_t args[2] = { (drive & 0xFF), 0 };
|
||||
uint32_t args[2] = { ((drive & 0x01) << 31), 0 };
|
||||
uint32_t result[2];
|
||||
do {
|
||||
sc64_perform_cmd(SC64_CMD_DRIVE_BUSY, args, result);
|
||||
@ -92,7 +92,7 @@ static uint32_t sc64_wait_drive_ready (drive_id_t drive) {
|
||||
}
|
||||
|
||||
bool sc64_storage_init (drive_id_t drive) {
|
||||
uint32_t args[2] = { (drive & 0xFF), 0 };
|
||||
uint32_t args[2] = { ((drive & 0x01) << 31), 0 };
|
||||
if (sc64_perform_cmd(SC64_CMD_DRIVE_INIT, args, NULL)) {
|
||||
return true;
|
||||
}
|
||||
@ -103,7 +103,7 @@ bool sc64_storage_init (drive_id_t drive) {
|
||||
}
|
||||
|
||||
static bool sc64_drive_start_rw (drive_id_t drive, bool write, uint32_t sector, uint32_t offset) {
|
||||
uint32_t args[2] = { (((offset & 0xFFFFFF) << 8) | (drive & 0xFF)), sector };
|
||||
uint32_t args[2] = { (((drive & 0x01) << 31) | (offset & 0x7FFFFFFF)), sector };
|
||||
if (sc64_perform_cmd(write ? SC64_CMD_DRIVE_WRITE : SC64_CMD_DRIVE_READ, args, NULL)) {
|
||||
return true;
|
||||
}
|
||||
@ -116,7 +116,7 @@ bool sc64_storage_read (drive_id_t drive, void *buffer, uint32_t sector, uint32_
|
||||
uint32_t current_offset = 0;
|
||||
uint32_t next_offset = SECTOR_SIZE;
|
||||
|
||||
if (sc64_drive_start_rw(drive, false, sector++, 0)) {
|
||||
if (sc64_drive_start_rw(drive, false, sector++, 0x03FF0000UL)) {
|
||||
return true;
|
||||
}
|
||||
while (count > 0) {
|
||||
@ -124,12 +124,12 @@ bool sc64_storage_read (drive_id_t drive, void *buffer, uint32_t sector, uint32_
|
||||
return true;
|
||||
}
|
||||
if (count > 1) {
|
||||
if (sc64_drive_start_rw(drive, false, sector++, next_offset)) {
|
||||
if (sc64_drive_start_rw(drive, false, sector++, 0x03FF0000UL + next_offset)) {
|
||||
return true;
|
||||
}
|
||||
next_offset = next_offset ? 0 : SECTOR_SIZE;
|
||||
}
|
||||
src = &SC64->BUFFER[current_offset / sizeof(io32_t)];
|
||||
src = (io32_t *) (0x13FF0000UL + current_offset);
|
||||
for (int i = 0; i < (SECTOR_SIZE / sizeof(uint32_t)); i++) {
|
||||
uint32_t data = pi_io_read(src + i);
|
||||
*dst++ = ((data >> 24) & 0xFF);
|
||||
@ -146,7 +146,7 @@ bool sc64_storage_read (drive_id_t drive, void *buffer, uint32_t sector, uint32_
|
||||
|
||||
bool sc64_storage_write (drive_id_t drive, const void *buffer, uint32_t sector, uint32_t count) {
|
||||
uint8_t *src = (uint8_t *) (buffer);
|
||||
io32_t *dst = SC64->BUFFER;
|
||||
io32_t *dst = (io32_t *) (0x13FF0000UL);
|
||||
|
||||
while (count > 0) {
|
||||
for (int i = 0; i < (SECTOR_SIZE / sizeof(uint32_t)); i++) {
|
||||
@ -157,7 +157,7 @@ bool sc64_storage_write (drive_id_t drive, const void *buffer, uint32_t sector,
|
||||
data |= ((*src++) << 0);
|
||||
pi_io_write((dst + i), data);
|
||||
}
|
||||
if (sc64_drive_start_rw(drive, true, sector, 0)) {
|
||||
if (sc64_drive_start_rw(drive, true, sector, 0x03FF0000UL)) {
|
||||
return true;
|
||||
}
|
||||
if (sc64_wait_drive_ready(drive)) {
|
||||
|
110
sw/pc/sc64.py
110
sw/pc/sc64.py
@ -1,7 +1,8 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
from datetime import datetime
|
||||
from ft232 import Ft232, Ft232Exception
|
||||
from serial import Serial, SerialException
|
||||
from serial.tools import list_ports
|
||||
from io import TextIOWrapper
|
||||
from typing import Union
|
||||
import argparse
|
||||
@ -9,7 +10,6 @@ import filecmp
|
||||
import helpers
|
||||
import os
|
||||
import progressbar
|
||||
import re
|
||||
import struct
|
||||
import sys
|
||||
import time
|
||||
@ -50,8 +50,6 @@ class SC64:
|
||||
__DEBUG_ID_TEXT = 0x01
|
||||
__EVENT_ID_FSD_READ = 0xF0
|
||||
__EVENT_ID_FSD_WRITE = 0xF1
|
||||
__EVENT_ID_FSD_LOAD = 0xF2
|
||||
__EVENT_ID_FSD_STORE = 0xF3
|
||||
__EVENT_ID_DD_BLOCK = 0xF4
|
||||
__EVENT_ID_IS_VIEWER = 0xF5
|
||||
|
||||
@ -76,7 +74,6 @@ class SC64:
|
||||
|
||||
def __del__(self) -> None:
|
||||
if (self.__usb):
|
||||
self.__reset_n64("release")
|
||||
self.__usb.close()
|
||||
if (self.__fsd_file):
|
||||
self.__fsd_file.close()
|
||||
@ -101,14 +98,15 @@ class SC64:
|
||||
return (value + (align - 1)) & ~(align - 1)
|
||||
|
||||
|
||||
def __escape(self, data: bytes) -> bytes:
|
||||
return re.sub(b"\x1B", b"\x1B\x1B", data)
|
||||
|
||||
|
||||
def reset_link(self) -> None:
|
||||
self.__usb.write(b"\x1BR")
|
||||
time.sleep(0.1)
|
||||
self.__usb.flushInput()
|
||||
if (self.__usb):
|
||||
self.__usb.flush()
|
||||
self.__usb.setDTR(1)
|
||||
while (self.__usb.getDSR() == 0):
|
||||
pass
|
||||
self.__usb.setDTR(0)
|
||||
while (self.__usb.getDSR() == 1):
|
||||
pass
|
||||
|
||||
|
||||
def __read(self, bytes: int) -> bytes:
|
||||
@ -116,7 +114,7 @@ class SC64:
|
||||
|
||||
|
||||
def __write(self, data: bytes) -> None:
|
||||
self.__usb.write(self.__escape(data))
|
||||
self.__usb.write(data)
|
||||
|
||||
|
||||
def __read_long(self, length: int) -> bytes:
|
||||
@ -151,29 +149,28 @@ class SC64:
|
||||
self.__write_int(arg2)
|
||||
|
||||
|
||||
def __reset_n64(self, type: str) -> None:
|
||||
if (self.__usb):
|
||||
if (type == "hold"):
|
||||
self.__usb.cbus_setup(mask=1, init=0)
|
||||
time.sleep(0.6)
|
||||
elif (type == "release"):
|
||||
self.__usb.cbus_setup(mask=0)
|
||||
|
||||
|
||||
def __find_sc64(self) -> None:
|
||||
if (self.__usb != None and not self.__usb.closed):
|
||||
ports = list_ports.comports()
|
||||
device_found = False
|
||||
|
||||
if (self.__usb != None and self.__usb.isOpen()):
|
||||
self.__usb.close()
|
||||
|
||||
try:
|
||||
self.__usb = Ft232(description="SummerCart64")
|
||||
self.__reset_n64("hold")
|
||||
self.__usb.flushOutput()
|
||||
self.reset_link()
|
||||
self.__probe_device()
|
||||
except Ft232Exception as e:
|
||||
if (self.__usb):
|
||||
self.__usb.close()
|
||||
raise SC64Exception(f"No SummerCart64 device was found: {e}")
|
||||
for p in ports:
|
||||
if (p.vid == 0x0403 and p.pid == 0x6014 and p.serial_number.startswith("SC")):
|
||||
try:
|
||||
self.__usb = Serial(p.device, timeout=0.5, write_timeout=0.5)
|
||||
self.reset_link()
|
||||
self.__probe_device()
|
||||
except (SerialException, SC64Exception):
|
||||
if (self.__usb):
|
||||
self.__usb.close()
|
||||
continue
|
||||
device_found = True
|
||||
break
|
||||
|
||||
if (not device_found):
|
||||
raise SC64Exception("No SummerCart64 device was found")
|
||||
|
||||
|
||||
def __probe_device(self) -> None:
|
||||
@ -197,25 +194,22 @@ class SC64:
|
||||
self.__read_cmd_status("C")
|
||||
|
||||
|
||||
def __read_file_from_sdram(self, file: str, offset: int, length: int, align: int = 2) -> None:
|
||||
def __read_file_from_sdram(self, file: str, offset: int, length: int) -> None:
|
||||
with open(file, "wb") as f:
|
||||
transfer_size = self.__align(length, align)
|
||||
self.__set_progress_init(transfer_size, os.path.basename(f.name))
|
||||
self.__write_cmd("R", offset, transfer_size)
|
||||
self.__set_progress_init(length, os.path.basename(f.name))
|
||||
self.__write_cmd("R", offset, length)
|
||||
while (f.tell() < length):
|
||||
chunk_size = min(self.__CHUNK_SIZE, length - f.tell())
|
||||
f.write(self.__read(chunk_size))
|
||||
self.__set_progress_value(f.tell())
|
||||
if (transfer_size != length):
|
||||
self.__read(transfer_size - length)
|
||||
self.__read_cmd_status("R")
|
||||
self.__set_progress_finish()
|
||||
|
||||
|
||||
def __write_file_to_sdram(self, file: str, offset: int, align: int = 2, min_length: int = 0) -> None:
|
||||
def __write_file_to_sdram(self, file: str, offset: int, min_length: int = 0) -> None:
|
||||
with open(file, "rb") as f:
|
||||
length = os.fstat(f.fileno()).st_size
|
||||
transfer_size = self.__align(max(length, min_length), align)
|
||||
transfer_size = max(length, min_length)
|
||||
self.__set_progress_init(transfer_size, os.path.basename(f.name))
|
||||
self.__write_cmd("W", offset, transfer_size)
|
||||
while (f.tell() < length):
|
||||
@ -243,7 +237,7 @@ class SC64:
|
||||
def __reconfigure(self) -> None:
|
||||
magic = self.__query_config(self.__CFG_ID_RECONFIGURE)
|
||||
self.__change_config(self.__CFG_ID_RECONFIGURE, magic, ignore_response=True)
|
||||
time.sleep(0.2)
|
||||
time.sleep(0.5)
|
||||
|
||||
|
||||
def backup_firmware(self, file: str) -> None:
|
||||
@ -259,7 +253,6 @@ class SC64:
|
||||
self.__change_config(self.__CFG_ID_FLASH_PROGRAM, self.__UPDATE_OFFSET)
|
||||
self.__usb.timeout = saved_timeout
|
||||
self.__reconfigure()
|
||||
self.__find_sc64()
|
||||
|
||||
|
||||
def set_rtc(self, t: datetime) -> None:
|
||||
@ -544,7 +537,7 @@ class SC64:
|
||||
data += struct.pack(">I", offset)
|
||||
self.__disk_lba_table[lba] = offset
|
||||
self.__write_cmd("W", thb_table_offset, len(data))
|
||||
self.__write(data)
|
||||
self.__write(bytes(data))
|
||||
self.__read_cmd_status("W")
|
||||
id_mapping = {
|
||||
"retail": self.__DD_DRIVE_ID_RETAIL,
|
||||
@ -561,26 +554,28 @@ class SC64:
|
||||
def __debug_process_fsd_read(self, data: bytes) -> None:
|
||||
sector = int.from_bytes(data[0:4], byteorder="little")
|
||||
offset = int.from_bytes(data[4:8], byteorder="little")
|
||||
count = int.from_bytes(data[8:12], byteorder="little")
|
||||
|
||||
if (self.__fsd_file):
|
||||
self.__fsd_file.seek(sector * 512)
|
||||
self.__write_cmd("T", offset, 512)
|
||||
self.__write(self.__fsd_file.read(512))
|
||||
self.__write_cmd("S", offset, count * 512)
|
||||
self.__write(self.__fsd_file.read(count * 512))
|
||||
else:
|
||||
self.__write_cmd("T", offset, 0)
|
||||
self.__write_cmd("S", offset, 0)
|
||||
|
||||
|
||||
def __debug_process_fsd_write(self, data: bytes) -> None:
|
||||
sector = int.from_bytes(data[0:4], byteorder="little")
|
||||
offset = int.from_bytes(data[4:8], byteorder="little")
|
||||
count = int.from_bytes(data[8:12], byteorder="little")
|
||||
|
||||
if (self.__fsd_file):
|
||||
with helpers.lock_volume(self.__fsd_file):
|
||||
self.__fsd_file.seek(sector * 512)
|
||||
self.__write_cmd("F", offset, 512)
|
||||
self.__fsd_file.write(self.__read(512))
|
||||
self.__write_cmd("L", offset, count * 512)
|
||||
self.__fsd_file.write(self.__read(count * 512))
|
||||
else:
|
||||
self.__write_cmd("F", offset, 0)
|
||||
self.__write_cmd("L", offset, 0)
|
||||
|
||||
|
||||
def __debug_process_dd_block(self, data: bytes) -> None:
|
||||
@ -588,7 +583,7 @@ class SC64:
|
||||
sdram_offset = int.from_bytes(data[4:8], byteorder="little")
|
||||
disk_file_offset = int.from_bytes(data[8:12], byteorder="big")
|
||||
block_length = int.from_bytes(data[12:16], byteorder="little")
|
||||
|
||||
print(f"DD BLOCK {disk_file_offset:08X} {block_length}")
|
||||
if (self.__disk_file):
|
||||
self.__disk_file.seek(disk_file_offset)
|
||||
if (transfer_mode):
|
||||
@ -605,10 +600,8 @@ class SC64:
|
||||
def __debug_process_is_viewer(self, data: bytes) -> None:
|
||||
length = int.from_bytes(data[0:4], byteorder="little")
|
||||
address = int.from_bytes(data[4:8], byteorder="little")
|
||||
offset = (address & 0x01)
|
||||
transfer_length = self.__align(length + offset, 2)
|
||||
self.__write_cmd("L", (address & 0xFFFFFFFE), transfer_length)
|
||||
text = self.__read(transfer_length)[offset:][:length]
|
||||
self.__write_cmd("L", address, length)
|
||||
text = self.__read(length)
|
||||
print(text.decode("EUC-JP", errors="backslashreplace"), end="")
|
||||
|
||||
|
||||
@ -625,13 +618,9 @@ class SC64:
|
||||
|
||||
print("\r\n\033[34m --- Debug server started --- \033[0m\r\n")
|
||||
|
||||
self.__usb.setTimeout(0.1)
|
||||
|
||||
start_indicator = bytearray()
|
||||
dropped_bytes = 0
|
||||
|
||||
self.__reset_n64("release")
|
||||
|
||||
while (True):
|
||||
while (start_indicator != b"DMA@"):
|
||||
start_indicator.append(self.__read_long(1)[0])
|
||||
@ -752,6 +741,8 @@ if __name__ == "__main__":
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
sc64 = None
|
||||
|
||||
try:
|
||||
sc64 = SC64()
|
||||
|
||||
@ -855,7 +846,6 @@ if __name__ == "__main__":
|
||||
pass
|
||||
finally:
|
||||
if (sc64):
|
||||
sc64.reset_link()
|
||||
if (disk_file):
|
||||
print(f"Setting 64DD disk state to [Ejected]")
|
||||
sc64.set_dd_disk_state("ejected")
|
||||
|
@ -6,7 +6,7 @@ OBJDUMP = $(TOOLCHAIN)objdump
|
||||
SIZE = $(TOOLCHAIN)size
|
||||
|
||||
FLAGS = -mabi=ilp32 -march=rv32i $(USER_FLAGS)
|
||||
CFLAGS = -Os -Wall -ffunction-sections -fdata-sections -ffreestanding -MMD -MP
|
||||
CFLAGS = -Os -Wall -ffunction-sections -fdata-sections -ffreestanding -fno-delete-null-pointer-checks -MMD -MP
|
||||
LDFLAGS = -nostartfiles -Wl,--gc-sections
|
||||
|
||||
SRC_DIR = src
|
||||
@ -17,7 +17,6 @@ SRC_FILES = \
|
||||
process.c \
|
||||
usb.c \
|
||||
cfg.c \
|
||||
dma.c \
|
||||
joybus.c \
|
||||
rtc.c \
|
||||
i2c.c \
|
||||
@ -46,7 +45,7 @@ $(BUILD_DIR)/governor.elf: $(OBJS) SC64.ld
|
||||
@$(OBJDUMP) -D $@ > $(BUILD_DIR)/governor.lst
|
||||
|
||||
$(BUILD_DIR)/governor.bin: $(BUILD_DIR)/governor.elf
|
||||
@$(OBJCOPY) -O binary --gap-fill 0xFF --pad-to 0x10016800 $< $@
|
||||
@$(OBJCOPY) -O binary --gap-fill 0xFF --pad-to 0x00016800 $< $@
|
||||
|
||||
$(BUILD_DIR)/governor.hex: $(BUILD_DIR)/governor.bin
|
||||
@$(OBJCOPY) -I binary -O ihex $< $@
|
||||
|
@ -1,7 +1,6 @@
|
||||
MEMORY {
|
||||
ram (rwx) : org = 0x00000000, len = 15k
|
||||
buffer (rw) : org = 0x00003C00, len = 1k
|
||||
rom (rx) : org = 0x10010000, len = 26k
|
||||
rom (rx) : org = 0x00010000, len = 26k
|
||||
ram (rwx) : org = 0x10000000, len = 32k
|
||||
}
|
||||
|
||||
ENTRY(reset_handler)
|
||||
@ -45,10 +44,6 @@ SECTIONS {
|
||||
_ebss = .;
|
||||
} > ram
|
||||
|
||||
.buffer : {
|
||||
*(.buffer)
|
||||
} > buffer
|
||||
|
||||
__global_pointer$ = MIN(_ssdata + 0x800, MAX(_sdata + 0x800, _ebss - 0x800));
|
||||
__stack_pointer$ = ORIGIN(ram) + LENGTH(ram);
|
||||
}
|
||||
|
@ -311,9 +311,7 @@ void process_cfg (void) {
|
||||
break;
|
||||
|
||||
case 0xF0:
|
||||
if (args[0] == 0) {
|
||||
change_scr_bits(CFG_SCR_CMD_ERROR, true);
|
||||
} else if (args[0] == 1) {
|
||||
if (args[0] & (1 << 31)) {
|
||||
p.usb_drive_busy = false;
|
||||
} else {
|
||||
change_scr_bits(CFG_SCR_CMD_ERROR, true);
|
||||
@ -321,10 +319,7 @@ void process_cfg (void) {
|
||||
break;
|
||||
|
||||
case 0xF1:
|
||||
if (args[0] == 0) {
|
||||
args[0] = 0;
|
||||
change_scr_bits(CFG_SCR_CMD_ERROR, true);
|
||||
} else if (args[0] == 1) {
|
||||
if (args[0] & (1 << 31)) {
|
||||
args[0] = p.usb_drive_busy;
|
||||
} else {
|
||||
args[0] = 0;
|
||||
@ -334,18 +329,20 @@ void process_cfg (void) {
|
||||
break;
|
||||
|
||||
case 0xF2:
|
||||
if ((args[0] & 0xFF) == 0) {
|
||||
change_scr_bits(CFG_SCR_CMD_ERROR, true);
|
||||
} else if ((args[0] & 0xFF) == 1 && (!p.usb_drive_busy)) {
|
||||
usb_event_t event;
|
||||
event.id = EVENT_ID_FSD_READ;
|
||||
event.trigger = CALLBACK_BUFFER_WRITE;
|
||||
event.callback = set_usb_drive_not_busy;
|
||||
uint32_t data[2] = { args[1], (args[0] >> 8) };
|
||||
if (usb_put_event(&event, data, sizeof(data))) {
|
||||
p.usb_drive_busy = true;
|
||||
if (args[0] & (1 << 31)) {
|
||||
if (!p.usb_drive_busy) {
|
||||
usb_event_t event;
|
||||
event.id = EVENT_ID_FSD_READ;
|
||||
event.trigger = CALLBACK_SDRAM_WRITE;
|
||||
event.callback = set_usb_drive_not_busy;
|
||||
uint32_t data[3] = { args[1], (args[0] & 0x7FFFFFFF), 1 };
|
||||
if (usb_put_event(&event, data, sizeof(data))) {
|
||||
p.usb_drive_busy = true;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
return;
|
||||
change_scr_bits(CFG_SCR_CMD_ERROR, true);
|
||||
}
|
||||
} else {
|
||||
change_scr_bits(CFG_SCR_CMD_ERROR, true);
|
||||
@ -353,18 +350,20 @@ void process_cfg (void) {
|
||||
break;
|
||||
|
||||
case 0xF3:
|
||||
if ((args[0] & 0xFF) == 0) {
|
||||
change_scr_bits(CFG_SCR_CMD_ERROR, true);
|
||||
} else if ((args[0] & 0xFF) == 1 && (!p.usb_drive_busy)) {
|
||||
usb_event_t event;
|
||||
event.id = EVENT_ID_FSD_WRITE;
|
||||
event.trigger = CALLBACK_BUFFER_READ;
|
||||
event.callback = set_usb_drive_not_busy;
|
||||
uint32_t data[2] = { args[1], (args[0] >> 8) };
|
||||
if (usb_put_event(&event, data, sizeof(data))) {
|
||||
p.usb_drive_busy = true;
|
||||
if (args[0] & (1 << 31)) {
|
||||
if (!p.usb_drive_busy) {
|
||||
usb_event_t event;
|
||||
event.id = EVENT_ID_FSD_WRITE;
|
||||
event.trigger = CALLBACK_SDRAM_READ;
|
||||
event.callback = set_usb_drive_not_busy;
|
||||
uint32_t data[3] = { args[1], (args[0] & 0x7FFFFFFF), 1 };
|
||||
if (usb_put_event(&event, data, sizeof(data))) {
|
||||
p.usb_drive_busy = true;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
return;
|
||||
change_scr_bits(CFG_SCR_CMD_ERROR, true);
|
||||
}
|
||||
} else {
|
||||
change_scr_bits(CFG_SCR_CMD_ERROR, true);
|
||||
|
@ -1,21 +0,0 @@
|
||||
#include "dma.h"
|
||||
|
||||
|
||||
bool dma_busy (void) {
|
||||
return DMA->SCR & DMA_SCR_BUSY;
|
||||
}
|
||||
|
||||
void dma_start (uint32_t memory_address, size_t length, enum dma_id id, enum dma_dir dir) {
|
||||
DMA->MADDR = memory_address;
|
||||
DMA->ID_LEN = ((id & 0x03) << 30) | (length & 0x3FFFFFFF);
|
||||
DMA->SCR = ((dir == DMA_DIR_TO_SDRAM) ? DMA_SCR_DIR : 0) | DMA_SCR_START;
|
||||
}
|
||||
|
||||
void dma_stop (void) {
|
||||
DMA->SCR = DMA_SCR_STOP;
|
||||
}
|
||||
|
||||
|
||||
void dma_init (void) {
|
||||
dma_stop();
|
||||
}
|
@ -1,25 +0,0 @@
|
||||
#ifndef DMA_H__
|
||||
#define DMA_H__
|
||||
|
||||
|
||||
#include "sys.h"
|
||||
|
||||
|
||||
enum dma_dir {
|
||||
DMA_DIR_TO_SDRAM,
|
||||
DMA_DIR_FROM_SDRAM,
|
||||
};
|
||||
|
||||
enum dma_id {
|
||||
DMA_ID_USB = 0,
|
||||
DMA_ID_SD = 1,
|
||||
};
|
||||
|
||||
|
||||
bool dma_busy (void);
|
||||
void dma_start (uint32_t memory_address, size_t length, enum dma_id id, enum dma_dir dir);
|
||||
void dma_stop (void);
|
||||
void dma_init (void);
|
||||
|
||||
|
||||
#endif
|
@ -1,6 +1,9 @@
|
||||
#include "flash.h"
|
||||
|
||||
|
||||
static io32_t dummy;
|
||||
|
||||
|
||||
uint32_t flash_size (void) {
|
||||
return FLASH_SIZE;
|
||||
}
|
||||
@ -9,54 +12,30 @@ void flash_read (uint32_t sdram_offset) {
|
||||
io32_t *flash = (io32_t *) (FLASH_BASE);
|
||||
io32_t *sdram = (io32_t *) (SDRAM_BASE + sdram_offset);
|
||||
|
||||
for (size_t i = 0; i < FLASH_SIZE; i += 4) {
|
||||
for (size_t i = 0; i < FLASH_SIZE; i += sizeof(io32_t)) {
|
||||
*sdram++ = *flash++;
|
||||
}
|
||||
}
|
||||
|
||||
void flash_program (uint32_t sdram_offset) {
|
||||
uint32_t cr;
|
||||
|
||||
io32_t *flash = (io32_t *) (FLASH_BASE);
|
||||
io32_t *sdram = (io32_t *) (SDRAM_BASE + sdram_offset);
|
||||
|
||||
cr = FLASH_CONFIG->CR;
|
||||
for (size_t sector = 0; sector < FLASH_NUM_SECTORS; sector++) {
|
||||
cr &= ~(1 << (FLASH_CR_WRITE_PROTECT_BIT + sector));
|
||||
}
|
||||
FLASH_CONFIG->CR = cr;
|
||||
CFG->SCR |= CFG_SCR_FLASH_WP_DISABLE;
|
||||
|
||||
while ((FLASH_CONFIG->SR & FLASH_SR_STATUS_MASK) != FLASH_SR_STATUS_IDLE);
|
||||
CFG->SCR |= CFG_SCR_FLASH_ERASE_START;
|
||||
|
||||
for (size_t sector = 0; sector < FLASH_NUM_SECTORS; sector++) {
|
||||
cr = FLASH_CONFIG->CR;
|
||||
cr &= ~(FLASH_CR_SECTOR_ERASE_MASK);
|
||||
cr |= ((sector + 1) << FLASH_CR_SECTOR_ERASE_BIT);
|
||||
FLASH_CONFIG->CR = cr;
|
||||
while (CFG->SCR & CFG_SCR_FLASH_ERASE_BUSY);
|
||||
|
||||
while ((FLASH_CONFIG->SR & FLASH_SR_STATUS_MASK) == FLASH_SR_STATUS_BUSY_ERASE);
|
||||
|
||||
if (!(FLASH_CONFIG->SR & FLASH_SR_ERASE_SUCCESSFUL)) {
|
||||
break;
|
||||
}
|
||||
for (int i = 0; i < FLASH_SIZE; i += sizeof(io32_t)) {
|
||||
*flash++ = *sdram++;
|
||||
}
|
||||
|
||||
if (FLASH_CONFIG->SR & FLASH_SR_ERASE_SUCCESSFUL) {
|
||||
for (size_t word = 0; word < FLASH_SIZE; word += 4) {
|
||||
*flash++ = *sdram++;
|
||||
CFG->SCR |= CFG_SCR_FLASH_WP_ENABLE;
|
||||
|
||||
if (!(FLASH_CONFIG->SR & FLASH_SR_WRITE_SUCCESSFUL)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
flash = (io32_t *) (FLASH_BASE);
|
||||
|
||||
cr = FLASH_CONFIG->CR;
|
||||
cr |= FLASH_CR_SECTOR_ERASE_MASK;
|
||||
for (size_t sector = 0; sector < FLASH_NUM_SECTORS; sector++) {
|
||||
cr |= (1 << (FLASH_CR_WRITE_PROTECT_BIT + sector));
|
||||
}
|
||||
FLASH_CONFIG->CR = cr;
|
||||
dummy = *flash;
|
||||
|
||||
return;
|
||||
}
|
||||
|
@ -5,7 +5,7 @@
|
||||
#include "sys.h"
|
||||
|
||||
|
||||
uint32_t flash_size(void);
|
||||
uint32_t flash_size (void);
|
||||
void flash_read (uint32_t sdram_offset);
|
||||
void flash_program (uint32_t sdram_offset);
|
||||
|
||||
|
@ -1,7 +1,6 @@
|
||||
#include "process.h"
|
||||
#include "usb.h"
|
||||
#include "cfg.h"
|
||||
#include "dma.h"
|
||||
#include "joybus.h"
|
||||
#include "rtc.h"
|
||||
#include "i2c.h"
|
||||
@ -29,7 +28,6 @@ __attribute__((naked)) void process_loop (void) {
|
||||
|
||||
usb_init();
|
||||
cfg_init();
|
||||
dma_init();
|
||||
joybus_init();
|
||||
rtc_init();
|
||||
i2c_init();
|
||||
|
@ -21,54 +21,48 @@ typedef volatile uint16_t io16_t;
|
||||
typedef volatile uint32_t io32_t;
|
||||
|
||||
|
||||
#define RAM_BASE (0x00000000UL)
|
||||
#define RAMBUFFER_SIZE (1024)
|
||||
#define RAM_SIZE ((16 * 1024) - RAMBUFFER_SIZE)
|
||||
#define RAMBUFFER_BASE (RAM_BASE + RAM_SIZE)
|
||||
#define RAM (*((io32_t *) RAM_BASE))
|
||||
#define RAMBUFFER (*((io8_t *) RAMBUFFER_BASE))
|
||||
|
||||
|
||||
#define FLASH_BASE (0x10000000UL)
|
||||
#define FLASH_BASE (0x00000000UL)
|
||||
#define FLASH_SIZE (0x39800)
|
||||
#define FLASH (*((io32_t *) FLASH_BASE))
|
||||
|
||||
#define FLASH_SIZE (0x39800)
|
||||
#define FLASH_NUM_SECTORS (4)
|
||||
|
||||
#define RAM_BASE (0x10000000UL)
|
||||
#define RAM_SIZE (16 * 1024)
|
||||
#define RAM (*((io32_t *) RAM_BASE))
|
||||
|
||||
|
||||
typedef volatile struct flash_config_regs {
|
||||
io32_t SR;
|
||||
io32_t CR;
|
||||
} flash_config_regs_t;
|
||||
typedef volatile struct cfg_regs {
|
||||
io32_t SCR;
|
||||
io32_t DDIPL_OFFSET;
|
||||
io32_t SAVE_OFFSET;
|
||||
io8_t CMD;
|
||||
io8_t __padding[3];
|
||||
io32_t DATA[2];
|
||||
io32_t VERSION;
|
||||
io32_t RECONFIGURE;
|
||||
io32_t ISV_OFFSET;
|
||||
io16_t ISV_RD_PTR;
|
||||
io16_t ISV_CURRENT_RD_PTR;
|
||||
} cfg_regs_t;
|
||||
|
||||
#define FLASH_CONFIG_BASE (0x18000000UL)
|
||||
#define FLASH_CONFIG ((flash_config_regs_t *) FLASH_CONFIG_BASE)
|
||||
#define CFG_BASE (0x20000000UL)
|
||||
#define CFG ((cfg_regs_t *) CFG_BASE)
|
||||
|
||||
#define FLASH_SR_STATUS_MASK (3 << 0)
|
||||
#define FLASH_SR_STATUS_IDLE (0)
|
||||
#define FLASH_SR_STATUS_BUSY_ERASE (1)
|
||||
#define FLASH_SR_STATUS_BUSY_WRITE (2)
|
||||
#define FLASH_SR_STATUS_BUSY_READ (3)
|
||||
#define FLASH_SR_READ_SUCCESSFUL (1 << 2)
|
||||
#define FLASH_SR_WRITE_SUCCESSFUL (1 << 3)
|
||||
#define FLASH_SR_ERASE_SUCCESSFUL (1 << 4)
|
||||
#define FLASH_SR_WRITE_PROTECT_BIT (5)
|
||||
|
||||
#define FLASH_CR_PAGE_ERASE_BIT (0)
|
||||
#define FLASH_CR_SECTOR_ERASE_BIT (20)
|
||||
#define FLASH_CR_SECTOR_ERASE_MASK (7 << FLASH_CR_SECTOR_ERASE_BIT)
|
||||
#define FLASH_CR_WRITE_PROTECT_BIT (23)
|
||||
|
||||
|
||||
typedef volatile struct gpio_regs {
|
||||
io8_t ODR;
|
||||
io8_t IDR;
|
||||
io8_t OER;
|
||||
io8_t __padding;
|
||||
} gpio_regs_t;
|
||||
|
||||
#define GPIO_BASE (0x20000000UL)
|
||||
#define GPIO ((gpio_regs_t *) GPIO_BASE)
|
||||
#define CFG_SCR_SDRAM_SWITCH (1 << 0)
|
||||
#define CFG_SCR_SDRAM_WRITABLE (1 << 1)
|
||||
#define CFG_SCR_DD_EN (1 << 2)
|
||||
#define CFG_SCR_SRAM_EN (1 << 3)
|
||||
#define CFG_SCR_SRAM_BANKED (1 << 4)
|
||||
#define CFG_SCR_FLASHRAM_EN (1 << 5)
|
||||
#define CFG_SCR_SKIP_BOOTLOADER (1 << 6)
|
||||
#define CFG_SCR_ISV_EN (1 << 7)
|
||||
#define CFG_SCR_FLASH_ERASE_START (1 << 24)
|
||||
#define CFG_SCR_FLASH_ERASE_BUSY (1 << 25)
|
||||
#define CFG_SCR_FLASH_WP_ENABLE (1 << 26)
|
||||
#define CFG_SCR_FLASH_WP_DISABLE (1 << 27)
|
||||
#define CFG_SCR_CMD_ERROR (1 << 28)
|
||||
#define CFG_SCR_CPU_BUSY (1 << 30)
|
||||
#define CFG_SCR_CPU_READY (1 << 31)
|
||||
|
||||
|
||||
typedef volatile struct i2c_regs {
|
||||
@ -90,8 +84,8 @@ typedef volatile struct usb_regs {
|
||||
io32_t SCR;
|
||||
io8_t DR;
|
||||
io8_t __padding_1[3];
|
||||
io8_t ESCAPE;
|
||||
io8_t __padding_2[3];
|
||||
io32_t ADDR;
|
||||
io32_t LEN;
|
||||
} usb_regs_t;
|
||||
|
||||
#define USB_BASE (0x40000000UL)
|
||||
@ -101,11 +95,14 @@ typedef volatile struct usb_regs {
|
||||
#define USB_SCR_TXE (1 << 1)
|
||||
#define USB_SCR_FLUSH_RX (1 << 2)
|
||||
#define USB_SCR_FLUSH_TX (1 << 3)
|
||||
#define USB_SCR_ENABLED (1 << 4)
|
||||
#define USB_SCR_PWREN (1 << 5)
|
||||
#define USB_SCR_ESCAPE_PENDING (1 << 6)
|
||||
#define USB_SCR_ESCAPE_ACK (1 << 7)
|
||||
#define USB_SCR_FORCE_TX (1 << 8)
|
||||
#define USB_SCR_ENABLE (1 << 4)
|
||||
#define USB_SCR_FORCE_TX (1 << 5)
|
||||
#define USB_SCR_RESET_PENDING (1 << 6)
|
||||
#define USB_SCR_RESET_ACK (1 << 7)
|
||||
#define USB_SCR_DMA_BUSY (1 << 8)
|
||||
#define USB_SCR_DMA_START (1 << 9)
|
||||
#define USB_SCR_DMA_STOP (1 << 10)
|
||||
#define USB_SCR_DMA_DIR (1 << 11)
|
||||
|
||||
|
||||
typedef volatile struct uart_regs {
|
||||
@ -121,91 +118,6 @@ typedef volatile struct uart_regs {
|
||||
#define UART_SCR_TXE (1 << 1)
|
||||
|
||||
|
||||
typedef volatile struct dma_regs {
|
||||
io32_t SCR;
|
||||
io32_t MADDR;
|
||||
io32_t ID_LEN;
|
||||
} dma_regs_t;
|
||||
|
||||
#define DMA_BASE (0x60000000UL)
|
||||
#define DMA ((dma_regs_t *) DMA_BASE)
|
||||
|
||||
#define DMA_SCR_START (1 << 0)
|
||||
#define DMA_SCR_STOP (1 << 1)
|
||||
#define DMA_SCR_DIR (1 << 2)
|
||||
#define DMA_SCR_BUSY (1 << 3)
|
||||
|
||||
|
||||
typedef volatile struct cfg_regs {
|
||||
io32_t SCR;
|
||||
io32_t DDIPL_OFFSET;
|
||||
io32_t SAVE_OFFSET;
|
||||
io8_t CMD;
|
||||
io8_t __padding[3];
|
||||
io32_t DATA[2];
|
||||
io32_t VERSION;
|
||||
io32_t RECONFIGURE;
|
||||
io32_t ISV_OFFSET;
|
||||
io16_t ISV_RD_PTR;
|
||||
io16_t ISV_CURRENT_RD_PTR;
|
||||
} cfg_regs_t;
|
||||
|
||||
#define CFG_BASE (0x70000000UL)
|
||||
#define CFG ((cfg_regs_t *) CFG_BASE)
|
||||
|
||||
#define CFG_SCR_SDRAM_SWITCH (1 << 0)
|
||||
#define CFG_SCR_SDRAM_WRITABLE (1 << 1)
|
||||
#define CFG_SCR_DD_EN (1 << 2)
|
||||
#define CFG_SCR_SRAM_EN (1 << 3)
|
||||
#define CFG_SCR_SRAM_BANKED (1 << 4)
|
||||
#define CFG_SCR_FLASHRAM_EN (1 << 5)
|
||||
#define CFG_SCR_SKIP_BOOTLOADER (1 << 6)
|
||||
#define CFG_SCR_ISV_EN (1 << 7)
|
||||
#define CFG_SCR_CMD_ERROR (1 << 28)
|
||||
#define CFG_SCR_CPU_BUSY (1 << 30)
|
||||
#define CFG_SCR_CPU_READY (1 << 31)
|
||||
|
||||
|
||||
#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_PAGE_BIT (8)
|
||||
|
||||
|
||||
typedef volatile struct joybus_regs {
|
||||
io32_t SCR;
|
||||
io32_t DATA[3];
|
||||
} joybus_regs_t;
|
||||
|
||||
#define JOYBUS_BASE (0xA0000000UL)
|
||||
#define JOYBUS ((joybus_regs_t *) JOYBUS_BASE)
|
||||
|
||||
#define JOYBUS_SCR_RX_READY (1 << 0)
|
||||
#define JOYBUS_SCR_RX_STOP_BIT (1 << 1)
|
||||
#define JOYBUS_SCR_TX_START (1 << 2)
|
||||
#define JOYBUS_SCR_TX_BUSY (1 << 3)
|
||||
#define JOYBUS_SCR_RX_RESET (1 << 6)
|
||||
#define JOYBUS_SCR_TX_RESET (1 << 7)
|
||||
#define JOYBUS_SCR_RX_LENGTH_BIT (8)
|
||||
#define JOYBUS_SCR_RX_LENGTH_MASK (0x7F << JOYBUS_SCR_RX_LENGTH_BIT)
|
||||
#define JOYBUS_SCR_TX_LENGTH_BIT (16)
|
||||
|
||||
|
||||
typedef volatile struct dd_regs {
|
||||
io32_t SCR;
|
||||
io16_t DATA;
|
||||
@ -224,7 +136,7 @@ typedef volatile struct dd_regs {
|
||||
io32_t SECTOR_BUFFER[64];
|
||||
} dd_regs_t;
|
||||
|
||||
#define DD_BASE (0xB0000000UL)
|
||||
#define DD_BASE (0x60000000UL)
|
||||
#define DD ((dd_regs_t *) DD_BASE)
|
||||
|
||||
#define DD_SCR_HARD_RESET (1 << 0)
|
||||
@ -255,6 +167,46 @@ typedef volatile struct dd_regs {
|
||||
#define DD_HEAD_TRACK_INDEX_LOCK (1 << 13)
|
||||
|
||||
|
||||
#define SDRAM_BASE (0x70000000UL)
|
||||
#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 (0x80000000UL)
|
||||
#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_PAGE_BIT (8)
|
||||
|
||||
|
||||
typedef volatile struct joybus_regs {
|
||||
io32_t SCR;
|
||||
io32_t DATA[3];
|
||||
} joybus_regs_t;
|
||||
|
||||
#define JOYBUS_BASE (0x90000000UL)
|
||||
#define JOYBUS ((joybus_regs_t *) JOYBUS_BASE)
|
||||
|
||||
#define JOYBUS_SCR_RX_READY (1 << 0)
|
||||
#define JOYBUS_SCR_RX_STOP_BIT (1 << 1)
|
||||
#define JOYBUS_SCR_TX_START (1 << 2)
|
||||
#define JOYBUS_SCR_TX_BUSY (1 << 3)
|
||||
#define JOYBUS_SCR_RX_RESET (1 << 6)
|
||||
#define JOYBUS_SCR_TX_RESET (1 << 7)
|
||||
#define JOYBUS_SCR_RX_LENGTH_BIT (8)
|
||||
#define JOYBUS_SCR_RX_LENGTH_MASK (0x7F << JOYBUS_SCR_RX_LENGTH_BIT)
|
||||
#define JOYBUS_SCR_TX_LENGTH_BIT (16)
|
||||
|
||||
|
||||
void reset_handler(void);
|
||||
|
||||
|
||||
|
@ -1,5 +1,4 @@
|
||||
#include "usb.h"
|
||||
#include "dma.h"
|
||||
#include "cfg.h"
|
||||
#include "dd.h"
|
||||
|
||||
@ -140,24 +139,12 @@ static bool rx_cmd (uint32_t *data) {
|
||||
return false;
|
||||
}
|
||||
|
||||
static void handle_escape (void) {
|
||||
if (USB->SCR & USB_SCR_ESCAPE_PENDING) {
|
||||
if (USB->ESCAPE == 'R') {
|
||||
if (p.dma_in_progress) {
|
||||
dma_stop();
|
||||
while (dma_busy());
|
||||
}
|
||||
usb_init();
|
||||
}
|
||||
USB->SCR |= USB_SCR_ESCAPE_ACK;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void usb_init (void) {
|
||||
USB->SCR = (USB_SCR_ENABLED | USB_SCR_FLUSH_TX | USB_SCR_FLUSH_RX);
|
||||
USB->SCR = (USB_SCR_DMA_STOP | USB_SCR_ENABLE | USB_SCR_FLUSH_TX | USB_SCR_FLUSH_RX);
|
||||
|
||||
p.state = STATE_IDLE;
|
||||
p.dma_in_progress = false;
|
||||
p.event_pending = false;
|
||||
p.event_callback_pending = false;
|
||||
|
||||
@ -170,7 +157,11 @@ void usb_init (void) {
|
||||
|
||||
|
||||
void process_usb (void) {
|
||||
handle_escape();
|
||||
if (USB->SCR & USB_SCR_RESET_PENDING) {
|
||||
usb_init();
|
||||
USB->SCR |= USB_SCR_RESET_ACK;
|
||||
return;
|
||||
}
|
||||
|
||||
switch (p.state) {
|
||||
case STATE_IDLE:
|
||||
@ -247,11 +238,15 @@ void process_usb (void) {
|
||||
case 'W':
|
||||
case 'L':
|
||||
case 'S':
|
||||
if (!dma_busy()) {
|
||||
if (!(USB->SCR & USB_SCR_DMA_BUSY)) {
|
||||
if (!p.dma_in_progress) {
|
||||
bool is_write = (p.cmd == 'W') || (p.cmd == 'S');
|
||||
enum dma_dir dir = is_write ? DMA_DIR_TO_SDRAM : DMA_DIR_FROM_SDRAM;
|
||||
dma_start(p.args[0], p.args[1], DMA_ID_USB, dir);
|
||||
USB->ADDR = p.args[0];
|
||||
USB->LEN = p.args[1];
|
||||
if ((p.cmd == 'W') || (p.cmd == 'S')) {
|
||||
USB->SCR |= (USB_SCR_DMA_DIR | USB_SCR_DMA_START);
|
||||
} else {
|
||||
USB->SCR |= USB_SCR_DMA_START;
|
||||
}
|
||||
p.dma_in_progress = true;
|
||||
} else {
|
||||
if (p.cmd == 'L' || p.cmd == 'S') {
|
||||
@ -276,43 +271,6 @@ void process_usb (void) {
|
||||
}
|
||||
break;
|
||||
|
||||
case 'F':
|
||||
case 'T':
|
||||
while ((p.args[0] + p.counter) != (p.args[0] + p.args[1])) {
|
||||
uint8_t *buffer = (uint8_t *) (RAMBUFFER_BASE + p.args[0] + p.counter);
|
||||
if (p.cmd == 'F') {
|
||||
if (tx_byte(*buffer)) {
|
||||
p.counter += 1;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (p.cmd == 'T') {
|
||||
if (rx_byte(buffer)) {
|
||||
p.counter += 1;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ((p.args[0] + p.counter) == (p.args[0] + p.args[1])) {
|
||||
if (p.event_callback_pending) {
|
||||
if (p.cmd == 'F' && p.event.trigger == CALLBACK_BUFFER_READ) {
|
||||
p.event_callback_pending = false;
|
||||
p.event.callback();
|
||||
}
|
||||
if (p.cmd == 'T' && p.event.trigger == CALLBACK_BUFFER_WRITE) {
|
||||
p.event_callback_pending = false;
|
||||
p.event.callback();
|
||||
}
|
||||
}
|
||||
if (p.cmd == 'F') {
|
||||
USB->SCR |= USB_SCR_FORCE_TX;
|
||||
}
|
||||
p.state = STATE_IDLE;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
p.error = true;
|
||||
p.state = STATE_RESPONSE;
|
||||
|
@ -18,8 +18,6 @@ typedef enum {
|
||||
CALLBACK_NONE = 0,
|
||||
CALLBACK_SDRAM_WRITE = 1,
|
||||
CALLBACK_SDRAM_READ = 2,
|
||||
CALLBACK_BUFFER_WRITE = 3,
|
||||
CALLBACK_BUFFER_READ = 4,
|
||||
} usb_event_callback_t;
|
||||
|
||||
typedef struct {
|
||||
|
Loading…
Reference in New Issue
Block a user