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
if [ "$SKIP_FPGA_REBUILD" = true ] && [ -f output_files/SummerCart64.sof ]; then
echo Skipping FPGA build
quartus_cpf -c SummerCart64.cof
else
if [ "$DEBUG_ENABLED" = true ]; then
quartus_sh --set VERILOG_MACRO="DEBUG" ./SummerCart64.qpf

View File

@ -19,7 +19,7 @@
#
# Quartus Prime
# Version 21.1.0 Build 842 10/21/2021 SJ Lite Edition
# Date created = 13:29:40 November 11, 2021
# Date created = 19:00:58 February 02, 2022
#
# -------------------------------------------------------------------------- #
#
@ -46,6 +46,7 @@ set_global_assignment -name LAST_QUARTUS_VERSION "21.1.0 Lite Edition"
set_global_assignment -name PROJECT_OUTPUT_DIRECTORY output_files
set_global_assignment -name NUM_PARALLEL_PROCESSORS ALL
set_global_assignment -name FLOW_ENABLE_POWER_ANALYZER ON
set_global_assignment -name POST_MODULE_SCRIPT_FILE "quartus_sh:scripts/post_module.tcl"
set_global_assignment -name QSYS_FILE rtl/intel/flash/intel_flash.qsys
set_global_assignment -name QIP_FILE rtl/intel/fifo/intel_fifo_8.qip
set_global_assignment -name QIP_FILE rtl/intel/gpio/intel_gpio_ddro.qip
@ -55,10 +56,8 @@ set_global_assignment -name SYSTEMVERILOG_FILE picorv32/picorv32.v
set_global_assignment -name SYSTEMVERILOG_FILE rtl/cpu/cpu_bus.sv
set_global_assignment -name SYSTEMVERILOG_FILE rtl/cpu/cpu_cfg.sv
set_global_assignment -name SYSTEMVERILOG_FILE rtl/cpu/cpu_dd.sv
set_global_assignment -name SYSTEMVERILOG_FILE rtl/cpu/cpu_dma.sv
set_global_assignment -name SYSTEMVERILOG_FILE rtl/cpu/cpu_flash.sv
set_global_assignment -name SYSTEMVERILOG_FILE rtl/cpu/cpu_flashram.sv
set_global_assignment -name SYSTEMVERILOG_FILE rtl/cpu/cpu_gpio.sv
set_global_assignment -name SYSTEMVERILOG_FILE rtl/cpu/cpu_i2c.sv
set_global_assignment -name SYSTEMVERILOG_FILE rtl/cpu/cpu_ram.sv
set_global_assignment -name SYSTEMVERILOG_FILE rtl/cpu/cpu_sdram.sv
@ -67,6 +66,7 @@ set_global_assignment -name SYSTEMVERILOG_FILE rtl/cpu/cpu_soc.sv
set_global_assignment -name SYSTEMVERILOG_FILE rtl/cpu/cpu_uart.sv
set_global_assignment -name SYSTEMVERILOG_FILE rtl/cpu/cpu_usb.sv
set_global_assignment -name SYSTEMVERILOG_FILE rtl/cpu/cpu_wrapper.sv
set_global_assignment -name SYSTEMVERILOG_FILE rtl/memory/memory_dma.sv
set_global_assignment -name SYSTEMVERILOG_FILE rtl/memory/memory_sdram.sv
set_global_assignment -name SYSTEMVERILOG_FILE rtl/n64/n64_bootloader.sv
set_global_assignment -name SYSTEMVERILOG_FILE rtl/n64/n64_bus.sv
@ -83,7 +83,8 @@ set_global_assignment -name SYSTEMVERILOG_FILE rtl/system/config.sv
set_global_assignment -name SYSTEMVERILOG_FILE rtl/system/sc64.sv
set_global_assignment -name SYSTEMVERILOG_FILE rtl/system/system.sv
set_global_assignment -name SYSTEMVERILOG_FILE rtl/usb/usb_ft1248.sv
set_global_assignment -name POST_MODULE_SCRIPT_FILE "quartus_sh:scripts/post_module.tcl"
set_global_assignment -name SYSTEMVERILOG_FILE rtl/vendor/vendor_flash.sv
set_global_assignment -name SYSTEMVERILOG_FILE rtl/vendor/vendor_reconfigure.sv
# Pin & Location Assignments
# ==========================
@ -164,8 +165,11 @@ set_location_assignment PIN_114 -to o_sd_clk
set_location_assignment PIN_118 -to io_sd_cmd
set_location_assignment PIN_119 -to io_sd_dat[3]
set_location_assignment PIN_120 -to io_sd_dat[2]
set_location_assignment PIN_121 -to io_usb_miosi[5]
set_location_assignment PIN_122 -to io_usb_miosi[7]
set_location_assignment PIN_123 -to o_n64_irq
set_location_assignment PIN_138 -to i_usb_pwren
set_location_assignment PIN_124 -to io_usb_miosi[6]
set_location_assignment PIN_126 -to io_usb_miosi[4]
set_location_assignment PIN_140 -to o_usb_cs
set_location_assignment PIN_141 -to i_usb_miso
@ -191,6 +195,7 @@ set_global_assignment -name VHDL_SHOW_LMF_MAPPING_MESSAGES OFF
set_global_assignment -name VERILOG_INPUT_VERSION SYSTEMVERILOG_2005
set_global_assignment -name VERILOG_SHOW_LMF_MAPPING_MESSAGES OFF
set_global_assignment -name TOP_LEVEL_ENTITY SummerCart64
set_global_assignment -name VERILOG_MACRO DEBUG
# Fitter Assignments
# ==================
@ -200,7 +205,7 @@ set_global_assignment -name ENABLE_CONFIGURATION_PINS OFF
set_global_assignment -name ENABLE_BOOT_SEL_PIN OFF
set_global_assignment -name INTERNAL_FLASH_UPDATE_MODE "SINGLE COMP IMAGE"
set_global_assignment -name CRC_ERROR_OPEN_DRAIN OFF
set_global_assignment -name STRATIX_DEVICE_IO_STANDARD "3.3-V LVTTL"
set_global_assignment -name STRATIX_DEVICE_IO_STANDARD "3.0-V LVTTL"
# Assembler Assignments
# =====================
@ -226,10 +231,8 @@ set_global_assignment -name OUTPUT_IO_TIMING_FAR_END_VMEAS "HALF SIGNAL SWING" -
# Pin & Location Assignments
# ==========================
set_instance_assignment -name FAST_INPUT_REGISTER ON -to io_usb_miosi[*]
set_instance_assignment -name FAST_INPUT_REGISTER ON -to i_uart_rxd
set_instance_assignment -name FAST_INPUT_REGISTER ON -to io_rtc_sda
set_instance_assignment -name FAST_INPUT_REGISTER ON -to io_n64_si_dq
set_instance_assignment -name FAST_INPUT_REGISTER ON -to i_n64_nmi
set_instance_assignment -name FAST_INPUT_REGISTER ON -to i_n64_reset
set_instance_assignment -name FAST_INPUT_REGISTER ON -to i_n64_si_clk
@ -239,25 +242,19 @@ set_global_assignment -name OUTPUT_IO_TIMING_FAR_END_VMEAS "HALF SIGNAL SWING" -
set_instance_assignment -name FAST_INPUT_REGISTER ON -to i_n64_pi_write
set_instance_assignment -name FAST_INPUT_REGISTER ON -to i_n64_pi_alel
set_instance_assignment -name FAST_INPUT_REGISTER ON -to io_sdram_dq[*]
set_instance_assignment -name FAST_INPUT_REGISTER ON -to io_sd_*
set_instance_assignment -name FAST_INPUT_REGISTER ON -to i_usb_pwren
set_instance_assignment -name FAST_INPUT_REGISTER ON -to i_usb_miso
set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to o_usb_clk
set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to io_usb_miosi[*]
set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to o_uart_txd
set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to o_rtc_scl
set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to io_rtc_sda
set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to io_n64_pi_ad[*]
set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to o_sdram_*
set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to o_sdram_cs
set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to o_sdram_ras
set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to o_sdram_cas
set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to o_sdram_we
set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to o_sdram_a[*]
set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to o_sdram_ba[*]
set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to io_sdram_dq[*]
set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to o_sd_clk
set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to io_sd_*
set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to o_usb_cs
set_instance_assignment -name FAST_OUTPUT_ENABLE_REGISTER ON -to io_usb_miosi[*]
set_instance_assignment -name FAST_OUTPUT_ENABLE_REGISTER ON -to io_n64_pi_ad[*]
set_instance_assignment -name FAST_OUTPUT_ENABLE_REGISTER ON -to io_sdram_dq[*]
set_instance_assignment -name FAST_OUTPUT_ENABLE_REGISTER ON -to io_sd_*
set_instance_assignment -name FAST_OUTPUT_ENABLE_REGISTER ON -to io_rtc_sda
# Fitter Assignments
# ==================
@ -272,7 +269,6 @@ set_global_assignment -name OUTPUT_IO_TIMING_FAR_END_VMEAS "HALF SIGNAL SWING" -
set_instance_assignment -name WEAK_PULL_UP_RESISTOR ON -to i_n64_pi_write
set_instance_assignment -name WEAK_PULL_UP_RESISTOR ON -to i_n64_pi_alel
set_instance_assignment -name WEAK_PULL_UP_RESISTOR ON -to o_n64_irq
set_instance_assignment -name WEAK_PULL_UP_RESISTOR ON -to i_usb_pwren
set_instance_assignment -name WEAK_PULL_UP_RESISTOR ON -to i_usb_miso
# start DESIGN_PARTITION(Top)

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}
create_generated_clock -name sdram_clk -source [get_pins $sdram_pll_clk] [get_ports {o_sdram_clk}]
create_clock -name usb_clk -period 40.0 [get_ports {o_usb_clk}]
# create_generated_clock -name sd_reg_clk -source [get_pins {sd_interface_inst|sd_clk_inst|o_sd_clk|clk}] -divide_by 2 [get_pins $sd_reg_clk]
# create_generated_clock -name sd_clk -source [get_pins $sd_reg_clk] [get_ports {o_sd_clk}]
create_generated_clock -name flash_se_neg_reg \
-source [get_pins -compatibility_mode {*altera_onchip_flash:*onchip_flash_0|altera_onchip_flash_avmm_data_controller:avmm_data_controller|flash_se_neg_reg|clk}] \
-divide_by 2 \
@ -30,6 +30,7 @@ set_input_delay -clock [get_clocks {sdram_clk}] -max 5.4 [get_ports $sdram_input
set_input_delay -clock [get_clocks {sdram_clk}] -min 2.5 [get_ports $sdram_inputs]
set_multicycle_path -setup -end 2 -from [get_clocks {sdram_clk}] -to [get_clocks $sys_clk]
set_multicycle_path -hold -end 1 -from [get_clocks {sdram_clk}] -to [get_clocks $sys_clk]
# SD card timings
@ -48,8 +49,17 @@ set_multicycle_path -setup -end 2 -from [get_clocks {sdram_clk}] -to [get_clocks
# FT1248 timings
set_false_path -to [get_ports {o_usb_clk io_usb_miosi[*] o_usb_cs}]
set_false_path -from [get_ports {io_usb_miosi[*] i_usb_miso i_usb_pwren}]
set_output_delay -clock [get_clocks {usb_clk}] -max 5.0 [get_ports {io_usb_miosi[*] o_usb_cs}]
set_output_delay -clock [get_clocks {usb_clk}] -min -5.0 [get_ports {io_usb_miosi[*] o_usb_cs}]
set_input_delay -clock [get_clocks {usb_clk}] -max 5.0 [get_ports {io_usb_miosi[*] i_usb_miso}]
set_input_delay -clock [get_clocks {usb_clk}] -min 5.0 [get_ports {io_usb_miosi[*] i_usb_miso}]
set_multicycle_path -setup -start 2 -from [get_clocks $sys_clk] -to [get_clocks {usb_clk}]
set_multicycle_path -hold -start 3 -from [get_clocks $sys_clk] -to [get_clocks {usb_clk}]
set_multicycle_path -setup -end 2 -from [get_clocks {usb_clk}] -to [get_clocks $sys_clk]
set_multicycle_path -hold -end 3 -from [get_clocks {usb_clk}] -to [get_clocks $sys_clk]
# N64, PI and SI timings

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

View File

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

View File

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

View File

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

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

View File

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

View File

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

View File

@ -28,12 +28,29 @@ module cpu_wrapper (
end
end
logic trap;
logic mem_valid;
logic mem_instr;
logic [31:0] mem_la_addr;
logic [31:0] mem_la_wdata;
logic [3:0] mem_la_wstrb;
logic pcpi_valid;
logic [31:0] pcpi_insn;
logic [31:0] pcpi_rs1;
logic [31:0] pcpi_rs2;
logic [31:0] eoi;
logic trace_valid;
logic [35:0] trace_data;
picorv32 #(
.ENABLE_COUNTERS(0),
.ENABLE_COUNTERS64(0),
.TWO_STAGE_SHIFT(0),
.TWO_CYCLE_COMPARE(1),
.TWO_CYCLE_ALU(1),
.CATCH_MISALIGN(0),
.CATCH_ILLINSN(0),
.PROGADDR_RESET(sc64::CPU_RESET_VECTOR)
.PROGADDR_RESET(32'h0001_0000)
) cpu_inst (
.clk(sys.clk),
.resetn(~sys.reset),
@ -43,7 +60,26 @@ module cpu_wrapper (
.mem_ready(bus.ack),
.mem_rdata(bus.rdata),
.mem_la_read(mem_la_read),
.mem_la_write(mem_la_write)
.mem_la_write(mem_la_write),
.trap(trap),
.mem_valid(mem_valid),
.mem_instr(mem_instr),
.mem_la_addr(mem_la_addr),
.mem_la_wdata(mem_la_wdata),
.mem_la_wstrb(mem_la_wstrb),
.pcpi_valid(pcpi_valid),
.pcpi_insn(pcpi_insn),
.pcpi_rs1(pcpi_rs1),
.pcpi_rs2(pcpi_rs2),
.pcpi_wr(1'b0),
.pcpi_rd(32'd0),
.pcpi_wait(1'b0),
.pcpi_ready(1'b0),
.irq(32'd0),
.eoi(eoi),
.trace_valid(trace_valid),
.trace_data(trace_data)
);
endmodule

View File

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

View File

@ -9,7 +9,7 @@
// altpll
//
// Simulation Library Files(s):
//
// altera_mf
// ============================================================
// ************************************************************
// THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE!
@ -337,4 +337,5 @@ endmodule
// Retrieval info: GEN_FILE: TYPE_NORMAL intel_pll.bsf FALSE
// Retrieval info: GEN_FILE: TYPE_NORMAL intel_pll_inst.v FALSE
// Retrieval info: GEN_FILE: TYPE_NORMAL intel_pll_bb.v FALSE
// Retrieval info: LIB_FILE: altera_mf
// Retrieval info: CBX_MODULE_PREFIX: ON

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

View File

@ -1,8 +1,7 @@
module n64_cfg (
if_system sys,
if_n64_bus bus,
if_config.n64 cfg,
if_cpu_ram.external cpu_ram
if_config.n64 cfg
);
typedef enum bit [2:0] {
@ -32,10 +31,6 @@ module n64_cfg (
logic [31:0] isv_id;
always_comb begin
cpu_ram.write = bus.request && bus.write && (bus.address[15:14] == 2'b01);
cpu_ram.address = bus.address[13:1];
cpu_ram.wdata = {bus.wdata[7:0], bus.wdata[15:8]};
bus.rdata = 16'd0;
if (bus.ack) begin
if (bus.address[15:14] == 2'b00) begin
@ -54,14 +49,14 @@ module n64_cfg (
R_DATA_1_L: bus.rdata = cfg.data[1][15:0];
R_VERSION_H: bus.rdata = sc64::SC64_VER[31:16];
R_VERSION_L: bus.rdata = sc64::SC64_VER[15:0];
default: bus.rdata = 16'd0;
endcase
end else if (bus.address[15:14] == 2'b01) begin
bus.rdata = {cpu_ram.rdata[7:0], cpu_ram.rdata[15:8]};
end else if (bus.address[15:14] == 2'b11) begin
case (bus.address[4:1])
R_ISV_ID_H: bus.rdata = isv_id[31:16];
R_ISV_ID_L: bus.rdata = isv_id[15:0];
R_ISV_RD_PTR: bus.rdata = cfg.isv_rd_ptr;
default: bus.rdata = 16'd0;
endcase
end
end

View File

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

View File

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

View File

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

View File

@ -9,31 +9,8 @@ package sc64;
__ID_N64_END
} e_n64_id;
typedef enum bit [3:0] {
ID_CPU_RAM,
ID_CPU_FLASH,
ID_CPU_GPIO,
ID_CPU_I2C,
ID_CPU_USB,
ID_CPU_UART,
ID_CPU_DMA,
ID_CPU_CFG,
ID_CPU_SDRAM,
ID_CPU_FLASHRAM,
ID_CPU_SI,
ID_CPU_DD,
__ID_CPU_END
} e_cpu_id;
typedef enum bit [1:0] {
ID_DMA_USB,
ID_DMA_SD,
__ID_DMA_END
} e_dma_id;
parameter bit [31:0] SC64_VER = 32'h53437632;
parameter int CLOCK_FREQUENCY = 32'd100_000_000;
parameter bit [31:0] CPU_RESET_VECTOR = {4'(ID_CPU_FLASH), 28'h0010000};
parameter int UART_BAUD_RATE = 32'd1_000_000;
`ifdef DEBUG

View File

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

175
fw/rtl/vendor/vendor_flash.sv vendored Normal file
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 DATA[2];
io32_t VERSION;
io32_t __padding[4092];
io32_t CPU_RAM[3840];
io32_t BUFFER[256];
} sc64_regs_t;
#define SC64_BASE (0x1FFF0000UL)

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

View File

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

View File

@ -6,7 +6,7 @@ OBJDUMP = $(TOOLCHAIN)objdump
SIZE = $(TOOLCHAIN)size
FLAGS = -mabi=ilp32 -march=rv32i $(USER_FLAGS)
CFLAGS = -Os -Wall -ffunction-sections -fdata-sections -ffreestanding -MMD -MP
CFLAGS = -Os -Wall -ffunction-sections -fdata-sections -ffreestanding -fno-delete-null-pointer-checks -MMD -MP
LDFLAGS = -nostartfiles -Wl,--gc-sections
SRC_DIR = src
@ -17,7 +17,6 @@ SRC_FILES = \
process.c \
usb.c \
cfg.c \
dma.c \
joybus.c \
rtc.c \
i2c.c \
@ -46,7 +45,7 @@ $(BUILD_DIR)/governor.elf: $(OBJS) SC64.ld
@$(OBJDUMP) -D $@ > $(BUILD_DIR)/governor.lst
$(BUILD_DIR)/governor.bin: $(BUILD_DIR)/governor.elf
@$(OBJCOPY) -O binary --gap-fill 0xFF --pad-to 0x10016800 $< $@
@$(OBJCOPY) -O binary --gap-fill 0xFF --pad-to 0x00016800 $< $@
$(BUILD_DIR)/governor.hex: $(BUILD_DIR)/governor.bin
@$(OBJCOPY) -I binary -O ihex $< $@

View File

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

View File

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

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

View File

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

View File

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

View File

@ -21,54 +21,48 @@ typedef volatile uint16_t io16_t;
typedef volatile uint32_t io32_t;
#define RAM_BASE (0x00000000UL)
#define RAMBUFFER_SIZE (1024)
#define RAM_SIZE ((16 * 1024) - RAMBUFFER_SIZE)
#define RAMBUFFER_BASE (RAM_BASE + RAM_SIZE)
#define RAM (*((io32_t *) RAM_BASE))
#define RAMBUFFER (*((io8_t *) RAMBUFFER_BASE))
#define FLASH_BASE (0x10000000UL)
#define FLASH_BASE (0x00000000UL)
#define FLASH_SIZE (0x39800)
#define FLASH (*((io32_t *) FLASH_BASE))
#define FLASH_SIZE (0x39800)
#define FLASH_NUM_SECTORS (4)
#define RAM_BASE (0x10000000UL)
#define RAM_SIZE (16 * 1024)
#define RAM (*((io32_t *) RAM_BASE))
typedef volatile struct flash_config_regs {
io32_t SR;
io32_t CR;
} flash_config_regs_t;
typedef volatile struct cfg_regs {
io32_t SCR;
io32_t DDIPL_OFFSET;
io32_t SAVE_OFFSET;
io8_t CMD;
io8_t __padding[3];
io32_t DATA[2];
io32_t VERSION;
io32_t RECONFIGURE;
io32_t ISV_OFFSET;
io16_t ISV_RD_PTR;
io16_t ISV_CURRENT_RD_PTR;
} cfg_regs_t;
#define FLASH_CONFIG_BASE (0x18000000UL)
#define FLASH_CONFIG ((flash_config_regs_t *) FLASH_CONFIG_BASE)
#define CFG_BASE (0x20000000UL)
#define CFG ((cfg_regs_t *) CFG_BASE)
#define FLASH_SR_STATUS_MASK (3 << 0)
#define FLASH_SR_STATUS_IDLE (0)
#define FLASH_SR_STATUS_BUSY_ERASE (1)
#define FLASH_SR_STATUS_BUSY_WRITE (2)
#define FLASH_SR_STATUS_BUSY_READ (3)
#define FLASH_SR_READ_SUCCESSFUL (1 << 2)
#define FLASH_SR_WRITE_SUCCESSFUL (1 << 3)
#define FLASH_SR_ERASE_SUCCESSFUL (1 << 4)
#define FLASH_SR_WRITE_PROTECT_BIT (5)
#define FLASH_CR_PAGE_ERASE_BIT (0)
#define FLASH_CR_SECTOR_ERASE_BIT (20)
#define FLASH_CR_SECTOR_ERASE_MASK (7 << FLASH_CR_SECTOR_ERASE_BIT)
#define FLASH_CR_WRITE_PROTECT_BIT (23)
typedef volatile struct gpio_regs {
io8_t ODR;
io8_t IDR;
io8_t OER;
io8_t __padding;
} gpio_regs_t;
#define GPIO_BASE (0x20000000UL)
#define GPIO ((gpio_regs_t *) GPIO_BASE)
#define CFG_SCR_SDRAM_SWITCH (1 << 0)
#define CFG_SCR_SDRAM_WRITABLE (1 << 1)
#define CFG_SCR_DD_EN (1 << 2)
#define CFG_SCR_SRAM_EN (1 << 3)
#define CFG_SCR_SRAM_BANKED (1 << 4)
#define CFG_SCR_FLASHRAM_EN (1 << 5)
#define CFG_SCR_SKIP_BOOTLOADER (1 << 6)
#define CFG_SCR_ISV_EN (1 << 7)
#define CFG_SCR_FLASH_ERASE_START (1 << 24)
#define CFG_SCR_FLASH_ERASE_BUSY (1 << 25)
#define CFG_SCR_FLASH_WP_ENABLE (1 << 26)
#define CFG_SCR_FLASH_WP_DISABLE (1 << 27)
#define CFG_SCR_CMD_ERROR (1 << 28)
#define CFG_SCR_CPU_BUSY (1 << 30)
#define CFG_SCR_CPU_READY (1 << 31)
typedef volatile struct i2c_regs {
@ -90,8 +84,8 @@ typedef volatile struct usb_regs {
io32_t SCR;
io8_t DR;
io8_t __padding_1[3];
io8_t ESCAPE;
io8_t __padding_2[3];
io32_t ADDR;
io32_t LEN;
} usb_regs_t;
#define USB_BASE (0x40000000UL)
@ -101,11 +95,14 @@ typedef volatile struct usb_regs {
#define USB_SCR_TXE (1 << 1)
#define USB_SCR_FLUSH_RX (1 << 2)
#define USB_SCR_FLUSH_TX (1 << 3)
#define USB_SCR_ENABLED (1 << 4)
#define USB_SCR_PWREN (1 << 5)
#define USB_SCR_ESCAPE_PENDING (1 << 6)
#define USB_SCR_ESCAPE_ACK (1 << 7)
#define USB_SCR_FORCE_TX (1 << 8)
#define USB_SCR_ENABLE (1 << 4)
#define USB_SCR_FORCE_TX (1 << 5)
#define USB_SCR_RESET_PENDING (1 << 6)
#define USB_SCR_RESET_ACK (1 << 7)
#define USB_SCR_DMA_BUSY (1 << 8)
#define USB_SCR_DMA_START (1 << 9)
#define USB_SCR_DMA_STOP (1 << 10)
#define USB_SCR_DMA_DIR (1 << 11)
typedef volatile struct uart_regs {
@ -121,91 +118,6 @@ typedef volatile struct uart_regs {
#define UART_SCR_TXE (1 << 1)
typedef volatile struct dma_regs {
io32_t SCR;
io32_t MADDR;
io32_t ID_LEN;
} dma_regs_t;
#define DMA_BASE (0x60000000UL)
#define DMA ((dma_regs_t *) DMA_BASE)
#define DMA_SCR_START (1 << 0)
#define DMA_SCR_STOP (1 << 1)
#define DMA_SCR_DIR (1 << 2)
#define DMA_SCR_BUSY (1 << 3)
typedef volatile struct cfg_regs {
io32_t SCR;
io32_t DDIPL_OFFSET;
io32_t SAVE_OFFSET;
io8_t CMD;
io8_t __padding[3];
io32_t DATA[2];
io32_t VERSION;
io32_t RECONFIGURE;
io32_t ISV_OFFSET;
io16_t ISV_RD_PTR;
io16_t ISV_CURRENT_RD_PTR;
} cfg_regs_t;
#define CFG_BASE (0x70000000UL)
#define CFG ((cfg_regs_t *) CFG_BASE)
#define CFG_SCR_SDRAM_SWITCH (1 << 0)
#define CFG_SCR_SDRAM_WRITABLE (1 << 1)
#define CFG_SCR_DD_EN (1 << 2)
#define CFG_SCR_SRAM_EN (1 << 3)
#define CFG_SCR_SRAM_BANKED (1 << 4)
#define CFG_SCR_FLASHRAM_EN (1 << 5)
#define CFG_SCR_SKIP_BOOTLOADER (1 << 6)
#define CFG_SCR_ISV_EN (1 << 7)
#define CFG_SCR_CMD_ERROR (1 << 28)
#define CFG_SCR_CPU_BUSY (1 << 30)
#define CFG_SCR_CPU_READY (1 << 31)
#define SDRAM_BASE (0x80000000UL)
#define SDRAM (*((io32_t *) SDRAM_BASE))
#define SDRAM_SIZE (64 * 1024 * 1024)
typedef volatile struct flashram_regs {
io32_t SCR;
io32_t __padding[31];
io32_t BUFFER[32];
} flashram_regs_t;
#define FLASHRAM_BASE (0x90000000UL)
#define FLASHRAM ((flashram_regs_t *) FLASHRAM_BASE)
#define FLASHRAM_OPERATION_PENDING (1 << 0)
#define FLASHRAM_OPERATION_DONE (1 << 1)
#define FLASHRAM_WRITE_OR_ERASE (1 << 2)
#define FLASHRAM_SECTOR_OR_ALL (1 << 3)
#define FLASHRAM_PAGE_BIT (8)
typedef volatile struct joybus_regs {
io32_t SCR;
io32_t DATA[3];
} joybus_regs_t;
#define JOYBUS_BASE (0xA0000000UL)
#define JOYBUS ((joybus_regs_t *) JOYBUS_BASE)
#define JOYBUS_SCR_RX_READY (1 << 0)
#define JOYBUS_SCR_RX_STOP_BIT (1 << 1)
#define JOYBUS_SCR_TX_START (1 << 2)
#define JOYBUS_SCR_TX_BUSY (1 << 3)
#define JOYBUS_SCR_RX_RESET (1 << 6)
#define JOYBUS_SCR_TX_RESET (1 << 7)
#define JOYBUS_SCR_RX_LENGTH_BIT (8)
#define JOYBUS_SCR_RX_LENGTH_MASK (0x7F << JOYBUS_SCR_RX_LENGTH_BIT)
#define JOYBUS_SCR_TX_LENGTH_BIT (16)
typedef volatile struct dd_regs {
io32_t SCR;
io16_t DATA;
@ -224,7 +136,7 @@ typedef volatile struct dd_regs {
io32_t SECTOR_BUFFER[64];
} dd_regs_t;
#define DD_BASE (0xB0000000UL)
#define DD_BASE (0x60000000UL)
#define DD ((dd_regs_t *) DD_BASE)
#define DD_SCR_HARD_RESET (1 << 0)
@ -255,6 +167,46 @@ typedef volatile struct dd_regs {
#define DD_HEAD_TRACK_INDEX_LOCK (1 << 13)
#define SDRAM_BASE (0x70000000UL)
#define SDRAM (*((io32_t *) SDRAM_BASE))
#define SDRAM_SIZE (64 * 1024 * 1024)
typedef volatile struct flashram_regs {
io32_t SCR;
io32_t __padding[31];
io32_t BUFFER[32];
} flashram_regs_t;
#define FLASHRAM_BASE (0x80000000UL)
#define FLASHRAM ((flashram_regs_t *) FLASHRAM_BASE)
#define FLASHRAM_OPERATION_PENDING (1 << 0)
#define FLASHRAM_OPERATION_DONE (1 << 1)
#define FLASHRAM_WRITE_OR_ERASE (1 << 2)
#define FLASHRAM_SECTOR_OR_ALL (1 << 3)
#define FLASHRAM_PAGE_BIT (8)
typedef volatile struct joybus_regs {
io32_t SCR;
io32_t DATA[3];
} joybus_regs_t;
#define JOYBUS_BASE (0x90000000UL)
#define JOYBUS ((joybus_regs_t *) JOYBUS_BASE)
#define JOYBUS_SCR_RX_READY (1 << 0)
#define JOYBUS_SCR_RX_STOP_BIT (1 << 1)
#define JOYBUS_SCR_TX_START (1 << 2)
#define JOYBUS_SCR_TX_BUSY (1 << 3)
#define JOYBUS_SCR_RX_RESET (1 << 6)
#define JOYBUS_SCR_TX_RESET (1 << 7)
#define JOYBUS_SCR_RX_LENGTH_BIT (8)
#define JOYBUS_SCR_RX_LENGTH_MASK (0x7F << JOYBUS_SCR_RX_LENGTH_BIT)
#define JOYBUS_SCR_TX_LENGTH_BIT (16)
void reset_handler(void);

View File

@ -1,5 +1,4 @@
#include "usb.h"
#include "dma.h"
#include "cfg.h"
#include "dd.h"
@ -140,24 +139,12 @@ static bool rx_cmd (uint32_t *data) {
return false;
}
static void handle_escape (void) {
if (USB->SCR & USB_SCR_ESCAPE_PENDING) {
if (USB->ESCAPE == 'R') {
if (p.dma_in_progress) {
dma_stop();
while (dma_busy());
}
usb_init();
}
USB->SCR |= USB_SCR_ESCAPE_ACK;
}
}
void usb_init (void) {
USB->SCR = (USB_SCR_ENABLED | USB_SCR_FLUSH_TX | USB_SCR_FLUSH_RX);
USB->SCR = (USB_SCR_DMA_STOP | USB_SCR_ENABLE | USB_SCR_FLUSH_TX | USB_SCR_FLUSH_RX);
p.state = STATE_IDLE;
p.dma_in_progress = false;
p.event_pending = false;
p.event_callback_pending = false;
@ -170,7 +157,11 @@ void usb_init (void) {
void process_usb (void) {
handle_escape();
if (USB->SCR & USB_SCR_RESET_PENDING) {
usb_init();
USB->SCR |= USB_SCR_RESET_ACK;
return;
}
switch (p.state) {
case STATE_IDLE:
@ -247,11 +238,15 @@ void process_usb (void) {
case 'W':
case 'L':
case 'S':
if (!dma_busy()) {
if (!(USB->SCR & USB_SCR_DMA_BUSY)) {
if (!p.dma_in_progress) {
bool is_write = (p.cmd == 'W') || (p.cmd == 'S');
enum dma_dir dir = is_write ? DMA_DIR_TO_SDRAM : DMA_DIR_FROM_SDRAM;
dma_start(p.args[0], p.args[1], DMA_ID_USB, dir);
USB->ADDR = p.args[0];
USB->LEN = p.args[1];
if ((p.cmd == 'W') || (p.cmd == 'S')) {
USB->SCR |= (USB_SCR_DMA_DIR | USB_SCR_DMA_START);
} else {
USB->SCR |= USB_SCR_DMA_START;
}
p.dma_in_progress = true;
} else {
if (p.cmd == 'L' || p.cmd == 'S') {
@ -276,43 +271,6 @@ void process_usb (void) {
}
break;
case 'F':
case 'T':
while ((p.args[0] + p.counter) != (p.args[0] + p.args[1])) {
uint8_t *buffer = (uint8_t *) (RAMBUFFER_BASE + p.args[0] + p.counter);
if (p.cmd == 'F') {
if (tx_byte(*buffer)) {
p.counter += 1;
} else {
break;
}
}
if (p.cmd == 'T') {
if (rx_byte(buffer)) {
p.counter += 1;
} else {
break;
}
}
}
if ((p.args[0] + p.counter) == (p.args[0] + p.args[1])) {
if (p.event_callback_pending) {
if (p.cmd == 'F' && p.event.trigger == CALLBACK_BUFFER_READ) {
p.event_callback_pending = false;
p.event.callback();
}
if (p.cmd == 'T' && p.event.trigger == CALLBACK_BUFFER_WRITE) {
p.event_callback_pending = false;
p.event.callback();
}
}
if (p.cmd == 'F') {
USB->SCR |= USB_SCR_FORCE_TX;
}
p.state = STATE_IDLE;
}
break;
default:
p.error = true;
p.state = STATE_RESPONSE;

View File

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