good stopping point

This commit is contained in:
Polprzewodnikowy 2022-02-02 19:07:43 +01:00
parent 8bde0ccfb2
commit 8493c2edb1
40 changed files with 1164 additions and 1268 deletions

View File

@ -86,7 +86,7 @@ build_fpga () {
pushd fw > /dev/null pushd fw > /dev/null
if [ "$SKIP_FPGA_REBUILD" = true ] && [ -f output_files/SummerCart64.sof ]; then if [ "$SKIP_FPGA_REBUILD" = true ] && [ -f output_files/SummerCart64.sof ]; then
echo Skipping FPGA build quartus_cpf -c SummerCart64.cof
else else
if [ "$DEBUG_ENABLED" = true ]; then if [ "$DEBUG_ENABLED" = true ]; then
quartus_sh --set VERILOG_MACRO="DEBUG" ./SummerCart64.qpf quartus_sh --set VERILOG_MACRO="DEBUG" ./SummerCart64.qpf

View File

@ -19,7 +19,7 @@
# #
# Quartus Prime # Quartus Prime
# Version 21.1.0 Build 842 10/21/2021 SJ Lite Edition # 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 PROJECT_OUTPUT_DIRECTORY output_files
set_global_assignment -name NUM_PARALLEL_PROCESSORS ALL set_global_assignment -name NUM_PARALLEL_PROCESSORS ALL
set_global_assignment -name FLOW_ENABLE_POWER_ANALYZER ON 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 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/fifo/intel_fifo_8.qip
set_global_assignment -name QIP_FILE rtl/intel/gpio/intel_gpio_ddro.qip set_global_assignment -name QIP_FILE rtl/intel/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_bus.sv
set_global_assignment -name SYSTEMVERILOG_FILE rtl/cpu/cpu_cfg.sv set_global_assignment -name SYSTEMVERILOG_FILE rtl/cpu/cpu_cfg.sv
set_global_assignment -name SYSTEMVERILOG_FILE rtl/cpu/cpu_dd.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_flash.sv
set_global_assignment -name SYSTEMVERILOG_FILE rtl/cpu/cpu_flashram.sv set_global_assignment -name SYSTEMVERILOG_FILE rtl/cpu/cpu_flashram.sv
set_global_assignment -name SYSTEMVERILOG_FILE rtl/cpu/cpu_gpio.sv
set_global_assignment -name SYSTEMVERILOG_FILE rtl/cpu/cpu_i2c.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_ram.sv
set_global_assignment -name SYSTEMVERILOG_FILE rtl/cpu/cpu_sdram.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_uart.sv
set_global_assignment -name SYSTEMVERILOG_FILE rtl/cpu/cpu_usb.sv set_global_assignment -name SYSTEMVERILOG_FILE rtl/cpu/cpu_usb.sv
set_global_assignment -name SYSTEMVERILOG_FILE rtl/cpu/cpu_wrapper.sv set_global_assignment -name SYSTEMVERILOG_FILE rtl/cpu/cpu_wrapper.sv
set_global_assignment -name SYSTEMVERILOG_FILE rtl/memory/memory_dma.sv
set_global_assignment -name SYSTEMVERILOG_FILE rtl/memory/memory_sdram.sv set_global_assignment -name SYSTEMVERILOG_FILE rtl/memory/memory_sdram.sv
set_global_assignment -name SYSTEMVERILOG_FILE rtl/n64/n64_bootloader.sv set_global_assignment -name SYSTEMVERILOG_FILE rtl/n64/n64_bootloader.sv
set_global_assignment -name SYSTEMVERILOG_FILE rtl/n64/n64_bus.sv set_global_assignment -name SYSTEMVERILOG_FILE rtl/n64/n64_bus.sv
@ -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/sc64.sv
set_global_assignment -name SYSTEMVERILOG_FILE rtl/system/system.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 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 # 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_118 -to io_sd_cmd
set_location_assignment PIN_119 -to io_sd_dat[3] set_location_assignment PIN_119 -to io_sd_dat[3]
set_location_assignment PIN_120 -to io_sd_dat[2] 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_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_140 -to o_usb_cs
set_location_assignment PIN_141 -to i_usb_miso 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_INPUT_VERSION SYSTEMVERILOG_2005
set_global_assignment -name VERILOG_SHOW_LMF_MAPPING_MESSAGES OFF set_global_assignment -name VERILOG_SHOW_LMF_MAPPING_MESSAGES OFF
set_global_assignment -name TOP_LEVEL_ENTITY SummerCart64 set_global_assignment -name TOP_LEVEL_ENTITY SummerCart64
set_global_assignment -name VERILOG_MACRO DEBUG
# Fitter Assignments # 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 ENABLE_BOOT_SEL_PIN OFF
set_global_assignment -name INTERNAL_FLASH_UPDATE_MODE "SINGLE COMP IMAGE" set_global_assignment -name INTERNAL_FLASH_UPDATE_MODE "SINGLE COMP IMAGE"
set_global_assignment -name CRC_ERROR_OPEN_DRAIN OFF 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 # Assembler Assignments
# ===================== # =====================
@ -226,10 +231,8 @@ set_global_assignment -name OUTPUT_IO_TIMING_FAR_END_VMEAS "HALF SIGNAL SWING" -
# Pin & Location Assignments # 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 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_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_nmi
set_instance_assignment -name FAST_INPUT_REGISTER ON -to i_n64_reset 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 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_write
set_instance_assignment -name FAST_INPUT_REGISTER ON -to i_n64_pi_alel 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_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_uart_txd
set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to o_rtc_scl 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_rtc_sda
set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to io_n64_pi_ad[*] 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 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_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_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 # 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_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 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 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 set_instance_assignment -name WEAK_PULL_UP_RESISTOR ON -to i_usb_miso
# start DESIGN_PARTITION(Top) # start DESIGN_PARTITION(Top)

View File

@ -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} # 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_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_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 sd_clk -source [get_pins $sd_reg_clk] [get_ports {o_sd_clk}]
create_generated_clock -name flash_se_neg_reg \ 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}] \ -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 \ -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_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 -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 # SD card timings
@ -48,8 +49,17 @@ set_multicycle_path -setup -end 2 -from [get_clocks {sdram_clk}] -to [get_clocks
# FT1248 timings # FT1248 timings
set_false_path -to [get_ports {o_usb_clk io_usb_miosi[*] o_usb_cs}] set_output_delay -clock [get_clocks {usb_clk}] -max 5.0 [get_ports {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}] -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 # N64, PI and SI timings

@ -1 +1 @@
Subproject commit f9b1beb4cfd6b382157b54bc8f38c61d5ae7d785 Subproject commit f00a88c36eaab478b64ee27d8162e421049bcc66

View File

@ -29,8 +29,7 @@ module SummerCart64 (
output o_usb_clk, output o_usb_clk,
output o_usb_cs, output o_usb_cs,
input i_usb_miso, input i_usb_miso,
inout [3:0] io_usb_miosi, inout [7:0] io_usb_miosi,
input i_usb_pwren,
input i_uart_rxd, input i_uart_rxd,
output o_uart_txd, output o_uart_txd,
@ -42,10 +41,6 @@ module SummerCart64 (
output o_led output o_led
); );
logic [7:0] gpio_o;
logic [7:0] gpio_i;
logic [7:0] gpio_oe;
logic dd_interrupt; logic dd_interrupt;
if_system sys ( if_system sys (
@ -56,7 +51,7 @@ module SummerCart64 (
if_config cfg (); if_config cfg ();
if_dma dma (); if_memory_dma usb_dma ();
if_sdram sdram (); if_sdram sdram ();
@ -70,7 +65,6 @@ module SummerCart64 (
.dd_interrupt(dd_interrupt) .dd_interrupt(dd_interrupt)
); );
if_cpu_ram cpu_ram ();
system system_inst ( system system_inst (
.sys(sys) .sys(sys)
@ -85,13 +79,12 @@ module SummerCart64 (
n64_soc n64_soc_inst ( n64_soc n64_soc_inst (
.sys(sys), .sys(sys),
.cfg(cfg), .cfg(cfg),
.dma(dma), .usb_dma(usb_dma),
.sdram(sdram), .sdram(sdram),
.flashram(flashram), .flashram(flashram),
.si(si), .si(si),
.flash(flash), .flash(flash),
.dd(dd), .dd(dd),
.cpu_ram(cpu_ram),
.n64_pi_alel(i_n64_pi_alel), .n64_pi_alel(i_n64_pi_alel),
.n64_pi_aleh(i_n64_pi_aleh), .n64_pi_aleh(i_n64_pi_aleh),
@ -114,17 +107,12 @@ module SummerCart64 (
cpu_soc cpu_soc_inst ( cpu_soc cpu_soc_inst (
.sys(sys), .sys(sys),
.cfg(cfg), .cfg(cfg),
.dma(dma), .usb_dma(usb_dma),
.sdram(sdram), .sdram(sdram),
.flashram(flashram), .flashram(flashram),
.si(si), .si(si),
.flash(flash), .flash(flash),
.dd(dd), .dd(dd),
.cpu_ram(cpu_ram),
.gpio_o(gpio_o),
.gpio_i(gpio_i),
.gpio_oe(gpio_oe),
.i2c_scl(o_rtc_scl), .i2c_scl(o_rtc_scl),
.i2c_sda(io_rtc_sda), .i2c_sda(io_rtc_sda),
@ -133,7 +121,6 @@ module SummerCart64 (
.usb_cs(o_usb_cs), .usb_cs(o_usb_cs),
.usb_miso(i_usb_miso), .usb_miso(i_usb_miso),
.usb_miosi(io_usb_miosi), .usb_miosi(io_usb_miosi),
.usb_pwren(i_usb_pwren),
.uart_rxd(i_uart_rxd), .uart_rxd(i_uart_rxd),
.uart_txd(o_uart_txd), .uart_txd(o_uart_txd),
@ -145,14 +132,7 @@ module SummerCart64 (
always_comb begin always_comb begin
o_n64_irq = dd_interrupt ? 1'b0 : 1'bZ; o_n64_irq = dd_interrupt ? 1'b0 : 1'bZ;
end o_led = 1'bZ;
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]};
end end
endmodule endmodule

View File

@ -1,6 +1,6 @@
interface if_cpu_bus (); interface if_cpu_bus #(
parameter bit [3:0] NUM_DEVICES
localparam [3:0] NUM_DEVICES = sc64::__ID_CPU_END; ) ();
logic request; logic request;
logic ack; logic ack;

View File

@ -18,7 +18,8 @@ module cpu_cfg (
R_VERSION, R_VERSION,
R_RECONFIGURE, R_RECONFIGURE,
R_ISV_OFFSET, R_ISV_OFFSET,
R_ISV_RD_PTR R_ISV_RD_PTR,
R_FLASH
} e_reg_id; } e_reg_id;
const logic [31:0] RECONFIGURE_MAGIC = 32'h52535446; const logic [31:0] RECONFIGURE_MAGIC = 32'h52535446;
@ -39,7 +40,10 @@ module cpu_cfg (
cfg.cpu_busy, cfg.cpu_busy,
1'b0, 1'b0,
cfg.cmd_error, cfg.cmd_error,
20'd0, 2'd0,
cfg.flash_erase_busy,
1'd0,
16'd0,
cfg.isv_enabled, cfg.isv_enabled,
skip_bootloader, skip_bootloader,
cfg.flashram_enabled, cfg.flashram_enabled,
@ -73,6 +77,10 @@ module cpu_cfg (
end end
always_ff @(posedge sys.clk) begin 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 if (sys.reset) begin
cfg.cpu_ready <= 1'b0; cfg.cpu_ready <= 1'b0;
cfg.cpu_busy <= 1'b0; cfg.cpu_busy <= 1'b0;
@ -95,9 +103,11 @@ module cpu_cfg (
cfg.sdram_writable <= 1'b0; cfg.sdram_writable <= 1'b0;
isv_current_rd_ptr <= 16'd0; isv_current_rd_ptr <= 16'd0;
end end
if (cfg.cmd_request) begin if (cfg.cmd_request) begin
cfg.cpu_busy <= 1'b1; cfg.cpu_busy <= 1'b1;
end end
if (bus.request) begin if (bus.request) begin
case (bus.address[5:2]) case (bus.address[5:2])
R_SCR: begin R_SCR: begin
@ -105,8 +115,11 @@ module cpu_cfg (
{ {
cfg.cpu_ready, cfg.cpu_ready,
cfg.cpu_busy, cfg.cpu_busy,
cfg.cmd_error cfg.cmd_error,
} <= {bus.wdata[31:30], bus.wdata[28]}; cfg.flash_wp_disable,
cfg.flash_wp_enable,
cfg.flash_erase_start
} <= {bus.wdata[31:30], bus.wdata[28:26], bus.wdata[24]};
end end
if (bus.wmask[0]) begin if (bus.wmask[0]) begin
{ {
@ -156,31 +169,11 @@ module cpu_cfg (
end end
end end
logic [1:0] ru_clk; vendor_reconfigure vendor_reconfigure_inst (
logic ru_rconfig; .clk(sys.clk),
logic ru_regout; .reset(sys.reset),
always_ff @(posedge sys.clk) begin .trigger_reconfiguration(trigger_reconfiguration)
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)
); );
endmodule endmodule

View File

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

View File

@ -16,7 +16,7 @@ interface if_flash ();
output wdata output wdata
); );
modport memory ( modport flash (
input request, input request,
output ack, output ack,
input write, input write,

View File

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

View File

@ -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 ( module cpu_ram (
if_system.sys sys, if_system.sys sys,
if_cpu_bus bus, if_cpu_bus bus
if_cpu_ram.cpu cpu_ram
); );
logic [3:0][7:0] ram [0:4095]; logic [3:0][7:0] ram [0:8191];
logic [31:0] q_cpu; logic [31:0] q;
logic [31:0] q_external;
always_ff @(posedge sys.clk) begin always_ff @(posedge sys.clk) begin
bus.ack <= 1'b0; bus.ack <= 1'b0;
@ -40,33 +14,19 @@ module cpu_ram (
end end
always_comb begin always_comb begin
cpu_ram.rdata = cpu_ram.address[0] ? q_external[31:16] : q_external[15:0];
bus.rdata = 32'd0; bus.rdata = 32'd0;
if (bus.ack) begin if (bus.ack) begin
bus.rdata = q_cpu; bus.rdata = q;
end end
end end
always_ff @(posedge sys.clk) begin 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.request) begin
if (bus.wmask[0]) ram[bus.address[13:2]][0] <= bus.wdata[7:0]; if (bus.wmask[0]) ram[bus.address[14:2]][0] <= bus.wdata[7:0];
if (bus.wmask[1]) ram[bus.address[13:2]][1] <= bus.wdata[15:8]; if (bus.wmask[1]) ram[bus.address[14:2]][1] <= bus.wdata[15:8];
if (bus.wmask[2]) ram[bus.address[13:2]][2] <= bus.wdata[23:16]; if (bus.wmask[2]) ram[bus.address[14:2]][2] <= bus.wdata[23:16];
if (bus.wmask[3]) ram[bus.address[13:2]][3] <= bus.wdata[31:24]; if (bus.wmask[3]) ram[bus.address[14: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
end end
end end

View File

@ -1,17 +1,12 @@
module cpu_soc ( module cpu_soc (
if_system.sys sys, if_system.sys sys,
if_config.cpu cfg, if_config.cpu cfg,
if_dma dma, if_memory_dma usb_dma,
if_sdram.cpu sdram, if_sdram.cpu sdram,
if_flashram.cpu flashram, if_flashram.cpu flashram,
if_si.cpu si, if_si.cpu si,
if_flash.cpu flash, if_flash flash,
if_dd.cpu dd, 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, output i2c_scl,
inout i2c_sda, inout i2c_sda,
@ -19,8 +14,7 @@ module cpu_soc (
output usb_clk, output usb_clk,
output usb_cs, output usb_cs,
input usb_miso, input usb_miso,
inout [3:0] usb_miosi, inout [7:0] usb_miosi,
input usb_pwren,
input uart_rxd, input uart_rxd,
output uart_txd, output uart_txd,
@ -30,98 +24,98 @@ module cpu_soc (
inout [3:0] sd_dat 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 ( cpu_wrapper cpu_wrapper_inst (
.sys(sys), .sys(sys),
.bus(bus) .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 ( cpu_flash cpu_flash_inst (
.sys(sys), .sys(sys),
.bus(bus.at[sc64::ID_CPU_FLASH].device), .bus(bus.at[DEV_FLASH].device),
.flash(flash) .flash(flash)
); );
cpu_gpio cpu_gpio_inst ( cpu_ram cpu_ram_inst (
.sys(sys), .sys(sys),
.bus(bus.at[sc64::ID_CPU_GPIO].device), .bus(bus.at[DEV_RAM].device)
.gpio_i(gpio_i), );
.gpio_o(gpio_o),
.gpio_oe(gpio_oe) cpu_cfg cpu_cfg_inst (
.sys(sys),
.bus(bus.at[DEV_CFG].device),
.cfg(cfg)
); );
cpu_i2c cpu_i2c_inst ( cpu_i2c cpu_i2c_inst (
.sys(sys), .sys(sys),
.bus(bus.at[sc64::ID_CPU_I2C].device), .bus(bus.at[DEV_I2C].device),
.i2c_scl(i2c_scl), .i2c_scl(i2c_scl),
.i2c_sda(i2c_sda) .i2c_sda(i2c_sda)
); );
cpu_usb cpu_usb_inst ( cpu_usb cpu_usb_inst (
.sys(sys), .sys(sys),
.bus(bus.at[sc64::ID_CPU_USB].device), .bus(bus.at[DEV_USB].device),
.dma(dma.at[sc64::ID_DMA_USB].device), .dma(usb_dma),
.usb_clk(usb_clk), .usb_clk(usb_clk),
.usb_cs(usb_cs), .usb_cs(usb_cs),
.usb_miso(usb_miso), .usb_miso(usb_miso),
.usb_miosi(usb_miosi), .usb_miosi(usb_miosi)
.usb_pwren(usb_pwren)
); );
generate generate
if (sc64::CPU_HAS_UART) begin if (sc64::CPU_HAS_UART) begin
cpu_uart cpu_uart_inst ( cpu_uart cpu_uart_inst (
.sys(sys), .sys(sys),
.bus(bus.at[sc64::ID_CPU_UART].device), .bus(bus.at[DEV_UART].device),
.uart_rxd(uart_rxd), .uart_rxd(uart_rxd),
.uart_txd(uart_txd) .uart_txd(uart_txd)
); );
end end
endgenerate endgenerate
cpu_dma cpu_dma_inst ( cpu_dd cpu_dd_inst (
.sys(sys), .sys(sys),
.bus(bus.at[sc64::ID_CPU_DMA].device), .bus(bus.at[DEV_DD].device),
.dma(dma) .dd(dd)
);
cpu_cfg cpu_cfg_inst (
.sys(sys),
.bus(bus.at[sc64::ID_CPU_CFG].device),
.cfg(cfg)
); );
cpu_sdram cpu_sdram_inst ( cpu_sdram cpu_sdram_inst (
.sys(sys), .sys(sys),
.bus(bus.at[sc64::ID_CPU_SDRAM].device), .bus(bus.at[DEV_SDRAM].device),
.sdram(sdram) .sdram(sdram)
); );
cpu_flashram cpu_flashram_inst ( cpu_flashram cpu_flashram_inst (
.sys(sys), .sys(sys),
.bus(bus.at[sc64::ID_CPU_FLASHRAM].device), .bus(bus.at[DEV_FLASHRAM].device),
.flashram(flashram) .flashram(flashram)
); );
cpu_si cpu_si_inst ( cpu_si cpu_si_inst (
.sys(sys), .sys(sys),
.bus(bus.at[sc64::ID_CPU_SI].device), .bus(bus.at[DEV_SI].device),
.si(si) .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_clk = 1'bZ;
assign sd_cmd = 1'bZ; assign sd_cmd = 1'bZ;
assign sd_dat = 4'bZZZZ; assign sd_dat = 4'bZZZZ;

View File

@ -1,44 +1,27 @@
module cpu_usb ( module cpu_usb (
if_system sys, if_system sys,
if_cpu_bus bus, if_cpu_bus bus,
if_dma dma, if_memory_dma dma,
output usb_clk, output usb_clk,
output usb_cs, output usb_cs,
input usb_miso, input usb_miso,
inout [3:0] usb_miosi, inout [7:0] usb_miosi
input usb_pwren
); );
logic rx_flush; logic rx_flush;
logic rx_empty;
logic rx_read;
logic [7:0] rx_rdata;
logic tx_flush; logic tx_flush;
logic tx_full; logic usb_enable;
logic tx_write; logic reset_pending;
logic [7:0] tx_wdata; logic reset_ack;
logic write_buffer_flush;
logic rx_escape_valid; typedef enum bit [1:0] {
logic rx_escape_ack; R_SCR,
logic [7:0] rx_escape; R_DATA,
R_ADDR,
logic cpu_rx_read; R_LEN
logic cpu_tx_write; } e_reg_id;
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
always_ff @(posedge sys.clk) begin always_ff @(posedge sys.clk) begin
bus.ack <= 1'b0; bus.ack <= 1'b0;
@ -51,75 +34,93 @@ module cpu_usb (
bus.rdata = 32'd0; bus.rdata = 32'd0;
if (bus.ack) begin if (bus.ack) begin
case (bus.address[3:2]) case (bus.address[3:2])
0: bus.rdata = {25'd0, rx_escape_valid, usb_pwren, usb_enabled, 2'b00, ~tx_full, ~rx_empty}; R_SCR: bus.rdata = {
1: bus.rdata = {24'd0, rx_rdata}; 23'd0,
2: bus.rdata = {24'd0, rx_escape}; 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; default: bus.rdata = 32'd0;
endcase endcase
end end
end end
always_ff @(posedge sys.clk) begin 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; rx_flush <= 1'b0;
cpu_rx_read <= 1'b0;
tx_flush <= 1'b0; tx_flush <= 1'b0;
cpu_tx_write <= 1'b0; reset_ack <= 1'b0;
write_buffer_flush <= 1'b0;
rx_escape_ack <= 1'b0;
tx_force <= 1'b0;
if (sys.reset) begin if (sys.reset) begin
usb_enabled <= 1'b0; usb_enable <= 1'b0;
end else begin end else begin
if (bus.request) begin if (bus.request) begin
case (bus.address[2:2]) case (bus.address[3:2])
2'd0: begin R_SCR: if (&bus.wmask) begin
if (bus.wmask[1]) begin {dma.direction, dma.stop, dma.start} <= bus.wdata[11:9];
tx_force <= bus.wdata[8]; reset_ack <= bus.wdata[7];
end {write_buffer_flush, usb_enable, tx_flush, rx_flush} <= bus.wdata[5:2];
if (bus.wmask[0]) begin
rx_escape_ack <= bus.wdata[7];
{usb_enabled, tx_flush, rx_flush} <= bus.wdata[4:2];
end
end end
2'd1: begin R_DATA: if (bus.wmask == 4'b0000) begin
if (bus.wmask[0]) begin dma.cpu_rx_read <= 1'b1;
cpu_tx_write <= 1'b1; end else if (bus.wmask == 4'b0001) begin
end else begin dma.cpu_tx_write <= 1'b1;
cpu_rx_read <= 1'b1; dma.cpu_tx_wdata <= bus.wdata[7:0];
end 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 end
endcase endcase
end end
end end
end end
usb_ft1248 usb_ft1248_inst ( memory_dma usb_memory_dma_inst (
.sys(sys), .clk(sys.clk),
.reset(~usb_enable),
.dma(dma)
);
.usb_enabled(usb_enabled), usb_ft1248 usb_ft1248_inst (
.tx_force(tx_force), .clk(sys.clk),
.reset(~usb_enable),
.usb_clk(usb_clk), .usb_clk(usb_clk),
.usb_cs(usb_cs), .usb_cs(usb_cs),
.usb_miso(usb_miso), .usb_miso(usb_miso),
.usb_miosi(usb_miosi), .usb_miosi(usb_miosi),
.reset_pending(reset_pending),
.reset_ack(reset_ack),
.write_buffer_flush(write_buffer_flush),
.rx_flush(rx_flush), .rx_flush(rx_flush),
.rx_empty(rx_empty), .rx_empty(dma.rx_empty),
.rx_read(rx_read), .rx_almost_empty(dma.rx_almost_empty),
.rx_rdata(rx_rdata), .rx_read(dma.rx_read),
.rx_rdata(dma.rx_rdata),
.tx_flush(tx_flush), .tx_flush(tx_flush),
.tx_full(tx_full), .tx_full(dma.tx_full),
.tx_write(tx_write), .tx_almost_full(dma.tx_almost_full),
.tx_wdata(tx_wdata), .tx_write(dma.tx_write),
.tx_wdata(dma.tx_wdata)
.rx_escape_valid(rx_escape_valid),
.rx_escape_ack(rx_escape_ack),
.rx_escape(rx_escape)
); );
endmodule endmodule

View File

@ -28,12 +28,29 @@ module cpu_wrapper (
end end
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 #( picorv32 #(
.ENABLE_COUNTERS(0), .ENABLE_COUNTERS(0),
.ENABLE_COUNTERS64(0), .ENABLE_COUNTERS64(0),
.TWO_STAGE_SHIFT(0),
.TWO_CYCLE_COMPARE(1),
.TWO_CYCLE_ALU(1),
.CATCH_MISALIGN(0), .CATCH_MISALIGN(0),
.CATCH_ILLINSN(0), .CATCH_ILLINSN(0),
.PROGADDR_RESET(sc64::CPU_RESET_VECTOR) .PROGADDR_RESET(32'h0001_0000)
) cpu_inst ( ) cpu_inst (
.clk(sys.clk), .clk(sys.clk),
.resetn(~sys.reset), .resetn(~sys.reset),
@ -43,7 +60,26 @@ module cpu_wrapper (
.mem_ready(bus.ack), .mem_ready(bus.ack),
.mem_rdata(bus.rdata), .mem_rdata(bus.rdata),
.mem_la_read(mem_la_read), .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 endmodule

View File

@ -9,7 +9,7 @@
// scfifo // scfifo
// //
// Simulation Library Files(s): // Simulation Library Files(s):
// // altera_mf
// ============================================================ // ============================================================
// ************************************************************ // ************************************************************
// THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE! // THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE!
@ -43,6 +43,8 @@ module intel_fifo_8 (
rdreq, rdreq,
sclr, sclr,
wrreq, wrreq,
almost_empty,
almost_full,
empty, empty,
full, full,
q); q);
@ -52,16 +54,22 @@ module intel_fifo_8 (
input rdreq; input rdreq;
input sclr; input sclr;
input wrreq; input wrreq;
output almost_empty;
output almost_full;
output empty; output empty;
output full; output full;
output [7:0] q; output [7:0] q;
wire sub_wire0; wire sub_wire0;
wire sub_wire1; wire sub_wire1;
wire [7:0] sub_wire2; wire sub_wire2;
wire empty = sub_wire0; wire sub_wire3;
wire full = sub_wire1; wire [7:0] sub_wire4;
wire [7:0] q = sub_wire2[7:0]; 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 ( scfifo scfifo_component (
.clock (clock), .clock (clock),
@ -69,16 +77,18 @@ module intel_fifo_8 (
.rdreq (rdreq), .rdreq (rdreq),
.sclr (sclr), .sclr (sclr),
.wrreq (wrreq), .wrreq (wrreq),
.empty (sub_wire0), .almost_empty (sub_wire0),
.full (sub_wire1), .almost_full (sub_wire1),
.q (sub_wire2), .empty (sub_wire2),
.full (sub_wire3),
.q (sub_wire4),
.aclr (), .aclr (),
.almost_empty (),
.almost_full (),
.eccstatus (), .eccstatus (),
.usedw ()); .usedw ());
defparam 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.intended_device_family = "MAX 10",
scfifo_component.lpm_numwords = 1024, scfifo_component.lpm_numwords = 1024,
scfifo_component.lpm_showahead = "ON", scfifo_component.lpm_showahead = "ON",
@ -95,10 +105,10 @@ endmodule
// ============================================================ // ============================================================
// CNX file retrieval info // CNX file retrieval info
// ============================================================ // ============================================================
// Retrieval info: PRIVATE: AlmostEmpty NUMERIC "0" // Retrieval info: PRIVATE: AlmostEmpty NUMERIC "1"
// Retrieval info: PRIVATE: AlmostEmptyThr NUMERIC "-1" // Retrieval info: PRIVATE: AlmostEmptyThr NUMERIC "2"
// Retrieval info: PRIVATE: AlmostFull NUMERIC "0" // Retrieval info: PRIVATE: AlmostFull NUMERIC "1"
// Retrieval info: PRIVATE: AlmostFullThr NUMERIC "-1" // Retrieval info: PRIVATE: AlmostFullThr NUMERIC "1023"
// Retrieval info: PRIVATE: CLOCKS_ARE_SYNCHRONIZED NUMERIC "1" // Retrieval info: PRIVATE: CLOCKS_ARE_SYNCHRONIZED NUMERIC "1"
// Retrieval info: PRIVATE: Clock NUMERIC "0" // Retrieval info: PRIVATE: Clock NUMERIC "0"
// Retrieval info: PRIVATE: Depth NUMERIC "1024" // Retrieval info: PRIVATE: Depth NUMERIC "1024"
@ -109,7 +119,7 @@ endmodule
// Retrieval info: PRIVATE: LegacyRREQ NUMERIC "0" // Retrieval info: PRIVATE: LegacyRREQ NUMERIC "0"
// Retrieval info: PRIVATE: MAX_DEPTH_BY_9 NUMERIC "0" // Retrieval info: PRIVATE: MAX_DEPTH_BY_9 NUMERIC "0"
// Retrieval info: PRIVATE: OVERFLOW_CHECKING 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: RAM_BLOCK_TYPE NUMERIC "0"
// Retrieval info: PRIVATE: SYNTH_WRAPPER_GEN_POSTFIX STRING "0" // Retrieval info: PRIVATE: SYNTH_WRAPPER_GEN_POSTFIX STRING "0"
// Retrieval info: PRIVATE: UNDERFLOW_CHECKING NUMERIC "0" // Retrieval info: PRIVATE: UNDERFLOW_CHECKING NUMERIC "0"
@ -128,7 +138,9 @@ endmodule
// Retrieval info: PRIVATE: wsFull NUMERIC "1" // Retrieval info: PRIVATE: wsFull NUMERIC "1"
// Retrieval info: PRIVATE: wsUsedW NUMERIC "0" // Retrieval info: PRIVATE: wsUsedW NUMERIC "0"
// Retrieval info: LIBRARY: altera_mf altera_mf.altera_mf_components.all // 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: INTENDED_DEVICE_FAMILY STRING "MAX 10"
// Retrieval info: CONSTANT: LPM_NUMWORDS NUMERIC "1024" // Retrieval info: CONSTANT: LPM_NUMWORDS NUMERIC "1024"
// Retrieval info: CONSTANT: LPM_SHOWAHEAD STRING "ON" // Retrieval info: CONSTANT: LPM_SHOWAHEAD STRING "ON"
@ -138,6 +150,8 @@ endmodule
// Retrieval info: CONSTANT: OVERFLOW_CHECKING STRING "ON" // Retrieval info: CONSTANT: OVERFLOW_CHECKING STRING "ON"
// Retrieval info: CONSTANT: UNDERFLOW_CHECKING STRING "ON" // Retrieval info: CONSTANT: UNDERFLOW_CHECKING STRING "ON"
// Retrieval info: CONSTANT: USE_EAB 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: 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: data 0 0 8 0 INPUT NODEFVAL "data[7..0]"
// Retrieval info: USED_PORT: empty 0 0 0 0 OUTPUT NODEFVAL "empty" // 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: @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: @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: @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: 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: full 0 0 0 0 @full 0 0 0 0
// Retrieval info: CONNECT: q 0 0 8 0 @q 0 0 8 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.bsf FALSE
// Retrieval info: GEN_FILE: TYPE_NORMAL intel_fifo_8_inst.v 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: GEN_FILE: TYPE_NORMAL intel_fifo_8_bb.v FALSE
// Retrieval info: LIB_FILE: altera_mf

View File

@ -9,7 +9,7 @@
// altpll // altpll
// //
// Simulation Library Files(s): // Simulation Library Files(s):
// // altera_mf
// ============================================================ // ============================================================
// ************************************************************ // ************************************************************
// THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE! // 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.bsf FALSE
// Retrieval info: GEN_FILE: TYPE_NORMAL intel_pll_inst.v 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: GEN_FILE: TYPE_NORMAL intel_pll_bb.v FALSE
// Retrieval info: LIB_FILE: altera_mf
// Retrieval info: CBX_MODULE_PREFIX: ON // Retrieval info: CBX_MODULE_PREFIX: ON

237
fw/rtl/memory/memory_dma.sv Normal file
View 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

View File

@ -1,20 +1,10 @@
module n64_bootloader ( module n64_bootloader (
if_system.sys sys, if_system.sys sys,
if_n64_bus bus, if_n64_bus bus,
if_flash.memory flash 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] { typedef enum bit [0:0] {
S_IDLE, S_IDLE,
S_WAIT S_WAIT
@ -28,97 +18,77 @@ module n64_bootloader (
e_state state; e_state state;
e_source_request source_request; e_source_request source_request;
always_ff @(posedge sys.clk) begin logic request;
csr_ack <= 1'b0; logic ack;
write_ack <= 1'b0; logic write;
logic [31:0] address;
logic [31:0] wdata;
logic [31:0] rdata;
always_ff @(posedge sys.clk) begin
if (sys.reset) begin if (sys.reset) begin
state <= S_IDLE; state <= S_IDLE;
mem_request <= 1'b0; request <= 1'b0;
end else begin end else begin
case (state) case (state)
S_IDLE: begin S_IDLE: begin
if (bus.request || flash.request) begin if (bus.request || flash.request) begin
state <= S_WAIT; state <= S_WAIT;
mem_request <= 1'b1; request <= 1'b1;
if (bus.request) begin if (bus.request) begin
mem_write <= 1'b0; write <= 1'b0;
mem_address <= bus.address; address <= bus.address;
mem_wdata <= bus.wdata; wdata <= bus.wdata;
source_request <= T_N64; source_request <= T_N64;
end else if (flash.request) begin end else if (flash.request) begin
mem_write <= flash.write; write <= flash.write;
mem_address <= flash.address; address <= flash.address;
mem_wdata <= flash.wdata; wdata <= flash.wdata;
source_request <= T_CPU; source_request <= T_CPU;
end end
end end
end end
S_WAIT: begin S_WAIT: begin
if (mem_address[27] && source_request != T_N64 && !csr_ack) begin if (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
state <= S_IDLE; state <= S_IDLE;
request <= 1'b0;
end end
end end
endcase endcase
end end
end end
logic csr_or_data;
logic csr_read;
logic csr_write;
logic data_read;
logic data_write;
always_comb begin always_comb begin
csr_or_data = mem_address[27] && source_request == T_CPU; bus.ack = source_request == T_N64 && ack;
csr_read = csr_or_data && mem_request && !mem_write;
csr_write = csr_or_data && mem_request && mem_write;
data_read = !csr_or_data && mem_request && !mem_write;
data_write = !csr_or_data && mem_request && mem_write;
bus.ack = source_request == T_N64 && data_ack;
bus.rdata = 16'd0; bus.rdata = 16'd0;
if (bus.ack && bus.address < 32'h00010000) begin if (bus.ack && bus.address < 32'h00010000) begin
if (bus.address[1]) bus.rdata = {data_rdata[23:16], data_rdata[31:24]}; if (bus.address[1]) bus.rdata = {rdata[23:16], rdata[31:24]};
else bus.rdata = {data_rdata[7:0], data_rdata[15:8]}; else bus.rdata = {rdata[7:0], rdata[15:8]};
end end
flash.ack = source_request == T_CPU && (csr_ack || data_ack || write_ack); flash.ack = source_request == T_CPU && ack;
flash.rdata = 32'd0; flash.rdata = 32'd0;
if (flash.ack) begin if (flash.ack) begin
flash.rdata = csr_or_data ? csr_rdata : data_rdata; flash.rdata = rdata;
end end
end end
intel_flash intel_flash_inst ( vendor_flash vendor_flash_inst (
.clock(sys.clk), .clk(sys.clk),
.reset_n(~sys.reset), .reset(sys.reset),
.avmm_csr_addr(mem_address[2]), .erase_start(cfg.flash_erase_start),
.avmm_csr_read(csr_read), .erase_busy(cfg.flash_erase_busy),
.avmm_csr_writedata(mem_wdata), .wp_enable(cfg.flash_wp_enable),
.avmm_csr_write(csr_write), .wp_disable(cfg.flash_wp_disable),
.avmm_csr_readdata(csr_rdata),
.avmm_data_addr(mem_address[31:2]), .request(request),
.avmm_data_read(data_read), .ack(ack),
.avmm_data_writedata(mem_wdata), .write(write),
.avmm_data_write(data_write), .address(address),
.avmm_data_readdata(data_rdata), .wdata(wdata),
.avmm_data_waitrequest(data_busy), .rdata(rdata)
.avmm_data_readdatavalid(data_ack),
.avmm_data_burstcount(2'd1)
); );
endmodule endmodule

View File

@ -1,8 +1,7 @@
module n64_cfg ( module n64_cfg (
if_system sys, if_system sys,
if_n64_bus bus, if_n64_bus bus,
if_config.n64 cfg, if_config.n64 cfg
if_cpu_ram.external cpu_ram
); );
typedef enum bit [2:0] { typedef enum bit [2:0] {
@ -32,10 +31,6 @@ module n64_cfg (
logic [31:0] isv_id; logic [31:0] isv_id;
always_comb begin 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; bus.rdata = 16'd0;
if (bus.ack) begin if (bus.ack) begin
if (bus.address[15:14] == 2'b00) 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_DATA_1_L: bus.rdata = cfg.data[1][15:0];
R_VERSION_H: bus.rdata = sc64::SC64_VER[31:16]; R_VERSION_H: bus.rdata = sc64::SC64_VER[31:16];
R_VERSION_L: bus.rdata = sc64::SC64_VER[15:0]; R_VERSION_L: bus.rdata = sc64::SC64_VER[15:0];
default: bus.rdata = 16'd0;
endcase 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 end else if (bus.address[15:14] == 2'b11) begin
case (bus.address[4:1]) case (bus.address[4:1])
R_ISV_ID_H: bus.rdata = isv_id[31:16]; R_ISV_ID_H: bus.rdata = isv_id[31:16];
R_ISV_ID_L: bus.rdata = isv_id[15:0]; R_ISV_ID_L: bus.rdata = isv_id[15:0];
R_ISV_RD_PTR: bus.rdata = cfg.isv_rd_ptr; R_ISV_RD_PTR: bus.rdata = cfg.isv_rd_ptr;
default: bus.rdata = 16'd0;
endcase endcase
end end
end end

View File

@ -1,7 +1,7 @@
module n64_sdram ( module n64_sdram (
if_system sys, if_system sys,
if_n64_bus bus, if_n64_bus bus,
if_dma.memory dma, if_memory_dma.memory usb_dma,
if_sdram.memory sdram, if_sdram.memory sdram,
output sdram_cs, output sdram_cs,
@ -20,70 +20,52 @@ module n64_sdram (
logic [15:0] mem_rdata; logic [15:0] mem_rdata;
logic [15:0] mem_wdata; logic [15:0] mem_wdata;
typedef enum bit [0:0] {
S_IDLE,
S_WAIT
} e_state;
typedef enum bit [1:0] { typedef enum bit [1:0] {
T_BUS, T_BUS,
T_DMA, T_SDRAM,
T_SDRAM T_USB_DMA
} e_source_request; } e_source_request;
e_state state;
e_source_request source_request; e_source_request source_request;
always_ff @(posedge sys.clk) begin always_ff @(posedge sys.clk) begin
if (sys.reset) begin if (sys.reset) begin
state <= S_IDLE;
mem_request <= 1'b0; mem_request <= 1'b0;
end else begin end else begin
case (state) if (!mem_request && (bus.request || sdram.request || usb_dma.request)) begin
S_IDLE: begin
if (bus.request) begin
state <= S_WAIT;
mem_request <= 1'b1; mem_request <= 1'b1;
if (bus.request) begin
mem_write <= bus.write; mem_write <= bus.write;
mem_address <= bus.address; mem_address <= bus.address;
mem_wdata <= bus.wdata; mem_wdata <= bus.wdata;
source_request <= T_BUS; source_request <= T_BUS;
end else if ((!bus.n64_active) && (sdram.request || dma.request)) begin end else if (sdram.request) begin
state <= S_WAIT;
mem_request <= 1'b1;
if (sdram.request) begin
mem_write <= sdram.write; mem_write <= sdram.write;
mem_address <= sdram.address; mem_address <= sdram.address;
mem_wdata <= sdram.wdata; mem_wdata <= sdram.wdata;
source_request <= T_SDRAM; source_request <= T_SDRAM;
end else if (dma.request) begin end else if (usb_dma.request) begin
mem_write <= dma.write; mem_write <= usb_dma.write;
mem_address <= dma.address; mem_address <= usb_dma.address;
mem_wdata <= dma.wdata; mem_wdata <= usb_dma.wdata;
source_request <= T_DMA; source_request <= T_USB_DMA;
end end
end end
end
S_WAIT: begin
if (mem_ack) begin if (mem_ack) begin
state <= S_IDLE;
mem_request <= 1'b0; mem_request <= 1'b0;
end end
end end
endcase
end
end end
always_comb begin always_comb begin
bus.ack = source_request == T_BUS && mem_ack; bus.ack = source_request == T_BUS && mem_ack;
bus.rdata = bus.ack ? mem_rdata : 16'd0; 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.ack = source_request == T_SDRAM && mem_ack;
sdram.rdata = mem_rdata; sdram.rdata = mem_rdata;
usb_dma.ack = source_request == T_USB_DMA && mem_ack;
usb_dma.rdata = mem_rdata;
end end
memory_sdram memory_sdram_inst ( memory_sdram memory_sdram_inst (

View File

@ -1,13 +1,12 @@
module n64_soc ( module n64_soc (
if_system sys, if_system sys,
if_config cfg, if_config cfg,
if_dma.memory dma, if_memory_dma.memory usb_dma,
if_sdram.memory sdram, if_sdram.memory sdram,
if_flashram.flashram flashram, if_flashram.flashram flashram,
if_si.si si, if_si.si si,
if_flash.memory flash, if_flash.flash flash,
if_dd dd, if_dd dd,
if_cpu_ram.external cpu_ram,
input n64_pi_alel, input n64_pi_alel,
input n64_pi_aleh, input n64_pi_aleh,
@ -52,7 +51,7 @@ module n64_soc (
n64_sdram n64_sdram_inst ( n64_sdram n64_sdram_inst (
.sys(sys), .sys(sys),
.bus(bus.at[sc64::ID_N64_SDRAM].device), .bus(bus.at[sc64::ID_N64_SDRAM].device),
.dma(dma), .usb_dma(usb_dma),
.sdram(sdram), .sdram(sdram),
.sdram_cs(sdram_cs), .sdram_cs(sdram_cs),
@ -67,6 +66,7 @@ module n64_soc (
n64_bootloader n64_bootloader_inst ( n64_bootloader n64_bootloader_inst (
.sys(sys), .sys(sys),
.bus(bus.at[sc64::ID_N64_BOOTLOADER].device), .bus(bus.at[sc64::ID_N64_BOOTLOADER].device),
.cfg(cfg),
.flash(flash) .flash(flash)
); );
@ -91,8 +91,7 @@ module n64_soc (
n64_cfg n64_cfg_inst ( n64_cfg n64_cfg_inst (
.sys(sys), .sys(sys),
.bus(bus.at[sc64::ID_N64_CFG].device), .bus(bus.at[sc64::ID_N64_CFG].device),
.cfg(cfg), .cfg(cfg)
.cpu_ram(cpu_ram)
); );
endmodule endmodule

View File

@ -20,6 +20,10 @@ interface if_config ();
logic [25:0] save_offset; logic [25:0] save_offset;
logic [25:0] isv_offset; logic [25:0] isv_offset;
logic [15:0] isv_rd_ptr; logic [15:0] isv_rd_ptr;
logic flash_erase_start;
logic flash_erase_busy;
logic flash_wp_enable;
logic flash_wp_disable;
modport pi ( modport pi (
input sdram_switch, input sdram_switch,
@ -39,6 +43,13 @@ interface if_config ();
output flashram_read_mode output flashram_read_mode
); );
modport flash (
input flash_erase_start,
output flash_erase_busy,
input flash_wp_enable,
input flash_wp_disable
);
modport n64 ( modport n64 (
input cpu_ready, input cpu_ready,
input cpu_busy, input cpu_busy,
@ -70,7 +81,11 @@ interface if_config ();
output ddipl_offset, output ddipl_offset,
output save_offset, output save_offset,
output isv_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 endinterface

View File

@ -9,31 +9,8 @@ package sc64;
__ID_N64_END __ID_N64_END
} e_n64_id; } 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 bit [31:0] SC64_VER = 32'h53437632;
parameter int CLOCK_FREQUENCY = 32'd100_000_000; 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; parameter int UART_BAUD_RATE = 32'd1_000_000;
`ifdef DEBUG `ifdef DEBUG

View File

@ -1,281 +1,242 @@
module usb_ft1248 ( module usb_ft1248 (
if_system.sys sys, input clk,
input reset,
input usb_enabled,
input tx_force,
output usb_clk, output usb_clk,
output usb_cs, output usb_cs,
input usb_miso, 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, input rx_flush,
output rx_empty, output rx_empty,
output rx_almost_empty,
input rx_read, input rx_read,
output [7:0] rx_rdata, output [7:0] rx_rdata,
input tx_flush, input tx_flush,
output tx_full, output tx_full,
output tx_almost_full,
input tx_write, input tx_write,
input [7:0] tx_wdata, input [7:0] tx_wdata
output rx_escape_valid,
input rx_escape_ack,
output [7:0] rx_escape
); );
parameter bit [7:0] ESCAPE_CHARACTER = 8'h1B;
// FIFOs
logic rx_full; logic rx_full;
logic rx_almost_full;
logic rx_write; logic rx_write;
logic [7:0] rx_wdata;
logic tx_empty; logic tx_empty;
logic tx_almost_empty;
logic tx_read; logic tx_read;
logic [7:0] tx_rdata; logic [7:0] tx_rdata;
logic rx_wdata_valid;
logic rx_escape_active;
intel_fifo_8 fifo_8_rx_inst ( intel_fifo_8 fifo_8_rx_inst (
.clock(sys.clk), .clock(clk),
.sclr(rx_flush || !usb_enabled), .sclr(reset || rx_flush),
.empty(rx_empty), .empty(rx_empty),
.almost_empty(rx_almost_empty),
.rdreq(rx_read), .rdreq(rx_read),
.q(rx_rdata), .q(rx_rdata),
.full(rx_full), .full(rx_full),
.almost_full(rx_almost_full),
.wrreq(rx_write), .wrreq(rx_write),
.data(rx_wdata) .data(usb_miosi)
); );
intel_fifo_8 fifo_8_tx_inst ( intel_fifo_8 fifo_8_tx_inst (
.clock(sys.clk), .clock(clk),
.sclr(tx_flush || !usb_enabled), .sclr(reset || tx_flush),
.empty(tx_empty), .empty(tx_empty),
.almost_empty(tx_almost_empty),
.rdreq(tx_read), .rdreq(tx_read),
.q(tx_rdata), .q(tx_rdata),
.full(tx_full), .full(tx_full),
.almost_full(tx_almost_full),
.wrreq(tx_write), .wrreq(tx_write),
.data(tx_wdata) .data(tx_wdata)
); );
typedef enum bit [2:0] {
// Escape character detection STATE_IDLE,
STATE_SELECT,
always_comb begin STATE_COMMAND,
rx_write = 1'b0; STATE_STATUS,
if (rx_wdata_valid) begin STATE_DATA,
rx_write = rx_escape_active ? rx_wdata == ESCAPE_CHARACTER : rx_wdata != ESCAPE_CHARACTER; STATE_DESELECT
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
} e_state; } e_state;
typedef enum bit [7:0] { typedef enum bit [7:0] {
C_WRITE = 8'h00, CMD_WRITE = 8'h00,
C_READ = 8'h04, CMD_READ = 8'h40,
C_FORCE = 8'h80 CMD_READ_MODEM_STATUS = 8'h20,
CMD_WRITE_MODEM_STATUS = 8'h60,
CMD_WRITE_BUFFER_FLUSH = 8'h08
} e_command; } e_command;
typedef enum bit [1:0] { logic usb_miosi_oe;
P_PRE_RISING, logic write_buffer_flush_pending;
P_RISING, logic write_modem_status_pending;
P_PRE_FALLING, logic [4:0] modem_status_counter;
P_FALLING logic modem_status_read;
} e_clock_phase; logic last_reset_status;
logic reset_reply;
logic [3:0] phase;
logic [7:0] usb_cmd;
e_state state; 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 always_comb begin
usb_miosi = usb_miosi_output_enable ? usb_miosi_output : 4'bZZZZ; 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
end
end
end end
always_comb begin always_ff @(posedge clk) begin
case (state) rx_write <= 1'b0;
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];
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
always_ff @(posedge sys.clk) begin
rx_wdata_valid <= 1'b0;
tx_read <= 1'b0; tx_read <= 1'b0;
modem_status_read <= 1'b0;
phase <= {phase[2:0], phase[3]};
if (clock_phase[P_RISING]) begin if (reset) begin
nibble_counter <= nibble_counter + 1'd1; 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 (write_buffer_flush) begin
write_buffer_flush_pending <= 1'b1;
end end
if (sys.reset || !usb_enabled) begin if (reset_ack) begin
state <= S_TRY_RX; reset_pending <= 1'b0;
tx_force_pending <= 1'b0; write_modem_status_pending <= 1'b1;
end else begin reset_reply <= 1'b1;
if (tx_force) begin end
tx_force_pending <= 1'b1;
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 end
case (state) case (state)
S_TRY_RX: begin STATE_IDLE: begin
if (!rx_full && !rx_escape_valid) begin usb_cs <= 1'b0;
state <= S_COMMAND; state <= STATE_SELECT;
is_cmd_write <= 1'b0; if (write_modem_status_pending) begin
is_cmd_tx_force <= 1'b0; usb_cmd <= CMD_WRITE_MODEM_STATUS;
nibble_counter <= 2'b11; 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 end else begin
state <= S_TRY_TX; usb_cs <= 1'b1;
modem_status_counter <= modem_status_counter + 1'd1;
state <= STATE_IDLE;
end end
end end
S_TRY_TX: begin STATE_SELECT: begin
if (!tx_empty) begin phase <= 4'b0001;
state <= S_COMMAND; state <= STATE_COMMAND;
is_cmd_write <= 1'b1; end
is_cmd_tx_force <= 1'b0;
nibble_counter <= 2'b11; STATE_COMMAND: begin
end else if (tx_force_pending) begin if (phase[0]) begin
state <= S_COMMAND; usb_clk <= 1'b1;
tx_force_pending <= 1'b0; usb_miosi_oe <= 1'b1;
is_cmd_write <= 1'b1; end else if (phase[2]) begin
is_cmd_tx_force <= 1'b1; usb_clk <= 1'b0;
nibble_counter <= 2'b11; end else if (phase[3]) begin
end else begin state <= STATE_STATUS;
state <= S_TRY_RX;
end end
end end
S_COMMAND: begin STATE_STATUS: begin
if (clock_phase[P_RISING]) begin if (phase[0]) begin
if (nibble_counter == 2'd2) begin usb_clk <= 1'b1;
if (usb_miso_input || is_cmd_tx_force) begin usb_miosi_oe <= 1'b0;
state <= is_cmd_write ? S_TRY_RX : S_TRY_TX; end else if (phase[2]) begin
end else begin usb_clk <= 1'b0;
state <= S_DATA; end else if (phase[3]) begin
nibble_counter <= 2'd0; state <= STATE_DATA;
end end
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
end end
S_DATA: begin STATE_DESELECT: begin
if (clock_phase[P_FALLING]) begin usb_cs <= 1'b1;
if (nibble_counter[0]) begin usb_miosi_oe <= 1'b0;
tx_read <= is_cmd_write; if (phase[1]) begin
modem_status_counter <= modem_status_counter + 1'd1;
state <= STATE_IDLE;
end end
end 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 endcase
end end
end end

175
fw/rtl/vendor/vendor_flash.sv vendored Normal file
View 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
View 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

View File

@ -229,9 +229,6 @@ typedef struct {
io32_t SR_CMD; io32_t SR_CMD;
io32_t DATA[2]; io32_t DATA[2];
io32_t VERSION; io32_t VERSION;
io32_t __padding[4092];
io32_t CPU_RAM[3840];
io32_t BUFFER[256];
} sc64_regs_t; } sc64_regs_t;
#define SC64_BASE (0x1FFF0000UL) #define SC64_BASE (0x1FFF0000UL)

View File

@ -83,7 +83,7 @@ void sc64_set_time (rtc_time_t *t) {
} }
static uint32_t sc64_wait_drive_ready (drive_id_t drive) { 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]; uint32_t result[2];
do { do {
sc64_perform_cmd(SC64_CMD_DRIVE_BUSY, args, result); 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) { 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)) { if (sc64_perform_cmd(SC64_CMD_DRIVE_INIT, args, NULL)) {
return true; 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) { 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)) { if (sc64_perform_cmd(write ? SC64_CMD_DRIVE_WRITE : SC64_CMD_DRIVE_READ, args, NULL)) {
return true; 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 current_offset = 0;
uint32_t next_offset = SECTOR_SIZE; 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; return true;
} }
while (count > 0) { while (count > 0) {
@ -124,12 +124,12 @@ bool sc64_storage_read (drive_id_t drive, void *buffer, uint32_t sector, uint32_
return true; return true;
} }
if (count > 1) { 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; return true;
} }
next_offset = next_offset ? 0 : SECTOR_SIZE; 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++) { for (int i = 0; i < (SECTOR_SIZE / sizeof(uint32_t)); i++) {
uint32_t data = pi_io_read(src + i); uint32_t data = pi_io_read(src + i);
*dst++ = ((data >> 24) & 0xFF); *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) { bool sc64_storage_write (drive_id_t drive, const void *buffer, uint32_t sector, uint32_t count) {
uint8_t *src = (uint8_t *) (buffer); uint8_t *src = (uint8_t *) (buffer);
io32_t *dst = SC64->BUFFER; io32_t *dst = (io32_t *) (0x13FF0000UL);
while (count > 0) { while (count > 0) {
for (int i = 0; i < (SECTOR_SIZE / sizeof(uint32_t)); i++) { 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); data |= ((*src++) << 0);
pi_io_write((dst + i), data); 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; return true;
} }
if (sc64_wait_drive_ready(drive)) { if (sc64_wait_drive_ready(drive)) {

View File

@ -1,7 +1,8 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
from datetime import datetime 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 io import TextIOWrapper
from typing import Union from typing import Union
import argparse import argparse
@ -9,7 +10,6 @@ import filecmp
import helpers import helpers
import os import os
import progressbar import progressbar
import re
import struct import struct
import sys import sys
import time import time
@ -50,8 +50,6 @@ class SC64:
__DEBUG_ID_TEXT = 0x01 __DEBUG_ID_TEXT = 0x01
__EVENT_ID_FSD_READ = 0xF0 __EVENT_ID_FSD_READ = 0xF0
__EVENT_ID_FSD_WRITE = 0xF1 __EVENT_ID_FSD_WRITE = 0xF1
__EVENT_ID_FSD_LOAD = 0xF2
__EVENT_ID_FSD_STORE = 0xF3
__EVENT_ID_DD_BLOCK = 0xF4 __EVENT_ID_DD_BLOCK = 0xF4
__EVENT_ID_IS_VIEWER = 0xF5 __EVENT_ID_IS_VIEWER = 0xF5
@ -76,7 +74,6 @@ class SC64:
def __del__(self) -> None: def __del__(self) -> None:
if (self.__usb): if (self.__usb):
self.__reset_n64("release")
self.__usb.close() self.__usb.close()
if (self.__fsd_file): if (self.__fsd_file):
self.__fsd_file.close() self.__fsd_file.close()
@ -101,14 +98,15 @@ class SC64:
return (value + (align - 1)) & ~(align - 1) 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: def reset_link(self) -> None:
self.__usb.write(b"\x1BR") if (self.__usb):
time.sleep(0.1) self.__usb.flush()
self.__usb.flushInput() 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: def __read(self, bytes: int) -> bytes:
@ -116,7 +114,7 @@ class SC64:
def __write(self, data: bytes) -> None: def __write(self, data: bytes) -> None:
self.__usb.write(self.__escape(data)) self.__usb.write(data)
def __read_long(self, length: int) -> bytes: def __read_long(self, length: int) -> bytes:
@ -151,29 +149,28 @@ class SC64:
self.__write_int(arg2) 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: 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() self.__usb.close()
for p in ports:
if (p.vid == 0x0403 and p.pid == 0x6014 and p.serial_number.startswith("SC")):
try: try:
self.__usb = Ft232(description="SummerCart64") self.__usb = Serial(p.device, timeout=0.5, write_timeout=0.5)
self.__reset_n64("hold")
self.__usb.flushOutput()
self.reset_link() self.reset_link()
self.__probe_device() self.__probe_device()
except Ft232Exception as e: except (SerialException, SC64Exception):
if (self.__usb): if (self.__usb):
self.__usb.close() self.__usb.close()
raise SC64Exception(f"No SummerCart64 device was found: {e}") continue
device_found = True
break
if (not device_found):
raise SC64Exception("No SummerCart64 device was found")
def __probe_device(self) -> None: def __probe_device(self) -> None:
@ -197,25 +194,22 @@ class SC64:
self.__read_cmd_status("C") 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: with open(file, "wb") as f:
transfer_size = self.__align(length, align) self.__set_progress_init(length, os.path.basename(f.name))
self.__set_progress_init(transfer_size, os.path.basename(f.name)) self.__write_cmd("R", offset, length)
self.__write_cmd("R", offset, transfer_size)
while (f.tell() < length): while (f.tell() < length):
chunk_size = min(self.__CHUNK_SIZE, length - f.tell()) chunk_size = min(self.__CHUNK_SIZE, length - f.tell())
f.write(self.__read(chunk_size)) f.write(self.__read(chunk_size))
self.__set_progress_value(f.tell()) self.__set_progress_value(f.tell())
if (transfer_size != length):
self.__read(transfer_size - length)
self.__read_cmd_status("R") self.__read_cmd_status("R")
self.__set_progress_finish() 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: with open(file, "rb") as f:
length = os.fstat(f.fileno()).st_size 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.__set_progress_init(transfer_size, os.path.basename(f.name))
self.__write_cmd("W", offset, transfer_size) self.__write_cmd("W", offset, transfer_size)
while (f.tell() < length): while (f.tell() < length):
@ -243,7 +237,7 @@ class SC64:
def __reconfigure(self) -> None: def __reconfigure(self) -> None:
magic = self.__query_config(self.__CFG_ID_RECONFIGURE) magic = self.__query_config(self.__CFG_ID_RECONFIGURE)
self.__change_config(self.__CFG_ID_RECONFIGURE, magic, ignore_response=True) 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: 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.__change_config(self.__CFG_ID_FLASH_PROGRAM, self.__UPDATE_OFFSET)
self.__usb.timeout = saved_timeout self.__usb.timeout = saved_timeout
self.__reconfigure() self.__reconfigure()
self.__find_sc64()
def set_rtc(self, t: datetime) -> None: def set_rtc(self, t: datetime) -> None:
@ -544,7 +537,7 @@ class SC64:
data += struct.pack(">I", offset) data += struct.pack(">I", offset)
self.__disk_lba_table[lba] = offset self.__disk_lba_table[lba] = offset
self.__write_cmd("W", thb_table_offset, len(data)) self.__write_cmd("W", thb_table_offset, len(data))
self.__write(data) self.__write(bytes(data))
self.__read_cmd_status("W") self.__read_cmd_status("W")
id_mapping = { id_mapping = {
"retail": self.__DD_DRIVE_ID_RETAIL, "retail": self.__DD_DRIVE_ID_RETAIL,
@ -561,26 +554,28 @@ class SC64:
def __debug_process_fsd_read(self, data: bytes) -> None: def __debug_process_fsd_read(self, data: bytes) -> None:
sector = int.from_bytes(data[0:4], byteorder="little") sector = int.from_bytes(data[0:4], byteorder="little")
offset = int.from_bytes(data[4:8], byteorder="little") offset = int.from_bytes(data[4:8], byteorder="little")
count = int.from_bytes(data[8:12], byteorder="little")
if (self.__fsd_file): if (self.__fsd_file):
self.__fsd_file.seek(sector * 512) self.__fsd_file.seek(sector * 512)
self.__write_cmd("T", offset, 512) self.__write_cmd("S", offset, count * 512)
self.__write(self.__fsd_file.read(512)) self.__write(self.__fsd_file.read(count * 512))
else: else:
self.__write_cmd("T", offset, 0) self.__write_cmd("S", offset, 0)
def __debug_process_fsd_write(self, data: bytes) -> None: def __debug_process_fsd_write(self, data: bytes) -> None:
sector = int.from_bytes(data[0:4], byteorder="little") sector = int.from_bytes(data[0:4], byteorder="little")
offset = int.from_bytes(data[4:8], byteorder="little") offset = int.from_bytes(data[4:8], byteorder="little")
count = int.from_bytes(data[8:12], byteorder="little")
if (self.__fsd_file): if (self.__fsd_file):
with helpers.lock_volume(self.__fsd_file): with helpers.lock_volume(self.__fsd_file):
self.__fsd_file.seek(sector * 512) self.__fsd_file.seek(sector * 512)
self.__write_cmd("F", offset, 512) self.__write_cmd("L", offset, count * 512)
self.__fsd_file.write(self.__read(512)) self.__fsd_file.write(self.__read(count * 512))
else: else:
self.__write_cmd("F", offset, 0) self.__write_cmd("L", offset, 0)
def __debug_process_dd_block(self, data: bytes) -> None: 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") sdram_offset = int.from_bytes(data[4:8], byteorder="little")
disk_file_offset = int.from_bytes(data[8:12], byteorder="big") disk_file_offset = int.from_bytes(data[8:12], byteorder="big")
block_length = int.from_bytes(data[12:16], byteorder="little") block_length = int.from_bytes(data[12:16], byteorder="little")
print(f"DD BLOCK {disk_file_offset:08X} {block_length}")
if (self.__disk_file): if (self.__disk_file):
self.__disk_file.seek(disk_file_offset) self.__disk_file.seek(disk_file_offset)
if (transfer_mode): if (transfer_mode):
@ -605,10 +600,8 @@ class SC64:
def __debug_process_is_viewer(self, data: bytes) -> None: def __debug_process_is_viewer(self, data: bytes) -> None:
length = int.from_bytes(data[0:4], byteorder="little") length = int.from_bytes(data[0:4], byteorder="little")
address = int.from_bytes(data[4:8], byteorder="little") address = int.from_bytes(data[4:8], byteorder="little")
offset = (address & 0x01) self.__write_cmd("L", address, length)
transfer_length = self.__align(length + offset, 2) text = self.__read(length)
self.__write_cmd("L", (address & 0xFFFFFFFE), transfer_length)
text = self.__read(transfer_length)[offset:][:length]
print(text.decode("EUC-JP", errors="backslashreplace"), end="") 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") print("\r\n\033[34m --- Debug server started --- \033[0m\r\n")
self.__usb.setTimeout(0.1)
start_indicator = bytearray() start_indicator = bytearray()
dropped_bytes = 0 dropped_bytes = 0
self.__reset_n64("release")
while (True): while (True):
while (start_indicator != b"DMA@"): while (start_indicator != b"DMA@"):
start_indicator.append(self.__read_long(1)[0]) start_indicator.append(self.__read_long(1)[0])
@ -752,6 +741,8 @@ if __name__ == "__main__":
args = parser.parse_args() args = parser.parse_args()
sc64 = None
try: try:
sc64 = SC64() sc64 = SC64()
@ -855,7 +846,6 @@ if __name__ == "__main__":
pass pass
finally: finally:
if (sc64): if (sc64):
sc64.reset_link()
if (disk_file): if (disk_file):
print(f"Setting 64DD disk state to [Ejected]") print(f"Setting 64DD disk state to [Ejected]")
sc64.set_dd_disk_state("ejected") sc64.set_dd_disk_state("ejected")

View File

@ -6,7 +6,7 @@ OBJDUMP = $(TOOLCHAIN)objdump
SIZE = $(TOOLCHAIN)size SIZE = $(TOOLCHAIN)size
FLAGS = -mabi=ilp32 -march=rv32i $(USER_FLAGS) 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 LDFLAGS = -nostartfiles -Wl,--gc-sections
SRC_DIR = src SRC_DIR = src
@ -17,7 +17,6 @@ SRC_FILES = \
process.c \ process.c \
usb.c \ usb.c \
cfg.c \ cfg.c \
dma.c \
joybus.c \ joybus.c \
rtc.c \ rtc.c \
i2c.c \ i2c.c \
@ -46,7 +45,7 @@ $(BUILD_DIR)/governor.elf: $(OBJS) SC64.ld
@$(OBJDUMP) -D $@ > $(BUILD_DIR)/governor.lst @$(OBJDUMP) -D $@ > $(BUILD_DIR)/governor.lst
$(BUILD_DIR)/governor.bin: $(BUILD_DIR)/governor.elf $(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 $(BUILD_DIR)/governor.hex: $(BUILD_DIR)/governor.bin
@$(OBJCOPY) -I binary -O ihex $< $@ @$(OBJCOPY) -I binary -O ihex $< $@

View File

@ -1,7 +1,6 @@
MEMORY { MEMORY {
ram (rwx) : org = 0x00000000, len = 15k rom (rx) : org = 0x00010000, len = 26k
buffer (rw) : org = 0x00003C00, len = 1k ram (rwx) : org = 0x10000000, len = 32k
rom (rx) : org = 0x10010000, len = 26k
} }
ENTRY(reset_handler) ENTRY(reset_handler)
@ -45,10 +44,6 @@ SECTIONS {
_ebss = .; _ebss = .;
} > ram } > ram
.buffer : {
*(.buffer)
} > buffer
__global_pointer$ = MIN(_ssdata + 0x800, MAX(_sdata + 0x800, _ebss - 0x800)); __global_pointer$ = MIN(_ssdata + 0x800, MAX(_sdata + 0x800, _ebss - 0x800));
__stack_pointer$ = ORIGIN(ram) + LENGTH(ram); __stack_pointer$ = ORIGIN(ram) + LENGTH(ram);
} }

View File

@ -311,9 +311,7 @@ void process_cfg (void) {
break; break;
case 0xF0: case 0xF0:
if (args[0] == 0) { if (args[0] & (1 << 31)) {
change_scr_bits(CFG_SCR_CMD_ERROR, true);
} else if (args[0] == 1) {
p.usb_drive_busy = false; p.usb_drive_busy = false;
} else { } else {
change_scr_bits(CFG_SCR_CMD_ERROR, true); change_scr_bits(CFG_SCR_CMD_ERROR, true);
@ -321,10 +319,7 @@ void process_cfg (void) {
break; break;
case 0xF1: case 0xF1:
if (args[0] == 0) { if (args[0] & (1 << 31)) {
args[0] = 0;
change_scr_bits(CFG_SCR_CMD_ERROR, true);
} else if (args[0] == 1) {
args[0] = p.usb_drive_busy; args[0] = p.usb_drive_busy;
} else { } else {
args[0] = 0; args[0] = 0;
@ -334,14 +329,13 @@ void process_cfg (void) {
break; break;
case 0xF2: case 0xF2:
if ((args[0] & 0xFF) == 0) { if (args[0] & (1 << 31)) {
change_scr_bits(CFG_SCR_CMD_ERROR, true); if (!p.usb_drive_busy) {
} else if ((args[0] & 0xFF) == 1 && (!p.usb_drive_busy)) {
usb_event_t event; usb_event_t event;
event.id = EVENT_ID_FSD_READ; event.id = EVENT_ID_FSD_READ;
event.trigger = CALLBACK_BUFFER_WRITE; event.trigger = CALLBACK_SDRAM_WRITE;
event.callback = set_usb_drive_not_busy; event.callback = set_usb_drive_not_busy;
uint32_t data[2] = { args[1], (args[0] >> 8) }; uint32_t data[3] = { args[1], (args[0] & 0x7FFFFFFF), 1 };
if (usb_put_event(&event, data, sizeof(data))) { if (usb_put_event(&event, data, sizeof(data))) {
p.usb_drive_busy = true; p.usb_drive_busy = true;
} else { } else {
@ -350,17 +344,19 @@ void process_cfg (void) {
} else { } else {
change_scr_bits(CFG_SCR_CMD_ERROR, true); change_scr_bits(CFG_SCR_CMD_ERROR, true);
} }
} else {
change_scr_bits(CFG_SCR_CMD_ERROR, true);
}
break; break;
case 0xF3: case 0xF3:
if ((args[0] & 0xFF) == 0) { if (args[0] & (1 << 31)) {
change_scr_bits(CFG_SCR_CMD_ERROR, true); if (!p.usb_drive_busy) {
} else if ((args[0] & 0xFF) == 1 && (!p.usb_drive_busy)) {
usb_event_t event; usb_event_t event;
event.id = EVENT_ID_FSD_WRITE; event.id = EVENT_ID_FSD_WRITE;
event.trigger = CALLBACK_BUFFER_READ; event.trigger = CALLBACK_SDRAM_READ;
event.callback = set_usb_drive_not_busy; event.callback = set_usb_drive_not_busy;
uint32_t data[2] = { args[1], (args[0] >> 8) }; uint32_t data[3] = { args[1], (args[0] & 0x7FFFFFFF), 1 };
if (usb_put_event(&event, data, sizeof(data))) { if (usb_put_event(&event, data, sizeof(data))) {
p.usb_drive_busy = true; p.usb_drive_busy = true;
} else { } else {
@ -369,6 +365,9 @@ void process_cfg (void) {
} else { } else {
change_scr_bits(CFG_SCR_CMD_ERROR, true); change_scr_bits(CFG_SCR_CMD_ERROR, true);
} }
} else {
change_scr_bits(CFG_SCR_CMD_ERROR, true);
}
break; break;
case 0xFF: case 0xFF:

View File

@ -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();
}

View File

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

View File

@ -1,6 +1,9 @@
#include "flash.h" #include "flash.h"
static io32_t dummy;
uint32_t flash_size (void) { uint32_t flash_size (void) {
return FLASH_SIZE; return FLASH_SIZE;
} }
@ -9,54 +12,30 @@ void flash_read (uint32_t sdram_offset) {
io32_t *flash = (io32_t *) (FLASH_BASE); io32_t *flash = (io32_t *) (FLASH_BASE);
io32_t *sdram = (io32_t *) (SDRAM_BASE + sdram_offset); 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++; *sdram++ = *flash++;
} }
} }
void flash_program (uint32_t sdram_offset) { void flash_program (uint32_t sdram_offset) {
uint32_t cr;
io32_t *flash = (io32_t *) (FLASH_BASE); io32_t *flash = (io32_t *) (FLASH_BASE);
io32_t *sdram = (io32_t *) (SDRAM_BASE + sdram_offset); io32_t *sdram = (io32_t *) (SDRAM_BASE + sdram_offset);
cr = FLASH_CONFIG->CR; CFG->SCR |= CFG_SCR_FLASH_WP_DISABLE;
for (size_t sector = 0; sector < FLASH_NUM_SECTORS; sector++) {
cr &= ~(1 << (FLASH_CR_WRITE_PROTECT_BIT + sector));
}
FLASH_CONFIG->CR = cr;
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++) { while (CFG->SCR & CFG_SCR_FLASH_ERASE_BUSY);
cr = FLASH_CONFIG->CR;
cr &= ~(FLASH_CR_SECTOR_ERASE_MASK);
cr |= ((sector + 1) << FLASH_CR_SECTOR_ERASE_BIT);
FLASH_CONFIG->CR = cr;
while ((FLASH_CONFIG->SR & FLASH_SR_STATUS_MASK) == FLASH_SR_STATUS_BUSY_ERASE); for (int i = 0; i < FLASH_SIZE; i += sizeof(io32_t)) {
if (!(FLASH_CONFIG->SR & FLASH_SR_ERASE_SUCCESSFUL)) {
break;
}
}
if (FLASH_CONFIG->SR & FLASH_SR_ERASE_SUCCESSFUL) {
for (size_t word = 0; word < FLASH_SIZE; word += 4) {
*flash++ = *sdram++; *flash++ = *sdram++;
if (!(FLASH_CONFIG->SR & FLASH_SR_WRITE_SUCCESSFUL)) {
break;
}
}
} }
cr = FLASH_CONFIG->CR; CFG->SCR |= CFG_SCR_FLASH_WP_ENABLE;
cr |= FLASH_CR_SECTOR_ERASE_MASK;
for (size_t sector = 0; sector < FLASH_NUM_SECTORS; sector++) { flash = (io32_t *) (FLASH_BASE);
cr |= (1 << (FLASH_CR_WRITE_PROTECT_BIT + sector));
} dummy = *flash;
FLASH_CONFIG->CR = cr;
return; return;
} }

View File

@ -5,7 +5,7 @@
#include "sys.h" #include "sys.h"
uint32_t flash_size(void); uint32_t flash_size (void);
void flash_read (uint32_t sdram_offset); void flash_read (uint32_t sdram_offset);
void flash_program (uint32_t sdram_offset); void flash_program (uint32_t sdram_offset);

View File

@ -1,7 +1,6 @@
#include "process.h" #include "process.h"
#include "usb.h" #include "usb.h"
#include "cfg.h" #include "cfg.h"
#include "dma.h"
#include "joybus.h" #include "joybus.h"
#include "rtc.h" #include "rtc.h"
#include "i2c.h" #include "i2c.h"
@ -29,7 +28,6 @@ __attribute__((naked)) void process_loop (void) {
usb_init(); usb_init();
cfg_init(); cfg_init();
dma_init();
joybus_init(); joybus_init();
rtc_init(); rtc_init();
i2c_init(); i2c_init();

View File

@ -21,54 +21,48 @@ typedef volatile uint16_t io16_t;
typedef volatile uint32_t io32_t; typedef volatile uint32_t io32_t;
#define RAM_BASE (0x00000000UL) #define FLASH_BASE (0x00000000UL)
#define RAMBUFFER_SIZE (1024) #define FLASH_SIZE (0x39800)
#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 (*((io32_t *) FLASH_BASE)) #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 { typedef volatile struct cfg_regs {
io32_t SR; io32_t SCR;
io32_t CR; io32_t DDIPL_OFFSET;
} flash_config_regs_t; 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 CFG_BASE (0x20000000UL)
#define FLASH_CONFIG ((flash_config_regs_t *) FLASH_CONFIG_BASE) #define CFG ((cfg_regs_t *) CFG_BASE)
#define FLASH_SR_STATUS_MASK (3 << 0) #define CFG_SCR_SDRAM_SWITCH (1 << 0)
#define FLASH_SR_STATUS_IDLE (0) #define CFG_SCR_SDRAM_WRITABLE (1 << 1)
#define FLASH_SR_STATUS_BUSY_ERASE (1) #define CFG_SCR_DD_EN (1 << 2)
#define FLASH_SR_STATUS_BUSY_WRITE (2) #define CFG_SCR_SRAM_EN (1 << 3)
#define FLASH_SR_STATUS_BUSY_READ (3) #define CFG_SCR_SRAM_BANKED (1 << 4)
#define FLASH_SR_READ_SUCCESSFUL (1 << 2) #define CFG_SCR_FLASHRAM_EN (1 << 5)
#define FLASH_SR_WRITE_SUCCESSFUL (1 << 3) #define CFG_SCR_SKIP_BOOTLOADER (1 << 6)
#define FLASH_SR_ERASE_SUCCESSFUL (1 << 4) #define CFG_SCR_ISV_EN (1 << 7)
#define FLASH_SR_WRITE_PROTECT_BIT (5) #define CFG_SCR_FLASH_ERASE_START (1 << 24)
#define CFG_SCR_FLASH_ERASE_BUSY (1 << 25)
#define FLASH_CR_PAGE_ERASE_BIT (0) #define CFG_SCR_FLASH_WP_ENABLE (1 << 26)
#define FLASH_CR_SECTOR_ERASE_BIT (20) #define CFG_SCR_FLASH_WP_DISABLE (1 << 27)
#define FLASH_CR_SECTOR_ERASE_MASK (7 << FLASH_CR_SECTOR_ERASE_BIT) #define CFG_SCR_CMD_ERROR (1 << 28)
#define FLASH_CR_WRITE_PROTECT_BIT (23) #define CFG_SCR_CPU_BUSY (1 << 30)
#define CFG_SCR_CPU_READY (1 << 31)
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)
typedef volatile struct i2c_regs { typedef volatile struct i2c_regs {
@ -90,8 +84,8 @@ typedef volatile struct usb_regs {
io32_t SCR; io32_t SCR;
io8_t DR; io8_t DR;
io8_t __padding_1[3]; io8_t __padding_1[3];
io8_t ESCAPE; io32_t ADDR;
io8_t __padding_2[3]; io32_t LEN;
} usb_regs_t; } usb_regs_t;
#define USB_BASE (0x40000000UL) #define USB_BASE (0x40000000UL)
@ -101,11 +95,14 @@ typedef volatile struct usb_regs {
#define USB_SCR_TXE (1 << 1) #define USB_SCR_TXE (1 << 1)
#define USB_SCR_FLUSH_RX (1 << 2) #define USB_SCR_FLUSH_RX (1 << 2)
#define USB_SCR_FLUSH_TX (1 << 3) #define USB_SCR_FLUSH_TX (1 << 3)
#define USB_SCR_ENABLED (1 << 4) #define USB_SCR_ENABLE (1 << 4)
#define USB_SCR_PWREN (1 << 5) #define USB_SCR_FORCE_TX (1 << 5)
#define USB_SCR_ESCAPE_PENDING (1 << 6) #define USB_SCR_RESET_PENDING (1 << 6)
#define USB_SCR_ESCAPE_ACK (1 << 7) #define USB_SCR_RESET_ACK (1 << 7)
#define USB_SCR_FORCE_TX (1 << 8) #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 { typedef volatile struct uart_regs {
@ -121,91 +118,6 @@ typedef volatile struct uart_regs {
#define UART_SCR_TXE (1 << 1) #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 { typedef volatile struct dd_regs {
io32_t SCR; io32_t SCR;
io16_t DATA; io16_t DATA;
@ -224,7 +136,7 @@ typedef volatile struct dd_regs {
io32_t SECTOR_BUFFER[64]; io32_t SECTOR_BUFFER[64];
} dd_regs_t; } dd_regs_t;
#define DD_BASE (0xB0000000UL) #define DD_BASE (0x60000000UL)
#define DD ((dd_regs_t *) DD_BASE) #define DD ((dd_regs_t *) DD_BASE)
#define DD_SCR_HARD_RESET (1 << 0) #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 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); void reset_handler(void);

View File

@ -1,5 +1,4 @@
#include "usb.h" #include "usb.h"
#include "dma.h"
#include "cfg.h" #include "cfg.h"
#include "dd.h" #include "dd.h"
@ -140,24 +139,12 @@ static bool rx_cmd (uint32_t *data) {
return false; 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) { 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.state = STATE_IDLE;
p.dma_in_progress = false;
p.event_pending = false; p.event_pending = false;
p.event_callback_pending = false; p.event_callback_pending = false;
@ -170,7 +157,11 @@ void usb_init (void) {
void process_usb (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) { switch (p.state) {
case STATE_IDLE: case STATE_IDLE:
@ -247,11 +238,15 @@ void process_usb (void) {
case 'W': case 'W':
case 'L': case 'L':
case 'S': case 'S':
if (!dma_busy()) { if (!(USB->SCR & USB_SCR_DMA_BUSY)) {
if (!p.dma_in_progress) { if (!p.dma_in_progress) {
bool is_write = (p.cmd == 'W') || (p.cmd == 'S'); USB->ADDR = p.args[0];
enum dma_dir dir = is_write ? DMA_DIR_TO_SDRAM : DMA_DIR_FROM_SDRAM; USB->LEN = p.args[1];
dma_start(p.args[0], p.args[1], DMA_ID_USB, dir); 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; p.dma_in_progress = true;
} else { } else {
if (p.cmd == 'L' || p.cmd == 'S') { if (p.cmd == 'L' || p.cmd == 'S') {
@ -276,43 +271,6 @@ void process_usb (void) {
} }
break; 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: default:
p.error = true; p.error = true;
p.state = STATE_RESPONSE; p.state = STATE_RESPONSE;

View File

@ -18,8 +18,6 @@ typedef enum {
CALLBACK_NONE = 0, CALLBACK_NONE = 0,
CALLBACK_SDRAM_WRITE = 1, CALLBACK_SDRAM_WRITE = 1,
CALLBACK_SDRAM_READ = 2, CALLBACK_SDRAM_READ = 2,
CALLBACK_BUFFER_WRITE = 3,
CALLBACK_BUFFER_READ = 4,
} usb_event_callback_t; } usb_event_callback_t;
typedef struct { typedef struct {