Merge pull request #2 from Polprzewodnikowy/new_concept

* [SC64][SW][SL64] Cleanup boot process

* [SC64][FW][HW][SW] Completely new concept for firmware, abandoned SummerBanger64 for N64-UNFLoader, added UltraCIC-III as submodule, CI configuration
This commit is contained in:
Mateusz Faderewski 2020-11-06 00:23:02 +01:00 committed by GitHub
commit 02db96d9c5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
61 changed files with 4689 additions and 8039 deletions

1
.gitignore vendored
View File

@ -1 +1,2 @@
/packages
**/.vscode

4
.gitmodules vendored Normal file
View File

@ -0,0 +1,4 @@
[submodule "sw/cic"]
path = sw/cic
url = https://github.com/ManCloud/UltraCIC-III.git
ignore = dirty

25
.travis.yml Normal file
View File

@ -0,0 +1,25 @@
os: linux
dist: focal
arch: amd64
language: shell
services:
- docker
before_install:
- sudo apt-get update
- sudo apt-get install -y avra
script:
./build_release.sh "${TRAVIS_BRANCH}-${TRAVIS_TAG}"
deploy:
provider: releases
token:
secure: LNBOWTFd5wz3sR7ec4OA/wbVjIWFCv2WJnx6QBIOhgh2VIicNd91ZgMxq77T7/DBxPJ7GhAuG76s4K68ve8m5+klhpjtxVwstDzHBaNbRIUbhxjKh8oJGX8T+qeB60cnjz1YwmGASWSXNpXPhW/SZRw1lAjpv3W2cxTmDyAzayV+xO7HeVfOAgaKOAL600LwjEdWGLFVRx2MQqMe2NAJ4XWu8oJBXjrlQc/5jHW/3o4oFILs+Jr7VwRt3qYrU0xJ8XPJFDo7AWvAHYH4vrACIOXMPIuI29tsi9eWcT/+q96IKmpDPRvn3nrMnb7bMN995WyW2tFvGqABsFRwUXJ6Ydc7aFdTAC2+u/cWpR4AEpLGNWFqpDlLwjNfqiZ1rhDDAlEI/bA+zU/qyziT5lDaARFJtRxuQIWeZRa7EgmaTc0izghrzIBC807+G1cUTGntSjgVb8B6rtJa6tBt3/9Iu4RmRxJnKkgWQBNo8CEVVDAe/Ms7igashEoaidr545eR/9ervxGLftFUctKWjnsEL4r7ifjUOj9h/E7BZx61WkJ8hORoMValcc+Kv0aCmkzWKe0UsSsuMzsXHc3x782AO2Xq5fZLk0urdqQ/uzu5crSnReJh/lCZxjg11BG31r5kAixBaSkiJFFrAs+GOSR/IskRn8gKThjZtna8DUnHApE=
file: packages/SummerCart64-${TRAVIS_BRANCH}-${TRAVIS_TAG}.zip
on:
repo: Polprzewodnikowy/SummerCollection
tags: true
draft: true

View File

@ -2,42 +2,69 @@
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.
### Hardware
Folder **`hw`** contains PCB design made in Autodesk Eagle.
### Software
Folder **`sw`** contains several helper programs that makes flash cart work all together, including bootloader and PC communication software.
Folder **`sw`** contains several helper programs that makes flash cart work all together, including bootloader and CIC emulation.
## What works
Currently hardware implements basic functionality for playing games - ROM emulation, 4/16K EEPROM, bootloader and PC communication. You can send any ROM to the SDRAM from PC and if game doesn't check for save hardware other than EEPROM then it most likely will work. Bootloader does all the work necessary to setup the console registers for specific CIC chip that game requires.
## How to build
Instructions below are mostly written for Windows users and point to Windows specific executables.
1. Download latest zip files from [releases tab](https://github.com/Polprzewodnikowy/SummerCollection/releases).
2. Order PCBs in your farovite company, all gerbers, bill of materials and schematics are in **`SummerCart64_PCB-main-[version].zip`** file.
3. Order all necessary components, eg. in [Mouser](https://mouser.com/).
4. Solder all components onto the PCB.
5. Connect flashcart to PC.
6. Download [FT_PROG](https://www.ftdichip.com/Support/Utilities.htm#FT_PROG) from FTDI website.
7. Open FT_PROG and scan for devices.
8. Load `ftdi-template.xml` from **`SummerCart64-main-[version].zip`** located in `hw` folder.
9. Program FTDI chip, then right click on the device and select "Cycle port"
10. Download and install [Arrow USB Blaster drivers](https://shop.trenz-electronic.de/en/Download/?path=Trenz_Electronic/Software/Drivers/Arrow_USB_Programmer/Arrow_USB_Programmer_2.4) from Trenz Electronic website.
11. Download and install [QuartusProgrammer](https://download.altera.com/akdlm/software/acdsinst/20.1std/711/ib_installers/QuartusProgrammerSetup-20.1.0.711-windows.exe) from Intel website.
12. Click on "Hardware Setup..." button and select "Arrow-USB-Blaster [AR*xxxxxx*]" in "Currently selected hardware", then close window.
13. Click on "Auto Detect" button and select "10M08SC" option.
14. Click on the newly shown row, then click on "Change File..." button and select `SummerCart64.pof` file from **`SummerCart64-main-[version].zip`** located in `fw/output_files` folder.
15. Select "Program/Configure" and "Verify" checkboxes.
16. Click on "Start" button and wait for operation to finish.
17. Download latest release of [N64-UNFLoader](https://github.com/buu342/N64-UNFLoader).
18. Insert flashcart in the Nintendo 64.
19. Upload ROM by executing `UNFLoader -r your_rom_file.n64`
20. Turn on console and enjoy playing homebrew games on real hardware.
## Issues
There are several issues with the project at the moment in order of importance:
There are several issues with the project at the moment in order of importance. Keep in mind that core flashcart functionality is fully working:
- Documentation is not finished for most of the modules.
- PCB schematic is unorganized and some component values are missing.
- There's no BOM for hardware.
- Currently PC communication disables N64 PI interface completely as there's no bus arbiter implemented.
- No debug interface for the [N64-UNFLoader](https://github.com/buu342/N64-UNFLoader).
- No read functionality through USB interface.
- No SRAM/FlashRAM save hardware implementation.
- No SD card interface hardware implementation.
- No save write-back to SD card hardware implementation.
- PCB design and necessary components needs to be reconsidered for next version.
- No SRAM/FlashRAM save hardware implementation.
- No RTC hardware implementation.
- 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 document the project.
Current goal is to write debug module for the [N64-UNFLoader](https://github.com/buu342/N64-UNFLoader).
## Finished sample

41
build_pcb.sh Executable file
View File

@ -0,0 +1,41 @@
#!/bin/bash
PACKAGES_FOLDER_NAME="packages"
PACKAGE_FILE_NAME="SummerCart64_PCB"
FILES=(
"./hw/CAMOutputs"
# Manually created files
"./hw/SummerCart64_sch.pdf"
"./hw/SummerCart64_brd_top.pdf"
"./hw/SummerCart64_brd_bot.pdf"
"./hw/SummerCart64_brd_place_top.pdf"
)
# Add version to zip file name if provided
if [[ $1 ]]; then
PACKAGE_FILE_NAME="${PACKAGE_FILE_NAME}-${1}"
fi
# Generate Gerbers
pushd hw
if [[ -e CAMOutputs ]]; then
rm -rf CAMOutputs
fi
echo "Generating Gerbers"
eaglecon.exe -X -dCAMJOB -jSummerCart64.cam SummerCart64.brd
popd
# Create packages directory
echo "Creating ${PACKAGES_FOLDER_NAME} directory"
mkdir -p "${PACKAGES_FOLDER_NAME}"
# ZIP files for release
echo "Zipping PCB files"
if [[ -e "${PACKAGES_FOLDER_NAME}/${PACKAGE_FILE_NAME}.zip" ]]; then
rm -f "${PACKAGES_FOLDER_NAME}/${PACKAGE_FILE_NAME}.zip"
fi
zip -r "${PACKAGES_FOLDER_NAME}/${PACKAGE_FILE_NAME}.zip" ${FILES[@]}

48
build_release.sh Executable file
View File

@ -0,0 +1,48 @@
#!/bin/bash
PACKAGES_FOLDER_NAME="packages"
PACKAGE_FILE_NAME="SummerCart64"
FILES=(
"./fw/output_files/SummerCart64.pof"
"./hw/ftdi-template.xml"
"./sw/cic/UltraCIC-III.hex"
"./sw/cic/UltraCIC-III.eep.hex"
)
# Add version to zip file name if provided
if [[ $1 ]]; then
PACKAGE_FILE_NAME="${PACKAGE_FILE_NAME}-${1}"
fi
# Build bootloader
echo "Building bootloader"
pushd sw/bootloader
docker run -t --mount type=bind,src="$(pwd)",target="/libdragon" anacierdem/libdragon:4.1.1 /bin/bash -c "/usr/bin/make clean; /usr/bin/make all N64_BYTE_SWAP=false"
popd
# Build UltraCIC-III
pushd sw/cic
echo "Building UltraCIC-III"
avra UltraCIC-III.asm -D attiny45
popd
# Build FPGA firmware
echo "Building FPGA firmware"
docker run -t --mount type=bind,src="$(pwd)",target="/build" chriz2600/quartus-lite:20.1.0 /usr/local/bin/quartus_wrapper quartus_sh --flow compile /build/fw/SummerCart64.qpf
# Create packages directory
echo "Creating ${PACKAGES_FOLDER_NAME} directory"
mkdir -p "${PACKAGES_FOLDER_NAME}"
# ZIP files for release
echo "Zipping files"
if [[ -e "${PACKAGES_FOLDER_NAME}/${PACKAGE_FILE_NAME}.zip" ]]; then
rm -f "${PACKAGES_FOLDER_NAME}/${PACKAGE_FILE_NAME}.zip"
fi
zip -r "${PACKAGES_FOLDER_NAME}/${PACKAGE_FILE_NAME}.zip" ${FILES[@]}

2
fw/.gitignore vendored
View File

@ -2,6 +2,8 @@
/greybox_tmp
/incremental_db
/output_files
**/.qsys_edit
*.qws
*.rpt
*.txt
*.sopcinfo

View File

@ -2,18 +2,16 @@
A FPGA firmware written in Verilog for SummerCart64.
# Technical Reference Manual
## Bus peripheral addresses
- **`0x1000 0000 - 0x13FF FFFF`** - [R/W] *SDRAM Memory*
- **`0x1000 0000 - 0x10FF FFFF`** - [R] *Flash Memory* (no remap)
- **`0x1800 0000 - 0x18FF FFFF`** - [R] *Flash Memory* (remapped)
- **`0x1C00 0000 - 0x1C00 0000`** - [R/W] *Flash Registers*
- **`0x1D00 0000 - 0x1D00 07FF`** - [R/W] *EEPROM Memory*
- **`0x1D10 0000 - 0x1D10 03FF`** - [R] *Debug RX FIFO* (unimplemented)
- **`0x1D10 0800 - 0x1D10 0BFF`** - [W] *Debug TX FIFO* (unimplemented)
- **`0x1E00 0000 - 0x1E00 0014`** - [R/W] *Cart Registers*
- **`0x1E00 0000 - 0x1E00 0007`** - [R/W] *Cart Registers*
## Memory spaces
@ -25,14 +23,6 @@ Access: Read or Write, 2 byte (16 bit) aligned
64 MB of SDRAM memory. Available on the bus when **SDRAM** bit in **CART->CR** register is set. Used as ROM storage.
### Flash Memory
Base address: **`0x1000 0000`** (no remap) or **`0x1800 0000`** (remapped)\
Length: **`16 MB`**\
Access: Read only, 2 byte (16 bit) aligned
16 MB of Flash Memory. Available on the bus when **FLASH** bit in **CART->CR** register is set. Used as bootloader storage.
### EEPROM Memory
Base address: **`0x1D00 0000`**\
@ -41,23 +31,6 @@ Access: Read or Write, 4 byte (32 bit) aligned
2 kB of EEPROM Memory. Available on the bus when **EEPROM_PI** bit in **CART->CR** register is set. Used to upload/download EEPROM contents to/from PC.
### Debug FIFO DMA (unimplemented)
#### RX FIFO DMA Memory (unimplemented)
Base address: **`0x1D100 0000`**\
Length: **`1kB`**\
Access: Read only, 4 byte (32 bit) aligned
1 kB of RX FIFO. Available on the bus when **DEBUG** bit in **CART->CR** register is set. Used to receive arbitrary data from PC. Only 4 byte reads are supported, for single byte reads use **CART->DEBUG_RX** register.
#### TX FIFO DMA Memory (unimplemented)
Base address: **`0x1D100 0800`**\
Length: **`1kB`**\
Access: Write only, 4 byte (32 bit) aligned
1 kB of TX FIFO. Available on the bus when **DEBUG** bit in **CART->CR** register is set. Used to send arbitrary data to PC. Only 4 byte writes are supported, for single byte writes use **CART->DEBUG_TX** register.
## Registers
@ -68,34 +41,29 @@ Base address: **`0x1E00 0000`**
#### Configuration register (**CR**)
Address offset: **`0x00`**\
Powerup value: **`0b0000 0001`**\
Soft reset value: **`0b00xx x001`**\
Powerup value: **`0b0000 0000`**\
Soft reset value: **`0b00xx x000`**\
Access: Read or write, 4 byte (32 bit) aligned
This register is used to enable or disable various modules available on the cart.
31:6 | 5 | 4 | 3 | 2 | 1 | 0
--------|-------|------------|-----------|-----------|-------|-------
0 | DEBUG | EEPROM_16K | EEPROM_SI | EEPROM_PI | SDRAM | FLASH
x | R/W | R/W | R/W | R/W | R/W | R/W
31:5 | 4 | 3 | 2 | 1 | 0
------|------------|-----------|---|----------|---
0 | EEPROM_16K | EEPROM_EN | 0 | SDRAM_EN | 0
x | R/W | R/W | x | R/W | x
- Bits 31:6: Reserved. Reads as 0, writes are ignored but it's recommended to be set as 0 for future compatibility.
- Bit 5 **DEBUG** (unimplemented): Enable debug FIFO access at address base **`0x1D100 0000`** and **`0x1D100 0800`**.
- 0: Debug FIFO disabled
- 1: Debug FIFO enabled
- Bits 31:5: Reserved. Reads as 0, writes are ignored but it's recommended to be set as 0 for future compatibility.
- Bit 4 **EEPROM_16K**: Sets ID returned by EEPROM to identify itself as 4k or 16k variant.
- 0: EEPROM 4k variant
- 1: EEPROM 16k variant
- Bit 3 **EEPROM_SI**: Enable EEPROM access through SI bus.
- Bit 3 **EEPROM_EN**: Enable EEPROM access through SI bus.
- 0: EEPROM SI access disabled
- 1: EEPROM SI access enabled
- Bit 2 **EEPROM_PI**: Enable EEPROM access through PI bus at address base **`0x1D00 0000`**. Cleared by hardware on N64 Reset/NMI event.
- 0: EEPROM PI access disabled
- 1: EEPROM PI access enabled
- Bit 1 **SDRAM**: Enable SDRAM access at address base **`0x1000 0000`**. This bit also remaps Flash base address. Cleared by hardware on N64 Reset/NMI event.
- Bit 2: Reserved. Reads as 0, writes are ignored but it's recommended to be set as 0 for future compatibility.
- Bit 1 **SDRAM_EN**: Enable SDRAM access at address base **`0x1000 0000`**. When disabled bootloader flash image is mapped at this address. Cleared by hardware on N64 Reset/NMI event.
- 0: SDRAM disabled
- 1: SDRAM enabled
- Bit 0 **FLASH**: Enable Flash access at address base **`0x1000 0000`** (**SDRAM** = 0) or **`0x1800 0000`** (**SDRAM** = 1). Set by hardware on N64 Reset/NMI event.
- Bit 0: Reserved. Reads as 0, writes are ignored but it's recommended to be set as 0 for future compatibility.
- 0: Flash disabled
- 1: Flash enabled
@ -107,13 +75,12 @@ Access: Read or write, 4 byte (32 bit) aligned
This register is used for PC -> bootloader communication.
31:8 | 7:6 | 5:4 | 3:0
--------|--------|---------|----------
0 | SWITCH | TV_TYPE | CIC_TYPE
x | R/W | R/W | R/W
31:6 | 5:4 | 3:0
--------|---------|----------
SWITCH | TV_TYPE | CIC_TYPE
R/W | R/W | R/W
- Bits 31:8: Reserved. Reads as 0, writes are ignored but it's recommended to be set as 0 for future compatibility.
- Bits 7:6 **SWITCH**: Additional bits that can be passed to bootloader, currently unused.
- Bits 31:6 **SWITCH**: Additional bits that can be passed to bootloader, currently unused.
- Bits 5:4 **TV_TYPE**: Overrides TV type in bootloader. Used only when **CIC_TYPE** value is valid (values 1 - 7).
- 0: PAL TV type
- 1: NTSC TV type
@ -129,469 +96,3 @@ This register is used for PC -> bootloader communication.
- 6: CIC X106
- 7: CIC 8303
- 8 - 15: Same effect as value 0
#### Debug single byte RX FIFO access (**DEBUG_RX**) (unimplemented)
Address offset: **`0x08`** and **`0x0C`**\
Access: Read only, 4 byte (32 bit) aligned
This register grabs single byte from debug RX FIFO.
Due to how PI interface read prefetch is implemented this register exists on 2 addresses but it's necessary to do only single read on address offset **`0x08`**. Never read from address **`0x0C`** directly as it will not perform read action properly (read pointer is not incremented).
31:8 | 7:0
-------|------------
0 | RX_DATA
x | R
- Bits 31:8: Reserved. Reads as 0.
- Bits 7:0 **RX_DATA**: Data read from debug RX FIFO.
#### Debug single byte TX FIFO access (**DEBUG_TX**) (unimplemented)
Address offset: **`0x10`**\
Access: Write only, 4 byte (32 bit) aligned
This register puts single byte on debug TX FIFO.
31:8 | 7:0
-------|------------
0 | TX_DATA
x | W
- Bits 31:8: Reserved. Writes are ignored but it's recommended to be set as 0 for future compatibility.
- Bits 7:0 **TX_DATA**: Data to be written to debug TX FIFO.
#### Debug status register (**DEBUG_SR**) (unimplemented)
Address offset: **`0x14`**\
Access: Read or write, 4 byte (32 bit) aligned
This register is used for reading status and flushing debug RX/TX FIFOs.
31:24 | 23 | 22 | 21:11 | 10:0
--------|----------|----------|------------|------------
0 | TX_FLUSH | RX_FLUSH | TX_FIFO_UB | RX_FIFO_UB
x | W | W | R | R
- Bits 31:24: Reserved. Reads as 0, writes are ignored but it's recommended to be set as 0 for future compatibility.
- Bit 23 **TX_FLUSH**: Flushes TX FIFO.
- 0: No action
- 1: Flush TX FIFO
- Bit 22 **RX_FLUSH**: Flushes RX FIFO.
- 0: No action
- 1: Flush RX FIFO
- Bits 21:11 **TX_FIFO_UB**: Number of bytes waiting to be read by PC.
- Bits 10:0 **RX_FIFO_UB**: Number of bytes waiting to be processed by N64.
### Flash (**FLASH**) registers
Base address: **`0x1C00 0000`**
#### Arbitrary command register (**ACR**)
Address offset: **`0x00`**\
Access: Read or write, 4 byte (32 bit) aligned
This register is used to send arbitrary commands to Flash chip, useful for erasing and programming memory from PC or N64. Extended register documentation is available at [this webpage](https://zipcpu.com/blog/2019/03/27/qflexpress.html).
31:13 | 12 | 11 | 10 | 9 | 8 | 7:0
---------|------|------|----|-----------|-------------|-------
0 | MODE | QUAD | 0 | DIRECTION | CHIP_SELECT | DATA
x | W | W | x | W | W | R/W
- Bits 31:13: Reserved. Reads as 0, writes are ignored but it's recommended to be set as 0 for future compatibility
- Bit 12 **MODE**: Sets flash module arbitrary command mode.
- 0: Normal mode, no command is send to the Flash chip
- 1: Arbitrary command mode. When set no reads should be made on the *Flash Memory* address space
- Bit 11 **QUAD**: Sets next Q/SPI transaction transfer speed.
- 0: SPI 1-bit transaction
- 1: QSPI 4-bit transaction
- Bit 10: Reserved. Reads as 0, writes are ignored but it's recommended to be set as 0 for future compatibility
- Bit 9 **DIRECTION**: Sets next QSPI transaction direction. This bit has no effect when **QUAD** bit is set to 0
- 0: QSPI read transaction
- 1: QSPI write transaction
- Bit 8 **CHIP_SELECT**: Sets next Q/SPI transaction CS pin value and enables/disables next transaction.
- 0: Deselects Flash chip, no transaction is made
- 1: Selects Flash chip, transaction is made
- Bits 7:0 **DATA**: Data transferred to/from Flash chip
- Read: Data returned from last transaction
- Write: Data to be written in next transaction
## PC communication
PC <-> Cart communication uses SPI as hardware layer. Communication is command based and PC is always responsible for transfer initiation.
Module contains two 1024 word (4 kB) FIFOs used as a gate between SPI clock domain and Cart clock domain. Debug communication uses its own set of FIFOs, 1 kB in size each.
### Commands
Every command starts with setting CS pin low, then sending command, writing and/or reading data and setting CS pin high. Only SPI mode 0 is supported.
#### Status (**0x00**)
Reads PC communication module status word.
Command bytes:
Byte(s) | 0 | 1:4
-----------|------|-------------
Value | 0x00 | Status word
Direction | W | R
Status word bits:
31:24 | 23 | 22 | 21:11 | 10:0
-------|-----------|-------------|------------|------------
ID | ADDR_INCR | N64_DISABLE | TX_FIFO_UW | RX_FIFO_UW
- Bits 31:24 **ID**: Always **`0xAA`**, can be used to identify proper communication with cart.
- Bit 23 **ADDR_INCR**: Returns current status of **ADDR_INCR** bit in configuration.
- 0: No address increment
- 1: Address increment
- Bit 22 **N64_DISABLE**: Returns current status of **N64_DISABLE** bit in configuration.
- 0: N64 PI interface enabled, PC bus access disabled
- 1: N64 PI interface disabled, PC bus access enabled
- Bits 21:11 **TX_FIFO_UW**: Number of 4 byte (32 bit) words waiting to be processed by bus controller.
- Bits 10:0 **RX_FIFO_UW**: Number of 4 byte (32 bit) words waiting to be read by PC.
Example - read status word:
Byte | 0 | 1 | 2 | 3 | 4
------|------|------|------|------|------
TX | 0x00 | x | x | x | x
RX | x | 0xAA | 0x00 | 0x00 | 0x00
*x = don't care*
#### Config (**0x10**)
Sets PC communication module bus controller configuration.
This command consumes space in TX FIFO. Check TX FIFO availability before issuing this command.
Command bytes:
Byte(s) | 0 | 1:4
-----------|------|--------------------
Value | 0x10 | Configuration word
Direction | W | W
Configuration word bits:
31:2 | 1 | 0
------|-----------|-------------
x | ADDR_INCR | N64_DISABLE
- Bits 31:2: Reserved. Writes are ignored but it's recommended to be set as 0 for future compatibility.
- Bit 1 **ADDR_INCR**: Sets address increment mode when reading or writing to bus. Useful for writing/reading many values to/from single address.
- 0: No address increment
- 1: Address increment
- Bit 0 **N64_DISABLE**: Disables N64 PI interface and enables communication module access to the bus.
- 0: N64 PI interface enabled, PC bus access disabled
- 1: N64 PI interface disabled, PC bus access enabled
Example - set address increment and disable N64:
Byte | 0 | 1 | 2 | 3 | 4
------|------|------|------|------|------
TX | 0x10 | 0x00 | 0x00 | 0x00 | 0x03
RX | x | x | x | x | x
*x = don't care*
#### Set address (**0x20**)
Sets starting bus address.
This command consumes space in TX FIFO. Check TX FIFO availability before issuing this command.
Command bytes:
Byte(s) | 0 | 1:4
-----------|------|--------------
Value | 0x20 | Address word
Direction | W | W
Address word bits:
31:0 |
---------|
ADDRESS |
- Bits 31:0 **ADDRESS**: Starting address in bus address space.
Example - set starting address **`0x1034 5678`**:
Byte | 0 | 1 | 2 | 3 | 4
------|------|------|------|------|------
TX | 0x20 | 0x10 | 0x34 | 0x56 | 0x78
RX | x | x | x | x | x
*x = don't care*
#### Initiate read to RX FIFO (**0x30**)
Initiates read of X 4 byte (32 bit) words to RX FIFO. Maximum possible read length is 64 MB. However, it's possible to send multiple commands in series to achieve longer read lengths. After issuing this command it's necesarry to read data with "Read from RX FIFO (0x50)" command. Command will read dummy data when **N64_DISABLE** bit is cleared in communication module configuration.
This command consumes space in TX FIFO. Check TX FIFO availability before issuing this command.
Command bytes:
Byte(s) | 0 | 1:4
-----------|------|------------------
Value | 0x30 | Read length word
Direction | W | W
Read length word bits:
31:24 | 23:0 |
-------|-------------|
x | READ_LENGTH |
- Bits 31:24: Reserved. Writes are ignored but it's recommended to be set as 0 for future compatibility.
- Bits 23:0 **READ_LENGTH**: Number of words to be read to RX FIFO minus one.
Example - fill RX FIFO with 5 words (20 bytes):
Byte | 0 | 1 | 2 | 3 | 4
------|------|------|------|------|------
TX | 0x30 | 0x00 | 0x00 | 0x00 | 0x04
RX | x | x | x | x | x
*x = don't care*
#### Write to TX FIFO (**0x40**)
Writes data to TX FIFO. Sent words then are processed immediately as bus writes at current internal bus address. Data can be written only as 4 byte (32 bit) words. When **N64_DISABLE** bit in communication module configuration is cleared then command will process data in TX FIFO but it won't write anything to bus.
This command consumes space in TX FIFO. Check TX FIFO availability before issuing this command.
Command bytes:
Byte(s) | 0 | 1:4 | 5:8 | 9:12 | ...
-----------|------|-----------|-----------|-----------|-----
Value | 0x40 | Data word | Data word | Data word | ...
Direction | W | W | W | W | ...
Data word bits:
31:0 |
------|
DATA |
- Bits 31:0 **DATA**: Word to be written to bus.
Example - fill TX FIFO with 2 words (8 bytes) **`0xDEAD BEEF`**, **`0x0102 0304`**:
Byte | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8
------|------|------|------|------|------|------|------|------|------
TX | 0x40 | 0xDE | 0xAD | 0xBE | 0xEF | 0x01 | 0x02 | 0x03 | 0x04
RX | x | x | x | x | x | x | x | x | x
*x = don't care*
#### Read from RX FIFO (**0x50**)
Reads data from RX FIFO. Data can be read only as 4 byte (32 bit) words. Before reading it's necessary to check RX FIFO availability. Reading empty FIFO won't break anything but it's pointless.
Command bytes:
Byte(s) | 0 | 1:4 | 5:8 | 9:12 | ...
-----------|------|-----------|-----------|-----------|-----
Value | 0x50 | Data word | Data word | Data word | ...
Direction | W | R | R | R | ...
Data word bits:
31:0 |
------|
DATA |
- Bits 31:0 **DATA**: Word read from the bus.
Example - read 2 words (8 bytes) **`0xDEAD BEEF`**, **`0x0102 0304`** from RX FIFO:
Byte | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8
------|------|------|------|------|------|------|------|------|------
TX | 0x50 | x | x | x | x | x | x | x | x
RX | x | 0xDE | 0xAD | 0xBE | 0xEF | 0x01 | 0x02 | 0x03 | 0x04
*x = don't care*
#### Read debug FIFO status (**0x60**) (unimplemented)
Reads debug FIFO status.
Command bytes:
Byte(s) | 0 | 1:4
-----------|------|------------------------
Value | 0x00 | Debug FIFO status word
Direction | W | R
Debug FIFO status word bits:
31:22 | 21:11 | 10:0
-------|------------|------------
x | TX_FIFO_UB | RX_FIFO_UB
- Bits 31:22: Reserved. Reads as 0.
- Bits 21:11 **TX_FIFO_UB**: Number of bytes waiting to be processed by N64.
- Bits 10:0 **RX_FIFO_UB**: Number of bytes waiting to be read by PC.
Example - read debug FIFO status word:
Byte | 0 | 1 | 2 | 3 | 4
------|------|------|------|------|------
TX | 0x60 | x | x | x | x
RX | x | 0x00 | 0x00 | 0x00 | 0x00
*x = don't care*
#### Write to debug TX FIFO (**0x70**) (unimplemented)
Writes bytes to debug TX FIFO.
This command consumes space in debug TX FIFO. Check debug TX FIFO availability before issuing this command.
Command bytes:
Byte(s) | 0 | 1 | 2 | 3 | ...
-----------|------|-----------|-----------|-----------|-----
Value | 0x70 | Data byte | Data byte | Data byte | ...
Direction | W | W | W | W | ...
Data byte bits:
7:0 |
------|
DATA |
- Bits 7:0 **DATA**: Byte to be written to debug TX FIFO.
Example - fill debug TX FIFO with 4 bytes **`0xDE`**, **`0xAD`**, **`0xBE`**, **`0xEF`**:
Byte | 0 | 1 | 2 | 3 | 4
------|------|------|------|------|------
TX | 0x70 | 0xDE | 0xAD | 0xBE | 0xEF
RX | x | x | x | x | x
*x = don't care*
#### Read from debug RX FIFO (**0x80**) (unimplemented)
Reads bytes from debug RX FIFO. Before reading it's necessary to check debug RX FIFO availability. Reading empty FIFO won't break anything but it's pointless.
Command bytes:
Byte(s) | 0 | 1 | 2 | 3 | ...
-----------|------|-----------|-----------|-----------|-----
Value | 0x70 | Data byte | Data byte | Data byte | ...
Direction | W | R | R | R | ...
Data byte bits:
7:0 |
------|
DATA |
- Bits 7:0 **DATA**: Byte read from debug RX FIFO.
Example - read 4 bytes from debug RX FIFO:
Byte | 0 | 1 | 2 | 3 | 4
------|------|------|------|------|------
TX | 0x80 | x | x | x | x
RX | x | 0xDE | 0xAD | 0xBE | 0xEF
*x = don't care*
#### PC communication module bus controller reset (**0xFC**)
Resets PC communication module bus controller. It's recommended to issue "Reset (**0xFF**)" command before sending this one.
This command consumes space in TX FIFO. Check TX FIFO availability before issuing this command.
Command bytes:
Byte(s) | 0 | 1:4
-----------|------|------------
Value | 0xFC | Reset word
Direction | W | W
Reset word bits:
31:0 |
------|
x |
- Bits 31:0: Reserved. Writes are ignored but it's recommended to be set as 0 for future compatibility.
Example - reset PC communication module:
Byte | 0 | 1 | 2 | 3 | 4
------|------|------|------|------|------
TX | 0xFC | 0x00 | 0x00 | 0x00 | 0x00
RX | x | x | x | x | x
*x = don't care*
#### Flush TX FIFO (**0xFD**)
Flushes TX FIFO.
Command bytes:
Byte(s) | 0
-----------|------
Value | 0xFD
Direction | W
Example - flush TX FIFO:
Byte | 0
------|------
TX | 0xFD
RX | x
*x = don't care*
#### Flush RX FIFO (**0xFE**)
Flushes RX FIFO.
Command bytes:
Byte(s) | 0
-----------|------
Value | 0xFE
Direction | W
Example - flush RX FIFO:
Byte | 0
------|------
TX | 0xFE
RX | x
*x = don't care*
#### Reset (**0xFF**)
Resets PC communication module SPI controller and flushes both TX and RX data/debug FIFOs.
Command bytes:
Byte(s) | 0
-----------|------
Value | 0xFF
Direction | W
Example - send reset:
Byte | 0
------|------
TX | 0xFF
RX | x
*x = don't care*

View File

@ -19,7 +19,7 @@
#
# Quartus Prime
# Version 20.1.0 Build 711 06/05/2020 SJ Lite Edition
# Date created = 23:45:19 July 29, 2020
# Date created = 00:00:00 November 06, 2020
#
# -------------------------------------------------------------------------- #
#
@ -37,30 +37,35 @@
# -------------------------------------------------------------------------- #
set_global_assignment -name FAMILY "MAX 10"
set_global_assignment -name DEVICE 10M08SCE144C8G
set_global_assignment -name TOP_LEVEL_ENTITY top
# Project-Wide Assignments
# ========================
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_global_assignment -name FLOW_ENABLE_POWER_ANALYZER ON
set_global_assignment -name SMART_RECOMPILE OFF
set_global_assignment -name VERILOG_FILE rtl/cart/control.v
set_global_assignment -name VERILOG_FILE rtl/usb/pc.v
set_global_assignment -name VERILOG_FILE rtl/usb/ftdi_fsi.v
set_global_assignment -name QSYS_FILE rtl/intel/flash/onchip_flash.qsys
set_global_assignment -name VERILOG_FILE rtl/glue/device_arbiter.v
set_global_assignment -name SYSTEMVERILOG_FILE rtl/intel/gpio/gpio_ddro/altera_gpio_lite.sv -library gpio_ddro
set_global_assignment -name QIP_FILE rtl/intel/gpio/gpio_ddro.qip
set_global_assignment -name QIP_FILE rtl/intel/pll/pll.qip
set_global_assignment -name QIP_FILE rtl/intel/ram/ram_n64_eeprom.qip
set_global_assignment -name VERILOG_FILE rtl/memory/sdram.v
set_global_assignment -name VERILOG_FILE rtl/memory/embedded_flash.v
set_global_assignment -name VERILOG_FILE rtl/n64/si.v
set_global_assignment -name VERILOG_FILE rtl/n64/pi.v
set_global_assignment -name VERILOG_FILE rtl/n64/bank_decoder.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/fifo/fifo_ack.qip
# Pin & Location Assignments
# ==========================
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]
@ -140,18 +145,6 @@ 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]
@ -165,46 +158,121 @@ 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 BALANCED
set_global_assignment -name ENABLE_SIGNALTAP ON
set_global_assignment -name USE_SIGNALTAP_FILE misc/SignalTapLogicAnalyzer.stp
set_location_assignment PIN_15 -to i_ftdi_cts
set_location_assignment PIN_14 -to i_ftdi_so
set_location_assignment PIN_13 -to o_ftdi_clk
set_location_assignment PIN_12 -to o_ftdi_si
# Classic Timing Assignments
# ==========================
set_global_assignment -name MIN_CORE_JUNCTION_TEMP 0
set_global_assignment -name MAX_CORE_JUNCTION_TEMP 85
set_global_assignment -name TIMING_ANALYZER_MULTICORNER_ANALYSIS ON
set_global_assignment -name TIMING_ANALYZER_DO_REPORT_TIMING ON
# Compiler Assignments
# ====================
set_global_assignment -name OPTIMIZATION_MODE "HIGH PERFORMANCE EFFORT"
# Analysis & Synthesis Assignments
# ================================
set_global_assignment -name FAMILY "MAX 10"
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 VERILOG_INPUT_VERSION SYSTEMVERILOG_2005
set_global_assignment -name VERILOG_SHOW_LMF_MAPPING_MESSAGES OFF
set_global_assignment -name TOP_LEVEL_ENTITY top
# Fitter Assignments
# ==================
set_global_assignment -name DEVICE 10M08SCE144C8G
set_global_assignment -name ERROR_CHECK_FREQUENCY_DIVISOR 256
set_global_assignment -name ENABLE_CONFIGURATION_PINS OFF
set_global_assignment -name ENABLE_BOOT_SEL_PIN OFF
set_global_assignment -name CRC_ERROR_OPEN_DRAIN OFF
set_global_assignment -name STRATIX_DEVICE_IO_STANDARD "3.3-V LVTTL"
set_global_assignment -name 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/n64_si.v
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_global_assignment -name QIP_FILE rtl/intel/ram/ram_n64_eeprom.qip
set_instance_assignment -name PARTITION_HIERARCHY root_partition -to | -section_id Top
set_global_assignment -name SLD_FILE db/SignalTapLogicAnalyzer_auto_stripped.stp
# Assembler Assignments
# =====================
set_global_assignment -name ENABLE_OCT_DONE OFF
set_global_assignment -name EXTERNAL_FLASH_FALLBACK_ADDRESS 00000000
set_global_assignment -name USE_CONFIGURATION_DEVICE OFF
# Programmer Assignments
# ======================
set_global_assignment -name GENERATE_SVF_FILE ON
# Signal Tap Assignments
# ======================
set_global_assignment -name ENABLE_SIGNALTAP OFF
set_global_assignment -name USE_SIGNALTAP_FILE output_files/signal_tap_logic_analyzer.stp
# Power Estimation Assignments
# ============================
set_global_assignment -name POWER_PRESET_COOLING_SOLUTION "NO HEAT SINK WITH STILL AIR"
set_global_assignment -name POWER_BOARD_THERMAL_MODEL "NONE (CONSERVATIVE)"
set_global_assignment -name POWER_DEFAULT_INPUT_IO_TOGGLE_RATE "12.5 %"
# Advanced I/O Timing Assignments
# ===============================
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
# ------------------------------
# start ENTITY(altera_gpio_lite)
# Project-Wide Assignments
# ========================
# end ENTITY(altera_gpio_lite)
# ----------------------------
# -----------------------
# start ENTITY(gpio_ddro)
# Project-Wide Assignments
# ========================
# end ENTITY(gpio_ddro)
# ---------------------
# -----------------
# start ENTITY(top)
# Fitter Assignments
# ==================
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_n64_si_clk
set_instance_assignment -name GLOBAL_SIGNAL GLOBAL_CLOCK -to i_clk
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]"
# start DESIGN_PARTITION(Top)
# ---------------------------
# Incremental Compilation Assignments
# ===================================
set_global_assignment -name PARTITION_NETLIST_TYPE SOURCE -section_id Top
set_global_assignment -name PARTITION_FITTER_PRESERVATION_LEVEL PLACEMENT_AND_ROUTING -section_id Top
set_global_assignment -name PARTITION_COLOR 16764057 -section_id Top
set_instance_assignment -name PARTITION_HIERARCHY root_partition -to | -section_id Top
# end DESIGN_PARTITION(Top)
# -------------------------
# end ENTITY(top)
# ---------------

View File

@ -1,7 +1,5 @@
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

View File

@ -1,95 +0,0 @@
<session jtag_chain="Arrow-USB-Blaster [AR4XF287]" jtag_device="@1: 10M08SA(.|ES)/10M08SC (0x031820DD)" sof_file="../output_files/SummerCart64.sof">
<display_tree gui_logging_enabled="0">
<display_branch instance="auto_signaltap_0" signal_set="USE_GLOBAL_TEMP" trigger="USE_GLOBAL_TEMP"/>
</display_tree>
<instance enabled="false" entity_name="sld_signaltap" is_auto_node="yes" is_expanded="true" name="auto_signaltap_0" source_file="sld_signaltap.vhd">
<node_ip_info instance_id="0" mfg_id="110" node_id="0" version="6"/>
<signal_set global_temp="1" is_expanded="true" name="signal_set: 2020/10/10 04:31:29 #0">
<clock name="pll:sys_pll|c0" polarity="posedge" tap_mode="classic"/>
<config pipeline_level="0" ram_type="AUTO" reserved_data_nodes="0" reserved_storage_qualifier_nodes="0" reserved_trigger_nodes="0" sample_depth="131072" trigger_in_enable="no" trigger_out_enable="no"/>
<top_entity/>
<signal_vec>
<trigger_input_vec>
<wire name="io_n64_si_dq" tap_mode="classic"/>
<wire name="r_n64_reset_ff2" tap_mode="classic"/>
</trigger_input_vec>
<data_input_vec>
<wire name="io_n64_si_dq" tap_mode="classic"/>
</data_input_vec>
<storage_qualifier_input_vec>
<wire name="io_n64_si_dq" tap_mode="classic"/>
<wire name="r_n64_reset_ff2" tap_mode="classic"/>
</storage_qualifier_input_vec>
</signal_vec>
<presentation>
<unified_setup_data_view>
<node data_index="0" duplicate_name_allowed="false" is_data_input="true" is_node_valid="true" is_selected="false" is_storage_input="true" is_trigger_input="true" level-0="dont_care" name="io_n64_si_dq" pwr_level-0="dont_care" pwr_storage-0="dont_care" pwr_storage-1="dont_care" pwr_storage-2="dont_care" storage-0="dont_care" storage-1="dont_care" storage-2="dont_care" storage_index="0" tap_mode="classic" trigger_index="0" type="unknown"/>
<node duplicate_name_allowed="false" is_data_input="false" is_node_valid="true" is_selected="false" is_storage_input="true" is_trigger_input="true" level-0="high" name="r_n64_reset_ff2" pwr_level-0="dont_care" pwr_storage-0="dont_care" pwr_storage-1="dont_care" pwr_storage-2="dont_care" storage-0="dont_care" storage-1="dont_care" storage-2="dont_care" storage_index="1" tap_mode="classic" trigger_index="1" type="unknown"/>
</unified_setup_data_view>
<data_view>
<net data_index="0" duplicate_name_allowed="false" is_data_input="true" is_node_valid="true" is_selected="false" is_storage_input="true" is_trigger_input="true" level-0="dont_care" name="io_n64_si_dq" pwr_level-0="dont_care" pwr_storage-0="dont_care" pwr_storage-1="dont_care" pwr_storage-2="dont_care" storage-0="dont_care" storage-1="dont_care" storage-2="dont_care" storage_index="0" tap_mode="classic" trigger_index="0" type="unknown"/>
</data_view>
<setup_view>
<net data_index="0" duplicate_name_allowed="false" is_data_input="true" is_node_valid="true" is_selected="false" is_storage_input="true" is_trigger_input="true" level-0="dont_care" name="io_n64_si_dq" pwr_level-0="dont_care" pwr_storage-0="dont_care" pwr_storage-1="dont_care" pwr_storage-2="dont_care" storage-0="dont_care" storage-1="dont_care" storage-2="dont_care" storage_index="0" tap_mode="classic" trigger_index="0" type="unknown"/>
<net duplicate_name_allowed="false" is_data_input="false" is_node_valid="true" is_selected="false" is_storage_input="true" is_trigger_input="true" level-0="high" name="r_n64_reset_ff2" pwr_level-0="dont_care" pwr_storage-0="dont_care" pwr_storage-1="dont_care" pwr_storage-2="dont_care" storage-0="dont_care" storage-1="dont_care" storage-2="dont_care" storage_index="1" tap_mode="classic" trigger_index="1" type="unknown"/>
</setup_view>
<trigger_in_editor/>
<trigger_out_editor/>
</presentation>
<trigger attribute_mem_mode="false" gap_record="true" global_temp="1" is_expanded="true" name="trigger: 2020/10/10 04:31:29 #1" position="pre" power_up_trigger_mode="false" record_data_gap="true" segment_size="32768" storage_mode="off" storage_qualifier_disabled="no" storage_qualifier_port_is_pin="false" storage_qualifier_port_name="auto_stp_external_storage_qualifier" storage_qualifier_port_tap_mode="classic" trigger_type="circular">
<power_up_trigger position="pre" storage_qualifier_disabled="no"/>
<events use_custom_flow_control="no">
<level enabled="yes" name="condition1" type="basic">'r_n64_reset_ff2' == high
<power_up enabled="yes">
</power_up><op_node/>
</level>
</events>
<storage_qualifier_events>
<transitional>11
<pwr_up_transitional>11</pwr_up_transitional>
</transitional>
<storage_qualifier_level type="basic">
<power_up>
</power_up>
<op_node/>
</storage_qualifier_level>
<storage_qualifier_level type="basic">
<power_up>
</power_up>
<op_node/>
</storage_qualifier_level>
<storage_qualifier_level type="basic">
<power_up>
</power_up>
<op_node/>
</storage_qualifier_level>
</storage_qualifier_events>
</trigger>
</signal_set>
<position_info>
<single attribute="active tab" value="0"/>
<single attribute="data horizontal scroll position" value="13707"/>
<single attribute="data vertical scroll position" value="0"/>
<single attribute="setup horizontal scroll position" value="0"/>
<single attribute="setup vertical scroll position" value="0"/>
<single attribute="zoom level denominator" value="2"/>
<single attribute="zoom level numerator" value="1"/>
<single attribute="zoom offset denominator" value="1"/>
<single attribute="zoom offset numerator" value="245760"/>
</position_info>
</instance>
<mnemonics/>
<static_plugin_mnemonics/>
<global_info>
<single attribute="active instance" value="0"/>
<single attribute="config widget visible" value="1"/>
<single attribute="data log widget visible" value="1"/>
<single attribute="hierarchy widget visible" value="1"/>
<single attribute="instance widget visible" value="1"/>
<single attribute="jtag widget visible" value="1"/>
<single attribute="lock mode" value="0"/>
<multi attribute="column width" size="23" value="34,34,355,74,68,78,95,96,98,98,88,88,110,101,101,101,101,101,101,101,101,107,78"/>
<multi attribute="frame size" size="2" value="1718,1378"/>
<multi attribute="jtag widget size" size="2" value="348,135"/>
</global_info>
</session>

View File

@ -1,44 +0,0 @@
module address_decoder (
input [31:0] i_address,
output o_cart_config,
output o_flash,
output o_flash_cfg,
output o_sdram,
output o_eeprom,
input i_flash_enable,
input i_sdram_enable,
input i_eeprom_pi_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]);
localparam EEPROM_ADDR = 32'h1D00_0000;
localparam EEPROM_WIDTH = 11;
assign o_eeprom = i_eeprom_pi_enable && (i_address[31:EEPROM_WIDTH] == EEPROM_ADDR[31:EEPROM_WIDTH]);
assign o_address_valid = (|{o_cart_config, o_flash, o_flash_cfg, o_sdram, o_eeprom});
endmodule

77
fw/rtl/cart/control.v Normal file
View File

@ -0,0 +1,77 @@
module cart_control (
input i_clk,
input i_reset,
input i_n64_reset,
input i_n64_nmi,
input i_request,
input i_write,
output o_busy,
output reg o_ack,
input [0:0] i_address,
output reg [31:0] o_data,
input [31:0] i_data,
output reg o_rom_switch,
output reg o_eeprom_enable,
output reg o_eeprom_16k_mode
);
// Input synchronization
reg r_reset_ff1, r_reset_ff2;
reg r_nmi_ff1, r_nmi_ff2;
always @(posedge i_clk) begin
{r_reset_ff2, r_reset_ff1} <= {r_reset_ff1, i_n64_reset};
{r_nmi_ff2, r_nmi_ff1} <= {r_nmi_ff1, i_n64_nmi};
end
// Registers
reg [31:0] r_bootloader;
// Bus controller
assign o_busy = 1'b0;
always @(posedge i_clk) begin
if (i_reset) begin
o_ack <= 1'b0;
end else begin
o_ack <= i_request && !i_write && !o_busy;
end
end
always @(posedge i_clk) begin
if (i_reset) begin
o_rom_switch <= 1'b0;
o_eeprom_enable <= 1'b0;
o_eeprom_16k_mode <= 1'b0;
r_bootloader <= 32'h0000_0000;
end else begin
if (i_request && i_write && !o_busy) begin
case (i_address)
1'd0: {o_eeprom_16k_mode, o_eeprom_enable, o_rom_switch} <= {i_data[4], i_data[3], i_data[1]};
1'd1: r_bootloader <= i_data;
endcase
end
if (!r_reset_ff2 || !r_nmi_ff2) begin
o_rom_switch <= 1'b0;
end
end
end
always @(posedge i_clk) begin
if (i_request && !i_write && !o_busy) begin
case (i_address)
1'd0: o_data <= {o_eeprom_16k_mode, o_eeprom_enable, 1'b0, o_rom_switch, 1'b0};
1'd1: o_data <= r_bootloader;
endcase
end
end
endmodule

View File

@ -1,67 +0,0 @@
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 reg [31:0] o_data,
input i_n64_disabled,
output o_flash_enable,
output o_sdram_enable,
output o_eeprom_pi_enable,
output o_eeprom_enable,
output o_eeprom_16k_enable
);
reg [4:0] r_cart_config;
reg [7:0] r_cic_type;
always @(*) begin
o_data = 32'd0;
if (!i_address[2]) o_data = {27'd0, r_cart_config};
if (i_address[2]) o_data = {24'd0, r_cic_type};
end
assign {
o_eeprom_16k_enable,
o_eeprom_enable,
o_eeprom_pi_enable,
o_sdram_enable,
o_flash_enable,
} = r_cart_config;
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) || (!r_last_n64_nmi && i_n64_nmi));
always @(posedge i_clk) begin
r_last_n64_reset <= i_n64_reset;
r_last_n64_nmi <= i_n64_nmi;
end
always @(posedge i_clk) begin
if (i_reset) r_cart_config[4:0] <= 5'b00001;
if (w_n64_reset_op) r_cart_config[2:0] <= 3'b001;
if (!i_reset && i_select && i_write_rq && !i_address[2]) r_cart_config <= i_data[4:0];
end
always @(posedge i_clk) begin
if (i_reset) r_cic_type <= 8'd0;
if (!i_reset && i_select && i_write_rq && i_address[2]) r_cic_type <= i_data[7:0];
end
always @(posedge i_clk) begin
o_ack <= !i_reset && i_select && (i_read_rq || i_write_rq);
end
endmodule

View File

@ -1,29 +0,0 @@
# 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)
### Documentation
There's [comprehensive documentation](https://zipcpu.com/blog/2019/03/27/qflexpress.html) for this module:
### 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 chip.
- Changed column and row address widths.

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,79 +0,0 @@
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,80 @@
module device_arbiter (
input i_clk,
input i_reset,
input i_request_pri,
input i_write_pri,
output o_busy_pri,
output o_ack_pri,
input [3:0] i_bank_pri,
input [25:0] i_address_pri,
output [31:0] o_data_pri,
input [31:0] i_data_pri,
input i_request_sec,
input i_write_sec,
output o_busy_sec,
output o_ack_sec,
input [3:0] i_bank_sec,
input [25:0] i_address_sec,
output [31:0] o_data_sec,
input [31:0] i_data_sec,
output o_request,
output o_write,
input i_busy,
input i_ack,
output [25:0] o_address,
input [31:0] i_data,
output [31:0] o_data
);
parameter [3:0] DEVICE_BANK = 4'd0;
wire w_request_pri = i_request_pri && i_bank_pri == DEVICE_BANK;
wire w_request_sec = i_request_sec && i_bank_sec == DEVICE_BANK;
wire w_request_pri_successful = w_request_pri && !o_busy_pri;
wire w_request_sec_successful = w_request_sec && !o_busy_sec;
wire w_read_fifo_ack_full;
wire w_read_fifo_ack_pri_sec;
fifo_ack fifo_ack_inst (
.clock(i_clk),
.sclr(w_read_fifo_ack_reset),
.data(w_request_sec_successful && !i_write_sec),
.wrreq((w_request_pri_successful && !i_write_pri) || (w_request_sec_successful && !i_write_sec)),
.full(w_read_fifo_ack_full),
.rdreq(i_ack),
.q(w_read_fifo_ack_pri_sec)
);
assign o_busy_pri = w_request_pri && (i_busy || (!i_write_pri && w_read_fifo_ack_full));
assign o_ack_pri = i_ack && !w_read_fifo_ack_pri_sec;
assign o_data_pri = i_data;
assign o_busy_sec = w_request_sec && (i_request_pri || i_busy || (!i_write_sec && w_read_fifo_ack_full));
assign o_ack_sec = i_ack && w_read_fifo_ack_pri_sec;
assign o_data_sec = i_data;
assign o_request = w_request_pri || w_request_sec;
always @(*) begin
o_write = 1'b0;
o_address = 26'd0;
o_data = 32'd0;
if (w_request_pri_successful) begin
o_write = i_write_pri;
o_address = i_address_pri;
o_data = i_data_pri;
end else if (w_request_sec_successful) begin
o_write = i_write_sec;
o_address = i_address_sec;
o_data = i_data_sec;
end
end
endmodule

View File

@ -1,4 +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"]
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_ack.v"]

View File

@ -0,0 +1,163 @@
// megafunction wizard: %FIFO%
// GENERATION: STANDARD
// VERSION: WM1.0
// MODULE: scfifo
// ============================================================
// File Name: fifo_ack.v
// Megafunction Name(s):
// scfifo
//
// 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_ack (
clock,
data,
rdreq,
sclr,
wrreq,
empty,
full,
q);
input clock;
input [0:0] data;
input rdreq;
input sclr;
input wrreq;
output empty;
output full;
output [0:0] q;
wire sub_wire0;
wire sub_wire1;
wire [0:0] sub_wire2;
wire empty = sub_wire0;
wire full = sub_wire1;
wire [0:0] q = sub_wire2[0:0];
scfifo scfifo_component (
.clock (clock),
.data (data),
.rdreq (rdreq),
.sclr (sclr),
.wrreq (wrreq),
.empty (sub_wire0),
.full (sub_wire1),
.q (sub_wire2),
.aclr (),
.almost_empty (),
.almost_full (),
.eccstatus (),
.usedw ());
defparam
scfifo_component.add_ram_output_register = "OFF",
scfifo_component.intended_device_family = "MAX 10",
scfifo_component.lpm_numwords = 16,
scfifo_component.lpm_showahead = "ON",
scfifo_component.lpm_type = "scfifo",
scfifo_component.lpm_width = 1,
scfifo_component.lpm_widthu = 4,
scfifo_component.overflow_checking = "ON",
scfifo_component.underflow_checking = "ON",
scfifo_component.use_eab = "OFF";
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 "0"
// Retrieval info: PRIVATE: Depth NUMERIC "16"
// 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 "1"
// 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 "0"
// Retrieval info: PRIVATE: Width NUMERIC "1"
// Retrieval info: PRIVATE: dc_aclr NUMERIC "0"
// Retrieval info: PRIVATE: diff_widths NUMERIC "0"
// Retrieval info: PRIVATE: msb_usedw NUMERIC "0"
// Retrieval info: PRIVATE: output_width NUMERIC "1"
// 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 "1"
// 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_RAM_OUTPUT_REGISTER STRING "OFF"
// Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "MAX 10"
// Retrieval info: CONSTANT: LPM_NUMWORDS NUMERIC "16"
// Retrieval info: CONSTANT: LPM_SHOWAHEAD STRING "ON"
// Retrieval info: CONSTANT: LPM_TYPE STRING "scfifo"
// Retrieval info: CONSTANT: LPM_WIDTH NUMERIC "1"
// Retrieval info: CONSTANT: LPM_WIDTHU NUMERIC "4"
// Retrieval info: CONSTANT: OVERFLOW_CHECKING STRING "ON"
// Retrieval info: CONSTANT: UNDERFLOW_CHECKING STRING "ON"
// Retrieval info: CONSTANT: USE_EAB STRING "OFF"
// Retrieval info: USED_PORT: clock 0 0 0 0 INPUT NODEFVAL "clock"
// Retrieval info: USED_PORT: data 0 0 1 0 INPUT NODEFVAL "data[0..0]"
// Retrieval info: USED_PORT: empty 0 0 0 0 OUTPUT NODEFVAL "empty"
// Retrieval info: USED_PORT: full 0 0 0 0 OUTPUT NODEFVAL "full"
// Retrieval info: USED_PORT: q 0 0 1 0 OUTPUT NODEFVAL "q[0..0]"
// Retrieval info: USED_PORT: rdreq 0 0 0 0 INPUT NODEFVAL "rdreq"
// Retrieval info: USED_PORT: sclr 0 0 0 0 INPUT NODEFVAL "sclr"
// Retrieval info: USED_PORT: wrreq 0 0 0 0 INPUT NODEFVAL "wrreq"
// Retrieval info: CONNECT: @clock 0 0 0 0 clock 0 0 0 0
// Retrieval info: CONNECT: @data 0 0 1 0 data 0 0 1 0
// Retrieval info: CONNECT: @rdreq 0 0 0 0 rdreq 0 0 0 0
// Retrieval info: CONNECT: @sclr 0 0 0 0 sclr 0 0 0 0
// Retrieval info: CONNECT: @wrreq 0 0 0 0 wrreq 0 0 0 0
// Retrieval info: CONNECT: empty 0 0 0 0 @empty 0 0 0 0
// Retrieval info: CONNECT: full 0 0 0 0 @full 0 0 0 0
// Retrieval info: CONNECT: q 0 0 1 0 @q 0 0 1 0
// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_ack.v TRUE
// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_ack.inc FALSE
// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_ack.cmp FALSE
// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_ack.bsf FALSE
// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_ack_inst.v FALSE
// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_ack_bb.v FALSE
// Retrieval info: LIB_FILE: altera_mf

View File

@ -1,183 +0,0 @@
// 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

@ -1,4 +0,0 @@
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

@ -1,183 +0,0 @@
// 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,82 @@
<?xml version="1.0" encoding="UTF-8"?>
<system name="$${FILENAME}">
<component
name="$${FILENAME}"
displayName="$${FILENAME}"
version="1.0"
description=""
tags="INTERNAL_COMPONENT=true"
categories="" />
<parameter name="bonusData"><![CDATA[bonusData
{
element onchip_flash_0
{
datum _sortIndex
{
value = "0";
type = "int";
}
}
}
]]></parameter>
<parameter name="clockCrossingAdapter" value="HANDSHAKE" />
<parameter name="device" value="10M08SCE144C8G" />
<parameter name="deviceFamily" value="MAX 10" />
<parameter name="deviceSpeedGrade" value="8" />
<parameter name="fabricMode" value="QSYS" />
<parameter name="generateLegacySim" value="false" />
<parameter name="generationId" value="0" />
<parameter name="globalResetBus" value="false" />
<parameter name="hdlLanguage" value="VERILOG" />
<parameter name="hideFromIPCatalog" value="true" />
<parameter name="lockedInterfaceDefinition" value="" />
<parameter name="maxAdditionalLatency" value="1" />
<parameter name="projectName" value="" />
<parameter name="sopcBorderPoints" value="false" />
<parameter name="systemHash" value="0" />
<parameter name="testBenchDutName" value="" />
<parameter name="timeStamp" value="0" />
<parameter name="useTestBenchNamingPattern" value="false" />
<instanceScript></instanceScript>
<interface name="clk" internal="onchip_flash_0.clk" type="clock" dir="end">
<port name="clock" internal="clock" />
</interface>
<interface name="csr" internal="onchip_flash_0.csr" />
<interface name="data" internal="onchip_flash_0.data" type="avalon" dir="end">
<port name="avmm_data_addr" internal="avmm_data_addr" />
<port name="avmm_data_read" internal="avmm_data_read" />
<port name="avmm_data_readdata" internal="avmm_data_readdata" />
<port name="avmm_data_waitrequest" internal="avmm_data_waitrequest" />
<port name="avmm_data_readdatavalid" internal="avmm_data_readdatavalid" />
<port name="avmm_data_burstcount" internal="avmm_data_burstcount" />
</interface>
<interface name="nreset" internal="onchip_flash_0.nreset" type="reset" dir="end">
<port name="reset_n" internal="reset_n" />
</interface>
<module
name="onchip_flash_0"
kind="altera_onchip_flash"
version="20.1"
enabled="1"
autoexport="1">
<parameter name="AUTO_CLOCK_RATE" value="0" />
<parameter name="CLOCK_FREQUENCY" value="90.0" />
<parameter name="CONFIGURATION_MODE">Single Compressed Image</parameter>
<parameter name="CONFIGURATION_SCHEME">Internal Configuration</parameter>
<parameter name="DATA_INTERFACE" value="Parallel" />
<parameter name="DEVICE_FAMILY" value="MAX 10" />
<parameter name="PART_NAME" value="10M08SCE144C8G" />
<parameter name="READ_BURST_COUNT" value="2" />
<parameter name="READ_BURST_MODE" value="Incrementing" />
<parameter name="SECTOR_ACCESS_MODE">Read only,Read only,Hidden,Read only,Hidden</parameter>
<parameter name="autoInitializationFileName">$${FILENAME}_onchip_flash_0</parameter>
<parameter name="initFlashContent" value="true" />
<parameter name="initializationFileName">../sw/bootloader/build/SummerLoader64.hex</parameter>
<parameter name="initializationFileNameForSim">../sw/bootloader/build/SummerLoader64.hex</parameter>
<parameter name="useNonDefaultInitFile" value="true" />
</module>
<interconnectRequirement for="$system" name="qsys_mm.clockCrossingAdapter" value="HANDSHAKE" />
<interconnectRequirement for="$system" name="qsys_mm.enableEccProtection" value="FALSE" />
<interconnectRequirement for="$system" name="qsys_mm.insertDefaultSlave" value="FALSE" />
<interconnectRequirement for="$system" name="qsys_mm.maxAdditionalLatency" value="1" />
</system>

View File

@ -0,0 +1,56 @@
module memory_embedded_flash (
input i_clk,
input i_reset,
input i_request,
output reg o_busy,
output o_ack,
input [18:0] i_address,
output reg [31:0] o_data
);
localparam [18:0] ONCHIP_FLASH_END = 19'h059FF;
wire w_onchip_flash_in_address_range = i_address <= ONCHIP_FLASH_END;
reg r_dummy_ack;
always @(posedge i_clk) begin
r_dummy_ack <= i_request && !w_onchip_flash_in_address_range;
end
reg r_onchip_flash_request;
wire w_onchip_flash_busy;
wire w_onchip_flash_ack;
wire [31:0] w_onchip_flash_o_data;
assign o_ack = r_dummy_ack || w_onchip_flash_ack;
always @(*) begin
r_onchip_flash_request = 1'b0;
o_busy = 1'b0;
o_data = 32'h0000_0000;
if (w_onchip_flash_in_address_range) begin
r_onchip_flash_request = i_request;
o_busy = w_onchip_flash_busy;
o_data = {
w_onchip_flash_o_data[7:0],
w_onchip_flash_o_data[15:8],
w_onchip_flash_o_data[23:16],
w_onchip_flash_o_data[31:24],
};
end
end
onchip_flash onchip_flash_inst (
.clock(i_clk),
.reset_n(~i_reset),
.avmm_data_addr(i_address),
.avmm_data_read(r_onchip_flash_request),
.avmm_data_readdata(w_onchip_flash_o_data),
.avmm_data_waitrequest(w_onchip_flash_busy),
.avmm_data_readdatavalid(w_onchip_flash_ack),
.avmm_data_burstcount(2'd1)
);
endmodule

371
fw/rtl/memory/sdram.v Normal file
View File

@ -0,0 +1,371 @@
module memory_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,
inout [15:0] io_sdram_dq,
input i_request,
input i_write,
output o_busy,
output reg o_ack,
input [24:0] i_address,
output reg [31:0] o_data,
input [31:0] i_data
);
// SDRAM timings (in nanoseconds)
parameter real CLK_FREQ = 90_000_000.0;
parameter [2:0] CAS_LATENCY = 3'd2;
parameter real T_INIT = 100_000.0;
parameter real T_RC = 60.0;
parameter real T_RP = 15.0;
parameter real T_RCD = 15.0;
parameter real T_RAS = 37.0;
parameter real T_WR = T_RAS - T_RCD;
parameter real T_MRD = 14.0;
parameter real T_REF = 7_800.0;
localparam real T_CLK = (1.0 / CLK_FREQ) * 1_000_000_000.0;
localparam int C_INIT = int'((T_INIT + T_CLK - 1) / T_CLK);
localparam int C_RC = int'((T_RC + T_CLK - 1) / T_CLK);
localparam int C_RP = int'((T_RP + T_CLK - 1) / T_CLK);
localparam int C_RCD = int'((T_RCD + T_CLK - 1) / T_CLK);
localparam int C_RAS = int'((T_RAS + T_CLK - 1) / T_CLK);
localparam int C_WR = int'((T_WR + T_CLK - 1) / T_CLK);
localparam int C_MRD = int'((T_MRD + T_CLK - 1) / T_CLK);
localparam int C_REF = int'((T_REF + T_CLK - 1) / T_CLK);
localparam INIT_PRECHARGE = C_INIT;
localparam INIT_REFRESH_1 = C_INIT + C_RP;
localparam INIT_REFRESH_2 = C_INIT + C_RP + C_RC;
localparam INIT_MODE_REG = C_INIT + C_RP + (2 * C_RC);
localparam INIT_DONE = C_INIT + C_RP + (2 * C_RC) + C_MRD;
// SDRAM commands (CS, RAS, CAS, WE) and mode register
localparam [3:0] CMD_DESL = 4'b1111;
localparam [3:0] CMD_NOP = 4'b0111;
localparam [3:0] CMD_READ = 4'b0101;
localparam [3:0] CMD_WRITE = 4'b0100;
localparam [3:0] CMD_ACT = 4'b0011;
localparam [3:0] CMD_PRE = 4'b0010;
localparam [3:0] CMD_REF = 4'b0001;
localparam [3:0] CMD_MRS = 4'b0000;
localparam MODE_REGISTER = {2'b00, 1'b0, 1'b0, 2'b00, CAS_LATENCY, 1'b0, 3'b000};
// Command signal decoder
reg [3:0] r_sdram_cmd;
assign {o_sdram_cs, o_sdram_ras, o_sdram_cas, o_sdram_we} = r_sdram_cmd;
// Address signal decoder
reg r_sdram_precharge;
reg [1:0] r_sdram_bank;
reg [12:0] r_sdram_row;
reg [9:0] r_sdram_column;
reg [14:0] r_active_bank_row;
always @(*) begin
case (r_sdram_cmd)
CMD_READ, CMD_WRITE: o_sdram_a = {2'b00, r_sdram_precharge, r_sdram_column};
CMD_ACT: o_sdram_a = r_sdram_row;
CMD_PRE: o_sdram_a = {2'b00, r_sdram_precharge, 10'b0000000000};
CMD_MRS: o_sdram_a = MODE_REGISTER;
default: o_sdram_a = 13'b0000000000000;
endcase
end
always @(*) begin
case (r_sdram_cmd)
CMD_READ, CMD_WRITE, CMD_ACT, CMD_PRE: o_sdram_ba = r_sdram_bank;
default: o_sdram_ba = 2'b00;
endcase
end
always @(posedge i_clk) begin
if (i_request && !o_busy) begin
{r_sdram_bank, r_sdram_row, r_sdram_column} <= i_address;
end
if (r_sdram_cmd == CMD_ACT) begin
r_active_bank_row <= {r_sdram_bank, r_sdram_row};
end
if (r_sdram_cmd == CMD_READ || r_sdram_cmd == CMD_WRITE) begin
{r_sdram_bank, r_sdram_row, r_sdram_column} <= {r_sdram_bank, r_sdram_row, r_sdram_column} + 1'b1;
end
end
wire w_next_address_in_another_row = (&r_sdram_column);
wire w_request_in_another_row = i_address[24:10] != r_active_bank_row;
// Data signal decoder
reg [31:0] r_sdram_data;
reg r_current_write_word;
always @(*) begin
io_sdram_dq = 16'hZZZZ;
if (r_sdram_cmd == CMD_WRITE) begin
io_sdram_dq = r_current_write_word ? r_sdram_data[15:0] : r_sdram_data[31:16];
end
end
always @(posedge i_clk) begin
if (i_reset) begin
r_current_write_word <= 1'b0;
end else if (r_sdram_cmd == CMD_WRITE) begin
r_current_write_word <= ~r_current_write_word;
end
end
// Read latency timing
reg [(CAS_LATENCY - 1):0] r_read_latency;
reg r_current_read_word;
always @(posedge i_clk) begin
o_ack <= 1'b0;
if (i_reset) begin
r_read_latency <= {CAS_LATENCY{1'b0}};
r_current_read_word <= 1'b0;
end else begin
r_read_latency <= {r_read_latency[(CAS_LATENCY - 2):0], r_sdram_cmd == CMD_READ};
if (r_read_latency[CAS_LATENCY - 1]) begin
o_data <= {o_data[15:0], io_sdram_dq};
if (r_current_read_word) o_ack <= 1'b1;
r_current_read_word <= ~r_current_read_word;
end
end
end
wire w_read_pending = |r_read_latency;
// Init timing and logic
reg [15:0] r_init_counter;
always @(posedge i_clk) begin
if (i_reset) begin
r_init_counter <= 1'd0;
end else if (r_init_counter < INIT_DONE) begin
r_init_counter <= r_init_counter + 1'd1;
end
end
wire w_init_hold = r_init_counter <= C_INIT - 1;
wire w_init_precharge = r_init_counter == INIT_PRECHARGE;
wire w_init_refresh_1 = r_init_counter == INIT_REFRESH_1;
wire w_init_refresh_2 = r_init_counter == INIT_REFRESH_2;
wire w_init_mode_reg = r_init_counter == INIT_MODE_REG;
wire w_init_done = r_init_counter == INIT_DONE;
// SDRAM controller FSM
localparam [2:0] STATE_INIT = 3'd0;
localparam [2:0] STATE_IDLE = 3'd1;
localparam [2:0] STATE_ACTIVATING = 3'd2;
localparam [2:0] STATE_ACTIVE = 3'd3;
localparam [2:0] STATE_PRECHARGING = 3'd4;
localparam [2:0] STATE_REFRESHING = 3'd5;
reg [9:0] r_refresh_counter;
reg [4:0] r_rcd_ras_rc_counter;
reg [1:0] r_wr_counter;
reg [2:0] r_rp_counter;
wire w_refresh_pending = r_refresh_counter >= (C_REF - 1'd1);
wire w_rcd_timing_met = r_rcd_ras_rc_counter >= (C_RCD - 1'd1);
wire w_ras_timing_met = r_rcd_ras_rc_counter >= (C_RAS - 1'd1);
wire w_rc_timing_met = r_rcd_ras_rc_counter >= (C_RC - 1'd1);
wire w_wr_timing_met = r_wr_counter >= (C_WR - 1'd1);
wire w_rp_timing_met = r_rp_counter >= (C_RP - 1'd1);
reg [2:0] r_state;
reg r_busy;
reg r_cross_row_request;
reg r_request_pending;
reg r_write_pending;
reg r_current_word;
reg r_wr_wait;
assign o_busy = i_request && (
w_refresh_pending ||
r_busy ||
r_request_pending ||
r_cross_row_request ||
w_read_pending ||
r_sdram_cmd == CMD_READ ||
r_sdram_cmd == CMD_WRITE
);
always @(posedge i_clk) begin
if (i_reset || w_init_hold) begin
r_sdram_cmd <= CMD_DESL;
r_state <= STATE_INIT;
r_busy <= 1'b1;
r_cross_row_request <= 1'b0;
r_wr_wait <= 1'b0;
end else begin
r_sdram_cmd <= CMD_NOP;
r_sdram_precharge <= 1'b0;
if (r_refresh_counter < (C_REF - 1)) r_refresh_counter <= r_refresh_counter + 1'd1;
if (r_rcd_ras_rc_counter < (C_RC - 1)) r_rcd_ras_rc_counter <= r_rcd_ras_rc_counter + 1'd1;
if (r_wr_counter < (C_WR - 1)) r_wr_counter <= r_wr_counter + 1'd1;
if (r_rp_counter < (C_RP - 1)) r_rp_counter <= r_rp_counter + 1'd1;
case (r_state)
STATE_INIT: begin
if (w_init_precharge) begin
r_sdram_cmd <= CMD_PRE;
r_sdram_precharge <= 1'b1;
end else if (w_init_refresh_1 || w_init_refresh_2) begin
r_sdram_cmd <= CMD_REF;
r_refresh_counter <= 1'd0;
end else if (w_init_mode_reg) begin
r_sdram_cmd <= CMD_MRS;
end else if (w_init_done) begin
r_state <= STATE_IDLE;
r_busy <= 1'b0;
end
end
STATE_IDLE: begin
if (w_refresh_pending) begin
r_sdram_cmd <= CMD_REF;
r_refresh_counter <= 1'd0;
r_rcd_ras_rc_counter <= 1'd0;
r_state <= STATE_REFRESHING;
r_busy <= 1'b1;
end else if (r_request_pending || r_cross_row_request) begin
r_sdram_cmd <= CMD_ACT;
r_rcd_ras_rc_counter <= 1'd0;
r_state <= STATE_ACTIVATING;
r_busy <= 1'b1;
end else if (i_request && !o_busy) begin
r_sdram_cmd <= CMD_ACT;
r_sdram_data <= i_data;
r_rcd_ras_rc_counter <= 1'd0;
r_state <= STATE_ACTIVATING;
r_request_pending <= 1'b1;
r_write_pending <= i_write;
r_current_word <= 1'b0;
r_busy <= 1'b1;
end
end
STATE_ACTIVATING: begin
if (w_rcd_timing_met) begin
r_sdram_cmd <= r_write_pending ? CMD_WRITE : CMD_READ;
if (r_write_pending) r_wr_counter <= 1'd0;
if (r_cross_row_request) begin
r_cross_row_request <= 1'b0;
r_busy <= 1'b0;
end else if (r_request_pending) begin
r_current_word <= 1'b1;
end
r_state <= STATE_ACTIVE;
end
end
STATE_ACTIVE: begin
if (r_wr_wait) begin
if (w_wr_timing_met) begin
r_rp_counter <= 1'd0;
r_state <= STATE_PRECHARGING;
r_wr_wait <= 1'b0;
end
end else if (r_request_pending && !(r_write_pending && w_read_pending)) begin
r_sdram_cmd <= r_write_pending ? CMD_WRITE : CMD_READ;
if (r_write_pending) r_wr_counter <= 1'd0;
r_current_word <= 1'b1;
if (r_current_word) begin
r_busy <= 1'b0;
r_request_pending <= 1'b0;
end
end else if (w_refresh_pending) begin
if (w_ras_timing_met && w_wr_timing_met) begin
r_sdram_cmd <= CMD_PRE;
r_sdram_precharge <= 1'b1;
r_rp_counter <= 1'd0;
r_state <= STATE_PRECHARGING;
end
end else if (i_request && !o_busy) begin
r_sdram_data <= i_data;
r_busy <= 1'b1;
r_write_pending <= i_write;
if (w_request_in_another_row || (i_write && w_read_pending)) begin
r_request_pending <= 1'b1;
r_current_word <= 1'b0;
if (!(i_write && w_read_pending)) begin
if (!w_wr_timing_met) begin
r_wr_wait <= 1'b1;
end else begin
r_sdram_cmd <= CMD_PRE;
r_sdram_precharge <= 1'b1;
r_rp_counter <= 1'd0;
r_state <= STATE_PRECHARGING;
end
end
end else begin
r_sdram_cmd <= i_write ? CMD_WRITE : CMD_READ;
if (i_write) r_wr_counter <= 1'd0;
r_current_word <= 1'b1;
if (w_next_address_in_another_row) begin
r_sdram_precharge <= 1'b1;
r_cross_row_request <= 1'b1;
if (!i_write) begin
r_rp_counter <= 1'd0;
r_state <= STATE_PRECHARGING;
end else begin
r_wr_wait <= 1'b1;
end
end else begin
r_request_pending <= 1'b1;
end
end
end
end
STATE_PRECHARGING: begin
if (w_rc_timing_met && w_rp_timing_met) begin
r_state <= STATE_IDLE;
r_busy <= r_request_pending || r_cross_row_request;
end
end
STATE_REFRESHING: begin
if (w_rc_timing_met) begin
r_state <= STATE_IDLE;
r_busy <= 1'b0;
end
end
default: begin
r_state <= STATE_IDLE;
r_busy <= 1'b0;
end
endcase
end
end
endmodule

42
fw/rtl/n64/bank_decoder.v Normal file
View File

@ -0,0 +1,42 @@
module n64_bank_decoder (
input [31:0] i_address,
output reg [25:0] o_translated_address,
output reg [3:0] o_bank,
output reg o_bank_prefetch
);
localparam [3:0] BANK_INVALID = 4'd0;
localparam [3:0] BANK_ROM = 4'd1;
localparam [3:0] BANK_CART = 4'd2;
localparam [3:0] BANK_EEPROM = 4'd3;
localparam [31:0] ROM_BASE = 32'h1000_0000;
localparam [31:0] ROM_END = 32'h13FF_FFFF;
localparam [31:0] CART_BASE = 32'h1E00_0000;
localparam [31:0] CART_END = 32'h1EFF_FFFF;
localparam [31:0] EEPROM_BASE = 32'h1D00_0000;
localparam [31:0] EEPROM_END = 32'h1D00_07FF;
always @(*) begin
o_bank = BANK_INVALID;
o_bank_prefetch = 1'b0;
o_translated_address = i_address[25:0];
if (i_address >= ROM_BASE && i_address <= ROM_END) begin
o_translated_address = i_address - ROM_BASE;
o_bank = BANK_ROM;
o_bank_prefetch = 1'b1;
end
if (i_address >= CART_BASE && i_address <= CART_END) begin
o_translated_address = i_address - CART_BASE;
o_bank = BANK_CART;
end
if (i_address >= EEPROM_BASE && i_address <= EEPROM_END) begin
o_translated_address = i_address - EEPROM_BASE;
o_bank = BANK_EEPROM;
o_bank_prefetch = 1'b1;
end
end
endmodule

189
fw/rtl/n64/pi.v Normal file
View File

@ -0,0 +1,189 @@
module n64_pi (
input i_clk,
input i_reset,
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,
output reg o_request,
output reg o_write,
input i_busy,
input i_ack,
output [3:0] o_bank,
output reg [25:0] o_address,
input [31:0] i_data,
output reg [31:0] o_data
);
// Parameters
parameter bit PREFETCH_DISABLE = 1'b0;
// Input synchronization
reg r_reset_ff1, r_reset_ff2;
reg r_alel_ff1, r_alel_ff2;
reg r_aleh_ff1, r_aleh_ff2;
reg r_read_ff1, r_read_ff2;
reg r_write_ff1, r_write_ff2;
always @(posedge i_clk) begin
{r_reset_ff2, r_reset_ff1} <= {r_reset_ff1, i_n64_reset};
{r_alel_ff2, r_alel_ff1} <= {r_alel_ff1, i_n64_pi_alel};
{r_aleh_ff2, r_aleh_ff1} <= {r_aleh_ff1, i_n64_pi_aleh};
{r_read_ff2, r_read_ff1} <= {r_read_ff1, i_n64_pi_read};
{r_write_ff2, r_write_ff1} <= {r_write_ff1, i_n64_pi_write};
end
// PI event signals generator
wire [1:0] w_pi_mode = {r_aleh_ff2, r_alel_ff2};
reg [1:0] r_last_pi_mode;
reg r_last_read;
reg r_last_write;
always @(posedge i_clk) begin
r_last_pi_mode <= w_pi_mode;
r_last_read <= r_read_ff2;
r_last_write <= r_write_ff2;
end
localparam [1:0] PI_MODE_IDLE = 2'b10;
localparam [1:0] PI_MODE_HIGH = 2'b11;
localparam [1:0] PI_MODE_LOW = 2'b01;
localparam [1:0] PI_MODE_VALID = 2'b00;
wire w_address_high_op = r_reset_ff2 && (r_last_pi_mode != PI_MODE_HIGH) && (w_pi_mode == PI_MODE_HIGH);
wire w_address_low_op = r_reset_ff2 && (r_last_pi_mode != PI_MODE_LOW) && (w_pi_mode == PI_MODE_LOW);
wire w_address_valid_op = r_reset_ff2 && (r_last_pi_mode != PI_MODE_VALID) && (w_pi_mode == PI_MODE_VALID);
wire w_read_op = r_reset_ff2 && (w_pi_mode == PI_MODE_VALID) && r_last_read && !r_read_ff2;
wire w_write_op = r_reset_ff2 && (w_pi_mode == PI_MODE_VALID) && r_last_write && !r_write_ff2;
// Bus address register
reg [31:0] r_pi_address;
always @(posedge i_clk) begin
if (w_address_high_op) r_pi_address[31:16] <= io_n64_pi_ad;
if (w_address_low_op) r_pi_address[15:0] <= {io_n64_pi_ad[15:1], 1'b0};
end
// Bank decoder, address translator and prefetch signal
wire [25:0] w_translated_address;
wire w_bank_prefetch;
wire w_prefetch = !PREFETCH_DISABLE && w_bank_prefetch;
n64_bank_decoder n64_bank_decoder_inst (
.i_address(r_pi_address),
.o_translated_address(w_translated_address),
.o_bank(o_bank),
.o_bank_prefetch(w_bank_prefetch)
);
// Read/write current word logic
reg r_word_counter;
always @(posedge i_clk) begin
if (w_address_valid_op) r_word_counter <= 1'b0;
if (w_read_op || w_write_op) r_word_counter <= ~r_word_counter;
end
// N64 PI output data logic
reg [31:0] r_pi_output_data;
always @(*) begin
io_n64_pi_ad = 16'hZZZZ;
if (r_reset_ff2 && !r_read_ff2 && o_bank != 4'd0) begin
io_n64_pi_ad = r_word_counter ? r_pi_output_data[31:16] : r_pi_output_data[15:0];
end
end
// Bus event signals generator
wire w_bus_read_op = w_read_op && !r_word_counter;
wire w_bus_write_op = w_write_op && r_word_counter;
// Read buffer logic
reg [31:0] r_pi_read_buffer;
always @(posedge i_clk) begin
if (i_ack) begin
if (w_prefetch) r_pi_read_buffer <= i_data;
else r_pi_output_data <= i_data;
end
if (w_prefetch && w_bus_read_op) r_pi_output_data <= r_pi_read_buffer;
end
// Write data logic
reg [15:0] r_pi_write_buffer;
always @(posedge i_clk) begin
if (w_write_op) begin
if (!r_word_counter) begin
r_pi_write_buffer <= io_n64_pi_ad;
end else begin
o_data <= {r_pi_write_buffer, io_n64_pi_ad};
end
end
end
// Bus request logic
wire w_bus_request_op = !o_request && ((w_address_valid_op && w_prefetch) || w_bus_read_op || w_bus_write_op);
always @(posedge i_clk) begin
if (i_reset) begin
o_request <= 1'b0;
o_write <= 1'b0;
end else begin
if (w_bus_request_op) begin
o_request <= 1'b1;
o_write <= w_bus_write_op;
end
if (o_request && !i_busy) begin
o_request <= 1'b0;
o_write <= 1'b0;
end
end
end
// Address increment logic
reg r_first_transfer;
wire w_address_increment_op = (
(w_bus_read_op && (!r_first_transfer || w_prefetch)) ||
(w_bus_write_op && !r_first_transfer)
);
wire w_first_transfer_clear_op = w_bus_read_op || w_bus_write_op;
always @(posedge i_clk) begin
if (w_address_valid_op) begin
o_address <= w_translated_address;
r_first_transfer <= 1'b1;
end
if (w_first_transfer_clear_op) r_first_transfer <= 1'b0;
if (w_address_increment_op) o_address[8:2] <= o_address[8:2] + 1'b1;
end
endmodule

View File

@ -2,23 +2,41 @@ module n64_si (
input i_clk,
input i_reset,
input i_si_clk,
input i_si_reset,
input i_si_dq,
output reg o_si_dq,
input i_n64_reset,
input i_n64_si_clk,
inout io_n64_si_dq,
input i_eeprom_select,
input i_read_rq,
input i_write_rq,
input i_request,
input i_write,
output o_busy,
output reg o_ack,
input [31:0] i_address,
input [10:0] i_address,
input [31:0] i_data,
output [31:0] o_data,
input i_eeprom_enable,
input i_eeprom_16k_enable
input i_eeprom_16k_mode
);
// Input synchronization
reg r_reset_ff1, r_reset_ff2;
reg r_si_clk_ff1, r_si_clk_ff2;
reg r_si_dq_ff1, r_si_dq_ff2;
always @(posedge i_clk) begin
{r_reset_ff2, r_reset_ff1} <= {r_reset_ff1, i_n64_reset};
{r_si_clk_ff2, r_si_clk_ff1} <= {r_si_clk_ff1, i_n64_si_clk};
{r_si_dq_ff2, r_si_dq_ff1} <= {r_si_dq_ff1, io_n64_si_dq};
end
reg r_si_dq_o;
assign io_n64_si_dq = r_si_dq_o ? 1'bZ : 1'b0;
// SI commands
localparam CMD_EEPROM_STATUS = 8'h00;
localparam CMD_EEPROM_READ = 8'h04;
localparam CMD_EEPROM_WRITE = 8'h05;
@ -26,19 +44,23 @@ module n64_si (
localparam EEPROM_4K_ID = 8'h80;
localparam EEPROM_16K_ID = 8'hC0;
// Event signal generation
reg r_last_si_clk;
reg r_last_si_dq;
wire w_si_clk_falling_edge = !i_reset && !i_si_reset && r_last_si_clk && !i_si_clk;
wire w_si_clk_rising_edge = !i_reset && !i_si_reset && !r_last_si_clk && i_si_clk;
wire w_si_dq_falling_edge = r_last_si_dq && !i_si_dq;
wire w_si_dq_rising_edge = !r_last_si_dq && i_si_dq;
wire w_si_clk_falling_edge = !i_reset && r_reset_ff2 && r_last_si_clk && !r_si_clk_ff2;
wire w_si_clk_rising_edge = !i_reset && r_reset_ff2 && !r_last_si_clk && r_si_clk_ff2;
wire w_si_dq_falling_edge = r_last_si_dq && !r_si_dq_ff2;
wire w_si_dq_rising_edge = !r_last_si_dq && r_si_dq_ff2;
always @(posedge i_clk) begin
r_last_si_clk <= i_si_clk;
if (w_si_clk_rising_edge) r_last_si_dq <= i_si_dq;
r_last_si_clk <= r_si_clk_ff2;
if (w_si_clk_rising_edge) r_last_si_dq <= r_si_dq_ff2;
end
// RX module
reg r_rx_enabled;
@ -92,7 +114,7 @@ module n64_si (
wire w_cmd_op = r_rx_byte_ready && r_rx_byte_counter == 4'd0;
always @(posedge i_clk) begin
if (i_reset || i_si_reset || w_rx_start || r_tx_finished) begin
if (i_reset || !r_reset_ff2 || w_rx_start || r_tx_finished) begin
r_cmd_eeprom_status <= 1'b0;
r_cmd_eeprom_read <= 1'b0;
r_cmd_eeprom_write <= 1'b0;
@ -117,6 +139,7 @@ module n64_si (
if (w_eeprom_address_next_op) r_eeprom_address[2:0] <= r_eeprom_address[2:0] + 3'd1;
end
// TX module
reg [2:0] r_tx_sub_bit_counter;
@ -132,13 +155,13 @@ module n64_si (
always @(*) begin
r_tx_data = 8'h00;
if (r_cmd_eeprom_status && r_tx_byte_counter == 4'd1) r_tx_data = i_eeprom_16k_enable ? EEPROM_16K_ID : EEPROM_4K_ID;
if (r_cmd_eeprom_status && r_tx_byte_counter == 4'd1) r_tx_data = i_eeprom_16k_mode ? EEPROM_16K_ID : EEPROM_4K_ID;
if (r_cmd_eeprom_read) r_tx_data = w_eeprom_o_data;
end
always @(posedge i_clk) begin
if (i_reset || i_si_reset) begin
o_si_dq <= 1'b1;
if (i_reset || !r_reset_ff2) begin
r_si_dq_o <= 1'b1;
r_rx_enabled <= 1'b1;
r_tx_finished <= 1'b0;
r_eeprom_read_rq <= 1'b0;
@ -161,12 +184,12 @@ module n64_si (
if (w_si_clk_falling_edge) begin
r_tx_sub_bit_counter <= r_tx_sub_bit_counter + 3'd1;
if (r_tx_sub_bit_counter == 3'd0) o_si_dq <= 1'b0;
if (r_tx_sub_bit_counter == 3'd0) r_si_dq_o <= 1'b0;
if ((w_tx_current_bit && r_tx_sub_bit_counter == 3'd2) ||
(!w_tx_current_bit && r_tx_sub_bit_counter == 3'd6) ||
(w_tx_stop_bit && r_tx_sub_bit_counter == 3'd4)) begin
o_si_dq <= 1'b1;
r_si_dq_o <= 1'b1;
end
if (&r_tx_sub_bit_counter) begin
@ -185,6 +208,7 @@ module n64_si (
end
end
// Block RAM
ram_n64_eeprom ram_n64_eeprom_inst (
@ -197,14 +221,17 @@ module n64_si (
.address_b(i_address[10:2]),
.data_b({i_data[7:0], i_data[15:8], i_data[23:16], i_data[31:24]}),
.wren_b(!i_reset && i_eeprom_select && i_write_rq),
.wren_b(!i_reset && i_request && i_write),
.q_b({o_data[7:0], o_data[15:8], o_data[23:16], o_data[31:24]})
);
// Bus logic
always @(posedge i_clk) begin
o_ack <= !i_reset && i_eeprom_select && (i_read_rq || i_write_rq);
o_ack <= !i_reset && i_request;
end
assign o_busy = 1'b0;
endmodule

View File

@ -1,95 +0,0 @@
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

View File

@ -1,289 +0,0 @@
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

View File

@ -1,133 +0,0 @@
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

View File

@ -1,10 +1,10 @@
module top (
input i_clk,
input i_ftdi_clk,
input i_ftdi_cs,
input i_ftdi_do,
output o_ftdi_di,
output o_ftdi_clk,
output o_ftdi_si,
input i_ftdi_so,
input i_ftdi_cts,
input i_n64_nmi,
input i_n64_reset,
@ -23,8 +23,8 @@ module top (
output o_sdram_clk,
output o_sdram_cs,
output o_sdram_cas,
output o_sdram_ras,
output o_sdram_cas,
output o_sdram_we,
output [1:0] o_sdram_ba,
output [12:0] o_sdram_a,
@ -50,314 +50,277 @@ module top (
inout [7:0] io_pmod
);
// Clock and reset
// Clock and reset signals
wire w_sys_clk;
wire w_sdram_clk;
wire w_pll_lock;
wire w_sys_reset = ~w_pll_lock;
pll sys_pll(
// PLL clock generator
pll sys_pll (
.inclk0(i_clk),
.c0(w_sys_clk),
.c1(w_sdram_clk),
.locked(w_pll_lock)
);
gpio_ddro sdram_clk_ddro(
// SDRAM clock output
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;
// Bank ids
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;
localparam [3:0] BANK_INVALID = 4'd0;
localparam [3:0] BANK_ROM = 4'd1;
localparam [3:0] BANK_CART = 4'd2;
localparam [3:0] BANK_EEPROM = 4'd3;
reg r_n64_si_clk_ff1, r_n64_si_clk_ff2;
reg r_n64_si_dq_ff1, r_n64_si_dq_ff2;
always @(posedge w_sys_clk) 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};
// N64 PI
{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_si_dq_ff2, r_n64_si_dq_ff1} <= {r_n64_si_dq_ff1, io_n64_si_dq};
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_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_request;
wire w_n64_write;
wire w_n64_busy;
wire w_n64_ack;
wire [31:0] w_n64_address;
wire [3:0] w_n64_bank;
wire [25: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_busy_cart_control;
wire w_n64_ack_cart_control;
wire [31:0] w_n64_i_data_cart_control;
wire w_bus_read_rq;
wire w_bus_write_rq;
wire w_bus_ack;
wire [31:0] w_bus_address;
reg [31:0] r_bus_i_data;
wire [31:0] w_bus_o_data;
wire w_n64_busy_sdram;
wire w_n64_ack_sdram;
wire [31:0] w_n64_i_data_sdram;
wire w_n64_disable;
wire w_n64_busy_embedded_flash;
wire w_n64_ack_embedded_flash;
wire [31:0] w_n64_i_data_embedded_flash;
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_eeprom_select;
wire w_flash_enable;
wire w_sdram_enable;
wire w_eeprom_pi_enable;
wire w_eeprom_enable;
wire w_eeprom_16k_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;
wire w_eeprom_ack;
wire [31:0] w_eeprom_o_data;
reg r_empty_ack;
assign w_bus_ack = w_cart_config_ack || w_flash_ack || w_sdram_ack || w_eeprom_ack || r_empty_ack;
wire w_n64_busy_eeprom;
wire w_n64_ack_eeprom;
wire [31:0] w_n64_i_data_eeprom;
always @(*) begin
r_bus_i_data = 32'hFFFF_FFFF;
if (w_cart_config_select) r_bus_i_data = w_cart_config_o_data;
if (w_flash_select || w_flash_cfg_select) r_bus_i_data = w_flash_o_data;
if (w_sdram_select) r_bus_i_data = w_sdram_o_data;
if (w_eeprom_select) r_bus_i_data = w_eeprom_o_data;
w_n64_busy = w_n64_busy_cart_control || w_n64_busy_sdram || w_n64_busy_embedded_flash || w_n64_busy_eeprom;
w_n64_ack = w_n64_ack_cart_control || w_n64_ack_sdram || w_n64_ack_embedded_flash || w_n64_ack_eeprom;
w_n64_i_data = 32'h0000_0000;
if (w_n64_ack_cart_control) w_n64_i_data = w_n64_i_data_cart_control;
if (w_n64_ack_sdram) w_n64_i_data = w_n64_i_data_sdram;
if (w_n64_ack_embedded_flash) w_n64_i_data = w_n64_i_data_embedded_flash;
if (w_n64_ack_eeprom) w_n64_i_data = w_n64_i_data_eeprom;
end
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(r_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_reset(w_sys_reset),
.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),
.i_n64_reset(i_n64_reset),
.i_n64_pi_alel(i_n64_pi_alel),
.i_n64_pi_aleh(i_n64_pi_aleh),
.i_n64_pi_read(i_n64_pi_read),
.i_n64_pi_write(i_n64_pi_write),
.io_n64_pi_ad(io_n64_pi_ad),
.o_read_rq(w_n64_read_rq),
.o_write_rq(w_n64_write_rq),
.o_request(w_n64_request),
.o_write(w_n64_write),
.i_busy(w_n64_busy),
.i_ack(w_n64_ack),
.o_bank(w_n64_bank),
.o_address(w_n64_address),
.i_data(r_bus_i_data),
.o_data(w_n64_o_data),
.i_address_valid(w_address_valid)
.i_data(w_n64_i_data),
.o_data(w_n64_o_data)
);
n64_si n64_si_inst (
// PC USB
wire w_pc_request;
wire w_pc_write;
wire w_pc_busy;
wire w_pc_ack;
wire [3:0] w_pc_bank;
wire [25:0] w_pc_address;
wire [31:0] w_pc_i_data;
wire [31:0] w_pc_o_data;
wire w_pc_busy_cart_control;
wire w_pc_ack_cart_control;
wire [31:0] w_pc_i_data_cart_control;
wire w_pc_busy_sdram;
wire w_pc_ack_sdram;
wire [31:0] w_pc_i_data_sdram;
wire w_pc_busy_eeprom;
wire w_pc_ack_eeprom;
wire [31:0] w_pc_i_data_eeprom;
always @(*) begin
w_pc_busy = w_pc_busy_cart_control || w_pc_busy_sdram || w_pc_busy_eeprom;
w_pc_ack = w_pc_ack_cart_control || w_pc_ack_sdram || w_pc_ack_eeprom;
w_pc_i_data = 32'h0000_0000;
if (w_pc_ack_cart_control) w_pc_i_data = w_pc_i_data_cart_control;
if (w_pc_ack_sdram) w_pc_i_data = w_pc_i_data_sdram;
if (w_pc_ack_eeprom) w_pc_i_data = w_pc_i_data_eeprom;
end
usb_pc usb_pc_inst (
.i_clk(w_sys_clk),
.i_reset(w_sys_reset),
.o_ftdi_clk(o_ftdi_clk),
.o_ftdi_si(o_ftdi_si),
.i_ftdi_so(i_ftdi_so),
.i_ftdi_cts(i_ftdi_cts),
.o_request(w_pc_request),
.o_write(w_pc_write),
.i_busy(w_pc_busy),
.i_ack(w_pc_ack),
.o_bank(w_pc_bank),
.o_address(w_pc_address),
.i_data(w_pc_i_data),
.o_data(w_pc_o_data)
);
// Cart interface
wire w_cart_control_request;
wire w_cart_control_write;
wire w_cart_control_busy;
wire w_cart_control_ack;
wire [25:0] w_cart_control_address;
wire [31:0] w_cart_control_o_data;
wire [31:0] w_cart_control_i_data;
wire w_rom_switch;
wire w_eeprom_enable;
wire w_eeprom_16k_mode;
device_arbiter device_arbiter_cart_control_inst (
.i_clk(w_sys_clk),
.i_reset(w_sys_reset),
.i_si_clk(r_n64_si_clk_ff2),
.i_si_reset(~r_n64_reset_ff2),
.i_si_dq(r_n64_si_dq_ff2),
.o_si_dq(w_n64_si_dq_o),
.i_eeprom_select(w_eeprom_select),
.i_read_rq(w_bus_read_rq),
.i_write_rq(w_bus_write_rq),
.o_ack(w_eeprom_ack),
.i_address(w_bus_address),
.i_data(w_bus_o_data),
.o_data(w_eeprom_o_data),
.i_eeprom_enable(w_eeprom_enable),
.i_eeprom_16k_enable(w_eeprom_16k_enable)
.i_request_pri(w_n64_request),
.i_write_pri(w_n64_write),
.o_busy_pri(w_n64_busy_cart_control),
.o_ack_pri(w_n64_ack_cart_control),
.i_bank_pri(w_n64_bank),
.i_address_pri(w_n64_address[25:2]),
.o_data_pri(w_n64_i_data_cart_control),
.i_data_pri(w_n64_o_data),
.i_request_sec(w_pc_request),
.i_write_sec(w_pc_write),
.o_busy_sec(w_pc_busy_cart_control),
.o_ack_sec(w_pc_ack_cart_control),
.i_bank_sec(w_pc_bank),
.i_address_sec(w_pc_address[25:2]),
.o_data_sec(w_pc_i_data_cart_control),
.i_data_sec(w_pc_o_data),
.o_request(w_cart_control_request),
.o_write(w_cart_control_write),
.i_busy(w_cart_control_busy),
.i_ack(w_cart_control_ack),
.o_address(w_cart_control_address),
.i_data(w_cart_control_o_data),
.o_data(w_cart_control_i_data)
);
defparam device_arbiter_cart_control_inst.DEVICE_BANK = BANK_CART;
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),
.o_eeprom(w_eeprom_select),
.i_flash_enable(w_flash_enable),
.i_sdram_enable(w_sdram_enable),
.i_eeprom_pi_enable(w_eeprom_pi_enable),
.o_address_valid(w_address_valid)
);
cart_config cart_config_inst (
cart_control cart_control_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_n64_reset(i_n64_reset),
.i_n64_nmi(i_n64_nmi),
.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),
.o_eeprom_pi_enable(w_eeprom_pi_enable),
.i_request(w_cart_control_request),
.i_write(w_cart_control_write),
.o_busy(w_cart_control_busy),
.o_ack(w_cart_control_ack),
.i_address(w_cart_control_address),
.o_data(w_cart_control_o_data),
.i_data(w_cart_control_i_data),
.o_rom_switch(w_rom_switch),
.o_eeprom_enable(w_eeprom_enable),
.o_eeprom_16k_enable(w_eeprom_16k_enable)
.o_eeprom_16k_mode(w_eeprom_16k_mode)
);
flash flash_inst (
// Embedded flash
memory_embedded_flash memory_embedded_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)
.i_request(!w_rom_switch && w_n64_request && !w_n64_write && w_n64_bank == BANK_ROM),
.o_busy(w_n64_busy_embedded_flash),
.o_ack(w_n64_ack_embedded_flash),
.i_address(w_n64_address[25:2]),
.o_data(w_n64_i_data_embedded_flash)
);
sdram sdram_inst (
// SDRAM
wire w_sdram_request;
wire w_sdram_write;
wire w_sdram_busy;
wire w_sdram_ack;
wire [25:0] w_sdram_address;
wire [31:0] w_sdram_o_data;
wire [31:0] w_sdram_i_data;
device_arbiter device_arbiter_sdram_inst (
.i_clk(w_sys_clk),
.i_reset(w_sys_reset),
.i_request_pri(w_rom_switch && w_n64_request),
.i_write_pri(w_n64_write),
.o_busy_pri(w_n64_busy_sdram),
.o_ack_pri(w_n64_ack_sdram),
.i_bank_pri(w_n64_bank),
.i_address_pri(w_n64_address[25:1]),
.o_data_pri(w_n64_i_data_sdram),
.i_data_pri(w_n64_o_data),
.i_request_sec(w_pc_request),
.i_write_sec(w_pc_write),
.o_busy_sec(w_pc_busy_sdram),
.o_ack_sec(w_pc_ack_sdram),
.i_bank_sec(w_pc_bank),
.i_address_sec(w_pc_address[25:1]),
.o_data_sec(w_pc_i_data_sdram),
.i_data_sec(w_pc_o_data),
.o_request(w_sdram_request),
.o_write(w_sdram_write),
.i_busy(w_sdram_busy),
.i_ack(w_sdram_ack),
.o_address(w_sdram_address),
.i_data(w_sdram_o_data),
.o_data(w_sdram_i_data)
);
defparam device_arbiter_sdram_inst.DEVICE_BANK = BANK_ROM;
memory_sdram memory_sdram_inst (
.i_clk(w_sys_clk),
.i_reset(w_sys_reset),
@ -367,30 +330,78 @@ module top (
.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),
.io_sdram_dq(io_sdram_dq),
.i_select(w_sdram_select),
.i_read_rq(w_bus_read_rq),
.i_write_rq(w_bus_write_rq),
.i_request(w_sdram_request),
.i_write(w_sdram_write),
.o_busy(w_sdram_busy),
.o_ack(w_sdram_ack),
.i_address(w_bus_address),
.i_data(w_bus_o_data),
.o_data(w_sdram_o_data)
.i_address(w_sdram_address),
.o_data(w_sdram_o_data),
.i_data(w_sdram_i_data)
);
// LED
localparam ROLLING_LED_WIDTH = 8;
// EEPROM 4/16k
reg [(ROLLING_LED_WIDTH-1):0] r_rolling_led;
wire w_eeprom_request;
wire w_eeprom_write;
wire w_eeprom_busy;
wire w_eeprom_ack;
wire [25:0] w_eeprom_address;
wire [31:0] w_eeprom_o_data;
wire [31:0] w_eeprom_i_data;
assign o_led = |r_rolling_led;
device_arbiter device_arbiter_eeprom_inst (
.i_clk(w_sys_clk),
.i_reset(w_sys_reset),
.i_request_pri(w_n64_request),
.i_write_pri(w_n64_write),
.o_busy_pri(w_n64_busy_eeprom),
.o_ack_pri(w_n64_ack_eeprom),
.i_bank_pri(w_n64_bank),
.i_address_pri(w_n64_address[25:2]),
.o_data_pri(w_n64_i_data_eeprom),
.i_data_pri(w_n64_o_data),
.i_request_sec(w_pc_request),
.i_write_sec(w_pc_write),
.o_busy_sec(w_pc_busy_eeprom),
.o_ack_sec(w_pc_ack_eeprom),
.i_bank_sec(w_pc_bank),
.i_address_sec(w_pc_address[25:2]),
.o_data_sec(w_pc_i_data_eeprom),
.i_data_sec(w_pc_o_data),
.o_request(w_eeprom_request),
.o_write(w_eeprom_write),
.i_busy(w_eeprom_busy),
.i_ack(w_eeprom_ack),
.o_address(w_eeprom_address),
.i_data(w_eeprom_o_data),
.o_data(w_eeprom_i_data)
);
defparam device_arbiter_eeprom_inst.DEVICE_BANK = BANK_EEPROM;
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
n64_si n64_si_inst (
.i_clk(w_sys_clk),
.i_reset(w_sys_reset),
.i_n64_reset(i_n64_reset),
.i_n64_si_clk(i_n64_si_clk),
.io_n64_si_dq(io_n64_si_dq),
.i_request(w_eeprom_request),
.i_write(w_eeprom_write),
.o_busy(w_eeprom_busy),
.o_ack(w_eeprom_ack),
.i_address(w_eeprom_address),
.i_data(w_eeprom_i_data),
.o_data(w_eeprom_o_data),
.i_eeprom_enable(w_eeprom_enable),
.i_eeprom_16k_mode(w_eeprom_16k_mode)
);
endmodule

116
fw/rtl/usb/ftdi_fsi.v Normal file
View File

@ -0,0 +1,116 @@
module usb_ftdi_fsi (
input i_clk,
input i_reset,
output reg o_ftdi_clk,
output reg o_ftdi_si,
input i_ftdi_so,
input i_ftdi_cts,
input i_rx_ready,
output reg o_rx_valid,
output reg o_rx_channel,
output reg [7:0] o_rx_data,
output reg o_tx_busy,
input i_tx_valid,
input i_tx_channel,
input [7:0] i_tx_data
);
// Output clock generation and control
always @(posedge i_clk) begin
if (i_reset || !i_rx_ready) begin
o_ftdi_clk <= 1'b1;
end else begin
o_ftdi_clk <= ~o_ftdi_clk;
end
end
// RX module
reg r_rx_in_progress;
reg [3:0] r_rx_bit_counter;
reg r_tx_start_bit;
reg r_rx_tx_contention;
always @(posedge i_clk) begin
o_rx_valid <= 1'b0;
if (i_reset) begin
r_rx_in_progress <= 1'b0;
end else begin
if (!o_ftdi_clk) begin
if (!r_rx_in_progress) begin
r_rx_in_progress <= !i_ftdi_so;
r_rx_bit_counter <= 4'd0;
r_rx_tx_contention <= r_tx_start_bit;
end else begin
r_rx_bit_counter <= r_rx_bit_counter + 4'd1;
if (!r_rx_bit_counter[3]) begin
o_rx_data <= {i_ftdi_so, o_rx_data[7:1]};
end else begin
r_rx_in_progress <= 1'b0;
o_rx_valid <= !r_rx_tx_contention;
o_rx_channel <= i_ftdi_so;
end
end
end
end
end
// TX module
reg r_tx_pending;
reg [3:0] r_tx_bit_counter;
reg [7:0] r_tx_data;
reg r_tx_channel;
wire w_tx_request_op = i_tx_valid && !o_tx_busy;
wire w_tx_pending_op = !o_ftdi_clk || !i_ftdi_cts || !i_rx_ready || r_rx_in_progress;
wire w_tx_reset_output_op = o_ftdi_clk && !o_tx_busy;
wire w_tx_start_op = (w_tx_request_op || r_tx_pending) && !w_tx_pending_op;
wire w_tx_shift_op = o_ftdi_clk && o_tx_busy && !r_tx_pending;
always @(posedge i_clk) begin
r_tx_start_bit <= 1'b0;
if (i_reset) begin
o_ftdi_si <= 1'b1;
o_tx_busy <= 1'b0;
r_tx_pending <= 1'b0;
end else begin
if (w_tx_request_op) begin
o_tx_busy <= 1'b1;
r_tx_data <= i_tx_data;
r_tx_channel <= i_tx_channel;
r_tx_pending <= w_tx_pending_op;
end
if (w_tx_reset_output_op) begin
o_ftdi_si <= 1'b1;
end
if (w_tx_start_op) begin
o_ftdi_si <= 1'b0;
r_tx_start_bit <= 1'b1;
r_tx_pending <= 1'b0;
r_tx_bit_counter <= 4'd0;
end
if (w_tx_shift_op) begin
r_tx_bit_counter <= r_tx_bit_counter + 4'd1;
{r_tx_data[6:0], o_ftdi_si} <= r_tx_data;
if (r_tx_bit_counter[3]) begin
o_ftdi_si <= r_tx_channel;
o_tx_busy <= 1'b0;
end
end
end
end
endmodule

379
fw/rtl/usb/pc.v Normal file
View File

@ -0,0 +1,379 @@
module usb_pc (
input i_clk,
input i_reset,
output o_ftdi_clk,
output o_ftdi_si,
input i_ftdi_so,
input i_ftdi_cts,
output reg o_request,
output reg o_write,
input i_busy,
input i_ack,
output reg [3:0] o_bank,
output reg [25:0] o_address,
input [31:0] i_data,
output reg [31:0] o_data
);
// FTDI transport
reg r_ftdi_rx_ready;
wire w_ftdi_rx_valid;
wire [7:0] w_ftdi_rx_data;
wire w_ftdi_tx_busy;
reg r_ftdi_tx_valid;
reg [7:0] r_ftdi_tx_data;
usb_ftdi_fsi usb_ftdi_fsi_inst (
.i_clk(i_clk),
.i_reset(i_reset),
.o_ftdi_clk(o_ftdi_clk),
.o_ftdi_si(o_ftdi_si),
.i_ftdi_so(i_ftdi_so),
.i_ftdi_cts(i_ftdi_cts),
.i_rx_ready(r_ftdi_rx_ready),
.o_rx_valid(w_ftdi_rx_valid),
.o_rx_data(w_ftdi_rx_data),
.o_tx_busy(w_ftdi_tx_busy),
.i_tx_valid(r_ftdi_tx_valid),
.i_tx_channel(1'b1), // Channel B
.i_tx_data(r_ftdi_tx_data)
);
// Command ids
localparam byte CMD_TRIGGER [0:2] = '{"C", "M", "D"};
localparam byte CMD_IDENTIFY = "I";
localparam byte CMD_READ = "R";
localparam byte CMD_WRITE = "W";
localparam byte CMD_DEBUG_MODE = "D";
localparam byte CMD_DEBUG_WRITE = "F";
localparam [1:0] RX_STAGE_CMD = 2'd0;
localparam [1:0] RX_STAGE_PARAM = 2'd1;
localparam [1:0] RX_STAGE_DATA = 2'd2;
localparam [1:0] RX_STAGE_IGNORE = 2'd3;
// RX module
reg [1:0] r_rx_stage;
reg [2:0] r_rx_byte_counter;
reg [7:0] r_rx_cmd;
reg r_rx_buffer_valid;
reg r_rx_param_valid;
reg [63:0] r_rx_buffer;
reg [19:0] r_data_items_remaining;
reg r_tx_cmd_valid;
reg [7:0] r_tx_cmd;
reg r_tx_done;
always @(posedge i_clk) begin
r_rx_buffer_valid <= 1'b0;
r_rx_param_valid <= 1'b0;
r_tx_cmd_valid <= 1'b0;
if (i_reset) begin
r_rx_stage <= RX_STAGE_CMD;
r_rx_byte_counter <= 3'd0;
end else begin
if (w_ftdi_rx_valid) begin
r_rx_byte_counter <= r_rx_byte_counter + 3'd1;
case (r_rx_stage)
RX_STAGE_CMD: begin
if (w_ftdi_rx_data != CMD_TRIGGER[r_rx_byte_counter]) begin
r_rx_byte_counter <= 3'd0;
end
if (r_rx_byte_counter == 3'd3) begin
r_rx_byte_counter <= 3'd0;
r_rx_cmd <= w_ftdi_rx_data;
case (w_ftdi_rx_data)
CMD_IDENTIFY: begin
r_rx_stage <= RX_STAGE_IGNORE;
r_tx_cmd_valid <= 1'b1;
r_tx_cmd <= w_ftdi_rx_data;
end
CMD_READ: r_rx_stage <= RX_STAGE_PARAM;
CMD_WRITE: r_rx_stage <= RX_STAGE_PARAM;
CMD_DEBUG_MODE: r_rx_stage <= RX_STAGE_PARAM;
CMD_DEBUG_WRITE: r_rx_stage <= RX_STAGE_DATA;
default: r_rx_stage <= RX_STAGE_CMD;
endcase
end
end
RX_STAGE_PARAM: begin
r_rx_buffer <= {r_rx_buffer[55:0], w_ftdi_rx_data};
case (r_rx_cmd)
CMD_READ: begin
if (r_rx_byte_counter == 3'd7) begin
r_rx_stage <= RX_STAGE_IGNORE;
r_rx_byte_counter <= 3'd0;
r_rx_param_valid <= 1'b1;
r_tx_cmd_valid <= 1'b1;
r_tx_cmd <= r_rx_cmd;
end
end
CMD_WRITE: begin
if (r_rx_byte_counter == 3'd7) begin
r_rx_stage <= RX_STAGE_DATA;
r_rx_byte_counter <= 3'd0;
r_rx_param_valid <= 1'b1;
end
end
CMD_DEBUG_MODE: begin
if (r_rx_byte_counter == 3'd3) begin
r_rx_stage <= RX_STAGE_CMD;
r_rx_byte_counter <= 3'd0;
r_rx_param_valid <= 1'b1;
end
end
CMD_DEBUG_WRITE: begin
if (r_rx_byte_counter == 3'd3) begin
r_rx_stage <= RX_STAGE_DATA;
r_rx_byte_counter <= 3'd0;
r_rx_param_valid <= 1'b1;
end
end
default: begin
r_rx_stage <= RX_STAGE_CMD;
r_rx_byte_counter <= 3'd0;
end
endcase
end
RX_STAGE_DATA: begin
r_rx_buffer <= {r_rx_buffer[55:0], w_ftdi_rx_data};
case (r_rx_cmd)
CMD_WRITE: begin
if (r_rx_byte_counter == 3'd3) begin
if (r_data_items_remaining == 20'd0) begin
r_rx_stage <= RX_STAGE_IGNORE;
r_tx_cmd_valid <= 1'b1;
r_tx_cmd <= r_rx_cmd;
end
r_rx_byte_counter <= 3'd0;
r_rx_buffer_valid <= 1'b1;
end
end
CMD_DEBUG_WRITE: begin
if (r_data_items_remaining == 20'd0) begin
r_rx_stage <= RX_STAGE_CMD;
end
r_rx_buffer_valid <= 1'b1;
end
default: begin
r_rx_stage <= RX_STAGE_CMD;
r_rx_byte_counter <= 3'd0;
end
endcase
end
RX_STAGE_IGNORE: begin
end
default: begin
r_rx_stage <= RX_STAGE_CMD;
r_rx_byte_counter <= 3'd0;
end
endcase
end
if (r_tx_done) begin
r_rx_stage <= RX_STAGE_CMD;
r_rx_byte_counter <= 3'd0;
end
end
end
// Command parameter decoder
reg r_tx_debug_enabled;
always @(posedge i_clk) begin
if (i_reset) begin
r_tx_debug_enabled <= 1'b0;
end else begin
if (r_rx_param_valid) begin
case (r_rx_cmd)
CMD_READ, CMD_WRITE: begin
o_address <= {r_rx_buffer[63:34], 2'b00};
o_bank <= r_rx_buffer[27:24];
r_data_items_remaining <= r_rx_buffer[19:0];
end
CMD_DEBUG_MODE: begin
r_tx_debug_enabled <= r_rx_buffer[0];
end
CMD_DEBUG_WRITE: begin
r_data_items_remaining <= r_rx_buffer[19:0];
end
endcase
end
if (o_request && !i_busy && r_data_items_remaining > 20'd0) begin
o_address[25:2] <= o_address[25:2] + 1'd1;
r_data_items_remaining <= r_data_items_remaining - 1'd1;
end
end
end
// TX module
localparam byte IDENTIFY_STRING [0:3] = '{"S", "6", "4", "a"};
localparam byte RSP_COMPLETE [0:2] = '{"C", "M", "P"};
localparam [1:0] TX_STAGE_IDLE = 2'd0;
localparam [1:0] TX_STAGE_DATA = 2'd1;
localparam [1:0] TX_STAGE_RESPONSE = 2'd2;
reg [1:0] r_tx_stage;
reg [1:0] r_tx_byte_counter;
reg [31:0] r_i_data_buffer;
always @(*) begin
r_ftdi_tx_data = 8'h00;
case (r_tx_stage)
TX_STAGE_DATA: begin
case (r_tx_cmd)
CMD_IDENTIFY: r_ftdi_tx_data = IDENTIFY_STRING[r_tx_byte_counter];
CMD_READ: r_ftdi_tx_data = r_i_data_buffer[(r_tx_byte_counter * 8) -: 8];
endcase
end
TX_STAGE_RESPONSE: begin
if (r_tx_byte_counter != 2'd3) r_ftdi_tx_data = RSP_COMPLETE[r_tx_byte_counter];
else r_ftdi_tx_data = r_tx_cmd;
end
endcase
end
wire w_tx_successful = r_ftdi_tx_valid && !w_ftdi_tx_busy;
always @(posedge i_clk) begin
r_ftdi_tx_valid <= 1'b0;
r_tx_done <= 1'b0;
if (i_reset) begin
r_tx_stage <= TX_STAGE_IDLE;
end else begin
if (w_tx_successful) r_tx_byte_counter <= r_tx_byte_counter + 2'd1;
case (r_tx_stage)
TX_STAGE_IDLE: begin
r_tx_byte_counter <= 2'd0;
if (r_tx_cmd_valid) begin
r_ftdi_tx_valid <= 1'b1;
case (r_tx_cmd)
CMD_IDENTIFY: r_tx_stage <= TX_STAGE_DATA;
default: r_tx_stage <= TX_STAGE_RESPONSE;
endcase
end
end
TX_STAGE_DATA: begin
r_ftdi_tx_valid <= 1'b1;
if (r_tx_byte_counter == 2'd3 && w_tx_successful) begin
case (r_tx_cmd)
CMD_IDENTIFY: begin
r_tx_stage <= TX_STAGE_RESPONSE;
end
CMD_READ: begin
if (r_data_items_remaining == 20'd0) begin
r_tx_stage <= TX_STAGE_RESPONSE;
end
end
default: r_tx_stage <= TX_STAGE_RESPONSE;
endcase
end
end
TX_STAGE_RESPONSE: begin
r_ftdi_tx_valid <= 1'b1;
if (r_tx_byte_counter == 2'd3 && w_tx_successful) begin
r_tx_stage <= TX_STAGE_IDLE;
r_tx_done <= 1'b1;
end
end
default: r_tx_stage <= TX_STAGE_IDLE;
endcase
end
end
// Bus controller
always @(posedge i_clk) begin
o_request <= 1'b0;
o_write <= 1'b0;
if (i_reset) begin
r_ftdi_rx_ready <= 1'b1;
end else begin
case (r_rx_cmd)
CMD_WRITE: begin
if ((r_rx_buffer_valid || !r_ftdi_rx_ready) && !i_busy) begin
o_request <= 1'b1;
o_write <= 1'b1;
o_data <= r_rx_buffer[31:0];
r_ftdi_rx_ready <= 1'b1;
end
if (o_request && i_busy) begin
o_request <= 1'b1;
o_write <= 1'b1;
end
if (r_rx_buffer_valid && i_busy) begin
r_ftdi_rx_ready <= 1'b0;
end
end
endcase
// TODO: Read from bus
// case (r_tx_cmd)
// CMD_READ: begin
// end
// endcase
end
end
endmodule

1
hw/.gitignore vendored
View File

@ -1,3 +1,4 @@
/CAMOutputs
*.b#*
*.l#*
*.s#*

View File

@ -333,7 +333,7 @@ Designed by Polprzewodnikowy</text>
<text x="-10" y="-12" size="1.27" layer="27" align="top-left">&gt;VALUE</text>
<circle x="-9" y="9" radius="0.2" width="0.4" layer="21"/>
<circle x="-12.1" y="8.75" radius="0.1" width="0.2" layer="21"/>
<smd name="CASE_B" x="0" y="0" dx="5" dy="5" layer="16"/>
<smd name="CASE_B" x="0" y="0" dx="5" dy="5" layer="16" cream="no"/>
<pad name="P$1" x="-1.5" y="1.5" drill="0.35"/>
<pad name="P$2" x="0" y="1.5" drill="0.35"/>
<pad name="P$3" x="1.5" y="1.5" drill="0.35"/>
@ -2529,7 +2529,7 @@ design rules under a new name.</description>
<attribute name="VALUE" x="1.499996875" y="11.000003125" size="1.27" layer="27" align="top-left"/>
</element>
<element name="J1" library="SummerCart64" package="N64_EDGE" value="N64_EDGE" x="0" y="0" smashed="yes"/>
<element name="U2" library="memory-micron" library_urn="urn:adsk.eagle:library:274" package="TSOP54-400" package3d_urn="urn:adsk.eagle:package:18739/1" value="MT48LC16M16A2" x="38.5" y="16.5" smashed="yes" rot="R270">
<element name="U2" library="memory-micron" library_urn="urn:adsk.eagle:library:274" package="TSOP54-400" package3d_urn="urn:adsk.eagle:package:18739/1" value="IS42S16320F-7TL" x="38.5" y="16.5" smashed="yes" rot="R270">
<attribute name="MF" value="" x="38.5" y="16.5" size="1" layer="27" rot="R270" display="off"/>
<attribute name="MPN" value="" x="38.5" y="16.5" size="1" layer="27" rot="R270" display="off"/>
<attribute name="NAME" x="34.5" y="4.5" size="1" layer="25" align="center"/>
@ -2537,7 +2537,7 @@ design rules under a new name.</description>
<attribute name="OC_NEWARK" value="unknown" x="38.5" y="16.5" size="1" layer="27" rot="R270" display="off"/>
<attribute name="VALUE" x="38.1" y="22.5" size="1.27" layer="27" rot="R270"/>
</element>
<element name="RN1" library="resistor-dil" library_urn="urn:adsk.eagle:library:342" package="CAY16" package3d_urn="urn:adsk.eagle:package:24918/1" value="" x="-8.3" y="6" smashed="yes">
<element name="RN1" library="resistor-dil" library_urn="urn:adsk.eagle:library:342" package="CAY16" package3d_urn="urn:adsk.eagle:package:24918/1" value="47R" x="-8.3" y="6" smashed="yes">
<attribute name="MF" value="" x="-8.3" y="6" size="1" layer="27" display="off"/>
<attribute name="MPN" value="" x="-8.3" y="6" size="1" layer="27" display="off"/>
<attribute name="NAME" x="-8.3" y="4" size="1" layer="25" ratio="10" rot="R180" align="center"/>
@ -2546,7 +2546,7 @@ design rules under a new name.</description>
<attribute name="POPULARITY" value="12" x="-8.3" y="6" size="1" layer="27" display="off"/>
<attribute name="VALUE" x="-10.205" y="7.27" size="1.27" layer="27" ratio="10"/>
</element>
<element name="RN3" library="resistor-dil" library_urn="urn:adsk.eagle:library:342" package="CAY16" package3d_urn="urn:adsk.eagle:package:24918/1" value="" x="-0.3" y="6" smashed="yes">
<element name="RN3" library="resistor-dil" library_urn="urn:adsk.eagle:library:342" package="CAY16" package3d_urn="urn:adsk.eagle:package:24918/1" value="47R" x="-0.3" y="6" smashed="yes">
<attribute name="MF" value="" x="-0.3" y="6" size="1" layer="27" display="off"/>
<attribute name="MPN" value="" x="-0.3" y="6" size="1" layer="27" display="off"/>
<attribute name="NAME" x="-0.3" y="4" size="1" layer="25" ratio="10" rot="R180" align="center"/>
@ -2555,7 +2555,7 @@ design rules under a new name.</description>
<attribute name="POPULARITY" value="12" x="-0.3" y="6" size="1" layer="27" display="off"/>
<attribute name="VALUE" x="-2.205" y="7.27" size="1.27" layer="27" ratio="10"/>
</element>
<element name="RN4" library="resistor-dil" library_urn="urn:adsk.eagle:library:342" package="CAY16" package3d_urn="urn:adsk.eagle:package:24918/1" value="" x="3.7" y="6" smashed="yes">
<element name="RN4" library="resistor-dil" library_urn="urn:adsk.eagle:library:342" package="CAY16" package3d_urn="urn:adsk.eagle:package:24918/1" value="47R" x="3.7" y="6" smashed="yes">
<attribute name="MF" value="" x="3.7" y="6" size="1" layer="27" display="off"/>
<attribute name="MPN" value="" x="3.7" y="6" size="1" layer="27" display="off"/>
<attribute name="NAME" x="3.7" y="4" size="1" layer="25" ratio="10" rot="R180" align="center"/>
@ -2564,7 +2564,7 @@ design rules under a new name.</description>
<attribute name="POPULARITY" value="12" x="3.7" y="6" size="1" layer="27" display="off"/>
<attribute name="VALUE" x="1.795" y="7.27" size="1.27" layer="27" ratio="10"/>
</element>
<element name="RN6" library="resistor-dil" library_urn="urn:adsk.eagle:library:342" package="CAY16" package3d_urn="urn:adsk.eagle:package:24918/1" value="" x="11.7" y="6" smashed="yes">
<element name="RN6" library="resistor-dil" library_urn="urn:adsk.eagle:library:342" package="CAY16" package3d_urn="urn:adsk.eagle:package:24918/1" value="47R" x="11.7" y="6" smashed="yes">
<attribute name="MF" value="" x="11.7" y="6" size="1" layer="27" display="off"/>
<attribute name="MPN" value="" x="11.7" y="6" size="1" layer="27" display="off"/>
<attribute name="NAME" x="11.7" y="4" size="1" layer="25" ratio="10" rot="R180" align="center"/>
@ -2573,7 +2573,7 @@ design rules under a new name.</description>
<attribute name="POPULARITY" value="12" x="11.7" y="6" size="1" layer="27" display="off"/>
<attribute name="VALUE" x="9.795" y="7.27" size="1.27" layer="27" ratio="10"/>
</element>
<element name="RN7" library="resistor-dil" library_urn="urn:adsk.eagle:library:342" package="CAY16" package3d_urn="urn:adsk.eagle:package:24918/1" value="" x="15.7" y="6" smashed="yes">
<element name="RN7" library="resistor-dil" library_urn="urn:adsk.eagle:library:342" package="CAY16" package3d_urn="urn:adsk.eagle:package:24918/1" value="47R" x="15.7" y="6" smashed="yes">
<attribute name="MF" value="" x="15.7" y="6" size="1" layer="27" display="off"/>
<attribute name="MPN" value="" x="15.7" y="6" size="1" layer="27" display="off"/>
<attribute name="NAME" x="15.7" y="4" size="1" layer="25" ratio="10" rot="R180" align="center"/>
@ -2582,7 +2582,7 @@ design rules under a new name.</description>
<attribute name="POPULARITY" value="12" x="15.7" y="6" size="1" layer="27" display="off"/>
<attribute name="VALUE" x="13.795" y="7.27" size="1.27" layer="27" ratio="10"/>
</element>
<element name="RN5" library="resistor-dil" library_urn="urn:adsk.eagle:library:342" package="CAY16" package3d_urn="urn:adsk.eagle:package:24918/1" value="" x="7.7" y="6" smashed="yes">
<element name="RN5" library="resistor-dil" library_urn="urn:adsk.eagle:library:342" package="CAY16" package3d_urn="urn:adsk.eagle:package:24918/1" value="47R" x="7.7" y="6" smashed="yes">
<attribute name="MF" value="" x="7.7" y="6" size="1" layer="27" display="off"/>
<attribute name="MPN" value="" x="7.7" y="6" size="1" layer="27" display="off"/>
<attribute name="NAME" x="7.7" y="4" size="1" layer="25" ratio="10" rot="R180" align="center"/>
@ -2591,15 +2591,15 @@ design rules under a new name.</description>
<attribute name="POPULARITY" value="12" x="7.7" y="6" size="1" layer="27" display="off"/>
<attribute name="VALUE" x="5.795" y="7.27" size="1.27" layer="27" ratio="10"/>
</element>
<element name="J2" library="SummerCart64" package="MICRO_SD" value="MICRO_SD" x="50.35" y="38.6" smashed="yes" rot="R90">
<element name="J2" library="SummerCart64" package="MICRO_SD" value="molex 104031-0811" x="50.35" y="38.6" smashed="yes" rot="R90">
<attribute name="NAME" x="37.75" y="33" size="1" layer="25" align="center"/>
<attribute name="VALUE" x="36.35" y="44.6" size="1.27" layer="27" rot="R270" align="top-left"/>
</element>
<element name="J3" library="SummerCart64" package="MICRO_USB" value="MICRO_USB" x="-49.55" y="40" smashed="yes" rot="R270">
<element name="J3" library="SummerCart64" package="MICRO_USB" value="10118192-0002LF" x="-49.55" y="40" smashed="yes" rot="R270">
<attribute name="NAME" x="-47.55" y="34.8" size="1" layer="25" rot="R270" align="center"/>
<attribute name="VALUE" x="-43.55" y="36" size="1.27" layer="27" rot="R270" align="bottom-right"/>
</element>
<element name="U6" library="SummerCart64" package="TSSOP8" value="93C66" x="-13.5" y="37.5" smashed="yes" rot="R270">
<element name="U6" library="SummerCart64" package="TSSOP8" value="AT93C66B-XHM" x="-13.5" y="37.5" smashed="yes" rot="R270">
<attribute name="NAME" x="-16.1" y="35.3" size="1" layer="25" align="center"/>
<attribute name="VALUE" x="-15.5" y="35.5" size="0.7" layer="27" align="top-left"/>
</element>
@ -2609,11 +2609,11 @@ design rules under a new name.</description>
<attribute name="SPICEPREFIX" value="R" x="-13.5" y="34.5" size="1.778" layer="27" display="off"/>
<attribute name="VALUE" x="-14.135" y="32.595" size="1.27" layer="27"/>
</element>
<element name="U3" library="SummerCart64" package="TSSOP8" value="ATTINY45" x="-14.5" y="8.7" smashed="yes">
<element name="U3" library="SummerCart64" package="TSSOP8" value="ATTINY45-20XU" x="-14.5" y="8.7" smashed="yes">
<attribute name="NAME" x="-12" y="7.4" size="1" layer="25" rot="R90" align="center"/>
<attribute name="VALUE" x="-12.5" y="6.7" size="0.7" layer="27" rot="R90" align="top-left"/>
</element>
<element name="RN2" library="resistor-dil" library_urn="urn:adsk.eagle:library:342" package="CAY16" package3d_urn="urn:adsk.eagle:package:24918/1" value="" x="-4.3" y="6" smashed="yes">
<element name="RN2" library="resistor-dil" library_urn="urn:adsk.eagle:library:342" package="CAY16" package3d_urn="urn:adsk.eagle:package:24918/1" value="47R" x="-4.3" y="6" smashed="yes">
<attribute name="MF" value="" x="-4.3" y="6" size="1.778" layer="27" display="off"/>
<attribute name="MPN" value="" x="-4.3" y="6" size="1.778" layer="27" display="off"/>
<attribute name="NAME" x="-4.3" y="4" size="1" layer="25" ratio="10" align="center"/>
@ -2622,7 +2622,7 @@ design rules under a new name.</description>
<attribute name="POPULARITY" value="12" x="-4.3" y="6" size="1.778" layer="27" display="off"/>
<attribute name="VALUE" x="-6.205" y="7.27" size="1.27" layer="27" ratio="10"/>
</element>
<element name="RN8" library="resistor-dil" library_urn="urn:adsk.eagle:library:342" package="CAY16" package3d_urn="urn:adsk.eagle:package:24918/1" value="" x="26.3" y="44" smashed="yes">
<element name="RN8" library="resistor-dil" library_urn="urn:adsk.eagle:library:342" package="CAY16" package3d_urn="urn:adsk.eagle:package:24918/1" value="20k" x="26.3" y="44" smashed="yes">
<attribute name="MF" value="" x="26.3" y="44" size="1.778" layer="27" display="off"/>
<attribute name="MPN" value="" x="26.3" y="44" size="1.778" layer="27" display="off"/>
<attribute name="NAME" x="26.3" y="42" size="1" layer="25" ratio="10" align="center"/>
@ -2631,7 +2631,7 @@ design rules under a new name.</description>
<attribute name="POPULARITY" value="12" x="26.3" y="44" size="1.778" layer="27" display="off"/>
<attribute name="VALUE" x="24.395" y="45.27" size="1.27" layer="27" ratio="10"/>
</element>
<element name="RN9" library="resistor-dil" library_urn="urn:adsk.eagle:library:342" package="CAY16" package3d_urn="urn:adsk.eagle:package:24918/1" value="" x="30.3" y="44" smashed="yes">
<element name="RN9" library="resistor-dil" library_urn="urn:adsk.eagle:library:342" package="CAY16" package3d_urn="urn:adsk.eagle:package:24918/1" value="20k" x="30.3" y="44" smashed="yes">
<attribute name="MF" value="" x="30.3" y="44" size="1.778" layer="27" display="off"/>
<attribute name="MPN" value="" x="30.3" y="44" size="1.778" layer="27" display="off"/>
<attribute name="NAME" x="30.3" y="42" size="1" layer="25" ratio="10" align="center"/>
@ -2648,107 +2648,107 @@ design rules under a new name.</description>
<attribute name="NAME" x="13" y="37.5" size="1" layer="25" align="center"/>
<attribute name="VALUE" x="12" y="38" size="1.27" layer="27" align="top-left"/>
</element>
<element name="X1" library="SummerCart64" package="3.2X2.5_OSCILLATOR" value="XLH336" x="-5.5" y="15.5" smashed="yes" rot="R90">
<element name="X1" library="SummerCart64" package="3.2X2.5_OSCILLATOR" value="XLH336050.000000I" x="-5.5" y="15.5" smashed="yes" rot="R90">
<attribute name="NAME" x="-8" y="14.75" size="1" layer="25" rot="R90" align="center"/>
<attribute name="VALUE" x="-3.5" y="13.5" size="1.27" layer="27" rot="R90" align="top-left"/>
</element>
<element name="C1" library="rcl" library_urn="urn:adsk.eagle:library:334" package="C0603" package3d_urn="urn:adsk.eagle:package:23616/2" value="" x="-5.5" y="12" smashed="yes">
<element name="C1" library="rcl" library_urn="urn:adsk.eagle:library:334" package="C0603" package3d_urn="urn:adsk.eagle:package:23616/2" value="10n" x="-5.5" y="12" smashed="yes">
<attribute name="NAME" x="-5.5" y="10.5" size="1" layer="25" align="center"/>
<attribute name="POPULARITY" value="73" x="-5.5" y="12" size="1.778" layer="27" display="off"/>
<attribute name="SPICEPREFIX" value="C" x="-5.5" y="12" size="1.778" layer="27" display="off"/>
<attribute name="VALUE" x="-6.135" y="10.095" size="1.27" layer="27"/>
</element>
<element name="C2" library="rcl" library_urn="urn:adsk.eagle:library:334" package="C0603" package3d_urn="urn:adsk.eagle:package:23616/2" value="" x="-17.05" y="8.65" smashed="yes" rot="R270">
<element name="C2" library="rcl" library_urn="urn:adsk.eagle:library:334" package="C0603" package3d_urn="urn:adsk.eagle:package:23616/2" value="100n" x="-17.05" y="8.65" smashed="yes" rot="R270">
<attribute name="NAME" x="-17.05" y="5.9" size="1" layer="25" rot="R270" align="center"/>
<attribute name="POPULARITY" value="73" x="-17.05" y="8.65" size="1.778" layer="27" rot="R270" display="off"/>
<attribute name="SPICEPREFIX" value="C" x="-17.05" y="8.65" size="1.778" layer="27" rot="R270" display="off"/>
<attribute name="VALUE" x="-18.955" y="9.285" size="1.27" layer="27" rot="R270"/>
</element>
<element name="C3" library="rcl" library_urn="urn:adsk.eagle:library:334" package="C0603" package3d_urn="urn:adsk.eagle:package:23616/2" value="" x="-25.1" y="44.6" smashed="yes" rot="R180">
<element name="C3" library="rcl" library_urn="urn:adsk.eagle:library:334" package="C0603" package3d_urn="urn:adsk.eagle:package:23616/2" value="100n" x="-25.1" y="44.6" smashed="yes" rot="R180">
<attribute name="NAME" x="-22.85" y="43.9" size="1" layer="25" rot="R90" align="center"/>
<attribute name="POPULARITY" value="73" x="-25.1" y="44.6" size="1.778" layer="27" rot="R180" display="off"/>
<attribute name="SPICEPREFIX" value="C" x="-25.1" y="44.6" size="1.778" layer="27" rot="R180" display="off"/>
<attribute name="VALUE" x="-24.465" y="46.505" size="1.27" layer="27" rot="R180"/>
</element>
<element name="C4" library="rcl" library_urn="urn:adsk.eagle:library:334" package="C0603" package3d_urn="urn:adsk.eagle:package:23616/2" value="" x="33.4" y="44" smashed="yes" rot="R270">
<element name="C4" library="rcl" library_urn="urn:adsk.eagle:library:334" package="C0603" package3d_urn="urn:adsk.eagle:package:23616/2" value="100n" x="33.4" y="44" smashed="yes" rot="R270">
<attribute name="NAME" x="33.4" y="41" size="1" layer="25" rot="R270" align="center"/>
<attribute name="POPULARITY" value="73" x="33.4" y="44" size="1.778" layer="27" rot="R270" display="off"/>
<attribute name="SPICEPREFIX" value="C" x="33.4" y="44" size="1.778" layer="27" rot="R270" display="off"/>
<attribute name="VALUE" x="31.495" y="44.635" size="1.27" layer="27" rot="R270"/>
</element>
<element name="C5" library="rcl" library_urn="urn:adsk.eagle:library:334" package="C0603" package3d_urn="urn:adsk.eagle:package:23616/2" value="" x="3" y="45" smashed="yes" rot="R180">
<element name="C5" library="rcl" library_urn="urn:adsk.eagle:library:334" package="C0603" package3d_urn="urn:adsk.eagle:package:23616/2" value="100n" x="3" y="45" smashed="yes" rot="R180">
<attribute name="NAME" x="0.5" y="45" size="1" layer="25" rot="R180" align="center"/>
<attribute name="POPULARITY" value="73" x="3" y="45" size="1.778" layer="27" rot="R180" display="off"/>
<attribute name="SPICEPREFIX" value="C" x="3" y="45" size="1.778" layer="27" rot="R180" display="off"/>
<attribute name="VALUE" x="3.635" y="46.905" size="1.27" layer="27" rot="R180"/>
</element>
<element name="C6" library="rcl" library_urn="urn:adsk.eagle:library:334" package="C0603" package3d_urn="urn:adsk.eagle:package:23616/2" value="" x="14" y="45" smashed="yes" rot="R180">
<element name="C6" library="rcl" library_urn="urn:adsk.eagle:library:334" package="C0603" package3d_urn="urn:adsk.eagle:package:23616/2" value="100n" x="14" y="45" smashed="yes" rot="R180">
<attribute name="NAME" x="11.5" y="45" size="1" layer="25" rot="R180" align="center"/>
<attribute name="POPULARITY" value="73" x="14" y="45" size="1.778" layer="27" rot="R180" display="off"/>
<attribute name="SPICEPREFIX" value="C" x="14" y="45" size="1.778" layer="27" rot="R180" display="off"/>
<attribute name="VALUE" x="14.635" y="46.905" size="1.27" layer="27" rot="R180"/>
</element>
<element name="C7" library="rcl" library_urn="urn:adsk.eagle:library:334" package="C0805" package3d_urn="urn:adsk.eagle:package:23617/2" value="" x="35.5" y="44" smashed="yes" rot="R270">
<element name="C7" library="rcl" library_urn="urn:adsk.eagle:library:334" package="C0805" package3d_urn="urn:adsk.eagle:package:23617/2" value="47u" x="35.5" y="44" smashed="yes" rot="R270">
<attribute name="NAME" x="35.5" y="41" size="1" layer="25" rot="R270" align="center"/>
<attribute name="POPULARITY" value="88" x="35.5" y="44" size="0.254" layer="27" rot="R270" display="off"/>
<attribute name="SPICEPREFIX" value="C" x="35.5" y="44" size="0.254" layer="27" rot="R270" display="off"/>
<attribute name="VALUE" x="32.96" y="45.27" size="1.27" layer="27" rot="R270"/>
</element>
<element name="C8" library="rcl" library_urn="urn:adsk.eagle:library:334" package="C0603" package3d_urn="urn:adsk.eagle:package:23616/2" value="" x="0" y="10.5" smashed="yes" rot="R270">
<element name="C8" library="rcl" library_urn="urn:adsk.eagle:library:334" package="C0603" package3d_urn="urn:adsk.eagle:package:23616/2" value="100n" x="0" y="10.5" smashed="yes" rot="R270">
<attribute name="NAME" x="-1.5" y="10.5" size="1" layer="25" rot="R90" align="center"/>
<attribute name="POPULARITY" value="73" x="0" y="10.5" size="1.778" layer="27" rot="R270" display="off"/>
<attribute name="SPICEPREFIX" value="C" x="0" y="10.5" size="1.778" layer="27" rot="R270" display="off"/>
<attribute name="VALUE" x="-1.905" y="11.135" size="1.27" layer="27" rot="R270"/>
</element>
<element name="C9" library="rcl" library_urn="urn:adsk.eagle:library:334" package="C0603" package3d_urn="urn:adsk.eagle:package:23616/2" value="" x="23" y="10.5" smashed="yes" rot="R270">
<element name="C9" library="rcl" library_urn="urn:adsk.eagle:library:334" package="C0603" package3d_urn="urn:adsk.eagle:package:23616/2" value="100n" x="23" y="10.5" smashed="yes" rot="R270">
<attribute name="NAME" x="21.5" y="10.5" size="1" layer="25" rot="R270" align="center"/>
<attribute name="POPULARITY" value="73" x="23" y="10.5" size="1.778" layer="27" rot="R270" display="off"/>
<attribute name="SPICEPREFIX" value="C" x="23" y="10.5" size="1.778" layer="27" rot="R270" display="off"/>
<attribute name="VALUE" x="21.095" y="11.135" size="1.27" layer="27" rot="R270"/>
</element>
<element name="C10" library="rcl" library_urn="urn:adsk.eagle:library:334" package="C0603" package3d_urn="urn:adsk.eagle:package:23616/2" value="" x="25.5" y="33" smashed="yes">
<element name="C10" library="rcl" library_urn="urn:adsk.eagle:library:334" package="C0603" package3d_urn="urn:adsk.eagle:package:23616/2" value="100n" x="25.5" y="33" smashed="yes">
<attribute name="NAME" x="25.5" y="34.5" size="1" layer="25" align="center"/>
<attribute name="POPULARITY" value="73" x="25.5" y="33" size="1.778" layer="27" display="off"/>
<attribute name="SPICEPREFIX" value="C" x="25.5" y="33" size="1.778" layer="27" display="off"/>
<attribute name="VALUE" x="24.865" y="31.095" size="1.27" layer="27"/>
</element>
<element name="C11" library="rcl" library_urn="urn:adsk.eagle:library:334" package="C0603" package3d_urn="urn:adsk.eagle:package:23616/2" value="" x="-2.5" y="33" smashed="yes" rot="R180">
<element name="C11" library="rcl" library_urn="urn:adsk.eagle:library:334" package="C0603" package3d_urn="urn:adsk.eagle:package:23616/2" value="100n" x="-2.5" y="33" smashed="yes" rot="R180">
<attribute name="NAME" x="-2.5" y="34.5" size="1" layer="25" rot="R180" align="center"/>
<attribute name="POPULARITY" value="73" x="-2.5" y="33" size="1.778" layer="27" rot="R180" display="off"/>
<attribute name="SPICEPREFIX" value="C" x="-2.5" y="33" size="1.778" layer="27" rot="R180" display="off"/>
<attribute name="VALUE" x="-1.865" y="34.905" size="1.27" layer="27" rot="R180"/>
</element>
<element name="C12" library="rcl" library_urn="urn:adsk.eagle:library:334" package="C0603" package3d_urn="urn:adsk.eagle:package:23616/2" value="" x="29" y="7" smashed="yes" rot="R180">
<element name="C12" library="rcl" library_urn="urn:adsk.eagle:library:334" package="C0603" package3d_urn="urn:adsk.eagle:package:23616/2" value="100n" x="29" y="7" smashed="yes" rot="R180">
<attribute name="NAME" x="29" y="5.5" size="1" layer="25" rot="R180" align="center"/>
<attribute name="POPULARITY" value="73" x="29" y="7" size="1.778" layer="27" rot="R180" display="off"/>
<attribute name="SPICEPREFIX" value="C" x="29" y="7" size="1.778" layer="27" rot="R180" display="off"/>
<attribute name="VALUE" x="29.635" y="8.905" size="1.27" layer="27" rot="R180"/>
</element>
<element name="C13" library="rcl" library_urn="urn:adsk.eagle:library:334" package="C0603" package3d_urn="urn:adsk.eagle:package:23616/2" value="" x="43" y="4" smashed="yes" rot="R180">
<element name="C13" library="rcl" library_urn="urn:adsk.eagle:library:334" package="C0603" package3d_urn="urn:adsk.eagle:package:23616/2" value="100n" x="43" y="4" smashed="yes" rot="R180">
<attribute name="NAME" x="43" y="2.5" size="1" layer="25" rot="R180" align="center"/>
<attribute name="POPULARITY" value="73" x="43" y="4" size="1.778" layer="27" rot="R180" display="off"/>
<attribute name="SPICEPREFIX" value="C" x="43" y="4" size="1.778" layer="27" rot="R180" display="off"/>
<attribute name="VALUE" x="43.635" y="5.905" size="1.27" layer="27" rot="R180"/>
</element>
<element name="C14" library="rcl" library_urn="urn:adsk.eagle:library:334" package="C0603" package3d_urn="urn:adsk.eagle:package:23616/2" value="" x="43" y="29" smashed="yes" rot="R180">
<element name="C14" library="rcl" library_urn="urn:adsk.eagle:library:334" package="C0603" package3d_urn="urn:adsk.eagle:package:23616/2" value="100n" x="43" y="29" smashed="yes" rot="R180">
<attribute name="NAME" x="46" y="29" size="1" layer="25" rot="R180" align="center"/>
<attribute name="POPULARITY" value="73" x="43" y="29" size="1.778" layer="27" rot="R180" display="off"/>
<attribute name="SPICEPREFIX" value="C" x="43" y="29" size="1.778" layer="27" rot="R180" display="off"/>
<attribute name="VALUE" x="43.635" y="30.905" size="1.27" layer="27" rot="R180"/>
</element>
<element name="C15" library="rcl" library_urn="urn:adsk.eagle:library:334" package="C0603" package3d_urn="urn:adsk.eagle:package:23616/2" value="" x="39.5" y="29" smashed="yes">
<element name="C15" library="rcl" library_urn="urn:adsk.eagle:library:334" package="C0603" package3d_urn="urn:adsk.eagle:package:23616/2" value="100n" x="39.5" y="29" smashed="yes">
<attribute name="NAME" x="36.5" y="29" size="1" layer="25" align="center"/>
<attribute name="POPULARITY" value="73" x="39.5" y="29" size="1.778" layer="27" display="off"/>
<attribute name="SPICEPREFIX" value="C" x="39.5" y="29" size="1.778" layer="27" display="off"/>
<attribute name="VALUE" x="38.865" y="27.095" size="1.27" layer="27"/>
</element>
<element name="C16" library="rcl" library_urn="urn:adsk.eagle:library:334" package="C0603" package3d_urn="urn:adsk.eagle:package:23616/2" value="" x="-3.7" y="21.5" smashed="yes" rot="R180">
<element name="C16" library="rcl" library_urn="urn:adsk.eagle:library:334" package="C0603" package3d_urn="urn:adsk.eagle:package:23616/2" value="4.7u" x="-3.7" y="21.5" smashed="yes" rot="R180">
<attribute name="NAME" x="-3.7" y="20" size="1" layer="25" rot="R180" align="center"/>
<attribute name="POPULARITY" value="73" x="-3.7" y="21.5" size="1.778" layer="27" rot="R180" display="off"/>
<attribute name="SPICEPREFIX" value="C" x="-3.7" y="21.5" size="1.778" layer="27" rot="R180" display="off"/>
<attribute name="VALUE" x="-3.065" y="23.405" size="1.27" layer="27" rot="R180"/>
</element>
<element name="C17" library="rcl" library_urn="urn:adsk.eagle:library:334" package="C0603" package3d_urn="urn:adsk.eagle:package:23616/2" value="" x="39.5" y="31.2" smashed="yes">
<element name="C17" library="rcl" library_urn="urn:adsk.eagle:library:334" package="C0603" package3d_urn="urn:adsk.eagle:package:23616/2" value="4.7u" x="39.5" y="31.2" smashed="yes">
<attribute name="NAME" x="36.5" y="31.2" size="1" layer="25" align="center"/>
<attribute name="POPULARITY" value="73" x="39.5" y="31.2" size="1.778" layer="27" display="off"/>
<attribute name="SPICEPREFIX" value="C" x="39.5" y="31.2" size="1.778" layer="27" display="off"/>
@ -2766,7 +2766,7 @@ design rules under a new name.</description>
<attribute name="SPICEPREFIX" value="R" x="-19.15" y="8.65" size="1.778" layer="27" rot="R90" display="off"/>
<attribute name="VALUE" x="-17.245" y="8.015" size="1.27" layer="27" rot="R90"/>
</element>
<element name="U7" library="74xx-eu" library_urn="urn:adsk.eagle:library:85" package="TSSOP14" package3d_urn="urn:adsk.eagle:package:2019/3" value="74ABT125PW" x="-16" y="20.5" smashed="yes">
<element name="U7" library="74xx-eu" library_urn="urn:adsk.eagle:library:85" package="TSSOP14" package3d_urn="urn:adsk.eagle:package:2019/3" value="SN74LVC125APWR" x="-16" y="20.5" smashed="yes">
<attribute name="NAME" x="-12.5" y="19.5" size="1" layer="25" rot="R90" align="center"/>
<attribute name="POPULARITY" value="0" x="-16" y="20.5" size="1.778" layer="27" display="off"/>
<attribute name="VALUE" x="-11.775" y="17.575" size="1.27" layer="27" rot="R90"/>
@ -2777,7 +2777,7 @@ design rules under a new name.</description>
<attribute name="SPICEPREFIX" value="R" x="-20.5" y="19.4" size="1.778" layer="27" rot="R180" display="off"/>
<attribute name="VALUE" x="-19.865" y="21.305" size="1.27" layer="27" rot="R180"/>
</element>
<element name="C18" library="rcl" library_urn="urn:adsk.eagle:library:334" package="C0603" package3d_urn="urn:adsk.eagle:package:23616/2" value="" x="-20.5" y="21.6" smashed="yes">
<element name="C18" library="rcl" library_urn="urn:adsk.eagle:library:334" package="C0603" package3d_urn="urn:adsk.eagle:package:23616/2" value="100n" x="-20.5" y="21.6" smashed="yes">
<attribute name="NAME" x="-23.4" y="21.6" size="1" layer="25" align="center"/>
<attribute name="POPULARITY" value="73" x="-20.5" y="21.6" size="1.778" layer="27" display="off"/>
<attribute name="SPICEPREFIX" value="C" x="-20.5" y="21.6" size="1.778" layer="27" display="off"/>
@ -2789,47 +2789,47 @@ design rules under a new name.</description>
<attribute name="SPICEPREFIX" value="R" x="9" y="45" size="1.778" layer="27" rot="R180" display="off"/>
<attribute name="VALUE" x="9.635" y="46.905" size="1.27" layer="27" rot="R180"/>
</element>
<element name="R9" library="rcl" library_urn="urn:adsk.eagle:library:334" package="R0603" package3d_urn="urn:adsk.eagle:package:23555/3" value="10K" x="-2.9" y="45" smashed="yes">
<element name="R9" library="rcl" library_urn="urn:adsk.eagle:library:334" package="R0603" package3d_urn="urn:adsk.eagle:package:23555/3" value="10k" x="-2.9" y="45" smashed="yes">
<attribute name="NAME" x="-3.6" y="43.5" size="1" layer="25" align="center"/>
<attribute name="POPULARITY" value="70" x="-2.9" y="45" size="1" layer="27" display="off"/>
<attribute name="SPICEPREFIX" value="R" x="-2.9" y="45" size="1" layer="27" display="off"/>
<attribute name="VALUE" x="-3.535" y="43.095" size="1.27" layer="27"/>
</element>
<element name="U8" library="SummerCart64" package="TSSOP8" value="MCP7940N" x="-16" y="27" smashed="yes" rot="R270">
<element name="U8" library="SummerCart64" package="TSSOP8" value="MCP7940NT-I/ST" x="-16" y="27" smashed="yes" rot="R270">
<attribute name="NAME" x="-14.7" y="29.25" size="1" layer="25" align="center"/>
<attribute name="VALUE" x="-18" y="25" size="0.7" layer="27" align="top-left"/>
</element>
<element name="C19" library="rcl" library_urn="urn:adsk.eagle:library:334" package="C0603" package3d_urn="urn:adsk.eagle:package:23616/2" value="" x="-10.5" y="30.4" smashed="yes">
<element name="C19" library="rcl" library_urn="urn:adsk.eagle:library:334" package="C0603" package3d_urn="urn:adsk.eagle:package:23616/2" value="100n" x="-10.5" y="30.4" smashed="yes">
<attribute name="NAME" x="-10.5" y="32" size="1" layer="25" align="center"/>
<attribute name="POPULARITY" value="73" x="-10.5" y="30.4" size="1" layer="27" display="off"/>
<attribute name="SPICEPREFIX" value="C" x="-10.5" y="30.4" size="1" layer="27" display="off"/>
<attribute name="VALUE" x="-11.135" y="28.495" size="1.27" layer="27"/>
</element>
<element name="R10" library="rcl" library_urn="urn:adsk.eagle:library:334" package="R0603" package3d_urn="urn:adsk.eagle:package:23555/3" value="10K" x="-10.5" y="24.5" smashed="yes" rot="R180">
<element name="R10" library="rcl" library_urn="urn:adsk.eagle:library:334" package="R0603" package3d_urn="urn:adsk.eagle:package:23555/3" value="2.2k" x="-10.5" y="24.5" smashed="yes" rot="R180">
<attribute name="NAME" x="-10.5" y="23" size="1" layer="25" rot="R180" align="center"/>
<attribute name="POPULARITY" value="70" x="-10.5" y="24.5" size="1" layer="27" rot="R180" display="off"/>
<attribute name="SPICEPREFIX" value="R" x="-10.5" y="24.5" size="1" layer="27" rot="R180" display="off"/>
<attribute name="VALUE" x="-9.865" y="26.405" size="1.27" layer="27" rot="R180"/>
</element>
<element name="R11" library="rcl" library_urn="urn:adsk.eagle:library:334" package="R0603" package3d_urn="urn:adsk.eagle:package:23555/3" value="10K" x="-10.5" y="28.2" smashed="yes" rot="R180">
<element name="R11" library="rcl" library_urn="urn:adsk.eagle:library:334" package="R0603" package3d_urn="urn:adsk.eagle:package:23555/3" value="2.2k" x="-10.5" y="28.2" smashed="yes" rot="R180">
<attribute name="NAME" x="-10.5" y="26.7" size="1" layer="25" rot="R180" align="center"/>
<attribute name="POPULARITY" value="70" x="-10.5" y="28.2" size="1" layer="27" rot="R180" display="off"/>
<attribute name="SPICEPREFIX" value="R" x="-10.5" y="28.2" size="1" layer="27" rot="R180" display="off"/>
<attribute name="VALUE" x="-9.865" y="30.105" size="1.27" layer="27" rot="R180"/>
</element>
<element name="C20" library="rcl" library_urn="urn:adsk.eagle:library:334" package="C0603" package3d_urn="urn:adsk.eagle:package:23616/2" value="" x="-20.5" y="30.1" smashed="yes">
<element name="C20" library="rcl" library_urn="urn:adsk.eagle:library:334" package="C0603" package3d_urn="urn:adsk.eagle:package:23616/2" value="9p" x="-20.5" y="30.1" smashed="yes">
<attribute name="NAME" x="-18.4" y="30.1" size="1" layer="25" rot="R90" align="center"/>
<attribute name="POPULARITY" value="73" x="-20.5" y="30.1" size="1" layer="27" display="off"/>
<attribute name="SPICEPREFIX" value="C" x="-20.5" y="30.1" size="1" layer="27" display="off"/>
<attribute name="VALUE" x="-21.135" y="28.195" size="1.27" layer="27"/>
</element>
<element name="C21" library="rcl" library_urn="urn:adsk.eagle:library:334" package="C0603" package3d_urn="urn:adsk.eagle:package:23616/2" value="" x="-20.5" y="24.6" smashed="yes">
<element name="C21" library="rcl" library_urn="urn:adsk.eagle:library:334" package="C0603" package3d_urn="urn:adsk.eagle:package:23616/2" value="9p" x="-20.5" y="24.6" smashed="yes">
<attribute name="NAME" x="-22.6" y="24.6" size="1" layer="25" rot="R90" align="center"/>
<attribute name="POPULARITY" value="73" x="-20.5" y="24.6" size="1" layer="27" display="off"/>
<attribute name="SPICEPREFIX" value="C" x="-20.5" y="24.6" size="1" layer="27" display="off"/>
<attribute name="VALUE" x="-21.135" y="22.695" size="1.27" layer="27"/>
</element>
<element name="X2" library="crystal" library_urn="urn:adsk.eagle:library:204" package="FC-12M" package3d_urn="urn:adsk.eagle:package:12123/1" value="FC-12M" x="-21" y="27.65" smashed="yes" rot="R90">
<element name="X2" library="crystal" library_urn="urn:adsk.eagle:library:204" package="FC-12M" package3d_urn="urn:adsk.eagle:package:12123/1" value="FC-12M 32.7680KA-AC3" x="-21" y="27.65" smashed="yes" rot="R90">
<attribute name="NAME" x="-22.4" y="27.65" size="1" layer="25" rot="R90" align="center"/>
<attribute name="POPULARITY" value="2" x="-21" y="27.65" size="1" layer="27" rot="R90" display="off"/>
<attribute name="VALUE" x="-18.85" y="26.625" size="1.27" layer="27" rot="R90"/>
@ -2839,27 +2839,27 @@ design rules under a new name.</description>
<attribute name="POPULARITY" value="1" x="-29" y="10" size="1" layer="27" rot="R90" display="off"/>
<attribute name="VALUE" x="-25.5" y="11.75" size="1.27" layer="27" font="vector" rot="R90"/>
</element>
<element name="D1" library="diode" library_urn="urn:adsk.eagle:library:210" package="SOD323_ST" package3d_urn="urn:adsk.eagle:package:43461/1" value="BAT60J" x="-21.3" y="44.8" smashed="yes" rot="R90">
<element name="D1" library="diode" library_urn="urn:adsk.eagle:library:210" package="SOD323_ST" package3d_urn="urn:adsk.eagle:package:43461/1" value="BAT60AE6327HTSA1" x="-21.3" y="44.8" smashed="yes" rot="R90">
<attribute name="NAME" x="-22.8" y="46" size="1" layer="25" rot="R180" align="center"/>
<attribute name="POPULARITY" value="7" x="-21.3" y="44.8" size="1" layer="27" rot="R90" display="off"/>
<attribute name="VALUE" x="-19.3" y="43.15" size="1.27" layer="27" rot="R90"/>
</element>
<element name="D2" library="diode" library_urn="urn:adsk.eagle:library:210" package="SOD323_ST" package3d_urn="urn:adsk.eagle:package:43461/1" value="BAT60J" x="-22.5" y="8.75" smashed="yes" rot="R270">
<element name="D2" library="diode" library_urn="urn:adsk.eagle:library:210" package="SOD323_ST" package3d_urn="urn:adsk.eagle:package:43461/1" value="BAT60AE6327HTSA1" x="-22.5" y="8.75" smashed="yes" rot="R270">
<attribute name="NAME" x="-23.8" y="8.75" size="1" layer="25" rot="R270" align="center"/>
<attribute name="POPULARITY" value="7" x="-22.5" y="8.75" size="1" layer="27" rot="R270" display="off"/>
<attribute name="VALUE" x="-24.5" y="10.4" size="1.27" layer="27" rot="R270"/>
</element>
<element name="C22" library="rcl" library_urn="urn:adsk.eagle:library:334" package="C0805" package3d_urn="urn:adsk.eagle:package:23617/2" value="" x="-20.5" y="14.7" smashed="yes">
<element name="C22" library="rcl" library_urn="urn:adsk.eagle:library:334" package="C0805" package3d_urn="urn:adsk.eagle:package:23617/2" value="47u" x="-20.5" y="14.7" smashed="yes">
<attribute name="NAME" x="-20.5" y="13.2" size="1" layer="25" align="center"/>
<attribute name="POPULARITY" value="88" x="-20.5" y="14.7" size="1" layer="27" display="off"/>
<attribute name="SPICEPREFIX" value="C" x="-20.5" y="14.7" size="1" layer="27" display="off"/>
<attribute name="VALUE" x="-21.77" y="12.16" size="1.27" layer="27"/>
</element>
<element name="X3" library="SummerCart64" package="3.2X2.5_OSCILLATOR" value="XLH336" x="-23.2" y="40.4" smashed="yes" rot="R270">
<element name="X3" library="SummerCart64" package="3.2X2.5_OSCILLATOR" value="XLH336012.000000X" x="-23.2" y="40.4" smashed="yes" rot="R270">
<attribute name="NAME" x="-23.65" y="37.7" size="1" layer="25" align="center"/>
<attribute name="VALUE" x="-25.2" y="42.4" size="1.27" layer="27" rot="R270" align="top-left"/>
</element>
<element name="C23" library="rcl" library_urn="urn:adsk.eagle:library:334" package="C0603" package3d_urn="urn:adsk.eagle:package:23616/2" value="" x="-8.5" y="37.5" smashed="yes" rot="R270">
<element name="C23" library="rcl" library_urn="urn:adsk.eagle:library:334" package="C0603" package3d_urn="urn:adsk.eagle:package:23616/2" value="10n" x="-8.5" y="37.5" smashed="yes" rot="R270">
<attribute name="NAME" x="-7" y="37.5" size="1" layer="25" rot="R270" align="center"/>
<attribute name="POPULARITY" value="73" x="-8.5" y="37.5" size="1" layer="27" rot="R270" display="off"/>
<attribute name="SPICEPREFIX" value="C" x="-8.5" y="37.5" size="1" layer="27" rot="R270" display="off"/>
@ -2873,13 +2873,13 @@ design rules under a new name.</description>
<attribute name="OC_NEWARK" value="11P9414" x="-12.5" y="44.2" size="1.778" layer="27" display="off"/>
<attribute name="VALUE" x="-2.975" y="41.66" size="1.27" layer="27" rot="R90"/>
</element>
<element name="R12" library="rcl" library_urn="urn:adsk.eagle:library:334" package="R0603" package3d_urn="urn:adsk.eagle:package:23555/3" value="10K" x="-5.5" y="25.9" smashed="yes" rot="R90">
<element name="R12" library="rcl" library_urn="urn:adsk.eagle:library:334" package="R0603" package3d_urn="urn:adsk.eagle:package:23555/3" value="1k" x="-5.5" y="25.9" smashed="yes" rot="R90">
<attribute name="NAME" x="-7" y="25.9" size="1" layer="25" rot="R90" align="center"/>
<attribute name="POPULARITY" value="70" x="-5.5" y="25.9" size="1" layer="27" rot="R90" display="off"/>
<attribute name="SPICEPREFIX" value="R" x="-5.5" y="25.9" size="1" layer="27" rot="R90" display="off"/>
<attribute name="VALUE" x="-3.595" y="25.265" size="1.27" layer="27" rot="R90"/>
</element>
<element name="LD1" library="led" library_urn="urn:adsk.eagle:library:259" package="SML0603" package3d_urn="urn:adsk.eagle:package:15832/1" value="" x="-3.7" y="25.9" smashed="yes" rot="R270">
<element name="LD1" library="led" library_urn="urn:adsk.eagle:library:259" package="SML0603" package3d_urn="urn:adsk.eagle:package:15832/1" value="150060RS75000" x="-3.7" y="25.9" smashed="yes" rot="R270">
<attribute name="NAME" x="-2.4" y="25.9" size="1" layer="25" rot="R270" align="center"/>
<attribute name="POPULARITY" value="17" x="-3.7" y="25.9" size="1" layer="27" rot="R270" display="off"/>
<attribute name="VALUE" x="-5.7" y="26.9" size="1.27" layer="27" rot="R270"/>
@ -2888,126 +2888,126 @@ design rules under a new name.</description>
<attribute name="NAME" x="-30.5" y="23.3" size="1" layer="25" rot="R180" align="center"/>
<attribute name="VALUE" x="-40.6" y="34.5" size="1.27" layer="27" rot="R270" align="top-left"/>
</element>
<element name="C24" library="rcl" library_urn="urn:adsk.eagle:library:334" package="C0603" package3d_urn="urn:adsk.eagle:package:23616/2" value="" x="-37.5" y="22.3" smashed="yes" rot="R180">
<element name="C24" library="rcl" library_urn="urn:adsk.eagle:library:334" package="C0603" package3d_urn="urn:adsk.eagle:package:23616/2" value="3.3u" x="-37.5" y="22.3" smashed="yes" rot="R180">
<attribute name="NAME" x="-37.5" y="20.8" size="1" layer="25" rot="R180" align="center"/>
<attribute name="POPULARITY" value="73" x="-37.5" y="22.3" size="1.778" layer="27" rot="R180" display="off"/>
<attribute name="SPICEPREFIX" value="C" x="-37.5" y="22.3" size="1.778" layer="27" rot="R180" display="off"/>
<attribute name="VALUE" x="-36.865" y="24.205" size="1.27" layer="27" rot="R180"/>
</element>
<element name="R13" library="rcl" library_urn="urn:adsk.eagle:library:334" package="R0603" package3d_urn="urn:adsk.eagle:package:23555/3" value="10K" x="-40.1" y="38.7" smashed="yes" rot="R180">
<element name="R13" library="rcl" library_urn="urn:adsk.eagle:library:334" package="R0603" package3d_urn="urn:adsk.eagle:package:23555/3" value="12k" x="-40.1" y="38.7" smashed="yes" rot="R180">
<attribute name="NAME" x="-43" y="38.7" size="1" layer="25" rot="R180" align="center"/>
<attribute name="POPULARITY" value="70" x="-40.1" y="38.7" size="1.778" layer="27" rot="R180" display="off"/>
<attribute name="SPICEPREFIX" value="R" x="-40.1" y="38.7" size="1.778" layer="27" rot="R180" display="off"/>
<attribute name="VALUE" x="-39.465" y="40.605" size="1.27" layer="27" rot="R180"/>
</element>
<element name="R14" library="rcl" library_urn="urn:adsk.eagle:library:334" package="R0603" package3d_urn="urn:adsk.eagle:package:23555/3" value="10K" x="-41.8" y="35.7" smashed="yes" rot="R270">
<element name="R14" library="rcl" library_urn="urn:adsk.eagle:library:334" package="R0603" package3d_urn="urn:adsk.eagle:package:23555/3" value="1k" x="-41.8" y="35.7" smashed="yes" rot="R270">
<attribute name="NAME" x="-43.35" y="35.7" size="1" layer="25" rot="R90" align="center"/>
<attribute name="POPULARITY" value="70" x="-41.8" y="35.7" size="1.778" layer="27" rot="R270" display="off"/>
<attribute name="SPICEPREFIX" value="R" x="-41.8" y="35.7" size="1.778" layer="27" rot="R270" display="off"/>
<attribute name="VALUE" x="-43.705" y="36.335" size="1.27" layer="27" rot="R270"/>
</element>
<element name="C25" library="rcl" library_urn="urn:adsk.eagle:library:334" package="C0603" package3d_urn="urn:adsk.eagle:package:23616/2" value="" x="-16.5" y="40.5" smashed="yes">
<element name="C25" library="rcl" library_urn="urn:adsk.eagle:library:334" package="C0603" package3d_urn="urn:adsk.eagle:package:23616/2" value="100n" x="-16.5" y="40.5" smashed="yes">
<attribute name="NAME" x="-13.6" y="40.5" size="1" layer="25" align="center"/>
<attribute name="POPULARITY" value="73" x="-16.5" y="40.5" size="1.778" layer="27" display="off"/>
<attribute name="SPICEPREFIX" value="C" x="-16.5" y="40.5" size="1.778" layer="27" display="off"/>
<attribute name="VALUE" x="-17.135" y="38.595" size="1.27" layer="27"/>
</element>
<element name="L2" library="rcl" library_urn="urn:adsk.eagle:library:334" package="R0603" package3d_urn="urn:adsk.eagle:package:23555/3" value="" x="-27.9" y="45.1" smashed="yes" rot="R90">
<element name="L2" library="rcl" library_urn="urn:adsk.eagle:library:334" package="R0603" package3d_urn="urn:adsk.eagle:package:23555/3" value="MI0603K300R-10" x="-27.9" y="45.1" smashed="yes" rot="R90">
<attribute name="NAME" x="-25.1" y="46" size="1" layer="25" rot="R90" align="center"/>
<attribute name="POPULARITY" value="70" x="-27.9" y="45.1" size="1" layer="27" rot="R90" display="off"/>
<attribute name="SPICEPREFIX" value="R" x="-27.9" y="45.1" size="1" layer="27" rot="R90" display="off"/>
<attribute name="VALUE" x="-25.995" y="44.465" size="1.27" layer="27" rot="R90"/>
</element>
<element name="L1" library="rcl" library_urn="urn:adsk.eagle:library:334" package="R0603" package3d_urn="urn:adsk.eagle:package:23555/3" value="" x="-30" y="45.1" smashed="yes" rot="R90">
<element name="L1" library="rcl" library_urn="urn:adsk.eagle:library:334" package="R0603" package3d_urn="urn:adsk.eagle:package:23555/3" value="MI0603K300R-10" x="-30" y="45.1" smashed="yes" rot="R90">
<attribute name="NAME" x="-26.4" y="46" size="1" layer="25" rot="R90" align="center"/>
<attribute name="POPULARITY" value="70" x="-30" y="45.1" size="1" layer="27" rot="R90" display="off"/>
<attribute name="SPICEPREFIX" value="R" x="-30" y="45.1" size="1" layer="27" rot="R90" display="off"/>
<attribute name="VALUE" x="-28.095" y="44.465" size="1.27" layer="27" rot="R90"/>
</element>
<element name="C26" library="rcl" library_urn="urn:adsk.eagle:library:334" package="C0603" package3d_urn="urn:adsk.eagle:package:23616/2" value="" x="-31.05" y="42.5" smashed="yes" rot="R180">
<element name="C26" library="rcl" library_urn="urn:adsk.eagle:library:334" package="C0603" package3d_urn="urn:adsk.eagle:package:23616/2" value="4.7u" x="-31.05" y="42.5" smashed="yes" rot="R180">
<attribute name="NAME" x="-33.1" y="42.2" size="1" layer="25" rot="R270" align="center"/>
<attribute name="POPULARITY" value="73" x="-31.05" y="42.5" size="1" layer="27" rot="R180" display="off"/>
<attribute name="SPICEPREFIX" value="C" x="-31.05" y="42.5" size="1" layer="27" rot="R180" display="off"/>
<attribute name="VALUE" x="-30.415" y="44.405" size="1.27" layer="27" rot="R180"/>
</element>
<element name="C27" library="rcl" library_urn="urn:adsk.eagle:library:334" package="C0603" package3d_urn="urn:adsk.eagle:package:23616/2" value="" x="-31.05" y="40.4" smashed="yes" rot="R180">
<element name="C27" library="rcl" library_urn="urn:adsk.eagle:library:334" package="C0603" package3d_urn="urn:adsk.eagle:package:23616/2" value="100n" x="-31.05" y="40.4" smashed="yes" rot="R180">
<attribute name="NAME" x="-31.05" y="38.9" size="1" layer="25" rot="R180" align="center"/>
<attribute name="POPULARITY" value="73" x="-31.05" y="40.4" size="1" layer="27" rot="R180" display="off"/>
<attribute name="SPICEPREFIX" value="C" x="-31.05" y="40.4" size="1" layer="27" rot="R180" display="off"/>
<attribute name="VALUE" x="-30.415" y="42.305" size="1.27" layer="27" rot="R180"/>
</element>
<element name="C28" library="rcl" library_urn="urn:adsk.eagle:library:334" package="C0603" package3d_urn="urn:adsk.eagle:package:23616/2" value="" x="-26.85" y="42.5" smashed="yes">
<element name="C28" library="rcl" library_urn="urn:adsk.eagle:library:334" package="C0603" package3d_urn="urn:adsk.eagle:package:23616/2" value="4.7u" x="-26.85" y="42.5" smashed="yes">
<attribute name="NAME" x="-28.9" y="42.2" size="1" layer="25" rot="R90" align="center"/>
<attribute name="POPULARITY" value="73" x="-26.85" y="42.5" size="1" layer="27" display="off"/>
<attribute name="SPICEPREFIX" value="C" x="-26.85" y="42.5" size="1" layer="27" display="off"/>
<attribute name="VALUE" x="-27.485" y="40.595" size="1.27" layer="27"/>
</element>
<element name="C29" library="rcl" library_urn="urn:adsk.eagle:library:334" package="C0603" package3d_urn="urn:adsk.eagle:package:23616/2" value="" x="-26.85" y="40.4" smashed="yes">
<element name="C29" library="rcl" library_urn="urn:adsk.eagle:library:334" package="C0603" package3d_urn="urn:adsk.eagle:package:23616/2" value="100n" x="-26.85" y="40.4" smashed="yes">
<attribute name="NAME" x="-26.85" y="38.9" size="1" layer="25" align="center"/>
<attribute name="POPULARITY" value="73" x="-26.85" y="40.4" size="1" layer="27" display="off"/>
<attribute name="SPICEPREFIX" value="C" x="-26.85" y="40.4" size="1" layer="27" display="off"/>
<attribute name="VALUE" x="-27.485" y="38.495" size="1.27" layer="27"/>
</element>
<element name="C30" library="rcl" library_urn="urn:adsk.eagle:library:334" package="C0603" package3d_urn="urn:adsk.eagle:package:23616/2" value="" x="-25.7" y="25" smashed="yes">
<element name="C30" library="rcl" library_urn="urn:adsk.eagle:library:334" package="C0603" package3d_urn="urn:adsk.eagle:package:23616/2" value="100n" x="-25.7" y="25" smashed="yes">
<attribute name="NAME" x="-25.7" y="23.5" size="1" layer="25" align="center"/>
<attribute name="POPULARITY" value="73" x="-25.7" y="25" size="1" layer="27" display="off"/>
<attribute name="SPICEPREFIX" value="C" x="-25.7" y="25" size="1" layer="27" display="off"/>
<attribute name="VALUE" x="-26.335" y="23.095" size="1.27" layer="27"/>
</element>
<element name="C31" library="rcl" library_urn="urn:adsk.eagle:library:334" package="C0603" package3d_urn="urn:adsk.eagle:package:23616/2" value="" x="-36.3" y="38.7" smashed="yes" rot="R180">
<element name="C31" library="rcl" library_urn="urn:adsk.eagle:library:334" package="C0603" package3d_urn="urn:adsk.eagle:package:23616/2" value="100n" x="-36.3" y="38.7" smashed="yes" rot="R180">
<attribute name="NAME" x="-34.1" y="38.7" size="1" layer="25" rot="R270" align="center"/>
<attribute name="POPULARITY" value="73" x="-36.3" y="38.7" size="1" layer="27" rot="R180" display="off"/>
<attribute name="SPICEPREFIX" value="C" x="-36.3" y="38.7" size="1" layer="27" rot="R180" display="off"/>
<attribute name="VALUE" x="-35.665" y="40.605" size="1.27" layer="27" rot="R180"/>
</element>
<element name="C32" library="rcl" library_urn="urn:adsk.eagle:library:334" package="C0603" package3d_urn="urn:adsk.eagle:package:23616/2" value="" x="-25.7" y="36" smashed="yes">
<element name="C32" library="rcl" library_urn="urn:adsk.eagle:library:334" package="C0603" package3d_urn="urn:adsk.eagle:package:23616/2" value="100n" x="-25.7" y="36" smashed="yes">
<attribute name="NAME" x="-25.7" y="34.5" size="1" layer="25" align="center"/>
<attribute name="POPULARITY" value="73" x="-25.7" y="36" size="1" layer="27" display="off"/>
<attribute name="SPICEPREFIX" value="C" x="-25.7" y="36" size="1" layer="27" display="off"/>
<attribute name="VALUE" x="-26.335" y="34.095" size="1.27" layer="27"/>
</element>
<element name="C33" library="rcl" library_urn="urn:adsk.eagle:library:334" package="C0603" package3d_urn="urn:adsk.eagle:package:23616/2" value="" x="-41.8" y="28.1" smashed="yes" rot="R90">
<element name="C33" library="rcl" library_urn="urn:adsk.eagle:library:334" package="C0603" package3d_urn="urn:adsk.eagle:package:23616/2" value="100n" x="-41.8" y="28.1" smashed="yes" rot="R90">
<attribute name="NAME" x="-43.35" y="28.1" size="1" layer="25" rot="R90" align="center"/>
<attribute name="POPULARITY" value="73" x="-41.8" y="28.1" size="1" layer="27" rot="R90" display="off"/>
<attribute name="SPICEPREFIX" value="C" x="-41.8" y="28.1" size="1" layer="27" rot="R90" display="off"/>
<attribute name="VALUE" x="-39.895" y="27.465" size="1.27" layer="27" rot="R90"/>
</element>
<element name="C34" library="rcl" library_urn="urn:adsk.eagle:library:334" package="C0603" package3d_urn="urn:adsk.eagle:package:23616/2" value="" x="-41.8" y="31.9" smashed="yes" rot="R270">
<element name="C34" library="rcl" library_urn="urn:adsk.eagle:library:334" package="C0603" package3d_urn="urn:adsk.eagle:package:23616/2" value="100n" x="-41.8" y="31.9" smashed="yes" rot="R270">
<attribute name="NAME" x="-43.35" y="31.9" size="1" layer="25" rot="R270" align="center"/>
<attribute name="POPULARITY" value="73" x="-41.8" y="31.9" size="1" layer="27" rot="R270" display="off"/>
<attribute name="SPICEPREFIX" value="C" x="-41.8" y="31.9" size="1" layer="27" rot="R270" display="off"/>
<attribute name="VALUE" x="-43.705" y="32.535" size="1.27" layer="27" rot="R270"/>
</element>
<element name="C35" library="rcl" library_urn="urn:adsk.eagle:library:334" package="C0603" package3d_urn="urn:adsk.eagle:package:23616/2" value="" x="-33.7" y="22.3" smashed="yes" rot="R180">
<element name="C35" library="rcl" library_urn="urn:adsk.eagle:library:334" package="C0603" package3d_urn="urn:adsk.eagle:package:23616/2" value="100n" x="-33.7" y="22.3" smashed="yes" rot="R180">
<attribute name="NAME" x="-33.7" y="20.8" size="1" layer="25" rot="R180" align="center"/>
<attribute name="POPULARITY" value="73" x="-33.7" y="22.3" size="1" layer="27" rot="R180" display="off"/>
<attribute name="SPICEPREFIX" value="C" x="-33.7" y="22.3" size="1" layer="27" rot="R180" display="off"/>
<attribute name="VALUE" x="-33.065" y="24.205" size="1.27" layer="27" rot="R180"/>
</element>
<element name="C36" library="rcl" library_urn="urn:adsk.eagle:library:334" package="C0603" package3d_urn="urn:adsk.eagle:package:23616/2" value="" x="-24.3" y="30.1" smashed="yes">
<element name="C36" library="rcl" library_urn="urn:adsk.eagle:library:334" package="C0603" package3d_urn="urn:adsk.eagle:package:23616/2" value="100n" x="-24.3" y="30.1" smashed="yes">
<attribute name="NAME" x="-24.3" y="31.6" size="1" layer="25" align="center"/>
<attribute name="POPULARITY" value="73" x="-24.3" y="30.1" size="1" layer="27" display="off"/>
<attribute name="SPICEPREFIX" value="C" x="-24.3" y="30.1" size="1" layer="27" display="off"/>
<attribute name="VALUE" x="-24.935" y="28.195" size="1.27" layer="27"/>
</element>
<element name="C37" library="rcl" library_urn="urn:adsk.eagle:library:334" package="C0603" package3d_urn="urn:adsk.eagle:package:23616/2" value="" x="-44" y="45" smashed="yes" rot="R270">
<element name="C37" library="rcl" library_urn="urn:adsk.eagle:library:334" package="C0603" package3d_urn="urn:adsk.eagle:package:23616/2" value="4.7u" x="-44" y="45" smashed="yes" rot="R270">
<attribute name="NAME" x="-46.3" y="45.9" size="1" layer="25" align="center"/>
<attribute name="POPULARITY" value="73" x="-44" y="45" size="1" layer="27" rot="R270" display="off"/>
<attribute name="SPICEPREFIX" value="C" x="-44" y="45" size="1" layer="27" rot="R270" display="off"/>
<attribute name="VALUE" x="-45.905" y="45.635" size="1.27" layer="27" rot="R270"/>
</element>
<element name="C38" library="rcl" library_urn="urn:adsk.eagle:library:334" package="C0603" package3d_urn="urn:adsk.eagle:package:23616/2" value="" x="-32.1" y="45.1" smashed="yes" rot="R90">
<element name="C38" library="rcl" library_urn="urn:adsk.eagle:library:334" package="C0603" package3d_urn="urn:adsk.eagle:package:23616/2" value="4.7u" x="-32.1" y="45.1" smashed="yes" rot="R90">
<attribute name="NAME" x="-34.5" y="46.1" size="1" layer="25" rot="R180" align="center"/>
<attribute name="POPULARITY" value="73" x="-32.1" y="45.1" size="1" layer="27" rot="R90" display="off"/>
<attribute name="SPICEPREFIX" value="C" x="-32.1" y="45.1" size="1" layer="27" rot="R90" display="off"/>
<attribute name="VALUE" x="-30.195" y="44.465" size="1.27" layer="27" rot="R90"/>
</element>
<element name="U10" library="v-reg" library_urn="urn:adsk.eagle:library:409" package="SOT223" package3d_urn="urn:adsk.eagle:package:30370/1" value="LD117AS33TR" x="-38" y="43.4" smashed="yes" rot="R270">
<element name="U10" library="v-reg" library_urn="urn:adsk.eagle:library:409" package="SOT223" package3d_urn="urn:adsk.eagle:package:30370/1" value="AZ1117IH-3.3TRG1" x="-38" y="43.4" smashed="yes" rot="R270">
<attribute name="NAME" x="-43.6" y="41.2" size="1" layer="25" rot="R180" align="center"/>
<attribute name="POPULARITY" value="9" x="-38" y="43.4" size="1" layer="27" rot="R270" display="off"/>
<attribute name="VALUE" x="-39.3208" y="45.94" size="1.27" layer="27" rot="R270"/>
</element>
<element name="RN10" library="resistor-dil" library_urn="urn:adsk.eagle:library:342" package="CAY16" package3d_urn="urn:adsk.eagle:package:24918/1" value="" x="-19.5" y="37.5" smashed="yes" rot="R90">
<element name="RN10" library="resistor-dil" library_urn="urn:adsk.eagle:library:342" package="CAY16" package3d_urn="urn:adsk.eagle:package:24918/1" value="20k" x="-19.5" y="37.5" smashed="yes" rot="R90">
<attribute name="MF" value="" x="-19.5" y="37.5" size="1" layer="27" rot="R90" display="off"/>
<attribute name="MPN" value="" x="-19.5" y="37.5" size="1" layer="27" rot="R90" display="off"/>
<attribute name="NAME" x="-19.5" y="35.1" size="1" layer="25" ratio="10" rot="R180" align="center"/>
@ -3016,7 +3016,7 @@ design rules under a new name.</description>
<attribute name="POPULARITY" value="12" x="-19.5" y="37.5" size="1" layer="27" rot="R90" display="off"/>
<attribute name="VALUE" x="-20.77" y="35.595" size="1.27" layer="27" ratio="10" rot="R90"/>
</element>
<element name="S1" library="SummerCart64" package="218-2" value="218-2" x="-43" y="21" smashed="yes">
<element name="S1" library="SummerCart64" package="218-2" value="218-2LPSTRF" x="-43" y="21" smashed="yes">
<attribute name="NAME" x="-45.7" y="19" size="1" layer="25" rot="R90" align="center"/>
<attribute name="VALUE" x="-40.7" y="18" size="1.27" layer="27" rot="R90" align="top-left"/>
</element>

276
hw/SummerCart64.cam Normal file
View File

@ -0,0 +1,276 @@
{
"author": {
"email": "sc@mateuszfaderewski.pl",
"name": "Polprzewodnikowy"
},
"description": {
"EN": "SummerCart64 CAM job."
},
"output_type": "zip",
"outputs": [
{
"filename_prefix": "CAMOutputs/GerberFiles",
"format_specifier": {
"decimal": 4,
"integer": 3
},
"generate_job_file": true,
"output_type": "gerber",
"outputs": [
{
"advanced_options": {
"mirror": false,
"offset_x": 0,
"offset_y": 0,
"rotate": false,
"upside_down": false
},
"board_outline": false,
"config": {
"file_function": "Copper",
"layer": 1,
"layer_details": "mixed",
"layer_type": "top"
},
"filename_format": "%PREFIX/copper_top.gbr",
"layers": [
1,
17,
18
],
"name": "Top Copper",
"polarity": "positive",
"type": "gerber_layer"
},
{
"advanced_options": {
"mirror": false,
"offset_x": 0,
"offset_y": 0,
"rotate": false,
"upside_down": false
},
"board_outline": false,
"config": {
"file_function": "Copper",
"layer": 2,
"layer_details": "mixed",
"layer_type": "bottom"
},
"filename_format": "%PREFIX/copper_bottom.gbr",
"layers": [
16,
17,
18
],
"name": "Bottom Copper",
"polarity": "positive",
"type": "gerber_layer"
},
{
"advanced_options": {
"mirror": false,
"offset_x": 0,
"offset_y": 0,
"rotate": false,
"upside_down": false
},
"board_outline": true,
"config": {
"file_function": "Profile",
"plating": "non-plated"
},
"filename_format": "%PREFIX/profile.gbr",
"layers": [
],
"milling": true,
"polarity": "positive",
"type": "gerber_layer"
},
{
"advanced_options": {
"mirror": false,
"offset_x": 0,
"offset_y": 0,
"rotate": false,
"upside_down": false
},
"board_outline": false,
"config": {
"file_function": "Soldermask",
"index": 1,
"layer_type": "top"
},
"filename_format": "%PREFIX/soldermask_top.gbr",
"layers": [
29
],
"name": "Soldermask Top",
"polarity": "positive",
"type": "gerber_layer"
},
{
"advanced_options": {
"mirror": false,
"offset_x": 0,
"offset_y": 0,
"rotate": false,
"upside_down": false
},
"board_outline": false,
"config": {
"file_function": "Soldermask",
"index": 1,
"layer_type": "bottom"
},
"filename_format": "%PREFIX/soldermask_bottom.gbr",
"layers": [
30
],
"name": "Soldermask Bottom",
"polarity": "positive",
"type": "gerber_layer"
},
{
"advanced_options": {
"mirror": false,
"offset_x": 0,
"offset_y": 0,
"rotate": false,
"upside_down": false
},
"board_outline": false,
"config": {
"file_function": "Paste",
"layer_type": "top"
},
"filename_format": "%PREFIX/solderpaste_top.gbr",
"layers": [
31
],
"milling": false,
"name": "Solderpaste Top",
"polarity": "positive",
"type": "gerber_layer"
},
{
"advanced_options": {
"mirror": false,
"offset_x": 0,
"offset_y": 0,
"rotate": false,
"upside_down": false
},
"board_outline": false,
"config": {
"file_function": "Paste",
"layer_type": "bottom"
},
"filename_format": "%PREFIX/solderpaste_bottom.gbr",
"layers": [
32
],
"milling": false,
"name": "Solderpaste Bottom",
"polarity": "positive",
"type": "gerber_layer"
},
{
"advanced_options": {
"mirror": false,
"offset_x": 0,
"offset_y": 0,
"rotate": false,
"upside_down": false
},
"board_outline": false,
"config": {
"file_function": "Legend",
"index": 1,
"layer_type": "top"
},
"filename_format": "%PREFIX/silkscreen_top.gbr",
"layers": [
21,
25
],
"milling": false,
"name": "Silkscreen Top",
"polarity": "positive",
"type": "gerber_layer"
},
{
"advanced_options": {
"mirror": false,
"offset_x": 0,
"offset_y": 0,
"rotate": false,
"upside_down": false
},
"board_outline": false,
"config": {
"file_function": "Legend",
"index": 1,
"layer_type": "bottom"
},
"filename_format": "%PREFIX/silkscreen_bottom.gbr",
"layers": [
22,
26
],
"milling": false,
"name": "Silkscreen Bottom",
"polarity": "positive",
"type": "gerber_layer"
}
],
"version": "RS274X"
},
{
"filename_prefix": "CAMOutputs/DrillFiles",
"format_specifier": {
"decimal": 3,
"integer": 3
},
"output_type": "drill",
"outputs": [
{
"advanced_options": {
"mirror": false,
"offset_x": 0,
"offset_y": 0,
"rotate": false,
"upside_down": false
},
"filename_format": "%DRILLPREFIX/drill_%FROM_%TO.xln",
"name": "Auto Drill",
"type": "autodrills"
}
]
},
{
"filename_prefix": "CAMOutputs/Assembly",
"output_type": "assembly",
"outputs": [
{
"filename_format": "%ASSEMBLYPREFIX/%N",
"list_attribute": true,
"list_type": "values",
"name": "Bill of Material",
"output_format": "txt",
"type": "bom"
}
]
},
{
"filename_prefix": "CAMOutputs/DrawingFiles",
"output_type": "drawing",
"outputs": [
]
}
],
"timestamp": "2020-10-25T01:41:35",
"type": "EAGLE CAM job",
"units": "metric",
"version": "9.2.0"
}

View File

@ -229,7 +229,7 @@
<text x="-10" y="-12" size="1.27" layer="27" align="top-left">&gt;VALUE</text>
<circle x="-9" y="9" radius="0.2" width="0.4" layer="21"/>
<circle x="-12.1" y="8.75" radius="0.1" width="0.2" layer="21"/>
<smd name="CASE_B" x="0" y="0" dx="5" dy="5" layer="16"/>
<smd name="CASE_B" x="0" y="0" dx="5" dy="5" layer="16" cream="no"/>
<pad name="P$1" x="-1.5" y="1.5" drill="0.35"/>
<pad name="P$2" x="0" y="1.5" drill="0.35"/>
<pad name="P$3" x="1.5" y="1.5" drill="0.35"/>

File diff suppressed because it is too large Load Diff

BIN
hw/ftdi-template.xml Normal file

Binary file not shown.

View File

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

View File

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

View File

@ -1,393 +0,0 @@
#!/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 = {
5101: 0x11,
6101: 0x12,
6102: 0x13,
6103: 0x14,
6105: 0x15,
6106: 0x16,
7101: 0x03,
7102: 0x02,
7103: 0x04,
7105: 0x05,
7106: 0x06,
8303: 0x07,
}
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

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

View File

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

View File

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

View File

@ -19,7 +19,7 @@ SRC_FILES = $(wildcard $(patsubst %, %/*.c, . $(SRC_DIRS)))
OBJ_FILES = $(addprefix build/, $(notdir $(SRC_FILES:.c=.o)))
VPATH = $(SRC_DIRS)
ROM_SIZE = 1028k
ROM_SIZE = 90k
ifeq ($(N64_BYTE_SWAP),true)
ROM_EXTENSION = .v64
@ -41,6 +41,7 @@ build/$(PROG_NAME)$(ROM_EXTENSION): build/$(PROG_NAME).elf
rm -f build/$(PROG_NAME)$(ROM_EXTENSION)
$(N64TOOL) $(N64_FLAGS) -t $(PROG_NAME) build/$(PROG_NAME).bin
$(CHKSUM64PATH) build/$(PROG_NAME)$(ROM_EXTENSION)
$(OBJCOPY) build/$(PROG_NAME)$(ROM_EXTENSION) build/$(PROG_NAME).hex -I binary -O ihex
build/$(PROG_NAME).elf: $(OBJ_FILES)
$(LD) -o build/$(PROG_NAME).elf $(OBJ_FILES) $(LINK_FLAGS)

View File

@ -66,7 +66,7 @@ tv_type_t boot_get_tv_type(cart_header_t *cart_header) {
}
}
void boot(cic_type_t cic_type, tv_type_t tv_type) {
void boot(cart_header_t *cart_header, 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];
@ -95,36 +95,29 @@ void boot(cic_type_t cic_type, tv_type_t tv_type) {
AI->dram_addr = 0;
AI->len = 0;
while (SP->status & SP_STATUS_DMA_BUSY);
PI->dom1_lat = cart_header->pi_conf & 0xFF;
PI->dom1_pwd = cart_header->pi_conf >> 8;
PI->dom1_pgs = cart_header->pi_conf >> 16;
PI->dom1_rls = cart_header->pi_conf >> 20;
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];
for (size_t i = 0; i < ARRAY_ITEMS(cart_header->boot_code); i++) {
SP_MEM->dmem[16 + i] = cart_header->boot_code[i];
}
while (PI->status & (PI_STATUS_IO_BUSY | PI_STATUS_DMA_BUSY));
// CIC X105 based games checks if start of IPL2 code exists in SP IMEM
PI->status = PI_STATUS_CLEAR_INTERRUPT | PI_STATUS_RESET_CONTROLLER;
for (size_t i = 0; i < ARRAY_ITEMS(SP_MEM->imem); i++) {
SP_MEM->imem[i] = 0;
}
if (cic_type == E_CIC_TYPE_X105) {
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;
}
SP_MEM->imem[0] = 0x3C0DBFC0; // lui t5, 0xBFC0
SP_MEM->imem[1] = 0x8DA807FC; // lw t0, 0x07FC(t5)
SP_MEM->imem[2] = 0x25AD07C0; // addiu t5, t5, 0x07C0
SP_MEM->imem[3] = 0x31080080; // andi t0, t0, 0x0080
SP_MEM->imem[4] = 0x5500FFFC; // bnel t0, zero, &SP_MEM->imem[0]
SP_MEM->imem[5] = 0x3C0DBFC0; // lui t5, 0xBFC0
SP_MEM->imem[6] = 0x8DA80024; // lw t0, 0x0024(t5)
SP_MEM->imem[7] = 0x3C0BB000; // lui t3, 0xB000
if (cic_type == E_CIC_TYPE_X105) {
OS_BOOT_CONFIG->mem_size_6105 = OS_BOOT_CONFIG->mem_size;
@ -139,7 +132,7 @@ void boot(cic_type_t cic_type, tv_type_t tv_type) {
gpr_regs[CPU_REG_S4] = os_tv_type;
gpr_regs[CPU_REG_S5] = OS_BOOT_CONFIG->reset_type;
gpr_regs[CPU_REG_S6] = BOOT_SEED_IPL3(cic_seeds[cic_type]);
gpr_regs[CPU_REG_S7] = (os_tv_type == E_TV_TYPE_PAL) ? OS_BOOT_VERSION_PAL : OS_BOOT_VERSION_NTSC;
gpr_regs[CPU_REG_S7] = BOOT_SEED_OS_VERSION(cic_seeds[cic_type]);
gpr_regs[CPU_REG_SP] = CPU_ADDRESS_IN_REG(SP_MEM->imem[ARRAY_ITEMS(SP_MEM->imem) - 4]);
gpr_regs[CPU_REG_RA] = CPU_ADDRESS_IN_REG(SP_MEM->imem[(os_tv_type == E_TV_TYPE_PAL) ? 341 : 340]);

View File

@ -1,24 +1,27 @@
#ifndef BOOT_H__
#define BOOT_H__
#define BOOT_CRC32_5101 (0x587BD543)
#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_CRC32_8303 (0x0E018159)
#include <inttypes.h>
#define BOOT_SEED_5101 (0x0000AC00)
#define BOOT_SEED_X101 (0x00043F3F)
#define BOOT_SEED_X102 (0x00003F3F)
#define BOOT_SEED_X103 (0x0000783F)
#define BOOT_SEED_X105 (0x0000913F)
#define BOOT_SEED_X106 (0x0000853F)
#define BOOT_SEED_8303 (0x0000DD00)
#define BOOT_CRC32_5101 (0x587BD543)
#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_CRC32_8303 (0x0E018159)
#define BOOT_SEED_IPL3(x) (((x) & 0x0000FF00) >> 8)
#define BOOT_SEED_5101 (0x0000AC00)
#define BOOT_SEED_X101 (0x00043F3F)
#define BOOT_SEED_X102 (0x00003F3F)
#define BOOT_SEED_X103 (0x0000783F)
#define BOOT_SEED_X105 (0x0000913F)
#define BOOT_SEED_X106 (0x0000853F)
#define BOOT_SEED_8303 (0x0000DD00)
#define BOOT_SEED_IPL3(x) (((x) & 0x0000FF00) >> 8)
#define BOOT_SEED_OS_VERSION(x) (((x) & 0x00040000) >> 18)
typedef enum cic_type_e {
E_CIC_TYPE_UNKNOWN,
@ -79,12 +82,9 @@ typedef struct os_boot_config_s os_boot_config_t;
#define OS_BOOT_ROM_TYPE_GAME_PAK (0)
#define OS_BOOT_ROM_TYPE_DD (1)
#define OS_BOOT_VERSION_NTSC (0)
#define OS_BOOT_VERSION_PAL (6)
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);
void boot(cart_header_t *cart_header, cic_type_t cic_type, tv_type_t tv_type);
#endif

View File

@ -1,5 +1,3 @@
#include <inttypes.h>
#include "crc32.h"
const uint32_t crc_table[256] = {

View File

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

View File

@ -7,16 +7,14 @@ 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();
cart_header_t *cart_header = boot_load_cart_header();
// Try to guess CIC and TV type from ROM in SDRAM if no override is provided
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);
}
@ -28,5 +26,5 @@ int main(void) {
disable_interrupts();
boot(cic_type, tv_type);
boot(cart_header, cic_type, tv_type);
}

View File

@ -28,14 +28,6 @@ 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);

View File

@ -3,8 +3,6 @@
#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);

View File

@ -5,7 +5,6 @@
#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
@ -19,8 +18,4 @@
#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

1
sw/cic Submodule

@ -0,0 +1 @@
Subproject commit 16fd1eecd8528ab2d7fd0490f24fb7738017bd39