[SC64][FW][HW][SW] New version based on LCMXO2 FPGA (#19)

* isv support + usb/dd improvements

* make room for saves

* update offset

* fixed debug address

* idk

* exception

* ironed out all broken stuff

* cleanup

* return epc fix

* better

* more cleanup

* even more cleanup

* mooore cleanup

* fixed printf

* no assert

* improved docker build, pyft232 instead of pyserial

* fixed displaying long message strings

description test

* just straight cleanup

* smallest cleanup

* PAL

* cpu buffer

* n64 bootloader done

* super slow usb storage reading implemented

* reduced buffer size

* usb gets fast

* little cleanup

* double buffered reads

* removed separate event id

* ISV in hardware finally

* small exception changes

* mac testing

* py spacing

* fsd write, rtc, isv and reset fixes

* fixxx

* good stopping point

* usb fixed?

* pretend we have 128 MB sdram

* backup

* chmod

* test

* test done

* more tests

* user rm

* help

* final fix

* updated component values

* nice asset names

* cic 64dd support

* ddipl enable separation

* pre DMA rewrite, created dedicated buffer memory space, simplified code

* dma rewrite, needs testing

* moved xml

* dd basics

* timing

* 64dd working yet again, isv brought back, dma fixes, usb path rewrite, pc code rewrite

* added usb read functionality, general cleanup

* changed mem addressing

* added fpga flash update access

* added mcu update

* chmod

* little cleanup

* update format and stuff

* fixes

* uninitialized fix

* small fixes

* update fixes

* update stuff done

* fpga update tested

* build time fix

* boot fix

* test timing

* readme test

* test 2

* reports

* testseet

* final

* build test

* forgot

* button and naming

* General cleanup

And multiline commit message test

* Exception screen UI touch ups

* display separation and tests beginning

* pc software update

* pc software done

* timing test

* delete launch.json

* sw fixes

* fixed button hole diameter in shell

* small cleanup, rpi testing

* shell fillet fix, pc rtc printing

* added cfg lock mechanism

* moved lock to cfg address space

* extended ROM and ISV fixes

* preliminary sd card support

* little sd card cleanup

* sd menu fixes

* 5 second limit

* reduced shell thickness

* basic led act blinking

* faster sd menu loading

* inst cache invalidate

* sd card writing is working

* SD card CSD and CID registers

* wait for previous command

* led error codes

* fixed cfg_translate_address use

* 64dd from sd card working

* 64dd speedup and button handling

* delayed address latching cycle - might break other builds, needs testing

* bootloader improvements

* small fixes

* return previous cfg when setting new

* cache stuff

* unfloader debug protocol support

* UNFLoader style debug command line support

* requirements.txt

* shell groove fillet

* reset state inside controller

* fixed fast PI read, added PI R/W fifo debug info

* PI access prioritize

* SD clock stop when RX FIFO is more than half full

* flash erase method change

* CFG error handling, TLOZ MM debug ISV support

* CIC5167 support

* general fixes

* USB unplugged cable handling

* turn off led when changing between error/act modes

* rtc 2 bit clock stop support

* line endings

* Revert "line endings"

This reverts commit d0ddfe5ec7.

* PI address debug

* readme test

* diagram update

* diagram background

* diagram background

* diagram background

* updated readme
This commit is contained in:
Mateusz Faderewski 2022-11-10 11:46:54 +01:00 committed by GitHub
parent 92e5c5747b
commit ff69030643
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
256 changed files with 101725 additions and 35434 deletions

1
.github/FUNDING.yml vendored
View File

@ -1 +0,0 @@
ko_fi: polprzewodnikowy

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 MiB

4
.github/sc64_v2_block_diagram.svg vendored Normal file

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 92 KiB

BIN
.github/sc64_v2_example.jpg vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

View File

@ -20,15 +20,25 @@ jobs:
- uses: actions/checkout@v2
with:
submodules: true
- name: Prepare Lattice Diamond license
env:
ENCODED_LICENSE: ${{ secrets.LATTICE_DIAMOND_LICENSE }}
run: |
mkdir -p ./flexlm
echo "$ENCODED_LICENSE" > ./flexlm/encoded_license
base64 -d ./flexlm/encoded_license > ./flexlm/license.dat
- name: Build script
env:
MAC_ADDRESS: ${{ secrets.LATTICE_DIAMOND_MAC }}
run: ./docker_build.sh release --force-clean
- name: Upload artifact
uses: actions/upload-artifact@v2
with:
name: SummerCart64
path: SummerCart64.zip
name: SC64
path: SC64.zip
- name: Get release
if: github.event_name == 'release' && github.event.action == 'created'
@ -44,6 +54,6 @@ jobs:
GITHUB_TOKEN: ${{ github.token }}
with:
upload_url: ${{ steps.get_release.outputs.upload_url }}
asset_path: SummerCart64.zip
asset_name: SummerCart64.zip
asset_path: SC64.zip
asset_name: SC64.zip
asset_content_type: application/zip

5
.gitignore vendored
View File

@ -1,4 +1,7 @@
**/.DS_Store
**/.vscode
**/.vscode/
**/*.bak
**/*.zip
/flexlm
!**/.vscode/tasks.json

8
.gitmodules vendored
View File

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

73
.vscode/tasks.json vendored Normal file
View File

@ -0,0 +1,73 @@
{
"version": "2.0.0",
"tasks": [
{
"label": "build_bootloader",
"type": "shell",
"command": "./docker_build.sh bootloader",
"presentation": {
"showReuseMessage": false,
"clear": true
},
"windows": {
"command": "wsl -- ./docker_build.sh bootloader"
},
"group": "build"
},
{
"label": "build_controller",
"type": "shell",
"command": "./docker_build.sh controller",
"presentation": {
"showReuseMessage": false,
"clear": true
},
"windows": {
"command": "wsl -- ./docker_build.sh controller"
},
"group": "build"
},
{
"label": "build_fpga",
"type": "shell",
"command": "./docker_build.sh fpga",
"presentation": {
"showReuseMessage": false,
"clear": true
},
"windows": {
"command": "wsl -- ./docker_build.sh fpga"
},
"group": "build"
},
{
"label": "build_update",
"type": "shell",
"command": "./docker_build.sh update",
"presentation": {
"showReuseMessage": false,
"clear": true
},
"windows": {
"command": "wsl -- ./docker_build.sh update"
},
"group": {
"kind": "build",
"isDefault": true
}
},
{
"label": "build_release",
"type": "shell",
"command": "./docker_build.sh release --force-clean",
"presentation": {
"showReuseMessage": false,
"clear": true
},
"windows":{
"command": "wsl -- ./docker_build.sh release --force-clean"
},
"group": "build"
},
]
}

View File

@ -1,78 +1,29 @@
# SummerCollection
A collection of hardware, firmware and software designs of SummerCart64 - Nintendo 64 FlashCart/DevKit.
# SC64 - an open source Nintendo 64 flashcart
## Project parts
### Firmware
Folder **`fw`** contains firmware written in Verilog for Intel MAX10 FPGA.
### Hardware
Folder **`hw`** contains PCB design made in Autodesk Eagle.
### Software
Folder **`sw`** contains several helper programs that makes flash cart work all together, including bootloader and CIC emulation.
## Features
- 64 MB SDRAM memory for game and save data
- 16 MB FLASH memory for bootloader and extended game data
- 8 kB on-chip buffer for general use
- 25 MB/s peak transfer rate USB interface for data upload/download and debug functionality
- 25 MB/s peak transfer rate SD card interface
- EEPROM, SRAM and FlashRAM save types ~~with automatic writeback to SD card~~ (_not implemented yet_)
- Battery backed real time clock (RTC)
- Status LED and button for general use
- 64DD add-on emulation
- IS-Viewer 64 debug interface
- Software and firmware update via USB interface
- N64 bootloader with support for IPL2 registers spoofing and loading menu from SD card
- Enhanced [UltraCIC_C](https://github.com/jago85/UltraCIC_C) emulation with automatic region switching and programmable seed/checksum values
- PC app for communicating with flashcart (game/save data upload/download, feature enable control and debug console)
- [UNFLoader](https://github.com/buu342/N64-UNFLoader) support
## What works
## High-level flashcart block diagram
### **OLD STATUS, WILL BE UPDATED SOON**
~~Currently hardware implements basic functionality for playing games - ROM emulation, 4/16K EEPROM, bootloader and PC communication. You can send any ROM to the SDRAM from PC and if game doesn't check for save hardware other than EEPROM then it most likely will work. Bootloader does all the work necessary to setup the console registers for specific CIC chip that game requires.~~
[<img src=".github/sc64_v2_block_diagram.svg" width="800" />](.github/sc64_v2_block_diagram.svg)
## How to build
## Finished sample
### **OLD INSTRUCTIONS, WILL BE UPDATED SOON**
~~Instructions below are mostly written for Windows users and point to Windows specific executables.~~
1. ~~Download latest zip files from [releases tab](https://github.com/Polprzewodnikowy/SummerCollection/releases).~~
2. ~~Order PCBs in your farovite company, all gerbers, bill of materials and schematics are in **`SummerCart64_PCB-[version].zip`** file.~~
3. ~~Order all necessary components, eg. in [Mouser](https://mouser.com/).~~
4. ~~Solder all components onto the PCB.~~
5. ~~Connect flashcart to PC.~~
6. ~~Download [FT_PROG](https://www.ftdichip.com/Support/Utilities.htm#FT_PROG) from FTDI website.~~
7. ~~Open FT_PROG and scan for devices.~~
8. ~~Load `ftdi-template.xml` from **`SummerCart64-[version].zip`** located in `hw` folder.~~
9. ~~Program FTDI chip, then right click on the device and select "Cycle port"~~
10. ~~Download and install [Arrow USB Blaster drivers](https://shop.trenz-electronic.de/en/Download/?path=Trenz_Electronic/Software/Drivers/Arrow_USB_Programmer/Arrow_USB_Programmer_2.4) from Trenz Electronic website.~~
11. ~~Download and install [QuartusProgrammer](https://download.altera.com/akdlm/software/acdsinst/20.1std/711/ib_installers/QuartusProgrammerSetup-20.1.0.711-windows.exe) from Intel website.~~
12. ~~Click on "Hardware Setup..." button and select "Arrow-USB-Blaster [AR*xxxxxx*]" in "Currently selected hardware", then close window.~~
13. ~~Click on "Auto Detect" button and select "10M08SC" option.~~
14. ~~Click on the newly shown row, then click on "Change File..." button and select `SummerCart64.pof` file from **`SummerCart64-[version].zip`** located in `fw/output_files` folder.~~
15. ~~Select "Program/Configure" and "Verify" checkboxes.~~
16. ~~Click on "Start" button and wait for operation to finish.~~
17. ~~Download and install avrdude.~~
18. ~~Program ATtiny45 with `UltraCIC-III.hex` file from **`SummerCart64-[version].zip`** located in `sw/cic` folder, more information is available [here](https://github.com/ManCloud/UltraCIC-III).~~
19. ~~Download latest release of [N64-UNFLoader](https://github.com/buu342/N64-UNFLoader).~~
20. ~~Insert flashcart in the Nintendo 64.~~
21. ~~Upload ROM by executing `UNFLoader -r your_rom_file.n64`~~
22. ~~Turn on console and enjoy playing homebrew games on real hardware.~~
## Issues
### **OLD STATUS, WILL BE UPDATED SOON**
~~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 save write-back to SD card without console reset implementation.~~
## What's next
Current goal is to rewrite README.md
## Finished sample (obsolete v1 version, to be replaced with v2)
![SummerCart64 clean PCB](.github/sc64_clean_pcb.jpg)
![SummerCart64 on table](.github/sc64_on_table.jpg)
![SummerCart64 in partialy disassembled Nintendo 64](.github/sc64_in_n64.jpg)
[<img src=".github/sc64_v2_example.jpg" alt="SC64 HW ver: 2.0" width="800" />](.github/sc64_v2_example.jpg)

BIN
assets/sc64_logo.blend Normal file

Binary file not shown.

148
build.sh
View File

@ -2,80 +2,66 @@
set -e
PACKAGE_FILE_NAME="SummerCart64"
PACKAGE_FILE_NAME="SC64"
FILES=(
"./fw/output_files/SC64_firmware.pof"
"./fw/output_files/SC64_update.bin"
"./hw/ftdi-template.xml"
"./sw/cic/UltraCIC-III.hex"
"./fw/ftdi/ft232h_config.xml"
"./fw/project/lcmxo2/impl1/sc64_impl1.mrp"
"./fw/project/lcmxo2/impl1/sc64_impl1.twr"
"./sw/pc/dd64.py"
"./sw/pc/sc64.py"
"./sw/update/sc64.upd"
"./LICENSE"
"./README.md"
)
BUILT_CIC=false
BUILT_N64=false
BUILT_RISCV=false
BUILT_BOOTLOADER=false
BUILT_CONTROLLER=false
BUILT_FPGA=false
BUILT_UPDATE=false
BUILT_RELEASE=false
FORCE_CLEAN=false
SKIP_FPGA_REBUILD=false
DEBUG_ENABLED=false
USER_FLAGS+=" -D__SC64_VERSION=\"$__SC64_VERSION\""
build_cic () {
if [ "$BUILT_CIC" = true ]; then return; fi
build_bootloader () {
if [ "$BUILT_BOOTLOADER" = true ]; then return; fi
pushd sw/cic > /dev/null
avra UltraCIC-III.asm -D attiny45
popd > /dev/null
BUILT_CIC=true
}
build_n64 () {
if [ "$BUILT_N64" = true ]; then return; fi
pushd sw/n64 > /dev/null
pushd sw/bootloader > /dev/null
if [ "$FORCE_CLEAN" = true ]; then
make clean
fi
make all -j USER_FLAGS="$USER_FLAGS"
FLAGS="$USER_FLAGS"
if [ ! -z "${GIT_BRANCH+x}" ]; then FLAGS+=" -DGIT_BRANCH='\"$GIT_BRANCH\"'"; fi
if [ ! -z "${GIT_TAG+x}" ]; then FLAGS+=" -DGIT_TAG='\"$GIT_TAG\"'"; fi
if [ ! -z "${GIT_SHA+x}" ]; then FLAGS+=" -DGIT_SHA='\"$GIT_SHA\"'"; fi
if [ ! -z "${GIT_MESSAGE+x}" ]; then FLAGS+=" -DGIT_MESSAGE='\"$GIT_MESSAGE\"'"; fi
make all -j USER_FLAGS="$FLAGS"
popd > /dev/null
BUILT_N64=true
BUILT_BOOTLOADER=true
}
build_riscv () {
if [ "$BUILT_RISCV" = true ]; then return; fi
build_controller () {
if [ "$BUILT_CONTROLLER" = true ]; then return; fi
pushd sw/riscv > /dev/null
pushd sw/controller > /dev/null
if [ "$FORCE_CLEAN" = true ]; then
make clean
./build.sh clean
fi
make all -j USER_FLAGS="$USER_FLAGS"
USER_FLAGS="$USER_FLAGS" ./build.sh all
popd > /dev/null
BUILT_RISCV=true
BUILT_CONTROLLER=true
}
build_fpga () {
if [ "$BUILT_FPGA" = true ]; then return; fi
build_n64
build_riscv
pushd fw > /dev/null
if [ "$SKIP_FPGA_REBUILD" = true ] && [ -f output_files/SummerCart64.sof ]; then
quartus_cpf -c SummerCart64.cof
else
if [ "$DEBUG_ENABLED" = true ]; then
quartus_sh --set VERILOG_MACRO="DEBUG" ./SummerCart64.qpf
fi
quartus_sh --flow compile ./SummerCart64.qpf
quartus_sh --set -remove VERILOG_MACRO="DEBUG" ./SummerCart64.qpf
pushd fw/project/lcmxo2 > /dev/null
if [ "$FORCE_CLEAN" = true ]; then
rm -rf ./impl1/
fi
./build.sh
popd > /dev/null
BUILT_FPGA=true
@ -84,12 +70,26 @@ build_fpga () {
build_update () {
if [ "$BUILT_UPDATE" = true ]; then return; fi
build_bootloader
build_controller
build_fpga
pushd fw/output_files > /dev/null
cat sc64_firmware_ufm_auto.rpd sc64_firmware_cfm0_auto.rpd > SC64_update_tmp.bin
objcopy -I binary -O binary --reverse-bytes=4 SC64_update_tmp.bin SC64_update.bin
rm SC64_update_tmp.bin
pushd sw/update > /dev/null
if [ "$FORCE_CLEAN" = true ]; then
rm -f ./sc64.upd
fi
GIT_INFO=""
if [ ! -z "${GIT_BRANCH}" ]; then GIT_INFO+="branch: [$GIT_BRANCH] "; fi
if [ ! -z "${GIT_TAG}" ]; then GIT_INFO+="tag: [$GIT_TAG] "; fi
if [ ! -z "${GIT_SHA}" ]; then GIT_INFO+="sha: [$GIT_SHA] "; fi
if [ ! -z "${GIT_MESSAGE}" ]; then GIT_INFO+="message: [$GIT_MESSAGE] "; fi
GIT_INFO=$(echo "$GIT_INFO" | xargs)
python3 update.py \
--git "$GIT_INFO" \
--mcu ../controller/build/app/app.bin \
--fpga ../../fw/project/lcmxo2/impl1/sc64_impl1.jed \
--boot ../bootloader/build/bootloader.bin \
sc64.upd
popd > /dev/null
BUILT_UPDATE=true
@ -98,7 +98,6 @@ build_update () {
build_release () {
if [ "$BUILT_RELEASE" = true ]; then return; fi
build_cic
build_update
if [ -e "./${PACKAGE_FILE_NAME}.zip" ]; then
@ -110,22 +109,17 @@ build_release () {
}
print_usage () {
echo "builder script for SummerCart64"
echo "usage: ./build.sh [cic] [n64] [riscv] [fpga] [update] [release] [-c] [-s] [-d] [--help]"
echo "builder script for SC64"
echo "usage: ./build.sh [bootloader] [controller] [fpga] [update] [release] [-c] [--help]"
echo "parameters:"
echo " cic - assemble UltraCIC-III software"
echo " n64 - compile N64 bootloader software"
echo " riscv - compile cart governor software"
echo " fpga - compile FPGA design (triggers 'n64' and 'riscv' build)"
echo " update - convert programming .pof file to raw binary for self-upgrade (triggers 'fpga' build)"
echo " release - collect and zip files for release (triggers 'cic' and 'update' build)"
echo " bootloader - compile N64 bootloader software"
echo " controller - compile ARM controller software"
echo " fpga - compile FPGA design"
echo " update - compile all software and designs"
echo " release - collect and zip files for release (triggers 'update' build)"
echo " -c | --force-clean"
echo " - clean software compilation result directories before build"
echo " -s | --skip-fpga-rebuild"
echo " - do not recompile whole FPGA design if it's already done, just update software binaries"
echo " -d | --debug"
echo " - enable debug features"
echo " --help - print this guide"
echo " - clean compilation result directories before build"
echo " --help - print this guide"
}
if test $# -eq 0; then
@ -135,23 +129,19 @@ if test $# -eq 0; then
exit 1
fi
TRIGGER_CIC=false
TRIGGER_N64=false
TRIGGER_RISCV=false
TRIGGER_BOOTLOADER=false
TRIGGER_CONTROLLER=false
TRIGGER_FPGA=false
TRIGGER_UPDATE=false
TRIGGER_RELEASE=false
while test $# -gt 0; do
case "$1" in
cic)
TRIGGER_CIC=true
bootloader)
TRIGGER_BOOTLOADER=true
;;
n64)
TRIGGER_N64=true
;;
riscv)
TRIGGER_RISCV=true
controller)
TRIGGER_CONTROLLER=true
;;
fpga)
TRIGGER_FPGA=true
@ -165,12 +155,6 @@ while test $# -gt 0; do
-c|--force-clean)
FORCE_CLEAN=true
;;
-s|--skip-fpga-rebuild)
SKIP_FPGA_REBUILD=true
;;
-d|--debug)
DEBUG_ENABLED=true
;;
--help)
print_usage
exit 0
@ -185,10 +169,8 @@ while test $# -gt 0; do
shift
done
if [ "$DEBUG_ENABLED" = true ]; then USER_FLAGS+=" -DDEBUG"; fi
if [ "$TRIGGER_CIC" = true ]; then build_cic; fi
if [ "$TRIGGER_N64" = true ]; then build_n64; fi
if [ "$TRIGGER_RISCV" = true ]; then build_riscv; fi
if [ "$TRIGGER_BOOTLOADER" = true ]; then build_bootloader; fi
if [ "$TRIGGER_CONTROLLER" = true ]; then build_controller; fi
if [ "$TRIGGER_FPGA" = true ]; then build_fpga; fi
if [ "$TRIGGER_UPDATE" = true ]; then build_update; fi
if [ "$TRIGGER_RELEASE" = true ]; then build_release; fi

View File

@ -1,18 +1,37 @@
#!/bin/bash
GIT_SHA=$(git rev-parse --short HEAD)
GIT_TAG=$(git describe --tags --exact-match 2> /dev/null)
BUILDER_IMAGE="ghcr.io/polprzewodnikowy/sc64env:v1.5"
if [ ! -z $GIT_TAG ]; then
__SC64_VERSION=$(printf "%.7q\ %.7q" $GIT_SHA $GIT_TAG)
else
__SC64_VERSION=$(printf "%.7q\ develop" $GIT_SHA)
pushd $(dirname $0) > /dev/null
GIT_BRANCH=$(git rev-parse --abbrev-ref HEAD)
GIT_TAG=$(git describe --tags 2> /dev/null)
GIT_SHA=$(git rev-parse HEAD)
GIT_MESSAGE=$(git log --oneline --format=%B -n 1 HEAD | head -n 1)
if [ -t 1 ]; then
DOCKER_OPTIONS="-it"
fi
docker run \
$DOCKER_OPTIONS \
--rm \
--user $(id -u):$(id -g) \
--mac-address ${MAC_ADDRESS:-F8:12:34:56:78:90} \
--mount type=bind,src="$(pwd)/flexlm",target="/flexlm" \
--mount type=bind,src="$(pwd)",target="/workdir" \
-e __SC64_VERSION="$__SC64_VERSION" \
ghcr.io/polprzewodnikowy/sc64env:v1.2 \
-h=`hostname` \
-e GIT_BRANCH="$GIT_BRANCH" \
-e GIT_TAG="$GIT_TAG" \
-e GIT_SHA="$GIT_SHA" \
-e GIT_MESSAGE="$GIT_MESSAGE" \
$BUILDER_IMAGE \
./build.sh $@
BUILD_ERROR=$?
popd > /dev/null
if [ $BUILD_ERROR -ne 0 ]; then
exit -1
fi

13
fw/.gitignore vendored
View File

@ -1,13 +0,0 @@
/db
/greybox_tmp
/incremental_db
/output_files
**/.qsys_edit
**/*.bin
**/*.dat
**/*.elf
*.qws
*.rpt
*.sopcinfo
*.srf
*.txt

View File

@ -1,42 +0,0 @@
<?xml version="1.0" encoding="US-ASCII" standalone="yes"?>
<cof>
<output_filename>output_files/SC64_firmware.pof</output_filename>
<n_pages>1</n_pages>
<width>1</width>
<mode>14</mode>
<sof_data>
<user_name>Page_0</user_name>
<page_flags>1</page_flags>
<bit0>
<sof_filename>output_files/SummerCart64.sof<compress_bitstream>1</compress_bitstream></sof_filename>
</bit0>
</sof_data>
<version>10</version>
<create_cvp_file>0</create_cvp_file>
<create_hps_iocsr>0</create_hps_iocsr>
<auto_create_rpd>1</auto_create_rpd>
<rpd_little_endian>0</rpd_little_endian>
<options>
<map_file>1</map_file>
</options>
<MAX10_device_options>
<por>0</por>
<io_pullup>1</io_pullup>
<config_from_cfm0_only>0</config_from_cfm0_only>
<isp_source>0</isp_source>
<verify_protect>0</verify_protect>
<epof>0</epof>
<ufm_source>2</ufm_source>
<ufm_filepath>../sw/n64/build/n64boot.hex</ufm_filepath>
<cfm0_filepath>../sw/riscv/build/governor.hex</cfm0_filepath>
<cfm0_file_start_addr>305152</cfm0_file_start_addr>
</MAX10_device_options>
<advanced_options>
<ignore_epcs_id_check>1</ignore_epcs_id_check>
<ignore_condone_check>2</ignore_condone_check>
<plc_adjustment>0</plc_adjustment>
<post_chain_bitstream_pad_bytes>-1</post_chain_bitstream_pad_bytes>
<post_device_bitstream_pad_bytes>-1</post_device_bitstream_pad_bytes>
<bitslice_pre_padding>1</bitslice_pre_padding>
</advanced_options>
</cof>

View File

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

View File

@ -1,292 +0,0 @@
# -------------------------------------------------------------------------- #
#
# Copyright (C) 2021 Intel Corporation. All rights reserved.
# Your use of Intel Corporation's design tools, logic functions
# and other software and tools, and any partner logic
# functions, and any output files from any of the foregoing
# (including device programming or simulation files), and any
# associated documentation or information are expressly subject
# to the terms and conditions of the Intel Program License
# Subscription Agreement, the Intel Quartus Prime License Agreement,
# the Intel FPGA IP License Agreement, or other applicable license
# agreement, including, without limitation, that your use is for
# the sole purpose of programming logic devices manufactured by
# Intel and sold by Intel or its authorized distributors. Please
# refer to the applicable agreement for further details, at
# https://fpgasoftware.intel.com/eula.
#
# -------------------------------------------------------------------------- #
#
# Quartus Prime
# Version 21.1.0 Build 842 10/21/2021 SJ Lite Edition
# Date created = 13:29:40 November 11, 2021
#
# -------------------------------------------------------------------------- #
#
# Notes:
#
# 1) The default values for assignments are stored in the file:
# SummerCart64_assignment_defaults.qdf
# If this file doesn't exist, see file:
# assignment_defaults.qdf
#
# 2) Intel recommends that you do not modify this file. This
# file is updated automatically by the Quartus Prime software
# and any changes you make may be lost or overwritten.
#
# -------------------------------------------------------------------------- #
# Project-Wide Assignments
# ========================
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 "21.1.0 Lite Edition"
set_global_assignment -name PROJECT_OUTPUT_DIRECTORY output_files
set_global_assignment -name NUM_PARALLEL_PROCESSORS ALL
set_global_assignment -name FLOW_ENABLE_POWER_ANALYZER ON
set_global_assignment -name QSYS_FILE rtl/intel/flash/intel_flash.qsys
set_global_assignment -name QIP_FILE rtl/intel/fifo/intel_fifo_8.qip
set_global_assignment -name QIP_FILE rtl/intel/gpio/intel_gpio_ddro.qip
set_global_assignment -name QIP_FILE rtl/intel/pll/intel_pll.qip
set_global_assignment -name SDC_FILE SummerCart64.sdc
set_global_assignment -name SYSTEMVERILOG_FILE picorv32/picorv32.v
set_global_assignment -name SYSTEMVERILOG_FILE rtl/cpu/cpu_bus.sv
set_global_assignment -name SYSTEMVERILOG_FILE rtl/cpu/cpu_cfg.sv
set_global_assignment -name SYSTEMVERILOG_FILE rtl/cpu/cpu_dd.sv
set_global_assignment -name SYSTEMVERILOG_FILE rtl/cpu/cpu_dma.sv
set_global_assignment -name SYSTEMVERILOG_FILE rtl/cpu/cpu_flash.sv
set_global_assignment -name SYSTEMVERILOG_FILE rtl/cpu/cpu_flashram.sv
set_global_assignment -name SYSTEMVERILOG_FILE rtl/cpu/cpu_gpio.sv
set_global_assignment -name SYSTEMVERILOG_FILE rtl/cpu/cpu_i2c.sv
set_global_assignment -name SYSTEMVERILOG_FILE rtl/cpu/cpu_ram.sv
set_global_assignment -name SYSTEMVERILOG_FILE rtl/cpu/cpu_sdram.sv
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_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 POST_MODULE_SCRIPT_FILE "quartus_sh:scripts/post_module.tcl"
# Pin & Location Assignments
# ==========================
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_17 -to o_led
set_location_assignment PIN_21 -to o_rtc_scl
set_location_assignment PIN_22 -to io_rtc_sda
set_location_assignment PIN_24 -to io_n64_si_dq
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_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]
set_location_assignment PIN_39 -to io_n64_pi_ad[9]
set_location_assignment PIN_41 -to io_n64_pi_ad[5]
set_location_assignment PIN_43 -to io_n64_pi_ad[10]
set_location_assignment PIN_44 -to io_n64_pi_ad[4]
set_location_assignment PIN_45 -to io_n64_pi_ad[11]
set_location_assignment PIN_46 -to i_n64_pi_aleh
set_location_assignment PIN_47 -to i_n64_pi_read
set_location_assignment PIN_48 -to i_n64_pi_write
set_location_assignment PIN_50 -to i_n64_pi_alel
set_location_assignment PIN_52 -to io_n64_pi_ad[12]
set_location_assignment PIN_54 -to io_n64_pi_ad[3]
set_location_assignment PIN_55 -to io_n64_pi_ad[13]
set_location_assignment PIN_56 -to io_n64_pi_ad[2]
set_location_assignment PIN_57 -to io_n64_pi_ad[14]
set_location_assignment PIN_58 -to io_n64_pi_ad[1]
set_location_assignment PIN_59 -to io_n64_pi_ad[15]
set_location_assignment PIN_60 -to io_n64_pi_ad[0]
set_location_assignment PIN_61 -to o_sdram_a[4]
set_location_assignment PIN_62 -to o_sdram_a[5]
set_location_assignment PIN_64 -to o_sdram_a[6]
set_location_assignment PIN_65 -to o_sdram_a[7]
set_location_assignment PIN_66 -to o_sdram_a[8]
set_location_assignment PIN_69 -to o_sdram_a[9]
set_location_assignment PIN_70 -to o_sdram_a[11]
set_location_assignment PIN_74 -to o_sdram_a[12]
set_location_assignment PIN_75 -to o_sdram_clk
set_location_assignment PIN_76 -to o_sdram_a[3]
set_location_assignment PIN_77 -to o_sdram_a[2]
set_location_assignment PIN_78 -to o_sdram_a[1]
set_location_assignment PIN_79 -to o_sdram_a[0]
set_location_assignment PIN_80 -to o_sdram_a[10]
set_location_assignment PIN_81 -to o_sdram_ba[1]
set_location_assignment PIN_84 -to o_sdram_ba[0]
set_location_assignment PIN_85 -to o_sdram_cs
set_location_assignment PIN_86 -to o_sdram_ras
set_location_assignment PIN_87 -to o_sdram_cas
set_location_assignment PIN_88 -to o_sdram_we
set_location_assignment PIN_89 -to io_sdram_dq[7]
set_location_assignment PIN_90 -to io_sdram_dq[6]
set_location_assignment PIN_91 -to io_sdram_dq[5]
set_location_assignment PIN_92 -to io_sdram_dq[4]
set_location_assignment PIN_93 -to io_sdram_dq[3]
set_location_assignment PIN_96 -to io_sdram_dq[2]
set_location_assignment PIN_97 -to io_sdram_dq[1]
set_location_assignment PIN_98 -to io_sdram_dq[0]
set_location_assignment PIN_99 -to io_sdram_dq[8]
set_location_assignment PIN_100 -to io_sdram_dq[9]
set_location_assignment PIN_101 -to io_sdram_dq[10]
set_location_assignment PIN_102 -to io_sdram_dq[11]
set_location_assignment PIN_105 -to io_sdram_dq[12]
set_location_assignment PIN_106 -to io_sdram_dq[13]
set_location_assignment PIN_110 -to io_sdram_dq[14]
set_location_assignment PIN_111 -to io_sdram_dq[15]
set_location_assignment PIN_112 -to io_sd_dat[1]
set_location_assignment PIN_113 -to io_sd_dat[0]
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_123 -to o_n64_irq
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
# Compiler Assignments
# ====================
set_global_assignment -name OPTIMIZATION_MODE "HIGH PERFORMANCE EFFORT"
# Analysis & Synthesis Assignments
# ================================
set_global_assignment -name FAMILY "MAX 10"
set_global_assignment -name DEVICE_FILTER_PACKAGE EQFP
set_global_assignment -name DEVICE_FILTER_PIN_COUNT 144
set_global_assignment -name DEVICE_FILTER_SPEED_GRADE 8
set_global_assignment -name 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 SummerCart64
# Fitter Assignments
# ==================
set_global_assignment -name DEVICE 10M08SCE144C8G
set_global_assignment -name ERROR_CHECK_FREQUENCY_DIVISOR 256
set_global_assignment -name ENABLE_CONFIGURATION_PINS OFF
set_global_assignment -name ENABLE_BOOT_SEL_PIN OFF
set_global_assignment -name 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"
# Assembler Assignments
# =====================
set_global_assignment -name ENABLE_OCT_DONE OFF
set_global_assignment -name EXTERNAL_FLASH_FALLBACK_ADDRESS 00000000
set_global_assignment -name USE_CONFIGURATION_DEVICE OFF
# Power Estimation Assignments
# ============================
set_global_assignment -name POWER_PRESET_COOLING_SOLUTION "NO HEAT SINK WITH STILL AIR"
set_global_assignment -name POWER_BOARD_THERMAL_MODEL "NONE (CONSERVATIVE)"
set_global_assignment -name POWER_DEFAULT_INPUT_IO_TOGGLE_RATE "12.5 %"
# Advanced I/O Timing Assignments
# ===============================
set_global_assignment -name OUTPUT_IO_TIMING_NEAR_END_VMEAS "HALF VCCIO" -rise
set_global_assignment -name OUTPUT_IO_TIMING_NEAR_END_VMEAS "HALF VCCIO" -fall
set_global_assignment -name OUTPUT_IO_TIMING_FAR_END_VMEAS "HALF SIGNAL SWING" -rise
set_global_assignment -name OUTPUT_IO_TIMING_FAR_END_VMEAS "HALF SIGNAL SWING" -fall
# --------------------------
# start ENTITY(SummerCart64)
# Pin & Location Assignments
# ==========================
set_instance_assignment -name FAST_INPUT_REGISTER ON -to io_usb_miosi[*]
set_instance_assignment -name FAST_INPUT_REGISTER ON -to i_uart_rxd
set_instance_assignment -name FAST_INPUT_REGISTER ON -to io_rtc_sda
set_instance_assignment -name FAST_INPUT_REGISTER ON -to io_n64_si_dq
set_instance_assignment -name FAST_INPUT_REGISTER ON -to i_n64_nmi
set_instance_assignment -name FAST_INPUT_REGISTER ON -to i_n64_reset
set_instance_assignment -name FAST_INPUT_REGISTER ON -to i_n64_si_clk
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_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_uart_rxd
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 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)
# ---------------------------
# Incremental Compilation Assignments
# ===================================
set_global_assignment -name PARTITION_NETLIST_TYPE SOURCE -section_id Top
set_global_assignment -name PARTITION_FITTER_PRESERVATION_LEVEL PLACEMENT_AND_ROUTING -section_id Top
set_global_assignment -name PARTITION_COLOR 16764057 -section_id Top
set_instance_assignment -name PARTITION_HIERARCHY root_partition -to | -section_id Top
# end DESIGN_PARTITION(Top)
# -------------------------
# end ENTITY(SummerCart64)
# ------------------------

View File

@ -1,81 +0,0 @@
# 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 i_usb_pwren}]
# 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}]
set_false_path -from [get_ports {i_uart_rxd}]
# I2C timings
set_false_path -to [get_ports {o_rtc_scl io_rtc_sda}]
set_false_path -from [get_ports {io_rtc_sda}]

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

17
fw/project/lcmxo2/.gitignore vendored Normal file
View File

@ -0,0 +1,17 @@
.recovery
*.dir/
*.ccl
*.dmp
*.html
*.ini
*.rva
*.rvl
*.rvs
*.svf
*.tcl
*.tpf
*.trc
*.xml
impl*/
!build.tcl

5
fw/project/lcmxo2/build.sh Executable file
View File

@ -0,0 +1,5 @@
#!/bin/bash
source $bindir/diamond_env
diamondc build.tcl

View File

@ -0,0 +1,2 @@
prj_project open sc64.ldf
prj_run Export -impl impl1 -task Jedecgen

205
fw/project/lcmxo2/debug.sty Normal file
View File

@ -0,0 +1,205 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE strategy>
<Strategy version="1.0" predefined="0" description="" label="debug">
<Property name="PROP_BD_CmdLineArgs" value="" time="0"/>
<Property name="PROP_BD_EdfHardtimer" value="Enable" time="0"/>
<Property name="PROP_BD_EdfInBusNameConv" value="None" time="0"/>
<Property name="PROP_BD_EdfInLibPath" value="" time="0"/>
<Property name="PROP_BD_EdfInRemLoc" value="Off" time="0"/>
<Property name="PROP_BD_EdfMemPath" value="" time="0"/>
<Property name="PROP_BD_ParSearchPath" value="" time="0"/>
<Property name="PROP_BIT_AddressBitGen" value="Increment" time="0"/>
<Property name="PROP_BIT_AllowReadBitGen" value="Disable" time="0"/>
<Property name="PROP_BIT_ByteWideBitMirror" value="Disable" time="0"/>
<Property name="PROP_BIT_CapReadBitGen" value="Disable" time="0"/>
<Property name="PROP_BIT_ConModBitGen" value="Disable" time="0"/>
<Property name="PROP_BIT_CreateBitFile" value="True" time="0"/>
<Property name="PROP_BIT_DisRAMResBitGen" value="True" time="0"/>
<Property name="PROP_BIT_DisableUESBitgen" value="False" time="0"/>
<Property name="PROP_BIT_DonePinBitGen" value="Pullup" time="0"/>
<Property name="PROP_BIT_DoneSigBitGen" value="4" time="0"/>
<Property name="PROP_BIT_EnIOBitGen" value="TriStateDuringReConfig" time="0"/>
<Property name="PROP_BIT_EnIntOscBitGen" value="Disable" time="0"/>
<Property name="PROP_BIT_ExtClockBitGen" value="False" time="0"/>
<Property name="PROP_BIT_GSREnableBitGen" value="True" time="0"/>
<Property name="PROP_BIT_GSRRelOnBitGen" value="DoneIn" time="0"/>
<Property name="PROP_BIT_GranTimBitGen" value="0" time="0"/>
<Property name="PROP_BIT_IOTriRelBitGen" value="Cycle 2" time="0"/>
<Property name="PROP_BIT_JTAGEnableBitGen" value="False" time="0"/>
<Property name="PROP_BIT_LenBitsBitGen" value="24" time="0"/>
<Property name="PROP_BIT_MIFFileBitGen" value="" time="0"/>
<Property name="PROP_BIT_NoHeader" value="False" time="0"/>
<Property name="PROP_BIT_OutFormatBitGen" value="Bit File (Binary)" time="0"/>
<Property name="PROP_BIT_OutFormatBitGen_REF" value="" time="0"/>
<Property name="PROP_BIT_OutFormatPromGen" value="Intel Hex 32-bit" time="0"/>
<Property name="PROP_BIT_ParityCheckBitGen" value="True" time="0"/>
<Property name="PROP_BIT_ReadBackBitGen" value="Flash" time="0"/>
<Property name="PROP_BIT_ReadCaptureBitGen" value="Disable" time="0"/>
<Property name="PROP_BIT_RemZeroFramesBitGen" value="False" time="0"/>
<Property name="PROP_BIT_RunDRCBitGen" value="True" time="0"/>
<Property name="PROP_BIT_SearchPthBitGen" value="" time="0"/>
<Property name="PROP_BIT_StartUpClkBitGen" value="Cclk" time="0"/>
<Property name="PROP_BIT_SynchIOBitGen" value="True" time="0"/>
<Property name="PROP_BIT_SysClockConBitGen" value="Reset" time="0"/>
<Property name="PROP_BIT_SysConBitGen" value="Reset" time="0"/>
<Property name="PROP_BIT_WaitStTimBitGen" value="5" time="0"/>
<Property name="PROP_IOTIMING_AllSpeed" value="False" time="0"/>
<Property name="PROP_LST_AllowDUPMod" value="False" time="0"/>
<Property name="PROP_LST_CarryChain" value="True" time="0"/>
<Property name="PROP_LST_CarryChainLength" value="0" time="0"/>
<Property name="PROP_LST_CmdLineArgs" value="" time="0"/>
<Property name="PROP_LST_DSPStyle" value="DSP" time="0"/>
<Property name="PROP_LST_DSPUtil" value="100" time="0"/>
<Property name="PROP_LST_DecodeUnreachableStates" value="False" time="0"/>
<Property name="PROP_LST_DisableDistRam" value="False" time="0"/>
<Property name="PROP_LST_EBRUtil" value="100" time="0"/>
<Property name="PROP_LST_EdfFrequency" value="200" time="0"/>
<Property name="PROP_LST_EdfHardtimer" value="Enable" time="0"/>
<Property name="PROP_LST_EdfInLibPath" value="" time="0"/>
<Property name="PROP_LST_EdfInRemLoc" value="Off" time="0"/>
<Property name="PROP_LST_EdfMemPath" value="" time="0"/>
<Property name="PROP_LST_FIXGATEDCLKS" value="True" time="0"/>
<Property name="PROP_LST_FSMEncodeStyle" value="Auto" time="0"/>
<Property name="PROP_LST_ForceGSRInfer" value="Auto" time="0"/>
<Property name="PROP_LST_IOInsertion" value="True" time="0"/>
<Property name="PROP_LST_InterFileDump" value="False" time="0"/>
<Property name="PROP_LST_LoopLimit" value="1950" time="0"/>
<Property name="PROP_LST_MaxFanout" value="1000" time="0"/>
<Property name="PROP_LST_MuxStyle" value="Auto" time="0"/>
<Property name="PROP_LST_NumCriticalPaths" value="3" time="0"/>
<Property name="PROP_LST_OptimizeGoal" value="Balanced" time="0"/>
<Property name="PROP_LST_PropagatConst" value="True" time="0"/>
<Property name="PROP_LST_RAMStyle" value="Auto" time="0"/>
<Property name="PROP_LST_ROMStyle" value="Auto" time="0"/>
<Property name="PROP_LST_RemoveDupRegs" value="True" time="0"/>
<Property name="PROP_LST_ResolvedMixedDrivers" value="False" time="0"/>
<Property name="PROP_LST_ResourceShare" value="True" time="0"/>
<Property name="PROP_LST_UseIOReg" value="Auto" time="0"/>
<Property name="PROP_LST_UseLPF" value="True" time="0"/>
<Property name="PROP_LST_VHDL2008" value="False" time="0"/>
<Property name="PROP_MAPSTA_AnalysisOption" value="Standard Setup and Hold Analysis" time="0"/>
<Property name="PROP_MAPSTA_AutoTiming" value="True" time="0"/>
<Property name="PROP_MAPSTA_CheckUnconstrainedConns" value="False" time="0"/>
<Property name="PROP_MAPSTA_CheckUnconstrainedPaths" value="True" time="0"/>
<Property name="PROP_MAPSTA_FullName" value="True" time="0"/>
<Property name="PROP_MAPSTA_NumUnconstrainedPaths" value="0" time="0"/>
<Property name="PROP_MAPSTA_ReportStyle" value="Verbose Timing Report" time="0"/>
<Property name="PROP_MAPSTA_RouteEstAlogtithm" value="0" time="0"/>
<Property name="PROP_MAPSTA_RptAsynTimLoop" value="False" time="0"/>
<Property name="PROP_MAPSTA_WordCasePaths" value="1" time="0"/>
<Property name="PROP_MAP_IgnorePreErr" value="True" time="0"/>
<Property name="PROP_MAP_MAPIORegister" value="Auto" time="0"/>
<Property name="PROP_MAP_MAPInferGSR" value="True" time="0"/>
<Property name="PROP_MAP_MapModArgs" value="" time="0"/>
<Property name="PROP_MAP_OvermapDevice" value="False" time="0"/>
<Property name="PROP_MAP_PackLogMapDes" value="" time="0"/>
<Property name="PROP_MAP_RegRetiming" value="False" time="0"/>
<Property name="PROP_MAP_SigCrossRef" value="False" time="0"/>
<Property name="PROP_MAP_SymCrossRef" value="False" time="0"/>
<Property name="PROP_MAP_TimingDriven" value="False" time="0"/>
<Property name="PROP_MAP_TimingDrivenNodeRep" value="False" time="0"/>
<Property name="PROP_MAP_TimingDrivenPack" value="False" time="0"/>
<Property name="PROP_PARSTA_AnalysisOption" value="Standard Setup and Hold Analysis" time="0"/>
<Property name="PROP_PARSTA_AutoTiming" value="True" time="0"/>
<Property name="PROP_PARSTA_CheckUnconstrainedConns" value="False" time="0"/>
<Property name="PROP_PARSTA_CheckUnconstrainedPaths" value="True" time="0"/>
<Property name="PROP_PARSTA_FullName" value="True" time="0"/>
<Property name="PROP_PARSTA_NumUnconstrainedPaths" value="0" time="0"/>
<Property name="PROP_PARSTA_ReportStyle" value="Verbose Timing Report" time="0"/>
<Property name="PROP_PARSTA_RptAsynTimLoop" value="False" time="0"/>
<Property name="PROP_PARSTA_SpeedForHoldAnalysis" value="6" time="0"/>
<Property name="PROP_PARSTA_SpeedForSetupAnalysis" value="6" time="0"/>
<Property name="PROP_PARSTA_WordCasePaths" value="10" time="0"/>
<Property name="PROP_PAR_CrDlyStFileParDes" value="False" time="0"/>
<Property name="PROP_PAR_DisableTDParDes" value="False" time="0"/>
<Property name="PROP_PAR_EffortParDes" value="5" time="0"/>
<Property name="PROP_PAR_MultiSeedSortMode" value="Worst Slack" time="0"/>
<Property name="PROP_PAR_NewRouteParDes" value="NBR" time="0"/>
<Property name="PROP_PAR_PARClockSkew" value="Off" time="0"/>
<Property name="PROP_PAR_PARModArgs" value="" time="0"/>
<Property name="PROP_PAR_ParMultiNodeList" value="" time="0"/>
<Property name="PROP_PAR_ParRunPlaceOnly" value="False" time="0"/>
<Property name="PROP_PAR_PlcIterParDes" value="5" time="0"/>
<Property name="PROP_PAR_PlcStCostTblParDes" value="1" time="0"/>
<Property name="PROP_PAR_PrefErrorOut" value="True" time="0"/>
<Property name="PROP_PAR_RemoveDir" value="True" time="0"/>
<Property name="PROP_PAR_RouteDlyRedParDes" value="0" time="0"/>
<Property name="PROP_PAR_RoutePassParDes" value="6" time="0"/>
<Property name="PROP_PAR_RouteResOptParDes" value="0" time="0"/>
<Property name="PROP_PAR_RoutingCDP" value="0" time="0"/>
<Property name="PROP_PAR_RoutingCDR" value="0" time="0"/>
<Property name="PROP_PAR_RunParWithTrce" value="False" time="0"/>
<Property name="PROP_PAR_RunTimeReduction" value="True" time="0"/>
<Property name="PROP_PAR_SaveBestRsltParDes" value="1" time="0"/>
<Property name="PROP_PAR_StopZero" value="True" time="0"/>
<Property name="PROP_PAR_parHold" value="On" time="0"/>
<Property name="PROP_PAR_parPathBased" value="Off" time="0"/>
<Property name="PROP_PRE_CmdLineArgs" value="" time="0"/>
<Property name="PROP_PRE_EdfArrayBoundsCase" value="False" time="0"/>
<Property name="PROP_PRE_EdfAutoResOfRam" value="False" time="0"/>
<Property name="PROP_PRE_EdfClockDomainCross" value="False" time="0"/>
<Property name="PROP_PRE_EdfDSPAcrossHie" value="False" time="0"/>
<Property name="PROP_PRE_EdfFullCase" value="False" time="0"/>
<Property name="PROP_PRE_EdfIgnoreRamRWCol" value="False" time="0"/>
<Property name="PROP_PRE_EdfMissConstraint" value="False" time="0"/>
<Property name="PROP_PRE_EdfNetFanout" value="True" time="0"/>
<Property name="PROP_PRE_EdfParaCase" value="False" time="0"/>
<Property name="PROP_PRE_EdfReencodeFSM" value="True" time="0"/>
<Property name="PROP_PRE_EdfResSharing" value="True" time="0"/>
<Property name="PROP_PRE_EdfTimingViolation" value="True" time="0"/>
<Property name="PROP_PRE_EdfUseSafeFSM" value="False" time="0"/>
<Property name="PROP_PRE_EdfVlog2001" value="True" time="0"/>
<Property name="PROP_PRE_VSynComArea" value="True" time="0"/>
<Property name="PROP_PRE_VSynCritcal" value="3" time="0"/>
<Property name="PROP_PRE_VSynFSM" value="Auto" time="0"/>
<Property name="PROP_PRE_VSynFreq" value="200" time="0"/>
<Property name="PROP_PRE_VSynGSR" value="False" time="0"/>
<Property name="PROP_PRE_VSynGatedClk" value="False" time="0"/>
<Property name="PROP_PRE_VSynIOPad" value="False" time="0"/>
<Property name="PROP_PRE_VSynOutNetForm" value="None" time="0"/>
<Property name="PROP_PRE_VSynOutPref" value="True" time="0"/>
<Property name="PROP_PRE_VSynRepClkFreq" value="True" time="0"/>
<Property name="PROP_PRE_VSynRetime" value="True" time="0"/>
<Property name="PROP_PRE_VSynTimSum" value="10" time="0"/>
<Property name="PROP_PRE_VSynTransform" value="True" time="0"/>
<Property name="PROP_PRE_VSyninpd" value="0" time="0"/>
<Property name="PROP_PRE_VSynoutd" value="0" time="0"/>
<Property name="PROP_SYN_ClockConversion" value="True" time="0"/>
<Property name="PROP_SYN_CmdLineArgs" value="" time="0"/>
<Property name="PROP_SYN_DisableRegisterRep" value="False" time="0"/>
<Property name="PROP_SYN_EdfAllowDUPMod" value="False" time="0"/>
<Property name="PROP_SYN_EdfArea" value="False" time="0"/>
<Property name="PROP_SYN_EdfArrangeVHDLFiles" value="True" time="0"/>
<Property name="PROP_SYN_EdfDefEnumEncode" value="Default" time="0"/>
<Property name="PROP_SYN_EdfFanout" value="1000" time="0"/>
<Property name="PROP_SYN_EdfFrequency" value="110" time="0"/>
<Property name="PROP_SYN_EdfGSR" value="False" time="0"/>
<Property name="PROP_SYN_EdfInsertIO" value="False" time="0"/>
<Property name="PROP_SYN_EdfNumCritPath" value="" time="0"/>
<Property name="PROP_SYN_EdfNumStartEnd" value="" time="0"/>
<Property name="PROP_SYN_EdfOutNetForm" value="None" time="0"/>
<Property name="PROP_SYN_EdfPushTirstates" value="True" time="0"/>
<Property name="PROP_SYN_EdfResSharing" value="True" time="0"/>
<Property name="PROP_SYN_EdfRunRetiming" value="Pipelining Only" time="0"/>
<Property name="PROP_SYN_EdfSymFSM" value="True" time="0"/>
<Property name="PROP_SYN_EdfUnconsClk" value="False" time="0"/>
<Property name="PROP_SYN_EdfVerilogInput" value="Verilog 2001" time="0"/>
<Property name="PROP_SYN_ExportSetting" value="No" time="0"/>
<Property name="PROP_SYN_LibPath" value="" time="0"/>
<Property name="PROP_SYN_ResolvedMixedDrivers" value="False" time="0"/>
<Property name="PROP_SYN_UpdateCompilePtTimData" value="False" time="0"/>
<Property name="PROP_SYN_UseLPF" value="True" time="0"/>
<Property name="PROP_SYN_VHDL2008" value="False" time="0"/>
<Property name="PROP_THERMAL_DefaultFreq" value="0" time="0"/>
<Property name="PROP_TIM_MaxDelSimDes" value="" time="0"/>
<Property name="PROP_TIM_MinSpeedGrade" value="False" time="0"/>
<Property name="PROP_TIM_ModPreSimDes" value="" time="0"/>
<Property name="PROP_TIM_NegStupHldTim" value="True" time="0"/>
<Property name="PROP_TIM_TimSimGenPUR" value="True" time="0"/>
<Property name="PROP_TIM_TimSimGenX" value="False" time="0"/>
<Property name="PROP_TIM_TimSimHierSep" value="" time="0"/>
<Property name="PROP_TIM_TransportModeOfPathDelay" value="False" time="0"/>
<Property name="PROP_TIM_TrgtSpeedGrade" value="" time="0"/>
<Property name="PROP_TIM_WriteVerboseNetlist" value="False" time="0"/>
<Property name="PROP_TMCHK_EnableCheck" value="True" time="0"/>
</Strategy>

View File

@ -0,0 +1,205 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE strategy>
<Strategy version="1.0" predefined="0" description="" label="release">
<Property name="PROP_BD_CmdLineArgs" value="" time="0"/>
<Property name="PROP_BD_EdfHardtimer" value="Enable" time="0"/>
<Property name="PROP_BD_EdfInBusNameConv" value="None" time="0"/>
<Property name="PROP_BD_EdfInLibPath" value="" time="0"/>
<Property name="PROP_BD_EdfInRemLoc" value="Off" time="0"/>
<Property name="PROP_BD_EdfMemPath" value="" time="0"/>
<Property name="PROP_BD_ParSearchPath" value="" time="0"/>
<Property name="PROP_BIT_AddressBitGen" value="Increment" time="0"/>
<Property name="PROP_BIT_AllowReadBitGen" value="Disable" time="0"/>
<Property name="PROP_BIT_ByteWideBitMirror" value="Disable" time="0"/>
<Property name="PROP_BIT_CapReadBitGen" value="Disable" time="0"/>
<Property name="PROP_BIT_ConModBitGen" value="Disable" time="0"/>
<Property name="PROP_BIT_CreateBitFile" value="True" time="0"/>
<Property name="PROP_BIT_DisRAMResBitGen" value="True" time="0"/>
<Property name="PROP_BIT_DisableUESBitgen" value="False" time="0"/>
<Property name="PROP_BIT_DonePinBitGen" value="Pullup" time="0"/>
<Property name="PROP_BIT_DoneSigBitGen" value="4" time="0"/>
<Property name="PROP_BIT_EnIOBitGen" value="TriStateDuringReConfig" time="0"/>
<Property name="PROP_BIT_EnIntOscBitGen" value="Disable" time="0"/>
<Property name="PROP_BIT_ExtClockBitGen" value="False" time="0"/>
<Property name="PROP_BIT_GSREnableBitGen" value="True" time="0"/>
<Property name="PROP_BIT_GSRRelOnBitGen" value="DoneIn" time="0"/>
<Property name="PROP_BIT_GranTimBitGen" value="0" time="0"/>
<Property name="PROP_BIT_IOTriRelBitGen" value="Cycle 2" time="0"/>
<Property name="PROP_BIT_JTAGEnableBitGen" value="False" time="0"/>
<Property name="PROP_BIT_LenBitsBitGen" value="24" time="0"/>
<Property name="PROP_BIT_MIFFileBitGen" value="" time="0"/>
<Property name="PROP_BIT_NoHeader" value="False" time="0"/>
<Property name="PROP_BIT_OutFormatBitGen" value="Bit File (Binary)" time="0"/>
<Property name="PROP_BIT_OutFormatBitGen_REF" value="" time="0"/>
<Property name="PROP_BIT_OutFormatPromGen" value="Intel Hex 32-bit" time="0"/>
<Property name="PROP_BIT_ParityCheckBitGen" value="True" time="0"/>
<Property name="PROP_BIT_ReadBackBitGen" value="Flash" time="0"/>
<Property name="PROP_BIT_ReadCaptureBitGen" value="Disable" time="0"/>
<Property name="PROP_BIT_RemZeroFramesBitGen" value="False" time="0"/>
<Property name="PROP_BIT_RunDRCBitGen" value="True" time="0"/>
<Property name="PROP_BIT_SearchPthBitGen" value="" time="0"/>
<Property name="PROP_BIT_StartUpClkBitGen" value="Cclk" time="0"/>
<Property name="PROP_BIT_SynchIOBitGen" value="True" time="0"/>
<Property name="PROP_BIT_SysClockConBitGen" value="Reset" time="0"/>
<Property name="PROP_BIT_SysConBitGen" value="Reset" time="0"/>
<Property name="PROP_BIT_WaitStTimBitGen" value="5" time="0"/>
<Property name="PROP_IOTIMING_AllSpeed" value="False" time="0"/>
<Property name="PROP_LST_AllowDUPMod" value="False" time="0"/>
<Property name="PROP_LST_CarryChain" value="True" time="0"/>
<Property name="PROP_LST_CarryChainLength" value="0" time="0"/>
<Property name="PROP_LST_CmdLineArgs" value="" time="0"/>
<Property name="PROP_LST_DSPStyle" value="DSP" time="0"/>
<Property name="PROP_LST_DSPUtil" value="100" time="0"/>
<Property name="PROP_LST_DecodeUnreachableStates" value="False" time="0"/>
<Property name="PROP_LST_DisableDistRam" value="False" time="0"/>
<Property name="PROP_LST_EBRUtil" value="100" time="0"/>
<Property name="PROP_LST_EdfFrequency" value="200" time="0"/>
<Property name="PROP_LST_EdfHardtimer" value="Enable" time="0"/>
<Property name="PROP_LST_EdfInLibPath" value="" time="0"/>
<Property name="PROP_LST_EdfInRemLoc" value="Off" time="0"/>
<Property name="PROP_LST_EdfMemPath" value="" time="0"/>
<Property name="PROP_LST_FIXGATEDCLKS" value="True" time="0"/>
<Property name="PROP_LST_FSMEncodeStyle" value="Auto" time="0"/>
<Property name="PROP_LST_ForceGSRInfer" value="Auto" time="0"/>
<Property name="PROP_LST_IOInsertion" value="True" time="0"/>
<Property name="PROP_LST_InterFileDump" value="False" time="0"/>
<Property name="PROP_LST_LoopLimit" value="1950" time="0"/>
<Property name="PROP_LST_MaxFanout" value="1000" time="0"/>
<Property name="PROP_LST_MuxStyle" value="Auto" time="0"/>
<Property name="PROP_LST_NumCriticalPaths" value="3" time="0"/>
<Property name="PROP_LST_OptimizeGoal" value="Balanced" time="0"/>
<Property name="PROP_LST_PropagatConst" value="True" time="0"/>
<Property name="PROP_LST_RAMStyle" value="Auto" time="0"/>
<Property name="PROP_LST_ROMStyle" value="Auto" time="0"/>
<Property name="PROP_LST_RemoveDupRegs" value="True" time="0"/>
<Property name="PROP_LST_ResolvedMixedDrivers" value="False" time="0"/>
<Property name="PROP_LST_ResourceShare" value="True" time="0"/>
<Property name="PROP_LST_UseIOReg" value="Auto" time="0"/>
<Property name="PROP_LST_UseLPF" value="True" time="0"/>
<Property name="PROP_LST_VHDL2008" value="False" time="0"/>
<Property name="PROP_MAPSTA_AnalysisOption" value="Standard Setup and Hold Analysis" time="0"/>
<Property name="PROP_MAPSTA_AutoTiming" value="True" time="0"/>
<Property name="PROP_MAPSTA_CheckUnconstrainedConns" value="False" time="0"/>
<Property name="PROP_MAPSTA_CheckUnconstrainedPaths" value="True" time="0"/>
<Property name="PROP_MAPSTA_FullName" value="True" time="0"/>
<Property name="PROP_MAPSTA_NumUnconstrainedPaths" value="0" time="0"/>
<Property name="PROP_MAPSTA_ReportStyle" value="Verbose Timing Report" time="0"/>
<Property name="PROP_MAPSTA_RouteEstAlogtithm" value="0" time="0"/>
<Property name="PROP_MAPSTA_RptAsynTimLoop" value="False" time="0"/>
<Property name="PROP_MAPSTA_WordCasePaths" value="1" time="0"/>
<Property name="PROP_MAP_IgnorePreErr" value="True" time="0"/>
<Property name="PROP_MAP_MAPIORegister" value="Auto" time="0"/>
<Property name="PROP_MAP_MAPInferGSR" value="True" time="0"/>
<Property name="PROP_MAP_MapModArgs" value="" time="0"/>
<Property name="PROP_MAP_OvermapDevice" value="False" time="0"/>
<Property name="PROP_MAP_PackLogMapDes" value="" time="0"/>
<Property name="PROP_MAP_RegRetiming" value="False" time="0"/>
<Property name="PROP_MAP_SigCrossRef" value="False" time="0"/>
<Property name="PROP_MAP_SymCrossRef" value="False" time="0"/>
<Property name="PROP_MAP_TimingDriven" value="False" time="0"/>
<Property name="PROP_MAP_TimingDrivenNodeRep" value="False" time="0"/>
<Property name="PROP_MAP_TimingDrivenPack" value="False" time="0"/>
<Property name="PROP_PARSTA_AnalysisOption" value="Standard Setup and Hold Analysis" time="0"/>
<Property name="PROP_PARSTA_AutoTiming" value="True" time="0"/>
<Property name="PROP_PARSTA_CheckUnconstrainedConns" value="False" time="0"/>
<Property name="PROP_PARSTA_CheckUnconstrainedPaths" value="True" time="0"/>
<Property name="PROP_PARSTA_FullName" value="True" time="0"/>
<Property name="PROP_PARSTA_NumUnconstrainedPaths" value="0" time="0"/>
<Property name="PROP_PARSTA_ReportStyle" value="Verbose Timing Report" time="0"/>
<Property name="PROP_PARSTA_RptAsynTimLoop" value="False" time="0"/>
<Property name="PROP_PARSTA_SpeedForHoldAnalysis" value="6" time="0"/>
<Property name="PROP_PARSTA_SpeedForSetupAnalysis" value="6" time="0"/>
<Property name="PROP_PARSTA_WordCasePaths" value="10" time="0"/>
<Property name="PROP_PAR_CrDlyStFileParDes" value="False" time="0"/>
<Property name="PROP_PAR_DisableTDParDes" value="False" time="0"/>
<Property name="PROP_PAR_EffortParDes" value="5" time="0"/>
<Property name="PROP_PAR_MultiSeedSortMode" value="Worst Slack" time="0"/>
<Property name="PROP_PAR_NewRouteParDes" value="NBR" time="0"/>
<Property name="PROP_PAR_PARClockSkew" value="Off" time="0"/>
<Property name="PROP_PAR_PARModArgs" value="" time="0"/>
<Property name="PROP_PAR_ParMultiNodeList" value="" time="0"/>
<Property name="PROP_PAR_ParRunPlaceOnly" value="False" time="0"/>
<Property name="PROP_PAR_PlcIterParDes" value="10" time="0"/>
<Property name="PROP_PAR_PlcStCostTblParDes" value="1" time="0"/>
<Property name="PROP_PAR_PrefErrorOut" value="True" time="0"/>
<Property name="PROP_PAR_RemoveDir" value="True" time="0"/>
<Property name="PROP_PAR_RouteDlyRedParDes" value="0" time="0"/>
<Property name="PROP_PAR_RoutePassParDes" value="10" time="0"/>
<Property name="PROP_PAR_RouteResOptParDes" value="0" time="0"/>
<Property name="PROP_PAR_RoutingCDP" value="1" time="0"/>
<Property name="PROP_PAR_RoutingCDR" value="1" time="0"/>
<Property name="PROP_PAR_RunParWithTrce" value="False" time="0"/>
<Property name="PROP_PAR_RunTimeReduction" value="True" time="0"/>
<Property name="PROP_PAR_SaveBestRsltParDes" value="1" time="0"/>
<Property name="PROP_PAR_StopZero" value="False" time="0"/>
<Property name="PROP_PAR_parHold" value="On" time="0"/>
<Property name="PROP_PAR_parPathBased" value="On" time="0"/>
<Property name="PROP_PRE_CmdLineArgs" value="" time="0"/>
<Property name="PROP_PRE_EdfArrayBoundsCase" value="False" time="0"/>
<Property name="PROP_PRE_EdfAutoResOfRam" value="False" time="0"/>
<Property name="PROP_PRE_EdfClockDomainCross" value="False" time="0"/>
<Property name="PROP_PRE_EdfDSPAcrossHie" value="False" time="0"/>
<Property name="PROP_PRE_EdfFullCase" value="False" time="0"/>
<Property name="PROP_PRE_EdfIgnoreRamRWCol" value="False" time="0"/>
<Property name="PROP_PRE_EdfMissConstraint" value="False" time="0"/>
<Property name="PROP_PRE_EdfNetFanout" value="True" time="0"/>
<Property name="PROP_PRE_EdfParaCase" value="False" time="0"/>
<Property name="PROP_PRE_EdfReencodeFSM" value="True" time="0"/>
<Property name="PROP_PRE_EdfResSharing" value="True" time="0"/>
<Property name="PROP_PRE_EdfTimingViolation" value="True" time="0"/>
<Property name="PROP_PRE_EdfUseSafeFSM" value="False" time="0"/>
<Property name="PROP_PRE_EdfVlog2001" value="True" time="0"/>
<Property name="PROP_PRE_VSynComArea" value="True" time="0"/>
<Property name="PROP_PRE_VSynCritcal" value="3" time="0"/>
<Property name="PROP_PRE_VSynFSM" value="Auto" time="0"/>
<Property name="PROP_PRE_VSynFreq" value="200" time="0"/>
<Property name="PROP_PRE_VSynGSR" value="False" time="0"/>
<Property name="PROP_PRE_VSynGatedClk" value="False" time="0"/>
<Property name="PROP_PRE_VSynIOPad" value="False" time="0"/>
<Property name="PROP_PRE_VSynOutNetForm" value="None" time="0"/>
<Property name="PROP_PRE_VSynOutPref" value="True" time="0"/>
<Property name="PROP_PRE_VSynRepClkFreq" value="True" time="0"/>
<Property name="PROP_PRE_VSynRetime" value="True" time="0"/>
<Property name="PROP_PRE_VSynTimSum" value="10" time="0"/>
<Property name="PROP_PRE_VSynTransform" value="True" time="0"/>
<Property name="PROP_PRE_VSyninpd" value="0" time="0"/>
<Property name="PROP_PRE_VSynoutd" value="0" time="0"/>
<Property name="PROP_SYN_ClockConversion" value="True" time="0"/>
<Property name="PROP_SYN_CmdLineArgs" value="" time="0"/>
<Property name="PROP_SYN_DisableRegisterRep" value="False" time="0"/>
<Property name="PROP_SYN_EdfAllowDUPMod" value="False" time="0"/>
<Property name="PROP_SYN_EdfArea" value="False" time="0"/>
<Property name="PROP_SYN_EdfArrangeVHDLFiles" value="True" time="0"/>
<Property name="PROP_SYN_EdfDefEnumEncode" value="Default" time="0"/>
<Property name="PROP_SYN_EdfFanout" value="1000" time="0"/>
<Property name="PROP_SYN_EdfFrequency" value="110" time="0"/>
<Property name="PROP_SYN_EdfGSR" value="False" time="0"/>
<Property name="PROP_SYN_EdfInsertIO" value="False" time="0"/>
<Property name="PROP_SYN_EdfNumCritPath" value="" time="0"/>
<Property name="PROP_SYN_EdfNumStartEnd" value="" time="0"/>
<Property name="PROP_SYN_EdfOutNetForm" value="None" time="0"/>
<Property name="PROP_SYN_EdfPushTirstates" value="True" time="0"/>
<Property name="PROP_SYN_EdfResSharing" value="True" time="0"/>
<Property name="PROP_SYN_EdfRunRetiming" value="Pipelining Only" time="0"/>
<Property name="PROP_SYN_EdfSymFSM" value="True" time="0"/>
<Property name="PROP_SYN_EdfUnconsClk" value="False" time="0"/>
<Property name="PROP_SYN_EdfVerilogInput" value="Verilog 2001" time="0"/>
<Property name="PROP_SYN_ExportSetting" value="No" time="0"/>
<Property name="PROP_SYN_LibPath" value="" time="0"/>
<Property name="PROP_SYN_ResolvedMixedDrivers" value="False" time="0"/>
<Property name="PROP_SYN_UpdateCompilePtTimData" value="False" time="0"/>
<Property name="PROP_SYN_UseLPF" value="True" time="0"/>
<Property name="PROP_SYN_VHDL2008" value="False" time="0"/>
<Property name="PROP_THERMAL_DefaultFreq" value="0" time="0"/>
<Property name="PROP_TIM_MaxDelSimDes" value="" time="0"/>
<Property name="PROP_TIM_MinSpeedGrade" value="False" time="0"/>
<Property name="PROP_TIM_ModPreSimDes" value="" time="0"/>
<Property name="PROP_TIM_NegStupHldTim" value="True" time="0"/>
<Property name="PROP_TIM_TimSimGenPUR" value="True" time="0"/>
<Property name="PROP_TIM_TimSimGenX" value="False" time="0"/>
<Property name="PROP_TIM_TimSimHierSep" value="" time="0"/>
<Property name="PROP_TIM_TransportModeOfPathDelay" value="False" time="0"/>
<Property name="PROP_TIM_TrgtSpeedGrade" value="" time="0"/>
<Property name="PROP_TIM_WriteVerboseNetlist" value="False" time="0"/>
<Property name="PROP_TMCHK_EnableCheck" value="True" time="0"/>
</Strategy>

126
fw/project/lcmxo2/sc64.ldf Normal file
View File

@ -0,0 +1,126 @@
<?xml version="1.0" encoding="UTF-8"?>
<BaliProject version="3.2" title="sc64" device="LCMXO2-7000HC-6TG144C" default_implementation="impl1">
<Options/>
<Implementation title="impl1" dir="impl1" description="impl1" synthesis="synplify" default_strategy="release">
<Options VerilogStandard="System Verilog" def_top="top" top="top"/>
<Source name="../../rtl/memory/mem_bus.sv" type="Verilog" type_short="Verilog">
<Options VerilogStandard="System Verilog"/>
</Source>
<Source name="../../rtl/fifo/fifo_bus.sv" type="Verilog" type_short="Verilog">
<Options VerilogStandard="System Verilog"/>
</Source>
<Source name="../../rtl/fifo/fifo_junction.sv" type="Verilog" type_short="Verilog">
<Options VerilogStandard="System Verilog"/>
</Source>
<Source name="../../rtl/mcu/mcu_spi.sv" type="Verilog" type_short="Verilog">
<Options VerilogStandard="System Verilog"/>
</Source>
<Source name="../../rtl/mcu/mcu_top.sv" type="Verilog" type_short="Verilog">
<Options VerilogStandard="System Verilog"/>
</Source>
<Source name="../../rtl/memory/memory_arbiter.sv" type="Verilog" type_short="Verilog">
<Options VerilogStandard="System Verilog"/>
</Source>
<Source name="../../rtl/memory/memory_bram.sv" type="Verilog" type_short="Verilog">
<Options VerilogStandard="System Verilog"/>
</Source>
<Source name="../../rtl/memory/memory_dma.sv" type="Verilog" type_short="Verilog">
<Options VerilogStandard="System Verilog"/>
</Source>
<Source name="../../rtl/memory/memory_flash.sv" type="Verilog" type_short="Verilog">
<Options VerilogStandard="System Verilog"/>
</Source>
<Source name="../../rtl/memory/memory_sdram.sv" type="Verilog" type_short="Verilog">
<Options VerilogStandard="System Verilog"/>
</Source>
<Source name="../../rtl/n64/n64_cfg.sv" type="Verilog" type_short="Verilog">
<Options VerilogStandard="System Verilog"/>
</Source>
<Source name="../../rtl/n64/n64_dd.sv" type="Verilog" type_short="Verilog">
<Options VerilogStandard="System Verilog"/>
</Source>
<Source name="../../rtl/n64/n64_flashram.sv" type="Verilog" type_short="Verilog">
<Options VerilogStandard="System Verilog"/>
</Source>
<Source name="../../rtl/n64/n64_pi.sv" type="Verilog" type_short="Verilog">
<Options VerilogStandard="System Verilog"/>
</Source>
<Source name="../../rtl/n64/n64_pi_fifo.sv" type="Verilog" type_short="Verilog">
<Options VerilogStandard="System Verilog"/>
</Source>
<Source name="../../rtl/n64/n64_reg_bus.sv" type="Verilog" type_short="Verilog">
<Options VerilogStandard="System Verilog"/>
</Source>
<Source name="../../rtl/n64/n64_scb.sv" type="Verilog" type_short="Verilog">
<Options VerilogStandard="System Verilog"/>
</Source>
<Source name="../../rtl/n64/n64_si.sv" type="Verilog" type_short="Verilog">
<Options VerilogStandard="System Verilog"/>
</Source>
<Source name="../../rtl/n64/n64_top.sv" type="Verilog" type_short="Verilog">
<Options VerilogStandard="System Verilog"/>
</Source>
<Source name="../../rtl/sd/sd_clk.sv" type="Verilog" type_short="Verilog">
<Options VerilogStandard="System Verilog"/>
</Source>
<Source name="../../rtl/sd/sd_cmd.sv" type="Verilog" type_short="Verilog">
<Options VerilogStandard="System Verilog"/>
</Source>
<Source name="../../rtl/sd/sd_crc_7.sv" type="Verilog" type_short="Verilog">
<Options VerilogStandard="System Verilog"/>
</Source>
<Source name="../../rtl/sd/sd_crc_16.sv" type="Verilog" type_short="Verilog">
<Options VerilogStandard="System Verilog"/>
</Source>
<Source name="../../rtl/sd/sd_dat.sv" type="Verilog" type_short="Verilog">
<Options VerilogStandard="System Verilog"/>
</Source>
<Source name="../../rtl/sd/sd_scb.sv" type="Verilog" type_short="Verilog">
<Options VerilogStandard="System Verilog"/>
</Source>
<Source name="../../rtl/sd/sd_top.sv" type="Verilog" type_short="Verilog">
<Options VerilogStandard="System Verilog"/>
</Source>
<Source name="../../rtl/usb/usb_ft1248.sv" type="Verilog" type_short="Verilog">
<Options VerilogStandard="System Verilog"/>
</Source>
<Source name="../../rtl/vendor/vendor_scb.sv" type="Verilog" type_short="Verilog">
<Options VerilogStandard="System Verilog"/>
</Source>
<Source name="../../rtl/vendor/lcmxo2/fifo_8kb.sv" type="Verilog" type_short="Verilog">
<Options VerilogStandard="System Verilog"/>
</Source>
<Source name="../../rtl/vendor/lcmxo2/pll.sv" type="Verilog" type_short="Verilog">
<Options VerilogStandard="System Verilog"/>
</Source>
<Source name="../../rtl/vendor/lcmxo2/vendor.sv" type="Verilog" type_short="Verilog">
<Options VerilogStandard="System Verilog"/>
</Source>
<Source name="../../rtl/vendor/lcmxo2/generated/efb_lattice_generated.v" type="Verilog" type_short="Verilog">
<Options/>
</Source>
<Source name="../../rtl/vendor/lcmxo2/generated/fifo_8kb_lattice_generated.v" type="Verilog" type_short="Verilog">
<Options/>
</Source>
<Source name="../../rtl/vendor/lcmxo2/generated/pll_lattice_generated.v" type="Verilog" type_short="Verilog">
<Options/>
</Source>
<Source name="../../rtl/top.sv" type="Verilog" type_short="Verilog">
<Options VerilogStandard="System Verilog" top_module="top"/>
</Source>
<Source name="impl1/sc64.xcf" type="Programming Project File" type_short="Programming">
<Options/>
</Source>
<Source name="sc64.lpf" type="Logic Preference" type_short="LPF">
<Options/>
</Source>
<Source name="si.rva" type="Reveal Analyzer Project File" type_short="RVA" excluded="TRUE">
<Options/>
</Source>
<Source name="si.rvl" type="Reveal" type_short="Reveal" excluded="TRUE">
<Options/>
</Source>
</Implementation>
<Strategy name="debug" file="debug.sty"/>
<Strategy name="release" file="release.sty"/>
</BaliProject>

209
fw/project/lcmxo2/sc64.lpf Normal file
View File

@ -0,0 +1,209 @@
RVL_ALIAS "clk" "clk";
BANK 0 VCCIO 3.3 V;
BANK 1 VCCIO 3.3 V;
BANK 2 VCCIO 3.3 V;
BANK 3 VCCIO 3.3 V;
BANK 4 VCCIO 3.3 V;
BANK 5 VCCIO 3.3 V;
BLOCK ASYNCPATHS ;
BLOCK JTAGPATHS ;
BLOCK PATH FROM PORT "button" ;
BLOCK RESETPATHS ;
IOBUF ALLPORTS IO_TYPE=LVCMOS33 ;
IOBUF PORT "button" PULLMODE=UP IO_TYPE=LVCMOS33 ;
IOBUF PORT "flash_clk" PULLMODE=NONE IO_TYPE=LVCMOS33 ;
IOBUF PORT "flash_cs" PULLMODE=UP IO_TYPE=LVCMOS33 ;
IOBUF PORT "flash_dq[0]" PULLMODE=NONE IO_TYPE=LVCMOS33 ;
IOBUF PORT "flash_dq[1]" PULLMODE=NONE IO_TYPE=LVCMOS33 ;
IOBUF PORT "flash_dq[2]" PULLMODE=NONE IO_TYPE=LVCMOS33 ;
IOBUF PORT "flash_dq[3]" PULLMODE=NONE IO_TYPE=LVCMOS33 ;
IOBUF PORT "inclk" PULLMODE=NONE IO_TYPE=LVCMOS33 ;
IOBUF PORT "mcu_clk" PULLMODE=NONE IO_TYPE=LVCMOS33 ;
IOBUF PORT "mcu_cs" PULLMODE=UP IO_TYPE=LVCMOS33 ;
IOBUF PORT "mcu_int" PULLMODE=UP IO_TYPE=LVCMOS33 ;
IOBUF PORT "mcu_miso" IO_TYPE=LVCMOS33 PULLMODE=NONE ;
IOBUF PORT "mcu_mosi" IO_TYPE=LVCMOS33 PULLMODE=NONE ;
IOBUF PORT "n64_irq" PULLMODE=UP IO_TYPE=LVCMOS33 ;
IOBUF PORT "n64_nmi" PULLMODE=DOWN IO_TYPE=LVCMOS33 ;
IOBUF PORT "n64_pi_ad[0]" PULLMODE=NONE IO_TYPE=LVCMOS33 ;
IOBUF PORT "n64_pi_ad[1]" PULLMODE=NONE IO_TYPE=LVCMOS33 ;
IOBUF PORT "n64_pi_ad[10]" PULLMODE=NONE IO_TYPE=LVCMOS33 ;
IOBUF PORT "n64_pi_ad[11]" PULLMODE=NONE IO_TYPE=LVCMOS33 ;
IOBUF PORT "n64_pi_ad[12]" PULLMODE=NONE IO_TYPE=LVCMOS33 ;
IOBUF PORT "n64_pi_ad[13]" PULLMODE=NONE IO_TYPE=LVCMOS33 ;
IOBUF PORT "n64_pi_ad[14]" PULLMODE=NONE IO_TYPE=LVCMOS33 ;
IOBUF PORT "n64_pi_ad[15]" PULLMODE=NONE IO_TYPE=LVCMOS33 ;
IOBUF PORT "n64_pi_ad[2]" PULLMODE=NONE IO_TYPE=LVCMOS33 ;
IOBUF PORT "n64_pi_ad[3]" PULLMODE=NONE IO_TYPE=LVCMOS33 ;
IOBUF PORT "n64_pi_ad[4]" PULLMODE=NONE IO_TYPE=LVCMOS33 ;
IOBUF PORT "n64_pi_ad[5]" PULLMODE=NONE IO_TYPE=LVCMOS33 ;
IOBUF PORT "n64_pi_ad[6]" PULLMODE=NONE IO_TYPE=LVCMOS33 ;
IOBUF PORT "n64_pi_ad[7]" PULLMODE=NONE IO_TYPE=LVCMOS33 ;
IOBUF PORT "n64_pi_ad[8]" PULLMODE=NONE IO_TYPE=LVCMOS33 ;
IOBUF PORT "n64_pi_ad[9]" PULLMODE=NONE IO_TYPE=LVCMOS33 ;
IOBUF PORT "n64_pi_aleh" PULLMODE=UP IO_TYPE=LVCMOS33 ;
IOBUF PORT "n64_pi_alel" PULLMODE=DOWN IO_TYPE=LVCMOS33 ;
IOBUF PORT "n64_pi_read" PULLMODE=UP IO_TYPE=LVCMOS33 ;
IOBUF PORT "n64_pi_write" PULLMODE=UP IO_TYPE=LVCMOS33 ;
IOBUF PORT "n64_reset" PULLMODE=DOWN IO_TYPE=LVCMOS33 ;
IOBUF PORT "n64_si_clk" PULLMODE=DOWN IO_TYPE=LVCMOS33 ;
IOBUF PORT "n64_si_dq" PULLMODE=UP IO_TYPE=LVCMOS33 ;
IOBUF PORT "sd_clk" PULLMODE=UP IO_TYPE=LVCMOS33 ;
IOBUF PORT "sd_cmd" PULLMODE=UP IO_TYPE=LVCMOS33 ;
IOBUF PORT "sd_dat[0]" PULLMODE=UP IO_TYPE=LVCMOS33 ;
IOBUF PORT "sd_dat[1]" PULLMODE=UP IO_TYPE=LVCMOS33 ;
IOBUF PORT "sd_dat[2]" PULLMODE=UP IO_TYPE=LVCMOS33 ;
IOBUF PORT "sd_dat[3]" PULLMODE=UP IO_TYPE=LVCMOS33 ;
IOBUF PORT "sd_det" PULLMODE=UP IO_TYPE=LVCMOS33 ;
IOBUF PORT "sdram_a[0]" PULLMODE=NONE IO_TYPE=LVCMOS33 ;
IOBUF PORT "sdram_a[1]" PULLMODE=NONE IO_TYPE=LVCMOS33 ;
IOBUF PORT "sdram_a[10]" PULLMODE=NONE IO_TYPE=LVCMOS33 ;
IOBUF PORT "sdram_a[11]" PULLMODE=NONE IO_TYPE=LVCMOS33 ;
IOBUF PORT "sdram_a[12]" PULLMODE=NONE IO_TYPE=LVCMOS33 ;
IOBUF PORT "sdram_a[2]" PULLMODE=NONE IO_TYPE=LVCMOS33 ;
IOBUF PORT "sdram_a[3]" PULLMODE=NONE IO_TYPE=LVCMOS33 ;
IOBUF PORT "sdram_a[4]" PULLMODE=NONE IO_TYPE=LVCMOS33 ;
IOBUF PORT "sdram_a[5]" PULLMODE=NONE IO_TYPE=LVCMOS33 ;
IOBUF PORT "sdram_a[6]" PULLMODE=NONE IO_TYPE=LVCMOS33 ;
IOBUF PORT "sdram_a[7]" PULLMODE=NONE IO_TYPE=LVCMOS33 ;
IOBUF PORT "sdram_a[8]" PULLMODE=NONE IO_TYPE=LVCMOS33 ;
IOBUF PORT "sdram_a[9]" PULLMODE=NONE IO_TYPE=LVCMOS33 ;
IOBUF PORT "sdram_ba[0]" PULLMODE=NONE IO_TYPE=LVCMOS33 ;
IOBUF PORT "sdram_ba[1]" PULLMODE=NONE IO_TYPE=LVCMOS33 ;
IOBUF PORT "sdram_cas" PULLMODE=NONE IO_TYPE=LVCMOS33 ;
IOBUF PORT "sdram_clk" PULLMODE=NONE IO_TYPE=LVCMOS33 ;
IOBUF PORT "sdram_cs" PULLMODE=UP IO_TYPE=LVCMOS33 ;
IOBUF PORT "sdram_dq[0]" PULLMODE=NONE IO_TYPE=LVCMOS33 ;
IOBUF PORT "sdram_dq[1]" PULLMODE=NONE IO_TYPE=LVCMOS33 ;
IOBUF PORT "sdram_dq[10]" PULLMODE=NONE IO_TYPE=LVCMOS33 ;
IOBUF PORT "sdram_dq[11]" PULLMODE=NONE IO_TYPE=LVCMOS33 ;
IOBUF PORT "sdram_dq[12]" PULLMODE=NONE IO_TYPE=LVCMOS33 ;
IOBUF PORT "sdram_dq[13]" PULLMODE=NONE IO_TYPE=LVCMOS33 ;
IOBUF PORT "sdram_dq[14]" PULLMODE=NONE IO_TYPE=LVCMOS33 ;
IOBUF PORT "sdram_dq[15]" PULLMODE=NONE IO_TYPE=LVCMOS33 ;
IOBUF PORT "sdram_dq[2]" PULLMODE=NONE IO_TYPE=LVCMOS33 ;
IOBUF PORT "sdram_dq[3]" PULLMODE=NONE IO_TYPE=LVCMOS33 ;
IOBUF PORT "sdram_dq[4]" PULLMODE=NONE IO_TYPE=LVCMOS33 ;
IOBUF PORT "sdram_dq[5]" PULLMODE=NONE IO_TYPE=LVCMOS33 ;
IOBUF PORT "sdram_dq[6]" PULLMODE=NONE IO_TYPE=LVCMOS33 ;
IOBUF PORT "sdram_dq[7]" PULLMODE=NONE IO_TYPE=LVCMOS33 ;
IOBUF PORT "sdram_dq[8]" PULLMODE=NONE IO_TYPE=LVCMOS33 ;
IOBUF PORT "sdram_dq[9]" PULLMODE=NONE IO_TYPE=LVCMOS33 ;
IOBUF PORT "sdram_dqm[0]" PULLMODE=NONE IO_TYPE=LVCMOS33 ;
IOBUF PORT "sdram_dqm[1]" PULLMODE=NONE IO_TYPE=LVCMOS33 ;
IOBUF PORT "sdram_ras" PULLMODE=NONE IO_TYPE=LVCMOS33 ;
IOBUF PORT "sdram_we" PULLMODE=NONE IO_TYPE=LVCMOS33 ;
IOBUF PORT "usb_clk" PULLMODE=NONE IO_TYPE=LVCMOS33 ;
IOBUF PORT "usb_cs" PULLMODE=UP IO_TYPE=LVCMOS33 ;
IOBUF PORT "usb_miosi[0]" PULLMODE=NONE IO_TYPE=LVCMOS33 ;
IOBUF PORT "usb_miosi[1]" PULLMODE=NONE IO_TYPE=LVCMOS33 ;
IOBUF PORT "usb_miosi[2]" PULLMODE=NONE IO_TYPE=LVCMOS33 ;
IOBUF PORT "usb_miosi[3]" PULLMODE=NONE IO_TYPE=LVCMOS33 ;
IOBUF PORT "usb_miosi[4]" PULLMODE=NONE IO_TYPE=LVCMOS33 ;
IOBUF PORT "usb_miosi[5]" PULLMODE=NONE IO_TYPE=LVCMOS33 ;
IOBUF PORT "usb_miosi[6]" PULLMODE=NONE IO_TYPE=LVCMOS33 ;
IOBUF PORT "usb_miosi[7]" PULLMODE=NONE IO_TYPE=LVCMOS33 ;
IOBUF PORT "usb_miso" PULLMODE=NONE IO_TYPE=LVCMOS33 ;
IOBUF PORT "usb_pwrsav" PULLMODE=NONE IO_TYPE=LVCMOS33 ;
LOCATE COMP "button" SITE "1" ;
LOCATE COMP "flash_clk" SITE "142" ;
LOCATE COMP "flash_cs" SITE "138" ;
LOCATE COMP "flash_dq[0]" SITE "141" ;
LOCATE COMP "flash_dq[1]" SITE "139" ;
LOCATE COMP "flash_dq[2]" SITE "140" ;
LOCATE COMP "flash_dq[3]" SITE "143" ;
LOCATE COMP "inclk" SITE "3" ;
LOCATE COMP "mcu_clk" SITE "121" ;
LOCATE COMP "mcu_cs" SITE "122" ;
LOCATE COMP "mcu_int" SITE "117" ;
LOCATE COMP "mcu_miso" SITE "119" ;
LOCATE COMP "mcu_mosi" SITE "120" ;
LOCATE COMP "n64_irq" SITE "32" ;
LOCATE COMP "n64_nmi" SITE "28" ;
LOCATE COMP "n64_pi_ad[0]" SITE "60" ;
LOCATE COMP "n64_pi_ad[1]" SITE "58" ;
LOCATE COMP "n64_pi_ad[10]" SITE "42" ;
LOCATE COMP "n64_pi_ad[11]" SITE "44" ;
LOCATE COMP "n64_pi_ad[12]" SITE "52" ;
LOCATE COMP "n64_pi_ad[13]" SITE "55" ;
LOCATE COMP "n64_pi_ad[14]" SITE "57" ;
LOCATE COMP "n64_pi_ad[15]" SITE "59" ;
LOCATE COMP "n64_pi_ad[2]" SITE "56" ;
LOCATE COMP "n64_pi_ad[3]" SITE "54" ;
LOCATE COMP "n64_pi_ad[4]" SITE "45" ;
LOCATE COMP "n64_pi_ad[5]" SITE "43" ;
LOCATE COMP "n64_pi_ad[6]" SITE "40" ;
LOCATE COMP "n64_pi_ad[7]" SITE "38" ;
LOCATE COMP "n64_pi_ad[8]" SITE "39" ;
LOCATE COMP "n64_pi_ad[9]" SITE "41" ;
LOCATE COMP "n64_pi_aleh" SITE "48" ;
LOCATE COMP "n64_pi_alel" SITE "50" ;
LOCATE COMP "n64_pi_read" SITE "47" ;
LOCATE COMP "n64_pi_write" SITE "49" ;
LOCATE COMP "n64_reset" SITE "31" ;
LOCATE COMP "n64_si_clk" SITE "33" ;
LOCATE COMP "n64_si_dq" SITE "27" ;
LOCATE COMP "sd_clk" SITE "111" ;
LOCATE COMP "sd_cmd" SITE "112" ;
LOCATE COMP "sd_dat[0]" SITE "110" ;
LOCATE COMP "sd_dat[1]" SITE "109" ;
LOCATE COMP "sd_dat[2]" SITE "114" ;
LOCATE COMP "sd_dat[3]" SITE "113" ;
LOCATE COMP "sd_det" SITE "115" ;
LOCATE COMP "sdram_a[0]" SITE "85" ;
LOCATE COMP "sdram_a[1]" SITE "86" ;
LOCATE COMP "sdram_a[10]" SITE "84" ;
LOCATE COMP "sdram_a[11]" SITE "63" ;
LOCATE COMP "sdram_a[12]" SITE "62" ;
LOCATE COMP "sdram_a[2]" SITE "87" ;
LOCATE COMP "sdram_a[3]" SITE "89" ;
LOCATE COMP "sdram_a[4]" SITE "71" ;
LOCATE COMP "sdram_a[5]" SITE "70" ;
LOCATE COMP "sdram_a[6]" SITE "69" ;
LOCATE COMP "sdram_a[7]" SITE "68" ;
LOCATE COMP "sdram_a[8]" SITE "67" ;
LOCATE COMP "sdram_a[9]" SITE "65" ;
LOCATE COMP "sdram_ba[0]" SITE "92" ;
LOCATE COMP "sdram_ba[1]" SITE "91" ;
LOCATE COMP "sdram_cas" SITE "95" ;
LOCATE COMP "sdram_clk" SITE "61" ;
LOCATE COMP "sdram_cs" SITE "93" ;
LOCATE COMP "sdram_dq[0]" SITE "107" ;
LOCATE COMP "sdram_dq[1]" SITE "106" ;
LOCATE COMP "sdram_dq[10]" SITE "76" ;
LOCATE COMP "sdram_dq[11]" SITE "77" ;
LOCATE COMP "sdram_dq[12]" SITE "78" ;
LOCATE COMP "sdram_dq[13]" SITE "81" ;
LOCATE COMP "sdram_dq[14]" SITE "82" ;
LOCATE COMP "sdram_dq[15]" SITE "83" ;
LOCATE COMP "sdram_dq[2]" SITE "105" ;
LOCATE COMP "sdram_dq[3]" SITE "104" ;
LOCATE COMP "sdram_dq[4]" SITE "103" ;
LOCATE COMP "sdram_dq[5]" SITE "100" ;
LOCATE COMP "sdram_dq[6]" SITE "99" ;
LOCATE COMP "sdram_dq[7]" SITE "98" ;
LOCATE COMP "sdram_dq[8]" SITE "74" ;
LOCATE COMP "sdram_dq[9]" SITE "75" ;
LOCATE COMP "sdram_dqm[0]" SITE "97" ;
LOCATE COMP "sdram_dqm[1]" SITE "73" ;
LOCATE COMP "sdram_ras" SITE "94" ;
LOCATE COMP "sdram_we" SITE "96" ;
LOCATE COMP "usb_clk" SITE "12" ;
LOCATE COMP "usb_cs" SITE "11" ;
LOCATE COMP "usb_miosi[0]" SITE "22" ;
LOCATE COMP "usb_miosi[1]" SITE "21" ;
LOCATE COMP "usb_miosi[2]" SITE "20" ;
LOCATE COMP "usb_miosi[3]" SITE "19" ;
LOCATE COMP "usb_miosi[4]" SITE "17" ;
LOCATE COMP "usb_miosi[5]" SITE "15" ;
LOCATE COMP "usb_miosi[6]" SITE "14" ;
LOCATE COMP "usb_miosi[7]" SITE "13" ;
LOCATE COMP "usb_miso" SITE "10" ;
LOCATE COMP "usb_pwrsav" SITE "2" ;
SYSCONFIG SDM_PORT=DISABLE ;
VOLTAGE 3.300 V;
FREQUENCY NET "clk" 100.000000 MHz PAR_ADJ 10.000000 ;
BLOCK PATH TO PORT "mcu_int" ;
BLOCK PATH TO PORT "n64_irq" ;
BLOCK PATH FROM PORT "usb_pwrsav" ;
BLOCK PATH FROM PORT "sd_det" ;

View File

@ -1,154 +0,0 @@
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,
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;
logic dd_interrupt;
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 ();
if_flash flash ();
if_dd dd (
.dd_interrupt(dd_interrupt)
);
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),
.flash(flash),
.dd(dd),
.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),
.flash(flash),
.dd(dd),
.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),
.sd_clk(o_sd_clk),
.sd_cmd(io_sd_cmd),
.sd_dat(io_sd_dat)
);
always_comb begin
o_n64_irq = dd_interrupt ? 1'b0 : 1'bZ;
end
always_comb begin
o_led = gpio_oe[0] ? gpio_o[0] : 1'bZ;
end
always_ff @(posedge sys.clk) begin
gpio_i <= {4'b0000, i_n64_nmi, i_n64_reset, gpio_o[1:0]};
end
endmodule

View File

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

View File

@ -1,164 +0,0 @@
module cpu_cfg (
if_system.sys sys,
if_cpu_bus bus,
if_config.cpu cfg
);
logic skip_bootloader;
logic trigger_reconfiguration;
typedef enum bit [2:0] {
R_SCR,
R_DDIPL_OFFSET,
R_SAVE_OFFSET,
R_COMMAND,
R_DATA_0,
R_DATA_1,
R_VERSION,
R_RECONFIGURE
} e_reg_id;
const logic [31:0] RECONFIGURE_MAGIC = 32'h52535446;
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,
1'b0,
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_DDIPL_OFFSET: bus.rdata = {6'd0, cfg.ddipl_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;
R_RECONFIGURE: bus.rdata = RECONFIGURE_MAGIC;
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.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.ddipl_offset <= 26'h3BE_0000;
cfg.save_offset <= 26'h3FE_0000;
skip_bootloader <= 1'b0;
trigger_reconfiguration <= 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.cmd_error
} <= {bus.wdata[31:30], bus.wdata[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_DDIPL_OFFSET: begin
if (&bus.wmask) begin
cfg.ddipl_offset <= bus.wdata[25:0];
end
end
R_SAVE_OFFSET: begin
if (&bus.wmask) begin
cfg.save_offset <= bus.wdata[25:0];
end
end
R_RECONFIGURE: begin
if (&bus.wmask && bus.wdata == RECONFIGURE_MAGIC) begin
trigger_reconfiguration <= 1'b1;
end
end
endcase
end
end
end
logic [1:0] ru_clk;
logic ru_rconfig;
logic ru_regout;
always_ff @(posedge sys.clk) begin
if (sys.reset) begin
ru_clk <= 2'd0;
ru_rconfig <= 1'b0;
end else begin
ru_clk <= ru_clk + 1'd1;
if (ru_clk == 2'd1) begin
ru_rconfig <= trigger_reconfiguration;
end
end
end
fiftyfivenm_rublock fiftyfivenm_rublock_inst (
.clk(ru_clk[1]),
.shiftnld(1'b0),
.captnupdt(1'b0),
.regin(1'b0),
.rsttimer(1'b0),
.rconfig(ru_rconfig),
.regout(ru_regout)
);
endmodule

View File

@ -1,141 +0,0 @@
module cpu_dd (
if_system.sys sys,
if_cpu_bus bus,
if_dd.cpu dd
);
const bit [8:0] M_SECTOR_BUFFER = 9'h100;
logic bm_ack;
logic [31:0] seek_timer;
typedef enum bit [2:0] {
R_SCR,
R_CMD_DATA,
R_HEAD_TRACK,
R_SECTOR_INFO,
R_DRIVE_ID,
R_SEEK_TIMER
} 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
if (bus.address[8] == M_SECTOR_BUFFER[8]) begin
bus.rdata = {
dd.sector_rdata[7:0],
dd.sector_rdata[15:8],
dd.sector_rdata[23:16],
dd.sector_rdata[31:24]
};
end else begin
case (bus.address[5:2])
R_SCR: bus.rdata = {
14'd0,
bm_ack,
dd.bm_micro_error,
dd.bm_transfer_c2,
dd.bm_transfer_data,
dd.bm_transfer_blocks,
dd.bm_transfer_mode,
1'b0,
dd.bm_stop_pending,
1'b0,
dd.bm_start_pending,
dd.disk_changed,
dd.disk_inserted,
1'b0,
dd.bm_pending,
1'b0,
dd.cmd_pending,
1'b0,
dd.hard_reset
};
R_CMD_DATA: bus.rdata = {8'd0, dd.cmd, dd.data};
R_HEAD_TRACK: bus.rdata = {18'd0, dd.index_lock, dd.head_track};
R_SECTOR_INFO: bus.rdata = {
dd.sectors_in_block,
dd.sector_size_full,
dd.sector_size,
dd.sector_num
};
R_DRIVE_ID: bus.rdata = {dd.drive_id};
R_SEEK_TIMER: bus.rdata = seek_timer;
default: bus.rdata = 32'd0;
endcase
end
end
end
always_comb begin
dd.sector_address = bus.address[7:2];
dd.sector_address_valid = bus.request && bus.address[8] == M_SECTOR_BUFFER[8];
dd.sector_write = (&bus.wmask) && dd.sector_address_valid;
dd.sector_wdata = {bus.wdata[7:0], bus.wdata[15:8], bus.wdata[23:16], bus.wdata[31:24]};
end
always_ff @(posedge sys.clk) begin
dd.hard_reset_clear <= 1'b0;
dd.cmd_ready <= 1'b0;
dd.bm_start_clear <= 1'b0;
dd.bm_stop_clear <= 1'b0;
dd.bm_clear <= 1'b0;
dd.bm_ready <= 1'b0;
if (dd.bm_interrupt_ack) begin
bm_ack <= 1'b1;
end
if (!(&seek_timer)) begin
seek_timer <= seek_timer + 1'd1;
end
if (sys.reset) begin
bm_ack <= 1'b0;
end else begin
if (bus.request && (!bus.address[8])) begin
case (bus.address[4:2])
R_SCR: if (&bus.wmask) begin
if (bus.wdata[20]) begin
seek_timer <= 32'd0;
end
dd.bm_clear <= bus.wdata[19];
if (bus.wdata[18]) begin
bm_ack <= 1'b0;
end
dd.bm_micro_error <= bus.wdata[16];
dd.bm_transfer_c2 <= bus.wdata[15];
dd.bm_transfer_data <= bus.wdata[14];
dd.bm_stop_clear <= bus.wdata[11];
dd.bm_start_clear <= bus.wdata[9];
dd.disk_changed <= bus.wdata[7];
dd.disk_inserted <= bus.wdata[6];
dd.bm_ready <= bus.wdata[5];
dd.cmd_ready <= bus.wdata[3];
dd.hard_reset_clear <= bus.wdata[1];
end
R_CMD_DATA: if (&bus.wmask[1:0]) begin
dd.cmd_data <= bus.wdata[15:0];
end
R_HEAD_TRACK: if (&bus.wmask[1:0]) begin
{dd.index_lock, dd.head_track} <= bus.wdata[13:0];
end
R_DRIVE_ID: if (&bus.wmask[1:0]) begin
dd.drive_id <= bus.wdata[15:0];
end
endcase
end
end
end
endmodule

View File

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

View File

@ -1,61 +0,0 @@
interface if_flash ();
logic request;
logic ack;
logic write;
logic [31:0] address;
logic [31:0] rdata;
logic [31: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_flash (
if_system.sys sys,
if_cpu_bus bus,
if_flash.cpu flash
);
logic request;
always_comb begin
bus.ack = flash.ack;
bus.rdata = flash.rdata;
flash.request = bus.request || request;
flash.write = &bus.wmask;
flash.address = bus.address;
flash.wdata = bus.wdata;
end
always_ff @(posedge sys.clk) begin
if (sys.reset) begin
request <= 1'b0;
end else begin
if (bus.request) begin
request <= 1'b1;
end
if (flash.ack) begin
request <= 1'b0;
end
end
end
endmodule

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,127 +0,0 @@
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,
if_flash.cpu flash,
if_dd.cpu dd,
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,
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_flash cpu_flash_inst (
.sys(sys),
.bus(bus.at[sc64::ID_CPU_FLASH].device),
.flash(flash)
);
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)
);
generate
if (sc64::CPU_HAS_UART) begin
cpu_uart cpu_uart_inst (
.sys(sys),
.bus(bus.at[sc64::ID_CPU_UART].device),
.uart_rxd(uart_rxd),
.uart_txd(uart_txd)
);
end
endgenerate
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)
);
cpu_dd cpu_dd_inst (
.sys(sys),
.bus(bus.at[sc64::ID_CPU_DD].device),
.dd(dd)
);
assign sd_clk = 1'bZ;
assign sd_cmd = 1'bZ;
assign sd_dat = 4'bZZZZ;
endmodule

View File

@ -1,153 +0,0 @@
module cpu_uart (
if_system.sys sys,
if_cpu_bus bus,
input uart_rxd,
output uart_txd
);
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

View File

@ -1,119 +0,0 @@
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 rx_escape_valid;
logic rx_escape_ack;
logic [7:0] rx_escape;
logic cpu_rx_read;
logic cpu_tx_write;
logic usb_enabled;
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[3:2])
0: bus.rdata = {25'd0, rx_escape_valid, usb_pwren, usb_enabled, 2'b00, ~tx_full, ~rx_empty};
1: bus.rdata = {24'd0, rx_rdata};
2: bus.rdata = {24'd0, rx_escape};
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;
rx_escape_ack <= 1'b0;
if (sys.reset) begin
usb_enabled <= 1'b0;
end else begin
if (bus.request) begin
case (bus.address[2:2])
2'd0: begin
if (bus.wmask[0]) begin
rx_escape_ack <= bus.wdata[7];
{usb_enabled, tx_flush, rx_flush} <= bus.wdata[4: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
end
usb_ft1248 usb_ft1248_inst (
.sys(sys),
.usb_enabled(usb_enabled),
.usb_clk(usb_clk),
.usb_cs(usb_cs),
.usb_miso(usb_miso),
.usb_miosi(usb_miosi),
.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),
.rx_escape_valid(rx_escape_valid),
.rx_escape_ack(rx_escape_ack),
.rx_escape(rx_escape)
);
endmodule

View File

@ -1,49 +0,0 @@
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(sc64::CPU_RESET_VECTOR)
) 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

37
fw/rtl/fifo/fifo_bus.sv Normal file
View File

@ -0,0 +1,37 @@
interface fifo_bus ();
logic rx_empty;
logic rx_almost_empty;
logic rx_read;
logic [7:0] rx_rdata;
logic tx_full;
logic tx_almost_full;
logic tx_write;
logic [7:0] tx_wdata;
modport controller (
input rx_empty,
input rx_almost_empty,
output rx_read,
input rx_rdata,
input tx_full,
input tx_almost_full,
output tx_write,
output tx_wdata
);
modport fifo (
output rx_empty,
output rx_almost_empty,
input rx_read,
output rx_rdata,
output tx_full,
output tx_almost_full,
input tx_write,
input tx_wdata
);
endinterface

View File

@ -0,0 +1,26 @@
module fifo_junction (
fifo_bus.controller dev_bus,
fifo_bus.fifo cfg_bus,
fifo_bus.fifo dma_bus
);
always_comb begin
dev_bus.rx_read = cfg_bus.rx_read || dma_bus.rx_read;
dev_bus.tx_write = cfg_bus.tx_write || dma_bus.tx_write;
dev_bus.tx_wdata = cfg_bus.tx_write ? cfg_bus.tx_wdata : dma_bus.tx_wdata;
cfg_bus.rx_empty = dev_bus.rx_empty;
cfg_bus.rx_almost_empty = dev_bus.rx_almost_empty;
cfg_bus.rx_rdata = dev_bus.rx_rdata;
cfg_bus.tx_full = dev_bus.tx_full;
cfg_bus.tx_almost_full = dev_bus.tx_almost_full;
dma_bus.rx_empty = dev_bus.rx_empty;
dma_bus.rx_almost_empty = dev_bus.rx_almost_empty;
dma_bus.rx_rdata = dev_bus.rx_rdata;
dma_bus.tx_full = dev_bus.tx_full;
dma_bus.tx_almost_full = dev_bus.tx_almost_full;
end
endmodule

View File

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

View File

@ -1,162 +0,0 @@
// megafunction wizard: %FIFO%
// GENERATION: STANDARD
// VERSION: WM1.0
// MODULE: scfifo
// ============================================================
// File Name: intel_fifo_8.v
// Megafunction Name(s):
// scfifo
//
// Simulation Library Files(s):
//
// ============================================================
// ************************************************************
// THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE!
//
// 21.1.0 Build 842 10/21/2021 SJ Lite Edition
// ************************************************************
//Copyright (C) 2021 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 intel_fifo_8 (
clock,
data,
rdreq,
sclr,
wrreq,
empty,
full,
q);
input clock;
input [7:0] data;
input rdreq;
input sclr;
input wrreq;
output empty;
output full;
output [7:0] q;
wire sub_wire0;
wire sub_wire1;
wire [7:0] sub_wire2;
wire empty = sub_wire0;
wire full = sub_wire1;
wire [7:0] q = sub_wire2[7:0];
scfifo scfifo_component (
.clock (clock),
.data (data),
.rdreq (rdreq),
.sclr (sclr),
.wrreq (wrreq),
.empty (sub_wire0),
.full (sub_wire1),
.q (sub_wire2),
.aclr (),
.almost_empty (),
.almost_full (),
.eccstatus (),
.usedw ());
defparam
scfifo_component.add_ram_output_register = "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 = 8,
scfifo_component.lpm_widthu = 10,
scfifo_component.overflow_checking = "ON",
scfifo_component.underflow_checking = "ON",
scfifo_component.use_eab = "ON";
endmodule
// ============================================================
// CNX file retrieval info
// ============================================================
// Retrieval info: PRIVATE: AlmostEmpty NUMERIC "0"
// Retrieval info: PRIVATE: AlmostEmptyThr NUMERIC "-1"
// Retrieval info: PRIVATE: AlmostFull NUMERIC "0"
// Retrieval info: PRIVATE: AlmostFullThr NUMERIC "-1"
// Retrieval info: PRIVATE: CLOCKS_ARE_SYNCHRONIZED NUMERIC "1"
// Retrieval info: PRIVATE: Clock NUMERIC "0"
// Retrieval info: PRIVATE: Depth NUMERIC "1024"
// Retrieval info: PRIVATE: Empty NUMERIC "1"
// Retrieval info: PRIVATE: Full NUMERIC "1"
// Retrieval info: PRIVATE: INTENDED_DEVICE_FAMILY STRING "MAX 10"
// Retrieval info: PRIVATE: LE_BasedFIFO NUMERIC "0"
// Retrieval info: PRIVATE: LegacyRREQ NUMERIC "0"
// Retrieval info: PRIVATE: MAX_DEPTH_BY_9 NUMERIC "0"
// Retrieval info: PRIVATE: OVERFLOW_CHECKING NUMERIC "0"
// Retrieval info: PRIVATE: Optimize NUMERIC "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 "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 "8"
// Retrieval info: PRIVATE: rsEmpty NUMERIC "1"
// Retrieval info: PRIVATE: rsFull NUMERIC "0"
// Retrieval info: PRIVATE: rsUsedW NUMERIC "0"
// Retrieval info: PRIVATE: sc_aclr NUMERIC "0"
// Retrieval info: PRIVATE: sc_sclr NUMERIC "1"
// Retrieval info: PRIVATE: wsEmpty NUMERIC "0"
// Retrieval info: PRIVATE: wsFull NUMERIC "1"
// Retrieval info: PRIVATE: wsUsedW NUMERIC "0"
// Retrieval info: LIBRARY: altera_mf altera_mf.altera_mf_components.all
// Retrieval info: CONSTANT: ADD_RAM_OUTPUT_REGISTER STRING "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 "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 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 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: 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 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 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

View File

@ -1,90 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<system name="$${FILENAME}">
<component
name="$${FILENAME}"
displayName="$${FILENAME}"
version="1.0"
description=""
tags="INTERNAL_COMPONENT=true"
categories="System" />
<parameter name="bonusData"><![CDATA[bonusData
{
element onchip_flash_0
{
datum _sortIndex
{
value = "0";
type = "int";
}
}
}
]]></parameter>
<parameter name="clockCrossingAdapter" value="HANDSHAKE" />
<parameter name="device" value="10M08SCE144C8G" />
<parameter name="deviceFamily" value="MAX 10" />
<parameter name="deviceSpeedGrade" value="8" />
<parameter name="fabricMode" value="QSYS" />
<parameter name="generateLegacySim" value="false" />
<parameter name="generationId" value="0" />
<parameter name="globalResetBus" value="false" />
<parameter name="hdlLanguage" value="VERILOG" />
<parameter name="hideFromIPCatalog" value="true" />
<parameter name="lockedInterfaceDefinition" value="" />
<parameter name="maxAdditionalLatency" value="1" />
<parameter name="projectName" value="" />
<parameter name="sopcBorderPoints" value="false" />
<parameter name="systemHash" value="0" />
<parameter name="testBenchDutName" value="" />
<parameter name="timeStamp" value="0" />
<parameter name="useTestBenchNamingPattern" value="false" />
<instanceScript></instanceScript>
<interface name="clk" internal="onchip_flash_0.clk" type="clock" dir="end">
<port name="clock" internal="clock" />
</interface>
<interface name="csr" internal="onchip_flash_0.csr" type="avalon" dir="end">
<port name="avmm_csr_addr" internal="avmm_csr_addr" />
<port name="avmm_csr_read" internal="avmm_csr_read" />
<port name="avmm_csr_writedata" internal="avmm_csr_writedata" />
<port name="avmm_csr_write" internal="avmm_csr_write" />
<port name="avmm_csr_readdata" internal="avmm_csr_readdata" />
</interface>
<interface name="data" internal="onchip_flash_0.data" type="avalon" dir="end">
<port name="avmm_data_addr" internal="avmm_data_addr" />
<port name="avmm_data_read" internal="avmm_data_read" />
<port name="avmm_data_writedata" internal="avmm_data_writedata" />
<port name="avmm_data_write" internal="avmm_data_write" />
<port name="avmm_data_readdata" internal="avmm_data_readdata" />
<port name="avmm_data_waitrequest" internal="avmm_data_waitrequest" />
<port name="avmm_data_readdatavalid" internal="avmm_data_readdatavalid" />
<port name="avmm_data_burstcount" internal="avmm_data_burstcount" />
</interface>
<interface name="nreset" internal="onchip_flash_0.nreset" type="reset" dir="end">
<port name="reset_n" internal="reset_n" />
</interface>
<module
name="onchip_flash_0"
kind="altera_onchip_flash"
version="21.1"
enabled="1"
autoexport="1">
<parameter name="AUTO_CLOCK_RATE" value="0" />
<parameter name="CLOCK_FREQUENCY" value="100.0" />
<parameter name="CONFIGURATION_MODE">Single Compressed Image</parameter>
<parameter name="CONFIGURATION_SCHEME">Internal Configuration</parameter>
<parameter name="DATA_INTERFACE" value="Parallel" />
<parameter name="DEVICE_FAMILY" value="MAX 10" />
<parameter name="PART_NAME" value="10M08SCE144C8G" />
<parameter name="READ_BURST_COUNT" value="2" />
<parameter name="READ_BURST_MODE" value="Incrementing" />
<parameter name="SECTOR_ACCESS_MODE">Read and write,Read and write,Hidden,Read and write,Read and write</parameter>
<parameter name="autoInitializationFileName">$${FILENAME}_onchip_flash_0</parameter>
<parameter name="initFlashContent" value="false" />
<parameter name="initializationFileName"></parameter>
<parameter name="initializationFileNameForSim"></parameter>
<parameter name="useNonDefaultInitFile" value="false" />
</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,77 +0,0 @@
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 "21.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 "MjEuMQ=="
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 "MjEuMQ=="
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 "21.1"
set_global_assignment -entity "altera_gpio_lite" -library "intel_gpio_ddro" -name IP_TOOL_ENV "mwpim"

View File

@ -1,123 +0,0 @@
// megafunction wizard: %GPIO Lite Intel FPGA IP v21.1%
// GENERATION: XML
// intel_gpio_ddro.v
// Generated using ACDS version 21.1 842
`timescale 1 ps / 1 ps
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 #(
.PIN_TYPE ("output"),
.SIZE (1),
.REGISTER_MODE ("ddr"),
.BUFFER_TYPE ("single-ended"),
.ASYNC_MODE ("none"),
.SYNC_MODE ("none"),
.BUS_HOLD ("false"),
.OPEN_DRAIN_OUTPUT ("false"),
.ENABLE_OE_PORT ("false"),
.ENABLE_NSLEEP_PORT ("false"),
.ENABLE_CLOCK_ENA_PORT ("false"),
.SET_REGISTER_OUTPUTS_HIGH ("false"),
.INVERT_OUTPUT ("false"),
.INVERT_INPUT_CLOCK ("false"),
.USE_ONE_REG_TO_DRIVE_OE ("false"),
.USE_DDIO_REG_TO_DRIVE_OE ("false"),
.USE_ADVANCED_DDR_FEATURES ("false"),
.USE_ADVANCED_DDR_FEATURES_FOR_INPUT_ONLY ("false"),
.ENABLE_OE_HALF_CYCLE_DELAY ("true"),
.INVERT_CLKDIV_INPUT_CLOCK ("false"),
.ENABLE_PHASE_INVERT_CTRL_PORT ("false"),
.ENABLE_HR_CLOCK ("false"),
.INVERT_OUTPUT_CLOCK ("false"),
.INVERT_OE_INCLOCK ("false"),
.ENABLE_PHASE_DETECTOR_FOR_CK ("false")
) 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
// Retrieval info: <?xml version="1.0"?>
//<!--
// Generated by Altera MegaWizard Launcher Utility version 1.0
// ************************************************************
// THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE!
// ************************************************************
// Copyright (C) 1991-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
// under Altera's Megafunction Partnership Program may be used only to
// program PLD devices (but not masked PLD devices) from Altera. Any other
// use of such megafunction design, net list, support information, device
// programming or simulation file, or any other related documentation or
// information is prohibited for any other purpose, including, but not
// limited to modification, reverse engineering, de-compiling, or use with
// any other silicon devices, unless such use is explicitly licensed under
// a separate agreement with Altera or a megafunction partner. Title to
// the intellectual property, including patents, copyrights, trademarks,
// trade secrets, or maskworks, embodied in any such megafunction design,
// net list, support information, device programming or simulation file, or
// any other related documentation or information provided by Altera or a
// megafunction partner, remains with Altera, the megafunction partner, or
// their respective licensors. No other licenses, including any licenses
// needed under any third party's intellectual property, are provided herein.
//-->
// Retrieval info: <instance entity-name="altera_gpio_lite" version="21.1" >
// Retrieval info: <generic name="DEVICE_FAMILY" value="MAX 10" />
// Retrieval info: <generic name="PIN_TYPE" value="output" />
// Retrieval info: <generic name="SIZE" value="1" />
// Retrieval info: <generic name="gui_true_diff_buf" value="false" />
// Retrieval info: <generic name="gui_pseudo_diff_buf" value="false" />
// Retrieval info: <generic name="gui_bus_hold" value="false" />
// Retrieval info: <generic name="gui_open_drain" value="false" />
// Retrieval info: <generic name="gui_enable_oe_port" value="false" />
// Retrieval info: <generic name="gui_enable_nsleep_port" value="false" />
// Retrieval info: <generic name="gui_io_reg_mode" value="ddr" />
// Retrieval info: <generic name="gui_enable_aclr_port" value="false" />
// Retrieval info: <generic name="gui_enable_aset_port" value="false" />
// Retrieval info: <generic name="gui_enable_sclr_port" value="false" />
// Retrieval info: <generic name="gui_set_registers_to_power_up_high" value="false" />
// Retrieval info: <generic name="gui_clock_enable" value="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" />
// Retrieval info: <generic name="gui_use_ddio_reg_to_drive_oe" value="false" />
// Retrieval info: <generic name="gui_use_advanced_ddr_features" value="false" />
// Retrieval info: <generic name="gui_enable_phase_detector_for_ck" value="false" />
// Retrieval info: <generic name="gui_enable_oe_half_cycle_delay" value="true" />
// Retrieval info: <generic name="gui_enable_hr_clock" value="false" />
// Retrieval info: <generic name="gui_enable_invert_hr_clock_port" value="false" />
// Retrieval info: <generic name="gui_invert_clkdiv_input_clock" value="false" />
// Retrieval info: <generic name="gui_invert_output_clock" value="false" />
// Retrieval info: <generic name="gui_invert_oe_inclock" value="false" />
// Retrieval info: <generic name="gui_use_hardened_ddio_input_registers" value="false" />
// Retrieval info: </instance>
// IPFS_FILES : intel_gpio_ddro.vo
// RELATED_FILES: intel_gpio_ddro.v, altera_gpio_lite.sv

File diff suppressed because it is too large Load Diff

View File

@ -1,11 +0,0 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE pinplan>
<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" />
<pin name="c1" direction="output" scope="external" source="clock" />
<pin name="locked" direction="output" scope="external" />
</global>
</pinplan>

View File

@ -1,5 +0,0 @@
set_global_assignment -name IP_TOOL_NAME "ALTPLL"
set_global_assignment -name IP_TOOL_VERSION "21.1"
set_global_assignment -name IP_GENERATED_DEVICE_FAMILY "{MAX 10}"
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

@ -1,340 +0,0 @@
// megafunction wizard: %ALTPLL%
// GENERATION: STANDARD
// VERSION: WM1.0
// MODULE: altpll
// ============================================================
// File Name: intel_pll.v
// Megafunction Name(s):
// altpll
//
// Simulation Library Files(s):
//
// ============================================================
// ************************************************************
// THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE!
//
// 21.1.0 Build 842 10/21/2021 SJ Lite Edition
// ************************************************************
//Copyright (C) 2021 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 intel_pll (
inclk0,
c0,
c1,
locked);
input inclk0;
output c0;
output c1;
output locked;
wire [0:0] sub_wire2 = 1'h0;
wire [4:0] sub_wire3;
wire sub_wire6;
wire sub_wire0 = inclk0;
wire [1:0] sub_wire1 = {sub_wire2, sub_wire0};
wire [1:1] sub_wire5 = sub_wire3[1:1];
wire [0:0] sub_wire4 = sub_wire3[0:0];
wire c0 = sub_wire4;
wire c1 = sub_wire5;
wire locked = sub_wire6;
altpll altpll_component (
.inclk (sub_wire1),
.clk (sub_wire3),
.locked (sub_wire6),
.activeclock (),
.areset (1'b0),
.clkbad (),
.clkena ({6{1'b1}}),
.clkloss (),
.clkswitch (1'b0),
.configupdate (1'b0),
.enable0 (),
.enable1 (),
.extclk (),
.extclkena ({4{1'b1}}),
.fbin (1'b1),
.fbmimicbidir (),
.fbout (),
.fref (),
.icdrclk (),
.pfdena (1'b1),
.phasecounterselect ({4{1'b1}}),
.phasedone (),
.phasestep (1'b1),
.phaseupdown (1'b1),
.pllena (1'b1),
.scanaclr (1'b0),
.scanclk (1'b0),
.scanclkena (1'b1),
.scandata (1'b0),
.scandataout (),
.scandone (),
.scanread (1'b0),
.scanwrite (1'b0),
.sclkout0 (),
.sclkout1 (),
.vcooverrange (),
.vcounderrange ());
defparam
altpll_component.bandwidth_type = "AUTO",
altpll_component.clk0_divide_by = 1,
altpll_component.clk0_duty_cycle = 50,
altpll_component.clk0_multiply_by = 2,
altpll_component.clk0_phase_shift = "0",
altpll_component.clk1_divide_by = 1,
altpll_component.clk1_duty_cycle = 50,
altpll_component.clk1_multiply_by = 2,
altpll_component.clk1_phase_shift = "-1500",
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=intel_pll",
altpll_component.lpm_type = "altpll",
altpll_component.operation_mode = "NORMAL",
altpll_component.pll_type = "AUTO",
altpll_component.port_activeclock = "PORT_UNUSED",
altpll_component.port_areset = "PORT_UNUSED",
altpll_component.port_clkbad0 = "PORT_UNUSED",
altpll_component.port_clkbad1 = "PORT_UNUSED",
altpll_component.port_clkloss = "PORT_UNUSED",
altpll_component.port_clkswitch = "PORT_UNUSED",
altpll_component.port_configupdate = "PORT_UNUSED",
altpll_component.port_fbin = "PORT_UNUSED",
altpll_component.port_inclk0 = "PORT_USED",
altpll_component.port_inclk1 = "PORT_UNUSED",
altpll_component.port_locked = "PORT_USED",
altpll_component.port_pfdena = "PORT_UNUSED",
altpll_component.port_phasecounterselect = "PORT_UNUSED",
altpll_component.port_phasedone = "PORT_UNUSED",
altpll_component.port_phasestep = "PORT_UNUSED",
altpll_component.port_phaseupdown = "PORT_UNUSED",
altpll_component.port_pllena = "PORT_UNUSED",
altpll_component.port_scanaclr = "PORT_UNUSED",
altpll_component.port_scanclk = "PORT_UNUSED",
altpll_component.port_scanclkena = "PORT_UNUSED",
altpll_component.port_scandata = "PORT_UNUSED",
altpll_component.port_scandataout = "PORT_UNUSED",
altpll_component.port_scandone = "PORT_UNUSED",
altpll_component.port_scanread = "PORT_UNUSED",
altpll_component.port_scanwrite = "PORT_UNUSED",
altpll_component.port_clk0 = "PORT_USED",
altpll_component.port_clk1 = "PORT_USED",
altpll_component.port_clk2 = "PORT_UNUSED",
altpll_component.port_clk3 = "PORT_UNUSED",
altpll_component.port_clk4 = "PORT_UNUSED",
altpll_component.port_clk5 = "PORT_UNUSED",
altpll_component.port_clkena0 = "PORT_UNUSED",
altpll_component.port_clkena1 = "PORT_UNUSED",
altpll_component.port_clkena2 = "PORT_UNUSED",
altpll_component.port_clkena3 = "PORT_UNUSED",
altpll_component.port_clkena4 = "PORT_UNUSED",
altpll_component.port_clkena5 = "PORT_UNUSED",
altpll_component.port_extclk0 = "PORT_UNUSED",
altpll_component.port_extclk1 = "PORT_UNUSED",
altpll_component.port_extclk2 = "PORT_UNUSED",
altpll_component.port_extclk3 = "PORT_UNUSED",
altpll_component.self_reset_on_loss_lock = "ON",
altpll_component.width_clock = 5;
endmodule
// ============================================================
// CNX file retrieval info
// ============================================================
// Retrieval info: PRIVATE: ACTIVECLK_CHECK STRING "0"
// Retrieval info: PRIVATE: BANDWIDTH STRING "1.000"
// Retrieval info: PRIVATE: BANDWIDTH_FEATURE_ENABLED STRING "1"
// Retrieval info: PRIVATE: BANDWIDTH_FREQ_UNIT STRING "MHz"
// Retrieval info: PRIVATE: BANDWIDTH_PRESET STRING "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"
// Retrieval info: PRIVATE: CLKLOSS_CHECK STRING "0"
// Retrieval info: PRIVATE: CLKSWITCH_CHECK STRING "0"
// Retrieval info: PRIVATE: CNX_NO_COMPENSATE_RADIO STRING "0"
// Retrieval info: PRIVATE: CREATE_CLKBAD_CHECK STRING "0"
// Retrieval info: PRIVATE: CREATE_INCLK1_CHECK STRING "0"
// Retrieval info: PRIVATE: CUR_DEDICATED_CLK STRING "c0"
// Retrieval info: PRIVATE: CUR_FBIN_CLK STRING "c0"
// Retrieval info: PRIVATE: DEVICE_SPEED_GRADE STRING "Any"
// Retrieval info: PRIVATE: DIV_FACTOR0 NUMERIC "1"
// Retrieval info: PRIVATE: DIV_FACTOR1 NUMERIC "1"
// Retrieval info: PRIVATE: DUTY_CYCLE0 STRING "50.00000000"
// Retrieval info: PRIVATE: DUTY_CYCLE1 STRING "50.00000000"
// Retrieval info: PRIVATE: EFF_OUTPUT_FREQ_VALUE0 STRING "100.000000"
// Retrieval info: PRIVATE: EFF_OUTPUT_FREQ_VALUE1 STRING "100.000000"
// Retrieval info: PRIVATE: EXPLICIT_SWITCHOVER_COUNTER STRING "0"
// Retrieval info: PRIVATE: EXT_FEEDBACK_RADIO STRING "0"
// Retrieval info: PRIVATE: GLOCKED_COUNTER_EDIT_CHANGED STRING "1"
// Retrieval info: PRIVATE: GLOCKED_FEATURE_ENABLED STRING "0"
// Retrieval info: PRIVATE: GLOCKED_MODE_CHECK STRING "0"
// Retrieval info: PRIVATE: GLOCK_COUNTER_EDIT NUMERIC "1048575"
// Retrieval info: PRIVATE: HAS_MANUAL_SWITCHOVER STRING "1"
// Retrieval info: PRIVATE: INCLK0_FREQ_EDIT STRING "50.000"
// Retrieval info: PRIVATE: INCLK0_FREQ_UNIT_COMBO STRING "MHz"
// Retrieval info: PRIVATE: INCLK1_FREQ_EDIT STRING "100.000"
// Retrieval info: PRIVATE: INCLK1_FREQ_EDIT_CHANGED STRING "1"
// Retrieval info: PRIVATE: INCLK1_FREQ_UNIT_CHANGED STRING "1"
// Retrieval info: PRIVATE: INCLK1_FREQ_UNIT_COMBO STRING "MHz"
// Retrieval info: PRIVATE: INTENDED_DEVICE_FAMILY STRING "MAX 10"
// Retrieval info: PRIVATE: INT_FEEDBACK__MODE_RADIO STRING "1"
// Retrieval info: PRIVATE: LOCKED_OUTPUT_CHECK STRING "1"
// Retrieval info: PRIVATE: LONG_SCAN_RADIO STRING "1"
// Retrieval info: PRIVATE: LVDS_MODE_DATA_RATE STRING "Not Available"
// Retrieval info: PRIVATE: LVDS_MODE_DATA_RATE_DIRTY NUMERIC "0"
// Retrieval info: PRIVATE: LVDS_PHASE_SHIFT_UNIT0 STRING "deg"
// Retrieval info: PRIVATE: LVDS_PHASE_SHIFT_UNIT1 STRING "deg"
// Retrieval info: PRIVATE: MIG_DEVICE_SPEED_GRADE STRING "Any"
// Retrieval info: PRIVATE: MIRROR_CLK0 STRING "0"
// Retrieval info: PRIVATE: MIRROR_CLK1 STRING "0"
// Retrieval info: PRIVATE: MULT_FACTOR0 NUMERIC "1"
// Retrieval info: PRIVATE: MULT_FACTOR1 NUMERIC "1"
// Retrieval info: PRIVATE: NORMAL_MODE_RADIO STRING "1"
// Retrieval info: PRIVATE: OUTPUT_FREQ0 STRING "100.00000000"
// Retrieval info: PRIVATE: OUTPUT_FREQ1 STRING "100.00000000"
// Retrieval info: PRIVATE: OUTPUT_FREQ_MODE0 STRING "1"
// Retrieval info: PRIVATE: OUTPUT_FREQ_MODE1 STRING "1"
// Retrieval info: PRIVATE: OUTPUT_FREQ_UNIT0 STRING "MHz"
// Retrieval info: PRIVATE: OUTPUT_FREQ_UNIT1 STRING "MHz"
// Retrieval info: PRIVATE: PHASE_RECONFIG_FEATURE_ENABLED STRING "1"
// Retrieval info: PRIVATE: PHASE_RECONFIG_INPUTS_CHECK STRING "0"
// Retrieval info: PRIVATE: PHASE_SHIFT0 STRING "0.00000000"
// Retrieval info: PRIVATE: PHASE_SHIFT1 STRING "-54.00000000"
// Retrieval info: PRIVATE: PHASE_SHIFT_STEP_ENABLED_CHECK STRING "0"
// Retrieval info: PRIVATE: PHASE_SHIFT_UNIT0 STRING "deg"
// Retrieval info: PRIVATE: PHASE_SHIFT_UNIT1 STRING "deg"
// Retrieval info: PRIVATE: PLL_ADVANCED_PARAM_CHECK STRING "0"
// Retrieval info: PRIVATE: PLL_ARESET_CHECK STRING "0"
// Retrieval info: PRIVATE: PLL_AUTOPLL_CHECK NUMERIC "1"
// Retrieval info: PRIVATE: PLL_ENHPLL_CHECK NUMERIC "0"
// Retrieval info: PRIVATE: PLL_FASTPLL_CHECK NUMERIC "0"
// Retrieval info: PRIVATE: PLL_FBMIMIC_CHECK STRING "0"
// Retrieval info: PRIVATE: PLL_LVDS_PLL_CHECK NUMERIC "0"
// Retrieval info: PRIVATE: PLL_PFDENA_CHECK STRING "0"
// Retrieval info: PRIVATE: PLL_TARGET_HARCOPY_CHECK NUMERIC "0"
// Retrieval info: PRIVATE: PRIMARY_CLK_COMBO STRING "inclk0"
// Retrieval info: PRIVATE: RECONFIG_FILE STRING "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"
// Retrieval info: PRIVATE: SHORT_SCAN_RADIO STRING "0"
// Retrieval info: PRIVATE: SPREAD_FEATURE_ENABLED STRING "0"
// Retrieval info: PRIVATE: SPREAD_FREQ STRING "50.000"
// Retrieval info: PRIVATE: SPREAD_FREQ_UNIT STRING "KHz"
// Retrieval info: PRIVATE: SPREAD_PERCENT STRING "0.500"
// Retrieval info: PRIVATE: SPREAD_USE STRING "0"
// Retrieval info: PRIVATE: SRC_SYNCH_COMP_RADIO STRING "0"
// Retrieval info: PRIVATE: STICKY_CLK0 STRING "1"
// Retrieval info: PRIVATE: STICKY_CLK1 STRING "1"
// Retrieval info: PRIVATE: STICKY_CLK2 STRING "0"
// Retrieval info: PRIVATE: STICKY_CLK3 STRING "0"
// Retrieval info: PRIVATE: STICKY_CLK4 STRING "0"
// Retrieval info: PRIVATE: SWITCHOVER_COUNT_EDIT NUMERIC "1"
// Retrieval info: PRIVATE: SWITCHOVER_FEATURE_ENABLED STRING "1"
// Retrieval info: PRIVATE: SYNTH_WRAPPER_GEN_POSTFIX STRING "0"
// Retrieval info: PRIVATE: USE_CLK0 STRING "1"
// Retrieval info: PRIVATE: USE_CLK1 STRING "1"
// Retrieval info: PRIVATE: USE_CLKENA0 STRING "0"
// Retrieval info: PRIVATE: USE_CLKENA1 STRING "0"
// Retrieval info: PRIVATE: USE_MIL_SPEED_GRADE NUMERIC "0"
// Retrieval info: PRIVATE: ZERO_DELAY_RADIO STRING "0"
// Retrieval info: LIBRARY: altera_mf altera_mf.altera_mf_components.all
// Retrieval info: CONSTANT: BANDWIDTH_TYPE STRING "AUTO"
// Retrieval info: CONSTANT: CLK0_DIVIDE_BY NUMERIC "1"
// Retrieval info: CONSTANT: CLK0_DUTY_CYCLE NUMERIC "50"
// Retrieval info: CONSTANT: CLK0_MULTIPLY_BY NUMERIC "2"
// Retrieval info: CONSTANT: CLK0_PHASE_SHIFT STRING "0"
// Retrieval info: CONSTANT: CLK1_DIVIDE_BY NUMERIC "1"
// Retrieval info: CONSTANT: CLK1_DUTY_CYCLE NUMERIC "50"
// Retrieval info: CONSTANT: CLK1_MULTIPLY_BY NUMERIC "2"
// Retrieval info: CONSTANT: CLK1_PHASE_SHIFT STRING "-1500"
// Retrieval info: CONSTANT: COMPENSATE_CLOCK STRING "CLK0"
// Retrieval info: CONSTANT: INCLK0_INPUT_FREQUENCY NUMERIC "20000"
// Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "MAX 10"
// Retrieval info: CONSTANT: LPM_TYPE STRING "altpll"
// Retrieval info: CONSTANT: OPERATION_MODE STRING "NORMAL"
// Retrieval info: CONSTANT: PLL_TYPE STRING "AUTO"
// Retrieval info: CONSTANT: PORT_ACTIVECLOCK STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_ARESET STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_CLKBAD0 STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_CLKBAD1 STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_CLKLOSS STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_CLKSWITCH STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_CONFIGUPDATE STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_FBIN STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_INCLK0 STRING "PORT_USED"
// Retrieval info: CONSTANT: PORT_INCLK1 STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_LOCKED STRING "PORT_USED"
// Retrieval info: CONSTANT: PORT_PFDENA STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_PHASECOUNTERSELECT STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_PHASEDONE STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_PHASESTEP STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_PHASEUPDOWN STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_PLLENA STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_SCANACLR STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_SCANCLK STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_SCANCLKENA STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_SCANDATA STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_SCANDATAOUT STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_SCANDONE STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_SCANREAD STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_SCANWRITE STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_clk0 STRING "PORT_USED"
// Retrieval info: CONSTANT: PORT_clk1 STRING "PORT_USED"
// Retrieval info: CONSTANT: PORT_clk2 STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_clk3 STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_clk4 STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_clk5 STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_clkena0 STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_clkena1 STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_clkena2 STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_clkena3 STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_clkena4 STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_clkena5 STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_extclk0 STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_extclk1 STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_extclk2 STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_extclk3 STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: SELF_RESET_ON_LOSS_LOCK STRING "ON"
// Retrieval info: CONSTANT: WIDTH_CLOCK NUMERIC "5"
// Retrieval info: USED_PORT: @clk 0 0 5 0 OUTPUT_CLK_EXT VCC "@clk[4..0]"
// Retrieval info: USED_PORT: c0 0 0 0 0 OUTPUT_CLK_EXT VCC "c0"
// Retrieval info: USED_PORT: c1 0 0 0 0 OUTPUT_CLK_EXT VCC "c1"
// Retrieval info: USED_PORT: inclk0 0 0 0 0 INPUT_CLK_EXT GND "inclk0"
// Retrieval info: USED_PORT: locked 0 0 0 0 OUTPUT GND "locked"
// Retrieval info: CONNECT: @inclk 0 0 1 1 GND 0 0 0 0
// Retrieval info: CONNECT: @inclk 0 0 1 0 inclk0 0 0 0 0
// Retrieval info: CONNECT: c0 0 0 0 0 @clk 0 0 1 0
// Retrieval info: CONNECT: c1 0 0 0 0 @clk 0 0 1 1
// Retrieval info: CONNECT: locked 0 0 0 0 @locked 0 0 0 0
// Retrieval info: GEN_FILE: TYPE_NORMAL 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: CBX_MODULE_PREFIX: ON

92
fw/rtl/mcu/mcu_spi.sv Normal file
View File

@ -0,0 +1,92 @@
module mcu_spi (
input clk,
input reset,
output logic frame_start,
output logic data_ready,
output logic [7:0] rx_data,
input [7:0] tx_data,
input mcu_clk,
input mcu_cs,
input mcu_mosi,
output logic mcu_miso
);
logic [2:0] mcu_clk_ff;
logic [2:0] mcu_cs_ff;
always_ff @(posedge clk) begin
mcu_clk_ff <= {mcu_clk_ff[1:0], mcu_clk};
mcu_cs_ff <= {mcu_cs_ff[1:0], mcu_cs};
end
logic mcu_clk_falling;
logic mcu_clk_rising;
logic mcu_cs_falling;
logic mcu_cs_rising;
always_comb begin
mcu_clk_falling = mcu_clk_ff[2] && !mcu_clk_ff[1];
mcu_clk_rising = !mcu_clk_ff[2] && mcu_clk_ff[1];
mcu_cs_falling = mcu_cs_ff[2] && !mcu_cs_ff[1];
mcu_cs_rising = !mcu_cs_ff[2] && mcu_cs_ff[1];
end
logic mcu_dq_in;
logic mcu_dq_out;
logic mcu_miso_out;
assign mcu_miso = mcu_cs_ff[1] ? 1'bZ : mcu_miso_out;
always_ff @(posedge clk) begin
mcu_dq_in <= mcu_mosi;
mcu_miso_out <= mcu_dq_out;
end
logic [7:0] spi_tx_shift;
assign mcu_dq_out = spi_tx_shift[7];
logic spi_enabled;
logic [2:0] spi_bit_counter;
always_ff @(posedge clk) begin
frame_start <= 1'b0;
data_ready <= 1'b0;
if (reset) begin
spi_enabled <= 1'b0;
spi_bit_counter <= 3'd0;
end else begin
if (mcu_cs_falling) begin
spi_enabled <= 1'b1;
spi_bit_counter <= 3'd0;
frame_start <= 1'b1;
end
if (mcu_cs_rising) begin
spi_enabled <= 1'b0;
end
if (spi_enabled) begin
if (mcu_clk_rising) begin
if (spi_bit_counter == 3'd0) begin
spi_tx_shift <= tx_data;
end else begin
spi_tx_shift <= {spi_tx_shift[6:0], 1'b0};
end
end
if (mcu_clk_falling) begin
spi_bit_counter <= spi_bit_counter + 1'd1;
rx_data <= {rx_data[6:0], mcu_dq_in};
if (spi_bit_counter == 3'd7) begin
data_ready <= 1'b1;
end
end
end
end
end
endmodule

901
fw/rtl/mcu/mcu_top.sv Normal file
View File

@ -0,0 +1,901 @@
module mcu_top (
input clk,
input reset,
n64_scb.controller n64_scb,
dd_scb.controller dd_scb,
usb_scb.controller usb_scb,
dma_scb.controller usb_dma_scb,
sd_scb.controller sd_scb,
dma_scb.controller sd_dma_scb,
flash_scb.controller flash_scb,
vendor_scb.controller vendor_scb,
fifo_bus.controller fifo_bus,
mem_bus.controller mem_bus,
input sd_det,
input button,
output logic mcu_int,
input mcu_clk,
input mcu_cs,
input mcu_mosi,
output mcu_miso
);
// Button input synchronization
logic [2:0] sd_det_ff;
logic [2:0] button_ff;
always_ff @(posedge clk) begin
sd_det_ff <= {sd_det_ff[1:0], sd_det};
button_ff <= {button_ff[1:0], button};
end
// MCU <-> FPGA transport
logic frame_start;
logic data_ready;
logic [7:0] rdata;
logic [7:0] wdata;
mcu_spi mcu_spi_inst (
.clk(clk),
.reset(reset),
.frame_start(frame_start),
.data_ready(data_ready),
.rx_data(rdata),
.tx_data(wdata),
.mcu_clk(mcu_clk),
.mcu_cs(mcu_cs),
.mcu_mosi(mcu_mosi),
.mcu_miso(mcu_miso)
);
// Protocol controller
const bit [7:0] FPGA_ID = 8'h64;
typedef enum bit [1:0] {
PHASE_CMD,
PHASE_ADDRESS,
PHASE_DATA,
PHASE_NOP
} phase_e;
typedef enum bit [7:0] {
CMD_IDENTIFY,
CMD_REG_READ,
CMD_REG_WRITE,
CMD_MEM_READ,
CMD_MEM_WRITE,
CMD_USB_STATUS,
CMD_USB_READ,
CMD_USB_WRITE
} cmd_e;
phase_e phase;
cmd_e cmd;
logic [1:0] counter;
logic [7:0] address;
logic reg_read;
logic reg_write;
logic [31:0] reg_rdata;
logic [31:0] reg_wdata;
logic mem_read;
logic mem_write;
logic [15:0] mem_rdata;
logic [15:0] mem_wdata;
logic mem_word_select;
always_ff @(posedge clk) begin
fifo_bus.rx_read <= 1'b0;
fifo_bus.tx_write <= 1'b0;
reg_read <= 1'b0;
reg_write <= 1'b0;
mem_read <= 1'b0;
mem_write <= 1'b0;
if (reset) begin
end else begin
if (frame_start) begin
counter <= 2'd0;
phase <= PHASE_CMD;
end
if (reg_read || reg_write || (mem_word_select && (mem_read || mem_write))) begin
address <= address + 1'd1;
end
if (data_ready) begin
case (phase)
PHASE_CMD: begin
cmd <= cmd_e'(rdata);
phase <= PHASE_ADDRESS;
if (rdata == CMD_USB_STATUS) begin
phase <= PHASE_NOP;
end
if (rdata == CMD_USB_READ) begin
fifo_bus.rx_read <= 1'b1;
phase <= PHASE_DATA;
end
if (rdata == CMD_USB_WRITE) begin
phase <= PHASE_DATA;
end
end
PHASE_ADDRESS: begin
address <= rdata;
phase <= PHASE_DATA;
if (cmd == CMD_REG_READ) begin
reg_read <= 1'b1;
end
if (cmd == CMD_MEM_READ) begin
mem_read <= 1'b1;
mem_word_select <= 1'b0;
end
end
PHASE_DATA: begin
counter <= counter + 1'd1;
if (cmd == CMD_REG_READ) begin
if (counter == 2'd3) begin
reg_read <= 1'd1;
end
end
if (cmd == CMD_REG_WRITE) begin
case (counter)
2'd0: reg_wdata[7:0] <= rdata;
2'd1: reg_wdata[15:8] <= rdata;
2'd2: reg_wdata[23:16] <= rdata;
2'd3: reg_wdata[31:24] <= rdata;
endcase
if (counter == 2'd3) begin
reg_write <= 1'd1;
end
end
if (cmd == CMD_MEM_READ) begin
if (counter[0]) begin
mem_read <= 1'b1;
mem_word_select <= ~mem_word_select;
end
end
if (cmd == CMD_MEM_WRITE) begin
case (counter[0])
1'd0: mem_wdata[15:8] <= rdata;
1'd1: mem_wdata[7:0] <= rdata;
endcase
if (counter[0]) begin
mem_write <= 1'b1;
mem_word_select <= counter[1];
end
end
if (cmd == CMD_USB_READ) begin
phase <= PHASE_NOP;
end
if (cmd == CMD_USB_WRITE) begin
fifo_bus.tx_write <= 1'b1;
fifo_bus.tx_wdata <= rdata;
phase <= PHASE_NOP;
end
end
PHASE_NOP: begin end
endcase
end
end
end
always_comb begin
wdata = 8'h00;
case (cmd)
CMD_IDENTIFY: begin
wdata = FPGA_ID;
end
CMD_REG_READ: begin
case (counter)
2'd0: wdata = reg_rdata[7:0];
2'd1: wdata = reg_rdata[15:8];
2'd2: wdata = reg_rdata[23:16];
2'd3: wdata = reg_rdata[31:24];
endcase
end
CMD_REG_WRITE: begin
wdata = 8'h00;
end
CMD_MEM_READ: begin
case (counter[0])
1'd0: wdata = mem_rdata[15:8];
1'd1: wdata = mem_rdata[7:0];
endcase
end
CMD_MEM_WRITE: begin
wdata = 8'h00;
end
CMD_USB_STATUS: begin
wdata = {6'd0, ~fifo_bus.tx_full, ~fifo_bus.rx_empty};
end
CMD_USB_READ: begin
wdata = fifo_bus.rx_rdata;
end
CMD_USB_WRITE: begin
wdata = 8'h00;
end
endcase
end
// Mem bus controller
logic [15:0] mem_buffer [0:511];
logic mem_start;
logic mem_stop;
logic mem_direction;
logic [8:0] mem_length;
logic [31:0] mem_address;
logic mem_busy;
logic mem_stop_pending;
logic [8:0] mem_counter;
always_ff @(posedge clk) begin
if (reset) begin
mem_busy <= 1'b0;
mem_stop_pending <= 1'b0;
mem_bus.request <= 1'b0;
end else begin
if (mem_read) begin
mem_rdata <= mem_buffer[{address, mem_word_select}];
end
if (mem_write) begin
mem_buffer[{address, mem_word_select}] <= mem_wdata;
end
if (mem_stop) begin
mem_stop_pending <= mem_busy;
end else if (mem_start && !mem_busy) begin
mem_bus.write <= mem_direction;
mem_bus.address <= mem_address;
mem_busy <= 1'b1;
mem_counter <= 9'd0;
end
if (mem_busy) begin
if (!mem_bus.request) begin
mem_bus.request <= 1'b1;
mem_bus.wdata <= mem_buffer[mem_counter];
end
if (mem_bus.ack) begin
mem_bus.request <= 1'b0;
mem_bus.address <= mem_bus.address + 2'd2;
mem_counter <= mem_counter + 1'd1;
if (!mem_bus.write) begin
mem_buffer[mem_counter] <= mem_bus.rdata;
end
if ((mem_counter == mem_length) || mem_stop_pending) begin
mem_busy <= 1'b0;
mem_stop_pending <= 1'b0;
end
end
end
end
end
always_comb begin
mem_bus.wmask = 2'b11;
end
// Register list
typedef enum bit [7:0] {
REG_MEM_ADDRESS,
REG_MEM_SCR,
REG_USB_SCR,
REG_USB_DMA_ADDRESS,
REG_USB_DMA_LENGTH,
REG_USB_DMA_SCR,
REG_CFG_SCR,
REG_CFG_DATA_0,
REG_CFG_DATA_1,
REG_CFG_CMD,
REG_CFG_VERSION,
REG_FLASHRAM_SCR,
REG_FLASH_SCR,
REG_RTC_SCR,
REG_RTC_TIME_0,
REG_RTC_TIME_1,
REG_SD_SCR,
REG_SD_ARG,
REG_SD_CMD,
REG_SD_RSP_0,
REG_SD_RSP_1,
REG_SD_RSP_2,
REG_SD_RSP_3,
REG_SD_DAT,
REG_SD_DMA_ADDRESS,
REG_SD_DMA_LENGTH,
REG_SD_DMA_SCR,
REG_DD_SCR,
REG_DD_CMD_DATA,
REG_DD_HEAD_TRACK,
REG_DD_SECTOR_INFO,
REG_DD_DRIVE_ID,
REG_VENDOR_SCR,
REG_VENDOR_DATA,
REG_DEBUG_0,
REG_DEBUG_1
} reg_address_e;
logic bootloader_skip;
assign n64_scb.cfg_version = 32'h53437632;
logic dd_bm_ack;
// Register read logic
always_ff @(posedge clk) begin
if (reg_read) begin
reg_rdata <= 32'd0;
case (address)
REG_MEM_ADDRESS: begin
reg_rdata <= mem_address;
end
REG_MEM_SCR: begin
reg_rdata <= {
28'd0,
mem_busy,
3'b000
};
end
REG_USB_SCR: begin
reg_rdata <= {
2'd0,
usb_scb.pwrsav,
usb_scb.reset_state,
usb_scb.tx_count,
usb_scb.rx_count,
2'b00,
usb_scb.reset_pending,
~fifo_bus.tx_full,
~fifo_bus.rx_empty,
1'b0
};
end
REG_USB_DMA_ADDRESS: begin
reg_rdata <= {
5'd0,
usb_dma_scb.starting_address
};
end
REG_USB_DMA_LENGTH: begin
reg_rdata <= {
5'd0,
usb_dma_scb.transfer_length
};
end
REG_USB_DMA_SCR: begin
reg_rdata <= {
28'd0,
usb_dma_scb.busy,
usb_dma_scb.direction,
2'b00
};
end
REG_CFG_SCR: begin
reg_rdata <= {
~button_ff[2],
19'd0,
n64_scb.rom_extended_enabled,
n64_scb.eeprom_16k_mode,
n64_scb.eeprom_enabled,
n64_scb.ddipl_enabled,
n64_scb.dd_enabled,
n64_scb.flashram_enabled,
n64_scb.sram_banked,
n64_scb.sram_enabled,
n64_scb.rom_shadow_enabled,
n64_scb.rom_write_enabled,
bootloader_skip,
n64_scb.bootloader_enabled
};
end
REG_CFG_DATA_0: begin
reg_rdata <= n64_scb.cfg_rdata[0];
end
REG_CFG_DATA_1: begin
reg_rdata <= n64_scb.cfg_rdata[1];
end
REG_CFG_CMD: begin
reg_rdata <= {
23'd0,
n64_scb.cfg_pending,
n64_scb.cfg_cmd
};
end
REG_CFG_VERSION: begin
reg_rdata <= n64_scb.cfg_version;
end
REG_FLASHRAM_SCR: begin
reg_rdata <= {
18'd0,
n64_scb.flashram_write_or_erase,
n64_scb.flashram_sector_or_all,
n64_scb.flashram_sector,
n64_scb.flashram_pending,
1'b0
};
end
REG_FLASH_SCR: begin
reg_rdata <= {
31'd0,
flash_scb.erase_pending
};
end
REG_RTC_SCR: begin
reg_rdata <= {
24'h525443,
7'd0,
n64_scb.rtc_pending
};
end
REG_RTC_TIME_0: begin
reg_rdata <= {
5'd0, n64_scb.rtc_rdata[28:26],
2'd0, n64_scb.rtc_rdata[19:14],
1'd0, n64_scb.rtc_rdata[13:7],
1'd0, n64_scb.rtc_rdata[6:0]
};
end
REG_RTC_TIME_1: begin
reg_rdata <= {
8'd0,
n64_scb.rtc_rdata[41:34],
3'd0, n64_scb.rtc_rdata[33:29],
2'd0, n64_scb.rtc_rdata[25:20]
};
end
REG_SD_SCR: begin
reg_rdata <= {
4'd0,
sd_scb.tx_count,
sd_scb.rx_count,
~sd_det_ff[2],
sd_scb.card_busy,
sd_scb.cmd_error,
sd_scb.cmd_busy,
sd_scb.clock_mode
};
end
REG_SD_ARG: begin
reg_rdata <= sd_scb.cmd_arg;
end
REG_SD_CMD: begin
reg_rdata <= {
22'd0,
sd_scb.cmd_ignore_crc,
sd_scb.cmd_long_response,
sd_scb.cmd_reserved_response,
sd_scb.cmd_skip_response,
sd_scb.cmd_index
};
end
REG_SD_RSP_0: begin
reg_rdata <= sd_scb.cmd_rsp[31:0];
end
REG_SD_RSP_1: begin
reg_rdata <= sd_scb.cmd_rsp[63:32];
end
REG_SD_RSP_2: begin
reg_rdata <= sd_scb.cmd_rsp[95:64];
end
REG_SD_RSP_3: begin
reg_rdata <= sd_scb.cmd_rsp[127:96];
end
REG_SD_DAT: begin
reg_rdata <= {
18'd0,
sd_scb.dat_error,
sd_scb.dat_busy,
12'd0
};
end
REG_SD_DMA_ADDRESS: begin
reg_rdata <= {
5'd0,
sd_dma_scb.starting_address
};
end
REG_SD_DMA_LENGTH: begin
reg_rdata <= {
5'd0,
sd_dma_scb.transfer_length
};
end
REG_SD_DMA_SCR: begin
reg_rdata <= {
28'd0,
sd_dma_scb.busy,
sd_dma_scb.direction,
2'b00
};
end
REG_DD_SCR: begin
reg_rdata <= {
14'd0,
dd_bm_ack,
dd_scb.bm_micro_error,
dd_scb.bm_transfer_c2,
dd_scb.bm_transfer_data,
dd_scb.bm_transfer_blocks,
dd_scb.bm_transfer_mode,
1'b0,
dd_scb.bm_stop_pending,
1'b0,
dd_scb.bm_start_pending,
dd_scb.disk_changed,
dd_scb.disk_inserted,
1'b0,
dd_scb.bm_pending,
1'b0,
dd_scb.cmd_pending,
1'b0,
dd_scb.hard_reset
};
end
REG_DD_CMD_DATA: begin
reg_rdata <= {8'd0, dd_scb.cmd, dd_scb.data};
end
REG_DD_HEAD_TRACK: begin
reg_rdata <= {18'd0, dd_scb.index_lock, dd_scb.head_track};
end
REG_DD_SECTOR_INFO: begin
reg_rdata <= {
dd_scb.sectors_in_block,
dd_scb.sector_size_full,
dd_scb.sector_size,
dd_scb.sector_num
};
end
REG_VENDOR_SCR: begin
reg_rdata <= vendor_scb.control_rdata;
end
REG_VENDOR_DATA: begin
reg_rdata <= vendor_scb.data_rdata;
end
REG_DEBUG_0: begin
reg_rdata <= n64_scb.pi_debug[31:0];
end
REG_DEBUG_1: begin
reg_rdata <= {
28'd0,
n64_scb.pi_debug[35:32]
};
end
endcase
end
end
// Register write logic
always_ff @(posedge clk) begin
mem_start <= 1'b0;
mem_stop <= 1'b0;
usb_scb.write_buffer_flush <= 1'b0;
usb_scb.reset_ack <= 1'b0;
usb_scb.fifo_flush <= 1'b0;
usb_dma_scb.start <= 1'b0;
usb_dma_scb.stop <= 1'b0;
sd_scb.cmd_start <= 1'b0;
sd_scb.dat_fifo_flush <= 1'b0;
sd_scb.dat_start_write <= 1'b0;
sd_scb.dat_start_read <= 1'b0;
sd_scb.dat_stop <= 1'b0;
sd_dma_scb.start <= 1'b0;
sd_dma_scb.stop <= 1'b0;
n64_scb.cfg_done <= 1'b0;
n64_scb.cfg_error <= 1'b0;
n64_scb.cfg_irq <= 1'b0;
n64_scb.flashram_done <= 1'b0;
n64_scb.rtc_done <= 1'b0;
dd_scb.hard_reset_clear <= 1'b0;
dd_scb.cmd_ready <= 1'b0;
dd_scb.bm_start_clear <= 1'b0;
dd_scb.bm_stop_clear <= 1'b0;
dd_scb.bm_clear <= 1'b0;
dd_scb.bm_ready <= 1'b0;
vendor_scb.control_valid <= 1'b0;
if (n64_scb.n64_nmi) begin
n64_scb.bootloader_enabled <= !bootloader_skip;
end
if (flash_scb.erase_done) begin
flash_scb.erase_pending <= 1'b0;
end
if (dd_scb.bm_interrupt_ack) begin
dd_bm_ack <= 1'b1;
end
if (reset) begin
mcu_int <= 1'b0;
sd_scb.clock_mode <= 2'd0;
n64_scb.rom_extended_enabled <= 1'b0;
n64_scb.eeprom_16k_mode <= 1'b0;
n64_scb.eeprom_enabled <= 1'b0;
n64_scb.dd_enabled <= 1'b0;
n64_scb.ddipl_enabled <= 1'b0;
n64_scb.flashram_enabled <= 1'b0;
n64_scb.sram_banked <= 1'b0;
n64_scb.sram_enabled <= 1'b0;
n64_scb.rom_shadow_enabled <= 1'b0;
n64_scb.rom_write_enabled <= 1'b0;
bootloader_skip <= 1'b0;
n64_scb.bootloader_enabled <= 1'b1;
flash_scb.erase_pending <= 1'b0;
dd_bm_ack <= 1'b0;
n64_scb.rtc_wdata_valid <= 1'b0;
end else if (reg_write) begin
case (address)
REG_MEM_ADDRESS: begin
mem_address <= reg_wdata;
end
REG_MEM_SCR: begin
{
mem_length,
mem_direction,
mem_stop,
mem_start
} <= {(reg_wdata[14:5] - 1'd1), reg_wdata[2:0]};
end
REG_USB_SCR: begin
{
usb_scb.write_buffer_flush,
usb_scb.reset_ack,
usb_scb.fifo_flush
} <= {reg_wdata[5:4], reg_wdata[0]};
end
REG_USB_DMA_ADDRESS: begin
usb_dma_scb.starting_address <= reg_wdata[26:0];
end
REG_USB_DMA_LENGTH: begin
usb_dma_scb.transfer_length <= reg_wdata[26:0];
end
REG_USB_DMA_SCR: begin
{
usb_dma_scb.direction,
usb_dma_scb.stop,
usb_dma_scb.start
} <= reg_wdata[2:0];
end
REG_CFG_SCR: begin
{
n64_scb.rom_extended_enabled,
n64_scb.eeprom_16k_mode,
n64_scb.eeprom_enabled,
n64_scb.ddipl_enabled,
n64_scb.dd_enabled,
n64_scb.flashram_enabled,
n64_scb.sram_banked,
n64_scb.sram_enabled,
n64_scb.rom_shadow_enabled,
n64_scb.rom_write_enabled,
bootloader_skip,
n64_scb.bootloader_enabled
} <= reg_wdata[11:0];
end
REG_CFG_DATA_0: begin
n64_scb.cfg_wdata[0] <= reg_wdata;
end
REG_CFG_DATA_1: begin
n64_scb.cfg_wdata[1] <= reg_wdata;
end
REG_CFG_CMD: begin
{
n64_scb.cfg_irq,
n64_scb.cfg_error,
n64_scb.cfg_done
} <= reg_wdata[11:9];
end
REG_FLASHRAM_SCR: begin
n64_scb.flashram_done <= reg_wdata[0];
end
REG_FLASH_SCR: begin
flash_scb.erase_pending <= 1'b1;
flash_scb.erase_block <= reg_wdata[23:16];
end
REG_RTC_SCR: begin
n64_scb.rtc_done <= reg_wdata[1];
end
REG_RTC_TIME_0: begin
n64_scb.rtc_wdata_valid <= 1'b0;
n64_scb.rtc_wdata[28:26] <= reg_wdata[26:24];
n64_scb.rtc_wdata[19:14] <= reg_wdata[21:16];
n64_scb.rtc_wdata[13:7] <= reg_wdata[14:8];
n64_scb.rtc_wdata[6:0] <= reg_wdata[6:0];
end
REG_RTC_TIME_1: begin
n64_scb.rtc_wdata_valid <= 1'b1;
n64_scb.rtc_wdata[41:34] <= reg_wdata[23:16];
n64_scb.rtc_wdata[33:29] <= reg_wdata[12:8];
n64_scb.rtc_wdata[25:20] <= reg_wdata[5:0];
end
REG_SD_SCR: begin
sd_scb.clock_mode <= reg_wdata[1:0];
end
REG_SD_ARG: begin
sd_scb.cmd_arg <= reg_wdata;
end
REG_SD_CMD: begin
sd_scb.cmd_start <= 1'b1;
sd_scb.cmd_ignore_crc <= reg_wdata[9];
sd_scb.cmd_long_response <= reg_wdata[8];
sd_scb.cmd_reserved_response <= reg_wdata[7];
sd_scb.cmd_skip_response <= reg_wdata[6];
sd_scb.cmd_index <= reg_wdata[5:0];
end
REG_SD_DAT: begin
sd_scb.dat_blocks <= reg_wdata[11:4];
sd_scb.dat_stop <= reg_wdata[3];
sd_scb.dat_start_read <= reg_wdata[2];
sd_scb.dat_start_write <= reg_wdata[1];
sd_scb.dat_fifo_flush <= reg_wdata[0];
end
REG_SD_DMA_ADDRESS: begin
sd_dma_scb.starting_address <= reg_wdata[26:0];
end
REG_SD_DMA_LENGTH: begin
sd_dma_scb.transfer_length <= reg_wdata[26:0];
end
REG_SD_DMA_SCR: begin
{
sd_dma_scb.direction,
sd_dma_scb.stop,
sd_dma_scb.start
} <= reg_wdata[2:0];
end
REG_DD_SCR: begin
dd_scb.bm_clear <= reg_wdata[19];
if (reg_wdata[18]) begin
dd_bm_ack <= 1'b0;
end
dd_scb.bm_micro_error <= reg_wdata[16];
dd_scb.bm_transfer_c2 <= reg_wdata[15];
dd_scb.bm_transfer_data <= reg_wdata[14];
dd_scb.bm_stop_clear <= reg_wdata[11];
dd_scb.bm_start_clear <= reg_wdata[9];
dd_scb.disk_changed <= reg_wdata[7];
dd_scb.disk_inserted <= reg_wdata[6];
dd_scb.bm_ready <= reg_wdata[5];
dd_scb.cmd_ready <= reg_wdata[3];
dd_scb.hard_reset_clear <= reg_wdata[1];
end
REG_DD_CMD_DATA: begin
dd_scb.cmd_data <= reg_wdata[15:0];
end
REG_DD_HEAD_TRACK: begin
{dd_scb.index_lock, dd_scb.head_track} <= reg_wdata[13:0];
end
REG_DD_DRIVE_ID: begin
dd_scb.drive_id <= reg_wdata[15:0];
end
REG_VENDOR_SCR: begin
vendor_scb.control_valid <= 1'b1;
vendor_scb.control_wdata <= reg_wdata;
end
REG_VENDOR_DATA: begin
vendor_scb.data_wdata <= reg_wdata;
end
endcase
end
end
endmodule

31
fw/rtl/memory/mem_bus.sv Normal file
View File

@ -0,0 +1,31 @@
interface mem_bus ();
logic request;
logic ack;
logic write;
logic [1:0] wmask;
logic [26:0] address;
logic [15:0] rdata;
logic [15:0] wdata;
modport controller (
output request,
input ack,
output write,
output wmask,
output address,
input rdata,
output wdata
);
modport memory (
input request,
output ack,
input write,
input wmask,
input address,
output rdata,
input wdata
);
endinterface

View File

@ -0,0 +1,231 @@
module memory_arbiter (
input clk,
input reset,
n64_scb.arbiter n64_scb,
mem_bus.memory n64_bus,
mem_bus.memory cfg_bus,
mem_bus.memory usb_dma_bus,
mem_bus.memory sd_dma_bus,
mem_bus.controller sdram_mem_bus,
mem_bus.controller flash_mem_bus,
mem_bus.controller bram_mem_bus
);
typedef enum bit [1:0] {
SOURCE_N64,
SOURCE_CFG,
SOURCE_USB_DMA,
SOURCE_SD_DMA
} e_source_request;
logic n64_sdram_request;
logic cfg_sdram_request;
logic usb_dma_sdram_request;
logic sd_dma_sdram_request;
logic n64_flash_request;
logic cfg_flash_request;
logic usb_dma_flash_request;
logic sd_dma_flash_request;
logic n64_bram_request;
logic cfg_bram_request;
logic usb_dma_bram_request;
logic sd_dma_bram_request;
assign n64_sdram_request = n64_bus.request && !n64_bus.address[26];
assign cfg_sdram_request = !n64_scb.pi_sdram_active && cfg_bus.request && !cfg_bus.address[26];
assign usb_dma_sdram_request = !n64_scb.pi_sdram_active && usb_dma_bus.request && !usb_dma_bus.address[26];
assign sd_dma_sdram_request = !n64_scb.pi_sdram_active && sd_dma_bus.request && !sd_dma_bus.address[26];
assign n64_flash_request = n64_bus.request && (n64_bus.address[26:24] == 3'b100);
assign cfg_flash_request = !n64_scb.pi_flash_active && cfg_bus.request && (cfg_bus.address[26:24] == 3'b100);
assign usb_dma_flash_request = !n64_scb.pi_flash_active && usb_dma_bus.request && (usb_dma_bus.address[26:24] == 3'b100);
assign sd_dma_flash_request = !n64_scb.pi_flash_active && sd_dma_bus.request && (sd_dma_bus.address[26:24] == 3'b100);
assign n64_bram_request = n64_bus.request && (n64_bus.address[26:24] >= 3'b101);
assign cfg_bram_request = cfg_bus.request && (cfg_bus.address[26:24] >= 3'b101);
assign usb_dma_bram_request = usb_dma_bus.request && (usb_dma_bus.address[26:24] >= 3'b101);
assign sd_dma_bram_request = sd_dma_bus.request && (sd_dma_bus.address[26:24] >= 3'b101);
e_source_request sdram_source_request;
always_ff @(posedge clk) begin
if (reset) begin
sdram_mem_bus.request <= 1'b0;
end else begin
if (!sdram_mem_bus.request) begin
sdram_mem_bus.request <= (
n64_sdram_request ||
cfg_sdram_request ||
usb_dma_sdram_request ||
sd_dma_sdram_request
);
if (n64_sdram_request) begin
sdram_mem_bus.write <= n64_bus.write;
sdram_mem_bus.wmask <= n64_bus.wmask;
sdram_mem_bus.address <= n64_bus.address;
sdram_mem_bus.wdata <= n64_bus.wdata;
sdram_source_request <= SOURCE_N64;
end else if (cfg_sdram_request) begin
sdram_mem_bus.write <= cfg_bus.write;
sdram_mem_bus.wmask <= cfg_bus.wmask;
sdram_mem_bus.address <= cfg_bus.address;
sdram_mem_bus.wdata <= cfg_bus.wdata;
sdram_source_request <= SOURCE_CFG;
end else if (usb_dma_sdram_request) begin
sdram_mem_bus.write <= usb_dma_bus.write;
sdram_mem_bus.wmask <= usb_dma_bus.wmask;
sdram_mem_bus.address <= usb_dma_bus.address;
sdram_mem_bus.wdata <= usb_dma_bus.wdata;
sdram_source_request <= SOURCE_USB_DMA;
end else if (sd_dma_sdram_request) begin
sdram_mem_bus.write <= sd_dma_bus.write;
sdram_mem_bus.wmask <= sd_dma_bus.wmask;
sdram_mem_bus.address <= sd_dma_bus.address;
sdram_mem_bus.wdata <= sd_dma_bus.wdata;
sdram_source_request <= SOURCE_SD_DMA;
end
end
if (sdram_mem_bus.ack) begin
sdram_mem_bus.request <= 1'b0;
end
end
end
e_source_request flash_source_request;
always_ff @(posedge clk) begin
if (reset) begin
flash_mem_bus.request <= 1'b0;
end else begin
if (!flash_mem_bus.request) begin
flash_mem_bus.request <= (
n64_flash_request ||
cfg_flash_request ||
usb_dma_flash_request ||
sd_dma_flash_request
);
if (n64_flash_request) begin
flash_mem_bus.write <= n64_bus.write;
flash_mem_bus.wmask <= n64_bus.wmask;
flash_mem_bus.address <= n64_bus.address;
flash_mem_bus.wdata <= n64_bus.wdata;
flash_source_request <= SOURCE_N64;
end else if (cfg_flash_request) begin
flash_mem_bus.write <= cfg_bus.write;
flash_mem_bus.wmask <= cfg_bus.wmask;
flash_mem_bus.address <= cfg_bus.address;
flash_mem_bus.wdata <= cfg_bus.wdata;
flash_source_request <= SOURCE_CFG;
end else if (usb_dma_flash_request) begin
flash_mem_bus.write <= usb_dma_bus.write;
flash_mem_bus.wmask <= usb_dma_bus.wmask;
flash_mem_bus.address <= usb_dma_bus.address;
flash_mem_bus.wdata <= usb_dma_bus.wdata;
flash_source_request <= SOURCE_USB_DMA;
end else if (sd_dma_flash_request) begin
flash_mem_bus.write <= sd_dma_bus.write;
flash_mem_bus.wmask <= sd_dma_bus.wmask;
flash_mem_bus.address <= sd_dma_bus.address;
flash_mem_bus.wdata <= sd_dma_bus.wdata;
flash_source_request <= SOURCE_SD_DMA;
end
end
if (flash_mem_bus.ack) begin
flash_mem_bus.request <= 1'b0;
end
end
end
e_source_request bram_source_request;
always_ff @(posedge clk) begin
if (reset) begin
bram_mem_bus.request <= 1'b0;
end else begin
if (!bram_mem_bus.request) begin
bram_mem_bus.request <= (
n64_bram_request ||
cfg_bram_request ||
usb_dma_bram_request ||
sd_dma_bram_request
);
if (n64_bram_request) begin
bram_mem_bus.write <= n64_bus.write;
bram_mem_bus.wmask <= n64_bus.wmask;
bram_mem_bus.address <= n64_bus.address;
bram_mem_bus.wdata <= n64_bus.wdata;
bram_source_request <= SOURCE_N64;
end else if (cfg_bram_request) begin
bram_mem_bus.write <= cfg_bus.write;
bram_mem_bus.wmask <= cfg_bus.wmask;
bram_mem_bus.address <= cfg_bus.address;
bram_mem_bus.wdata <= cfg_bus.wdata;
bram_source_request <= SOURCE_CFG;
end else if (usb_dma_bram_request) begin
bram_mem_bus.write <= usb_dma_bus.write;
bram_mem_bus.wmask <= usb_dma_bus.wmask;
bram_mem_bus.address <= usb_dma_bus.address;
bram_mem_bus.wdata <= usb_dma_bus.wdata;
bram_source_request <= SOURCE_USB_DMA;
end else if (sd_dma_bram_request) begin
bram_mem_bus.write <= sd_dma_bus.write;
bram_mem_bus.wmask <= sd_dma_bus.wmask;
bram_mem_bus.address <= sd_dma_bus.address;
bram_mem_bus.wdata <= sd_dma_bus.wdata;
bram_source_request <= SOURCE_SD_DMA;
end
end
if (bram_mem_bus.ack) begin
bram_mem_bus.request <= 1'b0;
end
end
end
always_comb begin
n64_bus.ack = (
((sdram_source_request == SOURCE_N64) && sdram_mem_bus.ack) ||
((flash_source_request == SOURCE_N64) && flash_mem_bus.ack) ||
((bram_source_request == SOURCE_N64) && bram_mem_bus.ack)
);
cfg_bus.ack = (
((sdram_source_request == SOURCE_CFG) && sdram_mem_bus.ack) ||
((flash_source_request == SOURCE_CFG) && flash_mem_bus.ack) ||
((bram_source_request == SOURCE_CFG) && bram_mem_bus.ack)
);
usb_dma_bus.ack = (
((sdram_source_request == SOURCE_USB_DMA) && sdram_mem_bus.ack) ||
((flash_source_request == SOURCE_USB_DMA) && flash_mem_bus.ack) ||
((bram_source_request == SOURCE_USB_DMA) && bram_mem_bus.ack)
);
sd_dma_bus.ack = (
((sdram_source_request == SOURCE_SD_DMA) && sdram_mem_bus.ack) ||
((flash_source_request == SOURCE_SD_DMA) && flash_mem_bus.ack) ||
((bram_source_request == SOURCE_SD_DMA) && bram_mem_bus.ack)
);
n64_bus.rdata = n64_bram_request ? bram_mem_bus.rdata :
n64_flash_request ? flash_mem_bus.rdata :
sdram_mem_bus.rdata;
cfg_bus.rdata = cfg_bram_request ? bram_mem_bus.rdata :
cfg_flash_request ? flash_mem_bus.rdata :
sdram_mem_bus.rdata;
usb_dma_bus.rdata = usb_dma_bram_request ? bram_mem_bus.rdata :
usb_dma_flash_request ? flash_mem_bus.rdata :
sdram_mem_bus.rdata;
sd_dma_bus.rdata = sd_dma_bram_request ? bram_mem_bus.rdata :
sd_dma_flash_request ? flash_mem_bus.rdata :
sdram_mem_bus.rdata;
end
endmodule

View File

@ -0,0 +1,164 @@
module memory_bram (
input clk,
n64_scb.bram n64_scb,
mem_bus.memory mem_bus
);
// Request logic
logic [1:0] last_request;
logic write;
always_ff @(posedge clk) begin
last_request <= {last_request[0], mem_bus.request};
end
always_ff @(posedge clk) begin
mem_bus.ack <= mem_bus.request && last_request[0] && !last_request[1];
end
always_comb begin
write = mem_bus.request && !last_request[0] && mem_bus.write;
end
// Address decoding
logic buffer_selected;
logic eeprom_selected;
logic dd_selected;
logic flashram_selected;
always_comb begin
buffer_selected = 1'b0;
eeprom_selected = 1'b0;
dd_selected = 1'b0;
flashram_selected = 1'b0;
if (mem_bus.address[25:24] == 2'b01 && mem_bus.address[23:14] == 10'd0) begin
buffer_selected = mem_bus.address[13] == 1'b0;
eeprom_selected = mem_bus.address[13:11] == 3'b100;
dd_selected = mem_bus.address[13:8] == 6'b101000;
flashram_selected = mem_bus.address[13:7] == 7'b1010010;
end
end
// Buffer memory
logic [15:0] buffer_bram [0:4095];
logic [15:0] buffer_bram_rdata;
always_ff @(posedge clk) begin
if (write && buffer_selected) begin
if (mem_bus.wmask[1]) buffer_bram[mem_bus.address[12:1]][15:8] <= mem_bus.wdata[15:8];
if (mem_bus.wmask[0]) buffer_bram[mem_bus.address[12:1]][7:0] <= mem_bus.wdata[7:0];
end
end
always_ff @(posedge clk) begin
buffer_bram_rdata <= buffer_bram[mem_bus.address[12:1]];
end
// EEPROM memory
logic [7:0] eeprom_bram_high [0:1023];
logic [7:0] eeprom_bram_low [0:1023];
logic [7:0] eeprom_bram_high_rdata;
logic [7:0] eeprom_bram_low_rdata;
logic [7:0] eeprom_bram_high_n64_rdata;
logic [7:0] eeprom_bram_low_n64_rdata;
logic [15:0] eeprom_bram_rdata;
always_ff @(posedge clk) begin
if (write && mem_bus.wmask[1] && eeprom_selected) begin
eeprom_bram_high[mem_bus.address[10:1]] <= mem_bus.wdata[15:8];
end
if (n64_scb.eeprom_write && !n64_scb.eeprom_address[0]) begin
eeprom_bram_high[n64_scb.eeprom_address[10:1]] <= n64_scb.eeprom_wdata;
end
end
always_ff @(posedge clk) begin
if (write && mem_bus.wmask[0] && eeprom_selected) begin
eeprom_bram_low[mem_bus.address[10:1]] <= mem_bus.wdata[7:0];
end
if (n64_scb.eeprom_write && n64_scb.eeprom_address[0]) begin
eeprom_bram_low[n64_scb.eeprom_address[10:1]] <= n64_scb.eeprom_wdata;
end
end
always_ff @(posedge clk) begin
eeprom_bram_high_rdata <= eeprom_bram_high[mem_bus.address[10:1]];
end
always_ff @(posedge clk) begin
eeprom_bram_low_rdata <= eeprom_bram_low[mem_bus.address[10:1]];
end
always_ff @(posedge clk) begin
eeprom_bram_high_n64_rdata <= eeprom_bram_high[n64_scb.eeprom_address[10:1]];
end
always_ff @(posedge clk) begin
eeprom_bram_low_n64_rdata <= eeprom_bram_low[n64_scb.eeprom_address[10:1]];
end
always_comb begin
eeprom_bram_rdata = {eeprom_bram_high_rdata, eeprom_bram_low_rdata};
n64_scb.eeprom_rdata = n64_scb.eeprom_address[0] ? eeprom_bram_low_n64_rdata : eeprom_bram_high_n64_rdata;
end
// DD memory
logic [15:0] dd_bram [0:127];
logic [15:0] dd_bram_rdata;
always_ff @(posedge clk) begin
if (write && dd_selected) begin
dd_bram[mem_bus.address[7:1]] <= mem_bus.wdata;
end
if (n64_scb.dd_write) begin
dd_bram[n64_scb.dd_address] <= n64_scb.dd_wdata;
end
end
always_ff @(posedge clk) begin
dd_bram_rdata <= dd_bram[mem_bus.address[7:1]];
end
always_ff @(posedge clk) begin
n64_scb.dd_rdata <= dd_bram[n64_scb.dd_address];
end
// FlashRAM memory
logic [15:0] flashram_bram [0:63];
logic [15:0] flashram_bram_rdata;
always_ff @(posedge clk) begin
if (n64_scb.flashram_write) begin
flashram_bram[n64_scb.flashram_address] <= n64_scb.flashram_wdata;
end
end
always_ff @(posedge clk) begin
flashram_bram_rdata <= flashram_bram[mem_bus.address[6:1]];
end
// Output data mux
always_ff @(posedge clk) begin
mem_bus.rdata <= 16'd0;
if (buffer_selected) mem_bus.rdata <= buffer_bram_rdata;
if (eeprom_selected) mem_bus.rdata <= eeprom_bram_rdata;
if (dd_selected) mem_bus.rdata <= dd_bram_rdata;
if (flashram_selected) mem_bus.rdata <= flashram_bram_rdata;
end
endmodule

243
fw/rtl/memory/memory_dma.sv Normal file
View File

@ -0,0 +1,243 @@
interface dma_scb ();
logic start;
logic stop;
logic busy;
logic direction;
logic [26:0] starting_address;
logic [26:0] transfer_length;
modport controller (
output start,
output stop,
input busy,
output direction,
output starting_address,
output transfer_length
);
modport dma (
input start,
input stop,
output busy,
input direction,
input starting_address,
input transfer_length
);
endinterface
module memory_dma (
input clk,
input reset,
dma_scb.dma dma_scb,
fifo_bus.controller fifo_bus,
mem_bus.controller mem_bus
);
// DMA start/stop control
logic dma_start;
logic dma_stop;
always_comb begin
dma_start = dma_scb.start && !dma_scb.stop && !dma_scb.busy;
dma_stop = dma_scb.stop;
end
// Remaining counter and FIFO enable
logic [26:0] remaining;
logic trx_enabled;
always_comb begin
trx_enabled = remaining > 27'd0;
end
// RX FIFO controller
logic rx_rdata_pop;
logic rx_rdata_shift;
logic rx_rdata_valid;
logic [15:0] rx_buffer;
logic rx_buffer_valid;
logic [1:0] rx_buffer_counter;
logic [1:0] rx_buffer_valid_counter;
always_comb begin
rx_buffer_valid = rx_buffer_valid_counter == 2'd2;
end
always_ff @(posedge clk) begin
rx_rdata_pop <= (
!rx_rdata_pop &&
!fifo_bus.rx_read &&
trx_enabled &&
rx_buffer_counter < 2'd2 &&
!fifo_bus.rx_empty &&
mem_bus.write
);
rx_rdata_shift <= 1'b0;
fifo_bus.rx_read <= rx_rdata_pop;
rx_rdata_valid <= fifo_bus.rx_read;
if (dma_start) begin
if (dma_scb.starting_address[0]) begin
mem_bus.wmask <= 2'b01;
rx_buffer_counter <= 2'd1;
rx_buffer_valid_counter <= 2'd1;
end else begin
mem_bus.wmask <= 2'b11;
rx_buffer_counter <= 2'd0;
rx_buffer_valid_counter <= 2'd0;
end
end
if (rx_rdata_pop) begin
rx_buffer_counter <= rx_buffer_counter + 1'd1;
end
if (rx_rdata_shift || rx_rdata_valid) begin
rx_buffer <= {rx_buffer[7:0], fifo_bus.rx_rdata};
rx_buffer_valid_counter <= rx_buffer_valid_counter + 1'd1;
if (remaining == 27'd0 && rx_buffer_counter == 2'd1) begin
mem_bus.wmask <= 2'b10;
rx_rdata_shift <= 1'b1;
rx_buffer_counter <= rx_buffer_counter + 1'd1;
end
end
if (rx_buffer_valid && !mem_bus.request) begin
rx_buffer_counter <= 2'd0;
rx_buffer_valid_counter <= 2'd0;
end
end
// TX FIFO controller
logic tx_wdata_push;
logic tx_wdata_first_push;
logic [7:0] tx_buffer;
logic tx_buffer_counter;
logic tx_buffer_ready;
logic tx_buffer_valid;
always_comb begin
fifo_bus.tx_write = tx_wdata_push;
end
always_ff @(posedge clk) begin
tx_wdata_push <= (
!tx_wdata_push &&
trx_enabled &&
tx_buffer_valid &&
!fifo_bus.tx_full &&
!mem_bus.write
);
if (reset || dma_stop) begin
tx_buffer_ready <= 1'b0;
tx_buffer_valid <= 1'b0;
end
if (dma_start) begin
tx_wdata_first_push <= 1'b1;
tx_buffer_ready <= 1'b1;
tx_buffer_valid <= 1'b0;
end
if (tx_buffer_ready && mem_bus.request) begin
tx_buffer_ready <= 1'b0;
end
if (mem_bus.ack) begin
tx_wdata_first_push <= 1'b0;
tx_buffer_counter <= 1'd1;
tx_buffer_valid <= 1'b1;
{fifo_bus.tx_wdata, tx_buffer} <= mem_bus.rdata;
if (tx_wdata_first_push && dma_scb.starting_address[0]) begin
fifo_bus.tx_wdata <= mem_bus.rdata[7:0];
tx_buffer_counter <= 1'd0;
end
end
if (tx_wdata_push) begin
tx_buffer_counter <= tx_buffer_counter - 1'd1;
fifo_bus.tx_wdata <= tx_buffer;
if (tx_buffer_counter == 1'd0) begin
tx_buffer_ready <= 1'b1;
tx_buffer_valid <= 1'b0;
end
end
end
// Remaining counter controller
always_ff @(posedge clk) begin
if (reset || dma_stop) begin
remaining <= 27'd0;
end else begin
if (dma_start) begin
remaining <= dma_scb.transfer_length;
end
if ((mem_bus.write && rx_rdata_pop) || (!mem_bus.write && tx_wdata_push)) begin
remaining <= remaining - 1'd1;
end
end
end
// Mem bus controller
always_ff @(posedge clk) begin
dma_scb.busy <= mem_bus.request || trx_enabled;
end
always_ff @(posedge clk) begin
if (reset) begin
mem_bus.request <= 1'b0;
end else begin
if (!mem_bus.request) begin
if (mem_bus.write) begin
if (rx_buffer_valid) begin
mem_bus.request <= 1'b1;
mem_bus.wdata <= rx_buffer;
end
end else begin
if (tx_buffer_ready) begin
mem_bus.request <= 1'b1;
end
end
end
end
if (mem_bus.ack) begin
mem_bus.request <= 1'b0;
end
end
always_ff @(posedge clk) begin
if (dma_start) begin
mem_bus.write <= dma_scb.direction;
end
end
always_ff @(posedge clk) begin
if (dma_start) begin
mem_bus.address <= {dma_scb.starting_address[26:1], 1'b0};
end
if (mem_bus.ack) begin
mem_bus.address <= mem_bus.address + 2'd2;
end
end
endmodule

View File

@ -0,0 +1,492 @@
interface flash_scb ();
logic erase_pending;
logic erase_done;
logic [7:0] erase_block;
modport controller (
output erase_pending,
input erase_done,
output erase_block
);
modport flash (
input erase_pending,
output erase_done,
input erase_block
);
endinterface
module flash_qspi (
input clk,
input reset,
input start,
input finish,
output logic busy,
output logic valid,
input output_enable,
input quad_enable,
output logic [7:0] rdata,
input [7:0] wdata,
output logic flash_clk,
output logic flash_cs,
inout [3:0] flash_dq
);
logic flash_dq_oe_s;
logic flash_dq_oe_q;
logic [3:0] flash_dq_out;
assign flash_dq[0] = flash_dq_oe_s ? flash_dq_out[0] : 1'bZ;
assign flash_dq[3:1] = flash_dq_oe_q ? flash_dq_out[3:1] : 3'bZZZ;
logic ff_clk;
logic ff_cs;
logic ff_dq_oe_s;
logic ff_dq_oe_q;
logic [3:0] ff_dq_out;
logic [3:0] ff_dq_in;
always_ff @(posedge clk) begin
flash_clk <= ff_clk;
flash_cs <= ff_cs;
flash_dq_oe_s <= ff_dq_oe_s;
flash_dq_oe_q <= ff_dq_oe_q;
flash_dq_out <= ff_dq_out;
ff_dq_in <= flash_dq;
end
logic running;
logic exit;
logic valid_enable;
logic quad_mode;
logic [2:0] counter;
logic [7:0] output_shift;
logic [2:0] sample_s;
logic [2:0] sample_q;
logic [2:0] valid_ff;
assign ff_dq_out = quad_mode ? output_shift[7:4] : {3'bXXX, output_shift[7]};
always_ff @(posedge clk) begin
sample_s <= {sample_s[1:0], 1'b0};
sample_q <= {sample_q[1:0], 1'b0};
valid_ff <= {valid_ff[1:0], 1'b0};
if (reset) begin
ff_clk <= 1'b0;
ff_cs <= 1'b1;
ff_dq_oe_s <= 1'b0;
ff_dq_oe_q <= 1'b0;
busy <= 1'b0;
running <= 1'b0;
end else begin
if (running) begin
ff_clk <= ~ff_clk;
if (!ff_clk) begin
if (counter == 3'd0) begin
busy <= 1'b0;
valid_ff[0] <= valid_enable;
end
if (!quad_mode) begin
sample_s[0] <= 1'b1;
end else begin
sample_q[0] <= 1'b1;
end
end else begin
counter <= counter - 1'd1;
if (counter == 3'd0) begin
running <= 1'b0;
end
if (!quad_mode) begin
output_shift <= {output_shift[6:0], 1'bX};
end else begin
output_shift <= {output_shift[3:0], 4'bXXXX};
end
end
end
if (exit) begin
ff_cs <= 1'b1;
counter <= counter - 1'd1;
if (counter == 3'd0) begin
busy <= 1'b0;
exit <= 1'b0;
end
end
if (!busy) begin
if (start) begin
ff_clk <= 1'b0;
ff_cs <= 1'b0;
ff_dq_oe_s <= !quad_enable || (quad_enable && output_enable);
ff_dq_oe_q <= quad_enable && output_enable;
busy <= 1'b1;
running <= 1'b1;
valid_enable <= !output_enable;
quad_mode <= quad_enable;
counter <= quad_enable ? 3'd1 : 3'd7;
output_shift <= wdata;
end else if (finish) begin
busy <= 1'b1;
exit <= 1'b1;
counter <= wdata[2:0];
end
end
end
end
always_ff @(posedge clk) begin
valid <= 1'b0;
if (sample_s[2]) begin
rdata <= {rdata[6:0], ff_dq_in[1]};
end
if (sample_q[2]) begin
rdata <= {rdata[3:0], ff_dq_in};
end
if (valid_ff[2]) begin
valid <= 1'b1;
end
end
endmodule
module memory_flash (
input clk,
input reset,
flash_scb.flash flash_scb,
mem_bus.memory mem_bus,
output flash_clk,
output flash_cs,
inout [3:0] flash_dq
);
logic start;
logic finish;
logic busy;
logic valid;
logic output_enable;
logic quad_enable;
logic [7:0] rdata;
logic [7:0] wdata;
flash_qspi flash_qspi_inst (
.clk(clk),
.reset(reset),
.start(start),
.finish(finish),
.busy(busy),
.valid(valid),
.output_enable(output_enable),
.quad_enable(quad_enable),
.rdata(rdata),
.wdata(wdata),
.flash_clk(flash_clk),
.flash_cs(flash_cs),
.flash_dq(flash_dq)
);
typedef enum bit [7:0] {
FLASH_CMD_PAGE_PROGRAM = 8'h02,
FLASH_CMD_READ_STATUS_1 = 8'h05,
FLASH_CMD_WRITE_ENABLE = 8'h06,
FLASH_CMD_BLOCK_ERASE_64KB = 8'hD8,
FLASH_CMD_FAST_READ_QUAD_IO = 8'hEB
} e_flash_cmd;
typedef enum {
FLASH_STATUS_1_BUSY = 0
} e_flash_status_1;
typedef enum bit [3:0] {
STATE_IDLE,
STATE_WRITE_ENABLE,
STATE_ERASE,
STATE_PROGRAM_START,
STATE_PROGRAM,
STATE_PROGRAM_END,
STATE_WAIT,
STATE_READ_START,
STATE_READ,
STATE_READ_END
} e_state;
e_state state;
logic [2:0] counter;
logic valid_counter;
logic [23:0] current_address;
always_ff @(posedge clk) begin
start <= 1'b0;
finish <= 1'b0;
flash_scb.erase_done <= 1'b0;
mem_bus.ack <= 1'b0;
if (reset) begin
state <= STATE_IDLE;
end else begin
if (!busy && (start || finish)) begin
counter <= counter + 1'd1;
end
case (state)
STATE_IDLE: begin
output_enable <= 1'b1;
quad_enable <= 1'b0;
counter <= 3'd0;
if (flash_scb.erase_pending) begin
state <= STATE_WRITE_ENABLE;
end else if (mem_bus.request) begin
current_address <= {mem_bus.address[23:1], 1'b0};
if (mem_bus.write) begin
state <= STATE_WRITE_ENABLE;
end else begin
state <= STATE_READ_START;
end
end
end
STATE_WRITE_ENABLE: begin
case (counter)
3'd0: begin
start <= 1'b1;
wdata <= FLASH_CMD_WRITE_ENABLE;
end
3'd1: begin
finish <= 1'b1;
wdata <= 8'd4;
if (!busy) begin
counter <= 3'd0;
if (flash_scb.erase_pending) begin
state <= STATE_ERASE;
end else begin
state <= STATE_PROGRAM_START;
end
end
end
endcase
end
STATE_ERASE: begin
case (counter)
3'd0: begin
start <= 1'b1;
wdata <= FLASH_CMD_BLOCK_ERASE_64KB;
end
3'd1: begin
start <= 1'b1;
wdata <= flash_scb.erase_block;
end
3'd2: begin
start <= 1'b1;
wdata <= 8'd0;
end
3'd3: begin
start <= 1'b1;
wdata <= 8'd0;
end
3'd4: begin
finish <= 1'b1;
wdata <= 8'd4;
if (!busy) begin
flash_scb.erase_done <= 1'b1;
counter <= 3'd0;
state <= STATE_WAIT;
end
end
endcase
end
STATE_PROGRAM_START: begin
case (counter)
3'd0: begin
start <= 1'b1;
wdata <= FLASH_CMD_PAGE_PROGRAM;
end
3'd1: begin
start <= 1'b1;
wdata <= mem_bus.address[23:16];
end
3'd2: begin
start <= 1'b1;
wdata <= mem_bus.address[15:8];
end
3'd3: begin
start <= 1'b1;
wdata <= mem_bus.address[7:0];
if (!busy) begin
counter <= 3'd0;
state <= STATE_PROGRAM;
end
end
endcase
end
STATE_PROGRAM: begin
case (counter)
3'd0: begin
start <= 1'b1;
wdata <= mem_bus.wdata[15:8];
end
3'd1: begin
start <= 1'b1;
wdata <= mem_bus.wdata[7:0];
if (!busy) begin
mem_bus.ack <= 1'b1;
current_address <= current_address + 2'd2;
end
end
3'd2: begin
if (current_address[7:0] == 8'h00) begin
state <= STATE_PROGRAM_END;
end else if (flash_scb.erase_pending) begin
state <= STATE_PROGRAM_END;
end else if (mem_bus.request && !mem_bus.ack) begin
if (!mem_bus.write || (mem_bus.address[23:0] != current_address)) begin
state <= STATE_PROGRAM_END;
end else begin
counter <= 3'd0;
end
end
end
endcase
end
STATE_PROGRAM_END: begin
finish <= 1'b1;
wdata <= 8'd4;
if (!busy) begin
counter <= 3'd0;
state <= STATE_WAIT;
end
end
STATE_WAIT: begin
case (counter)
3'd0: begin
start <= 1'b1;
output_enable <= 1'b1;
wdata <= FLASH_CMD_READ_STATUS_1;
end
3'd1: begin
start <= 1'b1;
output_enable <= 1'b0;
end
3'd2: begin
finish <= 1'b1;
wdata <= 8'd0;
end
3'd3: begin
counter <= counter;
end
endcase
if (valid) begin
if (rdata[FLASH_STATUS_1_BUSY]) begin
counter <= 3'd0;
end else begin
state <= STATE_IDLE;
end
end
end
STATE_READ_START: begin
case (counter)
3'd0: begin
start <= 1'b1;
wdata <= FLASH_CMD_FAST_READ_QUAD_IO;
end
3'd1: begin
start <= 1'b1;
quad_enable <= 1'b1;
wdata <= mem_bus.address[23:16];
end
3'd2: begin
start <= 1'b1;
wdata <= mem_bus.address[15:8];
end
3'd3: begin
start <= 1'b1;
wdata <= mem_bus.address[7:0];
end
3'd4: begin
start <= 1'b1;
wdata <= 8'hFF;
end
3'd5: begin
start <= 1'b1;
end
3'd6: begin
start <= 1'b1;
if (!busy) begin
counter <= 3'd0;
valid_counter <= 1'b0;
state <= STATE_READ;
end
end
endcase
end
STATE_READ: begin
case (counter)
3'd0: begin
start <= 1'b1;
output_enable <= 1'b0;
end
3'd1: begin
start <= 1'b1;
end
3'd2: begin end
3'd3: begin
if (flash_scb.erase_pending) begin
state <= STATE_READ_END;
end else if (mem_bus.request && !mem_bus.ack) begin
if (mem_bus.write || (mem_bus.address[23:0] != current_address)) begin
state <= STATE_READ_END;
end else begin
start <= 1'b1;
counter <= 3'd0;
end
end
end
endcase
if (valid) begin
valid_counter <= ~valid_counter;
if (valid_counter) begin
mem_bus.ack <= 1'b1;
counter <= counter + 1'd1;
current_address <= current_address + 2'd2;
end
end
end
STATE_READ_END: begin
finish <= 1'b1;
wdata <= 8'd0;
if (!busy) begin
state <= STATE_IDLE;
end
end
default: begin
state <= STATE_IDLE;
end
endcase
end
end
always_ff @(posedge clk) begin
if (valid) begin
mem_bus.rdata <= {mem_bus.rdata[7:0], rdata};
end
end
endmodule

View File

@ -1,48 +1,41 @@
module memory_sdram (
if_system sys,
input clk,
input reset,
input request,
output ack,
input write,
input [25:0] address,
output [15:0] rdata,
input [15:0] wdata,
mem_bus.memory mem_bus,
output sdram_cs,
output sdram_ras,
output sdram_cas,
output sdram_we,
output [1:0] sdram_ba,
output [12:0] sdram_a,
output logic sdram_cs,
output logic sdram_ras,
output logic sdram_cas,
output logic sdram_we,
output logic [1:0] sdram_ba,
output logic [12:0] sdram_a,
output logic [1:0] sdram_dqm,
inout [15:0] sdram_dq
);
parameter [2:0] CAS_LATENCY = 3'd2;
localparam [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_INIT = 100_000.0;
localparam real T_RC = 60.0;
localparam real T_RP = 15.0;
localparam real T_RCD = 15.0;
localparam real T_MRD = 14.0;
localparam real T_REF = 7_800.0;
localparam real T_CLK = (1.0 / sc64::CLOCK_FREQUENCY) * 1_000_000_000.0;
localparam real T_CLK = (1.0 / 100_000_000) * 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;
localparam INIT_PRECHARGE = 4'd0;
localparam INIT_REFRESH_1 = C_RP;
localparam INIT_REFRESH_2 = C_RP + C_RC;
localparam INIT_MODE_REG = C_RP + (2 * C_RC);
localparam INIT_DONE = C_RP + (2 * C_RC) + C_MRD;
typedef enum bit [3:0] {
CMD_DESL = 4'b1111,
@ -63,37 +56,51 @@ module memory_sdram (
logic [14:0] current_active_bank_row;
logic request_in_current_active_bank_row;
always_ff @(posedge sys.clk) begin
always_ff @(posedge clk) begin
{sdram_cs, sdram_ras, sdram_cas, sdram_we} <= 4'(sdram_next_cmd);
{sdram_ba, sdram_a} <= 15'd0;
sdram_dqm <= 2'b00;
sdram_dq_input <= sdram_dq;
sdram_dq_output <= wdata;
sdram_dq_output <= mem_bus.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;
{sdram_ba, sdram_a} <= {mem_bus.address[25:24], 3'b000, mem_bus.address[10:1]};
sdram_dqm <= (sdram_next_cmd == CMD_WRITE) ? (~mem_bus.wmask) : 2'b00;
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];
{sdram_ba, sdram_a} <= mem_bus.address[25:11];
sdram_dqm <= 2'b00;
current_active_bank_row <= mem_bus.address[25:11];
end
CMD_PRE: begin
{sdram_ba, sdram_a} <= {2'b00, 2'b00, 1'b1, 10'd0};
sdram_dqm <= 2'b00;
end
CMD_MRS: begin
{sdram_ba, sdram_a} <= {2'b00, 1'b0, 1'b0, 2'b00, CAS_LATENCY, 1'b0, 3'b000};
sdram_dqm <= 2'b00;
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
assign sdram_dq = sdram_dq_output_enable ? sdram_dq_output : 16'hZZZZ;
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;
mem_bus.rdata = sdram_dq_input;
request_in_current_active_bank_row = mem_bus.address[25:11] == current_active_bank_row;
end
typedef enum bit [2:0] {
S_POWERUP,
S_INIT,
S_IDLE,
S_ACTIVATING,
@ -106,44 +113,54 @@ module memory_sdram (
e_state state;
e_state next_state;
always_ff @(posedge sys.clk) begin
if (sys.reset) begin
state <= S_INIT;
always_ff @(posedge clk) begin
if (reset) begin
state <= S_POWERUP;
end else begin
state <= next_state;
end
end
logic [13:0] wait_counter;
logic [13:0] powerup_coutner;
logic powerup_done;
logic [4: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;
always_ff @(posedge clk) begin
if (reset) begin
powerup_coutner <= 14'd0;
powerup_done <= 1'b0;
end else if (powerup_coutner < C_INIT) begin
powerup_coutner <= powerup_coutner + 1'd1;
end else begin
powerup_done <= 1'b1;
end
if (reset || state != next_state) begin
wait_counter <= 5'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
pending_refresh <= 1'b0;
end else if (refresh_counter < C_REF) begin
refresh_counter <= refresh_counter + 1'd1;
end else begin
pending_refresh <= 1'b1;
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;
always_ff @(posedge clk) begin
mem_bus.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;
mem_bus.ack <= 1'b1;
end
end
@ -152,10 +169,14 @@ module memory_sdram (
next_state = state;
case (state)
S_INIT: begin
if (wait_counter < INIT_PRECHARGE) begin
sdram_next_cmd = CMD_DESL;
S_POWERUP: begin
sdram_next_cmd = CMD_DESL;
if (powerup_done) begin
next_state = S_INIT;
end
end
S_INIT: begin
if (wait_counter == INIT_PRECHARGE) begin
sdram_next_cmd = CMD_PRE;
end
@ -174,7 +195,7 @@ module memory_sdram (
if (pending_refresh) begin
next_state = S_REFRESH;
sdram_next_cmd = CMD_REF;
end else if (request) begin
end else if (mem_bus.request) begin
next_state = S_ACTIVATING;
sdram_next_cmd = CMD_ACT;
end
@ -190,10 +211,10 @@ module memory_sdram (
if (pending_refresh) begin
next_state = S_PRECHARGE;
sdram_next_cmd = CMD_PRE;
end else if (request) begin
end else if (mem_bus.request) begin
if (request_in_current_active_bank_row) begin
next_state = S_BUSY;
sdram_next_cmd = write ? CMD_WRITE : CMD_READ;
sdram_next_cmd = mem_bus.write ? CMD_WRITE : CMD_READ;
end else begin
next_state = S_PRECHARGE;
sdram_next_cmd = CMD_PRE;
@ -202,7 +223,7 @@ module memory_sdram (
end
S_BUSY: begin
if (ack) begin
if (mem_bus.ack) begin
next_state = S_ACTIVE;
end
end

View File

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

View File

@ -1,67 +0,0 @@
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 [31:0] real_address;
logic read_op;
logic write_op;
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,
output real_address,
output read_op,
output write_op
);
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]),
input .real_address(real_address),
input .read_op(read_op),
input .write_op(write_op)
);
end
endgenerate
endinterface

View File

@ -1,83 +1,137 @@
module n64_cfg (
if_system sys,
if_n64_bus bus,
if_config.n64 cfg
input clk,
input reset,
n64_reg_bus.cfg reg_bus,
n64_scb.cfg n64_scb,
output logic irq
);
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;
REG_STATUS,
REG_COMMAND,
REG_DATA_0_H,
REG_DATA_0_L,
REG_DATA_1_H,
REG_DATA_1_L,
REG_VERSION_H,
REG_VERSION_L,
REG_KEY_H,
REG_KEY_L
} e_reg;
typedef enum bit [0:0] {
S_IDLE,
S_WAIT
} e_state;
e_state state;
logic cfg_error;
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,
1'b0,
cfg.cmd_error,
12'd0
reg_bus.rdata = 16'd0;
if (reg_bus.address[16] && (reg_bus.address[15:5] == 11'd0)) begin
case (reg_bus.address[4:1])
REG_STATUS: reg_bus.rdata = {
n64_scb.cfg_pending,
cfg_error,
irq,
13'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];
REG_COMMAND: reg_bus.rdata = {8'd0, n64_scb.cfg_cmd};
REG_DATA_0_H: reg_bus.rdata = n64_scb.cfg_wdata[0][31:16];
REG_DATA_0_L: reg_bus.rdata = n64_scb.cfg_wdata[0][15:0];
REG_DATA_1_H: reg_bus.rdata = n64_scb.cfg_wdata[1][31:16];
REG_DATA_1_L: reg_bus.rdata = n64_scb.cfg_wdata[1][15:0];
REG_VERSION_H: reg_bus.rdata = n64_scb.cfg_version[31:16];
REG_VERSION_L: reg_bus.rdata = n64_scb.cfg_version[15:0];
REG_KEY_H: reg_bus.rdata = 16'd0;
REG_KEY_L: reg_bus.rdata = 16'd0;
endcase
end
end
always_ff @(posedge sys.clk) begin
bus.ack <= 1'b0;
cfg.cmd_request <= 1'b0;
logic unlock_flag;
logic lock_sequence_counter;
if (cfg.data_write[0]) cfg.data[0] <= cfg.wdata;
if (cfg.data_write[1]) cfg.data[1] <= cfg.wdata;
always_ff @(posedge clk) begin
if (n64_scb.cfg_done) begin
n64_scb.cfg_pending <= 1'b0;
cfg_error <= n64_scb.cfg_error;
end
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
if (n64_scb.cfg_irq) begin
irq <= 1'b1;
end
if (unlock_flag) begin
n64_scb.cfg_unlock <= 1'b1;
end
if (reset || n64_scb.n64_reset || n64_scb.n64_nmi) begin
n64_scb.cfg_unlock <= 1'b0;
n64_scb.cfg_pending <= 1'b0;
n64_scb.cfg_cmd <= 8'h00;
irq <= 1'b0;
cfg_error <= 1'b0;
lock_sequence_counter <= 1'd0;
end else if (n64_scb.cfg_unlock) begin
if (reg_bus.write && reg_bus.address[16] && (reg_bus.address[15:5] == 11'd0)) begin
case (reg_bus.address[4:1])
REG_COMMAND: begin
n64_scb.cfg_pending <= 1'b1;
n64_scb.cfg_cmd <= reg_bus.wdata[7:0];
cfg_error <= 1'b0;
end
REG_DATA_0_H: n64_scb.cfg_rdata[0][31:16] <= reg_bus.wdata;
REG_DATA_0_L: n64_scb.cfg_rdata[0][15:0] <= reg_bus.wdata;
REG_DATA_1_H: n64_scb.cfg_rdata[1][31:16] <= reg_bus.wdata;
REG_DATA_1_L: n64_scb.cfg_rdata[1][15:0] <= reg_bus.wdata;
REG_VERSION_H: irq <= 1'b0;
REG_KEY_H, REG_KEY_L: begin
lock_sequence_counter <= lock_sequence_counter + 1'd1;
if (reg_bus.wdata != 16'hFFFF) begin
lock_sequence_counter <= 1'd0;
end
if (lock_sequence_counter == 1'd1) begin
n64_scb.cfg_unlock <= (reg_bus.wdata != 16'hFFFF);
end
end
end
endcase
end
end
end
S_WAIT: begin
state <= S_IDLE;
end
endcase
const bit [15:0] UNLOCK_SEQUENCE [4] = {
16'h5F55,
16'h4E4C,
16'h4F43,
16'h4B5F
};
logic [1:0] unlock_sequence_counter;
always_ff @(posedge clk) begin
unlock_flag <= 1'b0;
if (reset || n64_scb.n64_reset || n64_scb.n64_nmi) begin
unlock_sequence_counter <= 2'd0;
end else if (!n64_scb.cfg_unlock) begin
if (reg_bus.write && reg_bus.address[16] && (reg_bus.address[15:5] == 11'd0)) begin
case (reg_bus.address[4:1])
REG_KEY_H, REG_KEY_L: begin
for (int index = 0; index < $size(UNLOCK_SEQUENCE); index++) begin
if (index == unlock_sequence_counter) begin
if (reg_bus.wdata == UNLOCK_SEQUENCE[index]) begin
unlock_sequence_counter <= unlock_sequence_counter + 1'd1;
if (index == ($size(UNLOCK_SEQUENCE) - 1'd1)) begin
unlock_flag <= 1'b1;
unlock_sequence_counter <= 2'd0;
end
end else begin
unlock_sequence_counter <= 2'd0;
end
end
end
end
endcase
end
end
end

View File

@ -1,21 +1,4 @@
interface if_dd (
output dd_interrupt
);
// Sector buffer regs
logic [6:0] n64_sector_address;
logic n64_sector_address_valid;
logic n64_sector_write;
logic [15:0] n64_sector_wdata;
logic [5:0] cpu_sector_address;
logic cpu_sector_address_valid;
logic cpu_sector_write;
logic [31:0] cpu_sector_wdata;
logic [31:0] sector_rdata;
interface dd_scb ();
// N64 controlled regs
@ -55,11 +38,38 @@ interface if_dd (
logic [12:0] head_track;
logic [15:0] drive_id;
modport controller (
input hard_reset,
input data,
input cmd,
input cmd_pending,
input bm_start_pending,
input bm_stop_pending,
input bm_transfer_mode,
input bm_transfer_blocks,
input bm_pending,
input bm_interrupt_ack,
input sector_num,
input sector_size,
input sector_size_full,
input sectors_in_block,
always_comb begin
dd_interrupt = cmd_interrupt || bm_interrupt;
end
output hard_reset_clear,
output cmd_data,
output cmd_ready,
output bm_start_clear,
output bm_stop_clear,
output bm_transfer_c2,
output bm_transfer_data,
output bm_micro_error,
output bm_ready,
output bm_clear,
output disk_inserted,
output disk_changed,
output index_lock,
output head_track,
output drive_id
);
modport dd (
output hard_reset,
@ -93,90 +103,36 @@ interface if_dd (
input disk_changed,
input index_lock,
input head_track,
input drive_id,
output .sector_address(n64_sector_address),
output .sector_address_valid(n64_sector_address_valid),
output .sector_write(n64_sector_write),
output .sector_wdata(n64_sector_wdata),
input sector_rdata
);
modport cpu (
input hard_reset,
input data,
input cmd,
input cmd_pending,
input bm_start_pending,
input bm_stop_pending,
input bm_transfer_mode,
input bm_transfer_blocks,
input bm_pending,
input bm_interrupt_ack,
input sector_num,
input sector_size,
input sector_size_full,
input sectors_in_block,
output hard_reset_clear,
output cmd_data,
output cmd_ready,
output bm_start_clear,
output bm_stop_clear,
output bm_transfer_c2,
output bm_transfer_data,
output bm_micro_error,
output bm_ready,
output bm_clear,
output disk_inserted,
output disk_changed,
output index_lock,
output head_track,
output drive_id,
output .sector_address(cpu_sector_address),
output .sector_address_valid(cpu_sector_address_valid),
output .sector_write(cpu_sector_write),
output .sector_wdata(cpu_sector_wdata),
input sector_rdata
);
modport sector_buffer (
input n64_sector_address,
input n64_sector_address_valid,
input n64_sector_write,
input n64_sector_wdata,
input cpu_sector_address,
input cpu_sector_address_valid,
input cpu_sector_write,
input cpu_sector_wdata,
output sector_rdata
input drive_id
);
endinterface
module n64_dd (
if_system.sys sys,
if_n64_bus bus,
if_dd.dd dd
input clk,
input reset,
n64_reg_bus.dd reg_bus,
n64_scb.dd n64_scb,
dd_scb.dd dd_scb,
output logic irq
);
const bit [31:0] M_BASE = 32'h0500_0000;
const bit [31:0] M_C2_BUFFER = M_BASE + 11'h000;
const bit [31:0] M_SECTOR_BUFFER = M_BASE + 11'h400;
const bit [10:0] MEM_C2_BUFFER = 11'h000;
const bit [10:0] MEM_SECTOR_BUFFER = 11'h400;
typedef enum bit [10:0] {
R_DATA = 11'h500,
R_CMD_SR = 11'h508,
R_TRK_CUR = 11'h50C,
R_BM_SCR = 11'h510,
R_RESET = 11'h520,
R_SEC_SIZ = 11'h528,
R_SEC_INFO = 11'h530,
R_ID = 11'h540
REG_DATA = 11'h500,
REG_CMD_SR = 11'h508,
REG_TRK_CUR = 11'h50C,
REG_BM_SCR = 11'h510,
REG_RESET = 11'h520,
REG_SEC_SIZ = 11'h528,
REG_SEC_INFO = 11'h530,
REG_ID = 11'h540
} e_reg_id;
typedef enum bit [3:0] {
@ -187,218 +143,144 @@ module n64_dd (
BM_CONTROL_MECHANIC_INTERRUPT_RESET = 4'd8
} e_bm_control_id;
typedef enum bit [0:0] {
S_IDLE,
S_WAIT
} e_state;
e_state state;
always_comb begin
dd.sector_address = bus.address[7:1];
dd.sector_address_valid = bus.request && bus.address[11:8] == M_SECTOR_BUFFER[11:8];
dd.sector_write = bus.write && dd.sector_address_valid;
dd.sector_wdata = bus.wdata;
end
always_comb begin
bus.rdata = 16'd0;
if (bus.ack) begin
if (bus.address[10:8] == M_SECTOR_BUFFER[10:8]) begin
if (bus.address[1]) begin
bus.rdata = dd.sector_rdata[15:0];
end else begin
bus.rdata = dd.sector_rdata[31:16];
end
end else begin
case (bus.address[10:0])
R_DATA: bus.rdata = dd.data;
R_CMD_SR: bus.rdata = {
1'b0,
dd.bm_transfer_data,
1'b0,
dd.bm_transfer_c2,
1'b0,
dd.bm_interrupt,
dd.cmd_interrupt,
dd.disk_inserted,
dd.cmd_pending,
dd.hard_reset,
1'b0,
1'b0,
1'b0,
1'b0,
1'b0,
dd.disk_changed
};
R_TRK_CUR: bus.rdata = {1'd0, {2{dd.index_lock}}, dd.head_track};
R_BM_SCR: bus.rdata = {6'd0, dd.bm_micro_error, 9'd0};
R_ID: bus.rdata = {dd.drive_id};
default: bus.rdata = 16'd0;
endcase
end
end
end
always_ff @(posedge sys.clk) begin
bus.ack <= 1'b0;
dd.bm_interrupt_ack <= 1'b0;
if (dd.hard_reset_clear) begin
dd.hard_reset <= 1'b0;
end
if (dd.cmd_ready) begin
dd.data <= dd.cmd_data;
dd.cmd_pending <= 1'b0;
dd.cmd_interrupt <= 1'b1;
end
if (dd.bm_start_clear) begin
dd.bm_start_pending <= 1'b0;
end
if (dd.bm_stop_clear) begin
dd.bm_stop_pending <= 1'b0;
end
if (dd.bm_clear) begin
dd.bm_pending <= 1'b0;
end
if (dd.bm_ready) begin
dd.bm_interrupt <= 1'b1;
end
if (bus.real_address == (M_C2_BUFFER + ({dd.sector_size[7:1], 1'b0} * 3'd4)) && bus.read_op) begin
dd.bm_pending <= 1'b1;
end
if (bus.real_address == (M_SECTOR_BUFFER + {dd.sector_size[7:1], 1'b0}) && (bus.read_op || bus.write_op)) begin
dd.bm_pending <= 1'b1;
end
if (bus.real_address == (M_BASE + R_CMD_SR) && bus.read_op) begin
dd.bm_interrupt <= 1'b0;
dd.bm_interrupt_ack <= 1'b1;
end
if (sys.reset || sys.n64_hard_reset) begin
dd.hard_reset <= 1'b1;
dd.cmd_pending <= 1'b0;
dd.cmd_interrupt <= 1'b0;
dd.bm_start_pending <= 1'b0;
dd.bm_stop_pending <= 1'b0;
dd.bm_pending <= 1'b0;
dd.bm_interrupt <= 1'b0;
state <= S_IDLE;
reg_bus.rdata = 16'd0;
if (reg_bus.address[10:8] == MEM_SECTOR_BUFFER[10:8]) begin
reg_bus.rdata = n64_scb.dd_rdata;
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[10:0])
R_DATA: begin
dd.data <= bus.wdata;
end
case (reg_bus.address[10:0])
REG_DATA: reg_bus.rdata = dd_scb.data;
REG_CMD_SR: reg_bus.rdata = {
1'b0,
dd_scb.bm_transfer_data,
1'b0,
dd_scb.bm_transfer_c2,
1'b0,
dd_scb.bm_interrupt,
dd_scb.cmd_interrupt,
dd_scb.disk_inserted,
dd_scb.cmd_pending,
dd_scb.hard_reset,
1'b0,
1'b0,
1'b0,
1'b0,
1'b0,
dd_scb.disk_changed
};
REG_TRK_CUR: reg_bus.rdata = {1'd0, {2{dd_scb.index_lock}}, dd_scb.head_track};
REG_BM_SCR: reg_bus.rdata = {6'd0, dd_scb.bm_micro_error, 9'd0};
REG_ID: reg_bus.rdata = dd_scb.drive_id;
endcase
end
end
R_CMD_SR: begin
dd.cmd <= bus.wdata[7:0];
dd.cmd_pending <= 1'b1;
end
always_ff @(posedge clk) begin
dd_scb.bm_interrupt_ack <= 1'b0;
R_BM_SCR: begin
dd.sector_num <= bus.wdata[7:0];
if (bus.wdata[BM_CONTROL_START_BUFFER_MANAGER]) begin
dd.bm_start_pending <= 1'b1;
dd.bm_stop_pending <= 1'b0;
dd.bm_transfer_mode <= bus.wdata[BM_CONTROL_BUFFER_MANAGER_MODE];
dd.bm_transfer_blocks <= bus.wdata[BM_CONTROL_BLOCK_TRANSFER];
end
if (bus.wdata[BM_CONTROL_BUFFER_MANAGER_RESET]) begin
dd.bm_start_pending <= 1'b0;
dd.bm_stop_pending <= 1'b1;
dd.bm_transfer_mode <= 1'b0;
dd.bm_transfer_blocks <= 1'b0;
dd.bm_pending <= 1'b0;
dd.bm_interrupt <= 1'b0;
end
if (bus.wdata[BM_CONTROL_MECHANIC_INTERRUPT_RESET]) begin
dd.cmd_interrupt <= 1'b0;
end
end
if (dd_scb.hard_reset_clear) begin
dd_scb.hard_reset <= 1'b0;
end
if (dd_scb.cmd_ready) begin
dd_scb.data <= dd_scb.cmd_data;
dd_scb.cmd_pending <= 1'b0;
dd_scb.cmd_interrupt <= 1'b1;
end
if (dd_scb.bm_start_clear) begin
dd_scb.bm_start_pending <= 1'b0;
end
if (dd_scb.bm_stop_clear) begin
dd_scb.bm_stop_pending <= 1'b0;
end
if (dd_scb.bm_clear) begin
dd_scb.bm_pending <= 1'b0;
end
if (dd_scb.bm_ready) begin
dd_scb.bm_interrupt <= 1'b1;
end
if (reg_bus.address[10:0] == (MEM_C2_BUFFER + ({dd_scb.sector_size[7:1], 1'b0} * 3'd4)) && reg_bus.read) begin
dd_scb.bm_pending <= 1'b1;
end
if (reg_bus.address[10:0] == (MEM_SECTOR_BUFFER + {dd_scb.sector_size[7:1], 1'b0}) && (reg_bus.read || reg_bus.write)) begin
dd_scb.bm_pending <= 1'b1;
end
if (reg_bus.address[10:0] == REG_CMD_SR && reg_bus.read) begin
dd_scb.bm_interrupt <= 1'b0;
dd_scb.bm_interrupt_ack <= 1'b1;
end
R_RESET: begin
if (bus.wdata == 16'hAAAA) begin
dd.hard_reset <= 1'b1;
dd.cmd_pending <= 1'b0;
dd.cmd_interrupt <= 1'b0;
dd.bm_start_pending <= 1'b0;
dd.bm_stop_pending <= 1'b0;
dd.bm_pending <= 1'b0;
dd.bm_interrupt <= 1'b0;
end
end
if (reset || n64_scb.n64_reset) begin
dd_scb.hard_reset <= 1'b1;
dd_scb.cmd_pending <= 1'b0;
dd_scb.cmd_interrupt <= 1'b0;
dd_scb.bm_start_pending <= 1'b0;
dd_scb.bm_stop_pending <= 1'b0;
dd_scb.bm_pending <= 1'b0;
dd_scb.bm_interrupt <= 1'b0;
end else if (reg_bus.write) begin
case (reg_bus.address[10:0])
REG_DATA: begin
dd_scb.data <= reg_bus.wdata;
end
R_SEC_SIZ: begin
dd.sector_size <= bus.wdata[7:0];
end
REG_CMD_SR: begin
dd_scb.cmd <= reg_bus.wdata[7:0];
dd_scb.cmd_pending <= 1'b1;
end
R_SEC_INFO: begin
dd.sectors_in_block <= bus.wdata[15:8];
dd.sector_size_full <= bus.wdata[7:0];
end
endcase
end
REG_BM_SCR: begin
dd_scb.sector_num <= reg_bus.wdata[7:0];
if (reg_bus.wdata[BM_CONTROL_START_BUFFER_MANAGER]) begin
dd_scb.bm_start_pending <= 1'b1;
dd_scb.bm_stop_pending <= 1'b0;
dd_scb.bm_transfer_mode <= reg_bus.wdata[BM_CONTROL_BUFFER_MANAGER_MODE];
dd_scb.bm_transfer_blocks <= reg_bus.wdata[BM_CONTROL_BLOCK_TRANSFER];
end
if (reg_bus.wdata[BM_CONTROL_BUFFER_MANAGER_RESET]) begin
dd_scb.bm_start_pending <= 1'b0;
dd_scb.bm_stop_pending <= 1'b1;
dd_scb.bm_transfer_mode <= 1'b0;
dd_scb.bm_transfer_blocks <= 1'b0;
dd_scb.bm_pending <= 1'b0;
dd_scb.bm_interrupt <= 1'b0;
end
if (reg_bus.wdata[BM_CONTROL_MECHANIC_INTERRUPT_RESET]) begin
dd_scb.cmd_interrupt <= 1'b0;
end
end
S_WAIT: begin
state <= S_IDLE;
REG_RESET: begin
if (reg_bus.wdata == 16'hAAAA) begin
dd_scb.hard_reset <= 1'b1;
dd_scb.cmd_pending <= 1'b0;
dd_scb.cmd_interrupt <= 1'b0;
dd_scb.bm_start_pending <= 1'b0;
dd_scb.bm_stop_pending <= 1'b0;
dd_scb.bm_pending <= 1'b0;
dd_scb.bm_interrupt <= 1'b0;
end
end
REG_SEC_SIZ: begin
dd_scb.sector_size <= reg_bus.wdata[7:0];
end
REG_SEC_INFO: begin
dd_scb.sectors_in_block <= reg_bus.wdata[15:8];
dd_scb.sector_size_full <= reg_bus.wdata[7:0];
end
endcase
end
end
endmodule
module n64_dd_sector_buffer (
if_system.sys sys,
if_dd.sector_buffer dd
);
logic [5:0] sector_address;
logic [31:0] sector_buffer [0:63];
logic [15:0] sector_high_buffer;
logic sector_write;
logic [31:0] sector_wdata;
always_comb begin
irq = dd_scb.cmd_interrupt || dd_scb.bm_interrupt;
end
always_comb begin
sector_address = 6'd0;
sector_write = 1'b0;
sector_wdata = 32'd0;
if (dd.n64_sector_address_valid) begin
sector_address = dd.n64_sector_address[6:1];
end else if (dd.cpu_sector_address_valid) begin
sector_address = dd.cpu_sector_address;
end
if (dd.n64_sector_write && dd.n64_sector_address[0]) begin
sector_write = 1'b1;
sector_wdata = {sector_high_buffer, dd.n64_sector_wdata};
end else if (dd.cpu_sector_write) begin
sector_write = 1'b1;
sector_wdata = dd.cpu_sector_wdata;
end
end
always_ff @(posedge sys.clk) begin
if (dd.n64_sector_write && !dd.n64_sector_address[0]) begin
sector_high_buffer <= dd.n64_sector_wdata;
end
end
always_ff @(posedge sys.clk) begin
dd.sector_rdata <= sector_buffer[sector_address];
if (sector_write) begin
sector_buffer[sector_address] <= sector_wdata;
end
n64_scb.dd_write = reg_bus.write && reg_bus.address[10:8] == MEM_SECTOR_BUFFER[10:8];
n64_scb.dd_address = reg_bus.address[7:1];
n64_scb.dd_wdata = reg_bus.wdata;
end
endmodule

View File

@ -1,189 +1,152 @@
module n64_flashram (
if_system.sys sys,
if_n64_bus bus,
if_config.flashram cfg,
if_flashram.flashram flashram
input clk,
input reset,
n64_reg_bus.flashram reg_bus,
n64_scb.flashram n64_scb
);
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
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] {
STATE_STATUS,
STATE_ID,
STATE_READ,
STATE_BUFFER
} e_state;
typedef enum bit [1:0] {
FS_STATUS,
FS_ID,
FS_READ,
FS_BUFFER
} e_flashram_state;
WRITE_BUSY,
ERASE_BUSY,
WRITE_DONE,
ERASE_DONE
} e_status_bits;
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;
e_state state;
logic [3:0] status;
logic [7:0] cmd;
logic erase_enabled;
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];
n64_scb.flashram_read_mode = (state == STATE_READ);
reg_bus.rdata = 16'd0;
if (state == STATE_ID) begin
case (reg_bus.address[2:1])
0: reg_bus.rdata = FLASH_TYPE_ID[31:16];
1: reg_bus.rdata = FLASH_TYPE_ID[15:0];
2: reg_bus.rdata = FLASH_MODEL_ID[31:16];
3: reg_bus.rdata = FLASH_MODEL_ID[15:0];
endcase
end else if (reg_bus.address[1]) begin
reg_bus.rdata = {12'd0, status};
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;
always_ff @(posedge clk) begin
if (reset) begin
state <= STATE_STATUS;
status <= 4'b0000;
erase_enabled <= 1'b0;
n64_scb.flashram_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;
if (n64_scb.flashram_done) begin
n64_scb.flashram_pending <= 1'b0;
if (n64_scb.flashram_write_or_erase) begin
status[ERASE_BUSY] <= 1'b0;
status[ERASE_DONE] <= 1'b1;
end else begin
flashram_status[B_WRITE_BUSY] <= 1'b0;
flashram_status[B_WRITE_DONE] <= 1'b1;
status[WRITE_BUSY] <= 1'b0;
status[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;
if (reg_bus.write && !n64_scb.flashram_pending) begin
if (reg_bus.address[16]) begin
if (!reg_bus.address[1]) begin
cmd <= reg_bus.wdata[15:8];
end else begin
erase_enabled <= 1'b0;
case (flashram_command)
CMD_STATUS_MODE: begin
flashram_state <= FS_STATUS;
end
case (cmd)
CMD_STATUS_MODE: begin
state <= STATE_STATUS;
end
CMD_READID_MODE: begin
flashram_state <= FS_ID;
end
CMD_READID_MODE: begin
state <= STATE_ID;
end
CMD_READ_MODE: begin
flashram_state <= FS_READ;
end
CMD_READ_MODE: begin
state <= STATE_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_SECTOR: begin
state <= STATE_STATUS;
erase_enabled <= 1'b1;
n64_scb.flashram_sector <= reg_bus.wdata[9:0];
n64_scb.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_ERASE_CHIP: begin
state <= STATE_STATUS;
erase_enabled <= 1'b1;
n64_scb.flashram_sector <= 10'd0;
n64_scb.flashram_sector_or_all <= 1'b1;
end
CMD_BUFFER_MODE: begin
flashram_state <= FS_BUFFER;
end
CMD_BUFFER_MODE: begin
state <= STATE_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_BUSY] <= bus.wdata[B_ERASE_BUSY];
flashram_status[B_WRITE_BUSY] <= bus.wdata[B_WRITE_BUSY];
CMD_ERASE_START: begin
state <= STATE_STATUS;
if (erase_enabled) begin
status[ERASE_BUSY] <= 1'b1;
status[ERASE_DONE] <= 1'b0;
n64_scb.flashram_pending <= 1'b1;
n64_scb.flashram_write_or_erase <= 1'b1;
end
end
end
CMD_WRITE_START: begin
state <= STATE_STATUS;
status[WRITE_BUSY] <= 1'b1;
status[WRITE_DONE] <= 1'b0;
n64_scb.flashram_sector <= reg_bus.wdata[9:0];
n64_scb.flashram_pending <= 1'b1;
n64_scb.flashram_write_or_erase <= 1'b0;
n64_scb.flashram_sector_or_all <= 1'b0;
end
endcase
end
end else begin
if (reg_bus.address[1] && state != STATE_BUFFER) begin
status[ERASE_BUSY] <= reg_bus.wdata[ERASE_BUSY];
status[WRITE_BUSY] <= reg_bus.wdata[WRITE_BUSY];
end
end
S_WAIT: begin
bus_state <= S_IDLE;
end
endcase
end
end
end
always_comb begin
n64_scb.flashram_write = reg_bus.write && !reg_bus.address[16] && state == STATE_BUFFER;
n64_scb.flashram_address = reg_bus.address[6:1];
n64_scb.flashram_wdata = reg_bus.wdata;
end
endmodule

View File

@ -1,8 +1,14 @@
module n64_pi (
if_system.sys sys,
if_config.pi cfg,
if_n64_bus.n64 bus,
input clk,
input reset,
mem_bus.controller mem_bus,
n64_reg_bus.controller reg_bus,
n64_scb.pi n64_scb,
input n64_reset,
input n64_nmi,
input n64_pi_alel,
input n64_pi_aleh,
input n64_pi_read,
@ -10,81 +16,36 @@ module n64_pi (
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 [1:0] n64_reset_ff;
logic [1:0] n64_nmi_ff;
logic [3:0] n64_pi_alel_ff;
logic [3:0] n64_pi_aleh_ff;
logic [1: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};
always_ff @(posedge clk) begin
n64_reset_ff <= {n64_reset_ff[0], n64_reset};
n64_nmi_ff <= {n64_nmi_ff[0], n64_nmi};
n64_pi_aleh_ff <= {n64_pi_aleh_ff[2:0], n64_pi_aleh};
n64_pi_alel_ff <= {n64_pi_alel_ff[2:0], n64_pi_alel};
n64_pi_read_ff <= {n64_pi_read_ff[0], n64_pi_read};
n64_pi_write_ff <= {n64_pi_write_ff[1:0], n64_pi_write};
end
logic pi_reset;
logic pi_nmi;
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_reset = n64_reset_ff[1];
pi_nmi = n64_nmi_ff[1];
pi_aleh = n64_pi_aleh_ff[3];
pi_alel = n64_pi_alel_ff[3];
pi_read = n64_pi_read_ff[1];
pi_write = n64_pi_write_ff[2];
end
@ -99,16 +60,30 @@ module n64_pi (
PI_MODE_VALID = 2'b00
} e_pi_mode;
typedef enum bit [1:0] {
PORT_NONE,
PORT_MEM,
PORT_REG
} e_port;
e_pi_mode pi_mode;
e_pi_mode last_pi_mode;
logic last_read;
logic last_write;
e_port read_port;
e_port write_port;
always_comb begin
pi_mode = e_pi_mode'({pi_aleh, pi_alel});
end
always_ff @(posedge sys.clk) begin
logic last_reset;
logic last_nmi;
e_pi_mode last_pi_mode;
logic last_read;
logic last_write;
always_ff @(posedge clk) begin
last_reset <= pi_reset;
last_nmi <= pi_nmi;
last_pi_mode <= pi_mode;
last_read <= pi_read;
last_write <= pi_write;
@ -121,250 +96,394 @@ module n64_pi (
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;
n64_scb.n64_reset = !last_reset && pi_reset;
n64_scb.n64_nmi = !last_nmi && pi_nmi;
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) && (read_port != PORT_NONE) && (last_read && !pi_read);
write_op = pi_reset && (pi_mode == PI_MODE_VALID) && (write_port != PORT_NONE) && (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;
logic n64_pi_ad_oe;
logic [15:0] n64_pi_ad_out;
logic [15:0] n64_pi_dq_in;
logic [15:0] n64_pi_dq_out;
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];
assign n64_pi_ad = n64_pi_ad_oe ? n64_pi_ad_out : 16'hZZZZ;
always_ff @(posedge clk) begin
n64_pi_ad_oe <= pi_reset && (pi_mode == PI_MODE_VALID) && !last_read && (read_port != PORT_NONE);
n64_pi_ad_out <= n64_pi_dq_out;
n64_pi_dq_in <= n64_pi_ad;
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
// Debug: last accessed PI address
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
always_comb begin
bus.read_op = read_op;
bus.write_op = write_op;
end
always_ff @(posedge sys.clk) begin
always_ff @(posedge clk) begin
if (aleh_op) begin
bus.real_address[31:16] <= n64_pi_ad_input;
n64_scb.pi_debug[31:16] <= n64_pi_dq_in;
end
if (alel_op) begin
bus.real_address[15:0] <= {n64_pi_ad_input[15:1], 1'b0};
end
if (read_op || write_op) begin
bus.real_address <= bus.real_address + 2'd2;
n64_scb.pi_debug[15:0] <= n64_pi_dq_in;
end
end
// Address decoding
sc64::e_n64_id next_id;
logic [31:0] next_offset;
logic sram_selected;
logic cfg_selected;
const bit [31:0] DDIPL_OFFSET = 32'h03BC_0000;
const bit [31:0] SAVE_OFFSET = 32'h03FE_0000;
const bit [31:0] FLASH_OFFSET = 32'h0400_0000;
const bit [31:0] BOOTLOADER_OFFSET = 32'h04E0_0000;
const bit [31:0] SHADOW_OFFSET = 32'h04FE_0000;
const bit [31:0] BUFFER_OFFSET = 32'h0500_0000;
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.ddipl_offset + 32'h0A00_0000;
logic [31:0] mem_offset;
always_ff @(posedge clk) begin
if (reset || !pi_reset || end_op) begin
n64_scb.pi_sdram_active <= 1'b0;
n64_scb.pi_flash_active <= 1'b0;
end
if (reset) begin
read_port <= PORT_NONE;
write_port <= PORT_NONE;
reg_bus.dd_select <= 1'b0;
reg_bus.flashram_select <= 1'b0;
reg_bus.cfg_select <= 1'b0;
end else if (aleh_op) begin
read_port <= PORT_NONE;
write_port <= PORT_NONE;
mem_offset <= 32'd0;
reg_bus.dd_select <= 1'b0;
reg_bus.flashram_select <= 1'b0;
reg_bus.cfg_select <= 1'b0;
if (n64_scb.dd_enabled) begin
if (n64_pi_dq_in == 16'h0500) begin
read_port <= PORT_REG;
write_port <= PORT_REG;
reg_bus.dd_select <= 1'b1;
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;
if (n64_scb.ddipl_enabled) begin
if (n64_pi_dq_in >= 16'h0600 && n64_pi_dq_in < 16'h0640) begin
read_port <= PORT_MEM;
write_port <= PORT_NONE;
mem_offset <= (-32'h0600_0000) + DDIPL_OFFSET;
n64_scb.pi_sdram_active <= 1'b1;
end
end
if (n64_scb.flashram_enabled) begin
if (n64_pi_dq_in >= 16'h0800 && n64_pi_dq_in < 16'h0802) begin
read_port <= PORT_REG;
write_port <= PORT_REG;
mem_offset <= (-32'h0800_0000) + SAVE_OFFSET;
reg_bus.flashram_select <= 1'b1;
if (n64_scb.flashram_read_mode) begin
read_port <= PORT_MEM;
n64_scb.pi_sdram_active <= 1'b1;
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 else if (n64_scb.sram_enabled) begin
if (n64_scb.sram_banked) begin
if (n64_pi_dq_in >= 16'h0800 && n64_pi_dq_in < 16'h0810) begin
if (n64_pi_dq_in[3:2] != 2'b11 && n64_pi_dq_in[1:0] == 2'b00) begin
read_port <= PORT_MEM;
write_port <= PORT_MEM;
mem_offset <= (-32'h0800_0000) - {n64_pi_dq_in[3:2], 18'd0} + {n64_pi_dq_in[3:2], 15'd0} + SAVE_OFFSET;
n64_scb.pi_sdram_active <= 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;
if (n64_pi_dq_in >= 16'h0800 && n64_pi_dq_in < 16'h0802) begin
read_port <= PORT_MEM;
write_port <= PORT_MEM;
mem_offset <= (-32'h0800_0000) + SAVE_OFFSET;
n64_scb.pi_sdram_active <= 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 (next_id == sc64::ID_N64_DD) begin
if (|n64_pi_ad_input[15:11]) begin
n64_pi_address_valid <= 1'b0;
if (n64_scb.bootloader_enabled) begin
if (n64_pi_dq_in >= 16'h1000 && n64_pi_dq_in < 16'h101C) begin
read_port <= PORT_MEM;
write_port <= PORT_NONE;
mem_offset <= (-32'h1000_0000) + BOOTLOADER_OFFSET;
n64_scb.pi_flash_active <= 1'b1;
end
end else begin
if (n64_pi_dq_in >= 16'h1000 && n64_pi_dq_in < 16'h1400) begin
read_port <= PORT_MEM;
write_port <= n64_scb.rom_write_enabled ? PORT_MEM : PORT_NONE;
mem_offset <= (-32'h1000_0000);
n64_scb.pi_sdram_active <= 1'b1;
end
end
if (sram_selected) begin
if (n64_pi_ad_input[15]) begin
n64_pi_address_valid <= 1'b0;
if (n64_scb.rom_shadow_enabled) begin
if (n64_pi_dq_in >= 16'h13FE && n64_pi_dq_in < 16'h1400) begin
read_port <= PORT_MEM;
write_port <= PORT_NONE;
mem_offset <= (-32'h13FE_0000) + SHADOW_OFFSET;
n64_scb.pi_flash_active <= 1'b1;
end
end
if (cfg_selected) begin
if (|n64_pi_ad_input[15:4]) begin
n64_pi_address_valid <= 1'b0;
if (n64_scb.rom_extended_enabled) begin
if (n64_pi_dq_in >= 16'h1400 && n64_pi_dq_in < 16'h14E0) begin
read_port <= PORT_MEM;
write_port <= PORT_NONE;
mem_offset <= (-32'h1400_0000) + FLASH_OFFSET;
n64_scb.pi_flash_active <= 1'b1;
end
end
if (n64_scb.cfg_unlock) begin
if (n64_pi_dq_in >= 16'h1FFC && n64_pi_dq_in < 16'h1FFE) begin
read_port <= PORT_MEM;
write_port <= PORT_NONE;
mem_offset <= (-32'h1FFC_0000) + SHADOW_OFFSET;
n64_scb.pi_flash_active <= 1'b1;
end
if (n64_pi_dq_in >= 16'h1FFE && n64_pi_dq_in < 16'h1FFF) begin
read_port <= PORT_MEM;
write_port <= PORT_MEM;
mem_offset <= (-32'h1FFE_0000) + BUFFER_OFFSET;
end
end
if (n64_pi_dq_in >= 16'h1FFF && n64_pi_dq_in < 16'h2000) begin
read_port <= n64_scb.cfg_unlock ? PORT_REG : PORT_NONE;
write_port <= PORT_REG;
reg_bus.cfg_select <= 1'b1;
end
end
end
// Bus controller
// Mem bus read FIFO controller
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;
logic read_fifo_wait;
n64_pi_fifo read_fifo_inst (
.clk(clk),
.reset(reset),
.flush(reset || !pi_reset || alel_op),
.full(read_fifo_full),
.write(read_fifo_write),
.wdata(read_fifo_wdata),
.empty(read_fifo_empty),
.read(read_fifo_read),
.rdata(read_fifo_rdata)
);
always_ff @(posedge clk) begin
read_fifo_read <= 1'b0;
if (!pi_reset) begin
n64_scb.pi_debug[33:32] <= 2'b00;
end
if (reset || !pi_reset || alel_op) begin
read_fifo_wait <= 1'b0;
end
if (read_port == PORT_MEM) begin
if (read_op) begin
if (read_fifo_empty) begin
read_fifo_wait <= 1'b1;
n64_scb.pi_debug[32] <= 1'b1;
if (read_fifo_wait) begin
n64_scb.pi_debug[33] <= 1'b1;
end
end else begin
read_fifo_read <= 1'b1;
n64_pi_dq_out <= read_fifo_rdata;
end
end
if (!read_fifo_empty && read_fifo_wait) begin
read_fifo_read <= 1'b1;
read_fifo_wait <= 1'b0;
n64_pi_dq_out <= read_fifo_rdata;
end
end
if (read_port == PORT_REG) begin
if (read_op) begin
n64_pi_dq_out <= reg_bus.rdata;
end
end
end
// Mem bus write FIFO controller
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;
logic write_fifo_wait;
n64_pi_fifo write_fifo_inst (
.clk(clk),
.reset(reset),
.flush(reset),
.full(write_fifo_full),
.write(write_fifo_write),
.wdata(write_fifo_wdata),
.empty(write_fifo_empty),
.read(write_fifo_read),
.rdata(write_fifo_rdata)
);
always_ff @(posedge clk) begin
write_fifo_write <= 1'b0;
if (!pi_reset) begin
n64_scb.pi_debug[35:34] <= 2'b00;
end
if (reset) begin
write_fifo_wait <= 1'b0;
end
if (write_port == PORT_MEM) begin
if (write_op) begin
if (write_fifo_full) begin
write_fifo_wait <= 1'b1;
n64_scb.pi_debug[34] <= 1'b1;
if (write_fifo_wait) begin
n64_scb.pi_debug[35] <= 1'b1;
end
end else begin
write_fifo_write <= 1'b1;
write_fifo_wdata <= n64_pi_dq_in;
end
end
if (!write_fifo_full && write_fifo_wait) begin
write_fifo_write <= 1'b1;
write_fifo_wait <= 1'b0;
write_fifo_wdata <= n64_pi_dq_in;
end
end
end
// Mem bus controller
logic can_read;
logic first_write_op;
logic load_starting_address;
sc64::e_n64_id starting_id;
logic [31:0] starting_address;
logic load_starting_address;
logic read_enabled;
logic first_write_op;
always_ff @(posedge sys.clk) begin
read_fifo_flush <= 1'b0;
always_ff @(posedge clk) begin
write_fifo_read <= 1'b0;
load_starting_address <= 1'b0;
if (sys.reset || sys.n64_hard_reset) begin
bus.request <= 1'b0;
read_fifo_flush <= 1'b1;
write_fifo_flush <= 1'b1;
if (reset || !pi_reset) begin
mem_bus.request <= 1'b0;
read_enabled <= 1'b0;
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;
starting_address[31:16] <= n64_pi_dq_in;
end
if (alel_op) begin
read_fifo_flush <= 1'b1;
can_read <= 1'b1;
first_write_op <= 1'b1;
starting_address <= {starting_address[31:16], n64_pi_dq_in} + mem_offset;
load_starting_address <= 1'b1;
starting_id <= next_id;
starting_address <= {starting_address[31:16], n64_pi_ad_input[15:1], 1'b0};
read_enabled <= 1'b1;
first_write_op <= 1'b1;
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
if (load_starting_address) begin
mem_bus.address <= starting_address;
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 + next_offset;
if (starting_id == sc64::ID_N64_FLASHRAM) begin
bus.address <= starting_address;
end
load_starting_address <= 1'b0;
end
bus.wdata <= write_fifo_rdata;
if (!mem_bus.request) begin
if ((write_port == PORT_MEM) && !write_fifo_empty) begin
mem_bus.request <= 1'b1;
mem_bus.write <= 1'b1;
mem_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;
bus.address <= starting_address + next_offset;
if (starting_id == sc64::ID_N64_FLASHRAM && cfg.flashram_read_mode) begin
bus.id <= sc64::ID_N64_SDRAM;
end
load_starting_address <= 1'b0;
read_enabled <= 1'b0;
if (first_write_op) begin
mem_bus.address <= starting_address;
first_write_op <= 1'b0;
end
end else if ((read_port == PORT_MEM) && !read_fifo_full && read_enabled) begin
mem_bus.request <= 1'b1;
mem_bus.write <= 1'b0;
end
end else if (bus.ack) begin
bus.request <= 1'b0;
bus.address <= bus.address + 2'd2;
end
if (mem_bus.ack) begin
mem_bus.request <= 1'b0;
mem_bus.address[16:0] <= mem_bus.address[16:0] + 2'd2;
end
if (end_op) begin
can_read <= 1'b0;
read_enabled <= 1'b0;
end
end
end
always_comb begin
read_fifo_write = !mem_bus.write && mem_bus.ack;
read_fifo_wdata = mem_bus.rdata;
mem_bus.wmask = 2'b11;
end
// Reg bus controller
always_ff @(posedge clk) begin
if (aleh_op) begin
reg_bus.address[16] <= n64_pi_dq_in[0];
end
if (alel_op) begin
reg_bus.address[15:0] <= n64_pi_dq_in;
end
if (read_op || write_op) begin
reg_bus.address <= reg_bus.address + 2'd2;
end
end
always_comb begin
reg_bus.read = read_op && (read_port == PORT_REG);
reg_bus.write = write_op && (write_port == PORT_REG);
reg_bus.wdata = n64_pi_dq_in;
end
endmodule

View File

@ -1,5 +1,6 @@
module n64_pi_fifo (
if_system.sys sys,
input clk,
input reset,
input flush,
@ -18,15 +19,13 @@ module n64_pi_fifo (
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
assign rdata = fifo_mem[fifo_rd_ptr[1:0]];
assign empty_or_full = fifo_wr_ptr[1:0] == fifo_rd_ptr[1:0];
assign empty = empty_or_full && fifo_wr_ptr[2] == fifo_rd_ptr[2];
assign full = empty_or_full && fifo_wr_ptr[2] != fifo_rd_ptr[2];
always_ff @(posedge sys.clk) begin
if (sys.reset || flush) begin
always_ff @(posedge clk) begin
if (reset || flush) begin
fifo_wr_ptr <= 3'd0;
fifo_rd_ptr <= 3'd0;
end else begin

66
fw/rtl/n64/n64_reg_bus.sv Normal file
View File

@ -0,0 +1,66 @@
interface n64_reg_bus ();
logic flashram_select;
logic dd_select;
logic cfg_select;
logic read;
logic write;
logic [16:0] address;
logic [15:0] rdata;
logic [15:0] wdata;
logic [15:0] flashram_rdata;
logic [15:0] dd_rdata;
logic [15:0] cfg_rdata;
modport controller (
output flashram_select,
output dd_select,
output cfg_select,
output read,
output write,
output address,
input rdata,
output wdata
);
always_comb begin
rdata = 16'd0;
if (flashram_select) begin
rdata = flashram_rdata;
end
if (dd_select) begin
rdata = dd_rdata;
end
if (cfg_select) begin
rdata = cfg_rdata;
end
end
modport flashram (
input .read(read && flashram_select),
input .write(write && flashram_select),
input address,
output .rdata(flashram_rdata),
input wdata
);
modport dd (
input .read(read && dd_select),
input .write(write && dd_select),
input address,
output .rdata(dd_rdata),
input wdata
);
modport cfg (
input .read(read && cfg_select),
input .write(write && cfg_select),
input address,
output .rdata(cfg_rdata),
input wdata
);
endinterface

197
fw/rtl/n64/n64_scb.sv Normal file
View File

@ -0,0 +1,197 @@
interface n64_scb ();
logic n64_reset;
logic n64_nmi;
logic bootloader_enabled;
logic rom_write_enabled;
logic rom_shadow_enabled;
logic rom_extended_enabled;
logic sram_enabled;
logic sram_banked;
logic flashram_enabled;
logic dd_enabled;
logic ddipl_enabled;
logic eeprom_enabled;
logic eeprom_16k_mode;
logic dd_write;
logic [6:0] dd_address;
logic [15:0] dd_rdata;
logic [15:0] dd_wdata;
logic flashram_pending;
logic flashram_done;
logic [9:0] flashram_sector;
logic flashram_sector_or_all;
logic flashram_write_or_erase;
logic flashram_read_mode;
logic flashram_write;
logic [5:0] flashram_address;
logic [15:0] flashram_wdata;
logic eeprom_write;
logic [10:0] eeprom_address;
logic [7:0] eeprom_rdata;
logic [7:0] eeprom_wdata;
logic rtc_pending;
logic rtc_done;
logic rtc_wdata_valid;
logic [41:0] rtc_rdata;
logic [41:0] rtc_wdata;
logic cfg_unlock;
logic cfg_pending;
logic cfg_done;
logic cfg_error;
logic cfg_irq;
logic [7:0] cfg_cmd;
logic [31:0] cfg_rdata [0:1];
logic [31:0] cfg_wdata [0:1];
logic [31:0] cfg_version;
logic pi_sdram_active;
logic pi_flash_active;
logic [35:0] pi_debug;
modport controller (
input n64_reset,
input n64_nmi,
output bootloader_enabled,
output rom_write_enabled,
output rom_shadow_enabled,
output rom_extended_enabled,
output sram_enabled,
output sram_banked,
output flashram_enabled,
output dd_enabled,
output ddipl_enabled,
output eeprom_enabled,
output eeprom_16k_mode,
input flashram_pending,
output flashram_done,
input flashram_sector,
input flashram_sector_or_all,
input flashram_write_or_erase,
input rtc_pending,
output rtc_done,
output rtc_wdata_valid,
input rtc_rdata,
output rtc_wdata,
input cfg_pending,
output cfg_done,
output cfg_error,
output cfg_irq,
input cfg_cmd,
input cfg_rdata,
output cfg_wdata,
output cfg_version,
input pi_debug
);
modport pi (
output n64_reset,
output n64_nmi,
input bootloader_enabled,
input rom_write_enabled,
input rom_shadow_enabled,
input rom_extended_enabled,
input sram_enabled,
input sram_banked,
input flashram_enabled,
input dd_enabled,
input ddipl_enabled,
input flashram_read_mode,
input cfg_unlock,
output pi_sdram_active,
output pi_flash_active,
output pi_debug
);
modport flashram (
output flashram_pending,
input flashram_done,
output flashram_sector,
output flashram_sector_or_all,
output flashram_write_or_erase,
output flashram_read_mode,
output flashram_write,
output flashram_address,
output flashram_wdata
);
modport si (
input eeprom_enabled,
input eeprom_16k_mode,
output eeprom_write,
output eeprom_address,
input eeprom_rdata,
output eeprom_wdata,
output rtc_pending,
input rtc_done,
input rtc_wdata_valid,
output rtc_rdata,
input rtc_wdata
);
modport dd (
input n64_reset,
input n64_nmi,
output dd_write,
output dd_address,
input dd_rdata,
output dd_wdata
);
modport bram (
input flashram_write,
input flashram_address,
input flashram_wdata,
input eeprom_write,
input eeprom_address,
output eeprom_rdata,
input eeprom_wdata,
input dd_write,
input dd_address,
output dd_rdata,
input dd_wdata
);
modport cfg (
input n64_reset,
input n64_nmi,
output cfg_unlock,
output cfg_pending,
input cfg_done,
input cfg_error,
input cfg_irq,
output cfg_cmd,
output cfg_rdata,
input cfg_wdata,
input cfg_version
);
modport arbiter (
input pi_sdram_active,
input pi_flash_active
);
endinterface

View File

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

View File

@ -1,164 +1,253 @@
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 clk,
input reset,
n64_scb.si n64_scb,
input n64_reset,
input n64_si_clk,
inout n64_si_dq
);
// Control signals and input synchronization
// Input/output synchronization
logic [1:0] n64_reset_ff;
logic [1:0] n64_si_clk_ff;
always_ff @(posedge sys.clk) begin
always_ff @(posedge clk) begin
n64_reset_ff <= {n64_reset_ff[0], n64_reset};
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_reset = n64_reset_ff[1];
si_clk = n64_si_clk_ff[1];
si_dq = n64_si_dq;
end
logic si_dq_oe;
logic si_dq_out;
logic si_dq_in;
assign n64_si_dq = si_dq_oe ? 1'b0 : 1'bZ;
always_ff @(posedge clk) begin
si_dq_oe <= ~si_dq_out;
si_dq_in <= n64_si_dq;
end
// Clock falling/rising event generator
logic last_si_clk;
always_ff @(posedge sys.clk) begin
always_ff @(posedge clk) begin
last_si_clk <= si_clk;
end
logic si_clk_rising_edge;
logic si_clk_falling_edge;
logic si_clk_rising_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;
si_clk_falling_edge = si_reset && last_si_clk && !si_clk;
si_clk_rising_edge = si_reset && !last_si_clk && si_clk;
end
// Data register and shifter
// Data falling/rising event generator
logic [80:0] trx_data;
logic rx_shift;
logic tx_shift;
logic last_si_dq_in;
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};
always_ff @(posedge clk) begin
if (si_clk_rising_edge) begin
last_si_dq_in <= si_dq_in;
end
end
logic si_dq_falling_edge;
logic si_dq_rising_edge;
always_comb begin
si_dq_falling_edge = si_clk_rising_edge && last_si_dq_in && !si_dq_in;
si_dq_rising_edge = si_clk_rising_edge && !last_si_dq_in && si_dq_in;
end
// RX bit generator
logic [3:0] rx_sub_bit_counter;
logic rx_timeout;
logic rx_bit_valid;
logic rx_bit_data;
always_ff @(posedge clk) begin
if (si_clk_rising_edge && !(&rx_sub_bit_counter)) begin
rx_sub_bit_counter <= rx_sub_bit_counter + 1'd1;
end
if (si_dq_falling_edge) begin
rx_sub_bit_counter <= 4'd0;
end
end
always_comb begin
rx_timeout = si_clk_rising_edge && si_dq_in && (&rx_sub_bit_counter);
rx_bit_valid = si_dq_rising_edge;
rx_bit_data = (rx_sub_bit_counter >= 4'd3) ? 1'b0 : 1'b1;
end
// RX byte generator
logic [2:0] rx_bit_counter;
logic rx_byte_valid;
logic [7:0] rx_byte_data;
always_ff @(posedge clk) begin
rx_byte_valid <= 1'b0;
if (rx_timeout) begin
rx_bit_counter <= 3'd0;
end
if (rx_bit_valid) begin
rx_bit_counter <= rx_bit_counter + 1'd1;
rx_byte_data <= {rx_byte_data[6:0], rx_bit_data};
if (&rx_bit_counter) begin
rx_byte_valid <= 1'b1;
end
end
end
// RX stop generator
logic rx_stop;
always_comb begin
rx_stop = si_clk_rising_edge && si_dq_in && (rx_sub_bit_counter == 4'd7) && (rx_bit_counter == 3'd1);
end
// TX byte/stop generator
logic tx_busy;
logic [2:0] tx_sub_bit_counter;
logic [2:0] tx_bit_counter;
logic [7:0] tx_shift;
logic tx_start;
logic tx_stop;
logic tx_byte_valid;
logic [7:0] tx_byte_data;
always_ff @(posedge clk) begin
if (reset) begin
si_dq_out <= 1'b1;
tx_busy <= 1'b0;
end else begin
if (tx_busy) begin
if (si_clk_falling_edge) begin
tx_sub_bit_counter <= tx_sub_bit_counter + 1'd1;
if (&tx_sub_bit_counter) begin
tx_bit_counter <= tx_bit_counter + 1'd1;
tx_shift <= {tx_shift[6:0], 1'bX};
if (&tx_bit_counter) begin
tx_busy <= 1'b0;
end
end
if (tx_shift[7]) begin
si_dq_out <= !(tx_sub_bit_counter < 3'd2);
end else begin
si_dq_out <= !(tx_sub_bit_counter < 3'd6);
end
end
end else begin
if (tx_byte_valid) begin
tx_busy <= 1'b1;
tx_sub_bit_counter <= 3'd0;
tx_bit_counter <= 3'd0;
tx_shift <= tx_byte_data;
end else if (tx_stop) begin
tx_busy <= 1'b1;
tx_sub_bit_counter <= 3'd0;
tx_bit_counter <= 3'd7;
tx_shift <= 8'hFF;
end
end
end
end
// Joybus CMDs
typedef enum bit [7:0] {
CMD_EEPROM_STATUS = 8'h00,
CMD_EEPROM_READ = 8'h04,
CMD_EEPROM_WRITE = 8'h05,
CMD_RTC_STATUS = 8'h06,
CMD_RTC_READ = 8'h07,
CMD_RTC_WRITE = 8'h08
} e_cmd;
e_cmd cmd;
// RX path
typedef enum bit [0:0] {
S_RX_IDLE,
S_RX_WAITING
typedef enum bit [1:0] {
RX_STATE_IDLE,
RX_STATE_DATA,
RX_STATE_IGNORE
} e_rx_state;
e_rx_state rx_state;
logic [3:0] rx_byte_counter;
logic rx_data_valid;
logic [1:0] rx_sub_bit_counter;
logic [3:0] rx_timeout_counter;
always_comb begin
rx_data_valid = rx_byte_valid && (rx_state == RX_STATE_DATA);
end
always_ff @(posedge sys.clk) begin
rx_shift <= 1'b0;
always_ff @(posedge clk) begin
tx_start <= 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
if (rx_byte_valid) begin
rx_byte_counter <= rx_byte_counter + 1'd1;
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
if (reset || rx_timeout) begin
rx_state <= RX_STATE_IDLE;
end else 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;
RX_STATE_IDLE: begin
if (rx_byte_valid) begin
cmd <= e_cmd'(rx_byte_data);
rx_byte_counter <= 4'd0;
rx_state <= RX_STATE_IGNORE;
case (rx_byte_data)
CMD_EEPROM_STATUS,
CMD_EEPROM_READ,
CMD_EEPROM_WRITE: begin
rx_state <= n64_scb.eeprom_enabled ? RX_STATE_DATA : RX_STATE_IGNORE;
end
CMD_RTC_STATUS,
CMD_RTC_READ,
CMD_RTC_WRITE: begin
rx_state <= RX_STATE_DATA;
end
endcase
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
RX_STATE_DATA: begin
if (rx_stop) begin
tx_start <= 1'b1;
rx_state <= RX_STATE_IGNORE;
end
end
RX_STATE_IGNORE: begin
if (rx_stop) begin
rx_state <= RX_STATE_IDLE;
end
end
endcase
@ -168,57 +257,217 @@ module n64_si (
// TX path
typedef enum bit [0:0] {
S_TX_IDLE,
S_TX_SENDING
typedef enum bit [1:0] {
TX_STATE_IDLE,
TX_STATE_DATA,
TX_STATE_STOP
} e_tx_state;
e_tx_state tx_state;
logic [2:0] tx_sub_bit_counter;
logic [6:0] tx_bit_counter;
logic [3:0] tx_byte_counter;
logic [3:0] tx_length;
always_ff @(posedge sys.clk) begin
tx_shift <= 1'b0;
always_ff @(posedge clk) begin
tx_byte_valid <= 1'b0;
tx_stop <= 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;
if (!tx_busy && tx_byte_valid) begin
tx_byte_counter <= tx_byte_counter + 1'd1;
end
if (reset) begin
tx_state <= TX_STATE_IDLE;
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;
TX_STATE_IDLE: begin
if (tx_start) begin
tx_byte_counter <= 4'd0;
tx_state <= TX_STATE_DATA;
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;
TX_STATE_DATA: begin
tx_byte_valid <= 1'b1;
if (!tx_busy && tx_byte_valid) begin
if (tx_byte_counter == tx_length) begin
tx_state <= TX_STATE_STOP;
end
end
end
TX_STATE_STOP: begin
tx_stop <= 1'b1;
if (!tx_busy && tx_stop) begin
tx_state <= TX_STATE_IDLE;
end
end
endcase
end
end
// Joybus address latching
logic [7:0] joybus_address;
logic [2:0] joybus_subaddress;
logic [10:0] joybus_full_address;
always_comb begin
joybus_full_address = {joybus_address, joybus_subaddress};
end
always_ff @(posedge clk) begin
if (rx_data_valid || (!tx_busy && tx_byte_valid)) begin
joybus_subaddress <= joybus_subaddress + 1'd1;
end
if (rx_data_valid) begin
if (rx_byte_counter == 4'd0) begin
joybus_address <= rx_byte_data;
joybus_subaddress <= 3'd0;
end
end
end
// EEPROM controller
always_comb begin
n64_scb.eeprom_write = rx_data_valid && (cmd == CMD_EEPROM_WRITE) && rx_byte_counter > 4'd0;
n64_scb.eeprom_address = joybus_full_address;
n64_scb.eeprom_wdata = rx_byte_data;
end
// RTC controller
logic rtc_backup_wp;
logic rtc_time_wp;
logic [1:0] rtc_stopped;
logic [6:0] rtc_time_second;
logic [6:0] rtc_time_minute;
logic [5:0] rtc_time_hour;
logic [5:0] rtc_time_day;
logic [2:0] rtc_time_weekday;
logic [4:0] rtc_time_month;
logic [7:0] rtc_time_year;
always_ff @(posedge clk) begin
if (reset) begin
rtc_backup_wp <= 1'b1;
rtc_time_wp <= 1'b1;
rtc_stopped <= 2'b00;
n64_scb.rtc_pending <= 1'b0;
end
if (n64_scb.rtc_done) begin
n64_scb.rtc_pending <= 1'b0;
end
if (!(|rtc_stopped) && !n64_scb.rtc_pending && n64_scb.rtc_wdata_valid && (tx_state != TX_STATE_DATA)) begin
{
rtc_time_year,
rtc_time_month,
rtc_time_weekday,
rtc_time_day,
rtc_time_hour,
rtc_time_minute,
rtc_time_second
} <= n64_scb.rtc_wdata;
end
if (rx_data_valid && (cmd == CMD_RTC_WRITE)) begin
if (joybus_address[1:0] == 2'd0) begin
case (rx_byte_counter)
4'd1: {rtc_time_wp, rtc_backup_wp} <= rx_byte_data[1:0];
4'd2: begin
rtc_stopped <= rx_byte_data[2:1];
if (rx_byte_data[2:1] == 2'b00) begin
n64_scb.rtc_pending <= 1'b1;
end
end
endcase
end
if ((joybus_address[1:0] == 2'd2) && !rtc_time_wp) begin
case (rx_byte_counter)
4'd1: rtc_time_second <= rx_byte_data[6:0];
4'd2: rtc_time_minute <= rx_byte_data[6:0];
4'd3: rtc_time_hour <= rx_byte_data[5:0];
4'd4: rtc_time_day <= rx_byte_data[5:0];
4'd5: rtc_time_weekday <= rx_byte_data[2:0];
4'd6: rtc_time_month <= rx_byte_data[4:0];
4'd7: rtc_time_year <= rx_byte_data;
endcase
end
end
end
always_comb begin
n64_scb.rtc_rdata = {
rtc_time_year,
rtc_time_month,
rtc_time_weekday,
rtc_time_day,
rtc_time_hour,
rtc_time_minute,
rtc_time_second
};
end
// TX data multiplexer
always_comb begin
tx_length = 4'd0;
tx_byte_data = 8'h00;
case (cmd)
CMD_EEPROM_STATUS: begin
tx_length = 4'd2;
case (tx_byte_counter)
4'd1: tx_byte_data = {1'b1, n64_scb.eeprom_16k_mode, 6'd0};
endcase
end
CMD_EEPROM_READ: begin
tx_length = 4'd7;
tx_byte_data = n64_scb.eeprom_rdata;
end
CMD_EEPROM_WRITE: begin
tx_length = 4'd0;
end
CMD_RTC_STATUS: begin
tx_length = 4'd2;
case (tx_byte_counter)
4'd1: tx_byte_data = 8'h10;
4'd2: tx_byte_data = {(|rtc_stopped), 7'd0};
endcase
end
CMD_RTC_READ: begin
tx_length = 4'd8;
if (joybus_address[1:0] == 2'd0) begin
case (tx_byte_counter)
4'd0: tx_byte_data = {6'd0, rtc_time_wp, rtc_backup_wp};
4'd1: tx_byte_data = {5'd0, rtc_stopped, 1'b0};
4'd8: tx_byte_data = {(|rtc_stopped), 7'd0};
endcase
end else if (joybus_address[1:0] == 2'd2) begin
case (tx_byte_counter)
4'd0: tx_byte_data = {1'd0, rtc_time_second};
4'd1: tx_byte_data = {1'd0, rtc_time_minute};
4'd2: tx_byte_data = {2'b10, rtc_time_hour};
4'd3: tx_byte_data = {2'd0, rtc_time_day};
4'd4: tx_byte_data = {5'd0, rtc_time_weekday};
4'd5: tx_byte_data = {3'd0, rtc_time_month};
4'd6: tx_byte_data = rtc_time_year;
4'd7: tx_byte_data = 8'h01;
4'd8: tx_byte_data = {(|rtc_stopped), 7'd0};
endcase
end
end
CMD_RTC_WRITE: begin
tx_length = 4'd0;
tx_byte_data = {(|rtc_stopped), 7'd0};
end
endcase
end
endmodule

View File

@ -1,96 +0,0 @@
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,
if_flash.memory flash,
if_dd dd,
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),
.flash(flash)
);
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),
.dd(dd)
);
n64_dd_sector_buffer n64_dd_sector_buffer_inst (
.sys(sys),
.dd(dd)
);
n64_cfg n64_cfg_inst (
.sys(sys),
.bus(bus.at[sc64::ID_N64_CFG].device),
.cfg(cfg)
);
endmodule

97
fw/rtl/n64/n64_top.sv Normal file
View File

@ -0,0 +1,97 @@
module n64_top (
input clk,
input reset,
n64_scb n64_scb,
dd_scb.dd dd_scb,
mem_bus.controller mem_bus,
input n64_reset,
input n64_nmi,
output n64_irq,
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
);
logic n64_dd_irq;
logic n64_cfg_irq;
logic n64_irq_oe;
always @(posedge clk) begin
n64_irq_oe <= (n64_dd_irq || n64_cfg_irq);
end
assign n64_irq = n64_irq_oe ? 1'b0 : 1'bZ;
n64_reg_bus reg_bus ();
n64_pi n64_pi_inst (
.clk(clk),
.reset(reset),
.mem_bus(mem_bus),
.reg_bus(reg_bus),
.n64_scb(n64_scb),
.n64_reset(n64_reset),
.n64_nmi(n64_nmi),
.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_dd n64_dd_inst (
.clk(clk),
.reset(reset),
.reg_bus(reg_bus),
.n64_scb(n64_scb),
.dd_scb(dd_scb),
.irq(n64_dd_irq)
);
n64_flashram n64_flashram_inst (
.clk(clk),
.reset(reset),
.reg_bus(reg_bus),
.n64_scb(n64_scb)
);
n64_cfg n64_cfg_inst (
.clk(clk),
.reset(reset),
.reg_bus(reg_bus),
.n64_scb(n64_scb),
.irq(n64_cfg_irq)
);
n64_si n64_si_inst (
.clk(clk),
.reset(reset),
.n64_scb(n64_scb),
.n64_reset(n64_reset),
.n64_si_clk(n64_si_clk),
.n64_si_dq(n64_si_dq)
);
endmodule

48
fw/rtl/sd/sd_clk.sv Normal file
View File

@ -0,0 +1,48 @@
module sd_clk (
input clk,
input reset,
sd_scb.clk sd_scb,
output logic sd_clk_rising,
output logic sd_clk_falling,
output logic sd_clk
);
logic [7:0] clock_divider;
always_ff @(posedge clk) begin
if (!sd_scb.clock_stop) begin
clock_divider <= clock_divider + 1'd1;
end
end
logic selected_clock;
always_comb begin
selected_clock = 1'b0;
case (sd_scb.clock_mode)
2'd0: selected_clock = 1'b0;
2'd1: selected_clock = clock_divider[7];
2'd2: selected_clock = clock_divider[1];
2'd3: selected_clock = clock_divider[0];
endcase
end
logic last_selected_clock;
always_ff @(posedge clk) begin
last_selected_clock <= selected_clock;
end
always_comb begin
sd_clk_rising = !last_selected_clock && selected_clock;
sd_clk_falling = last_selected_clock && !selected_clock;
end
always_ff @(posedge clk) begin
sd_clk <= last_selected_clock;
end
endmodule

231
fw/rtl/sd/sd_cmd.sv Normal file
View File

@ -0,0 +1,231 @@
module sd_cmd (
input clk,
input reset,
sd_scb.cmd sd_scb,
input sd_clk_rising,
input sd_clk_falling,
inout sd_cmd
);
// Input and output data sampling
logic sd_cmd_oe;
logic sd_cmd_out;
logic sd_cmd_in;
logic sd_cmd_oe_data;
logic sd_cmd_data;
assign sd_cmd = sd_cmd_oe ? sd_cmd_out : 1'bZ;
always_ff @(posedge clk) begin
sd_cmd_oe <= sd_cmd_oe_data;
sd_cmd_out <= sd_cmd_data;
sd_cmd_in <= sd_cmd;
end
// CMD state
typedef enum bit [1:0] {
STATE_IDLE,
STATE_TX,
STATE_WAIT,
STATE_RX
} e_state;
e_state state;
e_state next_state;
always_ff @(posedge clk) begin
if (reset) begin
state <= STATE_IDLE;
end else begin
state <= next_state;
end
end
assign sd_scb.cmd_busy = (state != STATE_IDLE);
logic [7:0] counter;
always_comb begin
next_state = state;
case (state)
STATE_IDLE: begin
if (sd_scb.cmd_start) begin
next_state = STATE_TX;
end
end
STATE_TX: begin
if (sd_clk_falling) begin
if (counter == 8'd48) begin
if (sd_scb.cmd_skip_response) begin
next_state = STATE_IDLE;
end else begin
next_state = STATE_WAIT;
end
end
end
end
STATE_WAIT: begin
if (sd_clk_rising) begin
if (counter == 8'd64) begin
next_state = STATE_IDLE;
end
if (!sd_cmd_in) begin
next_state = STATE_RX;
end
end
end
STATE_RX: begin
if (sd_clk_rising) begin
if (sd_scb.cmd_long_response) begin
if (counter == 8'd136) begin
next_state = STATE_IDLE;
end
end else begin
if (counter == 8'd48) begin
next_state = STATE_IDLE;
end
end
end
end
default: begin
next_state = STATE_IDLE;
end
endcase
end
// CRC7 unit
logic crc_reset;
logic crc_enable;
logic crc_data;
logic [6:0] crc_result;
sd_crc_7 sd_crc_7_inst (
.clk(clk),
.reset(crc_reset),
.enable(crc_enable),
.data(crc_data),
.result(crc_result)
);
// Data shifting
logic [7:0] data_shift;
assign crc_data = (state == STATE_RX) ? data_shift[0] : data_shift[7];
always_ff @(posedge clk) begin
crc_reset <= 1'b0;
crc_enable <= 1'b0;
if (reset) begin
sd_cmd_oe_data <= 1'b0;
sd_cmd_data <= 1'b1;
end else begin
case (state)
STATE_IDLE: begin
if (sd_scb.cmd_start) begin
sd_scb.cmd_error <= 1'b0;
crc_reset <= 1'b1;
data_shift <= {2'b01, sd_scb.cmd_index};
counter <= 8'd0;
end
end
STATE_TX: begin
if (sd_clk_falling) begin
sd_cmd_oe_data <= 1'b1;
sd_cmd_data <= data_shift[7];
counter <= counter + 1'd1;
crc_enable <= 1'b1;
data_shift <= {data_shift[6:0], 1'bX};
if (counter == 8'd7) begin
data_shift <= sd_scb.cmd_arg[31:24];
end
if (counter == 8'd15) begin
data_shift <= sd_scb.cmd_arg[23:16];
end
if (counter == 8'd23) begin
data_shift <= sd_scb.cmd_arg[15:8];
end
if (counter == 8'd31) begin
data_shift <= sd_scb.cmd_arg[7:0];
end
if (counter == 8'd39) begin
data_shift <= {crc_result, 1'b1};
end
if (counter == 8'd48) begin
sd_cmd_oe_data <= 1'b0;
counter <= 8'd0;
end
end
end
STATE_WAIT: begin
if (sd_clk_rising) begin
counter <= counter + 1'd1;
if (counter == 8'd64) begin
sd_scb.cmd_error <= 1'b1;
end
if (!sd_cmd_in) begin
counter <= 8'd1;
crc_reset <= 1'b1;
data_shift <= 8'h00;
end
end
end
STATE_RX: begin
if (sd_clk_rising) begin
counter <= counter + 1'd1;
data_shift <= {data_shift[6:0], sd_cmd_in};
if (counter == 8'd8) begin
if (data_shift[6:0] != (sd_scb.cmd_reserved_response ? 7'h3F : {1'b0, sd_scb.cmd_index})) begin
sd_scb.cmd_error <= 1'b1;
end
end
if (sd_scb.cmd_long_response) begin
if (counter >= 8'd8 && counter < 8'd128) begin
crc_enable <= 1'b1;
end
if (counter[2:0] == 3'd0) begin
sd_scb.cmd_rsp <= {sd_scb.cmd_rsp[119:0], data_shift};
end
if (!sd_scb.cmd_ignore_crc && counter == 8'd136) begin
if (data_shift[7:1] != crc_result) begin
sd_scb.cmd_error <= 1'b1;
end
end
end else begin
if (counter < 8'd40) begin
crc_enable <= 1'b1;
end
if (counter <= 8'd40 && counter[2:0] == 3'd0) begin
sd_scb.cmd_rsp <= {sd_scb.cmd_rsp[119:0], data_shift};
end
if (!sd_scb.cmd_ignore_crc && counter == 8'd48) begin
if (data_shift[7:1] != crc_result) begin
sd_scb.cmd_error <= 1'b1;
end
end
end
end
end
endcase
end
end
endmodule

33
fw/rtl/sd/sd_crc_16.sv Normal file
View File

@ -0,0 +1,33 @@
module sd_crc_16 (
input clk,
input reset,
input enable,
input shift,
input data,
output logic [15:0] result
);
logic crc_inv;
assign crc_inv = result[15] ^ data;
always_ff @(posedge clk) begin
if (reset) begin
result <= 16'd0;
end else if (enable) begin
result <= {
result[14:12],
result[11] ^ crc_inv,
result[10:5],
result[4] ^ crc_inv,
result[3:0],
crc_inv
};
end else if (shift) begin
result <= {result[14:0], 1'b1};
end
end
endmodule

28
fw/rtl/sd/sd_crc_7.sv Normal file
View File

@ -0,0 +1,28 @@
module sd_crc_7 (
input clk,
input reset,
input enable,
input data,
output logic [6:0] result
);
logic crc_inv;
assign crc_inv = result[6] ^ data;
always_ff @(posedge clk) begin
if (reset) begin
result <= 7'd0;
end else if (enable) begin
result <= {
result[5:3],
result[2] ^ crc_inv,
result[1:0],
crc_inv
};
end
end
endmodule

373
fw/rtl/sd/sd_dat.sv Normal file
View File

@ -0,0 +1,373 @@
module sd_dat (
input clk,
input reset,
sd_scb.dat sd_scb,
fifo_bus.fifo fifo_bus,
input sd_clk_rising,
input sd_clk_falling,
inout [3:0] sd_dat
);
// Input and output data sampling
logic sd_dat_oe;
logic [3:0] sd_dat_out;
logic [3:0] sd_dat_in;
logic sd_dat_oe_data;
logic [3:0] sd_dat_data;
assign sd_dat = sd_dat_oe ? sd_dat_out : 4'hZ;
always_ff @(posedge clk) begin
sd_dat_oe <= sd_dat_oe_data;
sd_dat_out <= sd_dat_data;
sd_dat_in <= sd_dat;
end
always_ff @(posedge clk) begin
sd_scb.card_busy <= !sd_dat_in[0];
end
// FIFO
logic rx_full;
logic rx_almost_full;
logic rx_write;
logic [7:0] rx_wdata;
logic tx_empty;
logic tx_almost_empty;
logic tx_read;
logic [7:0] tx_rdata;
fifo_8kb fifo_8kb_rx_inst (
.clk(clk),
.reset(reset || sd_scb.dat_fifo_flush),
.empty(fifo_bus.rx_empty),
.almost_empty(fifo_bus.rx_almost_empty),
.read(fifo_bus.rx_read),
.rdata(fifo_bus.rx_rdata),
.full(rx_full),
.almost_full(rx_almost_full),
.write(rx_write),
.wdata(rx_wdata),
.count(sd_scb.rx_count)
);
fifo_8kb fifo_8kb_tx_inst (
.clk(clk),
.reset(reset || sd_scb.dat_fifo_flush),
.empty(tx_empty),
.almost_empty(tx_almost_empty),
.read(tx_read),
.rdata(tx_rdata),
.full(fifo_bus.tx_full),
.almost_full(fifo_bus.tx_almost_full),
.write(fifo_bus.tx_write),
.wdata(fifo_bus.tx_wdata),
.count(sd_scb.tx_count)
);
// DAT state
typedef enum bit [2:0] {
STATE_IDLE,
STATE_RX_WAIT,
STATE_RX,
STATE_TX_WAIT,
STATE_TX,
STATE_TX_STATUS_WAIT,
STATE_TX_STATUS
} e_state;
e_state state;
e_state next_state;
always_ff @(posedge clk) begin
if (reset || sd_scb.dat_stop) begin
state <= STATE_IDLE;
end else begin
state <= next_state;
end
end
assign sd_scb.dat_busy = (state != STATE_IDLE);
logic [10:0] counter;
logic [7:0] blocks_remaining;
always_comb begin
next_state = state;
case (state)
STATE_IDLE: begin
if (sd_scb.dat_start_read) begin
next_state = STATE_RX_WAIT;
end
if (sd_scb.dat_start_write) begin
next_state = STATE_TX_WAIT;
end
end
STATE_RX_WAIT: begin
if (sd_clk_rising) begin
if (!sd_dat_in[0]) begin
next_state = STATE_RX;
end
end
end
STATE_RX: begin
if (sd_clk_rising) begin
if (counter == 11'd1041) begin
if (blocks_remaining == 8'd0) begin
next_state = STATE_IDLE;
end else begin
next_state = STATE_RX_WAIT;
end
end
end
end
STATE_TX_WAIT: begin
if (sd_clk_falling) begin
if (sd_scb.tx_count >= 11'd512) begin
next_state = STATE_TX;
end
end
end
STATE_TX: begin
if (sd_clk_falling) begin
if (counter == 11'd1042) begin
next_state = STATE_TX_STATUS_WAIT;
end
end
end
STATE_TX_STATUS_WAIT: begin
if (sd_clk_rising) begin
if (counter == 11'd8) begin
next_state = STATE_IDLE;
end else if (!sd_dat_in[0]) begin
next_state = STATE_TX_STATUS;
end
end
end
STATE_TX_STATUS: begin
if (sd_clk_rising) begin
if (counter == 11'd5) begin
if (sd_dat_in[0]) begin
if (blocks_remaining == 8'd0) begin
next_state = STATE_IDLE;
end else begin
next_state = STATE_TX_WAIT;
end
end
end
end
end
endcase
end
// CRC16 units
logic crc_reset;
logic crc_enable;
logic crc_shift;
logic [3:0] crc_data;
logic [15:0] crc_result [0:3];
sd_crc_16 sd_crc_16_inst_0 (
.clk(clk),
.reset(crc_reset),
.enable(crc_enable),
.shift(crc_shift),
.data(crc_data[0]),
.result(crc_result[0])
);
sd_crc_16 sd_crc_16_inst_1 (
.clk(clk),
.reset(crc_reset),
.enable(crc_enable),
.shift(crc_shift),
.data(crc_data[1]),
.result(crc_result[1])
);
sd_crc_16 sd_crc_16_inst_2 (
.clk(clk),
.reset(crc_reset),
.enable(crc_enable),
.shift(crc_shift),
.data(crc_data[2]),
.result(crc_result[2])
);
sd_crc_16 sd_crc_16_inst_3 (
.clk(clk),
.reset(crc_reset),
.enable(crc_enable),
.shift(crc_shift),
.data(crc_data[3]),
.result(crc_result[3])
);
// Data shifting
logic [7:0] data_shift;
logic tx_rdata_valid;
assign crc_data = (state == STATE_RX) ? rx_wdata[3:0] : sd_dat_data;
always_comb begin
tx_read = (state == STATE_TX) && sd_clk_falling && (counter < 11'd1024) && (!counter[0]);
end
always_ff @(posedge clk) begin
rx_write <= 1'b0;
tx_rdata_valid <= tx_read;
crc_reset <= 1'b0;
crc_enable <= 1'b0;
crc_shift <= 1'b0;
if (reset || sd_scb.dat_stop) begin
sd_scb.clock_stop <= 1'b0;
sd_dat_oe_data <= 1'b0;
sd_dat_data <= 4'hF;
end else begin
case (state)
STATE_IDLE: begin
if (sd_scb.dat_start_read || sd_scb.dat_start_write) begin
sd_scb.dat_error <= 1'b0;
blocks_remaining <= sd_scb.dat_blocks;
end
end
STATE_RX_WAIT: begin
if (sd_scb.rx_count <= 11'd512) begin
sd_scb.clock_stop <= 1'b0;
end
if (sd_clk_rising) begin
if (!sd_dat_in[0]) begin
counter <= 11'd1;
crc_reset <= 1'b1;
end
end
end
STATE_RX: begin
if (sd_clk_rising) begin
counter <= counter + 1'd1;
rx_wdata <= {rx_wdata[3:0], sd_dat_in};
if (counter <= 11'd1024) begin
crc_enable <= 1'b1;
if (!counter[0]) begin
if (rx_full) begin
sd_scb.dat_error <= 1'b1;
end else begin
rx_write <= 1'b1;
end
end
end else begin
crc_shift <= 1'b1;
if ({crc_result[3][15], crc_result[2][15], crc_result[1][15], crc_result[0][15]} != sd_dat_in) begin
sd_scb.dat_error <= 1'b1;
end
end
if (counter == 11'd1041) begin
if ((blocks_remaining > 8'd0) && (sd_scb.rx_count > 11'd512)) begin
sd_scb.clock_stop <= 1'b1;
end
blocks_remaining <= blocks_remaining - 1'd1;
end
end
end
STATE_TX_WAIT: begin
if (sd_clk_falling) begin
if (sd_scb.tx_count >= 11'd512) begin
counter <= 11'd0;
end
end
end
STATE_TX: begin
if (sd_clk_falling) begin
counter <= counter + 1'd1;
if (counter == 11'd0) begin
crc_reset <= 1'b1;
sd_dat_oe_data <= 1'b1;
sd_dat_data <= 4'h0;
end else if (counter <= 11'd1024) begin
crc_enable <= 1'b1;
{sd_dat_data, data_shift} <= {data_shift, 4'h0};
end else begin
crc_shift <= 1'b1;
sd_dat_data <= {crc_result[3][15], crc_result[2][15], crc_result[1][15], crc_result[0][15]};
end
if (counter == 11'd1042) begin
sd_dat_oe_data <= 1'b0;
counter <= 11'd0;
end
end
end
STATE_TX_STATUS_WAIT: begin
if (sd_clk_rising) begin
counter <= counter + 1'd1;
if (counter == 11'd8) begin
sd_scb.dat_error <= 1'b1;
end else if (!sd_dat_in[0]) begin
counter <= 11'd1;
end
end
end
STATE_TX_STATUS: begin
if (sd_clk_rising) begin
if (counter < 11'd5) begin
counter <= counter + 1'd1;
end
if ((counter == 11'd1) && (sd_dat_in[0] != 1'b0)) begin
sd_scb.dat_error <= 1'b1;
end
if ((counter == 11'd2) && (sd_dat_in[0] != 1'b1)) begin
sd_scb.dat_error <= 1'b1;
end
if ((counter == 11'd3) && (sd_dat_in[0] != 1'b0)) begin
sd_scb.dat_error <= 1'b1;
end
if ((counter == 11'd4) && (sd_dat_in[0] != 1'b1)) begin
sd_scb.dat_error <= 1'b1;
end
if ((counter == 11'd5) && (sd_dat_in[0] == 1'b1)) begin
blocks_remaining <= blocks_remaining - 1'd1;
end
end
end
endcase
end
if (tx_rdata_valid) begin
data_shift <= tx_rdata;
end
end
endmodule

93
fw/rtl/sd/sd_scb.sv Normal file
View File

@ -0,0 +1,93 @@
interface sd_scb ();
logic [1:0] clock_mode;
logic clock_stop;
logic card_busy;
logic [10:0] rx_count;
logic [10:0] tx_count;
logic [5:0] cmd_index;
logic [31:0] cmd_arg;
logic [127:0] cmd_rsp;
logic cmd_start;
logic cmd_skip_response;
logic cmd_reserved_response;
logic cmd_long_response;
logic cmd_ignore_crc;
logic cmd_busy;
logic cmd_error;
logic dat_fifo_flush;
logic dat_start_write;
logic dat_start_read;
logic dat_stop;
logic [7:0] dat_blocks;
logic dat_busy;
logic dat_error;
modport controller (
output clock_mode,
input card_busy,
input rx_count,
input tx_count,
output cmd_index,
output cmd_arg,
input cmd_rsp,
output cmd_start,
output cmd_skip_response,
output cmd_reserved_response,
output cmd_long_response,
output cmd_ignore_crc,
input cmd_busy,
input cmd_error,
output dat_fifo_flush,
output dat_start_write,
output dat_start_read,
output dat_stop,
output dat_blocks,
input dat_busy,
input dat_error
);
modport clk (
input clock_mode,
input clock_stop
);
modport cmd (
input cmd_index,
input cmd_arg,
output cmd_rsp,
input cmd_start,
input cmd_skip_response,
input cmd_reserved_response,
input cmd_long_response,
input cmd_ignore_crc,
output cmd_busy,
output cmd_error
);
modport dat (
output clock_stop,
output card_busy,
output rx_count,
output tx_count,
input dat_fifo_flush,
input dat_start_write,
input dat_start_read,
input dat_stop,
input dat_blocks,
output dat_busy,
output dat_error
);
endinterface

55
fw/rtl/sd/sd_top.sv Normal file
View File

@ -0,0 +1,55 @@
module sd_top (
input clk,
input reset,
sd_scb sd_scb,
fifo_bus.fifo fifo_bus,
output sd_clk,
inout sd_cmd,
inout [3:0] sd_dat
);
logic sd_clk_rising;
logic sd_clk_falling;
sd_clk sd_clk_inst (
.clk(clk),
.reset(reset),
.sd_scb(sd_scb),
.sd_clk_rising(sd_clk_rising),
.sd_clk_falling(sd_clk_falling),
.sd_clk(sd_clk)
);
sd_cmd sd_cmd_inst (
.clk(clk),
.reset(reset),
.sd_scb(sd_scb),
.sd_clk_rising(sd_clk_rising),
.sd_clk_falling(sd_clk_falling),
.sd_cmd(sd_cmd)
);
sd_dat sd_dat_inst (
.clk(clk),
.reset(reset),
.sd_scb(sd_scb),
.fifo_bus(fifo_bus),
.sd_clk_rising(sd_clk_rising),
.sd_clk_falling(sd_clk_falling),
.sd_dat(sd_dat)
);
endmodule

View File

@ -1,67 +0,0 @@
interface if_config ();
logic cpu_ready;
logic cpu_busy;
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] ddipl_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 ddipl_offset,
input save_offset
);
modport flashram (
output flashram_read_mode
);
modport n64 (
input cpu_ready,
input cpu_busy,
input cmd_error,
output cmd_request,
output cmd,
output data,
input data_write,
input wdata
);
modport cpu (
output cpu_ready,
output cpu_busy,
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 ddipl_offset,
output save_offset
);
endinterface

View File

@ -1,45 +0,0 @@
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_FLASH,
ID_CPU_GPIO,
ID_CPU_I2C,
ID_CPU_USB,
ID_CPU_UART,
ID_CPU_DMA,
ID_CPU_CFG,
ID_CPU_SDRAM,
ID_CPU_FLASHRAM,
ID_CPU_SI,
ID_CPU_DD,
__ID_CPU_END
} e_cpu_id;
typedef enum bit [1:0] {
ID_DMA_USB,
ID_DMA_SD,
__ID_DMA_END
} e_dma_id;
parameter bit [31:0] SC64_VER = 32'h53437632;
parameter int CLOCK_FREQUENCY = 32'd100_000_000;
parameter bit [31:0] CPU_RESET_VECTOR = {4'(ID_CPU_FLASH), 28'h0035800};
parameter int UART_BAUD_RATE = 32'd1_000_000;
`ifdef DEBUG
parameter bit CPU_HAS_UART = 1'b1;
`else
parameter bit CPU_HAS_UART = 1'b0;
`endif
endpackage

View File

@ -1,62 +0,0 @@
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 [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)
);
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;
sys.n64_hard_reset = ~n64_reset_ff[1];
sys.n64_soft_reset = ~n64_nmi_ff[1];
end
endmodule

267
fw/rtl/top.sv Normal file
View File

@ -0,0 +1,267 @@
module top (
input inclk,
input n64_reset,
input n64_nmi,
output n64_irq,
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,
input usb_pwrsav,
output usb_clk,
output usb_cs,
input usb_miso,
inout [7:0] usb_miosi,
input sd_det,
output sd_clk,
inout sd_cmd,
inout [3:0] sd_dat,
output sdram_clk,
output sdram_cs,
output sdram_ras,
output sdram_cas,
output sdram_we,
output [1:0] sdram_ba,
output [12:0] sdram_a,
output [1:0] sdram_dqm,
inout [15:0] sdram_dq,
output flash_clk,
output flash_cs,
inout [3:0] flash_dq,
input button,
output mcu_int,
input mcu_clk,
input mcu_cs,
input mcu_mosi,
output mcu_miso
);
logic clk;
logic reset;
n64_scb n64_scb ();
dd_scb dd_scb ();
usb_scb usb_scb ();
dma_scb usb_dma_scb ();
sd_scb sd_scb ();
dma_scb sd_dma_scb ();
flash_scb flash_scb ();
vendor_scb vendor_scb ();
fifo_bus usb_cfg_fifo_bus ();
fifo_bus usb_dma_fifo_bus ();
fifo_bus usb_fifo_bus ();
fifo_bus sd_fifo_bus ();
mem_bus n64_mem_bus ();
mem_bus cfg_mem_bus ();
mem_bus usb_dma_mem_bus ();
mem_bus sd_dma_mem_bus ();
mem_bus sdram_mem_bus ();
mem_bus flash_mem_bus ();
mem_bus bram_mem_bus ();
pll pll_inst (
.inclk(inclk),
.clk(clk),
.sdram_clk(sdram_clk),
.reset(reset)
);
// MCU controller
mcu_top mcu_top_inst (
.clk(clk),
.reset(reset),
.n64_scb(n64_scb),
.dd_scb(dd_scb),
.usb_scb(usb_scb),
.usb_dma_scb(usb_dma_scb),
.sd_scb(sd_scb),
.sd_dma_scb(sd_dma_scb),
.flash_scb(flash_scb),
.vendor_scb(vendor_scb),
.fifo_bus(usb_cfg_fifo_bus),
.mem_bus(cfg_mem_bus),
.sd_det(sd_det),
.button(button),
.mcu_int(mcu_int),
.mcu_clk(mcu_clk),
.mcu_cs(mcu_cs),
.mcu_mosi(mcu_mosi),
.mcu_miso(mcu_miso)
);
// N64 controller
n64_top n64_top_inst (
.clk(clk),
.reset(reset),
.n64_scb(n64_scb),
.dd_scb(dd_scb),
.mem_bus(n64_mem_bus),
.n64_reset(n64_reset),
.n64_nmi(n64_nmi),
.n64_irq(n64_irq),
.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_clk(n64_si_clk),
.n64_si_dq(n64_si_dq)
);
// USB
usb_ft1248 usb_ft1248_inst (
.clk(clk),
.reset(reset),
.usb_scb(usb_scb),
.fifo_bus(usb_fifo_bus),
.usb_pwrsav(usb_pwrsav),
.usb_clk(usb_clk),
.usb_cs(usb_cs),
.usb_miso(usb_miso),
.usb_miosi(usb_miosi)
);
memory_dma memory_usb_dma_inst (
.clk(clk),
.reset(reset),
.dma_scb(usb_dma_scb),
.fifo_bus(usb_dma_fifo_bus),
.mem_bus(usb_dma_mem_bus)
);
fifo_junction usb_fifo_junction_inst (
.cfg_bus(usb_cfg_fifo_bus),
.dma_bus(usb_dma_fifo_bus),
.dev_bus(usb_fifo_bus)
);
// SD card
sd_top sd_top_inst (
.clk(clk),
.reset(reset),
.sd_scb(sd_scb),
.fifo_bus(sd_fifo_bus),
.sd_clk(sd_clk),
.sd_cmd(sd_cmd),
.sd_dat(sd_dat)
);
memory_dma memory_sd_dma_inst (
.clk(clk),
.reset(reset),
.dma_scb(sd_dma_scb),
.fifo_bus(sd_fifo_bus),
.mem_bus(sd_dma_mem_bus)
);
// Memory bus arbiter
memory_arbiter memory_arbiter_inst (
.clk(clk),
.reset(reset),
.n64_scb(n64_scb),
.n64_bus(n64_mem_bus),
.cfg_bus(cfg_mem_bus),
.usb_dma_bus(usb_dma_mem_bus),
.sd_dma_bus(sd_dma_mem_bus),
.sdram_mem_bus(sdram_mem_bus),
.flash_mem_bus(flash_mem_bus),
.bram_mem_bus(bram_mem_bus)
);
// Memory controllers
memory_sdram memory_sdram_inst (
.clk(clk),
.reset(reset),
.mem_bus(sdram_mem_bus),
.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_dqm(sdram_dqm),
.sdram_dq(sdram_dq)
);
memory_flash memory_flash_inst (
.clk(clk),
.reset(reset),
.flash_scb(flash_scb),
.mem_bus(flash_mem_bus),
.flash_clk(flash_clk),
.flash_cs(flash_cs),
.flash_dq(flash_dq)
);
memory_bram memory_bram_inst (
.clk(clk),
.n64_scb(n64_scb),
.mem_bus(bram_mem_bus)
);
// Vendor specific control
vendor vendor_inst (
.clk(clk),
.reset(reset),
.vendor_scb(vendor_scb)
);
endmodule

View File

@ -1,261 +1,356 @@
interface usb_scb ();
logic fifo_flush;
logic reset_pending;
logic reset_ack;
logic write_buffer_flush;
logic [10:0] rx_count;
logic [10:0] tx_count;
logic pwrsav;
logic reset_state;
modport controller (
output fifo_flush,
input reset_pending,
output reset_ack,
output write_buffer_flush,
input rx_count,
input tx_count,
input pwrsav,
input reset_state
);
modport usb (
input fifo_flush,
output reset_pending,
input reset_ack,
input write_buffer_flush,
output rx_count,
output tx_count,
output pwrsav,
output reset_state
);
endinterface
module usb_ft1248 (
if_system.sys sys,
input clk,
input reset,
input usb_enabled,
usb_scb.usb usb_scb,
output usb_clk,
output usb_cs,
fifo_bus.fifo fifo_bus,
input usb_pwrsav,
output logic usb_clk,
output logic usb_cs,
input usb_miso,
inout [3:0] usb_miosi,
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,
output rx_escape_valid,
input rx_escape_ack,
output [7:0] rx_escape
inout [7:0] usb_miosi
);
parameter bit [7:0] ESCAPE_CHARACTER = 8'h1B;
// FIFOs
logic rx_full;
logic rx_almost_full;
logic rx_write;
logic [7:0] rx_wdata;
logic tx_empty;
logic tx_almost_empty;
logic tx_read;
logic [7:0] tx_rdata;
logic rx_wdata_valid;
logic rx_escape_active;
fifo_8kb fifo_8kb_rx_inst (
.clk(clk),
.reset(reset || usb_scb.fifo_flush),
intel_fifo_8 fifo_8_rx_inst (
.clock(sys.clk),
.sclr(rx_flush || !usb_enabled),
.empty(rx_empty),
.rdreq(rx_read),
.q(rx_rdata),
.empty(fifo_bus.rx_empty),
.almost_empty(fifo_bus.rx_almost_empty),
.read(fifo_bus.rx_read),
.rdata(fifo_bus.rx_rdata),
.full(rx_full),
.wrreq(rx_write),
.data(rx_wdata)
.almost_full(rx_almost_full),
.write(rx_write),
.wdata(rx_wdata),
.count(usb_scb.rx_count)
);
intel_fifo_8 fifo_8_tx_inst (
.clock(sys.clk),
.sclr(tx_flush || !usb_enabled),
fifo_8kb fifo_8kb_tx_inst (
.clk(clk),
.reset(reset || usb_scb.fifo_flush),
.empty(tx_empty),
.rdreq(tx_read),
.q(tx_rdata),
.almost_empty(tx_almost_empty),
.read(tx_read),
.rdata(tx_rdata),
.full(tx_full),
.wrreq(tx_write),
.data(tx_wdata)
.full(fifo_bus.tx_full),
.almost_full(fifo_bus.tx_almost_full),
.write(fifo_bus.tx_write),
.wdata(fifo_bus.tx_wdata),
.count(usb_scb.tx_count)
);
logic [1:0] usb_pwrsav_ff;
logic [7:0] usb_miosi_out;
logic usb_oe;
// Escape character detection
logic ft_pwrsav;
logic ft_clk;
logic ft_cs;
logic ft_miso;
logic [7:0] ft_miosi_in;
logic [7:0] ft_miosi_out;
logic ft_oe;
always_comb begin
rx_write = 1'b0;
if (rx_wdata_valid) begin
rx_write = rx_escape_active ? rx_wdata == ESCAPE_CHARACTER : rx_wdata != ESCAPE_CHARACTER;
end
always_ff @(posedge clk) begin
usb_pwrsav_ff <= {usb_pwrsav_ff[0], usb_pwrsav};
ft_pwrsav <= usb_pwrsav_ff[1];
usb_clk <= ft_clk;
usb_cs <= ft_cs;
ft_miso <= usb_miso;
ft_miosi_in <= usb_miosi;
usb_miosi_out <= ft_miosi_out;
usb_oe <= ft_oe;
end
always_ff @(posedge sys.clk) begin
if (sys.reset || !usb_enabled) begin
rx_escape_valid <= 1'b0;
rx_escape_active <= 1'b0;
end else begin
if (rx_escape_ack) begin
rx_escape_valid <= 1'b0;
end
assign usb_miosi = usb_oe ? usb_miosi_out : 8'hZZ;
if (rx_wdata_valid) begin
if (!rx_escape_active) begin
if (rx_wdata == ESCAPE_CHARACTER) begin
rx_escape_active <= 1'b1;
end
end else begin
rx_escape_active <= 1'b0;
rx_escape <= rx_wdata;
if (rx_wdata != ESCAPE_CHARACTER) begin
rx_escape_valid <= 1'b1;
end
end
end
end
end
// FT1248 interface controller
typedef enum bit [1:0] {
S_TRY_RX,
S_TRY_TX,
S_COMMAND,
S_DATA
typedef enum bit [2:0] {
STATE_IDLE,
STATE_SELECT,
STATE_COMMAND,
STATE_STATUS,
STATE_DATA,
STATE_DESELECT
} e_state;
typedef enum bit [7:0] {
C_WRITE = 8'h00,
C_READ = 8'h04
} e_command;
typedef enum bit [1:0] {
P_PRE_RISING,
P_RISING,
P_PRE_FALLING,
P_FALLING
} e_clock_phase;
CMD_WRITE = 8'h00,
CMD_READ = 8'h40,
CMD_READ_MODEM_STATUS = 8'h20,
CMD_WRITE_MODEM_STATUS = 8'h60,
CMD_WRITE_BUFFER_FLUSH = 8'h08
} e_cmd;
e_state state;
e_state next_state;
e_cmd cmd;
e_cmd next_cmd;
logic [3:0] phase;
logic last_tx_failed;
logic reset_reply;
logic last_reset_status;
logic [4:0] modem_status_counter;
logic write_modem_status_pending;
logic write_buffer_flush_pending;
logic [3:0] clock_phase;
always_ff @(posedge clk) begin
state <= next_state;
cmd <= next_cmd;
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;
usb_scb.pwrsav <= !ft_pwrsav;
usb_scb.reset_state <= last_reset_status;
logic is_cmd_write;
logic [1:0] nibble_counter;
logic [7:0] tx_buffer;
phase <= {phase[2:0], phase[3]};
if (state == STATE_IDLE) begin
phase <= 4'b0100;
end
always_ff @(posedge sys.clk) begin
if (sys.reset || state == S_TRY_RX || state == S_TRY_TX) begin
clock_phase <= 4'b0001;
if (reset) begin
last_tx_failed <= 1'b0;
usb_scb.reset_pending <= 1'b0;
last_reset_status <= 1'b0;
modem_status_counter <= 5'd0;
write_modem_status_pending <= 1'b0;
write_buffer_flush_pending <= 1'b0;
end else begin
clock_phase <= {clock_phase[2:0], clock_phase[3]};
end
end
if (usb_scb.reset_ack) begin
usb_scb.reset_pending <= 1'b0;
reset_reply <= 1'b1;
write_modem_status_pending <= 1'b1;
end
always_ff @(posedge sys.clk) begin
usb_clk <= usb_clk_output;
usb_cs <= usb_cs_output;
if (usb_scb.write_buffer_flush) begin
write_buffer_flush_pending <= 1'b1;
end
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;
if (state == STATE_IDLE) begin
modem_status_counter <= modem_status_counter + 1'd1;
end
tx_buffer <= tx_rdata;
end
if ((state == STATE_DATA) && (cmd == CMD_WRITE) && phase[3]) begin
last_tx_failed <= ft_miso;
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];
if (!ft_miso && (state == STATE_DATA) && phase[3]) begin
if (cmd == CMD_READ_MODEM_STATUS) begin
last_reset_status <= ft_miosi_in[0];
if (!last_reset_status && ft_miosi_in[0]) begin
usb_scb.reset_pending <= 1'b1;
end
if (last_reset_status && !ft_miosi_in[0]) begin
reset_reply <= 1'b0;
write_modem_status_pending <= 1'b1;
end
end
if (cmd == CMD_WRITE_MODEM_STATUS) begin
write_modem_status_pending <= 1'b0;
end
if (cmd == CMD_WRITE_BUFFER_FLUSH) begin
write_buffer_flush_pending <= 1'b0;
end
usb_miosi_output_enable_data = nibble_counter < 2'd2;
end
S_DATA: begin
usb_clk_output = clock_phase[P_PRE_FALLING] || clock_phase[P_FALLING];
usb_cs_output = 1'b0;
usb_miosi_output_data = nibble_counter[0] ? tx_buffer[7:4] : tx_buffer[3:0];
usb_miosi_output_enable_data = is_cmd_write;
end
default: begin
usb_clk_output = 1'b0;
usb_cs_output = 1'b1;
usb_miosi_output_data = 4'hF;
usb_miosi_output_enable_data = 1'b0;
end
endcase
end
end
always_ff @(posedge sys.clk) begin
rx_wdata_valid <= 1'b0;
tx_read <= 1'b0;
always_comb begin
ft_clk = 1'b0;
ft_cs = 1'b1;
ft_miosi_out = 8'hFF;
ft_oe = 1'b0;
if (clock_phase[P_RISING]) begin
nibble_counter <= nibble_counter + 1'd1;
if (state == STATE_SELECT) begin
ft_cs = 1'b0;
end
if (sys.reset || !usb_enabled) begin
state <= S_TRY_RX;
if (state == STATE_COMMAND) begin
if (phase[0] || phase[1]) begin
ft_clk = 1'b1;
end
ft_cs = 1'b0;
ft_miosi_out = cmd;
ft_oe = 1'b1;
end
if (state == STATE_STATUS) begin
if (phase[0] || phase[1]) begin
ft_clk = 1'b1;
end
ft_cs = 1'b0;
end
if (state == STATE_DATA) begin
if (phase[0] || phase[1]) begin
ft_clk = 1'b1;
end
ft_cs = 1'b0;
if (cmd == CMD_WRITE) begin
ft_miosi_out = tx_rdata;
ft_oe = 1'b1;
end
if (cmd == CMD_WRITE_MODEM_STATUS) begin
ft_miosi_out = {2'b00, reset_reply, 5'b00000};
ft_oe = 1'b1;
end
end
end
always_comb begin
rx_write = 1'b0;
tx_read = 1'b0;
rx_wdata = ft_miosi_in;
if (!ft_miso && phase[3]) begin
case (state)
STATE_STATUS: begin
if (cmd == CMD_WRITE && !last_tx_failed) begin
tx_read = 1'b1;
end
end
STATE_DATA: begin
if (cmd == CMD_READ) begin
rx_write = 1'b1;
end
if (cmd == CMD_WRITE && !tx_empty) begin
tx_read = 1'b1;
end
end
endcase
end
end
always_comb begin
next_state = state;
next_cmd = cmd;
if (reset) begin
next_state = STATE_IDLE;
end else begin
case (state)
S_TRY_RX: begin
if (!rx_full && !rx_escape_valid) begin
state <= S_COMMAND;
is_cmd_write <= 1'b0;
nibble_counter <= 2'b11;
end else begin
state <= S_TRY_TX;
STATE_IDLE: begin
if (ft_pwrsav) begin
if (write_modem_status_pending) begin
next_state = STATE_SELECT;
next_cmd = CMD_WRITE_MODEM_STATUS;
end else if (&modem_status_counter) begin
next_state = STATE_SELECT;
next_cmd = CMD_READ_MODEM_STATUS;
end else if (!tx_empty || last_tx_failed) begin
next_state = STATE_SELECT;
next_cmd = CMD_WRITE;
end else if (write_buffer_flush_pending) begin
next_state = STATE_SELECT;
next_cmd = CMD_WRITE_BUFFER_FLUSH;
end else if (!rx_full) begin
next_state = STATE_SELECT;
next_cmd = CMD_READ;
end
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;
STATE_SELECT: begin
if (phase[3]) begin
next_state = STATE_COMMAND;
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;
STATE_COMMAND: begin
if (phase[3]) begin
next_state = STATE_STATUS;
end
end
STATE_STATUS: begin
if (phase[3]) begin
if (ft_miso) begin
next_state = STATE_DESELECT;
end else begin
next_state = STATE_DATA;
end
end
end
STATE_DATA: begin
if (phase[3]) begin
if (ft_miso) begin
next_state = STATE_DESELECT;
end else if (cmd == CMD_READ) begin
if (rx_almost_full) begin
next_state = STATE_DESELECT;
end
end else if (cmd == CMD_WRITE) begin
if (tx_empty) begin
next_state = STATE_DESELECT;
end
end else begin
next_state = STATE_DESELECT;
end
end
end
S_DATA: begin
if (clock_phase[P_FALLING]) begin
if (nibble_counter[0]) begin
tx_read <= is_cmd_write;
end
end
if (clock_phase[P_RISING]) begin
rx_wdata <= {usb_miosi_input, rx_wdata[7:4]};
if (nibble_counter[0]) begin
rx_wdata_valid <= !is_cmd_write;
end
if (usb_miso_input || (!is_cmd_write && (rx_full || rx_escape_valid)) || (is_cmd_write && tx_empty)) begin
state <= is_cmd_write ? S_TRY_RX : S_TRY_TX;
end
STATE_DESELECT: begin
if (phase[1]) begin
next_state = STATE_IDLE;
end
end
default: begin
state <= S_TRY_RX;
next_state = STATE_IDLE;
end
endcase
end

47
fw/rtl/vendor/lcmxo2/fifo_8kb.sv vendored Normal file
View File

@ -0,0 +1,47 @@
module fifo_8kb (
input clk,
input reset,
output empty,
output almost_empty,
input read,
output [7:0] rdata,
output full,
output almost_full,
input write,
input [7:0] wdata,
output logic [10:0] count
);
fifo_8kb_lattice_generated fifo_8kb_lattice_generated_inst (
.Data(wdata),
.WrClock(clk),
.RdClock(clk),
.WrEn(write),
.RdEn(read),
.Reset(reset),
.RPReset(reset),
.Q(rdata),
.Empty(empty),
.Full(full),
.AlmostEmpty(almost_empty),
.AlmostFull(almost_full)
);
always_ff @(posedge clk) begin
if (reset) begin
count <= 11'd0;
end else begin
if (write && read) begin
count <= count;
end else if (write) begin
count <= count + 1'd1;
end else if (read) begin
count <= count - 1'd1;
end
end
end
endmodule

View File

@ -0,0 +1,113 @@
/* Verilog netlist generated by SCUBA Diamond (64-bit) 3.12.1.454 */
/* Module Version: 1.2 */
/* C:\lscc\diamond\3.12\ispfpga\bin\nt64\scuba.exe -w -n efb_lattice_generated -lang verilog -synth synplify -bus_exp 7 -bb -type efb -arch xo2c00 -freq 100 -ufm -ufm_ebr 2038 -mem_size 8 -ufm_0 -wb -dev 7000 */
/* Sun Jul 31 17:59:17 2022 */
`timescale 1 ns / 1 ps
module efb_lattice_generated (wb_clk_i, wb_rst_i, wb_cyc_i, wb_stb_i,
wb_we_i, wb_adr_i, wb_dat_i, wb_dat_o, wb_ack_o, wbc_ufm_irq)/* synthesis NGD_DRC_MASK=1 */;
input wire wb_clk_i;
input wire wb_rst_i;
input wire wb_cyc_i;
input wire wb_stb_i;
input wire wb_we_i;
input wire [7:0] wb_adr_i;
input wire [7:0] wb_dat_i;
output wire [7:0] wb_dat_o;
output wire wb_ack_o;
output wire wbc_ufm_irq;
wire scuba_vhi;
wire scuba_vlo;
VHI scuba_vhi_inst (.Z(scuba_vhi));
VLO scuba_vlo_inst (.Z(scuba_vlo));
defparam EFBInst_0.UFM_INIT_FILE_FORMAT = "HEX" ;
defparam EFBInst_0.UFM_INIT_FILE_NAME = "NONE" ;
defparam EFBInst_0.UFM_INIT_ALL_ZEROS = "ENABLED" ;
defparam EFBInst_0.UFM_INIT_START_PAGE = 2038 ;
defparam EFBInst_0.UFM_INIT_PAGES = 8 ;
defparam EFBInst_0.DEV_DENSITY = "7000L" ;
defparam EFBInst_0.EFB_UFM = "ENABLED" ;
defparam EFBInst_0.TC_ICAPTURE = "DISABLED" ;
defparam EFBInst_0.TC_OVERFLOW = "DISABLED" ;
defparam EFBInst_0.TC_ICR_INT = "OFF" ;
defparam EFBInst_0.TC_OCR_INT = "OFF" ;
defparam EFBInst_0.TC_OV_INT = "OFF" ;
defparam EFBInst_0.TC_TOP_SEL = "OFF" ;
defparam EFBInst_0.TC_RESETN = "ENABLED" ;
defparam EFBInst_0.TC_OC_MODE = "TOGGLE" ;
defparam EFBInst_0.TC_OCR_SET = 32767 ;
defparam EFBInst_0.TC_TOP_SET = 65535 ;
defparam EFBInst_0.GSR = "ENABLED" ;
defparam EFBInst_0.TC_CCLK_SEL = 1 ;
defparam EFBInst_0.TC_MODE = "CTCM" ;
defparam EFBInst_0.TC_SCLK_SEL = "PCLOCK" ;
defparam EFBInst_0.EFB_TC_PORTMODE = "WB" ;
defparam EFBInst_0.EFB_TC = "DISABLED" ;
defparam EFBInst_0.SPI_WAKEUP = "DISABLED" ;
defparam EFBInst_0.SPI_INTR_RXOVR = "DISABLED" ;
defparam EFBInst_0.SPI_INTR_TXOVR = "DISABLED" ;
defparam EFBInst_0.SPI_INTR_RXRDY = "DISABLED" ;
defparam EFBInst_0.SPI_INTR_TXRDY = "DISABLED" ;
defparam EFBInst_0.SPI_SLAVE_HANDSHAKE = "DISABLED" ;
defparam EFBInst_0.SPI_PHASE_ADJ = "DISABLED" ;
defparam EFBInst_0.SPI_CLK_INV = "DISABLED" ;
defparam EFBInst_0.SPI_LSB_FIRST = "DISABLED" ;
defparam EFBInst_0.SPI_CLK_DIVIDER = 2 ;
defparam EFBInst_0.SPI_MODE = "MASTER" ;
defparam EFBInst_0.EFB_SPI = "DISABLED" ;
defparam EFBInst_0.I2C2_WAKEUP = "DISABLED" ;
defparam EFBInst_0.I2C2_GEN_CALL = "DISABLED" ;
defparam EFBInst_0.I2C2_CLK_DIVIDER = 1 ;
defparam EFBInst_0.I2C2_BUS_PERF = "100kHz" ;
defparam EFBInst_0.I2C2_SLAVE_ADDR = "0b1000010" ;
defparam EFBInst_0.I2C2_ADDRESSING = "7BIT" ;
defparam EFBInst_0.EFB_I2C2 = "DISABLED" ;
defparam EFBInst_0.I2C1_WAKEUP = "DISABLED" ;
defparam EFBInst_0.I2C1_GEN_CALL = "DISABLED" ;
defparam EFBInst_0.I2C1_CLK_DIVIDER = 1 ;
defparam EFBInst_0.I2C1_BUS_PERF = "100kHz" ;
defparam EFBInst_0.I2C1_SLAVE_ADDR = "0b1000001" ;
defparam EFBInst_0.I2C1_ADDRESSING = "7BIT" ;
defparam EFBInst_0.EFB_I2C1 = "DISABLED" ;
defparam EFBInst_0.EFB_WB_CLK_FREQ = "100.0" ;
EFB EFBInst_0 (.WBCLKI(wb_clk_i), .WBRSTI(wb_rst_i), .WBCYCI(wb_cyc_i),
.WBSTBI(wb_stb_i), .WBWEI(wb_we_i), .WBADRI7(wb_adr_i[7]), .WBADRI6(wb_adr_i[6]),
.WBADRI5(wb_adr_i[5]), .WBADRI4(wb_adr_i[4]), .WBADRI3(wb_adr_i[3]),
.WBADRI2(wb_adr_i[2]), .WBADRI1(wb_adr_i[1]), .WBADRI0(wb_adr_i[0]),
.WBDATI7(wb_dat_i[7]), .WBDATI6(wb_dat_i[6]), .WBDATI5(wb_dat_i[5]),
.WBDATI4(wb_dat_i[4]), .WBDATI3(wb_dat_i[3]), .WBDATI2(wb_dat_i[2]),
.WBDATI1(wb_dat_i[1]), .WBDATI0(wb_dat_i[0]), .PLL0DATI7(scuba_vlo),
.PLL0DATI6(scuba_vlo), .PLL0DATI5(scuba_vlo), .PLL0DATI4(scuba_vlo),
.PLL0DATI3(scuba_vlo), .PLL0DATI2(scuba_vlo), .PLL0DATI1(scuba_vlo),
.PLL0DATI0(scuba_vlo), .PLL0ACKI(scuba_vlo), .PLL1DATI7(scuba_vlo),
.PLL1DATI6(scuba_vlo), .PLL1DATI5(scuba_vlo), .PLL1DATI4(scuba_vlo),
.PLL1DATI3(scuba_vlo), .PLL1DATI2(scuba_vlo), .PLL1DATI1(scuba_vlo),
.PLL1DATI0(scuba_vlo), .PLL1ACKI(scuba_vlo), .I2C1SCLI(scuba_vlo),
.I2C1SDAI(scuba_vlo), .I2C2SCLI(scuba_vlo), .I2C2SDAI(scuba_vlo),
.SPISCKI(scuba_vlo), .SPIMISOI(scuba_vlo), .SPIMOSII(scuba_vlo),
.SPISCSN(scuba_vlo), .TCCLKI(scuba_vlo), .TCRSTN(scuba_vlo), .TCIC(scuba_vlo),
.UFMSN(scuba_vhi), .WBDATO7(wb_dat_o[7]), .WBDATO6(wb_dat_o[6]),
.WBDATO5(wb_dat_o[5]), .WBDATO4(wb_dat_o[4]), .WBDATO3(wb_dat_o[3]),
.WBDATO2(wb_dat_o[2]), .WBDATO1(wb_dat_o[1]), .WBDATO0(wb_dat_o[0]),
.WBACKO(wb_ack_o), .PLLCLKO(), .PLLRSTO(), .PLL0STBO(), .PLL1STBO(),
.PLLWEO(), .PLLADRO4(), .PLLADRO3(), .PLLADRO2(), .PLLADRO1(), .PLLADRO0(),
.PLLDATO7(), .PLLDATO6(), .PLLDATO5(), .PLLDATO4(), .PLLDATO3(),
.PLLDATO2(), .PLLDATO1(), .PLLDATO0(), .I2C1SCLO(), .I2C1SCLOEN(),
.I2C1SDAO(), .I2C1SDAOEN(), .I2C2SCLO(), .I2C2SCLOEN(), .I2C2SDAO(),
.I2C2SDAOEN(), .I2C1IRQO(), .I2C2IRQO(), .SPISCKO(), .SPISCKEN(),
.SPIMISOO(), .SPIMISOEN(), .SPIMOSIO(), .SPIMOSIEN(), .SPIMCSN7(),
.SPIMCSN6(), .SPIMCSN5(), .SPIMCSN4(), .SPIMCSN3(), .SPIMCSN2(),
.SPIMCSN1(), .SPIMCSN0(), .SPICSNEN(), .SPIIRQO(), .TCINT(), .TCOC(),
.WBCUFMIRQ(wbc_ufm_irq), .CFGWAKE(), .CFGSTDBY());
// exemplar begin
// exemplar end
endmodule

View File

@ -0,0 +1,66 @@
/* Verilog netlist generated by SCUBA Diamond (64-bit) 3.12.1.454 */
/* Module Version: 5.8 */
/* C:\lscc\diamond\3.12\ispfpga\bin\nt64\scuba.exe -w -n fifo_8kb_lattice_generated -lang verilog -synth synplify -bus_exp 7 -bb -arch xo2c00 -type ebfifo -depth 1024 -width 8 -rwidth 8 -no_enable -pe 1 -pf 1023 */
/* Sat Mar 19 13:53:20 2022 */
`timescale 1 ns / 1 ps
module fifo_8kb_lattice_generated (Data, WrClock, RdClock, WrEn, RdEn,
Reset, RPReset, Q, Empty, Full, AlmostEmpty, AlmostFull)/* synthesis NGD_DRC_MASK=1 */;
input wire [7:0] Data;
input wire WrClock;
input wire RdClock;
input wire WrEn;
input wire RdEn;
input wire Reset;
input wire RPReset;
output wire [7:0] Q;
output wire Empty;
output wire Full;
output wire AlmostEmpty;
output wire AlmostFull;
wire scuba_vhi;
wire Empty_int;
wire Full_int;
wire scuba_vlo;
VHI scuba_vhi_inst (.Z(scuba_vhi));
VLO scuba_vlo_inst (.Z(scuba_vlo));
defparam fifo_8kb_lattice_generated_0_0.FULLPOINTER1 = "0b01111111111000" ;
defparam fifo_8kb_lattice_generated_0_0.FULLPOINTER = "0b10000000000000" ;
defparam fifo_8kb_lattice_generated_0_0.AFPOINTER1 = "0b01111111110000" ;
defparam fifo_8kb_lattice_generated_0_0.AFPOINTER = "0b01111111111000" ;
defparam fifo_8kb_lattice_generated_0_0.AEPOINTER1 = "0b00000000010000" ;
defparam fifo_8kb_lattice_generated_0_0.AEPOINTER = "0b00000000001000" ;
defparam fifo_8kb_lattice_generated_0_0.ASYNC_RESET_RELEASE = "SYNC" ;
defparam fifo_8kb_lattice_generated_0_0.GSR = "DISABLED" ;
defparam fifo_8kb_lattice_generated_0_0.RESETMODE = "ASYNC" ;
defparam fifo_8kb_lattice_generated_0_0.REGMODE = "NOREG" ;
defparam fifo_8kb_lattice_generated_0_0.CSDECODE_R = "0b11" ;
defparam fifo_8kb_lattice_generated_0_0.CSDECODE_W = "0b11" ;
defparam fifo_8kb_lattice_generated_0_0.DATA_WIDTH_R = 9 ;
defparam fifo_8kb_lattice_generated_0_0.DATA_WIDTH_W = 9 ;
FIFO8KB fifo_8kb_lattice_generated_0_0 (.DI0(Data[0]), .DI1(Data[1]),
.DI2(Data[2]), .DI3(Data[3]), .DI4(Data[4]), .DI5(Data[5]), .DI6(Data[6]),
.DI7(Data[7]), .DI8(scuba_vlo), .DI9(scuba_vlo), .DI10(scuba_vlo),
.DI11(scuba_vlo), .DI12(scuba_vlo), .DI13(scuba_vlo), .DI14(scuba_vlo),
.DI15(scuba_vlo), .DI16(scuba_vlo), .DI17(scuba_vlo), .CSW0(scuba_vhi),
.CSW1(scuba_vhi), .CSR0(scuba_vhi), .CSR1(scuba_vhi), .FULLI(Full_int),
.EMPTYI(Empty_int), .WE(WrEn), .RE(RdEn), .ORE(RdEn), .CLKW(WrClock),
.CLKR(RdClock), .RST(Reset), .RPRST(RPReset), .DO0(Q[0]), .DO1(Q[1]),
.DO2(Q[2]), .DO3(Q[3]), .DO4(Q[4]), .DO5(Q[5]), .DO6(Q[6]), .DO7(Q[7]),
.DO8(), .DO9(), .DO10(), .DO11(), .DO12(), .DO13(), .DO14(), .DO15(),
.DO16(), .DO17(), .EF(Empty_int), .AEF(AlmostEmpty), .AFF(AlmostFull),
.FF(Full_int));
assign Empty = Empty_int;
assign Full = Full_int;
// exemplar begin
// exemplar end
endmodule

View File

@ -0,0 +1,98 @@
/* Verilog netlist generated by SCUBA Diamond (64-bit) 3.12.1.454 */
/* Module Version: 5.7 */
/* C:\lscc\diamond\3.12\ispfpga\bin\nt64\scuba.exe -w -n pll_lattice_generated -lang verilog -synth synplify -arch xo2c00 -type pll -fin 50 -fclkop 100 -fclkop_tol 0.0 -fclkos 100 -fclkos_tol 0.0 -trimp 0 -phasep 0 -trimp_r -trims 0 -phases 90 -trims_r -phase_cntl STATIC -fb_mode 1 -lock */
/* Sat Mar 19 17:10:12 2022 */
`timescale 1 ns / 1 ps
module pll_lattice_generated (CLKI, CLKOP, CLKOS, LOCK)/* synthesis NGD_DRC_MASK=1 */;
input wire CLKI;
output wire CLKOP;
output wire CLKOS;
output wire LOCK;
wire CLKOS_t;
wire CLKOP_t;
wire scuba_vlo;
VLO scuba_vlo_inst (.Z(scuba_vlo));
defparam PLLInst_0.DDRST_ENA = "DISABLED" ;
defparam PLLInst_0.DCRST_ENA = "DISABLED" ;
defparam PLLInst_0.MRST_ENA = "DISABLED" ;
defparam PLLInst_0.PLLRST_ENA = "DISABLED" ;
defparam PLLInst_0.INTFB_WAKE = "DISABLED" ;
defparam PLLInst_0.STDBY_ENABLE = "DISABLED" ;
defparam PLLInst_0.DPHASE_SOURCE = "DISABLED" ;
defparam PLLInst_0.PLL_USE_WB = "DISABLED" ;
defparam PLLInst_0.CLKOS3_FPHASE = 0 ;
defparam PLLInst_0.CLKOS3_CPHASE = 0 ;
defparam PLLInst_0.CLKOS2_FPHASE = 0 ;
defparam PLLInst_0.CLKOS2_CPHASE = 0 ;
defparam PLLInst_0.CLKOS_FPHASE = 2 ;
defparam PLLInst_0.CLKOS_CPHASE = 5 ;
defparam PLLInst_0.CLKOP_FPHASE = 0 ;
defparam PLLInst_0.CLKOP_CPHASE = 4 ;
defparam PLLInst_0.PLL_LOCK_MODE = 0 ;
defparam PLLInst_0.CLKOS_TRIM_DELAY = 0 ;
defparam PLLInst_0.CLKOS_TRIM_POL = "RISING" ;
defparam PLLInst_0.CLKOP_TRIM_DELAY = 0 ;
defparam PLLInst_0.CLKOP_TRIM_POL = "RISING" ;
defparam PLLInst_0.FRACN_DIV = 0 ;
defparam PLLInst_0.FRACN_ENABLE = "DISABLED" ;
defparam PLLInst_0.OUTDIVIDER_MUXD2 = "DIVD" ;
defparam PLLInst_0.PREDIVIDER_MUXD1 = 0 ;
defparam PLLInst_0.VCO_BYPASS_D0 = "DISABLED" ;
defparam PLLInst_0.CLKOS3_ENABLE = "DISABLED" ;
defparam PLLInst_0.OUTDIVIDER_MUXC2 = "DIVC" ;
defparam PLLInst_0.PREDIVIDER_MUXC1 = 0 ;
defparam PLLInst_0.VCO_BYPASS_C0 = "DISABLED" ;
defparam PLLInst_0.CLKOS2_ENABLE = "DISABLED" ;
defparam PLLInst_0.OUTDIVIDER_MUXB2 = "DIVB" ;
defparam PLLInst_0.PREDIVIDER_MUXB1 = 0 ;
defparam PLLInst_0.VCO_BYPASS_B0 = "DISABLED" ;
defparam PLLInst_0.CLKOS_ENABLE = "ENABLED" ;
defparam PLLInst_0.OUTDIVIDER_MUXA2 = "DIVA" ;
defparam PLLInst_0.PREDIVIDER_MUXA1 = 0 ;
defparam PLLInst_0.VCO_BYPASS_A0 = "DISABLED" ;
defparam PLLInst_0.CLKOP_ENABLE = "ENABLED" ;
defparam PLLInst_0.CLKOS3_DIV = 1 ;
defparam PLLInst_0.CLKOS2_DIV = 1 ;
defparam PLLInst_0.CLKOS_DIV = 5 ;
defparam PLLInst_0.CLKOP_DIV = 5 ;
defparam PLLInst_0.CLKFB_DIV = 2 ;
defparam PLLInst_0.CLKI_DIV = 1 ;
defparam PLLInst_0.FEEDBK_PATH = "CLKOP" ;
EHXPLLJ PLLInst_0 (.CLKI(CLKI), .CLKFB(CLKOP_t), .PHASESEL1(scuba_vlo),
.PHASESEL0(scuba_vlo), .PHASEDIR(scuba_vlo), .PHASESTEP(scuba_vlo),
.LOADREG(scuba_vlo), .STDBY(scuba_vlo), .PLLWAKESYNC(scuba_vlo),
.RST(scuba_vlo), .RESETM(scuba_vlo), .RESETC(scuba_vlo), .RESETD(scuba_vlo),
.ENCLKOP(scuba_vlo), .ENCLKOS(scuba_vlo), .ENCLKOS2(scuba_vlo),
.ENCLKOS3(scuba_vlo), .PLLCLK(scuba_vlo), .PLLRST(scuba_vlo), .PLLSTB(scuba_vlo),
.PLLWE(scuba_vlo), .PLLADDR4(scuba_vlo), .PLLADDR3(scuba_vlo), .PLLADDR2(scuba_vlo),
.PLLADDR1(scuba_vlo), .PLLADDR0(scuba_vlo), .PLLDATI7(scuba_vlo),
.PLLDATI6(scuba_vlo), .PLLDATI5(scuba_vlo), .PLLDATI4(scuba_vlo),
.PLLDATI3(scuba_vlo), .PLLDATI2(scuba_vlo), .PLLDATI1(scuba_vlo),
.PLLDATI0(scuba_vlo), .CLKOP(CLKOP_t), .CLKOS(CLKOS_t), .CLKOS2(),
.CLKOS3(), .LOCK(LOCK), .INTLOCK(), .REFCLK(), .CLKINTFB(), .DPHSRC(),
.PLLACK(), .PLLDATO7(), .PLLDATO6(), .PLLDATO5(), .PLLDATO4(), .PLLDATO3(),
.PLLDATO2(), .PLLDATO1(), .PLLDATO0())
/* synthesis FREQUENCY_PIN_CLKOS="100.000000" */
/* synthesis FREQUENCY_PIN_CLKOP="100.000000" */
/* synthesis FREQUENCY_PIN_CLKI="50.000000" */
/* synthesis ICP_CURRENT="9" */
/* synthesis LPF_RESISTOR="72" */;
assign CLKOS = CLKOS_t;
assign CLKOP = CLKOP_t;
// exemplar begin
// exemplar attribute PLLInst_0 FREQUENCY_PIN_CLKOS 100.000000
// exemplar attribute PLLInst_0 FREQUENCY_PIN_CLKOP 100.000000
// exemplar attribute PLLInst_0 FREQUENCY_PIN_CLKI 50.000000
// exemplar attribute PLLInst_0 ICP_CURRENT 9
// exemplar attribute PLLInst_0 LPF_RESISTOR 72
// exemplar end
endmodule

36
fw/rtl/vendor/lcmxo2/pll.sv vendored Normal file
View File

@ -0,0 +1,36 @@
module pll (
input inclk,
output logic reset,
output clk,
output sdram_clk
);
logic pll_sdram_clk;
logic buf_sdram_clk;
logic pll_lock;
pll_lattice_generated pll_lattice_generated_inst (
.CLKI(inclk),
.CLKOP(clk),
.CLKOS(pll_sdram_clk),
.LOCK(pll_lock)
);
ODDRXE oddrxe_sdram_clk_inst (
.D0(1'b0),
.D1(1'b1),
.SCLK(pll_sdram_clk),
.RST(1'b0),
.Q(buf_sdram_clk)
);
OB ob_sdram_clk_inst (
.I(buf_sdram_clk),
.O(sdram_clk)
) /* synthesis IO_TYPE="LVCMOS33" */;
always_ff @(posedge clk) begin
reset <= ~pll_lock;
end
endmodule

127
fw/rtl/vendor/lcmxo2/vendor.sv vendored Normal file
View File

@ -0,0 +1,127 @@
module vendor (
input clk,
input reset,
vendor_scb.vendor vendor_scb
);
logic start;
logic busy;
logic [1:0] length;
logic [5:0] delay;
logic request;
logic write;
logic ack;
logic [7:0] address;
logic [7:0] rdata;
logic [7:0] wdata;
logic [23:0] wdata_buffer;
logic ufm_irq;
always_comb begin
start = vendor_scb.control_valid && vendor_scb.control_wdata[0] && !busy;
vendor_scb.control_rdata = {
16'd0,
address,
4'b0000,
length,
write,
busy
};
end
always_ff @(posedge clk) begin
if (reset) begin
busy <= 1'b0;
end else begin
if (start) begin
busy <= 1'b1;
end
if (length == 2'd0 && ack) begin
busy <= 1'b0;
end
end
end
always_ff @(posedge clk) begin
if (start) begin
length <= vendor_scb.control_wdata[3:2];
end
if (ack && length > 2'd0) begin
length <= length - 1'd1;
end
end
always_ff @(posedge clk) begin
if (reset) begin
delay <= 6'd0;
end else begin
if (start && vendor_scb.control_wdata[4]) begin
delay <= 6'd35;
end
if (delay > 6'd0) begin
delay <= delay - 1'd1;
end
end
end
always_ff @(posedge clk) begin
if (reset) begin
request <= 1'b0;
end else begin
if (start) begin
request <= 1'b1;
end
if (busy && !request && delay == 6'd0) begin
request <= 1'b1;
end
if (ack) begin
request <= 1'b0;
end
end
end
always_ff @(posedge clk) begin
if (start) begin
write <= vendor_scb.control_wdata[1];
end
end
always_ff @(posedge clk) begin
if (start) begin
address <= vendor_scb.control_wdata[15:8];
end
end
always_ff @(posedge clk) begin
if (ack) begin
vendor_scb.data_rdata <= {vendor_scb.data_rdata[23:0], rdata};
end
end
always_ff @(posedge clk) begin
if (start) begin
{wdata, wdata_buffer} <= vendor_scb.data_wdata;
end
if (ack) begin
{wdata, wdata_buffer} <= {wdata_buffer, 8'h00};
end
end
efb_lattice_generated efb_lattice_generated_inst (
.wb_clk_i(clk),
.wb_rst_i(reset),
.wb_cyc_i(request),
.wb_stb_i(request),
.wb_we_i(write),
.wb_adr_i(address),
.wb_dat_i(wdata),
.wb_dat_o(rdata),
.wb_ack_o(ack),
.wbc_ufm_irq(ufm_irq)
);
endmodule

25
fw/rtl/vendor/vendor_scb.sv vendored Normal file
View File

@ -0,0 +1,25 @@
interface vendor_scb ();
logic control_valid;
logic [31:0] control_rdata;
logic [31:0] control_wdata;
logic [31:0] data_rdata;
logic [31:0] data_wdata;
modport controller (
output control_valid,
input control_rdata,
output control_wdata,
input data_rdata,
output data_wdata
);
modport vendor (
input control_valid,
output control_rdata,
input control_wdata,
output data_rdata,
input data_wdata
);
endinterface

View File

@ -1,6 +0,0 @@
set flow [lindex $quartus(args) 0]
if [string match "quartus_asm" $flow] {
post_message "Generating final programming file"
qexec "quartus_cpf -c SummerCart64.cof"
}

7
hw/.gitignore vendored
View File

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

View File

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

File diff suppressed because it is too large Load Diff

View File

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

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