[SC64] Initial version

This commit is contained in:
Polprzewodnikowy 2020-10-08 02:04:42 +02:00
parent 5901ff3805
commit bc802619d2
57 changed files with 33722 additions and 0 deletions

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
**/.vscode

BIN
.media/sc64_clean_pcb.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

BIN
.media/sc64_in_n64.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

BIN
.media/sc64_on_table.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 MiB

View File

@ -0,0 +1,48 @@
# SummerCollection
A collection of hardware, firmware and software designs of SummerCart64 - Nintendo 64 FlashCart/DevKit.
## Project parts
### Hardware
Folder **`hw`** contains PCB design made in Autodesk Eagle.
### Firmware
Folder **`fw`** contains firmware written in Verilog for Intel MAX10 FPGA.
### Software
Folder **`sw`** contains several helper programs that makes flash cart work all together, including bootloader and PC communication software.
## What works
Currently hardware implements basic functionality for playing games - ROM emulation, bootloader and PC communication. You can send any ROM to the SDRAM from PC and if game doesn't check for save hardware then it most likely will work. Bootloader does all the work necessary to setup the console registers for specific CIC chip that game requires.
## Issues
There are several issues with the project at the moment in order of importance:
- Documentation is not finished for most of the modules.
- No save hardware implementation.
- No SD card interface hardware implementation.
- No RTC hardware implementation.
- Currently PC communication disables N64 PI interface completely as there's no bus arbiter implemented.
- No save write-back to SD card hardware implementation.
- PCB schematic is unorganized and some component values are missing.
- There's no BOM for hardware.
- PCB design and necessary components needs to be reconsidered for next version.
- No CIC implementation in FPGA, current solution uses [UltraCIC II](https://github.com/perkinsb1024/UltraCIC-II) based on ATtiny45.
## What's next
Current goal is to implement EEPROM save emulation.
## Finished sample
![SummerCart64 clean PCB](.media/sc64_clean_pcb.jpg)
![SummerCart64 on table](.media/sc64_on_table.jpg)
![SummerCart64 in partialy disassembled Nintendo 64](.media/sc64_in_n64.jpg)

7
fw/.gitignore vendored Normal file
View File

@ -0,0 +1,7 @@
/db
/greybox_tmp
/incremental_db
/output_files
*.qws
*.rpt
*.txt

View File

@ -0,0 +1,7 @@
# SummerCart64 Firmware
A FPGA firmware written in Verilog for SummerCart64.
## TODO
- Expand documentation

31
fw/SummerCart64.qpf Normal file
View File

@ -0,0 +1,31 @@
# -------------------------------------------------------------------------- #
#
# Copyright (C) 2020 Intel Corporation. All rights reserved.
# Your use of Intel Corporation's design tools, logic functions
# and other software and tools, and any partner logic
# functions, and any output files from any of the foregoing
# (including device programming or simulation files), and any
# associated documentation or information are expressly subject
# to the terms and conditions of the Intel Program License
# Subscription Agreement, the Intel Quartus Prime License Agreement,
# the Intel FPGA IP License Agreement, or other applicable license
# agreement, including, without limitation, that your use is for
# the sole purpose of programming logic devices manufactured by
# Intel and sold by Intel or its authorized distributors. Please
# refer to the applicable agreement for further details, at
# https://fpgasoftware.intel.com/eula.
#
# -------------------------------------------------------------------------- #
#
# Quartus Prime
# Version 20.1.0 Build 711 06/05/2020 SJ Lite Edition
# Date created = 23:45:19 July 29, 2020
#
# -------------------------------------------------------------------------- #
QUARTUS_VERSION = "20.1"
DATE = "23:45:19 July 29, 2020"
# Revisions
PROJECT_REVISION = "SummerCart64"

208
fw/SummerCart64.qsf Normal file
View File

@ -0,0 +1,208 @@
# -------------------------------------------------------------------------- #
#
# Copyright (C) 2020 Intel Corporation. All rights reserved.
# Your use of Intel Corporation's design tools, logic functions
# and other software and tools, and any partner logic
# functions, and any output files from any of the foregoing
# (including device programming or simulation files), and any
# associated documentation or information are expressly subject
# to the terms and conditions of the Intel Program License
# Subscription Agreement, the Intel Quartus Prime License Agreement,
# the Intel FPGA IP License Agreement, or other applicable license
# agreement, including, without limitation, that your use is for
# the sole purpose of programming logic devices manufactured by
# Intel and sold by Intel or its authorized distributors. Please
# refer to the applicable agreement for further details, at
# https://fpgasoftware.intel.com/eula.
#
# -------------------------------------------------------------------------- #
#
# Quartus Prime
# Version 20.1.0 Build 711 06/05/2020 SJ Lite Edition
# Date created = 23:45:19 July 29, 2020
#
# -------------------------------------------------------------------------- #
#
# Notes:
#
# 1) The default values for assignments are stored in the file:
# SummerCart64_assignment_defaults.qdf
# If this file doesn't exist, see file:
# assignment_defaults.qdf
#
# 2) Altera recommends that you do not modify this file. This
# file is updated automatically by the Quartus Prime software
# and any changes you make may be lost or overwritten.
#
# -------------------------------------------------------------------------- #
set_global_assignment -name FAMILY "MAX 10"
set_global_assignment -name DEVICE 10M08SCE144C8G
set_global_assignment -name TOP_LEVEL_ENTITY top
set_global_assignment -name ORIGINAL_QUARTUS_VERSION 20.1.0
set_global_assignment -name PROJECT_CREATION_TIME_DATE "23:45:19 JULY 29, 2020"
set_global_assignment -name LAST_QUARTUS_VERSION "20.1.0 Lite Edition"
set_global_assignment -name PROJECT_OUTPUT_DIRECTORY output_files
set_global_assignment -name MIN_CORE_JUNCTION_TEMP 0
set_global_assignment -name MAX_CORE_JUNCTION_TEMP 85
set_global_assignment -name DEVICE_FILTER_PACKAGE EQFP
set_global_assignment -name DEVICE_FILTER_PIN_COUNT 144
set_global_assignment -name DEVICE_FILTER_SPEED_GRADE 8
set_global_assignment -name ERROR_CHECK_FREQUENCY_DIVISOR 256
set_global_assignment -name ENABLE_OCT_DONE OFF
set_global_assignment -name ENABLE_CONFIGURATION_PINS OFF
set_global_assignment -name ENABLE_BOOT_SEL_PIN OFF
set_global_assignment -name EXTERNAL_FLASH_FALLBACK_ADDRESS 00000000
set_global_assignment -name USE_CONFIGURATION_DEVICE OFF
set_global_assignment -name CRC_ERROR_OPEN_DRAIN OFF
set_global_assignment -name OUTPUT_IO_TIMING_NEAR_END_VMEAS "HALF VCCIO" -rise
set_global_assignment -name OUTPUT_IO_TIMING_NEAR_END_VMEAS "HALF VCCIO" -fall
set_global_assignment -name OUTPUT_IO_TIMING_FAR_END_VMEAS "HALF SIGNAL SWING" -rise
set_global_assignment -name OUTPUT_IO_TIMING_FAR_END_VMEAS "HALF SIGNAL SWING" -fall
set_global_assignment -name STRATIX_DEVICE_IO_STANDARD "3.3-V LVTTL"
set_location_assignment PIN_26 -to i_clk
set_location_assignment PIN_98 -to io_sdram_dq[0]
set_location_assignment PIN_97 -to io_sdram_dq[1]
set_location_assignment PIN_96 -to io_sdram_dq[2]
set_location_assignment PIN_93 -to io_sdram_dq[3]
set_location_assignment PIN_92 -to io_sdram_dq[4]
set_location_assignment PIN_91 -to io_sdram_dq[5]
set_location_assignment PIN_90 -to io_sdram_dq[6]
set_location_assignment PIN_89 -to io_sdram_dq[7]
set_location_assignment PIN_99 -to io_sdram_dq[8]
set_location_assignment PIN_100 -to io_sdram_dq[9]
set_location_assignment PIN_101 -to io_sdram_dq[10]
set_location_assignment PIN_102 -to io_sdram_dq[11]
set_location_assignment PIN_105 -to io_sdram_dq[12]
set_location_assignment PIN_106 -to io_sdram_dq[13]
set_location_assignment PIN_110 -to io_sdram_dq[14]
set_location_assignment PIN_111 -to io_sdram_dq[15]
set_location_assignment PIN_79 -to o_sdram_a[0]
set_location_assignment PIN_78 -to o_sdram_a[1]
set_location_assignment PIN_77 -to o_sdram_a[2]
set_location_assignment PIN_76 -to o_sdram_a[3]
set_location_assignment PIN_61 -to o_sdram_a[4]
set_location_assignment PIN_62 -to o_sdram_a[5]
set_location_assignment PIN_64 -to o_sdram_a[6]
set_location_assignment PIN_65 -to o_sdram_a[7]
set_location_assignment PIN_66 -to o_sdram_a[8]
set_location_assignment PIN_69 -to o_sdram_a[9]
set_location_assignment PIN_80 -to o_sdram_a[10]
set_location_assignment PIN_70 -to o_sdram_a[11]
set_location_assignment PIN_74 -to o_sdram_a[12]
set_location_assignment PIN_84 -to o_sdram_ba[0]
set_location_assignment PIN_81 -to o_sdram_ba[1]
set_location_assignment PIN_75 -to o_sdram_clk
set_location_assignment PIN_85 -to o_sdram_cs
set_location_assignment PIN_87 -to o_sdram_cas
set_location_assignment PIN_86 -to o_sdram_ras
set_location_assignment PIN_88 -to o_sdram_we
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_112 -to io_sd_dat[1]
set_location_assignment PIN_113 -to io_sd_dat[0]
set_location_assignment PIN_134 -to o_flash_cs
set_location_assignment PIN_131 -to o_flash_clk
set_location_assignment PIN_132 -to io_flash_dq[3]
set_location_assignment PIN_136 -to io_flash_dq[2]
set_location_assignment PIN_135 -to io_flash_dq[1]
set_location_assignment PIN_130 -to io_flash_dq[0]
set_location_assignment PIN_122 -to o_sram_clk
set_location_assignment PIN_123 -to io_sram_dq[3]
set_location_assignment PIN_127 -to io_sram_dq[2]
set_location_assignment PIN_126 -to io_sram_dq[1]
set_location_assignment PIN_121 -to io_sram_dq[0]
set_location_assignment PIN_124 -to o_sram_cs
set_location_assignment PIN_24 -to io_n64_si_dq
set_location_assignment PIN_25 -to i_n64_nmi
set_location_assignment PIN_27 -to i_n64_reset
set_location_assignment PIN_28 -to i_n64_si_clk
set_location_assignment PIN_46 -to i_n64_pi_aleh
set_location_assignment PIN_50 -to i_n64_pi_alel
set_location_assignment PIN_47 -to i_n64_pi_read
set_location_assignment PIN_48 -to i_n64_pi_write
set_location_assignment PIN_60 -to io_n64_pi_ad[0]
set_location_assignment PIN_58 -to io_n64_pi_ad[1]
set_location_assignment PIN_56 -to io_n64_pi_ad[2]
set_location_assignment PIN_54 -to io_n64_pi_ad[3]
set_location_assignment PIN_44 -to io_n64_pi_ad[4]
set_location_assignment PIN_41 -to io_n64_pi_ad[5]
set_location_assignment PIN_38 -to io_n64_pi_ad[6]
set_location_assignment PIN_32 -to io_n64_pi_ad[7]
set_location_assignment PIN_33 -to io_n64_pi_ad[8]
set_location_assignment PIN_39 -to io_n64_pi_ad[9]
set_location_assignment PIN_43 -to io_n64_pi_ad[10]
set_location_assignment PIN_45 -to io_n64_pi_ad[11]
set_location_assignment PIN_52 -to io_n64_pi_ad[12]
set_location_assignment PIN_55 -to io_n64_pi_ad[13]
set_location_assignment PIN_57 -to io_n64_pi_ad[14]
set_location_assignment PIN_59 -to io_n64_pi_ad[15]
set_location_assignment PIN_13 -to i_ftdi_do
set_location_assignment PIN_14 -to o_ftdi_di
set_location_assignment PIN_12 -to i_ftdi_clk
set_location_assignment PIN_15 -to i_ftdi_cs
set_global_assignment -name POWER_PRESET_COOLING_SOLUTION "23 MM HEAT SINK WITH 200 LFPM AIRFLOW"
set_global_assignment -name POWER_BOARD_THERMAL_MODEL "NONE (CONSERVATIVE)"
set_global_assignment -name FLOW_ENABLE_POWER_ANALYZER ON
set_global_assignment -name POWER_DEFAULT_INPUT_IO_TOGGLE_RATE "12.5 %"
set_global_assignment -name PARTITION_NETLIST_TYPE SOURCE -section_id Top
set_global_assignment -name PARTITION_FITTER_PRESERVATION_LEVEL PLACEMENT_AND_ROUTING -section_id Top
set_global_assignment -name PARTITION_COLOR 16764057 -section_id Top
set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to o_sdram_clk
set_location_assignment PIN_29 -to i_n64_cic_clk
set_location_assignment PIN_30 -to io_n64_cic_dq
set_location_assignment PIN_138 -to io_pmod[0]
set_location_assignment PIN_140 -to io_pmod[1]
set_location_assignment PIN_141 -to io_pmod[2]
set_location_assignment PIN_6 -to io_pmod[3]
set_location_assignment PIN_7 -to io_pmod[4]
set_location_assignment PIN_8 -to io_pmod[5]
set_location_assignment PIN_10 -to io_pmod[6]
set_location_assignment PIN_11 -to io_pmod[7]
set_location_assignment PIN_22 -to io_rtc_sda
set_location_assignment PIN_21 -to o_rtc_scl
set_location_assignment PIN_17 -to o_led
set_global_assignment -name OPTIMIZATION_MODE "HIGH PERFORMANCE EFFORT"
set_global_assignment -name ENABLE_SIGNALTAP ON
set_global_assignment -name USE_SIGNALTAP_FILE misc/SignalTapLogicAnalyzer.stp
set_global_assignment -name RESERVE_ALL_UNUSED_PINS_WEAK_PULLUP "AS INPUT TRI-STATED WITH WEAK PULL-UP"
set_global_assignment -name INTERNAL_FLASH_UPDATE_MODE "SINGLE COMP IMAGE"
set_instance_assignment -name WEAK_PULL_UP_RESISTOR ON -to io_n64_si_dq
set_instance_assignment -name WEAK_PULL_UP_RESISTOR ON -to io_n64_cic_dq
set_instance_assignment -name WEAK_PULL_UP_RESISTOR ON -to i_n64_pi_aleh
set_instance_assignment -name WEAK_PULL_UP_RESISTOR ON -to i_n64_pi_read
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_cic_clk
set_instance_assignment -name WEAK_PULL_UP_RESISTOR ON -to i_ftdi_do
set_instance_assignment -name WEAK_PULL_UP_RESISTOR ON -to i_n64_si_clk
set_global_assignment -name SMART_RECOMPILE OFF
set_instance_assignment -name GLOBAL_SIGNAL GLOBAL_CLOCK -to i_clk
set_global_assignment -name TIMING_ANALYZER_MULTICORNER_ANALYSIS ON
set_instance_assignment -name GLOBAL_SIGNAL GLOBAL_CLOCK -to i_ftdi_clk
set_global_assignment -name TIMING_ANALYZER_DO_REPORT_TIMING ON
set_global_assignment -name PHYSICAL_SYNTHESIS_ASYNCHRONOUS_SIGNAL_PIPELINING OFF
set_global_assignment -name ROUTER_CLOCKING_TOPOLOGY_ANALYSIS ON
set_instance_assignment -name GLOBAL_SIGNAL GLOBAL_CLOCK -to "pll:sys_pll|altpll:altpll_component|pll_altpll:auto_generated|wire_pll1_clk[0]"
set_instance_assignment -name GLOBAL_SIGNAL GLOBAL_CLOCK -to "pll:sys_pll|altpll:altpll_component|pll_altpll:auto_generated|wire_pll1_clk[1]"
set_global_assignment -name FITTER_EFFORT "STANDARD FIT"
set_global_assignment -name VERILOG_FILE rtl/cart_config.v
set_global_assignment -name VERILOG_FILE rtl/sdram.v
set_global_assignment -name VERILOG_FILE rtl/external/wbsdram.v
set_global_assignment -name VERILOG_FILE rtl/external/qflexpress.v
set_global_assignment -name VERILOG_FILE rtl/address_decoder.v
set_global_assignment -name VERILOG_FILE rtl/flash.v
set_global_assignment -name VERILOG_FILE rtl/n64_pi.v
set_global_assignment -name VERILOG_FILE rtl/pc.v
set_global_assignment -name VERILOG_FILE rtl/top.v
set_global_assignment -name SDC_FILE constraints.sdc
set_global_assignment -name QIP_FILE rtl/intel/pll/pll.qip
set_global_assignment -name QIP_FILE rtl/intel/gpio/gpio_ddro.qip
set_global_assignment -name QIP_FILE rtl/intel/fifo/fifo_bus_to_pc.qip
set_global_assignment -name QIP_FILE rtl/intel/fifo/fifo_pc_to_bus.qip
set_global_assignment -name SIGNALTAP_FILE misc/SignalTapLogicAnalyzer.stp
set_instance_assignment -name PARTITION_HIERARCHY root_partition -to | -section_id Top
set_global_assignment -name SLD_FILE db/SignalTapLogicAnalyzer_auto_stripped.stp

7
fw/constraints.sdc Normal file
View File

@ -0,0 +1,7 @@
create_clock -name i_clk -period 20 [get_ports i_clk]
create_clock -name i_ftdi_clk -period 33.333 [get_ports i_ftdi_clk]
derive_pll_clocks -create_base_clocks
derive_clock_uncertainty

File diff suppressed because one or more lines are too long

37
fw/rtl/address_decoder.v Normal file
View File

@ -0,0 +1,37 @@
module address_decoder (
input [31:0] i_address,
output o_cart_config,
output o_flash,
output o_flash_cfg,
output o_sdram,
input i_flash_enable,
input i_sdram_enable,
output o_address_valid
);
localparam CART_CONFIG_ADDR = 32'h1E00_0000;
localparam CART_CONFIG_WIDTH = 8;
assign o_cart_config = i_address[31:CART_CONFIG_WIDTH] == CART_CONFIG_ADDR[31:CART_CONFIG_WIDTH];
localparam FLASH_ADDR = 32'h1000_0000;
localparam FLASH_REMAP_ADDR = 32'h1800_0000;
localparam FLASH_WIDTH = 24;
assign o_flash = i_flash_enable && (i_address[31:FLASH_WIDTH] == (i_sdram_enable ? FLASH_REMAP_ADDR[31:FLASH_WIDTH] : FLASH_ADDR[31:FLASH_WIDTH]));
localparam FLASH_CFG_ADDR = 32'h1C00_0000;
assign o_flash_cfg = i_flash_enable && (i_address == FLASH_CFG_ADDR);
localparam SDRAM_ADDR = 32'h1000_0000;
localparam SDRAM_WIDTH = 26;
assign o_sdram = i_sdram_enable && (i_address[31:SDRAM_WIDTH] == SDRAM_ADDR[31:SDRAM_WIDTH]);
assign o_address_valid = (|{o_cart_config, o_flash, o_flash_cfg, o_sdram});
endmodule

71
fw/rtl/cart_config.v Normal file
View File

@ -0,0 +1,71 @@
module cart_config (
input i_clk,
input i_reset,
input i_n64_reset,
input i_n64_nmi,
input i_select,
input i_read_rq,
input i_write_rq,
output reg o_ack,
input [31:0] i_address,
input [31:0] i_data,
output [31:0] o_data,
input i_n64_disabled,
output o_flash_enable,
output o_sdram_enable
);
reg [1:0] r_cart_config;
reg [7:0] r_cic_type;
wire [31:0] w_regs [1:0];
assign w_regs[0] = {30'd0, r_cart_config};
assign w_regs[1] = {24'd0, r_cic_type};
assign o_data = w_regs[i_address[2]];
assign o_flash_enable = r_cart_config[0];
assign o_sdram_enable = r_cart_config[1];
reg r_last_n64_reset;
reg r_last_n64_nmi;
wire w_n64_reset_op = !i_n64_disabled && !r_last_n64_reset && i_n64_reset;
wire w_n64_nmi_op = !i_n64_disabled && !r_last_n64_nmi && i_n64_nmi;
always @(posedge i_clk or posedge i_reset) begin
if (i_reset) begin
r_last_n64_reset <= 1'b0;
r_last_n64_nmi <= 1'b0;
end else begin
r_last_n64_reset <= i_n64_reset;
r_last_n64_nmi <= i_n64_nmi;
end
end
always @(posedge i_clk or posedge i_reset or posedge w_n64_reset_op or posedge w_n64_nmi_op) begin
if (i_reset || w_n64_reset_op || w_n64_nmi_op) begin
r_cart_config <= 2'b01;
end else begin
if (i_select && i_write_rq && !i_address[2]) r_cart_config <= i_data[1:0];
end
end
always @(posedge i_clk or posedge i_reset) begin
if (i_reset) begin
r_cic_type <= 8'd0;
end else begin
if (i_select && i_write_rq && i_address[2]) r_cic_type <= i_data[7:0];
end
end
always @(posedge i_clk) begin
o_ack <= 1'b0;
if (i_select && (i_read_rq || i_write_rq)) o_ack <= 1'b1;
end
endmodule

25
fw/rtl/external/README.md vendored Normal file
View File

@ -0,0 +1,25 @@
# External code for SummerCart64 Firmware
This folder contains code downloaded directly from external repositories with minor modifications.
## qflexpress.v
### Source
[https://github.com/ZipCPU/qspiflash/blob/master/rtl/qflexpress.v](https://github.com/ZipCPU/qspiflash/blob/master/rtl/qflexpress.v)
### Modifications
- Changed initialization sequence.
- Extended address space for 16-bit address alignment.
## wbsdram.v
### Source
[https://github.com/ZipCPU/arrowzip/blob/master/rtl/arrowzip/wbsdram.v](https://github.com/ZipCPU/arrowzip/blob/master/rtl/arrowzip/wbsdram.v)
### Modifications
- Changed refresh interval that suits 90 MHz clock and used SDRAM.
- Changed column and row address widths.

2239
fw/rtl/external/qflexpress.v vendored Normal file

File diff suppressed because it is too large Load Diff

1038
fw/rtl/external/wbsdram.v vendored Normal file

File diff suppressed because it is too large Load Diff

79
fw/rtl/flash.v Normal file
View File

@ -0,0 +1,79 @@
module flash (
input i_clk,
input i_reset,
output o_flash_clk,
output o_flash_cs,
input [3:0] i_flash_dq,
output [3:0] o_flash_dq,
output [1:0] o_flash_dq_mode,
input i_select,
input i_cfg_select,
input i_read_rq,
input i_write_rq,
output o_ack,
input [31:0] i_address,
input [31:0] i_data,
output [31:0] o_data
);
reg r_wb_cyc;
wire w_wb_cyc;
wire w_stb;
wire w_wb_stb;
wire w_cfg_stb;
wire w_wb_ack;
wire w_wb_stall;
assign w_wb_cyc = w_wb_stb || w_cfg_stb || r_wb_cyc;
assign w_stb = !w_wb_stall && (i_read_rq || i_write_rq);
assign w_wb_stb = i_select && w_stb;
assign w_cfg_stb = i_cfg_select && w_stb;
assign o_ack = w_wb_ack;
always @(posedge i_clk or posedge i_reset) begin
if (i_reset) begin
r_wb_cyc <= 1'b0;
end else begin
if (w_wb_stb || w_cfg_stb) begin
r_wb_cyc <= 1'b1;
end else if (w_wb_ack) begin
r_wb_cyc <= 1'b0;
end
end
end
qflexpress qflexpress_inst(
.i_clk(i_clk),
.i_reset(i_reset),
.i_wb_cyc(w_wb_cyc),
.i_wb_stb(w_wb_stb), // FIXME: Currently strobe can be missed when w_wb_stall is high
.i_cfg_stb(w_cfg_stb),
.i_wb_we(i_write_rq),
.i_wb_addr(i_address[31:1]),
.i_wb_data(i_data),
.o_wb_ack(w_wb_ack),
.o_wb_stall(w_wb_stall),
.o_wb_data(o_data),
.o_qspi_sck(o_flash_clk),
.o_qspi_cs_n(o_flash_cs),
.o_qspi_mod(o_flash_dq_mode),
.o_qspi_dat(o_flash_dq),
.i_qspi_dat(i_flash_dq)
);
defparam
qflexpress_inst.LGFLASHSZ = 24,
qflexpress_inst.OPT_PIPE = 0,
qflexpress_inst.OPT_CFG = 1,
qflexpress_inst.OPT_STARTUP = 1,
qflexpress_inst.OPT_CLKDIV = 1,
qflexpress_inst.OPT_ENDIANSWAP = 0,
qflexpress_inst.RDDELAY = 0,
qflexpress_inst.NDUMMY = 6,
qflexpress_inst.OPT_STARTUP_FILE = "";
endmodule

View File

@ -0,0 +1,4 @@
set_global_assignment -name IP_TOOL_NAME "FIFO"
set_global_assignment -name IP_TOOL_VERSION "20.1"
set_global_assignment -name IP_GENERATED_DEVICE_FAMILY "{MAX 10}"
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) "fifo_bus_to_pc.v"]

View File

@ -0,0 +1,183 @@
// megafunction wizard: %FIFO%
// GENERATION: STANDARD
// VERSION: WM1.0
// MODULE: dcfifo
// ============================================================
// File Name: fifo_bus_to_pc.v
// Megafunction Name(s):
// dcfifo
//
// Simulation Library Files(s):
// altera_mf
// ============================================================
// ************************************************************
// THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE!
//
// 20.1.0 Build 711 06/05/2020 SJ Lite Edition
// ************************************************************
//Copyright (C) 2020 Intel Corporation. All rights reserved.
//Your use of Intel Corporation's design tools, logic functions
//and other software and tools, and any partner logic
//functions, and any output files from any of the foregoing
//(including device programming or simulation files), and any
//associated documentation or information are expressly subject
//to the terms and conditions of the Intel Program License
//Subscription Agreement, the Intel Quartus Prime License Agreement,
//the Intel FPGA IP License Agreement, or other applicable license
//agreement, including, without limitation, that your use is for
//the sole purpose of programming logic devices manufactured by
//Intel and sold by Intel or its authorized distributors. Please
//refer to the applicable agreement for further details, at
//https://fpgasoftware.intel.com/eula.
// synopsys translate_off
`timescale 1 ps / 1 ps
// synopsys translate_on
module fifo_bus_to_pc (
aclr,
data,
rdclk,
rdreq,
wrclk,
wrreq,
q,
rdusedw,
wrfull);
input aclr;
input [31:0] data;
input rdclk;
input rdreq;
input wrclk;
input wrreq;
output [31:0] q;
output [10:0] rdusedw;
output wrfull;
`ifndef ALTERA_RESERVED_QIS
// synopsys translate_off
`endif
tri0 aclr;
`ifndef ALTERA_RESERVED_QIS
// synopsys translate_on
`endif
wire [31:0] sub_wire0;
wire [10:0] sub_wire1;
wire sub_wire2;
wire [31:0] q = sub_wire0[31:0];
wire [10:0] rdusedw = sub_wire1[10:0];
wire wrfull = sub_wire2;
dcfifo dcfifo_component (
.aclr (aclr),
.data (data),
.rdclk (rdclk),
.rdreq (rdreq),
.wrclk (wrclk),
.wrreq (wrreq),
.q (sub_wire0),
.rdusedw (sub_wire1),
.wrfull (sub_wire2),
.eccstatus (),
.rdempty (),
.rdfull (),
.wrempty (),
.wrusedw ());
defparam
dcfifo_component.add_usedw_msb_bit = "ON",
dcfifo_component.intended_device_family = "MAX 10",
dcfifo_component.lpm_numwords = 1024,
dcfifo_component.lpm_showahead = "ON",
dcfifo_component.lpm_type = "dcfifo",
dcfifo_component.lpm_width = 32,
dcfifo_component.lpm_widthu = 11,
dcfifo_component.overflow_checking = "ON",
dcfifo_component.rdsync_delaypipe = 4,
dcfifo_component.read_aclr_synch = "OFF",
dcfifo_component.underflow_checking = "ON",
dcfifo_component.use_eab = "ON",
dcfifo_component.write_aclr_synch = "OFF",
dcfifo_component.wrsync_delaypipe = 4;
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: CLOCKS_ARE_SYNCHRONIZED NUMERIC "0"
// Retrieval info: PRIVATE: Clock NUMERIC "4"
// Retrieval info: PRIVATE: Depth NUMERIC "1024"
// Retrieval info: PRIVATE: Empty NUMERIC "1"
// Retrieval info: PRIVATE: Full NUMERIC "1"
// Retrieval info: PRIVATE: INTENDED_DEVICE_FAMILY STRING "MAX 10"
// Retrieval info: PRIVATE: LE_BasedFIFO NUMERIC "0"
// 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 "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"
// Retrieval info: PRIVATE: UsedW NUMERIC "1"
// Retrieval info: PRIVATE: Width NUMERIC "32"
// Retrieval info: PRIVATE: dc_aclr NUMERIC "1"
// Retrieval info: PRIVATE: diff_widths NUMERIC "0"
// Retrieval info: PRIVATE: msb_usedw NUMERIC "1"
// Retrieval info: PRIVATE: output_width NUMERIC "32"
// Retrieval info: PRIVATE: rsEmpty NUMERIC "0"
// Retrieval info: PRIVATE: rsFull NUMERIC "0"
// Retrieval info: PRIVATE: rsUsedW NUMERIC "1"
// Retrieval info: PRIVATE: sc_aclr NUMERIC "0"
// Retrieval info: PRIVATE: sc_sclr NUMERIC "0"
// Retrieval info: PRIVATE: wsEmpty NUMERIC "0"
// 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_USEDW_MSB_BIT STRING "ON"
// Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "MAX 10"
// Retrieval info: CONSTANT: LPM_NUMWORDS NUMERIC "1024"
// Retrieval info: CONSTANT: LPM_SHOWAHEAD STRING "ON"
// Retrieval info: CONSTANT: LPM_TYPE STRING "dcfifo"
// Retrieval info: CONSTANT: LPM_WIDTH NUMERIC "32"
// Retrieval info: CONSTANT: LPM_WIDTHU NUMERIC "11"
// Retrieval info: CONSTANT: OVERFLOW_CHECKING STRING "ON"
// Retrieval info: CONSTANT: RDSYNC_DELAYPIPE NUMERIC "4"
// Retrieval info: CONSTANT: READ_ACLR_SYNCH STRING "OFF"
// Retrieval info: CONSTANT: UNDERFLOW_CHECKING STRING "ON"
// Retrieval info: CONSTANT: USE_EAB STRING "ON"
// Retrieval info: CONSTANT: WRITE_ACLR_SYNCH STRING "OFF"
// Retrieval info: CONSTANT: WRSYNC_DELAYPIPE NUMERIC "4"
// Retrieval info: USED_PORT: aclr 0 0 0 0 INPUT GND "aclr"
// Retrieval info: USED_PORT: data 0 0 32 0 INPUT NODEFVAL "data[31..0]"
// Retrieval info: USED_PORT: q 0 0 32 0 OUTPUT NODEFVAL "q[31..0]"
// Retrieval info: USED_PORT: rdclk 0 0 0 0 INPUT NODEFVAL "rdclk"
// Retrieval info: USED_PORT: rdreq 0 0 0 0 INPUT NODEFVAL "rdreq"
// Retrieval info: USED_PORT: rdusedw 0 0 11 0 OUTPUT NODEFVAL "rdusedw[10..0]"
// Retrieval info: USED_PORT: wrclk 0 0 0 0 INPUT NODEFVAL "wrclk"
// Retrieval info: USED_PORT: wrfull 0 0 0 0 OUTPUT NODEFVAL "wrfull"
// Retrieval info: USED_PORT: wrreq 0 0 0 0 INPUT NODEFVAL "wrreq"
// Retrieval info: CONNECT: @aclr 0 0 0 0 aclr 0 0 0 0
// Retrieval info: CONNECT: @data 0 0 32 0 data 0 0 32 0
// Retrieval info: CONNECT: @rdclk 0 0 0 0 rdclk 0 0 0 0
// Retrieval info: CONNECT: @rdreq 0 0 0 0 rdreq 0 0 0 0
// Retrieval info: CONNECT: @wrclk 0 0 0 0 wrclk 0 0 0 0
// Retrieval info: CONNECT: @wrreq 0 0 0 0 wrreq 0 0 0 0
// Retrieval info: CONNECT: q 0 0 32 0 @q 0 0 32 0
// Retrieval info: CONNECT: rdusedw 0 0 11 0 @rdusedw 0 0 11 0
// Retrieval info: CONNECT: wrfull 0 0 0 0 @wrfull 0 0 0 0
// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_bus_to_pc.v TRUE
// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_bus_to_pc.inc FALSE
// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_bus_to_pc.cmp FALSE
// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_bus_to_pc.bsf FALSE
// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_bus_to_pc_inst.v FALSE
// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_bus_to_pc_bb.v FALSE
// Retrieval info: LIB_FILE: altera_mf

View File

@ -0,0 +1,4 @@
set_global_assignment -name IP_TOOL_NAME "FIFO"
set_global_assignment -name IP_TOOL_VERSION "20.1"
set_global_assignment -name IP_GENERATED_DEVICE_FAMILY "{MAX 10}"
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) "fifo_pc_to_bus.v"]

View File

@ -0,0 +1,183 @@
// megafunction wizard: %FIFO%
// GENERATION: STANDARD
// VERSION: WM1.0
// MODULE: dcfifo
// ============================================================
// File Name: fifo_pc_to_bus.v
// Megafunction Name(s):
// dcfifo
//
// Simulation Library Files(s):
// altera_mf
// ============================================================
// ************************************************************
// THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE!
//
// 20.1.0 Build 711 06/05/2020 SJ Lite Edition
// ************************************************************
//Copyright (C) 2020 Intel Corporation. All rights reserved.
//Your use of Intel Corporation's design tools, logic functions
//and other software and tools, and any partner logic
//functions, and any output files from any of the foregoing
//(including device programming or simulation files), and any
//associated documentation or information are expressly subject
//to the terms and conditions of the Intel Program License
//Subscription Agreement, the Intel Quartus Prime License Agreement,
//the Intel FPGA IP License Agreement, or other applicable license
//agreement, including, without limitation, that your use is for
//the sole purpose of programming logic devices manufactured by
//Intel and sold by Intel or its authorized distributors. Please
//refer to the applicable agreement for further details, at
//https://fpgasoftware.intel.com/eula.
// synopsys translate_off
`timescale 1 ps / 1 ps
// synopsys translate_on
module fifo_pc_to_bus (
aclr,
data,
rdclk,
rdreq,
wrclk,
wrreq,
q,
rdempty,
wrusedw);
input aclr;
input [39:0] data;
input rdclk;
input rdreq;
input wrclk;
input wrreq;
output [39:0] q;
output rdempty;
output [10:0] wrusedw;
`ifndef ALTERA_RESERVED_QIS
// synopsys translate_off
`endif
tri0 aclr;
`ifndef ALTERA_RESERVED_QIS
// synopsys translate_on
`endif
wire [39:0] sub_wire0;
wire sub_wire1;
wire [10:0] sub_wire2;
wire [39:0] q = sub_wire0[39:0];
wire rdempty = sub_wire1;
wire [10:0] wrusedw = sub_wire2[10:0];
dcfifo dcfifo_component (
.aclr (aclr),
.data (data),
.rdclk (rdclk),
.rdreq (rdreq),
.wrclk (wrclk),
.wrreq (wrreq),
.q (sub_wire0),
.rdempty (sub_wire1),
.wrusedw (sub_wire2),
.eccstatus (),
.rdfull (),
.rdusedw (),
.wrempty (),
.wrfull ());
defparam
dcfifo_component.add_usedw_msb_bit = "ON",
dcfifo_component.intended_device_family = "MAX 10",
dcfifo_component.lpm_numwords = 1024,
dcfifo_component.lpm_showahead = "ON",
dcfifo_component.lpm_type = "dcfifo",
dcfifo_component.lpm_width = 40,
dcfifo_component.lpm_widthu = 11,
dcfifo_component.overflow_checking = "ON",
dcfifo_component.rdsync_delaypipe = 4,
dcfifo_component.read_aclr_synch = "OFF",
dcfifo_component.underflow_checking = "ON",
dcfifo_component.use_eab = "ON",
dcfifo_component.write_aclr_synch = "OFF",
dcfifo_component.wrsync_delaypipe = 4;
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: CLOCKS_ARE_SYNCHRONIZED NUMERIC "0"
// Retrieval info: PRIVATE: Clock NUMERIC "4"
// Retrieval info: PRIVATE: Depth NUMERIC "1024"
// Retrieval info: PRIVATE: Empty NUMERIC "1"
// Retrieval info: PRIVATE: Full NUMERIC "1"
// Retrieval info: PRIVATE: INTENDED_DEVICE_FAMILY STRING "MAX 10"
// Retrieval info: PRIVATE: LE_BasedFIFO NUMERIC "0"
// 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 "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"
// Retrieval info: PRIVATE: UsedW NUMERIC "1"
// Retrieval info: PRIVATE: Width NUMERIC "40"
// Retrieval info: PRIVATE: dc_aclr NUMERIC "1"
// Retrieval info: PRIVATE: diff_widths NUMERIC "0"
// Retrieval info: PRIVATE: msb_usedw NUMERIC "1"
// Retrieval info: PRIVATE: output_width NUMERIC "40"
// Retrieval info: PRIVATE: rsEmpty NUMERIC "1"
// Retrieval info: PRIVATE: rsFull NUMERIC "0"
// Retrieval info: PRIVATE: rsUsedW NUMERIC "0"
// Retrieval info: PRIVATE: sc_aclr NUMERIC "0"
// Retrieval info: PRIVATE: sc_sclr NUMERIC "0"
// Retrieval info: PRIVATE: wsEmpty NUMERIC "0"
// Retrieval info: PRIVATE: wsFull NUMERIC "0"
// Retrieval info: PRIVATE: wsUsedW NUMERIC "1"
// Retrieval info: LIBRARY: altera_mf altera_mf.altera_mf_components.all
// Retrieval info: CONSTANT: ADD_USEDW_MSB_BIT STRING "ON"
// Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "MAX 10"
// Retrieval info: CONSTANT: LPM_NUMWORDS NUMERIC "1024"
// Retrieval info: CONSTANT: LPM_SHOWAHEAD STRING "ON"
// Retrieval info: CONSTANT: LPM_TYPE STRING "dcfifo"
// Retrieval info: CONSTANT: LPM_WIDTH NUMERIC "40"
// Retrieval info: CONSTANT: LPM_WIDTHU NUMERIC "11"
// Retrieval info: CONSTANT: OVERFLOW_CHECKING STRING "ON"
// Retrieval info: CONSTANT: RDSYNC_DELAYPIPE NUMERIC "4"
// Retrieval info: CONSTANT: READ_ACLR_SYNCH STRING "OFF"
// Retrieval info: CONSTANT: UNDERFLOW_CHECKING STRING "ON"
// Retrieval info: CONSTANT: USE_EAB STRING "ON"
// Retrieval info: CONSTANT: WRITE_ACLR_SYNCH STRING "OFF"
// Retrieval info: CONSTANT: WRSYNC_DELAYPIPE NUMERIC "4"
// Retrieval info: USED_PORT: aclr 0 0 0 0 INPUT GND "aclr"
// Retrieval info: USED_PORT: data 0 0 40 0 INPUT NODEFVAL "data[39..0]"
// Retrieval info: USED_PORT: q 0 0 40 0 OUTPUT NODEFVAL "q[39..0]"
// Retrieval info: USED_PORT: rdclk 0 0 0 0 INPUT NODEFVAL "rdclk"
// Retrieval info: USED_PORT: rdempty 0 0 0 0 OUTPUT NODEFVAL "rdempty"
// Retrieval info: USED_PORT: rdreq 0 0 0 0 INPUT NODEFVAL "rdreq"
// Retrieval info: USED_PORT: wrclk 0 0 0 0 INPUT NODEFVAL "wrclk"
// Retrieval info: USED_PORT: wrreq 0 0 0 0 INPUT NODEFVAL "wrreq"
// Retrieval info: USED_PORT: wrusedw 0 0 11 0 OUTPUT NODEFVAL "wrusedw[10..0]"
// Retrieval info: CONNECT: @aclr 0 0 0 0 aclr 0 0 0 0
// Retrieval info: CONNECT: @data 0 0 40 0 data 0 0 40 0
// Retrieval info: CONNECT: @rdclk 0 0 0 0 rdclk 0 0 0 0
// Retrieval info: CONNECT: @rdreq 0 0 0 0 rdreq 0 0 0 0
// Retrieval info: CONNECT: @wrclk 0 0 0 0 wrclk 0 0 0 0
// Retrieval info: CONNECT: @wrreq 0 0 0 0 wrreq 0 0 0 0
// Retrieval info: CONNECT: q 0 0 40 0 @q 0 0 40 0
// Retrieval info: CONNECT: rdempty 0 0 0 0 @rdempty 0 0 0 0
// Retrieval info: CONNECT: wrusedw 0 0 11 0 @wrusedw 0 0 11 0
// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_pc_to_bus.v TRUE
// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_pc_to_bus.inc FALSE
// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_pc_to_bus.cmp FALSE
// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_pc_to_bus.bsf FALSE
// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_pc_to_bus_inst.v FALSE
// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_pc_to_bus_bb.v FALSE
// Retrieval info: LIB_FILE: altera_mf

View File

@ -0,0 +1,76 @@
set_global_assignment -entity "gpio_ddro" -library "gpio_ddro" -name IP_TOOL_NAME "altera_gpio_lite"
set_global_assignment -entity "gpio_ddro" -library "gpio_ddro" -name IP_TOOL_VERSION "20.1"
set_global_assignment -entity "gpio_ddro" -library "gpio_ddro" -name IP_TOOL_ENV "mwpim"
set_global_assignment -entity "gpio_ddro" -library "gpio_ddro" -name IP_TARGETED_DEVICE_FAMILY "MAX 10"
set_global_assignment -entity "gpio_ddro" -library "gpio_ddro" -name IP_GENERATED_DEVICE_FAMILY "{MAX 10}"
set_global_assignment -entity "gpio_ddro" -library "gpio_ddro" -name IP_QSYS_MODE "UNKNOWN"
set_global_assignment -name SYNTHESIS_ONLY_QIP ON
set_global_assignment -entity "gpio_ddro" -library "gpio_ddro" -name IP_COMPONENT_NAME "Z3Bpb19kZHJv"
set_global_assignment -entity "gpio_ddro" -library "gpio_ddro" -name IP_COMPONENT_DISPLAY_NAME "R1BJTyBMaXRlIEludGVsIEZQR0EgSVA="
set_global_assignment -entity "gpio_ddro" -library "gpio_ddro" -name IP_COMPONENT_REPORT_HIERARCHY "Off"
set_global_assignment -entity "gpio_ddro" -library "gpio_ddro" -name IP_COMPONENT_INTERNAL "Off"
set_global_assignment -entity "gpio_ddro" -library "gpio_ddro" -name IP_COMPONENT_AUTHOR "SW50ZWwgQ29ycG9yYXRpb24="
set_global_assignment -entity "gpio_ddro" -library "gpio_ddro" -name IP_COMPONENT_VERSION "MjAuMQ=="
set_global_assignment -entity "gpio_ddro" -library "gpio_ddro" -name IP_COMPONENT_DESCRIPTION "R1BJTyBMaXRlIEludGVsIEZQR0EgSVA="
set_global_assignment -entity "altera_gpio_lite" -library "gpio_ddro" -name IP_COMPONENT_NAME "YWx0ZXJhX2dwaW9fbGl0ZQ=="
set_global_assignment -entity "altera_gpio_lite" -library "gpio_ddro" -name IP_COMPONENT_DISPLAY_NAME "R1BJTyBMaXRlIEludGVsIEZQR0EgSVA="
set_global_assignment -entity "altera_gpio_lite" -library "gpio_ddro" -name IP_COMPONENT_REPORT_HIERARCHY "Off"
set_global_assignment -entity "altera_gpio_lite" -library "gpio_ddro" -name IP_COMPONENT_INTERNAL "Off"
set_global_assignment -entity "altera_gpio_lite" -library "gpio_ddro" -name IP_COMPONENT_AUTHOR "SW50ZWwgQ29ycG9yYXRpb24="
set_global_assignment -entity "altera_gpio_lite" -library "gpio_ddro" -name IP_COMPONENT_VERSION "MjAuMQ=="
set_global_assignment -entity "altera_gpio_lite" -library "gpio_ddro" -name IP_COMPONENT_DESCRIPTION "R1BJTyBMaXRlIEludGVsIEZQR0EgSVA="
set_global_assignment -entity "altera_gpio_lite" -library "gpio_ddro" -name IP_COMPONENT_PARAMETER "REVWSUNFX0ZBTUlMWQ==::TUFYIDEw::RGV2aWNlIGZhbWlseQ=="
set_global_assignment -entity "altera_gpio_lite" -library "gpio_ddro" -name IP_COMPONENT_PARAMETER "UElOX1RZUEU=::b3V0cHV0::RGF0YSBkaXJlY3Rpb24="
set_global_assignment -entity "altera_gpio_lite" -library "gpio_ddro" -name IP_COMPONENT_PARAMETER "U0laRQ==::MQ==::RGF0YSB3aWR0aA=="
set_global_assignment -entity "altera_gpio_lite" -library "gpio_ddro" -name IP_COMPONENT_PARAMETER "Z3VpX3RydWVfZGlmZl9idWY=::ZmFsc2U=::VXNlIHRydWUgZGlmZmVyZW50aWFsIGJ1ZmZlcg=="
set_global_assignment -entity "altera_gpio_lite" -library "gpio_ddro" -name IP_COMPONENT_PARAMETER "Z3VpX3BzZXVkb19kaWZmX2J1Zg==::ZmFsc2U=::VXNlIHBzZXVkbyBkaWZmZXJlbnRpYWwgYnVmZmVy"
set_global_assignment -entity "altera_gpio_lite" -library "gpio_ddro" -name IP_COMPONENT_PARAMETER "Z3VpX2J1c19ob2xk::ZmFsc2U=::VXNlIGJ1cy1ob2xkIGNpcmN1aXRyeQ=="
set_global_assignment -entity "altera_gpio_lite" -library "gpio_ddro" -name IP_COMPONENT_PARAMETER "Z3VpX29wZW5fZHJhaW4=::ZmFsc2U=::VXNlIG9wZW4gZHJhaW4gb3V0cHV0"
set_global_assignment -entity "altera_gpio_lite" -library "gpio_ddro" -name IP_COMPONENT_PARAMETER "Z3VpX2VuYWJsZV9vZV9wb3J0::ZmFsc2U=::RW5hYmxlIG9lIHBvcnQ="
set_global_assignment -entity "altera_gpio_lite" -library "gpio_ddro" -name IP_COMPONENT_PARAMETER "Z3VpX2lvX3JlZ19tb2Rl::ZGRy::UmVnaXN0ZXIgbW9kZQ=="
set_global_assignment -entity "altera_gpio_lite" -library "gpio_ddro" -name IP_COMPONENT_PARAMETER "Z3VpX2VuYWJsZV9hY2xyX3BvcnQ=::ZmFsc2U=::RW5hYmxlIGFjbHIgcG9ydA=="
set_global_assignment -entity "altera_gpio_lite" -library "gpio_ddro" -name IP_COMPONENT_PARAMETER "Z3VpX2VuYWJsZV9hc2V0X3BvcnQ=::ZmFsc2U=::RW5hYmxlIGFzZXQgcG9ydA=="
set_global_assignment -entity "altera_gpio_lite" -library "gpio_ddro" -name IP_COMPONENT_PARAMETER "Z3VpX2VuYWJsZV9zY2xyX3BvcnQ=::ZmFsc2U=::RW5hYmxlIHNjbHIgcG9ydA=="
set_global_assignment -entity "altera_gpio_lite" -library "gpio_ddro" -name IP_COMPONENT_PARAMETER "Z3VpX3NldF9yZWdpc3RlcnNfdG9fcG93ZXJfdXBfaGlnaA==::ZmFsc2U=::U2V0IHJlZ2lzdGVycyB0byBwb3dlciB1cCBoaWdoICh3aGVuIGFjbHIsIHNjbHIgYW5kIGFzZXQgcG9ydHMgYXJlIG5vdCB1c2VkKQ=="
set_global_assignment -entity "altera_gpio_lite" -library "gpio_ddro" -name IP_COMPONENT_PARAMETER "Z3VpX2Nsb2NrX2VuYWJsZQ==::dHJ1ZQ==::RW5hYmxlIGluY2xvY2tlbi9vdXRjbG9ja2VuIHBvcnRz"
set_global_assignment -entity "altera_gpio_lite" -library "gpio_ddro" -name IP_COMPONENT_PARAMETER "Z3VpX2ludmVydF9vdXRwdXQ=::ZmFsc2U=::SW52ZXJ0IGRpbg=="
set_global_assignment -entity "altera_gpio_lite" -library "gpio_ddro" -name IP_COMPONENT_PARAMETER "Z3VpX3VzZV9yZWdpc3Rlcl90b19kcml2ZV9vYnVmX29l::ZmFsc2U=::VXNlIGEgc2luZ2xlIHJlZ2lzdGVyIHRvIGRyaXZlIHRoZSBvdXRwdXQgZW5hYmxlIChvZSkgc2lnbmFsIGF0IHRoZSBJL08gYnVmZmVy"
set_global_assignment -entity "altera_gpio_lite" -library "gpio_ddro" -name IP_COMPONENT_PARAMETER "Z3VpX3VzZV9kZGlvX3JlZ190b19kcml2ZV9vZQ==::ZmFsc2U=::VXNlIERESU8gcmVnaXN0ZXJzIHRvIGRyaXZlIHRoZSBvdXRwdXQgZW5hYmxlIChvZSkgc2lnbmFsIGF0IHRoZSBJL08gYnVmZmVy"
set_global_assignment -entity "altera_gpio_lite" -library "gpio_ddro" -name IP_COMPONENT_PARAMETER "Z3VpX3VzZV9hZHZhbmNlZF9kZHJfZmVhdHVyZXM=::ZmFsc2U=::RW5hYmxlIGFkdmFuY2VkIEREUiBmZWF0dXJlcw=="
set_global_assignment -entity "altera_gpio_lite" -library "gpio_ddro" -name IP_COMPONENT_PARAMETER "Z3VpX2VuYWJsZV9waGFzZV9kZXRlY3Rvcl9mb3JfY2s=::ZmFsc2U=::RW5hYmxlIFBoYXNlIERldGVjdG9yIGZyb20gQ0sgbG9vcGJhY2sgc2lnbmFs"
set_global_assignment -entity "altera_gpio_lite" -library "gpio_ddro" -name IP_COMPONENT_PARAMETER "Z3VpX2VuYWJsZV9vZV9oYWxmX2N5Y2xlX2RlbGF5::dHJ1ZQ==::QWRkIGhhbGYtY3ljbGUgZGVsYXkgdG8gT0Ugc2lnbmFs"
set_global_assignment -entity "altera_gpio_lite" -library "gpio_ddro" -name IP_COMPONENT_PARAMETER "Z3VpX2VuYWJsZV9ocl9jbG9jaw==::ZmFsc2U=::RW5hYmxlIGhhbGYtcmF0ZSBjbG9jayBwb3J0"
set_global_assignment -entity "altera_gpio_lite" -library "gpio_ddro" -name IP_COMPONENT_PARAMETER "Z3VpX2VuYWJsZV9pbnZlcnRfaHJfY2xvY2tfcG9ydA==::ZmFsc2U=::RW5hYmxlIGludmVydF9ocl9jbG9jayBwb3J0"
set_global_assignment -entity "altera_gpio_lite" -library "gpio_ddro" -name IP_COMPONENT_PARAMETER "Z3VpX2ludmVydF9jbGtkaXZfaW5wdXRfY2xvY2s=::ZmFsc2U=::SW52ZXJ0IGNsb2NrIGRpdmlkZXIgaW5wdXQgY2xvY2s="
set_global_assignment -entity "altera_gpio_lite" -library "gpio_ddro" -name IP_COMPONENT_PARAMETER "Z3VpX2ludmVydF9vdXRwdXRfY2xvY2s=::ZmFsc2U=::SW52ZXJ0IERESU8gb3V0Y2xvY2s="
set_global_assignment -entity "altera_gpio_lite" -library "gpio_ddro" -name IP_COMPONENT_PARAMETER "Z3VpX2ludmVydF9vZV9pbmNsb2Nr::ZmFsc2U=::SW52ZXJ0IG91dHB1dCBlbmFibGUgKG9lKSByZWdpc3RlciBpbmNsb2Nr"
set_global_assignment -entity "altera_gpio_lite" -library "gpio_ddro" -name IP_COMPONENT_PARAMETER "UkVHSVNURVJfTU9ERQ==::ZGRy::UkVHSVNURVJfTU9ERQ=="
set_global_assignment -entity "altera_gpio_lite" -library "gpio_ddro" -name IP_COMPONENT_PARAMETER "QlVGRkVSX1RZUEU=::c2luZ2xlLWVuZGVk::QlVGRkVSX1RZUEU="
set_global_assignment -entity "altera_gpio_lite" -library "gpio_ddro" -name IP_COMPONENT_PARAMETER "QVNZTkNfTU9ERQ==::bm9uZQ==::QVNZTkNfTU9ERQ=="
set_global_assignment -entity "altera_gpio_lite" -library "gpio_ddro" -name IP_COMPONENT_PARAMETER "U1lOQ19NT0RF::bm9uZQ==::U1lOQ19NT0RF"
set_global_assignment -entity "altera_gpio_lite" -library "gpio_ddro" -name IP_COMPONENT_PARAMETER "QlVTX0hPTEQ=::ZmFsc2U=::QlVTX0hPTEQ="
set_global_assignment -entity "altera_gpio_lite" -library "gpio_ddro" -name IP_COMPONENT_PARAMETER "T1BFTl9EUkFJTl9PVVRQVVQ=::ZmFsc2U=::T1BFTl9EUkFJTl9PVVRQVVQ="
set_global_assignment -entity "altera_gpio_lite" -library "gpio_ddro" -name IP_COMPONENT_PARAMETER "RU5BQkxFX09FX1BPUlQ=::ZmFsc2U=::RU5BQkxFX09FX1BPUlQ="
set_global_assignment -entity "altera_gpio_lite" -library "gpio_ddro" -name IP_COMPONENT_PARAMETER "RU5BQkxFX05TTEVFUF9QT1JU::ZmFsc2U=::RU5BQkxFX05TTEVFUF9QT1JU"
set_global_assignment -entity "altera_gpio_lite" -library "gpio_ddro" -name IP_COMPONENT_PARAMETER "RU5BQkxFX0NMT0NLX0VOQV9QT1JU::dHJ1ZQ==::RU5BQkxFX0NMT0NLX0VOQV9QT1JU"
set_global_assignment -entity "altera_gpio_lite" -library "gpio_ddro" -name IP_COMPONENT_PARAMETER "U0VUX1JFR0lTVEVSX09VVFBVVFNfSElHSA==::ZmFsc2U=::U0VUX1JFR0lTVEVSX09VVFBVVFNfSElHSA=="
set_global_assignment -entity "altera_gpio_lite" -library "gpio_ddro" -name IP_COMPONENT_PARAMETER "SU5WRVJUX09VVFBVVA==::ZmFsc2U=::SU5WRVJUX09VVFBVVA=="
set_global_assignment -entity "altera_gpio_lite" -library "gpio_ddro" -name IP_COMPONENT_PARAMETER "SU5WRVJUX0lOUFVUX0NMT0NL::ZmFsc2U=::SU5WRVJUX0lOUFVUX0NMT0NL"
set_global_assignment -entity "altera_gpio_lite" -library "gpio_ddro" -name IP_COMPONENT_PARAMETER "VVNFX09ORV9SRUdfVE9fRFJJVkVfT0U=::ZmFsc2U=::VVNFX09ORV9SRUdfVE9fRFJJVkVfT0U="
set_global_assignment -entity "altera_gpio_lite" -library "gpio_ddro" -name IP_COMPONENT_PARAMETER "VVNFX0RESU9fUkVHX1RPX0RSSVZFX09F::ZmFsc2U=::VVNFX0RESU9fUkVHX1RPX0RSSVZFX09F"
set_global_assignment -entity "altera_gpio_lite" -library "gpio_ddro" -name IP_COMPONENT_PARAMETER "VVNFX0FEVkFOQ0VEX0REUl9GRUFUVVJFUw==::ZmFsc2U=::VVNFX0FEVkFOQ0VEX0REUl9GRUFUVVJFUw=="
set_global_assignment -entity "altera_gpio_lite" -library "gpio_ddro" -name IP_COMPONENT_PARAMETER "VVNFX0FEVkFOQ0VEX0REUl9GRUFUVVJFU19GT1JfSU5QVVRfT05MWQ==::ZmFsc2U=::VVNFX0FEVkFOQ0VEX0REUl9GRUFUVVJFU19GT1JfSU5QVVRfT05MWQ=="
set_global_assignment -entity "altera_gpio_lite" -library "gpio_ddro" -name IP_COMPONENT_PARAMETER "RU5BQkxFX09FX0hBTEZfQ1lDTEVfREVMQVk=::dHJ1ZQ==::RU5BQkxFX09FX0hBTEZfQ1lDTEVfREVMQVk="
set_global_assignment -entity "altera_gpio_lite" -library "gpio_ddro" -name IP_COMPONENT_PARAMETER "SU5WRVJUX0NMS0RJVl9JTlBVVF9DTE9DSw==::ZmFsc2U=::SU5WRVJUX0NMS0RJVl9JTlBVVF9DTE9DSw=="
set_global_assignment -entity "altera_gpio_lite" -library "gpio_ddro" -name IP_COMPONENT_PARAMETER "RU5BQkxFX1BIQVNFX0lOVkVSVF9DVFJMX1BPUlQ=::ZmFsc2U=::RU5BQkxFX1BIQVNFX0lOVkVSVF9DVFJMX1BPUlQ="
set_global_assignment -entity "altera_gpio_lite" -library "gpio_ddro" -name IP_COMPONENT_PARAMETER "RU5BQkxFX0hSX0NMT0NL::ZmFsc2U=::RU5BQkxFX0hSX0NMT0NL"
set_global_assignment -entity "altera_gpio_lite" -library "gpio_ddro" -name IP_COMPONENT_PARAMETER "SU5WRVJUX09VVFBVVF9DTE9DSw==::ZmFsc2U=::SU5WRVJUX09VVFBVVF9DTE9DSw=="
set_global_assignment -entity "altera_gpio_lite" -library "gpio_ddro" -name IP_COMPONENT_PARAMETER "SU5WRVJUX09FX0lOQ0xPQ0s=::ZmFsc2U=::SU5WRVJUX09FX0lOQ0xPQ0s="
set_global_assignment -entity "altera_gpio_lite" -library "gpio_ddro" -name IP_COMPONENT_PARAMETER "RU5BQkxFX1BIQVNFX0RFVEVDVE9SX0ZPUl9DSw==::ZmFsc2U=::RU5BQkxFX1BIQVNFX0RFVEVDVE9SX0ZPUl9DSw=="
set_global_assignment -library "gpio_ddro" -name VERILOG_FILE [file join $::quartus(qip_path) "gpio_ddro.v"]
set_global_assignment -library "gpio_ddro" -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) "gpio_ddro/altera_gpio_lite.sv"]
set_global_assignment -entity "altera_gpio_lite" -library "gpio_ddro" -name IP_TOOL_NAME "altera_gpio_lite"
set_global_assignment -entity "altera_gpio_lite" -library "gpio_ddro" -name IP_TOOL_VERSION "20.1"
set_global_assignment -entity "altera_gpio_lite" -library "gpio_ddro" -name IP_TOOL_ENV "mwpim"

View File

@ -0,0 +1,124 @@
// megafunction wizard: %GPIO Lite Intel FPGA IP v20.1%
// GENERATION: XML
// gpio_ddro.v
// Generated using ACDS version 20.1 711
`timescale 1 ps / 1 ps
module gpio_ddro (
input wire outclock, // outclock.export
input wire outclocken, // outclocken.export
input wire [1:0] din, // din.export
output wire [0:0] pad_out // pad_out.export
);
altera_gpio_lite #(
.PIN_TYPE ("output"),
.SIZE (1),
.REGISTER_MODE ("ddr"),
.BUFFER_TYPE ("single-ended"),
.ASYNC_MODE ("none"),
.SYNC_MODE ("none"),
.BUS_HOLD ("false"),
.OPEN_DRAIN_OUTPUT ("false"),
.ENABLE_OE_PORT ("false"),
.ENABLE_NSLEEP_PORT ("false"),
.ENABLE_CLOCK_ENA_PORT ("true"),
.SET_REGISTER_OUTPUTS_HIGH ("false"),
.INVERT_OUTPUT ("false"),
.INVERT_INPUT_CLOCK ("false"),
.USE_ONE_REG_TO_DRIVE_OE ("false"),
.USE_DDIO_REG_TO_DRIVE_OE ("false"),
.USE_ADVANCED_DDR_FEATURES ("false"),
.USE_ADVANCED_DDR_FEATURES_FOR_INPUT_ONLY ("false"),
.ENABLE_OE_HALF_CYCLE_DELAY ("true"),
.INVERT_CLKDIV_INPUT_CLOCK ("false"),
.ENABLE_PHASE_INVERT_CTRL_PORT ("false"),
.ENABLE_HR_CLOCK ("false"),
.INVERT_OUTPUT_CLOCK ("false"),
.INVERT_OE_INCLOCK ("false"),
.ENABLE_PHASE_DETECTOR_FOR_CK ("false")
) gpio_ddro_inst (
.outclock (outclock), // outclock.export
.outclocken (outclocken), // outclocken.export
.din (din), // din.export
.pad_out (pad_out), // pad_out.export
.inclock (1'b0), // (terminated)
.inclocken (1'b0), // (terminated)
.fr_clock (), // (terminated)
.hr_clock (), // (terminated)
.invert_hr_clock (1'b0), // (terminated)
.phy_mem_clock (1'b0), // (terminated)
.mimic_clock (), // (terminated)
.dout (), // (terminated)
.pad_io (), // (terminated)
.pad_io_b (), // (terminated)
.pad_in (1'b0), // (terminated)
.pad_in_b (1'b0), // (terminated)
.pad_out_b (), // (terminated)
.aset (1'b0), // (terminated)
.aclr (1'b0), // (terminated)
.sclr (1'b0), // (terminated)
.nsleep (1'b0), // (terminated)
.oe (1'b0) // (terminated)
);
endmodule
// Retrieval info: <?xml version="1.0"?>
//<!--
// Generated by Altera MegaWizard Launcher Utility version 1.0
// ************************************************************
// THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE!
// ************************************************************
// Copyright (C) 1991-2020 Altera Corporation
// Any megafunction design, and related net list (encrypted or decrypted),
// support information, device programming or simulation file, and any other
// associated documentation or information provided by Altera or a partner
// under Altera's Megafunction Partnership Program may be used only to
// program PLD devices (but not masked PLD devices) from Altera. Any other
// use of such megafunction design, net list, support information, device
// programming or simulation file, or any other related documentation or
// information is prohibited for any other purpose, including, but not
// limited to modification, reverse engineering, de-compiling, or use with
// any other silicon devices, unless such use is explicitly licensed under
// a separate agreement with Altera or a megafunction partner. Title to
// the intellectual property, including patents, copyrights, trademarks,
// trade secrets, or maskworks, embodied in any such megafunction design,
// net list, support information, device programming or simulation file, or
// any other related documentation or information provided by Altera or a
// megafunction partner, remains with Altera, the megafunction partner, or
// their respective licensors. No other licenses, including any licenses
// needed under any third party's intellectual property, are provided herein.
//-->
// Retrieval info: <instance entity-name="altera_gpio_lite" version="20.1" >
// Retrieval info: <generic name="DEVICE_FAMILY" value="MAX 10" />
// Retrieval info: <generic name="PIN_TYPE" value="output" />
// Retrieval info: <generic name="SIZE" value="1" />
// Retrieval info: <generic name="gui_true_diff_buf" value="false" />
// Retrieval info: <generic name="gui_pseudo_diff_buf" value="false" />
// Retrieval info: <generic name="gui_bus_hold" value="false" />
// Retrieval info: <generic name="gui_open_drain" value="false" />
// Retrieval info: <generic name="gui_enable_oe_port" value="false" />
// Retrieval info: <generic name="gui_enable_nsleep_port" value="false" />
// Retrieval info: <generic name="gui_io_reg_mode" value="ddr" />
// Retrieval info: <generic name="gui_enable_aclr_port" value="false" />
// Retrieval info: <generic name="gui_enable_aset_port" value="false" />
// Retrieval info: <generic name="gui_enable_sclr_port" value="false" />
// Retrieval info: <generic name="gui_set_registers_to_power_up_high" value="false" />
// Retrieval info: <generic name="gui_clock_enable" value="true" />
// Retrieval info: <generic name="gui_invert_output" value="false" />
// Retrieval info: <generic name="gui_invert_input_clock" value="false" />
// Retrieval info: <generic name="gui_use_register_to_drive_obuf_oe" value="false" />
// Retrieval info: <generic name="gui_use_ddio_reg_to_drive_oe" value="false" />
// Retrieval info: <generic name="gui_use_advanced_ddr_features" value="false" />
// Retrieval info: <generic name="gui_enable_phase_detector_for_ck" value="false" />
// Retrieval info: <generic name="gui_enable_oe_half_cycle_delay" value="true" />
// Retrieval info: <generic name="gui_enable_hr_clock" value="false" />
// Retrieval info: <generic name="gui_enable_invert_hr_clock_port" value="false" />
// Retrieval info: <generic name="gui_invert_clkdiv_input_clock" value="false" />
// Retrieval info: <generic name="gui_invert_output_clock" value="false" />
// Retrieval info: <generic name="gui_invert_oe_inclock" value="false" />
// Retrieval info: <generic name="gui_use_hardened_ddio_input_registers" value="false" />
// Retrieval info: </instance>
// IPFS_FILES : gpio_ddro.vo
// RELATED_FILES: gpio_ddro.v, altera_gpio_lite.sv

File diff suppressed because it is too large Load Diff

11
fw/rtl/intel/pll/pll.ppf Normal file
View File

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE pinplan>
<pinplan intended_family="MAX 10" variation_name="pll" megafunction_name="ALTPLL" specifies="all_ports">
<global>
<pin name="inclk0" direction="input" scope="external" source="clock" />
<pin name="c0" direction="output" scope="external" source="clock" />
<pin name="c1" direction="output" scope="external" source="clock" />
<pin name="locked" direction="output" scope="external" />
</global>
</pinplan>

5
fw/rtl/intel/pll/pll.qip Normal file
View File

@ -0,0 +1,5 @@
set_global_assignment -name IP_TOOL_NAME "ALTPLL"
set_global_assignment -name IP_TOOL_VERSION "20.1"
set_global_assignment -name IP_GENERATED_DEVICE_FAMILY "{MAX 10}"
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) "pll.v"]
set_global_assignment -name MISC_FILE [file join $::quartus(qip_path) "pll.ppf"]

341
fw/rtl/intel/pll/pll.v Normal file
View File

@ -0,0 +1,341 @@
// megafunction wizard: %ALTPLL%
// GENERATION: STANDARD
// VERSION: WM1.0
// MODULE: altpll
// ============================================================
// File Name: pll.v
// Megafunction Name(s):
// altpll
//
// Simulation Library Files(s):
// altera_mf
// ============================================================
// ************************************************************
// THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE!
//
// 20.1.0 Build 711 06/05/2020 SJ Lite Edition
// ************************************************************
//Copyright (C) 2020 Intel Corporation. All rights reserved.
//Your use of Intel Corporation's design tools, logic functions
//and other software and tools, and any partner logic
//functions, and any output files from any of the foregoing
//(including device programming or simulation files), and any
//associated documentation or information are expressly subject
//to the terms and conditions of the Intel Program License
//Subscription Agreement, the Intel Quartus Prime License Agreement,
//the Intel FPGA IP License Agreement, or other applicable license
//agreement, including, without limitation, that your use is for
//the sole purpose of programming logic devices manufactured by
//Intel and sold by Intel or its authorized distributors. Please
//refer to the applicable agreement for further details, at
//https://fpgasoftware.intel.com/eula.
// synopsys translate_off
`timescale 1 ps / 1 ps
// synopsys translate_on
module pll (
inclk0,
c0,
c1,
locked);
input inclk0;
output c0;
output c1;
output locked;
wire [0:0] sub_wire2 = 1'h0;
wire [4:0] sub_wire3;
wire sub_wire6;
wire sub_wire0 = inclk0;
wire [1:0] sub_wire1 = {sub_wire2, sub_wire0};
wire [1:1] sub_wire5 = sub_wire3[1:1];
wire [0:0] sub_wire4 = sub_wire3[0:0];
wire c0 = sub_wire4;
wire c1 = sub_wire5;
wire locked = sub_wire6;
altpll altpll_component (
.inclk (sub_wire1),
.clk (sub_wire3),
.locked (sub_wire6),
.activeclock (),
.areset (1'b0),
.clkbad (),
.clkena ({6{1'b1}}),
.clkloss (),
.clkswitch (1'b0),
.configupdate (1'b0),
.enable0 (),
.enable1 (),
.extclk (),
.extclkena ({4{1'b1}}),
.fbin (1'b1),
.fbmimicbidir (),
.fbout (),
.fref (),
.icdrclk (),
.pfdena (1'b1),
.phasecounterselect ({4{1'b1}}),
.phasedone (),
.phasestep (1'b1),
.phaseupdown (1'b1),
.pllena (1'b1),
.scanaclr (1'b0),
.scanclk (1'b0),
.scanclkena (1'b1),
.scandata (1'b0),
.scandataout (),
.scandone (),
.scanread (1'b0),
.scanwrite (1'b0),
.sclkout0 (),
.sclkout1 (),
.vcooverrange (),
.vcounderrange ());
defparam
altpll_component.bandwidth_type = "AUTO",
altpll_component.clk0_divide_by = 5,
altpll_component.clk0_duty_cycle = 50,
altpll_component.clk0_multiply_by = 9,
altpll_component.clk0_phase_shift = "0",
altpll_component.clk1_divide_by = 5,
altpll_component.clk1_duty_cycle = 50,
altpll_component.clk1_multiply_by = 9,
altpll_component.clk1_phase_shift = "-2778",
altpll_component.compensate_clock = "CLK0",
altpll_component.inclk0_input_frequency = 20000,
altpll_component.intended_device_family = "MAX 10",
altpll_component.lpm_hint = "CBX_MODULE_PREFIX=pll",
altpll_component.lpm_type = "altpll",
altpll_component.operation_mode = "NORMAL",
altpll_component.pll_type = "AUTO",
altpll_component.port_activeclock = "PORT_UNUSED",
altpll_component.port_areset = "PORT_UNUSED",
altpll_component.port_clkbad0 = "PORT_UNUSED",
altpll_component.port_clkbad1 = "PORT_UNUSED",
altpll_component.port_clkloss = "PORT_UNUSED",
altpll_component.port_clkswitch = "PORT_UNUSED",
altpll_component.port_configupdate = "PORT_UNUSED",
altpll_component.port_fbin = "PORT_UNUSED",
altpll_component.port_inclk0 = "PORT_USED",
altpll_component.port_inclk1 = "PORT_UNUSED",
altpll_component.port_locked = "PORT_USED",
altpll_component.port_pfdena = "PORT_UNUSED",
altpll_component.port_phasecounterselect = "PORT_UNUSED",
altpll_component.port_phasedone = "PORT_UNUSED",
altpll_component.port_phasestep = "PORT_UNUSED",
altpll_component.port_phaseupdown = "PORT_UNUSED",
altpll_component.port_pllena = "PORT_UNUSED",
altpll_component.port_scanaclr = "PORT_UNUSED",
altpll_component.port_scanclk = "PORT_UNUSED",
altpll_component.port_scanclkena = "PORT_UNUSED",
altpll_component.port_scandata = "PORT_UNUSED",
altpll_component.port_scandataout = "PORT_UNUSED",
altpll_component.port_scandone = "PORT_UNUSED",
altpll_component.port_scanread = "PORT_UNUSED",
altpll_component.port_scanwrite = "PORT_UNUSED",
altpll_component.port_clk0 = "PORT_USED",
altpll_component.port_clk1 = "PORT_USED",
altpll_component.port_clk2 = "PORT_UNUSED",
altpll_component.port_clk3 = "PORT_UNUSED",
altpll_component.port_clk4 = "PORT_UNUSED",
altpll_component.port_clk5 = "PORT_UNUSED",
altpll_component.port_clkena0 = "PORT_UNUSED",
altpll_component.port_clkena1 = "PORT_UNUSED",
altpll_component.port_clkena2 = "PORT_UNUSED",
altpll_component.port_clkena3 = "PORT_UNUSED",
altpll_component.port_clkena4 = "PORT_UNUSED",
altpll_component.port_clkena5 = "PORT_UNUSED",
altpll_component.port_extclk0 = "PORT_UNUSED",
altpll_component.port_extclk1 = "PORT_UNUSED",
altpll_component.port_extclk2 = "PORT_UNUSED",
altpll_component.port_extclk3 = "PORT_UNUSED",
altpll_component.self_reset_on_loss_lock = "ON",
altpll_component.width_clock = 5;
endmodule
// ============================================================
// CNX file retrieval info
// ============================================================
// Retrieval info: PRIVATE: ACTIVECLK_CHECK STRING "0"
// Retrieval info: PRIVATE: BANDWIDTH STRING "1.000"
// Retrieval info: PRIVATE: BANDWIDTH_FEATURE_ENABLED STRING "1"
// Retrieval info: PRIVATE: BANDWIDTH_FREQ_UNIT STRING "MHz"
// Retrieval info: PRIVATE: BANDWIDTH_PRESET STRING "High"
// Retrieval info: PRIVATE: BANDWIDTH_USE_AUTO STRING "1"
// Retrieval info: PRIVATE: BANDWIDTH_USE_PRESET STRING "0"
// Retrieval info: PRIVATE: CLKBAD_SWITCHOVER_CHECK STRING "0"
// Retrieval info: PRIVATE: CLKLOSS_CHECK STRING "0"
// Retrieval info: PRIVATE: CLKSWITCH_CHECK STRING "0"
// Retrieval info: PRIVATE: CNX_NO_COMPENSATE_RADIO STRING "0"
// Retrieval info: PRIVATE: CREATE_CLKBAD_CHECK STRING "0"
// Retrieval info: PRIVATE: CREATE_INCLK1_CHECK STRING "0"
// Retrieval info: PRIVATE: CUR_DEDICATED_CLK STRING "c0"
// Retrieval info: PRIVATE: CUR_FBIN_CLK STRING "c0"
// Retrieval info: PRIVATE: DEVICE_SPEED_GRADE STRING "8"
// Retrieval info: PRIVATE: DIV_FACTOR0 NUMERIC "1"
// Retrieval info: PRIVATE: DIV_FACTOR1 NUMERIC "1"
// Retrieval info: PRIVATE: DUTY_CYCLE0 STRING "50.00000000"
// Retrieval info: PRIVATE: DUTY_CYCLE1 STRING "50.00000000"
// Retrieval info: PRIVATE: EFF_OUTPUT_FREQ_VALUE0 STRING "90.000000"
// Retrieval info: PRIVATE: EFF_OUTPUT_FREQ_VALUE1 STRING "90.000000"
// Retrieval info: PRIVATE: EXPLICIT_SWITCHOVER_COUNTER STRING "0"
// Retrieval info: PRIVATE: EXT_FEEDBACK_RADIO STRING "0"
// Retrieval info: PRIVATE: GLOCKED_COUNTER_EDIT_CHANGED STRING "1"
// Retrieval info: PRIVATE: GLOCKED_FEATURE_ENABLED STRING "0"
// Retrieval info: PRIVATE: GLOCKED_MODE_CHECK STRING "0"
// Retrieval info: PRIVATE: GLOCK_COUNTER_EDIT NUMERIC "1048575"
// Retrieval info: PRIVATE: HAS_MANUAL_SWITCHOVER STRING "1"
// Retrieval info: PRIVATE: INCLK0_FREQ_EDIT STRING "50.000"
// Retrieval info: PRIVATE: INCLK0_FREQ_UNIT_COMBO STRING "MHz"
// Retrieval info: PRIVATE: INCLK1_FREQ_EDIT STRING "100.000"
// Retrieval info: PRIVATE: INCLK1_FREQ_EDIT_CHANGED STRING "1"
// Retrieval info: PRIVATE: INCLK1_FREQ_UNIT_CHANGED STRING "1"
// Retrieval info: PRIVATE: INCLK1_FREQ_UNIT_COMBO STRING "MHz"
// Retrieval info: PRIVATE: INTENDED_DEVICE_FAMILY STRING "MAX 10"
// Retrieval info: PRIVATE: INT_FEEDBACK__MODE_RADIO STRING "1"
// Retrieval info: PRIVATE: LOCKED_OUTPUT_CHECK STRING "1"
// Retrieval info: PRIVATE: LONG_SCAN_RADIO STRING "1"
// Retrieval info: PRIVATE: LVDS_MODE_DATA_RATE STRING "Not Available"
// Retrieval info: PRIVATE: LVDS_MODE_DATA_RATE_DIRTY NUMERIC "0"
// Retrieval info: PRIVATE: LVDS_PHASE_SHIFT_UNIT0 STRING "deg"
// Retrieval info: PRIVATE: LVDS_PHASE_SHIFT_UNIT1 STRING "deg"
// Retrieval info: PRIVATE: MIG_DEVICE_SPEED_GRADE STRING "Any"
// Retrieval info: PRIVATE: MIRROR_CLK0 STRING "0"
// Retrieval info: PRIVATE: MIRROR_CLK1 STRING "0"
// Retrieval info: PRIVATE: MULT_FACTOR0 NUMERIC "1"
// Retrieval info: PRIVATE: MULT_FACTOR1 NUMERIC "1"
// Retrieval info: PRIVATE: NORMAL_MODE_RADIO STRING "1"
// Retrieval info: PRIVATE: OUTPUT_FREQ0 STRING "90.00000000"
// Retrieval info: PRIVATE: OUTPUT_FREQ1 STRING "90.00000000"
// Retrieval info: PRIVATE: OUTPUT_FREQ_MODE0 STRING "1"
// Retrieval info: PRIVATE: OUTPUT_FREQ_MODE1 STRING "1"
// Retrieval info: PRIVATE: OUTPUT_FREQ_UNIT0 STRING "MHz"
// Retrieval info: PRIVATE: OUTPUT_FREQ_UNIT1 STRING "MHz"
// Retrieval info: PRIVATE: PHASE_RECONFIG_FEATURE_ENABLED STRING "1"
// Retrieval info: PRIVATE: PHASE_RECONFIG_INPUTS_CHECK STRING "0"
// Retrieval info: PRIVATE: PHASE_SHIFT0 STRING "0.00000000"
// Retrieval info: PRIVATE: PHASE_SHIFT1 STRING "-90.00000000"
// Retrieval info: PRIVATE: PHASE_SHIFT_STEP_ENABLED_CHECK STRING "0"
// Retrieval info: PRIVATE: PHASE_SHIFT_UNIT0 STRING "deg"
// Retrieval info: PRIVATE: PHASE_SHIFT_UNIT1 STRING "deg"
// Retrieval info: PRIVATE: PLL_ADVANCED_PARAM_CHECK STRING "0"
// Retrieval info: PRIVATE: PLL_ARESET_CHECK STRING "0"
// Retrieval info: PRIVATE: PLL_AUTOPLL_CHECK NUMERIC "1"
// Retrieval info: PRIVATE: PLL_ENHPLL_CHECK NUMERIC "0"
// Retrieval info: PRIVATE: PLL_FASTPLL_CHECK NUMERIC "0"
// Retrieval info: PRIVATE: PLL_FBMIMIC_CHECK STRING "0"
// Retrieval info: PRIVATE: PLL_LVDS_PLL_CHECK NUMERIC "0"
// Retrieval info: PRIVATE: PLL_PFDENA_CHECK STRING "0"
// Retrieval info: PRIVATE: PLL_TARGET_HARCOPY_CHECK NUMERIC "0"
// Retrieval info: PRIVATE: PRIMARY_CLK_COMBO STRING "inclk0"
// Retrieval info: PRIVATE: RECONFIG_FILE STRING "pll.mif"
// Retrieval info: PRIVATE: SACN_INPUTS_CHECK STRING "0"
// Retrieval info: PRIVATE: SCAN_FEATURE_ENABLED STRING "1"
// Retrieval info: PRIVATE: SELF_RESET_LOCK_LOSS STRING "1"
// Retrieval info: PRIVATE: SHORT_SCAN_RADIO STRING "0"
// Retrieval info: PRIVATE: SPREAD_FEATURE_ENABLED STRING "0"
// Retrieval info: PRIVATE: SPREAD_FREQ STRING "50.000"
// Retrieval info: PRIVATE: SPREAD_FREQ_UNIT STRING "KHz"
// Retrieval info: PRIVATE: SPREAD_PERCENT STRING "0.500"
// Retrieval info: PRIVATE: SPREAD_USE STRING "0"
// Retrieval info: PRIVATE: SRC_SYNCH_COMP_RADIO STRING "0"
// Retrieval info: PRIVATE: STICKY_CLK0 STRING "1"
// Retrieval info: PRIVATE: STICKY_CLK1 STRING "1"
// Retrieval info: PRIVATE: STICKY_CLK2 STRING "0"
// Retrieval info: PRIVATE: STICKY_CLK3 STRING "0"
// Retrieval info: PRIVATE: STICKY_CLK4 STRING "0"
// Retrieval info: PRIVATE: SWITCHOVER_COUNT_EDIT NUMERIC "1"
// Retrieval info: PRIVATE: SWITCHOVER_FEATURE_ENABLED STRING "1"
// Retrieval info: PRIVATE: SYNTH_WRAPPER_GEN_POSTFIX STRING "0"
// Retrieval info: PRIVATE: USE_CLK0 STRING "1"
// Retrieval info: PRIVATE: USE_CLK1 STRING "1"
// Retrieval info: PRIVATE: USE_CLKENA0 STRING "0"
// Retrieval info: PRIVATE: USE_CLKENA1 STRING "0"
// Retrieval info: PRIVATE: USE_MIL_SPEED_GRADE NUMERIC "0"
// Retrieval info: PRIVATE: ZERO_DELAY_RADIO STRING "0"
// Retrieval info: LIBRARY: altera_mf altera_mf.altera_mf_components.all
// Retrieval info: CONSTANT: BANDWIDTH_TYPE STRING "AUTO"
// Retrieval info: CONSTANT: CLK0_DIVIDE_BY NUMERIC "5"
// Retrieval info: CONSTANT: CLK0_DUTY_CYCLE NUMERIC "50"
// Retrieval info: CONSTANT: CLK0_MULTIPLY_BY NUMERIC "9"
// Retrieval info: CONSTANT: CLK0_PHASE_SHIFT STRING "0"
// Retrieval info: CONSTANT: CLK1_DIVIDE_BY NUMERIC "5"
// Retrieval info: CONSTANT: CLK1_DUTY_CYCLE NUMERIC "50"
// Retrieval info: CONSTANT: CLK1_MULTIPLY_BY NUMERIC "9"
// Retrieval info: CONSTANT: CLK1_PHASE_SHIFT STRING "-2778"
// Retrieval info: CONSTANT: COMPENSATE_CLOCK STRING "CLK0"
// Retrieval info: CONSTANT: INCLK0_INPUT_FREQUENCY NUMERIC "20000"
// Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "MAX 10"
// Retrieval info: CONSTANT: LPM_TYPE STRING "altpll"
// Retrieval info: CONSTANT: OPERATION_MODE STRING "NORMAL"
// Retrieval info: CONSTANT: PLL_TYPE STRING "AUTO"
// Retrieval info: CONSTANT: PORT_ACTIVECLOCK STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_ARESET STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_CLKBAD0 STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_CLKBAD1 STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_CLKLOSS STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_CLKSWITCH STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_CONFIGUPDATE STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_FBIN STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_INCLK0 STRING "PORT_USED"
// Retrieval info: CONSTANT: PORT_INCLK1 STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_LOCKED STRING "PORT_USED"
// Retrieval info: CONSTANT: PORT_PFDENA STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_PHASECOUNTERSELECT STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_PHASEDONE STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_PHASESTEP STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_PHASEUPDOWN STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_PLLENA STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_SCANACLR STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_SCANCLK STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_SCANCLKENA STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_SCANDATA STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_SCANDATAOUT STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_SCANDONE STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_SCANREAD STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_SCANWRITE STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_clk0 STRING "PORT_USED"
// Retrieval info: CONSTANT: PORT_clk1 STRING "PORT_USED"
// Retrieval info: CONSTANT: PORT_clk2 STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_clk3 STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_clk4 STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_clk5 STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_clkena0 STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_clkena1 STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_clkena2 STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_clkena3 STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_clkena4 STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_clkena5 STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_extclk0 STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_extclk1 STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_extclk2 STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_extclk3 STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: SELF_RESET_ON_LOSS_LOCK STRING "ON"
// Retrieval info: CONSTANT: WIDTH_CLOCK NUMERIC "5"
// Retrieval info: USED_PORT: @clk 0 0 5 0 OUTPUT_CLK_EXT VCC "@clk[4..0]"
// Retrieval info: USED_PORT: c0 0 0 0 0 OUTPUT_CLK_EXT VCC "c0"
// Retrieval info: USED_PORT: c1 0 0 0 0 OUTPUT_CLK_EXT VCC "c1"
// Retrieval info: USED_PORT: inclk0 0 0 0 0 INPUT_CLK_EXT GND "inclk0"
// Retrieval info: USED_PORT: locked 0 0 0 0 OUTPUT GND "locked"
// Retrieval info: CONNECT: @inclk 0 0 1 1 GND 0 0 0 0
// Retrieval info: CONNECT: @inclk 0 0 1 0 inclk0 0 0 0 0
// Retrieval info: CONNECT: c0 0 0 0 0 @clk 0 0 1 0
// Retrieval info: CONNECT: c1 0 0 0 0 @clk 0 0 1 1
// Retrieval info: CONNECT: locked 0 0 0 0 @locked 0 0 0 0
// Retrieval info: GEN_FILE: TYPE_NORMAL pll.v TRUE
// Retrieval info: GEN_FILE: TYPE_NORMAL pll.ppf TRUE
// Retrieval info: GEN_FILE: TYPE_NORMAL pll.inc FALSE
// Retrieval info: GEN_FILE: TYPE_NORMAL pll.cmp FALSE
// Retrieval info: GEN_FILE: TYPE_NORMAL pll.bsf FALSE
// Retrieval info: GEN_FILE: TYPE_NORMAL pll_inst.v FALSE
// Retrieval info: GEN_FILE: TYPE_NORMAL pll_bb.v FALSE
// Retrieval info: LIB_FILE: altera_mf
// Retrieval info: CBX_MODULE_PREFIX: ON

95
fw/rtl/n64_pi.v Normal file
View File

@ -0,0 +1,95 @@
module n64_pi (
input i_clk,
input i_reset,
input [1:0] i_n64_pi_alel,
input [1:0] i_n64_pi_aleh,
input i_n64_pi_read,
input i_n64_pi_write,
input [15:0] i_n64_pi_ad,
output reg [15:0] o_n64_pi_ad,
output o_n64_pi_ad_mode,
output reg o_read_rq,
output reg o_write_rq,
input i_ack,
output reg [31:0] o_address,
input [31:0] i_data,
output reg [31:0] o_data,
input i_address_valid
);
reg r_last_n64_pi_alel;
reg r_last_n64_pi_aleh;
reg r_last_n64_pi_read;
reg r_last_n64_pi_write;
reg r_first_transfer;
reg r_word_select;
reg [31:0] r_data_i_buffer;
reg [15:0] r_word_buffer;
reg r_address_valid;
reg r_address_valid_buffer;
wire w_aleh_valid = (&i_n64_pi_alel) && (&i_n64_pi_aleh);
wire w_alel_valid = (&i_n64_pi_alel) && (~|i_n64_pi_aleh);
wire w_address_op = r_last_n64_pi_alel && !i_n64_pi_alel[0] && !i_n64_pi_aleh[0];
wire w_read_op = r_last_n64_pi_read && !i_n64_pi_read;
wire w_write_op = r_last_n64_pi_write && !i_n64_pi_write;
wire w_bus_read_op = w_read_op && r_word_select;
wire w_bus_write_op = w_write_op && !r_word_select;
wire w_address_increment = w_bus_read_op || (w_bus_write_op && !r_first_transfer);
assign o_n64_pi_ad_mode = !i_reset && !i_n64_pi_alel[0] && !i_n64_pi_aleh[0] && !i_n64_pi_read && !r_last_n64_pi_read && r_address_valid;
always @(posedge i_clk) begin
r_last_n64_pi_alel <= i_n64_pi_alel[0];
r_last_n64_pi_aleh <= i_n64_pi_aleh[0];
r_last_n64_pi_read <= i_n64_pi_read;
r_last_n64_pi_write <= i_n64_pi_write;
o_read_rq <= 1'b0;
o_write_rq <= 1'b0;
if (!i_reset) begin
o_read_rq <= w_bus_read_op || w_address_op;
o_write_rq <= w_bus_write_op;
if (w_aleh_valid) begin
o_address <= {i_n64_pi_ad, o_address[15:0]};
end
if (w_alel_valid) begin
o_address <= {o_address[31:16], i_n64_pi_ad[15:1], 1'b0};
end
if (w_address_op) begin
r_first_transfer <= 1'b1;
r_word_select <= 1'b1;
end
if (w_read_op || w_write_op) begin
r_word_select <= ~r_word_select;
o_address <= {o_address[31:10], (o_address[9:0] + {w_address_increment, 2'b00})};
end
if (w_write_op && !r_word_select) begin
r_first_transfer <= 1'b0;
end
if (w_read_op) begin
{o_n64_pi_ad, r_word_buffer} <= r_word_select ? r_data_i_buffer : {r_word_buffer, 16'hXXXX};
end
if (w_write_op) begin
o_data <= {o_data[15:0], i_n64_pi_ad};
end
if (w_bus_read_op) begin
r_address_valid <= r_address_valid_buffer;
end
if (o_read_rq) begin
r_address_valid_buffer <= i_address_valid;
end
if (i_ack) begin
r_data_i_buffer <= i_data;
end
end
end
endmodule

289
fw/rtl/pc.v Normal file
View File

@ -0,0 +1,289 @@
module pc (
input i_clk,
input i_reset,
input i_ftdi_clk,
input i_ftdi_cs,
input i_ftdi_do,
output reg o_ftdi_di,
output reg o_read_rq,
output reg o_write_rq,
input i_ack,
output reg [31:0] o_address,
input [31:0] i_data,
output reg [31:0] o_data,
input i_bus_active,
output reg o_n64_disable
);
// Command ids
localparam [7:0] CMD_STATUS = 8'h00;
localparam [7:0] CMD_CONFIG = 8'h10;
localparam [7:0] CMD_ADDR = 8'h20;
localparam [7:0] CMD_READ_LENGTH = 8'h30;
localparam [7:0] CMD_WRITE = 8'h40;
localparam [7:0] CMD_READ = 8'h50;
localparam [7:0] CMD_CART_RESET = 8'hFC;
localparam [7:0] CMD_FLUSH_WRITE = 8'hFD;
localparam [7:0] CMD_FLUSH_READ = 8'hFE;
localparam [7:0] CMD_SPI_RESET = 8'hFF;
// SPI [de]serializer
reg [4:0] r_spi_bit_counter;
reg [30:0] r_spi_i_shift;
reg [7:0] r_spi_cmd;
reg r_spi_cmd_valid;
reg r_fifo_pc_to_bus_flush;
reg r_fifo_bus_to_pc_flush;
reg r_fifo_pc_to_bus_rq;
reg r_fifo_bus_to_pc_rq;
wire [31:0] w_fifo_bus_to_pc_data;
wire [10:0] w_fifo_pc_to_bus_usedw;
wire [10:0] w_fifo_bus_to_pc_usedw;
reg r_n64_disabled_ff1, r_n64_disabled_ff2;
reg r_address_inc_ff1, r_address_inc_ff2;
wire [31:0] w_spi_status = {
8'hAA, // Test control byte
r_address_inc_ff2,
r_n64_disabled_ff2,
w_fifo_pc_to_bus_usedw,
w_fifo_bus_to_pc_usedw,
};
// SPI bit control and command stage
always @(posedge i_ftdi_clk or posedge i_ftdi_cs or posedge i_reset) begin
if (i_ftdi_cs || i_reset) begin
r_spi_bit_counter <= 5'd0;
r_spi_cmd <= 8'd0;
r_spi_cmd_valid <= 1'b0;
end else begin
r_spi_bit_counter <= r_spi_bit_counter + 5'd1;
if (&r_spi_bit_counter[2:0] && !r_spi_cmd_valid) begin
r_spi_bit_counter <= 5'd0;
r_spi_cmd <= {r_spi_i_shift[6:0], i_ftdi_do};
r_spi_cmd_valid <= 1'b1;
end
end
end
// SPI input shift register
always @(posedge i_ftdi_clk) begin
r_spi_i_shift <= {r_spi_i_shift[29:0], i_ftdi_do};
end
// SPI command control signals
always @(posedge i_ftdi_clk or posedge i_ftdi_cs or posedge i_reset) begin
if (i_ftdi_cs || i_reset) begin
r_fifo_pc_to_bus_flush <= 1'b0;
r_fifo_bus_to_pc_flush <= 1'b0;
r_fifo_pc_to_bus_rq <= 1'b0;
r_fifo_bus_to_pc_rq <= 1'b0;
end else begin
if (&r_spi_bit_counter[2:0] && !r_spi_cmd_valid) begin
case ({r_spi_i_shift[6:0], i_ftdi_do})
CMD_FLUSH_WRITE: r_fifo_pc_to_bus_flush <= 1'b1;
CMD_FLUSH_READ: r_fifo_bus_to_pc_flush <= 1'b1;
CMD_SPI_RESET: begin
r_fifo_pc_to_bus_flush <= 1'b1;
r_fifo_bus_to_pc_flush <= 1'b1;
end
endcase
end
if (r_spi_bit_counter == 5'd30) begin
case (r_spi_cmd)
CMD_CONFIG, CMD_ADDR, CMD_READ_LENGTH, CMD_WRITE, CMD_CART_RESET: begin
r_fifo_pc_to_bus_rq <= 1'b1;
end
CMD_READ: r_fifo_bus_to_pc_rq <= 1'b1;
endcase
end else begin
r_fifo_pc_to_bus_rq <= 1'b0;
r_fifo_bus_to_pc_rq <= 1'b0;
end
end
end
// SPI output data stage
always @(negedge i_ftdi_clk or posedge i_ftdi_cs or posedge i_reset) begin
if (i_ftdi_cs || i_reset) begin
o_ftdi_di <= 1'b0;
end else begin
if (r_spi_cmd_valid) begin
case (r_spi_cmd)
CMD_STATUS: o_ftdi_di <= w_spi_status[5'd31 - r_spi_bit_counter];
CMD_READ: o_ftdi_di <= w_fifo_bus_to_pc_data[5'd31 - r_spi_bit_counter];
default: o_ftdi_di <= 1'b1;
endcase
end else begin
o_ftdi_di <= 1'b0;
end
end
end
// sys_clk -> spi_clk signal synchronization
reg r_address_inc;
always @(posedge i_ftdi_clk) begin
{r_n64_disabled_ff2, r_n64_disabled_ff1} <= {r_n64_disabled_ff1, o_n64_disable};
{r_address_inc_ff2, r_address_inc_ff1} <= {r_address_inc_ff1, r_address_inc};
end
// FIFOs
reg r_fifo_pc_to_bus_rdreq;
wire [39:0] w_fifo_pc_to_bus_q;
wire w_fifo_pc_to_bus_rdempty;
wire [7:0] w_fifo_pc_to_bus_cmd;
wire [31:0] w_fifo_pc_to_bus_data;
assign {w_fifo_pc_to_bus_cmd, w_fifo_pc_to_bus_data} = w_fifo_pc_to_bus_q;
wire w_fifo_bus_to_pc_wrfull;
reg r_bus_read_in_progress;
fifo_pc_to_bus fifo_pc_to_bus_inst (
.aclr(r_fifo_pc_to_bus_flush),
.wrclk(i_ftdi_clk || i_ftdi_cs),
.wrreq(r_fifo_pc_to_bus_rq),
.data({r_spi_cmd, r_spi_i_shift, i_ftdi_do}),
.wrusedw(w_fifo_pc_to_bus_usedw),
.rdclk(i_clk),
.rdreq(r_fifo_pc_to_bus_rdreq),
.q(w_fifo_pc_to_bus_q),
.rdempty(w_fifo_pc_to_bus_rdempty)
);
fifo_bus_to_pc fifo_bus_to_pc_inst (
.aclr(r_fifo_bus_to_pc_flush),
.rdclk(i_ftdi_clk || i_ftdi_cs),
.rdreq(r_fifo_bus_to_pc_rq),
.q(w_fifo_bus_to_pc_data),
.rdusedw(w_fifo_bus_to_pc_usedw),
.wrclk(i_clk),
.wrreq(i_ack && r_bus_read_in_progress),
.data(i_data),
.wrfull(w_fifo_bus_to_pc_wrfull),
);
// Bus controller
reg r_cmd_config;
reg r_cmd_addr;
reg r_cmd_read_length;
reg r_cmd_write;
reg r_cmd_cart_reset;
always @(posedge i_clk) begin
r_cmd_config <= w_fifo_pc_to_bus_cmd == CMD_CONFIG;
r_cmd_addr <= w_fifo_pc_to_bus_cmd == CMD_ADDR;
r_cmd_read_length <= w_fifo_pc_to_bus_cmd == CMD_READ_LENGTH;
r_cmd_write <= w_fifo_pc_to_bus_cmd == CMD_WRITE;
r_cmd_cart_reset <= w_fifo_pc_to_bus_cmd == CMD_CART_RESET;
end
reg r_bus_read_pending_rq;
reg [23:0] r_bus_read_remaining_words; // Max 64 MB
reg r_bus_write_in_progress;
always @(posedge i_clk or posedge i_reset) begin
if (i_reset) begin
o_read_rq <= 1'b0;
o_write_rq <= 1'b0;
o_n64_disable <= 1'b0;
r_address_inc <= 1'b1;
r_fifo_pc_to_bus_rdreq <= 1'b0;
r_bus_read_pending_rq <= 1'b0;
r_bus_read_in_progress <= 1'b0;
r_bus_write_in_progress <= 1'b0;
end else begin
o_read_rq <= 1'b0;
o_write_rq <= 1'b0;
r_fifo_pc_to_bus_rdreq <= 1'b0;
if (!w_fifo_pc_to_bus_rdempty && !r_fifo_pc_to_bus_rdreq && !r_bus_read_in_progress && !r_bus_write_in_progress) begin
if (r_cmd_config && !i_bus_active) begin
{r_address_inc, o_n64_disable} <= w_fifo_pc_to_bus_data[1:0];
r_fifo_pc_to_bus_rdreq <= 1'b1;
end
if (r_cmd_addr) begin
o_address <= w_fifo_pc_to_bus_data;
r_fifo_pc_to_bus_rdreq <= 1'b1;
end
if (r_cmd_read_length) begin
if (o_n64_disable) begin
r_bus_read_pending_rq <= 1'b1;
r_bus_read_remaining_words <= w_fifo_pc_to_bus_data[23:0];
r_bus_read_in_progress <= 1'b1;
end else begin
r_fifo_pc_to_bus_rdreq <= 1'b1;
end
end
if (r_cmd_write) begin
if (o_n64_disable) begin
o_write_rq <= 1'b1;
o_data <= w_fifo_pc_to_bus_data;
r_bus_write_in_progress <= 1'b1;
end else begin
r_fifo_pc_to_bus_rdreq <= 1'b1;
end
end
end
if (i_ack) o_address[31:2] <= o_address[31:2] + r_address_inc;
if (!w_fifo_bus_to_pc_wrfull && r_bus_read_pending_rq) begin
o_read_rq <= 1'b1;
r_bus_read_pending_rq <= 1'b0;
end
if (i_ack && r_bus_read_in_progress) begin
if (r_bus_read_remaining_words > 24'd0) begin
r_bus_read_pending_rq <= 1'b1;
r_bus_read_remaining_words <= r_bus_read_remaining_words - 24'd1;
end else begin
r_fifo_pc_to_bus_rdreq <= 1'b1;
r_bus_read_in_progress <= 1'b0;
end
end
if (i_ack && r_bus_write_in_progress) begin
r_fifo_pc_to_bus_rdreq <= 1'b1;
r_bus_write_in_progress <= 1'b0;
end
if (!w_fifo_pc_to_bus_rdempty && !r_fifo_pc_to_bus_rdreq && r_cmd_cart_reset) begin
o_read_rq <= 1'b0;
o_write_rq <= 1'b0;
o_n64_disable <= 1'b0;
r_address_inc <= 1'b1;
r_fifo_pc_to_bus_rdreq <= 1'b1;
r_bus_read_pending_rq <= 1'b0;
r_bus_read_in_progress <= 1'b0;
r_bus_write_in_progress <= 1'b0;
end
end
end
endmodule

133
fw/rtl/sdram.v Normal file
View File

@ -0,0 +1,133 @@
module sdram (
input i_clk,
input i_reset,
output o_sdram_cs,
output o_sdram_ras,
output o_sdram_cas,
output o_sdram_we,
output [1:0] o_sdram_ba,
output [12:0] o_sdram_a,
input [15:0] i_sdram_dq,
output [15:0] o_sdram_dq,
output o_sdram_dq_mode,
input i_select,
input i_read_rq,
input i_write_rq,
output reg o_ack,
input [31:0] i_address,
input [31:0] i_data,
output reg [31:0] o_data
);
reg r_wb_cyc;
reg r_wb_stb;
wire w_wb_cyc;
wire w_wb_stb;
wire [31:0] w_wb_addr;
wire w_wb_ack;
wire w_wb_stall;
wire [31:0] w_wb_o_data;
assign w_wb_cyc = w_wb_stb || r_wb_cyc;
assign w_wb_stb = i_select && !w_wb_stall && (i_read_rq || i_write_rq || r_wb_stb);
always @(posedge i_clk or posedge i_reset) begin
if (i_reset) begin
r_wb_cyc <= 1'b0;
end else begin
if (w_wb_stb) begin
r_wb_cyc <= 1'b1;
end else if (w_wb_ack) begin
r_wb_cyc <= 1'b0;
end
end
end
// FIXME: Ugly solution for 16-bit address read align
reg r_unaligned_access;
reg r_next_word;
assign w_wb_addr = i_address + {r_next_word, 2'b00};
always @(posedge i_clk or posedge i_reset) begin
if (i_reset) begin
o_ack <= 1'b0;
r_wb_stb <= 1'b0;
r_unaligned_access <= 1'b0;
r_next_word <= 1'b0;
end else begin
o_ack <= 1'b0;
r_wb_stb <= 1'b0;
if (i_read_rq) begin
if (!i_address[1]) begin
r_unaligned_access <= 1'b0;
r_next_word <= 1'b0;
end else begin
r_unaligned_access <= 1'b1;
r_next_word <= 1'b0;
end
end
if (w_wb_ack) begin
if (!r_unaligned_access) begin
o_data <= w_wb_o_data;
o_ack <= 1'b1;
end else begin
if (!r_next_word) begin
o_data[31:16] <= w_wb_o_data[15:0];
r_wb_stb <= 1'b1;
r_next_word <= 1'b1;
end else begin
o_ack <= 1'b1;
o_data[15:0] <= w_wb_o_data[31:16];
r_unaligned_access <= 1'b0;
r_next_word <= 1'b0;
end
end
end
end
end
// Weird shift register required by this module
// https://github.com/ZipCPU/arrowzip/blob/master/rtl/arrowzip/toplevel.v#L176
reg [15:0] r_sdram_dq_ext_clk;
reg [15:0] r_sdram_dq;
always @(posedge i_clk) begin
{r_sdram_dq, r_sdram_dq_ext_clk} <= {r_sdram_dq_ext_clk, i_sdram_dq};
end
wbsdram wbsdram_inst (
.i_clk(i_clk),
.i_wb_cyc(w_wb_cyc),
.i_wb_stb(w_wb_stb), // FIXME: Currently strobe can be missed when w_wb_stall is high
.i_wb_we(i_write_rq),
.i_wb_addr(w_wb_addr[31:2]),
.i_wb_data(i_data),
.i_wb_sel({4'b1111}), // No need to control this signal
.o_wb_ack(w_wb_ack),
.o_wb_stall(w_wb_stall),
.o_wb_data(w_wb_o_data),
.o_ram_cs_n(o_sdram_cs),
// .o_ram_cke(), // No connection on PCB
.o_ram_ras_n(o_sdram_ras),
.o_ram_cas_n(o_sdram_cas),
.o_ram_we_n(o_sdram_we),
.o_ram_bs(o_sdram_ba),
.o_ram_addr(o_sdram_a),
.o_ram_dmod(o_sdram_dq_mode),
.i_ram_data(r_sdram_dq),
.o_ram_data(o_sdram_dq)
// .o_ram_dqm(), // No connection on PCB
// .o_debug() // No need for this signal
);
endmodule

387
fw/rtl/top.v Normal file
View File

@ -0,0 +1,387 @@
module top (
input i_clk,
input i_ftdi_clk,
input i_ftdi_cs,
input i_ftdi_do,
output o_ftdi_di,
input i_n64_nmi,
input i_n64_reset,
input i_n64_pi_alel,
input i_n64_pi_aleh,
input i_n64_pi_read,
input i_n64_pi_write,
inout [15:0] io_n64_pi_ad,
input i_n64_si_clk,
inout io_n64_si_dq,
input i_n64_cic_clk,
inout io_n64_cic_dq,
output o_sdram_clk,
output o_sdram_cs,
output o_sdram_cas,
output o_sdram_ras,
output o_sdram_we,
output [1:0] o_sdram_ba,
output [12:0] o_sdram_a,
inout [15:0] io_sdram_dq,
output o_sd_clk,
inout io_sd_cmd,
inout [3:0] io_sd_dat,
output o_flash_clk,
output o_flash_cs,
inout [3:0] io_flash_dq,
output o_sram_clk,
output o_sram_cs,
inout [3:0] io_sram_dq,
output o_rtc_scl,
inout io_rtc_sda,
output o_led,
inout [7:0] io_pmod
);
// Clock and reset
wire w_sys_clk;
wire w_sdram_clk;
wire w_pll_lock;
wire w_sys_reset = ~w_pll_lock;
pll sys_pll(
.inclk0(i_clk),
.c0(w_sys_clk),
.c1(w_sdram_clk),
.locked(w_pll_lock)
);
gpio_ddro sdram_clk_ddro(
.outclock(w_sdram_clk),
.outclocken(1'b1),
.din({1'b0, 1'b1}),
.pad_out(o_sdram_clk)
);
// Input synchronization
reg r_n64_nmi_ff1, r_n64_nmi_ff2;
reg r_n64_reset_ff1, r_n64_reset_ff2;
reg r_n64_alel_ff1, r_n64_alel_ff2;
reg r_n64_aleh_ff1, r_n64_aleh_ff2;
reg r_n64_read_ff1, r_n64_read_ff2;
reg r_n64_write_ff1, r_n64_write_ff2;
reg r_n64_si_clk_ff1, r_n64_si_clk_ff2;
reg r_n64_cic_clk_ff1, r_n64_cic_clk_ff2;
always @(posedge w_sys_clk or posedge w_sys_reset) begin
if (w_sys_reset) begin
r_n64_nmi_ff1 <= 1'b0;
r_n64_nmi_ff2 <= 1'b0;
r_n64_reset_ff1 <= 1'b0;
r_n64_reset_ff2 <= 1'b0;
r_n64_alel_ff1 <= 1'b0;
r_n64_alel_ff2 <= 1'b0;
r_n64_aleh_ff1 <= 1'b0;
r_n64_aleh_ff2 <= 1'b0;
r_n64_read_ff1 <= 1'b0;
r_n64_read_ff2 <= 1'b0;
r_n64_write_ff1 <= 1'b0;
r_n64_write_ff2 <= 1'b0;
r_n64_si_clk_ff1 <= 1'b0;
r_n64_si_clk_ff2 <= 1'b0;
r_n64_cic_clk_ff1 <= 1'b0;
r_n64_cic_clk_ff2 <= 1'b0;
end else begin
{r_n64_nmi_ff2, r_n64_nmi_ff1} <= {r_n64_nmi_ff1, i_n64_nmi};
{r_n64_reset_ff2, r_n64_reset_ff1} <= {r_n64_reset_ff1, i_n64_reset};
{r_n64_alel_ff2, r_n64_alel_ff1} <= {r_n64_alel_ff1, i_n64_pi_alel};
{r_n64_aleh_ff2, r_n64_aleh_ff1} <= {r_n64_aleh_ff1, i_n64_pi_aleh};
{r_n64_read_ff2, r_n64_read_ff1} <= {r_n64_read_ff1, i_n64_pi_read};
{r_n64_write_ff2, r_n64_write_ff1} <= {r_n64_write_ff1, i_n64_pi_write};
{r_n64_si_clk_ff2, r_n64_si_clk_ff1} <= {r_n64_si_clk_ff1, i_n64_si_clk};
{r_n64_cic_clk_ff2, r_n64_cic_clk_ff1} <= {r_n64_cic_clk_ff1, i_n64_cic_clk};
end
end
// Tri-state connection management
wire w_n64_pi_ad_mode;
wire [15:0] w_n64_pi_ad_o;
assign io_n64_pi_ad = w_n64_pi_ad_mode ? w_n64_pi_ad_o : 16'hZZZZ;
wire w_n64_si_dq_o;
assign io_n64_si_dq = w_n64_si_dq_o ? 1'bZ : 1'b0;
wire w_n64_cic_dq_o;
assign io_n64_cic_dq = w_n64_cic_dq_o ? 1'bZ : 1'b0;
wire w_sdram_dq_mode;
wire [15:0] w_sdram_dq_o;
assign io_sdram_dq = w_sdram_dq_mode ? w_sdram_dq_o : 16'hZZZZ;
wire w_sd_cmd_mode;
wire [1:0] w_sd_dat_mode;
wire w_sd_cmd_o;
wire [3:0] w_sd_dat_o;
assign io_sd_cmd = w_sd_cmd_mode ? w_sd_cmd_o : 1'bZ;
assign io_sd_dat = w_sd_dat_mode == 2'b00 ? {3'bZZZ, w_sd_dat_o[0]} :
w_sd_dat_mode == 2'b10 ? w_sd_dat_o : 4'bZZZZ;
wire [1:0] w_flash_dq_mode;
wire [3:0] w_flash_dq_o;
assign io_flash_dq = w_flash_dq_mode == 2'b00 ? {3'bZZZ, w_flash_dq_o[0]} :
w_flash_dq_mode == 2'b10 ? w_flash_dq_o : 4'bZZZZ;
wire [1:0] w_sram_dq_mode;
wire [3:0] w_sram_dq_o;
assign io_sram_dq = w_sram_dq_mode == 2'b00 ? {3'bZZZ, w_sram_dq_o[0]} :
w_sram_dq_mode == 2'b10 ? w_sram_dq_o : 4'bZZZZ;
wire w_rtc_sda_o;
assign io_rtc_sda = w_rtc_sda_o ? 1'bZ : 1'b0;
// Temporary assignments
assign w_n64_si_dq_o = 1'b1;
assign w_n64_cic_dq_o = 1'b1;
assign w_sd_cmd_mode = 1'b0;
assign w_sd_dat_mode = 2'b00;
assign w_sram_dq_mode = 2'b00;
assign w_rtc_sda_o = 1'b1;
assign io_pmod = 8'hZZ;
// Modules connection
wire w_n64_read_rq;
wire w_n64_write_rq;
wire w_n64_ack;
wire [31:0] w_n64_address;
wire [31:0] w_n64_i_data;
wire [31:0] w_n64_o_data;
wire w_pc_read_rq;
wire w_pc_write_rq;
wire w_pc_ack;
wire [31:0] w_pc_address;
wire [31:0] w_pc_i_data;
wire [31:0] w_pc_o_data;
wire w_n64_disable;
wire w_bus_read_rq;
wire w_bus_write_rq;
wire w_bus_ack;
wire [31:0] w_bus_address;
wire [31:0] w_bus_i_data;
wire [31:0] w_bus_o_data;
assign w_n64_ack = !w_n64_disable && w_bus_ack;
assign w_pc_ack = w_n64_disable && w_bus_ack;
assign w_bus_read_rq = w_n64_disable ? w_pc_read_rq : w_n64_read_rq;
assign w_bus_write_rq = w_n64_disable ? w_pc_write_rq : w_n64_write_rq;
assign w_bus_address = w_n64_disable ? w_pc_address : w_n64_address;
assign w_bus_o_data = w_n64_disable ? w_pc_o_data : w_n64_o_data;
wire w_cart_config_select;
wire w_flash_select;
wire w_flash_cfg_select;
wire w_sdram_select;
wire w_flash_enable;
wire w_sdram_enable;
wire w_address_valid;
wire w_cart_config_ack;
wire [31:0] w_cart_config_o_data;
wire w_flash_ack;
wire [31:0] w_flash_o_data;
wire w_sdram_ack;
wire [31:0] w_sdram_o_data;
reg r_empty_ack;
assign w_bus_ack = w_cart_config_ack || w_flash_ack || w_sdram_ack || r_empty_ack;
assign w_bus_i_data = w_cart_config_select ? w_cart_config_o_data :
(w_flash_select || w_flash_cfg_select) ? w_flash_o_data :
w_sdram_select ? w_sdram_o_data : 32'hFFFF_FFFF;
always @(posedge w_sys_clk) begin
r_empty_ack <= !w_address_valid && (w_bus_read_rq || w_bus_write_rq);
end
// Bus activity signal
reg r_bus_active;
wire w_bus_active = r_bus_active && !w_bus_ack;
always @(posedge w_sys_clk or posedge w_sys_reset) begin
if (w_sys_reset) begin
r_bus_active <= 1'b0;
end else begin
if (w_bus_read_rq || w_bus_write_rq) r_bus_active <= 1'b1;
if (w_bus_ack) r_bus_active <= 1'b0;
end
end
// Modules
pc pc_inst (
.i_clk(w_sys_clk),
.i_reset(w_sys_reset),
.i_ftdi_clk(i_ftdi_clk),
.i_ftdi_cs(i_ftdi_cs),
.i_ftdi_do(i_ftdi_do),
.o_ftdi_di(o_ftdi_di),
.o_read_rq(w_pc_read_rq),
.o_write_rq(w_pc_write_rq),
.i_ack(w_pc_ack),
.o_address(w_pc_address),
.i_data(w_bus_i_data),
.o_data(w_pc_o_data),
.i_bus_active(w_bus_active),
.o_n64_disable(w_n64_disable)
);
n64_pi n64_pi_inst (
.i_clk(w_sys_clk),
.i_reset(~r_n64_reset_ff2),
.i_n64_pi_alel({i_n64_pi_alel, r_n64_alel_ff2}),
.i_n64_pi_aleh({i_n64_pi_aleh, r_n64_aleh_ff2}),
.i_n64_pi_read(r_n64_read_ff2),
.i_n64_pi_write(r_n64_write_ff2),
.i_n64_pi_ad(io_n64_pi_ad),
.o_n64_pi_ad(w_n64_pi_ad_o),
.o_n64_pi_ad_mode(w_n64_pi_ad_mode),
.o_read_rq(w_n64_read_rq),
.o_write_rq(w_n64_write_rq),
.i_ack(w_n64_ack),
.o_address(w_n64_address),
.i_data(w_bus_i_data),
.o_data(w_n64_o_data),
.i_address_valid(w_address_valid)
);
address_decoder address_decoder_inst (
.i_address(w_bus_address),
.o_cart_config(w_cart_config_select),
.o_flash(w_flash_select),
.o_flash_cfg(w_flash_cfg_select),
.o_sdram(w_sdram_select),
.i_flash_enable(w_flash_enable),
.i_sdram_enable(w_sdram_enable),
.o_address_valid(w_address_valid)
);
cart_config cart_config_inst (
.i_clk(w_sys_clk),
.i_reset(w_sys_reset),
.i_n64_reset(~r_n64_reset_ff2),
.i_n64_nmi(~r_n64_nmi_ff2),
.i_select(w_cart_config_select),
.i_read_rq(w_bus_read_rq),
.i_write_rq(w_bus_write_rq),
.o_ack(w_cart_config_ack),
.i_address(w_bus_address),
.i_data(w_bus_o_data),
.o_data(w_cart_config_o_data),
.i_n64_disabled(w_n64_disable),
.o_flash_enable(w_flash_enable),
.o_sdram_enable(w_sdram_enable)
);
flash flash_inst (
.i_clk(w_sys_clk),
.i_reset(w_sys_reset),
.o_flash_clk(o_flash_clk),
.o_flash_cs(o_flash_cs),
.i_flash_dq(io_flash_dq),
.o_flash_dq(w_flash_dq_o),
.o_flash_dq_mode(w_flash_dq_mode),
.i_select(w_flash_select),
.i_cfg_select(w_flash_cfg_select),
.i_read_rq(w_bus_read_rq),
.i_write_rq(w_bus_write_rq),
.o_ack(w_flash_ack),
.i_address(w_bus_address),
.i_data(w_bus_o_data),
.o_data(w_flash_o_data)
);
sdram sdram_inst (
.i_clk(w_sys_clk),
.i_reset(w_sys_reset),
.o_sdram_cs(o_sdram_cs),
.o_sdram_ras(o_sdram_ras),
.o_sdram_cas(o_sdram_cas),
.o_sdram_we(o_sdram_we),
.o_sdram_ba(o_sdram_ba),
.o_sdram_a(o_sdram_a),
.i_sdram_dq(io_sdram_dq),
.o_sdram_dq(w_sdram_dq_o),
.o_sdram_dq_mode(w_sdram_dq_mode),
.i_select(w_sdram_select),
.i_read_rq(w_bus_read_rq),
.i_write_rq(w_bus_write_rq),
.o_ack(w_sdram_ack),
.i_address(w_bus_address),
.i_data(w_bus_o_data),
.o_data(w_sdram_o_data)
);
// LED
localparam ROLLING_LED_WIDTH = 8;
reg [(ROLLING_LED_WIDTH-1):0] r_rolling_led;
assign o_led = |r_rolling_led;
always @(posedge w_sys_clk or posedge w_sys_reset) begin
if (w_sys_reset) r_rolling_led <= {(ROLLING_LED_WIDTH){1'b0}};
else r_rolling_led <= {r_rolling_led[(ROLLING_LED_WIDTH-2):0], w_bus_active};
end
endmodule

6
hw/.gitignore vendored Normal file
View File

@ -0,0 +1,6 @@
*.b#*
*.l#*
*.s#*
*.pdf
*.zip
eagle.epf

View File

@ -0,0 +1,7 @@
# SummerCart64 Hardware
Schematics and PCB design for SummerCart64 done in Autodesk Eagle software.
## TODO
- Expand documentation

5643
hw/SummerCart64.brd Normal file

File diff suppressed because it is too large Load Diff

1532
hw/SummerCart64.lbr Normal file

File diff suppressed because it is too large Load Diff

17912
hw/SummerCart64.sch Normal file

File diff suppressed because it is too large Load Diff

View File

3
sw/SummerBanger64/.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
/__pycache__
/roms
*.z64

View File

@ -0,0 +1,7 @@
# SummerBanger64
A PC communication program for SummerCart64.
## TODO
- Expand documentation

View File

@ -0,0 +1,391 @@
#!/usr/bin/env python3
import argparse
import progressbar
import struct
import sys
import time
from pyftdi.spi import SpiController
class SummerBanger64:
# Command ids
__CMD_STATUS = 0x00
__CMD_CONFIG = 0x10
__CMD_ADDR = 0x20
__CMD_READ_LENGTH = 0x30
__CMD_WRITE = 0x40
__CMD_READ = 0x50
__CMD_CART_RESET = 0xFC
__CMD_FLUSH_WRITE = 0xFD
__CMD_FLUSH_READ = 0xFE
__CMD_SPI_RESET = 0xFF
# Size declarations
__FIFO_SIZE = 1024
__FIFO_SIZE_BYTES = __FIFO_SIZE * 4
__FLASH_PAGE_SIZE = 256
# Cart addresses
__SDRAM_ADDRESS = 0x10000000
__FLASH_ADDRESS = 0x18000000
__FLASH_CFG_ADDRESS = 0x1C000000
__CART_CONFIG_ADDRESS = 0x1E000000
__CIC_TYPE_ADDRESS = 0x1E000004
# Cart config register bits
__FLASH_ENABLE = (1 << 0)
__SDRAM_ENABLE = (1 << 1)
def __init__(self, config = {}):
self.__spi_controller = SpiController(cs_count=1)
self.__spi_controller.configure('ftdi://ftdi:2232h/1')
self.__spi = self.__spi_controller.get_port(0, float(config['spi_speed']))
self.__update_progress = config['update_progress']
if (not config['no_init']):
self.__reset()
self.__set_config(n64_disable=True, address_increment=True)
self.__write_word(self.__CART_CONFIG_ADDRESS, (self.__SDRAM_ENABLE | self.__FLASH_ENABLE))
self.__config = config
def __del__(self):
if (not self.__config['no_init']):
self.__reset()
self.__spi_controller.terminate()
def __get_status(self, field=None):
status_word = struct.unpack('>I', self.__spi.exchange([self.__CMD_STATUS], 4))[0]
status = {
'status': hex(status_word),
'control_byte': (status_word & (0xFF << 24)) >> 24,
'address_increment': (status_word & (0x1 << 23)) >> 23,
'n64_disabled': (status_word & (0x1 << 22)) >> 22,
'write_used': (status_word & (0x7FF << 11)) >> 11,
'read_used': (status_word & (0x7FF << 0)) >> 0,
}
return status.get(field) if field else status
def __set_config(self, n64_disable=False, address_increment=True):
config = (
((1 if address_increment else 0) << 1) |
((1 if n64_disable else 0) << 0)
)
self.__spi.write(bytearray([self.__CMD_CONFIG]) + struct.pack('>I', int(config)))
def __set_address(self, address):
self.__spi.write(bytearray([self.__CMD_ADDR]) + struct.pack('>I', int(address)))
def __set_read_length(self, length):
self.__spi.write(bytearray([self.__CMD_READ_LENGTH]) + struct.pack('>I', int(length - 1)))
def __read_data(self, length):
return self.__spi.exchange([self.__CMD_READ], int(length * 4))
def __write_data(self, data):
self.__spi.write(bytearray([self.__CMD_WRITE]) + data)
def __cart_reset(self):
self.__spi.write([self.__CMD_CART_RESET, 0x00, 0x00, 0x00, 0x00])
def __spi_reset(self):
self.__spi.write([self.__CMD_SPI_RESET])
def __reset(self):
self.__spi_reset()
self.__cart_reset()
def __wait_for_read_fill(self, length):
while (self.__get_status('read_used') < int(length)):
pass
def __wait_for_write_space(self, length):
while ((self.__FIFO_SIZE - self.__get_status('write_used')) < int(length)):
pass
def __wait_for_write_completion(self):
while (self.__get_status('write_used') > 0):
pass
def __read_word(self, address):
self.__set_address(address)
self.__set_read_length(1)
self.__wait_for_read_fill(1)
return struct.unpack('>I', self.__read_data(1))[0]
def __write_word(self, address, data):
self.__set_address(address)
self.__wait_for_write_space(1)
self.__write_data(struct.pack('>I', data))
def __flash_operation(self, byte, mode='s', direction='w', select=False, cfg_mode=True):
return int(
((1 if cfg_mode else 0) << 12) |
((1 if mode == 'q' else 0) << 11) |
((1 if direction == 'w' else 0) << 9) |
((1 if select else 0) << 8) |
(byte & 0xFF)
)
def __flash_create_operation(self, byte, mode='s', direction='w', select=False, cfg_mode=True):
return bytearray(struct.pack('>I', self.__flash_operation(byte, mode, direction, select, cfg_mode)))
def __flash_issue_operation(self, byte, mode='s', direction='w', select=False, cfg_mode=True):
self.__write_word(self.__FLASH_CFG_ADDRESS, self.__flash_operation(byte, mode, direction, select, cfg_mode))
return ((self.__read_word(self.__FLASH_CFG_ADDRESS) & 0xFF) if direction == 'r' else 0x00).to_bytes(1, 'big')
def __flash_exchange(self, command, address=None, data=[], length=0, address_mode='s', write_mode='s', read_mode='s', cfg_mode=True):
operations = bytearray([])
operations += self.__flash_create_operation(command)
if (address != None):
for byte in bytearray(struct.pack('>I', address))[1:4]:
operations += self.__flash_create_operation(byte, mode=address_mode)
for byte in data:
operations += self.__flash_create_operation(byte, mode=write_mode)
if (not length):
operations += self.__flash_create_operation(0x00, select=True, cfg_mode=cfg_mode)
self.__set_address(self.__FLASH_CFG_ADDRESS)
self.__write_data(operations)
self.__wait_for_write_completion()
data_read = bytearray([])
for _ in range(length):
data_read += self.__flash_issue_operation(0x00, mode=read_mode, direction='r')
if (length > 0):
self.__flash_issue_operation(0x00, select=True, cfg_mode=cfg_mode)
return data_read
def __flash_exit_xip(self):
self.__flash_exchange(0xFF, data=[0xFF, 0xFF])
def __flash_enter_xip(self):
self.__flash_exchange(
0xEB,
address=0,
data=[0xA0, 0x00, 0x00],
length=1,
address_mode='q',
write_mode='q',
read_mode='q',
cfg_mode=False
)
def __flash_read_status(self):
return self.__flash_exchange(0x05, length=1)[0]
def __flash_write_enable(self):
self.__flash_exchange(0x06)
def __flash_write_disable(self):
self.__flash_exchange(0x04)
def __flash_sector_erase(self, address):
self.__flash_exchange(0x20, address=address)
def __flash_chip_erase(self):
self.__flash_exchange(0xC7)
self.__flash_exchange(0x60)
def __flash_program_page(self, address, data):
self.__flash_exchange(0x32, address=address, data=data, address_mode='s', write_mode='q')
def __flash_wait_for_not_busy(self):
while (self.__flash_read_status() & 0x01):
pass
def __flash_wait_for_write_enable_latch(self):
while (not (self.__flash_read_status() & 0x02)):
pass
def __calculate_length_in_words(self, length):
return int((length + 3) / 4)
def __get_chunk_iterator(self, data, chunk_size):
for i in range(0, len(data), chunk_size):
yield (data[i:i + chunk_size], i)
def print_status(self):
print(self.__get_status())
def read_rom(self, length, from_flash=False):
length_in_words = self.__calculate_length_in_words(length)
chunk_size = int((self.__FIFO_SIZE_BYTES * 3) / 4)
data = bytearray([])
self.__set_address(self.__FLASH_ADDRESS if from_flash else self.__SDRAM_ADDRESS)
self.__set_read_length(length_in_words)
while (length > 0):
current_chunk_size = min(length, chunk_size)
read_length_in_words = self.__calculate_length_in_words(current_chunk_size)
self.__wait_for_read_fill(read_length_in_words)
data += self.__read_data(read_length_in_words)
length -= current_chunk_size
if (self.__update_progress): self.__update_progress(len(data))
return data
def write_sdram(self, data):
length = len(data)
chunk_size = int((self.__FIFO_SIZE_BYTES * 3) / 4)
self.__set_address(self.__SDRAM_ADDRESS)
for (chunk, offset) in self.__get_chunk_iterator(data, chunk_size):
current_chunk_size = min(chunk_size, length - offset)
self.__wait_for_write_space(self.__calculate_length_in_words(current_chunk_size))
self.__write_data(chunk)
if (self.__update_progress): self.__update_progress(offset)
if (self.__update_progress): self.__update_progress(length)
self.__wait_for_write_completion()
def write_flash(self, data):
self.__set_config(n64_disable=True, address_increment=False)
self.__flash_exit_xip()
print('\rErasing Flash, this may take a while...', end=' ')
self.__flash_write_enable()
self.__flash_wait_for_write_enable_latch()
self.__flash_chip_erase()
self.__flash_wait_for_not_busy()
print('Done')
for (page, offset) in self.__get_chunk_iterator(data, self.__FLASH_PAGE_SIZE):
self.__flash_write_enable()
self.__flash_wait_for_write_enable_latch()
self.__flash_program_page(offset, page)
self.__flash_wait_for_not_busy()
if (self.__update_progress): self.__update_progress(offset)
self.__flash_write_disable()
self.__flash_enter_xip()
self.__set_config(n64_disable=True, address_increment=True)
def set_cic_type(self, cic_type=0):
cic_lut = {
6101: 0x11,
6102: 0x12,
6103: 0x13,
6105: 0x14,
6106: 0x15,
7101: 0x02,
7102: 0x01,
7103: 0x03,
7105: 0x04,
7106: 0x05,
}
self.__write_word(self.__CIC_TYPE_ADDRESS, int(cic_lut.get(cic_type) or 0))
if __name__ == "__main__":
formatter = lambda prog: argparse.HelpFormatter(prog, max_help_position=30)
parser = argparse.ArgumentParser(description='Write/Read N64 ROM to SummerCart', formatter_class=formatter)
parser.add_argument('-s', '--speed', default=30E6, required=False, help='set SPI communication speed (in Hz, 30MHz max)')
parser.add_argument('-r', '--read', action='store_true', required=False, help='read ROM instead of writing')
parser.add_argument('-l', '--length', required=False, help='specify ROM length to read (in bytes)', default=2**26)
parser.add_argument('-f', '--flash', action='store_true', required=False, help='use Flash instead of SDRAM')
parser.add_argument('-c', '--cic', type=int, required=False, help='set CIC type to use by bootloader')
parser.add_argument('-q', '--status', action='store_true', required=False, help='just query and print the status word')
parser.add_argument('rom', help='path to ROM file (only .z64 files are supported)', nargs='?')
args = parser.parse_args()
if ((len(sys.argv) == 1) or (not args.rom and (args.read or args.flash))):
parser.print_help()
parser.exit()
bar = progressbar.DataTransferBar()
def update_progress(length):
bar.update(length)
config = {
'no_init': args.status,
'spi_speed': args.speed,
'update_progress': update_progress,
}
banger = SummerBanger64(config)
if (args.cic != None):
banger.set_cic_type(args.cic)
elif (args.rom and not args.flash):
banger.set_cic_type()
if (args.status):
banger.print_status()
elif (args.rom):
if (args.read):
with open(args.rom, 'wb') as f:
length = int(args.length)
bar.max_value = length
data = banger.read_rom(length, from_flash=args.flash)
f.write(data)
else:
with open(args.rom, 'rb') as f:
data = f.read()
bar.max_value = len(data)
if (args.flash):
banger.write_flash(data)
else:
banger.write_sdram(data)

View File

@ -0,0 +1,3 @@
@echo off
cd /d "%~dp0"
python SummerBanger64.py -f "%~1"

View File

@ -0,0 +1,3 @@
@echo off
cd /d "%~dp0"
python SummerBanger64.py "%~1"

View File

@ -0,0 +1,2 @@
pyftdi>=0.51.2
progressbar2>=3.53.1

1
sw/SummerLoader64/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
/build

View File

@ -0,0 +1,57 @@
ROOTDIR = $(N64_INST)
GCCN64PREFIX = $(ROOTDIR)/bin/mips64-elf-
CHKSUM64PATH = $(ROOTDIR)/bin/chksum64
MKDFSPATH = $(ROOTDIR)/bin/mkdfs
HEADERPATH = $(ROOTDIR)/mips64-elf/lib
N64TOOL = $(ROOTDIR)/bin/n64tool
HEADERNAME = header
LINK_FLAGS = -L$(ROOTDIR)/mips64-elf/lib -ldragon -lc -lm -ldragonsys -Tn64.ld
CFLAGS = -std=gnu99 -march=vr4300 -mtune=vr4300 -Os -Wall -Werror -I$(ROOTDIR)/mips64-elf/include
ASFLAGS = -mtune=vr4300 -march=vr4300
CC = $(GCCN64PREFIX)gcc
AS = $(GCCN64PREFIX)as
LD = $(GCCN64PREFIX)ld
OBJCOPY = $(GCCN64PREFIX)objcopy
OBJDUMP = $(GCCN64PREFIX)objdump
SRC_DIRS = src
SRC_FILES = $(wildcard $(patsubst %, %/*.c, . $(SRC_DIRS)))
OBJ_FILES = $(addprefix build/, $(notdir $(SRC_FILES:.c=.o)))
VPATH = $(SRC_DIRS)
ROM_SIZE = 1028k
ifeq ($(N64_BYTE_SWAP),true)
ROM_EXTENSION = .v64
N64_FLAGS = -b -l $(ROM_SIZE) -h $(HEADERPATH)/$(HEADERNAME) -o build/$(PROG_NAME)$(ROM_EXTENSION)
else
ROM_EXTENSION = .z64
N64_FLAGS = -l $(ROM_SIZE) -h $(HEADERPATH)/$(HEADERNAME) -o build/$(PROG_NAME)$(ROM_EXTENSION)
endif
PROG_NAME = SummerLoader64
all: make_output_dir build/$(PROG_NAME)$(ROM_EXTENSION)
$(OBJ_FILES): Makefile
build/$(PROG_NAME)$(ROM_EXTENSION): build/$(PROG_NAME).elf
$(OBJCOPY) build/$(PROG_NAME).elf build/$(PROG_NAME).bin -O binary
$(OBJDUMP) -S build/$(PROG_NAME).elf > build/$(PROG_NAME).lst
rm -f build/$(PROG_NAME)$(ROM_EXTENSION)
$(N64TOOL) $(N64_FLAGS) -t $(PROG_NAME) build/$(PROG_NAME).bin
$(CHKSUM64PATH) build/$(PROG_NAME)$(ROM_EXTENSION)
build/$(PROG_NAME).elf: $(OBJ_FILES)
$(LD) -o build/$(PROG_NAME).elf $(OBJ_FILES) $(LINK_FLAGS)
build/%.o: %.c
$(COMPILE.c) $(OUTPUT_OPTION) $<
make_output_dir:
$(shell mkdir ./build 2>/dev/null)
clean:
rm -rf ./build
.PHONY: all clean make_output_dir

View File

@ -0,0 +1,7 @@
# SummerLoader64
A N64 bootloader for SummerCart64. This project is mainly based on work by **`jago85`** contained in [Brutzelkarte_Bootloader repository](https://github.com/jago85/Brutzelkarte_Bootloader) with some modifications that made code a little bit more readable.
## TODO
- Expand documentation

View File

@ -0,0 +1,210 @@
#include <libdragon.h>
#include "boot.h"
#include "crc32.h"
#include "n64_regs.h"
cart_header_t global_cart_header __attribute__((aligned(8)));
cart_header_t *boot_load_cart_header(void) {
cart_header_t *cart_header_pointer = &global_cart_header;
data_cache_hit_writeback_invalidate(cart_header_pointer, sizeof(cart_header_t));
dma_read(cart_header_pointer, CART_BASE, sizeof(cart_header_t));
data_cache_hit_invalidate(cart_header_pointer, sizeof(cart_header_t));
return cart_header_pointer;
}
cic_type_t boot_get_cic_type(cart_header_t *cart_header) {
switch (crc32_calculate(cart_header->boot_code, sizeof(cart_header->boot_code))) {
case BOOT_CRC32_6101:
case BOOT_CRC32_7102:
return E_CIC_TYPE_6101;
case BOOT_CRC32_X102:
return E_CIC_TYPE_6102;
case BOOT_CRC32_X103:
return E_CIC_TYPE_6103;
case BOOT_CRC32_X105:
return E_CIC_TYPE_6105;
case BOOT_CRC32_X106:
return E_CIC_TYPE_6106;
default:
return E_CIC_TYPE_UNKNOWN;
}
}
tv_type_t boot_get_tv_type(cart_header_t *cart_header) {
switch (cart_header->country_code) {
case 'D':
case 'F':
case 'H':
case 'I':
case 'P':
case 'S':
case 'W':
case 'X':
case 'Y':
return E_TV_TYPE_PAL;
case '7':
case 'A':
case 'C':
case 'E':
case 'J':
case 'K':
case 'N':
case 'U':
return E_TV_TYPE_NTSC;
case 'B':
return E_TV_TYPE_MPAL;
default:
return E_TV_TYPE_UNKNOWN;
}
}
void boot(cic_type_t cic_type, tv_type_t tv_type) {
tv_type_t os_tv_type = tv_type == E_TV_TYPE_UNKNOWN ? OS_BOOT_CONFIG->tv_type : tv_type;
volatile uint64_t gpr_regs[32];
const uint8_t cic_seeds[] = {
BOOT_SEED_X102,
BOOT_SEED_X101,
BOOT_SEED_X102,
BOOT_SEED_X103,
BOOT_SEED_X105,
BOOT_SEED_X106,
};
while (!(SP->status & SP_STATUS_HALT));
SP->status = SP_STATUS_CLEAR_INTERRUPT | SP_STATUS_SET_HALT;
while (SP->dma_busy & SP_DMA_BUSY);
PI->status = PI_STATUS_CLEAR_INTERRUPT | PI_STATUS_RESET_CONTROLLER;
VI->v_intr = 0x3FF;
VI->h_limits = 0;
VI->current_line = 0;
AI->dram_addr = 0;
AI->len = 0;
while (SP->status & SP_STATUS_DMA_BUSY);
if (DP_CMD->status & DP_CMD_STATUS_XBUS_DMEM_DMA) {
while (DP_CMD->status & DP_CMD_STATUS_PIPE_BUSY);
}
DP_CMD->status = DP_CMD_STATUS_CLEAR_FLUSH | DP_CMD_STATUS_CLEAR_FREEZE | DP_CMD_STATUS_CLEAR_XBUS_DMEM_DMA;
for (size_t i = 0; i < ARRAY_ITEMS(SP_MEM->dmem); i++) {
SP_MEM->dmem[i] = CART[i];
}
while (PI->status & (PI_STATUS_IO_BUSY | PI_STATUS_DMA_BUSY));
PI->status = PI_STATUS_CLEAR_INTERRUPT | PI_STATUS_RESET_CONTROLLER;
if (cic_type == E_CIC_TYPE_6105) {
OS_BOOT_CONFIG->mem_size_6105 = OS_BOOT_CONFIG->mem_size;
}
for (size_t i = 0; i < ARRAY_ITEMS(SP_MEM->imem); i++) {
SP_MEM->imem[i] = 0;
}
if (cic_type == E_CIC_TYPE_6105) {
SP_MEM->imem[0] = 0x3C0DBFC0;
SP_MEM->imem[1] = os_tv_type == E_TV_TYPE_PAL ? 0xBDA807FC : 0x8DA807FC;
SP_MEM->imem[2] = 0x25AD07C0;
SP_MEM->imem[3] = 0x31080080;
SP_MEM->imem[4] = 0x5500FFFC;
SP_MEM->imem[5] = 0x3C0DBFC0;
SP_MEM->imem[6] = 0x8DA80024;
SP_MEM->imem[7] = 0x3C0BB000;
}
for (size_t i = 0; i < ARRAY_ITEMS(gpr_regs); i++) {
gpr_regs[i] = 0;
}
gpr_regs[CPU_REG_T3] = (0xFFFFFFFFLL << 32) | ((uint32_t) &SP_MEM->dmem[16]);
gpr_regs[CPU_REG_S4] = os_tv_type;
gpr_regs[CPU_REG_S6] = cic_seeds[cic_type];
if (os_tv_type == E_TV_TYPE_PAL) {
gpr_regs[CPU_REG_S7] = 6;
}
gpr_regs[CPU_REG_SP] = (0xFFFFFFFFLL << 32) | ((uint32_t) &SP_MEM->imem[ARRAY_ITEMS(SP_MEM->imem) - 4]);
gpr_regs[CPU_REG_RA] = (0xFFFFFFFFLL << 32) | ((uint32_t) &SP_MEM->imem[(os_tv_type == E_TV_TYPE_PAL) ? 341 : 340]);
__asm__ (
".set noat \n\t"
".set noreorder \n\t"
"li $t0, 0x34000000 \n\t"
"mtc0 $t0, $12 \n\t"
"nop \n\t"
"li $t0, 0x0006E463 \n\t"
"mtc0 $t0, $16 \n\t"
"nop \n\t"
"li $t0, 0x00005000 \n\t"
"mtc0 $t0, $9 \n\t"
"nop \n\t"
"li $t0, 0x0000005C \n\t"
"mtc0 $t0, $13 \n\t"
"nop \n\t"
"li $t0, 0x007FFFF0 \n\t"
"mtc0 $t0, $4 \n\t"
"nop \n\t"
"li $t0, 0xFFFFFFFF \n\t"
"mtc0 $t0, $14 \n\t"
"nop \n\t"
"mtc0 $t0, $30 \n\t"
"nop \n\t"
"lui $t0, 0x0000 \n\t"
"mthi $t0 \n\t"
"nop \n\t"
"mtlo $t0 \n\t"
"nop \n\t"
"ctc1 $t0, $31 \n\t"
"nop \n\t"
"add $ra, $zero, %[gpr_regs] \n\t"
"ld $at, 0x08($ra) \n\t"
"ld $v0, 0x10($ra) \n\t"
"ld $v1, 0x18($ra) \n\t"
"ld $a0, 0x20($ra) \n\t"
"ld $a1, 0x28($ra) \n\t"
"ld $a2, 0x30($ra) \n\t"
"ld $a3, 0x38($ra) \n\t"
"ld $t0, 0x40($ra) \n\t"
"ld $t1, 0x48($ra) \n\t"
"ld $t2, 0x50($ra) \n\t"
"ld $t3, 0x58($ra) \n\t"
"ld $t4, 0x60($ra) \n\t"
"ld $t5, 0x68($ra) \n\t"
"ld $t6, 0x70($ra) \n\t"
"ld $t7, 0x78($ra) \n\t"
"ld $s0, 0x80($ra) \n\t"
"ld $s1, 0x88($ra) \n\t"
"ld $s2, 0x90($ra) \n\t"
"ld $s3, 0x98($ra) \n\t"
"ld $s4, 0xA0($ra) \n\t"
"ld $s5, 0xA8($ra) \n\t"
"ld $s6, 0xB0($ra) \n\t"
"ld $s7, 0xB8($ra) \n\t"
"ld $t8, 0xC0($ra) \n\t"
"ld $t9, 0xC8($ra) \n\t"
"ld $k0, 0xD0($ra) \n\t"
"ld $k1, 0xD8($ra) \n\t"
"ld $gp, 0xE0($ra) \n\t"
"ld $sp, 0xE8($ra) \n\t"
"ld $fp, 0xF0($ra) \n\t"
"ld $ra, 0xF8($ra) \n\t"
"jr $t3 \n\t"
"nop"
:
: [gpr_regs] "r" (gpr_regs)
: "t0"
);
while (1);
}

View File

@ -0,0 +1,77 @@
#ifndef BOOT_H__
#define BOOT_H__
#define BOOT_CRC32_6101 (0x6170A4A1)
#define BOOT_CRC32_7102 (0x009E9EA3)
#define BOOT_CRC32_X102 (0x90BB6CB5)
#define BOOT_CRC32_X103 (0x0B050EE0)
#define BOOT_CRC32_X105 (0x98BC2C86)
#define BOOT_CRC32_X106 (0xACC8580A)
#define BOOT_SEED_X102 (0x3F)
#define BOOT_SEED_X101 (0x3F)
#define BOOT_SEED_X102 (0x3F)
#define BOOT_SEED_X103 (0x78)
#define BOOT_SEED_X105 (0x91)
#define BOOT_SEED_X106 (0x85)
typedef enum cic_type_e {
E_CIC_TYPE_UNKNOWN,
E_CIC_TYPE_6101,
E_CIC_TYPE_6102,
E_CIC_TYPE_6103,
E_CIC_TYPE_6105,
E_CIC_TYPE_6106,
E_CIC_TYPE_END,
} cic_type_t;
typedef enum tv_type_e {
E_TV_TYPE_PAL,
E_TV_TYPE_NTSC,
E_TV_TYPE_MPAL,
E_TV_TYPE_UNKNOWN,
} tv_type_t;
struct cart_header_s {
uint32_t pi_conf;
uint32_t clock_rate;
uint32_t boot_addr;
uint32_t release_addr;
uint32_t crc_1;
uint32_t crc_2;
uint32_t __unused_1[2];
char name[20];
uint32_t __unused_2;
uint32_t format;
char id[2];
char country_code;
uint8_t version;
uint32_t boot_code[1008];
} __attribute__((packed, aligned(1)));
typedef struct cart_header_s cart_header_t;
struct os_boot_config_s {
uint32_t tv_type;
uint32_t rom_type;
uint32_t rom_base;
uint32_t reset_type;
uint32_t cic_id;
uint32_t version;
uint32_t mem_size;
uint8_t app_nmi_buffer[64];
uint32_t __unused[37];
uint32_t mem_size_6105;
} __attribute__((packed, aligned(1)));
typedef struct os_boot_config_s os_boot_config_t;
#define OS_BOOT_CONFIG_BASE (0xA0000300)
#define OS_BOOT_CONFIG ((os_boot_config_t *) OS_BOOT_CONFIG_BASE)
cart_header_t *boot_load_cart_header(void);
cic_type_t boot_get_cic_type(cart_header_t *cart_header);
tv_type_t boot_get_tv_type(cart_header_t *cart_header);
void boot(cic_type_t cic_type, tv_type_t tv_type);
#endif

View File

@ -0,0 +1,50 @@
#include <inttypes.h>
#include "crc32.h"
const uint32_t crc_table[256] = {
0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3,
0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91,
0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7,
0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5,
0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B,
0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59,
0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F,
0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D,
0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,
0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01,
0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457,
0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65,
0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB,
0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9,
0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD,
0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683,
0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,
0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7,
0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5,
0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79,
0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F,
0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D,
0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713,
0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21,
0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,
0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45,
0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB,
0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9,
0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF,
0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D,
};
uint32_t crc32_calculate(void *buffer, size_t length) {
uint32_t crc32 = 0xFFFFFFFF;
uint8_t *byte_pointer = (uint8_t *) buffer;
while (length--) {
crc32 = (crc32 >> 8) ^ crc_table[(crc32 & 0xFF) ^ (*byte_pointer++)];
}
return ~crc32;
}

View File

@ -0,0 +1,8 @@
#ifndef CRC32_H__
#define CRC32_H__
#include <stddef.h>
uint32_t crc32_calculate(void *buffer, size_t length);
#endif

View File

@ -0,0 +1,32 @@
#include <libdragon.h>
#include "boot.h"
#include "sc64.h"
int main(void) {
init_interrupts();
sc64_enable_sdram();
sc64_disable_flash();
cic_type_t cic_type = sc64_get_cic_type();
tv_type_t tv_type = sc64_get_tv_type();
if (cic_type == E_CIC_TYPE_UNKNOWN || tv_type == E_TV_TYPE_UNKNOWN) {
// Try to guess CIC and TV type from ROM in SDRAM if no override is provided
cart_header_t *cart_header = boot_load_cart_header();
if (cic_type == E_CIC_TYPE_UNKNOWN) {
cic_type = boot_get_cic_type(cart_header);
}
if (tv_type == E_TV_TYPE_UNKNOWN) {
tv_type = boot_get_tv_type(cart_header);
}
}
disable_interrupts();
boot(cic_type, tv_type);
}

View File

@ -0,0 +1,143 @@
#ifndef N64_REGS_H__
#define N64_REGS_H__
#include <inttypes.h>
#define ARRAY_ITEMS(x) (sizeof(x) / sizeof(x[0]))
#define CPU_REG_Z0 (0)
#define CPU_REG_AT (1)
#define CPU_REG_V0 (2)
#define CPU_REG_V1 (3)
#define CPU_REG_A0 (4)
#define CPU_REG_A1 (5)
#define CPU_REG_A2 (6)
#define CPU_REG_A3 (7)
#define CPU_REG_T0 (8)
#define CPU_REG_T1 (9)
#define CPU_REG_T2 (10)
#define CPU_REG_T3 (11)
#define CPU_REG_T4 (12)
#define CPU_REG_T5 (13)
#define CPU_REG_T6 (14)
#define CPU_REG_T7 (15)
#define CPU_REG_S0 (16)
#define CPU_REG_S1 (17)
#define CPU_REG_S2 (18)
#define CPU_REG_S3 (19)
#define CPU_REG_S4 (20)
#define CPU_REG_S5 (21)
#define CPU_REG_S6 (22)
#define CPU_REG_S7 (23)
#define CPU_REG_T8 (24)
#define CPU_REG_T9 (25)
#define CPU_REG_K0 (26)
#define CPU_REG_K1 (27)
#define CPU_REG_GP (28)
#define CPU_REG_SP (29)
#define CPU_REG_FP (30)
#define CPU_REG_RA (31)
typedef struct SP_MEM_s {
volatile uint32_t dmem[1024];
volatile uint32_t imem[1024];
} SP_MEM_t;
typedef struct SP_regs_s {
volatile void *mem_addr;
volatile void *dram_addr;
volatile uint32_t rd_len;
volatile uint32_t wr_len;
volatile uint32_t status;
volatile uint32_t dma_full;
volatile uint32_t dma_busy;
volatile uint32_t semaphore;
} SP_regs_t;
typedef struct DP_CMD_regs_s {
volatile void *start;
volatile void *end;
volatile void *current;
volatile uint32_t status;
volatile uint32_t clock;
volatile uint32_t buf_busy;
volatile uint32_t pipe_busy;
volatile uint32_t tmem;
} DP_CMD_regs_t;
typedef struct VI_regs_s {
volatile uint32_t control;
volatile void *dram_addr;
volatile uint32_t h_width;
volatile uint32_t v_intr;
volatile uint32_t current_line;
volatile uint32_t timing;
volatile uint32_t v_sync;
volatile uint32_t h_sync;
volatile uint32_t h_sync_leap;
volatile uint32_t h_limits;
volatile uint32_t v_limits;
volatile uint32_t color_burst;
volatile uint32_t h_scale;
volatile uint32_t v_scale;
} VI_regs_t;
typedef struct AI_regs_s {
volatile void *dram_addr;
volatile uint32_t len;
volatile uint32_t control;
volatile uint32_t status;
volatile uint32_t dacrate;
volatile uint32_t bitrate;
} AI_regs_t;
typedef struct PI_regs_s {
volatile void *dram_addr;
volatile uint32_t cart_addr;
volatile uint32_t rd_len;
volatile uint32_t wr_len;
volatile uint32_t status;
volatile uint32_t dom1_lat;
volatile uint32_t dom1_pwd;
volatile uint32_t dom1_pgs;
volatile uint32_t dom1_rls;
volatile uint32_t dom2_lat;
volatile uint32_t dom2_pwd;
volatile uint32_t dom2_pgs;
volatile uint32_t dom2_rls;
} PI_regs_t;
#define SP_MEM_BASE (0xA4000000)
#define SP_REGS_BASE (0xA4040000)
#define DP_CMD_REGS_BASE (0xA4100000)
#define VI_REGS_BASE (0xA4400000)
#define AI_REGS_BASE (0xA4500000)
#define PI_REGS_BASE (0xA4600000)
#define CART_BASE (0xB0000000)
#define SP_MEM ((volatile SP_MEM_t *) SP_MEM_BASE)
#define SP ((volatile SP_regs_t *) SP_REGS_BASE)
#define DP_CMD ((volatile DP_CMD_regs_t *) DP_CMD_REGS_BASE)
#define VI ((volatile VI_regs_t *) VI_REGS_BASE)
#define AI ((volatile AI_regs_t *) AI_REGS_BASE)
#define PI ((volatile PI_regs_t *) PI_REGS_BASE)
#define CART ((volatile uint32_t *) CART_BASE)
#define SP_STATUS_HALT (1 << 0)
#define SP_STATUS_DMA_BUSY (1 << 2)
#define SP_STATUS_SET_HALT (1 << 1)
#define SP_STATUS_CLEAR_INTERRUPT (1 << 3)
#define SP_DMA_BUSY (1 << 0)
#define DP_CMD_STATUS_XBUS_DMEM_DMA (1 << 0)
#define DP_CMD_STATUS_PIPE_BUSY (1 << 5)
#define DP_CMD_STATUS_CLEAR_XBUS_DMEM_DMA (1 << 0)
#define DP_CMD_STATUS_CLEAR_FREEZE (1 << 2)
#define DP_CMD_STATUS_CLEAR_FLUSH (1 << 4)
#define PI_STATUS_DMA_BUSY (1 << 0)
#define PI_STATUS_IO_BUSY (1 << 1)
#define PI_STATUS_RESET_CONTROLLER (1 << 0)
#define PI_STATUS_CLEAR_INTERRUPT (1 << 1)
#endif

View File

@ -0,0 +1,55 @@
#include <libdragon.h>
#include <inttypes.h>
#include "sc64.h"
#include "sc64_regs.h"
static void sc64_enable_peripheral(uint32_t mask) {
uint32_t config = io_read(SC64_CONFIG_REG);
config |= mask;
io_write(SC64_CONFIG_REG, config);
}
static void sc64_disable_peripheral(uint32_t mask) {
uint32_t config = io_read(SC64_CONFIG_REG);
config &= ~mask;
io_write(SC64_CONFIG_REG, config);
}
void sc64_enable_sdram(void) {
sc64_enable_peripheral(SC64_CONFIG_SDRAM_ENABLE);
}
void sc64_disable_sdram(void) {
sc64_disable_peripheral(SC64_CONFIG_SDRAM_ENABLE);
}
void sc64_enable_flash(void) {
sc64_enable_peripheral(SC64_CONFIG_FLASH_ENABLE);
}
void sc64_disable_flash(void) {
sc64_disable_peripheral(SC64_CONFIG_FLASH_ENABLE);
}
cic_type_t sc64_get_cic_type(void) {
uint32_t boot = io_read(SC64_BOOT_REG);
cic_type_t cic_type = (cic_type_t)(SC64_BOOT_CIC_TYPE(boot));
return (cic_type >= E_CIC_TYPE_END) ? E_CIC_TYPE_UNKNOWN : cic_type;
}
tv_type_t sc64_get_tv_type(void) {
uint32_t boot = io_read(SC64_BOOT_REG);
if ((SC64_BOOT_CIC_TYPE(boot) == E_CIC_TYPE_UNKNOWN) || (SC64_BOOT_CIC_TYPE(boot) >= E_CIC_TYPE_END)) {
return E_TV_TYPE_UNKNOWN;
} else {
return (tv_type_t)(SC64_BOOT_TV_TYPE(boot));
}
}

View File

@ -0,0 +1,13 @@
#ifndef SC64_H__
#define SC64_H__
#include "boot.h"
void sc64_enable_flash(void);
void sc64_disable_flash(void);
void sc64_enable_sdram(void);
void sc64_disable_sdram(void);
cic_type_t sc64_get_cic_type(void);
tv_type_t sc64_get_tv_type(void);
#endif

View File

@ -0,0 +1,26 @@
#ifndef SC64_REGS_H__
#define SC64_REGS_H__
// SummerCart64 config register
#define SC64_CONFIG_REG (0x1E000000)
#define SC64_CONFIG_FLASH_ENABLE (1 << 0)
#define SC64_CONFIG_SDRAM_ENABLE (1 << 1)
// Boot CIC and TV type override register
#define SC64_BOOT_REG (0x1E000004)
#define SC64_BOOT_CIC_TYPE_MSK (0x0F)
#define SC64_BOOT_CIC_TYPE_BIT (0)
#define SC64_BOOT_CIC_TYPE(x) (((x) & SC64_BOOT_CIC_TYPE_MSK) >> SC64_BOOT_CIC_TYPE_BIT)
#define SC64_BOOT_TV_TYPE_MSK (0x30)
#define SC64_BOOT_TV_TYPE_BIT (4)
#define SC64_BOOT_TV_TYPE(x) (((x) & SC64_BOOT_TV_TYPE_MSK) >> SC64_BOOT_TV_TYPE_BIT)
// Flash arbitrary command register
#define SC64_FLASH_CFG_REG (0x1C000000)
#endif