[SC64][FW][SW] Complete fw/sw rewrite with RISC-V softcore CPU as flashcart controller (#5)

This commit is contained in:
Mateusz Faderewski 2021-09-25 20:00:36 +02:00 committed by GitHub
parent 200f164363
commit 45fbd53001
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
157 changed files with 6033 additions and 29634 deletions

40
.github/workflows/docker.yml vendored Normal file
View File

@ -0,0 +1,40 @@
name: Build docker
on:
workflow_dispatch:
env:
REGISTRY: ghcr.io
IMAGE_NAME: sc64env
jobs:
build-and-push-image:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- name: Checkout repository
uses: actions/checkout@v2
- name: Log in to the Container registry
uses: docker/login-action@f054a8b539a109f9f41c372932f1ae047eff08c9
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Extract metadata (tags, labels) for Docker
id: meta
uses: docker/metadata-action@98669ae865ea3cffbcbaa878cf57c20bbf1c6c38
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
- name: Build and push Docker image
uses: docker/build-push-action@ad44023a93711e3deb337508980b4b5e9bcdc5dc
with:
context: .
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}

View File

@ -1,4 +1,4 @@
name: Build
name: Build fw/hw/sw
on:
push:
@ -18,19 +18,14 @@ jobs:
with:
submodules: true
- name: Install dependencies
run: |
sudo apt-get update
sudo apt-get install avra
- name: Build script
run: ./build_release.sh
run: ./build.sh
- name: Upload artifact
uses: actions/upload-artifact@v2
with:
name: SummerCart64
path: packages/SummerCart64.zip
path: SummerCart64.zip
- name: Get release
if: github.event_name == 'release' && github.event.action == 'created'

3
.gitignore vendored
View File

@ -1,3 +1,2 @@
/packages
**/.vscode
/sw/test
*.zip

4
.gitmodules vendored
View File

@ -1,3 +1,7 @@
[submodule "fw/cpu/picorv32"]
path = fw/cpu/picorv32
url = https://github.com/cliffordwolf/picorv32.git
ignore = dirty
[submodule "sw/cic"]
path = sw/cic
url = https://github.com/ManCloud/UltraCIC-III.git

View File

@ -1,25 +0,0 @@
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_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_TAG}.zip
on:
repo: Polprzewodnikowy/SummerCollection
tags: true
skip_cleanup: true

View File

@ -55,8 +55,7 @@ Instructions below are mostly written for Windows users and point to Windows spe
There are several issues with the project at the moment in order of importance. Keep in mind that core flashcart functionality is fully working:
- No FlashRAM save emulation implementation.
- No save write-back to SD card implementation.
- No save write-back to SD card without console reset implementation.
- No RTC implementation.

3
build.sh Executable file
View File

@ -0,0 +1,3 @@
#!/bin/bash
docker run --mount type=bind,src="$(pwd)",target="/workdir" polprzewodnikowy/sc64env:0.9 /bin/bash ./docker/build.sh

View File

@ -1,41 +0,0 @@
#!/bin/bash
PACKAGES_FOLDER_NAME="packages"
PACKAGE_FILE_NAME="SummerCart64_PCB"
FILES=(
"./hw/v1/CAMOutputs"
# Manually created files
"./hw/v1/SummerCart64_sch.pdf"
"./hw/v1/SummerCart64_brd_top.pdf"
"./hw/v1/SummerCart64_brd_bot.pdf"
"./hw/v1/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/v1
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[@]}

View File

@ -1,48 +0,0 @@
#!/bin/bash
PACKAGES_FOLDER_NAME="packages"
PACKAGE_FILE_NAME="SummerCart64"
FILES=(
"./fw/output_files/SummerCart64.pof"
"./hw/v1/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
./build.sh
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[@]}

93
docker/Dockerfile Normal file
View File

@ -0,0 +1,93 @@
FROM ubuntu:18.04 AS base
FROM base AS build_base
SHELL ["/bin/bash", "-c"]
WORKDIR /tmp/scratchpad
ENV DEBIAN_FRONTEND="noninteractive"
RUN apt-get update && \
apt-get upgrade -y && \
apt-get install -y \
autoconf \
automake \
autotools-dev \
bc \
bison \
build-essential \
bzip2 \
curl \
expect \
file \
flex \
g++ \
gawk \
gcc \
gcc-multilib \
git \
gperf \
libexpat-dev \
libgmp-dev \
libmpc-dev \
libmpfr-dev \
libpng-dev \
libtool \
make \
patchutils \
python3 \
texinfo \
texinfo \
wget \
zlib1g-dev
FROM build_base AS build_riscv
RUN git clone --branch 2021.09.21 https://github.com/riscv/riscv-gnu-toolchain && \
pushd ./riscv-gnu-toolchain && \
./configure --prefix=/opt/riscv --with-arch=rv32i --with-abi=ilp32 && \
make -j$(nproc) && \
popd && \
rm -rf ./riscv-gnu-toolchain
FROM build_base AS build_n64
ENV N64_INST=/opt/n64
ENV FORCE_DEFAULT_GCC=true
RUN git clone https://github.com/DragonMinded/libdragon && \
pushd ./libdragon && \
git checkout fc4b6708df7439b9386bb6631e24d8909d78d6ae && \
pushd ./tools && \
./build-toolchain.sh && \
popd && \
make install && \
make tools-install && \
popd && \
rm -rf ./libdragon
FROM build_base AS build_quartus
ADD setup_quartus.sh .
RUN mkdir -p ./quartus && \
pushd ./quartus && \
wget -q http://download.altera.com/akdlm/software/acdsinst/20.1std.1/720/ib_tar/Quartus-lite-20.1.1.720-linux.tar && \
tar xvf Quartus-lite-20.1.1.720-linux.tar && \
popd && \
./setup_quartus.sh 20.1 && \
rm -rf ./quartus setup_quartus.sh
FROM base AS release
WORKDIR /workdir
ENV DEBIAN_FRONTEND="noninteractive"
ENV LC_ALL="en_US.UTF-8"
ENV N64_INST="/usr/local"
ENV PATH="${PATH}:/opt/intelFPGA_lite/20.1/quartus/bin"
RUN apt-get update && \
apt-get upgrade -y && \
apt-get install -y avra make python3 libglib2.0-0 libtcmalloc-minimal4 libmpc3 locales zip && \
echo "en_US.UTF-8 UTF-8" > /etc/locale.gen && \
locale-gen en_US.UTF-8 && \
/usr/sbin/update-locale LANG=en_US.UTF-8
COPY --from=build_riscv /opt/riscv /usr/local
COPY --from=build_n64 /opt/n64 /usr/local
COPY --from=build_quartus /opt/intelFPGA_lite /opt/intelFPGA_lite
ENV LD_PRELOAD="/usr/lib/x86_64-linux-gnu/libtcmalloc_minimal.so.4"

42
docker/build.sh Executable file
View File

@ -0,0 +1,42 @@
#!/bin/bash
PACKAGE_FILE_NAME="SummerCart64"
FILES=(
"./fw/output_files/SummerCart64.pof"
"./hw/v1/ftdi-template.xml"
"./sw/cic/UltraCIC-III.hex"
"./sw/riscv/build/controller.rom"
"./LICENSE"
)
pushd sw/cic
echo "Building UltraCIC-III software"
avra UltraCIC-III.asm -D attiny45
popd
pushd sw/n64
echo "Building N64 bootloader software"
make clean all
popd
pushd sw/riscv
echo "Building RISC-V controller software"
make clean all
popd
pushd fw
echo "Building FPGA firmware"
quartus_sh --flow compile SummerCart64.qpf
popd
echo "Zipping files"
if [[ -e "./${PACKAGE_FILE_NAME}.zip" ]]; then
rm -f "./${PACKAGE_FILE_NAME}.zip"
fi
zip -r "./${PACKAGE_FILE_NAME}.zip" ${FILES[@]}

25
docker/setup_quartus.sh Executable file
View File

@ -0,0 +1,25 @@
#!/usr/bin/expect
set timeout -1
set version [lindex $argv 0]
spawn ./quartus/setup.sh
expect {
"Press \\\[Enter\\\] to continue:" { send "\r"; exp_continue }
"Do you accept this license? \\\[y/n\\\]" { send "y\r"; exp_continue }
"Installation directory \\\[/root/intelFPGA_lite/$version\\\]:" { send "/opt/intelFPGA_lite/$version\r"; exp_continue }
"Quartus Prime Lite Edition (Free) \\\[Y/n\\\] :" { send "y\r"; exp_continue }
"Quartus Prime Lite Edition (Free) - Quartus Prime Help" { send "n\r"; exp_continue }
"Quartus Prime Lite Edition (Free) - Devices \\\[Y/n\\\] " { send "y\r"; exp_continue }
"Quartus Prime Lite Edition (Free) - Devices - MAX 10 FPGA" { send "y\r"; exp_continue }
"Quartus Prime Lite Edition (Free) - Devices - " { send "n\r"; exp_continue }
"ModelSim - Intel FPGA Starter Edition (Free)" { send "n\r"; exp_continue }
"ModelSim - Intel FPGA Edition" { send "n\r"; exp_continue }
"Is the selection above correct? \\\[Y/n\\\]:" { send "y\r"; exp_continue }
"Create shortcuts on Desktop \\\[Y/n\\\]:" { send "n\r"; exp_continue }
"Launch Quartus Prime Lite Edition \\\[Y/n\\\]:" { send "n\r"; exp_continue }
"Provide your feedback at" { send "n\r"; exp_continue }
eof { }
}

3
fw/.gitignore vendored
View File

@ -7,3 +7,6 @@
*.rpt
*.txt
*.sopcinfo
**/*.elf
**/*.bin
**/*.dat

View File

@ -1,98 +0,0 @@
# SummerCart64 Firmware
A FPGA firmware written in Verilog for SummerCart64.
# Technical Reference Manual
## Bus peripheral addresses
- **`0x1000 0000 - 0x13FF FFFF`** - [R/W] *SDRAM Memory*
- **`0x1D00 0000 - 0x1D00 07FF`** - [R/W] *EEPROM Memory*
- **`0x1E00 0000 - 0x1E00 0007`** - [R/W] *Cart Registers*
## Memory spaces
### SDRAM Memory
Base address: **`0x1000 0000`**\
Length: **`64 MB`**\
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.
### EEPROM Memory
Base address: **`0x1D00 0000`**\
Length: **`2 kB`**\
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.
## Registers
### Cart (**CART**) registers
Base address: **`0x1E00 0000`**
#### Configuration register (**CR**)
Address offset: **`0x00`**\
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: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: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_EN**: Enable EEPROM access through SI bus.
- 0: EEPROM SI access disabled
- 1: EEPROM SI access enabled
- 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: 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
#### CIC and TV type override register (**CIC_TV**)
Address offset: **`0x04`**\
Powerup value: **`0x0000 0000`**\
Access: Read or write, 4 byte (32 bit) aligned
This register is used for PC -> bootloader communication.
31:6 | 5:4 | 3:0
--------|---------|----------
SWITCH | TV_TYPE | CIC_TYPE
R/W | R/W | R/W
- 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
- 2: MPAL TV type
- 3: No TV type override - use TV type provided by ROM header
- Bits 3:0 **CIC_TYPE**: Overrides CIC type in bootloader.
- 0: No CIC type override - use CIC type determined from ROM bootcode
- 1: CIC 5101
- 2: CIC 6101/7102
- 3: CIC 6102/7101
- 4: CIC X103
- 5: CIC X105
- 6: CIC X106
- 7: CIC 8303
- 8 - 15: Same effect as value 0

View File

@ -18,13 +18,13 @@
# -------------------------------------------------------------------------- #
#
# Quartus Prime
# Version 20.1.0 Build 711 06/05/2020 SJ Lite Edition
# Date created = 23:45:19 July 29, 2020
# Version 20.1.1 Build 720 11/11/2020 SJ Lite Edition
# Date created = 10:53:32 August 01, 2021
#
# -------------------------------------------------------------------------- #
QUARTUS_VERSION = "20.1"
DATE = "23:45:19 July 29, 2020"
DATE = "10:53:32 August 01, 2021"
# Revisions

View File

@ -19,7 +19,7 @@
#
# Quartus Prime
# Version 20.1.1 Build 720 11/11/2020 SJ Lite Edition
# Date created = 00:00:00 November 06, 2020
# Date created = 21:23:28 September 18, 2021
#
# -------------------------------------------------------------------------- #
#
@ -40,55 +40,65 @@
# 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 ORIGINAL_QUARTUS_VERSION 20.1.1
set_global_assignment -name PROJECT_CREATION_TIME_DATE "10:53:32 AUGUST 01, 2021"
set_global_assignment -name LAST_QUARTUS_VERSION "20.1.1 Lite Edition"
set_global_assignment -name PROJECT_OUTPUT_DIRECTORY output_files
set_global_assignment -name NUM_PARALLEL_PROCESSORS ALL
set_global_assignment -name FLOW_ENABLE_POWER_ANALYZER ON
set_global_assignment -name SMART_RECOMPILE OFF
set_global_assignment -name NUM_PARALLEL_PROCESSORS 16
set_global_assignment -name QIP_FILE rtl/intel/fifo/fifo_usb.qip
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 QSYS_FILE rtl/intel/flash/onchip_flash.qsys
set_global_assignment -name SDC_FILE constraints.sdc
set_global_assignment -name SIGNALTAP_FILE output_files/signal_tap_logic_analyzer.stp
set_global_assignment -name SYSTEMVERILOG_FILE rtl/intel/gpio/gpio_ddro/altera_gpio_lite.sv -library gpio_ddro
set_global_assignment -name VERILOG_FILE rtl/cart/cart_control.v
set_global_assignment -name VERILOG_FILE rtl/cart/cart_led.v
set_global_assignment -name VERILOG_FILE rtl/glue/device_arbiter.v
set_global_assignment -name VERILOG_FILE rtl/memory/memory_embedded_flash.v
set_global_assignment -name VERILOG_FILE rtl/memory/memory_sdram.v
set_global_assignment -name VERILOG_FILE rtl/n64/n64_bank_decoder.v
set_global_assignment -name VERILOG_FILE rtl/n64/n64_pi.v
set_global_assignment -name VERILOG_FILE rtl/n64/n64_si.v
set_global_assignment -name VERILOG_FILE rtl/sd/sd_clk.v
set_global_assignment -name VERILOG_FILE rtl/sd/sd_cmd.v
set_global_assignment -name VERILOG_FILE rtl/sd/sd_crc_16.v
set_global_assignment -name VERILOG_FILE rtl/sd/sd_crc_7.v
set_global_assignment -name VERILOG_FILE rtl/sd/sd_dat.v
set_global_assignment -name VERILOG_FILE rtl/sd/sd_dma.v
set_global_assignment -name VERILOG_FILE rtl/sd/sd_fifo.v
set_global_assignment -name VERILOG_FILE rtl/sd/sd_interface.v
set_global_assignment -name VERILOG_FILE rtl/sd/sd_regs.v
set_global_assignment -name VERILOG_FILE rtl/top.v
set_global_assignment -name VERILOG_FILE rtl/usb/usb_ftdi_fsi.v
set_global_assignment -name VERILOG_FILE rtl/usb/usb_pc.v
set_global_assignment -name VERILOG_INCLUDE_FILE rtl/constants.vh
set_global_assignment -name SLD_FILE db/signal_tap_logic_analyzer_auto_stripped.stp
set_global_assignment -name QSYS_FILE rtl/intel/flash/intel_flash.qsys
set_global_assignment -name QSYS_FILE rtl/intel/snp/intel_snp.qsys
set_global_assignment -name QIP_FILE rtl/intel/fifo/intel_fifo_8.qip
set_global_assignment -name QIP_FILE rtl/intel/gpio/intel_gpio_ddro.qip
set_global_assignment -name QIP_FILE rtl/intel/pll/intel_pll.qip
set_global_assignment -name SDC_FILE SummerCart64.sdc
set_global_assignment -name SIGNALTAP_FILE stp.stp
set_global_assignment -name SYSTEMVERILOG_FILE cpu/picorv32/picorv32.v
set_global_assignment -name SYSTEMVERILOG_FILE ../sw/riscv/build/cpu_bootloader.sv
set_global_assignment -name SYSTEMVERILOG_FILE rtl/cpu/cpu_bus.sv
set_global_assignment -name SYSTEMVERILOG_FILE rtl/cpu/cpu_cfg.sv
set_global_assignment -name SYSTEMVERILOG_FILE rtl/cpu/cpu_dma.sv
set_global_assignment -name SYSTEMVERILOG_FILE rtl/cpu/cpu_flashram.sv
set_global_assignment -name SYSTEMVERILOG_FILE rtl/cpu/cpu_gpio.sv
set_global_assignment -name SYSTEMVERILOG_FILE rtl/cpu/cpu_i2c.sv
set_global_assignment -name SYSTEMVERILOG_FILE rtl/cpu/cpu_ram.sv
set_global_assignment -name SYSTEMVERILOG_FILE rtl/cpu/cpu_sdram.sv
set_global_assignment -name SYSTEMVERILOG_FILE rtl/cpu/cpu_si.sv
set_global_assignment -name SYSTEMVERILOG_FILE rtl/cpu/cpu_soc.sv
set_global_assignment -name SYSTEMVERILOG_FILE rtl/cpu/cpu_uart.sv
set_global_assignment -name SYSTEMVERILOG_FILE rtl/cpu/cpu_usb.sv
set_global_assignment -name SYSTEMVERILOG_FILE rtl/cpu/cpu_wrapper.sv
set_global_assignment -name SYSTEMVERILOG_FILE rtl/memory/memory_flash.sv
set_global_assignment -name SYSTEMVERILOG_FILE rtl/memory/memory_sdram.sv
set_global_assignment -name SYSTEMVERILOG_FILE rtl/n64/n64_bootloader.sv
set_global_assignment -name SYSTEMVERILOG_FILE rtl/n64/n64_bus.sv
set_global_assignment -name SYSTEMVERILOG_FILE rtl/n64/n64_cfg.sv
set_global_assignment -name SYSTEMVERILOG_FILE rtl/n64/n64_dd.sv
set_global_assignment -name SYSTEMVERILOG_FILE rtl/n64/n64_flashram.sv
set_global_assignment -name SYSTEMVERILOG_FILE rtl/n64/n64_pi.sv
set_global_assignment -name SYSTEMVERILOG_FILE rtl/n64/n64_pi_fifo.sv
set_global_assignment -name SYSTEMVERILOG_FILE rtl/n64/n64_sdram.sv
set_global_assignment -name SYSTEMVERILOG_FILE rtl/n64/n64_si.sv
set_global_assignment -name SYSTEMVERILOG_FILE rtl/n64/n64_soc.sv
set_global_assignment -name SYSTEMVERILOG_FILE rtl/SummerCart64.sv
set_global_assignment -name SYSTEMVERILOG_FILE rtl/system/config.sv
set_global_assignment -name SYSTEMVERILOG_FILE rtl/system/sc64.sv
set_global_assignment -name SYSTEMVERILOG_FILE rtl/system/system.sv
set_global_assignment -name SYSTEMVERILOG_FILE rtl/usb/usb_ft1248.sv
set_global_assignment -name SIGNALTAP_FILE output_files/signaltap.stp
set_global_assignment -name SLD_FILE db/signaltap_auto_stripped.stp
# Pin & Location Assignments
# ==========================
set_location_assignment PIN_6 -to io_pmod[3]
set_location_assignment PIN_7 -to io_pmod[4]
set_location_assignment PIN_8 -to io_pmod[5]
set_location_assignment PIN_10 -to io_pmod[6]
set_location_assignment PIN_11 -to io_pmod[7]
set_location_assignment PIN_12 -to o_ftdi_si
set_location_assignment PIN_13 -to o_ftdi_clk
set_location_assignment PIN_14 -to i_ftdi_so
set_location_assignment PIN_15 -to i_ftdi_cts
set_location_assignment PIN_6 -to o_usb_clk
set_location_assignment PIN_7 -to io_usb_miosi[2]
set_location_assignment PIN_8 -to io_usb_miosi[3]
set_location_assignment PIN_10 -to io_usb_miosi[0]
set_location_assignment PIN_11 -to io_usb_miosi[1]
set_location_assignment PIN_12 -to i_uart_rxd
set_location_assignment PIN_13 -to o_uart_txd
set_location_assignment PIN_14 -to i_uart_cts
set_location_assignment PIN_15 -to o_uart_rts
set_location_assignment PIN_17 -to o_led
set_location_assignment PIN_21 -to o_rtc_scl
set_location_assignment PIN_22 -to io_rtc_sda
@ -97,6 +107,8 @@ set_location_assignment PIN_25 -to i_n64_nmi
set_location_assignment PIN_26 -to i_clk
set_location_assignment PIN_27 -to i_n64_reset
set_location_assignment PIN_28 -to i_n64_si_clk
set_location_assignment PIN_29 -to io_n64_cic_clk
set_location_assignment PIN_30 -to io_n64_cic_dq
set_location_assignment PIN_32 -to io_n64_pi_ad[7]
set_location_assignment PIN_33 -to io_n64_pi_ad[8]
set_location_assignment PIN_38 -to io_n64_pi_ad[6]
@ -159,26 +171,27 @@ set_location_assignment PIN_114 -to o_sd_clk
set_location_assignment PIN_118 -to io_sd_cmd
set_location_assignment PIN_119 -to io_sd_dat[3]
set_location_assignment PIN_120 -to io_sd_dat[2]
set_location_assignment PIN_121 -to io_sram_dq[0]
set_location_assignment PIN_122 -to o_sram_clk
set_location_assignment PIN_123 -to io_sram_dq[3]
set_location_assignment PIN_124 -to o_sram_cs
set_location_assignment PIN_126 -to io_sram_dq[1]
set_location_assignment PIN_127 -to io_sram_dq[2]
set_location_assignment PIN_138 -to io_pmod[0]
set_location_assignment PIN_140 -to io_pmod[1]
set_location_assignment PIN_141 -to io_pmod[2]
set_location_assignment PIN_123 -to o_n64_irq
set_location_assignment PIN_127 -to io_avr_mosi
set_location_assignment PIN_130 -to io_flash_dq[0]
set_location_assignment PIN_131 -to o_flash_clk
set_location_assignment PIN_132 -to io_flash_dq[3]
set_location_assignment PIN_134 -to o_flash_cs
set_location_assignment PIN_135 -to io_flash_dq[1]
set_location_assignment PIN_136 -to io_flash_dq[2]
set_location_assignment PIN_138 -to i_usb_pwren
set_location_assignment PIN_140 -to o_usb_cs
set_location_assignment PIN_141 -to i_usb_miso
# 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"
set_global_assignment -name OPTIMIZATION_MODE BALANCED
# Analysis & Synthesis Assignments
# ================================
@ -186,9 +199,12 @@ 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 PROJECT_IP_REGENERATION_POLICY ALWAYS_REGENERATE_IP
set_global_assignment -name VHDL_INPUT_VERSION VHDL_2008
set_global_assignment -name VHDL_SHOW_LMF_MAPPING_MESSAGES OFF
set_global_assignment -name VERILOG_INPUT_VERSION SYSTEMVERILOG_2005
set_global_assignment -name VERILOG_SHOW_LMF_MAPPING_MESSAGES OFF
set_global_assignment -name TOP_LEVEL_ENTITY top
set_global_assignment -name TOP_LEVEL_ENTITY SummerCart64
# Fitter Assignments
# ==================
@ -196,13 +212,9 @@ 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 INTERNAL_FLASH_UPDATE_MODE "SINGLE COMP IMAGE"
set_global_assignment -name CRC_ERROR_OPEN_DRAIN OFF
set_global_assignment -name STRATIX_DEVICE_IO_STANDARD "3.3-V LVTTL"
set_global_assignment -name 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_global_assignment -name PHYSICAL_SYNTHESIS_ASYNCHRONOUS_SIGNAL_PIPELINING OFF
set_global_assignment -name ROUTER_CLOCKING_TOPOLOGY_ANALYSIS ON
set_global_assignment -name FITTER_EFFORT "STANDARD FIT"
# Assembler Assignments
# =====================
@ -210,14 +222,10 @@ 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 ON
set_global_assignment -name USE_SIGNALTAP_FILE output_files/signal_tap_logic_analyzer.stp
set_global_assignment -name USE_SIGNALTAP_FILE output_files/signaltap.stp
# Power Estimation Assignments
# ============================
@ -232,40 +240,62 @@ 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)
# --------------------------
# start ENTITY(SummerCart64)
# Project-Wide Assignments
# ========================
# end ENTITY(altera_gpio_lite)
# ----------------------------
# -----------------------
# start ENTITY(gpio_ddro)
# Project-Wide Assignments
# ========================
# end ENTITY(gpio_ddro)
# ---------------------
# -----------------
# start ENTITY(top)
# Pin & Location Assignments
# ==========================
set_instance_assignment -name FAST_INPUT_REGISTER ON -to io_usb_miosi[*]
set_instance_assignment -name FAST_INPUT_REGISTER ON -to i_uart_rxd
set_instance_assignment -name FAST_INPUT_REGISTER ON -to i_uart_cts
set_instance_assignment -name FAST_INPUT_REGISTER ON -to io_rtc_sda
set_instance_assignment -name FAST_INPUT_REGISTER ON -to io_n64_si_dq
set_instance_assignment -name FAST_INPUT_REGISTER ON -to i_n64_nmi
set_instance_assignment -name FAST_INPUT_REGISTER ON -to i_n64_reset
set_instance_assignment -name FAST_INPUT_REGISTER ON -to i_n64_si_clk
set_instance_assignment -name FAST_INPUT_REGISTER ON -to io_n64_pi_ad[*]
set_instance_assignment -name FAST_INPUT_REGISTER ON -to i_n64_pi_aleh
set_instance_assignment -name FAST_INPUT_REGISTER ON -to i_n64_pi_read
set_instance_assignment -name FAST_INPUT_REGISTER ON -to i_n64_pi_write
set_instance_assignment -name FAST_INPUT_REGISTER ON -to i_n64_pi_alel
set_instance_assignment -name FAST_INPUT_REGISTER ON -to io_sdram_dq[*]
set_instance_assignment -name FAST_INPUT_REGISTER ON -to io_sd_*
set_instance_assignment -name FAST_INPUT_REGISTER ON -to i_usb_pwren
set_instance_assignment -name FAST_INPUT_REGISTER ON -to i_usb_miso
set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to o_usb_clk
set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to io_usb_miosi[*]
set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to o_uart_txd
set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to o_uart_rts
set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to o_rtc_scl
set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to io_rtc_sda
set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to io_n64_pi_ad[*]
set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to o_sdram_*
set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to io_sdram_dq[*]
set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to o_sd_clk
set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to io_sd_*
set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to o_usb_cs
set_instance_assignment -name FAST_OUTPUT_ENABLE_REGISTER ON -to io_usb_miosi[*]
set_instance_assignment -name FAST_OUTPUT_ENABLE_REGISTER ON -to io_n64_pi_ad[*]
set_instance_assignment -name FAST_OUTPUT_ENABLE_REGISTER ON -to io_sdram_dq[*]
set_instance_assignment -name FAST_OUTPUT_ENABLE_REGISTER ON -to io_sd_*
set_instance_assignment -name FAST_OUTPUT_ENABLE_REGISTER ON -to io_rtc_sda
# Fitter Assignments
# ==================
set_instance_assignment -name WEAK_PULL_UP_RESISTOR ON -to io_usb_miosi[*]
set_instance_assignment -name WEAK_PULL_UP_RESISTOR ON -to i_n64_nmi
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_alel
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_uart_rxd
set_instance_assignment -name WEAK_PULL_UP_RESISTOR ON -to i_uart_cts
set_instance_assignment -name WEAK_PULL_UP_RESISTOR ON -to io_n64_si_dq
set_instance_assignment -name WEAK_PULL_UP_RESISTOR ON -to i_n64_reset
set_instance_assignment -name WEAK_PULL_UP_RESISTOR ON -to i_n64_si_clk
set_instance_assignment -name WEAK_PULL_UP_RESISTOR ON -to io_n64_si_dq
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]"
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 o_n64_irq
set_instance_assignment -name WEAK_PULL_UP_RESISTOR ON -to i_usb_pwren
set_instance_assignment -name WEAK_PULL_UP_RESISTOR ON -to i_usb_miso
# start DESIGN_PARTITION(Top)
# ---------------------------
@ -280,5 +310,23 @@ set_global_assignment -name OUTPUT_IO_TIMING_FAR_END_VMEAS "HALF SIGNAL SWING" -
# end DESIGN_PARTITION(Top)
# -------------------------
# end ENTITY(top)
# ---------------
# end ENTITY(SummerCart64)
# ------------------------
# ------------------------------
# start ENTITY(altera_gpio_lite)
# Project-Wide Assignments
# ========================
# end ENTITY(altera_gpio_lite)
# ----------------------------
# -----------------------------
# start ENTITY(intel_gpio_ddro)
# Project-Wide Assignments
# ========================
# end ENTITY(intel_gpio_ddro)
# ---------------------------

87
fw/SummerCart64.sdc Normal file
View File

@ -0,0 +1,87 @@
# Clocks
derive_pll_clocks -create_base_clocks
set sys_clk {system_inst|intel_pll_inst|altpll_component|auto_generated|pll1|clk[0]}
set sdram_pll_clk {system_inst|intel_pll_inst|altpll_component|auto_generated|pll1|clk[1]}
# set sd_reg_clk {sd_interface_inst|sd_clk_inst|o_sd_clk|q}
create_generated_clock -name sdram_clk -source [get_pins $sdram_pll_clk] [get_ports {o_sdram_clk}]
# create_generated_clock -name sd_reg_clk -source [get_pins {sd_interface_inst|sd_clk_inst|o_sd_clk|clk}] -divide_by 2 [get_pins $sd_reg_clk]
# create_generated_clock -name sd_clk -source [get_pins $sd_reg_clk] [get_ports {o_sd_clk}]
create_generated_clock -name flash_se_neg_reg \
-source [get_pins -compatibility_mode {*altera_onchip_flash:*onchip_flash_0|altera_onchip_flash_avmm_data_controller:avmm_data_controller|flash_se_neg_reg|clk}] \
-divide_by 2 \
[get_pins -compatibility_mode {*altera_onchip_flash:*onchip_flash_0|altera_onchip_flash_avmm_data_controller:avmm_data_controller|flash_se_neg_reg|q}]
derive_clock_uncertainty
# SDRAM timings
set sdram_outputs {o_sdram_cs o_sdram_ras o_sdram_cas o_sdram_we o_sdram_a[*] o_sdram_ba[*] io_sdram_dq[*]}
set sdram_inputs {io_sdram_dq[*]}
set_output_delay -clock [get_clocks {sdram_clk}] -max 1.5 [get_ports $sdram_outputs]
set_output_delay -clock [get_clocks {sdram_clk}] -min -0.8 [get_ports $sdram_outputs]
set_input_delay -clock [get_clocks {sdram_clk}] -max 5.4 [get_ports $sdram_inputs]
set_input_delay -clock [get_clocks {sdram_clk}] -min 2.5 [get_ports $sdram_inputs]
set_multicycle_path -setup -end 2 -from [get_clocks {sdram_clk}] -to [get_clocks $sys_clk]
# SD card timings
# set_output_delay -clock [get_clocks {sd_clk}] -max 6.0 [get_ports {io_sd_cmd io_sd_dat[*]}]
# set_output_delay -clock [get_clocks {sd_clk}] -min -2.0 [get_ports {io_sd_cmd io_sd_dat[*]}]
# set_input_delay -clock [get_clocks {sd_clk}] -max 15.0 [get_ports {io_sd_cmd io_sd_dat[*]}]
# set_input_delay -clock [get_clocks {sd_clk}] -min 6.5 [get_ports {io_sd_cmd io_sd_dat[*]}]
# set_multicycle_path -hold -start 1 -from [get_clocks $sys_clk] -to [get_clocks {sd_clk}]
# set_multicycle_path -setup -end 3 -from [get_clocks {sd_clk}] -to [get_clocks $sys_clk]
# set_multicycle_path -hold -end 1 -from [get_clocks {sd_clk}] -to [get_clocks $sys_clk]
# FT1248 timings
set_false_path -to [get_ports {o_usb_clk io_usb_miosi[*] o_usb_cs}]
set_false_path -from [get_ports {io_usb_miosi[*] i_usb_miso}]
# N64, PI and SI timings
set_false_path -to [get_ports {o_n64_irq}]
set_false_path -from [get_ports {i_n64_reset i_n64_nmi}]
set_false_path -to [get_ports {io_n64_pi_ad[*]}]
set_false_path -from [get_ports {i_n64_pi_* io_n64_pi_ad[*]}]
set_false_path -to [get_ports {io_n64_si_dq}]
set_false_path -from [get_ports {i_n64_si_clk io_n64_si_dq}]
# LED timings
set_false_path -to [get_ports {o_led}]
# UART timings
set_false_path -to [get_ports {o_uart_txd o_uart_rts}]
set_false_path -from [get_ports {i_uart_rxd i_uart_cts}]
# I2C timings
set_false_path -to [get_ports {o_rtc_scl io_rtc_sda}]
set_false_path -from [get_ports {io_rtc_sda}]
# JTAG timings
# set_false_path -to [get_ports {altera_reserved_tdo}]
# set_false_path -from [get_ports {altera_reserved_tdi altera_reserved_tms}]

View File

@ -1,61 +0,0 @@
# Clocks
derive_pll_clocks -create_base_clocks
set sys_clk {sys_pll|altpll_component|auto_generated|pll1|clk[0]}
set sdram_pll_clk {sys_pll|altpll_component|auto_generated|pll1|clk[1]}
create_generated_clock -name sdram_clk -source [get_pins $sdram_pll_clk] -master_clock $sdram_pll_clk [get_ports {o_sdram_clk}]
create_generated_clock -name flash_se_neg_reg -divide_by 2 \
-source [get_pins -compatibility_mode {*altera_onchip_flash:*onchip_flash_0|altera_onchip_flash_avmm_data_controller:avmm_data_controller|flash_se_neg_reg|clk}] \
[get_pins -compatibility_mode {*altera_onchip_flash:*onchip_flash_0|altera_onchip_flash_avmm_data_controller:avmm_data_controller|flash_se_neg_reg|q}]
derive_clock_uncertainty
# SDRAM timings
set sdram_outputs {o_sdram_cs o_sdram_ras o_sdram_cas o_sdram_we o_sdram_a[*] o_sdram_ba[*] io_sdram_dq[*]}
set sdram_inputs {io_sdram_dq[*]}
set_output_delay -clock [get_clocks {sdram_clk}] -max 1.5 [get_ports $sdram_outputs]
set_output_delay -clock [get_clocks {sdram_clk}] -min -0.8 [get_ports $sdram_outputs]
set_input_delay -clock [get_clocks {sdram_clk}] -max 5.4 [get_ports $sdram_inputs]
set_input_delay -clock [get_clocks {sdram_clk}] -min 2.5 [get_ports $sdram_inputs]
set_multicycle_path -setup -end 2 -from [get_clocks {sdram_clk}] -to [get_clocks $sys_clk]
# FTDI timings
set_false_path -to [get_ports {o_ftdi_clk o_ftdi_si}]
set_false_path -from [get_ports {i_ftdi_so i_ftdi_cts}]
# SD card timings
set_false_path -to [get_ports {o_sd_clk io_sd_cmd io_sd_dat[*]}]
set_false_path -from [get_ports {io_sd_cmd io_sd_dat[*]}]
# N64, PI and SI timings
set_false_path -from [get_ports {i_n64_reset i_n64_nmi}]
set_false_path -to [get_ports {io_n64_pi_ad[*]}]
set_false_path -from [get_ports {i_n64_pi_* io_n64_pi_ad[*]}]
set_false_path -to [get_ports {io_n64_si_dq}]
set_false_path -from [get_ports {i_n64_si_clk io_n64_si_dq}]
# LED timings
set_false_path -to [get_ports {o_led}]
# PMOD timings
set_false_path -to [get_ports {io_pmod[*]}]
set_false_path -from [get_ports {io_pmod[*]}]

1
fw/cpu/picorv32 Submodule

@ -0,0 +1 @@
Subproject commit f9b1beb4cfd6b382157b54bc8f38c61d5ae7d785

143
fw/rtl/SummerCart64.sv Normal file
View File

@ -0,0 +1,143 @@
module SummerCart64 (
input i_clk,
input i_n64_reset,
input i_n64_nmi,
output o_n64_irq,
input i_n64_pi_alel,
input i_n64_pi_aleh,
input i_n64_pi_read,
input i_n64_pi_write,
inout [15:0] io_n64_pi_ad,
input i_n64_si_clk,
inout io_n64_si_dq,
output o_sdram_clk,
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,
output o_rtc_scl,
inout io_rtc_sda,
output o_usb_clk,
output o_usb_cs,
input i_usb_miso,
inout [3:0] io_usb_miosi,
input i_usb_pwren,
input i_uart_rxd,
output o_uart_txd,
input i_uart_cts,
output o_uart_rts,
output o_sd_clk,
inout io_sd_cmd,
inout [3:0] io_sd_dat,
output o_led
);
logic [7:0] gpio_o;
logic [7:0] gpio_i;
logic [7:0] gpio_oe;
if_system sys (
.in_clk(i_clk),
.n64_reset(i_n64_reset),
.n64_nmi(i_n64_nmi)
);
if_config cfg ();
if_dma dma ();
if_sdram sdram ();
if_flashram flashram ();
if_si si ();
system system_inst (
.sys(sys)
);
intel_gpio_ddro sdram_clk_ddro (
.outclock(sys.sdram.sdram_clk),
.din({1'b0, 1'b1}),
.pad_out(o_sdram_clk)
);
n64_soc n64_soc_inst (
.sys(sys),
.cfg(cfg),
.dma(dma),
.sdram(sdram),
.flashram(flashram),
.si(si),
.n64_pi_alel(i_n64_pi_alel),
.n64_pi_aleh(i_n64_pi_aleh),
.n64_pi_read(i_n64_pi_read),
.n64_pi_write(i_n64_pi_write),
.n64_pi_ad(io_n64_pi_ad),
.n64_si_clk(i_n64_si_clk),
.n64_si_dq(io_n64_si_dq),
.sdram_cs(o_sdram_cs),
.sdram_ras(o_sdram_ras),
.sdram_cas(o_sdram_cas),
.sdram_we(o_sdram_we),
.sdram_ba(o_sdram_ba),
.sdram_a(o_sdram_a),
.sdram_dq(io_sdram_dq)
);
cpu_soc cpu_soc_inst (
.sys(sys),
.cfg(cfg),
.dma(dma),
.sdram(sdram),
.flashram(flashram),
.si(si),
.gpio_o(gpio_o),
.gpio_i(gpio_i),
.gpio_oe(gpio_oe),
.i2c_scl(o_rtc_scl),
.i2c_sda(io_rtc_sda),
.usb_clk(o_usb_clk),
.usb_cs(o_usb_cs),
.usb_miso(i_usb_miso),
.usb_miosi(io_usb_miosi),
.usb_pwren(i_usb_pwren),
.uart_rxd(i_uart_rxd),
.uart_txd(o_uart_txd),
.uart_cts(i_uart_cts),
.uart_rts(o_uart_rts),
.sd_clk(o_sd_clk),
.sd_cmd(io_sd_cmd),
.sd_dat(io_sd_dat)
);
always_comb begin
o_led = gpio_oe[0] ? gpio_o[0] : 1'bZ;
o_n64_irq = gpio_oe[1] ? gpio_o[1] : 1'bZ;
end
always_ff @(posedge sys.clk) begin
gpio_i <= {4'b0000, i_n64_nmi, i_n64_reset, o_n64_irq, o_led};
end
endmodule

View File

@ -1,218 +0,0 @@
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 [10:0] i_address,
output reg [31:0] o_data,
input [31:0] i_data,
output reg o_sdram_writable,
output reg o_rom_switch,
output reg o_ddipl_enable,
output reg o_sram_enable,
output reg o_sram_768k_mode,
output reg o_flashram_enable,
output reg o_sd_enable,
output reg o_eeprom_pi_enable,
output reg o_eeprom_enable,
output reg o_eeprom_16k_mode,
output reg o_n64_reset_btn,
input i_debug_ready,
output reg o_debug_dma_start,
input i_debug_dma_busy,
output reg [3:0] o_debug_dma_bank,
output reg [23:0] o_debug_dma_address,
output reg [19:0] o_debug_dma_length,
output reg o_debug_fifo_request,
output reg o_debug_fifo_flush,
input [10:0] i_debug_fifo_items,
input [31:0] i_debug_fifo_data,
output reg [23:0] o_ddipl_address,
output reg [23:0] o_sram_address
);
// Module parameters
parameter byte VERSION = "a";
// Register offsets
localparam [3:0] REG_SCR = 4'd0;
localparam [3:0] REG_BOOT = 4'd1;
localparam [3:0] REG_VERSION = 4'd2;
localparam [3:0] REG_GPIO = 4'd3;
localparam [3:0] REG_USB_SCR = 4'd4;
localparam [3:0] REG_USB_DMA_ADDR = 4'd5;
localparam [3:0] REG_USB_DMA_LEN = 4'd6;
localparam [3:0] REG_DDIPL_ADDR = 4'd7;
localparam [3:0] REG_SRAM_ADDR = 4'd8;
localparam [10:0] MEM_USB_FIFO_BASE = 11'h400;
// 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 [15:0] r_bootloader;
// Bus controller
assign o_busy = 1'b0;
always @(posedge i_clk) begin
o_ack <= !i_reset && i_request && !i_write && !o_busy;
end
// Write logic
always @(posedge i_clk) begin
o_debug_dma_start <= 1'b0;
o_debug_fifo_flush <= 1'b0;
if (i_reset) begin
o_sdram_writable <= 1'b0;
o_rom_switch <= 1'b0;
o_ddipl_enable <= 1'b0;
o_sram_enable <= 1'b0;
o_sram_768k_mode <= 1'b0;
o_flashram_enable <= 1'b0;
o_sd_enable <= 1'b0;
o_eeprom_pi_enable <= 1'b0;
o_eeprom_enable <= 1'b0;
o_eeprom_16k_mode <= 1'b0;
o_n64_reset_btn <= 1'b1;
o_ddipl_address <= 24'hF0_0000;
o_sram_address <= 24'hFF_E000;
o_debug_dma_bank <= 4'd1;
o_debug_dma_address <= 24'hFC_0000;
o_debug_dma_length <= 20'd0;
r_bootloader <= 16'h0000;
end else begin
if (i_request && i_write && !o_busy) begin
case (i_address[3:0])
REG_SCR: begin
{
o_flashram_enable,
o_sram_768k_mode,
o_sram_enable,
o_sd_enable,
o_eeprom_pi_enable,
o_eeprom_16k_mode,
o_eeprom_enable,
o_ddipl_enable,
o_rom_switch,
o_sdram_writable
} <= i_data[9:0];
end
REG_BOOT: begin
r_bootloader <= i_data[15:0];
end
REG_GPIO: begin
o_n64_reset_btn <= ~i_data[0];
end
REG_USB_SCR: begin
{o_debug_fifo_flush, o_debug_dma_start} <= {i_data[2], i_data[0]};
end
REG_USB_DMA_ADDR: begin
{o_debug_dma_bank, o_debug_dma_address} <= {i_data[31:28], i_data[25:2]};
end
REG_USB_DMA_LEN: begin
o_debug_dma_length <= i_data[19:0];
end
REG_DDIPL_ADDR: begin
o_ddipl_address <= i_data[25:2];
end
REG_SRAM_ADDR: begin
o_sram_address <= i_data[25:2];
end
default: begin
end
endcase
end
if (!r_reset_ff2 || !r_nmi_ff2) begin
o_sdram_writable <= 1'b0;
o_rom_switch <= 1'b0;
o_n64_reset_btn <= 1'b1;
o_debug_fifo_flush <= 1'b1;
end
end
end
// Read logic
always @(posedge i_clk) begin
o_debug_fifo_request <= 1'b0;
if (!i_reset && i_request && !i_write && !o_busy) begin
if (i_address < MEM_USB_FIFO_BASE) begin
case (i_address[3:0])
REG_SCR: begin
o_data[9:0] <= {
o_flashram_enable,
o_sram_768k_mode,
o_sram_enable,
o_sd_enable,
o_eeprom_pi_enable,
o_eeprom_16k_mode,
o_eeprom_enable,
o_ddipl_enable,
o_rom_switch,
o_sdram_writable
};
end
REG_BOOT: begin
o_data[15:0] <= r_bootloader;
end
REG_VERSION: begin
o_data <= {"S", "6", "4", VERSION};
end
REG_GPIO: begin
o_data[2:0] <= {r_nmi_ff2, r_reset_ff2, ~o_n64_reset_btn};
end
REG_USB_SCR: begin
{o_data[13:3], o_data[1:0]} <= {i_debug_fifo_items, i_debug_ready, i_debug_dma_busy};
end
REG_DDIPL_ADDR: begin
o_data[25:0] <= {o_ddipl_address, 2'b00};
end
REG_SRAM_ADDR: begin
o_data[25:0] <= {o_sram_address, 2'b00};
end
default: begin
end
endcase
end else begin
o_data <= i_debug_fifo_data;
o_debug_fifo_request <= 1'b1;
end
end
end
endmodule

View File

@ -1,28 +0,0 @@
module cart_led (
input i_clk,
input i_reset,
input i_trigger,
output o_led
);
localparam COUNTER_LOAD_VALUE = 5'd31;
reg [4:0] r_counter;
assign o_led = r_counter > 5'd0;
always @(posedge i_clk) begin
if (i_reset) begin
r_counter <= 5'd0;
end else begin
if (i_trigger) begin
r_counter <= COUNTER_LOAD_VALUE;
end else if (r_counter > 5'd0) begin
r_counter <= r_counter - 1'd1;
end
end
end
endmodule

View File

@ -1,8 +0,0 @@
`define VERSION "a"
`define BANK_INVALID 4'd0
`define BANK_SDRAM 4'd1
`define BANK_CART 4'd2
`define BANK_EEPROM 4'd3
`define BANK_FLASHRAM 4'd4
`define BANK_SD 4'd5

54
fw/rtl/cpu/cpu_bus.sv Normal file
View File

@ -0,0 +1,54 @@
interface if_cpu_bus ();
localparam [3:0] NUM_DEVICES = sc64::__ID_CPU_END;
logic request;
logic ack;
logic [3:0] wmask;
logic [31:0] address;
logic [31:0] wdata;
logic [31:0] rdata;
logic device_ack [(NUM_DEVICES - 1):0];
logic [31:0] device_rdata [(NUM_DEVICES - 1):0];
always_comb begin
ack = 1'b0;
rdata = 32'd0;
for (integer i = 0; i < NUM_DEVICES; i++) begin
ack = ack | device_ack[i];
rdata = rdata | device_rdata[i];
end
end
modport cpu (
output request,
input ack,
output wmask,
output address,
output wdata,
input rdata
);
genvar n;
generate
for (n = 0; n < NUM_DEVICES; n++) begin : at
logic device_request;
always_comb begin
device_request = request && address[31:28] == n[3:0];
end
modport device (
input .request(device_request),
output .ack(device_ack[n]),
input .wmask(wmask),
input .address(address),
input .wdata(wdata),
output .rdata(device_rdata[n])
);
end
endgenerate
endinterface

127
fw/rtl/cpu/cpu_cfg.sv Normal file
View File

@ -0,0 +1,127 @@
module cpu_cfg (
if_system.sys sys,
if_cpu_bus bus,
if_config.cpu cfg
);
logic skip_bootloader;
typedef enum bit [2:0] {
R_SCR,
R_DD_OFFSET,
R_SAVE_OFFSET,
R_COMMAND,
R_DATA_0,
R_DATA_1,
R_VERSION
} e_reg_id;
always_ff @(posedge sys.clk) begin
bus.ack <= 1'b0;
if (bus.request) begin
bus.ack <= 1'b1;
end
end
always_comb begin
bus.rdata = 32'd0;
if (bus.ack) begin
case (bus.address[4:2])
R_SCR: bus.rdata = {
cfg.cpu_ready,
cfg.cpu_busy,
cfg.usb_waiting,
cfg.cmd_error,
21'd0,
skip_bootloader,
cfg.flashram_enabled,
cfg.sram_banked,
cfg.sram_enabled,
cfg.dd_enabled,
cfg.sdram_writable,
cfg.sdram_switch
};
R_DD_OFFSET: bus.rdata = {6'd0, cfg.dd_offset};
R_SAVE_OFFSET: bus.rdata = {6'd0, cfg.save_offset};
R_COMMAND: bus.rdata = {24'd0, cfg.cmd};
R_DATA_0: bus.rdata = cfg.data[0];
R_DATA_1: bus.rdata = cfg.data[1];
R_VERSION: bus.rdata = sc64::SC64_VER;
default: bus.rdata = 32'd0;
endcase
end
end
always_comb begin
cfg.wdata = bus.wdata;
cfg.data_write = 2'b00;
if (bus.request && (&bus.wmask)) begin
cfg.data_write[0] = bus.address[4:2] == R_DATA_0;
cfg.data_write[1] = bus.address[4:2] == R_DATA_1;
end
end
always_ff @(posedge sys.clk) begin
if (sys.reset) begin
cfg.cpu_ready <= 1'b0;
cfg.cpu_busy <= 1'b0;
cfg.usb_waiting <= 1'b0;
cfg.cmd_error <= 1'b0;
cfg.sdram_switch <= 1'b0;
cfg.sdram_writable <= 1'b0;
cfg.dd_enabled <= 1'b0;
cfg.sram_enabled <= 1'b0;
cfg.sram_banked <= 1'b0;
cfg.flashram_enabled <= 1'b0;
cfg.dd_offset <= 26'h3BE_0000;
cfg.save_offset <= 26'h3FE_0000;
skip_bootloader <= 1'b0;
end else begin
if (sys.n64_soft_reset) begin
cfg.sdram_switch <= skip_bootloader;
cfg.sdram_writable <= 1'b0;
end
if (cfg.cmd_request) begin
cfg.cpu_busy <= 1'b1;
end
if (bus.request) begin
case (bus.address[4:2])
R_SCR: begin
if (bus.wmask[3]) begin
{
cfg.cpu_ready,
cfg.cpu_busy,
cfg.usb_waiting,
cfg.cmd_error
} <= bus.wdata[31:28];
end
if (bus.wmask[0]) begin
{
skip_bootloader,
cfg.flashram_enabled,
cfg.sram_banked,
cfg.sram_enabled,
cfg.dd_enabled,
cfg.sdram_writable,
cfg.sdram_switch
} <= bus.wdata[6:0];
end
end
R_DD_OFFSET: begin
if (&bus.wmask) begin
cfg.dd_offset <= bus.wdata[25:0];
end
end
R_SAVE_OFFSET: begin
if (&bus.wmask) begin
cfg.save_offset <= bus.wdata[25:0];
end
end
endcase
end
end
end
endmodule

222
fw/rtl/cpu/cpu_dma.sv Normal file
View File

@ -0,0 +1,222 @@
interface if_dma ();
localparam [1:0] NUM_DEVICES = sc64::__ID_DMA_END;
sc64::e_dma_id id;
logic rx_empty;
logic rx_read;
logic [7:0] rx_rdata;
logic tx_full;
logic tx_write;
logic [7:0] tx_wdata;
logic request;
logic ack;
logic write;
logic [31:0] address;
logic [15:0] rdata;
logic [15:0] wdata;
modport controller (
output id,
input rx_empty,
output rx_read,
input rx_rdata,
input tx_full,
output tx_write,
output tx_wdata,
output request,
input ack,
output write,
output address,
input rdata,
output wdata
);
modport memory (
input request,
output ack,
input write,
input address,
output rdata,
input wdata
);
logic [7:0] device_rx_rdata [(NUM_DEVICES - 1):0];
logic device_rx_empty [(NUM_DEVICES - 1):0];
logic device_tx_full [(NUM_DEVICES - 1):0];
always_comb begin
rx_rdata = 8'd0;
rx_empty = 1'b0;
tx_full = 1'b0;
for (integer i = 0; i < NUM_DEVICES; i++) begin
rx_rdata = rx_rdata | (id == i[1:0] ? device_rx_rdata[i] : 8'd0);
rx_empty = rx_empty | (device_rx_empty[i] && id == i[1:0]);
tx_full = tx_full | (device_tx_full[i] && id == i[1:0]);
end
end
genvar n;
generate
for (n = 0; n < NUM_DEVICES; n++) begin : at
logic device_selected;
logic device_rx_read;
logic device_tx_write;
always_comb begin
device_selected = id == n[1:0];
device_rx_read = device_selected && rx_read;
device_tx_write = device_selected && tx_write;
end
modport device (
output .rx_empty(device_rx_empty[n]),
input .rx_read(device_rx_read),
output .rx_rdata(device_rx_rdata[n]),
output .tx_full(device_tx_full[n]),
input .tx_write(device_tx_write),
input .tx_wdata(tx_wdata)
);
end
endgenerate
endinterface
module cpu_dma (
if_system.sys sys,
if_cpu_bus bus,
if_dma.controller dma
);
typedef enum bit [2:0] {
S_IDLE,
S_FETCH,
S_TRANSFER
} e_state;
e_state state;
logic pending_stop;
logic direction;
logic [27:0] length;
logic [15:0] rdata_buffer;
logic byte_counter;
always_comb begin
bus.rdata = 32'd0;
if (bus.ack) begin
case (bus.address[3:2])
0: bus.rdata = {28'd0, state != S_IDLE, direction, 2'b00};
1: bus.rdata = dma.address;
2: bus.rdata = {2'b00, dma.id, length};
default: bus.rdata = 32'd0;
endcase
end
end
always_ff @(posedge sys.clk) begin
bus.ack <= 1'b0;
if (bus.request) begin
bus.ack <= 1'b1;
end
dma.rx_read <= 1'b0;
dma.tx_write <= 1'b0;
if (sys.reset) begin
state <= S_IDLE;
pending_stop <= 1'b0;
dma.request <= 1'b0;
end else begin
if (bus.request && bus.address[3:2] == 0 && bus.wmask[0]) begin
pending_stop <= bus.wdata[1];
end
case (state)
S_IDLE: begin
pending_stop <= 1'b0;
if (bus.request) begin
case (bus.address[3:2])
0: if (bus.wmask[0]) begin
direction <= bus.wdata[2];
if (bus.wdata[0]) begin
state <= S_FETCH;
byte_counter <= 1'b0;
end
end
1: if (&bus.wmask) begin
dma.address <= bus.wdata;
end
2: if (&bus.wmask) begin
{dma.id, length} <= {bus.wdata[29:1], 1'b0};
end
endcase
end
end
S_FETCH: begin
if (length != 28'd0 && !pending_stop) begin
if (direction) begin
if (!dma.rx_empty && !dma.rx_read) begin
dma.rx_read <= 1'b1;
dma.wdata <= {dma.wdata[7:0], dma.rx_rdata};
byte_counter <= ~byte_counter;
if (byte_counter) begin
state <= S_TRANSFER;
dma.request <= 1'b1;
dma.write <= 1'b1;
end
end
end else begin
dma.request <= 1'b1;
dma.write <= 1'b0;
if (dma.ack) begin
state <= S_TRANSFER;
dma.request <= 1'b0;
rdata_buffer <= dma.rdata;
end
end
end else begin
state <= S_IDLE;
end
end
S_TRANSFER: begin
if (direction) begin
if (dma.ack) begin
state <= S_FETCH;
dma.request <= 1'b0;
dma.address <= dma.address + 2'd2;
length <= length - 2'd2;
end
end else begin
if (!dma.tx_full && !dma.tx_write) begin
dma.tx_write <= 1'b1;
dma.tx_wdata <= byte_counter ? rdata_buffer[7:0] : rdata_buffer[15:8];
byte_counter <= ~byte_counter;
if (byte_counter) begin
state <= S_FETCH;
dma.address <= dma.address + 2'd2;
length <= length - 2'd2;
end
end
end
end
default: begin
state <= S_IDLE;
dma.request <= 1'b0;
end
endcase
end
end
endmodule

View File

@ -0,0 +1,77 @@
interface if_flashram ();
logic [4:0] address;
logic [31:0] rdata;
logic [9:0] sector;
logic operation_pending;
logic write_or_erase;
logic sector_or_all;
logic operation_done;
modport cpu (
output address,
input rdata,
input sector,
input operation_pending,
input write_or_erase,
input sector_or_all,
output operation_done
);
modport flashram (
input address,
output rdata,
output sector,
output operation_pending,
output write_or_erase,
output sector_or_all,
input operation_done
);
endinterface
module cpu_flashram (
if_system.sys sys,
if_cpu_bus bus,
if_flashram.cpu flashram
);
always_ff @(posedge sys.clk) begin
bus.ack <= 1'b0;
if (bus.request) begin
bus.ack <= 1'b1;
end
end
always_comb begin
bus.rdata = 32'd0;
if (bus.ack) begin
bus.rdata = {
14'd0,
flashram.sector,
4'd0,
flashram.sector_or_all,
flashram.write_or_erase,
1'b0,
flashram.operation_pending
};
if (bus.address[7]) begin
bus.rdata = {flashram.rdata[7:0], flashram.rdata[15:8], flashram.rdata[23:16], flashram.rdata[31:24]};
end
end
flashram.address = bus.address[6:2];
end
always_ff @(posedge sys.clk) begin
flashram.operation_done <= 1'b0;
if (bus.request) begin
if (!bus.address[7] && bus.wmask[0]) begin
flashram.operation_done <= bus.wdata[1];
end
end
end
endmodule

42
fw/rtl/cpu/cpu_gpio.sv Normal file
View File

@ -0,0 +1,42 @@
module cpu_gpio (
if_system.sys sys,
if_cpu_bus bus,
input [7:0] gpio_i,
output [7:0] gpio_o,
output [7:0] gpio_oe
);
logic [1:0][7:0] gpio_i_ff;
logic [7:0] gpio_o_value;
logic [7:0] gpio_oe_value;
always_ff @(posedge sys.clk) begin
bus.ack <= 1'b0;
if (bus.request) begin
bus.ack <= 1'b1;
end
end
always_comb begin
bus.rdata = 32'd0;
if (bus.ack) begin
bus.rdata = {8'd0, gpio_oe_value, gpio_i_ff[1], gpio_o_value};
end
end
always_ff @(posedge sys.clk) begin
gpio_i_ff <= {gpio_i_ff[0], gpio_i};
gpio_o <= gpio_o_value;
gpio_oe <= gpio_oe_value;
if (sys.reset) begin
gpio_o_value <= 8'd0;
gpio_oe_value <= 8'd0;
end else if (bus.request) begin
if (bus.wmask[0]) gpio_o_value <= bus.wdata[7:0];
if (bus.wmask[2]) gpio_oe_value <= bus.wdata[23:16];
end
end
endmodule

155
fw/rtl/cpu/cpu_i2c.sv Normal file
View File

@ -0,0 +1,155 @@
module cpu_i2c (
if_system.sys sys,
if_cpu_bus bus,
output i2c_scl,
inout i2c_sda
);
reg [1:0] state;
reg mack;
reg [8:0] trx_data;
always_comb begin
bus.rdata = 32'd0;
if (bus.ack) begin
case (bus.address[2])
0: bus.rdata = {27'd0, |state, ~trx_data[0], mack, 2'b00};
1: bus.rdata = {23'd0, trx_data[0], trx_data[8:1]};
default: bus.rdata = 32'd0;
endcase
end
end
always_ff @(posedge sys.clk) begin
bus.ack <= 1'b0;
if (bus.request) begin
bus.ack <= 1'b1;
end
if (sys.reset) begin
mack <= 1'b0;
end else if (bus.request && bus.wmask[0] && !bus.address[2]) begin
mack <= bus.wdata[2];
end
end
reg [5:0] clock_div;
reg [3:0] clock_phase_gen;
wire clock_tick = &clock_div;
wire [3:0] clock_phase = {4{clock_tick}} & clock_phase_gen;
always_ff @(posedge sys.clk) begin
if (sys.reset) begin
clock_div <= 6'd0;
end else begin
clock_div <= clock_div + 1'd1;
end
if (sys.reset || state == 2'd0) begin
clock_phase_gen <= 4'b0001;
end else if (clock_tick) begin
clock_phase_gen <= {clock_phase_gen[2:0], clock_phase_gen[3]};
end
end
reg [3:0] bit_counter;
reg sda_i_ff1, sda_i_ff2;
reg scl_o;
reg sda_o;
assign i2c_scl = scl_o ? 1'bZ : 1'b0;
assign i2c_sda = sda_o ? 1'bZ : 1'b0;
always_ff @(posedge sys.clk) begin
{sda_i_ff2, sda_i_ff1} <= {sda_i_ff1, i2c_sda};
if (sys.reset) begin
state <= 2'd0;
scl_o <= 1'b1;
sda_o <= 1'b1;
end else begin
case (state)
2'd0: begin
bit_counter <= 4'd0;
if (bus.request && bus.wmask[0]) begin
case (bus.address[2])
0: begin
if (bus.wdata[1]) state <= 2'd2;
if (bus.wdata[0]) state <= 2'd1;
end
1: begin
state <= 2'd3;
trx_data <= {bus.wdata[7:0], ~mack};
end
endcase
end
end
2'd1: begin
if (clock_phase[0]) begin
scl_o <= 1'b1;
sda_o <= 1'b1;
end
if (clock_phase[1]) begin
sda_o <= 1'b0;
end
if (clock_phase[3]) begin
state <= 2'd0;
scl_o <= 1'b0;
end
end
2'd2: begin
if (clock_phase[0]) begin
scl_o <= 1'b0;
sda_o <= 1'b0;
end
if (clock_phase[1]) begin
scl_o <= 1'b1;
end
if (clock_phase[3]) begin
state <= 2'd0;
sda_o <= 1'b1;
end
end
2'd3: begin
if (clock_phase[0]) begin
bit_counter <= bit_counter + 1'd1;
scl_o <= 1'b0;
sda_o <= trx_data[8];
end
if (clock_phase[1]) begin
scl_o <= 1'b1;
end
if (clock_phase[3]) begin
trx_data <= {trx_data[7:0], sda_i_ff2};
scl_o <= 1'b0;
end
if (bit_counter == 4'b1010) begin
state <= 2'd0;
end
end
default: begin
state <= 2'd0;
scl_o <= 1'b1;
sda_o <= 1'b1;
end
endcase
end
end
endmodule

33
fw/rtl/cpu/cpu_ram.sv Normal file
View File

@ -0,0 +1,33 @@
module cpu_ram (
if_system.sys sys,
if_cpu_bus bus
);
logic [3:0][7:0] ram [0:4095];
logic [31:0] q;
always_ff @(posedge sys.clk) begin
bus.ack <= 1'b0;
if (bus.request) begin
bus.ack <= 1'b1;
end
end
always_comb begin
bus.rdata = 32'd0;
if (bus.ack) begin
bus.rdata = q;
end
end
always_ff @(posedge sys.clk) begin
q <= ram[bus.address[13:2]];
if (bus.request) begin
if (bus.wmask[0]) ram[bus.address[13:2]][0] <= bus.wdata[7:0];
if (bus.wmask[1]) ram[bus.address[13:2]][1] <= bus.wdata[15:8];
if (bus.wmask[2]) ram[bus.address[13:2]][2] <= bus.wdata[23:16];
if (bus.wmask[3]) ram[bus.address[13:2]][3] <= bus.wdata[31:24];
end
end
endmodule

76
fw/rtl/cpu/cpu_sdram.sv Normal file
View File

@ -0,0 +1,76 @@
interface if_sdram ();
logic request;
logic ack;
logic write;
logic [31:0] address;
logic [15:0] rdata;
logic [15:0] wdata;
modport cpu (
output request,
input ack,
output write,
output address,
input rdata,
output wdata
);
modport memory (
input request,
output ack,
input write,
input address,
output rdata,
input wdata
);
endinterface
module cpu_sdram (
if_system.sys sys,
if_cpu_bus bus,
if_sdram.cpu sdram
);
logic request;
logic current_word;
logic [31:0] rdata;
always_comb begin
bus.rdata = 32'd0;
if (bus.ack) begin
bus.rdata = {rdata[7:0], rdata[15:8], rdata[23:16], rdata[31:24]};
end
sdram.write = current_word ? &bus.wmask[1:0] : &bus.wmask[3:2];
sdram.address = {1'b0, bus.address[30:2], current_word, 1'b0};
sdram.wdata = current_word ? {bus.wdata[23:16], bus.wdata[31:24]} : {bus.wdata[7:0], bus.wdata[15:8]};
end
always_ff @(posedge sys.clk) begin
bus.ack <= 1'b0;
if (sys.reset) begin
sdram.request <= 1'b0;
end else begin
if (bus.request) begin
sdram.request <= 1'b1;
current_word <= 1'b0;
end
if (sdram.ack) begin
if (!current_word) begin
current_word <= 1'b1;
rdata[31:16] <= sdram.rdata;
end else begin
bus.ack <= 1'b1;
sdram.request <= 1'b0;
rdata[15:0] <= sdram.rdata;
end
end
end
end
endmodule

59
fw/rtl/cpu/cpu_si.sv Normal file
View File

@ -0,0 +1,59 @@
module cpu_si (
if_system.sys sys,
if_cpu_bus bus,
if_si.cpu si
);
always_ff @(posedge sys.clk) begin
bus.ack <= 1'b0;
if (bus.request) begin
bus.ack <= 1'b1;
end
end
always_comb begin
bus.rdata = 32'd0;
if (bus.ack) begin
case (bus.address[3:2])
0: bus.rdata = {
20'd0,
si.rx_length[6:3],
4'd0,
si.tx_busy,
1'b0,
si.rx_data[0],
si.rx_ready
};
1: bus.rdata = {si.rx_data[56:49], si.rx_data[64:57], si.rx_data[72:65], si.rx_data[80:73]};
2: bus.rdata = {si.rx_data[24:17], si.rx_data[32:25], si.rx_data[40:33], si.rx_data[48:41]};
3: bus.rdata = {16'd0, si.rx_data[8:1], si.rx_data[16:9]};
default: bus.rdata = 32'd0;
endcase
end
end
always_comb begin
si.tx_data = {bus.wdata[7:0], bus.wdata[15:8], bus.wdata[23:16], bus.wdata[31:24]};
si.tx_length = bus.wdata[22:16];
end
always_ff @(posedge sys.clk) begin
si.tx_reset <= 1'b0;
si.rx_reset <= 1'b0;
si.tx_start <= 1'b0;
si.tx_wmask <= 3'b000;
if (bus.request && (&bus.wmask)) begin
case (bus.address[3:2])
0: begin
si.tx_reset <= bus.wdata[7];
si.rx_reset <= bus.wdata[6];
si.tx_start <= bus.wdata[2];
end
1: si.tx_wmask[0] <= 1'b1;
2: si.tx_wmask[1] <= 1'b1;
3: si.tx_wmask[2] <= 1'b1;
endcase
end
end
endmodule

114
fw/rtl/cpu/cpu_soc.sv Normal file
View File

@ -0,0 +1,114 @@
module cpu_soc (
if_system.sys sys,
if_config.cpu cfg,
if_dma dma,
if_sdram.cpu sdram,
if_flashram.cpu flashram,
if_si.cpu si,
input [7:0] gpio_i,
output [7:0] gpio_o,
output [7:0] gpio_oe,
output i2c_scl,
inout i2c_sda,
output usb_clk,
output usb_cs,
input usb_miso,
inout [3:0] usb_miosi,
input usb_pwren,
input uart_rxd,
output uart_txd,
input uart_cts,
output uart_rts,
output sd_clk,
inout sd_cmd,
inout [3:0] sd_dat
);
if_cpu_bus bus ();
cpu_wrapper cpu_wrapper_inst (
.sys(sys),
.bus(bus)
);
cpu_ram cpu_ram_inst (
.sys(sys),
.bus(bus.at[sc64::ID_CPU_RAM].device)
);
cpu_bootloader cpu_bootloader_inst (
.sys(sys),
.bus(bus.at[sc64::ID_CPU_BOOTLOADER].device)
);
cpu_gpio cpu_gpio_inst (
.sys(sys),
.bus(bus.at[sc64::ID_CPU_GPIO].device),
.gpio_i(gpio_i),
.gpio_o(gpio_o),
.gpio_oe(gpio_oe)
);
cpu_i2c cpu_i2c_inst (
.sys(sys),
.bus(bus.at[sc64::ID_CPU_I2C].device),
.i2c_scl(i2c_scl),
.i2c_sda(i2c_sda)
);
cpu_usb cpu_usb_inst (
.sys(sys),
.bus(bus.at[sc64::ID_CPU_USB].device),
.dma(dma.at[sc64::ID_DMA_USB].device),
.usb_clk(usb_clk),
.usb_cs(usb_cs),
.usb_miso(usb_miso),
.usb_miosi(usb_miosi),
.usb_pwren(usb_pwren)
);
cpu_uart cpu_uart_inst (
.sys(sys),
.bus(bus.at[sc64::ID_CPU_UART].device),
.uart_rxd(uart_rxd),
.uart_txd(uart_txd),
.uart_cts(uart_cts),
.uart_rts(uart_rts)
);
cpu_dma cpu_dma_inst (
.sys(sys),
.bus(bus.at[sc64::ID_CPU_DMA].device),
.dma(dma)
);
cpu_cfg cpu_cfg_inst (
.sys(sys),
.bus(bus.at[sc64::ID_CPU_CFG].device),
.cfg(cfg)
);
cpu_sdram cpu_sdram_inst (
.sys(sys),
.bus(bus.at[sc64::ID_CPU_SDRAM].device),
.sdram(sdram)
);
cpu_flashram cpu_flashram_inst (
.sys(sys),
.bus(bus.at[sc64::ID_CPU_FLASHRAM].device),
.flashram(flashram)
);
cpu_si cpu_si_inst (
.sys(sys),
.bus(bus.at[sc64::ID_CPU_SI].device),
.si(si)
);
endmodule

155
fw/rtl/cpu/cpu_uart.sv Normal file
View File

@ -0,0 +1,155 @@
module cpu_uart (
if_system.sys sys,
if_cpu_bus bus,
input uart_rxd,
output uart_txd,
input uart_cts,
output uart_rts
);
localparam BAUD_GEN_VALUE = int'(sc64::CLOCK_FREQUENCY / sc64::UART_BAUD_RATE) - 1'd1;
typedef enum bit [1:0] {
S_TRX_IDLE,
S_TRX_DATA,
S_TRX_SAMPLING_OFFSET
} e_trx_state;
// CPU bus controller
e_trx_state tx_state;
e_trx_state rx_state;
logic [7:0] rx_data;
logic rx_available;
logic rx_overrun;
always_ff @(posedge sys.clk) begin
bus.ack <= 1'b0;
if (bus.request) begin
bus.ack <= 1'b1;
end
end
always_comb begin
bus.rdata = 32'd0;
if (bus.ack) begin
case (bus.address[2:2])
0: bus.rdata = {29'd0, rx_overrun, tx_state == S_TRX_IDLE, rx_available};
1: bus.rdata = {24'd0, rx_data};
default: bus.rdata = 32'd0;
endcase
end
end
// TX path
logic [6:0] tx_baud_counter;
logic [3:0] tx_bit_counter;
logic [9:0] tx_shifter;
always_ff @(posedge sys.clk) begin
tx_baud_counter <= tx_baud_counter + 1'd1;
uart_txd <= tx_shifter[0];
if (sys.reset) begin
tx_state <= S_TRX_IDLE;
tx_shifter <= 10'h3FF;
end else begin
case (tx_state)
S_TRX_IDLE: begin
if (bus.request && bus.wmask[0] && bus.address[2]) begin
tx_state <= S_TRX_DATA;
tx_baud_counter <= 7'd0;
tx_bit_counter <= 4'd0;
tx_shifter <= {1'b1, bus.wdata[7:0], 1'b0};
end
end
S_TRX_DATA: begin
if (tx_baud_counter == BAUD_GEN_VALUE) begin
tx_baud_counter <= 7'd0;
tx_bit_counter <= tx_bit_counter + 1'd1;
tx_shifter <= {1'b1, tx_shifter[9:1]};
if (tx_bit_counter == 4'd9) begin
tx_state <= S_TRX_IDLE;
end
end
end
default: begin
tx_state <= S_TRX_IDLE;
tx_shifter <= 10'h3FF;
end
endcase
end
end
// RX path
logic [6:0] rx_baud_counter;
logic [3:0] rx_bit_counter;
logic [7:0] rx_shifter;
logic [1:0] rxd_ff;
always_ff @(posedge sys.clk) begin
rx_baud_counter <= rx_baud_counter + 1'd1;
rxd_ff <= {rxd_ff[0], uart_rxd};
if (bus.request && bus.wmask[0] && !bus.address[2]) begin
rx_overrun <= bus.wdata[2];
end
if (bus.request && !bus.wmask[0] && bus.address[2]) begin
rx_available <= 1'b0;
end
if (sys.reset) begin
rx_state <= S_TRX_IDLE;
rx_available <= 1'b0;
rx_overrun <= 1'b0;
end else begin
case (rx_state)
S_TRX_IDLE: begin
if (!rxd_ff[1]) begin
rx_state <= S_TRX_SAMPLING_OFFSET;
rx_baud_counter <= 7'd0;
rx_bit_counter <= 4'd0;
end
end
S_TRX_SAMPLING_OFFSET: begin
if (rx_baud_counter == (BAUD_GEN_VALUE / 2)) begin
rx_state <= S_TRX_DATA;
rx_baud_counter <= 7'd0;
end
end
S_TRX_DATA: begin
if (rx_baud_counter == BAUD_GEN_VALUE) begin
rx_baud_counter <= 7'd0;
rx_bit_counter <= rx_bit_counter + 1'd1;
rx_shifter <= {rxd_ff[1], rx_shifter[7:1]};
if (rx_bit_counter == 4'd8) begin
rx_state <= S_TRX_IDLE;
if (rxd_ff[1]) begin
rx_data <= rx_shifter[7:0];
rx_available <= 1'b1;
rx_overrun <= rx_available;
end
end
end
end
default: begin
rx_state <= S_TRX_IDLE;
rx_available <= 1'b0;
rx_overrun <= 1'b0;
end
endcase
end
end
endmodule

100
fw/rtl/cpu/cpu_usb.sv Normal file
View File

@ -0,0 +1,100 @@
module cpu_usb (
if_system sys,
if_cpu_bus bus,
if_dma dma,
output usb_clk,
output usb_cs,
input usb_miso,
inout [3:0] usb_miosi,
input usb_pwren
);
logic rx_flush;
logic rx_empty;
logic rx_read;
logic [7:0] rx_rdata;
logic tx_flush;
logic tx_full;
logic tx_write;
logic [7:0] tx_wdata;
logic cpu_rx_read;
logic cpu_tx_write;
always_comb begin
dma.rx_empty = rx_empty;
rx_read = cpu_rx_read || dma.rx_read;
dma.rx_rdata = rx_rdata;
dma.tx_full = tx_full;
tx_write = cpu_tx_write || dma.tx_write;
tx_wdata = dma.tx_write ? dma.tx_wdata : bus.wdata[7:0];
end
always_ff @(posedge sys.clk) begin
bus.ack <= 1'b0;
if (bus.request) begin
bus.ack <= 1'b1;
end
end
always_comb begin
bus.rdata = 32'd0;
if (bus.ack) begin
case (bus.address[2:2])
0: bus.rdata = {30'd0, ~tx_full, ~rx_empty};
1: bus.rdata = {24'd0, rx_rdata};
default: bus.rdata = 32'd0;
endcase
end
end
always_ff @(posedge sys.clk) begin
rx_flush <= 1'b0;
cpu_rx_read <= 1'b0;
tx_flush <= 1'b0;
cpu_tx_write <= 1'b0;
if (bus.request) begin
case (bus.address[2:2])
2'd0: begin
if (bus.wmask[0]) begin
{tx_flush, rx_flush} <= bus.wdata[3:2];
end
end
2'd1: begin
if (bus.wmask[0]) begin
cpu_tx_write <= 1'b1;
end else begin
cpu_rx_read <= 1'b1;
end
end
endcase
end
end
usb_ft1248 usb_ft1248_inst (
.sys(sys),
.usb_clk(usb_clk),
.usb_cs(usb_cs),
.usb_miso(usb_miso),
.usb_miosi(usb_miosi),
.usb_pwren(usb_pwren),
.rx_flush(rx_flush),
.rx_empty(rx_empty),
.rx_read(rx_read),
.rx_rdata(rx_rdata),
.tx_flush(tx_flush),
.tx_full(tx_full),
.tx_write(tx_write),
.tx_wdata(tx_wdata)
);
endmodule

49
fw/rtl/cpu/cpu_wrapper.sv Normal file
View File

@ -0,0 +1,49 @@
module cpu_wrapper (
if_system.sys sys,
if_cpu_bus.cpu bus
);
typedef enum bit [0:0] {
S_IDLE,
S_WAITING
} e_bus_state;
e_bus_state state;
logic mem_la_read;
logic mem_la_write;
always_ff @(posedge sys.clk) begin
bus.request <= 1'b0;
if (sys.reset) begin
state <= S_IDLE;
end else begin
if (state == S_IDLE && (mem_la_read || mem_la_write)) begin
state <= S_WAITING;
bus.request <= 1'b1;
end
if (state == S_WAITING && bus.ack) begin
state <= S_IDLE;
end
end
end
picorv32 #(
.ENABLE_COUNTERS(0),
.ENABLE_COUNTERS64(0),
.CATCH_MISALIGN(0),
.CATCH_ILLINSN(0),
.PROGADDR_RESET({4'(sc64::ID_CPU_BOOTLOADER), 28'h000_0000})
) cpu_inst (
.clk(sys.clk),
.resetn(~sys.reset),
.mem_addr(bus.address),
.mem_wdata(bus.wdata),
.mem_wstrb(bus.wmask),
.mem_ready(bus.ack),
.mem_rdata(bus.rdata),
.mem_la_read(mem_la_read),
.mem_la_write(mem_la_write)
);
endmodule

View File

@ -1,91 +0,0 @@
module device_arbiter #(
parameter NUM_CONTROLLERS = 2,
parameter ADDRESS_WIDTH = 26,
parameter [3:0] DEVICE_BANK = 4'd0,
parameter ACK_FIFO_LENGTH = 4
) (
input i_clk,
input i_reset,
input [(NUM_CONTROLLERS - 1):0] i_request,
input [(NUM_CONTROLLERS - 1):0] i_write,
output reg [(NUM_CONTROLLERS - 1):0] o_busy,
output reg [(NUM_CONTROLLERS - 1):0] o_ack,
input [((NUM_CONTROLLERS * 4) - 1):0] i_bank,
input [((NUM_CONTROLLERS * ADDRESS_WIDTH) - 1):0] i_address,
output reg [((NUM_CONTROLLERS * 32) - 1):0] o_data,
input [((NUM_CONTROLLERS * 32) - 1):0] i_data,
output reg o_device_request,
output reg o_device_write,
input i_device_busy,
input i_device_ack,
output reg [(ADDRESS_WIDTH - 1):0] o_device_address,
input [31:0] i_device_data,
output reg [31:0] o_device_data
);
localparam FIFO_ADDRESS_WIDTH = $clog2(ACK_FIFO_LENGTH);
reg [(NUM_CONTROLLERS - 1):0] r_request;
reg [(NUM_CONTROLLERS - 1):0] r_request_successful;
reg [(NUM_CONTROLLERS - 1):0] r_ack_fifo_mem [0:(ACK_FIFO_LENGTH - 1)];
reg [FIFO_ADDRESS_WIDTH:0] r_ack_fifo_wrptr;
reg [FIFO_ADDRESS_WIDTH:0] r_ack_fifo_rdptr;
wire w_ack_fifo_wrreq = |(r_request_successful & ~i_write);
wire w_ack_fifo_rdreq = i_device_ack;
wire w_empty = r_ack_fifo_wrptr[FIFO_ADDRESS_WIDTH] == r_ack_fifo_rdptr[FIFO_ADDRESS_WIDTH];
wire w_full_or_empty = r_ack_fifo_wrptr[(FIFO_ADDRESS_WIDTH - 1):0] == r_ack_fifo_rdptr[(FIFO_ADDRESS_WIDTH - 1):0];
wire w_ack_fifo_full = !w_empty && w_full_or_empty;
always @(posedge i_clk) begin
if (i_reset) begin
r_ack_fifo_wrptr <= {(FIFO_ADDRESS_WIDTH + 1){1'b0}};
r_ack_fifo_rdptr <= {(FIFO_ADDRESS_WIDTH + 1){1'b0}};
end else begin
if (w_ack_fifo_wrreq) begin
r_ack_fifo_mem[r_ack_fifo_wrptr[(FIFO_ADDRESS_WIDTH - 1):0]] <= r_request_successful & ~i_write;
r_ack_fifo_wrptr <= r_ack_fifo_wrptr + 1'd1;
end
if (w_ack_fifo_rdreq) begin
r_ack_fifo_rdptr <= r_ack_fifo_rdptr + 1'd1;
end
end
end
always @(*) begin
for (integer i = 0; i < NUM_CONTROLLERS; i = i + 1) begin
r_request[i] = i_request[i] && i_bank[(i * 4) +: 4] == DEVICE_BANK;
o_busy[i] = r_request[i] && (
i_device_busy ||
|(r_request & (({{(NUM_CONTROLLERS - 1){1'b0}}, 1'b1} << i) - 1)) ||
(!i_write[i] && w_ack_fifo_full)
);
end
r_request_successful = r_request & ~o_busy;
o_ack = {NUM_CONTROLLERS{i_device_ack}} & r_ack_fifo_mem[r_ack_fifo_rdptr[(FIFO_ADDRESS_WIDTH - 1):0]];
o_data = {NUM_CONTROLLERS{i_device_data}};
end
always @(*) begin
o_device_request = |r_request;
o_device_write = 1'b0;
o_device_address = {ADDRESS_WIDTH{1'b0}};
o_device_data = 32'h0000_0000;
for (integer i = (NUM_CONTROLLERS - 1); i >= 0 ; i = i - 1) begin
if (r_request[i]) begin
o_device_write = i_write[i];
o_device_address = i_address[(i * ADDRESS_WIDTH) +: ADDRESS_WIDTH];
o_device_data = i_data[(i * 32) +: 32];
end
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_usb.v"]
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) "intel_fifo_8.v"]

View File

@ -4,7 +4,7 @@
// MODULE: scfifo
// ============================================================
// File Name: fifo_usb.v
// File Name: intel_fifo_8.v
// Megafunction Name(s):
// scfifo
//
@ -37,31 +37,31 @@
// synopsys translate_off
`timescale 1 ps / 1 ps
// synopsys translate_on
module fifo_usb (
module intel_fifo_8 (
clock,
data,
rdreq,
sclr,
wrreq,
empty,
full,
q,
usedw);
q);
input clock;
input [31:0] data;
input [7:0] data;
input rdreq;
input sclr;
input wrreq;
output empty;
output full;
output [31:0] q;
output [9:0] usedw;
output [7:0] q;
wire sub_wire0;
wire [31:0] sub_wire1;
wire [9:0] sub_wire2;
wire full = sub_wire0;
wire [31:0] q = sub_wire1[31:0];
wire [9:0] usedw = sub_wire2[9:0];
wire sub_wire1;
wire [7:0] sub_wire2;
wire empty = sub_wire0;
wire full = sub_wire1;
wire [7:0] q = sub_wire2[7:0];
scfifo scfifo_component (
.clock (clock),
@ -69,21 +69,21 @@ module fifo_usb (
.rdreq (rdreq),
.sclr (sclr),
.wrreq (wrreq),
.full (sub_wire0),
.q (sub_wire1),
.usedw (sub_wire2),
.empty (sub_wire0),
.full (sub_wire1),
.q (sub_wire2),
.aclr (),
.almost_empty (),
.almost_full (),
.eccstatus (),
.empty ());
.usedw ());
defparam
scfifo_component.add_ram_output_register = "OFF",
scfifo_component.add_ram_output_register = "ON",
scfifo_component.intended_device_family = "MAX 10",
scfifo_component.lpm_numwords = 1024,
scfifo_component.lpm_showahead = "ON",
scfifo_component.lpm_type = "scfifo",
scfifo_component.lpm_width = 32,
scfifo_component.lpm_width = 8,
scfifo_component.lpm_widthu = 10,
scfifo_component.overflow_checking = "ON",
scfifo_component.underflow_checking = "ON",
@ -102,23 +102,23 @@ endmodule
// Retrieval info: PRIVATE: CLOCKS_ARE_SYNCHRONIZED NUMERIC "0"
// Retrieval info: PRIVATE: Clock NUMERIC "0"
// Retrieval info: PRIVATE: Depth NUMERIC "1024"
// Retrieval info: PRIVATE: Empty NUMERIC "0"
// 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 "0"
// Retrieval info: PRIVATE: Optimize NUMERIC "1"
// 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: UsedW NUMERIC "0"
// Retrieval info: PRIVATE: Width NUMERIC "8"
// 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 "32"
// Retrieval info: PRIVATE: output_width NUMERIC "8"
// Retrieval info: PRIVATE: rsEmpty NUMERIC "1"
// Retrieval info: PRIVATE: rsFull NUMERIC "0"
// Retrieval info: PRIVATE: rsUsedW NUMERIC "0"
@ -128,36 +128,36 @@ endmodule
// Retrieval info: PRIVATE: wsFull NUMERIC "1"
// Retrieval info: PRIVATE: wsUsedW NUMERIC "0"
// Retrieval info: LIBRARY: altera_mf altera_mf.altera_mf_components.all
// Retrieval info: CONSTANT: ADD_RAM_OUTPUT_REGISTER STRING "OFF"
// Retrieval info: CONSTANT: ADD_RAM_OUTPUT_REGISTER 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 "scfifo"
// Retrieval info: CONSTANT: LPM_WIDTH NUMERIC "32"
// Retrieval info: CONSTANT: LPM_WIDTH NUMERIC "8"
// Retrieval info: CONSTANT: LPM_WIDTHU NUMERIC "10"
// Retrieval info: CONSTANT: OVERFLOW_CHECKING STRING "ON"
// Retrieval info: CONSTANT: UNDERFLOW_CHECKING STRING "ON"
// Retrieval info: CONSTANT: USE_EAB STRING "ON"
// Retrieval info: USED_PORT: clock 0 0 0 0 INPUT NODEFVAL "clock"
// Retrieval info: USED_PORT: data 0 0 32 0 INPUT NODEFVAL "data[31..0]"
// Retrieval info: USED_PORT: data 0 0 8 0 INPUT NODEFVAL "data[7..0]"
// Retrieval info: USED_PORT: empty 0 0 0 0 OUTPUT NODEFVAL "empty"
// Retrieval info: USED_PORT: full 0 0 0 0 OUTPUT NODEFVAL "full"
// Retrieval info: USED_PORT: q 0 0 32 0 OUTPUT NODEFVAL "q[31..0]"
// Retrieval info: USED_PORT: q 0 0 8 0 OUTPUT NODEFVAL "q[7..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: usedw 0 0 10 0 OUTPUT NODEFVAL "usedw[9..0]"
// 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 32 0 data 0 0 32 0
// Retrieval info: CONNECT: @data 0 0 8 0 data 0 0 8 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 32 0 @q 0 0 32 0
// Retrieval info: CONNECT: usedw 0 0 10 0 @usedw 0 0 10 0
// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_usb.v TRUE
// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_usb.inc FALSE
// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_usb.cmp FALSE
// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_usb.bsf FALSE
// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_usb_inst.v FALSE
// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_usb_bb.v FALSE
// Retrieval info: CONNECT: q 0 0 8 0 @q 0 0 8 0
// Retrieval info: GEN_FILE: TYPE_NORMAL intel_fifo_8.v TRUE
// Retrieval info: GEN_FILE: TYPE_NORMAL intel_fifo_8.inc FALSE
// Retrieval info: GEN_FILE: TYPE_NORMAL intel_fifo_8.cmp FALSE
// Retrieval info: GEN_FILE: TYPE_NORMAL intel_fifo_8.bsf FALSE
// Retrieval info: GEN_FILE: TYPE_NORMAL intel_fifo_8_inst.v FALSE
// Retrieval info: GEN_FILE: TYPE_NORMAL intel_fifo_8_bb.v FALSE
// Retrieval info: LIB_FILE: altera_mf

View File

@ -6,7 +6,7 @@
version="1.0"
description=""
tags="INTERNAL_COMPONENT=true"
categories="" />
categories="System" />
<parameter name="bonusData"><![CDATA[bonusData
{
element onchip_flash_0
@ -68,11 +68,11 @@
<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="SECTOR_ACCESS_MODE">Read only,Read only,Hidden,Read only,Read only</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="initializationFileName">../sw/n64/build/SummerLoader64.hex</parameter>
<parameter name="initializationFileNameForSim">../sw/n64/build/SummerLoader64.hex</parameter>
<parameter name="useNonDefaultInitFile" value="true" />
</module>
<interconnectRequirement for="$system" name="qsys_mm.clockCrossingAdapter" value="HANDSHAKE" />

View File

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

View File

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

View File

@ -1,15 +1,14 @@
// megafunction wizard: %GPIO Lite Intel FPGA IP v20.1%
// GENERATION: XML
// gpio_ddro.v
// intel_gpio_ddro.v
// Generated using ACDS version 20.1 711
// Generated using ACDS version 20.1 720
`timescale 1 ps / 1 ps
module gpio_ddro (
input wire outclock, // outclock.export
input wire outclocken, // outclocken.export
input wire [1:0] din, // din.export
output wire [0:0] pad_out // pad_out.export
module intel_gpio_ddro (
input wire outclock, // outclock.export
input wire [1:0] din, // din.export
output wire [0:0] pad_out // pad_out.export
);
altera_gpio_lite #(
@ -23,7 +22,7 @@ module gpio_ddro (
.OPEN_DRAIN_OUTPUT ("false"),
.ENABLE_OE_PORT ("false"),
.ENABLE_NSLEEP_PORT ("false"),
.ENABLE_CLOCK_ENA_PORT ("true"),
.ENABLE_CLOCK_ENA_PORT ("false"),
.SET_REGISTER_OUTPUTS_HIGH ("false"),
.INVERT_OUTPUT ("false"),
.INVERT_INPUT_CLOCK ("false"),
@ -38,29 +37,29 @@ module gpio_ddro (
.INVERT_OUTPUT_CLOCK ("false"),
.INVERT_OE_INCLOCK ("false"),
.ENABLE_PHASE_DETECTOR_FOR_CK ("false")
) gpio_ddro_inst (
.outclock (outclock), // outclock.export
.outclocken (outclocken), // outclocken.export
.din (din), // din.export
.pad_out (pad_out), // pad_out.export
.inclock (1'b0), // (terminated)
.inclocken (1'b0), // (terminated)
.fr_clock (), // (terminated)
.hr_clock (), // (terminated)
.invert_hr_clock (1'b0), // (terminated)
.phy_mem_clock (1'b0), // (terminated)
.mimic_clock (), // (terminated)
.dout (), // (terminated)
.pad_io (), // (terminated)
.pad_io_b (), // (terminated)
.pad_in (1'b0), // (terminated)
.pad_in_b (1'b0), // (terminated)
.pad_out_b (), // (terminated)
.aset (1'b0), // (terminated)
.aclr (1'b0), // (terminated)
.sclr (1'b0), // (terminated)
.nsleep (1'b0), // (terminated)
.oe (1'b0) // (terminated)
) intel_gpio_ddro_inst (
.outclock (outclock), // outclock.export
.din (din), // din.export
.pad_out (pad_out), // pad_out.export
.outclocken (1'b1), // (terminated)
.inclock (1'b0), // (terminated)
.inclocken (1'b0), // (terminated)
.fr_clock (), // (terminated)
.hr_clock (), // (terminated)
.invert_hr_clock (1'b0), // (terminated)
.phy_mem_clock (1'b0), // (terminated)
.mimic_clock (), // (terminated)
.dout (), // (terminated)
.pad_io (), // (terminated)
.pad_io_b (), // (terminated)
.pad_in (1'b0), // (terminated)
.pad_in_b (1'b0), // (terminated)
.pad_out_b (), // (terminated)
.aset (1'b0), // (terminated)
.aclr (1'b0), // (terminated)
.sclr (1'b0), // (terminated)
.nsleep (1'b0), // (terminated)
.oe (1'b0) // (terminated)
);
endmodule
@ -70,7 +69,7 @@ endmodule
// ************************************************************
// THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE!
// ************************************************************
// Copyright (C) 1991-2020 Altera Corporation
// Copyright (C) 1991-2021 Altera Corporation
// Any megafunction design, and related net list (encrypted or decrypted),
// support information, device programming or simulation file, and any other
// associated documentation or information provided by Altera or a partner
@ -105,7 +104,7 @@ endmodule
// Retrieval info: <generic name="gui_enable_aset_port" value="false" />
// Retrieval info: <generic name="gui_enable_sclr_port" value="false" />
// Retrieval info: <generic name="gui_set_registers_to_power_up_high" value="false" />
// Retrieval info: <generic name="gui_clock_enable" value="true" />
// Retrieval info: <generic name="gui_clock_enable" value="false" />
// Retrieval info: <generic name="gui_invert_output" value="false" />
// Retrieval info: <generic name="gui_invert_input_clock" value="false" />
// Retrieval info: <generic name="gui_use_register_to_drive_obuf_oe" value="false" />
@ -120,5 +119,5 @@ endmodule
// Retrieval info: <generic name="gui_invert_oe_inclock" value="false" />
// Retrieval info: <generic name="gui_use_hardened_ddio_input_registers" value="false" />
// Retrieval info: </instance>
// IPFS_FILES : gpio_ddro.vo
// RELATED_FILES: gpio_ddro.v, altera_gpio_lite.sv
// IPFS_FILES : intel_gpio_ddro.vo
// RELATED_FILES: intel_gpio_ddro.v, altera_gpio_lite.sv

View File

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

View File

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

View File

@ -4,7 +4,7 @@
// MODULE: altpll
// ============================================================
// File Name: pll.v
// File Name: intel_pll.v
// Megafunction Name(s):
// altpll
//
@ -37,7 +37,7 @@
// synopsys translate_off
`timescale 1 ps / 1 ps
// synopsys translate_on
module pll (
module intel_pll (
inclk0,
c0,
c1,
@ -110,7 +110,7 @@ module pll (
altpll_component.compensate_clock = "CLK0",
altpll_component.inclk0_input_frequency = 20000,
altpll_component.intended_device_family = "MAX 10",
altpll_component.lpm_hint = "CBX_MODULE_PREFIX=pll",
altpll_component.lpm_hint = "CBX_MODULE_PREFIX=intel_pll",
altpll_component.lpm_type = "altpll",
altpll_component.operation_mode = "NORMAL",
altpll_component.pll_type = "AUTO",
@ -168,7 +168,7 @@ endmodule
// Retrieval info: PRIVATE: BANDWIDTH STRING "1.000"
// Retrieval info: PRIVATE: BANDWIDTH_FEATURE_ENABLED STRING "1"
// Retrieval info: PRIVATE: BANDWIDTH_FREQ_UNIT STRING "MHz"
// Retrieval info: PRIVATE: BANDWIDTH_PRESET STRING "High"
// Retrieval info: PRIVATE: BANDWIDTH_PRESET STRING "Low"
// Retrieval info: PRIVATE: BANDWIDTH_USE_AUTO STRING "1"
// Retrieval info: PRIVATE: BANDWIDTH_USE_PRESET STRING "0"
// Retrieval info: PRIVATE: CLKBAD_SWITCHOVER_CHECK STRING "0"
@ -179,7 +179,7 @@ endmodule
// Retrieval info: PRIVATE: CREATE_INCLK1_CHECK STRING "0"
// Retrieval info: PRIVATE: CUR_DEDICATED_CLK STRING "c0"
// Retrieval info: PRIVATE: CUR_FBIN_CLK STRING "c0"
// Retrieval info: PRIVATE: DEVICE_SPEED_GRADE STRING "8"
// Retrieval info: PRIVATE: DEVICE_SPEED_GRADE STRING "Any"
// Retrieval info: PRIVATE: DIV_FACTOR0 NUMERIC "1"
// Retrieval info: PRIVATE: DIV_FACTOR1 NUMERIC "1"
// Retrieval info: PRIVATE: DUTY_CYCLE0 STRING "50.00000000"
@ -236,7 +236,7 @@ endmodule
// Retrieval info: PRIVATE: PLL_PFDENA_CHECK STRING "0"
// Retrieval info: PRIVATE: PLL_TARGET_HARCOPY_CHECK NUMERIC "0"
// Retrieval info: PRIVATE: PRIMARY_CLK_COMBO STRING "inclk0"
// Retrieval info: PRIVATE: RECONFIG_FILE STRING "pll.mif"
// Retrieval info: PRIVATE: RECONFIG_FILE STRING "intel_pll.mif"
// Retrieval info: PRIVATE: SACN_INPUTS_CHECK STRING "0"
// Retrieval info: PRIVATE: SCAN_FEATURE_ENABLED STRING "1"
// Retrieval info: PRIVATE: SELF_RESET_LOCK_LOSS STRING "1"
@ -330,12 +330,12 @@ endmodule
// Retrieval info: CONNECT: c0 0 0 0 0 @clk 0 0 1 0
// Retrieval info: CONNECT: c1 0 0 0 0 @clk 0 0 1 1
// Retrieval info: CONNECT: locked 0 0 0 0 @locked 0 0 0 0
// Retrieval info: GEN_FILE: TYPE_NORMAL pll.v TRUE
// Retrieval info: GEN_FILE: TYPE_NORMAL pll.ppf TRUE
// Retrieval info: GEN_FILE: TYPE_NORMAL pll.inc FALSE
// Retrieval info: GEN_FILE: TYPE_NORMAL pll.cmp FALSE
// Retrieval info: GEN_FILE: TYPE_NORMAL pll.bsf FALSE
// Retrieval info: GEN_FILE: TYPE_NORMAL pll_inst.v FALSE
// Retrieval info: GEN_FILE: TYPE_NORMAL pll_bb.v FALSE
// Retrieval info: GEN_FILE: TYPE_NORMAL intel_pll.v TRUE
// Retrieval info: GEN_FILE: TYPE_NORMAL intel_pll.ppf TRUE
// Retrieval info: GEN_FILE: TYPE_NORMAL intel_pll.inc FALSE
// Retrieval info: GEN_FILE: TYPE_NORMAL intel_pll.cmp FALSE
// Retrieval info: GEN_FILE: TYPE_NORMAL intel_pll.bsf FALSE
// Retrieval info: GEN_FILE: TYPE_NORMAL intel_pll_inst.v FALSE
// Retrieval info: GEN_FILE: TYPE_NORMAL intel_pll_bb.v FALSE
// Retrieval info: LIB_FILE: altera_mf
// Retrieval info: CBX_MODULE_PREFIX: ON

View File

@ -1,4 +0,0 @@
set_global_assignment -name IP_TOOL_NAME "RAM: 2-PORT"
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) "ram_n64_eeprom.v"]

View File

@ -1,243 +0,0 @@
// megafunction wizard: %RAM: 2-PORT%
// GENERATION: STANDARD
// VERSION: WM1.0
// MODULE: altsyncram
// ============================================================
// File Name: ram_n64_eeprom.v
// Megafunction Name(s):
// altsyncram
//
// Simulation Library Files(s):
// altera_mf
// ============================================================
// ************************************************************
// THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE!
//
// 20.1.1 Build 720 11/11/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 ram_n64_eeprom (
address_a,
address_b,
clock,
data_a,
data_b,
wren_a,
wren_b,
q_a,
q_b);
input [10:0] address_a;
input [8:0] address_b;
input clock;
input [7:0] data_a;
input [31:0] data_b;
input wren_a;
input wren_b;
output [7:0] q_a;
output [31:0] q_b;
`ifndef ALTERA_RESERVED_QIS
// synopsys translate_off
`endif
tri1 clock;
tri0 wren_a;
tri0 wren_b;
`ifndef ALTERA_RESERVED_QIS
// synopsys translate_on
`endif
wire [7:0] sub_wire0;
wire [31:0] sub_wire1;
wire [7:0] q_a = sub_wire0[7:0];
wire [31:0] q_b = sub_wire1[31:0];
altsyncram altsyncram_component (
.address_a (address_a),
.address_b (address_b),
.clock0 (clock),
.data_a (data_a),
.data_b (data_b),
.wren_a (wren_a),
.wren_b (wren_b),
.q_a (sub_wire0),
.q_b (sub_wire1),
.aclr0 (1'b0),
.aclr1 (1'b0),
.addressstall_a (1'b0),
.addressstall_b (1'b0),
.byteena_a (1'b1),
.byteena_b (1'b1),
.clock1 (1'b1),
.clocken0 (1'b1),
.clocken1 (1'b1),
.clocken2 (1'b1),
.clocken3 (1'b1),
.eccstatus (),
.rden_a (1'b1),
.rden_b (1'b1));
defparam
altsyncram_component.address_reg_b = "CLOCK0",
altsyncram_component.clock_enable_input_a = "BYPASS",
altsyncram_component.clock_enable_input_b = "BYPASS",
altsyncram_component.clock_enable_output_a = "BYPASS",
altsyncram_component.clock_enable_output_b = "BYPASS",
altsyncram_component.indata_reg_b = "CLOCK0",
altsyncram_component.intended_device_family = "MAX 10",
altsyncram_component.lpm_type = "altsyncram",
altsyncram_component.numwords_a = 2048,
altsyncram_component.numwords_b = 512,
altsyncram_component.operation_mode = "BIDIR_DUAL_PORT",
altsyncram_component.outdata_aclr_a = "NONE",
altsyncram_component.outdata_aclr_b = "NONE",
altsyncram_component.outdata_reg_a = "UNREGISTERED",
altsyncram_component.outdata_reg_b = "UNREGISTERED",
altsyncram_component.power_up_uninitialized = "FALSE",
altsyncram_component.read_during_write_mode_mixed_ports = "DONT_CARE",
altsyncram_component.read_during_write_mode_port_a = "NEW_DATA_NO_NBE_READ",
altsyncram_component.read_during_write_mode_port_b = "NEW_DATA_NO_NBE_READ",
altsyncram_component.widthad_a = 11,
altsyncram_component.widthad_b = 9,
altsyncram_component.width_a = 8,
altsyncram_component.width_b = 32,
altsyncram_component.width_byteena_a = 1,
altsyncram_component.width_byteena_b = 1,
altsyncram_component.wrcontrol_wraddress_reg_b = "CLOCK0";
endmodule
// ============================================================
// CNX file retrieval info
// ============================================================
// Retrieval info: PRIVATE: ADDRESSSTALL_A NUMERIC "0"
// Retrieval info: PRIVATE: ADDRESSSTALL_B NUMERIC "0"
// Retrieval info: PRIVATE: BYTEENA_ACLR_A NUMERIC "0"
// Retrieval info: PRIVATE: BYTEENA_ACLR_B NUMERIC "0"
// Retrieval info: PRIVATE: BYTE_ENABLE_A NUMERIC "0"
// Retrieval info: PRIVATE: BYTE_ENABLE_B NUMERIC "0"
// Retrieval info: PRIVATE: BYTE_SIZE NUMERIC "8"
// Retrieval info: PRIVATE: BlankMemory NUMERIC "1"
// Retrieval info: PRIVATE: CLOCK_ENABLE_INPUT_A NUMERIC "0"
// Retrieval info: PRIVATE: CLOCK_ENABLE_INPUT_B NUMERIC "0"
// Retrieval info: PRIVATE: CLOCK_ENABLE_OUTPUT_A NUMERIC "0"
// Retrieval info: PRIVATE: CLOCK_ENABLE_OUTPUT_B NUMERIC "0"
// Retrieval info: PRIVATE: CLRdata NUMERIC "0"
// Retrieval info: PRIVATE: CLRq NUMERIC "0"
// Retrieval info: PRIVATE: CLRrdaddress NUMERIC "0"
// Retrieval info: PRIVATE: CLRrren NUMERIC "0"
// Retrieval info: PRIVATE: CLRwraddress NUMERIC "0"
// Retrieval info: PRIVATE: CLRwren NUMERIC "0"
// Retrieval info: PRIVATE: Clock NUMERIC "0"
// Retrieval info: PRIVATE: Clock_A NUMERIC "0"
// Retrieval info: PRIVATE: Clock_B NUMERIC "0"
// Retrieval info: PRIVATE: IMPLEMENT_IN_LES NUMERIC "0"
// Retrieval info: PRIVATE: INDATA_ACLR_B NUMERIC "0"
// Retrieval info: PRIVATE: INDATA_REG_B NUMERIC "1"
// Retrieval info: PRIVATE: INIT_FILE_LAYOUT STRING "PORT_A"
// Retrieval info: PRIVATE: INIT_TO_SIM_X NUMERIC "0"
// Retrieval info: PRIVATE: INTENDED_DEVICE_FAMILY STRING "MAX 10"
// Retrieval info: PRIVATE: JTAG_ENABLED NUMERIC "0"
// Retrieval info: PRIVATE: JTAG_ID STRING "NONE"
// Retrieval info: PRIVATE: MAXIMUM_DEPTH NUMERIC "0"
// Retrieval info: PRIVATE: MEMSIZE NUMERIC "16384"
// Retrieval info: PRIVATE: MEM_IN_BITS NUMERIC "1"
// Retrieval info: PRIVATE: MIFfilename STRING ""
// Retrieval info: PRIVATE: OPERATION_MODE NUMERIC "3"
// Retrieval info: PRIVATE: OUTDATA_ACLR_B NUMERIC "0"
// Retrieval info: PRIVATE: OUTDATA_REG_B NUMERIC "0"
// Retrieval info: PRIVATE: RAM_BLOCK_TYPE NUMERIC "0"
// Retrieval info: PRIVATE: READ_DURING_WRITE_MODE_MIXED_PORTS NUMERIC "2"
// Retrieval info: PRIVATE: READ_DURING_WRITE_MODE_PORT_A NUMERIC "3"
// Retrieval info: PRIVATE: READ_DURING_WRITE_MODE_PORT_B NUMERIC "3"
// Retrieval info: PRIVATE: REGdata NUMERIC "1"
// Retrieval info: PRIVATE: REGq NUMERIC "0"
// Retrieval info: PRIVATE: REGrdaddress NUMERIC "0"
// Retrieval info: PRIVATE: REGrren NUMERIC "0"
// Retrieval info: PRIVATE: REGwraddress NUMERIC "1"
// Retrieval info: PRIVATE: REGwren NUMERIC "1"
// Retrieval info: PRIVATE: SYNTH_WRAPPER_GEN_POSTFIX STRING "0"
// Retrieval info: PRIVATE: USE_DIFF_CLKEN NUMERIC "0"
// Retrieval info: PRIVATE: UseDPRAM NUMERIC "1"
// Retrieval info: PRIVATE: VarWidth NUMERIC "1"
// Retrieval info: PRIVATE: WIDTH_READ_A NUMERIC "8"
// Retrieval info: PRIVATE: WIDTH_READ_B NUMERIC "32"
// Retrieval info: PRIVATE: WIDTH_WRITE_A NUMERIC "8"
// Retrieval info: PRIVATE: WIDTH_WRITE_B NUMERIC "32"
// Retrieval info: PRIVATE: WRADDR_ACLR_B NUMERIC "0"
// Retrieval info: PRIVATE: WRADDR_REG_B NUMERIC "1"
// Retrieval info: PRIVATE: WRCTRL_ACLR_B NUMERIC "0"
// Retrieval info: PRIVATE: enable NUMERIC "0"
// Retrieval info: PRIVATE: rden NUMERIC "0"
// Retrieval info: LIBRARY: altera_mf altera_mf.altera_mf_components.all
// Retrieval info: CONSTANT: ADDRESS_REG_B STRING "CLOCK0"
// Retrieval info: CONSTANT: CLOCK_ENABLE_INPUT_A STRING "BYPASS"
// Retrieval info: CONSTANT: CLOCK_ENABLE_INPUT_B STRING "BYPASS"
// Retrieval info: CONSTANT: CLOCK_ENABLE_OUTPUT_A STRING "BYPASS"
// Retrieval info: CONSTANT: CLOCK_ENABLE_OUTPUT_B STRING "BYPASS"
// Retrieval info: CONSTANT: INDATA_REG_B STRING "CLOCK0"
// Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "MAX 10"
// Retrieval info: CONSTANT: LPM_TYPE STRING "altsyncram"
// Retrieval info: CONSTANT: NUMWORDS_A NUMERIC "2048"
// Retrieval info: CONSTANT: NUMWORDS_B NUMERIC "512"
// Retrieval info: CONSTANT: OPERATION_MODE STRING "BIDIR_DUAL_PORT"
// Retrieval info: CONSTANT: OUTDATA_ACLR_A STRING "NONE"
// Retrieval info: CONSTANT: OUTDATA_ACLR_B STRING "NONE"
// Retrieval info: CONSTANT: OUTDATA_REG_A STRING "UNREGISTERED"
// Retrieval info: CONSTANT: OUTDATA_REG_B STRING "UNREGISTERED"
// Retrieval info: CONSTANT: POWER_UP_UNINITIALIZED STRING "FALSE"
// Retrieval info: CONSTANT: READ_DURING_WRITE_MODE_MIXED_PORTS STRING "DONT_CARE"
// Retrieval info: CONSTANT: READ_DURING_WRITE_MODE_PORT_A STRING "NEW_DATA_NO_NBE_READ"
// Retrieval info: CONSTANT: READ_DURING_WRITE_MODE_PORT_B STRING "NEW_DATA_NO_NBE_READ"
// Retrieval info: CONSTANT: WIDTHAD_A NUMERIC "11"
// Retrieval info: CONSTANT: WIDTHAD_B NUMERIC "9"
// Retrieval info: CONSTANT: WIDTH_A NUMERIC "8"
// Retrieval info: CONSTANT: WIDTH_B NUMERIC "32"
// Retrieval info: CONSTANT: WIDTH_BYTEENA_A NUMERIC "1"
// Retrieval info: CONSTANT: WIDTH_BYTEENA_B NUMERIC "1"
// Retrieval info: CONSTANT: WRCONTROL_WRADDRESS_REG_B STRING "CLOCK0"
// Retrieval info: USED_PORT: address_a 0 0 11 0 INPUT NODEFVAL "address_a[10..0]"
// Retrieval info: USED_PORT: address_b 0 0 9 0 INPUT NODEFVAL "address_b[8..0]"
// Retrieval info: USED_PORT: clock 0 0 0 0 INPUT VCC "clock"
// Retrieval info: USED_PORT: data_a 0 0 8 0 INPUT NODEFVAL "data_a[7..0]"
// Retrieval info: USED_PORT: data_b 0 0 32 0 INPUT NODEFVAL "data_b[31..0]"
// Retrieval info: USED_PORT: q_a 0 0 8 0 OUTPUT NODEFVAL "q_a[7..0]"
// Retrieval info: USED_PORT: q_b 0 0 32 0 OUTPUT NODEFVAL "q_b[31..0]"
// Retrieval info: USED_PORT: wren_a 0 0 0 0 INPUT GND "wren_a"
// Retrieval info: USED_PORT: wren_b 0 0 0 0 INPUT GND "wren_b"
// Retrieval info: CONNECT: @address_a 0 0 11 0 address_a 0 0 11 0
// Retrieval info: CONNECT: @address_b 0 0 9 0 address_b 0 0 9 0
// Retrieval info: CONNECT: @clock0 0 0 0 0 clock 0 0 0 0
// Retrieval info: CONNECT: @data_a 0 0 8 0 data_a 0 0 8 0
// Retrieval info: CONNECT: @data_b 0 0 32 0 data_b 0 0 32 0
// Retrieval info: CONNECT: @wren_a 0 0 0 0 wren_a 0 0 0 0
// Retrieval info: CONNECT: @wren_b 0 0 0 0 wren_b 0 0 0 0
// Retrieval info: CONNECT: q_a 0 0 8 0 @q_a 0 0 8 0
// Retrieval info: CONNECT: q_b 0 0 32 0 @q_b 0 0 32 0
// Retrieval info: GEN_FILE: TYPE_NORMAL ram_n64_eeprom.v TRUE
// Retrieval info: GEN_FILE: TYPE_NORMAL ram_n64_eeprom.inc FALSE
// Retrieval info: GEN_FILE: TYPE_NORMAL ram_n64_eeprom.cmp FALSE
// Retrieval info: GEN_FILE: TYPE_NORMAL ram_n64_eeprom.bsf FALSE
// Retrieval info: GEN_FILE: TYPE_NORMAL ram_n64_eeprom_inst.v FALSE
// Retrieval info: GEN_FILE: TYPE_NORMAL ram_n64_eeprom_bb.v FALSE
// Retrieval info: LIB_FILE: altera_mf

View File

@ -0,0 +1,76 @@
<?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 in_system_sources_probes_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="probes" internal="in_system_sources_probes_0.probes" />
<interface
name="source_clk"
internal="in_system_sources_probes_0.source_clk"
type="clock"
dir="end">
<port name="source_clk" internal="source_clk" />
</interface>
<interface
name="sources"
internal="in_system_sources_probes_0.sources"
type="conduit"
dir="end">
<port name="source" internal="source" />
</interface>
<module
name="in_system_sources_probes_0"
kind="altera_in_system_sources_probes"
version="20.1"
enabled="1"
autoexport="1">
<parameter name="create_source_clock" value="true" />
<parameter name="create_source_clock_enable" value="false" />
<parameter name="device_family" value="MAX 10" />
<parameter name="gui_use_auto_index" value="true" />
<parameter name="instance_id" value="SC64" />
<parameter name="probe_width" value="0" />
<parameter name="sld_instance_index" value="0" />
<parameter name="source_initial_value" value="0" />
<parameter name="source_width" value="1" />
</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

@ -1,56 +0,0 @@
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[14:0]),
.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

View File

@ -0,0 +1,76 @@
module memory_flash (
if_system.sys sys,
input request,
output ack,
input [31:0] address,
output [15:0] rdata
);
logic flash_enable;
logic flash_request;
logic flash_busy;
logic flash_ack;
logic [31:0] flash_rdata;
logic dummy_ack;
always_comb begin
flash_enable = address < 32'h10016800;
ack = flash_ack | dummy_ack;
rdata = 16'd0;
if (ack && flash_enable) begin
if (address[1]) rdata = {flash_rdata[23:16], flash_rdata[31:24]};
else rdata = {flash_rdata[7:0], flash_rdata[15:8]};
end
end
typedef enum bit [0:0] {
S_IDLE,
S_WAIT
} e_state;
e_state state;
always_ff @(posedge sys.clk) begin
dummy_ack <= 1'b0;
if (sys.reset) begin
state <= S_IDLE;
flash_request <= 1'b0;
end else begin
case (state)
S_IDLE: begin
if (request) begin
state <= S_WAIT;
flash_request <= flash_enable;
dummy_ack <= !flash_enable;
end
end
S_WAIT: begin
if (!flash_busy) begin
flash_request <= 1'b0;
end
if (ack) begin
state <= S_IDLE;
end
end
endcase
end
end
intel_flash intel_flash_inst (
.clock(sys.clk),
.reset_n(~sys.reset),
.avmm_data_addr(address[31:2]),
.avmm_data_read(flash_request),
.avmm_data_readdata(flash_rdata),
.avmm_data_waitrequest(flash_busy),
.avmm_data_readdatavalid(flash_ack),
.avmm_data_burstcount(2'd1)
);
endmodule

View File

@ -0,0 +1,233 @@
module memory_sdram (
if_system sys,
input request,
output ack,
input write,
input [25:0] address,
output [15:0] rdata,
input [15:0] wdata,
output sdram_cs,
output sdram_ras,
output sdram_cas,
output sdram_we,
output [1:0] sdram_ba,
output [12:0] sdram_a,
inout [15:0] sdram_dq
);
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; //TODO: handle this timing
// parameter real T_WR = T_RAS - T_RCD; //TODO: handle this timing
parameter real T_MRD = 14.0;
parameter real T_REF = 7_800.0;
localparam real T_CLK = (1.0 / sc64::CLOCK_FREQUENCY) * 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;
typedef enum bit [3:0] {
CMD_DESL = 4'b1111,
CMD_NOP = 4'b0111,
CMD_READ = 4'b0101,
CMD_WRITE = 4'b0100,
CMD_ACT = 4'b0011,
CMD_PRE = 4'b0010,
CMD_REF = 4'b0001,
CMD_MRS = 4'b0000
} e_sdram_cmd;
e_sdram_cmd sdram_next_cmd;
logic [15:0] sdram_dq_input;
logic [15:0] sdram_dq_output;
logic sdram_dq_output_enable;
logic [14:0] current_active_bank_row;
logic request_in_current_active_bank_row;
always_ff @(posedge sys.clk) begin
{sdram_cs, sdram_ras, sdram_cas, sdram_we} <= 4'(sdram_next_cmd);
{sdram_ba, sdram_a} <= 15'd0;
sdram_dq_input <= sdram_dq;
sdram_dq_output <= wdata;
sdram_dq_output_enable <= 1'b0;
case (sdram_next_cmd)
CMD_READ, CMD_WRITE: begin
{sdram_ba, sdram_a} <= {address[25:24], 3'b000, address[10:1]};
sdram_dq_output_enable <= sdram_next_cmd == CMD_WRITE;
end
CMD_ACT: begin
{sdram_ba, sdram_a} <= address[25:11];
current_active_bank_row <= address[25:11];
end
CMD_PRE: {sdram_ba, sdram_a} <= {2'b00, 2'b00, 1'b1, 10'd0};
CMD_MRS: {sdram_ba, sdram_a} <= {2'b00, 1'b0, 1'b0, 2'b00, CAS_LATENCY, 1'b0, 3'b000};
endcase
end
always_comb begin
rdata = sdram_dq_input;
sdram_dq = sdram_dq_output_enable ? sdram_dq_output : 16'hZZZZ;
request_in_current_active_bank_row = address[25:11] == current_active_bank_row;
end
typedef enum bit [2:0] {
S_INIT,
S_IDLE,
S_ACTIVATING,
S_ACTIVE,
S_BUSY,
S_PRECHARGE,
S_REFRESH
} e_state;
e_state state;
e_state next_state;
always_ff @(posedge sys.clk) begin
if (sys.reset) begin
state <= S_INIT;
end else begin
state <= next_state;
end
end
logic [13:0] wait_counter;
logic [9:0] refresh_counter;
logic pending_refresh;
always_ff @(posedge sys.clk) begin
if (sys.reset || state != next_state) begin
wait_counter <= 14'd0;
end else begin
wait_counter <= wait_counter + 1'd1;
end
if (sdram_next_cmd == CMD_REF) begin
refresh_counter <= 10'd0;
end else if (refresh_counter < 10'h3FF) begin
refresh_counter <= refresh_counter + 1'd1;
end
end
always_comb begin
pending_refresh = refresh_counter >= C_REF;
end
logic [(CAS_LATENCY):0] read_cmd_ack_delay;
always_ff @(posedge sys.clk) begin
ack <= 1'b0;
read_cmd_ack_delay <= {sdram_next_cmd == CMD_READ, read_cmd_ack_delay[(CAS_LATENCY):1]};
if (sdram_next_cmd == CMD_WRITE || read_cmd_ack_delay[0]) begin
ack <= 1'b1;
end
end
always_comb begin
sdram_next_cmd = CMD_NOP;
next_state = state;
case (state)
S_INIT: begin
if (wait_counter < INIT_PRECHARGE) begin
sdram_next_cmd = CMD_DESL;
end
if (wait_counter == INIT_PRECHARGE) begin
sdram_next_cmd = CMD_PRE;
end
if (wait_counter == INIT_REFRESH_1 || wait_counter == INIT_REFRESH_2) begin
sdram_next_cmd = CMD_REF;
end
if (wait_counter == INIT_MODE_REG) begin
sdram_next_cmd = CMD_MRS;
end
if (wait_counter == INIT_DONE) begin
next_state = S_IDLE;
end
end
S_IDLE: begin
if (pending_refresh) begin
next_state = S_REFRESH;
sdram_next_cmd = CMD_REF;
end else if (request) begin
next_state = S_ACTIVATING;
sdram_next_cmd = CMD_ACT;
end
end
S_ACTIVATING: begin
if (wait_counter == C_RCD) begin
next_state = S_ACTIVE;
end
end
S_ACTIVE: begin
if (pending_refresh) begin
next_state = S_PRECHARGE;
sdram_next_cmd = CMD_PRE;
end else if (request) begin
if (request_in_current_active_bank_row) begin
next_state = S_BUSY;
sdram_next_cmd = write ? CMD_WRITE : CMD_READ;
end else begin
next_state = S_PRECHARGE;
sdram_next_cmd = CMD_PRE;
end
end
end
S_BUSY: begin
if (ack) begin
next_state = S_ACTIVE;
end
end
S_PRECHARGE: begin
if (wait_counter == C_RP) begin
if (pending_refresh) begin
next_state = S_REFRESH;
sdram_next_cmd = CMD_REF;
end else begin
next_state = S_IDLE;
end
end
end
S_REFRESH: begin
if (wait_counter == C_RC) begin
next_state = S_IDLE;
end
end
default: begin
next_state = S_IDLE;
end
endcase
end
endmodule

View File

@ -1,371 +0,0 @@
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 reg [1:0] o_sdram_ba,
output reg [12:0] o_sdram_a,
inout reg [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 = 100_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 <= 16'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 <= 10'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 <= 10'd0;
r_rcd_ras_rc_counter <= 5'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 <= 5'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 <= 5'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 <= 2'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 <= 3'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 <= 2'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 <= 3'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 <= 3'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 <= 2'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 <= 3'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

View File

@ -1,81 +0,0 @@
`include "../constants.vh"
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,
output o_sram_request,
input i_ddipl_enable,
input i_sram_enable,
input i_sram_768k_mode,
input i_flashram_enable,
input i_sd_enable,
input i_eeprom_enable,
input [23:0] i_ddipl_address,
input [23:0] i_sram_address
);
localparam [31:0] DDIPL_BASE = 32'h0600_0000;
localparam [31:0] DDIPL_END = 32'h063F_FFFF;
localparam [31:0] SRAM_BASE = 32'h0800_0000;
localparam [31:0] SRAM_END = 32'h0800_7FFF;
localparam [31:0] SRAM_768K_END = 32'h0801_7FFF;
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'h1E00_3FFF;
localparam [31:0] EEPROM_BASE = 32'h1E00_4000;
localparam [31:0] EEPROM_END = 32'h1E00_47FF;
localparam [31:0] SD_BASE = 32'h1E00_8000;
localparam [31:0] SD_END = 32'h1E00_83FF;
wire [25:0] w_ddipl_translated_address = i_address[25:0] + {i_ddipl_address, 2'd0};
wire [25:0] w_sram_translated_address = i_address[25:0] + {i_sram_address, 2'd0};
always @(*) begin
o_bank = `BANK_INVALID;
o_bank_prefetch = 1'b0;
o_translated_address = i_address[25:0];
o_sram_request = 1'b0;
if ((i_address >= DDIPL_BASE) && (i_address <= DDIPL_END) && i_ddipl_enable) begin
o_translated_address = w_ddipl_translated_address;
o_bank = `BANK_SDRAM;
o_bank_prefetch = 1'b1;
end
if ((i_address >= SRAM_BASE) && ((i_address <= SRAM_END) || ((i_sram_768k_mode && (i_address <= SRAM_768K_END))))) begin
if (i_sram_enable && !i_flashram_enable) begin
o_translated_address = w_sram_translated_address;
o_bank = `BANK_SDRAM;
o_bank_prefetch = 1'b1;
o_sram_request = 1'b1;
end
end
if ((i_address >= ROM_BASE) && (i_address <= ROM_END)) begin
o_bank = `BANK_SDRAM;
o_bank_prefetch = 1'b1;
end
if ((i_address >= CART_BASE) && (i_address <= CART_END)) begin
o_bank = `BANK_CART;
end
if ((i_address >= EEPROM_BASE) && (i_address <= EEPROM_END) && i_eeprom_enable) begin
o_bank = `BANK_EEPROM;
o_bank_prefetch = 1'b1;
end
if ((i_address >= SD_BASE) && (i_address <= SD_END) && i_sd_enable) begin
o_bank = `BANK_SD;
end
end
endmodule

View File

@ -0,0 +1,14 @@
module n64_bootloader (
if_system.sys sys,
if_n64_bus bus
);
memory_flash memory_flash_inst (
.sys(sys),
.request(bus.request),
.ack(bus.ack),
.address(bus.address),
.rdata(bus.rdata)
);
endmodule

56
fw/rtl/n64/n64_bus.sv Normal file
View File

@ -0,0 +1,56 @@
interface if_n64_bus ();
localparam sc64::e_n64_id NUM_DEVICES = sc64::__ID_N64_END;
sc64::e_n64_id id;
logic request;
logic ack;
logic write;
logic [31:0] address;
logic [15:0] wdata;
logic [15:0] rdata;
logic device_ack [(NUM_DEVICES - 1):0];
logic [15:0] device_rdata [(NUM_DEVICES - 1):0];
always_comb begin
ack = 1'b0;
rdata = 16'd0;
for (integer i = 0; i < NUM_DEVICES; i++) begin
ack = ack | device_ack[i];
rdata = rdata | device_rdata[i];
end
end
modport n64 (
output id,
output request,
input ack,
output write,
output address,
output wdata,
input rdata
);
genvar n;
generate
for (n = 0; n < NUM_DEVICES; n++) begin : at
logic device_request;
always_comb begin
device_request = request && id == sc64::e_n64_id'(n);
end
modport device (
input .request(device_request),
output .ack(device_ack[n]),
input .write(write),
input .address(address),
input .wdata(wdata),
output .rdata(device_rdata[n])
);
end
endgenerate
endinterface

84
fw/rtl/n64/n64_cfg.sv Normal file
View File

@ -0,0 +1,84 @@
module n64_cfg (
if_system sys,
if_n64_bus bus,
if_config.n64 cfg
);
typedef enum bit [3:0] {
R_SR,
R_COMMAND,
R_DATA_0_H,
R_DATA_0_L,
R_DATA_1_H,
R_DATA_1_L,
R_VERSION_H,
R_VERSION_L
} e_reg_id;
typedef enum bit [0:0] {
S_IDLE,
S_WAIT
} e_state;
e_state state;
always_comb begin
bus.rdata = 16'd0;
if (bus.ack) begin
case (bus.address[3:1])
R_SR: bus.rdata = {
cfg.cpu_ready,
cfg.cpu_busy,
cfg.usb_waiting,
cfg.cmd_error,
12'd0
};
R_COMMAND: bus.rdata = {8'd0, cfg.cmd};
R_DATA_0_H: bus.rdata = cfg.data[0][31:16];
R_DATA_0_L: bus.rdata = cfg.data[0][15:0];
R_DATA_1_H: bus.rdata = cfg.data[1][31:16];
R_DATA_1_L: bus.rdata = cfg.data[1][15:0];
R_VERSION_H: bus.rdata = sc64::SC64_VER[31:16];
R_VERSION_L: bus.rdata = sc64::SC64_VER[15:0];
endcase
end
end
always_ff @(posedge sys.clk) begin
bus.ack <= 1'b0;
cfg.cmd_request <= 1'b0;
if (cfg.data_write[0]) cfg.data[0] <= cfg.wdata;
if (cfg.data_write[1]) cfg.data[1] <= cfg.wdata;
if (sys.reset) begin
state <= S_IDLE;
end else begin
case (state)
S_IDLE: begin
if (bus.request) begin
state <= S_WAIT;
bus.ack <= 1'b1;
if (bus.write) begin
case (bus.address[3:1])
R_COMMAND: begin
cfg.cmd <= bus.wdata[7:0];
cfg.cmd_request <= 1'b1;
end
R_DATA_0_H: cfg.data[0][31:16] <= bus.wdata;
R_DATA_0_L: cfg.data[0][15:0] <= bus.wdata;
R_DATA_1_H: cfg.data[1][31:16] <= bus.wdata;
R_DATA_1_L: cfg.data[1][15:0] <= bus.wdata;
endcase
end
end
end
S_WAIT: begin
state <= S_IDLE;
end
endcase
end
end
endmodule

83
fw/rtl/n64/n64_dd.sv Normal file
View File

@ -0,0 +1,83 @@
interface if_dd();
logic hard_reset;
logic cmd_request;
logic cmd_ack;
logic [7:0] command;
logic [15:0] status;
logic [15:0] data_input;
logic [15:0] data_output;
logic bm_request;
logic [15:0] bm_control;
logic [15:0] bm_status;
modport n64 (
output hard_reset,
output cmd_request,
input cmd_ack,
output command,
input status,
output data_input,
input data_output,
output bm_request,
output bm_control,
input bm_status
);
modport cpu (
input hard_reset,
input cmd_request,
output cmd_ack,
input command,
output status,
input data_input,
output data_output,
input bm_request,
input bm_control,
output bm_status
);
endinterface
module n64_dd (
if_system.sys sys,
if_n64_bus bus
);
typedef enum bit [0:0] {
S_IDLE,
S_WAIT
} e_state;
e_state state;
always_comb begin
bus.rdata = 16'h0000;
if (bus.ack) begin
bus.rdata = !bus.address[1] ? 16'h0040 : 16'h0000;
end
end
always_ff @(posedge sys.clk) begin
bus.ack <= 1'b0;
if (sys.reset) begin
state <= S_IDLE;
end else begin
case (state)
S_IDLE: begin
if (bus.request) begin
state <= S_WAIT;
bus.ack <= 1'b1;
end
end
S_WAIT: begin
state <= S_IDLE;
end
endcase
end
end
endmodule

190
fw/rtl/n64/n64_flashram.sv Normal file
View File

@ -0,0 +1,190 @@
module n64_flashram (
if_system.sys sys,
if_n64_bus bus,
if_config.flashram cfg,
if_flashram.flashram flashram
);
localparam [31:0] FLASH_TYPE_ID = 32'h1111_8001;
localparam [31:0] FLASH_MODEL_ID = 32'h00C2_001D;
typedef enum bit [7:0] {
CMD_STATUS_MODE = 8'hD2,
CMD_READID_MODE = 8'hE1,
CMD_READ_MODE = 8'hF0,
CMD_ERASE_SECTOR = 8'h4B,
CMD_ERASE_CHIP = 8'h3C,
CMD_BUFFER_MODE = 8'hB4,
CMD_ERASE_START = 8'h78,
CMD_WRITE_START = 8'hA5
} e_cmd;
typedef enum bit [0:0] {
S_IDLE,
S_WAIT
} e_bus_state;
typedef enum bit [1:0] {
FS_STATUS,
FS_ID,
FS_READ,
FS_BUFFER
} e_flashram_state;
typedef enum bit [1:0] {
B_WRITE_BUSY,
B_ERASE_BUSY,
B_WRITE_DONE,
B_ERASE_DONE
} e_flashram_status;
e_bus_state bus_state;
e_flashram_state flashram_state;
logic [3:0] flashram_status;
logic [7:0] flashram_command;
logic flashram_erase_enabled;
logic [31:0] write_buffer [0:31];
logic [1:0] write_buffer_wmask;
logic [15:0] high_buffer;
always_comb begin
write_buffer_wmask = 2'b00;
if (bus.request && bus.write && !bus.address[16] && flashram_state == FS_BUFFER) begin
write_buffer_wmask[0] = !bus.address[1];
write_buffer_wmask[1] = bus.address[1];
end
end
always_ff @(posedge sys.clk) begin
if (write_buffer_wmask[0]) high_buffer <= bus.wdata;
end
always_ff @(posedge sys.clk) begin
flashram.rdata <= write_buffer[flashram.address];
if (write_buffer_wmask[1]) write_buffer[bus.address[6:2]] <= {high_buffer, bus.wdata};
end
always_comb begin
bus.rdata = 16'd0;
if (bus.ack) begin
if (bus.address[1]) begin
bus.rdata = {12'd0, flashram_status};
end
if (flashram_state == FS_ID) begin
case (bus.address[2:1])
0: bus.rdata = FLASH_TYPE_ID[31:16];
1: bus.rdata = FLASH_TYPE_ID[15:0];
2: bus.rdata = FLASH_MODEL_ID[31:16];
3: bus.rdata = FLASH_MODEL_ID[15:0];
endcase
end
end
cfg.flashram_read_mode = flashram_state == FS_READ;
end
always_ff @(posedge sys.clk) begin
bus.ack <= 1'b0;
if (sys.reset) begin
bus_state <= S_IDLE;
flashram_state <= FS_STATUS;
flashram_status <= 4'b0000;
flashram_erase_enabled <= 1'b0;
flashram.operation_pending <= 1'b0;
end else begin
if (flashram.operation_done) begin
flashram.operation_pending <= 1'b0;
if (flashram.write_or_erase) begin
flashram_status[B_ERASE_BUSY] <= 1'b0;
flashram_status[B_ERASE_DONE] <= 1'b1;
end else begin
flashram_status[B_WRITE_BUSY] <= 1'b0;
flashram_status[B_WRITE_DONE] <= 1'b1;
end
end
case (bus_state)
S_IDLE: begin
if (bus.request) begin
bus_state <= S_WAIT;
bus.ack <= 1'b1;
if (bus.write && !flashram.operation_pending) begin
if (bus.address[16]) begin
if (!bus.address[1]) begin
flashram_command <= bus.wdata[15:8];
end else begin
flashram_erase_enabled <= 1'b0;
case (flashram_command)
CMD_STATUS_MODE: begin
flashram_state <= FS_STATUS;
end
CMD_READID_MODE: begin
flashram_state <= FS_ID;
end
CMD_READ_MODE: begin
flashram_state <= FS_READ;
end
CMD_ERASE_SECTOR: begin
flashram_state <= FS_STATUS;
flashram_erase_enabled <= 1'b1;
flashram.sector <= bus.wdata[9:0];
flashram.sector_or_all <= 1'b0;
end
CMD_ERASE_CHIP: begin
flashram_state <= FS_STATUS;
flashram_erase_enabled <= 1'b1;
flashram.sector <= 10'd0;
flashram.sector_or_all <= 1'b1;
end
CMD_BUFFER_MODE: begin
flashram_state <= FS_BUFFER;
end
CMD_ERASE_START: begin
flashram_state <= FS_STATUS;
if (flashram_erase_enabled) begin
flashram_status[B_ERASE_BUSY] <= 1'b1;
flashram_status[B_ERASE_DONE] <= 1'b0;
flashram.operation_pending <= 1'b1;
flashram.write_or_erase <= 1'b1;
end
end
CMD_WRITE_START: begin
flashram_state <= FS_STATUS;
flashram_status[B_WRITE_BUSY] <= 1'b1;
flashram_status[B_WRITE_DONE] <= 1'b0;
flashram.sector <= bus.wdata[9:0];
flashram.operation_pending <= 1'b1;
flashram.write_or_erase <= 1'b0;
flashram.sector_or_all <= 1'b0;
end
endcase
end
end
// else begin
// if (bus.address[1] && flashram_state == FS_STATUS) begin
// flashram_status[B_ERASE_DONE] <= bus.wdata[B_ERASE_DONE];
// flashram_status[B_WRITE_DONE] <= bus.wdata[B_WRITE_DONE];
// end
// end
end
end
end
S_WAIT: begin
bus_state <= S_IDLE;
end
endcase
end
end
endmodule

347
fw/rtl/n64/n64_pi.sv Normal file
View File

@ -0,0 +1,347 @@
module n64_pi (
if_system.sys sys,
if_config.pi cfg,
if_n64_bus.n64 bus,
input n64_pi_alel,
input n64_pi_aleh,
input n64_pi_read,
input n64_pi_write,
inout [15:0] n64_pi_ad
);
// FIFOs
logic read_fifo_flush;
logic read_fifo_full;
logic read_fifo_write;
logic [15:0] read_fifo_wdata;
logic read_fifo_empty;
logic read_fifo_read;
logic [15:0] read_fifo_rdata;
n64_pi_fifo read_fifo_inst (
.sys(sys),
.flush(read_fifo_flush),
.full(read_fifo_full),
.write(read_fifo_write),
.wdata(read_fifo_wdata),
.empty(read_fifo_empty),
.read(read_fifo_read),
.rdata(read_fifo_rdata)
);
logic write_fifo_flush;
logic write_fifo_full;
logic write_fifo_write;
logic [15:0] write_fifo_wdata;
logic write_fifo_empty;
logic write_fifo_read;
logic [15:0] write_fifo_rdata;
n64_pi_fifo write_fifo_inst (
.sys(sys),
.flush(write_fifo_flush),
.full(write_fifo_full),
.write(write_fifo_write),
.wdata(write_fifo_wdata),
.empty(write_fifo_empty),
.read(write_fifo_read),
.rdata(write_fifo_rdata)
);
// Control signals and input synchronization
logic [2:0] n64_pi_alel_ff;
logic [2:0] n64_pi_aleh_ff;
logic [2:0] n64_pi_read_ff;
logic [2:0] n64_pi_write_ff;
always_ff @(posedge sys.clk) begin
n64_pi_aleh_ff <= {n64_pi_aleh_ff[1:0], n64_pi_aleh};
n64_pi_alel_ff <= {n64_pi_alel_ff[1:0], n64_pi_alel};
n64_pi_read_ff <= {n64_pi_read_ff[1:0], n64_pi_read};
n64_pi_write_ff <= {n64_pi_write_ff[1:0], n64_pi_write};
end
logic pi_reset;
logic pi_aleh;
logic pi_alel;
logic pi_read;
logic pi_write;
always_comb begin
pi_reset = sys.n64_hard_reset;
pi_aleh = n64_pi_aleh_ff[2];
pi_alel = n64_pi_alel_ff[2];
pi_read = n64_pi_read_ff[1];
pi_write = n64_pi_write_ff[2];
end
// PI bus state and event generator
typedef enum bit [1:0] {
PI_MODE_IDLE = 2'b10,
PI_MODE_HIGH = 2'b11,
PI_MODE_LOW = 2'b01,
PI_MODE_VALID = 2'b00
} e_pi_mode;
e_pi_mode pi_mode;
e_pi_mode last_pi_mode;
logic last_read;
logic last_write;
always_comb begin
pi_mode = e_pi_mode'({pi_aleh, pi_alel});
end
always_ff @(posedge sys.clk) begin
last_pi_mode <= pi_mode;
last_read <= pi_read;
last_write <= pi_write;
end
logic aleh_op;
logic alel_op;
logic read_op;
logic write_op;
logic end_op;
always_comb begin
aleh_op = !pi_reset && last_pi_mode != PI_MODE_HIGH && pi_mode == PI_MODE_HIGH;
alel_op = !pi_reset && last_pi_mode == PI_MODE_HIGH && pi_mode == PI_MODE_LOW;
read_op = !pi_reset && pi_mode == PI_MODE_VALID && last_read && !pi_read;
write_op = !pi_reset && pi_mode == PI_MODE_VALID && last_write && !pi_write;
end_op = !pi_reset && last_pi_mode == PI_MODE_VALID && pi_mode != PI_MODE_VALID;
end
// Input and output data sampling
logic [15:0] n64_pi_ad_input;
logic [15:0] n64_pi_ad_output;
logic [15:0] n64_pi_ad_output_data;
logic n64_pi_ad_output_enable;
logic n64_pi_ad_output_enable_data;
logic n64_pi_address_valid;
logic pending_operation;
logic pending_write;
always_comb begin
n64_pi_ad = n64_pi_ad_output_enable ? n64_pi_ad_output : 16'hZZZZ;
n64_pi_ad_output_enable_data = !pi_reset && pi_mode == PI_MODE_VALID && n64_pi_address_valid && !n64_pi_read_ff[2];
end
always_ff @(posedge sys.clk) begin
n64_pi_ad_input <= n64_pi_ad;
n64_pi_ad_output <= n64_pi_ad_output_data;
n64_pi_ad_output_enable <= n64_pi_ad_output_enable_data;
end
logic wait_for_read_fifo;
logic wait_for_write_fifo;
always_comb begin
read_fifo_write = bus.ack && !bus.write;
read_fifo_wdata = bus.rdata;
write_fifo_wdata = n64_pi_ad_input;
end
always_ff @(posedge sys.clk) begin
read_fifo_read <= 1'b0;
write_fifo_write <= 1'b0;
if (sys.reset || sys.n64_hard_reset) begin
wait_for_read_fifo <= 1'b0;
wait_for_write_fifo <= 1'b0;
end else if (n64_pi_address_valid) begin
if (read_op || wait_for_read_fifo) begin
if (read_fifo_empty) begin
wait_for_read_fifo <= 1'b1;
end else begin
n64_pi_ad_output_data <= read_fifo_rdata;
read_fifo_read <= 1'b1;
wait_for_read_fifo <= 1'b0;
end
end
if (write_op || wait_for_write_fifo) begin
if (write_fifo_full) begin
wait_for_write_fifo <= 1'b1;
end else begin
write_fifo_write <= 1'b1;
wait_for_write_fifo <= 1'b0;
end
end
end
end
// Address decoding
sc64::e_n64_id next_id;
logic [31:0] next_offset;
logic sram_selected;
logic cfg_selected;
always_ff @(posedge sys.clk) begin
if (aleh_op) begin
n64_pi_address_valid <= 1'b0;
next_offset <= 32'd0;
sram_selected <= 1'b0;
cfg_selected <= 1'b0;
if (cfg.dd_enabled) begin
if (n64_pi_ad_input == 16'h0500) begin
n64_pi_address_valid <= 1'b1;
next_id <= sc64::ID_N64_DD;
end
if (n64_pi_ad_input >= 16'h0600 && n64_pi_ad_input < 16'h0640) begin
n64_pi_address_valid <= 1'b1;
next_id <= sc64::ID_N64_SDRAM;
next_offset <= cfg.dd_offset + 32'h0A00_0000;
end
end
if (cfg.flashram_enabled) begin
if (n64_pi_ad_input >= 16'h0800 && n64_pi_ad_input < 16'h0802) begin
n64_pi_address_valid <= 1'b1;
next_id <= sc64::ID_N64_FLASHRAM;
if (cfg.flashram_read_mode) begin
next_offset <= cfg.save_offset + 32'h0800_0000;
end
end
end else if (cfg.sram_enabled) begin
if (cfg.sram_banked) begin
if (n64_pi_ad_input >= 16'h0800 && n64_pi_ad_input < 16'h0810) begin
if (n64_pi_ad_input[3:2] != 2'b11 && n64_pi_ad_input[1:0] == 2'b00) begin
n64_pi_address_valid <= 1'b1;
next_id <= sc64::ID_N64_SDRAM;
next_offset <= cfg.save_offset - {n64_pi_ad_input[3:2], 18'd0} + {n64_pi_ad_input[3:2], 15'd0} + 32'h0800_0000;
sram_selected <= 1'b1;
end
end
end else begin
if (n64_pi_ad_input == 16'h0800) begin
n64_pi_address_valid <= 1'b1;
next_id <= sc64::ID_N64_SDRAM;
next_offset <= cfg.save_offset + 32'h0800_0000;
sram_selected <= 1'b1;
end
end
end
if (n64_pi_ad_input >= 16'h1000 && n64_pi_ad_input < 16'h1400) begin
n64_pi_address_valid <= 1'b1;
next_id <= cfg.sdram_switch ? sc64::ID_N64_SDRAM : sc64::ID_N64_BOOTLOADER;
end
if (n64_pi_ad_input == 16'h1FFF) begin
n64_pi_address_valid <= 1'b1;
next_id <= sc64::ID_N64_CFG;
cfg_selected <= 1'b1;
end
end
if (alel_op) begin
if (sram_selected) begin
if (n64_pi_ad_input[15]) begin
n64_pi_address_valid <= 1'b0;
end
end
if (cfg_selected) begin
if (|n64_pi_ad_input[15:4]) begin
n64_pi_address_valid <= 1'b0;
end
end
end
end
// Bus controller
logic can_read;
logic first_write_op;
logic load_starting_address;
sc64::e_n64_id starting_id;
logic [31:0] starting_address;
always_ff @(posedge sys.clk) begin
read_fifo_flush <= 1'b0;
write_fifo_read <= 1'b0;
if (sys.reset || sys.n64_hard_reset) begin
bus.request <= 1'b0;
read_fifo_flush <= 1'b1;
write_fifo_flush <= 1'b1;
end else begin
write_fifo_flush <= starting_id == sc64::ID_N64_SDRAM && !cfg.sdram_writable && !sram_selected;
if (aleh_op) begin
starting_address[31:16] <= n64_pi_ad_input;
end
if (alel_op) begin
read_fifo_flush <= 1'b1;
can_read <= 1'b1;
first_write_op <= 1'b1;
load_starting_address <= 1'b1;
starting_id <= next_id;
starting_address <= {starting_address[31:16], n64_pi_ad_input[15:1], 1'b0} + next_offset;
end
if (write_op) begin
can_read <= 1'b0;
if (first_write_op) begin
first_write_op <= 1'b0;
load_starting_address <= 1'b1;
end
end
if (!bus.request) begin
if (!write_fifo_empty) begin
bus.request <= 1'b1;
bus.write <= 1'b1;
if (load_starting_address) begin
bus.id <= starting_id;
bus.address <= starting_address;
load_starting_address <= 1'b0;
end
bus.wdata <= write_fifo_rdata;
write_fifo_read <= 1'b1;
end else if (!read_fifo_full && can_read) begin
bus.request <= 1'b1;
bus.write <= 1'b0;
if (load_starting_address) begin
bus.id <= starting_id;
if (starting_id == sc64::ID_N64_FLASHRAM && cfg.flashram_read_mode) begin
bus.id <= sc64::ID_N64_SDRAM;
end
bus.address <= starting_address;
load_starting_address <= 1'b0;
end
end
end else begin
if (bus.ack) begin
bus.request <= 1'b0;
bus.address <= bus.address + 2'd2;
end
end
if (end_op) begin
can_read <= 1'b0;
end
end
end
endmodule

View File

@ -1,230 +0,0 @@
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 reg [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,
output o_sram_request,
input i_ddipl_enable,
input i_sram_enable,
input i_sram_768k_mode,
input i_flashram_enable,
input i_sd_enable,
input i_eeprom_enable,
input [23:0] i_ddipl_address,
input [23:0] i_sram_address
);
// 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),
.o_sram_request(o_sram_request),
.i_ddipl_enable(i_ddipl_enable),
.i_sram_enable(i_sram_enable),
.i_sram_768k_mode(i_sram_768k_mode),
.i_flashram_enable(i_flashram_enable),
.i_sd_enable(i_sd_enable),
.i_eeprom_enable(i_eeprom_enable),
.i_ddipl_address(i_ddipl_address),
.i_sram_address(i_sram_address)
);
// 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;
reg r_prefetch_read;
always @(posedge i_clk) begin
if (w_address_valid_op) begin
r_prefetch_read <= w_prefetch;
end
if (i_ack) begin
if (w_prefetch) r_pi_read_buffer <= i_data;
else r_pi_output_data <= i_data;
if (r_prefetch_read) r_pi_output_data <= i_data;
r_prefetch_read <= 1'b0;
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
reg r_pending_request;
reg r_pending_request_write;
wire w_bus_request_op = (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;
r_pending_request <= 1'b0;
end else begin
if (o_request && !i_busy) begin
o_request <= 1'b0;
o_write <= 1'b0;
end
if (w_bus_request_op) begin
if (o_request) begin
r_pending_request <= 1'b1;
r_pending_request_write <= w_bus_write_op;
end else begin
o_request <= 1'b1;
o_write <= w_bus_write_op;
end
end
if (r_pending_request && !i_busy) begin
o_request <= 1'b1;
o_write <= r_pending_request_write;
r_pending_request <= 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[15:2] <= o_address[15:2] + 1'b1;
end
endmodule

43
fw/rtl/n64/n64_pi_fifo.sv Normal file
View File

@ -0,0 +1,43 @@
module n64_pi_fifo (
if_system.sys sys,
input flush,
output full,
input write,
input [15:0] wdata,
output empty,
input read,
output [15:0] rdata
);
logic [15:0] fifo_mem [0:3];
logic [2:0] fifo_wr_ptr;
logic [2:0] fifo_rd_ptr;
logic empty_or_full;
always_comb begin
rdata = fifo_mem[fifo_rd_ptr[1:0]];
empty_or_full = fifo_wr_ptr[1:0] == fifo_rd_ptr[1:0];
empty = empty_or_full && fifo_wr_ptr[2] == fifo_rd_ptr[2];
full = empty_or_full && fifo_wr_ptr[2] != fifo_rd_ptr[2];
end
always_ff @(posedge sys.clk) begin
if (sys.reset || flush) begin
fifo_wr_ptr <= 3'd0;
fifo_rd_ptr <= 3'd0;
end else begin
if (write) begin
fifo_mem[fifo_wr_ptr[1:0]] <= wdata;
fifo_wr_ptr <= fifo_wr_ptr + 1'd1;
end
if (read) begin
fifo_rd_ptr <= fifo_rd_ptr + 1'd1;
end
end
end
endmodule

106
fw/rtl/n64/n64_sdram.sv Normal file
View File

@ -0,0 +1,106 @@
module n64_sdram (
if_system sys,
if_n64_bus bus,
if_dma.memory dma,
if_sdram.memory sdram,
output sdram_cs,
output sdram_ras,
output sdram_cas,
output sdram_we,
output [1:0] sdram_ba,
output [12:0] sdram_a,
inout [15:0] sdram_dq
);
logic mem_request;
logic mem_ack;
logic mem_write;
logic [31:0] mem_address;
logic [15:0] mem_rdata;
logic [15:0] mem_wdata;
typedef enum bit [0:0] {
S_IDLE,
S_WAIT
} e_state;
typedef enum bit [1:0] {
T_BUS,
T_DMA,
T_SDRAM
} e_source_request;
e_state state;
e_source_request source_request;
always_ff @(posedge sys.clk) begin
if (sys.reset) begin
state <= S_IDLE;
mem_request <= 1'b0;
end else begin
case (state)
S_IDLE: begin
if (bus.request || sdram.request || dma.request) begin
state <= S_WAIT;
mem_request <= 1'b1;
if (bus.request) begin
mem_write <= bus.write;
mem_address <= bus.address;
mem_wdata <= bus.wdata;
source_request <= T_BUS;
end else if (sdram.request) begin
mem_write <= sdram.write;
mem_address <= sdram.address;
mem_wdata <= sdram.wdata;
source_request <= T_SDRAM;
end else if (dma.request) begin
mem_write <= dma.write;
mem_address <= dma.address;
mem_wdata <= dma.wdata;
source_request <= T_DMA;
end
end
end
S_WAIT: begin
if (mem_ack) begin
state <= S_IDLE;
mem_request <= 1'b0;
end
end
endcase
end
end
always_comb begin
bus.ack = source_request == T_BUS && mem_ack;
bus.rdata = bus.ack ? mem_rdata : 16'd0;
dma.ack = source_request == T_DMA && mem_ack;
dma.rdata = mem_rdata;
sdram.ack = source_request == T_SDRAM && mem_ack;
sdram.rdata = mem_rdata;
end
memory_sdram memory_sdram_inst (
.sys(sys),
.request(mem_request),
.ack(mem_ack),
.write(mem_write),
.address(mem_address[25:0]),
.rdata(mem_rdata),
.wdata(mem_wdata),
.sdram_cs(sdram_cs),
.sdram_ras(sdram_ras),
.sdram_cas(sdram_cas),
.sdram_we(sdram_we),
.sdram_ba(sdram_ba),
.sdram_a(sdram_a),
.sdram_dq(sdram_dq)
);
endmodule

224
fw/rtl/n64/n64_si.sv Normal file
View File

@ -0,0 +1,224 @@
interface if_si ();
logic rx_reset;
logic rx_ready;
logic [6:0] rx_length;
logic [80:0] rx_data;
logic tx_reset;
logic tx_start;
logic tx_busy;
logic [2:0] tx_wmask;
logic [6:0] tx_length;
logic [31:0] tx_data;
modport si (
input rx_reset,
output rx_ready,
output rx_length,
output rx_data,
input tx_reset,
input tx_start,
output tx_busy,
input tx_wmask,
input tx_length,
input tx_data
);
modport cpu (
output rx_reset,
input rx_ready,
input rx_length,
input rx_data,
output tx_reset,
output tx_start,
input tx_busy,
output tx_wmask,
output tx_length,
output tx_data
);
endinterface
module n64_si (
if_system.sys sys,
if_si.si si,
input n64_si_clk,
inout n64_si_dq
);
// Control signals and input synchronization
logic [1:0] n64_si_clk_ff;
always_ff @(posedge sys.clk) begin
n64_si_clk_ff <= {n64_si_clk_ff[0], n64_si_clk};
end
logic si_reset;
logic si_clk;
logic si_dq;
always_comb begin
si_reset = sys.n64_hard_reset;
si_clk = n64_si_clk_ff[1];
si_dq = n64_si_dq;
end
logic last_si_clk;
always_ff @(posedge sys.clk) begin
last_si_clk <= si_clk;
end
logic si_clk_rising_edge;
logic si_clk_falling_edge;
always_comb begin
si_clk_rising_edge = !si_reset && !last_si_clk && si_clk;
si_clk_falling_edge = !si_reset && last_si_clk && !si_clk;
end
logic si_dq_output_enable;
logic si_dq_output_enable_data;
always_ff @(posedge sys.clk) begin
si_dq_output_enable <= si_dq_output_enable_data;
end
always_comb begin
n64_si_dq = si_dq_output_enable ? 1'b0 : 1'bZ;
end
// Data register and shifter
logic [80:0] trx_data;
logic rx_shift;
logic tx_shift;
always_comb begin
si.rx_data = trx_data;
end
always_ff @(posedge sys.clk) begin
if (si.tx_wmask[0]) trx_data[80:49] <= si.tx_data;
if (si.tx_wmask[1]) trx_data[48:17] <= si.tx_data;
if (si.tx_wmask[2]) trx_data[16:0] <= si.tx_data[16:0];
if (rx_shift || tx_shift) begin
trx_data <= {trx_data[79:0], rx_sub_bit_counter < 2'd2};
end
end
// RX path
typedef enum bit [0:0] {
S_RX_IDLE,
S_RX_WAITING
} e_rx_state;
e_rx_state rx_state;
logic [1:0] rx_sub_bit_counter;
logic [3:0] rx_timeout_counter;
always_ff @(posedge sys.clk) begin
rx_shift <= 1'b0;
if (si_clk_rising_edge) begin
if (rx_timeout_counter < 4'd8) begin
rx_timeout_counter <= rx_timeout_counter + 1'd1;
end else if (si.rx_length > 7'd0) begin
si.rx_ready <= 1'b1;
end
end
if (sys.reset || si.rx_reset) begin
rx_state <= S_RX_IDLE;
si.rx_ready <= 1'b0;
si.rx_length <= 7'd0;
end else if (!si.tx_busy) begin
case (rx_state)
S_RX_IDLE: begin
if (si_clk_rising_edge && !si_dq) begin
rx_state <= S_RX_WAITING;
rx_sub_bit_counter <= 2'd0;
rx_timeout_counter <= 3'd0;
end
end
S_RX_WAITING: begin
if (si_clk_rising_edge) begin
if (si_dq) begin
rx_state <= S_RX_IDLE;
rx_shift <= 1'b1;
si.rx_length <= si.rx_length + 1'd1;
end else if (rx_sub_bit_counter < 2'd3) begin
rx_sub_bit_counter <= rx_sub_bit_counter + 1'd1;
end
end
end
endcase
end
end
// TX path
typedef enum bit [0:0] {
S_TX_IDLE,
S_TX_SENDING
} e_tx_state;
e_tx_state tx_state;
logic [2:0] tx_sub_bit_counter;
logic [6:0] tx_bit_counter;
always_ff @(posedge sys.clk) begin
tx_shift <= 1'b0;
if (sys.reset || si.tx_reset) begin
tx_state <= S_TX_IDLE;
si_dq_output_enable_data <= 1'b0;
si.tx_busy <= 1'b0;
end else begin
case (tx_state)
S_TX_IDLE: begin
if (si.tx_start) begin
tx_state <= S_TX_SENDING;
tx_sub_bit_counter <= 3'd0;
tx_bit_counter <= si.tx_length;
si.tx_busy <= 1'b1;
end
end
S_TX_SENDING: begin
if (si_clk_falling_edge) begin
tx_sub_bit_counter <= tx_sub_bit_counter + 1'd1;
if (tx_sub_bit_counter == 3'd7) begin
tx_shift <= 1'b1;
if (tx_bit_counter >= 7'd1) begin
tx_bit_counter <= tx_bit_counter - 1'd1;
end else begin
tx_state <= S_TX_IDLE;
si.tx_busy <= 1'b0;
end
end
if (tx_bit_counter == 7'd0) begin
si_dq_output_enable_data <= tx_sub_bit_counter < 3'd4;
end else if (trx_data[80]) begin
si_dq_output_enable_data <= tx_sub_bit_counter < 3'd2;
end else begin
si_dq_output_enable_data <= tx_sub_bit_counter < 3'd6;
end
end
end
endcase
end
end
endmodule

View File

@ -1,237 +0,0 @@
module n64_si (
input i_clk,
input i_reset,
input i_n64_reset,
input i_n64_si_clk,
inout io_n64_si_dq,
input i_request,
input i_write,
output o_busy,
output reg o_ack,
input [8:0] i_address,
input [31:0] i_data,
output [31:0] o_data,
input i_eeprom_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;
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 && 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 <= 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;
reg [2:0] r_rx_sub_bit_counter;
reg [2:0] r_rx_bit_counter;
reg [3:0] r_rx_byte_counter;
reg [7:0] r_rx_buffer;
reg r_rx_byte_ready;
reg r_rx_finished, r_last_rx_finished;
wire w_rx_sub_bit_counter_timeout = &r_rx_sub_bit_counter;
wire w_rx_bit_value = r_rx_sub_bit_counter <= 3'd4;
wire w_rx_start = r_last_rx_finished && !r_rx_finished;
wire w_rx_finish = !r_last_rx_finished && r_rx_finished;
always @(posedge i_clk) begin
r_rx_byte_ready <= 1'b0;
r_last_rx_finished <= r_rx_finished;
if (r_rx_enabled && w_si_clk_rising_edge) begin
if (w_rx_sub_bit_counter_timeout) r_rx_finished <= 1'b1;
else r_rx_sub_bit_counter <= r_rx_sub_bit_counter + 3'd1;
if (w_si_dq_falling_edge) begin
r_rx_sub_bit_counter <= 3'd0;
if (r_rx_finished) begin
r_rx_bit_counter <= 3'd0;
r_rx_byte_counter <= 4'b1111;
end
r_rx_finished <= 1'b0;
end
if (w_si_dq_rising_edge) begin
r_rx_bit_counter <= r_rx_bit_counter + 3'd1;
r_rx_buffer <= {r_rx_buffer[6:0], w_rx_bit_value};
if (&r_rx_bit_counter) begin
r_rx_byte_counter <= r_rx_byte_counter + 4'd1;
r_rx_byte_ready <= 1'b1;
end
end
end
end
reg r_tx_finished;
reg r_cmd_eeprom_status;
reg r_cmd_eeprom_read;
reg r_cmd_eeprom_write;
wire w_cmd_valid = r_cmd_eeprom_status || r_cmd_eeprom_read || r_cmd_eeprom_write;
wire w_cmd_op = r_rx_byte_ready && r_rx_byte_counter == 4'd0;
always @(posedge i_clk) 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;
end else if (w_cmd_op) begin
if (i_eeprom_enable) begin
r_cmd_eeprom_status <= r_rx_buffer == CMD_EEPROM_STATUS;
r_cmd_eeprom_read <= r_rx_buffer == CMD_EEPROM_READ;
r_cmd_eeprom_write <= r_rx_buffer == CMD_EEPROM_WRITE;
end
end
end
reg r_eeprom_read_rq;
reg [10:0] r_eeprom_address;
wire w_eeprom_write_op = r_rx_byte_ready && r_rx_byte_counter >= 4'd2 && r_cmd_eeprom_write;
wire w_eeprom_address_op = r_rx_byte_ready && r_rx_byte_counter == 4'd1 && (r_cmd_eeprom_read || r_cmd_eeprom_write);
wire w_eeprom_address_next_op = r_eeprom_read_rq || w_eeprom_write_op;
always @(posedge i_clk) begin
if (w_eeprom_address_op) r_eeprom_address <= {r_rx_buffer, 3'b000};
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;
reg [2:0] r_tx_bit_counter;
reg [3:0] r_tx_byte_counter;
reg [3:0] r_tx_bytes_to_send;
reg [7:0] r_tx_data;
wire [7:0] w_eeprom_o_data;
wire w_tx_current_bit = r_tx_data[3'd7 - r_tx_bit_counter];
wire w_tx_stop_bit = r_tx_byte_counter == r_tx_bytes_to_send;
always @(*) begin
r_tx_data = 8'h00;
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 || !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;
end else begin
r_tx_finished <= 1'b0;
r_eeprom_read_rq <= 1'b0;
if (w_rx_finish && w_cmd_valid) begin
r_rx_enabled <= 1'b0;
r_tx_sub_bit_counter <= 3'd0;
r_tx_bit_counter <= 3'd0;
r_tx_byte_counter <= 4'd0;
r_tx_bytes_to_send <= 4'd0;
if (r_cmd_eeprom_status) r_tx_bytes_to_send <= 4'd3;
if (r_cmd_eeprom_read) r_tx_bytes_to_send <= 4'd8;
if (r_cmd_eeprom_write) r_tx_bytes_to_send <= 4'd1;
end
if (!r_rx_enabled) begin
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) 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
r_si_dq_o <= 1'b1;
end
if (&r_tx_sub_bit_counter) begin
if (w_tx_stop_bit) begin
r_rx_enabled <= 1'b1;
r_tx_finished <= 1'b1;
end
r_tx_bit_counter <= r_tx_bit_counter + 3'd1;
if (&r_tx_bit_counter) begin
r_eeprom_read_rq <= 1'b1;
r_tx_byte_counter <= r_tx_byte_counter + 4'd1;
end
end
end
end
end
end
// Block RAM
ram_n64_eeprom ram_n64_eeprom_inst (
.clock(i_clk),
.address_a(r_eeprom_address),
.data_a(r_rx_buffer),
.wren_a(w_eeprom_write_op),
.q_a(w_eeprom_o_data),
.address_b(i_address),
.data_b({i_data[7:0], i_data[15:8], i_data[23:16], i_data[31:24]}),
.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
assign o_busy = 1'b0;
always @(posedge i_clk) begin
o_ack <= !i_reset && i_request && !i_write;
end
endmodule

87
fw/rtl/n64/n64_soc.sv Normal file
View File

@ -0,0 +1,87 @@
module n64_soc (
if_system sys,
if_config cfg,
if_dma.memory dma,
if_sdram.memory sdram,
if_flashram.flashram flashram,
if_si.si si,
input n64_pi_alel,
input n64_pi_aleh,
input n64_pi_read,
input n64_pi_write,
inout [15:0] n64_pi_ad,
input n64_si_clk,
inout n64_si_dq,
output sdram_cs,
output sdram_ras,
output sdram_cas,
output sdram_we,
output [1:0] sdram_ba,
output [12:0] sdram_a,
inout [15:0] sdram_dq
);
if_n64_bus bus ();
n64_pi n64_pi_inst (
.sys(sys),
.cfg(cfg),
.bus(bus),
.n64_pi_alel(n64_pi_alel),
.n64_pi_aleh(n64_pi_aleh),
.n64_pi_read(n64_pi_read),
.n64_pi_write(n64_pi_write),
.n64_pi_ad(n64_pi_ad)
);
n64_si n64_si_inst (
.sys(sys),
.si(si),
.n64_si_clk(n64_si_clk),
.n64_si_dq(n64_si_dq)
);
n64_sdram n64_sdram_inst (
.sys(sys),
.bus(bus.at[sc64::ID_N64_SDRAM].device),
.dma(dma),
.sdram(sdram),
.sdram_cs(sdram_cs),
.sdram_ras(sdram_ras),
.sdram_cas(sdram_cas),
.sdram_we(sdram_we),
.sdram_ba(sdram_ba),
.sdram_a(sdram_a),
.sdram_dq(sdram_dq)
);
n64_bootloader n64_bootloader_inst (
.sys(sys),
.bus(bus.at[sc64::ID_N64_BOOTLOADER].device)
);
n64_flashram n64_flashram_inst (
.sys(sys),
.bus(bus.at[sc64::ID_N64_FLASHRAM].device),
.cfg(cfg),
.flashram(flashram)
);
n64_dd n64_dd_inst (
.sys(sys),
.bus(bus.at[sc64::ID_N64_DD].device)
);
n64_cfg n64_cfg_inst (
.sys(sys),
.bus(bus.at[sc64::ID_N64_CFG].device),
.cfg(cfg)
);
endmodule

View File

@ -1,107 +0,0 @@
module sd_clk (
input i_clk,
input i_reset,
output reg o_sd_clk,
input [1:0] i_sd_clk_config,
output reg o_sd_clk_strobe_rising,
output reg o_sd_clk_strobe_falling
);
// Clock configuration values
localparam [1:0] SD_CLK_CONFIG_STOP = 2'd0;
localparam [1:0] SD_CLK_CONFIG_DIV_256 = 2'd1;
localparam [1:0] SD_CLK_CONFIG_DIV_4 = 2'd2;
localparam [1:0] SD_CLK_CONFIG_DIV_2 = 2'd3;
// Clock configuration change detection
reg [1:0] r_prev_sd_clk_config;
wire w_sd_clk_config_changed = r_prev_sd_clk_config != i_sd_clk_config;
always @(posedge i_clk) begin
if (i_reset) begin
r_prev_sd_clk_config <= SD_CLK_CONFIG_STOP;
end else begin
r_prev_sd_clk_config <= i_sd_clk_config;
end
end
// Clock divider
reg [7:0] r_sd_clk_counter;
always @(posedge i_clk) begin
if (i_reset || w_sd_clk_config_changed) begin
r_sd_clk_counter <= 8'd0;
end else begin
r_sd_clk_counter <= r_sd_clk_counter + 1'd1;
end
end
// Clock divider selector
reg r_selected_sd_clk;
always @(*) begin
case (r_prev_sd_clk_config)
SD_CLK_CONFIG_STOP:
r_selected_sd_clk = 1'b0;
SD_CLK_CONFIG_DIV_256:
r_selected_sd_clk = r_sd_clk_counter[7];
SD_CLK_CONFIG_DIV_4:
r_selected_sd_clk = r_sd_clk_counter[1];
SD_CLK_CONFIG_DIV_2:
r_selected_sd_clk = r_sd_clk_counter[0];
endcase
end
// Clock strobe generation
reg r_prev_selected_sd_clk;
always @(posedge i_clk) begin
o_sd_clk_strobe_rising <= 1'b0;
o_sd_clk_strobe_falling <= 1'b0;
if (i_reset) begin
r_prev_selected_sd_clk <= 1'b0;
end else begin
r_prev_selected_sd_clk <= r_selected_sd_clk;
if (!r_prev_selected_sd_clk && r_selected_sd_clk) begin
o_sd_clk_strobe_rising <= 1'b1;
end
if (r_prev_selected_sd_clk && !r_selected_sd_clk) begin
o_sd_clk_strobe_falling <= 1'b1;
end
end
end
// SD clock generation
always @(posedge i_clk) begin
if (i_reset) begin
o_sd_clk <= 1'b0;
end else begin
if (o_sd_clk_strobe_rising) begin
o_sd_clk <= 1'b1;
end
if (o_sd_clk_strobe_falling) begin
o_sd_clk <= 1'b0;
end
end
end
endmodule

View File

@ -1,249 +0,0 @@
module sd_cmd (
input i_clk,
input i_reset,
inout io_sd_cmd,
input i_sd_clk_strobe_rising,
input i_sd_clk_strobe_falling,
input [5:0] i_command_index,
input [31:0] i_command_argument,
input i_command_long_response,
input i_command_skip_response,
output reg [5:0] o_command_index,
output reg [31:0] o_command_response,
input i_command_start,
output o_command_busy,
output reg o_command_timeout,
output reg o_command_response_crc_error
);
// Start synchronizer
reg r_pending_start;
wire w_start = r_pending_start && i_sd_clk_strobe_falling;
always @(posedge i_clk) begin
if (i_reset) begin
r_pending_start <= 1'b0;
end else begin
if (i_command_start) begin
r_pending_start <= 1'b1;
end else if (i_sd_clk_strobe_falling) begin
r_pending_start <= 1'b0;
end
end
end
// Module state
localparam STATE_IDLE = 0;
localparam STATE_SENDING = 1;
localparam STATE_RESP_WAIT = 2;
localparam STATE_RECEIVING = 3;
localparam STATE_HIZ_WAIT = 4;
reg [4:0] r_state;
// Bit counter logic
reg [8:0] r_bit_counter;
reg r_bit_done;
wire w_command_start = w_start && r_state[STATE_IDLE];
wire w_command_end = r_bit_done && r_state[STATE_SENDING];
wire w_response_timeout = r_bit_done && r_state[STATE_RESP_WAIT];
wire w_response_start = !io_sd_cmd && i_sd_clk_strobe_rising && r_state[STATE_RESP_WAIT];
wire w_response_end = r_bit_done && r_state[STATE_RECEIVING];
wire w_hiz_end = r_bit_done && r_state[STATE_HIZ_WAIT];
localparam [8:0] COMMAND_BIT_LENGTH = (9'd48 - 1'd1);
localparam [8:0] RESPONSE_WAIT_BIT_LENGTH = (9'd64 - 1'd1);
localparam [8:0] RESPONSE_SHORT_BIT_LENGTH = (9'd48 - 1'd1);
localparam [8:0] RESPONSE_LONG_BIT_LENGTH = (9'd136 - 1'd1);
localparam [8:0] HIZ_WAIT_BIT_LENGTH = (9'd8 - 1'd1);
always @(posedge i_clk) begin
if (w_command_start) begin
r_bit_counter <= COMMAND_BIT_LENGTH;
r_bit_done <= 1'b0;
end else if (w_command_end) begin
r_bit_counter <= RESPONSE_WAIT_BIT_LENGTH;
r_bit_done <= 1'b0;
end else if (w_response_start) begin
r_bit_counter <= i_command_long_response ? RESPONSE_LONG_BIT_LENGTH : RESPONSE_SHORT_BIT_LENGTH;
r_bit_done <= 1'b0;
end else if (w_response_end) begin
r_bit_counter <= HIZ_WAIT_BIT_LENGTH;
r_bit_done <= 1'b0;
end else if (i_sd_clk_strobe_rising) begin
if (r_bit_counter > 9'd0) begin
r_bit_counter <= r_bit_counter - 1'd1;
end else begin
r_bit_done <= 1'b1;
end
end
end
// CRC7 generator
reg [6:0] r_crc_7_received;
wire w_crc_shift_reset = !(r_state[STATE_SENDING] || r_state[STATE_RECEIVING]);
wire w_crc_shift_enabled = (r_bit_counter <= 9'd127) && (r_bit_counter > (r_state[STATE_SENDING] ? 9'd7 : 9'd8));
wire w_crc_shift = w_crc_shift_enabled && i_sd_clk_strobe_rising;
wire [6:0] w_crc_7_calculated;
sd_crc_7 sd_crc_7_inst (
.i_clk(i_clk),
.i_crc_reset(w_crc_shift_reset),
.i_crc_shift(w_crc_shift),
.i_crc_input(io_sd_cmd),
.o_crc_output(w_crc_7_calculated)
);
// Control signals
assign o_command_busy = r_pending_start || (!r_state[STATE_IDLE]);
always @(posedge i_clk) begin
if (i_reset) begin
o_command_timeout <= 1'b0;
o_command_response_crc_error <= 1'b0;
end else begin
if (w_command_start) begin
o_command_timeout <= 1'b0;
end
if (w_response_timeout) begin
o_command_timeout <= 1'b1;
end
if (w_response_end) begin
o_command_response_crc_error <= (w_crc_7_calculated != r_crc_7_received);
end
end
end
// State machine
always @(posedge i_clk) begin
if (i_reset) begin
r_state <= (1'b1 << STATE_IDLE);
end else begin
r_state <= 5'b00000;
unique case (1'b1)
r_state[STATE_IDLE]: begin
if (w_start) begin
r_state[STATE_SENDING] <= 1'b1;
end else begin
r_state[STATE_IDLE] <= 1'b1;
end
end
r_state[STATE_SENDING]: begin
if (w_command_end) begin
if (i_command_skip_response) begin
r_state[STATE_HIZ_WAIT] <= 1'b1;
end else begin
r_state[STATE_RESP_WAIT] <= 1'b1;
end
end else begin
r_state[STATE_SENDING] <= 1'b1;
end
end
r_state[STATE_RESP_WAIT]: begin
if (w_response_timeout) begin
r_state[STATE_IDLE] <= 1'b1;
end else if (w_response_start) begin
r_state[STATE_RECEIVING] <= 1'b1;
end else begin
r_state[STATE_RESP_WAIT] <= 1'b1;
end
end
r_state[STATE_RECEIVING]: begin
if (w_response_end) begin
r_state[STATE_HIZ_WAIT] <= 1'b1;
end else begin
r_state[STATE_RECEIVING] <= 1'b1;
end
end
r_state[STATE_HIZ_WAIT]: begin
if (w_hiz_end) begin
r_state[STATE_IDLE] <= 1'b1;
end else begin
r_state[STATE_HIZ_WAIT] <= 1'b1;
end
end
endcase
end
end
// Shifting operation
reg [7:0] r_shift;
wire w_shift = (r_state[STATE_SENDING] && i_sd_clk_strobe_falling) || (r_state[STATE_RECEIVING] && i_sd_clk_strobe_rising);
assign io_sd_cmd = r_state[STATE_SENDING] ? r_shift[7] : 1'bZ;
always @(posedge i_clk) begin
if (w_command_start) begin
o_command_response <= 32'h0000_0000;
r_shift <= {2'b01, i_command_index};
end else if (w_response_start) begin
r_shift <= 8'h00;
end else begin
if (w_shift) begin
r_shift <= {r_shift[6:0], io_sd_cmd};
end
if (i_sd_clk_strobe_falling && r_state[STATE_SENDING]) begin
if (r_bit_counter == 9'd39) begin
r_shift <= i_command_argument[31:24];
end
if (r_bit_counter == 9'd31) begin
r_shift <= i_command_argument[23:16];
end
if (r_bit_counter == 9'd23) begin
r_shift <= i_command_argument[15:8];
end
if (r_bit_counter == 9'd15) begin
r_shift <= i_command_argument[7:0];
end
if (r_bit_counter == 9'd7) begin
r_shift <= {w_crc_7_calculated, 1'b1};
end
end
if (i_sd_clk_strobe_rising && r_state[STATE_RECEIVING]) begin
if (r_bit_counter == (i_command_long_response ? 9'd128 : 9'd40)) begin
o_command_index <= r_shift[5:0];
end else if (r_bit_counter[2:0] == 3'd0) begin
if (r_bit_counter > 9'd7) begin
o_command_response <= {o_command_response[23:0], r_shift};
end else begin
r_crc_7_received <= r_shift[7:1];
end
end
end
end
end
endmodule

View File

@ -1,26 +0,0 @@
module sd_crc_16 (
input i_clk,
input i_crc_reset,
input i_crc_shift,
input i_crc_input,
output reg [15:0] o_crc_output
);
wire w_crc_inv = o_crc_output[15] ^ i_crc_input;
always @(posedge i_clk) begin
if (i_crc_reset) begin
o_crc_output <= 16'd0;
end else if (i_crc_shift) begin
o_crc_output <= {
o_crc_output[14:12],
o_crc_output[11] ^ w_crc_inv,
o_crc_output[10:5],
o_crc_output[4] ^ w_crc_inv,
o_crc_output[3:0],
w_crc_inv
};
end
end
endmodule

View File

@ -1,24 +0,0 @@
module sd_crc_7 (
input i_clk,
input i_crc_reset,
input i_crc_shift,
input i_crc_input,
output reg [6:0] o_crc_output
);
wire w_crc_inv = o_crc_output[6] ^ i_crc_input;
always @(posedge i_clk) begin
if (i_crc_reset) begin
o_crc_output <= 7'd0;
end else if (i_crc_shift) begin
o_crc_output <= {
o_crc_output[5:3],
o_crc_output[2] ^ w_crc_inv,
o_crc_output[1:0],
w_crc_inv
};
end
end
endmodule

View File

@ -1,208 +0,0 @@
module sd_dat (
input i_clk,
input i_reset,
inout reg [3:0] io_sd_dat,
input i_sd_clk_strobe_rising,
input i_sd_clk_strobe_falling,
input i_dat_width,
input i_dat_direction,
input [6:0] i_dat_block_size,
input [10:0] i_dat_num_blocks,
input i_dat_start,
input i_dat_stop,
output o_dat_busy,
output reg o_dat_crc_error,
output reg o_rx_fifo_push,
input i_rx_fifo_overrun,
output reg [31:0] o_rx_fifo_data,
input i_tx_fifo_full,
output reg o_tx_fifo_pop,
input [31:0] i_tx_fifo_data
);
// Module state
localparam STATE_IDLE = 0;
localparam STATE_READ_WAIT = 1;
localparam STATE_RECEIVING = 2;
reg [2:0] r_state;
// Bit counter logic
reg [12:0] r_bit_counter;
reg r_bit_done;
wire w_start_bit = !io_sd_dat[0] && i_sd_clk_strobe_rising && r_state[STATE_READ_WAIT];
wire w_data_end = r_bit_done && r_state[STATE_RECEIVING];
assign o_dat_busy = !r_state[STATE_IDLE];
always @(posedge i_clk) begin
if (w_start_bit) begin
r_bit_counter <= (i_dat_width ? (
{2'b00, {1'b0, i_dat_block_size} + 1'd1, 3'b000}
) : (
{{1'b0, i_dat_block_size} + 1'd1, 5'b00000}
)) + 13'd16;
r_bit_done <= 1'b0;
end else if (i_sd_clk_strobe_rising) begin
if (r_bit_counter > 13'd0) begin
r_bit_counter <= r_bit_counter - 1'd1;
end else begin
r_bit_done <= 1'b1;
end
end
end
// Block counter logic
reg [10:0] r_block_counter;
wire w_read_start = i_dat_start && r_state[STATE_IDLE];
wire w_read_stop = r_block_counter == 11'd0;
always @(posedge i_clk) begin
if (w_read_start) begin
r_block_counter <= i_dat_num_blocks;
end else if (w_data_end) begin
if (r_block_counter > 11'd0) begin
r_block_counter <= r_block_counter - 1'd1;
end
end
end
// CRC16 generator
reg [15:0] r_crc_16_received [0:3];
wire w_crc_shift_reset = !r_state[STATE_RECEIVING];
wire w_crc_shift_enabled = r_bit_counter > 13'd16;
wire w_crc_shift = w_crc_shift_enabled && i_sd_clk_strobe_rising;
wire [15:0] w_crc_16_calculated [0:3];
wire w_crc_error = (r_bit_counter == 13'd0) && (i_dat_width ? (
(w_crc_16_calculated[0] != r_crc_16_received[0]) &&
(w_crc_16_calculated[1] != r_crc_16_received[1]) &&
(w_crc_16_calculated[2] != r_crc_16_received[2]) &&
(w_crc_16_calculated[3] != r_crc_16_received[3])
) : (
w_crc_16_calculated[0] != r_crc_16_received[0]
));
genvar dat_index;
generate
for (dat_index = 0; dat_index < 4; dat_index = dat_index + 1) begin : crc_16_loop
sd_crc_16 sd_crc_16_inst (
.i_clk(i_clk),
.i_crc_reset(w_crc_shift_reset),
.i_crc_shift(w_crc_shift),
.i_crc_input(io_sd_dat[dat_index]),
.o_crc_output(w_crc_16_calculated[dat_index])
);
end
endgenerate
// Control signals
always @(posedge i_clk) begin
if (i_reset) begin
o_dat_crc_error <= 1'b0;
end else begin
if (w_data_end) begin
o_dat_crc_error <= w_crc_error;
end
end
end
// State machine
always @(posedge i_clk) begin
if (i_reset) begin
r_state <= (1'b1 << STATE_IDLE);
end else begin
r_state <= 3'b000;
if (i_dat_stop) begin
r_state[STATE_IDLE] <= 1'b1;
end else begin
unique case (1'b1)
r_state[STATE_IDLE]: begin
if (i_dat_start) begin
if (i_dat_direction) begin
r_state[STATE_IDLE] <= 1'b1; // TODO: Sending
end else begin
r_state[STATE_READ_WAIT] <= 1'b1;
end
end else begin
r_state[STATE_IDLE] <= 1'b1;
end
end
r_state[STATE_READ_WAIT]: begin
if (w_start_bit) begin
r_state[STATE_RECEIVING] <= 1'b1;
end else begin
r_state[STATE_READ_WAIT] <= 1'b1;
end
end
r_state[STATE_RECEIVING]: begin
if (w_crc_error || i_rx_fifo_overrun) begin
r_state[STATE_IDLE] <= 1'b1;
end else if (w_data_end) begin
if (w_read_stop) begin
r_state[STATE_IDLE] <= 1'b1;
end else begin
r_state[STATE_READ_WAIT] <= 1'b1;
end
end else begin
r_state[STATE_RECEIVING] <= 1'b1;
end
end
endcase
end
end
end
// Shifting operation
wire [31:0] w_shift_1_bit = {o_rx_fifo_data[30:0], io_sd_dat[0]};
wire [31:0] w_shift_4_bit = {o_rx_fifo_data[27:0], io_sd_dat};
always @(posedge i_clk) begin
o_rx_fifo_push <= 1'b0;
if (i_sd_clk_strobe_rising && r_state[STATE_RECEIVING]) begin
if (r_bit_counter > 13'd16) begin
if (i_dat_width) begin
o_rx_fifo_data <= w_shift_4_bit;
if (r_bit_counter[2:0] == 3'd1) begin
o_rx_fifo_push <= 1'b1;
end
end else begin
o_rx_fifo_data <= w_shift_1_bit;
if (r_bit_counter[4:0] == 5'd17) begin
o_rx_fifo_push <= 1'b1;
end
end
end else if (r_bit_counter > 13'd0) begin
for (integer i = 0; i < 4; i = i + 1) begin
r_crc_16_received[i] <= {r_crc_16_received[i][14:0], io_sd_dat[i]};
end
end
end
end
endmodule

View File

@ -1,93 +0,0 @@
module sd_dma (
input i_clk,
input i_reset,
input [3:0] i_dma_bank,
input [23:0] i_dma_address,
input [17:0] i_dma_length,
output [17:0] o_dma_left,
input i_dma_load_bank_address,
input i_dma_load_length,
input i_dma_direction,
input i_dma_start,
input i_dma_stop,
output reg o_dma_busy,
output o_rx_fifo_pop,
input i_rx_fifo_empty,
input [31:0] i_rx_fifo_data,
output reg o_tx_fifo_push,
input i_tx_fifo_full,
output [31:0] o_tx_fifo_data,
output o_request,
output reg o_write,
input i_busy,
input i_ack,
output reg [3:0] o_bank,
output reg [23:0] o_address,
input [31:0] i_data,
output [31:0] o_data
);
wire w_request_successful = o_request && !i_busy;
always @(posedge i_clk) begin
if (i_dma_load_bank_address && !o_dma_busy) begin
o_bank <= i_dma_bank;
end
end
always @(posedge i_clk) begin
if (i_dma_load_bank_address && !o_dma_busy) begin
o_address <= i_dma_address;
end else if (w_request_successful) begin
o_address <= o_address + 1'd1;
end
end
reg [17:0] r_remaining;
assign o_dma_left = r_remaining;
always @(posedge i_clk) begin
if (i_dma_load_length && !o_dma_busy) begin
r_remaining <= i_dma_length;
end else if (w_request_successful && r_remaining > 18'd0) begin
r_remaining <= r_remaining - 1'd1;
end
end
always @(posedge i_clk) begin
if (i_reset) begin
o_dma_busy <= 1'b0;
end else begin
if (i_dma_start && !o_dma_busy) begin
o_dma_busy <= 1'b1;
end
if (i_dma_stop || (w_request_successful && r_remaining == 18'd0)) begin
o_dma_busy <= 1'b0;
end
end
end
assign o_rx_fifo_pop = o_dma_busy && o_write && w_request_successful;
assign o_tx_fifo_data = i_data;
assign o_request = o_dma_busy && (o_write ? (
!i_rx_fifo_empty
) : (
1'b0 // TODO: Reading
));
always @(posedge i_clk) begin
if (i_dma_start) begin
o_write <= i_dma_direction;
end
end
assign o_data = i_rx_fifo_data;
endmodule

View File

@ -1,56 +0,0 @@
module sd_fifo (
input i_clk,
input i_reset,
input i_fifo_flush,
input i_fifo_push,
input i_fifo_pop,
output o_fifo_empty,
output o_fifo_full,
output [7:0] o_fifo_items,
output reg o_fifo_underrun,
output reg o_fifo_overrun,
input [31:0] i_fifo_data,
output [31:0] o_fifo_data
);
reg [31:0] r_fifo_mem [0:127];
reg [7:0] r_fifo_wrptr;
reg [7:0] r_fifo_rdptr;
assign o_fifo_data = r_fifo_mem[r_fifo_rdptr[6:0]];
wire w_empty = r_fifo_wrptr[7] == r_fifo_rdptr[7];
wire w_full_or_empty = r_fifo_wrptr[6:0] == r_fifo_rdptr[6:0];
assign o_fifo_empty = w_empty && w_full_or_empty;
assign o_fifo_full = !w_empty && w_full_or_empty;
assign o_fifo_items = r_fifo_wrptr - r_fifo_rdptr;
always @(posedge i_clk) begin
if (i_reset) begin
r_fifo_wrptr <= 8'd0;
r_fifo_rdptr <= 8'd0;
o_fifo_underrun <= 1'b0;
o_fifo_overrun <= 1'b0;
end else begin
if (i_fifo_flush) begin
r_fifo_wrptr <= 8'd0;
r_fifo_rdptr <= 8'd0;
o_fifo_underrun <= 1'b0;
o_fifo_overrun <= 1'b0;
end
if (i_fifo_push) begin
o_fifo_overrun <= o_fifo_overrun ? 1'b1 : o_fifo_full;
r_fifo_mem[r_fifo_wrptr[6:0]] <= i_fifo_data;
r_fifo_wrptr <= r_fifo_wrptr + 1'd1;
end
if (i_fifo_pop) begin
o_fifo_underrun <= o_fifo_underrun ? 1'b1 : o_fifo_empty;
r_fifo_rdptr <= r_fifo_rdptr + 1'd1;
end
end
end
endmodule

View File

@ -1,295 +0,0 @@
module sd_interface (
input i_clk,
input i_reset,
output o_sd_clk,
inout io_sd_cmd,
inout [3:0] io_sd_dat,
input i_request,
input i_write,
output o_busy,
output o_ack,
input [3:0] i_address,
output [31:0] o_data,
input [31:0] i_data,
output o_dma_request,
output o_dma_write,
input i_dma_busy,
input i_dma_ack,
output [3:0] o_dma_bank,
output [23:0] o_dma_address,
input [31:0] i_dma_data,
output [31:0] o_dma_data
);
// Clock generator
wire [1:0] w_sd_clk_config;
wire w_sd_clk_strobe_rising;
wire w_sd_clk_strobe_falling;
sd_clk sd_clk_inst (
.i_clk(i_clk),
.i_reset(i_reset),
.i_sd_clk_config(w_sd_clk_config),
.o_sd_clk_strobe_rising(w_sd_clk_strobe_rising),
.o_sd_clk_strobe_falling(w_sd_clk_strobe_falling),
.o_sd_clk(o_sd_clk)
);
// Command path
wire [5:0] w_command_index;
wire [31:0] w_command_argument;
wire w_command_skip_response;
wire w_command_long_response;
wire [5:0] w_command_response_index;
wire [31:0] w_command_response;
wire w_command_start;
wire w_command_busy;
wire w_command_timeout;
wire w_command_response_crc_error;
sd_cmd sd_cmd_inst (
.i_clk(i_clk),
.i_reset(i_reset),
.io_sd_cmd(io_sd_cmd),
.i_sd_clk_strobe_rising(w_sd_clk_strobe_rising),
.i_sd_clk_strobe_falling(w_sd_clk_strobe_falling),
.i_command_index(w_command_index),
.i_command_argument(w_command_argument),
.i_command_long_response(w_command_long_response),
.i_command_skip_response(w_command_skip_response),
.o_command_index(w_command_response_index),
.o_command_response(w_command_response),
.i_command_start(w_command_start),
.o_command_busy(w_command_busy),
.o_command_timeout(w_command_timeout),
.o_command_response_crc_error(w_command_response_crc_error)
);
// SD to FPGA (RX) data path FIFO
wire w_rx_fifo_flush;
wire w_rx_fifo_push;
wire w_rx_fifo_regs_pop;
wire w_rx_fifo_dma_pop;
wire w_rx_fifo_empty;
wire [7:0] w_rx_fifo_items;
wire w_rx_fifo_overrun;
wire [31:0] w_rx_fifo_i_data;
wire [31:0] w_rx_fifo_o_data;
sd_fifo sd_fifo_rx_inst (
.i_clk(i_clk),
.i_reset(i_reset),
.i_fifo_flush(w_rx_fifo_flush),
.i_fifo_push(w_rx_fifo_push),
.i_fifo_pop(w_rx_fifo_regs_pop || w_rx_fifo_dma_pop),
.o_fifo_empty(w_rx_fifo_empty),
.o_fifo_full(),
.o_fifo_items(w_rx_fifo_items),
.o_fifo_underrun(),
.o_fifo_overrun(w_rx_fifo_overrun),
.i_fifo_data(w_rx_fifo_i_data),
.o_fifo_data(w_rx_fifo_o_data)
);
// FPGA to SD (TX) data path FIFO
wire w_tx_fifo_flush;
wire w_tx_fifo_regs_push;
wire w_tx_fifo_dma_push;
wire w_tx_fifo_pop;
wire w_tx_fifo_empty;
wire w_tx_fifo_full;
reg [31:0] r_tx_fifo_i_data;
wire [31:0] w_tx_fifo_o_data;
wire [31:0] w_tx_fifo_i_data_regs;
wire [31:0] w_tx_fifo_i_data_dma;
always @(*) begin
r_tx_fifo_i_data = 32'h0000_0000;
if (w_tx_fifo_regs_push) r_tx_fifo_i_data = w_tx_fifo_i_data_regs;
if (w_tx_fifo_dma_push) r_tx_fifo_i_data = w_tx_fifo_i_data_dma;
end
sd_fifo sd_fifo_tx_inst (
.i_clk(i_clk),
.i_reset(i_reset),
.i_fifo_flush(w_tx_fifo_flush),
.i_fifo_push(w_tx_fifo_regs_push || w_tx_fifo_dma_push),
.i_fifo_pop(w_tx_fifo_pop),
.o_fifo_empty(w_tx_fifo_empty),
.o_fifo_full(w_tx_fifo_full),
.o_fifo_items(),
.o_fifo_underrun(),
.o_fifo_overrun(),
.i_fifo_data(r_tx_fifo_i_data),
.o_fifo_data(w_tx_fifo_o_data)
);
// Data path
wire w_dat_width;
wire w_dat_direction;
wire [6:0] w_dat_block_size;
wire [10:0] w_dat_num_blocks;
wire w_dat_start;
wire w_dat_stop;
wire w_dat_busy;
wire w_dat_crc_error;
sd_dat sd_dat_inst (
.i_clk(i_clk),
.i_reset(i_reset),
.io_sd_dat(io_sd_dat),
.i_sd_clk_strobe_rising(w_sd_clk_strobe_rising),
.i_sd_clk_strobe_falling(w_sd_clk_strobe_falling),
.i_dat_width(w_dat_width),
.i_dat_direction(w_dat_direction),
.i_dat_block_size(w_dat_block_size),
.i_dat_num_blocks(w_dat_num_blocks),
.i_dat_start(w_dat_start),
.i_dat_stop(w_dat_stop),
.o_dat_busy(w_dat_busy),
.o_dat_crc_error(w_dat_crc_error),
.o_rx_fifo_push(w_rx_fifo_push),
.i_rx_fifo_overrun(w_rx_fifo_overrun),
.o_rx_fifo_data(w_rx_fifo_i_data),
.i_tx_fifo_full(w_tx_fifo_full),
.o_tx_fifo_pop(w_tx_fifo_pop),
.i_tx_fifo_data(w_tx_fifo_o_data)
);
// DMA
wire [3:0] w_dma_bank;
wire [23:0] w_dma_address;
wire [17:0] w_dma_length;
wire [17:0] w_dma_left;
wire w_dma_load_bank_address;
wire w_dma_load_length;
wire w_dma_direction;
wire w_dma_start;
wire w_dma_stop;
wire w_dma_busy;
sd_dma sd_dma_inst (
.i_clk(i_clk),
.i_reset(i_reset),
.i_dma_bank(w_dma_bank),
.i_dma_address(w_dma_address),
.i_dma_length(w_dma_length),
.o_dma_left(w_dma_left),
.i_dma_load_bank_address(w_dma_load_bank_address),
.i_dma_load_length(w_dma_load_length),
.i_dma_direction(w_dma_direction),
.i_dma_start(w_dma_start),
.i_dma_stop(w_dma_stop),
.o_dma_busy(w_dma_busy),
.o_rx_fifo_pop(w_rx_fifo_dma_pop),
.i_rx_fifo_empty(w_rx_fifo_empty),
.i_rx_fifo_data(w_rx_fifo_o_data),
.o_tx_fifo_push(w_tx_fifo_dma_push),
.i_tx_fifo_full(w_tx_fifo_full),
.o_tx_fifo_data(w_tx_fifo_i_data_dma),
.o_request(o_dma_request),
.o_write(o_dma_write),
.i_busy(i_dma_busy),
.i_ack(i_dma_ack),
.o_bank(o_dma_bank),
.o_address(o_dma_address),
.i_data(i_dma_data),
.o_data(o_dma_data)
);
// Peripheral registers
sd_regs sd_regs_inst (
.i_clk(i_clk),
.i_reset(i_reset),
.o_sd_clk_config(w_sd_clk_config),
.o_command_index(w_command_index),
.o_command_argument(w_command_argument),
.o_command_long_response(w_command_long_response),
.o_command_skip_response(w_command_skip_response),
.i_command_index(w_command_response_index),
.i_command_response(w_command_response),
.o_command_start(w_command_start),
.i_command_busy(w_command_busy),
.i_command_timeout(w_command_timeout),
.i_command_response_crc_error(w_command_response_crc_error),
.o_dat_width(w_dat_width),
.o_dat_direction(w_dat_direction),
.o_dat_block_size(w_dat_block_size),
.o_dat_num_blocks(w_dat_num_blocks),
.o_dat_start(w_dat_start),
.o_dat_stop(w_dat_stop),
.i_dat_busy(w_dat_busy),
.i_dat_crc_error(w_dat_crc_error),
.o_rx_fifo_flush(w_rx_fifo_flush),
.o_rx_fifo_pop(w_rx_fifo_regs_pop),
.i_rx_fifo_items(w_rx_fifo_items),
.i_rx_fifo_overrun(w_rx_fifo_overrun),
.i_rx_fifo_data(w_rx_fifo_o_data),
.o_tx_fifo_flush(w_tx_fifo_flush),
.o_tx_fifo_push(w_tx_fifo_regs_push),
.i_tx_fifo_empty(w_tx_fifo_empty),
.i_tx_fifo_full(w_tx_fifo_full),
.o_tx_fifo_data(w_tx_fifo_i_data_regs),
.o_dma_bank(w_dma_bank),
.o_dma_address(w_dma_address),
.o_dma_length(w_dma_length),
.i_dma_bank(o_dma_bank),
.i_dma_address(o_dma_address),
.i_dma_left(w_dma_left),
.o_dma_load_bank_address(w_dma_load_bank_address),
.o_dma_load_length(w_dma_load_length),
.o_dma_direction(w_dma_direction),
.o_dma_start(w_dma_start),
.o_dma_stop(w_dma_stop),
.i_dma_busy(w_dma_busy),
.i_request(i_request),
.i_write(i_write),
.o_busy(o_busy),
.o_ack(o_ack),
.i_address(i_address),
.o_data(o_data),
.i_data(i_data)
);
endmodule

View File

@ -1,223 +0,0 @@
module sd_regs (
input i_clk,
input i_reset,
output reg [1:0] o_sd_clk_config,
output reg [5:0] o_command_index,
output reg [31:0] o_command_argument,
output reg o_command_long_response,
output reg o_command_skip_response,
input [5:0] i_command_index,
input [31:0] i_command_response,
output reg o_command_start,
input i_command_busy,
input i_command_timeout,
input i_command_response_crc_error,
output reg o_dat_width,
output reg o_dat_direction,
output reg [6:0] o_dat_block_size,
output reg [10:0] o_dat_num_blocks,
output reg o_dat_start,
output reg o_dat_stop,
input i_dat_busy,
input i_dat_crc_error,
output reg o_rx_fifo_flush,
output reg o_rx_fifo_pop,
input [7:0] i_rx_fifo_items,
input i_rx_fifo_overrun,
input [31:0] i_rx_fifo_data,
output reg o_tx_fifo_flush,
output reg o_tx_fifo_push,
input i_tx_fifo_empty,
input i_tx_fifo_full,
output reg [31:0] o_tx_fifo_data,
output reg [3:0] o_dma_bank,
output reg [23:0] o_dma_address,
output reg [17:0] o_dma_length,
input [3:0] i_dma_bank,
input [23:0] i_dma_address,
input [17:0] i_dma_left,
output reg o_dma_load_bank_address,
output reg o_dma_load_length,
output reg o_dma_direction,
output reg o_dma_start,
output reg o_dma_stop,
input i_dma_busy,
input i_request,
input i_write,
output o_busy,
output reg o_ack,
input [3:0] i_address,
output reg [31:0] o_data,
input [31:0] i_data
);
localparam [2:0] SD_REG_SCR = 3'd0;
localparam [2:0] SD_REG_ARG = 3'd1;
localparam [2:0] SD_REG_CMD = 3'd2;
localparam [2:0] SD_REG_RSP = 3'd3;
localparam [2:0] SD_REG_DAT = 3'd4;
localparam [2:0] SD_REG_DMA_SCR = 3'd5;
localparam [2:0] SD_REG_DMA_ADDR = 3'd6;
localparam [2:0] SD_REG_DMA_LEN = 3'd7;
wire w_write_request = i_request && i_write && !o_busy;
wire w_read_request = i_request && !i_write && !o_busy;
always @(*) begin
o_dma_bank = i_data[31:28];
o_dma_address = i_data[25:2];
o_dma_length = i_data[17:0];
o_dma_load_bank_address = w_write_request && !i_address[3] && (i_address[2:0] == SD_REG_DMA_ADDR);
o_dma_load_length = w_write_request && !i_address[3] && (i_address[2:0] == SD_REG_DMA_LEN);
o_busy = 1'b0;
end
always @(posedge i_clk) begin
o_command_start <= 1'b0;
o_dat_start <= 1'b0;
o_rx_fifo_flush <= 1'b0;
o_tx_fifo_flush <= 1'b0;
o_tx_fifo_push <= 1'b0;
o_dma_start <= 1'b0;
o_dat_stop <= 1'b0;
o_dma_stop <= 1'b0;
if (i_reset) begin
o_sd_clk_config <= 2'd0;
o_dat_width <= 1'b0;
o_dat_direction <= 1'b0;
o_dat_block_size <= 7'd0;
o_dat_num_blocks <= 11'd0;
o_dma_direction <= 1'b0;
end else if (w_write_request) begin
if (!i_address[3]) begin
case (i_address[2:0])
SD_REG_SCR: begin
{o_dat_width, o_sd_clk_config} <= i_data[2:0];
end
SD_REG_ARG: begin
o_command_argument <= i_data;
end
SD_REG_CMD: begin
{
o_command_skip_response,
o_command_long_response,
o_command_start,
o_command_index
} <= i_data[8:0];
end
SD_REG_RSP: begin
end
SD_REG_DAT: begin
{
o_tx_fifo_flush,
o_rx_fifo_flush,
o_dat_num_blocks,
o_dat_block_size,
o_dat_direction,
o_dat_stop,
o_dat_start
} <= i_data[22:0];
end
SD_REG_DMA_SCR: begin
{
o_dma_direction,
o_dma_stop,
o_dma_start
} <= i_data[2:0];
end
SD_REG_DMA_ADDR: begin
end
SD_REG_DMA_LEN: begin
end
endcase
end else begin
o_tx_fifo_push <= 1'b1;
o_tx_fifo_data <= i_data;
end
end
end
always @(posedge i_clk) begin
o_rx_fifo_pop <= 1'b0;
o_ack <= 1'b0;
if (i_reset) begin
o_data <= 32'h0000_0000;
end else if (w_read_request) begin
o_ack <= 1'b1;
if (!i_address[3]) begin
case (i_address[2:0])
SD_REG_SCR: begin
o_data <= {29'd0, o_dat_width, o_sd_clk_config};
end
SD_REG_ARG: begin
o_data <= o_command_argument;
end
SD_REG_CMD: begin
o_data <= {
21'd0,
i_command_response_crc_error,
i_command_timeout,
o_command_skip_response,
o_command_long_response,
i_command_busy,
i_command_index
};
end
SD_REG_RSP: begin
o_data <= i_command_response;
end
SD_REG_DAT: begin
o_data <= {
i_rx_fifo_items,
i_tx_fifo_full,
i_tx_fifo_empty,
i_rx_fifo_overrun,
o_dat_num_blocks,
o_dat_block_size,
o_dat_direction,
i_dat_crc_error,
i_dat_busy
};
end
SD_REG_DMA_SCR: begin
o_data <= {29'd0, o_dma_direction, 1'b0, i_dma_busy};
end
SD_REG_DMA_ADDR: begin
o_data <= {i_dma_bank, 2'd0, i_dma_address, 2'b00};
end
SD_REG_DMA_LEN: begin
o_data <= {14'd0, i_dma_left};
end
endcase
end else begin
o_rx_fifo_pop <= 1'b1;
o_data <= i_rx_fifo_data;
end
end
end
endmodule

70
fw/rtl/system/config.sv Normal file
View File

@ -0,0 +1,70 @@
interface if_config ();
logic cpu_ready;
logic cpu_busy;
logic usb_waiting;
logic cmd_error;
logic cmd_request;
logic [7:0] cmd;
logic [31:0] data [0:1];
logic [1:0] data_write;
logic [31:0] wdata;
logic sdram_switch;
logic sdram_writable;
logic dd_enabled;
logic sram_enabled;
logic sram_banked;
logic flashram_enabled;
logic flashram_read_mode;
logic [25:0] dd_offset;
logic [25:0] save_offset;
modport pi (
input sdram_switch,
input sdram_writable,
input dd_enabled,
input sram_enabled,
input sram_banked,
input flashram_enabled,
input flashram_read_mode,
input dd_offset,
input save_offset
);
modport flashram (
output flashram_read_mode
);
modport n64 (
input cpu_ready,
input cpu_busy,
input usb_waiting,
input cmd_error,
output cmd_request,
output cmd,
output data,
input data_write,
input wdata
);
modport cpu (
output cpu_ready,
output cpu_busy,
output usb_waiting,
output cmd_error,
input cmd_request,
input cmd,
input data,
output data_write,
output wdata,
output sdram_switch,
output sdram_writable,
output dd_enabled,
output sram_enabled,
output sram_banked,
output flashram_enabled,
output dd_offset,
output save_offset
);
endinterface

41
fw/rtl/system/sc64.sv Normal file
View File

@ -0,0 +1,41 @@
package sc64;
typedef enum bit [2:0] {
ID_N64_SDRAM,
ID_N64_BOOTLOADER,
ID_N64_FLASHRAM,
ID_N64_DD,
ID_N64_CFG,
__ID_N64_END
} e_n64_id;
typedef enum bit [3:0] {
ID_CPU_RAM,
ID_CPU_BOOTLOADER,
ID_CPU_GPIO,
ID_CPU_I2C,
ID_CPU_USB,
ID_CPU_UART,
ID_CPU_DMA,
ID_CPU_CFG,
ID_CPU_SDRAM,
ID_CPU_FLASHRAM,
ID_CPU_SI,
__ID_CPU_END
} e_cpu_id;
typedef enum bit [1:0] {
ID_DMA_USB,
ID_DMA_SD,
__ID_DMA_END
} e_dma_id;
parameter bit [31:0] SC64_VER = 32'h53437632;
parameter int CLOCK_FREQUENCY = 32'd100_000_000;
parameter int UART_BAUD_RATE = 32'd1_000_000;
parameter bit DEBUG_ENABLED = 1'b0;
endpackage

72
fw/rtl/system/system.sv Normal file
View File

@ -0,0 +1,72 @@
interface if_system (
input in_clk,
input n64_reset,
input n64_nmi
);
logic clk;
logic sdram_clk;
logic reset;
logic n64_soft_reset;
logic n64_hard_reset;
modport internal (
input in_clk,
input n64_reset,
input n64_nmi,
output clk,
output sdram_clk,
output reset,
output n64_soft_reset,
output n64_hard_reset
);
modport sys (
input clk,
input reset,
input n64_soft_reset,
input n64_hard_reset
);
modport sdram (
input sdram_clk
);
endinterface
module system (if_system.internal sys);
logic locked;
logic external_reset;
logic [1:0] n64_reset_ff;
logic [1:0] n64_nmi_ff;
intel_pll intel_pll_inst (
.inclk0(sys.in_clk),
.c0(sys.clk),
.c1(sys.sdram_clk),
.locked(locked)
);
generate
if (sc64::DEBUG_ENABLED) begin
intel_snp intel_snp_inst (
.source(external_reset),
.source_clk(sys.clk)
);
end
endgenerate
always_ff @(posedge sys.clk) begin
n64_reset_ff <= {n64_reset_ff[0], sys.n64_reset};
n64_nmi_ff <= {n64_nmi_ff[0], sys.n64_nmi};
end
always_comb begin
sys.reset = ~locked | external_reset;
sys.n64_hard_reset = ~n64_reset_ff[1];
sys.n64_soft_reset = ~n64_nmi_ff[1];
end
endmodule

View File

@ -1,541 +0,0 @@
`include "constants.vh"
module top (
input i_clk,
output o_ftdi_clk,
output o_ftdi_si,
input i_ftdi_so,
input i_ftdi_cts,
input i_n64_reset,
input i_n64_nmi,
input i_n64_pi_alel,
input i_n64_pi_aleh,
input i_n64_pi_read,
input i_n64_pi_write,
inout [15:0] io_n64_pi_ad,
input i_n64_si_clk,
inout io_n64_si_dq,
output o_sdram_clk,
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,
output o_sd_clk,
inout io_sd_cmd,
inout [3:0] io_sd_dat,
output o_sram_clk,
output o_sram_cs,
inout [3:0] io_sram_dq,
output o_rtc_scl,
inout io_rtc_sda,
output o_led,
inout [7:0] io_pmod
);
// Clock and reset signals
wire w_sys_clk;
wire w_sdram_clk;
wire w_pll_lock;
wire w_sys_reset = ~w_pll_lock;
// Temporary signal names
wire w_n64_reset_btn;
assign {o_sram_clk, o_sram_cs, io_sram_dq} = 6'bZZZZZZ;
assign {o_rtc_scl, io_rtc_sda} = 2'bZZ;
assign io_pmod[3] = w_n64_reset_btn ? 1'bZ : 1'b0;
assign {io_pmod[7:4], io_pmod[2:0]} = 7'bZZZZZZZ;
// PLL clock generator
pll sys_pll (
.inclk0(i_clk),
.c0(w_sys_clk),
.c1(w_sdram_clk),
.locked(w_pll_lock)
);
// 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)
);
// N64 PI
wire w_n64_request;
wire w_n64_write;
wire w_n64_busy;
wire w_n64_ack;
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_n64_busy_cart_control;
wire w_n64_ack_cart_control;
wire [31:0] w_n64_i_data_cart_control;
wire w_n64_busy_sdram;
wire w_n64_ack_sdram;
wire [31:0] w_n64_i_data_sdram;
wire w_n64_busy_embedded_flash;
wire w_n64_ack_embedded_flash;
wire [31:0] w_n64_i_data_embedded_flash;
wire w_n64_busy_eeprom;
wire w_n64_ack_eeprom;
wire [31:0] w_n64_i_data_eeprom;
wire w_n64_busy_sd;
wire w_n64_ack_sd;
wire [31:0] w_n64_i_data_sd;
wire w_sram_request;
wire w_ddipl_enable;
wire w_sram_enable;
wire w_sram_768k_mode;
wire w_flashram_enable;
wire w_sd_enable;
wire w_eeprom_pi_enable;
wire [23:0] w_ddipl_address;
wire [23:0] w_sram_address;
always @(*) begin
w_n64_busy = w_n64_busy_cart_control || w_n64_busy_sdram || w_n64_busy_embedded_flash || w_n64_busy_eeprom || w_n64_busy_sd;
w_n64_ack = w_n64_ack_cart_control || w_n64_ack_sdram || w_n64_ack_embedded_flash || w_n64_ack_eeprom || w_n64_ack_sd;
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;
if (w_n64_ack_sd) w_n64_i_data = w_n64_i_data_sd;
end
n64_pi n64_pi_inst (
.i_clk(w_sys_clk),
.i_reset(w_sys_reset),
.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_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(w_n64_i_data),
.o_data(w_n64_o_data),
.o_sram_request(w_sram_request),
.i_ddipl_enable(w_ddipl_enable),
.i_sram_enable(w_sram_enable),
.i_sram_768k_mode(w_sram_768k_mode),
.i_flashram_enable(w_flashram_enable),
.i_sd_enable(w_sd_enable),
.i_eeprom_enable(w_eeprom_pi_enable),
.i_ddipl_address(w_ddipl_address),
.i_sram_address(w_sram_address)
);
// 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;
wire w_debug_dma_start;
wire w_debug_dma_busy;
wire [3:0] w_debug_dma_bank;
wire [23:0] w_debug_dma_address;
wire [19:0] w_debug_dma_length;
wire w_debug_fifo_request;
wire w_debug_fifo_flush;
wire [10:0] w_debug_fifo_items;
wire [31:0] w_debug_fifo_data;
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 #(
.VERSION(`VERSION)
) 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),
.i_debug_start(w_debug_dma_start),
.o_debug_busy(w_debug_dma_busy),
.i_debug_bank(w_debug_dma_bank),
.i_debug_address(w_debug_dma_address),
.i_debug_length(w_debug_dma_length),
.i_debug_fifo_request(w_debug_fifo_request),
.i_debug_fifo_flush(w_debug_fifo_flush),
.o_debug_fifo_items(w_debug_fifo_items),
.o_debug_fifo_data(w_debug_fifo_data)
);
// Cart interface
wire w_cart_control_request;
wire w_cart_control_write;
wire w_cart_control_busy;
wire w_cart_control_ack;
wire [10:0] w_cart_control_address;
wire [31:0] w_cart_control_o_data;
wire [31:0] w_cart_control_i_data;
wire w_sdram_writable;
wire w_rom_switch;
wire w_eeprom_enable;
wire w_eeprom_16k_mode;
device_arbiter #(
.NUM_CONTROLLERS(2),
.ADDRESS_WIDTH(11),
.DEVICE_BANK(`BANK_CART)
) device_arbiter_cart_control_inst (
.i_clk(w_sys_clk),
.i_reset(w_sys_reset),
.i_request({w_pc_request, w_n64_request}),
.i_write({w_pc_write, w_n64_write}),
.o_busy({w_pc_busy_cart_control, w_n64_busy_cart_control}),
.o_ack({w_pc_ack_cart_control, w_n64_ack_cart_control}),
.i_bank({w_pc_bank, w_n64_bank}),
.i_address({w_pc_address[12:2], w_n64_address[12:2]}),
.o_data({w_pc_i_data_cart_control, w_n64_i_data_cart_control}),
.i_data({w_pc_o_data, w_n64_o_data}),
.o_device_request(w_cart_control_request),
.o_device_write(w_cart_control_write),
.i_device_busy(w_cart_control_busy),
.i_device_ack(w_cart_control_ack),
.o_device_address(w_cart_control_address),
.i_device_data(w_cart_control_o_data),
.o_device_data(w_cart_control_i_data)
);
cart_control #(
.VERSION(`VERSION)
) cart_control_inst (
.i_clk(w_sys_clk),
.i_reset(w_sys_reset),
.i_n64_reset(i_n64_reset),
.i_n64_nmi(i_n64_nmi),
.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_sdram_writable(w_sdram_writable),
.o_rom_switch(w_rom_switch),
.o_ddipl_enable(w_ddipl_enable),
.o_sram_enable(w_sram_enable),
.o_sram_768k_mode(w_sram_768k_mode),
.o_flashram_enable(w_flashram_enable),
.o_sd_enable(w_sd_enable),
.o_eeprom_pi_enable(w_eeprom_pi_enable),
.o_eeprom_enable(w_eeprom_enable),
.o_eeprom_16k_mode(w_eeprom_16k_mode),
.o_n64_reset_btn(w_n64_reset_btn),
.i_debug_ready(1'b1),
.o_debug_dma_start(w_debug_dma_start),
.i_debug_dma_busy(w_debug_dma_busy),
.o_debug_dma_bank(w_debug_dma_bank),
.o_debug_dma_address(w_debug_dma_address),
.o_debug_dma_length(w_debug_dma_length),
.o_debug_fifo_request(w_debug_fifo_request),
.o_debug_fifo_flush(w_debug_fifo_flush),
.i_debug_fifo_items(w_debug_fifo_items),
.i_debug_fifo_data(w_debug_fifo_data),
.o_ddipl_address(w_ddipl_address),
.o_sram_address(w_sram_address)
);
// Embedded flash
wire w_embedded_flash_request_n64 = w_n64_request && !w_rom_switch && !w_n64_write && w_n64_bank == `BANK_SDRAM;
memory_embedded_flash memory_embedded_flash_inst (
.i_clk(w_sys_clk),
.i_reset(w_sys_reset),
.i_request(w_embedded_flash_request_n64),
.o_busy(w_n64_busy_embedded_flash),
.o_ack(w_n64_ack_embedded_flash),
.i_address(w_n64_address[20:2]),
.o_data(w_n64_i_data_embedded_flash)
);
// SD card
wire w_n64_request_sd = w_n64_request && w_n64_bank == `BANK_SD;
wire w_sd_dma_request;
wire w_sd_dma_write;
wire w_sd_dma_busy;
wire w_sd_dma_ack;
wire [3:0] w_sd_dma_bank;
wire [23:0] w_sd_dma_address;
wire [31:0] w_sd_dma_i_data;
wire [31:0] w_sd_dma_o_data;
wire w_sd_dma_busy_sdram;
wire w_sd_dma_ack_sdram;
wire [31:0] w_sd_dma_i_data_sdram;
wire w_sd_dma_busy_eeprom;
wire w_sd_dma_ack_eeprom;
wire [31:0] w_sd_dma_i_data_eeprom;
always @(*) begin
w_sd_dma_busy = w_sd_dma_busy_sdram || w_sd_dma_busy_eeprom;
w_sd_dma_ack = w_sd_dma_ack_sdram || w_sd_dma_ack_eeprom;
w_sd_dma_i_data = 32'h0000_0000;
if (w_sd_dma_ack_sdram) w_sd_dma_i_data = w_sd_dma_i_data_sdram;
if (w_sd_dma_ack_eeprom) w_sd_dma_i_data = w_sd_dma_i_data_eeprom;
end
sd_interface sd_interface_inst (
.i_clk(w_sys_clk),
.i_reset(w_sys_reset),
.o_sd_clk(o_sd_clk),
.io_sd_cmd(io_sd_cmd),
.io_sd_dat(io_sd_dat),
.i_request(w_n64_request_sd),
.i_write(w_n64_write),
.o_busy(w_n64_busy_sd),
.o_ack(w_n64_ack_sd),
.i_address({w_n64_address[9], w_n64_address[4:2]}),
.o_data(w_n64_i_data_sd),
.i_data(w_n64_o_data),
.o_dma_request(w_sd_dma_request),
.o_dma_write(w_sd_dma_write),
.i_dma_busy(w_sd_dma_busy),
.i_dma_ack(w_sd_dma_ack),
.o_dma_bank(w_sd_dma_bank),
.o_dma_address(w_sd_dma_address),
.i_dma_data(w_sd_dma_i_data),
.o_dma_data(w_sd_dma_o_data)
);
// SDRAM
wire w_sdram_request_n64 = w_n64_request && w_rom_switch && (!w_n64_write || (w_n64_write && (w_sdram_writable || w_sram_request)));
wire w_sdram_request;
wire w_sdram_write;
wire w_sdram_busy;
wire w_sdram_ack;
wire [24:0] w_sdram_address;
wire [31:0] w_sdram_o_data;
wire [31:0] w_sdram_i_data;
device_arbiter #(
.NUM_CONTROLLERS(3),
.ADDRESS_WIDTH(25),
.DEVICE_BANK(`BANK_SDRAM)
) device_arbiter_sdram_inst (
.i_clk(w_sys_clk),
.i_reset(w_sys_reset),
.i_request({w_sd_dma_request, w_pc_request, w_sdram_request_n64}),
.i_write({w_sd_dma_write, w_pc_write, w_n64_write}),
.o_busy({w_sd_dma_busy_sdram, w_pc_busy_sdram, w_n64_busy_sdram}),
.o_ack({w_sd_dma_ack_sdram, w_pc_ack_sdram, w_n64_ack_sdram}),
.i_bank({w_sd_dma_bank, w_pc_bank, w_n64_bank}),
.i_address({{w_sd_dma_address, 1'b0}, w_pc_address[25:1], w_n64_address[25:1]}),
.o_data({w_sd_dma_i_data_sdram, w_pc_i_data_sdram, w_n64_i_data_sdram}),
.i_data({w_sd_dma_o_data, w_pc_o_data, w_n64_o_data}),
.o_device_request(w_sdram_request),
.o_device_write(w_sdram_write),
.i_device_busy(w_sdram_busy),
.i_device_ack(w_sdram_ack),
.o_device_address(w_sdram_address),
.i_device_data(w_sdram_o_data),
.o_device_data(w_sdram_i_data)
);
memory_sdram memory_sdram_inst (
.i_clk(w_sys_clk),
.i_reset(w_sys_reset),
.o_sdram_cs(o_sdram_cs),
.o_sdram_ras(o_sdram_ras),
.o_sdram_cas(o_sdram_cas),
.o_sdram_we(o_sdram_we),
.o_sdram_ba(o_sdram_ba),
.o_sdram_a(o_sdram_a),
.io_sdram_dq(io_sdram_dq),
.i_request(w_sdram_request),
.i_write(w_sdram_write),
.o_busy(w_sdram_busy),
.o_ack(w_sdram_ack),
.i_address(w_sdram_address),
.o_data(w_sdram_o_data),
.i_data(w_sdram_i_data)
);
// EEPROM 4/16k
wire w_eeprom_request;
wire w_eeprom_write;
wire w_eeprom_busy;
wire w_eeprom_ack;
wire [8:0] w_eeprom_address;
wire [31:0] w_eeprom_o_data;
wire [31:0] w_eeprom_i_data;
device_arbiter #(
.NUM_CONTROLLERS(3),
.ADDRESS_WIDTH(9),
.DEVICE_BANK(`BANK_EEPROM)
) device_arbiter_eeprom_inst (
.i_clk(w_sys_clk),
.i_reset(w_sys_reset),
.i_request({w_sd_dma_request, w_pc_request, w_n64_request}),
.i_write({w_sd_dma_write, w_pc_write, w_n64_write}),
.o_busy({w_sd_dma_busy_eeprom, w_pc_busy_eeprom, w_n64_busy_eeprom}),
.o_ack({w_sd_dma_ack_eeprom, w_pc_ack_eeprom, w_n64_ack_eeprom}),
.i_bank({w_sd_dma_bank, w_pc_bank, w_n64_bank}),
.i_address({w_sd_dma_address[8:0], w_pc_address[10:2], w_n64_address[10:2]}),
.o_data({w_sd_dma_i_data_eeprom, w_pc_i_data_eeprom, w_n64_i_data_eeprom}),
.i_data({w_sd_dma_o_data, w_pc_o_data, w_n64_o_data}),
.o_device_request(w_eeprom_request),
.o_device_write(w_eeprom_write),
.i_device_busy(w_eeprom_busy),
.i_device_ack(w_eeprom_ack),
.o_device_address(w_eeprom_address),
.i_device_data(w_eeprom_o_data),
.o_device_data(w_eeprom_i_data)
);
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)
);
// LED
wire w_led_trigger = (w_n64_request && !w_n64_busy) || (w_pc_request && !w_pc_busy);
cart_led cart_led_inst (
.i_clk(w_sys_clk),
.i_reset(w_sys_reset),
.i_trigger(w_led_trigger),
.o_led(o_led)
);
endmodule

221
fw/rtl/usb/usb_ft1248.sv Normal file
View File

@ -0,0 +1,221 @@
module usb_ft1248 (
if_system.sys sys,
output usb_clk,
output usb_cs,
input usb_miso,
inout [3:0] usb_miosi,
input usb_pwren,
input rx_flush,
output rx_empty,
input rx_read,
output [7:0] rx_rdata,
input tx_flush,
output tx_full,
input tx_write,
input [7:0] tx_wdata
);
// FIFOs
logic rx_full;
logic rx_write;
logic [7:0] rx_wdata;
logic tx_empty;
logic tx_read;
logic [7:0] tx_rdata;
intel_fifo_8 fifo_8_rx_inst (
.clock(sys.clk),
.sclr(rx_flush),
.empty(rx_empty),
.rdreq(rx_read),
.q(rx_rdata),
.full(rx_full),
.wrreq(rx_write),
.data(rx_wdata)
);
intel_fifo_8 fifo_8_tx_inst (
.clock(sys.clk),
.sclr(tx_flush),
.empty(tx_empty),
.rdreq(tx_read),
.q(tx_rdata),
.full(tx_full),
.wrreq(tx_write),
.data(tx_wdata)
);
// FT1248 interface controller
typedef enum bit [1:0] {
S_TRY_RX,
S_TRY_TX,
S_COMMAND,
S_DATA
} e_state;
typedef enum bit [7:0] {
C_WRITE = 8'h00,
C_READ = 8'h04
} e_command;
typedef enum bit [1:0] {
P_PRE_RISING,
P_RISING,
P_PRE_FALLING,
P_FALLING
} e_clock_phase;
e_state state;
logic [3:0] clock_phase;
logic usb_clk_output;
logic usb_cs_output;
logic [3:0] usb_miosi_input;
logic [3:0] usb_miosi_output;
logic [3:0] usb_miosi_output_data;
logic usb_miosi_output_enable;
logic usb_miosi_output_enable_data;
logic usb_miso_input;
logic usb_pwren_input;
logic is_cmd_write;
logic [1:0] nibble_counter;
logic [7:0] tx_buffer;
always_ff @(posedge sys.clk) begin
if (sys.reset || state == S_TRY_RX || state == S_TRY_TX) begin
clock_phase <= 4'b0001;
end else begin
clock_phase <= {clock_phase[2:0], clock_phase[3]};
end
end
always_ff @(posedge sys.clk) begin
usb_clk <= usb_clk_output;
usb_cs <= usb_cs_output;
usb_miosi_input <= usb_miosi;
usb_miosi_output <= usb_miosi_output_data;
usb_miosi_output_enable <= usb_miosi_output_enable_data;
usb_miso_input <= usb_miso;
usb_pwren_input <= usb_pwren;
tx_buffer <= tx_rdata;
end
always_comb begin
usb_miosi = usb_miosi_output_enable ? usb_miosi_output : 4'bZZZZ;
end
always_comb begin
case (state)
S_COMMAND: begin
usb_clk_output = clock_phase[P_PRE_FALLING] || clock_phase[P_FALLING];
usb_cs_output = 1'b0;
if (is_cmd_write) begin
usb_miosi_output_data = nibble_counter[0] ? C_WRITE[3:0] : C_WRITE[7:4];
end else begin
usb_miosi_output_data = nibble_counter[0] ? C_READ[3:0] : C_READ[7:4];
end
usb_miosi_output_enable_data = nibble_counter < 2'd2;
end
S_DATA: begin
usb_clk_output = clock_phase[P_PRE_FALLING] || clock_phase[P_FALLING];
usb_cs_output = 1'b0;
usb_miosi_output_data = nibble_counter[0] ? tx_buffer[7:4] : tx_buffer[3:0];
usb_miosi_output_enable_data = is_cmd_write;
end
default: begin
usb_clk_output = 1'b0;
usb_cs_output = 1'b1;
usb_miosi_output_data = 4'hF;
usb_miosi_output_enable_data = 1'b0;
end
endcase
end
always_ff @(posedge sys.clk) begin
rx_write <= 1'b0;
tx_read <= 1'b0;
if (clock_phase[P_RISING]) begin
nibble_counter <= nibble_counter + 1'd1;
end
if (sys.reset) begin
state <= S_TRY_RX;
end else begin
case (state)
S_TRY_RX: begin
if (!rx_full) begin
state <= S_COMMAND;
is_cmd_write <= 1'b0;
nibble_counter <= 2'b11;
end else begin
state <= S_TRY_TX;
end
end
S_TRY_TX: begin
if (!tx_empty) begin
state <= S_COMMAND;
is_cmd_write <= 1'b1;
nibble_counter <= 2'b11;
end else begin
state <= S_TRY_RX;
end
end
S_COMMAND: begin
if (clock_phase[P_RISING]) begin
if (nibble_counter == 2'd2) begin
if (usb_miso_input) begin
state <= is_cmd_write ? S_TRY_RX : S_TRY_TX;
end else begin
state <= S_DATA;
nibble_counter <= 2'd0;
end
end
end
end
S_DATA: begin
if (clock_phase[P_FALLING]) begin
if (nibble_counter[0]) begin
tx_read <= is_cmd_write;
end
end
if (clock_phase[P_RISING]) begin
rx_wdata <= {usb_miosi_input, rx_wdata[7:4]};
if (nibble_counter[0]) begin
rx_write <= !is_cmd_write;
end
if (usb_miso_input || (!is_cmd_write && rx_full) || (is_cmd_write && tx_empty)) begin
state <= is_cmd_write ? S_TRY_RX : S_TRY_TX;
end
end
end
default: begin
state <= S_TRY_RX;
end
endcase
end
end
endmodule

View File

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

View File

@ -1,466 +0,0 @@
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,
input i_debug_start,
output o_debug_busy,
input [3:0] i_debug_bank,
input [23:0] i_debug_address,
input [19:0] i_debug_length,
input i_debug_fifo_request,
input i_debug_fifo_flush,
output [10:0] o_debug_fifo_items,
output [31:0] o_debug_fifo_data
);
// Module parameters
parameter byte VERSION = "a";
// 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)
);
// Debug FIFO
wire w_fifo_usb_full;
wire [9:0] w_fifo_usb_items;
reg r_fifo_usb_write_request;
reg [31:0] r_fifo_usb_data;
assign o_debug_fifo_items = {w_fifo_usb_full, w_fifo_usb_items};
fifo_usb fifo_usb_inst (
.clock(i_clk),
.sclr(i_debug_fifo_flush),
.full(w_fifo_usb_full),
.usedw(w_fifo_usb_items),
.wrreq(r_fifo_usb_write_request),
.data(r_fifo_usb_data),
.rdreq(i_debug_fifo_request),
.q(o_debug_fifo_data)
);
// Command ids
localparam byte CMD_TRIGGER [0:2] = '{"C", "M", "D"};
localparam byte CMD_IDENTIFY = "I";
localparam byte CMD_WRITE = "W";
localparam byte CMD_DEBUG_WRITE = "D";
localparam byte CMD_DEBUG_SEND = "Q";
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 (i_debug_start) begin
r_rx_stage <= RX_STAGE_IGNORE;
r_rx_cmd <= CMD_DEBUG_SEND;
r_tx_cmd <= CMD_DEBUG_SEND;
r_tx_cmd_valid <= 1'b1;
end
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[1:0]]) 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_WRITE: r_rx_stage <= RX_STAGE_PARAM;
CMD_DEBUG_WRITE: r_rx_stage <= RX_STAGE_PARAM;
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_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_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_rx_byte_counter == 3'd3) begin
if (r_data_items_remaining == 20'd0) begin
r_rx_stage <= RX_STAGE_CMD;
end
r_rx_byte_counter <= 3'd0;
r_rx_buffer_valid <= 1'b1;
end
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
always @(posedge i_clk) begin
if (i_reset) begin
end else begin
if (r_rx_param_valid) begin
case (r_rx_cmd)
CMD_WRITE: begin
o_address <= {r_rx_buffer[57:34], 2'b00};
o_bank <= r_rx_buffer[27:24];
r_data_items_remaining <= r_rx_buffer[19:0];
end
CMD_DEBUG_WRITE: begin
r_data_items_remaining <= r_rx_buffer[19:0];
end
endcase
end
if (r_tx_cmd_valid && r_tx_cmd == CMD_DEBUG_SEND) begin
o_bank <= i_debug_bank;
o_address <= {i_debug_address, 2'b00};
r_data_items_remaining <= i_debug_length;
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
if (r_fifo_usb_write_request && r_data_items_remaining > 20'd0) begin
r_data_items_remaining <= r_data_items_remaining - 1'd1;
end
end
end
// TX module
localparam byte IDENTIFY_STRING [0:3] = '{"S", "6", "4", VERSION};
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_DEBUG_SEND: r_ftdi_tx_data = r_i_data_buffer[(((4 - r_tx_byte_counter) * 8) - 1) -: 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;
reg r_bus_data_request;
reg r_bus_data_valid;
reg r_bus_data_feisable;
assign o_debug_busy = r_tx_stage == TX_STAGE_DATA && r_tx_cmd == CMD_DEBUG_SEND;
always @(posedge i_clk) begin
r_ftdi_tx_valid <= 1'b0;
r_tx_done <= 1'b0;
r_bus_data_request <= 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
case (r_tx_cmd)
CMD_IDENTIFY: begin
r_tx_stage <= TX_STAGE_DATA;
r_ftdi_tx_valid <= 1'b1;
end
CMD_DEBUG_SEND: begin
r_bus_data_request <= 1'b1;
r_tx_stage <= TX_STAGE_DATA;
end
default: begin
r_tx_stage <= TX_STAGE_RESPONSE;
r_ftdi_tx_valid <= 1'b1;
end
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
endcase
end
if (r_tx_cmd == CMD_DEBUG_SEND) begin
r_ftdi_tx_valid <= 1'b0;
if (r_bus_data_valid) begin
r_bus_data_feisable <= 1'b1;
end
if (r_bus_data_feisable) begin
r_ftdi_tx_valid <= 1'b1;
end
if (w_tx_successful) begin
if (r_tx_byte_counter == 2'd3 && r_bus_data_feisable) begin
r_bus_data_request <= 1'b1;
r_bus_data_feisable <= 1'b0;
end
end
if (w_tx_successful && r_data_items_remaining == 20'd0 && r_tx_byte_counter == 2'd3) begin
r_bus_data_request <= 1'b0;
r_tx_stage <= TX_STAGE_IDLE;
r_tx_done <= 1'b1;
r_bus_data_feisable <= 1'b0;
end
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;
r_bus_data_valid <= 1'b0;
r_fifo_usb_write_request <= 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
CMD_DEBUG_WRITE: begin
if (r_rx_buffer_valid) begin
r_fifo_usb_data <= r_rx_buffer[31:0];
r_fifo_usb_write_request <= 1'b1;
end
if (w_fifo_usb_full) begin
r_ftdi_rx_ready <= 1'b0;
end else begin
r_ftdi_rx_ready <= 1'b1;
end
end
endcase
if (r_bus_data_request) begin
o_request <= 1'b1;
end
if (o_request && i_busy) begin
o_request <= 1'b1;
end
if (i_ack) begin
r_i_data_buffer <= i_data;
r_bus_data_valid <= 1'b1;
end
end
end
endmodule

View File

View File

View File

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

View File

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

View File

@ -1,3 +0,0 @@
#!/bin/bash
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"

View File

@ -1,45 +0,0 @@
#include <stdio.h>
#include "error_display.h"
void error_display_and_halt(menu_load_error_t error, const char *path) {
init_interrupts();
display_init(RESOLUTION_320x240, DEPTH_32_BPP, 2, GAMMA_NONE, ANTIALIAS_RESAMPLE);
console_init();
console_set_render_mode(RENDER_MANUAL);
console_clear();
printf("SC64 Bootloader ver. %d.%02d error:\n\n%2d: ", BOOTLOADER_VERSION_MAJOR, BOOTLOADER_VERSION_MINOR, error);
switch (error) {
case E_MENU_OK:
printf("No error :O");
break;
case E_MENU_ERROR_NOT_SC64:
printf("SummerCart64 not detected");
break;
case E_MENU_ERROR_NO_CARD:
printf("SD Card not detected");
break;
case E_MENU_ERROR_NO_FILESYSTEM:
printf("No filesystem (FAT or exFAT)\nfound on SD Card");
break;
case E_MENU_ERROR_NO_FILE:
printf("Unable to locate menu file:\n(%s)", path);
break;
case E_MENU_ERROR_READ_ERROR:
printf("Error while reading data from\nSD Card");
break;
case E_MENU_ERROR_OTHER_ERROR:
default:
printf("Unknown error");
break;
}
console_render();
while (1);
}

View File

@ -1,22 +0,0 @@
#ifndef ERROR_DISPLAY_H__
#define ERROR_DISPLAY_H__
#include "platform.h"
typedef enum menu_load_error_e {
E_MENU_OK,
E_MENU_ERROR_NOT_SC64,
E_MENU_ERROR_NO_CARD,
E_MENU_ERROR_NO_FILESYSTEM,
E_MENU_ERROR_NO_FILE,
E_MENU_ERROR_READ_ERROR,
E_MENU_ERROR_OTHER_ERROR,
} menu_load_error_t;
void error_display_and_halt(menu_load_error_t error, const char *path);
#endif

View File

@ -1,346 +0,0 @@
----------------------------------------------------------------------------
Revision history of FatFs module
----------------------------------------------------------------------------
R0.00 (February 26, 2006)
Prototype.
R0.01 (April 29, 2006)
The first release.
R0.02 (June 01, 2006)
Added FAT12 support.
Removed unbuffered mode.
Fixed a problem on small (<32M) partition.
R0.02a (June 10, 2006)
Added a configuration option (_FS_MINIMUM).
R0.03 (September 22, 2006)
Added f_rename().
Changed option _FS_MINIMUM to _FS_MINIMIZE.
R0.03a (December 11, 2006)
Improved cluster scan algorithm to write files fast.
Fixed f_mkdir() creates incorrect directory on FAT32.
R0.04 (February 04, 2007)
Added f_mkfs().
Supported multiple drive system.
Changed some interfaces for multiple drive system.
Changed f_mountdrv() to f_mount().
R0.04a (April 01, 2007)
Supported multiple partitions on a physical drive.
Added a capability of extending file size to f_lseek().
Added minimization level 3.
Fixed an endian sensitive code in f_mkfs().
R0.04b (May 05, 2007)
Added a configuration option _USE_NTFLAG.
Added FSINFO support.
Fixed DBCS name can result FR_INVALID_NAME.
Fixed short seek (<= csize) collapses the file object.
R0.05 (August 25, 2007)
Changed arguments of f_read(), f_write() and f_mkfs().
Fixed f_mkfs() on FAT32 creates incorrect FSINFO.
Fixed f_mkdir() on FAT32 creates incorrect directory.
R0.05a (February 03, 2008)
Added f_truncate() and f_utime().
Fixed off by one error at FAT sub-type determination.
Fixed btr in f_read() can be mistruncated.
Fixed cached sector is not flushed when create and close without write.
R0.06 (April 01, 2008)
Added fputc(), fputs(), fprintf() and fgets().
Improved performance of f_lseek() on moving to the same or following cluster.
R0.07 (April 01, 2009)
Merged Tiny-FatFs as a configuration option. (_FS_TINY)
Added long file name feature. (_USE_LFN)
Added multiple code page feature. (_CODE_PAGE)
Added re-entrancy for multitask operation. (_FS_REENTRANT)
Added auto cluster size selection to f_mkfs().
Added rewind option to f_readdir().
Changed result code of critical errors.
Renamed string functions to avoid name collision.
R0.07a (April 14, 2009)
Septemberarated out OS dependent code on reentrant cfg.
Added multiple sector size feature.
R0.07c (June 21, 2009)
Fixed f_unlink() can return FR_OK on error.
Fixed wrong cache control in f_lseek().
Added relative path feature.
Added f_chdir() and f_chdrive().
Added proper case conversion to extended character.
R0.07e (November 03, 2009)
Septemberarated out configuration options from ff.h to ffconf.h.
Fixed f_unlink() fails to remove a sub-directory on _FS_RPATH.
Fixed name matching error on the 13 character boundary.
Added a configuration option, _LFN_UNICODE.
Changed f_readdir() to return the SFN with always upper case on non-LFN cfg.
R0.08 (May 15, 2010)
Added a memory configuration option. (_USE_LFN = 3)
Added file lock feature. (_FS_SHARE)
Added fast seek feature. (_USE_FASTSEEK)
Changed some types on the API, XCHAR->TCHAR.
Changed .fname in the FILINFO structure on Unicode cfg.
String functions support UTF-8 encoding files on Unicode cfg.
R0.08a (August 16, 2010)
Added f_getcwd(). (_FS_RPATH = 2)
Added sector erase feature. (_USE_ERASE)
Moved file lock semaphore table from fs object to the bss.
Fixed f_mkfs() creates wrong FAT32 volume.
R0.08b (January 15, 2011)
Fast seek feature is also applied to f_read() and f_write().
f_lseek() reports required table size on creating CLMP.
Extended format syntax of f_printf().
Ignores duplicated directory separators in given path name.
R0.09 (September 06, 2011)
f_mkfs() supports multiple partition to complete the multiple partition feature.
Added f_fdisk().
R0.09a (August 27, 2012)
Changed f_open() and f_opendir() reject null object pointer to avoid crash.
Changed option name _FS_SHARE to _FS_LOCK.
Fixed assertion failure due to OS/2 EA on FAT12/16 volume.
R0.09b (January 24, 2013)
Added f_setlabel() and f_getlabel().
R0.10 (October 02, 2013)
Added selection of character encoding on the file. (_STRF_ENCODE)
Added f_closedir().
Added forced full FAT scan for f_getfree(). (_FS_NOFSINFO)
Added forced mount feature with changes of f_mount().
Improved behavior of volume auto detection.
Improved write throughput of f_puts() and f_printf().
Changed argument of f_chdrive(), f_mkfs(), disk_read() and disk_write().
Fixed f_write() can be truncated when the file size is close to 4GB.
Fixed f_open(), f_mkdir() and f_setlabel() can return incorrect value on error.
R0.10a (January 15, 2014)
Added arbitrary strings as drive number in the path name. (_STR_VOLUME_ID)
Added a configuration option of minimum sector size. (_MIN_SS)
2nd argument of f_rename() can have a drive number and it will be ignored.
Fixed f_mount() with forced mount fails when drive number is >= 1. (appeared at R0.10)
Fixed f_close() invalidates the file object without volume lock.
Fixed f_closedir() returns but the volume lock is left acquired. (appeared at R0.10)
Fixed creation of an entry with LFN fails on too many SFN collisions. (appeared at R0.07)
R0.10b (May 19, 2014)
Fixed a hard error in the disk I/O layer can collapse the directory entry.
Fixed LFN entry is not deleted when delete/rename an object with lossy converted SFN. (appeared at R0.07)
R0.10c (November 09, 2014)
Added a configuration option for the platforms without RTC. (_FS_NORTC)
Changed option name _USE_ERASE to _USE_TRIM.
Fixed volume label created by Mac OS X cannot be retrieved with f_getlabel(). (appeared at R0.09b)
Fixed a potential problem of FAT access that can appear on disk error.
Fixed null pointer dereference on attempting to delete the root direcotry. (appeared at R0.08)
R0.11 (February 09, 2015)
Added f_findfirst(), f_findnext() and f_findclose(). (_USE_FIND)
Fixed f_unlink() does not remove cluster chain of the file. (appeared at R0.10c)
Fixed _FS_NORTC option does not work properly. (appeared at R0.10c)
R0.11a (September 05, 2015)
Fixed wrong media change can lead a deadlock at thread-safe configuration.
Added code page 771, 860, 861, 863, 864, 865 and 869. (_CODE_PAGE)
Removed some code pages actually not exist on the standard systems. (_CODE_PAGE)
Fixed errors in the case conversion teble of code page 437 and 850 (ff.c).
Fixed errors in the case conversion teble of Unicode (cc*.c).
R0.12 (April 12, 2016)
Added support for exFAT file system. (_FS_EXFAT)
Added f_expand(). (_USE_EXPAND)
Changed some members in FINFO structure and behavior of f_readdir().
Added an option _USE_CHMOD.
Removed an option _WORD_ACCESS.
Fixed errors in the case conversion table of Unicode (cc*.c).
R0.12a (July 10, 2016)
Added support for creating exFAT volume with some changes of f_mkfs().
Added a file open method FA_OPEN_APPEND. An f_lseek() following f_open() is no longer needed.
f_forward() is available regardless of _FS_TINY.
Fixed f_mkfs() creates wrong volume. (appeared at R0.12)
Fixed wrong memory read in create_name(). (appeared at R0.12)
Fixed compilation fails at some configurations, _USE_FASTSEEK and _USE_FORWARD.
R0.12b (September 04, 2016)
Made f_rename() be able to rename objects with the same name but case.
Fixed an error in the case conversion teble of code page 866. (ff.c)
Fixed writing data is truncated at the file offset 4GiB on the exFAT volume. (appeared at R0.12)
Fixed creating a file in the root directory of exFAT volume can fail. (appeared at R0.12)
Fixed f_mkfs() creating exFAT volume with too small cluster size can collapse unallocated memory. (appeared at R0.12)
Fixed wrong object name can be returned when read directory at Unicode cfg. (appeared at R0.12)
Fixed large file allocation/removing on the exFAT volume collapses allocation bitmap. (appeared at R0.12)
Fixed some internal errors in f_expand() and f_lseek(). (appeared at R0.12)
R0.12c (March 04, 2017)
Improved write throughput at the fragmented file on the exFAT volume.
Made memory usage for exFAT be able to be reduced as decreasing _MAX_LFN.
Fixed successive f_getfree() can return wrong count on the FAT12/16 volume. (appeared at R0.12)
Fixed configuration option _VOLUMES cannot be set 10. (appeared at R0.10c)
R0.13 (May 21, 2017)
Changed heading character of configuration keywords "_" to "FF_".
Removed ASCII-only configuration, FF_CODE_PAGE = 1. Use FF_CODE_PAGE = 437 instead.
Added f_setcp(), run-time code page configuration. (FF_CODE_PAGE = 0)
Improved cluster allocation time on stretch a deep buried cluster chain.
Improved processing time of f_mkdir() with large cluster size by using FF_USE_LFN = 3.
Improved NoFatChain flag of the fragmented file to be set after it is truncated and got contiguous.
Fixed archive attribute is left not set when a file on the exFAT volume is renamed. (appeared at R0.12)
Fixed exFAT FAT entry can be collapsed when write or lseek operation to the existing file is done. (appeared at R0.12c)
Fixed creating a file can fail when a new cluster allocation to the exFAT directory occures. (appeared at R0.12c)
R0.13a (October 14, 2017)
Added support for UTF-8 encoding on the API. (FF_LFN_UNICODE = 2)
Added options for file name output buffer. (FF_LFN_BUF, FF_SFN_BUF).
Added dynamic memory allocation option for working buffer of f_mkfs() and f_fdisk().
Fixed f_fdisk() and f_mkfs() create the partition table with wrong CHS parameters. (appeared at R0.09)
Fixed f_unlink() can cause lost clusters at fragmented file on the exFAT volume. (appeared at R0.12c)
Fixed f_setlabel() rejects some valid characters for exFAT volume. (appeared at R0.12)
R0.13b (April 07, 2018)
Added support for UTF-32 encoding on the API. (FF_LFN_UNICODE = 3)
Added support for Unix style volume ID. (FF_STR_VOLUME_ID = 2)
Fixed accesing any object on the exFAT root directory beyond the cluster boundary can fail. (appeared at R0.12c)
Fixed f_setlabel() does not reject some invalid characters. (appeared at R0.09b)
R0.13c (October 14, 2018)
Supported stdint.h for C99 and later. (integer.h was included in ff.h)
Fixed reading a directory gets infinite loop when the last directory entry is not empty. (appeared at R0.12)
Fixed creating a sub-directory in the fragmented sub-directory on the exFAT volume collapses FAT chain of the parent directory. (appeared at R0.12)
Fixed f_getcwd() cause output buffer overrun when the buffer has a valid drive number. (appeared at R0.13b)
R0.14 (October 14, 2019)
Added support for 64-bit LBA and GUID partition table (FF_LBA64 = 1)
Changed some API functions, f_mkfs() and f_fdisk().
Fixed f_open() function cannot find the file with file name in length of FF_MAX_LFN characters.
Fixed f_readdir() function cannot retrieve long file names in length of FF_MAX_LFN - 1 characters.
Fixed f_readdir() function returns file names with wrong case conversion. (appeared at R0.12)
Fixed f_mkfs() function can fail to create exFAT volume in the second partition. (appeared at R0.12)
R0.14a (December 5, 2020)
Limited number of recursive calls in f_findnext().
Fixed old floppy disks formatted with MS-DOS 2.x and 3.x cannot be mounted.
Fixed some compiler warnings.

View File

@ -1,21 +0,0 @@
FatFs Module Source Files R0.14a
FILES
00readme.txt This file.
00history.txt Revision history.
ff.c FatFs module.
ffconf.h Configuration file of FatFs module.
ff.h Common include file for FatFs and application module.
diskio.h Common include file for FatFs and disk I/O module.
diskio.c An example of glue function to attach existing disk I/O module to FatFs.
ffunicode.c Optional Unicode utility functions.
ffsystem.c An example of optional O/S related functions.
Low level disk I/O module is not included in this archive because the FatFs
module is only a generic file system layer and it does not depend on any specific
storage device. You need to provide a low level disk I/O module written to
control the storage device that attached to the target system.

View File

@ -1,53 +0,0 @@
#include "ff.h"
#include "diskio.h"
#include "sc64_sd.h"
DSTATUS disk_status(BYTE pdrv) {
if (pdrv > 0) {
return STA_NOINIT;
}
return sc64_sd_get_status() ? 0 : STA_NOINIT;
}
DSTATUS disk_initialize(BYTE pdrv) {
if (pdrv > 0) {
return STA_NOINIT;
}
if (!sc64_sd_get_status()) {
if (sc64_sd_init()) {
return 0;
}
} else {
return 0;
}
return STA_NOINIT;
}
DRESULT disk_read(BYTE pdrv, BYTE *buff, LBA_t sector, UINT count) {
sc64_sd_err_t error;
if ((pdrv > 0) || (count == 0)) {
return RES_PARERR;
}
if (!sc64_sd_get_status()) {
return RES_NOTRDY;
}
error = sc64_sd_read_sectors(sector, count, buff);
if (error != E_OK) {
return RES_ERROR;
}
return RES_OK;
}
DRESULT disk_ioctl(BYTE pdrv, BYTE cmd, void *buff) {
return RES_PARERR;
}

View File

@ -1,77 +0,0 @@
/*-----------------------------------------------------------------------/
/ Low level disk interface modlue include file (C)ChaN, 2019 /
/-----------------------------------------------------------------------*/
#ifndef _DISKIO_DEFINED
#define _DISKIO_DEFINED
#ifdef __cplusplus
extern "C" {
#endif
/* Status of Disk Functions */
typedef BYTE DSTATUS;
/* Results of Disk Functions */
typedef enum {
RES_OK = 0, /* 0: Successful */
RES_ERROR, /* 1: R/W Error */
RES_WRPRT, /* 2: Write Protected */
RES_NOTRDY, /* 3: Not Ready */
RES_PARERR /* 4: Invalid Parameter */
} DRESULT;
/*---------------------------------------*/
/* Prototypes for disk control functions */
DSTATUS disk_initialize (BYTE pdrv);
DSTATUS disk_status (BYTE pdrv);
DRESULT disk_read (BYTE pdrv, BYTE* buff, LBA_t sector, UINT count);
DRESULT disk_write (BYTE pdrv, const BYTE* buff, LBA_t sector, UINT count);
DRESULT disk_ioctl (BYTE pdrv, BYTE cmd, void* buff);
/* Disk Status Bits (DSTATUS) */
#define STA_NOINIT 0x01 /* Drive not initialized */
#define STA_NODISK 0x02 /* No medium in the drive */
#define STA_PROTECT 0x04 /* Write protected */
/* Command code for disk_ioctrl fucntion */
/* Generic command (Used by FatFs) */
#define CTRL_SYNC 0 /* Complete pending write process (needed at FF_FS_READONLY == 0) */
#define GET_SECTOR_COUNT 1 /* Get media size (needed at FF_USE_MKFS == 1) */
#define GET_SECTOR_SIZE 2 /* Get sector size (needed at FF_MAX_SS != FF_MIN_SS) */
#define GET_BLOCK_SIZE 3 /* Get erase block size (needed at FF_USE_MKFS == 1) */
#define CTRL_TRIM 4 /* Inform device that the data on the block of sectors is no longer used (needed at FF_USE_TRIM == 1) */
/* Generic command (Not used by FatFs) */
#define CTRL_POWER 5 /* Get/Set power status */
#define CTRL_LOCK 6 /* Lock/Unlock media removal */
#define CTRL_EJECT 7 /* Eject media */
#define CTRL_FORMAT 8 /* Create physical format on the media */
/* MMC/SDC specific ioctl command */
#define MMC_GET_TYPE 10 /* Get card type */
#define MMC_GET_CSD 11 /* Get CSD */
#define MMC_GET_CID 12 /* Get CID */
#define MMC_GET_OCR 13 /* Get OCR */
#define MMC_GET_SDSTAT 14 /* Get SD status */
#define ISDIO_READ 55 /* Read data form SD iSDIO register */
#define ISDIO_WRITE 56 /* Write data to SD iSDIO register */
#define ISDIO_MRITE 57 /* Masked write data to SD iSDIO register */
/* ATA/CF specific ioctl command */
#define ATA_GET_REV 20 /* Get F/W revision */
#define ATA_GET_MODEL 21 /* Get model name */
#define ATA_GET_SN 22 /* Get serial number */
#ifdef __cplusplus
}
#endif
#endif

Some files were not shown because too many files have changed in this diff Show More