mirror of
https://github.com/olofk/serv.git
synced 2025-04-24 05:47:17 -04:00
Compare commits
No commits in common. "main" and "1.2.0" have entirely different histories.
133 changed files with 1760 additions and 4548 deletions
80
.github/workflows/ci.yml
vendored
80
.github/workflows/ci.yml
vendored
|
@ -1,52 +1,74 @@
|
||||||
name: Run compliance test suite
|
name: CI
|
||||||
|
|
||||||
on: [push, pull_request]
|
on: [push, pull_request]
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
compliance:
|
compliance:
|
||||||
name: RISC-V Compliance Test
|
name: RISC-V Compliance Test
|
||||||
runs-on: ubuntu-22.04
|
runs-on: ubuntu-20.04
|
||||||
|
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
compressed: [0, 1]
|
||||||
|
csr: [0, 1]
|
||||||
|
mdu: [0, 1]
|
||||||
|
exclude:
|
||||||
|
# compressed requires csr for the cebreak test
|
||||||
|
- compressed: 1
|
||||||
|
csr : 0
|
||||||
|
include:
|
||||||
|
- mdu: 1
|
||||||
|
mduflag: "--flag=mdu"
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v2
|
||||||
with:
|
with:
|
||||||
path: serv
|
path: serv
|
||||||
|
|
||||||
- name: install fusesoc, verilator, gcc and riscof
|
- name: install fusesoc, verilator and gcc
|
||||||
run: |
|
run: |
|
||||||
sudo apt-get install -y python3-setuptools verilator
|
sudo apt-get install -y python3-setuptools verilator gcc-riscv64-unknown-elf
|
||||||
pip3 install fusesoc
|
pip3 install fusesoc
|
||||||
pip3 install riscof
|
|
||||||
wget -qO- https://github.com/riscv-collab/riscv-gnu-toolchain/releases/download/2023.07.05/riscv64-elf-ubuntu-22.04-gcc-nightly-2023.07.05-nightly.tar.gz | tar xz
|
|
||||||
echo $GITHUB_WORKSPACE/riscv/bin >> $GITHUB_PATH
|
|
||||||
|
|
||||||
|
|
||||||
- name: set root and SERV directory
|
- name: set SERV directory
|
||||||
run: |
|
run: echo "SERV=$GITHUB_WORKSPACE/serv" >> $GITHUB_ENV
|
||||||
echo "SERV=$GITHUB_WORKSPACE/serv" >> $GITHUB_ENV
|
|
||||||
|
|
||||||
- name: setup workspace
|
- name: setup workspace
|
||||||
run: fusesoc library add serv $SERV
|
run: fusesoc library add serv $SERV
|
||||||
|
|
||||||
- name: Setup SAIL-RISCV Model
|
- name: Add MDU core as a library
|
||||||
|
run: fusesoc library add mdu https://github.com/zeeshanrafique23/mdu
|
||||||
|
|
||||||
|
- name: build servant
|
||||||
|
run: fusesoc run --target=verilator_tb ${{ matrix.mduflag }} --build --build-root=servant_x servant --memsize=8388608 --align=1 --compressed=${{ matrix.compressed }} --with_csr=${{ matrix.csr }}
|
||||||
|
|
||||||
|
- name: download riscv-arch-test version 2.7.4
|
||||||
|
run: git clone https://github.com/riscv-non-isa/riscv-arch-test.git --branch 2.7.4
|
||||||
|
|
||||||
|
- name: run RV32 I compliance tests
|
||||||
run: |
|
run: |
|
||||||
tar -xzf $SERV/verif/bin/sail-riscv.tar.gz
|
cd $GITHUB_WORKSPACE/riscv-arch-test
|
||||||
echo $GITHUB_WORKSPACE/sail-riscv >> $GITHUB_PATH
|
make RISCV_PREFIX=riscv64-unknown-elf- TARGETDIR=$SERV/riscv-target RISCV_TARGET=serv RISCV_DEVICE=I TARGET_SIM=$GITHUB_WORKSPACE/servant_x/verilator_tb-verilator/Vservant_sim
|
||||||
|
|
||||||
- name: Init arch tests
|
- if: ${{ matrix.compressed }}
|
||||||
run: riscof arch-test --clone
|
name: run RV32 C compliance tests
|
||||||
|
run: |
|
||||||
|
cd $GITHUB_WORKSPACE/riscv-arch-test
|
||||||
|
make RISCV_PREFIX=riscv64-unknown-elf- TARGETDIR=$SERV/riscv-target RISCV_TARGET=serv RISCV_DEVICE=C TARGET_SIM=$GITHUB_WORKSPACE/servant_x/verilator_tb-verilator/Vservant_sim
|
||||||
|
|
||||||
- name: Run RV32I compliance tests
|
- if: ${{ matrix.mdu }}
|
||||||
run: riscof run --config=$SERV/verif/config.ini --suite=riscv-arch-test/riscv-test-suite/rv32i_m/I --env=riscv-arch-test/riscv-test-suite/env --no-browser
|
name: run RV32 M compliance tests
|
||||||
|
run: |
|
||||||
|
cd $GITHUB_WORKSPACE/riscv-arch-test
|
||||||
|
make RISCV_PREFIX=riscv64-unknown-elf- TARGETDIR=$SERV/riscv-target RISCV_TARGET=serv RISCV_DEVICE=M TARGET_SIM=$GITHUB_WORKSPACE/servant_x/verilator_tb-verilator/Vservant_sim
|
||||||
|
|
||||||
- name: Run RV32IM compliance tests
|
- name: run RV32 Zifencei compliance tests
|
||||||
run: riscof run --config=$SERV/verif/config.ini --suite=riscv-arch-test/riscv-test-suite/rv32i_m/M --env=riscv-arch-test/riscv-test-suite/env --no-browser
|
run: |
|
||||||
|
cd $GITHUB_WORKSPACE/riscv-arch-test
|
||||||
|
make RISCV_PREFIX=riscv64-unknown-elf- TARGETDIR=$SERV/riscv-target RISCV_TARGET=serv RISCV_DEVICE=Zifencei TARGET_SIM=$GITHUB_WORKSPACE/servant_x/verilator_tb-verilator/Vservant_sim
|
||||||
|
|
||||||
- name: Run RV32IC compliance tests
|
- if: ${{ matrix.csr }}
|
||||||
run: riscof run --config=$SERV/verif/config.ini --suite=riscv-arch-test/riscv-test-suite/rv32i_m/C --env=riscv-arch-test/riscv-test-suite/env --no-browser
|
name: run RV32 privilege compliance tests
|
||||||
|
run: |
|
||||||
- name: Run RV32I Zifencei compliance tests
|
cd $GITHUB_WORKSPACE/riscv-arch-test
|
||||||
run: riscof run --config=$SERV/verif/config.ini --suite=riscv-arch-test/riscv-test-suite/rv32i_m/Zifencei --env=riscv-arch-test/riscv-test-suite/env --no-browser
|
make RISCV_PREFIX=riscv64-unknown-elf- TARGETDIR=$SERV/riscv-target RISCV_TARGET=serv RISCV_DEVICE=privilege TARGET_SIM=$GITHUB_WORKSPACE/servant_x/verilator_tb-verilator/Vservant_sim
|
||||||
|
|
||||||
- name: Run RV32I Privilege compliance tests
|
|
||||||
run: riscof run --config=$SERV/verif/config.ini --suite=riscv-arch-test/riscv-test-suite/rv32i_m/privilege --env=riscv-arch-test/riscv-test-suite/env --no-browser
|
|
||||||
|
|
67
.github/workflows/formal.yml
vendored
67
.github/workflows/formal.yml
vendored
|
@ -1,67 +0,0 @@
|
||||||
name: Formal verification
|
|
||||||
|
|
||||||
on: [push]
|
|
||||||
jobs:
|
|
||||||
formal:
|
|
||||||
name: Run RISCV-formal verification suite
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Checkout riscv-formal
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
with:
|
|
||||||
repository: YosysHQ/riscv-formal
|
|
||||||
- name: Checkout SERV
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
with:
|
|
||||||
path: cores/serv/serv-src
|
|
||||||
- uses: YosysHQ/setup-oss-cad-suite@v3
|
|
||||||
with:
|
|
||||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
- name: Prepare formal tests
|
|
||||||
run: |
|
|
||||||
cd cores/serv
|
|
||||||
python3 ../../checks/genchecks.py
|
|
||||||
# Skip non-instruction tests for now
|
|
||||||
# - run: make -C cores/serv/checks causal_ch0
|
|
||||||
# - run: make -C cores/serv/checks liveness_ch0
|
|
||||||
# - run: make -C cores/serv/checks pc_bwd_ch0
|
|
||||||
# - run: make -C cores/serv/checks pc_fwd_ch0
|
|
||||||
# - run: make -C cores/serv/checks reg_ch0
|
|
||||||
# - run: make -C cores/serv/checks unique_ch0
|
|
||||||
- run: make -C cores/serv/checks insn_add_ch0
|
|
||||||
- run: make -C cores/serv/checks insn_addi_ch0
|
|
||||||
- run: make -C cores/serv/checks insn_and_ch0
|
|
||||||
- run: make -C cores/serv/checks insn_andi_ch0
|
|
||||||
- run: make -C cores/serv/checks insn_auipc_ch0
|
|
||||||
- run: make -C cores/serv/checks insn_beq_ch0
|
|
||||||
- run: make -C cores/serv/checks insn_bge_ch0
|
|
||||||
- run: make -C cores/serv/checks insn_bgeu_ch0
|
|
||||||
- run: make -C cores/serv/checks insn_blt_ch0
|
|
||||||
- run: make -C cores/serv/checks insn_bltu_ch0
|
|
||||||
- run: make -C cores/serv/checks insn_bne_ch0
|
|
||||||
- run: make -C cores/serv/checks insn_jal_ch0
|
|
||||||
- run: make -C cores/serv/checks insn_jalr_ch0
|
|
||||||
- run: make -C cores/serv/checks insn_lb_ch0
|
|
||||||
- run: make -C cores/serv/checks insn_lbu_ch0
|
|
||||||
- run: make -C cores/serv/checks insn_lh_ch0
|
|
||||||
- run: make -C cores/serv/checks insn_lhu_ch0
|
|
||||||
- run: make -C cores/serv/checks insn_lui_ch0
|
|
||||||
- run: make -C cores/serv/checks insn_lw_ch0
|
|
||||||
- run: make -C cores/serv/checks insn_or_ch0
|
|
||||||
- run: make -C cores/serv/checks insn_ori_ch0
|
|
||||||
- run: make -C cores/serv/checks insn_sb_ch0
|
|
||||||
- run: make -C cores/serv/checks insn_sh_ch0
|
|
||||||
- run: make -C cores/serv/checks insn_sll_ch0
|
|
||||||
- run: make -C cores/serv/checks insn_slli_ch0
|
|
||||||
- run: make -C cores/serv/checks insn_slt_ch0
|
|
||||||
- run: make -C cores/serv/checks insn_slti_ch0
|
|
||||||
- run: make -C cores/serv/checks insn_sltiu_ch0
|
|
||||||
- run: make -C cores/serv/checks insn_sltu_ch0
|
|
||||||
- run: make -C cores/serv/checks insn_sra_ch0
|
|
||||||
- run: make -C cores/serv/checks insn_srai_ch0
|
|
||||||
- run: make -C cores/serv/checks insn_srl_ch0
|
|
||||||
- run: make -C cores/serv/checks insn_srli_ch0
|
|
||||||
- run: make -C cores/serv/checks insn_sub_ch0
|
|
||||||
- run: make -C cores/serv/checks insn_sw_ch0
|
|
||||||
- run: make -C cores/serv/checks insn_xor_ch0
|
|
||||||
- run: make -C cores/serv/checks insn_xori_ch0
|
|
22
.github/workflows/lint.yml
vendored
22
.github/workflows/lint.yml
vendored
|
@ -1,22 +1,16 @@
|
||||||
name: Run linter
|
|
||||||
|
|
||||||
on: [push, pull_request]
|
on: [push, pull_request]
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
lint:
|
lint:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
name: Linter
|
name: Linter
|
||||||
env:
|
|
||||||
REPO : serv
|
|
||||||
VLNV : serv
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repo
|
- name: Checkout
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v1
|
||||||
|
- name: Lint Verilog source files with Verilator
|
||||||
|
uses: librecores/ci-fusesoc-action@main
|
||||||
with:
|
with:
|
||||||
path: serv
|
command: 'run'
|
||||||
- run: sudo apt install verilator
|
core: 'serv'
|
||||||
- run: pip3 install fusesoc
|
target: 'lint'
|
||||||
- run: fusesoc library add $REPO $GITHUB_WORKSPACE/$REPO
|
tool: 'verilator'
|
||||||
- run: fusesoc run --target=lint $VLNV
|
|
||||||
- run: fusesoc run --target=lint servant
|
|
||||||
- run: fusesoc run --target=lint serving
|
|
||||||
|
|
27
.github/workflows/openlane.yml
vendored
27
.github/workflows/openlane.yml
vendored
|
@ -1,24 +1,19 @@
|
||||||
name: Build GDS using OpenLANE and sky130 PDK
|
name: build-openlane-sky130
|
||||||
|
|
||||||
on: [push]
|
on: [push]
|
||||||
jobs:
|
jobs:
|
||||||
build-openlane-sky130:
|
build-openlane:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
env:
|
|
||||||
REPO : serv
|
|
||||||
VLNV : serv
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repo
|
- name: Checkout subservient
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v2
|
||||||
|
- name: Build with Openlane
|
||||||
|
uses: librecores/ci-fusesoc-action@migrate-dockerized
|
||||||
with:
|
with:
|
||||||
path: serv
|
core: serv
|
||||||
- run: echo "EDALIZE_LAUNCHER=el_docker" >> $GITHUB_ENV
|
target: sky130
|
||||||
- run: pip3 install fusesoc
|
tool: openlane
|
||||||
- run: fusesoc library add $REPO $GITHUB_WORKSPACE/$REPO
|
|
||||||
- run: fusesoc run --target=sky130 $VLNV
|
|
||||||
- run: find -name *.gds
|
|
||||||
- name: Store artifacts
|
- name: Store artifacts
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v2
|
||||||
with:
|
with:
|
||||||
name: serv.gds
|
name: serv.gds
|
||||||
path: /home/runner/work/serv/serv/serv/build/serv_1.3.0/sky130-openlane/runs/serv_synth_wrapper/results/final/gds/serv_synth_wrapper.gds
|
path: /home/runner/work/serv/serv/build/serv_1.1.0/sky130-openlane/gds/serv_synth_wrapper.gds
|
||||||
|
|
4
.github/workflows/pages.yml
vendored
4
.github/workflows/pages.yml
vendored
|
@ -1,5 +1,3 @@
|
||||||
name: Build documentation
|
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
|
@ -11,7 +9,7 @@ jobs:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v1
|
||||||
- name: Set up Python
|
- name: Set up Python
|
||||||
uses: actions/setup-python@v1
|
uses: actions/setup-python@v1
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
|
|
|
@ -1,16 +0,0 @@
|
||||||
# Read the Docs configuration file
|
|
||||||
# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details
|
|
||||||
|
|
||||||
version: 2
|
|
||||||
|
|
||||||
sphinx:
|
|
||||||
configuration: doc/conf.py
|
|
||||||
|
|
||||||
python:
|
|
||||||
install:
|
|
||||||
- requirements: doc/requirements.txt
|
|
||||||
|
|
||||||
build:
|
|
||||||
os: "ubuntu-22.04"
|
|
||||||
tools:
|
|
||||||
python: "3.11"
|
|
27
NEWS
27
NEWS
|
@ -1,32 +1,7 @@
|
||||||
1.3.0 2024-07-05 Olof Kindgren
|
|
||||||
======================================================
|
|
||||||
|
|
||||||
* Zephyr BSP: Port to Zephyr 3.5.0 + support tickless timer
|
|
||||||
* Make RF RAM IF work with single-port RAM
|
|
||||||
* Add PC tracing
|
|
||||||
* Make most modules width-independent
|
|
||||||
* Avoid releasing trap signal too early
|
|
||||||
* Improve timer wraparound behavior
|
|
||||||
* Overhaul documentation
|
|
||||||
* Add Servile convenience wrapper component
|
|
||||||
* Base Serving and Serving on Servile
|
|
||||||
* Add simulation cycle counter to testbench
|
|
||||||
* Add Hello world ASM example for Servant
|
|
||||||
* New Servant ports: Arty S7-50, PolarFire Splash Kit, Machdyne Kolibri, GMM-7550, Alchistry AU, ECP5 Evaluation board, Terasic DE1 SoC
|
|
||||||
|
|
||||||
1.2.1 2022-12-25 Olof Kindgren
|
|
||||||
======================================================
|
|
||||||
|
|
||||||
* Guarantee at least 2 cycles of o_rst after ice40 PLL is locked
|
|
||||||
* New Servant ports: ICE-V Wireless
|
|
||||||
* Add reset input for Arty A7
|
|
||||||
* Add Servant documentation
|
|
||||||
* Updated RISC-V Compliance support from 2.7.4 to 3.x
|
|
||||||
|
|
||||||
1.2.0 2022-07-25 Olof Kindgren
|
1.2.0 2022-07-25 Olof Kindgren
|
||||||
======================================================
|
======================================================
|
||||||
|
|
||||||
* New Servant ports: EBAZ4205, Chameleon96, Nexys2, Alinx AX309
|
* New Servant ports: EBAZ4205, Chameleion96, Nexys2, Alinx AX309
|
||||||
* Support for M ISA extension
|
* Support for M ISA extension
|
||||||
* Support for C ISA extension
|
* Support for C ISA extension
|
||||||
* Fix occasionally wrong sign on immediates
|
* Fix occasionally wrong sign on immediates
|
||||||
|
|
251
README.md
251
README.md
|
@ -2,103 +2,53 @@
|
||||||
|
|
||||||
# SERV
|
# SERV
|
||||||
|
|
||||||
|
[](https://www.librecores.org/olofk/serv)
|
||||||
[](https://gitter.im/librecores/serv?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
[](https://gitter.im/librecores/serv?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
||||||
[](https://github.com/olofk/serv/actions/workflows/ci.yml)
|
[](https://github.com/olofk/serv/actions?query=workflow%3ACI)
|
||||||
[](https://serv.readthedocs.io/en/latest/?badge=latest)
|
[](https://serv.readthedocs.io/en/latest/?badge=latest)
|
||||||
|
|
||||||
SERV is an award-winning bit-serial RISC-V core
|
SERV is an award-winning bit-serial RISC-V core
|
||||||
|
|
||||||
In fact, the award-winning SERV is the world's smallest RISC-V CPU. It's the perfect companion whenever you need a bit of computation and silicon real estate is at a premium.
|
|
||||||
|
|
||||||
How small is it then? Synthesizing the latest version of SERV in its most minimal form, yields the following results for some popular FPGA architectures and a typical CMOS process.
|
|
||||||
|
|
||||||
| Lattice iCE40 | Intel Cyclone 10LP | AMD Artix-7 | CMOS |
|
|
||||||
| ------------- | ------------------ | ----------- | ------ |
|
|
||||||
| 198 LUT | 239 LUT | 125 LUT | 2.1kGE |
|
|
||||||
| 164 FF | 164 FF | 164 FF | |
|
|
||||||
|
|
||||||
|
|
||||||
If you want to know more about SERV, what a bit-serial CPU is and what it's good for, I recommend starting out by watching the fantastic short SERV movies
|
If you want to know more about SERV, what a bit-serial CPU is and what it's good for, I recommend starting out by watching the fantastic short SERV movies
|
||||||
* [introduction to SERV](https://www.award-winning.me/serv-introduction/)
|
* [introduction to SERV](https://www.award-winning.me/serv-introduction/)
|
||||||
* [SERV : RISC-V for a fistful of gates](https://www.award-winning.me/serv-for-a-fistful-of-gates/)
|
* [SERV : RISC-V for a fistful of gates](https://www.award-winning.me/serv-for-a-fistful-of-gates/)
|
||||||
* [SERV: 32-bit is the New 8-bit](https://www.award-winning.me/serv-32-bit-is-the-new-8-bit/)
|
|
||||||
* [Bit by bit - How to fit 8 RISC V cores in a $38 FPGA board (presentation from the Zürich 2019 RISC-V workshop)](https://www.youtube.com/watch?v=xjIxORBRaeQ)
|
* [Bit by bit - How to fit 8 RISC V cores in a $38 FPGA board (presentation from the Zürich 2019 RISC-V workshop)](https://www.youtube.com/watch?v=xjIxORBRaeQ)
|
||||||
|
|
||||||
All SERV videos and more can also be found [here](https://www.award-winning.me/videos/).
|
There's also an official [SERV user manual](https://serv.readthedocs.io/en/latest/#) with fancy block diagrams, timing diagrams and an in-depth description of how some things work.
|
||||||
|
|
||||||
Apart from being the world's smallest RISC-V CPU, SERV also aims at being the best documented RISC-V CPU. For this there is an official [SERV user manual](https://serv.readthedocs.io/en/latest/#) with block diagrams that are correct to the gate-level, cycle-accurate timing diagrams and an in-depth description of how things work.
|
## Prerequisites
|
||||||
|
|
||||||
## Systems using SERV
|
Create a directory to keep all the different parts of the project together. We
|
||||||
|
will refer to this directory as `$WORKSPACE` from now on. All commands will be run from this directory unless otherwise stated.
|
||||||
|
|
||||||
SERV can be easily integrated into any design, but if you are looking at just quickly trying it out, here is a list of some systems that are already using SERV:
|
Install FuseSoC
|
||||||
|
|
||||||
[Servant](https://serv.readthedocs.io/en/latest/servant.html) is the reference platform for SERV. It is a very basic SoC that contains just enough runs Zephyr RTOS. Servant is intended for FPGAs and has been ported to around 20 different FPGA boards. It is also used to run the RISC-V regression test suite.
|
`pip install fusesoc`
|
||||||
|
|
||||||
[CoreScore](https://corescore.store/) is an award-giving benchmark for FPGAs and their synthesis/P&R tools. It tests how many SERV cores that can be put into a particular FPGA.
|
Add the FuseSoC standard library
|
||||||
|
|
||||||
[Observer](https://github.com/olofk/observer) is a configurable and software-programmable sensor aggregation platform for heterogeneous sensors.
|
`fusesoc library add fusesoc_cores https://github.com/fusesoc/fusesoc-cores`
|
||||||
|
|
||||||
[Subservient](https://github.com/olofk/subservient/) is a small technology-independent SERV-based SoC intended for ASIC implementations together with a single-port SRAM.
|
The FuseSoC standard library already contain a version of SERV, but if we want to make changes to SERV, run the bundled example or use the Zephyr support, it is better to add SERV as a separate library into the workspace
|
||||||
|
|
||||||
[Litex](https://github.com/enjoy-digital/litex) is a Python-based framework for creating FPGA SoCs. SERV is one of the 30+ supported cores. A Litex-generated SoC has been used to run DooM on SERV.
|
`fusesoc library add serv https://github.com/olofk/serv`
|
||||||
|
|
||||||
|
The SERV repo will now be available in $WORKSPACE/fusesoc_libraries/serv. To save some typing, we will refer to that directory as `$SERV`.
|
||||||
|
|
||||||
|
We are now ready to do our first exercises with SERV
|
||||||
|
|
||||||
|
If [Verilator](https://www.veripool.org/wiki/verilator) is installed, we can use that as a linter to check the SERV source code
|
||||||
|
|
||||||
## Getting started
|
`fusesoc run --target=lint serv`
|
||||||
|
|
||||||
:o: Create a root directory to keep all the different parts of the project together. We
|
|
||||||
will refer to this directory as `$WORKSPACE` from now on.
|
|
||||||
|
|
||||||
$ export WORKSPACE=$(pwd)
|
|
||||||
|
|
||||||
All the following commands will be run from this directory unless otherwise stated.
|
|
||||||
- Install FuseSoC
|
|
||||||
|
|
||||||
$ pip install fusesoc
|
|
||||||
- Add the FuseSoC standard library
|
|
||||||
|
|
||||||
$ fusesoc library add fusesoc_cores https://github.com/fusesoc/fusesoc-cores
|
|
||||||
- The FuseSoC standard library already contain a version of SERV, but if we want to make changes to SERV, run the bundled example or use the Zephyr support, it is better to add SERV as a separate library into the workspace
|
|
||||||
|
|
||||||
|
|
||||||
$ fusesoc library add serv https://github.com/olofk/serv
|
|
||||||
>:warning: The SERV repo will now be available in `$WORKSPACE/fusesoc_libraries/serv`. We will refer to that directory as `$SERV`.
|
|
||||||
- Install latest version of [Verilator](https://www.veripool.org/wiki/verilator)
|
|
||||||
- (Optional) To support RISC-V M-extension extension, Multiplication and Division unit (MDU) can be added included into the SERV as a separate library.
|
|
||||||
|
|
||||||
$ fusesoc library add mdu https://github.com/zeeshanrafique23/mdu
|
|
||||||
MDU will be available in `$WORKSPACE/fusesoc_libraries/mdu`
|
|
||||||
|
|
||||||
We are now ready to do our first exercises with SERV. If everything above is done correctly,we can use Verilator as a linter to check the SERV source code.
|
|
||||||
|
|
||||||
$ fusesoc run --target=lint serv
|
|
||||||
|
|
||||||
If everything worked, the output should look like
|
If everything worked, the output should look like
|
||||||
|
|
||||||
INFO: Preparing ::serv:1.3.0
|
INFO: Preparing ::serv:1.2.0
|
||||||
INFO: Setting up project
|
INFO: Setting up project
|
||||||
|
|
||||||
INFO: Building simulation model
|
INFO: Building simulation model
|
||||||
INFO: Running
|
INFO: Running
|
||||||
|
|
||||||
After performing all the steps that are mentioned above, the directory structure from the `$WORKSPACE` should look like this:
|
|
||||||
|
|
||||||
.
|
|
||||||
$WORKSPACE
|
|
||||||
|
|
|
||||||
├── build
|
|
||||||
│ └── ...
|
|
||||||
├── fusesoc.conf
|
|
||||||
└── fusesoc_libraries
|
|
||||||
├── fusesoc_cores
|
|
||||||
│ └── ...
|
|
||||||
├── mdu
|
|
||||||
│ └── ...
|
|
||||||
└── serv
|
|
||||||
└── ...
|
|
||||||
|
|
||||||
|
|
||||||
## Running pre-built test software
|
## Running pre-built test software
|
||||||
|
|
||||||
Build and run the single threaded zephyr hello world example with verilator (should be stopped with Ctrl-C):
|
Build and run the single threaded zephyr hello world example with verilator (should be stopped with Ctrl-C):
|
||||||
|
@ -122,19 +72,167 @@ For a more advanced example, we can also run the Dining philosophers demo
|
||||||
|
|
||||||
fusesoc run --target=verilator_tb servant --uart_baudrate=57600 --firmware=$SERV/sw/zephyr_sync.hex --memsize=16384
|
fusesoc run --target=verilator_tb servant --uart_baudrate=57600 --firmware=$SERV/sw/zephyr_sync.hex --memsize=16384
|
||||||
|
|
||||||
...or... the blinky example (note that the ```uart_baudrate``` should not be defined for the blinky test)
|
Other applications can be tested by compiling and converting to bin and then hex e.g. with makehex.py found in `$SERV/sw`
|
||||||
|
|
||||||
fusesoc run --target=verilator_tb servant --firmware=$SERV/sw/blinky.hex --memsize=16384
|
## Run RISC-V compliance tests
|
||||||
|
|
||||||
|
Build the verilator model (if not already done)
|
||||||
|
|
||||||
|
fusesoc run --target=verilator_tb --build servant --memsize=8388608
|
||||||
|
|
||||||
|
To build the verilator model with MDU (for M extension compliance tests):
|
||||||
|
|
||||||
|
fusesoc run --target=verilator_tb --flag=mdu --build servant --memsize=8388608
|
||||||
|
|
||||||
|
To build the verilator model with C extension (for Compressed extension compliance tests):
|
||||||
|
|
||||||
|
fusesoc run --target=verilator_tb --build servant --memsize=8388608 --compressed=1
|
||||||
|
|
||||||
|
Download the tests repo
|
||||||
|
|
||||||
|
git clone --branch 2.7.4 https://github.com/riscv-non-isa/riscv-arch-test.git
|
||||||
|
|
||||||
|
To run the RISC-V compliance tests, we need to supply the SERV-specific support files and point the test suite to where it can find a target to run (i.e. the previously built Verilator model)
|
||||||
|
|
||||||
|
Run the compliance tests
|
||||||
|
|
||||||
|
cd riscv-arch-test && make TARGETDIR=$SERV/riscv-target RISCV_TARGET=serv RISCV_DEVICE=I TARGET_SIM=$WORKSPACE/build/servant_1.2.0/verilator_tb-verilator/Vservant_sim
|
||||||
|
|
||||||
|
The above will run all tests in the rv32i test suite. Since SERV also implement the `M`, `C`, `privilege` and `Zifencei` extensions, these can also be tested by choosing any of them instead of `I` as the `RISCV_DEVICE` variable.
|
||||||
|
|
||||||
|
## Run on hardware
|
||||||
|
|
||||||
|
The servant SoC has been ported to an increasing number of different FPGA boards. To see all currently supported targets run
|
||||||
|
|
||||||
|
fusesoc core show servant
|
||||||
|
|
||||||
|
By default, these targets have the program memory preloaded with a small Zephyr hello world example that writes its output on a UART pin. Don't forget to install the appropriate toolchain (e.g. icestorm, Vivado, Quartus...) and add to your PATH
|
||||||
|
|
||||||
|
Some targets also depend on functionality in the FuseSoC base library (fusesoc-cores). Running `fusesoc library list` should tell you if fusesoc-cores is already available. If not, add it to your workspace with
|
||||||
|
|
||||||
|
fusesoc library add fusesoc-cores https://github.com/fusesoc/fusesoc-cores
|
||||||
|
|
||||||
|
Now we're ready to build. Note, for all the cases below, it's possible to run with `--memfile=$SERV/sw/blinky.hex`
|
||||||
|
(or any other suitable program) as the last argument to preload the LED blink example
|
||||||
|
instead of hello world.
|
||||||
|
|
||||||
|
### TinyFPGA BX
|
||||||
|
|
||||||
|
Pin A6 is used for UART output with 115200 baud rate.
|
||||||
|
|
||||||
|
fusesoc run --target=tinyfpga_bx servant
|
||||||
|
tinyprog --program build/servant_1.0.1/tinyfpga_bx-icestorm/servant_1.0.1.bin
|
||||||
|
|
||||||
|
### Icebreaker
|
||||||
|
|
||||||
|
Pin 9 is used for UART output with 57600 baud rate.
|
||||||
|
|
||||||
|
fusesoc run --target=icebreaker servant
|
||||||
|
|
||||||
|
### Nexys 2
|
||||||
|
|
||||||
|
Pmod pin JA1 is conntected to UART tx with 57600 baud rate. A USB to TTL connector is used to display to hello world message on the serial monitor.
|
||||||
|
(To use blinky.hex change L15 to J14 (led[0]) in data/nexys_2.ucf).
|
||||||
|
|
||||||
|
fusesoc run --target=nexys_2_500 servant --uart_baudrate=57600 --firmware=$SERV/sw/zephyr_hello.hex
|
||||||
|
|
||||||
|
|
||||||
|
### iCESugar
|
||||||
|
|
||||||
If the [toolchain](https://github.com/riscv-collab/riscv-gnu-toolchain) is installed, other applications can be tested by compiling the assembly program and converting to bin and then hex with makehex.py found in [`$SERV/sw`](/sw/).
|
Pin 6 is used for UART output with 115200 baud rate. Thanks to the onboard
|
||||||
|
debugger, you can just connect the USB Type-C connector to the PC, and a
|
||||||
|
serial console will show up.
|
||||||
|
|
||||||
:bulb:RISC-V Compressed Extension can be enabled by passing `--compressed=1` parameter.
|
fusesoc run --target=icesugar servant
|
||||||
|
|
||||||
## Verification
|
### OrangeCrab R0.2
|
||||||
SERV is verified using RISC-V compliance tests for the base ISA (RV32I) and the implemented extensions (M, C, Zicsr). The instructions on running Compliance tests using RISCOF framework are given in [verif](/verif/) directory.
|
|
||||||
|
|
||||||
|
Pin D1 is used for UART output with 115200 baud rate.
|
||||||
|
|
||||||
|
fusesoc run --target=orangecrab_r0.2 servant
|
||||||
|
dfu-util -d 1209:5af0 -D build/servant_1.2.0/orangecrab_r0.2-trellis/servant_1.2.0.bit
|
||||||
|
|
||||||
|
### Arty A7 35T
|
||||||
|
|
||||||
|
Pin D10 (uart_rxd_out) is used for UART output with 57600 baud rate (to use
|
||||||
|
blinky.hex change D10 to H5 (led[4]) in data/arty_a7_35t.xdc).
|
||||||
|
|
||||||
|
fusesoc run --target=arty_a7_35t servant
|
||||||
|
|
||||||
|
### Chameleon96 (Arrow 96 CV SoC Board)
|
||||||
|
|
||||||
|
FPGA Pin W14 (1V8, pin 5 low speed connector) is used for UART Tx output with 115200 baud rate. No reset key. Yellow Wifi led is q output.
|
||||||
|
|
||||||
|
fusesoc run --target=chameleon96 servant
|
||||||
|
|
||||||
|
### DE0 Nano
|
||||||
|
|
||||||
|
FPGA Pin D11 (Connector JP1, pin 38) is used for UART output with 57600 baud rate. DE0 Nano needs an external 3.3V UART to connect to this pin
|
||||||
|
|
||||||
|
fusesoc run --target=de0_nano servant
|
||||||
|
|
||||||
|
### DE10 Nano
|
||||||
|
|
||||||
|
FPGA Pin Y15 (Connector JP7, pin 1) is used for UART output with 57600 baud rate. DE10 Nano needs an external 3.3V UART to connect to this pin
|
||||||
|
|
||||||
|
fusesoc run --target=de10_nano servant
|
||||||
|
|
||||||
|
### DECA development kit
|
||||||
|
|
||||||
|
FPGA Pin W18 (Pin 3 P8 connector) is used for UART output with 57600 baud rate. Key 0 is reset and Led 0 q output.
|
||||||
|
|
||||||
|
fusesoc run --target=deca servant
|
||||||
|
|
||||||
|
### EBAZ4205 'Development' Board
|
||||||
|
|
||||||
|
Pin B20 is used for UART output with 57600 baud rate. To use `blinky.hex`
|
||||||
|
change B20 to W14 (red led) in `data/ebaz4205.xdc` file).
|
||||||
|
|
||||||
|
fusesoc run --target=ebaz4205 servant
|
||||||
|
|
||||||
|
fusesoc run --target=ebaz4205 servant --memfile=$SERV/sw/blinky.hex
|
||||||
|
|
||||||
|
Reference: https://github.com/fusesoc/blinky#ebaz4205-development-board
|
||||||
|
|
||||||
|
### SoCKit development kit
|
||||||
|
|
||||||
|
FPGA Pin F14 (HSTC GPIO addon connector J2, pin 2) is used for UART output with 57600 baud rate.
|
||||||
|
|
||||||
|
fusesoc run --target=sockit servant
|
||||||
|
|
||||||
|
### Saanlima Pipistrello (Spartan6 LX45)
|
||||||
|
|
||||||
|
Pin A10 (usb_data<1>) is used for UART output with 57600 baud rate (to use
|
||||||
|
blinky.hex change A10 to V16 (led[0]) in data/pipistrello.ucf).
|
||||||
|
|
||||||
|
fusesoc run --target=pipistrello servant
|
||||||
|
|
||||||
|
### Alhambra II
|
||||||
|
|
||||||
|
Pin 61 is used for UART output with 115200 baud rate. This pin is connected to a FT2232H chip in board, that manages the communications between the FPGA and the computer.
|
||||||
|
|
||||||
|
fusesoc run --target=alhambra servant
|
||||||
|
iceprog -d i:0x0403:0x6010:0 build/servant_1.0.1/alhambra-icestorm/servant_1.0.1.bin
|
||||||
|
|
||||||
|
### iCEstick
|
||||||
|
|
||||||
|
Pin 95 is used as the GPIO output which is connected to the board's green LED. Due to this board's limited Embedded BRAM, programs with a maximum of 7168 bytes can be loaded. The default program for this board is blinky.hex.
|
||||||
|
|
||||||
|
fusesoc run --target=icestick servant
|
||||||
|
iceprog build/servant_1.2.0/icestick-icestorm/servant_1.2.0.bin
|
||||||
|
|
||||||
|
### Nandland Go Board
|
||||||
|
|
||||||
|
Pin 56 is used as the GPIO output which is connected to the board's LED1. Due to this board's limited Embedded BRAM, programs with a maximum of 7168 bytes can be loaded. The default program for this board is blinky.hex.
|
||||||
|
|
||||||
|
fusesoc run --target=go_board servant
|
||||||
|
iceprog build/servant_1.2.0/go_board-icestorm/servant_1.2.0.bin
|
||||||
|
|
||||||
|
### Alinx ax309 (Spartan6 LX9)
|
||||||
|
|
||||||
|
Pin D12 (the on-board RS232 TX pin) is used for UART output with 115200 baud rate and wired to Pin P4 (LED0).
|
||||||
|
|
||||||
|
fusesoc run --target=ax309 servant
|
||||||
|
|
||||||
## Other targets
|
## Other targets
|
||||||
|
|
||||||
|
@ -158,7 +256,7 @@ This will synthesize for the default Vivado part. To synthesise for a specific d
|
||||||
|
|
||||||
SERV, or rather the Servant SoC, can run the [Zephyr RTOS](https://www.zephyrproject.org). The Servant-specific drivers and BSP is located in the zephyr subdirectory of the SERV repository. In order to use Zephyr on Servant, a project directory structure must be set up that allows Zephyr to load the Servant-specific files as a module.
|
SERV, or rather the Servant SoC, can run the [Zephyr RTOS](https://www.zephyrproject.org). The Servant-specific drivers and BSP is located in the zephyr subdirectory of the SERV repository. In order to use Zephyr on Servant, a project directory structure must be set up that allows Zephyr to load the Servant-specific files as a module.
|
||||||
|
|
||||||
First, the Zephyr SDK and the "west" build tool must be installed. The [Zephyr getting started guide](https://docs.zephyrproject.org/latest/getting_started/index.html) describes these steps in more detail.
|
First, the Zephyr SDK and the "west" build too must be installed. The [Zephyr getting started guide](https://docs.zephyrproject.org/latest/getting_started/index.html) describes these steps in more detail.
|
||||||
|
|
||||||
Assuming that SERV was installed into `$WORKSPACE/fusesoc_libraries/serv` as per the prerequisites, run the following command to make the workspace also work as a Zephyr workspace.
|
Assuming that SERV was installed into `$WORKSPACE/fusesoc_libraries/serv` as per the prerequisites, run the following command to make the workspace also work as a Zephyr workspace.
|
||||||
|
|
||||||
|
@ -198,3 +296,8 @@ Don't feed serv any illegal instructions after midnight. Many logic expressions
|
||||||
The bus interface is kind of Wishbone, but with most signals removed. There's an important difference though. Don't send acks on the instruction or data buses unless serv explicitly asks for something by raising its cyc signal. Otherwise serv becomes very confused.
|
The bus interface is kind of Wishbone, but with most signals removed. There's an important difference though. Don't send acks on the instruction or data buses unless serv explicitly asks for something by raising its cyc signal. Otherwise serv becomes very confused.
|
||||||
|
|
||||||
Don't go changing the clock frequency on a whim when running Zephyr. Or well, it's ok I guess, but since the UART is bitbanged, this will change the baud rate as well. As of writing, the UART is running at 115200 baud rate when the CPU is 32 MHz. There are two NOPs in the driver to slow it down a bit, so if those are removed I think it could achieve baud rate 115200 on a 24MHz clock.. in case someone wants to try
|
Don't go changing the clock frequency on a whim when running Zephyr. Or well, it's ok I guess, but since the UART is bitbanged, this will change the baud rate as well. As of writing, the UART is running at 115200 baud rate when the CPU is 32 MHz. There are two NOPs in the driver to slow it down a bit, so if those are removed I think it could achieve baud rate 115200 on a 24MHz clock.. in case someone wants to try
|
||||||
|
|
||||||
|
## TODO
|
||||||
|
|
||||||
|
- Applications have to be preloaded to RAM at compile-time
|
||||||
|
- Make it faster and smaller
|
||||||
|
|
|
@ -1,14 +1,11 @@
|
||||||
`default_nettype none
|
`default_nettype none
|
||||||
module servant_sim
|
module servant_sim
|
||||||
(input wire wb_clk,
|
(input wire wb_clk,
|
||||||
input wire wb_rst,
|
input wire wb_rst,
|
||||||
output wire [31:0] pc_adr,
|
output wire q);
|
||||||
output wire pc_vld,
|
|
||||||
output wire q);
|
|
||||||
|
|
||||||
parameter memfile = "";
|
parameter memfile = "";
|
||||||
parameter memsize = 8192;
|
parameter memsize = 8192;
|
||||||
parameter width = 1;
|
|
||||||
parameter with_csr = 1;
|
parameter with_csr = 1;
|
||||||
parameter compressed = 0;
|
parameter compressed = 0;
|
||||||
parameter align = compressed;
|
parameter align = compressed;
|
||||||
|
@ -23,15 +20,10 @@ module servant_sim
|
||||||
servant
|
servant
|
||||||
#(.memfile (memfile),
|
#(.memfile (memfile),
|
||||||
.memsize (memsize),
|
.memsize (memsize),
|
||||||
.width (width),
|
|
||||||
.debug (1'b1),
|
|
||||||
.sim (1),
|
.sim (1),
|
||||||
.with_csr (with_csr),
|
.with_csr (with_csr),
|
||||||
.compress (compressed[0:0]),
|
.compress (compressed[0:0]),
|
||||||
.align (align[0:0]))
|
.align (align[0:0]))
|
||||||
dut(wb_clk, wb_rst, q);
|
dut(wb_clk, wb_rst, q);
|
||||||
|
|
||||||
assign pc_adr = dut.wb_mem_adr;
|
|
||||||
assign pc_vld = dut.wb_mem_ack;
|
|
||||||
|
|
||||||
endmodule
|
endmodule
|
||||||
|
|
|
@ -1,12 +1,9 @@
|
||||||
#include <fcntl.h>
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
|
|
||||||
#include "verilated_vcd_c.h"
|
#include "verilated_vcd_c.h"
|
||||||
#include "Vservant_sim.h"
|
#include "Vservant_sim.h"
|
||||||
|
|
||||||
#include <ctime>
|
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
static bool done;
|
static bool done;
|
||||||
|
@ -113,11 +110,6 @@ int main(int argc, char **argv, char **env)
|
||||||
|
|
||||||
signal(SIGINT, INThandler);
|
signal(SIGINT, INThandler);
|
||||||
|
|
||||||
int tf = 0;
|
|
||||||
const char *arg_trace_pc = Verilated::commandArgsPlusMatch("trace_pc=");
|
|
||||||
if (arg_trace_pc[0])
|
|
||||||
tf = open("trace.bin", O_WRONLY | O_CREAT | O_TRUNC, S_IRWXU);
|
|
||||||
|
|
||||||
vluint64_t timeout = 0;
|
vluint64_t timeout = 0;
|
||||||
const char *arg_timeout = Verilated::commandArgsPlusMatch("timeout=");
|
const char *arg_timeout = Verilated::commandArgsPlusMatch("timeout=");
|
||||||
if (arg_timeout[0])
|
if (arg_timeout[0])
|
||||||
|
@ -128,14 +120,6 @@ int main(int argc, char **argv, char **env)
|
||||||
if (arg_vcd_start[0])
|
if (arg_vcd_start[0])
|
||||||
vcd_start = atoi(arg_vcd_start+11);
|
vcd_start = atoi(arg_vcd_start+11);
|
||||||
|
|
||||||
int cur_cycle = 0;
|
|
||||||
int last_cycle = 0;
|
|
||||||
std::time_t last_time = std::time(nullptr);
|
|
||||||
int cps_file = 0;
|
|
||||||
const char *arg_cps = Verilated::commandArgsPlusMatch("cps=");
|
|
||||||
if (arg_cps[0])
|
|
||||||
cps_file = open("cps", O_WRONLY | O_CREAT | O_TRUNC, S_IRWXU);
|
|
||||||
|
|
||||||
bool dump = false;
|
bool dump = false;
|
||||||
top->wb_clk = 1;
|
top->wb_clk = 1;
|
||||||
bool q = top->q;
|
bool q = top->q;
|
||||||
|
@ -153,8 +137,6 @@ int main(int argc, char **argv, char **env)
|
||||||
} else {
|
} else {
|
||||||
do_gpio(&gpio_context, top->q);
|
do_gpio(&gpio_context, top->q);
|
||||||
}
|
}
|
||||||
if (tf && top->wb_clk && top->pc_vld)
|
|
||||||
if (write(tf, (void *)&top->pc_adr, 4) < 0) exit(1);
|
|
||||||
if (timeout && (main_time >= timeout)) {
|
if (timeout && (main_time >= timeout)) {
|
||||||
printf("Timeout: Exiting at time %lu\n", main_time);
|
printf("Timeout: Exiting at time %lu\n", main_time);
|
||||||
done = true;
|
done = true;
|
||||||
|
@ -163,17 +145,7 @@ int main(int argc, char **argv, char **env)
|
||||||
top->wb_clk = !top->wb_clk;
|
top->wb_clk = !top->wb_clk;
|
||||||
main_time+=31.25;
|
main_time+=31.25;
|
||||||
|
|
||||||
if (cps_file) {
|
|
||||||
cur_cycle++;
|
|
||||||
if (std::time(nullptr) > last_time) {
|
|
||||||
dprintf(cps_file,"%d\n", (cur_cycle-last_cycle)/2);
|
|
||||||
last_cycle = cur_cycle;
|
|
||||||
last_time++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
close(cps_file);
|
|
||||||
close(tf);
|
|
||||||
if (tfp)
|
if (tfp)
|
||||||
tfp->close();
|
tfp->close();
|
||||||
exit(0);
|
exit(0);
|
||||||
|
|
|
@ -1,15 +1,10 @@
|
||||||
`default_nettype none
|
`default_nettype none
|
||||||
module servant_tb;
|
module servant_tb;
|
||||||
|
|
||||||
parameter memfile = "hello_uart.hex";
|
parameter memfile = "";
|
||||||
parameter memsize = 8192;
|
parameter memsize = 8192;
|
||||||
parameter width = 1;
|
|
||||||
parameter with_csr = 1;
|
parameter with_csr = 1;
|
||||||
|
|
||||||
localparam baud_rate =
|
|
||||||
(width == 4) ? 57600*3 :
|
|
||||||
57600;
|
|
||||||
|
|
||||||
reg wb_clk = 1'b0;
|
reg wb_clk = 1'b0;
|
||||||
reg wb_rst = 1'b1;
|
reg wb_rst = 1'b1;
|
||||||
|
|
||||||
|
@ -20,18 +15,12 @@ module servant_tb;
|
||||||
|
|
||||||
vlog_tb_utils vtu();
|
vlog_tb_utils vtu();
|
||||||
|
|
||||||
uart_decoder #(baud_rate) uart_decoder (q);
|
uart_decoder #(57600) uart_decoder (q);
|
||||||
|
|
||||||
servant_sim
|
servant_sim
|
||||||
#(.memfile (memfile),
|
#(.memfile (memfile),
|
||||||
.memsize (memsize),
|
.memsize (memsize),
|
||||||
.width (width),
|
|
||||||
.with_csr (with_csr))
|
.with_csr (with_csr))
|
||||||
dut
|
dut(wb_clk, wb_rst, q);
|
||||||
(.wb_clk (wb_clk),
|
|
||||||
.wb_rst (wb_rst),
|
|
||||||
.pc_adr (),
|
|
||||||
.pc_vld (),
|
|
||||||
.q (q));
|
|
||||||
|
|
||||||
endmodule
|
endmodule
|
||||||
|
|
|
@ -1,16 +0,0 @@
|
||||||
## Clock signal
|
|
||||||
set_property -dict { PACKAGE_PIN N14 IOSTANDARD LVCMOS33 } [get_ports i_clk];
|
|
||||||
create_clock -add -name sys_clk_pin -period 10.00 -waveform {0 5} [get_ports i_clk];
|
|
||||||
|
|
||||||
## Reset
|
|
||||||
set_property -dict {PACKAGE_PIN P6 IOSTANDARD LVCMOS33 } [get_ports i_rst_n];
|
|
||||||
|
|
||||||
## LED
|
|
||||||
## set_property -dict { PACKAGE_PIN L14 IOSTANDARD LVCMOS33 } [get_ports q];
|
|
||||||
|
|
||||||
## USB Serial output
|
|
||||||
set_property -dict { PACKAGE_PIN P16 IOSTANDARD LVCMOS33 } [get_ports q]
|
|
||||||
|
|
||||||
set_property CONFIG_VOLTAGE 3.3 [current_design]
|
|
||||||
set_property CFGBVS VCCO [current_design]
|
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
set_property -dict {PACKAGE_PIN E3 IOSTANDARD LVCMOS33 } [get_ports i_clk];
|
set_property -dict {PACKAGE_PIN E3 IOSTANDARD LVCMOS33 } [get_ports i_clk];
|
||||||
|
|
||||||
set_property -dict {PACKAGE_PIN C2 IOSTANDARD LVCMOS33 } [get_ports i_rst_n];
|
|
||||||
|
|
||||||
set_property -dict {PACKAGE_PIN D10 IOSTANDARD LVCMOS33 } [get_ports q]
|
set_property -dict {PACKAGE_PIN D10 IOSTANDARD LVCMOS33 } [get_ports q]
|
||||||
|
|
||||||
#set_property -dict {PACKAGE_PIN H5 IOSTANDARD LVCMOS33 } [get_ports q]
|
#set_property -dict {PACKAGE_PIN H5 IOSTANDARD LVCMOS33 } [get_ports q]
|
||||||
|
|
|
@ -1,10 +0,0 @@
|
||||||
set_property -dict { PACKAGE_PIN R2 IOSTANDARD SSTL135 } [get_ports i_clk]; #IO_L12P_T1_MRCC_34 Sch=ddr3_clk[200]
|
|
||||||
set_property -dict { PACKAGE_PIN C18 IOSTANDARD LVCMOS33 } [get_ports i_rst_n]; #IO_L11N_T1_SRCC_15
|
|
||||||
|
|
||||||
set_property -dict { PACKAGE_PIN R12 IOSTANDARD LVCMOS33 } [get_ports q]; #IO_25_14 Sch=uart_rxd_out
|
|
||||||
#set_property -dict { PACKAGE_PIN E18 IOSTANDARD LVCMOS33 } [get_ports q]; #IO_L16N_T2_A27_15 Sch=led[2]
|
|
||||||
|
|
||||||
set_property CFGBVS VCCO [current_design]
|
|
||||||
set_property CONFIG_VOLTAGE 3.3 [current_design]
|
|
||||||
|
|
||||||
create_clock -add -name sys_clk_pin -period 10.00 -waveform {0 5} [get_ports i_clk];
|
|
|
@ -7,10 +7,8 @@ set_property -dict { PACKAGE_PIN A17 IOSTANDARD LVCMOS33 } [get_ports { q }];
|
||||||
#set_property -dict { PACKAGE_PIN C16 IOSTANDARD LVCMOS33 } [get_ports { q }]; #IO_L13P_T2_MRCC_16 Sch=led[2]
|
#set_property -dict { PACKAGE_PIN C16 IOSTANDARD LVCMOS33 } [get_ports { q }]; #IO_L13P_T2_MRCC_16 Sch=led[2]
|
||||||
|
|
||||||
## UART
|
## UART
|
||||||
set_property -dict { PACKAGE_PIN J18 IOSTANDARD LVCMOS33 } [get_ports { o_uart_tx }]; #IO_L7N_T1_D10_14 Sch=uart_rxd_out
|
#set_property -dict { PACKAGE_PIN J18 IOSTANDARD LVCMOS33 } [get_ports { q }]; #IO_L7N_T1_D10_14 Sch=uart_rxd_out
|
||||||
#set_property -dict { PACKAGE_PIN J17 IOSTANDARD LVCMOS33 } [get_ports { q }]; #IO_L7P_T1_D09_14 Sch=uart_txd_in
|
#set_property -dict { PACKAGE_PIN J17 IOSTANDARD LVCMOS33 } [get_ports { q }]; #IO_L7P_T1_D09_14 Sch=uart_txd_in
|
||||||
|
|
||||||
set_property -dict { PACKAGE_PIN A18 IOSTANDARD LVCMOS33 } [get_ports { i_rst }]; #IO_L19N_T3_VREF_16 Sch=btn[0]
|
|
||||||
|
|
||||||
set_property CFGBVS VCCO [current_design]
|
set_property CFGBVS VCCO [current_design]
|
||||||
set_property CONFIG_VOLTAGE 3.3 [current_design]
|
set_property CONFIG_VOLTAGE 3.3 [current_design]
|
||||||
|
|
|
@ -1,8 +0,0 @@
|
||||||
# Main system clock (50 Mhz)
|
|
||||||
create_clock -name "clk" -period 20.000ns [get_ports {i_clk}]
|
|
||||||
|
|
||||||
# Automatically constrain PLL and other generated clocks
|
|
||||||
derive_pll_clocks -create_base_clocks
|
|
||||||
|
|
||||||
# Automatically calculate clock uncertainty to jitter and other effects.
|
|
||||||
derive_clock_uncertainty
|
|
|
@ -1,11 +0,0 @@
|
||||||
set_location_assignment PIN_AF14 -to i_clk
|
|
||||||
set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to i_clk
|
|
||||||
|
|
||||||
set_location_assignment PIN_AA14 -to i_rst_n
|
|
||||||
set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to i_rst_n
|
|
||||||
|
|
||||||
set_location_assignment PIN_V16 -to q
|
|
||||||
set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to q
|
|
||||||
|
|
||||||
set_location_assignment PIN_AC18 -to uart_txd
|
|
||||||
set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to uart*
|
|
|
@ -1,16 +0,0 @@
|
||||||
# 12MHz clock from FTDI FT2232H
|
|
||||||
LOCATE COMP "clk" SITE "A10";
|
|
||||||
IOBUF PORT "clk" IO_TYPE=LVCMOS33;
|
|
||||||
FREQUENCY PORT "clk" 12 MHZ;
|
|
||||||
|
|
||||||
# SW4 button
|
|
||||||
LOCATE COMP "nreset" SITE "P4";
|
|
||||||
IOBUF PORT "nreset" IO_TYPE=LVCMOS33;
|
|
||||||
|
|
||||||
# LED0
|
|
||||||
LOCATE COMP "led0" SITE "A13";
|
|
||||||
IOBUF PORT "led0" IO_TYPE=LVCMOS25;
|
|
||||||
|
|
||||||
# J40 Header Pin #1
|
|
||||||
LOCATE COMP "uart_txd" SITE "K2";
|
|
||||||
IOBUF PORT "uart_txd" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
|
|
|
@ -1,65 +0,0 @@
|
||||||
## GMM-7550 pins
|
|
||||||
|
|
||||||
# This file is a part of the GMM-7550 VHDL Examples
|
|
||||||
# <https://github.com/ak-fau/gmm7550-examples.git>
|
|
||||||
#
|
|
||||||
# SPDX-License-Identifier: MIT
|
|
||||||
#
|
|
||||||
# Copyright (c) 2023 Anton Kuzmin <anton.kuzmin@cs.fau.de>
|
|
||||||
|
|
||||||
# Master clock input (100 MHz)
|
|
||||||
Pin_in "ser_clk" Loc = "SER_CLK";
|
|
||||||
|
|
||||||
### SPI
|
|
||||||
|
|
||||||
Pin_inout "CFG_SPI_nCS" Loc = "IO_WA_A8";
|
|
||||||
Pin_inout "CFG_SPI_CLK" Loc = "IO_WA_B8";
|
|
||||||
Pin_inout "CFG_SPI_IO0" Loc = "IO_WA_B7"; # MOSI
|
|
||||||
Pin_inout "CFG_SPI_IO1" Loc = "IO_WA_A7"; # MISO
|
|
||||||
# Pin_inout "CFG_SPI_IO2" Loc = "IO_WA_B6"; # May be reused on the HAT for UART
|
|
||||||
# Pin_inout "CFG_SPI_IO3" Loc = "IO_WA_A6"; # May be reused on the HAT for UART
|
|
||||||
## HAT Adapter board
|
|
||||||
|
|
||||||
# This file is a part of the GMM-7550 VHDL Examples
|
|
||||||
# <https://github.com/ak-fau/gmm7550-examples.git>
|
|
||||||
#
|
|
||||||
# SPDX-License-Identifier: MIT
|
|
||||||
#
|
|
||||||
# Copyright (c) 2023 Anton Kuzmin <anton.kuzmin@cs.fau.de>
|
|
||||||
|
|
||||||
# D4 CFG_FAILED (Red)
|
|
||||||
Pin_out "led_red_n" Loc = "IO_WA_A2";
|
|
||||||
|
|
||||||
# D2 CFG_DONE (Green)
|
|
||||||
Pin_out "led_green" Loc = "IO_WA_B2";
|
|
||||||
|
|
||||||
### UART
|
|
||||||
|
|
||||||
Pin_out "uart_tx" Loc = "IO_WA_A6"; # SPI D3, GPIO pin 10
|
|
||||||
Pin_in "uart_rx" Loc = "IO_WA_B6"; # SPI D2, GPIO pin 8
|
|
||||||
|
|
||||||
### Pmod J10
|
|
||||||
|
|
||||||
Pin_out "J10_EN" Loc = "IO_SA_A7";
|
|
||||||
|
|
||||||
Pin_inout "J10_IO[0]" Loc = "IO_SA_A0";
|
|
||||||
Pin_inout "J10_IO[1]" Loc = "IO_SA_A1";
|
|
||||||
Pin_inout "J10_IO[2]" Loc = "IO_SA_A2";
|
|
||||||
Pin_inout "J10_IO[3]" Loc = "IO_SA_A3";
|
|
||||||
Pin_inout "J10_IO[4]" Loc = "IO_SA_B0";
|
|
||||||
Pin_inout "J10_IO[5]" Loc = "IO_SA_B1";
|
|
||||||
Pin_inout "J10_IO[6]" Loc = "IO_SA_B2";
|
|
||||||
Pin_inout "J10_IO[7]" Loc = "IO_SA_B3";
|
|
||||||
|
|
||||||
### Pmod J9
|
|
||||||
|
|
||||||
Pin_out "J9_EN" Loc = "IO_SB_B3";
|
|
||||||
|
|
||||||
Pin_inout "J9_IO[0]" Loc = "IO_SB_A6"; # CLK_2
|
|
||||||
Pin_inout "J9_IO[1]" Loc = "IO_SB_A7"; # CLK_1
|
|
||||||
Pin_inout "J9_IO[2]" Loc = "IO_SB_A8"; # CLK_0
|
|
||||||
Pin_inout "J9_IO[3]" Loc = "IO_SB_A5"; # CLK_3
|
|
||||||
Pin_inout "J9_IO[4]" Loc = "IO_SB_B6";
|
|
||||||
Pin_inout "J9_IO[5]" Loc = "IO_SB_B7";
|
|
||||||
Pin_inout "J9_IO[6]" Loc = "IO_SB_B8";
|
|
||||||
Pin_inout "J9_IO[7]" Loc = "IO_SB_B5";
|
|
|
@ -1,7 +0,0 @@
|
||||||
# 12 MHz clock
|
|
||||||
set_io i_clk 35
|
|
||||||
|
|
||||||
# RS232
|
|
||||||
set_io q 9
|
|
||||||
|
|
||||||
# use q 39 for red, q 40 for green, q 41 for blue LED
|
|
|
@ -1,4 +0,0 @@
|
||||||
set_io clk48 G1
|
|
||||||
set_io led B11
|
|
||||||
set_io tx B1
|
|
||||||
set_io rx B2
|
|
|
@ -1,8 +0,0 @@
|
||||||
# Main system clock (50 Mhz)
|
|
||||||
create_clock -name "clk" -period 20.000ns [get_ports {i_clk}]
|
|
||||||
|
|
||||||
# Automatically constrain PLL and other generated clocks
|
|
||||||
derive_pll_clocks -create_base_clocks
|
|
||||||
|
|
||||||
# Automatically calculate clock uncertainty to jitter and other effects.
|
|
||||||
derive_clock_uncertainty
|
|
|
@ -1,24 +0,0 @@
|
||||||
#MAX10_CLK2_50 3.3V
|
|
||||||
set_location_assignment PIN_27 -to i_clk
|
|
||||||
set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to i_clk
|
|
||||||
|
|
||||||
#LED[0]
|
|
||||||
set_location_assignment PIN_132 -to q
|
|
||||||
set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to q
|
|
||||||
|
|
||||||
#P8 3 ARDUINO_IO1
|
|
||||||
set_location_assignment PIN_75 -to uart_txd
|
|
||||||
set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to uart_txd
|
|
||||||
|
|
||||||
#KEY[0]
|
|
||||||
set_location_assignment PIN_121 -to i_rst_n
|
|
||||||
set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to i_rst_n
|
|
||||||
|
|
||||||
# Configuration mode that allows Memory Initialisation
|
|
||||||
set_global_assignment -name INTERNAL_FLASH_UPDATE_MODE "SINGLE IMAGE WITH ERAM"
|
|
||||||
|
|
||||||
# Generate SVF File for openFPGALoader
|
|
||||||
set_global_assignment -name GENERATE_SVF_FILE ON
|
|
||||||
# set_global_assignment -name GENERATE_JBC_FILE ON
|
|
||||||
set_global_assignment -name GENERATE_JAM_FILE ON
|
|
||||||
|
|
|
@ -1,11 +0,0 @@
|
||||||
set_io -port_name {i_clk} -DIRECTION INPUT -pin_name H7 -io_std LVCMOS18 -fixed true
|
|
||||||
set_io -port_name {resetb} -DIRECTION INPUT -pin_name N4 -io_std LVCMOS18 -fixed true
|
|
||||||
set_io -port_name {o_led1} -DIRECTION OUTPUT -pin_name P7 -io_std LVCMOS18 -fixed true
|
|
||||||
set_io -port_name {o_led2} -DIRECTION OUTPUT -pin_name P8 -io_std LVCMOS18 -fixed true
|
|
||||||
set_io -port_name {o_led3} -DIRECTION OUTPUT -pin_name N7 -io_std LVCMOS18 -fixed true
|
|
||||||
set_io -port_name {o_led4} -DIRECTION OUTPUT -pin_name N8 -io_std LVCMOS18 -fixed true
|
|
||||||
set_io -port_name {o_led5} -DIRECTION OUTPUT -pin_name N6 -io_std LVCMOS18 -fixed true
|
|
||||||
set_io -port_name {o_led6} -DIRECTION OUTPUT -pin_name N5 -io_std LVCMOS18 -fixed true
|
|
||||||
set_io -port_name {o_led7} -DIRECTION OUTPUT -pin_name M8 -io_std LVCMOS18 -fixed true
|
|
||||||
set_io -port_name {o_led8} -DIRECTION OUTPUT -pin_name M9 -io_std LVCMOS18 -fixed true
|
|
||||||
set_io -port_name {o_uart_tx} -DIRECTION OUTPUT -pin_name R4 -io_std LVCMOS18 -fixed true
|
|
|
@ -1,22 +0,0 @@
|
||||||
## Clock signal
|
|
||||||
set_property -dict { PACKAGE_PIN J3 IOSTANDARD LVCMOS18 } [get_ports i_clk];
|
|
||||||
create_clock -add -name sys_clk_pin -period 40.00 [get_ports i_clk];
|
|
||||||
|
|
||||||
## LED 0
|
|
||||||
set_property -dict { PACKAGE_PIN P1 IOSTANDARD LVCMOS18 } [get_ports o_led_0];
|
|
||||||
|
|
||||||
# PMOD A, Connector J5
|
|
||||||
# Connector pin, Package pin, PMOD type 4 UART
|
|
||||||
# 1, F8, CTS
|
|
||||||
# 2, F7, TXD
|
|
||||||
# 3, E6, RXD
|
|
||||||
# 4, E5, RTS
|
|
||||||
# 5, GND
|
|
||||||
# 6, VCC
|
|
||||||
# 7, G6,
|
|
||||||
# 8, G5,
|
|
||||||
# 9, C8,
|
|
||||||
# 10, C7,
|
|
||||||
# 11, GND
|
|
||||||
# 12, VCC
|
|
||||||
set_property -dict { PACKAGE_PIN F7 IOSTANDARD LVCMOS33 } [get_ports o_uart_tx]
|
|
|
@ -1,12 +1,14 @@
|
||||||
`verilator_config
|
`verilator_config
|
||||||
// Bits [1:0] in i_wb_rdt are not used at all
|
// Bits [1:0] in i_wb_rdt are not used at all
|
||||||
lint_off -rule UNUSED -file "*/serv_top.v" -lines 179
|
lint_off -rule UNUSED -file "*/serv_top.v" -lines 178
|
||||||
|
|
||||||
//Some bits in the instruction word are not used in serv_decode but it's easier
|
//Some bits in the instruction word are not used in serv_decode but it's easier
|
||||||
//to just send in the whole word than picking out bits
|
//to just send in the whole word than picking out bits
|
||||||
lint_off -rule UNUSED -file "*/serv_decode.v" -lines 8
|
lint_off -rule UNUSED -file "*/serv_decode.v" -lines 8
|
||||||
|
|
||||||
|
lint_off -rule UNUSED -file "*/serv_top.v" -lines 177
|
||||||
|
|
||||||
//Some variables are only used when we connect an Extension with serv_decode
|
//Some variables are only used when we connect an Extension with serv_decode
|
||||||
lint_off -rule UNUSED -file "*/serv_top.v" -lines 70
|
lint_off -rule UNUSED -file "*/serv_top.v" -lines 67
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,6 +0,0 @@
|
||||||
*********
|
|
||||||
Datasheet
|
|
||||||
*********
|
|
||||||
|
|
||||||
.. include:: overview.rst
|
|
||||||
.. include:: interface.rst
|
|
|
@ -1,13 +1,11 @@
|
||||||
################
|
|
||||||
SERV user manual
|
SERV user manual
|
||||||
################
|
================
|
||||||
|
|
||||||
Welcome to the user manual of the award-winning SERV, the world's smallest RISC-V CPU.
|
Welcome to the user manual of the award-winning SERV, the world's smallest RISC-V CPU.
|
||||||
|
|
||||||
.. toctree::
|
.. toctree::
|
||||||
:maxdepth: 4
|
:maxdepth: 3
|
||||||
:caption: Contents:
|
:caption: Contents:
|
||||||
|
|
||||||
datasheet.rst
|
interface.rst
|
||||||
internals.rst
|
modules.rst
|
||||||
reservoir.rst
|
|
||||||
|
|
|
@ -1,14 +1,11 @@
|
||||||
Interface
|
Interface
|
||||||
=========
|
=========
|
||||||
|
|
||||||
Top level
|
|
||||||
---------
|
|
||||||
|
|
||||||
Users of SERV can choose to use either serv_top or serv_rf_top depending on what best fits the application. serv_top contains all the main logic of SERV except for the actual storage for the register file (RF).
|
Users of SERV can choose to use either serv_top or serv_rf_top depending on what best fits the application. serv_top contains all the main logic of SERV except for the actual storage for the register file (RF).
|
||||||
|
|
||||||
.. image:: serv_top.png
|
.. image:: serv_top.png
|
||||||
|
|
||||||
serv_rf_top is a convenience wrapper that combines serv_top with a memory-based RF (serf_rf_ram) and an adapter between them (serv_rf_ram_if). This allows users to choose between a drop-in implementation when the memory-based RF is good enough or supply an alternative RF implementation, such as a shift-register based one or a combined SRAM for instruction/data memory and RF.
|
serv_rf_top is a convenience wrapper that combines serv_top with a memory-based RF (serf_rf_ram) and an adapter between them (serv_rf_ram_if). This allows users to choose between a drop-in implemenentation when the memory-based RF is good enough or supply an alternative RF implementation, such as a shift-register based one or a combined SRAM for instruction/data memory and RF.
|
||||||
|
|
||||||
.. image:: serv_rf_top.png
|
.. image:: serv_rf_top.png
|
||||||
|
|
||||||
|
@ -194,29 +191,3 @@ Signals
|
||||||
- 1
|
- 1
|
||||||
- in
|
- in
|
||||||
- RF interface channel 1 read data
|
- RF interface channel 1 read data
|
||||||
|
|
||||||
Extension interface
|
|
||||||
-------------------
|
|
||||||
|
|
||||||
The SERV CPU, being the smallest RISC-V CPU, has a design that is primarily focused on simplicity and minimalism. However, to increase its utility without complicating the core design, it can be extended using an extension interface. The extension interface allows additional functionality to be added to the SERV CPU core through custom accelerators that are called for when specific instructions are encountered. SERV has built-in support for connecting an MDU (Multiplication/Division Unit) that implements the M ISA extension by setting the MDU parameter. Other accelerators need changes to the decoder.
|
|
||||||
|
|
||||||
When SERV detects instructions to be executed by an external accelerator through the extension interface, it will treat them as :ref:`two-stage operations`. In stage 1, the values in `o_ext_rs1` and `o_ext_rs2` are prepared to be sent to the accelerator. Once stage 1 is completed, SERV will assert the corresponding valid signal for the accelerator (e.g. `o_mdu_valid` for the M extension accelerator). The accelerator can now perform its work and when it has completed its result it will return that value in `i_ext_rd` and strobe `i_ext_ready` for one cycle. The following cycle, SERV will start stage two and store the received result. The waveform below explains this in more detail.
|
|
||||||
|
|
||||||
.. wavedrom::
|
|
||||||
|
|
||||||
{ signal: [
|
|
||||||
{ name: "clk" , wave: "P...|...|...|..."},
|
|
||||||
{ name: "init" , wave: "1...|..0|...|...", node: ".......d..", data: "r0"},
|
|
||||||
{ name: "o_rf_wreq" , wave: "0...|...|10.|...", node: ".........g", data: "r1"},
|
|
||||||
{ name: "i_rf_ready" , wave: "010.|...|10.|...", node: ".a.......h.", data: "r1"},
|
|
||||||
{ name: "cnt_en" , wave: "0.1.|..0|.1.|..0", node: "..b.......i"},
|
|
||||||
{ name: "cnt_done" , wave: "0...|.10|...|.10", node: "......c.."},
|
|
||||||
{ name: "o_ext_rs1" , wave: ".234567x|...|...", node: "..", data: "d0 d1 ... d30 d31"},
|
|
||||||
{ name: "o_ext_rs2" , wave: ".234567x|...|...", node: "..", data: "d0 d1 ... d30 d31"},
|
|
||||||
{ name: "o_mdu_valid", wave: "0...|..1|.0.|...", node: ".......e", data: "0 1 ... 30 31"},
|
|
||||||
{ name: "i_ext_ready", wave: "0...|...|10.|...", node: ".........f", data: "0 1 ... 30 31"},
|
|
||||||
{ name: "i_ext_rd" , wave: "....|...|234567x", node: "..", data: "d0 d1 ... d30 d31"},
|
|
||||||
],
|
|
||||||
edge : [
|
|
||||||
"a~>b", "c~>d", "e~>f", "f~>g", "h~>i"]
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,5 +0,0 @@
|
||||||
*********
|
|
||||||
Internals
|
|
||||||
*********
|
|
||||||
|
|
||||||
.. include:: modules.rst
|
|
|
@ -1,7 +1,7 @@
|
||||||
Modules
|
Modules
|
||||||
-------
|
-------
|
||||||
|
|
||||||
SERV is a bit-serial CPU which means that the internal datapath is one bit wide. :ref:`dataflow` shows the internal dataflow. For each instruction, data is read from the register file or the immediate fields of the instruction word and the result of the operation is stored back into the register file. Reading and writing memory is handled through the memory interface module.
|
SERV is a bit-serial CPU which means that the internal datapath is one bit wide. :ref:`dataflow` show the internal dataflow. For each instruction, data is read from the register file or the immediate fields of the instruction word and the result of the operation is stored back into the register file. Reading and writing memory is handled through the memory interface module.
|
||||||
|
|
||||||
.. _dataflow:
|
.. _dataflow:
|
||||||
|
|
||||||
|
@ -28,7 +28,7 @@ serv_alu
|
||||||
|
|
||||||
serv_alu handles alu operations. The first input operand (A) comes from i_rs1 and the second operand (B) comes from i_rs2 or i_imm depending on the type of operation. The data passes through the add/sub or bool logic unit and finally ends up in o_rd to be written to the destination register. The output o_cmp is used for conditional branches to decide whether or not to take the branch.
|
serv_alu handles alu operations. The first input operand (A) comes from i_rs1 and the second operand (B) comes from i_rs2 or i_imm depending on the type of operation. The data passes through the add/sub or bool logic unit and finally ends up in o_rd to be written to the destination register. The output o_cmp is used for conditional branches to decide whether or not to take the branch.
|
||||||
|
|
||||||
The add/sub unit can do additions A+B or subtractions A-B by converting it to A+B̅+1. Subtraction mode (i_sub = 1) is also used for the comparisons in the slt* and conditional branch instructions. The +1 used in subtraction mode is done by preloading the carry input with 1. Less-than comparisons are handled by converting the expression A<B to A-B<0 and checking the MSB, which will be set when the result is less than 0. This however requires sign-extending the operands to 33-bit inputs. For signed operands (when i_cmp_sig is set), the extra bit is the same as the MSB. For unsigned, the extra bit is always 0. Because the ALU is only active for 32 cycles, the 33rd bit must be calculated in parallel to the ordinary addition. The result from this operations is available in result_lt. For equality checks, result_eq checks that all bits are 0 from the subtraction.
|
The add/sub unit can do additions A+B or subtractions A-B by converting it to A+B̅+1. Subtraction mode (i_sub = 1) is also used for the comparisions in the slt* and conditional branch instructions. The +1 used in subtraction mode is done by preloading the carry input with 1. Less-than comparisons are handled by converting the expression A<B to A-B<0 and checking the MSB, which will be set when the result is less than 0. This however requires sign-extending the operands to 33-bit inputs. For signed operands (when i_cmp_sig is set), the extra bit is the same as the MSB. For unsigned, the extra bit is always 0. Because the ALU is only active for 32 cycles, the 33rd bit must be calculated in parallel to the ordinary addition. The result from this operations is available in result_lt. For equality checks, result_eq checks that all bits are 0 from the subtraction.
|
||||||
|
|
||||||
.. image:: serv_alu_int.png
|
.. image:: serv_alu_int.png
|
||||||
|
|
||||||
|
@ -37,7 +37,7 @@ serv_bufreg
|
||||||
|
|
||||||
.. image:: serv_bufreg.png
|
.. image:: serv_bufreg.png
|
||||||
|
|
||||||
For two-stage operations, serv_bufreg holds data between stages. This data can be the effective address for branches or load/stores or data to be shifted for shift ops. It has a serial output for streaming out results during stage two and a parallel output that forms the dbus address. serv_bufreg also keeps track of the two lsb when calculating addresses. This is used to check for alignment errors. In order to support these different modes, the input to the shift register can come from rs1, the immediate (imm), rs1+imm or looped back from the shift register output. The latter is used for shift operations. For some operations, the LSB of the immediate is cleared before written to the shift register. The two LSB of the shift register are special. When the shift register is loaded, these two get written first before the rest of the register is filled up. This allows the memory interface to check data/address alignment early.
|
For two-stage operations, serv_bufreg holds data between stages. This data can be the effective address for branches or load/stores or data to be shifted for shift ops. It has a serial output for streaming out results during stage two and a parallel output that forms the dbus address. serv_bufreg also keeps track of the two lsb when calculating adresses. This is used to check for alignment errors. In order to support these different modes, the input to the shift register can come from rs1, the immediate (imm), rs1+imm or looped back from the shift register output. The latter is used for shift operations. For some operations, the LSB of the immediate is cleared before written to the shift register. The two LSB of the shift register are special. When the shift register is loaded, these two get written first before the rest of the register is filled up. This allows the memory interface to check data/address alignment early.
|
||||||
|
|
||||||
.. image:: serv_bufreg_int.png
|
.. image:: serv_bufreg_int.png
|
||||||
|
|
||||||
|
@ -46,7 +46,7 @@ serv_bufreg2
|
||||||
|
|
||||||
.. image:: serv_bufreg2.png
|
.. image:: serv_bufreg2.png
|
||||||
|
|
||||||
serv_bufreg2 is a 32-bit buffer register with some special features. It is used for shift operations to store the shift amount. It's used in load and store operations to store the data to be written or be read from the data bus, and it holds rs2 for the SERV extension interface. For shift and store operations, the register is shifted in from MSB when dat_en is asserted, while for loads and uses of the extension interface, the whole data word is written to when the i_load signal is asserted. Once the data is in the buffer, it is used differently depending on the operation. For stores and the extension interface the whole buffer is directly connected to the data bus as a 32-bit register. For load operations, the data is fed out serially once it has been fetched from the data bus. To better support load operations of varying sizes the buffer contains logic for reading out data serially from any of the byte LSBs of the 32-bit word. Finally, in shift mode, the 6 LSB of the register is used as a downcounter that is initialized during the init stage and then counts the remaining number of steps to shift the data and signals using sh_done and sh_done_r when finished.
|
serv_bugreg2 is a 32-bit buffer register with some special features. It is used for shift operations to store the shift amount. It's used in load and store operations to store the data to be written or be read from the data bus, and it holds rs2 for the SERV extension interface. For shift and store operations, the register is shifted in from MSB when dat_en is asserted, while for loads and uses of the extension interface, the whole data word is written to when the i_load signal is asserted. Once the data is in the buffer, it is used differently depending on the operation. For stores and the extension interface the whole buffer is directly connected to the data bus as a 32-bit register. For load operations, the data is fed out serially once it has been fetched from the data bus. To better support load operations of varying sizes the buffer contains logic for reading out data serially from any of the byte LSBs of the 32-bit word. Finally, in shift mode, the 6 LSB of the register is used as a downcounter that is initialized during the init stage and then counts the remaining number of steps to shift the data and signals using sh_done and sh_done_r when finished.
|
||||||
|
|
||||||
.. image:: serv_bufreg2_int.png
|
.. image:: serv_bufreg2_int.png
|
||||||
|
|
||||||
|
@ -64,7 +64,7 @@ serv_ctrl
|
||||||
|
|
||||||
.. image:: serv_ctrl.png
|
.. image:: serv_ctrl.png
|
||||||
|
|
||||||
serv_ctrl keeps track of the current PC and contains the logic needed to calculate the next PC. The PC is stored in shift register with a parallel output connected to the instruction bus.
|
serv_ctrl keeps track of the current PC and contains the logic needed to calculate the next PC. The PC is stored in shift register with a parellel output connected to the instruction bus.
|
||||||
|
|
||||||
The new PC can come from three sources. For normal instructions, it is incremented by four, which is the next 32-bit address. Jumps can be absolute or relative to the current PC. Absolute jumps are precalculated in serv_bufreg and written directly to the PC. PC relative jumps have the offset part precalculated in serv_bufreg which gets added to the current PC before storing as the new PC. The third source for the new PC comes from the CSR registers when entering or returning traps.
|
The new PC can come from three sources. For normal instructions, it is incremented by four, which is the next 32-bit address. Jumps can be absolute or relative to the current PC. Absolute jumps are precalculated in serv_bufreg and written directly to the PC. PC relative jumps have the offset part precalculated in serv_bufreg which gets added to the current PC before storing as the new PC. The third source for the new PC comes from the CSR registers when entering or returning traps.
|
||||||
|
|
||||||
|
@ -281,7 +281,7 @@ External timer interrupts and ecall/ebreak are also one-stage operations with so
|
||||||
Two-stage operations
|
Two-stage operations
|
||||||
::::::::::::::::::::
|
::::::::::::::::::::
|
||||||
|
|
||||||
Some operations need to be executed in two stages. In the first stage the operands are read out from the instruction immediate fields and the rs1/rs2 registers. In the second stage rd and the PC are updated with the results from the operation. The operation-specific things happen between the aforementioned stages. SERV has four types of four two-stage operations; memory, shift, slt and branch operations. In all cases the first stage is distinguished by having the init signal raised and only performing reads from the RF.
|
Some operations need to be executed in two stages. In the first stage the operands are read out from the instruction immediate fields and the rs1/rs2 registers. In the second stage rd and the PC are updated with the results from the operation. The operation-specific things happen between the aformentioned stages. SERV has four types of four two-stage operations; memory, shift, slt and branch operations. In all cases the first stage is distinguished by having the init signal raised and only performing reads from the RF.
|
||||||
|
|
||||||
.. wavedrom::
|
.. wavedrom::
|
||||||
|
|
||||||
|
|
|
@ -1,42 +0,0 @@
|
||||||
Overview
|
|
||||||
========
|
|
||||||
|
|
||||||
The SERV RISC-V CPU is an award-winning and highly compact processor core based on the RISC-V instruction set architecture (ISA). It is designed to be the smallest possible RISC-V compliant CPU and is particularly well-suited for embedded systems and applications where silicon area is critical.
|
|
||||||
|
|
||||||
Key Features
|
|
||||||
------------
|
|
||||||
|
|
||||||
* **ISA:** RISC-V RV32IZifencei
|
|
||||||
* **Optional ISA extensions:** C, M, Zicsr
|
|
||||||
* **Optional features:** Timer interrupts, Extension interface
|
|
||||||
* **Architecture:** Bit-serial (one bit processed per clock cycle)
|
|
||||||
* **License:** ISC (available under other commercial licenses upon request)
|
|
||||||
* **OS support:** Zephyr 3.7
|
|
||||||
* **SW support:** Compatible with standard RISC-V toolchains
|
|
||||||
* **Area:** Smallest RISC-V core available
|
|
||||||
|
|
||||||
Applications
|
|
||||||
------------
|
|
||||||
|
|
||||||
* **Embedded Systems:** Ideal for minimalistic embedded control tasks
|
|
||||||
* **IoT Devices:** Suitable for Internet of Things devices where space and power are limited
|
|
||||||
* **Education:** Excellent resource for teaching and understanding the RISC-V architecture and CPU design
|
|
||||||
* **Research:** Platform for research in minimalistic computing designs and for bringing up new fabrication processes
|
|
||||||
|
|
||||||
Area
|
|
||||||
----
|
|
||||||
|
|
||||||
.. list-table:: Area for minimal configuration [#]_
|
|
||||||
:widths: 25 25 25 25
|
|
||||||
:header-rows: 1
|
|
||||||
|
|
||||||
* - Lattice iCE40
|
|
||||||
- Altera Cyclone10LP
|
|
||||||
- AMD Artix-7
|
|
||||||
- CMOS
|
|
||||||
* - 198LUT/164FF
|
|
||||||
- 239LUT/164FF
|
|
||||||
- 125LUT/164FF
|
|
||||||
- 2.1kGE
|
|
||||||
|
|
||||||
.. [#] Excluding register file
|
|
|
@ -1,12 +0,0 @@
|
||||||
**************************
|
|
||||||
Building systems with SERV
|
|
||||||
**************************
|
|
||||||
|
|
||||||
A CPU is only as good as its ecosystem. In order to make use of SERV, it needs to be combined with other components such as memories, accelerators and peripheral controllers.
|
|
||||||
|
|
||||||
Welcome to the reservoir, a pool of ready-made designs and subsystems for different purposes that you can use to quickly get started with SERV or integrate it into larger designs.
|
|
||||||
|
|
||||||
.. include:: servile.rst
|
|
||||||
.. include:: serving.rst
|
|
||||||
.. include:: servant.rst
|
|
||||||
.. include:: subservient.rst
|
|
BIN
doc/servant.png
BIN
doc/servant.png
Binary file not shown.
Before Width: | Height: | Size: 8.7 KiB |
293
doc/servant.rst
293
doc/servant.rst
|
@ -1,293 +0,0 @@
|
||||||
Servant : FPGA Reference platform
|
|
||||||
=================================
|
|
||||||
|
|
||||||
.. figure:: servant.png
|
|
||||||
|
|
||||||
Servant FPGA Reference platform
|
|
||||||
|
|
||||||
SERV comes with a small FPGA-focused reference platform called Servant, which is capable of running Zephyr RTOS, the regression test suite and other software. The platform consists of SERV, a timer, memory and a 1-bit GPIO output pin.
|
|
||||||
|
|
||||||
Available targets
|
|
||||||
-----------------
|
|
||||||
|
|
||||||
The servant SoC has been ported to an increasing number of different FPGA boards and is easy to modify for new targets. To see all currently supported targets run:
|
|
||||||
|
|
||||||
fusesoc core show servant
|
|
||||||
|
|
||||||
By default, these targets have the program memory preloaded with a small Zephyr hello world example that writes its output on a UART pin. Don't forget to install the appropriate toolchain (e.g. icestorm, Vivado, Quartus...) and add to your PATH
|
|
||||||
|
|
||||||
Some targets also depend on functionality in the FuseSoC base library (fusesoc-cores). Running `fusesoc library list` should tell you if fusesoc-cores is already available. If not, add it to your workspace with
|
|
||||||
|
|
||||||
fusesoc library add fusesoc-cores https://github.com/fusesoc/fusesoc-cores
|
|
||||||
|
|
||||||
Now we're ready to build. Note, for all the cases below, it's possible to run with `--memfile=$SERV/sw/blinky.hex`
|
|
||||||
(or any other suitable program) as the last argument to preload the LED blink example
|
|
||||||
instead of hello world.
|
|
||||||
|
|
||||||
AC701
|
|
||||||
^^^^^
|
|
||||||
|
|
||||||
fusesoc run --target=ac701 servant
|
|
||||||
|
|
||||||
Alchistry AU
|
|
||||||
^^^^^^^^^^^^
|
|
||||||
|
|
||||||
fusesoc run --target=alchistry_au servant
|
|
||||||
|
|
||||||
|
|
||||||
Alhambra II
|
|
||||||
^^^^^^^^^^^
|
|
||||||
|
|
||||||
Pin 61 is used for UART output with 115200 baud rate. This pin is connected to a FT2232H chip in board, that manages the communications between the FPGA and the computer.
|
|
||||||
|
|
||||||
fusesoc run --target=alhambra servant
|
|
||||||
iceprog -d i:0x0403:0x6010:0 build/servant_1.0.1/alhambra-icestorm/servant_1.0.1.bin
|
|
||||||
|
|
||||||
Alinx ax309 (Spartan6 LX9)
|
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
|
|
||||||
Pin D12 (the on-board RS232 TX pin) is used for UART output with 115200 baud rate and wired to Pin P4 (LED0).
|
|
||||||
|
|
||||||
fusesoc run --target=ax309 servant
|
|
||||||
|
|
||||||
Arty A7 35T
|
|
||||||
^^^^^^^^^^^
|
|
||||||
|
|
||||||
Pin D10 (uart_rxd_out) is used for UART output with 57600 baud rate (to use
|
|
||||||
blinky.hex change D10 to H5 (led[4]) in data/arty_a7_35t.xdc).
|
|
||||||
|
|
||||||
fusesoc run --target=arty_a7_35t servant
|
|
||||||
|
|
||||||
Arty S7 50T
|
|
||||||
^^^^^^^^^^^
|
|
||||||
|
|
||||||
Pin R12 (uart_rxd_out) is used for UART output with 57600 baud rate (to use
|
|
||||||
blinky.hex change R12 to E18 (led[4]) in data/arty_s7_50t.xdc).
|
|
||||||
|
|
||||||
fusesoc run --target=arty_s7_50t servant
|
|
||||||
|
|
||||||
Chameleon96 (Arrow 96 CV SoC Board)
|
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
|
|
||||||
FPGA Pin W14 (1V8, pin 5 low speed connector) is used for UART Tx output with 115200 baud rate. No reset key. Yellow Wifi led is q output.
|
|
||||||
|
|
||||||
fusesoc run --target=chameleon96 servant
|
|
||||||
|
|
||||||
CMOD A7 35t
|
|
||||||
^^^^^^^^^^^
|
|
||||||
|
|
||||||
FPGA Pin J18 is used for UART output with 57600 baud rate. btn0 is used for reset.
|
|
||||||
|
|
||||||
fusesoc run --target=cmod_a7_35t servant
|
|
||||||
|
|
||||||
CYC1000
|
|
||||||
^^^^^^^
|
|
||||||
|
|
||||||
fusesoc run --target=cyc1000 servant
|
|
||||||
|
|
||||||
DE0 Nano
|
|
||||||
^^^^^^^^
|
|
||||||
|
|
||||||
FPGA Pin D11 (Connector JP1, pin 38) is used for UART output with 57600 baud rate. DE0 Nano needs an external 3.3V UART to connect to this pin
|
|
||||||
|
|
||||||
fusesoc run --target=de0_nano servant
|
|
||||||
|
|
||||||
DE10 Nano
|
|
||||||
^^^^^^^^^
|
|
||||||
|
|
||||||
FPGA Pin Y15 (Connector JP7, pin 1) is used for UART output with 57600 baud rate. DE10 Nano needs an external 3.3V UART to connect to this pin
|
|
||||||
|
|
||||||
fusesoc run --target=de10_nano servant
|
|
||||||
|
|
||||||
|
|
||||||
DE1 SoC revF
|
|
||||||
^^^^^^^^^^^^
|
|
||||||
|
|
||||||
FPGA PIN_AC18 (Connector GPIO0, pin 0) is used for UART output with 57600 baud rate. DE1 SoC revF needs an external 3.3V UART to connect to this pin. The UART pin has not been tested.
|
|
||||||
|
|
||||||
fusesoc run --target=de1_soc_revF servant
|
|
||||||
|
|
||||||
DECA development kit
|
|
||||||
^^^^^^^^^^^^^^^^^^^^
|
|
||||||
|
|
||||||
FPGA Pin W18 (Pin 3 P8 connector) is used for UART output with 57600 baud rate. Key 0 is reset and Led 0 q output.
|
|
||||||
|
|
||||||
fusesoc run --target=deca servant
|
|
||||||
|
|
||||||
EBAZ4205 'Development' Board
|
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
|
|
||||||
Pin B20 is used for UART output with 57600 baud rate. To use `blinky.hex`
|
|
||||||
change B20 to W14 (red led) in `data/ebaz4205.xdc` file).
|
|
||||||
|
|
||||||
fusesoc run --target=ebaz4205 servant
|
|
||||||
|
|
||||||
fusesoc run --target=ebaz4205 servant --memfile=$SERV/sw/blinky.hex
|
|
||||||
|
|
||||||
Reference: https://github.com/fusesoc/blinky#ebaz4205-development-board
|
|
||||||
|
|
||||||
ECP5 EVN
|
|
||||||
^^^^^^^^
|
|
||||||
|
|
||||||
fusesoc run --target=ecp5_evn servant
|
|
||||||
|
|
||||||
Icebreaker
|
|
||||||
^^^^^^^^^^
|
|
||||||
|
|
||||||
Pin 9 is used for UART output with 57600 baud rate.
|
|
||||||
|
|
||||||
fusesoc run --target=icebreaker servant
|
|
||||||
|
|
||||||
iCEstick
|
|
||||||
^^^^^^^^
|
|
||||||
|
|
||||||
Pin 95 is used as the GPIO output which is connected to the board's green LED. Due to this board's limited Embedded BRAM, programs with a maximum of 7168 bytes can be loaded. The default program for this board is blinky.hex.
|
|
||||||
|
|
||||||
fusesoc run --target=icestick servant
|
|
||||||
iceprog build/servant_1.3.0/icestick-icestorm/servant_1.3.0.bin
|
|
||||||
|
|
||||||
iCESugar
|
|
||||||
^^^^^^^^
|
|
||||||
|
|
||||||
Pin 6 is used for UART output with 115200 baud rate. Thanks to the onboard
|
|
||||||
debugger, you can just connect the USB Type-C connector to the PC, and a
|
|
||||||
serial console will show up.
|
|
||||||
|
|
||||||
fusesoc run --target=icesugar servant
|
|
||||||
|
|
||||||
ICE-V Wireless
|
|
||||||
^^^^^^^^^^^^^^
|
|
||||||
|
|
||||||
Pin 9 is used for UART output with 57600 baud rate.
|
|
||||||
|
|
||||||
fusesoc run --target=icev_wireless servant
|
|
||||||
|
|
||||||
iceprog build/servant_1.3.0/icestick-icestorm/servant_1.3.0.bin
|
|
||||||
|
|
||||||
GMM7550
|
|
||||||
^^^^^^^
|
|
||||||
|
|
||||||
fusesoc run --target=gmm7550 servant
|
|
||||||
|
|
||||||
LX9 Microboard
|
|
||||||
^^^^^^^^^^^^^^
|
|
||||||
|
|
||||||
fusesoc run --target=lx9_microboard servant
|
|
||||||
|
|
||||||
Machdyne Kolibri
|
|
||||||
^^^^^^^^^^^^^^^^
|
|
||||||
|
|
||||||
Pin B1 is used for UART output with 115200 baud rate. The serial port on Kolibri is accessible as a USB-CDC device.
|
|
||||||
|
|
||||||
fusesoc run --target=machdyne_kolibri servant
|
|
||||||
|
|
||||||
ldprog -Ks build/servant_1.3.0/machdyne_kolibri-icestorm/servant_1.3.0.bin
|
|
||||||
|
|
||||||
MAX10 10M08 Evaluation Kit
|
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
|
|
||||||
FPGA Pin 75 (Arduino_IO01 J5 pin 7) is used for UART output with 57600 baud rate. SW1 is reset and Led 1 q output.
|
|
||||||
|
|
||||||
fusesoc run --target=max10_10m08evk servant
|
|
||||||
|
|
||||||
Nandland Go Board
|
|
||||||
^^^^^^^^^^^^^^^^^
|
|
||||||
|
|
||||||
Pin 56 is used as the GPIO output which is connected to the board's LED1. Due to this board's limited Embedded BRAM, programs with a maximum of 7168 bytes can be loaded. The default program for this board is blinky.hex.
|
|
||||||
|
|
||||||
fusesoc run --target=go_board servant
|
|
||||||
iceprog build/servant_1.3.0/go_board-icestorm/servant_1.3.0.bin
|
|
||||||
|
|
||||||
Nexys 2
|
|
||||||
^^^^^^^
|
|
||||||
|
|
||||||
Pmod pin JA1 is connected to UART tx with 57600 baud rate. A USB to TTL connector is used to display to hello world message on the serial monitor.
|
|
||||||
(To use blinky.hex change L15 to J14 (led[0]) in data/nexys_2.ucf).
|
|
||||||
|
|
||||||
fusesoc run --target=nexys_2_500 servant --uart_baudrate=57600 --firmware=$SERV/sw/zephyr_hello.hex
|
|
||||||
|
|
||||||
|
|
||||||
Nexys A7
|
|
||||||
^^^^^^^^
|
|
||||||
|
|
||||||
fusesoc run --target=nexys_a7 servant
|
|
||||||
|
|
||||||
OrangeCrab R0.2
|
|
||||||
^^^^^^^^^^^^^^^
|
|
||||||
|
|
||||||
Pin D1 is used for UART output with 115200 baud rate.
|
|
||||||
|
|
||||||
fusesoc run --target=orangecrab_r0.2 servant
|
|
||||||
dfu-util -d 1209:5af0 -D build/servant_1.3.0/orangecrab_r0.2-trellis/servant_1.3.0.bit
|
|
||||||
|
|
||||||
PolarFire Splash Kit
|
|
||||||
^^^^^^^^^^^^^^^^^^^^
|
|
||||||
|
|
||||||
Pin R5 is used for UART output with a 115200 baud rate, this is routed through
|
|
||||||
the onboard FTDI transceiver. LED1 (Pin P7) serves as the generic GPIO.
|
|
||||||
|
|
||||||
Pin P8 is used as the GPIO heartbeat with a 1Hz frequency and is connected to
|
|
||||||
the board's LED2.
|
|
||||||
|
|
||||||
Pin N4 (user reset) is used for the reset
|
|
||||||
|
|
||||||
fusesoc run --target=polarfire_splashkit servant --memfile=$SERV/sw/zephyr_hello.hex
|
|
||||||
|
|
||||||
Saanlima Pipistrello (Spartan6 LX45)
|
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
|
|
||||||
Pin A10 (usb_data<1>) is used for UART output with 57600 baud rate (to use
|
|
||||||
blinky.hex change A10 to V16 (led[0]) in data/pipistrello.ucf).
|
|
||||||
|
|
||||||
fusesoc run --target=pipistrello servant
|
|
||||||
|
|
||||||
SoCKit development kit
|
|
||||||
^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
|
|
||||||
FPGA Pin F14 (HSTC GPIO addon connector J2, pin 2) is used for UART output with 57600 baud rate.
|
|
||||||
|
|
||||||
fusesoc run --target=sockit servant
|
|
||||||
|
|
||||||
Trenz Electronic TE0802
|
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
|
|
||||||
PMOD A marked J5, pin two, on the board is used for UART output with 115200 baud rate.
|
|
||||||
|
|
||||||
fusesoc run --target=te0802 servant
|
|
||||||
|
|
||||||
TinyFPGA BX
|
|
||||||
^^^^^^^^^^^
|
|
||||||
|
|
||||||
Pin A6 is used for UART output with 115200 baud rate.
|
|
||||||
|
|
||||||
fusesoc run --target=tinyfpga_bx servant
|
|
||||||
tinyprog --program build/servant_1.0.1/tinyfpga_bx-icestorm/servant_1.0.1.bin
|
|
||||||
|
|
||||||
ULX3S
|
|
||||||
^^^^^
|
|
||||||
|
|
||||||
fusesoc run --target=ulx3s servant
|
|
||||||
|
|
||||||
Upduino2
|
|
||||||
^^^^^^^^
|
|
||||||
|
|
||||||
fusesoc run --target=upduino2 servant
|
|
||||||
|
|
||||||
zcu106
|
|
||||||
^^^^^^
|
|
||||||
|
|
||||||
fusesoc run --target=zcu106 servant
|
|
||||||
|
|
||||||
Porting Servant to a new target
|
|
||||||
-------------------------------
|
|
||||||
|
|
||||||
Mostly any FPGA board can be used to run the Servant SoC. In its simplest form it just needs an FPGA with a clock input and an output that can be used to connect an UART or a LED.
|
|
||||||
|
|
||||||
The porting process consists of FIXME steps.
|
|
||||||
We will use `<name>` as a placeholder for the name of the FPGA board.
|
|
||||||
1. Locate the pins used for clock input and for the outputs. Outputs should preferably be both a LED and an UART, but either works if not both are available. Optionally, locate an input pin connected to the reset as well. This is not required, but can be handy.
|
|
||||||
2. Write a pin constraints file with your located pins in the format of the FPGA toolchain you intend to use. For Vivado this would be an .xdc file. For Quartus a .tcl file, for nextpnr a .pcf file and so on. Save this as `data/<name>.{pcf,ucf,xdc...}` in the SERV repo.
|
|
||||||
3. Create a clock generation file
|
|
||||||
4. Create a top-level
|
|
||||||
5. Create a fileset
|
|
||||||
6. Create a target
|
|
BIN
doc/servile.png
BIN
doc/servile.png
Binary file not shown.
Before Width: | Height: | Size: 4.4 KiB |
166
doc/servile.rst
166
doc/servile.rst
|
@ -1,166 +0,0 @@
|
||||||
Servile : Convenience wrapper
|
|
||||||
=============================
|
|
||||||
|
|
||||||
.. figure:: servile.png
|
|
||||||
|
|
||||||
Servile convenience wrapper
|
|
||||||
|
|
||||||
Servile is a helper component that takes care of common configuration and is used as a building block in the other designs and subsystems. It exposes a memory bus intended to be connected to a combined data and instruction memory, an extension bus for peripheral controllers and accelerators and an RF interface for connecting to an SRAM for GPR and CSR registers.
|
|
||||||
|
|
||||||
.. figure:: servile_int.png
|
|
||||||
|
|
||||||
Servile block diagram
|
|
||||||
|
|
||||||
Internally, Servile contains logic for optionally instantiating an MDU core for the M extension, an arbiter to route instruction fetches and main memory accesses through the same interface and a mux to split up the memory map into memory (0x00000000-0x3FFFFFFF) and external accesses (0x40000000-0xFFFFFFFF). The mux also contains simulation-only logic to write output to a log file and stop the simulation.
|
|
||||||
|
|
||||||
Parameters
|
|
||||||
----------
|
|
||||||
|
|
||||||
.. list-table:: Parameters
|
|
||||||
:header-rows: 1
|
|
||||||
:widths: 10 20 80
|
|
||||||
|
|
||||||
* - Parameter
|
|
||||||
- Values
|
|
||||||
- Description
|
|
||||||
* - reset_pc
|
|
||||||
- 0x00000000 (default) - 0xFFFFFFFC
|
|
||||||
- Address of first instruction to fetch from memory after reset (Reset vector)
|
|
||||||
* - reset_strategy
|
|
||||||
- "MINI" (default), "NONE"
|
|
||||||
- | Amount of reset applied to design
|
|
||||||
| "NONE" : No reset at all. Relies on a POR to set correct initialization values and that core isn't reset during runtime
|
|
||||||
| "MINI" : Standard setting. Resets the minimal amount of FFs needed to restart execution from the instruction at RESET_PC.
|
|
||||||
* - rf_width
|
|
||||||
- 2 (default), 4, 8, 16, 32
|
|
||||||
- Width of the data bus to the RF memory. Typically smaller values use less resources, but can be implementation-dependant.
|
|
||||||
* - sim
|
|
||||||
- 0 (default), 1
|
|
||||||
- | Enable simulation mode. In simulation mode, two memory addresses have special purposes.
|
|
||||||
| 0x80000000: Writes to this address puts the byte in the lowest data byte into a log file decided by the "signature" plusarg.
|
|
||||||
| 0x90000000: Writes to this address ends the simulation.
|
|
||||||
* - with_c
|
|
||||||
- 0 (default), 1
|
|
||||||
- Enable the C extension. This also makes SERV support misaligned loads and stores.
|
|
||||||
* - with_csr
|
|
||||||
- 0 (default), 1
|
|
||||||
- Enable the Zicsr extension. This also enables timer IRQ and exception handling. Note that SERV only implements a small subset of the CSR registers.
|
|
||||||
* - with_mdu
|
|
||||||
- 0 (default), 1
|
|
||||||
- Enables the Multiplication and Division Unit (MDU) to support the M extension. Note that this only enables the interface and the decoder logic. The MDU itself is external from SERV.
|
|
||||||
|
|
||||||
Signals
|
|
||||||
-------
|
|
||||||
|
|
||||||
.. list-table:: Signals
|
|
||||||
:header-rows: 1
|
|
||||||
:widths: 30 10 5 75
|
|
||||||
|
|
||||||
* - Signal
|
|
||||||
- Width
|
|
||||||
- Direction
|
|
||||||
- Description
|
|
||||||
* - i_clk
|
|
||||||
- 1
|
|
||||||
- in
|
|
||||||
- Clock
|
|
||||||
* - i_rst
|
|
||||||
- 1
|
|
||||||
- in
|
|
||||||
- Synchronous reset
|
|
||||||
* - i_timer_irq
|
|
||||||
- 1
|
|
||||||
- in
|
|
||||||
- Timer interrupt
|
|
||||||
* - **Memory interface**
|
|
||||||
-
|
|
||||||
-
|
|
||||||
- Connect to instruction/data memory
|
|
||||||
* - o_wb_mem_adr
|
|
||||||
- 32
|
|
||||||
- out
|
|
||||||
- Memory bus address
|
|
||||||
* - o_wb_mem_dat
|
|
||||||
- 32
|
|
||||||
- out
|
|
||||||
- Memory bus data
|
|
||||||
* - o_wb_mem_sel
|
|
||||||
- 4
|
|
||||||
- out
|
|
||||||
- Memory bus write data byte select mask
|
|
||||||
* - o_wb_mem_we
|
|
||||||
- 1
|
|
||||||
- out
|
|
||||||
- Memory bus write transaction
|
|
||||||
* - o_wb_mem_stb
|
|
||||||
- 1
|
|
||||||
- out
|
|
||||||
- Memory bus active strobe
|
|
||||||
* - i_wb_mem_rdt
|
|
||||||
- 32
|
|
||||||
- in
|
|
||||||
- Memory bus read data
|
|
||||||
* - i_wb_mem_ack
|
|
||||||
- 1
|
|
||||||
- in
|
|
||||||
- Memory bus cycle acknowledged
|
|
||||||
* - **Extension interface**
|
|
||||||
-
|
|
||||||
-
|
|
||||||
- Connect to peripheral controllers
|
|
||||||
* - o_wb_ext_adr
|
|
||||||
- 32
|
|
||||||
- out
|
|
||||||
- Data bus address
|
|
||||||
* - o_wb_ext_dat
|
|
||||||
- 32
|
|
||||||
- out
|
|
||||||
- Data bus write data
|
|
||||||
* - o_wb_ext_sel
|
|
||||||
- 4
|
|
||||||
- out
|
|
||||||
- Data bus write data byte select mask
|
|
||||||
* - o_wb_ext_we
|
|
||||||
- 1
|
|
||||||
- out
|
|
||||||
- Data bus write transaction
|
|
||||||
* - o_wb_ext_stb
|
|
||||||
- 1
|
|
||||||
- out
|
|
||||||
- Data bus active cycle
|
|
||||||
* - i_wb_ext_rdt
|
|
||||||
- 32
|
|
||||||
- in
|
|
||||||
- Data bus return data
|
|
||||||
* - i_wb_ext_ack
|
|
||||||
- 1
|
|
||||||
- in
|
|
||||||
- Data bus return data valid
|
|
||||||
* - **RF (SRAM) interface**
|
|
||||||
-
|
|
||||||
-
|
|
||||||
-
|
|
||||||
* - o_rf_waddr
|
|
||||||
- ceil(log2(regs*32/rf_width)
|
|
||||||
- out
|
|
||||||
- RF memory write address
|
|
||||||
* - o_rf_wdata
|
|
||||||
- rf_width
|
|
||||||
- out
|
|
||||||
- RF memory write data
|
|
||||||
* - o_rf_wen
|
|
||||||
- 1
|
|
||||||
- out
|
|
||||||
- RF memory write enable
|
|
||||||
* - o_rf_raddr
|
|
||||||
- ceil(log2(regs*32/rf_width)
|
|
||||||
- out
|
|
||||||
- RF memory read address
|
|
||||||
* - i_rf_rdata
|
|
||||||
- rf_width
|
|
||||||
- out
|
|
||||||
- RF memory read data
|
|
||||||
* - o_rf_ren
|
|
||||||
- 1
|
|
||||||
- out
|
|
||||||
- RF memory read enable
|
|
Binary file not shown.
Before Width: | Height: | Size: 22 KiB |
BIN
doc/serving.png
BIN
doc/serving.png
Binary file not shown.
Before Width: | Height: | Size: 9.2 KiB |
|
@ -1,94 +0,0 @@
|
||||||
Serving : FPGA subsystem
|
|
||||||
========================
|
|
||||||
|
|
||||||
.. figure:: serving.png
|
|
||||||
|
|
||||||
Serving SoClet
|
|
||||||
|
|
||||||
Serving is ideal for FPGA implementations as it only uses a single combined block RAM for instructions, data and RF that can be preloaded with a RISC-V application. It exposes a wishbone data bus that can be used to connect peripheral controllers.
|
|
||||||
|
|
||||||
Parameters
|
|
||||||
----------
|
|
||||||
|
|
||||||
.. list-table:: Parameters
|
|
||||||
:header-rows: 1
|
|
||||||
:widths: 10 20 80
|
|
||||||
|
|
||||||
* - Parameter
|
|
||||||
- Values
|
|
||||||
- Description
|
|
||||||
* - memfile
|
|
||||||
- "" (default)
|
|
||||||
- Verilog hex file containing a RISC-V application to be preloaded into memory
|
|
||||||
* - memsize
|
|
||||||
- 1-4294967296 (default 8192)
|
|
||||||
- Size of memory (in bytes). Needs to be at least large enough to fit the application supplied by memsize. Note that the RF occupies the highest 128 bytes of memory in the RAM.
|
|
||||||
* - sim
|
|
||||||
- 0 (default), 1
|
|
||||||
- | Enable simulation mode. In simulation mode, two memory addresses have special purposes.
|
|
||||||
| 0x80000000: Writes to this address puts the byte in the lowest data byte into a log file decided by the "signature" plusarg.
|
|
||||||
| 0x90000000: Writes to this address ends the simulation.
|
|
||||||
* - RESET_STRATEGY
|
|
||||||
- "MINI" (default), "NONE"
|
|
||||||
- | Amount of reset applied to design
|
|
||||||
| "NONE" : No reset at all. Relies on a POR to set correct initialization values and that core isn't reset during runtime
|
|
||||||
| "MINI" : Standard setting. Resets the minimal amount of FFs needed to restart execution from the instruction at RESET_PC.
|
|
||||||
* - WITH_CSR
|
|
||||||
- 0 (default), 1
|
|
||||||
- Enable the Zicsr extension. This also enables timer IRQ and exception handling. Note that SERV only implements a small subset of the CSR registers.
|
|
||||||
|
|
||||||
Signals
|
|
||||||
-------
|
|
||||||
|
|
||||||
.. list-table:: Signals
|
|
||||||
:header-rows: 1
|
|
||||||
:widths: 30 10 5 75
|
|
||||||
|
|
||||||
* - Signal
|
|
||||||
- Width
|
|
||||||
- Direction
|
|
||||||
- Description
|
|
||||||
* - i_clk
|
|
||||||
- 1
|
|
||||||
- in
|
|
||||||
- Clock
|
|
||||||
* - i_rst
|
|
||||||
- 1
|
|
||||||
- in
|
|
||||||
- Synchronous reset
|
|
||||||
* - i_timer_irq
|
|
||||||
- 1
|
|
||||||
- in
|
|
||||||
- Timer interrupt
|
|
||||||
* - **Extension interface**
|
|
||||||
-
|
|
||||||
-
|
|
||||||
- Connect to peripheral controllers
|
|
||||||
* - o_wb_adr
|
|
||||||
- 32
|
|
||||||
- out
|
|
||||||
- Data bus address
|
|
||||||
* - o_wb_dat
|
|
||||||
- 32
|
|
||||||
- out
|
|
||||||
- Data bus write data
|
|
||||||
* - o_wb_sel
|
|
||||||
- 4
|
|
||||||
- out
|
|
||||||
- Data bus write data byte select mask
|
|
||||||
* - o_wb_we
|
|
||||||
- 1
|
|
||||||
- out
|
|
||||||
- Data bus write transaction
|
|
||||||
* - o_wb_cyc
|
|
||||||
- 1
|
|
||||||
- out
|
|
||||||
- Data bus active cycle
|
|
||||||
* - i_wb_rdt
|
|
||||||
- 32
|
|
||||||
- in
|
|
||||||
- Data bus return data
|
|
||||||
* - i_wb_ack
|
|
||||||
- 1
|
|
||||||
- in
|
|
||||||
- Data bus return data valid
|
|
Binary file not shown.
Before Width: | Height: | Size: 8.6 KiB |
|
@ -1,10 +0,0 @@
|
||||||
Subservient : SERV ASIC macro
|
|
||||||
=============================
|
|
||||||
|
|
||||||
.. figure:: subservient.png
|
|
||||||
|
|
||||||
Subservient ASIC macro
|
|
||||||
|
|
||||||
`Subservient <https://github.com/olofk/subservient>`_ is a minimal reference system that just requires connecting one single-port SRAM for data, instructions and RF. It is intended to make ASIC integration easier.
|
|
||||||
|
|
||||||
|
|
26
riscv-target/serv/device/rv32i_m/C/Makefile.include
Normal file
26
riscv-target/serv/device/rv32i_m/C/Makefile.include
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
TARGET_SIM ?= server
|
||||||
|
ifeq ($(shell command -v $(TARGET_SIM) 2> /dev/null),)
|
||||||
|
$(error Target simulator executable '$(TARGET_SIM)` not found)
|
||||||
|
endif
|
||||||
|
|
||||||
|
RUN_TARGET=\
|
||||||
|
$(TARGET_SIM) \
|
||||||
|
+timeout=100000000000 \
|
||||||
|
+signature=$(*).signature.output \
|
||||||
|
+firmware=$(<).hex 2> $@
|
||||||
|
|
||||||
|
RISCV_PREFIX ?= riscv32-unknown-elf-
|
||||||
|
RISCV_GCC ?= $(RISCV_PREFIX)gcc
|
||||||
|
RISCV_OBJCOPY ?= $(RISCV_PREFIX)objcopy
|
||||||
|
RISCV_OBJDUMP ?= $(RISCV_PREFIX)objdump
|
||||||
|
RISCV_GCC_OPTS ?= -static -mcmodel=medany -fvisibility=hidden -nostdlib -nostartfiles
|
||||||
|
|
||||||
|
COMPILE_TARGET=\
|
||||||
|
$$(RISCV_GCC) $(1) $$(RISCV_GCC_OPTS) \
|
||||||
|
-I$(ROOTDIR)/riscv-test-env/ \
|
||||||
|
-I$(TARGETDIR)/$(RISCV_TARGET)/ \
|
||||||
|
-T$(TARGETDIR)/$(RISCV_TARGET)/link.ld $$< \
|
||||||
|
-o $$@; \
|
||||||
|
$$(RISCV_OBJCOPY) -O binary $$@ $$@.bin; \
|
||||||
|
$$(RISCV_OBJDUMP) -D $$@ > $$@.objdump; \
|
||||||
|
python3 $(TARGETDIR)/$(RISCV_TARGET)/makehex.py $$@.bin 524288 > $$@.hex;
|
26
riscv-target/serv/device/rv32i_m/I/Makefile.include
Normal file
26
riscv-target/serv/device/rv32i_m/I/Makefile.include
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
TARGET_SIM ?= server
|
||||||
|
ifeq ($(shell command -v $(TARGET_SIM) 2> /dev/null),)
|
||||||
|
$(error Target simulator executable '$(TARGET_SIM)` not found)
|
||||||
|
endif
|
||||||
|
|
||||||
|
RUN_TARGET=\
|
||||||
|
$(TARGET_SIM) \
|
||||||
|
+timeout=100000000000 \
|
||||||
|
+signature=$(*).signature.output \
|
||||||
|
+firmware=$(<).hex 2> $@
|
||||||
|
|
||||||
|
RISCV_PREFIX ?= riscv32-unknown-elf-
|
||||||
|
RISCV_GCC ?= $(RISCV_PREFIX)gcc
|
||||||
|
RISCV_OBJCOPY ?= $(RISCV_PREFIX)objcopy
|
||||||
|
RISCV_OBJDUMP ?= $(RISCV_PREFIX)objdump
|
||||||
|
RISCV_GCC_OPTS ?= -static -mcmodel=medany -fvisibility=hidden -nostdlib -nostartfiles
|
||||||
|
|
||||||
|
COMPILE_TARGET=\
|
||||||
|
$$(RISCV_GCC) $(1) $$(RISCV_GCC_OPTS) \
|
||||||
|
-I$(ROOTDIR)/riscv-test-env/ \
|
||||||
|
-I$(TARGETDIR)/$(RISCV_TARGET)/ \
|
||||||
|
-T$(TARGETDIR)/$(RISCV_TARGET)/link.ld $$< \
|
||||||
|
-o $$@; \
|
||||||
|
$$(RISCV_OBJCOPY) -O binary $$@ $$@.bin; \
|
||||||
|
$$(RISCV_OBJDUMP) -D $$@ > $$@.objdump; \
|
||||||
|
python3 $(TARGETDIR)/$(RISCV_TARGET)/makehex.py $$@.bin 524288 > $$@.hex;
|
26
riscv-target/serv/device/rv32i_m/M/Makefile.include
Normal file
26
riscv-target/serv/device/rv32i_m/M/Makefile.include
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
TARGET_SIM ?= server
|
||||||
|
ifeq ($(shell command -v $(TARGET_SIM) 2> /dev/null),)
|
||||||
|
$(error Target simulator executable '$(TARGET_SIM)` not found)
|
||||||
|
endif
|
||||||
|
|
||||||
|
RUN_TARGET=\
|
||||||
|
$(TARGET_SIM) \
|
||||||
|
+timeout=100000000000 \
|
||||||
|
+signature=$(*).signature.output \
|
||||||
|
+firmware=$(<).hex 2> $@
|
||||||
|
|
||||||
|
RISCV_PREFIX ?= riscv32-unknown-elf-
|
||||||
|
RISCV_GCC ?= $(RISCV_PREFIX)gcc
|
||||||
|
RISCV_OBJCOPY ?= $(RISCV_PREFIX)objcopy
|
||||||
|
RISCV_OBJDUMP ?= $(RISCV_PREFIX)objdump
|
||||||
|
RISCV_GCC_OPTS ?= -static -mcmodel=medany -fvisibility=hidden -nostdlib -nostartfiles
|
||||||
|
|
||||||
|
COMPILE_TARGET=\
|
||||||
|
$$(RISCV_GCC) $(1) $$(RISCV_GCC_OPTS) \
|
||||||
|
-I$(ROOTDIR)/riscv-test-env/ \
|
||||||
|
-I$(TARGETDIR)/$(RISCV_TARGET)/ \
|
||||||
|
-T$(TARGETDIR)/$(RISCV_TARGET)/link.ld $$< \
|
||||||
|
-o $$@; \
|
||||||
|
$$(RISCV_OBJCOPY) -O binary $$@ $$@.bin; \
|
||||||
|
$$(RISCV_OBJDUMP) -D $$@ > $$@.objdump; \
|
||||||
|
python3 $(TARGETDIR)/$(RISCV_TARGET)/makehex.py $$@.bin 524288 > $$@.hex;
|
26
riscv-target/serv/device/rv32i_m/Zifencei/Makefile.include
Normal file
26
riscv-target/serv/device/rv32i_m/Zifencei/Makefile.include
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
TARGET_SIM ?= server
|
||||||
|
ifeq ($(shell command -v $(TARGET_SIM) 2> /dev/null),)
|
||||||
|
$(error Target simulator executable '$(TARGET_SIM)` not found)
|
||||||
|
endif
|
||||||
|
|
||||||
|
RUN_TARGET=\
|
||||||
|
$(TARGET_SIM) \
|
||||||
|
+timeout=100000000000 \
|
||||||
|
+signature=$(*).signature.output \
|
||||||
|
+firmware=$(<).hex 2> $@
|
||||||
|
|
||||||
|
RISCV_PREFIX ?= riscv32-unknown-elf-
|
||||||
|
RISCV_GCC ?= $(RISCV_PREFIX)gcc
|
||||||
|
RISCV_OBJCOPY ?= $(RISCV_PREFIX)objcopy
|
||||||
|
RISCV_OBJDUMP ?= $(RISCV_PREFIX)objdump
|
||||||
|
RISCV_GCC_OPTS ?= -static -mcmodel=medany -fvisibility=hidden -nostdlib -nostartfiles
|
||||||
|
|
||||||
|
COMPILE_TARGET=\
|
||||||
|
$$(RISCV_GCC) $(1) $$(RISCV_GCC_OPTS) \
|
||||||
|
-I$(ROOTDIR)/riscv-test-env/ \
|
||||||
|
-I$(TARGETDIR)/$(RISCV_TARGET)/ \
|
||||||
|
-T$(TARGETDIR)/$(RISCV_TARGET)/link.ld $$< \
|
||||||
|
-o $$@; \
|
||||||
|
$$(RISCV_OBJCOPY) -O binary $$@ $$@.bin; \
|
||||||
|
$$(RISCV_OBJDUMP) -D $$@ > $$@.objdump; \
|
||||||
|
python3 $(TARGETDIR)/$(RISCV_TARGET)/makehex.py $$@.bin 524288 > $$@.hex;
|
26
riscv-target/serv/device/rv32i_m/privilege/Makefile.include
Normal file
26
riscv-target/serv/device/rv32i_m/privilege/Makefile.include
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
TARGET_SIM ?= server
|
||||||
|
ifeq ($(shell command -v $(TARGET_SIM) 2> /dev/null),)
|
||||||
|
$(error Target simulator executable '$(TARGET_SIM)` not found)
|
||||||
|
endif
|
||||||
|
|
||||||
|
RUN_TARGET=\
|
||||||
|
$(TARGET_SIM) \
|
||||||
|
+timeout=100000000000 \
|
||||||
|
+signature=$(*).signature.output \
|
||||||
|
+firmware=$(<).hex 2> $@
|
||||||
|
|
||||||
|
RISCV_PREFIX ?= riscv32-unknown-elf-
|
||||||
|
RISCV_GCC ?= $(RISCV_PREFIX)gcc
|
||||||
|
RISCV_OBJCOPY ?= $(RISCV_PREFIX)objcopy
|
||||||
|
RISCV_OBJDUMP ?= $(RISCV_PREFIX)objdump
|
||||||
|
RISCV_GCC_OPTS ?= -static -mcmodel=medany -fvisibility=hidden -nostdlib -nostartfiles
|
||||||
|
|
||||||
|
COMPILE_TARGET=\
|
||||||
|
$$(RISCV_GCC) $(1) $$(RISCV_GCC_OPTS) \
|
||||||
|
-I$(ROOTDIR)/riscv-test-env/ \
|
||||||
|
-I$(TARGETDIR)/$(RISCV_TARGET)/ \
|
||||||
|
-T$(TARGETDIR)/$(RISCV_TARGET)/link.ld $$< \
|
||||||
|
-o $$@; \
|
||||||
|
$$(RISCV_OBJCOPY) -O binary $$@ $$@.bin; \
|
||||||
|
$$(RISCV_OBJDUMP) -D $$@ > $$@.objdump; \
|
||||||
|
python3 $(TARGETDIR)/$(RISCV_TARGET)/makehex.py $$@.bin 524288 > $$@.hex;
|
|
@ -1,9 +1,9 @@
|
||||||
OUTPUT_ARCH( "riscv" )
|
OUTPUT_ARCH( "riscv" )
|
||||||
ENTRY(rvtest_entry_point)
|
ENTRY(_start)
|
||||||
|
|
||||||
SECTIONS
|
SECTIONS
|
||||||
{
|
{
|
||||||
. = 0x80000000;
|
. = 0x00000000;
|
||||||
.text.init : { *(.text.init) }
|
.text.init : { *(.text.init) }
|
||||||
. = ALIGN(0x1000);
|
. = ALIGN(0x1000);
|
||||||
.tohost : { *(.tohost) }
|
.tohost : { *(.tohost) }
|
27
riscv-target/serv/makehex.py
Normal file
27
riscv-target/serv/makehex.py
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
#
|
||||||
|
# This is free and unencumbered software released into the public domain.
|
||||||
|
#
|
||||||
|
# Anyone is free to copy, modify, publish, use, compile, sell, or
|
||||||
|
# distribute this software, either in source code form or as a compiled
|
||||||
|
# binary, for any purpose, commercial or non-commercial, and by any
|
||||||
|
# means.
|
||||||
|
|
||||||
|
from sys import argv
|
||||||
|
|
||||||
|
binfile = argv[1]
|
||||||
|
nwords = int(argv[2])
|
||||||
|
|
||||||
|
with open(binfile, "rb") as f:
|
||||||
|
bindata = f.read()
|
||||||
|
|
||||||
|
assert len(bindata) < 4*nwords
|
||||||
|
assert len(bindata) % 4 == 0
|
||||||
|
|
||||||
|
for i in range(nwords):
|
||||||
|
if i < len(bindata) // 4:
|
||||||
|
w = bindata[4*i : 4*i+4]
|
||||||
|
print("%02x%02x%02x%02x" % (w[3], w[2], w[1], w[0]))
|
||||||
|
else:
|
||||||
|
print("0")
|
||||||
|
|
|
@ -5,10 +5,10 @@
|
||||||
la a0, begin_signature; \
|
la a0, begin_signature; \
|
||||||
la a1, end_signature; \
|
la a1, end_signature; \
|
||||||
li a2, 0x80000000; \
|
li a2, 0x80000000; \
|
||||||
compliance_halt_loop: \
|
complience_halt_loop: \
|
||||||
beq a0, a1, compliance_halt_break; \
|
beq a0, a1, complience_halt_break; \
|
||||||
addi a3, a0, 4; \
|
addi a3, a0, 4; \
|
||||||
compliance_halt_loop2: \
|
complience_halt_loop2: \
|
||||||
addi a3, a3, -1; \
|
addi a3, a3, -1; \
|
||||||
\
|
\
|
||||||
lb a4, 0 (a3); \
|
lb a4, 0 (a3); \
|
||||||
|
@ -29,14 +29,14 @@
|
||||||
notLetter2: \
|
notLetter2: \
|
||||||
addi a5, a5, 0x30; \
|
addi a5, a5, 0x30; \
|
||||||
sw a5, 0 (a2); \
|
sw a5, 0 (a2); \
|
||||||
bne a0, a3,compliance_halt_loop2; \
|
bne a0, a3,complience_halt_loop2; \
|
||||||
addi a0, a0, 4; \
|
addi a0, a0, 4; \
|
||||||
\
|
\
|
||||||
li a4, '\n'; \
|
li a4, '\n'; \
|
||||||
sw a4, 0 (a2); \
|
sw a4, 0 (a2); \
|
||||||
j compliance_halt_loop; \
|
j complience_halt_loop; \
|
||||||
j compliance_halt_break; \
|
j complience_halt_break; \
|
||||||
compliance_halt_break:; \
|
complience_halt_break:; \
|
||||||
lui a0,0x90000000>>12; \
|
lui a0,0x90000000>>12; \
|
||||||
sw a3,0(a0);
|
sw a3,0(a0);
|
||||||
|
|
||||||
|
@ -48,7 +48,12 @@
|
||||||
.align 4; .global end_signature; end_signature: \
|
.align 4; .global end_signature; end_signature: \
|
||||||
|
|
||||||
|
|
||||||
#define RVMODEL_BOOT
|
#define RVMODEL_BOOT \
|
||||||
|
.section .text.init; \
|
||||||
|
.align 4; \
|
||||||
|
.globl _start; \
|
||||||
|
_start:
|
||||||
|
|
||||||
|
|
||||||
#define LOCAL_IO_WRITE_STR(_STR) RVMODEL_IO_WRITE_STR(x31, _STR)
|
#define LOCAL_IO_WRITE_STR(_STR) RVMODEL_IO_WRITE_STR(x31, _STR)
|
||||||
#define RVMODEL_IO_WRITE_STR(_SP, _STR)
|
#define RVMODEL_IO_WRITE_STR(_SP, _STR)
|
||||||
|
@ -63,4 +68,4 @@
|
||||||
#define RVMODEL_CLEAR_MTIMER_INT
|
#define RVMODEL_CLEAR_MTIMER_INT
|
||||||
#define RVMODEL_CLEAR_MEXT_INT
|
#define RVMODEL_CLEAR_MEXT_INT
|
||||||
|
|
||||||
#endif // _COMPLIANCE_MODEL_H
|
#endif // _COMPLIANCE_MODEL_H
|
|
@ -1,4 +1,4 @@
|
||||||
module serv_aligner
|
module serv_aligner
|
||||||
(
|
(
|
||||||
input wire clk,
|
input wire clk,
|
||||||
input wire rst,
|
input wire rst,
|
||||||
|
@ -15,14 +15,14 @@ module serv_aligner
|
||||||
|
|
||||||
wire [31:0] ibus_rdt_concat;
|
wire [31:0] ibus_rdt_concat;
|
||||||
wire ack_en;
|
wire ack_en;
|
||||||
|
|
||||||
reg [15:0] lower_hw;
|
reg [15:0] lower_hw;
|
||||||
reg ctrl_misal ;
|
reg ctrl_misal ;
|
||||||
|
|
||||||
/* From SERV core to Memory
|
/* From SERV core to Memory
|
||||||
|
|
||||||
o_wb_ibus_adr: Carries address of instruction to memory. In case of misaligned access,
|
o_wb_ibus_adr: Carries address of instruction to memory. In case of misaligned access,
|
||||||
which is caused by pc+2 due to compressed instruction, next instruction is fetched
|
which is caused by pc+2 due to compressed instruction, next instruction is fetched
|
||||||
by pc+4 and concatenation is done to make the instruction aligned.
|
by pc+4 and concatenation is done to make the instruction aligned.
|
||||||
|
|
||||||
o_wb_ibus_cyc: Simply forwarded from SERV to Memory and is only altered by memory or SERV core.
|
o_wb_ibus_cyc: Simply forwarded from SERV to Memory and is only altered by memory or SERV core.
|
||||||
|
@ -43,7 +43,7 @@ module serv_aligner
|
||||||
|
|
||||||
/* 16-bit register used to hold the upper half word of the current instruction in-case
|
/* 16-bit register used to hold the upper half word of the current instruction in-case
|
||||||
concatenation will be required with the upper half word of upcoming instruction
|
concatenation will be required with the upper half word of upcoming instruction
|
||||||
*/
|
*/
|
||||||
always @(posedge clk) begin
|
always @(posedge clk) begin
|
||||||
if(i_wb_ibus_ack)begin
|
if(i_wb_ibus_ack)begin
|
||||||
lower_hw <= i_wb_ibus_rdt[31:16];
|
lower_hw <= i_wb_ibus_rdt[31:16];
|
||||||
|
@ -51,11 +51,11 @@ module serv_aligner
|
||||||
end
|
end
|
||||||
|
|
||||||
assign ibus_rdt_concat = {i_wb_ibus_rdt[15:0],lower_hw};
|
assign ibus_rdt_concat = {i_wb_ibus_rdt[15:0],lower_hw};
|
||||||
|
|
||||||
/* Two control signals: ack_en, ctrl_misal are set to control the bus transactions between
|
/* Two control signals: ack_en, ctrl_misal are set to control the bus transactions between
|
||||||
SERV core and the memory
|
SERV core and the memory
|
||||||
*/
|
*/
|
||||||
assign ack_en = !(i_ibus_adr[1] & !ctrl_misal);
|
assign ack_en = !(i_ibus_adr[1] & !ctrl_misal);
|
||||||
|
|
||||||
always @(posedge clk ) begin
|
always @(posedge clk ) begin
|
||||||
if(rst)
|
if(rst)
|
||||||
|
|
|
@ -1,9 +1,5 @@
|
||||||
`default_nettype none
|
`default_nettype none
|
||||||
module serv_alu
|
module serv_alu
|
||||||
#(
|
|
||||||
parameter W = 1,
|
|
||||||
parameter B = W-1
|
|
||||||
)
|
|
||||||
(
|
(
|
||||||
input wire clk,
|
input wire clk,
|
||||||
//State
|
//State
|
||||||
|
@ -17,30 +13,29 @@ module serv_alu
|
||||||
input wire i_cmp_sig,
|
input wire i_cmp_sig,
|
||||||
input wire [2:0] i_rd_sel,
|
input wire [2:0] i_rd_sel,
|
||||||
//Data
|
//Data
|
||||||
input wire [B:0] i_rs1,
|
input wire i_rs1,
|
||||||
input wire [B:0] i_op_b,
|
input wire i_op_b,
|
||||||
input wire [B:0] i_buf,
|
input wire i_buf,
|
||||||
output wire [B:0] o_rd);
|
output wire o_rd);
|
||||||
|
|
||||||
wire [B:0] result_add;
|
wire result_add;
|
||||||
wire [B:0] result_slt;
|
|
||||||
|
|
||||||
reg cmp_r;
|
reg cmp_r;
|
||||||
|
|
||||||
wire add_cy;
|
wire add_cy;
|
||||||
reg [B:0] add_cy_r;
|
reg add_cy_r;
|
||||||
|
|
||||||
//Sign-extended operands
|
//Sign-extended operands
|
||||||
wire rs1_sx = i_rs1[B] & i_cmp_sig;
|
wire rs1_sx = i_rs1 & i_cmp_sig;
|
||||||
wire op_b_sx = i_op_b[B] & i_cmp_sig;
|
wire op_b_sx = i_op_b & i_cmp_sig;
|
||||||
|
|
||||||
wire [B:0] add_b = i_op_b^{W{i_sub}};
|
wire add_b = i_op_b^i_sub;
|
||||||
|
|
||||||
assign {add_cy,result_add} = i_rs1+add_b+add_cy_r;
|
assign {add_cy,result_add} = i_rs1+add_b+add_cy_r;
|
||||||
|
|
||||||
wire result_lt = rs1_sx + ~op_b_sx + add_cy;
|
wire result_lt = rs1_sx + ~op_b_sx + add_cy;
|
||||||
|
|
||||||
wire result_eq = !(|result_add) & (cmp_r | i_cnt0);
|
wire result_eq = !result_add & (cmp_r | i_cnt0);
|
||||||
|
|
||||||
assign o_cmp = i_cmp_eq ? result_eq : result_lt;
|
assign o_cmp = i_cmp_eq ? result_eq : result_lt;
|
||||||
|
|
||||||
|
@ -56,23 +51,15 @@ module serv_alu
|
||||||
i_bool_op will be 01 during shift operations, so by outputting zero under
|
i_bool_op will be 01 during shift operations, so by outputting zero under
|
||||||
this condition we can safely or result_bool with i_buf
|
this condition we can safely or result_bool with i_buf
|
||||||
*/
|
*/
|
||||||
wire [B:0] result_bool = ((i_rs1 ^ i_op_b) & ~{W{i_bool_op[0]}}) | ({W{i_bool_op[1]}} & i_op_b & i_rs1);
|
wire result_bool = ((i_rs1 ^ i_op_b) & ~ i_bool_op[0]) | (i_bool_op[1] & i_op_b & i_rs1);
|
||||||
|
|
||||||
assign result_slt[0] = cmp_r & i_cnt0;
|
|
||||||
generate
|
|
||||||
if (W>1) begin : gen_w_gt_1
|
|
||||||
assign result_slt[B:1] = {B{1'b0}};
|
|
||||||
end
|
|
||||||
endgenerate
|
|
||||||
|
|
||||||
assign o_rd = i_buf |
|
assign o_rd = i_buf |
|
||||||
({W{i_rd_sel[0]}} & result_add) |
|
(i_rd_sel[0] & result_add) |
|
||||||
({W{i_rd_sel[1]}} & result_slt) |
|
(i_rd_sel[1] & cmp_r & i_cnt0) |
|
||||||
({W{i_rd_sel[2]}} & result_bool);
|
(i_rd_sel[2] & result_bool);
|
||||||
|
|
||||||
always @(posedge clk) begin
|
always @(posedge clk) begin
|
||||||
add_cy_r <= {W{1'b0}};
|
add_cy_r <= i_en ? add_cy : i_sub;
|
||||||
add_cy_r[0] <= i_en ? add_cy : i_sub;
|
|
||||||
|
|
||||||
if (i_en)
|
if (i_en)
|
||||||
cmp_r <= o_cmp;
|
cmp_r <= o_cmp;
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
module serv_bufreg #(
|
module serv_bufreg #(
|
||||||
parameter [0:0] MDU = 0,
|
parameter [0:0] MDU = 0
|
||||||
parameter W = 1,
|
|
||||||
parameter B = W-1
|
|
||||||
)(
|
)(
|
||||||
input wire i_clk,
|
input wire i_clk,
|
||||||
//State
|
//State
|
||||||
|
@ -15,51 +13,39 @@ module serv_bufreg #(
|
||||||
input wire i_rs1_en,
|
input wire i_rs1_en,
|
||||||
input wire i_imm_en,
|
input wire i_imm_en,
|
||||||
input wire i_clr_lsb,
|
input wire i_clr_lsb,
|
||||||
input wire i_sh_signed,
|
input wire i_sh_signed,
|
||||||
//Data
|
//Data
|
||||||
input wire [B:0] i_rs1,
|
input wire i_rs1,
|
||||||
input wire [B:0] i_imm,
|
input wire i_imm,
|
||||||
output wire [B:0] o_q,
|
output wire o_q,
|
||||||
//External
|
//External
|
||||||
output wire [31:0] o_dbus_adr,
|
output wire [31:0] o_dbus_adr,
|
||||||
//Extension
|
//Extension
|
||||||
output wire [31:0] o_ext_rs1);
|
output wire [31:0] o_ext_rs1);
|
||||||
|
|
||||||
wire c;
|
wire c, q;
|
||||||
wire [B:0] q;
|
reg c_r;
|
||||||
reg [B:0] c_r;
|
reg [31:2] data;
|
||||||
reg [31:0] data;
|
reg [1:0] lsb;
|
||||||
wire [B:0] clr_lsb;
|
|
||||||
|
|
||||||
assign clr_lsb[0] = i_cnt0 & i_clr_lsb;
|
wire clr_lsb = i_cnt0 & i_clr_lsb;
|
||||||
|
|
||||||
assign {c,q} = {1'b0,(i_rs1 & {W{i_rs1_en}})} + {1'b0,(i_imm & {W{i_imm_en}} & ~clr_lsb)} + c_r;
|
assign {c,q} = {1'b0,(i_rs1 & i_rs1_en)} + {1'b0,(i_imm & i_imm_en & !clr_lsb)} + c_r;
|
||||||
|
|
||||||
always @(posedge i_clk) begin
|
always @(posedge i_clk) begin
|
||||||
//Make sure carry is cleared before loading new data
|
//Make sure carry is cleared before loading new data
|
||||||
c_r <= {W{1'b0}};
|
c_r <= c & i_en;
|
||||||
c_r[0] <= c & i_en;
|
|
||||||
|
if (i_en)
|
||||||
|
data <= {i_init ? q : (data[31] & i_sh_signed), data[31:3]};
|
||||||
|
|
||||||
|
if (i_init ? (i_cnt0 | i_cnt1) : i_en)
|
||||||
|
lsb <= {i_init ? q : data[2],lsb[1]};
|
||||||
end
|
end
|
||||||
|
|
||||||
reg [1:0] lsb;
|
assign o_q = lsb[0] & i_en;
|
||||||
|
assign o_dbus_adr = {data, 2'b00};
|
||||||
generate
|
assign o_ext_rs1 = {o_dbus_adr[31:2],lsb};
|
||||||
if (W == 1) begin : gen_w_eq_1
|
|
||||||
always @(posedge i_clk) begin
|
|
||||||
if (i_en)
|
|
||||||
data[31:2] <= {i_init ? q : {W{data[31] & i_sh_signed}}, data[31:3]};
|
|
||||||
|
|
||||||
if (i_init ? (i_cnt0 | i_cnt1) : i_en)
|
|
||||||
data[1:0] <= {i_init ? q : data[2], data[1]};
|
|
||||||
end
|
|
||||||
always @(*) lsb = data[1:0];
|
|
||||||
assign o_q = data[0] & {W{i_en}};
|
|
||||||
end
|
|
||||||
endgenerate
|
|
||||||
|
|
||||||
|
|
||||||
assign o_dbus_adr = {data[31:2], 2'b00};
|
|
||||||
assign o_ext_rs1 = data;
|
|
||||||
assign o_lsb = (MDU & i_mdu_op) ? 2'b00 : lsb;
|
assign o_lsb = (MDU & i_mdu_op) ? 2'b00 : lsb;
|
||||||
|
|
||||||
endmodule
|
endmodule
|
||||||
|
|
|
@ -4,12 +4,11 @@ module serv_bufreg2
|
||||||
//State
|
//State
|
||||||
input wire i_en,
|
input wire i_en,
|
||||||
input wire i_init,
|
input wire i_init,
|
||||||
input wire i_cnt7,
|
|
||||||
input wire i_cnt_done,
|
input wire i_cnt_done,
|
||||||
input wire i_sh_right,
|
|
||||||
input wire [1:0] i_lsb,
|
input wire [1:0] i_lsb,
|
||||||
input wire [1:0] i_bytecnt,
|
input wire i_byte_valid,
|
||||||
output wire o_sh_done,
|
output wire o_sh_done,
|
||||||
|
output wire o_sh_done_r,
|
||||||
//Control
|
//Control
|
||||||
input wire i_op_b_sel,
|
input wire i_op_b_sel,
|
||||||
input wire i_shift_op,
|
input wire i_shift_op,
|
||||||
|
@ -25,46 +24,30 @@ module serv_bufreg2
|
||||||
|
|
||||||
reg [31:0] dat;
|
reg [31:0] dat;
|
||||||
|
|
||||||
/*
|
|
||||||
Before a store operation, the data to be written needs to be shifted into
|
|
||||||
place. Depending on the address alignment, we need to shift different
|
|
||||||
amounts. One formula for calculating this is to say that we shift when
|
|
||||||
i_lsb + i_bytecnt < 4. Unfortunately, the synthesis tools don't seem to be
|
|
||||||
clever enough so the hideous expression below is used to achieve the same
|
|
||||||
thing in a more optimal way.
|
|
||||||
*/
|
|
||||||
wire byte_valid
|
|
||||||
= (!i_lsb[0] & !i_lsb[1]) |
|
|
||||||
(!i_bytecnt[0] & !i_bytecnt[1]) |
|
|
||||||
(!i_bytecnt[1] & !i_lsb[1]) |
|
|
||||||
(!i_bytecnt[1] & !i_lsb[0]) |
|
|
||||||
(!i_bytecnt[0] & !i_lsb[1]);
|
|
||||||
|
|
||||||
assign o_op_b = i_op_b_sel ? i_rs2 : i_imm;
|
assign o_op_b = i_op_b_sel ? i_rs2 : i_imm;
|
||||||
|
|
||||||
wire shift_en = i_shift_op ? (i_en & i_init & (i_bytecnt == 2'b00)) : (i_en & byte_valid);
|
wire dat_en = i_shift_op | (i_en & i_byte_valid);
|
||||||
|
|
||||||
wire cnt_en = (i_shift_op & (!i_init | (i_cnt_done & i_sh_right)));
|
|
||||||
|
|
||||||
/* The dat register has three different use cases for store, load and
|
/* The dat register has three different use cases for store, load and
|
||||||
shift operations.
|
shift operations.
|
||||||
store : Data to be written is shifted to the correct position in dat during
|
store : Data to be written is shifted to the correct position in dat during
|
||||||
init by shift_en and is presented on the data bus as o_wb_dat
|
init by dat_en and is presented on the data bus as o_wb_dat
|
||||||
load : Data from the bus gets latched into dat during i_wb_ack and is then
|
load : Data from the bus gets latched into dat during i_wb_ack and is then
|
||||||
shifted out at the appropriate time to end up in the correct
|
shifted out at the appropriate time to end up in the correct
|
||||||
position in rd
|
position in rd
|
||||||
shift : Data is shifted in during init. After that, the six LSB are used as
|
shift : Data is shifted in during init. After that, the six LSB are used as
|
||||||
a downcounter (with bit 5 initially set to 0) that trigger
|
a downcounter (with bit 5 initially set to 0) that triggers
|
||||||
o_sh_done when they wrap around to indicate that
|
o_sh_done and o_sh_done_r when they wrap around to indicate that
|
||||||
the requested number of shifts have been performed
|
the requested number of shifts have been performed
|
||||||
*/
|
*/
|
||||||
wire [5:0] dat_shamt = cnt_en ?
|
wire [5:0] dat_shamt = (i_shift_op & !i_init) ?
|
||||||
//Down counter mode
|
//Down counter mode
|
||||||
dat[29:24]-1 :
|
dat[5:0]-1 :
|
||||||
//Shift reg mode with optional clearing of bit 5
|
//Shift reg mode with optional clearing of bit 5
|
||||||
{dat[30] & !(i_shift_op & i_cnt7),dat[29:25]};
|
{dat[6] & !(i_shift_op & i_cnt_done),dat[5:1]};
|
||||||
|
|
||||||
assign o_sh_done = dat_shamt[5];
|
assign o_sh_done = dat_shamt[5];
|
||||||
|
assign o_sh_done_r = dat[5];
|
||||||
|
|
||||||
assign o_q =
|
assign o_q =
|
||||||
((i_lsb == 2'd3) & dat[24]) |
|
((i_lsb == 2'd3) & dat[24]) |
|
||||||
|
@ -75,8 +58,8 @@ module serv_bufreg2
|
||||||
assign o_dat = dat;
|
assign o_dat = dat;
|
||||||
|
|
||||||
always @(posedge i_clk) begin
|
always @(posedge i_clk) begin
|
||||||
if (shift_en | cnt_en | i_load)
|
if (dat_en | i_load)
|
||||||
dat <= i_load ? i_dat : {o_op_b, dat[31], dat_shamt, dat[24:1]};
|
dat <= i_load ? i_dat : {o_op_b, dat[31:7], dat_shamt};
|
||||||
end
|
end
|
||||||
|
|
||||||
endmodule
|
endmodule
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
/* Copyright lowRISC contributors.
|
/* Copyright lowRISC contributors.
|
||||||
Copyright 2018 ETH Zurich and University of Bologna, see also CREDITS.md.
|
Copyright 2018 ETH Zurich and University of Bologna, see also CREDITS.md.
|
||||||
Licensed under the Apache License, Version 2.0, see LICENSE for details.
|
Licensed under the Apache License, Version 2.0, see LICENSE for details.
|
||||||
SPDX-License-Identifier: Apache-2.0
|
SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
* Adapted to SERV by @Abdulwadoodd as part of the project under spring '22 LFX Mentorship program */
|
* Adapted to SERV by @Abdulwadoodd as part of the project under spring '22 LFX Mentorship program */
|
||||||
|
|
||||||
/* Decodes RISC-V compressed instructions into their RV32i equivalent. */
|
/* Decodes RISC-V compressed instructions into their RV32i equivalent. */
|
||||||
|
|
||||||
module serv_compdec
|
module serv_compdec
|
||||||
(
|
(
|
||||||
input wire i_clk,
|
input wire i_clk,
|
||||||
input wire [31:0] i_instr,
|
input wire [31:0] i_instr,
|
||||||
|
@ -31,7 +31,7 @@ module serv_compdec
|
||||||
|
|
||||||
always @(posedge i_clk) begin
|
always @(posedge i_clk) begin
|
||||||
if(i_ack)
|
if(i_ack)
|
||||||
o_iscomp <= !illegal_instr;
|
o_iscomp <= !illegal_instr;
|
||||||
end
|
end
|
||||||
|
|
||||||
always @ (*) begin
|
always @ (*) begin
|
||||||
|
@ -71,7 +71,7 @@ module serv_compdec
|
||||||
end
|
end
|
||||||
|
|
||||||
// C1
|
// C1
|
||||||
|
|
||||||
// Register address checks for RV32E are performed in the regular instruction decoder.
|
// Register address checks for RV32E are performed in the regular instruction decoder.
|
||||||
// If this check fails, an illegal instruction exception is triggered and the controller
|
// If this check fails, an illegal instruction exception is triggered and the controller
|
||||||
// writes the actual faulting instruction to mtval.
|
// writes the actual faulting instruction to mtval.
|
||||||
|
@ -228,5 +228,7 @@ module serv_compdec
|
||||||
|
|
||||||
endcase
|
endcase
|
||||||
end
|
end
|
||||||
|
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,21 +1,15 @@
|
||||||
`default_nettype none
|
`default_nettype none
|
||||||
module serv_csr
|
module serv_csr
|
||||||
#(
|
#(parameter RESET_STRATEGY = "MINI")
|
||||||
parameter RESET_STRATEGY = "MINI",
|
|
||||||
parameter W = 1,
|
|
||||||
parameter B = W-1
|
|
||||||
)
|
|
||||||
(
|
(
|
||||||
input wire i_clk,
|
input wire i_clk,
|
||||||
input wire i_rst,
|
input wire i_rst,
|
||||||
//State
|
//State
|
||||||
input wire i_trig_irq,
|
input wire i_init,
|
||||||
input wire i_en,
|
input wire i_en,
|
||||||
input wire i_cnt0to3,
|
input wire i_cnt0to3,
|
||||||
input wire i_cnt3,
|
input wire i_cnt3,
|
||||||
input wire i_cnt7,
|
input wire i_cnt7,
|
||||||
input wire i_cnt11,
|
|
||||||
input wire i_cnt12,
|
|
||||||
input wire i_cnt_done,
|
input wire i_cnt_done,
|
||||||
input wire i_mem_op,
|
input wire i_mem_op,
|
||||||
input wire i_mtip,
|
input wire i_mtip,
|
||||||
|
@ -32,11 +26,11 @@ module serv_csr
|
||||||
input wire i_mret,
|
input wire i_mret,
|
||||||
input wire i_csr_d_sel,
|
input wire i_csr_d_sel,
|
||||||
//Data
|
//Data
|
||||||
input wire [B:0] i_rf_csr_out,
|
input wire i_rf_csr_out,
|
||||||
output wire [B:0] o_csr_in,
|
output wire o_csr_in,
|
||||||
input wire [B:0] i_csr_imm,
|
input wire i_csr_imm,
|
||||||
input wire [B:0] i_rs1,
|
input wire i_rs1,
|
||||||
output wire [B:0] o_q);
|
output wire o_q);
|
||||||
|
|
||||||
localparam [1:0]
|
localparam [1:0]
|
||||||
CSR_SOURCE_CSR = 2'b00,
|
CSR_SOURCE_CSR = 2'b00,
|
||||||
|
@ -50,53 +44,43 @@ module serv_csr
|
||||||
|
|
||||||
reg mcause31;
|
reg mcause31;
|
||||||
reg [3:0] mcause3_0;
|
reg [3:0] mcause3_0;
|
||||||
wire [B:0] mcause;
|
wire mcause;
|
||||||
|
|
||||||
wire [B:0] csr_in;
|
wire csr_in;
|
||||||
wire [B:0] csr_out;
|
wire csr_out;
|
||||||
|
|
||||||
reg timer_irq_r;
|
reg timer_irq_r;
|
||||||
|
|
||||||
wire [B:0] d = i_csr_d_sel ? i_csr_imm : i_rs1;
|
wire d = i_csr_d_sel ? i_csr_imm : i_rs1;
|
||||||
|
|
||||||
assign csr_in = (i_csr_source == CSR_SOURCE_EXT) ? d :
|
assign csr_in = (i_csr_source == CSR_SOURCE_EXT) ? d :
|
||||||
(i_csr_source == CSR_SOURCE_SET) ? csr_out | d :
|
(i_csr_source == CSR_SOURCE_SET) ? csr_out | d :
|
||||||
(i_csr_source == CSR_SOURCE_CLR) ? csr_out & ~d :
|
(i_csr_source == CSR_SOURCE_CLR) ? csr_out & ~d :
|
||||||
(i_csr_source == CSR_SOURCE_CSR) ? csr_out :
|
(i_csr_source == CSR_SOURCE_CSR) ? csr_out :
|
||||||
{W{1'bx}};
|
1'bx;
|
||||||
|
|
||||||
wire [B:0] mstatus;
|
assign csr_out = (i_mstatus_en & mstatus_mie & i_cnt3) |
|
||||||
|
|
||||||
generate
|
|
||||||
if (W==1) begin : gen_mstatus_w1
|
|
||||||
assign mstatus = ((mstatus_mie & i_cnt3) | (i_cnt11 | i_cnt12));
|
|
||||||
end else if (W==4) begin : gen_mstatus_w4
|
|
||||||
assign mstatus = {i_cnt11 | (mstatus_mie & i_cnt3), 2'b00, i_cnt12};
|
|
||||||
end
|
|
||||||
endgenerate
|
|
||||||
|
|
||||||
assign csr_out = ({W{i_mstatus_en & i_en}} & mstatus) |
|
|
||||||
i_rf_csr_out |
|
i_rf_csr_out |
|
||||||
({W{i_mcause_en & i_en}} & mcause);
|
(i_mcause_en & i_en & mcause);
|
||||||
|
|
||||||
assign o_q = csr_out;
|
assign o_q = csr_out;
|
||||||
|
|
||||||
wire timer_irq = i_mtip & mstatus_mie & mie_mtie;
|
wire timer_irq = i_mtip & mstatus_mie & mie_mtie;
|
||||||
|
|
||||||
assign mcause = i_cnt0to3 ? mcause3_0[B:0] : //[3:0]
|
assign mcause = i_cnt0to3 ? mcause3_0[0] : //[3:0]
|
||||||
i_cnt_done ? {mcause31,{B{1'b0}}} //[31]
|
i_cnt_done ? mcause31 //[31]
|
||||||
: {W{1'b0}};
|
: 1'b0;
|
||||||
|
|
||||||
assign o_csr_in = csr_in;
|
assign o_csr_in = csr_in;
|
||||||
|
|
||||||
always @(posedge i_clk) begin
|
always @(posedge i_clk) begin
|
||||||
if (i_trig_irq) begin
|
if (!i_init & i_cnt_done) begin
|
||||||
timer_irq_r <= timer_irq;
|
timer_irq_r <= timer_irq;
|
||||||
o_new_irq <= timer_irq & !timer_irq_r;
|
o_new_irq <= timer_irq & !timer_irq_r;
|
||||||
end
|
end
|
||||||
|
|
||||||
if (i_mie_en & i_cnt7)
|
if (i_mie_en & i_cnt7)
|
||||||
mie_mtie <= csr_in[B];
|
mie_mtie <= csr_in;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
The mie bit in mstatus gets updated under three conditions
|
The mie bit in mstatus gets updated under three conditions
|
||||||
|
@ -106,10 +90,10 @@ module serv_csr
|
||||||
During a mstatus CSR access instruction it's assigned when
|
During a mstatus CSR access instruction it's assigned when
|
||||||
bit 3 gets updated
|
bit 3 gets updated
|
||||||
|
|
||||||
These conditions are all mutually exclusive
|
These conditions are all mutually exclusibe
|
||||||
*/
|
*/
|
||||||
if ((i_trap & i_cnt_done) | i_mstatus_en & i_cnt3 & i_en | i_mret)
|
if ((i_trap & i_cnt_done) | i_mstatus_en & i_cnt3 | i_mret)
|
||||||
mstatus_mie <= !i_trap & (i_mret ? mstatus_mpie : csr_in[B]);
|
mstatus_mie <= !i_trap & (i_mret ? mstatus_mpie : csr_in);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Note: To save resources mstatus_mpie (mstatus bit 7) is not
|
Note: To save resources mstatus_mpie (mstatus bit 7) is not
|
||||||
|
@ -141,13 +125,13 @@ module serv_csr
|
||||||
ctrl => 0000 (jump=0)
|
ctrl => 0000 (jump=0)
|
||||||
*/
|
*/
|
||||||
if (i_mcause_en & i_en & i_cnt0to3 | (i_trap & i_cnt_done)) begin
|
if (i_mcause_en & i_en & i_cnt0to3 | (i_trap & i_cnt_done)) begin
|
||||||
mcause3_0[3] <= (i_e_op & !i_ebreak) | (!i_trap & csr_in[B]);
|
mcause3_0[3] <= (i_e_op & !i_ebreak) | (!i_trap & csr_in);
|
||||||
mcause3_0[2] <= o_new_irq | i_mem_op | (!i_trap & ((W == 1) ? mcause3_0[3] : csr_in[(W == 1) ? 0 : 2]));
|
mcause3_0[2] <= o_new_irq | i_mem_op | (!i_trap & mcause3_0[3]);
|
||||||
mcause3_0[1] <= o_new_irq | i_e_op | (i_mem_op & i_mem_cmd) | (!i_trap & ((W == 1) ? mcause3_0[2] : csr_in[(W == 1) ? 0 : 1]));
|
mcause3_0[1] <= o_new_irq | i_e_op | (i_mem_op & i_mem_cmd) | (!i_trap & mcause3_0[2]);
|
||||||
mcause3_0[0] <= o_new_irq | i_e_op | (!i_trap & ((W == 1) ? mcause3_0[1] : csr_in[0]));
|
mcause3_0[0] <= o_new_irq | i_e_op | (!i_trap & mcause3_0[1]);
|
||||||
end
|
end
|
||||||
if (i_mcause_en & i_cnt_done | i_trap)
|
if (i_mcause_en & i_cnt_done | i_trap)
|
||||||
mcause31 <= i_trap ? o_new_irq : csr_in[B];
|
mcause31 <= i_trap ? o_new_irq : csr_in;
|
||||||
if (i_rst)
|
if (i_rst)
|
||||||
if (RESET_STRATEGY != "NONE") begin
|
if (RESET_STRATEGY != "NONE") begin
|
||||||
o_new_irq <= 1'b0;
|
o_new_irq <= 1'b0;
|
||||||
|
|
|
@ -2,10 +2,7 @@
|
||||||
module serv_ctrl
|
module serv_ctrl
|
||||||
#(parameter RESET_STRATEGY = "MINI",
|
#(parameter RESET_STRATEGY = "MINI",
|
||||||
parameter RESET_PC = 32'd0,
|
parameter RESET_PC = 32'd0,
|
||||||
parameter WITH_CSR = 1,
|
parameter WITH_CSR = 1)
|
||||||
parameter W = 1,
|
|
||||||
parameter B = W-1
|
|
||||||
)
|
|
||||||
(
|
(
|
||||||
input wire clk,
|
input wire clk,
|
||||||
input wire i_rst,
|
input wire i_rst,
|
||||||
|
@ -23,74 +20,51 @@ module serv_ctrl
|
||||||
input wire i_trap,
|
input wire i_trap,
|
||||||
input wire i_iscomp,
|
input wire i_iscomp,
|
||||||
//Data
|
//Data
|
||||||
input wire [B:0] i_imm,
|
input wire i_imm,
|
||||||
input wire [B:0] i_buf,
|
input wire i_buf,
|
||||||
input wire [B:0] i_csr_pc,
|
input wire i_csr_pc,
|
||||||
output wire [B:0] o_rd,
|
output wire o_rd,
|
||||||
output wire [B:0] o_bad_pc,
|
output wire o_bad_pc,
|
||||||
//External
|
//External
|
||||||
output reg [31:0] o_ibus_adr);
|
output reg [31:0] o_ibus_adr);
|
||||||
|
|
||||||
wire [B:0] pc_plus_4;
|
wire pc_plus_4;
|
||||||
wire pc_plus_4_cy;
|
wire pc_plus_4_cy;
|
||||||
reg pc_plus_4_cy_r;
|
reg pc_plus_4_cy_r;
|
||||||
wire [B:0] pc_plus_4_cy_r_w;
|
wire pc_plus_offset;
|
||||||
wire [B:0] pc_plus_offset;
|
|
||||||
wire pc_plus_offset_cy;
|
wire pc_plus_offset_cy;
|
||||||
reg pc_plus_offset_cy_r;
|
reg pc_plus_offset_cy_r;
|
||||||
wire [B:0] pc_plus_offset_cy_r_w;
|
wire pc_plus_offset_aligned;
|
||||||
wire [B:0] pc_plus_offset_aligned;
|
wire plus_4;
|
||||||
wire [B:0] plus_4;
|
|
||||||
|
|
||||||
wire [B:0] pc = o_ibus_adr[B:0];
|
wire pc = o_ibus_adr[0];
|
||||||
|
|
||||||
wire [B:0] new_pc;
|
wire new_pc;
|
||||||
|
|
||||||
wire [B:0] offset_a;
|
wire offset_a;
|
||||||
wire [B:0] offset_b;
|
wire offset_b;
|
||||||
|
|
||||||
/* If i_iscomp=1: increment pc by 2 else increment pc by 4 */
|
/* If i_iscomp=1: increment pc by 2 else increment pc by 4 */
|
||||||
|
|
||||||
generate
|
assign plus_4 = i_iscomp ? i_cnt1 : i_cnt2;
|
||||||
if (W == 1) begin : gen_plus_4_w_eq_1
|
|
||||||
assign plus_4 = i_iscomp ? i_cnt1 : i_cnt2;
|
|
||||||
end else if (W == 4) begin : gen_plus_4_w_eq_4
|
|
||||||
assign plus_4 = (i_cnt0 | i_cnt1) ? (i_iscomp ? 2 : 4) : 0;
|
|
||||||
end
|
|
||||||
endgenerate
|
|
||||||
|
|
||||||
assign o_bad_pc = pc_plus_offset_aligned;
|
assign o_bad_pc = pc_plus_offset_aligned;
|
||||||
|
|
||||||
assign {pc_plus_4_cy,pc_plus_4} = pc+plus_4+pc_plus_4_cy_r_w;
|
assign {pc_plus_4_cy,pc_plus_4} = pc+plus_4+pc_plus_4_cy_r;
|
||||||
|
|
||||||
generate
|
generate
|
||||||
if (|WITH_CSR) begin : gen_csr
|
if (|WITH_CSR)
|
||||||
if (W == 1) begin : gen_new_pc_w_eq_1
|
assign new_pc = i_trap ? (i_csr_pc & !i_cnt0) : i_jump ? pc_plus_offset_aligned : pc_plus_4;
|
||||||
assign new_pc = i_trap ? (i_csr_pc & !(i_cnt0 || i_cnt1)) : i_jump ? pc_plus_offset_aligned : pc_plus_4;
|
else
|
||||||
end else if (W == 4) begin : gen_new_pc_w_eq_4
|
assign new_pc = i_jump ? pc_plus_offset_aligned : pc_plus_4;
|
||||||
assign new_pc = i_trap ? (i_csr_pc & ((i_cnt0 || i_cnt1) ? 4'b1100 : 4'b1111)) : i_jump ? pc_plus_offset_aligned : pc_plus_4;
|
|
||||||
end
|
|
||||||
end else begin : gen_no_csr
|
|
||||||
assign new_pc = i_jump ? pc_plus_offset_aligned : pc_plus_4;
|
|
||||||
end
|
|
||||||
endgenerate
|
endgenerate
|
||||||
assign o_rd = ({W{i_utype}} & pc_plus_offset_aligned) | (pc_plus_4 & {W{i_jal_or_jalr}});
|
assign o_rd = (i_utype & pc_plus_offset_aligned) | (pc_plus_4 & i_jal_or_jalr);
|
||||||
|
|
||||||
assign offset_a = {W{i_pc_rel}} & pc;
|
assign offset_a = i_pc_rel & pc;
|
||||||
assign offset_b = i_utype ? (i_imm & {W{i_cnt12to31}}) : i_buf;
|
assign offset_b = i_utype ? (i_imm & i_cnt12to31): i_buf;
|
||||||
assign {pc_plus_offset_cy,pc_plus_offset} = offset_a+offset_b+pc_plus_offset_cy_r_w;
|
assign {pc_plus_offset_cy,pc_plus_offset} = offset_a+offset_b+pc_plus_offset_cy_r;
|
||||||
|
|
||||||
generate
|
assign pc_plus_offset_aligned = pc_plus_offset & !i_cnt0;
|
||||||
if (W>1) begin : gen_w_gt_1
|
|
||||||
assign pc_plus_offset_aligned[B:1] = pc_plus_offset[B:1];
|
|
||||||
assign pc_plus_offset_cy_r_w[B:1] = {B{1'b0}};
|
|
||||||
assign pc_plus_4_cy_r_w[B:1] = {B{1'b0}};
|
|
||||||
end
|
|
||||||
endgenerate
|
|
||||||
|
|
||||||
assign pc_plus_offset_aligned[0] = pc_plus_offset[0] & !i_cnt0;
|
|
||||||
assign pc_plus_offset_cy_r_w[0] = pc_plus_offset_cy_r;
|
|
||||||
assign pc_plus_4_cy_r_w[0] = pc_plus_4_cy_r;
|
|
||||||
|
|
||||||
initial if (RESET_STRATEGY == "NONE") o_ibus_adr = RESET_PC;
|
initial if (RESET_STRATEGY == "NONE") o_ibus_adr = RESET_PC;
|
||||||
|
|
||||||
|
@ -100,10 +74,10 @@ module serv_ctrl
|
||||||
|
|
||||||
if (RESET_STRATEGY == "NONE") begin
|
if (RESET_STRATEGY == "NONE") begin
|
||||||
if (i_pc_en)
|
if (i_pc_en)
|
||||||
o_ibus_adr <= {new_pc, o_ibus_adr[31:W]};
|
o_ibus_adr <= {new_pc, o_ibus_adr[31:1]};
|
||||||
end else begin
|
end else begin
|
||||||
if (i_pc_en | i_rst)
|
if (i_pc_en | i_rst)
|
||||||
o_ibus_adr <= i_rst ? RESET_PC : {new_pc, o_ibus_adr[31:W]};
|
o_ibus_adr <= i_rst ? RESET_PC : {new_pc, o_ibus_adr[31:1]};
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
endmodule
|
endmodule
|
||||||
|
|
345
rtl/serv_debug.v
345
rtl/serv_debug.v
|
@ -1,345 +0,0 @@
|
||||||
module serv_debug
|
|
||||||
#(parameter W = 1,
|
|
||||||
parameter RESET_PC = 0,
|
|
||||||
//Internally calculated. Do not touch
|
|
||||||
parameter B=W-1)
|
|
||||||
(
|
|
||||||
`ifdef RISCV_FORMAL
|
|
||||||
output reg rvfi_valid = 1'b0,
|
|
||||||
output reg [63:0] rvfi_order = 64'd0,
|
|
||||||
output reg [31:0] rvfi_insn = 32'd0,
|
|
||||||
output reg rvfi_trap = 1'b0,
|
|
||||||
output reg rvfi_halt = 1'b0, // Not used
|
|
||||||
output reg rvfi_intr = 1'b0, // Not used
|
|
||||||
output reg [1:0] rvfi_mode = 2'b11, // Not used
|
|
||||||
output reg [1:0] rvfi_ixl = 2'b01, // Not used
|
|
||||||
output reg [4:0] rvfi_rs1_addr,
|
|
||||||
output reg [4:0] rvfi_rs2_addr,
|
|
||||||
output reg [31:0] rvfi_rs1_rdata,
|
|
||||||
output reg [31:0] rvfi_rs2_rdata,
|
|
||||||
output reg [4:0] rvfi_rd_addr,
|
|
||||||
output wire [31:0] rvfi_rd_wdata,
|
|
||||||
output reg [31:0] rvfi_pc_rdata,
|
|
||||||
output wire [31:0] rvfi_pc_wdata,
|
|
||||||
output reg [31:0] rvfi_mem_addr,
|
|
||||||
output reg [3:0] rvfi_mem_rmask,
|
|
||||||
output reg [3:0] rvfi_mem_wmask,
|
|
||||||
output reg [31:0] rvfi_mem_rdata,
|
|
||||||
output reg [31:0] rvfi_mem_wdata,
|
|
||||||
input wire [31:0] i_dbus_adr,
|
|
||||||
input wire [31:0] i_dbus_dat,
|
|
||||||
input wire [3:0] i_dbus_sel,
|
|
||||||
input wire i_dbus_we,
|
|
||||||
input wire [31:0] i_dbus_rdt,
|
|
||||||
input wire i_dbus_ack,
|
|
||||||
input wire i_ctrl_pc_en,
|
|
||||||
input wire [B:0] rs1,
|
|
||||||
input wire [B:0] rs2,
|
|
||||||
input wire [4:0] rs1_addr,
|
|
||||||
input wire [4:0] rs2_addr,
|
|
||||||
input wire [3:0] immdec_en,
|
|
||||||
input wire rd_en,
|
|
||||||
input wire trap,
|
|
||||||
input wire i_rf_ready,
|
|
||||||
input wire i_ibus_cyc,
|
|
||||||
input wire two_stage_op,
|
|
||||||
input wire init,
|
|
||||||
input wire [31:0] i_ibus_adr,
|
|
||||||
`endif
|
|
||||||
input wire i_clk,
|
|
||||||
input wire i_rst,
|
|
||||||
input wire [31:0] i_ibus_rdt,
|
|
||||||
input wire i_ibus_ack,
|
|
||||||
input wire [4:0] i_rd_addr,
|
|
||||||
input wire i_cnt_en,
|
|
||||||
input wire [B:0] i_csr_in,
|
|
||||||
input wire i_csr_mstatus_en,
|
|
||||||
input wire i_csr_mie_en,
|
|
||||||
input wire i_csr_mcause_en,
|
|
||||||
input wire i_csr_en,
|
|
||||||
input wire [1:0] i_csr_addr,
|
|
||||||
input wire i_wen0,
|
|
||||||
input wire [B:0] i_wdata0,
|
|
||||||
input wire i_cnt_done);
|
|
||||||
|
|
||||||
reg update_rd = 1'b0;
|
|
||||||
reg update_mscratch;
|
|
||||||
reg update_mtvec;
|
|
||||||
reg update_mepc;
|
|
||||||
reg update_mtval;
|
|
||||||
reg update_mstatus;
|
|
||||||
reg update_mie;
|
|
||||||
reg update_mcause;
|
|
||||||
|
|
||||||
reg [31:0] dbg_rd = 32'hxxxxxxxx;
|
|
||||||
reg [31:0] dbg_csr = 32'hxxxxxxxx;
|
|
||||||
reg [31:0] dbg_mstatus = 32'hxxxxxxxx;
|
|
||||||
reg [31:0] dbg_mie = 32'hxxxxxxxx;
|
|
||||||
reg [31:0] dbg_mcause = 32'hxxxxxxxx;
|
|
||||||
reg [31:0] dbg_mscratch = 32'hxxxxxxxx;
|
|
||||||
reg [31:0] dbg_mtvec = 32'hxxxxxxxx;
|
|
||||||
reg [31:0] dbg_mepc = 32'hxxxxxxxx;
|
|
||||||
reg [31:0] dbg_mtval = 32'hxxxxxxxx;
|
|
||||||
reg [31:0] x1 = 32'hxxxxxxxx;
|
|
||||||
reg [31:0] x2 = 32'hxxxxxxxx;
|
|
||||||
reg [31:0] x3 = 32'hxxxxxxxx;
|
|
||||||
reg [31:0] x4 = 32'hxxxxxxxx;
|
|
||||||
reg [31:0] x5 = 32'hxxxxxxxx;
|
|
||||||
reg [31:0] x6 = 32'hxxxxxxxx;
|
|
||||||
reg [31:0] x7 = 32'hxxxxxxxx;
|
|
||||||
reg [31:0] x8 = 32'hxxxxxxxx;
|
|
||||||
reg [31:0] x9 = 32'hxxxxxxxx;
|
|
||||||
reg [31:0] x10 = 32'hxxxxxxxx;
|
|
||||||
reg [31:0] x11 = 32'hxxxxxxxx;
|
|
||||||
reg [31:0] x12 = 32'hxxxxxxxx;
|
|
||||||
reg [31:0] x13 = 32'hxxxxxxxx;
|
|
||||||
reg [31:0] x14 = 32'hxxxxxxxx;
|
|
||||||
reg [31:0] x15 = 32'hxxxxxxxx;
|
|
||||||
reg [31:0] x16 = 32'hxxxxxxxx;
|
|
||||||
reg [31:0] x17 = 32'hxxxxxxxx;
|
|
||||||
reg [31:0] x18 = 32'hxxxxxxxx;
|
|
||||||
reg [31:0] x19 = 32'hxxxxxxxx;
|
|
||||||
reg [31:0] x20 = 32'hxxxxxxxx;
|
|
||||||
reg [31:0] x21 = 32'hxxxxxxxx;
|
|
||||||
reg [31:0] x22 = 32'hxxxxxxxx;
|
|
||||||
reg [31:0] x23 = 32'hxxxxxxxx;
|
|
||||||
reg [31:0] x24 = 32'hxxxxxxxx;
|
|
||||||
reg [31:0] x25 = 32'hxxxxxxxx;
|
|
||||||
reg [31:0] x26 = 32'hxxxxxxxx;
|
|
||||||
reg [31:0] x27 = 32'hxxxxxxxx;
|
|
||||||
reg [31:0] x28 = 32'hxxxxxxxx;
|
|
||||||
reg [31:0] x29 = 32'hxxxxxxxx;
|
|
||||||
reg [31:0] x30 = 32'hxxxxxxxx;
|
|
||||||
reg [31:0] x31 = 32'hxxxxxxxx;
|
|
||||||
|
|
||||||
always @(posedge i_clk) begin
|
|
||||||
update_rd <= i_cnt_done & i_wen0;
|
|
||||||
|
|
||||||
if (i_wen0)
|
|
||||||
dbg_rd <= {i_wdata0,dbg_rd[31:W]};
|
|
||||||
|
|
||||||
//End of instruction that writes to RF
|
|
||||||
if (update_rd) begin
|
|
||||||
case (i_rd_addr)
|
|
||||||
5'd1 : x1 <= dbg_rd;
|
|
||||||
5'd2 : x2 <= dbg_rd;
|
|
||||||
5'd3 : x3 <= dbg_rd;
|
|
||||||
5'd4 : x4 <= dbg_rd;
|
|
||||||
5'd5 : x5 <= dbg_rd;
|
|
||||||
5'd6 : x6 <= dbg_rd;
|
|
||||||
5'd7 : x7 <= dbg_rd;
|
|
||||||
5'd8 : x8 <= dbg_rd;
|
|
||||||
5'd9 : x9 <= dbg_rd;
|
|
||||||
5'd10 : x10 <= dbg_rd;
|
|
||||||
5'd11 : x11 <= dbg_rd;
|
|
||||||
5'd12 : x12 <= dbg_rd;
|
|
||||||
5'd13 : x13 <= dbg_rd;
|
|
||||||
5'd14 : x14 <= dbg_rd;
|
|
||||||
5'd15 : x15 <= dbg_rd;
|
|
||||||
5'd16 : x16 <= dbg_rd;
|
|
||||||
5'd17 : x17 <= dbg_rd;
|
|
||||||
5'd18 : x18 <= dbg_rd;
|
|
||||||
5'd19 : x19 <= dbg_rd;
|
|
||||||
5'd20 : x20 <= dbg_rd;
|
|
||||||
5'd21 : x21 <= dbg_rd;
|
|
||||||
5'd22 : x22 <= dbg_rd;
|
|
||||||
5'd23 : x23 <= dbg_rd;
|
|
||||||
5'd24 : x24 <= dbg_rd;
|
|
||||||
5'd25 : x25 <= dbg_rd;
|
|
||||||
5'd26 : x26 <= dbg_rd;
|
|
||||||
5'd27 : x27 <= dbg_rd;
|
|
||||||
5'd28 : x28 <= dbg_rd;
|
|
||||||
5'd29 : x29 <= dbg_rd;
|
|
||||||
5'd30 : x30 <= dbg_rd;
|
|
||||||
5'd31 : x31 <= dbg_rd;
|
|
||||||
default : ;
|
|
||||||
endcase
|
|
||||||
end
|
|
||||||
|
|
||||||
update_mscratch <= i_cnt_done & i_csr_en & (i_csr_addr == 2'b00);
|
|
||||||
update_mtvec <= i_cnt_done & i_csr_en & (i_csr_addr == 2'b01);
|
|
||||||
update_mepc <= i_cnt_done & i_csr_en & (i_csr_addr == 2'b10);
|
|
||||||
update_mtval <= i_cnt_done & i_csr_en & (i_csr_addr == 2'b11);
|
|
||||||
update_mstatus <= i_cnt_done & i_csr_mstatus_en;
|
|
||||||
update_mie <= i_cnt_done & i_csr_mie_en;
|
|
||||||
update_mcause <= i_cnt_done & i_csr_mcause_en;
|
|
||||||
|
|
||||||
if (i_cnt_en)
|
|
||||||
dbg_csr <= {i_csr_in, dbg_csr[31:W]};
|
|
||||||
|
|
||||||
if (update_mscratch) dbg_mscratch <= dbg_csr;
|
|
||||||
if (update_mtvec) dbg_mtvec <= dbg_csr;
|
|
||||||
if (update_mepc ) dbg_mepc <= dbg_csr;
|
|
||||||
if (update_mtval) dbg_mtval <= dbg_csr;
|
|
||||||
if (update_mstatus) dbg_mstatus <= dbg_csr;
|
|
||||||
if (update_mie) dbg_mie <= dbg_csr;
|
|
||||||
if (update_mcause) dbg_mcause <= dbg_csr;
|
|
||||||
end
|
|
||||||
|
|
||||||
reg LUI, AUIPC, JAL, JALR, BEQ, BNE, BLT, BGE, BLTU, BGEU, LB, LH, LW, LBU, LHU, SB, SH, SW, ADDI, SLTI, SLTIU, XORI, ORI, ANDI,SLLI, SRLI, SRAI, ADD, SUB, SLL, SLT, SLTU, XOR, SRL, SRA, OR, AND, FENCE, ECALL, EBREAK;
|
|
||||||
reg CSRRW, CSRRS, CSRRC, CSRRWI, CSRRSI, CSRRCI;
|
|
||||||
reg OTHER;
|
|
||||||
|
|
||||||
always @(posedge i_clk) begin
|
|
||||||
if (i_ibus_ack) begin
|
|
||||||
LUI <= 1'b0;
|
|
||||||
AUIPC <= 1'b0;
|
|
||||||
JAL <= 1'b0;
|
|
||||||
JALR <= 1'b0;
|
|
||||||
BEQ <= 1'b0;
|
|
||||||
BNE <= 1'b0;
|
|
||||||
BLT <= 1'b0;
|
|
||||||
BGE <= 1'b0;
|
|
||||||
BLTU <= 1'b0;
|
|
||||||
BGEU <= 1'b0;
|
|
||||||
LB <= 1'b0;
|
|
||||||
LH <= 1'b0;
|
|
||||||
LW <= 1'b0;
|
|
||||||
LBU <= 1'b0;
|
|
||||||
LHU <= 1'b0;
|
|
||||||
SB <= 1'b0;
|
|
||||||
SH <= 1'b0;
|
|
||||||
SW <= 1'b0;
|
|
||||||
ADDI <= 1'b0;
|
|
||||||
SLTI <= 1'b0;
|
|
||||||
SLTIU <= 1'b0;
|
|
||||||
XORI <= 1'b0;
|
|
||||||
ORI <= 1'b0;
|
|
||||||
ANDI <= 1'b0;
|
|
||||||
SLLI <= 1'b0;
|
|
||||||
SRLI <= 1'b0;
|
|
||||||
SRAI <= 1'b0;
|
|
||||||
ADD <= 1'b0;
|
|
||||||
SUB <= 1'b0;
|
|
||||||
SLL <= 1'b0;
|
|
||||||
SLT <= 1'b0;
|
|
||||||
SLTU <= 1'b0;
|
|
||||||
XOR <= 1'b0;
|
|
||||||
SRL <= 1'b0;
|
|
||||||
SRA <= 1'b0;
|
|
||||||
OR <= 1'b0;
|
|
||||||
AND <= 1'b0;
|
|
||||||
FENCE <= 1'b0;
|
|
||||||
ECALL <= 1'b0;
|
|
||||||
EBREAK <= 1'b0;
|
|
||||||
CSRRW <= 1'b0;
|
|
||||||
CSRRS <= 1'b0;
|
|
||||||
CSRRC <= 1'b0;
|
|
||||||
CSRRWI <= 1'b0;
|
|
||||||
CSRRSI <= 1'b0;
|
|
||||||
CSRRCI <= 1'b0;
|
|
||||||
OTHER <= 1'b0;
|
|
||||||
|
|
||||||
casez(i_ibus_rdt)
|
|
||||||
// 3322222_22222 11111_111 11
|
|
||||||
// 1098765_43210 98765_432 10987_65432_10
|
|
||||||
32'b???????_?????_?????_???_?????_01101_11 : LUI <= 1'b1;
|
|
||||||
32'b???????_?????_?????_???_?????_00101_11 : AUIPC <= 1'b1;
|
|
||||||
32'b???????_?????_?????_???_?????_11011_11 : JAL <= 1'b1;
|
|
||||||
32'b???????_?????_?????_000_?????_11001_11 : JALR <= 1'b1;
|
|
||||||
32'b???????_?????_?????_000_?????_11000_11 : BEQ <= 1'b1;
|
|
||||||
32'b???????_?????_?????_001_?????_11000_11 : BNE <= 1'b1;
|
|
||||||
32'b???????_?????_?????_100_?????_11000_11 : BLT <= 1'b1;
|
|
||||||
32'b???????_?????_?????_101_?????_11000_11 : BGE <= 1'b1;
|
|
||||||
32'b???????_?????_?????_110_?????_11000_11 : BLTU <= 1'b1;
|
|
||||||
32'b???????_?????_?????_111_?????_11000_11 : BGEU <= 1'b1;
|
|
||||||
32'b???????_?????_?????_000_?????_00000_11 : LB <= 1'b1;
|
|
||||||
32'b???????_?????_?????_001_?????_00000_11 : LH <= 1'b1;
|
|
||||||
32'b???????_?????_?????_010_?????_00000_11 : LW <= 1'b1;
|
|
||||||
32'b???????_?????_?????_100_?????_00000_11 : LBU <= 1'b1;
|
|
||||||
32'b???????_?????_?????_101_?????_00000_11 : LHU <= 1'b1;
|
|
||||||
32'b???????_?????_?????_000_?????_01000_11 : SB <= 1'b1;
|
|
||||||
32'b???????_?????_?????_001_?????_01000_11 : SH <= 1'b1;
|
|
||||||
32'b???????_?????_?????_010_?????_01000_11 : SW <= 1'b1;
|
|
||||||
32'b???????_?????_?????_000_?????_00100_11 : ADDI <= 1'b1;
|
|
||||||
32'b???????_?????_?????_010_?????_00100_11 : SLTI <= 1'b1;
|
|
||||||
32'b???????_?????_?????_011_?????_00100_11 : SLTIU <= 1'b1;
|
|
||||||
32'b???????_?????_?????_100_?????_00100_11 : XORI <= 1'b1;
|
|
||||||
32'b???????_?????_?????_110_?????_00100_11 : ORI <= 1'b1;
|
|
||||||
32'b???????_?????_?????_111_?????_00100_11 : ANDI <= 1'b1;
|
|
||||||
32'b0000000_?????_?????_001_?????_00100_11 : SLLI <= 1'b1;
|
|
||||||
32'b0000000_?????_?????_101_?????_00100_11 : SRLI <= 1'b1;
|
|
||||||
32'b0100000_?????_?????_101_?????_00100_11 : SRAI <= 1'b1;
|
|
||||||
32'b0000000_?????_?????_000_?????_01100_11 : ADD <= 1'b1;
|
|
||||||
32'b0100000_?????_?????_000_?????_01100_11 : SUB <= 1'b1;
|
|
||||||
32'b0000000_?????_?????_001_?????_01100_11 : SLL <= 1'b1;
|
|
||||||
32'b0000000_?????_?????_010_?????_01100_11 : SLT <= 1'b1;
|
|
||||||
32'b0000000_?????_?????_011_?????_01100_11 : SLTU <= 1'b1;
|
|
||||||
32'b???????_?????_?????_100_?????_01100_11 : XOR <= 1'b1;
|
|
||||||
32'b0000000_?????_?????_101_?????_01100_11 : SRL <= 1'b1;
|
|
||||||
32'b0100000_?????_?????_101_?????_01100_11 : SRA <= 1'b1;
|
|
||||||
32'b???????_?????_?????_110_?????_01100_11 : OR <= 1'b1;
|
|
||||||
32'b???????_?????_?????_111_?????_01100_11 : AND <= 1'b1;
|
|
||||||
32'b???????_?????_?????_000_?????_00011_11 : FENCE <= 1'b1;
|
|
||||||
32'b0000000_00000_00000_000_00000_11100_11 : ECALL <= 1'b1;
|
|
||||||
32'b0000000_00001_00000_000_00000_11100_11 : EBREAK <= 1'b1;
|
|
||||||
32'b???????_?????_?????_001_?????_11100_11 : CSRRW <= 1'b1;
|
|
||||||
32'b???????_?????_?????_010_?????_11100_11 : CSRRS <= 1'b1;
|
|
||||||
32'b???????_?????_?????_011_?????_11100_11 : CSRRC <= 1'b1;
|
|
||||||
32'b???????_?????_?????_101_?????_11100_11 : CSRRWI <= 1'b1;
|
|
||||||
32'b???????_?????_?????_110_?????_11100_11 : CSRRSI <= 1'b1;
|
|
||||||
32'b???????_?????_?????_111_?????_11100_11 : CSRRCI <= 1'b1;
|
|
||||||
default : OTHER <= 1'b1;
|
|
||||||
endcase
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
`ifdef RISCV_FORMAL
|
|
||||||
reg [31:0] pc = RESET_PC;
|
|
||||||
|
|
||||||
wire rs_en = two_stage_op ? init : i_ctrl_pc_en;
|
|
||||||
|
|
||||||
assign rvfi_rd_wdata = update_rd ? dbg_rd : 32'd0;
|
|
||||||
|
|
||||||
always @(posedge i_clk) begin
|
|
||||||
/* End of instruction */
|
|
||||||
rvfi_valid <= i_cnt_done & i_ctrl_pc_en & !i_rst;
|
|
||||||
rvfi_order <= rvfi_order + {63'd0,rvfi_valid};
|
|
||||||
|
|
||||||
/* Get instruction word when it's fetched from ibus */
|
|
||||||
if (i_ibus_cyc & i_ibus_ack)
|
|
||||||
rvfi_insn <= i_ibus_rdt;
|
|
||||||
|
|
||||||
|
|
||||||
if (i_cnt_done & i_ctrl_pc_en) begin
|
|
||||||
rvfi_pc_rdata <= pc;
|
|
||||||
if (!(rd_en & (|i_rd_addr))) begin
|
|
||||||
rvfi_rd_addr <= 5'd0;
|
|
||||||
end
|
|
||||||
end
|
|
||||||
rvfi_trap <= trap;
|
|
||||||
if (rvfi_valid) begin
|
|
||||||
rvfi_trap <= 1'b0;
|
|
||||||
pc <= rvfi_pc_wdata;
|
|
||||||
end
|
|
||||||
|
|
||||||
/* RS1 not valid during J, U instructions (immdec_en[1]) */
|
|
||||||
/* RS2 not valid during I, J, U instructions (immdec_en[2]) */
|
|
||||||
if (i_rf_ready) begin
|
|
||||||
rvfi_rs1_addr <= !immdec_en[1] ? rs1_addr : 5'd0;
|
|
||||||
rvfi_rs2_addr <= !immdec_en[2] /*rs2_valid*/ ? rs2_addr : 5'd0;
|
|
||||||
rvfi_rd_addr <= i_rd_addr;
|
|
||||||
end
|
|
||||||
if (rs_en) begin
|
|
||||||
rvfi_rs1_rdata <= {(!immdec_en[1] ? rs1 : {W{1'b0}}),rvfi_rs1_rdata[31:W]};
|
|
||||||
rvfi_rs2_rdata <= {(!immdec_en[2] ? rs2 : {W{1'b0}}),rvfi_rs2_rdata[31:W]};
|
|
||||||
end
|
|
||||||
|
|
||||||
if (i_dbus_ack) begin
|
|
||||||
rvfi_mem_addr <= i_dbus_adr;
|
|
||||||
rvfi_mem_rmask <= i_dbus_we ? 4'b0000 : i_dbus_sel;
|
|
||||||
rvfi_mem_wmask <= i_dbus_we ? i_dbus_sel : 4'b0000;
|
|
||||||
rvfi_mem_rdata <= i_dbus_rdt;
|
|
||||||
rvfi_mem_wdata <= i_dbus_dat;
|
|
||||||
end
|
|
||||||
if (i_ibus_ack) begin
|
|
||||||
rvfi_mem_rmask <= 4'b0000;
|
|
||||||
rvfi_mem_wmask <= 4'b0000;
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
assign rvfi_pc_wdata = i_ibus_adr;
|
|
||||||
|
|
||||||
`endif
|
|
||||||
|
|
||||||
endmodule
|
|
|
@ -15,6 +15,7 @@ module serv_decode
|
||||||
output reg o_ebreak,
|
output reg o_ebreak,
|
||||||
output reg o_branch_op,
|
output reg o_branch_op,
|
||||||
output reg o_shift_op,
|
output reg o_shift_op,
|
||||||
|
output reg o_slt_or_branch,
|
||||||
output reg o_rd_op,
|
output reg o_rd_op,
|
||||||
output reg o_two_stage_op,
|
output reg o_two_stage_op,
|
||||||
output reg o_dbus_en,
|
output reg o_dbus_en,
|
||||||
|
@ -78,9 +79,10 @@ module serv_decode
|
||||||
~opcode[2] | (funct3[0] & ~funct3[1] & ~opcode[0] & ~opcode[4]) |
|
~opcode[2] | (funct3[0] & ~funct3[1] & ~opcode[0] & ~opcode[4]) |
|
||||||
(funct3[1] & ~funct3[2] & ~opcode[0] & ~opcode[4]) | co_mdu_op;
|
(funct3[1] & ~funct3[2] & ~opcode[0] & ~opcode[4]) | co_mdu_op;
|
||||||
wire co_shift_op = (opcode[2] & ~funct3[1]) & !co_mdu_op;
|
wire co_shift_op = (opcode[2] & ~funct3[1]) & !co_mdu_op;
|
||||||
|
wire co_slt_or_branch = (opcode[4] | (funct3[1] & opcode[2]) | (imm30 & opcode[2] & opcode[3] & ~funct3[2])) & !co_mdu_op;
|
||||||
wire co_branch_op = opcode[4];
|
wire co_branch_op = opcode[4];
|
||||||
wire co_dbus_en = ~opcode[2] & ~opcode[4];
|
wire co_dbus_en = ~opcode[2] & ~opcode[4];
|
||||||
wire co_mtval_pc = opcode[4];
|
wire co_mtval_pc = opcode[4];
|
||||||
wire co_mem_word = funct3[1];
|
wire co_mem_word = funct3[1];
|
||||||
wire co_rd_alu_en = !opcode[0] & opcode[2] & !opcode[4] & !co_mdu_op;
|
wire co_rd_alu_en = !opcode[0] & opcode[2] & !opcode[4] & !co_mdu_op;
|
||||||
wire co_rd_mem_en = (!opcode[2] & !opcode[0]) | co_mdu_op;
|
wire co_rd_mem_en = (!opcode[2] & !opcode[0]) | co_mdu_op;
|
||||||
|
@ -186,7 +188,7 @@ module serv_decode
|
||||||
wire co_rd_csr_en = csr_op;
|
wire co_rd_csr_en = csr_op;
|
||||||
|
|
||||||
wire co_csr_en = csr_op & csr_valid;
|
wire co_csr_en = csr_op & csr_valid;
|
||||||
wire co_csr_mstatus_en = csr_op & !op26 & !op22 & !op20;
|
wire co_csr_mstatus_en = csr_op & !op26 & !op22;
|
||||||
wire co_csr_mie_en = csr_op & !op26 & op22 & !op20;
|
wire co_csr_mie_en = csr_op & !op26 & op22 & !op20;
|
||||||
wire co_csr_mcause_en = csr_op & op21 & !op20;
|
wire co_csr_mcause_en = csr_op & op21 & !op20;
|
||||||
|
|
||||||
|
@ -231,7 +233,7 @@ module serv_decode
|
||||||
wire co_op_b_source = opcode[3];
|
wire co_op_b_source = opcode[3];
|
||||||
|
|
||||||
generate
|
generate
|
||||||
if (PRE_REGISTER) begin : gen_pre_register
|
if (PRE_REGISTER) begin
|
||||||
|
|
||||||
always @(posedge clk) begin
|
always @(posedge clk) begin
|
||||||
if (i_wb_en) begin
|
if (i_wb_en) begin
|
||||||
|
@ -257,6 +259,7 @@ module serv_decode
|
||||||
o_ebreak = co_ebreak;
|
o_ebreak = co_ebreak;
|
||||||
o_branch_op = co_branch_op;
|
o_branch_op = co_branch_op;
|
||||||
o_shift_op = co_shift_op;
|
o_shift_op = co_shift_op;
|
||||||
|
o_slt_or_branch = co_slt_or_branch;
|
||||||
o_rd_op = co_rd_op;
|
o_rd_op = co_rd_op;
|
||||||
o_mdu_op = co_mdu_op;
|
o_mdu_op = co_mdu_op;
|
||||||
o_ext_funct3 = co_ext_funct3;
|
o_ext_funct3 = co_ext_funct3;
|
||||||
|
@ -293,7 +296,7 @@ module serv_decode
|
||||||
o_rd_mem_en = co_rd_mem_en;
|
o_rd_mem_en = co_rd_mem_en;
|
||||||
end
|
end
|
||||||
|
|
||||||
end else begin : gen_post_register
|
end else begin
|
||||||
|
|
||||||
always @(*) begin
|
always @(*) begin
|
||||||
funct3 = i_wb_rdt[14:12];
|
funct3 = i_wb_rdt[14:12];
|
||||||
|
@ -318,6 +321,7 @@ module serv_decode
|
||||||
o_mtval_pc <= co_mtval_pc;
|
o_mtval_pc <= co_mtval_pc;
|
||||||
o_branch_op <= co_branch_op;
|
o_branch_op <= co_branch_op;
|
||||||
o_shift_op <= co_shift_op;
|
o_shift_op <= co_shift_op;
|
||||||
|
o_slt_or_branch <= co_slt_or_branch;
|
||||||
o_rd_op <= co_rd_op;
|
o_rd_op <= co_rd_op;
|
||||||
o_mdu_op <= co_mdu_op;
|
o_mdu_op <= co_mdu_op;
|
||||||
o_ext_funct3 <= co_ext_funct3;
|
o_ext_funct3 <= co_ext_funct3;
|
||||||
|
|
|
@ -33,7 +33,7 @@ module serv_immdec
|
||||||
wire signbit = imm31 & !i_csr_imm_en;
|
wire signbit = imm31 & !i_csr_imm_en;
|
||||||
|
|
||||||
generate
|
generate
|
||||||
if (SHARED_RFADDR_IMM_REGS) begin : gen_shared_imm_regs
|
if (SHARED_RFADDR_IMM_REGS) begin
|
||||||
assign o_rs1_addr = imm19_12_20[8:4];
|
assign o_rs1_addr = imm19_12_20[8:4];
|
||||||
assign o_rs2_addr = imm24_20;
|
assign o_rs2_addr = imm24_20;
|
||||||
assign o_rd_addr = imm11_7;
|
assign o_rd_addr = imm11_7;
|
||||||
|
@ -57,7 +57,7 @@ module serv_immdec
|
||||||
if (i_wb_en | (i_cnt_en & i_immdec_en[0]))
|
if (i_wb_en | (i_cnt_en & i_immdec_en[0]))
|
||||||
imm11_7 <= i_wb_en ? i_wb_rdt[11:7] : {imm30_25[0], imm11_7[4:1]};
|
imm11_7 <= i_wb_en ? i_wb_rdt[11:7] : {imm30_25[0], imm11_7[4:1]};
|
||||||
end
|
end
|
||||||
end else begin : gen_separate_imm_regs
|
end else begin
|
||||||
reg [4:0] rd_addr;
|
reg [4:0] rd_addr;
|
||||||
reg [4:0] rs1_addr;
|
reg [4:0] rs1_addr;
|
||||||
reg [4:0] rs2_addr;
|
reg [4:0] rs2_addr;
|
||||||
|
@ -91,5 +91,5 @@ module serv_immdec
|
||||||
endgenerate
|
endgenerate
|
||||||
|
|
||||||
assign o_imm = i_cnt_done ? signbit : i_ctrl[0] ? imm11_7[0] : imm24_20[0];
|
assign o_imm = i_cnt_done ? signbit : i_ctrl[0] ? imm11_7[0] : imm24_20[0];
|
||||||
|
|
||||||
endmodule
|
endmodule
|
||||||
|
|
|
@ -1,15 +1,12 @@
|
||||||
`default_nettype none
|
`default_nettype none
|
||||||
module serv_mem_if
|
module serv_mem_if
|
||||||
#(
|
#(parameter [0:0] WITH_CSR = 1)
|
||||||
parameter [0:0] WITH_CSR = 1,
|
|
||||||
parameter W = 1,
|
|
||||||
parameter B = W-1
|
|
||||||
)
|
|
||||||
(
|
(
|
||||||
input wire i_clk,
|
input wire i_clk,
|
||||||
//State
|
//State
|
||||||
input wire [1:0] i_bytecnt,
|
input wire [1:0] i_bytecnt,
|
||||||
input wire [1:0] i_lsb,
|
input wire [1:0] i_lsb,
|
||||||
|
output wire o_byte_valid,
|
||||||
output wire o_misalign,
|
output wire o_misalign,
|
||||||
//Control
|
//Control
|
||||||
input wire i_signed,
|
input wire i_signed,
|
||||||
|
@ -18,12 +15,27 @@ module serv_mem_if
|
||||||
//MDU
|
//MDU
|
||||||
input wire i_mdu_op,
|
input wire i_mdu_op,
|
||||||
//Data
|
//Data
|
||||||
input wire [B:0] i_bufreg2_q,
|
input wire i_bufreg2_q,
|
||||||
output wire [B:0] o_rd,
|
output wire o_rd,
|
||||||
//External interface
|
//External interface
|
||||||
output wire [3:0] o_wb_sel);
|
output wire [3:0] o_wb_sel);
|
||||||
|
|
||||||
reg signbit;
|
reg signbit;
|
||||||
|
|
||||||
|
/*
|
||||||
|
Before a store operation, the data to be written needs to be shifted into
|
||||||
|
place. Depending on the address alignment, we need to shift different
|
||||||
|
amounts. One formula for calculating this is to say that we shift when
|
||||||
|
i_lsb + i_bytecnt < 4. Unfortunately, the synthesis tools don't seem to be
|
||||||
|
clever enough so the hideous expression below is used to achieve the same
|
||||||
|
thing in a more optimal way.
|
||||||
|
*/
|
||||||
|
assign o_byte_valid
|
||||||
|
= (!i_lsb[0] & !i_lsb[1]) |
|
||||||
|
(!i_bytecnt[0] & !i_bytecnt[1]) |
|
||||||
|
(!i_bytecnt[1] & !i_lsb[1]) |
|
||||||
|
(!i_bytecnt[1] & !i_lsb[0]) |
|
||||||
|
(!i_bytecnt[0] & !i_lsb[1]);
|
||||||
|
|
||||||
wire dat_valid =
|
wire dat_valid =
|
||||||
i_mdu_op |
|
i_mdu_op |
|
||||||
|
@ -31,7 +43,7 @@ module serv_mem_if
|
||||||
(i_bytecnt == 2'b00) |
|
(i_bytecnt == 2'b00) |
|
||||||
(i_half & !i_bytecnt[1]);
|
(i_half & !i_bytecnt[1]);
|
||||||
|
|
||||||
assign o_rd = dat_valid ? i_bufreg2_q : {W{i_signed & signbit}};
|
assign o_rd = dat_valid ? i_bufreg2_q : signbit & i_signed;
|
||||||
|
|
||||||
assign o_wb_sel[3] = (i_lsb == 2'b11) | i_word | (i_half & i_lsb[1]);
|
assign o_wb_sel[3] = (i_lsb == 2'b11) | i_word | (i_half & i_lsb[1]);
|
||||||
assign o_wb_sel[2] = (i_lsb == 2'b10) | i_word;
|
assign o_wb_sel[2] = (i_lsb == 2'b10) | i_word;
|
||||||
|
@ -40,7 +52,7 @@ module serv_mem_if
|
||||||
|
|
||||||
always @(posedge i_clk) begin
|
always @(posedge i_clk) begin
|
||||||
if (dat_valid)
|
if (dat_valid)
|
||||||
signbit <= i_bufreg2_q[B];
|
signbit <= i_bufreg2_q;
|
||||||
end
|
end
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -1,52 +1,49 @@
|
||||||
`default_nettype none
|
`default_nettype none
|
||||||
module serv_rf_if
|
module serv_rf_if
|
||||||
#(parameter WITH_CSR = 1,
|
#(parameter WITH_CSR = 1)
|
||||||
parameter W = 1,
|
|
||||||
parameter B = W-1
|
|
||||||
)
|
|
||||||
(//RF Interface
|
(//RF Interface
|
||||||
input wire i_cnt_en,
|
input wire i_cnt_en,
|
||||||
output wire [4+WITH_CSR:0] o_wreg0,
|
output wire [4+WITH_CSR:0] o_wreg0,
|
||||||
output wire [4+WITH_CSR:0] o_wreg1,
|
output wire [4+WITH_CSR:0] o_wreg1,
|
||||||
output wire o_wen0,
|
output wire o_wen0,
|
||||||
output wire o_wen1,
|
output wire o_wen1,
|
||||||
output wire [B:0] o_wdata0,
|
output wire o_wdata0,
|
||||||
output wire [B:0] o_wdata1,
|
output wire o_wdata1,
|
||||||
output wire [4+WITH_CSR:0] o_rreg0,
|
output wire [4+WITH_CSR:0] o_rreg0,
|
||||||
output wire [4+WITH_CSR:0] o_rreg1,
|
output wire [4+WITH_CSR:0] o_rreg1,
|
||||||
input wire [B:0] i_rdata0,
|
input wire i_rdata0,
|
||||||
input wire [B:0] i_rdata1,
|
input wire i_rdata1,
|
||||||
|
|
||||||
//Trap interface
|
//Trap interface
|
||||||
input wire i_trap,
|
input wire i_trap,
|
||||||
input wire i_mret,
|
input wire i_mret,
|
||||||
input wire [B:0] i_mepc,
|
input wire i_mepc,
|
||||||
input wire i_mtval_pc,
|
input wire i_mtval_pc,
|
||||||
input wire [B:0] i_bufreg_q,
|
input wire i_bufreg_q,
|
||||||
input wire [B:0] i_bad_pc,
|
input wire i_bad_pc,
|
||||||
output wire [B:0] o_csr_pc,
|
output wire o_csr_pc,
|
||||||
//CSR interface
|
//CSR interface
|
||||||
input wire i_csr_en,
|
input wire i_csr_en,
|
||||||
input wire [1:0] i_csr_addr,
|
input wire [1:0] i_csr_addr,
|
||||||
input wire [B:0] i_csr,
|
input wire i_csr,
|
||||||
output wire [B:0] o_csr,
|
output wire o_csr,
|
||||||
//RD write port
|
//RD write port
|
||||||
input wire i_rd_wen,
|
input wire i_rd_wen,
|
||||||
input wire [4:0] i_rd_waddr,
|
input wire [4:0] i_rd_waddr,
|
||||||
input wire [B:0] i_ctrl_rd,
|
input wire i_ctrl_rd,
|
||||||
input wire [B:0] i_alu_rd,
|
input wire i_alu_rd,
|
||||||
input wire i_rd_alu_en,
|
input wire i_rd_alu_en,
|
||||||
input wire [B:0] i_csr_rd,
|
input wire i_csr_rd,
|
||||||
input wire i_rd_csr_en,
|
input wire i_rd_csr_en,
|
||||||
input wire [B:0] i_mem_rd,
|
input wire i_mem_rd,
|
||||||
input wire i_rd_mem_en,
|
input wire i_rd_mem_en,
|
||||||
|
|
||||||
//RS1 read port
|
//RS1 read port
|
||||||
input wire [4:0] i_rs1_raddr,
|
input wire [4:0] i_rs1_raddr,
|
||||||
output wire [B:0] o_rs1,
|
output wire o_rs1,
|
||||||
//RS2 read port
|
//RS2 read port
|
||||||
input wire [4:0] i_rs2_raddr,
|
input wire [4:0] i_rs2_raddr,
|
||||||
output wire [B:0] o_rs2);
|
output wire o_rs2);
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -56,14 +53,13 @@ module serv_rf_if
|
||||||
wire rd_wen = i_rd_wen & (|i_rd_waddr);
|
wire rd_wen = i_rd_wen & (|i_rd_waddr);
|
||||||
|
|
||||||
generate
|
generate
|
||||||
if (|WITH_CSR) begin : gen_csr
|
if (|WITH_CSR) begin
|
||||||
wire [B:0] rd =
|
wire rd = (i_ctrl_rd ) |
|
||||||
{W{i_rd_alu_en}} & i_alu_rd |
|
(i_alu_rd & i_rd_alu_en) |
|
||||||
{W{i_rd_csr_en}} & i_csr_rd |
|
(i_csr_rd & i_rd_csr_en) |
|
||||||
{W{i_rd_mem_en}} & i_mem_rd |
|
(i_mem_rd & i_rd_mem_en);
|
||||||
i_ctrl_rd;
|
|
||||||
|
|
||||||
wire [B:0] mtval = i_mtval_pc ? i_bad_pc : i_bufreg_q;
|
wire mtval = i_mtval_pc ? i_bad_pc : i_bufreg_q;
|
||||||
|
|
||||||
assign o_wdata0 = i_trap ? mtval : rd;
|
assign o_wdata0 = i_trap ? mtval : rd;
|
||||||
assign o_wdata1 = i_trap ? i_mepc : i_csr;
|
assign o_wdata1 = i_trap ? i_mepc : i_csr;
|
||||||
|
@ -120,16 +116,16 @@ module serv_rf_if
|
||||||
|
|
||||||
assign o_rs1 = i_rdata0;
|
assign o_rs1 = i_rdata0;
|
||||||
assign o_rs2 = i_rdata1;
|
assign o_rs2 = i_rdata1;
|
||||||
assign o_csr = i_rdata1 & {W{i_csr_en}};
|
assign o_csr = i_rdata1 & i_csr_en;
|
||||||
assign o_csr_pc = i_rdata1;
|
assign o_csr_pc = i_rdata1;
|
||||||
|
|
||||||
end else begin : gen_no_csr
|
end else begin
|
||||||
wire [B:0] rd = (i_ctrl_rd) |
|
wire rd = (i_ctrl_rd ) |
|
||||||
i_alu_rd & {W{i_rd_alu_en}} |
|
(i_alu_rd & i_rd_alu_en) |
|
||||||
i_mem_rd & {W{i_rd_mem_en}};
|
(i_mem_rd & i_rd_mem_en);
|
||||||
|
|
||||||
assign o_wdata0 = rd;
|
assign o_wdata0 = rd;
|
||||||
assign o_wdata1 = {W{1'b0}};
|
assign o_wdata1 = 1'b0;
|
||||||
|
|
||||||
assign o_wreg0 = i_rd_waddr;
|
assign o_wreg0 = i_rd_waddr;
|
||||||
assign o_wreg1 = 5'd0;
|
assign o_wreg1 = 5'd0;
|
||||||
|
@ -146,8 +142,8 @@ module serv_rf_if
|
||||||
|
|
||||||
assign o_rs1 = i_rdata0;
|
assign o_rs1 = i_rdata0;
|
||||||
assign o_rs2 = i_rdata1;
|
assign o_rs2 = i_rdata1;
|
||||||
assign o_csr = {W{1'b0}};
|
assign o_csr = 1'b0;
|
||||||
assign o_csr_pc = {W{1'b0}};
|
assign o_csr_pc = 1'b0;
|
||||||
end // else: !if(WITH_CSR)
|
end // else: !if(WITH_CSR)
|
||||||
endgenerate
|
endgenerate
|
||||||
endmodule
|
endmodule
|
||||||
|
|
|
@ -7,7 +7,6 @@ module serv_rf_ram
|
||||||
input wire [width-1:0] i_wdata,
|
input wire [width-1:0] i_wdata,
|
||||||
input wire i_wen,
|
input wire i_wen,
|
||||||
input wire [$clog2(depth)-1:0] i_raddr,
|
input wire [$clog2(depth)-1:0] i_raddr,
|
||||||
input wire i_ren,
|
|
||||||
output wire [width-1:0] o_rdata);
|
output wire [width-1:0] o_rdata);
|
||||||
|
|
||||||
reg [width-1:0] memory [0:depth-1];
|
reg [width-1:0] memory [0:depth-1];
|
||||||
|
@ -16,7 +15,7 @@ module serv_rf_ram
|
||||||
always @(posedge i_clk) begin
|
always @(posedge i_clk) begin
|
||||||
if (i_wen)
|
if (i_wen)
|
||||||
memory[i_waddr] <= i_wdata;
|
memory[i_waddr] <= i_wdata;
|
||||||
rdata <= i_ren ? memory[i_raddr] : {width{1'bx}};
|
rdata <= memory[i_raddr];
|
||||||
end
|
end
|
||||||
|
|
||||||
/* Reads from reg x0 needs to return 0
|
/* Reads from reg x0 needs to return 0
|
||||||
|
|
|
@ -1,106 +1,89 @@
|
||||||
`default_nettype none
|
`default_nettype none
|
||||||
module serv_rf_ram_if
|
module serv_rf_ram_if
|
||||||
#(//Data width. Adjust to preferred width of SRAM data interface
|
#(parameter width=8,
|
||||||
parameter width=8,
|
|
||||||
|
|
||||||
parameter W = 1,
|
|
||||||
//Select reset strategy.
|
|
||||||
// "MINI" for resetting minimally required FFs
|
|
||||||
// "NONE" for relying on FFs having a defined value on startup
|
|
||||||
parameter reset_strategy="MINI",
|
parameter reset_strategy="MINI",
|
||||||
|
|
||||||
//Number of CSR registers. These are allocated after the normal
|
|
||||||
// GPR registers in the RAM.
|
|
||||||
parameter csr_regs=4,
|
parameter csr_regs=4,
|
||||||
|
parameter depth=32*(32+csr_regs)/width,
|
||||||
//Internal parameters calculated from above values. Do not change
|
parameter l2w = $clog2(width))
|
||||||
parameter B=W-1,
|
|
||||||
parameter raw=$clog2(32+csr_regs), //Register address width
|
|
||||||
parameter l2w=$clog2(width), //log2 of width
|
|
||||||
parameter aw=5+raw-l2w) //Address width
|
|
||||||
(
|
(
|
||||||
//SERV side
|
//SERV side
|
||||||
input wire i_clk,
|
input wire i_clk,
|
||||||
input wire i_rst,
|
input wire i_rst,
|
||||||
input wire i_wreq,
|
input wire i_wreq,
|
||||||
input wire i_rreq,
|
input wire i_rreq,
|
||||||
output wire o_ready,
|
output wire o_ready,
|
||||||
input wire [raw-1:0] i_wreg0,
|
input wire [$clog2(32+csr_regs)-1:0] i_wreg0,
|
||||||
input wire [raw-1:0] i_wreg1,
|
input wire [$clog2(32+csr_regs)-1:0] i_wreg1,
|
||||||
input wire i_wen0,
|
input wire i_wen0,
|
||||||
input wire i_wen1,
|
input wire i_wen1,
|
||||||
input wire [B:0] i_wdata0,
|
input wire i_wdata0,
|
||||||
input wire [B:0] i_wdata1,
|
input wire i_wdata1,
|
||||||
input wire [raw-1:0] i_rreg0,
|
input wire [$clog2(32+csr_regs)-1:0] i_rreg0,
|
||||||
input wire [raw-1:0] i_rreg1,
|
input wire [$clog2(32+csr_regs)-1:0] i_rreg1,
|
||||||
output wire [B:0] o_rdata0,
|
output wire o_rdata0,
|
||||||
output wire [B:0] o_rdata1,
|
output wire o_rdata1,
|
||||||
//RAM side
|
//RAM side
|
||||||
output wire [aw-1:0] o_waddr,
|
output wire [$clog2(depth)-1:0] o_waddr,
|
||||||
output wire [width-1:0] o_wdata,
|
output wire [width-1:0] o_wdata,
|
||||||
output wire o_wen,
|
output wire o_wen,
|
||||||
output wire [aw-1:0] o_raddr,
|
output wire [$clog2(depth)-1:0] o_raddr,
|
||||||
output wire o_ren,
|
input wire [width-1:0] i_rdata);
|
||||||
input wire [width-1:0] i_rdata);
|
|
||||||
|
|
||||||
localparam ratio = width/W;
|
|
||||||
localparam CMSB = 4-$clog2(W); //Counter MSB
|
|
||||||
localparam l2r = $clog2(ratio);
|
|
||||||
|
|
||||||
reg rgnt;
|
reg rgnt;
|
||||||
assign o_ready = rgnt | i_wreq;
|
assign o_ready = rgnt | i_wreq;
|
||||||
reg [CMSB:0] rcnt;
|
reg [4:0] rcnt;
|
||||||
|
|
||||||
reg rtrig1;
|
|
||||||
/*
|
/*
|
||||||
********** Write side ***********
|
********** Write side ***********
|
||||||
*/
|
*/
|
||||||
|
|
||||||
wire [CMSB:0] wcnt;
|
wire [4:0] wcnt;
|
||||||
|
|
||||||
reg [width-1:0] wdata0_r;
|
reg [width-2:0] wdata0_r;
|
||||||
reg [width+W-1:0] wdata1_r;
|
reg [width-1:0] wdata1_r;
|
||||||
|
|
||||||
reg wen0_r;
|
reg wen0_r;
|
||||||
reg wen1_r;
|
reg wen1_r;
|
||||||
wire wtrig0;
|
wire wtrig0;
|
||||||
wire wtrig1;
|
wire wtrig1;
|
||||||
|
|
||||||
assign wtrig0 = rtrig1;
|
generate if (width == 2) begin
|
||||||
|
assign wtrig0 = ~wcnt[0];
|
||||||
generate if (ratio == 2) begin : gen_wtrig_ratio_eq_2
|
|
||||||
assign wtrig1 = wcnt[0];
|
assign wtrig1 = wcnt[0];
|
||||||
end else begin : gen_wtrig_ratio_neq_2
|
end else begin
|
||||||
reg wtrig0_r;
|
reg wtrig0_r;
|
||||||
always @(posedge i_clk) wtrig0_r <= wtrig0;
|
always @(posedge i_clk) wtrig0_r <= wtrig0;
|
||||||
|
assign wtrig0 = (wcnt[l2w-1:0] == {{l2w-1{1'b1}},1'b0});
|
||||||
assign wtrig1 = wtrig0_r;
|
assign wtrig1 = wtrig0_r;
|
||||||
end
|
end
|
||||||
endgenerate
|
endgenerate
|
||||||
|
|
||||||
assign o_wdata = wtrig1 ?
|
assign o_wdata = wtrig1 ?
|
||||||
wdata1_r[width-1:0] :
|
wdata1_r :
|
||||||
wdata0_r;
|
{i_wdata0, wdata0_r};
|
||||||
|
|
||||||
wire [raw-1:0] wreg = wtrig1 ? i_wreg1 : i_wreg0;
|
wire [$clog2(32+csr_regs)-1:0] wreg = wtrig1 ? i_wreg1 : i_wreg0;
|
||||||
generate if (width == 32) begin : gen_w_eq_32
|
generate if (width == 32)
|
||||||
assign o_waddr = wreg;
|
assign o_waddr = wreg;
|
||||||
end else begin : gen_w_neq_32
|
else
|
||||||
assign o_waddr = {wreg, wcnt[CMSB:l2r]};
|
assign o_waddr = {wreg, wcnt[4:l2w]};
|
||||||
end
|
|
||||||
endgenerate
|
endgenerate
|
||||||
|
|
||||||
assign o_wen = (wtrig0 & wen0_r) | (wtrig1 & wen1_r);
|
assign o_wen = (wtrig0 & wen0_r) | (wtrig1 & wen1_r);
|
||||||
|
|
||||||
assign wcnt = rcnt-4;
|
generate if (width > 2)
|
||||||
|
always @(posedge i_clk) wdata0_r <= {i_wdata0, wdata0_r[width-2:1]};
|
||||||
|
else
|
||||||
|
always @(posedge i_clk) wdata0_r <= i_wdata0;
|
||||||
|
endgenerate
|
||||||
|
|
||||||
|
assign wcnt = rcnt-3;
|
||||||
|
|
||||||
always @(posedge i_clk) begin
|
always @(posedge i_clk) begin
|
||||||
if (wcnt[0]) begin
|
wen0_r <= i_wen0;
|
||||||
wen0_r <= i_wen0;
|
wen1_r <= i_wen1;
|
||||||
wen1_r <= i_wen1;
|
|
||||||
end
|
|
||||||
|
|
||||||
wdata0_r <= {i_wdata0,wdata0_r[width-1:W]};
|
wdata1_r <= {i_wdata1,wdata1_r[width-1:1]};
|
||||||
wdata1_r <= {i_wdata1,wdata1_r[width+W-1:W]};
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -110,67 +93,54 @@ module serv_rf_ram_if
|
||||||
|
|
||||||
|
|
||||||
wire rtrig0;
|
wire rtrig0;
|
||||||
|
reg rtrig1;
|
||||||
|
|
||||||
wire [raw-1:0] rreg = rtrig0 ? i_rreg1 : i_rreg0;
|
wire [$clog2(32+csr_regs)-1:0] rreg = rtrig0 ? i_rreg1 : i_rreg0;
|
||||||
generate if (width == 32) begin : gen_rreg_eq_32
|
generate if (width == 32)
|
||||||
assign o_raddr = rreg;
|
assign o_raddr = rreg;
|
||||||
end else begin : gen_rreg_neq_32
|
else
|
||||||
assign o_raddr = {rreg, rcnt[CMSB:l2r]};
|
assign o_raddr = {rreg, rcnt[4:l2w]};
|
||||||
end
|
|
||||||
endgenerate
|
endgenerate
|
||||||
|
|
||||||
reg [width-1:0] rdata0;
|
reg [width-1:0] rdata0;
|
||||||
reg [width-1-W:0] rdata1;
|
reg [width-2:0] rdata1;
|
||||||
|
|
||||||
reg rgate;
|
assign o_rdata0 = rdata0[0];
|
||||||
|
assign o_rdata1 = rtrig1 ? i_rdata[0] : rdata1[0];
|
||||||
|
|
||||||
assign o_rdata0 = rdata0[B:0];
|
assign rtrig0 = (rcnt[l2w-1:0] == 1);
|
||||||
assign o_rdata1 = rtrig1 ? i_rdata[B:0] : rdata1[B:0];
|
|
||||||
|
|
||||||
assign rtrig0 = (rcnt[l2r-1:0] == 1);
|
|
||||||
|
|
||||||
generate if (ratio == 2) begin : gen_ren_w_eq_2
|
|
||||||
assign o_ren = rgate;
|
|
||||||
end else begin : gen_ren_w_neq_2
|
|
||||||
assign o_ren = rgate & (rcnt[l2r-1:1] == 0);
|
|
||||||
end
|
|
||||||
endgenerate
|
|
||||||
|
|
||||||
reg rreq_r;
|
reg rreq_r;
|
||||||
|
|
||||||
generate if (ratio > 2) begin : gen_rdata1_w_neq_2
|
generate if (width>2)
|
||||||
always @(posedge i_clk) begin
|
always @(posedge i_clk) begin
|
||||||
rdata1 <= {{W{1'b0}},rdata1[width-W-1:W]};
|
rdata1 <= {1'b0,rdata1[width-2:1]}; //Optimize?
|
||||||
if (rtrig1)
|
if (rtrig1)
|
||||||
rdata1[width-W-1:0] <= i_rdata[width-1:W];
|
rdata1[width-2:0] <= i_rdata[width-1:1];
|
||||||
end
|
end
|
||||||
end else begin : gen_rdata1_w_eq_2
|
else
|
||||||
always @(posedge i_clk) if (rtrig1) rdata1 <= i_rdata[W*2-1:W];
|
always @(posedge i_clk) if (rtrig1) rdata1 <= i_rdata[1];
|
||||||
end
|
|
||||||
endgenerate
|
endgenerate
|
||||||
|
|
||||||
always @(posedge i_clk) begin
|
always @(posedge i_clk) begin
|
||||||
if (&rcnt | i_rreq)
|
|
||||||
rgate <= i_rreq;
|
|
||||||
|
|
||||||
rtrig1 <= rtrig0;
|
rtrig1 <= rtrig0;
|
||||||
rcnt <= rcnt+{{CMSB{1'b0}},1'b1};
|
rcnt <= rcnt+5'd1;
|
||||||
if (i_rreq | i_wreq)
|
if (i_rreq)
|
||||||
rcnt <= {{CMSB-1{1'b0}},i_wreq,1'b0};
|
rcnt <= 5'd0;
|
||||||
|
if (i_wreq)
|
||||||
|
rcnt <= 5'd2;
|
||||||
|
|
||||||
rreq_r <= i_rreq;
|
rreq_r <= i_rreq;
|
||||||
rgnt <= rreq_r;
|
rgnt <= rreq_r;
|
||||||
|
|
||||||
rdata0 <= {{W{1'b0}}, rdata0[width-1:W]};
|
rdata0 <= {1'b0,rdata0[width-1:1]};
|
||||||
if (rtrig0)
|
if (rtrig0)
|
||||||
rdata0 <= i_rdata;
|
rdata0 <= i_rdata;
|
||||||
|
|
||||||
if (i_rst) begin
|
if (i_rst) begin
|
||||||
if (reset_strategy != "NONE") begin
|
if (reset_strategy != "NONE") begin
|
||||||
rgate <= 1'b0;
|
|
||||||
rgnt <= 1'b0;
|
rgnt <= 1'b0;
|
||||||
rreq_r <= 1'b0;
|
rreq_r <= 1'b0;
|
||||||
rcnt <= {CMSB+1{1'b0}};
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -6,9 +6,9 @@ module serv_rf_top
|
||||||
COMPRESSED=0: Disable the compressed decoder and does not allow the misaligned jump of pc
|
COMPRESSED=0: Disable the compressed decoder and does not allow the misaligned jump of pc
|
||||||
*/
|
*/
|
||||||
parameter [0:0] COMPRESSED = 0,
|
parameter [0:0] COMPRESSED = 0,
|
||||||
/*
|
/*
|
||||||
ALIGN = 1: Fetch the aligned instruction by making two bus transactions if the misaligned address
|
ALIGN = 1: Fetch the aligned instruction by making two bus transactions if the misaligned address
|
||||||
is given to the instruction bus.
|
is given to the instruction bus.
|
||||||
*/
|
*/
|
||||||
parameter [0:0] ALIGN = COMPRESSED,
|
parameter [0:0] ALIGN = COMPRESSED,
|
||||||
/* Multiplication and Division Unit
|
/* Multiplication and Division Unit
|
||||||
|
@ -27,10 +27,8 @@ module serv_rf_top
|
||||||
restart execution from the instruction at RESET_PC
|
restart execution from the instruction at RESET_PC
|
||||||
*/
|
*/
|
||||||
parameter RESET_STRATEGY = "MINI",
|
parameter RESET_STRATEGY = "MINI",
|
||||||
parameter [0:0] DEBUG = 1'b0,
|
|
||||||
parameter WITH_CSR = 1,
|
parameter WITH_CSR = 1,
|
||||||
parameter W = 1,
|
parameter RF_WIDTH = 2,
|
||||||
parameter RF_WIDTH = W * 2,
|
|
||||||
parameter RF_L2D = $clog2((32+(WITH_CSR*4))*32/RF_WIDTH))
|
parameter RF_L2D = $clog2((32+(WITH_CSR*4))*32/RF_WIDTH))
|
||||||
(
|
(
|
||||||
input wire clk,
|
input wire clk,
|
||||||
|
@ -70,7 +68,7 @@ module serv_rf_top
|
||||||
output wire o_dbus_cyc,
|
output wire o_dbus_cyc,
|
||||||
input wire [31:0] i_dbus_rdt,
|
input wire [31:0] i_dbus_rdt,
|
||||||
input wire i_dbus_ack,
|
input wire i_dbus_ack,
|
||||||
|
|
||||||
// Extension
|
// Extension
|
||||||
output wire [31:0] o_ext_rs1,
|
output wire [31:0] o_ext_rs1,
|
||||||
output wire [31:0] o_ext_rs2,
|
output wire [31:0] o_ext_rs2,
|
||||||
|
@ -79,7 +77,7 @@ module serv_rf_top
|
||||||
input wire i_ext_ready,
|
input wire i_ext_ready,
|
||||||
// MDU
|
// MDU
|
||||||
output wire o_mdu_valid);
|
output wire o_mdu_valid);
|
||||||
|
|
||||||
localparam CSR_REGS = WITH_CSR*4;
|
localparam CSR_REGS = WITH_CSR*4;
|
||||||
|
|
||||||
wire rf_wreq;
|
wire rf_wreq;
|
||||||
|
@ -88,26 +86,24 @@ module serv_rf_top
|
||||||
wire [4+WITH_CSR:0] wreg1;
|
wire [4+WITH_CSR:0] wreg1;
|
||||||
wire wen0;
|
wire wen0;
|
||||||
wire wen1;
|
wire wen1;
|
||||||
wire [W-1:0] wdata0;
|
wire wdata0;
|
||||||
wire [W-1:0] wdata1;
|
wire wdata1;
|
||||||
wire [4+WITH_CSR:0] rreg0;
|
wire [4+WITH_CSR:0] rreg0;
|
||||||
wire [4+WITH_CSR:0] rreg1;
|
wire [4+WITH_CSR:0] rreg1;
|
||||||
wire rf_ready;
|
wire rf_ready;
|
||||||
wire [W-1:0] rdata0;
|
wire rdata0;
|
||||||
wire [W-1:0] rdata1;
|
wire rdata1;
|
||||||
|
|
||||||
wire [RF_L2D-1:0] waddr;
|
wire [RF_L2D-1:0] waddr;
|
||||||
wire [RF_WIDTH-1:0] wdata;
|
wire [RF_WIDTH-1:0] wdata;
|
||||||
wire wen;
|
wire wen;
|
||||||
wire [RF_L2D-1:0] raddr;
|
wire [RF_L2D-1:0] raddr;
|
||||||
wire ren;
|
|
||||||
wire [RF_WIDTH-1:0] rdata;
|
wire [RF_WIDTH-1:0] rdata;
|
||||||
|
|
||||||
serv_rf_ram_if
|
serv_rf_ram_if
|
||||||
#(.width (RF_WIDTH),
|
#(.width (RF_WIDTH),
|
||||||
.reset_strategy (RESET_STRATEGY),
|
.reset_strategy (RESET_STRATEGY),
|
||||||
.csr_regs (CSR_REGS),
|
.csr_regs (CSR_REGS))
|
||||||
.W(W))
|
|
||||||
rf_ram_if
|
rf_ram_if
|
||||||
(.i_clk (clk),
|
(.i_clk (clk),
|
||||||
.i_rst (i_rst),
|
.i_rst (i_rst),
|
||||||
|
@ -128,7 +124,6 @@ module serv_rf_top
|
||||||
.o_wdata (wdata),
|
.o_wdata (wdata),
|
||||||
.o_wen (wen),
|
.o_wen (wen),
|
||||||
.o_raddr (raddr),
|
.o_raddr (raddr),
|
||||||
.o_ren (ren),
|
|
||||||
.i_rdata (rdata));
|
.i_rdata (rdata));
|
||||||
|
|
||||||
serv_rf_ram
|
serv_rf_ram
|
||||||
|
@ -140,7 +135,6 @@ module serv_rf_top
|
||||||
.i_wdata (wdata),
|
.i_wdata (wdata),
|
||||||
.i_wen (wen),
|
.i_wen (wen),
|
||||||
.i_raddr (raddr),
|
.i_raddr (raddr),
|
||||||
.i_ren (ren),
|
|
||||||
.o_rdata (rdata));
|
.o_rdata (rdata));
|
||||||
|
|
||||||
serv_top
|
serv_top
|
||||||
|
@ -148,11 +142,9 @@ module serv_rf_top
|
||||||
.PRE_REGISTER (PRE_REGISTER),
|
.PRE_REGISTER (PRE_REGISTER),
|
||||||
.RESET_STRATEGY (RESET_STRATEGY),
|
.RESET_STRATEGY (RESET_STRATEGY),
|
||||||
.WITH_CSR (WITH_CSR),
|
.WITH_CSR (WITH_CSR),
|
||||||
.DEBUG (DEBUG),
|
|
||||||
.MDU(MDU),
|
.MDU(MDU),
|
||||||
.COMPRESSED(COMPRESSED),
|
.COMPRESSED(COMPRESSED),
|
||||||
.ALIGN(ALIGN),
|
.ALIGN(ALIGN))
|
||||||
.W(W))
|
|
||||||
cpu
|
cpu
|
||||||
(
|
(
|
||||||
.clk (clk),
|
.clk (clk),
|
||||||
|
@ -207,7 +199,7 @@ module serv_rf_top
|
||||||
.o_dbus_cyc (o_dbus_cyc),
|
.o_dbus_cyc (o_dbus_cyc),
|
||||||
.i_dbus_rdt (i_dbus_rdt),
|
.i_dbus_rdt (i_dbus_rdt),
|
||||||
.i_dbus_ack (i_dbus_ack),
|
.i_dbus_ack (i_dbus_ack),
|
||||||
|
|
||||||
//Extension
|
//Extension
|
||||||
.o_ext_funct3 (o_ext_funct3),
|
.o_ext_funct3 (o_ext_funct3),
|
||||||
.i_ext_ready (i_ext_ready),
|
.i_ext_ready (i_ext_ready),
|
||||||
|
|
133
rtl/serv_state.v
133
rtl/serv_state.v
|
@ -2,9 +2,7 @@ module serv_state
|
||||||
#(parameter RESET_STRATEGY = "MINI",
|
#(parameter RESET_STRATEGY = "MINI",
|
||||||
parameter [0:0] WITH_CSR = 1,
|
parameter [0:0] WITH_CSR = 1,
|
||||||
parameter [0:0] ALIGN =0,
|
parameter [0:0] ALIGN =0,
|
||||||
parameter [0:0] MDU = 0,
|
parameter [0:0] MDU = 0)
|
||||||
parameter W = 1
|
|
||||||
)
|
|
||||||
(
|
(
|
||||||
input wire i_clk,
|
input wire i_clk,
|
||||||
input wire i_rst,
|
input wire i_rst,
|
||||||
|
@ -12,7 +10,7 @@ module serv_state
|
||||||
input wire i_new_irq,
|
input wire i_new_irq,
|
||||||
input wire i_alu_cmp,
|
input wire i_alu_cmp,
|
||||||
output wire o_init,
|
output wire o_init,
|
||||||
output wire o_cnt_en,
|
output wire o_cnt_en,
|
||||||
output wire o_cnt0to3,
|
output wire o_cnt0to3,
|
||||||
output wire o_cnt12to31,
|
output wire o_cnt12to31,
|
||||||
output wire o_cnt0,
|
output wire o_cnt0,
|
||||||
|
@ -20,15 +18,14 @@ module serv_state
|
||||||
output wire o_cnt2,
|
output wire o_cnt2,
|
||||||
output wire o_cnt3,
|
output wire o_cnt3,
|
||||||
output wire o_cnt7,
|
output wire o_cnt7,
|
||||||
output wire o_cnt11,
|
output reg o_cnt_done,
|
||||||
output wire o_cnt12,
|
|
||||||
output wire o_cnt_done,
|
|
||||||
output wire o_bufreg_en,
|
output wire o_bufreg_en,
|
||||||
output wire o_ctrl_pc_en,
|
output wire o_ctrl_pc_en,
|
||||||
output reg o_ctrl_jump,
|
output reg o_ctrl_jump,
|
||||||
output wire o_ctrl_trap,
|
output wire o_ctrl_trap,
|
||||||
input wire i_ctrl_misalign,
|
input wire i_ctrl_misalign,
|
||||||
input wire i_sh_done,
|
input wire i_sh_done,
|
||||||
|
input wire i_sh_done_r,
|
||||||
output wire [1:0] o_mem_bytecnt,
|
output wire [1:0] o_mem_bytecnt,
|
||||||
input wire i_mem_misalign,
|
input wire i_mem_misalign,
|
||||||
//Control
|
//Control
|
||||||
|
@ -39,8 +36,7 @@ module serv_state
|
||||||
input wire i_branch_op,
|
input wire i_branch_op,
|
||||||
input wire i_shift_op,
|
input wire i_shift_op,
|
||||||
input wire i_sh_right,
|
input wire i_sh_right,
|
||||||
input wire i_alu_rd_sel1,
|
input wire i_slt_or_branch,
|
||||||
input wire i_rd_alu_en,
|
|
||||||
input wire i_e_op,
|
input wire i_e_op,
|
||||||
input wire i_rd_op,
|
input wire i_rd_op,
|
||||||
//MDU
|
//MDU
|
||||||
|
@ -59,27 +55,28 @@ module serv_state
|
||||||
input wire i_rf_ready,
|
input wire i_rf_ready,
|
||||||
output wire o_rf_rd_en);
|
output wire o_rf_rd_en);
|
||||||
|
|
||||||
|
reg stage_two_req;
|
||||||
reg init_done;
|
reg init_done;
|
||||||
wire misalign_trap_sync;
|
wire misalign_trap_sync;
|
||||||
|
|
||||||
reg [4:2] o_cnt;
|
reg [4:2] o_cnt;
|
||||||
wire [3:0] cnt_r;
|
reg [3:0] o_cnt_r;
|
||||||
|
|
||||||
reg ibus_cyc;
|
reg ibus_cyc;
|
||||||
//Update PC in RUN or TRAP states
|
//Update PC in RUN or TRAP states
|
||||||
assign o_ctrl_pc_en = o_cnt_en & !o_init;
|
assign o_ctrl_pc_en = o_cnt_en & !o_init;
|
||||||
|
|
||||||
|
assign o_cnt_en = |o_cnt_r;
|
||||||
|
|
||||||
assign o_mem_bytecnt = o_cnt[4:3];
|
assign o_mem_bytecnt = o_cnt[4:3];
|
||||||
|
|
||||||
assign o_cnt0to3 = (o_cnt[4:2] == 3'd0);
|
assign o_cnt0to3 = (o_cnt[4:2] == 3'd0);
|
||||||
assign o_cnt12to31 = (o_cnt[4] | (o_cnt[3:2] == 2'b11));
|
assign o_cnt12to31 = (o_cnt[4] | (o_cnt[3:2] == 2'b11));
|
||||||
assign o_cnt0 = (o_cnt[4:2] == 3'd0) & cnt_r[0];
|
assign o_cnt0 = (o_cnt[4:2] == 3'd0) & o_cnt_r[0];
|
||||||
assign o_cnt1 = (o_cnt[4:2] == 3'd0) & cnt_r[1];
|
assign o_cnt1 = (o_cnt[4:2] == 3'd0) & o_cnt_r[1];
|
||||||
assign o_cnt2 = (o_cnt[4:2] == 3'd0) & cnt_r[2];
|
assign o_cnt2 = (o_cnt[4:2] == 3'd0) & o_cnt_r[2];
|
||||||
assign o_cnt3 = (o_cnt[4:2] == 3'd0) & cnt_r[3];
|
assign o_cnt3 = (o_cnt[4:2] == 3'd0) & o_cnt_r[3];
|
||||||
assign o_cnt7 = (o_cnt[4:2] == 3'd1) & cnt_r[3];
|
assign o_cnt7 = (o_cnt[4:2] == 3'd1) & o_cnt_r[3];
|
||||||
assign o_cnt11 = (o_cnt[4:2] == 3'd2) & cnt_r[3];
|
|
||||||
assign o_cnt12 = (o_cnt[4:2] == 3'd3) & cnt_r[0];
|
|
||||||
|
|
||||||
//Take branch for jump or branch instructions (opcode == 1x0xx) if
|
//Take branch for jump or branch instructions (opcode == 1x0xx) if
|
||||||
//a) It's an unconditional branch (opcode[0] == 1)
|
//a) It's an unconditional branch (opcode[0] == 1)
|
||||||
|
@ -89,55 +86,46 @@ module serv_state
|
||||||
//been calculated.
|
//been calculated.
|
||||||
wire take_branch = i_branch_op & (!i_cond_branch | (i_alu_cmp^i_bne_or_bge));
|
wire take_branch = i_branch_op & (!i_cond_branch | (i_alu_cmp^i_bne_or_bge));
|
||||||
|
|
||||||
wire last_init = o_cnt_done & o_init;
|
|
||||||
|
|
||||||
//valid signal for mdu
|
//valid signal for mdu
|
||||||
assign o_mdu_valid = MDU & !o_cnt_en & init_done & i_mdu_op;
|
assign o_mdu_valid = MDU & !o_cnt_en & init_done & i_mdu_op;
|
||||||
|
|
||||||
//Prepare RF for writes when everything is ready to enter stage two
|
//Prepare RF for writes when everything is ready to enter stage two
|
||||||
// and the first stage didn't cause a misalign exception
|
// and the first stage didn't cause a misalign exception
|
||||||
//Left shifts, SLT & Branch ops. First cycle after init
|
assign o_rf_wreq = !misalign_trap_sync & !o_cnt_en & init_done &
|
||||||
//Right shift. o_sh_done
|
((i_shift_op & (i_sh_done | !i_sh_right)) |
|
||||||
//Mem ops. i_dbus_ack
|
|
||||||
//MDU ops. i_mdu_ready
|
|
||||||
assign o_rf_wreq = (i_shift_op & (i_sh_right ? (i_sh_done & (last_init | !o_cnt_en & init_done)) : last_init)) |
|
|
||||||
i_dbus_ack | (MDU & i_mdu_ready) |
|
i_dbus_ack | (MDU & i_mdu_ready) |
|
||||||
(i_branch_op & (last_init & !trap_pending)) |
|
i_slt_or_branch);
|
||||||
(i_rd_alu_en & i_alu_rd_sel1 & last_init);
|
|
||||||
|
|
||||||
assign o_dbus_cyc = !o_cnt_en & init_done & i_dbus_en & !i_mem_misalign;
|
assign o_dbus_cyc = !o_cnt_en & init_done & i_dbus_en & !i_mem_misalign;
|
||||||
|
|
||||||
//Prepare RF for reads when a new instruction is fetched
|
//Prepare RF for reads when a new instruction is fetched
|
||||||
// or when stage one caused an exception (rreq implies a write request too)
|
// or when stage one caused an exception (rreq implies a write request too)
|
||||||
assign o_rf_rreq = i_ibus_ack | (trap_pending & last_init);
|
assign o_rf_rreq = i_ibus_ack | (stage_two_req & misalign_trap_sync);
|
||||||
|
|
||||||
assign o_rf_rd_en = i_rd_op & !o_init;
|
assign o_rf_rd_en = i_rd_op & !o_init;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
bufreg is used during mem, branch, and shift operations
|
bufreg is used during mem. branch and shift operations
|
||||||
|
|
||||||
mem : bufreg is used for dbus address. Shift in data during phase 1.
|
mem : bufreg is used for dbus address. Shift in data during phase 1.
|
||||||
Shift out during phase 2 if there was a misalignment exception.
|
Shift out during phase 2 if there was an misalignment exception.
|
||||||
|
|
||||||
branch : Shift in during phase 1. Shift out during phase 2
|
branch : Shift in during phase 1. Shift out during phase 2
|
||||||
|
|
||||||
shift : Shift in during phase 1. Continue shifting between phases (except
|
shift : Shift in during phase 1. Continue shifting between phases (except
|
||||||
for the first cycle after init). Shift out during phase 2
|
for the first cycle after init). Shift out during phase 2
|
||||||
*/
|
*/
|
||||||
|
assign o_bufreg_en = (o_cnt_en & (o_init | ((o_ctrl_trap | i_branch_op) & i_two_stage_op))) | (i_shift_op & !stage_two_req & (i_sh_right | i_sh_done_r) & init_done);
|
||||||
assign o_bufreg_en = (o_cnt_en & (o_init | ((o_ctrl_trap | i_branch_op) & i_two_stage_op))) | (i_shift_op & init_done & (i_sh_right | i_sh_done));
|
|
||||||
|
|
||||||
assign o_ibus_cyc = ibus_cyc & !i_rst;
|
assign o_ibus_cyc = ibus_cyc & !i_rst;
|
||||||
|
|
||||||
assign o_init = i_two_stage_op & !i_new_irq & !init_done;
|
assign o_init = i_two_stage_op & !i_new_irq & !init_done;
|
||||||
|
|
||||||
assign o_cnt_done = (o_cnt[4:2] == 3'b111) & cnt_r[3];
|
|
||||||
|
|
||||||
always @(posedge i_clk) begin
|
always @(posedge i_clk) begin
|
||||||
//ibus_cyc changes on three conditions.
|
//ibus_cyc changes on three conditions.
|
||||||
//1. i_rst is asserted. Together with the async gating above, o_ibus_cyc
|
//1. i_rst is asserted. Together with the async gating above, o_ibus_cyc
|
||||||
// will be asserted as soon as the reset is released. This is how the
|
// will be asserted as soon as the reset is released. This is how the
|
||||||
// first instruction is fetched
|
// first instruction is fetced
|
||||||
//2. o_cnt_done and o_ctrl_pc_en are asserted. This means that SERV just
|
//2. o_cnt_done and o_ctrl_pc_en are asserted. This means that SERV just
|
||||||
// finished updating the PC, is done with the current instruction and
|
// finished updating the PC, is done with the current instruction and
|
||||||
// o_ibus_cyc gets asserted to fetch a new instruction
|
// o_ibus_cyc gets asserted to fetch a new instruction
|
||||||
|
@ -150,28 +138,23 @@ module serv_state
|
||||||
init_done <= o_init & !init_done;
|
init_done <= o_init & !init_done;
|
||||||
o_ctrl_jump <= o_init & take_branch;
|
o_ctrl_jump <= o_init & take_branch;
|
||||||
end
|
end
|
||||||
|
o_cnt_done <= (o_cnt[4:2] == 3'b111) & o_cnt_r[2];
|
||||||
|
|
||||||
if (i_rst) begin
|
//Need a strobe for the first cycle in the IDLE state after INIT
|
||||||
if (RESET_STRATEGY != "NONE") begin
|
stage_two_req <= o_cnt_done & o_init;
|
||||||
init_done <= 1'b0;
|
|
||||||
o_ctrl_jump <= 1'b0;
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
generate
|
|
||||||
/*
|
/*
|
||||||
Because SERV is 32-bit bit-serial we need a counter than can count 0-31
|
Because SERV is 32-bit bit-serial we need a counter than can count 0-31
|
||||||
to keep track of which bit we are currently processing. o_cnt and cnt_r
|
to keep track of which bit we are currently processing. o_cnt and o_cnt_r
|
||||||
are used together to create such a counter.
|
are used together to create such a counter.
|
||||||
The top three bits (o_cnt) are implemented as a normal counter, but
|
The top three bits (o_cnt) are implemented as a normal counter, but
|
||||||
instead of the two LSB, cnt_r is a 4-bit shift register which loops 0-3
|
instead of the two LSB, o_cnt_r is a 4-bit shift register which loops 0-3
|
||||||
When cnt_r[3] is 1, o_cnt will be increased.
|
When o_cnt_r[3] is 1, o_cnt will be increased.
|
||||||
|
|
||||||
The counting starts when the core is idle and the i_rf_ready signal
|
The counting starts when the core is idle and the i_rf_ready signal
|
||||||
comes in from the RF module by shifting in the i_rf_ready bit as LSB of
|
comes in from the RF module by shifting in the i_rf_ready bit as LSB of
|
||||||
the shift register. Counting is stopped by using o_cnt_done to block the
|
the shift register. Counting is stopped by using o_cnt_done to block the
|
||||||
bit that was supposed to be shifted into bit 0 of cnt_r.
|
bit that was supposed to be shifted into bit 0 of o_cnt_r.
|
||||||
|
|
||||||
There are two benefit of doing the counter this way
|
There are two benefit of doing the counter this way
|
||||||
1. We only need to check four bits instead of five when we want to check
|
1. We only need to check four bits instead of five when we want to check
|
||||||
|
@ -179,55 +162,43 @@ module serv_state
|
||||||
we only need one LUT instead of two for each comparison.
|
we only need one LUT instead of two for each comparison.
|
||||||
2. We don't need a separate enable signal to turn on and off the counter
|
2. We don't need a separate enable signal to turn on and off the counter
|
||||||
between stages, which saves an extra FF and a unique control signal. We
|
between stages, which saves an extra FF and a unique control signal. We
|
||||||
just need to check if cnt_r is not zero to see if the counter is
|
just need to check if o_cnt_r is not zero to see if the counter is
|
||||||
currently running
|
currently running
|
||||||
*/
|
*/
|
||||||
if (W == 1) begin : gen_cnt_w_eq_1
|
o_cnt <= o_cnt + {2'd0,o_cnt_r[3]};
|
||||||
reg [3:0] cnt_lsb;
|
o_cnt_r <= {o_cnt_r[2:0],(o_cnt_r[3] & !o_cnt_done) | (i_rf_ready & !o_cnt_en)};
|
||||||
always @(posedge i_clk) begin
|
if (i_rst) begin
|
||||||
o_cnt <= o_cnt + {2'd0,cnt_r[3]};
|
if (RESET_STRATEGY != "NONE") begin
|
||||||
cnt_lsb <= {cnt_lsb[2:0],(cnt_lsb[3] & !o_cnt_done) | i_rf_ready};
|
o_cnt <= 3'd0;
|
||||||
if (i_rst & (RESET_STRATEGY != "NONE")) begin
|
init_done <= 1'b0;
|
||||||
o_cnt <= 3'd0;
|
o_ctrl_jump <= 1'b0;
|
||||||
cnt_lsb <= 4'b0000;
|
o_cnt_done <= 1'b0;
|
||||||
end
|
o_cnt_r <= 4'b0000;
|
||||||
|
stage_two_req <= 1'b0;
|
||||||
end
|
end
|
||||||
assign cnt_r = cnt_lsb;
|
|
||||||
assign o_cnt_en = |cnt_lsb;
|
|
||||||
end else if (W == 4) begin : gen_cnt_w_eq_4
|
|
||||||
reg cnt_en;
|
|
||||||
always @(posedge i_clk) begin
|
|
||||||
if (i_rf_ready) cnt_en <= 1; else
|
|
||||||
if (o_cnt_done) cnt_en <= 0;
|
|
||||||
o_cnt <= o_cnt + { 2'd0, cnt_en };
|
|
||||||
if (i_rst & (RESET_STRATEGY != "NONE")) begin
|
|
||||||
o_cnt <= 3'd0;
|
|
||||||
cnt_en <= 1'b0;
|
|
||||||
end
|
|
||||||
end
|
|
||||||
assign cnt_r = 4'b1111;
|
|
||||||
assign o_cnt_en = cnt_en;
|
|
||||||
end
|
end
|
||||||
endgenerate
|
end
|
||||||
|
|
||||||
assign o_ctrl_trap = WITH_CSR & (i_e_op | i_new_irq | misalign_trap_sync);
|
assign o_ctrl_trap = WITH_CSR & (i_e_op | i_new_irq | misalign_trap_sync);
|
||||||
|
|
||||||
|
generate
|
||||||
|
if (WITH_CSR) begin
|
||||||
|
reg misalign_trap_sync_r;
|
||||||
|
|
||||||
//trap_pending is only guaranteed to have correct value during the
|
//trap_pending is only guaranteed to have correct value during the
|
||||||
// last cycle of the init stage
|
// last cycle of the init stage
|
||||||
wire trap_pending = WITH_CSR & ((take_branch & i_ctrl_misalign & !ALIGN) |
|
wire trap_pending = WITH_CSR & ((take_branch & i_ctrl_misalign & !ALIGN) |
|
||||||
(i_dbus_en & i_mem_misalign));
|
(i_dbus_en & i_mem_misalign));
|
||||||
|
|
||||||
generate
|
|
||||||
if (WITH_CSR) begin : gen_csr
|
|
||||||
reg misalign_trap_sync_r;
|
|
||||||
|
|
||||||
always @(posedge i_clk) begin
|
always @(posedge i_clk) begin
|
||||||
if (i_ibus_ack | o_cnt_done | i_rst)
|
if (o_cnt_done)
|
||||||
misalign_trap_sync_r <= !(i_ibus_ack | i_rst) & ((trap_pending & o_init) | misalign_trap_sync_r);
|
misalign_trap_sync_r <= trap_pending & o_init;
|
||||||
|
if (i_rst)
|
||||||
|
if (RESET_STRATEGY != "NONE")
|
||||||
|
misalign_trap_sync_r <= 1'b0;
|
||||||
end
|
end
|
||||||
assign misalign_trap_sync = misalign_trap_sync_r;
|
assign misalign_trap_sync = misalign_trap_sync_r;
|
||||||
end else begin : gen_no_csr
|
end else
|
||||||
assign misalign_trap_sync = 1'b0;
|
assign misalign_trap_sync = 1'b0;
|
||||||
end
|
|
||||||
endgenerate
|
endgenerate
|
||||||
endmodule
|
endmodule
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
`default_nettype none
|
`default_nettype none
|
||||||
|
|
||||||
module serv_synth_wrapper
|
module serv_synth_wrapper
|
||||||
#(
|
#(
|
||||||
/* Register signals before or after the decoder
|
/* Register signals before or after the decoder
|
||||||
0 : Register after the decoder. Faster but uses more resources
|
0 : Register after the decoder. Faster but uses more resources
|
||||||
|
@ -21,6 +21,29 @@ module serv_synth_wrapper
|
||||||
input wire clk,
|
input wire clk,
|
||||||
input wire i_rst,
|
input wire i_rst,
|
||||||
input wire i_timer_irq,
|
input wire i_timer_irq,
|
||||||
|
`ifdef RISCV_FORMAL
|
||||||
|
output wire rvfi_valid,
|
||||||
|
output wire [63:0] rvfi_order,
|
||||||
|
output wire [31:0] rvfi_insn,
|
||||||
|
output wire rvfi_trap,
|
||||||
|
output wire rvfi_halt,
|
||||||
|
output wire rvfi_intr,
|
||||||
|
output wire [1:0] rvfi_mode,
|
||||||
|
output wire [1:0] rvfi_ixl,
|
||||||
|
output wire [4:0] rvfi_rs1_addr,
|
||||||
|
output wire [4:0] rvfi_rs2_addr,
|
||||||
|
output wire [31:0] rvfi_rs1_rdata,
|
||||||
|
output wire [31:0] rvfi_rs2_rdata,
|
||||||
|
output wire [4:0] rvfi_rd_addr,
|
||||||
|
output wire [31:0] rvfi_rd_wdata,
|
||||||
|
output wire [31:0] rvfi_pc_rdata,
|
||||||
|
output wire [31:0] rvfi_pc_wdata,
|
||||||
|
output wire [31:0] rvfi_mem_addr,
|
||||||
|
output wire [3:0] rvfi_mem_rmask,
|
||||||
|
output wire [3:0] rvfi_mem_wmask,
|
||||||
|
output wire [31:0] rvfi_mem_rdata,
|
||||||
|
output wire [31:0] rvfi_mem_wdata,
|
||||||
|
`endif
|
||||||
output wire [31:0] o_ibus_adr,
|
output wire [31:0] o_ibus_adr,
|
||||||
output wire o_ibus_cyc,
|
output wire o_ibus_cyc,
|
||||||
input wire [31:0] i_ibus_rdt,
|
input wire [31:0] i_ibus_rdt,
|
||||||
|
@ -32,13 +55,13 @@ module serv_synth_wrapper
|
||||||
output wire o_dbus_cyc,
|
output wire o_dbus_cyc,
|
||||||
input wire [31:0] i_dbus_rdt,
|
input wire [31:0] i_dbus_rdt,
|
||||||
input wire i_dbus_ack,
|
input wire i_dbus_ack,
|
||||||
|
|
||||||
output wire [RF_L2D-1:0] o_waddr,
|
output wire [RF_L2D-1:0] o_waddr,
|
||||||
output wire [RF_WIDTH-1:0] o_wdata,
|
output wire [RF_WIDTH-1:0] o_wdata,
|
||||||
output wire o_wen,
|
output wire o_wen,
|
||||||
output wire [RF_L2D-1:0] o_raddr,
|
output wire [RF_L2D-1:0] o_raddr,
|
||||||
input wire [RF_WIDTH-1:0] i_rdata);
|
input wire [RF_WIDTH-1:0] i_rdata);
|
||||||
|
|
||||||
localparam CSR_REGS = WITH_CSR*4;
|
localparam CSR_REGS = WITH_CSR*4;
|
||||||
|
|
||||||
wire rf_wreq;
|
wire rf_wreq;
|
||||||
|
@ -118,7 +141,7 @@ module serv_synth_wrapper
|
||||||
.o_dbus_cyc (o_dbus_cyc),
|
.o_dbus_cyc (o_dbus_cyc),
|
||||||
.i_dbus_rdt (i_dbus_rdt),
|
.i_dbus_rdt (i_dbus_rdt),
|
||||||
.i_dbus_ack (i_dbus_ack),
|
.i_dbus_ack (i_dbus_ack),
|
||||||
|
|
||||||
//Extension
|
//Extension
|
||||||
.o_ext_funct3 (),
|
.o_ext_funct3 (),
|
||||||
.i_ext_ready (1'b0),
|
.i_ext_ready (1'b0),
|
||||||
|
|
286
rtl/serv_top.v
286
rtl/serv_top.v
|
@ -1,42 +1,39 @@
|
||||||
`default_nettype none
|
`default_nettype none
|
||||||
|
|
||||||
module serv_top
|
module serv_top
|
||||||
#(parameter WITH_CSR = 1,
|
#(parameter WITH_CSR = 1,
|
||||||
parameter W = 1,
|
parameter PRE_REGISTER = 1,
|
||||||
parameter B = W-1,
|
parameter RESET_STRATEGY = "MINI",
|
||||||
parameter PRE_REGISTER = 1,
|
parameter RESET_PC = 32'd0,
|
||||||
parameter RESET_STRATEGY = "MINI",
|
|
||||||
parameter RESET_PC = 32'd0,
|
|
||||||
parameter [0:0] DEBUG = 1'b0,
|
|
||||||
parameter [0:0] MDU = 1'b0,
|
parameter [0:0] MDU = 1'b0,
|
||||||
parameter [0:0] COMPRESSED=0,
|
parameter [0:0] COMPRESSED=0,
|
||||||
parameter [0:0] ALIGN = COMPRESSED)
|
parameter [0:0] ALIGN = 0)
|
||||||
(
|
(
|
||||||
input wire clk,
|
input wire clk,
|
||||||
input wire i_rst,
|
input wire i_rst,
|
||||||
input wire i_timer_irq,
|
input wire i_timer_irq,
|
||||||
`ifdef RISCV_FORMAL
|
`ifdef RISCV_FORMAL
|
||||||
output wire rvfi_valid,
|
output reg rvfi_valid = 1'b0,
|
||||||
output wire [63:0] rvfi_order,
|
output reg [63:0] rvfi_order = 64'd0,
|
||||||
output wire [31:0] rvfi_insn,
|
output reg [31:0] rvfi_insn = 32'd0,
|
||||||
output wire rvfi_trap,
|
output reg rvfi_trap = 1'b0,
|
||||||
output wire rvfi_halt,
|
output reg rvfi_halt = 1'b0,
|
||||||
output wire rvfi_intr,
|
output reg rvfi_intr = 1'b0,
|
||||||
output wire [1:0] rvfi_mode,
|
output reg [1:0] rvfi_mode = 2'b11,
|
||||||
output wire [1:0] rvfi_ixl,
|
output reg [1:0] rvfi_ixl = 2'b01,
|
||||||
output wire [4:0] rvfi_rs1_addr,
|
output reg [4:0] rvfi_rs1_addr,
|
||||||
output wire [4:0] rvfi_rs2_addr,
|
output reg [4:0] rvfi_rs2_addr,
|
||||||
output wire [31:0] rvfi_rs1_rdata,
|
output reg [31:0] rvfi_rs1_rdata,
|
||||||
output wire [31:0] rvfi_rs2_rdata,
|
output reg [31:0] rvfi_rs2_rdata,
|
||||||
output wire [4:0] rvfi_rd_addr,
|
output reg [4:0] rvfi_rd_addr,
|
||||||
output wire [31:0] rvfi_rd_wdata,
|
output reg [31:0] rvfi_rd_wdata,
|
||||||
output wire [31:0] rvfi_pc_rdata,
|
output reg [31:0] rvfi_pc_rdata,
|
||||||
output wire [31:0] rvfi_pc_wdata,
|
output reg [31:0] rvfi_pc_wdata,
|
||||||
output wire [31:0] rvfi_mem_addr,
|
output reg [31:0] rvfi_mem_addr,
|
||||||
output wire [3:0] rvfi_mem_rmask,
|
output reg [3:0] rvfi_mem_rmask,
|
||||||
output wire [3:0] rvfi_mem_wmask,
|
output reg [3:0] rvfi_mem_wmask,
|
||||||
output wire [31:0] rvfi_mem_rdata,
|
output reg [31:0] rvfi_mem_rdata,
|
||||||
output wire [31:0] rvfi_mem_wdata,
|
output reg [31:0] rvfi_mem_wdata,
|
||||||
`endif
|
`endif
|
||||||
//RF Interface
|
//RF Interface
|
||||||
output wire o_rf_rreq,
|
output wire o_rf_rreq,
|
||||||
|
@ -46,12 +43,12 @@ module serv_top
|
||||||
output wire [4+WITH_CSR:0] o_wreg1,
|
output wire [4+WITH_CSR:0] o_wreg1,
|
||||||
output wire o_wen0,
|
output wire o_wen0,
|
||||||
output wire o_wen1,
|
output wire o_wen1,
|
||||||
output wire [B:0] o_wdata0,
|
output wire o_wdata0,
|
||||||
output wire [B:0] o_wdata1,
|
output wire o_wdata1,
|
||||||
output wire [4+WITH_CSR:0] o_rreg0,
|
output wire [4+WITH_CSR:0] o_rreg0,
|
||||||
output wire [4+WITH_CSR:0] o_rreg1,
|
output wire [4+WITH_CSR:0] o_rreg1,
|
||||||
input wire [B:0] i_rdata0,
|
input wire i_rdata0,
|
||||||
input wire [B:0] i_rdata1,
|
input wire i_rdata1,
|
||||||
|
|
||||||
output wire [31:0] o_ibus_adr,
|
output wire [31:0] o_ibus_adr,
|
||||||
output wire o_ibus_cyc,
|
output wire o_ibus_cyc,
|
||||||
|
@ -88,16 +85,17 @@ module serv_top
|
||||||
wire ebreak;
|
wire ebreak;
|
||||||
wire branch_op;
|
wire branch_op;
|
||||||
wire shift_op;
|
wire shift_op;
|
||||||
|
wire slt_or_branch;
|
||||||
wire rd_op;
|
wire rd_op;
|
||||||
wire mdu_op;
|
wire mdu_op;
|
||||||
|
|
||||||
wire rd_alu_en;
|
wire rd_alu_en;
|
||||||
wire rd_csr_en;
|
wire rd_csr_en;
|
||||||
wire rd_mem_en;
|
wire rd_mem_en;
|
||||||
wire [B:0] ctrl_rd;
|
wire ctrl_rd;
|
||||||
wire [B:0] alu_rd;
|
wire alu_rd;
|
||||||
wire [B:0] mem_rd;
|
wire mem_rd;
|
||||||
wire [B:0] csr_rd;
|
wire csr_rd;
|
||||||
wire mtval_pc;
|
wire mtval_pc;
|
||||||
|
|
||||||
wire ctrl_pc_en;
|
wire ctrl_pc_en;
|
||||||
|
@ -105,7 +103,7 @@ module serv_top
|
||||||
wire jal_or_jalr;
|
wire jal_or_jalr;
|
||||||
wire utype;
|
wire utype;
|
||||||
wire mret;
|
wire mret;
|
||||||
wire [B:0] imm;
|
wire imm;
|
||||||
wire trap;
|
wire trap;
|
||||||
wire pc_rel;
|
wire pc_rel;
|
||||||
wire iscomp;
|
wire iscomp;
|
||||||
|
@ -119,8 +117,6 @@ module serv_top
|
||||||
wire cnt2;
|
wire cnt2;
|
||||||
wire cnt3;
|
wire cnt3;
|
||||||
wire cnt7;
|
wire cnt7;
|
||||||
wire cnt11;
|
|
||||||
wire cnt12;
|
|
||||||
|
|
||||||
wire cnt_done;
|
wire cnt_done;
|
||||||
|
|
||||||
|
@ -129,8 +125,8 @@ module serv_top
|
||||||
wire bufreg_rs1_en;
|
wire bufreg_rs1_en;
|
||||||
wire bufreg_imm_en;
|
wire bufreg_imm_en;
|
||||||
wire bufreg_clr_lsb;
|
wire bufreg_clr_lsb;
|
||||||
wire [B:0] bufreg_q;
|
wire bufreg_q;
|
||||||
wire [B:0] bufreg2_q;
|
wire bufreg2_q;
|
||||||
wire [31:0] dbus_rdt;
|
wire [31:0] dbus_rdt;
|
||||||
wire dbus_ack;
|
wire dbus_ack;
|
||||||
|
|
||||||
|
@ -141,11 +137,11 @@ module serv_top
|
||||||
wire alu_cmp;
|
wire alu_cmp;
|
||||||
wire [2:0] alu_rd_sel;
|
wire [2:0] alu_rd_sel;
|
||||||
|
|
||||||
wire [B:0] rs1;
|
wire rs1;
|
||||||
wire [B:0] rs2;
|
wire rs2;
|
||||||
wire rd_en;
|
wire rd_en;
|
||||||
|
|
||||||
wire [B:0] op_b;
|
wire op_b;
|
||||||
wire op_b_sel;
|
wire op_b_sel;
|
||||||
|
|
||||||
wire mem_signed;
|
wire mem_signed;
|
||||||
|
@ -153,23 +149,25 @@ module serv_top
|
||||||
wire mem_half;
|
wire mem_half;
|
||||||
wire [1:0] mem_bytecnt;
|
wire [1:0] mem_bytecnt;
|
||||||
wire sh_done;
|
wire sh_done;
|
||||||
|
wire sh_done_r;
|
||||||
|
wire byte_valid;
|
||||||
|
|
||||||
wire mem_misalign;
|
wire mem_misalign;
|
||||||
|
|
||||||
wire [B:0] bad_pc;
|
wire bad_pc;
|
||||||
|
|
||||||
wire csr_mstatus_en;
|
wire csr_mstatus_en;
|
||||||
wire csr_mie_en;
|
wire csr_mie_en;
|
||||||
wire csr_mcause_en;
|
wire csr_mcause_en;
|
||||||
wire [1:0] csr_source;
|
wire [1:0] csr_source;
|
||||||
wire [B:0] csr_imm;
|
wire csr_imm;
|
||||||
wire csr_d_sel;
|
wire csr_d_sel;
|
||||||
wire csr_en;
|
wire csr_en;
|
||||||
wire [1:0] csr_addr;
|
wire [1:0] csr_addr;
|
||||||
wire [B:0] csr_pc;
|
wire csr_pc;
|
||||||
wire csr_imm_en;
|
wire csr_imm_en;
|
||||||
wire [B:0] csr_in;
|
wire csr_in;
|
||||||
wire [B:0] rf_csr_out;
|
wire rf_csr_out;
|
||||||
wire dbus_en;
|
wire dbus_en;
|
||||||
|
|
||||||
wire new_irq;
|
wire new_irq;
|
||||||
|
@ -184,7 +182,7 @@ module serv_top
|
||||||
wire wb_ibus_ack;
|
wire wb_ibus_ack;
|
||||||
|
|
||||||
generate
|
generate
|
||||||
if (ALIGN) begin : gen_align
|
if (ALIGN) begin
|
||||||
serv_aligner align
|
serv_aligner align
|
||||||
(
|
(
|
||||||
.clk(clk),
|
.clk(clk),
|
||||||
|
@ -199,7 +197,7 @@ module serv_top
|
||||||
.o_wb_ibus_cyc(o_ibus_cyc),
|
.o_wb_ibus_cyc(o_ibus_cyc),
|
||||||
.i_wb_ibus_rdt(i_ibus_rdt),
|
.i_wb_ibus_rdt(i_ibus_rdt),
|
||||||
.i_wb_ibus_ack(i_ibus_ack));
|
.i_wb_ibus_ack(i_ibus_ack));
|
||||||
end else begin : gen_no_align
|
end else begin
|
||||||
assign o_ibus_adr = wb_ibus_adr;
|
assign o_ibus_adr = wb_ibus_adr;
|
||||||
assign o_ibus_cyc = wb_ibus_cyc;
|
assign o_ibus_cyc = wb_ibus_cyc;
|
||||||
assign wb_ibus_rdt = i_ibus_rdt;
|
assign wb_ibus_rdt = i_ibus_rdt;
|
||||||
|
@ -207,8 +205,8 @@ module serv_top
|
||||||
end
|
end
|
||||||
endgenerate
|
endgenerate
|
||||||
|
|
||||||
generate
|
generate
|
||||||
if (COMPRESSED) begin : gen_compressed
|
if (COMPRESSED) begin
|
||||||
serv_compdec compdec
|
serv_compdec compdec
|
||||||
(
|
(
|
||||||
.i_clk(clk),
|
.i_clk(clk),
|
||||||
|
@ -216,7 +214,7 @@ module serv_top
|
||||||
.i_ack(wb_ibus_ack),
|
.i_ack(wb_ibus_ack),
|
||||||
.o_instr(i_wb_rdt),
|
.o_instr(i_wb_rdt),
|
||||||
.o_iscomp(iscomp));
|
.o_iscomp(iscomp));
|
||||||
end else begin : gen_no_compressed
|
end else begin
|
||||||
assign i_wb_rdt = wb_ibus_rdt;
|
assign i_wb_rdt = wb_ibus_rdt;
|
||||||
assign iscomp = 1'b0;
|
assign iscomp = 1'b0;
|
||||||
end
|
end
|
||||||
|
@ -226,8 +224,7 @@ module serv_top
|
||||||
#(.RESET_STRATEGY (RESET_STRATEGY),
|
#(.RESET_STRATEGY (RESET_STRATEGY),
|
||||||
.WITH_CSR (WITH_CSR[0:0]),
|
.WITH_CSR (WITH_CSR[0:0]),
|
||||||
.MDU(MDU),
|
.MDU(MDU),
|
||||||
.ALIGN(ALIGN),
|
.ALIGN(ALIGN))
|
||||||
.W(W))
|
|
||||||
state
|
state
|
||||||
(
|
(
|
||||||
.i_clk (clk),
|
.i_clk (clk),
|
||||||
|
@ -244,8 +241,6 @@ module serv_top
|
||||||
.o_cnt2 (cnt2),
|
.o_cnt2 (cnt2),
|
||||||
.o_cnt3 (cnt3),
|
.o_cnt3 (cnt3),
|
||||||
.o_cnt7 (cnt7),
|
.o_cnt7 (cnt7),
|
||||||
.o_cnt11 (cnt11),
|
|
||||||
.o_cnt12 (cnt12),
|
|
||||||
.o_cnt_done (cnt_done),
|
.o_cnt_done (cnt_done),
|
||||||
.o_bufreg_en (bufreg_en),
|
.o_bufreg_en (bufreg_en),
|
||||||
.o_ctrl_pc_en (ctrl_pc_en),
|
.o_ctrl_pc_en (ctrl_pc_en),
|
||||||
|
@ -253,6 +248,7 @@ module serv_top
|
||||||
.o_ctrl_trap (trap),
|
.o_ctrl_trap (trap),
|
||||||
.i_ctrl_misalign(lsb[1]),
|
.i_ctrl_misalign(lsb[1]),
|
||||||
.i_sh_done (sh_done),
|
.i_sh_done (sh_done),
|
||||||
|
.i_sh_done_r (sh_done_r),
|
||||||
.o_mem_bytecnt (mem_bytecnt),
|
.o_mem_bytecnt (mem_bytecnt),
|
||||||
.i_mem_misalign (mem_misalign),
|
.i_mem_misalign (mem_misalign),
|
||||||
//Control
|
//Control
|
||||||
|
@ -263,8 +259,7 @@ module serv_top
|
||||||
.i_branch_op (branch_op),
|
.i_branch_op (branch_op),
|
||||||
.i_shift_op (shift_op),
|
.i_shift_op (shift_op),
|
||||||
.i_sh_right (sh_right),
|
.i_sh_right (sh_right),
|
||||||
.i_alu_rd_sel1 (alu_rd_sel[1]),
|
.i_slt_or_branch (slt_or_branch),
|
||||||
.i_rd_alu_en (rd_alu_en),
|
|
||||||
.i_e_op (e_op),
|
.i_e_op (e_op),
|
||||||
.i_rd_op (rd_op),
|
.i_rd_op (rd_op),
|
||||||
//MDU
|
//MDU
|
||||||
|
@ -300,6 +295,7 @@ module serv_top
|
||||||
.o_ebreak (ebreak),
|
.o_ebreak (ebreak),
|
||||||
.o_branch_op (branch_op),
|
.o_branch_op (branch_op),
|
||||||
.o_shift_op (shift_op),
|
.o_shift_op (shift_op),
|
||||||
|
.o_slt_or_branch (slt_or_branch),
|
||||||
.o_rd_op (rd_op),
|
.o_rd_op (rd_op),
|
||||||
.o_sh_right (sh_right),
|
.o_sh_right (sh_right),
|
||||||
.o_mdu_op (mdu_op),
|
.o_mdu_op (mdu_op),
|
||||||
|
@ -399,12 +395,11 @@ module serv_top
|
||||||
//State
|
//State
|
||||||
.i_en (cnt_en),
|
.i_en (cnt_en),
|
||||||
.i_init (init),
|
.i_init (init),
|
||||||
.i_cnt7 (cnt7),
|
|
||||||
.i_cnt_done (cnt_done),
|
.i_cnt_done (cnt_done),
|
||||||
.i_sh_right (sh_right),
|
|
||||||
.i_lsb (lsb),
|
.i_lsb (lsb),
|
||||||
.i_bytecnt (mem_bytecnt),
|
.i_byte_valid (byte_valid),
|
||||||
.o_sh_done (sh_done),
|
.o_sh_done (sh_done),
|
||||||
|
.o_sh_done_r (sh_done_r),
|
||||||
//Control
|
//Control
|
||||||
.i_op_b_sel (op_b_sel),
|
.i_op_b_sel (op_b_sel),
|
||||||
.i_shift_op (shift_op),
|
.i_shift_op (shift_op),
|
||||||
|
@ -421,8 +416,7 @@ module serv_top
|
||||||
serv_ctrl
|
serv_ctrl
|
||||||
#(.RESET_PC (RESET_PC),
|
#(.RESET_PC (RESET_PC),
|
||||||
.RESET_STRATEGY (RESET_STRATEGY),
|
.RESET_STRATEGY (RESET_STRATEGY),
|
||||||
.WITH_CSR (WITH_CSR),
|
.WITH_CSR (WITH_CSR))
|
||||||
.W (W))
|
|
||||||
ctrl
|
ctrl
|
||||||
(
|
(
|
||||||
.clk (clk),
|
.clk (clk),
|
||||||
|
@ -449,7 +443,7 @@ module serv_top
|
||||||
//External
|
//External
|
||||||
.o_ibus_adr (wb_ibus_adr));
|
.o_ibus_adr (wb_ibus_adr));
|
||||||
|
|
||||||
serv_alu #(.W (W)) alu
|
serv_alu alu
|
||||||
(
|
(
|
||||||
.clk (clk),
|
.clk (clk),
|
||||||
//State
|
//State
|
||||||
|
@ -469,7 +463,7 @@ module serv_top
|
||||||
.o_rd (alu_rd));
|
.o_rd (alu_rd));
|
||||||
|
|
||||||
serv_rf_if
|
serv_rf_if
|
||||||
#(.WITH_CSR (WITH_CSR), .W(W))
|
#(.WITH_CSR (WITH_CSR))
|
||||||
rf_if
|
rf_if
|
||||||
(//RF interface
|
(//RF interface
|
||||||
.i_cnt_en (cnt_en),
|
.i_cnt_en (cnt_en),
|
||||||
|
@ -487,7 +481,7 @@ module serv_top
|
||||||
//Trap interface
|
//Trap interface
|
||||||
.i_trap (trap),
|
.i_trap (trap),
|
||||||
.i_mret (mret),
|
.i_mret (mret),
|
||||||
.i_mepc (wb_ibus_adr[B:0]),
|
.i_mepc (wb_ibus_adr[0]),
|
||||||
.i_mtval_pc (mtval_pc),
|
.i_mtval_pc (mtval_pc),
|
||||||
.i_bufreg_q (bufreg_q),
|
.i_bufreg_q (bufreg_q),
|
||||||
.i_bad_pc (bad_pc),
|
.i_bad_pc (bad_pc),
|
||||||
|
@ -518,14 +512,14 @@ module serv_top
|
||||||
.o_csr (rf_csr_out));
|
.o_csr (rf_csr_out));
|
||||||
|
|
||||||
serv_mem_if
|
serv_mem_if
|
||||||
#(.WITH_CSR (WITH_CSR[0:0]),
|
#(.WITH_CSR (WITH_CSR[0:0]))
|
||||||
.W (W))
|
|
||||||
mem_if
|
mem_if
|
||||||
(
|
(
|
||||||
.i_clk (clk),
|
.i_clk (clk),
|
||||||
//State
|
//State
|
||||||
.i_bytecnt (mem_bytecnt),
|
.i_bytecnt (mem_bytecnt),
|
||||||
.i_lsb (lsb),
|
.i_lsb (lsb),
|
||||||
|
.o_byte_valid (byte_valid),
|
||||||
.o_misalign (mem_misalign),
|
.o_misalign (mem_misalign),
|
||||||
//Control
|
//Control
|
||||||
.i_mdu_op (mdu_op),
|
.i_mdu_op (mdu_op),
|
||||||
|
@ -539,22 +533,19 @@ module serv_top
|
||||||
.o_wb_sel (o_dbus_sel));
|
.o_wb_sel (o_dbus_sel));
|
||||||
|
|
||||||
generate
|
generate
|
||||||
if (|WITH_CSR) begin : gen_csr
|
if (|WITH_CSR) begin
|
||||||
serv_csr
|
serv_csr
|
||||||
#(.RESET_STRATEGY (RESET_STRATEGY),
|
#(.RESET_STRATEGY (RESET_STRATEGY))
|
||||||
.W(W))
|
|
||||||
csr
|
csr
|
||||||
(
|
(
|
||||||
.i_clk (clk),
|
.i_clk (clk),
|
||||||
.i_rst (i_rst),
|
.i_rst (i_rst),
|
||||||
//State
|
//State
|
||||||
.i_trig_irq (wb_ibus_ack),
|
.i_init (init),
|
||||||
.i_en (cnt_en),
|
.i_en (cnt_en),
|
||||||
.i_cnt0to3 (cnt0to3),
|
.i_cnt0to3 (cnt0to3),
|
||||||
.i_cnt3 (cnt3),
|
.i_cnt3 (cnt3),
|
||||||
.i_cnt7 (cnt7),
|
.i_cnt7 (cnt7),
|
||||||
.i_cnt11 (cnt11),
|
|
||||||
.i_cnt12 (cnt12),
|
|
||||||
.i_cnt_done (cnt_done),
|
.i_cnt_done (cnt_done),
|
||||||
.i_mem_op (!mtval_pc),
|
.i_mem_op (!mtval_pc),
|
||||||
.i_mtip (i_timer_irq),
|
.i_mtip (i_timer_irq),
|
||||||
|
@ -576,83 +567,88 @@ module serv_top
|
||||||
.i_csr_imm (csr_imm),
|
.i_csr_imm (csr_imm),
|
||||||
.i_rs1 (rs1),
|
.i_rs1 (rs1),
|
||||||
.o_q (csr_rd));
|
.o_q (csr_rd));
|
||||||
end else begin : gen_no_csr
|
end else begin
|
||||||
assign csr_in = {W{1'b0}};
|
assign csr_in = 1'b0;
|
||||||
assign csr_rd = {W{1'b0}};
|
assign csr_rd = 1'b0;
|
||||||
assign new_irq = 1'b0;
|
assign new_irq = 1'b0;
|
||||||
end
|
end
|
||||||
endgenerate
|
endgenerate
|
||||||
|
|
||||||
generate
|
|
||||||
if (DEBUG) begin : gen_debug
|
|
||||||
serv_debug #(.W (W), .RESET_PC (RESET_PC)) debug
|
|
||||||
(
|
|
||||||
`ifdef RISCV_FORMAL
|
|
||||||
.rvfi_valid (rvfi_valid ),
|
|
||||||
.rvfi_order (rvfi_order ),
|
|
||||||
.rvfi_insn (rvfi_insn ),
|
|
||||||
.rvfi_trap (rvfi_trap ),
|
|
||||||
.rvfi_halt (rvfi_halt ),
|
|
||||||
.rvfi_intr (rvfi_intr ),
|
|
||||||
.rvfi_mode (rvfi_mode ),
|
|
||||||
.rvfi_ixl (rvfi_ixl ),
|
|
||||||
.rvfi_rs1_addr (rvfi_rs1_addr ),
|
|
||||||
.rvfi_rs2_addr (rvfi_rs2_addr ),
|
|
||||||
.rvfi_rs1_rdata (rvfi_rs1_rdata),
|
|
||||||
.rvfi_rs2_rdata (rvfi_rs2_rdata),
|
|
||||||
.rvfi_rd_addr (rvfi_rd_addr ),
|
|
||||||
.rvfi_rd_wdata (rvfi_rd_wdata ),
|
|
||||||
.rvfi_pc_rdata (rvfi_pc_rdata ),
|
|
||||||
.rvfi_pc_wdata (rvfi_pc_wdata ),
|
|
||||||
.rvfi_mem_addr (rvfi_mem_addr ),
|
|
||||||
.rvfi_mem_rmask (rvfi_mem_rmask),
|
|
||||||
.rvfi_mem_wmask (rvfi_mem_wmask),
|
|
||||||
.rvfi_mem_rdata (rvfi_mem_rdata),
|
|
||||||
.rvfi_mem_wdata (rvfi_mem_wdata),
|
|
||||||
.i_dbus_adr (o_dbus_adr),
|
|
||||||
.i_dbus_dat (o_dbus_dat),
|
|
||||||
.i_dbus_sel (o_dbus_sel),
|
|
||||||
.i_dbus_we (o_dbus_we ),
|
|
||||||
.i_dbus_rdt (i_dbus_rdt),
|
|
||||||
.i_dbus_ack (i_dbus_ack),
|
|
||||||
.i_ctrl_pc_en (ctrl_pc_en),
|
|
||||||
.rs1 (rs1),
|
|
||||||
.rs2 (rs2),
|
|
||||||
.rs1_addr (rs1_addr),
|
|
||||||
.rs2_addr (rs2_addr),
|
|
||||||
.immdec_en (immdec_en),
|
|
||||||
.rd_en (rd_en),
|
|
||||||
.trap (trap),
|
|
||||||
.i_rf_ready (i_rf_ready),
|
|
||||||
.i_ibus_cyc (o_ibus_cyc),
|
|
||||||
.two_stage_op (two_stage_op),
|
|
||||||
.init (init),
|
|
||||||
.i_ibus_adr (o_ibus_adr),
|
|
||||||
`endif
|
|
||||||
.i_clk (clk),
|
|
||||||
.i_rst (i_rst),
|
|
||||||
.i_ibus_rdt (i_ibus_rdt),
|
|
||||||
.i_ibus_ack (i_ibus_ack),
|
|
||||||
.i_rd_addr (rd_addr ),
|
|
||||||
.i_cnt_en (cnt_en ),
|
|
||||||
.i_csr_in (csr_in ),
|
|
||||||
.i_csr_mstatus_en (csr_mstatus_en),
|
|
||||||
.i_csr_mie_en (csr_mie_en ),
|
|
||||||
.i_csr_mcause_en (csr_mcause_en ),
|
|
||||||
.i_csr_en (csr_en ),
|
|
||||||
.i_csr_addr (csr_addr),
|
|
||||||
.i_wen0 (o_wen0),
|
|
||||||
.i_wdata0 (o_wdata0),
|
|
||||||
.i_cnt_done (cnt_done));
|
|
||||||
end
|
|
||||||
endgenerate
|
|
||||||
|
|
||||||
|
`ifdef RISCV_FORMAL
|
||||||
|
reg [31:0] pc = RESET_PC;
|
||||||
|
|
||||||
|
wire rs_en = two_stage_op ? init : ctrl_pc_en;
|
||||||
|
|
||||||
|
always @(posedge clk) begin
|
||||||
|
/* End of instruction */
|
||||||
|
rvfi_valid <= cnt_done & ctrl_pc_en & !i_rst;
|
||||||
|
rvfi_order <= rvfi_order + {63'd0,rvfi_valid};
|
||||||
|
|
||||||
|
/* Get instruction word when it's fetched from ibus */
|
||||||
|
if (wb_ibus_cyc & wb_ibus_ack)
|
||||||
|
rvfi_insn <= i_wb_rdt;
|
||||||
|
|
||||||
|
/* Store data written to rd */
|
||||||
|
if (o_wen0)
|
||||||
|
rvfi_rd_wdata <= {o_wdata0,rvfi_rd_wdata[31:1]};
|
||||||
|
|
||||||
|
if (cnt_done & ctrl_pc_en) begin
|
||||||
|
rvfi_pc_rdata <= pc;
|
||||||
|
if (!(rd_en & (|rd_addr))) begin
|
||||||
|
rvfi_rd_addr <= 5'd0;
|
||||||
|
rvfi_rd_wdata <= 32'd0;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
rvfi_trap <= trap;
|
||||||
|
if (rvfi_valid) begin
|
||||||
|
rvfi_trap <= 1'b0;
|
||||||
|
pc <= rvfi_pc_wdata;
|
||||||
|
end
|
||||||
|
|
||||||
|
/* Not used */
|
||||||
|
rvfi_halt <= 1'b0;
|
||||||
|
rvfi_intr <= 1'b0;
|
||||||
|
rvfi_mode <= 2'd3;
|
||||||
|
rvfi_ixl = 2'd1;
|
||||||
|
|
||||||
|
/* RS1 not valid during J, U instructions (immdec_en[1]) */
|
||||||
|
/* RS2 not valid during I, J, U instructions (immdec_en[2]) */
|
||||||
|
if (i_rf_ready) begin
|
||||||
|
rvfi_rs1_addr <= !immdec_en[1] ? rs1_addr : 5'd0;
|
||||||
|
rvfi_rs2_addr <= !immdec_en[2] /*rs2_valid*/ ? rs2_addr : 5'd0;
|
||||||
|
rvfi_rd_addr <= rd_addr;
|
||||||
|
end
|
||||||
|
if (rs_en) begin
|
||||||
|
rvfi_rs1_rdata <= {!immdec_en[1] & rs1,rvfi_rs1_rdata[31:1]};
|
||||||
|
rvfi_rs2_rdata <= {!immdec_en[2] & rs2,rvfi_rs2_rdata[31:1]};
|
||||||
|
end
|
||||||
|
|
||||||
|
if (i_dbus_ack) begin
|
||||||
|
rvfi_mem_addr <= o_dbus_adr;
|
||||||
|
rvfi_mem_rmask <= o_dbus_we ? 4'b0000 : o_dbus_sel;
|
||||||
|
rvfi_mem_wmask <= o_dbus_we ? o_dbus_sel : 4'b0000;
|
||||||
|
rvfi_mem_rdata <= i_dbus_rdt;
|
||||||
|
rvfi_mem_wdata <= o_dbus_dat;
|
||||||
|
end
|
||||||
|
if (wb_ibus_ack) begin
|
||||||
|
rvfi_mem_rmask <= 4'b0000;
|
||||||
|
rvfi_mem_wmask <= 4'b0000;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
/* verilator lint_off COMBDLY */
|
||||||
|
always @(wb_ibus_adr)
|
||||||
|
rvfi_pc_wdata <= wb_ibus_adr;
|
||||||
|
/* verilator lint_on COMBDLY */
|
||||||
|
|
||||||
|
|
||||||
|
`endif
|
||||||
|
|
||||||
generate
|
generate
|
||||||
if (MDU) begin: gen_mdu
|
if (MDU) begin
|
||||||
assign dbus_rdt = i_ext_ready ? i_ext_rd:i_dbus_rdt;
|
assign dbus_rdt = i_ext_ready ? i_ext_rd:i_dbus_rdt;
|
||||||
assign dbus_ack = i_dbus_ack | i_ext_ready;
|
assign dbus_ack = i_dbus_ack | i_ext_ready;
|
||||||
end else begin : gen_no_mdu
|
end else begin
|
||||||
assign dbus_rdt = i_dbus_rdt;
|
assign dbus_rdt = i_dbus_rdt;
|
||||||
assign dbus_ack = i_dbus_ack;
|
assign dbus_ack = i_dbus_ack;
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
CAPI=2:
|
CAPI=2:
|
||||||
|
|
||||||
name : ::serv:1.3.0
|
name : ::serv:1.2.0
|
||||||
|
|
||||||
filesets:
|
filesets:
|
||||||
core:
|
core:
|
||||||
|
@ -18,7 +18,6 @@ filesets:
|
||||||
- rtl/serv_rf_ram_if.v
|
- rtl/serv_rf_ram_if.v
|
||||||
- rtl/serv_rf_ram.v
|
- rtl/serv_rf_ram.v
|
||||||
- rtl/serv_state.v
|
- rtl/serv_state.v
|
||||||
- rtl/serv_debug.v
|
|
||||||
- rtl/serv_top.v
|
- rtl/serv_top.v
|
||||||
- rtl/serv_rf_top.v
|
- rtl/serv_rf_top.v
|
||||||
- rtl/serv_aligner.v
|
- rtl/serv_aligner.v
|
||||||
|
@ -46,7 +45,6 @@ targets:
|
||||||
|
|
||||||
lint:
|
lint:
|
||||||
default_tool : verilator
|
default_tool : verilator
|
||||||
description: Run static code checks (linting)
|
|
||||||
filesets : [core]
|
filesets : [core]
|
||||||
tools:
|
tools:
|
||||||
verilator:
|
verilator:
|
||||||
|
@ -57,7 +55,6 @@ targets:
|
||||||
|
|
||||||
sky130:
|
sky130:
|
||||||
default_tool : openlane
|
default_tool : openlane
|
||||||
description: Create GDSII for SkyWater 130nm using OpenLANE
|
|
||||||
filesets : [core, openlane]
|
filesets : [core, openlane]
|
||||||
toplevel : serv_synth_wrapper
|
toplevel : serv_synth_wrapper
|
||||||
|
|
||||||
|
|
683
servant.core
683
servant.core
|
@ -1,10 +1,13 @@
|
||||||
CAPI=2:
|
CAPI=2:
|
||||||
|
|
||||||
name : ::servant:1.3.0
|
name : ::servant:1.2.0
|
||||||
description: Simple reference system for SERV
|
|
||||||
|
|
||||||
filesets:
|
filesets:
|
||||||
# Common filesets
|
service:
|
||||||
|
files: [servant/ice40_pll.v, servant/service.v]
|
||||||
|
file_type : verilogSource
|
||||||
|
depend : ["fusesoc:utils:generators"]
|
||||||
|
|
||||||
mem_files:
|
mem_files:
|
||||||
files:
|
files:
|
||||||
- sw/blinky.hex : {copyto : blinky.hex}
|
- sw/blinky.hex : {copyto : blinky.hex}
|
||||||
|
@ -13,32 +16,12 @@ filesets:
|
||||||
|
|
||||||
servant_tb:
|
servant_tb:
|
||||||
files:
|
files:
|
||||||
- sw/hello_uart.hex : {file_type: user, copyto: .}
|
|
||||||
- bench/servant_sim.v
|
- bench/servant_sim.v
|
||||||
- bench/uart_decoder.v
|
- bench/uart_decoder.v
|
||||||
- bench/servant_tb.v
|
- bench/servant_tb.v
|
||||||
file_type : verilogSource
|
file_type : verilogSource
|
||||||
depend : [vlog_tb_utils]
|
depend : [vlog_tb_utils]
|
||||||
|
|
||||||
service:
|
|
||||||
files:
|
|
||||||
- servant/ice40_pll.v
|
|
||||||
- servant/service_clock_gen.v
|
|
||||||
- servant/service.v
|
|
||||||
file_type : verilogSource
|
|
||||||
depend : ["fusesoc:utils:generators"]
|
|
||||||
|
|
||||||
soc:
|
|
||||||
files:
|
|
||||||
- servant/servant_timer.v
|
|
||||||
- servant/servant_gpio.v
|
|
||||||
- servant/servant_mux.v
|
|
||||||
- "tool_quartus? (servant/servant_ram_quartus.sv)" : {file_type : systemVerilogSource}
|
|
||||||
- "!tool_quartus? (servant/servant_ram.v)"
|
|
||||||
- servant/servant.v
|
|
||||||
file_type : verilogSource
|
|
||||||
depend : [servile, "mdu? (mdu)"]
|
|
||||||
|
|
||||||
verilator_tb:
|
verilator_tb:
|
||||||
files:
|
files:
|
||||||
- bench/servant_sim.v
|
- bench/servant_sim.v
|
||||||
|
@ -47,54 +30,18 @@ filesets:
|
||||||
file_type : verilogSource
|
file_type : verilogSource
|
||||||
depend : ["vidbo? (vidbo)"]
|
depend : ["vidbo? (vidbo)"]
|
||||||
|
|
||||||
# Target-specific filesets. Alphabetically sorted
|
soc:
|
||||||
|
|
||||||
ac701:
|
|
||||||
files:
|
files:
|
||||||
- servant/servix.v : {file_type : verilogSource}
|
- servant/servant_clock_gen.v
|
||||||
- servant/servant_ac701.v : {file_type : verilogSource}
|
- servant/servant_timer.v
|
||||||
- data/ac701.xdc : {file_type : xdc}
|
- servant/servant_gpio.v
|
||||||
|
- servant/servant_arbiter.v
|
||||||
alhambra : {files: [data/alhambra.pcf : {file_type : PCF}]}
|
- servant/servant_mux.v
|
||||||
|
- "tool_quartus? (servant/servant_ram_quartus.sv)" : {file_type : systemVerilogSource}
|
||||||
alchitry_au:
|
- "!tool_quartus? (servant/servant_ram.v)"
|
||||||
files:
|
- servant/servant.v
|
||||||
- servant/servix_clock_gen.v : {file_type : verilogSource}
|
file_type : verilogSource
|
||||||
- servant/servix.v : {file_type : verilogSource}
|
depend : [serv, "mdu? (mdu)"]
|
||||||
- data/alchitry_au.xdc : {file_type : xdc}
|
|
||||||
|
|
||||||
arty_a7_35t:
|
|
||||||
files:
|
|
||||||
- servant/servix_clock_gen.v : {file_type : verilogSource}
|
|
||||||
- servant/servix.v : {file_type : verilogSource}
|
|
||||||
- data/arty_a7_35t.xdc : {file_type : xdc}
|
|
||||||
|
|
||||||
arty_s7_50t:
|
|
||||||
files:
|
|
||||||
- servant/servix_clock_gen.v : {file_type : verilogSource}
|
|
||||||
- servant/servix.v : {file_type : verilogSource}
|
|
||||||
- data/arty_s7_50t.xdc : {file_type : xdc}
|
|
||||||
|
|
||||||
ax309:
|
|
||||||
files:
|
|
||||||
- servant/servant_ax309_clock_gen.v : {file_type : verilogSource}
|
|
||||||
- servant/servant_ax309.v : {file_type : verilogSource}
|
|
||||||
- data/ax309.ucf : {file_type : UCF}
|
|
||||||
|
|
||||||
chameleon96:
|
|
||||||
files:
|
|
||||||
- data/chameleon96/chameleon96.sdc : {file_type : SDC}
|
|
||||||
- data/chameleon96/pinmap.tcl : {file_type: tclSource}
|
|
||||||
- data/chameleon96/HPS.sv : {file_type : systemVerilogSource}
|
|
||||||
- data/chameleon96/CV_96.v : {file_type : verilogSource}
|
|
||||||
- servant/servive_clock_gen.v : {file_type : verilogSource}
|
|
||||||
- servant/servive.v : {file_type : verilogSource}
|
|
||||||
|
|
||||||
cmod_a7_35t:
|
|
||||||
files:
|
|
||||||
- servant/servant_cmod_a7_clock_gen.v : {file_type : verilogSource}
|
|
||||||
- servant/servant_cmod_a7.v : {file_type : verilogSource}
|
|
||||||
- data/cmod_a7_35t.xdc : {file_type : xdc}
|
|
||||||
|
|
||||||
cyc1000:
|
cyc1000:
|
||||||
files:
|
files:
|
||||||
|
@ -103,6 +50,22 @@ filesets:
|
||||||
- servant/servclone10_clock_gen.v : {file_type : verilogSource}
|
- servant/servclone10_clock_gen.v : {file_type : verilogSource}
|
||||||
- servant/servclone10.v : {file_type : verilogSource}
|
- servant/servclone10.v : {file_type : verilogSource}
|
||||||
|
|
||||||
|
sockit:
|
||||||
|
files:
|
||||||
|
- data/sockit.sdc : {file_type : SDC}
|
||||||
|
- data/sockit.tcl : {file_type : tclSource}
|
||||||
|
- servant/servive_clock_gen.v : {file_type : verilogSource}
|
||||||
|
- servant/servive.v : {file_type : verilogSource}
|
||||||
|
|
||||||
|
chameleon96:
|
||||||
|
files:
|
||||||
|
- data/chameleon96/chameleon96.sdc : {file_type : SDC}
|
||||||
|
- data/chameleon96/pinmap.tcl : {file_type: tclSource}
|
||||||
|
- data/chameleon96/HPS.sv : {file_type : systemVerilogSource}
|
||||||
|
- data/chameleon96/CV_96.v : {file_type : verilogSource}
|
||||||
|
- servant/servive_clock_gen.v : {file_type : verilogSource}
|
||||||
|
- servant/servive.v : {file_type : verilogSource}
|
||||||
|
|
||||||
deca:
|
deca:
|
||||||
files:
|
files:
|
||||||
- data/deca.sdc : {file_type : SDC}
|
- data/deca.sdc : {file_type : SDC}
|
||||||
|
@ -117,14 +80,6 @@ filesets:
|
||||||
- servant/servive_clock_gen.v : {file_type : verilogSource}
|
- servant/servive_clock_gen.v : {file_type : verilogSource}
|
||||||
- servant/servive.v : {file_type : verilogSource}
|
- servant/servive.v : {file_type : verilogSource}
|
||||||
|
|
||||||
de1_soc_revF:
|
|
||||||
files:
|
|
||||||
- data/de1_soc_revF.sdc : {file_type : SDC}
|
|
||||||
- data/de1_soc_revF.tcl : {file_type : tclSource}
|
|
||||||
- servant/servde1_soc_revF_clock_gen.v : {file_type : verilogSource}
|
|
||||||
- servant/servde1_soc_revF.v : {file_type : verilogSource}
|
|
||||||
|
|
||||||
|
|
||||||
de10_nano:
|
de10_nano:
|
||||||
files:
|
files:
|
||||||
- data/de10_nano.sdc : {file_type : SDC}
|
- data/de10_nano.sdc : {file_type : SDC}
|
||||||
|
@ -138,30 +93,22 @@ filesets:
|
||||||
- servant/servix_ebaz4205.v : {file_type : verilogSource}
|
- servant/servix_ebaz4205.v : {file_type : verilogSource}
|
||||||
- data/ebaz4205.xdc : {file_type : xdc}
|
- data/ebaz4205.xdc : {file_type : xdc}
|
||||||
|
|
||||||
ecp5_evn:
|
tinyfpga_bx: {files: [data/tinyfpga_bx.pcf : {file_type : PCF}]}
|
||||||
files:
|
icebreaker : {files: [data/icebreaker.pcf : {file_type : PCF}]}
|
||||||
- data/ecp5_evn.lpf : {file_type : LPF}
|
icesugar : {files: [data/icesugar.pcf : {file_type : PCF}]}
|
||||||
- servant/ecp5_evn_pll.v : {file_type : verilogSource}
|
alhambra : {files: [data/alhambra.pcf : {file_type : PCF}]}
|
||||||
- servant/servant_ecp5_evn_clock_gen.v : {file_type : verilogSource}
|
icestick : {files: [data/icestick.pcf : {file_type : PCF}]}
|
||||||
- servant/servant_ecp5_evn.v : {file_type : verilogSource}
|
|
||||||
|
|
||||||
go_board:
|
go_board:
|
||||||
files:
|
files:
|
||||||
- data/go_board.pcf : {file_type : PCF}
|
- data/go_board.pcf : {file_type : PCF}
|
||||||
- servant/service_go_board.v : {file_type : verilogSource}
|
- servant/service_go_board.v : {file_type : verilogSource}
|
||||||
|
|
||||||
icebreaker : {files: [data/icebreaker.pcf : {file_type : PCF}]}
|
ax309:
|
||||||
|
|
||||||
icestick : {files: [data/icestick.pcf : {file_type : PCF}]}
|
|
||||||
|
|
||||||
icesugar : {files: [data/icesugar.pcf : {file_type : PCF}]}
|
|
||||||
|
|
||||||
icev_wireless : {files: [data/icev_wireless.pcf : {file_type : PCF}]}
|
|
||||||
|
|
||||||
gmm7550:
|
|
||||||
files:
|
files:
|
||||||
- data/gmm7550.ccf : {file_type : CCF}
|
- servant/servant_ax309_clock_gen.v : {file_type : verilogSource}
|
||||||
- servant/servant_gmm7550.v : {file_type : verilogSource}
|
- servant/servant_ax309.v : {file_type : verilogSource}
|
||||||
|
- data/ax309.ucf : {file_type : UCF}
|
||||||
|
|
||||||
lx9_microboard:
|
lx9_microboard:
|
||||||
files:
|
files:
|
||||||
|
@ -169,31 +116,37 @@ filesets:
|
||||||
- servant/servant_lx9.v : {file_type : verilogSource}
|
- servant/servant_lx9.v : {file_type : verilogSource}
|
||||||
- data/lx9_microboard.ucf : {file_type : UCF}
|
- data/lx9_microboard.ucf : {file_type : UCF}
|
||||||
|
|
||||||
machdyne_kolibri:
|
|
||||||
files:
|
|
||||||
- servant/servant_md_kolibri.v : {file_type : verilogSource}
|
|
||||||
- data/machdyne_kolibri.pcf : {file_type : PCF}
|
|
||||||
|
|
||||||
max10_10m08evk:
|
|
||||||
files:
|
|
||||||
- data/max10_10m08evk.sdc : {file_type : SDC}
|
|
||||||
- data/max10_10m08evk.tcl : {file_type : tclSource}
|
|
||||||
- servant/servive_clock_gen.v : {file_type : verilogSource}
|
|
||||||
- servant/servive.v : {file_type : verilogSource}
|
|
||||||
|
|
||||||
nexys_2:
|
nexys_2:
|
||||||
files:
|
files:
|
||||||
- servant/servax_clock_gen.v : {file_type : verilogSource}
|
- servant/servax_clock_gen.v : {file_type : verilogSource}
|
||||||
- servant/servax.v : {file_type : verilogSource}
|
- servant/servax.v : {file_type : verilogSource}
|
||||||
- data/nexys_2.tcl : {file_type : tclSource}
|
- data/nexys_2.tcl : {file_type : tclSource}
|
||||||
- data/nexys_2.ucf : {file_type : UCF}
|
- data/nexys_2.ucf : {file_type : UCF}
|
||||||
|
|
||||||
nexys_a7:
|
nexys_a7:
|
||||||
files:
|
files:
|
||||||
- servant/servix_clock_gen.v : {file_type : verilogSource}
|
- servant/servix_clock_gen.v : {file_type : verilogSource}
|
||||||
- servant/servix.v : {file_type : verilogSource}
|
- servant/servix.v : {file_type : verilogSource}
|
||||||
- data/nexys_a7.xdc : {file_type : xdc}
|
- data/nexys_a7.xdc : {file_type : xdc}
|
||||||
|
|
||||||
|
cmod_a7_35t:
|
||||||
|
files:
|
||||||
|
- servant/servix_clock_gen.v : {file_type : verilogSource}
|
||||||
|
- servant/servix.v : {file_type : verilogSource}
|
||||||
|
- data/cmod_a7_35t.xdc : {file_type : xdc}
|
||||||
|
|
||||||
|
arty_a7_35t:
|
||||||
|
files:
|
||||||
|
- servant/servix_clock_gen.v : {file_type : verilogSource}
|
||||||
|
- servant/servix.v : {file_type : verilogSource}
|
||||||
|
- data/arty_a7_35t.xdc : {file_type : xdc}
|
||||||
|
|
||||||
|
ac701:
|
||||||
|
files:
|
||||||
|
- servant/servix.v : {file_type : verilogSource}
|
||||||
|
- servant/servant_ac701.v : {file_type : verilogSource}
|
||||||
|
- data/ac701.xdc : {file_type : xdc}
|
||||||
|
|
||||||
orangecrab:
|
orangecrab:
|
||||||
files:
|
files:
|
||||||
- data/orangecrab_r02.lpf : {file_type : LPF}
|
- data/orangecrab_r02.lpf : {file_type : LPF}
|
||||||
|
@ -205,27 +158,6 @@ filesets:
|
||||||
- servant/servis.v : {file_type : verilogSource}
|
- servant/servis.v : {file_type : verilogSource}
|
||||||
- data/pipistrello.ucf : {file_type : UCF}
|
- data/pipistrello.ucf : {file_type : UCF}
|
||||||
|
|
||||||
polarfire_splashkit:
|
|
||||||
files:
|
|
||||||
- servant/servant_pf.v : {file_type : verilogSource}
|
|
||||||
- servant/servant_pf_clock_gen.v : {file_type : verilogSource}
|
|
||||||
- data/polarfire_splashkit.pdc : {file_type : PDC}
|
|
||||||
|
|
||||||
sockit:
|
|
||||||
files:
|
|
||||||
- data/sockit.sdc : {file_type : SDC}
|
|
||||||
- data/sockit.tcl : {file_type : tclSource}
|
|
||||||
- servant/servive_clock_gen.v : {file_type : verilogSource}
|
|
||||||
- servant/servive.v : {file_type : verilogSource}
|
|
||||||
|
|
||||||
te0802:
|
|
||||||
files:
|
|
||||||
- servant/servant_te0802_clock_gen.v : {file_type : verilogSource}
|
|
||||||
- servant/servant_te0802.v : {file_type : verilogSource}
|
|
||||||
- data/te0802.xdc : {file_type : xdc}
|
|
||||||
|
|
||||||
tinyfpga_bx: {files: [data/tinyfpga_bx.pcf : {file_type : PCF}]}
|
|
||||||
|
|
||||||
ulx3s:
|
ulx3s:
|
||||||
files:
|
files:
|
||||||
- data/ulx3s.lpf : {file_type : LPF}
|
- data/ulx3s.lpf : {file_type : LPF}
|
||||||
|
@ -248,88 +180,6 @@ targets:
|
||||||
default:
|
default:
|
||||||
filesets : [soc]
|
filesets : [soc]
|
||||||
|
|
||||||
ac701:
|
|
||||||
default_tool: vivado
|
|
||||||
description: AC701 Evaluation Kit
|
|
||||||
filesets : [mem_files, soc, ac701]
|
|
||||||
parameters : [memfile, memsize, frequency=32]
|
|
||||||
tools:
|
|
||||||
vivado: {part : xc7a200t-fbg676-2}
|
|
||||||
toplevel : servant_ac701
|
|
||||||
|
|
||||||
alchitry_au:
|
|
||||||
default_tool: vivado
|
|
||||||
description: Open-hardware Alchitry AU FPGA board
|
|
||||||
filesets : [mem_files, soc, alchitry_au]
|
|
||||||
parameters : [memfile, memsize, frequency=16, "mdu? (MDU=1)", WITH_RESET]
|
|
||||||
tools:
|
|
||||||
vivado: {part : xc7a35tftg256-1}
|
|
||||||
toplevel : servix
|
|
||||||
|
|
||||||
alhambra:
|
|
||||||
default_tool : icestorm
|
|
||||||
description: Open-hardware iCE40HX4K FPGA board
|
|
||||||
filesets : [mem_files, soc, service, alhambra]
|
|
||||||
generate: [ice40pll: {freq_in : 12, freq_out : 32}]
|
|
||||||
parameters : [memfile, memsize, PLL=ICE40_CORE]
|
|
||||||
tools:
|
|
||||||
icestorm:
|
|
||||||
nextpnr_options : [--hx8k, --package, "tq144:4k", --freq, 32]
|
|
||||||
pnr: next
|
|
||||||
toplevel : service
|
|
||||||
|
|
||||||
arty_a7_35t:
|
|
||||||
default_tool: vivado
|
|
||||||
description: Digilent Arty A7-35
|
|
||||||
filesets : [mem_files, soc, arty_a7_35t]
|
|
||||||
parameters : [memfile, memsize, frequency=16, "mdu? (MDU=1)", WITH_RESET]
|
|
||||||
tools:
|
|
||||||
vivado: {part : xc7a35ticsg324-1L}
|
|
||||||
toplevel : servix
|
|
||||||
|
|
||||||
arty_s7_50t:
|
|
||||||
default_tool: vivado
|
|
||||||
description: Digilent Arty S7-50
|
|
||||||
filesets : [mem_files, soc, arty_s7_50t]
|
|
||||||
parameters : [memfile, memsize, frequency=16, "mdu? (MDU=1)", WITH_RESET]
|
|
||||||
tools:
|
|
||||||
vivado: {part : xc7s50csga324-1}
|
|
||||||
toplevel : servix
|
|
||||||
|
|
||||||
ax309:
|
|
||||||
default_tool : ise
|
|
||||||
description : XILINX Spartan-6 XC6SLX9 FPGA Development Board
|
|
||||||
filesets : [mem_files, soc, ax309]
|
|
||||||
parameters : [memfile, memsize]
|
|
||||||
tools:
|
|
||||||
ise:
|
|
||||||
family : Spartan6
|
|
||||||
device : xc6slx9
|
|
||||||
package : ftg256
|
|
||||||
speed : -3
|
|
||||||
toplevel : servant_ax309
|
|
||||||
|
|
||||||
chameleon96:
|
|
||||||
default_tool : quartus
|
|
||||||
description : Chameleon96 (Arrow 96 CV SoC Board)
|
|
||||||
filesets : [mem_files, soc, chameleon96]
|
|
||||||
parameters : [memfile, memsize]
|
|
||||||
tools:
|
|
||||||
quartus:
|
|
||||||
family : Cyclone V
|
|
||||||
device : 5CSEBA6U19I7
|
|
||||||
board_device_index : 2
|
|
||||||
toplevel: CV_96
|
|
||||||
|
|
||||||
cmod_a7_35t:
|
|
||||||
description: Digilent CMOD A7-35
|
|
||||||
filesets : [mem_files, soc, cmod_a7_35t]
|
|
||||||
flow: vivado
|
|
||||||
flow_options:
|
|
||||||
part : xc7a35tcpg236-1
|
|
||||||
parameters : [memfile, memsize]
|
|
||||||
toplevel : servant_cmod_a7
|
|
||||||
|
|
||||||
cyc1000:
|
cyc1000:
|
||||||
default_tool: quartus
|
default_tool: quartus
|
||||||
description: cyc1000 FPGA board
|
description: cyc1000 FPGA board
|
||||||
|
@ -341,9 +191,42 @@ targets:
|
||||||
device : 10CL025YU256C8G
|
device : 10CL025YU256C8G
|
||||||
toplevel : servclone10
|
toplevel : servclone10
|
||||||
|
|
||||||
|
sockit:
|
||||||
|
default_tool : quartus
|
||||||
|
description: SoCKit development kit by Arrow / Terasic
|
||||||
|
filesets : [mem_files, soc, sockit]
|
||||||
|
parameters : [memfile, memsize]
|
||||||
|
tools:
|
||||||
|
quartus:
|
||||||
|
family : CycloneV
|
||||||
|
device : 5CSXFC6D6F31C6
|
||||||
|
toplevel: servive
|
||||||
|
|
||||||
|
chameleon96:
|
||||||
|
default_tool : quartus
|
||||||
|
description : Chameleon96 (Arrow 96 CV SoC Board)
|
||||||
|
filesets : [mem_files, soc, chameleon96]
|
||||||
|
parameters : [memfile, memsize]
|
||||||
|
tools:
|
||||||
|
quartus:
|
||||||
|
family : Cyclone V
|
||||||
|
device : 5CSEBA6U19I7
|
||||||
|
board_device_index : 2
|
||||||
|
toplevel: CV_96
|
||||||
|
|
||||||
|
deca:
|
||||||
|
default_tool : quartus
|
||||||
|
description: DECA development kit by Arrow / Terasic
|
||||||
|
filesets : [mem_files, soc, deca]
|
||||||
|
parameters : [memfile, memsize]
|
||||||
|
tools:
|
||||||
|
quartus:
|
||||||
|
family : MAX 10
|
||||||
|
device : 10M50DAF484C6GES
|
||||||
|
toplevel: servive
|
||||||
|
|
||||||
de0_nano:
|
de0_nano:
|
||||||
default_tool : quartus
|
default_tool : quartus
|
||||||
description: Terasic DE0 Nano
|
|
||||||
filesets : [mem_files, soc, de0_nano]
|
filesets : [mem_files, soc, de0_nano]
|
||||||
parameters : [memfile, memsize]
|
parameters : [memfile, memsize]
|
||||||
tools:
|
tools:
|
||||||
|
@ -364,51 +247,10 @@ targets:
|
||||||
board_device_index : 2
|
board_device_index : 2
|
||||||
toplevel : servive
|
toplevel : servive
|
||||||
|
|
||||||
deca:
|
|
||||||
default_tool : quartus
|
|
||||||
description: DECA development kit by Arrow / Terasic
|
|
||||||
filesets : [mem_files, soc, deca]
|
|
||||||
parameters : [memfile, memsize]
|
|
||||||
tools:
|
|
||||||
quartus:
|
|
||||||
family : MAX 10
|
|
||||||
device : 10M50DAF484C6GES
|
|
||||||
toplevel: servive
|
|
||||||
|
|
||||||
ebaz4205:
|
|
||||||
default_tool: vivado
|
|
||||||
description: EBAZ4205 'Development' Board
|
|
||||||
filesets : [mem_files, soc, ebaz4205]
|
|
||||||
parameters : [memfile, memsize, frequency=16]
|
|
||||||
tools:
|
|
||||||
vivado: {part : xc7z010clg400-1}
|
|
||||||
toplevel : servix_ebaz4205
|
|
||||||
|
|
||||||
ecp5_evn:
|
|
||||||
default_tool: trellis
|
|
||||||
description : ECP5 evaluation board
|
|
||||||
filesets : [mem_files, soc, ecp5_evn]
|
|
||||||
parameters : [memfile, memsize]
|
|
||||||
tools:
|
|
||||||
trellis:
|
|
||||||
nextpnr_options : [--package, CABGA381, --um5g-85k]
|
|
||||||
toplevel: servant_ecp5_evn
|
|
||||||
|
|
||||||
go_board:
|
|
||||||
default_tool : icestorm
|
|
||||||
description: Nandland Go Board
|
|
||||||
filesets : [mem_files, soc, go_board]
|
|
||||||
tools:
|
|
||||||
icestorm:
|
|
||||||
nextpnr_options : [--hx1k, --package, vq100, --freq, 20]
|
|
||||||
pnr: next
|
|
||||||
toplevel : service_go_board
|
|
||||||
|
|
||||||
icebreaker:
|
icebreaker:
|
||||||
default_tool : icestorm
|
default_tool : icestorm
|
||||||
description: 1Bit Squared iCEBreaker
|
|
||||||
filesets : [mem_files, soc, service, icebreaker]
|
filesets : [mem_files, soc, service, icebreaker]
|
||||||
generate: [ice40pll : {freq_out : 16}]
|
generate: [icebreaker_pll]
|
||||||
parameters : [memfile, memsize, PLL=ICE40_PAD]
|
parameters : [memfile, memsize, PLL=ICE40_PAD]
|
||||||
tools:
|
tools:
|
||||||
icestorm:
|
icestorm:
|
||||||
|
@ -416,23 +258,11 @@ targets:
|
||||||
pnr: next
|
pnr: next
|
||||||
toplevel : service
|
toplevel : service
|
||||||
|
|
||||||
icestick:
|
|
||||||
default_tool : icestorm
|
|
||||||
description: Lattice iCEstick
|
|
||||||
filesets : [mem_files, soc, service, icestick]
|
|
||||||
generate: [ice40pll: {freq_in : 12, freq_out : 32}]
|
|
||||||
parameters : [memfile=blinky.hex, memsize=7168, PLL=ICE40_CORE]
|
|
||||||
tools:
|
|
||||||
icestorm:
|
|
||||||
nextpnr_options : [--hx1k, --package, tq144, --freq, 32]
|
|
||||||
pnr: next
|
|
||||||
toplevel : service
|
|
||||||
|
|
||||||
icesugar:
|
icesugar:
|
||||||
default_tool : icestorm
|
default_tool : icestorm
|
||||||
description : iCE40UP5K Development Board by MuseLab
|
description : iCE40UP5K Development Board by MuseLab
|
||||||
filesets : [mem_files, soc, service, icesugar]
|
filesets : [mem_files, soc, service, icesugar]
|
||||||
generate: [ice40pll : {freq_in : 12, freq_out : 32}]
|
generate: [icesugar_pll]
|
||||||
parameters : [memfile, memsize, PLL=ICE40_PAD]
|
parameters : [memfile, memsize, PLL=ICE40_PAD]
|
||||||
tools:
|
tools:
|
||||||
icestorm:
|
icestorm:
|
||||||
|
@ -440,38 +270,6 @@ targets:
|
||||||
pnr: next
|
pnr: next
|
||||||
toplevel : service
|
toplevel : service
|
||||||
|
|
||||||
icev_wireless:
|
|
||||||
default_tool : icestorm
|
|
||||||
description: ICE-V Wireless
|
|
||||||
filesets : [mem_files, soc, service, icev_wireless]
|
|
||||||
generate: [ice40pll : {freq_out : 16}]
|
|
||||||
parameters : [memfile, memsize, PLL=ICE40_PAD]
|
|
||||||
tools:
|
|
||||||
icestorm:
|
|
||||||
nextpnr_options: [--up5k, --freq, 16]
|
|
||||||
pnr: next
|
|
||||||
toplevel : service
|
|
||||||
|
|
||||||
gmm7550:
|
|
||||||
default_tool: gatemate
|
|
||||||
description: CologneChip GateMate FPGA Module
|
|
||||||
filesets : [mem_files, soc, gmm7550]
|
|
||||||
parameters : [memfile=blinky.hex, memsize=8192]
|
|
||||||
toplevel : servant_gmm7550
|
|
||||||
tools:
|
|
||||||
gatemate:
|
|
||||||
device : CCGM1A1
|
|
||||||
yosys_synth_options : [ -nomx8 ]
|
|
||||||
p_r_options : [ +uCIO -cCP ]
|
|
||||||
|
|
||||||
lint:
|
|
||||||
description: Run static code checks (linting)
|
|
||||||
filesets : [soc]
|
|
||||||
flow: lint
|
|
||||||
flow_options:
|
|
||||||
tool : verilator
|
|
||||||
toplevel : servant
|
|
||||||
|
|
||||||
lx9_microboard:
|
lx9_microboard:
|
||||||
default_tool: ise
|
default_tool: ise
|
||||||
description : LX9 Microboard
|
description : LX9 Microboard
|
||||||
|
@ -485,33 +283,60 @@ targets:
|
||||||
speed : -2
|
speed : -2
|
||||||
toplevel : servant_lx9
|
toplevel : servant_lx9
|
||||||
|
|
||||||
machdyne_kolibri:
|
ax309:
|
||||||
default_tool: icestorm
|
default_tool : ise
|
||||||
description : Machdyne Kolibri FPGA Dongle
|
description : XILINX Spartan-6 XC6SLX9 FPGA Development Board
|
||||||
filesets : [mem_files, soc, machdyne_kolibri]
|
filesets : [mem_files, soc, ax309]
|
||||||
parameters : [memfile, memsize]
|
parameters : [memfile, memsize]
|
||||||
|
tools:
|
||||||
|
ise:
|
||||||
|
family : Spartan6
|
||||||
|
device : xc6slx9
|
||||||
|
package : ftg256
|
||||||
|
speed : -3
|
||||||
|
toplevel : servant_ax309
|
||||||
|
|
||||||
|
tinyfpga_bx:
|
||||||
|
default_tool : icestorm
|
||||||
|
filesets : [mem_files, soc, service, tinyfpga_bx]
|
||||||
|
generate: [tinyfpga_bx_pll]
|
||||||
|
parameters : [memfile, memsize, PLL=ICE40_CORE]
|
||||||
tools:
|
tools:
|
||||||
icestorm:
|
icestorm:
|
||||||
nextpnr_options : [--hx4k, --package, bg121, --freq, 48]
|
nextpnr_options : [--lp8k, --package, cm81, --freq, 32]
|
||||||
pnr: next
|
pnr: next
|
||||||
toplevel : servant_md_kolibri
|
toplevel : service
|
||||||
|
|
||||||
max10_10m08evk:
|
alhambra:
|
||||||
default_tool : quartus
|
default_tool : icestorm
|
||||||
description: MAX10 10M08 evaluation kit
|
description: Open-hardware iCE40HX4K FPGA board
|
||||||
hooks:
|
filesets : [mem_files, soc, service, alhambra]
|
||||||
post_run: [jbc]
|
generate: [alhambra_pll]
|
||||||
filesets : [mem_files, soc, max10_10m08evk]
|
parameters : [memfile, memsize, PLL=ICE40_CORE]
|
||||||
parameters : [memfile, memsize]
|
|
||||||
tools:
|
tools:
|
||||||
quartus:
|
icestorm:
|
||||||
family : MAX 10
|
nextpnr_options : [--hx8k, --package, "tq144:4k", --freq, 32]
|
||||||
device : 10M08SAE144C8G
|
pnr: next
|
||||||
toplevel: servive
|
toplevel : service
|
||||||
|
|
||||||
|
lint:
|
||||||
|
default_tool : verilator
|
||||||
|
filesets : [soc]
|
||||||
|
tools:
|
||||||
|
verilator:
|
||||||
|
mode : lint-only
|
||||||
|
toplevel : servant
|
||||||
|
|
||||||
|
nexys_a7:
|
||||||
|
default_tool: vivado
|
||||||
|
filesets : [mem_files, soc, nexys_a7]
|
||||||
|
parameters : [memfile, memsize, frequency=32]
|
||||||
|
tools:
|
||||||
|
vivado: {part : xc7a100tcsg324-1}
|
||||||
|
toplevel : servix
|
||||||
|
|
||||||
nexys_2_500:
|
nexys_2_500:
|
||||||
default_tool: ise
|
default_tool: ise
|
||||||
description: Digilent Nexys 2-500
|
|
||||||
filesets : [mem_files, soc, nexys_2]
|
filesets : [mem_files, soc, nexys_2]
|
||||||
parameters : [memfile, memsize, compressed]
|
parameters : [memfile, memsize, compressed]
|
||||||
tools:
|
tools:
|
||||||
|
@ -524,7 +349,6 @@ targets:
|
||||||
|
|
||||||
nexys_2_1200:
|
nexys_2_1200:
|
||||||
default_tool: ise
|
default_tool: ise
|
||||||
description: Digilent Nexys 2-1200
|
|
||||||
filesets : [mem_files, soc, nexys_2]
|
filesets : [mem_files, soc, nexys_2]
|
||||||
parameters : [memfile, memsize, compressed]
|
parameters : [memfile, memsize, compressed]
|
||||||
tools:
|
tools:
|
||||||
|
@ -535,15 +359,39 @@ targets:
|
||||||
speed : -4
|
speed : -4
|
||||||
toplevel : servax
|
toplevel : servax
|
||||||
|
|
||||||
nexys_a7:
|
cmod_a7_35t:
|
||||||
description: Digilent Nexys A7
|
default_tool: vivado
|
||||||
filesets : [mem_files, soc, nexys_a7]
|
filesets : [mem_files, soc, cmod_a7_35t]
|
||||||
flow: vivado
|
parameters : [memfile=blinky.hex, memsize, frequency=12]
|
||||||
flow_options:
|
tools:
|
||||||
part : xc7a100tcsg324-1
|
vivado: {part : xc7a35tcpg236-1}
|
||||||
parameters : [memfile, memsize, frequency=32]
|
|
||||||
toplevel : servix
|
toplevel : servix
|
||||||
|
|
||||||
|
arty_a7_35t:
|
||||||
|
default_tool: vivado
|
||||||
|
filesets : [mem_files, soc, arty_a7_35t]
|
||||||
|
parameters : [memfile, memsize, frequency=16, "mdu? (MDU=1)"]
|
||||||
|
tools:
|
||||||
|
vivado: {part : xc7a35ticsg324-1L}
|
||||||
|
toplevel : servix
|
||||||
|
|
||||||
|
ebaz4205:
|
||||||
|
default_tool: vivado
|
||||||
|
description: EBAZ4205 'Development' Board
|
||||||
|
filesets : [mem_files, soc, ebaz4205]
|
||||||
|
parameters : [memfile, memsize, frequency=16]
|
||||||
|
tools:
|
||||||
|
vivado: {part : xc7z010clg400-1}
|
||||||
|
toplevel : servix_ebaz4205
|
||||||
|
|
||||||
|
ac701:
|
||||||
|
default_tool: vivado
|
||||||
|
filesets : [mem_files, soc, ac701]
|
||||||
|
parameters : [memfile, memsize, frequency=32]
|
||||||
|
tools:
|
||||||
|
vivado: {part : xc7a200t-fbg676-2}
|
||||||
|
toplevel : servant_ac701
|
||||||
|
|
||||||
orangecrab_r0.2:
|
orangecrab_r0.2:
|
||||||
default_tool: trellis
|
default_tool: trellis
|
||||||
description : OrangeCrab R0.2
|
description : OrangeCrab R0.2
|
||||||
|
@ -567,61 +415,17 @@ targets:
|
||||||
speed : -3
|
speed : -3
|
||||||
toplevel : servis
|
toplevel : servis
|
||||||
|
|
||||||
polarfire_splashkit:
|
|
||||||
default_tool: libero
|
|
||||||
description : Microsemi Polarfire Splash Kit
|
|
||||||
filesets : [mem_files, soc, polarfire_splashkit]
|
|
||||||
parameters : [memfile, memsize]
|
|
||||||
tools:
|
|
||||||
libero:
|
|
||||||
family : PolarFire
|
|
||||||
die : MPF300TS
|
|
||||||
package : FCG484
|
|
||||||
toplevel : servant_pf
|
|
||||||
|
|
||||||
sim:
|
sim:
|
||||||
default_tool: icarus
|
default_tool: icarus
|
||||||
description: Simulation target
|
|
||||||
filesets : [soc, servant_tb]
|
filesets : [soc, servant_tb]
|
||||||
parameters :
|
parameters :
|
||||||
- RISCV_FORMAL
|
- RISCV_FORMAL
|
||||||
- width
|
|
||||||
- "mdu? (MDU=1)"
|
- "mdu? (MDU=1)"
|
||||||
- SERV_CLEAR_RAM=true
|
- SERV_CLEAR_RAM=true
|
||||||
- firmware
|
- firmware
|
||||||
- memsize
|
- memsize
|
||||||
toplevel : servant_tb
|
toplevel : servant_tb
|
||||||
|
|
||||||
sockit:
|
|
||||||
default_tool : quartus
|
|
||||||
description: SoCKit development kit by Arrow / Terasic
|
|
||||||
filesets : [mem_files, soc, sockit]
|
|
||||||
parameters : [memfile, memsize]
|
|
||||||
tools:
|
|
||||||
quartus:
|
|
||||||
family : CycloneV
|
|
||||||
device : 5CSXFC6D6F31C6
|
|
||||||
toplevel: servive
|
|
||||||
|
|
||||||
te0802:
|
|
||||||
default_tool: vivado
|
|
||||||
description : Trenz Electronic TE0802
|
|
||||||
filesets : [mem_files, soc, te0802]
|
|
||||||
parameters : [memfile, memsize]
|
|
||||||
tools:
|
|
||||||
vivado: {part : xczu2cg-sbva484-1-e}
|
|
||||||
toplevel : servant_te0802
|
|
||||||
|
|
||||||
tinyfpga_bx:
|
|
||||||
description: TinyFPGA BX
|
|
||||||
filesets : [mem_files, soc, service, tinyfpga_bx]
|
|
||||||
flow: icestorm
|
|
||||||
flow_options:
|
|
||||||
nextpnr_options : [--lp8k, --package, cm81, --freq, '32']
|
|
||||||
generate: [ice40pll: {freq_in : 16, freq_out : 32}]
|
|
||||||
parameters : [memfile, memsize, PLL=ICE40_CORE]
|
|
||||||
toplevel : service
|
|
||||||
|
|
||||||
ulx3s_85:
|
ulx3s_85:
|
||||||
default_tool: diamond
|
default_tool: diamond
|
||||||
description : ULX3S 85k version
|
description : ULX3S 85k version
|
||||||
|
@ -636,7 +440,6 @@ targets:
|
||||||
|
|
||||||
upduino2:
|
upduino2:
|
||||||
default_tool : icestorm
|
default_tool : icestorm
|
||||||
description: Upduino2
|
|
||||||
filesets : [mem_files, soc, upduino2]
|
filesets : [mem_files, soc, upduino2]
|
||||||
parameters : [memfile, memsize]
|
parameters : [memfile, memsize]
|
||||||
tools:
|
tools:
|
||||||
|
@ -646,28 +449,24 @@ targets:
|
||||||
toplevel : servant_upduino2
|
toplevel : servant_upduino2
|
||||||
|
|
||||||
verilator_tb:
|
verilator_tb:
|
||||||
description: Verilator testbench
|
default_tool: verilator
|
||||||
filesets : [soc, verilator_tb]
|
filesets : [soc, verilator_tb]
|
||||||
flow: sim
|
|
||||||
flow_options:
|
|
||||||
tool: verilator
|
|
||||||
verilator_options : [--trace]
|
|
||||||
parameters :
|
parameters :
|
||||||
- RISCV_FORMAL
|
- RISCV_FORMAL
|
||||||
- "mdu? (MDU=1)"
|
- "mdu? (MDU=1)"
|
||||||
- cps
|
|
||||||
- firmware
|
- firmware
|
||||||
- memsize
|
- memsize
|
||||||
- signature
|
- signature
|
||||||
- timeout
|
- timeout
|
||||||
- trace_pc
|
|
||||||
- uart_baudrate
|
- uart_baudrate
|
||||||
- vcd
|
- vcd
|
||||||
- vcd_start
|
- vcd_start
|
||||||
- width
|
|
||||||
- compressed
|
- compressed
|
||||||
- align
|
- align
|
||||||
- with_csr=1
|
- with_csr=1
|
||||||
|
tools:
|
||||||
|
verilator:
|
||||||
|
verilator_options : [--trace]
|
||||||
toplevel : servant_sim
|
toplevel : servant_sim
|
||||||
|
|
||||||
zcu106:
|
zcu106:
|
||||||
|
@ -679,21 +478,44 @@ targets:
|
||||||
vivado: {part : xczu7ev-ffvc1156-2-e}
|
vivado: {part : xczu7ev-ffvc1156-2-e}
|
||||||
toplevel : servus
|
toplevel : servus
|
||||||
|
|
||||||
|
icestick:
|
||||||
|
default_tool : icestorm
|
||||||
|
filesets : [mem_files, soc, service, icestick]
|
||||||
|
generate: [icestick_pll]
|
||||||
|
parameters : [memfile=blinky.hex, memsize=7168, PLL=ICE40_CORE]
|
||||||
|
tools:
|
||||||
|
icestorm:
|
||||||
|
nextpnr_options : [--hx1k, --package, tq144, --freq, 32]
|
||||||
|
pnr: next
|
||||||
|
toplevel : service
|
||||||
|
|
||||||
|
go_board:
|
||||||
|
default_tool : icestorm
|
||||||
|
filesets : [mem_files, soc, go_board]
|
||||||
|
tools:
|
||||||
|
icestorm:
|
||||||
|
nextpnr_options : [--hx1k, --package, vq100, --freq, 20]
|
||||||
|
pnr: next
|
||||||
|
toplevel : service_go_board
|
||||||
|
|
||||||
parameters:
|
parameters:
|
||||||
align:
|
PLL:
|
||||||
datatype : int
|
datatype : str
|
||||||
description : Enable/Disable the Misaligned access of instruction
|
description : PLL type to use for main clock generation
|
||||||
paramtype : vlogparam
|
paramtype : vlogparam
|
||||||
|
|
||||||
compressed:
|
RISCV_FORMAL:
|
||||||
datatype : int
|
datatype : bool
|
||||||
description : Enable/Disable the Compressed extension
|
paramtype : vlogdefine
|
||||||
paramtype : vlogparam
|
|
||||||
|
MDU:
|
||||||
|
datatype : int
|
||||||
|
description : Enables RISC-V standard M-extension
|
||||||
|
paramtype : vlogdefine
|
||||||
|
|
||||||
cps:
|
SERV_CLEAR_RAM:
|
||||||
datatype : bool
|
datatype : bool
|
||||||
description: Write simulated cycles per second to a text file named cps
|
paramtype : vlogdefine
|
||||||
paramtype : plusarg
|
|
||||||
|
|
||||||
firmware:
|
firmware:
|
||||||
datatype : file
|
datatype : file
|
||||||
|
@ -702,14 +524,9 @@ parameters:
|
||||||
|
|
||||||
frequency:
|
frequency:
|
||||||
datatype : int
|
datatype : int
|
||||||
description : PLL output frequency in MHz
|
description : PLL output frequency
|
||||||
paramtype : vlogparam
|
paramtype : vlogparam
|
||||||
|
|
||||||
MDU:
|
|
||||||
datatype : int
|
|
||||||
description : Enables RISC-V standard M-extension
|
|
||||||
paramtype : vlogdefine
|
|
||||||
|
|
||||||
memfile:
|
memfile:
|
||||||
datatype : file
|
datatype : file
|
||||||
description : Preload RAM with a hex file at compile-time
|
description : Preload RAM with a hex file at compile-time
|
||||||
|
@ -721,36 +538,18 @@ parameters:
|
||||||
description : Memory size in bytes for RAM (default 8kiB)
|
description : Memory size in bytes for RAM (default 8kiB)
|
||||||
paramtype : vlogparam
|
paramtype : vlogparam
|
||||||
|
|
||||||
PLL:
|
|
||||||
datatype : str
|
|
||||||
description : PLL type to use for main clock generation
|
|
||||||
paramtype : vlogparam
|
|
||||||
|
|
||||||
RISCV_FORMAL:
|
|
||||||
datatype : bool
|
|
||||||
paramtype : vlogdefine
|
|
||||||
|
|
||||||
SERV_CLEAR_RAM:
|
|
||||||
datatype : bool
|
|
||||||
paramtype : vlogdefine
|
|
||||||
|
|
||||||
signature:
|
signature:
|
||||||
datatype : file
|
datatype : file
|
||||||
paramtype : plusarg
|
paramtype : plusarg
|
||||||
|
uart_baudrate:
|
||||||
|
datatype : int
|
||||||
|
description : Treat q output as an UART with the specified baudrate (0 or omitted parameter disables UART decoding)
|
||||||
|
paramtype : plusarg
|
||||||
|
|
||||||
timeout:
|
timeout:
|
||||||
datatype : int
|
datatype : int
|
||||||
paramtype : plusarg
|
paramtype : plusarg
|
||||||
|
|
||||||
trace_pc:
|
|
||||||
datatype : bool
|
|
||||||
paramtype : plusarg
|
|
||||||
|
|
||||||
uart_baudrate:
|
|
||||||
datatype : int
|
|
||||||
description : Treat q output as an UART with the specified baudrate (0 or omitted parameter disables UART decoding)
|
|
||||||
paramtype : plusarg
|
|
||||||
|
|
||||||
vcd:
|
vcd:
|
||||||
datatype : bool
|
datatype : bool
|
||||||
paramtype : plusarg
|
paramtype : plusarg
|
||||||
|
@ -759,28 +558,48 @@ parameters:
|
||||||
datatype : int
|
datatype : int
|
||||||
description : Delay start of VCD dumping until the specified time
|
description : Delay start of VCD dumping until the specified time
|
||||||
paramtype : plusarg
|
paramtype : plusarg
|
||||||
|
|
||||||
width:
|
compressed:
|
||||||
datatype : int
|
datatype : int
|
||||||
description : Interal datapath width (1=SERV, 4=QERV)
|
description : Enable/Disable the Compressed extension
|
||||||
paramtype : vlogparam
|
paramtype : vlogparam
|
||||||
|
|
||||||
|
align:
|
||||||
|
datatype : int
|
||||||
|
description : Enable/Disable the Misaligned access of instruction
|
||||||
|
paramtype : vlogparam
|
||||||
|
|
||||||
with_csr:
|
with_csr:
|
||||||
datatype : int
|
datatype : int
|
||||||
description : Enable/Disable CSR support
|
description : Enable/Disable CSR support
|
||||||
paramtype : vlogparam
|
paramtype : vlogparam
|
||||||
|
|
||||||
WITH_RESET:
|
|
||||||
datatype : bool
|
|
||||||
default : true
|
|
||||||
description : Enable reset input (for supported targets)
|
|
||||||
paramtype : vlogdefine
|
|
||||||
|
|
||||||
generate:
|
generate:
|
||||||
ice40pll:
|
icebreaker_pll:
|
||||||
generator: icepll
|
generator: icepll
|
||||||
|
parameters:
|
||||||
|
freq_out : 16
|
||||||
|
|
||||||
scripts:
|
icesugar_pll:
|
||||||
jbc:
|
generator: icepll
|
||||||
cmd : [quartus_jbcc, "-n", servant_1_2_1_pof.jam, servant_1_2_1_pof.jbc]
|
parameters:
|
||||||
|
freq_in : 12
|
||||||
|
freq_out : 32
|
||||||
|
|
||||||
|
tinyfpga_bx_pll:
|
||||||
|
generator: icepll
|
||||||
|
parameters:
|
||||||
|
freq_in : 16
|
||||||
|
freq_out : 32
|
||||||
|
|
||||||
|
alhambra_pll:
|
||||||
|
generator: icepll
|
||||||
|
parameters:
|
||||||
|
freq_in : 12
|
||||||
|
freq_out : 32
|
||||||
|
|
||||||
|
icestick_pll:
|
||||||
|
generator: icepll
|
||||||
|
parameters:
|
||||||
|
freq_in : 12
|
||||||
|
freq_out : 32
|
||||||
|
|
|
@ -1,48 +0,0 @@
|
||||||
// generated with "ecppll -n ecp5_evn_pll -i 12 -o 16 --clkin_name clki --clkout0_name clko -f ecp5_evn_pll.v"
|
|
||||||
|
|
||||||
// diamond 3.7 accepts this PLL
|
|
||||||
// diamond 3.8-3.9 is untested
|
|
||||||
// diamond 3.10 or higher is likely to abort with error about unable to use feedback signal
|
|
||||||
// cause of this could be from wrong CPHASE/FPHASE parameters
|
|
||||||
module ecp5_evn_pll
|
|
||||||
(
|
|
||||||
input clki, // 12 MHz, 0 deg
|
|
||||||
output clko, // 16 MHz, 0 deg
|
|
||||||
output locked
|
|
||||||
);
|
|
||||||
(* FREQUENCY_PIN_CLKI="12" *)
|
|
||||||
(* FREQUENCY_PIN_CLKOP="16" *)
|
|
||||||
(* ICP_CURRENT="12" *) (* LPF_RESISTOR="8" *) (* MFG_ENABLE_FILTEROPAMP="1" *) (* MFG_GMCREF_SEL="2" *)
|
|
||||||
EHXPLLL #(
|
|
||||||
.PLLRST_ENA("DISABLED"),
|
|
||||||
.INTFB_WAKE("DISABLED"),
|
|
||||||
.STDBY_ENABLE("DISABLED"),
|
|
||||||
.DPHASE_SOURCE("DISABLED"),
|
|
||||||
.OUTDIVIDER_MUXA("DIVA"),
|
|
||||||
.OUTDIVIDER_MUXB("DIVB"),
|
|
||||||
.OUTDIVIDER_MUXC("DIVC"),
|
|
||||||
.OUTDIVIDER_MUXD("DIVD"),
|
|
||||||
.CLKI_DIV(3),
|
|
||||||
.CLKOP_ENABLE("ENABLED"),
|
|
||||||
.CLKOP_DIV(37),
|
|
||||||
.CLKOP_CPHASE(18),
|
|
||||||
.CLKOP_FPHASE(0),
|
|
||||||
.FEEDBK_PATH("CLKOP"),
|
|
||||||
.CLKFB_DIV(4)
|
|
||||||
) pll_i (
|
|
||||||
.RST(1'b0),
|
|
||||||
.STDBY(1'b0),
|
|
||||||
.CLKI(clki),
|
|
||||||
.CLKOP(clko),
|
|
||||||
.CLKFB(clko),
|
|
||||||
.CLKINTFB(),
|
|
||||||
.PHASESEL0(1'b0),
|
|
||||||
.PHASESEL1(1'b0),
|
|
||||||
.PHASEDIR(1'b1),
|
|
||||||
.PHASESTEP(1'b1),
|
|
||||||
.PHASELOADREG(1'b1),
|
|
||||||
.PLLWAKESYNC(1'b0),
|
|
||||||
.ENCLKOP(1'b0),
|
|
||||||
.LOCK(locked)
|
|
||||||
);
|
|
||||||
endmodule
|
|
|
@ -11,8 +11,8 @@ module ice40_pll
|
||||||
|
|
||||||
reg [1:0] rst_reg;
|
reg [1:0] rst_reg;
|
||||||
always @(posedge o_clk)
|
always @(posedge o_clk)
|
||||||
rst_reg <= {rst_reg[0],locked};
|
rst_reg <= {!locked, rst_reg[1]};
|
||||||
assign o_rst = ~rst_reg[1];
|
assign o_rst = rst_reg[0];
|
||||||
|
|
||||||
generate
|
generate
|
||||||
if (PLL == "ICE40_CORE") begin
|
if (PLL == "ICE40_CORE") begin
|
||||||
|
|
|
@ -8,82 +8,108 @@ module servant
|
||||||
parameter memfile = "zephyr_hello.hex";
|
parameter memfile = "zephyr_hello.hex";
|
||||||
parameter memsize = 8192;
|
parameter memsize = 8192;
|
||||||
parameter reset_strategy = "MINI";
|
parameter reset_strategy = "MINI";
|
||||||
parameter width = 1;
|
|
||||||
parameter sim = 0;
|
parameter sim = 0;
|
||||||
parameter [0:0] debug = 1'b0;
|
|
||||||
parameter with_csr = 1;
|
parameter with_csr = 1;
|
||||||
parameter [0:0] compress = 0;
|
parameter [0:0] compress = 0;
|
||||||
parameter [0:0] align = compress;
|
parameter [0:0] align = 0;
|
||||||
|
|
||||||
|
|
||||||
`ifdef MDU
|
|
||||||
localparam [0:0] with_mdu = 1'b1;
|
|
||||||
`else
|
|
||||||
localparam [0:0] with_mdu = 1'b0;
|
|
||||||
`endif
|
|
||||||
|
|
||||||
localparam aw = $clog2(memsize);
|
|
||||||
localparam csr_regs = with_csr*4;
|
|
||||||
|
|
||||||
localparam rf_width = width * 2;
|
|
||||||
localparam rf_l2d = $clog2((32+csr_regs)*32/rf_width);
|
|
||||||
|
|
||||||
wire timer_irq;
|
wire timer_irq;
|
||||||
|
|
||||||
|
wire [31:0] wb_ibus_adr;
|
||||||
|
wire wb_ibus_cyc;
|
||||||
|
wire [31:0] wb_ibus_rdt;
|
||||||
|
wire wb_ibus_ack;
|
||||||
|
|
||||||
|
wire [31:0] wb_dbus_adr;
|
||||||
|
wire [31:0] wb_dbus_dat;
|
||||||
|
wire [3:0] wb_dbus_sel;
|
||||||
|
wire wb_dbus_we;
|
||||||
|
wire wb_dbus_cyc;
|
||||||
|
wire [31:0] wb_dbus_rdt;
|
||||||
|
wire wb_dbus_ack;
|
||||||
|
|
||||||
|
wire [31:0] wb_dmem_adr;
|
||||||
|
wire [31:0] wb_dmem_dat;
|
||||||
|
wire [3:0] wb_dmem_sel;
|
||||||
|
wire wb_dmem_we;
|
||||||
|
wire wb_dmem_cyc;
|
||||||
|
wire [31:0] wb_dmem_rdt;
|
||||||
|
wire wb_dmem_ack;
|
||||||
|
|
||||||
wire [31:0] wb_mem_adr;
|
wire [31:0] wb_mem_adr;
|
||||||
wire [31:0] wb_mem_dat;
|
wire [31:0] wb_mem_dat;
|
||||||
wire [3:0] wb_mem_sel;
|
wire [3:0] wb_mem_sel;
|
||||||
wire wb_mem_we;
|
wire wb_mem_we;
|
||||||
wire wb_mem_stb;
|
wire wb_mem_cyc;
|
||||||
wire [31:0] wb_mem_rdt;
|
wire [31:0] wb_mem_rdt;
|
||||||
wire wb_mem_ack;
|
wire wb_mem_ack;
|
||||||
|
|
||||||
wire wb_gpio_dat;
|
wire wb_gpio_dat;
|
||||||
wire wb_gpio_we;
|
wire wb_gpio_we;
|
||||||
wire wb_gpio_stb;
|
wire wb_gpio_cyc;
|
||||||
wire wb_gpio_rdt;
|
wire wb_gpio_rdt;
|
||||||
|
|
||||||
wire [31:0] wb_timer_dat;
|
wire [31:0] wb_timer_dat;
|
||||||
wire wb_timer_we;
|
wire wb_timer_we;
|
||||||
wire wb_timer_stb;
|
wire wb_timer_cyc;
|
||||||
wire [31:0] wb_timer_rdt;
|
wire [31:0] wb_timer_rdt;
|
||||||
|
|
||||||
wire [31:0] wb_ext_adr;
|
wire [31:0] mdu_rs1;
|
||||||
wire [31:0] wb_ext_dat;
|
wire [31:0] mdu_rs2;
|
||||||
wire [3:0] wb_ext_sel;
|
wire [ 2:0] mdu_op;
|
||||||
wire wb_ext_we;
|
wire mdu_valid;
|
||||||
wire wb_ext_stb;
|
wire [31:0] mdu_rd;
|
||||||
wire [31:0] wb_ext_rdt;
|
wire mdu_ready;
|
||||||
wire wb_ext_ack;
|
|
||||||
|
|
||||||
wire [rf_l2d-1:0] rf_waddr;
|
servant_arbiter arbiter
|
||||||
wire [rf_width-1:0] rf_wdata;
|
(.i_wb_cpu_dbus_adr (wb_dmem_adr),
|
||||||
wire rf_wen;
|
.i_wb_cpu_dbus_dat (wb_dmem_dat),
|
||||||
wire [rf_l2d-1:0] rf_raddr;
|
.i_wb_cpu_dbus_sel (wb_dmem_sel),
|
||||||
wire rf_ren;
|
.i_wb_cpu_dbus_we (wb_dmem_we ),
|
||||||
wire [rf_width-1:0] rf_rdata;
|
.i_wb_cpu_dbus_cyc (wb_dmem_cyc),
|
||||||
|
.o_wb_cpu_dbus_rdt (wb_dmem_rdt),
|
||||||
|
.o_wb_cpu_dbus_ack (wb_dmem_ack),
|
||||||
|
|
||||||
servant_mux servant_mux
|
.i_wb_cpu_ibus_adr (wb_ibus_adr),
|
||||||
|
.i_wb_cpu_ibus_cyc (wb_ibus_cyc),
|
||||||
|
.o_wb_cpu_ibus_rdt (wb_ibus_rdt),
|
||||||
|
.o_wb_cpu_ibus_ack (wb_ibus_ack),
|
||||||
|
|
||||||
|
.o_wb_cpu_adr (wb_mem_adr),
|
||||||
|
.o_wb_cpu_dat (wb_mem_dat),
|
||||||
|
.o_wb_cpu_sel (wb_mem_sel),
|
||||||
|
.o_wb_cpu_we (wb_mem_we ),
|
||||||
|
.o_wb_cpu_cyc (wb_mem_cyc),
|
||||||
|
.i_wb_cpu_rdt (wb_mem_rdt),
|
||||||
|
.i_wb_cpu_ack (wb_mem_ack));
|
||||||
|
|
||||||
|
servant_mux #(sim) servant_mux
|
||||||
(
|
(
|
||||||
.i_clk (wb_clk),
|
.i_clk (wb_clk),
|
||||||
.i_rst (wb_rst & (reset_strategy != "NONE")),
|
.i_rst (wb_rst & (reset_strategy != "NONE")),
|
||||||
.i_wb_cpu_adr (wb_ext_adr),
|
.i_wb_cpu_adr (wb_dbus_adr),
|
||||||
.i_wb_cpu_dat (wb_ext_dat),
|
.i_wb_cpu_dat (wb_dbus_dat),
|
||||||
.i_wb_cpu_sel (wb_ext_sel),
|
.i_wb_cpu_sel (wb_dbus_sel),
|
||||||
.i_wb_cpu_we (wb_ext_we),
|
.i_wb_cpu_we (wb_dbus_we),
|
||||||
.i_wb_cpu_cyc (wb_ext_stb),
|
.i_wb_cpu_cyc (wb_dbus_cyc),
|
||||||
.o_wb_cpu_rdt (wb_ext_rdt),
|
.o_wb_cpu_rdt (wb_dbus_rdt),
|
||||||
.o_wb_cpu_ack (wb_ext_ack),
|
.o_wb_cpu_ack (wb_dbus_ack),
|
||||||
|
|
||||||
|
.o_wb_mem_adr (wb_dmem_adr),
|
||||||
|
.o_wb_mem_dat (wb_dmem_dat),
|
||||||
|
.o_wb_mem_sel (wb_dmem_sel),
|
||||||
|
.o_wb_mem_we (wb_dmem_we),
|
||||||
|
.o_wb_mem_cyc (wb_dmem_cyc),
|
||||||
|
.i_wb_mem_rdt (wb_dmem_rdt),
|
||||||
|
|
||||||
.o_wb_gpio_dat (wb_gpio_dat),
|
.o_wb_gpio_dat (wb_gpio_dat),
|
||||||
.o_wb_gpio_we (wb_gpio_we),
|
.o_wb_gpio_we (wb_gpio_we),
|
||||||
.o_wb_gpio_cyc (wb_gpio_stb),
|
.o_wb_gpio_cyc (wb_gpio_cyc),
|
||||||
.i_wb_gpio_rdt (wb_gpio_rdt),
|
.i_wb_gpio_rdt (wb_gpio_rdt),
|
||||||
|
|
||||||
.o_wb_timer_dat (wb_timer_dat),
|
.o_wb_timer_dat (wb_timer_dat),
|
||||||
.o_wb_timer_we (wb_timer_we),
|
.o_wb_timer_we (wb_timer_we),
|
||||||
.o_wb_timer_cyc (wb_timer_stb),
|
.o_wb_timer_cyc (wb_timer_cyc),
|
||||||
.i_wb_timer_rdt (wb_timer_rdt));
|
.i_wb_timer_rdt (wb_timer_rdt));
|
||||||
|
|
||||||
servant_ram
|
servant_ram
|
||||||
|
@ -95,79 +121,114 @@ module servant
|
||||||
.i_wb_clk (wb_clk),
|
.i_wb_clk (wb_clk),
|
||||||
.i_wb_rst (wb_rst),
|
.i_wb_rst (wb_rst),
|
||||||
.i_wb_adr (wb_mem_adr[$clog2(memsize)-1:2]),
|
.i_wb_adr (wb_mem_adr[$clog2(memsize)-1:2]),
|
||||||
.i_wb_cyc (wb_mem_stb),
|
.i_wb_cyc (wb_mem_cyc),
|
||||||
.i_wb_we (wb_mem_we) ,
|
.i_wb_we (wb_mem_we) ,
|
||||||
.i_wb_sel (wb_mem_sel),
|
.i_wb_sel (wb_mem_sel),
|
||||||
.i_wb_dat (wb_mem_dat),
|
.i_wb_dat (wb_mem_dat),
|
||||||
.o_wb_rdt (wb_mem_rdt),
|
.o_wb_rdt (wb_mem_rdt),
|
||||||
.o_wb_ack (wb_mem_ack));
|
.o_wb_ack (wb_mem_ack));
|
||||||
|
|
||||||
servant_timer
|
generate
|
||||||
#(.RESET_STRATEGY (reset_strategy),
|
if (|with_csr) begin
|
||||||
.WIDTH (32))
|
servant_timer
|
||||||
timer
|
#(.RESET_STRATEGY (reset_strategy),
|
||||||
(.i_clk (wb_clk),
|
.WIDTH (32))
|
||||||
.i_rst (wb_rst),
|
timer
|
||||||
.o_irq (timer_irq),
|
(.i_clk (wb_clk),
|
||||||
.i_wb_cyc (wb_timer_stb),
|
.i_rst (wb_rst),
|
||||||
.i_wb_we (wb_timer_we) ,
|
.o_irq (timer_irq),
|
||||||
.i_wb_dat (wb_timer_dat),
|
.i_wb_cyc (wb_timer_cyc),
|
||||||
.o_wb_dat (wb_timer_rdt));
|
.i_wb_we (wb_timer_we) ,
|
||||||
|
.i_wb_dat (wb_timer_dat),
|
||||||
|
.o_wb_dat (wb_timer_rdt));
|
||||||
|
end else begin
|
||||||
|
assign wb_timer_rdt = 32'd0;
|
||||||
|
assign timer_irq = 1'b0;
|
||||||
|
end
|
||||||
|
endgenerate
|
||||||
|
|
||||||
servant_gpio gpio
|
servant_gpio gpio
|
||||||
(.i_wb_clk (wb_clk),
|
(.i_wb_clk (wb_clk),
|
||||||
.i_wb_dat (wb_gpio_dat),
|
.i_wb_dat (wb_gpio_dat),
|
||||||
.i_wb_we (wb_gpio_we),
|
.i_wb_we (wb_gpio_we),
|
||||||
.i_wb_cyc (wb_gpio_stb),
|
.i_wb_cyc (wb_gpio_cyc),
|
||||||
.o_wb_rdt (wb_gpio_rdt),
|
.o_wb_rdt (wb_gpio_rdt),
|
||||||
.o_gpio (q));
|
.o_gpio (q));
|
||||||
|
|
||||||
serv_rf_ram
|
serv_rf_top
|
||||||
#(.width (rf_width),
|
#(.RESET_PC (32'h0000_0000),
|
||||||
.csr_regs (csr_regs))
|
.RESET_STRATEGY (reset_strategy),
|
||||||
rf_ram
|
`ifdef MDU
|
||||||
(.i_clk (wb_clk),
|
.MDU(1),
|
||||||
.i_waddr (rf_waddr),
|
`endif
|
||||||
.i_wdata (rf_wdata),
|
.WITH_CSR (with_csr),
|
||||||
.i_wen (rf_wen),
|
.COMPRESSED(compress),
|
||||||
.i_raddr (rf_raddr),
|
.ALIGN(align))
|
||||||
.i_ren (rf_ren),
|
|
||||||
.o_rdata (rf_rdata));
|
|
||||||
|
|
||||||
servile
|
|
||||||
#(.width (width),
|
|
||||||
.sim (sim[0]),
|
|
||||||
.debug (debug),
|
|
||||||
.with_c (compress[0]),
|
|
||||||
.with_csr (with_csr[0]),
|
|
||||||
.with_mdu (with_mdu))
|
|
||||||
cpu
|
cpu
|
||||||
(
|
(
|
||||||
.i_clk (wb_clk),
|
.clk (wb_clk),
|
||||||
.i_rst (wb_rst),
|
.i_rst (wb_rst),
|
||||||
.i_timer_irq (timer_irq),
|
.i_timer_irq (timer_irq),
|
||||||
|
`ifdef RISCV_FORMAL
|
||||||
|
.rvfi_valid (),
|
||||||
|
.rvfi_order (),
|
||||||
|
.rvfi_insn (),
|
||||||
|
.rvfi_trap (),
|
||||||
|
.rvfi_halt (),
|
||||||
|
.rvfi_intr (),
|
||||||
|
.rvfi_mode (),
|
||||||
|
.rvfi_ixl (),
|
||||||
|
.rvfi_rs1_addr (),
|
||||||
|
.rvfi_rs2_addr (),
|
||||||
|
.rvfi_rs1_rdata (),
|
||||||
|
.rvfi_rs2_rdata (),
|
||||||
|
.rvfi_rd_addr (),
|
||||||
|
.rvfi_rd_wdata (),
|
||||||
|
.rvfi_pc_rdata (),
|
||||||
|
.rvfi_pc_wdata (),
|
||||||
|
.rvfi_mem_addr (),
|
||||||
|
.rvfi_mem_rmask (),
|
||||||
|
.rvfi_mem_wmask (),
|
||||||
|
.rvfi_mem_rdata (),
|
||||||
|
.rvfi_mem_wdata (),
|
||||||
|
`endif
|
||||||
|
|
||||||
.o_wb_mem_adr (wb_mem_adr),
|
.o_ibus_adr (wb_ibus_adr),
|
||||||
.o_wb_mem_dat (wb_mem_dat),
|
.o_ibus_cyc (wb_ibus_cyc),
|
||||||
.o_wb_mem_sel (wb_mem_sel),
|
.i_ibus_rdt (wb_ibus_rdt),
|
||||||
.o_wb_mem_we (wb_mem_we),
|
.i_ibus_ack (wb_ibus_ack),
|
||||||
.o_wb_mem_stb (wb_mem_stb),
|
|
||||||
.i_wb_mem_rdt (wb_mem_rdt),
|
|
||||||
.i_wb_mem_ack (wb_mem_ack),
|
|
||||||
|
|
||||||
.o_wb_ext_adr (wb_ext_adr),
|
.o_dbus_adr (wb_dbus_adr),
|
||||||
.o_wb_ext_dat (wb_ext_dat),
|
.o_dbus_dat (wb_dbus_dat),
|
||||||
.o_wb_ext_sel (wb_ext_sel),
|
.o_dbus_sel (wb_dbus_sel),
|
||||||
.o_wb_ext_we (wb_ext_we),
|
.o_dbus_we (wb_dbus_we),
|
||||||
.o_wb_ext_stb (wb_ext_stb),
|
.o_dbus_cyc (wb_dbus_cyc),
|
||||||
.i_wb_ext_rdt (wb_ext_rdt),
|
.i_dbus_rdt (wb_dbus_rdt),
|
||||||
.i_wb_ext_ack (wb_ext_ack),
|
.i_dbus_ack (wb_dbus_ack),
|
||||||
|
|
||||||
|
//Extension
|
||||||
|
.o_ext_rs1 (mdu_rs1),
|
||||||
|
.o_ext_rs2 (mdu_rs2),
|
||||||
|
.o_ext_funct3 (mdu_op),
|
||||||
|
.i_ext_rd (mdu_rd),
|
||||||
|
.i_ext_ready (mdu_ready),
|
||||||
|
//MDU
|
||||||
|
.o_mdu_valid (mdu_valid));
|
||||||
|
|
||||||
.o_rf_waddr (rf_waddr),
|
`ifdef MDU
|
||||||
.o_rf_wdata (rf_wdata),
|
mdu_top mdu_serv
|
||||||
.o_rf_wen (rf_wen),
|
(
|
||||||
.o_rf_raddr (rf_raddr),
|
.i_clk(wb_clk),
|
||||||
.o_rf_ren (rf_ren),
|
.i_rst(wb_rst),
|
||||||
.i_rf_rdata (rf_rdata));
|
.i_mdu_rs1(mdu_rs1),
|
||||||
|
.i_mdu_rs2(mdu_rs2),
|
||||||
|
.i_mdu_op(mdu_op),
|
||||||
|
.i_mdu_valid(mdu_valid),
|
||||||
|
.o_mdu_ready(mdu_ready),
|
||||||
|
.o_mdu_rd(mdu_rd));
|
||||||
|
`else
|
||||||
|
assign mdu_ready = 1'b0;
|
||||||
|
assign mdu_rd = 32'b0;
|
||||||
|
`endif
|
||||||
|
|
||||||
endmodule
|
endmodule
|
||||||
|
|
39
servant/servant_arbiter.v
Normal file
39
servant/servant_arbiter.v
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
/* Arbitrates between dbus and ibus accesses.
|
||||||
|
* Relies on the fact that not both masters are active at the same time
|
||||||
|
*/
|
||||||
|
module servant_arbiter
|
||||||
|
(
|
||||||
|
input wire [31:0] i_wb_cpu_dbus_adr,
|
||||||
|
input wire [31:0] i_wb_cpu_dbus_dat,
|
||||||
|
input wire [3:0] i_wb_cpu_dbus_sel,
|
||||||
|
input wire i_wb_cpu_dbus_we,
|
||||||
|
input wire i_wb_cpu_dbus_cyc,
|
||||||
|
output wire [31:0] o_wb_cpu_dbus_rdt,
|
||||||
|
output wire o_wb_cpu_dbus_ack,
|
||||||
|
|
||||||
|
input wire [31:0] i_wb_cpu_ibus_adr,
|
||||||
|
input wire i_wb_cpu_ibus_cyc,
|
||||||
|
output wire [31:0] o_wb_cpu_ibus_rdt,
|
||||||
|
output wire o_wb_cpu_ibus_ack,
|
||||||
|
|
||||||
|
output wire [31:0] o_wb_cpu_adr,
|
||||||
|
output wire [31:0] o_wb_cpu_dat,
|
||||||
|
output wire [3:0] o_wb_cpu_sel,
|
||||||
|
output wire o_wb_cpu_we,
|
||||||
|
output wire o_wb_cpu_cyc,
|
||||||
|
input wire [31:0] i_wb_cpu_rdt,
|
||||||
|
input wire i_wb_cpu_ack);
|
||||||
|
|
||||||
|
assign o_wb_cpu_dbus_rdt = i_wb_cpu_rdt;
|
||||||
|
assign o_wb_cpu_dbus_ack = i_wb_cpu_ack & !i_wb_cpu_ibus_cyc;
|
||||||
|
|
||||||
|
assign o_wb_cpu_ibus_rdt = i_wb_cpu_rdt;
|
||||||
|
assign o_wb_cpu_ibus_ack = i_wb_cpu_ack & i_wb_cpu_ibus_cyc;
|
||||||
|
|
||||||
|
assign o_wb_cpu_adr = i_wb_cpu_ibus_cyc ? i_wb_cpu_ibus_adr : i_wb_cpu_dbus_adr;
|
||||||
|
assign o_wb_cpu_dat = i_wb_cpu_dbus_dat;
|
||||||
|
assign o_wb_cpu_sel = i_wb_cpu_dbus_sel;
|
||||||
|
assign o_wb_cpu_we = i_wb_cpu_dbus_we & !i_wb_cpu_ibus_cyc;
|
||||||
|
assign o_wb_cpu_cyc = i_wb_cpu_ibus_cyc | i_wb_cpu_dbus_cyc;
|
||||||
|
|
||||||
|
endmodule
|
|
@ -1,5 +1,5 @@
|
||||||
`default_nettype none
|
`default_nettype none
|
||||||
module service_clock_gen
|
module servant_clock_gen
|
||||||
(
|
(
|
||||||
input wire i_clk,
|
input wire i_clk,
|
||||||
output wire o_clk,
|
output wire o_clk,
|
|
@ -1,33 +0,0 @@
|
||||||
`default_nettype none
|
|
||||||
module servant_cmod_a7
|
|
||||||
(
|
|
||||||
input wire i_clk,
|
|
||||||
input wire i_rst,
|
|
||||||
output wire o_uart_tx,
|
|
||||||
output wire q);
|
|
||||||
|
|
||||||
parameter memfile = "zephyr_hello.hex";
|
|
||||||
parameter memsize = 8192;
|
|
||||||
|
|
||||||
wire wb_clk;
|
|
||||||
wire wb_rst;
|
|
||||||
|
|
||||||
assign o_uart_tx = q;
|
|
||||||
|
|
||||||
servant_cmod_a7_clock_gen
|
|
||||||
clock_gen
|
|
||||||
(.i_clk (i_clk),
|
|
||||||
.i_rst (i_rst),
|
|
||||||
.o_clk (wb_clk),
|
|
||||||
.o_rst (wb_rst));
|
|
||||||
|
|
||||||
servant
|
|
||||||
#(.memfile (memfile),
|
|
||||||
.memsize (memsize))
|
|
||||||
servant
|
|
||||||
(.wb_clk (wb_clk),
|
|
||||||
.wb_rst (wb_rst),
|
|
||||||
.q (q));
|
|
||||||
|
|
||||||
endmodule
|
|
||||||
`default_nettype wire
|
|
|
@ -1,35 +0,0 @@
|
||||||
`default_nettype none
|
|
||||||
module servant_cmod_a7_clock_gen
|
|
||||||
(input wire i_clk,
|
|
||||||
input wire i_rst,
|
|
||||||
output wire o_clk,
|
|
||||||
output reg o_rst);
|
|
||||||
|
|
||||||
wire clkfb;
|
|
||||||
wire locked;
|
|
||||||
reg locked_r;
|
|
||||||
|
|
||||||
MMCME2_BASE
|
|
||||||
#(.CLKIN1_PERIOD (83.333), //12MHz
|
|
||||||
|
|
||||||
/* Set VCO frequency to 12*64=768 MHz
|
|
||||||
Allowed values are 2.0 to 64.0. Resulting VCO freq
|
|
||||||
needs to be 600-1200MHz */
|
|
||||||
.CLKFBOUT_MULT_F (64.000),
|
|
||||||
|
|
||||||
.CLKOUT0_DIVIDE_F (48.000)) // 768/48 = 16 MHz
|
|
||||||
pll
|
|
||||||
(.CLKIN1 (i_clk),
|
|
||||||
.RST (i_rst),
|
|
||||||
.CLKOUT0 (o_clk),
|
|
||||||
.LOCKED (locked),
|
|
||||||
.CLKFBOUT (clkfb),
|
|
||||||
.CLKFBIN (clkfb));
|
|
||||||
|
|
||||||
always @(posedge o_clk) begin
|
|
||||||
locked_r <= locked;
|
|
||||||
o_rst <= !locked_r;
|
|
||||||
end
|
|
||||||
|
|
||||||
endmodule
|
|
||||||
`default_nettype wire
|
|
|
@ -1,31 +0,0 @@
|
||||||
`default_nettype none
|
|
||||||
module servant_ecp5_evn
|
|
||||||
(
|
|
||||||
input wire clk,
|
|
||||||
input wire nreset,
|
|
||||||
output wire led0,
|
|
||||||
output wire uart_txd);
|
|
||||||
|
|
||||||
parameter memfile = "zephyr_hello.hex";
|
|
||||||
parameter memsize = 8192;
|
|
||||||
|
|
||||||
wire wb_clk;
|
|
||||||
wire wb_rst;
|
|
||||||
|
|
||||||
assign led0 = nreset;
|
|
||||||
|
|
||||||
servant_ecp5_evn_clock_gen clock_gen
|
|
||||||
(.i_clk (clk),
|
|
||||||
.i_rst (!nreset),
|
|
||||||
.o_clk (wb_clk),
|
|
||||||
.o_rst (wb_rst));
|
|
||||||
|
|
||||||
servant
|
|
||||||
#(.memfile (memfile),
|
|
||||||
.memsize (memsize))
|
|
||||||
servant
|
|
||||||
(.wb_clk (wb_clk),
|
|
||||||
.wb_rst (wb_rst),
|
|
||||||
.q (uart_txd));
|
|
||||||
|
|
||||||
endmodule
|
|
|
@ -1,25 +0,0 @@
|
||||||
`default_nettype none
|
|
||||||
module servant_ecp5_evn_clock_gen
|
|
||||||
(
|
|
||||||
input i_clk,
|
|
||||||
input i_rst,
|
|
||||||
output o_clk,
|
|
||||||
output o_rst);
|
|
||||||
|
|
||||||
wire locked;
|
|
||||||
|
|
||||||
reg [1:0] rst_reg;
|
|
||||||
always @(posedge o_clk)
|
|
||||||
if (i_rst)
|
|
||||||
rst_reg <= 2'b11;
|
|
||||||
else
|
|
||||||
rst_reg <= {!locked, rst_reg[1]};
|
|
||||||
|
|
||||||
assign o_rst = rst_reg[0];
|
|
||||||
|
|
||||||
ecp5_evn_pll pll
|
|
||||||
(.clki (i_clk),
|
|
||||||
.clko (o_clk),
|
|
||||||
.locked (locked));
|
|
||||||
|
|
||||||
endmodule
|
|
|
@ -1,75 +0,0 @@
|
||||||
`timescale 1ns / 1ps
|
|
||||||
|
|
||||||
module servant_gmm7550(
|
|
||||||
input wire ser_clk,
|
|
||||||
output wire led_green,
|
|
||||||
output wire led_red_n,
|
|
||||||
output wire uart_tx);
|
|
||||||
|
|
||||||
// parameter memfile = "zephyr_hello.hex";
|
|
||||||
parameter memfile = "blinky.hex";
|
|
||||||
parameter memsize = 8192;
|
|
||||||
|
|
||||||
wire clk270, clk180, clk90, clk0, usr_ref_out;
|
|
||||||
wire usr_pll_lock_stdy, usr_pll_lock;
|
|
||||||
|
|
||||||
wire usr_rstn;
|
|
||||||
reg[4:0] rst;
|
|
||||||
|
|
||||||
wire sys_clk;
|
|
||||||
wire sys_rst;
|
|
||||||
wire sys_rst_n;
|
|
||||||
wire q;
|
|
||||||
|
|
||||||
assign led_red_n = 1'b1;
|
|
||||||
assign led_green = q;
|
|
||||||
assign uart_tx = q;
|
|
||||||
|
|
||||||
CC_PLL #(
|
|
||||||
.REF_CLK("100.0"), // reference input in MHz
|
|
||||||
.OUT_CLK("32.0"), // pll output frequency in MHz
|
|
||||||
.PERF_MD("SPEED"), // LOWPOWER, ECONOMY, SPEED
|
|
||||||
.LOCK_REQ(1), // Lock status required before PLL output enable
|
|
||||||
.LOW_JITTER(1), // 0: disable, 1: enable low jitter mode
|
|
||||||
.CI_FILTER_CONST(2), // optional CI filter constant
|
|
||||||
.CP_FILTER_CONST(4) // optional CP filter constant
|
|
||||||
) pll_inst (
|
|
||||||
.CLK_REF(ser_clk), .CLK_FEEDBACK(1'b0), .USR_CLK_REF(1'b0),
|
|
||||||
.USR_LOCKED_STDY_RST(1'b0), .USR_PLL_LOCKED_STDY(usr_pll_lock_stdy), .USR_PLL_LOCKED(usr_pll_lock),
|
|
||||||
.CLK270(clk270), .CLK180(clk180), .CLK90(clk90), .CLK0(clk0), .CLK_REF_OUT(usr_ref_out)
|
|
||||||
);
|
|
||||||
|
|
||||||
assign sys_clk = clk0;
|
|
||||||
|
|
||||||
CC_USR_RSTN usr_rst_inst
|
|
||||||
(.USR_RSTN(usr_rstn));
|
|
||||||
|
|
||||||
always @(posedge sys_clk or negedge usr_rstn)
|
|
||||||
begin
|
|
||||||
if (!usr_rstn) begin
|
|
||||||
rst <= 5'b01111;
|
|
||||||
end else begin
|
|
||||||
if (usr_pll_lock) begin
|
|
||||||
if (!rst[4]) begin
|
|
||||||
rst <= rst - 1;
|
|
||||||
end else begin
|
|
||||||
rst <= rst;
|
|
||||||
end
|
|
||||||
end else begin
|
|
||||||
rst <= 5'b01111;
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
assign sys_rst = !rst[4];
|
|
||||||
assign sys_rst_n = rst[4];
|
|
||||||
|
|
||||||
servant
|
|
||||||
#(.memfile (memfile),
|
|
||||||
.memsize (memsize))
|
|
||||||
servant
|
|
||||||
(.wb_clk (sys_clk),
|
|
||||||
.wb_rst (sys_rst),
|
|
||||||
.q (q));
|
|
||||||
|
|
||||||
endmodule
|
|
|
@ -1,46 +0,0 @@
|
||||||
// based on servant_upduino2.v
|
|
||||||
|
|
||||||
`default_nettype none
|
|
||||||
module servant_md_kolibri
|
|
||||||
(
|
|
||||||
input wire clk48,
|
|
||||||
output wire led,
|
|
||||||
output wire tx);
|
|
||||||
|
|
||||||
parameter memfile = "zephyr_hello.hex";
|
|
||||||
parameter memsize = 8192;
|
|
||||||
|
|
||||||
wire clk32;
|
|
||||||
wire locked;
|
|
||||||
|
|
||||||
reg rst = 1'b1;
|
|
||||||
|
|
||||||
// 48MHz -> 32MHz
|
|
||||||
SB_PLL40_CORE #(
|
|
||||||
.FEEDBACK_PATH("SIMPLE"),
|
|
||||||
.DIVR(4'b0010), // DIVR = 2
|
|
||||||
.DIVF(7'b0111111), // DIVF = 63
|
|
||||||
.DIVQ(3'b101), // DIVQ = 5
|
|
||||||
.FILTER_RANGE(3'b001) // FILTER_RANGE = 1
|
|
||||||
) uut (
|
|
||||||
.LOCK(locked),
|
|
||||||
.RESETB(1'b1),
|
|
||||||
.BYPASS(1'b0),
|
|
||||||
.REFERENCECLK(clk48),
|
|
||||||
.PLLOUTCORE(clk32)
|
|
||||||
);
|
|
||||||
|
|
||||||
always @(posedge clk32)
|
|
||||||
rst <= !locked;
|
|
||||||
|
|
||||||
servant
|
|
||||||
#(.memfile (memfile),
|
|
||||||
.memsize (memsize))
|
|
||||||
servant
|
|
||||||
(.wb_clk (clk32),
|
|
||||||
.wb_rst (rst),
|
|
||||||
.q (tx));
|
|
||||||
|
|
||||||
assign led = tx;
|
|
||||||
|
|
||||||
endmodule
|
|
|
@ -16,6 +16,13 @@ module servant_mux
|
||||||
output wire [31:0] o_wb_cpu_rdt,
|
output wire [31:0] o_wb_cpu_rdt,
|
||||||
output reg o_wb_cpu_ack,
|
output reg o_wb_cpu_ack,
|
||||||
|
|
||||||
|
output wire [31:0] o_wb_mem_adr,
|
||||||
|
output wire [31:0] o_wb_mem_dat,
|
||||||
|
output wire [3:0] o_wb_mem_sel,
|
||||||
|
output wire o_wb_mem_we,
|
||||||
|
output wire o_wb_mem_cyc,
|
||||||
|
input wire [31:0] i_wb_mem_rdt,
|
||||||
|
|
||||||
output wire o_wb_gpio_dat,
|
output wire o_wb_gpio_dat,
|
||||||
output wire o_wb_gpio_we,
|
output wire o_wb_gpio_we,
|
||||||
output wire o_wb_gpio_cyc,
|
output wire o_wb_gpio_cyc,
|
||||||
|
@ -30,8 +37,8 @@ module servant_mux
|
||||||
|
|
||||||
wire [1:0] s = i_wb_cpu_adr[31:30];
|
wire [1:0] s = i_wb_cpu_adr[31:30];
|
||||||
|
|
||||||
assign o_wb_cpu_rdt = s[1] ? i_wb_timer_rdt : {31'd0,i_wb_gpio_rdt};
|
assign o_wb_cpu_rdt = s[1] ? i_wb_timer_rdt :
|
||||||
|
s[0] ? {31'd0,i_wb_gpio_rdt} : i_wb_mem_rdt;
|
||||||
always @(posedge i_clk) begin
|
always @(posedge i_clk) begin
|
||||||
o_wb_cpu_ack <= 1'b0;
|
o_wb_cpu_ack <= 1'b0;
|
||||||
if (i_wb_cpu_cyc & !o_wb_cpu_ack)
|
if (i_wb_cpu_cyc & !o_wb_cpu_ack)
|
||||||
|
@ -40,12 +47,43 @@ module servant_mux
|
||||||
o_wb_cpu_ack <= 1'b0;
|
o_wb_cpu_ack <= 1'b0;
|
||||||
end
|
end
|
||||||
|
|
||||||
|
assign o_wb_mem_adr = i_wb_cpu_adr;
|
||||||
|
assign o_wb_mem_dat = i_wb_cpu_dat;
|
||||||
|
assign o_wb_mem_sel = i_wb_cpu_sel;
|
||||||
|
assign o_wb_mem_we = i_wb_cpu_we;
|
||||||
|
assign o_wb_mem_cyc = i_wb_cpu_cyc & (s == 2'b00);
|
||||||
|
|
||||||
assign o_wb_gpio_dat = i_wb_cpu_dat[0];
|
assign o_wb_gpio_dat = i_wb_cpu_dat[0];
|
||||||
assign o_wb_gpio_we = i_wb_cpu_we;
|
assign o_wb_gpio_we = i_wb_cpu_we;
|
||||||
assign o_wb_gpio_cyc = i_wb_cpu_cyc & !s[1];
|
assign o_wb_gpio_cyc = i_wb_cpu_cyc & (s == 2'b01);
|
||||||
|
|
||||||
assign o_wb_timer_dat = i_wb_cpu_dat;
|
assign o_wb_timer_dat = i_wb_cpu_dat;
|
||||||
assign o_wb_timer_we = i_wb_cpu_we;
|
assign o_wb_timer_we = i_wb_cpu_we;
|
||||||
assign o_wb_timer_cyc = i_wb_cpu_cyc & s[1];
|
assign o_wb_timer_cyc = i_wb_cpu_cyc & s[1];
|
||||||
|
|
||||||
|
generate
|
||||||
|
if (sim) begin
|
||||||
|
wire sig_en = (i_wb_cpu_adr[31:28] == 4'h8) & i_wb_cpu_cyc & o_wb_cpu_ack;
|
||||||
|
wire halt_en = (i_wb_cpu_adr[31:28] == 4'h9) & i_wb_cpu_cyc & o_wb_cpu_ack;
|
||||||
|
|
||||||
|
reg [1023:0] signature_file;
|
||||||
|
integer f = 0;
|
||||||
|
|
||||||
|
initial
|
||||||
|
/* verilator lint_off WIDTH */
|
||||||
|
if ($value$plusargs("signature=%s", signature_file)) begin
|
||||||
|
$display("Writing signature to %0s", signature_file);
|
||||||
|
f = $fopen(signature_file, "w");
|
||||||
|
end
|
||||||
|
/* verilator lint_on WIDTH */
|
||||||
|
|
||||||
|
always @(posedge i_clk)
|
||||||
|
if (sig_en & (f != 0))
|
||||||
|
$fwrite(f, "%c", i_wb_cpu_dat[7:0]);
|
||||||
|
else if(halt_en) begin
|
||||||
|
$display("Test complete");
|
||||||
|
$finish;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
endgenerate
|
||||||
endmodule
|
endmodule
|
||||||
|
|
|
@ -71,7 +71,7 @@ module servant_orangecrab
|
||||||
.CLKOS2(), // secondary output
|
.CLKOS2(), // secondary output
|
||||||
.CLKOS3(), // secondary output
|
.CLKOS3(), // secondary output
|
||||||
.LOCK(pll_locked), // lock indicator
|
.LOCK(pll_locked), // lock indicator
|
||||||
.INTLOCK(), // internal lock indicator
|
.INTLOCK(), // internal lock indictor
|
||||||
.REFCLK(), // output of ref select mux
|
.REFCLK(), // output of ref select mux
|
||||||
.CLKINTFB() // internal fb
|
.CLKINTFB() // internal fb
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,66 +0,0 @@
|
||||||
`default_nettype none
|
|
||||||
|
|
||||||
module servant_pf (
|
|
||||||
input wire i_clk,
|
|
||||||
input wire resetb,
|
|
||||||
output wire o_led1,
|
|
||||||
output wire o_led2,
|
|
||||||
output wire o_led3 = 1'b0,
|
|
||||||
output wire o_led4 = 1'b0,
|
|
||||||
output wire o_led5 = 1'b0,
|
|
||||||
output wire o_led6 = 1'b0,
|
|
||||||
output wire o_led7 = 1'b0,
|
|
||||||
output wire o_led8 = 1'b0,
|
|
||||||
output wire o_uart_tx);
|
|
||||||
|
|
||||||
parameter memfile = "zephyr_hello.hex";
|
|
||||||
parameter memsize = 8192;
|
|
||||||
|
|
||||||
wire clk;
|
|
||||||
wire rst;
|
|
||||||
wire q;
|
|
||||||
wire CLKINT_0_Y;
|
|
||||||
reg heartbeat;
|
|
||||||
|
|
||||||
CLKINT CLKINT_0(
|
|
||||||
.A (i_clk),
|
|
||||||
.Y (CLKINT_0_Y)
|
|
||||||
);
|
|
||||||
|
|
||||||
servant_pf_clock_gen #(
|
|
||||||
.refclk(50),
|
|
||||||
.frequency(32)
|
|
||||||
) clock_gen (
|
|
||||||
.i_clk (CLKINT_0_Y),
|
|
||||||
.o_clk (clk)
|
|
||||||
);
|
|
||||||
|
|
||||||
servant #(
|
|
||||||
.memfile (memfile),
|
|
||||||
.memsize (memsize)
|
|
||||||
) servant (
|
|
||||||
.wb_clk (clk),
|
|
||||||
.wb_rst (rst),
|
|
||||||
.q (q)
|
|
||||||
);
|
|
||||||
|
|
||||||
// heartbeat LED
|
|
||||||
reg [$clog2(32000000)-1:0] count = 0;
|
|
||||||
always @(posedge clk) begin
|
|
||||||
if (rst) begin
|
|
||||||
count <= 0;
|
|
||||||
heartbeat <= 0;
|
|
||||||
end else
|
|
||||||
count <= count + 1;
|
|
||||||
if (count == 32000000-1) begin
|
|
||||||
heartbeat <= !heartbeat;
|
|
||||||
count <= 0;
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
assign rst = ~resetb;
|
|
||||||
assign o_led1 = q;
|
|
||||||
assign o_led2 = heartbeat;
|
|
||||||
assign o_uart_tx = q;
|
|
||||||
|
|
||||||
endmodule
|
|
|
@ -1,157 +0,0 @@
|
||||||
`timescale 1 ns/100 ps
|
|
||||||
|
|
||||||
module servant_pf_clock_gen(
|
|
||||||
input wire i_clk,
|
|
||||||
output wire o_clk,
|
|
||||||
output reg o_lock);
|
|
||||||
|
|
||||||
// for documentation
|
|
||||||
parameter refclk = 50;
|
|
||||||
parameter frequency = 32;
|
|
||||||
|
|
||||||
// PLL in internal Post-VCO Feedback mode
|
|
||||||
localparam [11:0] fbdiv = 12'b100111000000; // 2496
|
|
||||||
localparam [5:0] rfdiv = 6'b011001; // 25;
|
|
||||||
localparam vco = 4992; // refclk * fbdiv / rfdiv;
|
|
||||||
localparam [6:0] odiv = 7'b0100111; // vco / (4 * frequency);
|
|
||||||
|
|
||||||
wire gnd_net, vcc_net, pll_inst_0_clkint_0;
|
|
||||||
wire nc0, nc1, nc2, nc3, nc4, nc5, nc6, nc7, nc8, nc9, nc10, nc11, nc12,
|
|
||||||
nc13, nc14, nc15, nc16, nc17, nc18, nc19, nc20, nc21, nc22, nc23,
|
|
||||||
nc24, nc25, nc26, nc27, nc28, nc29, nc30, nc31, nc32, nc33, nc34,
|
|
||||||
nc35, nc36, nc37, nc38, nc39, nc40;
|
|
||||||
|
|
||||||
VCC vcc_inst (.Y(vcc_net));
|
|
||||||
GND gnd_inst (.Y(gnd_net));
|
|
||||||
|
|
||||||
PLL #(
|
|
||||||
.VCOFREQUENCY(vco),
|
|
||||||
.DELAY_LINE_SIMULATION_MODE(""),
|
|
||||||
.DATA_RATE(0.0),
|
|
||||||
.FORMAL_NAME(""),
|
|
||||||
.INTERFACE_NAME(""),
|
|
||||||
.INTERFACE_LEVEL(3'b0),
|
|
||||||
.SOFTRESET(1'b0),
|
|
||||||
.SOFT_POWERDOWN_N(1'b1),
|
|
||||||
.RFDIV_EN(1'b1),
|
|
||||||
.OUT0_DIV_EN(1'b1),
|
|
||||||
.OUT1_DIV_EN(1'b0),
|
|
||||||
.OUT2_DIV_EN(1'b0),
|
|
||||||
.OUT3_DIV_EN(1'b0),
|
|
||||||
.SOFT_REF_CLK_SEL(1'b0),
|
|
||||||
.RESET_ON_LOCK(1'b1),
|
|
||||||
.BYPASS_CLK_SEL(4'b0),
|
|
||||||
.BYPASS_GO_EN_N(1'b1),
|
|
||||||
.BYPASS_PLL(4'b0),
|
|
||||||
.BYPASS_OUT_DIVIDER(4'b0),
|
|
||||||
.FF_REQUIRES_LOCK(1'b0),
|
|
||||||
.FSE_N(1'b0),
|
|
||||||
.FB_CLK_SEL_0(2'b00),
|
|
||||||
.FB_CLK_SEL_1(1'b0),
|
|
||||||
.RFDIV(rfdiv),
|
|
||||||
.FRAC_EN(1'b0),
|
|
||||||
.FRAC_DAC_EN(1'b0),
|
|
||||||
.DIV0_RST_DELAY(3'b000),
|
|
||||||
.DIV0_VAL(odiv),
|
|
||||||
.DIV1_RST_DELAY(3'b0),
|
|
||||||
.DIV1_VAL(7'b1),
|
|
||||||
.DIV2_RST_DELAY(3'b0),
|
|
||||||
.DIV2_VAL(7'b1),
|
|
||||||
.DIV3_RST_DELAY(3'b0),
|
|
||||||
.DIV3_VAL(7'b1),
|
|
||||||
.DIV3_CLK_SEL(1'b0),
|
|
||||||
.BW_INT_CTRL(2'b0),
|
|
||||||
.BW_PROP_CTRL(2'b01),
|
|
||||||
.IREF_EN(1'b1),
|
|
||||||
.IREF_TOGGLE(1'b0),
|
|
||||||
.LOCK_CNT(4'b1000),
|
|
||||||
.DESKEW_CAL_CNT(3'b110),
|
|
||||||
.DESKEW_CAL_EN(1'b1),
|
|
||||||
.DESKEW_CAL_BYPASS(1'b0),
|
|
||||||
.SYNC_REF_DIV_EN(1'b0),
|
|
||||||
.SYNC_REF_DIV_EN_2(1'b0),
|
|
||||||
.OUT0_PHASE_SEL(3'b000),
|
|
||||||
.OUT1_PHASE_SEL(3'b0),
|
|
||||||
.OUT2_PHASE_SEL(3'b0),
|
|
||||||
.OUT3_PHASE_SEL(3'b0),
|
|
||||||
.SOFT_LOAD_PHASE_N(1'b1),
|
|
||||||
.SSM_DIV_VAL(6'b1),
|
|
||||||
.FB_FRAC_VAL(24'b0),
|
|
||||||
.SSM_SPREAD_MODE(1'b0),
|
|
||||||
.SSM_MODULATION(5'b00101),
|
|
||||||
.FB_INT_VAL(fbdiv),
|
|
||||||
.SSM_EN_N(1'b1),
|
|
||||||
.SSM_EXT_WAVE_EN(2'b0),
|
|
||||||
.SSM_EXT_WAVE_MAX_ADDR(8'b0),
|
|
||||||
.SSM_RANDOM_EN(1'b0),
|
|
||||||
.SSM_RANDOM_PATTERN_SEL(3'b0),
|
|
||||||
.CDMUX0_SEL(2'b0),
|
|
||||||
.CDMUX1_SEL(1'b1),
|
|
||||||
.CDMUX2_SEL(1'b0),
|
|
||||||
.CDELAY0_SEL(8'b0),
|
|
||||||
.CDELAY0_EN(1'b0),
|
|
||||||
.DRI_EN(1'b1)
|
|
||||||
) pll_inst_0 (
|
|
||||||
.LOCK(o_lock),
|
|
||||||
.SSCG_WAVE_TABLE_ADDR({
|
|
||||||
nc0, nc1, nc2, nc3, nc4, nc5, nc6, nc7
|
|
||||||
}),
|
|
||||||
.DELAY_LINE_OUT_OF_RANGE(),
|
|
||||||
.POWERDOWN_N(vcc_net),
|
|
||||||
.OUT0_EN(vcc_net),
|
|
||||||
.OUT1_EN(gnd_net),
|
|
||||||
.OUT2_EN(gnd_net),
|
|
||||||
.OUT3_EN(gnd_net),
|
|
||||||
.REF_CLK_SEL(gnd_net),
|
|
||||||
.BYPASS_EN_N(vcc_net),
|
|
||||||
.LOAD_PHASE_N(vcc_net),
|
|
||||||
.SSCG_WAVE_TABLE({
|
|
||||||
gnd_net, gnd_net, gnd_net, gnd_net, gnd_net, gnd_net, gnd_net,
|
|
||||||
gnd_net
|
|
||||||
}),
|
|
||||||
.PHASE_DIRECTION(gnd_net),
|
|
||||||
.PHASE_ROTATE(gnd_net),
|
|
||||||
.PHASE_OUT0_SEL(gnd_net),
|
|
||||||
.PHASE_OUT1_SEL(gnd_net),
|
|
||||||
.PHASE_OUT2_SEL(gnd_net),
|
|
||||||
.PHASE_OUT3_SEL(gnd_net),
|
|
||||||
.DELAY_LINE_MOVE(gnd_net),
|
|
||||||
.DELAY_LINE_DIRECTION(gnd_net),
|
|
||||||
.DELAY_LINE_WIDE(gnd_net),
|
|
||||||
.DELAY_LINE_LOAD(vcc_net),
|
|
||||||
.REFCLK_SYNC_EN(gnd_net),
|
|
||||||
.REF_CLK_0(i_clk),
|
|
||||||
.REF_CLK_1(gnd_net),
|
|
||||||
.FB_CLK(gnd_net),
|
|
||||||
.OUT0(pll_inst_0_clkint_0),
|
|
||||||
.OUT1(),
|
|
||||||
.OUT2(),
|
|
||||||
.OUT3(),
|
|
||||||
.DRI_CLK(gnd_net),
|
|
||||||
.DRI_CTRL({
|
|
||||||
gnd_net, gnd_net, gnd_net, gnd_net, gnd_net, gnd_net, gnd_net,
|
|
||||||
gnd_net, gnd_net, gnd_net, gnd_net
|
|
||||||
}),
|
|
||||||
.DRI_WDATA({
|
|
||||||
gnd_net, gnd_net, gnd_net, gnd_net, gnd_net, gnd_net, gnd_net,
|
|
||||||
gnd_net, gnd_net, gnd_net, gnd_net, gnd_net, gnd_net, gnd_net,
|
|
||||||
gnd_net, gnd_net, gnd_net, gnd_net, gnd_net, gnd_net, gnd_net,
|
|
||||||
gnd_net, gnd_net, gnd_net, gnd_net, gnd_net, gnd_net, gnd_net,
|
|
||||||
gnd_net, gnd_net, gnd_net, gnd_net, gnd_net
|
|
||||||
}),
|
|
||||||
.DRI_ARST_N(vcc_net),
|
|
||||||
.DRI_RDATA({
|
|
||||||
nc8, nc9, nc10, nc11, nc12, nc13, nc14, nc15, nc16, nc17, nc18,
|
|
||||||
nc19, nc20, nc21, nc22, nc23, nc24, nc25, nc26, nc27, nc28, nc29,
|
|
||||||
nc30, nc31, nc32, nc33, nc34, nc35, nc36, nc37, nc38, nc39,
|
|
||||||
nc40
|
|
||||||
}),
|
|
||||||
.DRI_INTERRUPT()
|
|
||||||
);
|
|
||||||
|
|
||||||
CLKINT clkint_0 (
|
|
||||||
.A(pll_inst_0_clkint_0),
|
|
||||||
.Y(o_clk)
|
|
||||||
);
|
|
||||||
|
|
||||||
endmodule
|
|
|
@ -38,9 +38,7 @@ module servant_ram
|
||||||
initial
|
initial
|
||||||
if(|memfile) begin
|
if(|memfile) begin
|
||||||
`ifndef ISE
|
`ifndef ISE
|
||||||
`ifndef CCGM
|
|
||||||
$display("Preloading %m from %s", memfile);
|
$display("Preloading %m from %s", memfile);
|
||||||
`endif
|
|
||||||
`endif
|
`endif
|
||||||
$readmemh(memfile, mem);
|
$readmemh(memfile, mem);
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,33 +0,0 @@
|
||||||
`default_nettype none
|
|
||||||
module servant_te0802
|
|
||||||
(
|
|
||||||
input wire i_clk,
|
|
||||||
output wire o_uart_tx,
|
|
||||||
output wire o_led_0
|
|
||||||
);
|
|
||||||
|
|
||||||
parameter memfile = "zephyr_hello.hex";
|
|
||||||
parameter memsize = 8192;
|
|
||||||
|
|
||||||
wire clk;
|
|
||||||
wire rst;
|
|
||||||
wire q;
|
|
||||||
|
|
||||||
assign o_uart_tx = q;
|
|
||||||
assign o_led_0 = q;
|
|
||||||
|
|
||||||
servant_te0802_clock_gen
|
|
||||||
clock_gen
|
|
||||||
(.i_clk (i_clk),
|
|
||||||
.o_clk (clk),
|
|
||||||
.o_rst (rst));
|
|
||||||
|
|
||||||
servant
|
|
||||||
#(.memfile (memfile),
|
|
||||||
.memsize (memsize))
|
|
||||||
servant
|
|
||||||
(.wb_clk (clk),
|
|
||||||
.wb_rst (rst),
|
|
||||||
.q (q));
|
|
||||||
|
|
||||||
endmodule
|
|
|
@ -1,45 +0,0 @@
|
||||||
`default_nettype none
|
|
||||||
module servant_te0802_clock_gen
|
|
||||||
(input wire i_clk,
|
|
||||||
output wire o_clk,
|
|
||||||
output reg o_rst);
|
|
||||||
|
|
||||||
wire clkfb;
|
|
||||||
wire locked;
|
|
||||||
reg locked_r;
|
|
||||||
|
|
||||||
// Generate a 32 MHz clock from the 25MHz clock input
|
|
||||||
MMCME4_ADV
|
|
||||||
#(.DIVCLK_DIVIDE (1),
|
|
||||||
.CLKFBOUT_MULT_F (48.000),
|
|
||||||
.CLKOUT0_DIVIDE_F (37.5),
|
|
||||||
.CLKIN1_PERIOD (40.0), //25MHz
|
|
||||||
.STARTUP_WAIT ("FALSE"))
|
|
||||||
mmcm
|
|
||||||
(.CLKFBOUT (clkfb),
|
|
||||||
.CLKFBOUTB (),
|
|
||||||
.CLKOUT0 (o_clk),
|
|
||||||
.CLKOUT0B (),
|
|
||||||
.CLKOUT1 (),
|
|
||||||
.CLKOUT1B (),
|
|
||||||
.CLKOUT2 (),
|
|
||||||
.CLKOUT2B (),
|
|
||||||
.CLKOUT3 (),
|
|
||||||
.CLKOUT3B (),
|
|
||||||
.CLKOUT4 (),
|
|
||||||
.CLKOUT5 (),
|
|
||||||
.CLKOUT6 (),
|
|
||||||
.CLKIN1 (i_clk),
|
|
||||||
.CLKIN2 (1'b0),
|
|
||||||
.CLKINSEL (1'b1),
|
|
||||||
.LOCKED (locked),
|
|
||||||
.PWRDWN (1'b0),
|
|
||||||
.RST (1'b0),
|
|
||||||
.CLKFBIN (clkfb));
|
|
||||||
|
|
||||||
always @(posedge o_clk) begin
|
|
||||||
locked_r <= locked;
|
|
||||||
o_rst <= !locked_r;
|
|
||||||
end
|
|
||||||
|
|
||||||
endmodule
|
|
|
@ -14,9 +14,9 @@ module servant_timer
|
||||||
localparam HIGH = WIDTH-1-DIVIDER;
|
localparam HIGH = WIDTH-1-DIVIDER;
|
||||||
|
|
||||||
reg [WIDTH-1:0] mtime;
|
reg [WIDTH-1:0] mtime;
|
||||||
reg signed [HIGH:0] mtimecmp;
|
reg [HIGH:0] mtimecmp;
|
||||||
|
|
||||||
wire signed [HIGH:0] mtimeslice = mtime[WIDTH-1:DIVIDER];
|
wire [HIGH:0] mtimeslice = mtime[WIDTH-1:DIVIDER];
|
||||||
|
|
||||||
always @(mtimeslice) begin
|
always @(mtimeslice) begin
|
||||||
o_wb_dat = 32'd0;
|
o_wb_dat = 32'd0;
|
||||||
|
@ -27,7 +27,7 @@ module servant_timer
|
||||||
if (i_wb_cyc & i_wb_we)
|
if (i_wb_cyc & i_wb_we)
|
||||||
mtimecmp <= i_wb_dat[HIGH:0];
|
mtimecmp <= i_wb_dat[HIGH:0];
|
||||||
mtime <= mtime + 'd1;
|
mtime <= mtime + 'd1;
|
||||||
o_irq <= (mtimeslice - mtimecmp >= 0);
|
o_irq <= (mtimeslice >= mtimecmp);
|
||||||
if (RESET_STRATEGY != "NONE")
|
if (RESET_STRATEGY != "NONE")
|
||||||
if (i_rst) begin
|
if (i_rst) begin
|
||||||
mtime <= 0;
|
mtime <= 0;
|
||||||
|
|
|
@ -1,31 +0,0 @@
|
||||||
`default_nettype none
|
|
||||||
module servde1_soc_revF
|
|
||||||
(
|
|
||||||
input wire i_clk,
|
|
||||||
input wire i_rst_n,
|
|
||||||
output wire q,
|
|
||||||
output wire uart_txd);
|
|
||||||
|
|
||||||
parameter memfile = "zephyr_hello.hex";
|
|
||||||
parameter memsize = 8192;
|
|
||||||
|
|
||||||
wire wb_clk;
|
|
||||||
wire wb_rst;
|
|
||||||
|
|
||||||
assign uart_txd = q;
|
|
||||||
|
|
||||||
servde1_soc_revF_clock_gen clock_gen
|
|
||||||
(.i_clk (i_clk),
|
|
||||||
.i_rst (!i_rst_n),
|
|
||||||
.o_clk (wb_clk),
|
|
||||||
.o_rst (wb_rst));
|
|
||||||
|
|
||||||
servant
|
|
||||||
#(.memfile (memfile),
|
|
||||||
.memsize (memsize))
|
|
||||||
servant
|
|
||||||
(.wb_clk (wb_clk),
|
|
||||||
.wb_rst (wb_rst),
|
|
||||||
.q (q));
|
|
||||||
|
|
||||||
endmodule
|
|
|
@ -1,34 +0,0 @@
|
||||||
`default_nettype none
|
|
||||||
module servde1_soc_revF_clock_gen
|
|
||||||
(input wire i_clk,
|
|
||||||
input wire i_rst,
|
|
||||||
output wire o_clk,
|
|
||||||
output wire o_rst);
|
|
||||||
|
|
||||||
wire locked;
|
|
||||||
reg [9:0] r;
|
|
||||||
|
|
||||||
assign o_rst = r[9];
|
|
||||||
|
|
||||||
always @(posedge o_clk)
|
|
||||||
if (locked)
|
|
||||||
r <= {r[8:0],1'b0};
|
|
||||||
else
|
|
||||||
r <= 10'b1111111111;
|
|
||||||
|
|
||||||
wire [5:0] clk;
|
|
||||||
|
|
||||||
assign o_clk = clk[0];
|
|
||||||
|
|
||||||
altpll
|
|
||||||
#(.operation_mode ("NORMAL"),
|
|
||||||
.clk0_divide_by (25),
|
|
||||||
.clk0_multiply_by (8),
|
|
||||||
.inclk0_input_frequency (20000))
|
|
||||||
pll
|
|
||||||
(.areset (i_rst),
|
|
||||||
.inclk ({1'b0, i_clk}),
|
|
||||||
.clk (clk),
|
|
||||||
.locked (locked));
|
|
||||||
|
|
||||||
endmodule
|
|
|
@ -11,7 +11,7 @@ module service
|
||||||
wire wb_clk;
|
wire wb_clk;
|
||||||
wire wb_rst;
|
wire wb_rst;
|
||||||
|
|
||||||
service_clock_gen #(.PLL (PLL))
|
servant_clock_gen #(.PLL (PLL))
|
||||||
clock_gen
|
clock_gen
|
||||||
(.i_clk (i_clk),
|
(.i_clk (i_clk),
|
||||||
.o_clk (wb_clk),
|
.o_clk (wb_clk),
|
||||||
|
|
|
@ -2,9 +2,6 @@
|
||||||
module servix
|
module servix
|
||||||
(
|
(
|
||||||
input wire i_clk,
|
input wire i_clk,
|
||||||
`ifdef WITH_RESET
|
|
||||||
input wire i_rst_n,
|
|
||||||
`endif
|
|
||||||
output wire q);
|
output wire q);
|
||||||
|
|
||||||
parameter frequency = 32;
|
parameter frequency = 32;
|
||||||
|
@ -19,11 +16,6 @@ module servix
|
||||||
#(.frequency (frequency))
|
#(.frequency (frequency))
|
||||||
clock_gen
|
clock_gen
|
||||||
(.i_clk (i_clk),
|
(.i_clk (i_clk),
|
||||||
`ifdef WITH_RESET
|
|
||||||
.i_rst (!i_rst_n),
|
|
||||||
`else
|
|
||||||
.i_rst (1'b0),
|
|
||||||
`endif
|
|
||||||
.o_clk (wb_clk),
|
.o_clk (wb_clk),
|
||||||
.o_rst (wb_rst));
|
.o_rst (wb_rst));
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
`default_nettype none
|
`default_nettype none
|
||||||
module servix_clock_gen
|
module servix_clock_gen
|
||||||
(input wire i_clk,
|
(input wire i_clk,
|
||||||
input wire i_rst,
|
|
||||||
output wire o_clk,
|
output wire o_clk,
|
||||||
output reg o_rst);
|
output reg o_rst);
|
||||||
|
|
||||||
|
@ -29,7 +28,7 @@ module servix_clock_gen
|
||||||
.LOCKED(locked),
|
.LOCKED(locked),
|
||||||
.CLKIN1(i_clk),
|
.CLKIN1(i_clk),
|
||||||
.PWRDWN(1'b0),
|
.PWRDWN(1'b0),
|
||||||
.RST(i_rst),
|
.RST(1'b0),
|
||||||
.CLKFBIN(clkfb));
|
.CLKFBIN(clkfb));
|
||||||
|
|
||||||
always @(posedge o_clk) begin
|
always @(posedge o_clk) begin
|
||||||
|
|
27
servile.core
27
servile.core
|
@ -1,27 +0,0 @@
|
||||||
CAPI=2:
|
|
||||||
|
|
||||||
name : ::servile:1.3.0
|
|
||||||
|
|
||||||
description: Convenience wrapper for SERV
|
|
||||||
|
|
||||||
filesets:
|
|
||||||
rtl:
|
|
||||||
files:
|
|
||||||
- servile/servile_rf_mem_if.v
|
|
||||||
- servile/servile_mux.v
|
|
||||||
- servile/servile_arbiter.v
|
|
||||||
- servile/servile.v
|
|
||||||
file_type: verilogSource
|
|
||||||
depend : [serv]
|
|
||||||
|
|
||||||
targets:
|
|
||||||
default:
|
|
||||||
filesets: [rtl]
|
|
||||||
|
|
||||||
lint:
|
|
||||||
description: Run static code checks (linting)
|
|
||||||
filesets: [rtl]
|
|
||||||
flow: lint
|
|
||||||
flow_options:
|
|
||||||
tool: verilator
|
|
||||||
toplevel: servile
|
|
|
@ -1,279 +0,0 @@
|
||||||
/*
|
|
||||||
* servile.v : Top-level for Servile, the SERV convenience wrapper
|
|
||||||
*
|
|
||||||
* SPDX-FileCopyrightText: 2024 Olof Kindgren <olof.kindgren@gmail.com>
|
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
|
||||||
*/
|
|
||||||
|
|
||||||
`default_nettype none
|
|
||||||
module servile
|
|
||||||
#(
|
|
||||||
parameter width = 1,
|
|
||||||
parameter reset_pc = 32'h00000000,
|
|
||||||
parameter reset_strategy = "MINI",
|
|
||||||
parameter rf_width = 2*width,
|
|
||||||
parameter [0:0] sim = 1'b0,
|
|
||||||
parameter [0:0] debug = 1'b0,
|
|
||||||
parameter [0:0] with_c = 1'b0,
|
|
||||||
parameter [0:0] with_csr = 1'b0,
|
|
||||||
parameter [0:0] with_mdu = 1'b0,
|
|
||||||
//Internally calculated. Do not touch
|
|
||||||
parameter B = width-1,
|
|
||||||
parameter regs = 32+with_csr*4,
|
|
||||||
parameter rf_l2d = $clog2(regs*32/rf_width))
|
|
||||||
(
|
|
||||||
input wire i_clk,
|
|
||||||
input wire i_rst,
|
|
||||||
input wire i_timer_irq,
|
|
||||||
|
|
||||||
//Memory (WB) interface
|
|
||||||
output wire [31:0] o_wb_mem_adr,
|
|
||||||
output wire [31:0] o_wb_mem_dat,
|
|
||||||
output wire [3:0] o_wb_mem_sel,
|
|
||||||
output wire o_wb_mem_we ,
|
|
||||||
output wire o_wb_mem_stb,
|
|
||||||
input wire [31:0] i_wb_mem_rdt,
|
|
||||||
input wire i_wb_mem_ack,
|
|
||||||
|
|
||||||
//Extension (WB) interface
|
|
||||||
output wire [31:0] o_wb_ext_adr,
|
|
||||||
output wire [31:0] o_wb_ext_dat,
|
|
||||||
output wire [3:0] o_wb_ext_sel,
|
|
||||||
output wire o_wb_ext_we ,
|
|
||||||
output wire o_wb_ext_stb,
|
|
||||||
input wire [31:0] i_wb_ext_rdt,
|
|
||||||
input wire i_wb_ext_ack,
|
|
||||||
|
|
||||||
//RF (SRAM) interface
|
|
||||||
output wire [rf_l2d-1:0] o_rf_waddr,
|
|
||||||
output wire [rf_width-1:0] o_rf_wdata,
|
|
||||||
output wire o_rf_wen,
|
|
||||||
output wire [rf_l2d-1:0] o_rf_raddr,
|
|
||||||
input wire [rf_width-1:0] i_rf_rdata,
|
|
||||||
output wire o_rf_ren);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
wire [31:0] wb_ibus_adr;
|
|
||||||
wire wb_ibus_stb;
|
|
||||||
wire [31:0] wb_ibus_rdt;
|
|
||||||
wire wb_ibus_ack;
|
|
||||||
|
|
||||||
wire [31:0] wb_dbus_adr;
|
|
||||||
wire [31:0] wb_dbus_dat;
|
|
||||||
wire [3:0] wb_dbus_sel;
|
|
||||||
wire wb_dbus_we;
|
|
||||||
wire wb_dbus_stb;
|
|
||||||
wire [31:0] wb_dbus_rdt;
|
|
||||||
wire wb_dbus_ack;
|
|
||||||
|
|
||||||
wire [31:0] wb_dmem_adr;
|
|
||||||
wire [31:0] wb_dmem_dat;
|
|
||||||
wire [3:0] wb_dmem_sel;
|
|
||||||
wire wb_dmem_we;
|
|
||||||
wire wb_dmem_stb;
|
|
||||||
wire [31:0] wb_dmem_rdt;
|
|
||||||
wire wb_dmem_ack;
|
|
||||||
|
|
||||||
wire rf_wreq;
|
|
||||||
wire rf_rreq;
|
|
||||||
wire [$clog2(regs)-1:0] wreg0;
|
|
||||||
wire [$clog2(regs)-1:0] wreg1;
|
|
||||||
wire wen0;
|
|
||||||
wire wen1;
|
|
||||||
wire [B:0] wdata0;
|
|
||||||
wire [B:0] wdata1;
|
|
||||||
wire [$clog2(regs)-1:0] rreg0;
|
|
||||||
wire [$clog2(regs)-1:0] rreg1;
|
|
||||||
wire rf_ready;
|
|
||||||
wire [B:0] rdata0;
|
|
||||||
wire [B:0] rdata1;
|
|
||||||
|
|
||||||
wire [31:0] mdu_rs1;
|
|
||||||
wire [31:0] mdu_rs2;
|
|
||||||
wire [ 2:0] mdu_op;
|
|
||||||
wire mdu_valid;
|
|
||||||
wire [31:0] mdu_rd;
|
|
||||||
wire mdu_ready;
|
|
||||||
|
|
||||||
servile_mux
|
|
||||||
#(.sim (sim))
|
|
||||||
mux
|
|
||||||
(.i_clk (i_clk),
|
|
||||||
.i_rst (i_rst & (reset_strategy != "NONE")),
|
|
||||||
|
|
||||||
.i_wb_cpu_adr (wb_dbus_adr),
|
|
||||||
.i_wb_cpu_dat (wb_dbus_dat),
|
|
||||||
.i_wb_cpu_sel (wb_dbus_sel),
|
|
||||||
.i_wb_cpu_we (wb_dbus_we),
|
|
||||||
.i_wb_cpu_stb (wb_dbus_stb),
|
|
||||||
.o_wb_cpu_rdt (wb_dbus_rdt),
|
|
||||||
.o_wb_cpu_ack (wb_dbus_ack),
|
|
||||||
|
|
||||||
.o_wb_mem_adr (wb_dmem_adr),
|
|
||||||
.o_wb_mem_dat (wb_dmem_dat),
|
|
||||||
.o_wb_mem_sel (wb_dmem_sel),
|
|
||||||
.o_wb_mem_we (wb_dmem_we),
|
|
||||||
.o_wb_mem_stb (wb_dmem_stb),
|
|
||||||
.i_wb_mem_rdt (wb_dmem_rdt),
|
|
||||||
.i_wb_mem_ack (wb_dmem_ack),
|
|
||||||
|
|
||||||
.o_wb_ext_adr (o_wb_ext_adr),
|
|
||||||
.o_wb_ext_dat (o_wb_ext_dat),
|
|
||||||
.o_wb_ext_sel (o_wb_ext_sel),
|
|
||||||
.o_wb_ext_we (o_wb_ext_we),
|
|
||||||
.o_wb_ext_stb (o_wb_ext_stb),
|
|
||||||
.i_wb_ext_rdt (i_wb_ext_rdt),
|
|
||||||
.i_wb_ext_ack (i_wb_ext_ack));
|
|
||||||
|
|
||||||
servile_arbiter arbiter
|
|
||||||
(.i_wb_cpu_dbus_adr (wb_dmem_adr),
|
|
||||||
.i_wb_cpu_dbus_dat (wb_dmem_dat),
|
|
||||||
.i_wb_cpu_dbus_sel (wb_dmem_sel),
|
|
||||||
.i_wb_cpu_dbus_we (wb_dmem_we ),
|
|
||||||
.i_wb_cpu_dbus_stb (wb_dmem_stb),
|
|
||||||
.o_wb_cpu_dbus_rdt (wb_dmem_rdt),
|
|
||||||
.o_wb_cpu_dbus_ack (wb_dmem_ack),
|
|
||||||
|
|
||||||
.i_wb_cpu_ibus_adr (wb_ibus_adr),
|
|
||||||
.i_wb_cpu_ibus_stb (wb_ibus_stb),
|
|
||||||
.o_wb_cpu_ibus_rdt (wb_ibus_rdt),
|
|
||||||
.o_wb_cpu_ibus_ack (wb_ibus_ack),
|
|
||||||
|
|
||||||
.o_wb_mem_adr (o_wb_mem_adr),
|
|
||||||
.o_wb_mem_dat (o_wb_mem_dat),
|
|
||||||
.o_wb_mem_sel (o_wb_mem_sel),
|
|
||||||
.o_wb_mem_we (o_wb_mem_we ),
|
|
||||||
.o_wb_mem_stb (o_wb_mem_stb),
|
|
||||||
.i_wb_mem_rdt (i_wb_mem_rdt),
|
|
||||||
.i_wb_mem_ack (i_wb_mem_ack));
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
serv_rf_ram_if
|
|
||||||
#(.width (rf_width),
|
|
||||||
.W (width),
|
|
||||||
.reset_strategy (reset_strategy),
|
|
||||||
.csr_regs (with_csr*4))
|
|
||||||
rf_ram_if
|
|
||||||
(.i_clk (i_clk),
|
|
||||||
.i_rst (i_rst),
|
|
||||||
//RF IF
|
|
||||||
.i_wreq (rf_wreq),
|
|
||||||
.i_rreq (rf_rreq),
|
|
||||||
.o_ready (rf_ready),
|
|
||||||
.i_wreg0 (wreg0),
|
|
||||||
.i_wreg1 (wreg1),
|
|
||||||
.i_wen0 (wen0),
|
|
||||||
.i_wen1 (wen1),
|
|
||||||
.i_wdata0 (wdata0),
|
|
||||||
.i_wdata1 (wdata1),
|
|
||||||
.i_rreg0 (rreg0),
|
|
||||||
.i_rreg1 (rreg1),
|
|
||||||
.o_rdata0 (rdata0),
|
|
||||||
.o_rdata1 (rdata1),
|
|
||||||
//SRAM IF
|
|
||||||
.o_waddr (o_rf_waddr),
|
|
||||||
.o_wdata (o_rf_wdata),
|
|
||||||
.o_wen (o_rf_wen),
|
|
||||||
.o_raddr (o_rf_raddr),
|
|
||||||
.o_ren (o_rf_ren),
|
|
||||||
.i_rdata (i_rf_rdata));
|
|
||||||
|
|
||||||
generate
|
|
||||||
if (with_mdu) begin : gen_mdu
|
|
||||||
mdu_top mdu_serv
|
|
||||||
(.i_clk (i_clk),
|
|
||||||
.i_rst (i_rst),
|
|
||||||
.i_mdu_rs1 (mdu_rs1),
|
|
||||||
.i_mdu_rs2 (mdu_rs2),
|
|
||||||
.i_mdu_op (mdu_op),
|
|
||||||
.i_mdu_valid (mdu_valid),
|
|
||||||
.o_mdu_ready (mdu_ready),
|
|
||||||
.o_mdu_rd (mdu_rd));
|
|
||||||
end else begin
|
|
||||||
assign mdu_ready = 1'b0;
|
|
||||||
assign mdu_rd = 32'd0;
|
|
||||||
end
|
|
||||||
endgenerate
|
|
||||||
|
|
||||||
serv_top
|
|
||||||
#(
|
|
||||||
.WITH_CSR (with_csr?1:0),
|
|
||||||
.W (width),
|
|
||||||
.PRE_REGISTER (1'b1),
|
|
||||||
.RESET_STRATEGY (reset_strategy),
|
|
||||||
.RESET_PC (reset_pc),
|
|
||||||
.DEBUG (debug),
|
|
||||||
.MDU (with_mdu),
|
|
||||||
.COMPRESSED (with_c))
|
|
||||||
cpu
|
|
||||||
(
|
|
||||||
.clk (i_clk),
|
|
||||||
.i_rst (i_rst),
|
|
||||||
.i_timer_irq (i_timer_irq),
|
|
||||||
|
|
||||||
`ifdef RISCV_FORMAL
|
|
||||||
.rvfi_valid (),
|
|
||||||
.rvfi_order (),
|
|
||||||
.rvfi_insn (),
|
|
||||||
.rvfi_trap (),
|
|
||||||
.rvfi_halt (),
|
|
||||||
.rvfi_intr (),
|
|
||||||
.rvfi_mode (),
|
|
||||||
.rvfi_ixl (),
|
|
||||||
.rvfi_rs1_addr (),
|
|
||||||
.rvfi_rs2_addr (),
|
|
||||||
.rvfi_rs1_rdata (),
|
|
||||||
.rvfi_rs2_rdata (),
|
|
||||||
.rvfi_rd_addr (),
|
|
||||||
.rvfi_rd_wdata (),
|
|
||||||
.rvfi_pc_rdata (),
|
|
||||||
.rvfi_pc_wdata (),
|
|
||||||
.rvfi_mem_addr (),
|
|
||||||
.rvfi_mem_rmask (),
|
|
||||||
.rvfi_mem_wmask (),
|
|
||||||
.rvfi_mem_rdata (),
|
|
||||||
.rvfi_mem_wdata (),
|
|
||||||
`endif
|
|
||||||
//RF IF
|
|
||||||
.o_rf_rreq (rf_rreq),
|
|
||||||
.o_rf_wreq (rf_wreq),
|
|
||||||
.i_rf_ready (rf_ready),
|
|
||||||
.o_wreg0 (wreg0),
|
|
||||||
.o_wreg1 (wreg1),
|
|
||||||
.o_wen0 (wen0),
|
|
||||||
.o_wen1 (wen1),
|
|
||||||
.o_wdata0 (wdata0),
|
|
||||||
.o_wdata1 (wdata1),
|
|
||||||
.o_rreg0 (rreg0),
|
|
||||||
.o_rreg1 (rreg1),
|
|
||||||
.i_rdata0 (rdata0),
|
|
||||||
.i_rdata1 (rdata1),
|
|
||||||
|
|
||||||
//Instruction bus
|
|
||||||
.o_ibus_adr (wb_ibus_adr),
|
|
||||||
.o_ibus_cyc (wb_ibus_stb),
|
|
||||||
.i_ibus_rdt (wb_ibus_rdt),
|
|
||||||
.i_ibus_ack (wb_ibus_ack),
|
|
||||||
|
|
||||||
//Data bus
|
|
||||||
.o_dbus_adr (wb_dbus_adr),
|
|
||||||
.o_dbus_dat (wb_dbus_dat),
|
|
||||||
.o_dbus_sel (wb_dbus_sel),
|
|
||||||
.o_dbus_we (wb_dbus_we),
|
|
||||||
.o_dbus_cyc (wb_dbus_stb),
|
|
||||||
.i_dbus_rdt (wb_dbus_rdt),
|
|
||||||
.i_dbus_ack (wb_dbus_ack),
|
|
||||||
|
|
||||||
//Extension IF
|
|
||||||
.o_ext_rs1 (mdu_rs1),
|
|
||||||
.o_ext_rs2 (mdu_rs2),
|
|
||||||
.o_ext_funct3 (mdu_op),
|
|
||||||
.i_ext_rd (mdu_rd),
|
|
||||||
.i_ext_ready (mdu_ready),
|
|
||||||
//MDU
|
|
||||||
.o_mdu_valid (mdu_valid));
|
|
||||||
|
|
||||||
endmodule
|
|
||||||
`default_nettype wire
|
|
|
@ -1,100 +0,0 @@
|
||||||
/*
|
|
||||||
* servile_mux.v : Simple Wishbone mux for the servile convenience wrapper.
|
|
||||||
*
|
|
||||||
* SPDX-FileCopyrightText: 2024 Olof Kindgren <olof.kindgren@gmail.com>
|
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
|
||||||
*/
|
|
||||||
|
|
||||||
module servile_mux
|
|
||||||
#(parameter [0:0] sim = 1'b0, //Enable simulation features
|
|
||||||
parameter [31:0] sim_sig_adr = 32'h80000000,
|
|
||||||
parameter [31:0] sim_halt_adr = 32'h90000000)
|
|
||||||
(
|
|
||||||
input wire i_clk,
|
|
||||||
input wire i_rst,
|
|
||||||
|
|
||||||
input wire [31:0] i_wb_cpu_adr,
|
|
||||||
input wire [31:0] i_wb_cpu_dat,
|
|
||||||
input wire [3:0] i_wb_cpu_sel,
|
|
||||||
input wire i_wb_cpu_we,
|
|
||||||
input wire i_wb_cpu_stb,
|
|
||||||
output wire [31:0] o_wb_cpu_rdt,
|
|
||||||
output wire o_wb_cpu_ack,
|
|
||||||
|
|
||||||
output wire [31:0] o_wb_mem_adr,
|
|
||||||
output wire [31:0] o_wb_mem_dat,
|
|
||||||
output wire [3:0] o_wb_mem_sel,
|
|
||||||
output wire o_wb_mem_we,
|
|
||||||
output wire o_wb_mem_stb,
|
|
||||||
input wire [31:0] i_wb_mem_rdt,
|
|
||||||
input wire i_wb_mem_ack,
|
|
||||||
|
|
||||||
output wire [31:0] o_wb_ext_adr,
|
|
||||||
output wire [31:0] o_wb_ext_dat,
|
|
||||||
output wire [3:0] o_wb_ext_sel,
|
|
||||||
output wire o_wb_ext_we,
|
|
||||||
output wire o_wb_ext_stb,
|
|
||||||
input wire [31:0] i_wb_ext_rdt,
|
|
||||||
input wire i_wb_ext_ack);
|
|
||||||
|
|
||||||
wire sig_en;
|
|
||||||
wire halt_en;
|
|
||||||
reg sim_ack;
|
|
||||||
|
|
||||||
wire ext = (i_wb_cpu_adr[31:30] != 2'b00);
|
|
||||||
|
|
||||||
assign o_wb_cpu_rdt = ext ? i_wb_ext_rdt : i_wb_mem_rdt;
|
|
||||||
assign o_wb_cpu_ack = i_wb_ext_ack | i_wb_mem_ack | sim_ack;
|
|
||||||
|
|
||||||
assign o_wb_mem_adr = i_wb_cpu_adr;
|
|
||||||
assign o_wb_mem_dat = i_wb_cpu_dat;
|
|
||||||
assign o_wb_mem_sel = i_wb_cpu_sel;
|
|
||||||
assign o_wb_mem_we = i_wb_cpu_we;
|
|
||||||
assign o_wb_mem_stb = i_wb_cpu_stb & !ext & !(sig_en|halt_en);
|
|
||||||
|
|
||||||
assign o_wb_ext_adr = i_wb_cpu_adr;
|
|
||||||
assign o_wb_ext_dat = i_wb_cpu_dat;
|
|
||||||
assign o_wb_ext_sel = i_wb_cpu_sel;
|
|
||||||
assign o_wb_ext_we = i_wb_cpu_we;
|
|
||||||
assign o_wb_ext_stb = i_wb_cpu_stb & ext & !(sig_en|halt_en);
|
|
||||||
|
|
||||||
generate
|
|
||||||
if (sim) begin
|
|
||||||
|
|
||||||
integer f = 0;
|
|
||||||
|
|
||||||
assign sig_en = |f & i_wb_cpu_we & (i_wb_cpu_adr == sim_sig_adr);
|
|
||||||
assign halt_en = i_wb_cpu_we & (i_wb_cpu_adr == sim_halt_adr);
|
|
||||||
|
|
||||||
reg [1023:0] signature_file;
|
|
||||||
|
|
||||||
initial
|
|
||||||
/* verilator lint_off WIDTH */
|
|
||||||
if ($value$plusargs("signature=%s", signature_file)) begin
|
|
||||||
$display("Writing signature to %0s", signature_file);
|
|
||||||
f = $fopen(signature_file, "w");
|
|
||||||
end
|
|
||||||
/* verilator lint_on WIDTH */
|
|
||||||
|
|
||||||
always @(posedge i_clk) begin
|
|
||||||
sim_ack <= 1'b0;
|
|
||||||
if (i_wb_cpu_stb & !sim_ack) begin
|
|
||||||
sim_ack <= sig_en|halt_en;
|
|
||||||
if (sig_en & (f != 0))
|
|
||||||
$fwrite(f, "%c", i_wb_cpu_dat[7:0]);
|
|
||||||
else if(halt_en) begin
|
|
||||||
$display("Test complete");
|
|
||||||
$finish;
|
|
||||||
end
|
|
||||||
end
|
|
||||||
if (i_rst)
|
|
||||||
sim_ack <= 1'b0;
|
|
||||||
end
|
|
||||||
end else begin
|
|
||||||
assign sig_en = 1'b0;
|
|
||||||
assign halt_en = 1'b0;
|
|
||||||
initial sim_ack = 1'b0;
|
|
||||||
end
|
|
||||||
endgenerate
|
|
||||||
|
|
||||||
endmodule
|
|
|
@ -1,77 +0,0 @@
|
||||||
/*
|
|
||||||
* servile_rf_mem_if.v : Arbiter to allow a shared SRAM for RF and memory accesses. RF is mapped to the highest 128 bytes of the memory. Requires 8-bit RF accesses.
|
|
||||||
*
|
|
||||||
* SPDX-FileCopyrightText: 2024 Olof Kindgren <olof.kindgren@gmail.com>
|
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
|
||||||
*/
|
|
||||||
|
|
||||||
`default_nettype none
|
|
||||||
module servile_rf_mem_if
|
|
||||||
#(//Memory parameters
|
|
||||||
parameter depth = 256,
|
|
||||||
//RF parameters
|
|
||||||
parameter rf_regs = 32,
|
|
||||||
//Internally calculated. Do not touch
|
|
||||||
parameter rf_depth = $clog2(rf_regs*4),
|
|
||||||
parameter aw = $clog2(depth))
|
|
||||||
(
|
|
||||||
input wire i_clk,
|
|
||||||
input wire i_rst,
|
|
||||||
input wire [rf_depth-1:0] i_waddr,
|
|
||||||
input wire [7:0] i_wdata,
|
|
||||||
input wire i_wen,
|
|
||||||
input wire [rf_depth-1:0] i_raddr,
|
|
||||||
output wire [7:0] o_rdata,
|
|
||||||
input wire i_ren,
|
|
||||||
|
|
||||||
output wire [aw-1:0] o_sram_waddr,
|
|
||||||
output wire [7:0] o_sram_wdata,
|
|
||||||
output wire o_sram_wen,
|
|
||||||
output wire [aw-1:0] o_sram_raddr,
|
|
||||||
input wire [7:0] i_sram_rdata,
|
|
||||||
output wire o_sram_ren,
|
|
||||||
|
|
||||||
input wire [aw-1:2] i_wb_adr,
|
|
||||||
input wire [31:0] i_wb_dat,
|
|
||||||
input wire [3:0] i_wb_sel,
|
|
||||||
input wire i_wb_we,
|
|
||||||
input wire i_wb_stb,
|
|
||||||
output wire [31:0] o_wb_rdt,
|
|
||||||
output reg o_wb_ack);
|
|
||||||
|
|
||||||
reg [1:0] bsel;
|
|
||||||
|
|
||||||
wire wb_en = i_wb_stb & !i_wen & !o_wb_ack;
|
|
||||||
|
|
||||||
wire wb_we = i_wb_we & i_wb_sel[bsel];
|
|
||||||
|
|
||||||
wire [aw-1:0] rf_waddr = ~{{aw-rf_depth{1'b0}},i_waddr};
|
|
||||||
wire [aw-1:0] rf_raddr = ~{{aw-rf_depth{1'b0}},i_raddr};
|
|
||||||
|
|
||||||
assign o_sram_waddr = wb_en ? {i_wb_adr[aw-1:2],bsel} : rf_waddr;
|
|
||||||
assign o_sram_wdata = wb_en ? i_wb_dat[bsel*8+:8] : i_wdata;
|
|
||||||
assign o_sram_wen = wb_en ? wb_we : i_wen;
|
|
||||||
assign o_sram_raddr = wb_en ? {i_wb_adr[aw-1:2],bsel} : rf_raddr;
|
|
||||||
assign o_sram_ren = wb_en ? !i_wb_we : i_ren;
|
|
||||||
|
|
||||||
reg [23:0] wb_rdt;
|
|
||||||
assign o_wb_rdt = {i_sram_rdata, wb_rdt};
|
|
||||||
|
|
||||||
reg regzero;
|
|
||||||
always @(posedge i_clk) begin
|
|
||||||
|
|
||||||
if (wb_en) bsel <= bsel + 2'd1;
|
|
||||||
o_wb_ack <= wb_en & &bsel;
|
|
||||||
if (bsel == 2'b01) wb_rdt[7:0] <= i_sram_rdata;
|
|
||||||
if (bsel == 2'b10) wb_rdt[15:8] <= i_sram_rdata;
|
|
||||||
if (bsel == 2'b11) wb_rdt[23:16] <= i_sram_rdata;
|
|
||||||
if (i_rst) begin
|
|
||||||
bsel <= 2'd0;
|
|
||||||
o_wb_ack <= 1'b0;
|
|
||||||
end
|
|
||||||
regzero <= &i_raddr[rf_depth-1:2];
|
|
||||||
end
|
|
||||||
|
|
||||||
assign o_rdata = regzero ? 8'd0 : i_sram_rdata;
|
|
||||||
|
|
||||||
endmodule
|
|
|
@ -1,15 +1,16 @@
|
||||||
CAPI=2:
|
CAPI=2:
|
||||||
|
|
||||||
name : ::serving:1.3.0
|
name : ::serving:1.2.0
|
||||||
description: SERV-based subsystem for FPGAs
|
|
||||||
|
|
||||||
filesets:
|
filesets:
|
||||||
rtl:
|
rtl:
|
||||||
files:
|
files:
|
||||||
|
- serving/serving_arbiter.v
|
||||||
|
- serving/serving_mux.v
|
||||||
- serving/serving_ram.v
|
- serving/serving_ram.v
|
||||||
- serving/serving.v
|
- serving/serving.v
|
||||||
file_type : verilogSource
|
file_type : verilogSource
|
||||||
depend : [servile]
|
depend : [serv]
|
||||||
|
|
||||||
targets:
|
targets:
|
||||||
default:
|
default:
|
||||||
|
@ -17,7 +18,6 @@ targets:
|
||||||
|
|
||||||
lint:
|
lint:
|
||||||
default_tool : verilator
|
default_tool : verilator
|
||||||
description: Run static code checks (linting)
|
|
||||||
filesets : [rtl]
|
filesets : [rtl]
|
||||||
tools:
|
tools:
|
||||||
verilator:
|
verilator:
|
||||||
|
|
|
@ -34,13 +34,35 @@ module serving
|
||||||
|
|
||||||
parameter memfile = "";
|
parameter memfile = "";
|
||||||
parameter memsize = 8192;
|
parameter memsize = 8192;
|
||||||
parameter sim = 1'b0;
|
|
||||||
parameter RESET_STRATEGY = "NONE";
|
parameter RESET_STRATEGY = "NONE";
|
||||||
parameter WITH_CSR = 1;
|
parameter WITH_CSR = 1;
|
||||||
localparam regs = 32+WITH_CSR*4;
|
localparam regs = 32+WITH_CSR*4;
|
||||||
|
|
||||||
localparam rf_width = 8;
|
localparam rf_width = 8;
|
||||||
|
|
||||||
|
localparam aw = $clog2(memsize);
|
||||||
|
|
||||||
|
wire [31:0] wb_ibus_adr;
|
||||||
|
wire wb_ibus_stb;
|
||||||
|
wire [31:0] wb_ibus_rdt;
|
||||||
|
wire wb_ibus_ack;
|
||||||
|
|
||||||
|
wire [31:0] wb_dbus_adr;
|
||||||
|
wire [31:0] wb_dbus_dat;
|
||||||
|
wire [3:0] wb_dbus_sel;
|
||||||
|
wire wb_dbus_we;
|
||||||
|
wire wb_dbus_stb;
|
||||||
|
wire [31:0] wb_dbus_rdt;
|
||||||
|
wire wb_dbus_ack;
|
||||||
|
|
||||||
|
wire [31:0] wb_dmem_adr;
|
||||||
|
wire [31:0] wb_dmem_dat;
|
||||||
|
wire [3:0] wb_dmem_sel;
|
||||||
|
wire wb_dmem_we;
|
||||||
|
wire wb_dmem_stb;
|
||||||
|
wire [31:0] wb_dmem_rdt;
|
||||||
|
wire wb_dmem_ack;
|
||||||
|
|
||||||
wire [31:0] wb_mem_adr;
|
wire [31:0] wb_mem_adr;
|
||||||
wire [31:0] wb_mem_dat;
|
wire [31:0] wb_mem_dat;
|
||||||
wire [3:0] wb_mem_sel;
|
wire [3:0] wb_mem_sel;
|
||||||
|
@ -49,19 +71,65 @@ module serving
|
||||||
wire [31:0] wb_mem_rdt;
|
wire [31:0] wb_mem_rdt;
|
||||||
wire wb_mem_ack;
|
wire wb_mem_ack;
|
||||||
|
|
||||||
wire [6+WITH_CSR:0] rf_waddr;
|
wire [6+WITH_CSR:0] waddr;
|
||||||
wire [rf_width-1:0] rf_wdata;
|
wire [rf_width-1:0] wdata;
|
||||||
wire rf_wen;
|
wire wen;
|
||||||
wire [6+WITH_CSR:0] rf_raddr;
|
wire [6+WITH_CSR:0] raddr;
|
||||||
wire [rf_width-1:0] rf_rdata;
|
wire [rf_width-1:0] rdata;
|
||||||
wire rf_ren;
|
|
||||||
|
|
||||||
wire [$clog2(memsize)-1:0] sram_waddr;
|
|
||||||
wire [rf_width-1:0] sram_wdata;
|
wire [aw-1:0] rf_waddr = ~{{aw-2-5-WITH_CSR{1'b0}},waddr};
|
||||||
wire sram_wen;
|
wire [aw-1:0] rf_raddr = ~{{aw-2-5-WITH_CSR{1'b0}},raddr};
|
||||||
wire [$clog2(memsize)-1:0] sram_raddr;
|
|
||||||
wire [rf_width-1:0] sram_rdata;
|
serving_arbiter arbiter
|
||||||
wire sram_ren;
|
(.i_wb_cpu_dbus_adr (wb_dmem_adr),
|
||||||
|
.i_wb_cpu_dbus_dat (wb_dmem_dat),
|
||||||
|
.i_wb_cpu_dbus_sel (wb_dmem_sel),
|
||||||
|
.i_wb_cpu_dbus_we (wb_dmem_we ),
|
||||||
|
.i_wb_cpu_dbus_stb (wb_dmem_stb),
|
||||||
|
.o_wb_cpu_dbus_rdt (wb_dmem_rdt),
|
||||||
|
.o_wb_cpu_dbus_ack (wb_dmem_ack),
|
||||||
|
|
||||||
|
.i_wb_cpu_ibus_adr (wb_ibus_adr),
|
||||||
|
.i_wb_cpu_ibus_stb (wb_ibus_stb),
|
||||||
|
.o_wb_cpu_ibus_rdt (wb_ibus_rdt),
|
||||||
|
.o_wb_cpu_ibus_ack (wb_ibus_ack),
|
||||||
|
|
||||||
|
.o_wb_mem_adr (wb_mem_adr),
|
||||||
|
.o_wb_mem_dat (wb_mem_dat),
|
||||||
|
.o_wb_mem_sel (wb_mem_sel),
|
||||||
|
.o_wb_mem_we (wb_mem_we ),
|
||||||
|
.o_wb_mem_stb (wb_mem_stb),
|
||||||
|
.i_wb_mem_rdt (wb_mem_rdt),
|
||||||
|
.i_wb_mem_ack (wb_mem_ack));
|
||||||
|
|
||||||
|
serving_mux mux
|
||||||
|
(.i_clk (i_clk),
|
||||||
|
.i_rst (i_rst & (RESET_STRATEGY != "NONE")),
|
||||||
|
|
||||||
|
.i_wb_cpu_adr (wb_dbus_adr),
|
||||||
|
.i_wb_cpu_dat (wb_dbus_dat),
|
||||||
|
.i_wb_cpu_sel (wb_dbus_sel),
|
||||||
|
.i_wb_cpu_we (wb_dbus_we),
|
||||||
|
.i_wb_cpu_stb (wb_dbus_stb),
|
||||||
|
.o_wb_cpu_rdt (wb_dbus_rdt),
|
||||||
|
.o_wb_cpu_ack (wb_dbus_ack),
|
||||||
|
|
||||||
|
.o_wb_mem_adr (wb_dmem_adr),
|
||||||
|
.o_wb_mem_dat (wb_dmem_dat),
|
||||||
|
.o_wb_mem_sel (wb_dmem_sel),
|
||||||
|
.o_wb_mem_we (wb_dmem_we),
|
||||||
|
.o_wb_mem_stb (wb_dmem_stb),
|
||||||
|
.i_wb_mem_rdt (wb_dmem_rdt),
|
||||||
|
.i_wb_mem_ack (wb_dmem_ack),
|
||||||
|
|
||||||
|
.o_wb_ext_adr (o_wb_adr),
|
||||||
|
.o_wb_ext_dat (o_wb_dat),
|
||||||
|
.o_wb_ext_sel (o_wb_sel),
|
||||||
|
.o_wb_ext_we (o_wb_we),
|
||||||
|
.o_wb_ext_stb (o_wb_stb),
|
||||||
|
.i_wb_ext_rdt (i_wb_rdt),
|
||||||
|
.i_wb_ext_ack (i_wb_ack));
|
||||||
|
|
||||||
serving_ram
|
serving_ram
|
||||||
#(.memfile (memfile),
|
#(.memfile (memfile),
|
||||||
|
@ -69,35 +137,11 @@ module serving
|
||||||
ram
|
ram
|
||||||
(// Wishbone interface
|
(// Wishbone interface
|
||||||
.i_clk (i_clk),
|
.i_clk (i_clk),
|
||||||
.i_waddr (sram_waddr),
|
|
||||||
.i_wdata (sram_wdata),
|
|
||||||
.i_wen (sram_wen),
|
|
||||||
.i_raddr (sram_raddr),
|
|
||||||
.o_rdata (sram_rdata)/*,
|
|
||||||
.i_ren (rf_ren)*/);
|
|
||||||
|
|
||||||
servile_rf_mem_if
|
|
||||||
#(.depth (memsize),
|
|
||||||
.rf_regs (regs))
|
|
||||||
rf_mem_if
|
|
||||||
(// Wishbone interface
|
|
||||||
.i_clk (i_clk),
|
|
||||||
.i_rst (i_rst),
|
|
||||||
|
|
||||||
.i_waddr (rf_waddr),
|
.i_waddr (rf_waddr),
|
||||||
.i_wdata (rf_wdata),
|
.i_wdata (wdata),
|
||||||
.i_wen (rf_wen),
|
.i_wen (wen),
|
||||||
.i_raddr (rf_raddr),
|
.i_raddr (rf_raddr),
|
||||||
.o_rdata (rf_rdata),
|
.o_rdata (rdata),
|
||||||
.i_ren (rf_ren),
|
|
||||||
|
|
||||||
.o_sram_waddr (sram_waddr),
|
|
||||||
.o_sram_wdata (sram_wdata),
|
|
||||||
.o_sram_wen (sram_wen),
|
|
||||||
.o_sram_raddr (sram_raddr),
|
|
||||||
.i_sram_rdata (sram_rdata),
|
|
||||||
.o_sram_ren (sram_ren),
|
|
||||||
|
|
||||||
.i_wb_adr (wb_mem_adr[$clog2(memsize)-1:2]),
|
.i_wb_adr (wb_mem_adr[$clog2(memsize)-1:2]),
|
||||||
.i_wb_stb (wb_mem_stb),
|
.i_wb_stb (wb_mem_stb),
|
||||||
.i_wb_we (wb_mem_we) ,
|
.i_wb_we (wb_mem_we) ,
|
||||||
|
@ -106,42 +150,86 @@ module serving
|
||||||
.o_wb_rdt (wb_mem_rdt),
|
.o_wb_rdt (wb_mem_rdt),
|
||||||
.o_wb_ack (wb_mem_ack));
|
.o_wb_ack (wb_mem_ack));
|
||||||
|
|
||||||
servile
|
localparam RF_L2W = $clog2(rf_width);
|
||||||
#(.reset_pc (32'h0000_0000),
|
|
||||||
|
wire rf_wreq;
|
||||||
|
wire rf_rreq;
|
||||||
|
wire [$clog2(regs)-1:0] wreg0;
|
||||||
|
wire [$clog2(regs)-1:0] wreg1;
|
||||||
|
wire wen0;
|
||||||
|
wire wen1;
|
||||||
|
wire wdata0;
|
||||||
|
wire wdata1;
|
||||||
|
wire [$clog2(regs)-1:0] rreg0;
|
||||||
|
wire [$clog2(regs)-1:0] rreg1;
|
||||||
|
wire rf_ready;
|
||||||
|
wire rdata0;
|
||||||
|
wire rdata1;
|
||||||
|
|
||||||
|
|
||||||
|
serv_rf_ram_if
|
||||||
|
#(.width (rf_width),
|
||||||
.reset_strategy (RESET_STRATEGY),
|
.reset_strategy (RESET_STRATEGY),
|
||||||
.rf_width (rf_width),
|
.csr_regs (WITH_CSR*4))
|
||||||
.sim (sim),
|
rf_ram_if
|
||||||
.with_csr (WITH_CSR))
|
(.i_clk (i_clk),
|
||||||
servile
|
.i_rst (i_rst),
|
||||||
|
.i_wreq (rf_wreq),
|
||||||
|
.i_rreq (rf_rreq),
|
||||||
|
.o_ready (rf_ready),
|
||||||
|
.i_wreg0 (wreg0),
|
||||||
|
.i_wreg1 (wreg1),
|
||||||
|
.i_wen0 (wen0),
|
||||||
|
.i_wen1 (wen1),
|
||||||
|
.i_wdata0 (wdata0),
|
||||||
|
.i_wdata1 (wdata1),
|
||||||
|
.i_rreg0 (rreg0),
|
||||||
|
.i_rreg1 (rreg1),
|
||||||
|
.o_rdata0 (rdata0),
|
||||||
|
.o_rdata1 (rdata1),
|
||||||
|
.o_waddr (waddr),
|
||||||
|
.o_wdata (wdata),
|
||||||
|
.o_wen (wen),
|
||||||
|
.o_raddr (raddr),
|
||||||
|
.i_rdata (rdata));
|
||||||
|
|
||||||
|
serv_top
|
||||||
|
#(.RESET_PC (32'h0000_0000),
|
||||||
|
.RESET_STRATEGY (RESET_STRATEGY),
|
||||||
|
.WITH_CSR (WITH_CSR))
|
||||||
|
cpu
|
||||||
(
|
(
|
||||||
.i_clk (i_clk),
|
.clk (i_clk),
|
||||||
.i_rst (i_rst),
|
.i_rst (i_rst),
|
||||||
.i_timer_irq (i_timer_irq),
|
.i_timer_irq (i_timer_irq),
|
||||||
//Memory interface
|
|
||||||
.o_wb_mem_adr (wb_mem_adr),
|
|
||||||
.o_wb_mem_dat (wb_mem_dat),
|
|
||||||
.o_wb_mem_sel (wb_mem_sel),
|
|
||||||
.o_wb_mem_we (wb_mem_we),
|
|
||||||
.o_wb_mem_stb (wb_mem_stb),
|
|
||||||
.i_wb_mem_rdt (wb_mem_rdt),
|
|
||||||
.i_wb_mem_ack (wb_mem_ack),
|
|
||||||
|
|
||||||
//Extension interface
|
|
||||||
.o_wb_ext_adr (o_wb_adr),
|
|
||||||
.o_wb_ext_dat (o_wb_dat),
|
|
||||||
.o_wb_ext_sel (o_wb_sel),
|
|
||||||
.o_wb_ext_we (o_wb_we),
|
|
||||||
.o_wb_ext_stb (o_wb_stb),
|
|
||||||
.i_wb_ext_rdt (i_wb_rdt),
|
|
||||||
.i_wb_ext_ack (i_wb_ack),
|
|
||||||
|
|
||||||
//RF IF
|
//RF IF
|
||||||
.o_rf_waddr (rf_waddr),
|
.o_rf_rreq (rf_rreq),
|
||||||
.o_rf_wdata (rf_wdata),
|
.o_rf_wreq (rf_wreq),
|
||||||
.o_rf_wen (rf_wen),
|
.i_rf_ready (rf_ready),
|
||||||
.o_rf_raddr (rf_raddr),
|
.o_wreg0 (wreg0),
|
||||||
.o_rf_ren (rf_ren),
|
.o_wreg1 (wreg1),
|
||||||
.i_rf_rdata (rf_rdata));
|
.o_wen0 (wen0),
|
||||||
|
.o_wen1 (wen1),
|
||||||
|
.o_wdata0 (wdata0),
|
||||||
|
.o_wdata1 (wdata1),
|
||||||
|
.o_rreg0 (rreg0),
|
||||||
|
.o_rreg1 (rreg1),
|
||||||
|
.i_rdata0 (rdata0),
|
||||||
|
.i_rdata1 (rdata1),
|
||||||
|
|
||||||
|
//Instruction bus
|
||||||
|
.o_ibus_adr (wb_ibus_adr),
|
||||||
|
.o_ibus_cyc (wb_ibus_stb),
|
||||||
|
.i_ibus_rdt (wb_ibus_rdt),
|
||||||
|
.i_ibus_ack (wb_ibus_ack),
|
||||||
|
|
||||||
|
//Data bus
|
||||||
|
.o_dbus_adr (wb_dbus_adr),
|
||||||
|
.o_dbus_dat (wb_dbus_dat),
|
||||||
|
.o_dbus_sel (wb_dbus_sel),
|
||||||
|
.o_dbus_we (wb_dbus_we),
|
||||||
|
.o_dbus_cyc (wb_dbus_stb),
|
||||||
|
.i_dbus_rdt (wb_dbus_rdt),
|
||||||
|
.i_dbus_ack (wb_dbus_ack));
|
||||||
|
|
||||||
endmodule
|
endmodule
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue