├── .github └── workflows │ ├── ci.yml │ ├── formal.yml │ ├── lint.yml │ ├── openlane.yml │ └── pages.yml ├── .gitmodules ├── .readthedocs.yml ├── LICENSE ├── NEWS ├── README.md ├── bench ├── servant_sim.v ├── servant_tb.cpp ├── servant_tb.v ├── servant_tb_vidbo.cpp └── uart_decoder.v ├── data ├── ac701.xdc ├── alchitry_au.xdc ├── alhambra.pcf ├── arty_a7_35t.xdc ├── arty_s7_50t.xdc ├── ax309.ucf ├── chameleon96 │ ├── CV_96.v │ ├── HPS.sv │ ├── chain1.cdf │ ├── chameleon96.sdc │ └── pinmap.tcl ├── cmod_a7_35t.xdc ├── cyc1000.sdc ├── cyc1000.tcl ├── de0_nano.sdc ├── de0_nano.tcl ├── de10_nano.sdc ├── de10_nano.tcl ├── de1_soc_revF.sdc ├── de1_soc_revF.tcl ├── deca.sdc ├── deca.tcl ├── ebaz4205.xdc ├── ecp5_evn.lpf ├── gmm7550.ccf ├── go_board.pcf ├── icebreaker.pcf ├── icestick.pcf ├── icesugar.pcf ├── icev_wireless.pcf ├── lx9_microboard.ucf ├── machdyne_kolibri.pcf ├── max10_10m08evk.sdc ├── max10_10m08evk.tcl ├── nexys_2.tcl ├── nexys_2.ucf ├── nexys_a7.xdc ├── orangecrab_r02.lpf ├── params.tcl ├── pipistrello.ucf ├── polarfire_splashkit.pdc ├── sockit.sdc ├── sockit.tcl ├── te0802.xdc ├── tinyfpga_bx.pcf ├── ulx3s.lpf ├── upduino2.pcf ├── verilator_waiver.vlt └── zcu106.xdc ├── doc ├── .nojekyll ├── Makefile ├── conf.py ├── datasheet.rst ├── index.rst ├── interface.rst ├── internals.rst ├── life_cycle.png ├── make.bat ├── modules.rst ├── overview.rst ├── requirements.txt ├── reservoir.rst ├── serv_alu.png ├── serv_alu_int.png ├── serv_bufreg.png ├── serv_bufreg2.png ├── serv_bufreg2_int.png ├── serv_bufreg_int.png ├── serv_csr.png ├── serv_csr_int.png ├── serv_ctrl.png ├── serv_ctrl_int.png ├── serv_dataflow.png ├── serv_decode.png ├── serv_decode_int.png ├── serv_immdec.png ├── serv_immdec_int.png ├── serv_mem_if.png ├── serv_mem_if_int.png ├── serv_rf_if.png ├── serv_rf_if_int.png ├── serv_rf_top.png ├── serv_top.png ├── servant.png ├── servant.rst ├── servile.png ├── servile.rst ├── servile_int.png ├── serving.png ├── serving.rst ├── subservient.png └── subservient.rst ├── rtl ├── serv_aligner.v ├── serv_alu.v ├── serv_bufreg.v ├── serv_bufreg2.v ├── serv_compdec.v ├── serv_csr.v ├── serv_ctrl.v ├── serv_debug.v ├── serv_decode.v ├── serv_immdec.v ├── serv_mem_if.v ├── serv_rf_if.v ├── serv_rf_ram.v ├── serv_rf_ram_if.v ├── serv_rf_top.v ├── serv_state.v ├── serv_synth_wrapper.v └── serv_top.v ├── serv.core ├── servant.core ├── servant ├── ecp5_evn_pll.v ├── ecppll.v ├── ice40_pll.v ├── servant.v ├── servant_ac701.v ├── servant_ax309.v ├── servant_ax309_clock_gen.v ├── servant_cmod_a7.v ├── servant_cmod_a7_clock_gen.v ├── servant_ecp5.v ├── servant_ecp5_clock_gen.v ├── servant_ecp5_evn.v ├── servant_ecp5_evn_clock_gen.v ├── servant_gmm7550.v ├── servant_gpio.v ├── servant_lx9.v ├── servant_lx9_clock_gen.v ├── servant_md_kolibri.v ├── servant_mux.v ├── servant_orangecrab.v ├── servant_pf.v ├── servant_pf_clock_gen.v ├── servant_ram.v ├── servant_ram_quartus.sv ├── servant_te0802.v ├── servant_te0802_clock_gen.v ├── servant_timer.v ├── servant_upduino2.v ├── servax.v ├── servax_clock_gen.v ├── servclone10.v ├── servclone10_clock_gen.v ├── servde1_soc_revF.v ├── servde1_soc_revF_clock_gen.v ├── service.v ├── service_clock_gen.v ├── service_go_board.v ├── servis.v ├── servis_clock_gen.v ├── servive.v ├── servive_clock_gen.v ├── servix.v ├── servix_clock_gen.v ├── servix_ebaz4205.v ├── servix_ebaz4205_clock_gen.v ├── servus.v └── servus_clock_gen.v ├── servile.core ├── servile ├── servile.v ├── servile_arbiter.v ├── servile_mux.v └── servile_rf_mem_if.v ├── serving.core ├── serving ├── serving.v └── serving_ram.v ├── sw ├── Makefile ├── blinky.S ├── blinky.hex ├── hello_uart.S ├── hello_uart.hex ├── link.ld ├── makehex.py ├── zephyr_hello.hex ├── zephyr_hello_mt.hex ├── zephyr_phil.hex └── zephyr_sync.hex ├── verif ├── Readme.md ├── bin │ ├── Readme.md │ └── sail-riscv.tar.gz ├── config.ini ├── plugin-sail_cSim │ ├── env │ │ ├── link.ld │ │ └── model_test.h │ └── riscof_sail_cSim.py └── plugin-serv │ ├── env │ ├── link.ld │ └── model_test.h │ ├── riscof_serv.py │ ├── serv_isa.yaml │ └── serv_platform.yaml ├── west.yml └── zephyr ├── CMakeLists.txt ├── Kconfig ├── boards └── riscv │ └── service │ ├── Kconfig.board │ ├── Kconfig.defconfig │ ├── board.h │ ├── service.dts │ ├── service.yaml │ └── service_defconfig ├── drivers ├── CMakeLists.txt ├── Kconfig ├── serial │ ├── CMakeLists.txt │ ├── Kconfig │ └── uart_bitbang.c └── timer │ ├── CMakeLists.txt │ ├── Kconfig │ └── serv_timer.c ├── dts └── riscv │ └── serv.dtsi ├── module.yml └── soc └── riscv └── servant ├── CMakeLists.txt ├── Kconfig.defconfig ├── Kconfig.soc ├── cpu_idle.c ├── irq.c ├── linker.ld ├── soc.h ├── soc_common.h ├── soc_irq.S └── vector.S /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: Run compliance test suite 2 | 3 | on: [push, pull_request] 4 | 5 | jobs: 6 | compliance: 7 | name: RISC-V Compliance Test 8 | runs-on: ubuntu-22.04 9 | 10 | steps: 11 | - uses: actions/checkout@v4 12 | with: 13 | path: serv 14 | 15 | - name: install fusesoc, verilator, gcc and riscof 16 | run: | 17 | sudo apt-get install -y python3-setuptools verilator 18 | pip3 install fusesoc 19 | pip3 install riscof 20 | 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 21 | echo $GITHUB_WORKSPACE/riscv/bin >> $GITHUB_PATH 22 | 23 | 24 | - name: set root and SERV directory 25 | run: | 26 | echo "SERV=$GITHUB_WORKSPACE/serv" >> $GITHUB_ENV 27 | 28 | - name: setup workspace 29 | run: fusesoc library add serv $SERV 30 | 31 | - name: Setup SAIL-RISCV Model 32 | run: | 33 | tar -xzf $SERV/verif/bin/sail-riscv.tar.gz 34 | echo $GITHUB_WORKSPACE/sail-riscv >> $GITHUB_PATH 35 | 36 | - name: Init arch tests 37 | run: riscof arch-test --clone 38 | 39 | - name: Run RV32I compliance tests 40 | 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 41 | 42 | - name: Run RV32IM compliance tests 43 | 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 44 | 45 | - name: Run RV32IC compliance tests 46 | 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 47 | 48 | - name: Run RV32I Zifencei compliance tests 49 | 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 50 | 51 | - name: Run RV32I Privilege compliance tests 52 | 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 53 | -------------------------------------------------------------------------------- /.github/workflows/formal.yml: -------------------------------------------------------------------------------- 1 | name: Formal verification 2 | 3 | on: [push] 4 | jobs: 5 | formal: 6 | name: Run RISCV-formal verification suite 7 | runs-on: ubuntu-latest 8 | steps: 9 | - name: Checkout riscv-formal 10 | uses: actions/checkout@v4 11 | with: 12 | repository: YosysHQ/riscv-formal 13 | - name: Checkout SERV 14 | uses: actions/checkout@v4 15 | with: 16 | path: cores/serv/serv-src 17 | - uses: YosysHQ/setup-oss-cad-suite@v3 18 | with: 19 | github-token: ${{ secrets.GITHUB_TOKEN }} 20 | - name: Prepare formal tests 21 | run: | 22 | cd cores/serv 23 | python3 ../../checks/genchecks.py 24 | # Skip non-instruction tests for now 25 | # - run: make -C cores/serv/checks causal_ch0 26 | # - run: make -C cores/serv/checks liveness_ch0 27 | # - run: make -C cores/serv/checks pc_bwd_ch0 28 | # - run: make -C cores/serv/checks pc_fwd_ch0 29 | # - run: make -C cores/serv/checks reg_ch0 30 | # - run: make -C cores/serv/checks unique_ch0 31 | - run: make -C cores/serv/checks insn_add_ch0 32 | - run: make -C cores/serv/checks insn_addi_ch0 33 | - run: make -C cores/serv/checks insn_and_ch0 34 | - run: make -C cores/serv/checks insn_andi_ch0 35 | - run: make -C cores/serv/checks insn_auipc_ch0 36 | - run: make -C cores/serv/checks insn_beq_ch0 37 | - run: make -C cores/serv/checks insn_bge_ch0 38 | - run: make -C cores/serv/checks insn_bgeu_ch0 39 | - run: make -C cores/serv/checks insn_blt_ch0 40 | - run: make -C cores/serv/checks insn_bltu_ch0 41 | - run: make -C cores/serv/checks insn_bne_ch0 42 | - run: make -C cores/serv/checks insn_jal_ch0 43 | - run: make -C cores/serv/checks insn_jalr_ch0 44 | - run: make -C cores/serv/checks insn_lb_ch0 45 | - run: make -C cores/serv/checks insn_lbu_ch0 46 | - run: make -C cores/serv/checks insn_lh_ch0 47 | - run: make -C cores/serv/checks insn_lhu_ch0 48 | - run: make -C cores/serv/checks insn_lui_ch0 49 | - run: make -C cores/serv/checks insn_lw_ch0 50 | - run: make -C cores/serv/checks insn_or_ch0 51 | - run: make -C cores/serv/checks insn_ori_ch0 52 | - run: make -C cores/serv/checks insn_sb_ch0 53 | - run: make -C cores/serv/checks insn_sh_ch0 54 | - run: make -C cores/serv/checks insn_sll_ch0 55 | - run: make -C cores/serv/checks insn_slli_ch0 56 | - run: make -C cores/serv/checks insn_slt_ch0 57 | - run: make -C cores/serv/checks insn_slti_ch0 58 | - run: make -C cores/serv/checks insn_sltiu_ch0 59 | - run: make -C cores/serv/checks insn_sltu_ch0 60 | - run: make -C cores/serv/checks insn_sra_ch0 61 | - run: make -C cores/serv/checks insn_srai_ch0 62 | - run: make -C cores/serv/checks insn_srl_ch0 63 | - run: make -C cores/serv/checks insn_srli_ch0 64 | - run: make -C cores/serv/checks insn_sub_ch0 65 | - run: make -C cores/serv/checks insn_sw_ch0 66 | - run: make -C cores/serv/checks insn_xor_ch0 67 | - run: make -C cores/serv/checks insn_xori_ch0 68 | -------------------------------------------------------------------------------- /.github/workflows/lint.yml: -------------------------------------------------------------------------------- 1 | name: Run linter 2 | 3 | on: [push, pull_request] 4 | 5 | jobs: 6 | lint: 7 | runs-on: ubuntu-latest 8 | strategy: 9 | matrix: 10 | width: [1, 4] 11 | name: Linter 12 | env: 13 | REPO : serv 14 | VLNV : serv 15 | steps: 16 | - name: Checkout repo 17 | uses: actions/checkout@v4 18 | with: 19 | path: serv 20 | - run: sudo apt install verilator 21 | - run: pip3 install fusesoc 22 | - run: fusesoc library add $REPO $GITHUB_WORKSPACE/$REPO 23 | - run: fusesoc run --target=lint $VLNV --W=${{ matrix.width }} 24 | - run: fusesoc run --target=lint servant --width=${{ matrix.width }} 25 | - run: fusesoc run --target=lint serving 26 | -------------------------------------------------------------------------------- /.github/workflows/openlane.yml: -------------------------------------------------------------------------------- 1 | name: Build GDS using OpenLANE and sky130 PDK 2 | 3 | on: [push] 4 | jobs: 5 | build-openlane-sky130: 6 | runs-on: ubuntu-latest 7 | env: 8 | REPO : serv 9 | VLNV : serv 10 | steps: 11 | - name: Checkout repo 12 | uses: actions/checkout@v4 13 | with: 14 | path: serv 15 | - run: echo "EDALIZE_LAUNCHER=el_docker" >> $GITHUB_ENV 16 | - run: pip3 install fusesoc 17 | - run: fusesoc library add $REPO $GITHUB_WORKSPACE/$REPO 18 | - run: fusesoc run --target=sky130 $VLNV 19 | - run: find -name *.gds 20 | - name: Store artifacts 21 | uses: actions/upload-artifact@v4 22 | with: 23 | name: serv.gds 24 | 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 25 | -------------------------------------------------------------------------------- /.github/workflows/pages.yml: -------------------------------------------------------------------------------- 1 | name: Build documentation 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | 8 | jobs: 9 | docs: 10 | name: Build documentation 11 | runs-on: ubuntu-latest 12 | steps: 13 | - name: Checkout 14 | uses: actions/checkout@v4 15 | - name: Set up Python 16 | uses: actions/setup-python@v1 17 | - name: Install dependencies 18 | run: | 19 | python3 -m pip install --upgrade pip 20 | pip install -r doc/requirements.txt 21 | - name: Build sphinx documentation 22 | run: | 23 | make -C doc html 24 | - name: Deploy to gh-pages 25 | uses: JamesIves/github-pages-deploy-action@4.1.1 26 | with: 27 | branch: gh-pages # The branch the action should deploy to. 28 | folder: doc/_build/html # The folder the action should deploy. 29 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/olofk/serv/a72c1e8737d424c31bf6ff909795acc37aa4cc90/.gitmodules -------------------------------------------------------------------------------- /.readthedocs.yml: -------------------------------------------------------------------------------- 1 | # Read the Docs configuration file 2 | # See https://docs.readthedocs.io/en/stable/config-file/v2.html for details 3 | 4 | version: 2 5 | 6 | sphinx: 7 | configuration: doc/conf.py 8 | 9 | python: 10 | install: 11 | - requirements: doc/requirements.txt 12 | 13 | build: 14 | os: "ubuntu-22.04" 15 | tools: 16 | python: "3.11" 17 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | ISC License 2 | 3 | Copyright 2019, Olof Kindgren 4 | 5 | Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -------------------------------------------------------------------------------- /NEWS: -------------------------------------------------------------------------------- 1 | 1.3.0 2024-07-05 Olof Kindgren 2 | ====================================================== 3 | 4 | * Zephyr BSP: Port to Zephyr 3.5.0 + support tickless timer 5 | * Make RF RAM IF work with single-port RAM 6 | * Add PC tracing 7 | * Make most modules width-independent 8 | * Avoid releasing trap signal too early 9 | * Improve timer wraparound behavior 10 | * Overhaul documentation 11 | * Add Servile convenience wrapper component 12 | * Base Serving and Serving on Servile 13 | * Add simulation cycle counter to testbench 14 | * Add Hello world ASM example for Servant 15 | * New Servant ports: Arty S7-50, PolarFire Splash Kit, Machdyne Kolibri, GMM-7550, Alchistry AU, ECP5 Evaluation board, Terasic DE1 SoC 16 | 17 | 1.2.1 2022-12-25 Olof Kindgren 18 | ====================================================== 19 | 20 | * Guarantee at least 2 cycles of o_rst after ice40 PLL is locked 21 | * New Servant ports: ICE-V Wireless 22 | * Add reset input for Arty A7 23 | * Add Servant documentation 24 | * Updated RISC-V Compliance support from 2.7.4 to 3.x 25 | 26 | 1.2.0 2022-07-25 Olof Kindgren 27 | ====================================================== 28 | 29 | * New Servant ports: EBAZ4205, Chameleon96, Nexys2, Alinx AX309 30 | * Support for M ISA extension 31 | * Support for C ISA extension 32 | * Fix occasionally wrong sign on immediates 33 | * Support for producing GDS with OpenLANE 34 | * Fix Model/QuestaSim compatibility 35 | * Add ViDBo support 36 | * Improved documentation 37 | * Less resource usage 38 | * Updated RISC-V Compliance support from 1.0 to 2.7.4 39 | -------------------------------------------------------------------------------- /bench/servant_sim.v: -------------------------------------------------------------------------------- 1 | `default_nettype none 2 | module servant_sim 3 | (input wire wb_clk, 4 | input wire wb_rst, 5 | output wire [31:0] pc_adr, 6 | output wire pc_vld, 7 | output wire q); 8 | 9 | parameter memfile = ""; 10 | parameter memsize = 8192; 11 | parameter width = 1; 12 | parameter with_csr = 1; 13 | parameter compressed = 0; 14 | parameter align = compressed; 15 | 16 | reg [1023:0] firmware_file; 17 | initial 18 | if ($value$plusargs("firmware=%s", firmware_file)) begin 19 | $display("Loading RAM from %0s", firmware_file); 20 | $readmemh(firmware_file, dut.ram.mem); 21 | end 22 | 23 | servant 24 | #(.memfile (memfile), 25 | .memsize (memsize), 26 | .width (width), 27 | .debug (1'b1), 28 | .sim (1), 29 | .with_csr (with_csr), 30 | .compress (compressed[0:0]), 31 | .align (align[0:0])) 32 | dut(wb_clk, wb_rst, q); 33 | 34 | assign pc_adr = dut.wb_mem_adr; 35 | assign pc_vld = dut.wb_mem_ack; 36 | 37 | endmodule 38 | -------------------------------------------------------------------------------- /bench/servant_tb.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "verilated_vcd_c.h" 6 | #include "Vservant_sim.h" 7 | 8 | #include 9 | 10 | using namespace std; 11 | 12 | static bool done; 13 | 14 | vluint64_t main_time = 0; // Current simulation time 15 | // This is a 64-bit integer to reduce wrap over issues and 16 | // allow modulus. You can also use a double, if you wish. 17 | 18 | double sc_time_stamp () { // Called by $time in Verilog 19 | return main_time; // converts to double, to match 20 | // what SystemC does 21 | } 22 | 23 | void INThandler(int signal) 24 | { 25 | printf("\nCaught ctrl-c\n"); 26 | done = true; 27 | } 28 | 29 | typedef struct { 30 | bool last_value; 31 | } gpio_context_t; 32 | 33 | void do_gpio(gpio_context_t *context, bool gpio) { 34 | if (context->last_value != gpio) { 35 | context->last_value = gpio; 36 | printf("%lu output q is %s\n", main_time, gpio ? "ON" : "OFF"); 37 | } 38 | } 39 | 40 | typedef struct { 41 | uint8_t state; 42 | char ch; 43 | uint32_t baud_t; 44 | vluint64_t last_update; 45 | } uart_context_t; 46 | 47 | void uart_init(uart_context_t *context, uint32_t baud_rate) { 48 | context->baud_t = 1000*1000*1000/baud_rate; 49 | context->state = 0; 50 | } 51 | 52 | bool do_uart(uart_context_t *context, bool rx) { 53 | if (context->state == 0) { 54 | if (rx) 55 | context->state++; 56 | } 57 | else if (context->state == 1) { 58 | if (!rx) { 59 | context->last_update = main_time + context->baud_t/2; 60 | context->state++; 61 | } 62 | } 63 | else if(context->state == 2) { 64 | if (main_time > context->last_update) { 65 | context->last_update += context->baud_t; 66 | context->ch = 0; 67 | context->state++; 68 | } 69 | } 70 | else if (context->state < 11) { 71 | if (main_time > context->last_update) { 72 | context->last_update += context->baud_t; 73 | context->ch |= rx << (context->state-3); 74 | context->state++; 75 | } 76 | } 77 | else { 78 | if (main_time > context->last_update) { 79 | context->last_update += context->baud_t; 80 | context->state=1; 81 | return true; 82 | } 83 | } 84 | return false; 85 | } 86 | 87 | int main(int argc, char **argv, char **env) 88 | { 89 | int baud_rate = 0; 90 | 91 | gpio_context_t gpio_context; 92 | uart_context_t uart_context; 93 | Verilated::commandArgs(argc, argv); 94 | 95 | Vservant_sim* top = new Vservant_sim; 96 | 97 | const char *arg = Verilated::commandArgsPlusMatch("uart_baudrate="); 98 | if (arg[0]) { 99 | baud_rate = atoi(arg+15); 100 | if (baud_rate) { 101 | uart_init(&uart_context, baud_rate); 102 | } 103 | } 104 | 105 | VerilatedVcdC * tfp = 0; 106 | const char *vcd = Verilated::commandArgsPlusMatch("vcd="); 107 | if (vcd[0]) { 108 | Verilated::traceEverOn(true); 109 | tfp = new VerilatedVcdC; 110 | top->trace (tfp, 99); 111 | tfp->open ("trace.vcd"); 112 | } 113 | 114 | signal(SIGINT, INThandler); 115 | 116 | int tf = 0; 117 | const char *arg_trace_pc = Verilated::commandArgsPlusMatch("trace_pc="); 118 | if (arg_trace_pc[0]) 119 | tf = open("trace.bin", O_WRONLY | O_CREAT | O_TRUNC, S_IRWXU); 120 | 121 | vluint64_t timeout = 0; 122 | const char *arg_timeout = Verilated::commandArgsPlusMatch("timeout="); 123 | if (arg_timeout[0]) 124 | timeout = atoi(arg_timeout+9); 125 | 126 | vluint64_t vcd_start = 0; 127 | const char *arg_vcd_start = Verilated::commandArgsPlusMatch("vcd_start="); 128 | if (arg_vcd_start[0]) 129 | vcd_start = atoi(arg_vcd_start+11); 130 | 131 | int cur_cycle = 0; 132 | int last_cycle = 0; 133 | std::time_t last_time = std::time(nullptr); 134 | int cps_file = 0; 135 | const char *arg_cps = Verilated::commandArgsPlusMatch("cps="); 136 | if (arg_cps[0]) 137 | cps_file = open("cps", O_WRONLY | O_CREAT | O_TRUNC, S_IRWXU); 138 | 139 | bool dump = false; 140 | top->wb_clk = 1; 141 | bool q = top->q; 142 | while (!(done || Verilated::gotFinish())) { 143 | if (tfp && !dump && (main_time > vcd_start)) { 144 | dump = true; 145 | } 146 | top->wb_rst = main_time < 100; 147 | top->eval(); 148 | if (dump) 149 | tfp->dump(main_time); 150 | if (baud_rate) { 151 | if (do_uart(&uart_context, top->q)) 152 | putchar(uart_context.ch); 153 | } else { 154 | do_gpio(&gpio_context, top->q); 155 | } 156 | if (tf && top->wb_clk && top->pc_vld) 157 | if (write(tf, (void *)&top->pc_adr, 4) < 0) exit(1); 158 | if (timeout && (main_time >= timeout)) { 159 | printf("Timeout: Exiting at time %lu\n", main_time); 160 | done = true; 161 | } 162 | 163 | top->wb_clk = !top->wb_clk; 164 | main_time+=31.25; 165 | 166 | if (cps_file) { 167 | cur_cycle++; 168 | if (std::time(nullptr) > last_time) { 169 | dprintf(cps_file,"%d\n", (cur_cycle-last_cycle)/2); 170 | last_cycle = cur_cycle; 171 | last_time++; 172 | } 173 | } 174 | } 175 | close(cps_file); 176 | close(tf); 177 | if (tfp) 178 | tfp->close(); 179 | exit(0); 180 | } 181 | -------------------------------------------------------------------------------- /bench/servant_tb.v: -------------------------------------------------------------------------------- 1 | `default_nettype none 2 | module servant_tb; 3 | 4 | parameter memfile = "hello_uart.hex"; 5 | parameter memsize = 8192; 6 | parameter width = 1; 7 | parameter with_csr = 1; 8 | 9 | localparam baud_rate = 10 | (width == 4) ? 57600*3 : 11 | 57600; 12 | 13 | reg wb_clk = 1'b0; 14 | reg wb_rst = 1'b1; 15 | 16 | wire q; 17 | 18 | always #31 wb_clk <= !wb_clk; 19 | initial #62 wb_rst <= 1'b0; 20 | 21 | vlog_tb_utils vtu(); 22 | 23 | uart_decoder #(baud_rate) uart_decoder (q); 24 | 25 | servant_sim 26 | #(.memfile (memfile), 27 | .memsize (memsize), 28 | .width (width), 29 | .with_csr (with_csr)) 30 | dut 31 | (.wb_clk (wb_clk), 32 | .wb_rst (wb_rst), 33 | .pc_adr (), 34 | .pc_vld (), 35 | .q (q)); 36 | 37 | endmodule 38 | -------------------------------------------------------------------------------- /bench/servant_tb_vidbo.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "verilated_vcd_c.h" 5 | #include "Vservant_sim.h" 6 | 7 | #include "vidbo.h" 8 | 9 | using namespace std; 10 | 11 | static bool done; 12 | 13 | vluint64_t main_time = 0; // Current simulation time 14 | // This is a 64-bit integer to reduce wrap over issues and 15 | // allow modulus. You can also use a double, if you wish. 16 | 17 | double sc_time_stamp () { // Called by $time in Verilog 18 | return main_time; // converts to double, to match 19 | // what SystemC does 20 | } 21 | 22 | void INThandler(int signal) 23 | { 24 | printf("\nCaught ctrl-c\n"); 25 | done = true; 26 | } 27 | 28 | typedef struct { 29 | bool last_value; 30 | } gpio_context_t; 31 | 32 | void do_gpio(gpio_context_t *context, bool gpio) { 33 | if (context->last_value != gpio) { 34 | context->last_value = gpio; 35 | printf("%lu output q is %s\n", main_time, gpio ? "ON" : "OFF"); 36 | } 37 | } 38 | 39 | typedef struct { 40 | uint8_t state; 41 | char ch; 42 | uint32_t baud_t; 43 | vluint64_t last_update; 44 | } uart_context_t; 45 | 46 | void uart_init(uart_context_t *context, uint32_t baud_rate) { 47 | context->baud_t = 1000*1000*1000/baud_rate; 48 | context->state = 0; 49 | } 50 | 51 | bool do_uart(uart_context_t *context, bool rx) { 52 | if (context->state == 0) { 53 | if (rx) 54 | context->state++; 55 | } 56 | else if (context->state == 1) { 57 | if (!rx) { 58 | context->last_update = main_time + context->baud_t/2; 59 | context->state++; 60 | } 61 | } 62 | else if(context->state == 2) { 63 | if (main_time > context->last_update) { 64 | context->last_update += context->baud_t; 65 | context->ch = 0; 66 | context->state++; 67 | } 68 | } 69 | else if (context->state < 11) { 70 | if (main_time > context->last_update) { 71 | context->last_update += context->baud_t; 72 | context->ch |= rx << (context->state-3); 73 | context->state++; 74 | } 75 | } 76 | else { 77 | if (main_time > context->last_update) { 78 | context->last_update += context->baud_t; 79 | context->state=1; 80 | return true; 81 | } 82 | } 83 | return false; 84 | } 85 | 86 | int main(int argc, char **argv, char **env) 87 | { 88 | int baud_rate = 0; 89 | 90 | gpio_context_t gpio_context; 91 | uart_context_t uart_context; 92 | 93 | vidbo_context_t vidbo_context; 94 | vidbo_init(&vidbo_context, 8081); 95 | int poll_vidbo = 0; 96 | 97 | Verilated::commandArgs(argc, argv); 98 | 99 | Vservant_sim* top = new Vservant_sim; 100 | 101 | const char *arg = Verilated::commandArgsPlusMatch("uart_baudrate="); 102 | if (arg[0]) { 103 | baud_rate = atoi(arg+15); 104 | if (baud_rate) { 105 | uart_init(&uart_context, baud_rate); 106 | } 107 | } 108 | 109 | VerilatedVcdC * tfp = 0; 110 | const char *vcd = Verilated::commandArgsPlusMatch("vcd="); 111 | if (vcd[0]) { 112 | Verilated::traceEverOn(true); 113 | tfp = new VerilatedVcdC; 114 | top->trace (tfp, 99); 115 | tfp->open ("trace.vcd"); 116 | } 117 | 118 | signal(SIGINT, INThandler); 119 | 120 | vluint64_t timeout = 0; 121 | const char *arg_timeout = Verilated::commandArgsPlusMatch("timeout="); 122 | if (arg_timeout[0]) 123 | timeout = atoi(arg_timeout+9); 124 | 125 | vluint64_t vcd_start = 0; 126 | const char *arg_vcd_start = Verilated::commandArgsPlusMatch("vcd_start="); 127 | if (arg_vcd_start[0]) 128 | vcd_start = atoi(arg_vcd_start+11); 129 | 130 | bool dump = false; 131 | top->wb_clk = 1; 132 | bool q = top->q; 133 | while (!(done || Verilated::gotFinish())) { 134 | if (tfp && !dump && (main_time > vcd_start)) { 135 | dump = true; 136 | } 137 | top->wb_rst = main_time < 100; 138 | top->eval(); 139 | if (dump) 140 | tfp->dump(main_time); 141 | if (baud_rate) { 142 | if (do_uart(&uart_context, top->q)) 143 | vidbo_send(&vidbo_context, main_time, "serial", "uart", uart_context.ch); 144 | } 145 | if (top->q != gpio_context.last_value) { 146 | vidbo_send(&vidbo_context, main_time, "gpio", "LD0", (top->q) & 0x1); 147 | gpio_context.last_value = top->q; 148 | } 149 | if (timeout && (main_time >= timeout)) { 150 | printf("Timeout: Exiting at time %lu\n", main_time); 151 | done = true; 152 | } 153 | 154 | if (!(poll_vidbo++ % 100000)) vidbo_recv(&vidbo_context, 0); 155 | 156 | top->wb_clk = !top->wb_clk; 157 | main_time+=31.25; 158 | 159 | } 160 | if (tfp) 161 | tfp->close(); 162 | exit(0); 163 | } 164 | -------------------------------------------------------------------------------- /bench/uart_decoder.v: -------------------------------------------------------------------------------- 1 | module uart_decoder 2 | #(parameter BAUD_RATE = 115200) 3 | (input rx); 4 | 5 | localparam T = 1000000000/BAUD_RATE; 6 | 7 | integer i; 8 | reg [7:0] ch; 9 | 10 | initial forever begin 11 | @(negedge rx); 12 | #(T/2) ch = 0; 13 | for (i=0;i<8;i=i+1) 14 | #T ch[i] = rx; 15 | $write("%c",ch); 16 | $fflush; 17 | end 18 | endmodule 19 | -------------------------------------------------------------------------------- /data/ac701.xdc: -------------------------------------------------------------------------------- 1 | ## Clock signal 2 | set_property IOSTANDARD DIFF_SSTL15 [get_ports sys_clk_p] 3 | set_property PACKAGE_PIN P3 [get_ports sys_clk_n] 4 | set_property PACKAGE_PIN R3 [get_ports sys_clk_p] 5 | set_property IOSTANDARD DIFF_SSTL15 [get_ports sys_clk_n] 6 | 7 | create_clock -period 5.000 -name clk_p [get_nets sys_clk_p] 8 | 9 | ## UART TX 10 | set_property PACKAGE_PIN U19 [get_ports q] 11 | set_property IOSTANDARD LVCMOS18 [get_ports q] 12 | -------------------------------------------------------------------------------- /data/alchitry_au.xdc: -------------------------------------------------------------------------------- 1 | ## Clock signal 2 | set_property -dict { PACKAGE_PIN N14 IOSTANDARD LVCMOS33 } [get_ports i_clk]; 3 | create_clock -add -name sys_clk_pin -period 10.00 -waveform {0 5} [get_ports i_clk]; 4 | 5 | ## Reset 6 | set_property -dict {PACKAGE_PIN P6 IOSTANDARD LVCMOS33 } [get_ports i_rst_n]; 7 | 8 | ## LED 9 | ## set_property -dict { PACKAGE_PIN L14 IOSTANDARD LVCMOS33 } [get_ports q]; 10 | 11 | ## USB Serial output 12 | set_property -dict { PACKAGE_PIN P16 IOSTANDARD LVCMOS33 } [get_ports q] 13 | 14 | set_property CONFIG_VOLTAGE 3.3 [current_design] 15 | set_property CFGBVS VCCO [current_design] 16 | 17 | -------------------------------------------------------------------------------- /data/alhambra.pcf: -------------------------------------------------------------------------------- 1 | # 12 MHz clock 2 | set_io i_clk 49 3 | 4 | # RS232 5 | set_io q 61 6 | -------------------------------------------------------------------------------- /data/arty_a7_35t.xdc: -------------------------------------------------------------------------------- 1 | set_property -dict {PACKAGE_PIN E3 IOSTANDARD LVCMOS33 } [get_ports i_clk]; 2 | 3 | set_property -dict {PACKAGE_PIN C2 IOSTANDARD LVCMOS33 } [get_ports i_rst_n]; 4 | 5 | set_property -dict {PACKAGE_PIN D10 IOSTANDARD LVCMOS33 } [get_ports q] 6 | 7 | #set_property -dict {PACKAGE_PIN H5 IOSTANDARD LVCMOS33 } [get_ports q] 8 | 9 | set_property CFGBVS VCCO [current_design] 10 | set_property CONFIG_VOLTAGE 3.3 [current_design] 11 | 12 | create_clock -add -name sys_clk_pin -period 10.00 -waveform {0 5} [get_ports i_clk]; 13 | -------------------------------------------------------------------------------- /data/arty_s7_50t.xdc: -------------------------------------------------------------------------------- 1 | set_property -dict { PACKAGE_PIN R2 IOSTANDARD SSTL135 } [get_ports i_clk]; #IO_L12P_T1_MRCC_34 Sch=ddr3_clk[200] 2 | set_property -dict { PACKAGE_PIN C18 IOSTANDARD LVCMOS33 } [get_ports i_rst_n]; #IO_L11N_T1_SRCC_15 3 | 4 | set_property -dict { PACKAGE_PIN R12 IOSTANDARD LVCMOS33 } [get_ports q]; #IO_25_14 Sch=uart_rxd_out 5 | #set_property -dict { PACKAGE_PIN E18 IOSTANDARD LVCMOS33 } [get_ports q]; #IO_L16N_T2_A27_15 Sch=led[2] 6 | 7 | set_property CFGBVS VCCO [current_design] 8 | set_property CONFIG_VOLTAGE 3.3 [current_design] 9 | 10 | create_clock -add -name sys_clk_pin -period 10.00 -waveform {0 5} [get_ports i_clk]; 11 | -------------------------------------------------------------------------------- /data/ax309.ucf: -------------------------------------------------------------------------------- 1 | CONFIG VCCAUX=3.3; 2 | 3 | NET i_clk LOC = T8 | IOSTANDARD = LVCMOS33; 4 | NET i_rst LOC = L3 | IOSTANDARD = LVCMOS33; 5 | NET q LOC = P4 | IOSTANDARD = LVCMOS33; 6 | NET o_uart_tx LOC = D12 | IOSTANDARD = LVCMOS33; 7 | 8 | NET i_clk TNM_NET = sys_clk_pin; 9 | TIMESPEC TS_USER_CLOCK = PERIOD sys_clk_pin 50000 kHz; 10 | -------------------------------------------------------------------------------- /data/chameleon96/CV_96.v: -------------------------------------------------------------------------------- 1 | 2 | module CV_96 ( 3 | output q, 4 | output uart_txd 5 | ); 6 | 7 | wire clk; 8 | 9 | HPS u0( 10 | .h2f_user0_clk( clk) //hps_0_h2f_user0_clock.clk 11 | ); 12 | 13 | 14 | servive u1 ( 15 | .i_clk ( clk ), 16 | .i_rst_n ( 1'b1), 17 | .q ( q ), 18 | .uart_txd( uart_txd ) 19 | ); 20 | 21 | 22 | endmodule 23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /data/chameleon96/HPS.sv: -------------------------------------------------------------------------------- 1 | 2 | module HPS( 3 | output wire [1 - 1 : 0 ] h2f_rst_n 4 | ,output wire [1 - 1 : 0 ] h2f_user0_clk 5 | ); 6 | 7 | 8 | cyclonev_hps_interface_clocks_resets clocks_resets( 9 | .f2h_pending_rst_ack({ 10 | 1'b1 // 0:0 11 | }) 12 | ,.f2h_warm_rst_req_n({ 13 | 1'b1 // 0:0 14 | }) 15 | ,.f2h_dbg_rst_req_n({ 16 | 1'b1 // 0:0 17 | }) 18 | ,.h2f_rst_n({ 19 | h2f_rst_n[0:0] // 0:0 20 | }) 21 | ,.f2h_cold_rst_req_n({ 22 | 1'b1 // 0:0 23 | }) 24 | ,.h2f_user0_clk({ 25 | h2f_user0_clk[0:0] // 0:0 26 | }) 27 | ); 28 | 29 | 30 | cyclonev_hps_interface_dbg_apb debug_apb( 31 | .DBG_APB_DISABLE({ 32 | 1'b0 // 0:0 33 | }) 34 | ,.P_CLK_EN({ 35 | 1'b0 // 0:0 36 | }) 37 | ); 38 | 39 | 40 | cyclonev_hps_interface_tpiu_trace tpiu( 41 | .traceclk_ctl({ 42 | 1'b1 // 0:0 43 | }) 44 | ); 45 | 46 | 47 | cyclonev_hps_interface_boot_from_fpga boot_from_fpga( 48 | .boot_from_fpga_ready({ 49 | 1'b0 // 0:0 50 | }) 51 | ,.boot_from_fpga_on_failure({ 52 | 1'b0 // 0:0 53 | }) 54 | ,.bsel_en({ 55 | 1'b0 // 0:0 56 | }) 57 | ,.csel_en({ 58 | 1'b0 // 0:0 59 | }) 60 | ,.csel({ 61 | 2'b01 // 1:0 62 | }) 63 | ,.bsel({ 64 | 3'b001 // 2:0 65 | }) 66 | ); 67 | 68 | 69 | cyclonev_hps_interface_fpga2hps fpga2hps( 70 | .port_size_config({ 71 | 2'b11 // 1:0 72 | }) 73 | ); 74 | 75 | 76 | cyclonev_hps_interface_hps2fpga hps2fpga( 77 | .port_size_config({ 78 | 2'b11 // 1:0 79 | }) 80 | ); 81 | 82 | 83 | cyclonev_hps_interface_fpga2sdram f2sdram( 84 | .cfg_cport_rfifo_map({ 85 | 18'b000000000000000000 // 17:0 86 | }) 87 | ,.cfg_axi_mm_select({ 88 | 6'b000000 // 5:0 89 | }) 90 | ,.cfg_wfifo_cport_map({ 91 | 16'b0000000000000000 // 15:0 92 | }) 93 | ,.cfg_cport_type({ 94 | 12'b000000000000 // 11:0 95 | }) 96 | ,.cfg_rfifo_cport_map({ 97 | 16'b0000000000000000 // 15:0 98 | }) 99 | ,.cfg_port_width({ 100 | 12'b000000000000 // 11:0 101 | }) 102 | ,.cfg_cport_wfifo_map({ 103 | 18'b000000000000000000 // 17:0 104 | }) 105 | ); 106 | 107 | endmodule 108 | 109 | -------------------------------------------------------------------------------- /data/chameleon96/chain1.cdf: -------------------------------------------------------------------------------- 1 | /* Quartus Prime Version 17.1.0 Build 590 10/25/2017 SJ Lite Edition */ 2 | JedecChain; 3 | FileRevision(JESD32A); 4 | DefaultMfr(6E); 5 | 6 | P ActionCode(Ign) 7 | Device PartName(SOCVHPS) MfrSpec(OpMask(0)); 8 | P ActionCode(Cfg) 9 | Device PartName(5CSEBA6U19) Path("/home/jordi/bin/fusesoc/build/fusesoc_utils_blinky_1.1/chameleon96-quartus/") File("fusesoc_utils_blinky_1_1.sof") MfrSpec(OpMask(1)); 10 | 11 | ChainEnd; 12 | 13 | AlteraBegin; 14 | ChainType(JTAG); 15 | AlteraEnd; 16 | -------------------------------------------------------------------------------- /data/chameleon96/chameleon96.sdc: -------------------------------------------------------------------------------- 1 | # Main system clock (100 Mhz) 2 | create_clock -name "clk" -period 10.000ns [get_pins -compatibility_mode u0|clocks_resets|h2f_user0_clk] 3 | 4 | # Automatically constrain PLL and other generated clocks 5 | derive_pll_clocks -create_base_clocks 6 | 7 | # Automatically calculate clock uncertainty to jitter and other effects. 8 | derive_clock_uncertainty 9 | -------------------------------------------------------------------------------- /data/chameleon96/pinmap.tcl: -------------------------------------------------------------------------------- 1 | # 2 | # Clock / Reset 3 | # 4 | # set_location_assignment PIN_xxxx -to i_clk 5 | # No direct clock. Using internal HPS clock 6 | 7 | # 8 | # GPIO 9 | # 10 | # LED Y19 Yellow WIFI, Y20 Blue Bluetooth 11 | set_location_assignment PIN_Y19 -to q 12 | set_instance_assignment -name IO_STANDARD "2.5 V" -to q 13 | 14 | # FPGA_1V8_HPS_EXP_UART1_TXD_PIN_W14 Pin 5 Low speed connector (WHITE C96 USB/serial cable) Pin 1 GND 15 | set_location_assignment PIN_W14 -to uart_txd 16 | set_instance_assignment -name IO_STANDARD "1.8 V" -to uart_txd 17 | 18 | # No reset button wired to FPGA 19 | # set_location_assignment PIN_xxx -to i_rst_n 20 | 21 | -------------------------------------------------------------------------------- /data/cmod_a7_35t.xdc: -------------------------------------------------------------------------------- 1 | ## 12 MHz Clock Signal 2 | set_property -dict { PACKAGE_PIN L17 IOSTANDARD LVCMOS33 } [get_ports { i_clk }]; #IO_L12P_T1_MRCC_14 Sch=gclk 3 | create_clock -add -name sys_clk_pin -period 83.33 -waveform {0 41.66} [get_ports { i_clk }]; 4 | 5 | ## LEDs 6 | set_property -dict { PACKAGE_PIN A17 IOSTANDARD LVCMOS33 } [get_ports { q }]; #IO_L12N_T1_MRCC_16 Sch=led[1] 7 | #set_property -dict { PACKAGE_PIN C16 IOSTANDARD LVCMOS33 } [get_ports { q }]; #IO_L13P_T2_MRCC_16 Sch=led[2] 8 | 9 | ## UART 10 | set_property -dict { PACKAGE_PIN J18 IOSTANDARD LVCMOS33 } [get_ports { o_uart_tx }]; #IO_L7N_T1_D10_14 Sch=uart_rxd_out 11 | #set_property -dict { PACKAGE_PIN J17 IOSTANDARD LVCMOS33 } [get_ports { q }]; #IO_L7P_T1_D09_14 Sch=uart_txd_in 12 | 13 | set_property -dict { PACKAGE_PIN A18 IOSTANDARD LVCMOS33 } [get_ports { i_rst }]; #IO_L19N_T3_VREF_16 Sch=btn[0] 14 | 15 | set_property CFGBVS VCCO [current_design] 16 | set_property CONFIG_VOLTAGE 3.3 [current_design] 17 | -------------------------------------------------------------------------------- /data/cyc1000.sdc: -------------------------------------------------------------------------------- 1 | # Main system clock (12 Mhz) 2 | create_clock -name "clk" -period 83.333ns [get_ports {i_clk}] 3 | 4 | # Automatically constrain PLL and other generated clocks 5 | derive_pll_clocks -create_base_clocks 6 | 7 | # Automatically calculate clock uncertainty to jitter and other effects. 8 | derive_clock_uncertainty 9 | -------------------------------------------------------------------------------- /data/cyc1000.tcl: -------------------------------------------------------------------------------- 1 | # 2 | # Clock / Reset 3 | # 4 | set_location_assignment PIN_M2 -to i_clk 5 | set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to i_clk 6 | set_location_assignment PIN_N6 -to i_rst 7 | set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to i_clk 8 | 9 | #UART/GPIO 10 | set_location_assignment PIN_M6 -to q 11 | set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to q 12 | 13 | set_location_assignment PIN_T7 -to uart_txd 14 | set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to uart* 15 | -------------------------------------------------------------------------------- /data/de0_nano.sdc: -------------------------------------------------------------------------------- 1 | # Main system clock (50 Mhz) 2 | create_clock -name "clk" -period 20.000ns [get_ports {i_clk}] 3 | 4 | # Automatically constrain PLL and other generated clocks 5 | derive_pll_clocks -create_base_clocks 6 | 7 | # Automatically calculate clock uncertainty to jitter and other effects. 8 | derive_clock_uncertainty 9 | -------------------------------------------------------------------------------- /data/de0_nano.tcl: -------------------------------------------------------------------------------- 1 | set_location_assignment PIN_R8 -to i_clk 2 | set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to i_clk 3 | 4 | set_location_assignment PIN_A15 -to q 5 | set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to q 6 | 7 | set_location_assignment PIN_D11 -to uart_txd 8 | set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to uart_txd 9 | 10 | set_location_assignment PIN_J15 -to i_rst_n 11 | set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to i_rst_n 12 | -------------------------------------------------------------------------------- /data/de10_nano.sdc: -------------------------------------------------------------------------------- 1 | # Main system clock (50 Mhz) 2 | create_clock -name "clk" -period 20.000ns [get_ports {i_clk}] 3 | 4 | # Automatically constrain PLL and other generated clocks 5 | derive_pll_clocks -create_base_clocks 6 | 7 | # Automatically calculate clock uncertainty to jitter and other effects. 8 | derive_clock_uncertainty 9 | -------------------------------------------------------------------------------- /data/de10_nano.tcl: -------------------------------------------------------------------------------- 1 | set_location_assignment PIN_V11 -to i_clk 2 | set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to i_clk 3 | 4 | set_location_assignment PIN_W15 -to q 5 | set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to q 6 | 7 | # GPIO0 Pin 1 8 | set_location_assignment PIN_Y15 -to uart_txd 9 | set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to uart_txd 10 | 11 | #KEY[0] 12 | set_location_assignment PIN_AH17 -to i_rst_n 13 | set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to i_rst_n 14 | -------------------------------------------------------------------------------- /data/de1_soc_revF.sdc: -------------------------------------------------------------------------------- 1 | # Main system clock (50 Mhz) 2 | create_clock -name "clk" -period 20.000ns [get_ports {i_clk}] 3 | 4 | # Automatically constrain PLL and other generated clocks 5 | derive_pll_clocks -create_base_clocks 6 | 7 | # Automatically calculate clock uncertainty to jitter and other effects. 8 | derive_clock_uncertainty 9 | -------------------------------------------------------------------------------- /data/de1_soc_revF.tcl: -------------------------------------------------------------------------------- 1 | set_location_assignment PIN_AF14 -to i_clk 2 | set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to i_clk 3 | 4 | set_location_assignment PIN_AA14 -to i_rst_n 5 | set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to i_rst_n 6 | 7 | set_location_assignment PIN_V16 -to q 8 | set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to q 9 | 10 | set_location_assignment PIN_AC18 -to uart_txd 11 | set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to uart* 12 | -------------------------------------------------------------------------------- /data/deca.sdc: -------------------------------------------------------------------------------- 1 | # Main system clock (50 Mhz) 2 | create_clock -name "clk" -period 20.000ns [get_ports {i_clk}] 3 | 4 | # Automatically constrain PLL and other generated clocks 5 | derive_pll_clocks -create_base_clocks 6 | 7 | # Automatically calculate clock uncertainty to jitter and other effects. 8 | derive_clock_uncertainty 9 | -------------------------------------------------------------------------------- /data/deca.tcl: -------------------------------------------------------------------------------- 1 | #MAX10_CLK2_50 3.3V 2 | set_location_assignment PIN_P11 -to i_clk 3 | set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to i_clk 4 | 5 | #LED[0] 6 | set_location_assignment PIN_C7 -to q 7 | set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to q 8 | 9 | #P8 3 GPIO0_D0 (P8 1 GND) 10 | set_location_assignment PIN_W18 -to uart_txd 11 | set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to uart_txd 12 | 13 | #KEY[0] 14 | set_location_assignment PIN_H21 -to i_rst_n 15 | set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to i_rst_n 16 | 17 | # Configuration mode that allows Memory Initialisation 18 | set_global_assignment -name INTERNAL_FLASH_UPDATE_MODE "SINGLE IMAGE WITH ERAM" 19 | 20 | -------------------------------------------------------------------------------- /data/ebaz4205.xdc: -------------------------------------------------------------------------------- 1 | ## 33.333 MHz Clock signal 2 | set_property -dict { PACKAGE_PIN N18 IOSTANDARD LVCMOS33 } [get_ports i_clk]; 3 | create_clock -add -name sys_clk_pin -period 30.00 -waveform {0 5} [get_ports i_clk]; 4 | 5 | ## LED(s) 6 | # set_property -dict { PACKAGE_PIN W13 IOSTANDARD LVCMOS33 } [get_ports { q_green }]; 7 | # set_property -dict { PACKAGE_PIN W14 IOSTANDARD LVCMOS33 } [get_ports { q }]; 8 | 9 | ## UART on DATA1_8 pin 10 | set_property -dict { PACKAGE_PIN B20 IOSTANDARD LVCMOS33 } [get_ports q]; 11 | -------------------------------------------------------------------------------- /data/ecp5_evn.lpf: -------------------------------------------------------------------------------- 1 | # 12MHz clock from FTDI FT2232H 2 | LOCATE COMP "clk" SITE "A10"; 3 | IOBUF PORT "clk" IO_TYPE=LVCMOS33; 4 | FREQUENCY PORT "clk" 12 MHZ; 5 | 6 | # SW4 button 7 | LOCATE COMP "nreset" SITE "P4"; 8 | IOBUF PORT "nreset" IO_TYPE=LVCMOS33; 9 | 10 | # LED0 11 | LOCATE COMP "led0" SITE "A13"; 12 | IOBUF PORT "led0" IO_TYPE=LVCMOS25; 13 | 14 | # J40 Header Pin #1 15 | LOCATE COMP "uart_txd" SITE "K2"; 16 | IOBUF PORT "uart_txd" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4; 17 | -------------------------------------------------------------------------------- /data/gmm7550.ccf: -------------------------------------------------------------------------------- 1 | ## GMM-7550 pins 2 | 3 | # This file is a part of the GMM-7550 VHDL Examples 4 | # 5 | # 6 | # SPDX-License-Identifier: MIT 7 | # 8 | # Copyright (c) 2023 Anton Kuzmin 9 | 10 | # Master clock input (100 MHz) 11 | Pin_in "ser_clk" Loc = "SER_CLK"; 12 | 13 | ### SPI 14 | 15 | Pin_inout "CFG_SPI_nCS" Loc = "IO_WA_A8"; 16 | Pin_inout "CFG_SPI_CLK" Loc = "IO_WA_B8"; 17 | Pin_inout "CFG_SPI_IO0" Loc = "IO_WA_B7"; # MOSI 18 | Pin_inout "CFG_SPI_IO1" Loc = "IO_WA_A7"; # MISO 19 | # Pin_inout "CFG_SPI_IO2" Loc = "IO_WA_B6"; # May be reused on the HAT for UART 20 | # Pin_inout "CFG_SPI_IO3" Loc = "IO_WA_A6"; # May be reused on the HAT for UART 21 | ## HAT Adapter board 22 | 23 | # This file is a part of the GMM-7550 VHDL Examples 24 | # 25 | # 26 | # SPDX-License-Identifier: MIT 27 | # 28 | # Copyright (c) 2023 Anton Kuzmin 29 | 30 | # D4 CFG_FAILED (Red) 31 | Pin_out "led_red_n" Loc = "IO_WA_A2"; 32 | 33 | # D2 CFG_DONE (Green) 34 | Pin_out "led_green" Loc = "IO_WA_B2"; 35 | 36 | ### UART 37 | 38 | Pin_out "uart_tx" Loc = "IO_WA_A6"; # SPI D3, GPIO pin 10 39 | Pin_in "uart_rx" Loc = "IO_WA_B6"; # SPI D2, GPIO pin 8 40 | 41 | ### Pmod J10 42 | 43 | Pin_out "J10_EN" Loc = "IO_SA_A7"; 44 | 45 | Pin_inout "J10_IO[0]" Loc = "IO_SA_A0"; 46 | Pin_inout "J10_IO[1]" Loc = "IO_SA_A1"; 47 | Pin_inout "J10_IO[2]" Loc = "IO_SA_A2"; 48 | Pin_inout "J10_IO[3]" Loc = "IO_SA_A3"; 49 | Pin_inout "J10_IO[4]" Loc = "IO_SA_B0"; 50 | Pin_inout "J10_IO[5]" Loc = "IO_SA_B1"; 51 | Pin_inout "J10_IO[6]" Loc = "IO_SA_B2"; 52 | Pin_inout "J10_IO[7]" Loc = "IO_SA_B3"; 53 | 54 | ### Pmod J9 55 | 56 | Pin_out "J9_EN" Loc = "IO_SB_B3"; 57 | 58 | Pin_inout "J9_IO[0]" Loc = "IO_SB_A6"; # CLK_2 59 | Pin_inout "J9_IO[1]" Loc = "IO_SB_A7"; # CLK_1 60 | Pin_inout "J9_IO[2]" Loc = "IO_SB_A8"; # CLK_0 61 | Pin_inout "J9_IO[3]" Loc = "IO_SB_A5"; # CLK_3 62 | Pin_inout "J9_IO[4]" Loc = "IO_SB_B6"; 63 | Pin_inout "J9_IO[5]" Loc = "IO_SB_B7"; 64 | Pin_inout "J9_IO[6]" Loc = "IO_SB_B8"; 65 | Pin_inout "J9_IO[7]" Loc = "IO_SB_B5"; 66 | -------------------------------------------------------------------------------- /data/go_board.pcf: -------------------------------------------------------------------------------- 1 | # 20 MHz clock input 2 | set_io i_clk 15 3 | 4 | # Onboard LEDs 1-4 5 | set_io o_led1 56 6 | set_io o_led2 57 7 | set_io o_led3 59 8 | set_io o_led4 60 9 | 10 | set_io o_uart_tx 74 11 | -------------------------------------------------------------------------------- /data/icebreaker.pcf: -------------------------------------------------------------------------------- 1 | # 12 MHz clock 2 | set_io i_clk 35 3 | 4 | # RS232 5 | set_io q 9 6 | -------------------------------------------------------------------------------- /data/icestick.pcf: -------------------------------------------------------------------------------- 1 | # 12 MHz clock input 2 | set_io i_clk 21 3 | 4 | # Onboard LED (Green) 5 | set_io q 95 6 | 7 | # UART TX 8 | #set_io q 62 9 | -------------------------------------------------------------------------------- /data/icesugar.pcf: -------------------------------------------------------------------------------- 1 | # 12 MHz clock 2 | set_io i_clk 35 3 | 4 | # RS232 5 | set_io q 6 6 | -------------------------------------------------------------------------------- /data/icev_wireless.pcf: -------------------------------------------------------------------------------- 1 | # 12 MHz clock 2 | set_io i_clk 35 3 | 4 | # RS232 5 | set_io q 9 6 | 7 | # use q 39 for red, q 40 for green, q 41 for blue LED 8 | -------------------------------------------------------------------------------- /data/lx9_microboard.ucf: -------------------------------------------------------------------------------- 1 | CONFIG VCCAUX=3.3; 2 | 3 | NET i_clk LOC = V10 | IOSTANDARD = LVCMOS33; 4 | NET i_rst LOC = V4 | IOSTANDARD = LVCMOS33 | PULLDOWN; 5 | NET q LOC = P4 | IOSTANDARD = LVCMOS18; 6 | NET o_uart_tx LOC = T7 | IOSTANDARD = LVCMOS33; 7 | 8 | NET i_clk TNM_NET = clk; 9 | TIMESPEC TS_USER_CLOCK = PERIOD clk 40000 kHz; 10 | -------------------------------------------------------------------------------- /data/machdyne_kolibri.pcf: -------------------------------------------------------------------------------- 1 | set_io clk48 G1 2 | set_io led B11 3 | set_io tx B1 4 | set_io rx B2 5 | -------------------------------------------------------------------------------- /data/max10_10m08evk.sdc: -------------------------------------------------------------------------------- 1 | # Main system clock (50 Mhz) 2 | create_clock -name "clk" -period 20.000ns [get_ports {i_clk}] 3 | 4 | # Automatically constrain PLL and other generated clocks 5 | derive_pll_clocks -create_base_clocks 6 | 7 | # Automatically calculate clock uncertainty to jitter and other effects. 8 | derive_clock_uncertainty 9 | -------------------------------------------------------------------------------- /data/max10_10m08evk.tcl: -------------------------------------------------------------------------------- 1 | #MAX10_CLK2_50 3.3V 2 | set_location_assignment PIN_27 -to i_clk 3 | set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to i_clk 4 | 5 | #LED[0] 6 | set_location_assignment PIN_132 -to q 7 | set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to q 8 | 9 | #P8 3 ARDUINO_IO1 10 | set_location_assignment PIN_75 -to uart_txd 11 | set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to uart_txd 12 | 13 | #KEY[0] 14 | set_location_assignment PIN_121 -to i_rst_n 15 | set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to i_rst_n 16 | 17 | # Configuration mode that allows Memory Initialisation 18 | set_global_assignment -name INTERNAL_FLASH_UPDATE_MODE "SINGLE IMAGE WITH ERAM" 19 | 20 | # Generate SVF File for openFPGALoader 21 | set_global_assignment -name GENERATE_SVF_FILE ON 22 | # set_global_assignment -name GENERATE_JBC_FILE ON 23 | set_global_assignment -name GENERATE_JAM_FILE ON 24 | 25 | -------------------------------------------------------------------------------- /data/nexys_2.tcl: -------------------------------------------------------------------------------- 1 | project set "Other XST Command Line Options" "-use_new_parser yes" -------------------------------------------------------------------------------- /data/nexys_2.ucf: -------------------------------------------------------------------------------- 1 | NET "i_clk" LOC = "B8" | IOSTANDARD = LVCMOS33 ; 2 | NET "i_clk" CLOCK_DEDICATED_ROUTE = FALSE; 3 | 4 | # Pin assignment for Uart tx 5 | NET "q" LOC = "L15" | IOSTANDARD = LVTTL | SLEW = FAST | DRIVE = 8 ; 6 | 7 | # Pin assignment for LED 8 | # NET "q" LOC = "J14" | IOSTANDARD = LVTTL | SLEW = FAST | DRIVE = 8 ; -------------------------------------------------------------------------------- /data/nexys_a7.xdc: -------------------------------------------------------------------------------- 1 | set_property -dict {PACKAGE_PIN E3 IOSTANDARD LVCMOS33 } [get_ports i_clk]; 2 | set_property -dict {PACKAGE_PIN D4 IOSTANDARD LVCMOS33 } [get_ports q] 3 | 4 | create_clock -add -name sys_clk_pin -period 10.00 -waveform {0 5} [get_ports i_clk]; 5 | -------------------------------------------------------------------------------- /data/orangecrab_r02.lpf: -------------------------------------------------------------------------------- 1 | LOCATE COMP "clk" SITE "A9"; 2 | IOBUF PORT "clk" PULLMODE=NONE IO_TYPE=LVCMOS33; 3 | FREQUENCY PORT "clk" 48.000 MHZ; 4 | 5 | LOCATE COMP "r" SITE "K4"; 6 | LOCATE COMP "g" SITE "M3"; 7 | LOCATE COMP "b" SITE "J3"; 8 | 9 | IOBUF PORT "r" IO_TYPE=LVCMOS33; 10 | IOBUF PORT "g" IO_TYPE=LVCMOS33; 11 | IOBUF PORT "b" IO_TYPE=LVCMOS33; 12 | 13 | LOCATE COMP "btn" SITE "J17"; # BTN_PWRn (inverted logic) 14 | IOBUF PORT "btn" PULLMODE=UP IO_TYPE=LVCMOS33; 15 | 16 | LOCATE COMP "tx" SITE "M18"; # FPGA serial output 17 | IOBUF PORT "tx" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4; 18 | -------------------------------------------------------------------------------- /data/params.tcl: -------------------------------------------------------------------------------- 1 | set ::env(CLOCK_PERIOD) "10" 2 | set ::env(CLOCK_PORT) "clk" 3 | set ::env(DIE_AREA) "0 0 200 200" 4 | set ::env(FP_SIZING) absolute 5 | set ::env(DESIGN_IS_CORE) 0 6 | set ::env(GLB_RT_MAXLAYER) 5 7 | -------------------------------------------------------------------------------- /data/pipistrello.ucf: -------------------------------------------------------------------------------- 1 | CONFIG VCCAUX=3.3; 2 | 3 | NET i_clk LOC = H17 | IOSTANDARD = LVTTL; 4 | 5 | NET i_clk TNM_NET = i_clk; 6 | TIMESPEC TS_USER_CLOCK = PERIOD i_clk 50000 kHz; 7 | 8 | 9 | # uart tx 10 | NET q LOC = A10 | IOSTANDARD = LVTTL | DRIVE = 8 | SLEW = FAST ; 11 | # led0 12 | #NET q LOC = V16 | IOSTANDARD = LVCMOS33; 13 | -------------------------------------------------------------------------------- /data/polarfire_splashkit.pdc: -------------------------------------------------------------------------------- 1 | set_io -port_name {i_clk} -DIRECTION INPUT -pin_name H7 -io_std LVCMOS18 -fixed true 2 | set_io -port_name {resetb} -DIRECTION INPUT -pin_name N4 -io_std LVCMOS18 -fixed true 3 | set_io -port_name {o_led1} -DIRECTION OUTPUT -pin_name P7 -io_std LVCMOS18 -fixed true 4 | set_io -port_name {o_led2} -DIRECTION OUTPUT -pin_name P8 -io_std LVCMOS18 -fixed true 5 | set_io -port_name {o_led3} -DIRECTION OUTPUT -pin_name N7 -io_std LVCMOS18 -fixed true 6 | set_io -port_name {o_led4} -DIRECTION OUTPUT -pin_name N8 -io_std LVCMOS18 -fixed true 7 | set_io -port_name {o_led5} -DIRECTION OUTPUT -pin_name N6 -io_std LVCMOS18 -fixed true 8 | set_io -port_name {o_led6} -DIRECTION OUTPUT -pin_name N5 -io_std LVCMOS18 -fixed true 9 | set_io -port_name {o_led7} -DIRECTION OUTPUT -pin_name M8 -io_std LVCMOS18 -fixed true 10 | set_io -port_name {o_led8} -DIRECTION OUTPUT -pin_name M9 -io_std LVCMOS18 -fixed true 11 | set_io -port_name {o_uart_tx} -DIRECTION OUTPUT -pin_name R4 -io_std LVCMOS18 -fixed true 12 | -------------------------------------------------------------------------------- /data/sockit.sdc: -------------------------------------------------------------------------------- 1 | # Main system clock (50 Mhz) 2 | create_clock -name "clk" -period 20.000ns [get_ports {i_clk}] 3 | 4 | # Automatically constrain PLL and other generated clocks 5 | derive_pll_clocks -create_base_clocks 6 | 7 | # Automatically calculate clock uncertainty to jitter and other effects. 8 | derive_clock_uncertainty 9 | -------------------------------------------------------------------------------- /data/sockit.tcl: -------------------------------------------------------------------------------- 1 | set_location_assignment PIN_AF14 -to i_clk 2 | set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to i_clk 3 | 4 | set_location_assignment PIN_AF10 -to q 5 | set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to q 6 | 7 | set_location_assignment PIN_F14 -to uart_txd 8 | set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to uart_txd 9 | 10 | set_location_assignment PIN_AE9 -to i_rst_n 11 | set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to i_rst_n 12 | -------------------------------------------------------------------------------- /data/te0802.xdc: -------------------------------------------------------------------------------- 1 | ## Clock signal 2 | set_property -dict { PACKAGE_PIN J3 IOSTANDARD LVCMOS18 } [get_ports i_clk]; 3 | create_clock -add -name sys_clk_pin -period 40.00 [get_ports i_clk]; 4 | 5 | ## LED 0 6 | set_property -dict { PACKAGE_PIN P1 IOSTANDARD LVCMOS18 } [get_ports o_led_0]; 7 | 8 | # PMOD A, Connector J5 9 | # Connector pin, Package pin, PMOD type 4 UART 10 | # 1, F8, CTS 11 | # 2, F7, TXD 12 | # 3, E6, RXD 13 | # 4, E5, RTS 14 | # 5, GND 15 | # 6, VCC 16 | # 7, G6, 17 | # 8, G5, 18 | # 9, C8, 19 | # 10, C7, 20 | # 11, GND 21 | # 12, VCC 22 | set_property -dict { PACKAGE_PIN F7 IOSTANDARD LVCMOS33 } [get_ports o_uart_tx] 23 | -------------------------------------------------------------------------------- /data/tinyfpga_bx.pcf: -------------------------------------------------------------------------------- 1 | set_io q A6 2 | set_io i_clk B2 3 | -------------------------------------------------------------------------------- /data/ulx3s.lpf: -------------------------------------------------------------------------------- 1 | LOCATE COMP "clk" SITE "G2"; 2 | IOBUF PORT "clk" PULLMODE=NONE IO_TYPE=LVCMOS33; 3 | FREQUENCY PORT "clk" 25.000 MHZ; 4 | LOCATE COMP "q" SITE "B2"; 5 | IOBUF PORT "q" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4; 6 | 7 | LOCATE COMP "btn0" SITE "D6"; # BTN_PWRn (inverted logic) 8 | IOBUF PORT "btn0" PULLMODE=UP IO_TYPE=LVCMOS33; 9 | 10 | LOCATE COMP "wifi_gpio0" SITE "L2"; 11 | IOBUF PORT "wifi_gpio0" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4; 12 | 13 | LOCATE COMP "uart_txd" SITE "L4"; # FPGA transmits to ftdi 14 | IOBUF PORT "uart_txd" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4; 15 | -------------------------------------------------------------------------------- /data/upduino2.pcf: -------------------------------------------------------------------------------- 1 | set_io g 39 2 | set_io b 40 3 | set_io r 41 4 | set_io q 14 5 | -------------------------------------------------------------------------------- /data/verilator_waiver.vlt: -------------------------------------------------------------------------------- 1 | `verilator_config 2 | // Bits [1:0] in i_wb_rdt are not used at all 3 | lint_off -rule UNUSED -file "*/serv_top.v" -lines 179 4 | 5 | //Some bits in the instruction word are not used in serv_decode but it's easier 6 | //to just send in the whole word than picking out bits 7 | lint_off -rule UNUSED -file "*/serv_decode.v" -lines 8 8 | 9 | //Some variables are only used when we connect an Extension with serv_decode 10 | lint_off -rule UNUSED -file "*/serv_top.v" -lines 70 11 | 12 | //Some bufreg signals are not used in 1-bit mode 13 | lint_off -rule UNUSED -file "*/serv_bufreg.v" -lines 10 14 | lint_off -rule UNUSED -file "*/serv_bufreg.v" -lines 19-21 15 | 16 | //Some signals not used in 4-bit mode 17 | lint_off -rule UNUSED -file "*/serv_immdec.v" -lines 12 18 | lint_off -rule UNUSED -file "*/serv_bufreg.v" -lines 9 19 | lint_off -rule UNUSED -file "*/serv_ctrl.v" -lines 17 20 | -------------------------------------------------------------------------------- /data/zcu106.xdc: -------------------------------------------------------------------------------- 1 | ## Clock signal 2 | set_property -dict { PACKAGE_PIN H9 IOSTANDARD LVDS } [get_ports i_clk_p]; 3 | set_property -dict { PACKAGE_PIN G9 IOSTANDARD LVDS } [get_ports i_clk_n]; 4 | create_clock -add -name sys_clk_pin -period 8 [get_nets i_clk]; 5 | 6 | ## LED 7 | set_property -dict { PACKAGE_PIN AL11 IOSTANDARD LVCMOS12 } [get_ports q]; 8 | set_property -dict { PACKAGE_PIN AL17 IOSTANDARD LVCMOS12 } [get_ports o_uart_tx] 9 | -------------------------------------------------------------------------------- /doc/.nojekyll: -------------------------------------------------------------------------------- 1 | This is published to GitHub Pages. It will ignore the _images path etc. otherwise. 2 | -------------------------------------------------------------------------------- /doc/Makefile: -------------------------------------------------------------------------------- 1 | # Minimal makefile for Sphinx documentation 2 | # 3 | 4 | # You can set these variables from the command line. 5 | SPHINXOPTS = 6 | SPHINXBUILD = sphinx-build 7 | SOURCEDIR = . 8 | BUILDDIR = _build 9 | 10 | # Put it first so that "make" without argument is like "make help". 11 | help: 12 | @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 13 | 14 | .PHONY: help Makefile 15 | 16 | # Catch-all target: route all unknown targets to Sphinx using the new 17 | # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). 18 | %: Makefile 19 | @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) -------------------------------------------------------------------------------- /doc/conf.py: -------------------------------------------------------------------------------- 1 | # Configuration file for the Sphinx documentation builder. 2 | # 3 | # This file only contains a selection of the most common options. For a full 4 | # list see the documentation: 5 | # http://www.sphinx-doc.org/en/master/config 6 | 7 | # -- Path setup -------------------------------------------------------------- 8 | 9 | # If extensions (or modules to document with autodoc) are in another directory, 10 | # add these directories to sys.path here. If the directory is relative to the 11 | # documentation root, use os.path.abspath to make it absolute, like shown here. 12 | # 13 | # import os 14 | # import sys 15 | # sys.path.insert(0, os.path.abspath('.')) 16 | 17 | 18 | # -- Project information ----------------------------------------------------- 19 | 20 | project = 'SERV' 21 | copyright = '2020, Olof Kindgren' 22 | author = 'Olof Kindgren' 23 | 24 | 25 | # -- General configuration --------------------------------------------------- 26 | 27 | # Add any Sphinx extension module names here, as strings. They can be 28 | # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom 29 | # ones. 30 | extensions = [ 31 | 'sphinxcontrib.wavedrom' 32 | ] 33 | 34 | # Add any paths that contain templates here, relative to this directory. 35 | templates_path = ['_templates'] 36 | 37 | # List of patterns, relative to source directory, that match files and 38 | # directories to ignore when looking for source files. 39 | # This pattern also affects html_static_path and html_extra_path. 40 | exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store'] 41 | 42 | 43 | # -- Options for HTML output ------------------------------------------------- 44 | 45 | # The theme to use for HTML and HTML Help pages. See the documentation for 46 | # a list of builtin themes. 47 | # 48 | html_theme = 'alabaster' 49 | 50 | # Add any paths that contain custom static files (such as style sheets) here, 51 | # relative to this directory. They are copied after the builtin static files, 52 | # so a file named "default.css" will overwrite the builtin "default.css". 53 | html_static_path = ['_static'] 54 | 55 | html_extra_path = ['.nojekyll'] 56 | 57 | master_doc = 'index' 58 | 59 | online_wavedrom_js_url = "https://wavedrom.com" 60 | -------------------------------------------------------------------------------- /doc/datasheet.rst: -------------------------------------------------------------------------------- 1 | ********* 2 | Datasheet 3 | ********* 4 | 5 | .. include:: overview.rst 6 | .. include:: interface.rst 7 | -------------------------------------------------------------------------------- /doc/index.rst: -------------------------------------------------------------------------------- 1 | ################ 2 | SERV user manual 3 | ################ 4 | 5 | Welcome to the user manual of the award-winning SERV, the world's smallest RISC-V CPU. 6 | 7 | .. toctree:: 8 | :maxdepth: 4 9 | :caption: Contents: 10 | 11 | datasheet.rst 12 | internals.rst 13 | reservoir.rst 14 | -------------------------------------------------------------------------------- /doc/internals.rst: -------------------------------------------------------------------------------- 1 | ********* 2 | Internals 3 | ********* 4 | 5 | .. include:: modules.rst 6 | -------------------------------------------------------------------------------- /doc/life_cycle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/olofk/serv/a72c1e8737d424c31bf6ff909795acc37aa4cc90/doc/life_cycle.png -------------------------------------------------------------------------------- /doc/make.bat: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | 3 | pushd %~dp0 4 | 5 | REM Command file for Sphinx documentation 6 | 7 | if "%SPHINXBUILD%" == "" ( 8 | set SPHINXBUILD=sphinx-build 9 | ) 10 | set SOURCEDIR=. 11 | set BUILDDIR=_build 12 | 13 | if "%1" == "" goto help 14 | 15 | %SPHINXBUILD% >NUL 2>NUL 16 | if errorlevel 9009 ( 17 | echo. 18 | echo.The 'sphinx-build' command was not found. Make sure you have Sphinx 19 | echo.installed, then set the SPHINXBUILD environment variable to point 20 | echo.to the full path of the 'sphinx-build' executable. Alternatively you 21 | echo.may add the Sphinx directory to PATH. 22 | echo. 23 | echo.If you don't have Sphinx installed, grab it from 24 | echo.http://sphinx-doc.org/ 25 | exit /b 1 26 | ) 27 | 28 | %SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% 29 | goto end 30 | 31 | :help 32 | %SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% 33 | 34 | :end 35 | popd 36 | -------------------------------------------------------------------------------- /doc/overview.rst: -------------------------------------------------------------------------------- 1 | Overview 2 | ======== 3 | 4 | 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. 5 | 6 | Key Features 7 | ------------ 8 | 9 | * **ISA:** RISC-V RV32IZifencei 10 | * **Optional ISA extensions:** C, M, Zicsr 11 | * **Optional features:** Timer interrupts, Extension interface 12 | * **Architecture:** Bit-serial (one bit processed per clock cycle) 13 | * **License:** ISC (available under other commercial licenses upon request) 14 | * **OS support:** Zephyr 3.7 15 | * **SW support:** Compatible with standard RISC-V toolchains 16 | * **Area:** Smallest RISC-V core available 17 | 18 | Applications 19 | ------------ 20 | 21 | * **Embedded Systems:** Ideal for minimalistic embedded control tasks 22 | * **IoT Devices:** Suitable for Internet of Things devices where space and power are limited 23 | * **Education:** Excellent resource for teaching and understanding the RISC-V architecture and CPU design 24 | * **Research:** Platform for research in minimalistic computing designs and for bringing up new fabrication processes 25 | 26 | Area 27 | ---- 28 | 29 | .. list-table:: Area for minimal configuration [#]_ 30 | :widths: 25 25 25 25 31 | :header-rows: 1 32 | 33 | * - Lattice iCE40 34 | - Altera Cyclone10LP 35 | - AMD Artix-7 36 | - CMOS 37 | * - 198LUT/164FF 38 | - 239LUT/164FF 39 | - 125LUT/164FF 40 | - 2.1kGE 41 | 42 | .. [#] Excluding register file 43 | -------------------------------------------------------------------------------- /doc/requirements.txt: -------------------------------------------------------------------------------- 1 | git+https://github.com/bavovanachte/sphinx-wavedrom@master#egg=sphinxcontrib-wavedrom 2 | -------------------------------------------------------------------------------- /doc/reservoir.rst: -------------------------------------------------------------------------------- 1 | ************************** 2 | Building systems with SERV 3 | ************************** 4 | 5 | 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. 6 | 7 | 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. 8 | 9 | .. include:: servile.rst 10 | .. include:: serving.rst 11 | .. include:: servant.rst 12 | .. include:: subservient.rst 13 | -------------------------------------------------------------------------------- /doc/serv_alu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/olofk/serv/a72c1e8737d424c31bf6ff909795acc37aa4cc90/doc/serv_alu.png -------------------------------------------------------------------------------- /doc/serv_alu_int.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/olofk/serv/a72c1e8737d424c31bf6ff909795acc37aa4cc90/doc/serv_alu_int.png -------------------------------------------------------------------------------- /doc/serv_bufreg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/olofk/serv/a72c1e8737d424c31bf6ff909795acc37aa4cc90/doc/serv_bufreg.png -------------------------------------------------------------------------------- /doc/serv_bufreg2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/olofk/serv/a72c1e8737d424c31bf6ff909795acc37aa4cc90/doc/serv_bufreg2.png -------------------------------------------------------------------------------- /doc/serv_bufreg2_int.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/olofk/serv/a72c1e8737d424c31bf6ff909795acc37aa4cc90/doc/serv_bufreg2_int.png -------------------------------------------------------------------------------- /doc/serv_bufreg_int.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/olofk/serv/a72c1e8737d424c31bf6ff909795acc37aa4cc90/doc/serv_bufreg_int.png -------------------------------------------------------------------------------- /doc/serv_csr.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/olofk/serv/a72c1e8737d424c31bf6ff909795acc37aa4cc90/doc/serv_csr.png -------------------------------------------------------------------------------- /doc/serv_csr_int.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/olofk/serv/a72c1e8737d424c31bf6ff909795acc37aa4cc90/doc/serv_csr_int.png -------------------------------------------------------------------------------- /doc/serv_ctrl.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/olofk/serv/a72c1e8737d424c31bf6ff909795acc37aa4cc90/doc/serv_ctrl.png -------------------------------------------------------------------------------- /doc/serv_ctrl_int.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/olofk/serv/a72c1e8737d424c31bf6ff909795acc37aa4cc90/doc/serv_ctrl_int.png -------------------------------------------------------------------------------- /doc/serv_dataflow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/olofk/serv/a72c1e8737d424c31bf6ff909795acc37aa4cc90/doc/serv_dataflow.png -------------------------------------------------------------------------------- /doc/serv_decode.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/olofk/serv/a72c1e8737d424c31bf6ff909795acc37aa4cc90/doc/serv_decode.png -------------------------------------------------------------------------------- /doc/serv_decode_int.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/olofk/serv/a72c1e8737d424c31bf6ff909795acc37aa4cc90/doc/serv_decode_int.png -------------------------------------------------------------------------------- /doc/serv_immdec.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/olofk/serv/a72c1e8737d424c31bf6ff909795acc37aa4cc90/doc/serv_immdec.png -------------------------------------------------------------------------------- /doc/serv_immdec_int.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/olofk/serv/a72c1e8737d424c31bf6ff909795acc37aa4cc90/doc/serv_immdec_int.png -------------------------------------------------------------------------------- /doc/serv_mem_if.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/olofk/serv/a72c1e8737d424c31bf6ff909795acc37aa4cc90/doc/serv_mem_if.png -------------------------------------------------------------------------------- /doc/serv_mem_if_int.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/olofk/serv/a72c1e8737d424c31bf6ff909795acc37aa4cc90/doc/serv_mem_if_int.png -------------------------------------------------------------------------------- /doc/serv_rf_if.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/olofk/serv/a72c1e8737d424c31bf6ff909795acc37aa4cc90/doc/serv_rf_if.png -------------------------------------------------------------------------------- /doc/serv_rf_if_int.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/olofk/serv/a72c1e8737d424c31bf6ff909795acc37aa4cc90/doc/serv_rf_if_int.png -------------------------------------------------------------------------------- /doc/serv_rf_top.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/olofk/serv/a72c1e8737d424c31bf6ff909795acc37aa4cc90/doc/serv_rf_top.png -------------------------------------------------------------------------------- /doc/serv_top.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/olofk/serv/a72c1e8737d424c31bf6ff909795acc37aa4cc90/doc/serv_top.png -------------------------------------------------------------------------------- /doc/servant.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/olofk/serv/a72c1e8737d424c31bf6ff909795acc37aa4cc90/doc/servant.png -------------------------------------------------------------------------------- /doc/servile.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/olofk/serv/a72c1e8737d424c31bf6ff909795acc37aa4cc90/doc/servile.png -------------------------------------------------------------------------------- /doc/servile_int.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/olofk/serv/a72c1e8737d424c31bf6ff909795acc37aa4cc90/doc/servile_int.png -------------------------------------------------------------------------------- /doc/serving.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/olofk/serv/a72c1e8737d424c31bf6ff909795acc37aa4cc90/doc/serving.png -------------------------------------------------------------------------------- /doc/serving.rst: -------------------------------------------------------------------------------- 1 | Serving : FPGA subsystem 2 | ======================== 3 | 4 | .. figure:: serving.png 5 | 6 | Serving SoClet 7 | 8 | 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. 9 | 10 | Parameters 11 | ---------- 12 | 13 | .. list-table:: Parameters 14 | :header-rows: 1 15 | :widths: 10 20 80 16 | 17 | * - Parameter 18 | - Values 19 | - Description 20 | * - memfile 21 | - "" (default) 22 | - Verilog hex file containing a RISC-V application to be preloaded into memory 23 | * - memsize 24 | - 1-4294967296 (default 8192) 25 | - 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. 26 | * - sim 27 | - 0 (default), 1 28 | - | Enable simulation mode. In simulation mode, two memory addresses have special purposes. 29 | | 0x80000000: Writes to this address puts the byte in the lowest data byte into a log file decided by the "signature" plusarg. 30 | | 0x90000000: Writes to this address ends the simulation. 31 | * - RESET_STRATEGY 32 | - "MINI" (default), "NONE" 33 | - | Amount of reset applied to design 34 | | "NONE" : No reset at all. Relies on a POR to set correct initialization values and that core isn't reset during runtime 35 | | "MINI" : Standard setting. Resets the minimal amount of FFs needed to restart execution from the instruction at RESET_PC. 36 | * - WITH_CSR 37 | - 0 (default), 1 38 | - Enable the Zicsr extension. This also enables timer IRQ and exception handling. Note that SERV only implements a small subset of the CSR registers. 39 | 40 | Signals 41 | ------- 42 | 43 | .. list-table:: Signals 44 | :header-rows: 1 45 | :widths: 30 10 5 75 46 | 47 | * - Signal 48 | - Width 49 | - Direction 50 | - Description 51 | * - i_clk 52 | - 1 53 | - in 54 | - Clock 55 | * - i_rst 56 | - 1 57 | - in 58 | - Synchronous reset 59 | * - i_timer_irq 60 | - 1 61 | - in 62 | - Timer interrupt 63 | * - **Extension interface** 64 | - 65 | - 66 | - Connect to peripheral controllers 67 | * - o_wb_adr 68 | - 32 69 | - out 70 | - Data bus address 71 | * - o_wb_dat 72 | - 32 73 | - out 74 | - Data bus write data 75 | * - o_wb_sel 76 | - 4 77 | - out 78 | - Data bus write data byte select mask 79 | * - o_wb_we 80 | - 1 81 | - out 82 | - Data bus write transaction 83 | * - o_wb_cyc 84 | - 1 85 | - out 86 | - Data bus active cycle 87 | * - i_wb_rdt 88 | - 32 89 | - in 90 | - Data bus return data 91 | * - i_wb_ack 92 | - 1 93 | - in 94 | - Data bus return data valid 95 | -------------------------------------------------------------------------------- /doc/subservient.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/olofk/serv/a72c1e8737d424c31bf6ff909795acc37aa4cc90/doc/subservient.png -------------------------------------------------------------------------------- /doc/subservient.rst: -------------------------------------------------------------------------------- 1 | Subservient : SERV ASIC macro 2 | ============================= 3 | 4 | .. figure:: subservient.png 5 | 6 | Subservient ASIC macro 7 | 8 | `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. 9 | 10 | 11 | -------------------------------------------------------------------------------- /rtl/serv_aligner.v: -------------------------------------------------------------------------------- 1 | module serv_aligner 2 | ( 3 | input wire clk, 4 | input wire rst, 5 | // serv_top 6 | input wire [31:0] i_ibus_adr, 7 | input wire i_ibus_cyc, 8 | output wire [31:0] o_ibus_rdt, 9 | output wire o_ibus_ack, 10 | // serv_rf_top 11 | output wire [31:0] o_wb_ibus_adr, 12 | output wire o_wb_ibus_cyc, 13 | input wire [31:0] i_wb_ibus_rdt, 14 | input wire i_wb_ibus_ack); 15 | 16 | wire [31:0] ibus_rdt_concat; 17 | wire ack_en; 18 | 19 | reg [15:0] lower_hw; 20 | reg ctrl_misal ; 21 | 22 | /* From SERV core to Memory 23 | 24 | o_wb_ibus_adr: Carries address of instruction to memory. In case of misaligned access, 25 | which is caused by pc+2 due to compressed instruction, next instruction is fetched 26 | by pc+4 and concatenation is done to make the instruction aligned. 27 | 28 | o_wb_ibus_cyc: Simply forwarded from SERV to Memory and is only altered by memory or SERV core. 29 | */ 30 | assign o_wb_ibus_adr = ctrl_misal ? (i_ibus_adr+32'b100) : i_ibus_adr; 31 | assign o_wb_ibus_cyc = i_ibus_cyc; 32 | 33 | /* From Memory to SERV core 34 | 35 | o_ibus_ack: Instruction bus acknowledge is send to SERV only when the aligned instruction, 36 | either compressed or un-compressed, is ready to dispatch. 37 | 38 | o_ibus_rdt: Carries the instruction from memory to SERV core. It can be either aligned 39 | instruction coming from memory or made aligned by two bus transactions and concatenation. 40 | */ 41 | assign o_ibus_ack = i_wb_ibus_ack & ack_en; 42 | assign o_ibus_rdt = ctrl_misal ? ibus_rdt_concat : i_wb_ibus_rdt; 43 | 44 | /* 16-bit register used to hold the upper half word of the current instruction in-case 45 | concatenation will be required with the upper half word of upcoming instruction 46 | */ 47 | always @(posedge clk) begin 48 | if(i_wb_ibus_ack)begin 49 | lower_hw <= i_wb_ibus_rdt[31:16]; 50 | end 51 | end 52 | 53 | assign ibus_rdt_concat = {i_wb_ibus_rdt[15:0],lower_hw}; 54 | 55 | /* Two control signals: ack_en, ctrl_misal are set to control the bus transactions between 56 | SERV core and the memory 57 | */ 58 | assign ack_en = !(i_ibus_adr[1] & !ctrl_misal); 59 | 60 | always @(posedge clk ) begin 61 | if(rst) 62 | ctrl_misal <= 0; 63 | else if(i_wb_ibus_ack & i_ibus_adr[1]) 64 | ctrl_misal <= !ctrl_misal; 65 | end 66 | 67 | endmodule 68 | -------------------------------------------------------------------------------- /rtl/serv_alu.v: -------------------------------------------------------------------------------- 1 | `default_nettype none 2 | module serv_alu 3 | #( 4 | parameter W = 1, 5 | parameter B = W-1 6 | ) 7 | ( 8 | input wire clk, 9 | //State 10 | input wire i_en, 11 | input wire i_cnt0, 12 | output wire o_cmp, 13 | //Control 14 | input wire i_sub, 15 | input wire [1:0] i_bool_op, 16 | input wire i_cmp_eq, 17 | input wire i_cmp_sig, 18 | input wire [2:0] i_rd_sel, 19 | //Data 20 | input wire [B:0] i_rs1, 21 | input wire [B:0] i_op_b, 22 | input wire [B:0] i_buf, 23 | output wire [B:0] o_rd); 24 | 25 | wire [B:0] result_add; 26 | wire [B:0] result_slt; 27 | 28 | reg cmp_r; 29 | 30 | wire add_cy; 31 | reg [B:0] add_cy_r; 32 | 33 | //Sign-extended operands 34 | wire rs1_sx = i_rs1[B] & i_cmp_sig; 35 | wire op_b_sx = i_op_b[B] & i_cmp_sig; 36 | 37 | wire [B:0] add_b = i_op_b^{W{i_sub}}; 38 | 39 | assign {add_cy,result_add} = i_rs1+add_b+add_cy_r; 40 | 41 | wire result_lt = rs1_sx + ~op_b_sx + add_cy; 42 | 43 | wire result_eq = !(|result_add) & (cmp_r | i_cnt0); 44 | 45 | assign o_cmp = i_cmp_eq ? result_eq : result_lt; 46 | 47 | /* 48 | The result_bool expression implements the following operations between 49 | i_rs1 and i_op_b depending on the value of i_bool_op 50 | 51 | 00 xor 52 | 01 0 53 | 10 or 54 | 11 and 55 | 56 | i_bool_op will be 01 during shift operations, so by outputting zero under 57 | this condition we can safely or result_bool with i_buf 58 | */ 59 | 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); 60 | 61 | assign result_slt[0] = cmp_r & i_cnt0; 62 | generate 63 | if (W>1) begin : gen_w_gt_1 64 | assign result_slt[B:1] = {B{1'b0}}; 65 | end 66 | endgenerate 67 | 68 | assign o_rd = i_buf | 69 | ({W{i_rd_sel[0]}} & result_add) | 70 | ({W{i_rd_sel[1]}} & result_slt) | 71 | ({W{i_rd_sel[2]}} & result_bool); 72 | 73 | always @(posedge clk) begin 74 | add_cy_r <= {W{1'b0}}; 75 | add_cy_r[0] <= i_en ? add_cy : i_sub; 76 | 77 | if (i_en) 78 | cmp_r <= o_cmp; 79 | end 80 | 81 | endmodule 82 | -------------------------------------------------------------------------------- /rtl/serv_bufreg.v: -------------------------------------------------------------------------------- 1 | module serv_bufreg #( 2 | parameter [0:0] MDU = 0, 3 | parameter W = 1, 4 | parameter B = W-1 5 | )( 6 | input wire i_clk, 7 | //State 8 | input wire i_cnt0, 9 | input wire i_cnt1, 10 | input wire i_cnt_done, 11 | input wire i_en, 12 | input wire i_init, 13 | input wire i_mdu_op, 14 | output wire [1:0] o_lsb, 15 | //Control 16 | input wire i_rs1_en, 17 | input wire i_imm_en, 18 | input wire i_clr_lsb, 19 | input wire i_shift_op, 20 | input wire i_right_shift_op, 21 | input wire [2:0] i_shamt, 22 | input wire i_sh_signed, 23 | //Data 24 | input wire [B:0] i_rs1, 25 | input wire [B:0] i_imm, 26 | output wire [B:0] o_q, 27 | //External 28 | output wire [31:0] o_dbus_adr, 29 | //Extension 30 | output wire [31:0] o_ext_rs1); 31 | 32 | wire c; 33 | wire [B:0] q; 34 | reg [B:0] c_r; 35 | reg [31:0] data; 36 | wire [B:0] clr_lsb; 37 | 38 | assign clr_lsb[0] = i_cnt0 & i_clr_lsb; 39 | 40 | generate 41 | if (W > 1) begin : gen_clr_lsb_w_gt_1 42 | assign clr_lsb[B:1] = {B{1'b0}}; 43 | end 44 | endgenerate 45 | 46 | assign {c,q} = {1'b0,(i_rs1 & {W{i_rs1_en}})} + {1'b0,(i_imm & {W{i_imm_en}} & ~clr_lsb)} + c_r; 47 | 48 | always @(posedge i_clk) begin 49 | //Make sure carry is cleared before loading new data 50 | c_r <= {W{1'b0}}; 51 | c_r[0] <= c & i_en; 52 | end 53 | 54 | generate 55 | if (W == 1) begin : gen_w_eq_1 56 | always @(posedge i_clk) begin 57 | if (i_en) 58 | data[31:2] <= {i_init ? q : {W{data[31] & i_sh_signed}}, data[31:3]}; 59 | 60 | if (i_init ? (i_cnt0 | i_cnt1) : i_en) 61 | data[1:0] <= {i_init ? q : data[2], data[1]}; 62 | end 63 | assign o_lsb = (MDU & i_mdu_op) ? 2'b00 : data[1:0]; 64 | assign o_q = data[0] & {W{i_en}}; 65 | end else if (W == 4) begin : gen_lsb_w_4 66 | reg [1:0] lsb; 67 | reg [W-2:0] data_tail; 68 | 69 | wire [2:0] shift_amount 70 | = !i_shift_op ? 3'd3 : 71 | i_right_shift_op ? (3'd3+{1'b0,i_shamt[1:0]}) : 72 | ({1'b0,~i_shamt[1:0]}); 73 | 74 | always @(posedge i_clk) begin 75 | if (i_en) 76 | if (i_cnt0) lsb <= q[1:0]; 77 | if (i_en) 78 | data <= {i_init ? q : {W{i_sh_signed & data[31]}}, data[31:W]}; 79 | if (i_en) 80 | data_tail <= data[B:1] & {B{~i_cnt_done}}; 81 | end 82 | 83 | wire [2*W+B-2:0] muxdata = {data[W+B-1:0],data_tail}; 84 | wire [B:0] muxout = muxdata[{1'b0,shift_amount}+:W]; 85 | 86 | assign o_lsb = (MDU & i_mdu_op) ? 2'b00 : lsb; 87 | assign o_q = i_en ? muxout : {W{1'b0}}; 88 | end 89 | endgenerate 90 | 91 | 92 | assign o_dbus_adr = {data[31:2], 2'b00}; 93 | assign o_ext_rs1 = data; 94 | 95 | endmodule 96 | -------------------------------------------------------------------------------- /rtl/serv_bufreg2.v: -------------------------------------------------------------------------------- 1 | module serv_bufreg2 2 | #(parameter W = 1, 3 | //Internally calculated. Do not touch 4 | parameter B=W-1) 5 | ( 6 | input wire i_clk, 7 | //State 8 | input wire i_en, 9 | input wire i_init, 10 | input wire i_cnt7, 11 | input wire i_cnt_done, 12 | input wire i_sh_right, 13 | input wire [1:0] i_lsb, 14 | input wire [1:0] i_bytecnt, 15 | output wire o_sh_done, 16 | //Control 17 | input wire i_op_b_sel, 18 | input wire i_shift_op, 19 | //Data 20 | input wire [B:0] i_rs2, 21 | input wire [B:0] i_imm, 22 | output wire [B:0] o_op_b, 23 | output wire [B:0] o_q, 24 | //External 25 | output wire [31:0] o_dat, 26 | input wire i_load, 27 | input wire [31:0] i_dat); 28 | 29 | // High and low data words form a 32-bit word 30 | reg [7:0] dhi; 31 | reg [23:0] dlo; 32 | 33 | /* 34 | Before a store operation, the data to be written needs to be shifted into 35 | place. Depending on the address alignment, we need to shift different 36 | amounts. One formula for calculating this is to say that we shift when 37 | i_lsb + i_bytecnt < 4. Unfortunately, the synthesis tools don't seem to be 38 | clever enough so the hideous expression below is used to achieve the same 39 | thing in a more optimal way. 40 | */ 41 | wire byte_valid 42 | = (!i_lsb[0] & !i_lsb[1]) | 43 | (!i_bytecnt[0] & !i_bytecnt[1]) | 44 | (!i_bytecnt[1] & !i_lsb[1]) | 45 | (!i_bytecnt[1] & !i_lsb[0]) | 46 | (!i_bytecnt[0] & !i_lsb[1]); 47 | 48 | assign o_op_b = i_op_b_sel ? i_rs2 : i_imm; 49 | 50 | wire shift_en = i_shift_op ? (i_en & i_init & (i_bytecnt == 2'b00)) : (i_en & byte_valid); 51 | 52 | wire cnt_en = (i_shift_op & (!i_init | (i_cnt_done & i_sh_right))); 53 | 54 | /* The dat register has three different use cases for store, load and 55 | shift operations. 56 | store : Data to be written is shifted to the correct position in dat during 57 | init by shift_en and is presented on the data bus as o_wb_dat 58 | load : Data from the bus gets latched into dat during i_wb_ack and is then 59 | shifted out at the appropriate time to end up in the correct 60 | position in rd 61 | shift : Data is shifted in during init. After that, the six LSB are used as 62 | a downcounter (with bit 5 initially set to 0) that trigger 63 | o_sh_done when they wrap around to indicate that 64 | the requested number of shifts have been performed 65 | */ 66 | 67 | wire [7:0] cnt_next; 68 | generate 69 | if (W == 1) begin : gen_cnt_w_eq_1 70 | assign cnt_next = {o_op_b, dhi[7], dhi[5:0]-6'd1}; 71 | end else if (W == 4) begin : gen_cnt_w_eq_4 72 | assign cnt_next = {o_op_b[3:2], dhi[5:0]-6'd4}; 73 | end 74 | endgenerate 75 | 76 | wire [7:0] dat_shamt = cnt_en ? 77 | //Down counter mode 78 | cnt_next : 79 | //Shift reg mode 80 | {o_op_b, dhi[7:W]}; 81 | 82 | assign o_sh_done = dat_shamt[5]; 83 | 84 | assign o_q = 85 | ({W{(i_lsb == 2'd3)}} & o_dat[W+23:24]) | 86 | ({W{(i_lsb == 2'd2)}} & o_dat[W+15:16]) | 87 | ({W{(i_lsb == 2'd1)}} & o_dat[W+7:8]) | 88 | ({W{(i_lsb == 2'd0)}} & o_dat[W-1:0]); 89 | 90 | assign o_dat = {dhi,dlo}; 91 | 92 | always @(posedge i_clk) begin 93 | if (shift_en | cnt_en | i_load) 94 | dhi <= i_load ? i_dat[31:24] : dat_shamt & {2'b11, !(i_shift_op & i_cnt7 & !cnt_en), 5'b11111}; 95 | if (shift_en | i_load) 96 | dlo <= i_load ? i_dat[23:0] : {dhi[B:0], dlo[23:W]}; 97 | end 98 | 99 | endmodule 100 | -------------------------------------------------------------------------------- /rtl/serv_ctrl.v: -------------------------------------------------------------------------------- 1 | `default_nettype none 2 | module serv_ctrl 3 | #(parameter RESET_STRATEGY = "MINI", 4 | parameter RESET_PC = 32'd0, 5 | parameter WITH_CSR = 1, 6 | parameter W = 1, 7 | parameter B = W-1 8 | ) 9 | ( 10 | input wire clk, 11 | input wire i_rst, 12 | //State 13 | input wire i_pc_en, 14 | input wire i_cnt12to31, 15 | input wire i_cnt0, 16 | input wire i_cnt1, 17 | input wire i_cnt2, 18 | //Control 19 | input wire i_jump, 20 | input wire i_jal_or_jalr, 21 | input wire i_utype, 22 | input wire i_pc_rel, 23 | input wire i_trap, 24 | input wire i_iscomp, 25 | //Data 26 | input wire [B:0] i_imm, 27 | input wire [B:0] i_buf, 28 | input wire [B:0] i_csr_pc, 29 | output wire [B:0] o_rd, 30 | output wire [B:0] o_bad_pc, 31 | //External 32 | output reg [31:0] o_ibus_adr); 33 | 34 | wire [B:0] pc_plus_4; 35 | wire pc_plus_4_cy; 36 | reg pc_plus_4_cy_r; 37 | wire [B:0] pc_plus_4_cy_r_w; 38 | wire [B:0] pc_plus_offset; 39 | wire pc_plus_offset_cy; 40 | reg pc_plus_offset_cy_r; 41 | wire [B:0] pc_plus_offset_cy_r_w; 42 | wire [B:0] pc_plus_offset_aligned; 43 | wire [B:0] plus_4; 44 | 45 | wire [B:0] pc = o_ibus_adr[B:0]; 46 | 47 | wire [B:0] new_pc; 48 | 49 | wire [B:0] offset_a; 50 | wire [B:0] offset_b; 51 | 52 | /* If i_iscomp=1: increment pc by 2 else increment pc by 4 */ 53 | 54 | generate 55 | if (W == 1) begin : gen_plus_4_w_eq_1 56 | assign plus_4 = i_iscomp ? i_cnt1 : i_cnt2; 57 | end else if (W == 4) begin : gen_plus_4_w_eq_4 58 | assign plus_4 = (i_cnt0 | i_cnt1) ? (i_iscomp ? 2 : 4) : 0; 59 | end 60 | endgenerate 61 | 62 | assign o_bad_pc = pc_plus_offset_aligned; 63 | 64 | assign {pc_plus_4_cy,pc_plus_4} = pc+plus_4+pc_plus_4_cy_r_w; 65 | 66 | generate 67 | if (|WITH_CSR) begin : gen_csr 68 | if (W == 1) begin : gen_new_pc_w_eq_1 69 | assign new_pc = i_trap ? (i_csr_pc & !(i_cnt0 || i_cnt1)) : i_jump ? pc_plus_offset_aligned : pc_plus_4; 70 | end else if (W == 4) begin : gen_new_pc_w_eq_4 71 | 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; 72 | end 73 | end else begin : gen_no_csr 74 | assign new_pc = i_jump ? pc_plus_offset_aligned : pc_plus_4; 75 | end 76 | endgenerate 77 | assign o_rd = ({W{i_utype}} & pc_plus_offset_aligned) | (pc_plus_4 & {W{i_jal_or_jalr}}); 78 | 79 | assign offset_a = {W{i_pc_rel}} & pc; 80 | assign offset_b = i_utype ? (i_imm & {W{i_cnt12to31}}) : i_buf; 81 | assign {pc_plus_offset_cy,pc_plus_offset} = offset_a+offset_b+pc_plus_offset_cy_r_w; 82 | 83 | generate 84 | if (W>1) begin : gen_w_gt_1 85 | assign pc_plus_offset_aligned[B:1] = pc_plus_offset[B:1]; 86 | assign pc_plus_offset_cy_r_w[B:1] = {B{1'b0}}; 87 | assign pc_plus_4_cy_r_w[B:1] = {B{1'b0}}; 88 | end 89 | endgenerate 90 | 91 | assign pc_plus_offset_aligned[0] = pc_plus_offset[0] & !i_cnt0; 92 | assign pc_plus_offset_cy_r_w[0] = pc_plus_offset_cy_r; 93 | assign pc_plus_4_cy_r_w[0] = pc_plus_4_cy_r; 94 | 95 | initial if (RESET_STRATEGY == "NONE") o_ibus_adr = RESET_PC; 96 | 97 | always @(posedge clk) begin 98 | pc_plus_4_cy_r <= i_pc_en & pc_plus_4_cy; 99 | pc_plus_offset_cy_r <= i_pc_en & pc_plus_offset_cy; 100 | 101 | if (RESET_STRATEGY == "NONE") begin 102 | if (i_pc_en) 103 | o_ibus_adr <= {new_pc, o_ibus_adr[31:W]}; 104 | end else begin 105 | if (i_pc_en | i_rst) 106 | o_ibus_adr <= i_rst ? RESET_PC : {new_pc, o_ibus_adr[31:W]}; 107 | end 108 | end 109 | endmodule 110 | -------------------------------------------------------------------------------- /rtl/serv_mem_if.v: -------------------------------------------------------------------------------- 1 | `default_nettype none 2 | module serv_mem_if 3 | #( 4 | parameter [0:0] WITH_CSR = 1, 5 | parameter W = 1, 6 | parameter B = W-1 7 | ) 8 | ( 9 | input wire i_clk, 10 | //State 11 | input wire [1:0] i_bytecnt, 12 | input wire [1:0] i_lsb, 13 | output wire o_misalign, 14 | //Control 15 | input wire i_signed, 16 | input wire i_word, 17 | input wire i_half, 18 | //MDU 19 | input wire i_mdu_op, 20 | //Data 21 | input wire [B:0] i_bufreg2_q, 22 | output wire [B:0] o_rd, 23 | //External interface 24 | output wire [3:0] o_wb_sel); 25 | 26 | reg signbit; 27 | 28 | wire dat_valid = 29 | i_mdu_op | 30 | i_word | 31 | (i_bytecnt == 2'b00) | 32 | (i_half & !i_bytecnt[1]); 33 | 34 | assign o_rd = dat_valid ? i_bufreg2_q : {W{i_signed & signbit}}; 35 | 36 | assign o_wb_sel[3] = (i_lsb == 2'b11) | i_word | (i_half & i_lsb[1]); 37 | assign o_wb_sel[2] = (i_lsb == 2'b10) | i_word; 38 | assign o_wb_sel[1] = (i_lsb == 2'b01) | i_word | (i_half & !i_lsb[1]); 39 | assign o_wb_sel[0] = (i_lsb == 2'b00); 40 | 41 | always @(posedge i_clk) begin 42 | if (dat_valid) 43 | signbit <= i_bufreg2_q[B]; 44 | end 45 | 46 | /* 47 | mem_misalign is checked after the init stage to decide whether to do a data 48 | bus transaction or go to the trap state. It is only guaranteed to be correct 49 | at this time 50 | */ 51 | assign o_misalign = WITH_CSR & ((i_lsb[0] & (i_word | i_half)) | (i_lsb[1] & i_word)); 52 | 53 | endmodule 54 | -------------------------------------------------------------------------------- /rtl/serv_rf_if.v: -------------------------------------------------------------------------------- 1 | `default_nettype none 2 | module serv_rf_if 3 | #(parameter WITH_CSR = 1, 4 | parameter W = 1, 5 | parameter B = W-1 6 | ) 7 | (//RF Interface 8 | input wire i_cnt_en, 9 | output wire [4+WITH_CSR:0] o_wreg0, 10 | output wire [4+WITH_CSR:0] o_wreg1, 11 | output wire o_wen0, 12 | output wire o_wen1, 13 | output wire [B:0] o_wdata0, 14 | output wire [B:0] o_wdata1, 15 | output wire [4+WITH_CSR:0] o_rreg0, 16 | output wire [4+WITH_CSR:0] o_rreg1, 17 | input wire [B:0] i_rdata0, 18 | input wire [B:0] i_rdata1, 19 | 20 | //Trap interface 21 | input wire i_trap, 22 | input wire i_mret, 23 | input wire [B:0] i_mepc, 24 | input wire i_mtval_pc, 25 | input wire [B:0] i_bufreg_q, 26 | input wire [B:0] i_bad_pc, 27 | output wire [B:0] o_csr_pc, 28 | //CSR interface 29 | input wire i_csr_en, 30 | input wire [1:0] i_csr_addr, 31 | input wire [B:0] i_csr, 32 | output wire [B:0] o_csr, 33 | //RD write port 34 | input wire i_rd_wen, 35 | input wire [4:0] i_rd_waddr, 36 | input wire [B:0] i_ctrl_rd, 37 | input wire [B:0] i_alu_rd, 38 | input wire i_rd_alu_en, 39 | input wire [B:0] i_csr_rd, 40 | input wire i_rd_csr_en, 41 | input wire [B:0] i_mem_rd, 42 | input wire i_rd_mem_en, 43 | 44 | //RS1 read port 45 | input wire [4:0] i_rs1_raddr, 46 | output wire [B:0] o_rs1, 47 | //RS2 read port 48 | input wire [4:0] i_rs2_raddr, 49 | output wire [B:0] o_rs2); 50 | 51 | 52 | /* 53 | ********** Write side *********** 54 | */ 55 | 56 | wire rd_wen = i_rd_wen & (|i_rd_waddr); 57 | 58 | generate 59 | if (|WITH_CSR) begin : gen_csr 60 | wire [B:0] rd = 61 | {W{i_rd_alu_en}} & i_alu_rd | 62 | {W{i_rd_csr_en}} & i_csr_rd | 63 | {W{i_rd_mem_en}} & i_mem_rd | 64 | i_ctrl_rd; 65 | 66 | wire [B:0] mtval = i_mtval_pc ? i_bad_pc : i_bufreg_q; 67 | 68 | assign o_wdata0 = i_trap ? mtval : rd; 69 | assign o_wdata1 = i_trap ? i_mepc : i_csr; 70 | 71 | /* Port 0 handles writes to mtval during traps and rd otherwise 72 | * Port 1 handles writes to mepc during traps and csr accesses otherwise 73 | * 74 | * GPR registers are mapped to address 0-31 (bits 0xxxxx). 75 | * Following that are four CSR registers 76 | * mscratch 100000 77 | * mtvec 100001 78 | * mepc 100010 79 | * mtval 100011 80 | */ 81 | 82 | assign o_wreg0 = i_trap ? {6'b100011} : {1'b0,i_rd_waddr}; 83 | assign o_wreg1 = i_trap ? {6'b100010} : {4'b1000,i_csr_addr}; 84 | 85 | assign o_wen0 = i_cnt_en & (i_trap | rd_wen); 86 | assign o_wen1 = i_cnt_en & (i_trap | i_csr_en); 87 | 88 | /* 89 | ********** Read side *********** 90 | */ 91 | 92 | //0 : RS1 93 | //1 : RS2 / CSR 94 | 95 | assign o_rreg0 = {1'b0, i_rs1_raddr}; 96 | 97 | /* 98 | The address of the second read port (o_rreg1) can get assigned from four 99 | different sources 100 | 101 | Normal operations : i_rs2_raddr 102 | CSR access : i_csr_addr 103 | trap : MTVEC 104 | mret : MEPC 105 | 106 | Address 0-31 in the RF are assigned to the GPRs. After that follows the four 107 | CSRs on addresses 32-35 108 | 109 | 32 MSCRATCH 110 | 33 MTVEC 111 | 34 MEPC 112 | 35 MTVAL 113 | 114 | The expression below is an optimized version of this logic 115 | */ 116 | wire sel_rs2 = !(i_trap | i_mret | i_csr_en); 117 | assign o_rreg1 = {~sel_rs2, 118 | i_rs2_raddr[4:2] & {3{sel_rs2}}, 119 | {1'b0,i_trap} | {i_mret,1'b0} | ({2{i_csr_en}} & i_csr_addr) | ({2{sel_rs2}} & i_rs2_raddr[1:0])}; 120 | 121 | assign o_rs1 = i_rdata0; 122 | assign o_rs2 = i_rdata1; 123 | assign o_csr = i_rdata1 & {W{i_csr_en}}; 124 | assign o_csr_pc = i_rdata1; 125 | 126 | end else begin : gen_no_csr 127 | wire [B:0] rd = (i_ctrl_rd) | 128 | i_alu_rd & {W{i_rd_alu_en}} | 129 | i_mem_rd & {W{i_rd_mem_en}}; 130 | 131 | assign o_wdata0 = rd; 132 | assign o_wdata1 = {W{1'b0}}; 133 | 134 | assign o_wreg0 = i_rd_waddr; 135 | assign o_wreg1 = 5'd0; 136 | 137 | assign o_wen0 = i_cnt_en & rd_wen; 138 | assign o_wen1 = 1'b0; 139 | 140 | /* 141 | ********** Read side *********** 142 | */ 143 | 144 | assign o_rreg0 = i_rs1_raddr; 145 | assign o_rreg1 = i_rs2_raddr; 146 | 147 | assign o_rs1 = i_rdata0; 148 | assign o_rs2 = i_rdata1; 149 | assign o_csr = {W{1'b0}}; 150 | assign o_csr_pc = {W{1'b0}}; 151 | end // else: !if(WITH_CSR) 152 | endgenerate 153 | endmodule 154 | -------------------------------------------------------------------------------- /rtl/serv_rf_ram.v: -------------------------------------------------------------------------------- 1 | module serv_rf_ram 2 | #(parameter width=0, 3 | parameter csr_regs=4, 4 | parameter depth=32*(32+csr_regs)/width) 5 | (input wire i_clk, 6 | input wire [$clog2(depth)-1:0] i_waddr, 7 | input wire [width-1:0] i_wdata, 8 | input wire i_wen, 9 | input wire [$clog2(depth)-1:0] i_raddr, 10 | input wire i_ren, 11 | output wire [width-1:0] o_rdata); 12 | 13 | reg [width-1:0] memory [0:depth-1]; 14 | reg [width-1:0] rdata ; 15 | 16 | always @(posedge i_clk) begin 17 | if (i_wen) 18 | memory[i_waddr] <= i_wdata; 19 | rdata <= i_ren ? memory[i_raddr] : {width{1'bx}}; 20 | end 21 | 22 | /* Reads from reg x0 needs to return 0 23 | Check that the part of the read address corresponding to the register 24 | is zero and gate the output 25 | width LSB of reg index $clog2(width) 26 | 2 4 1 27 | 4 3 2 28 | 8 2 3 29 | 16 1 4 30 | 32 0 5 31 | */ 32 | reg regzero; 33 | 34 | always @(posedge i_clk) 35 | regzero <= !(|i_raddr[$clog2(depth)-1:5-$clog2(width)]); 36 | 37 | assign o_rdata = rdata & ~{width{regzero}}; 38 | 39 | `ifdef SERV_CLEAR_RAM 40 | integer i; 41 | initial 42 | for (i=0;i 32MHz 19 | SB_PLL40_CORE #( 20 | .FEEDBACK_PATH("SIMPLE"), 21 | .DIVR(4'b0010), // DIVR = 2 22 | .DIVF(7'b0111111), // DIVF = 63 23 | .DIVQ(3'b101), // DIVQ = 5 24 | .FILTER_RANGE(3'b001) // FILTER_RANGE = 1 25 | ) uut ( 26 | .LOCK(locked), 27 | .RESETB(1'b1), 28 | .BYPASS(1'b0), 29 | .REFERENCECLK(clk48), 30 | .PLLOUTCORE(clk32) 31 | ); 32 | 33 | always @(posedge clk32) 34 | rst <= !locked; 35 | 36 | servant 37 | #(.memfile (memfile), 38 | .memsize (memsize)) 39 | servant 40 | (.wb_clk (clk32), 41 | .wb_rst (rst), 42 | .q (tx)); 43 | 44 | assign led = tx; 45 | 46 | endmodule 47 | -------------------------------------------------------------------------------- /servant/servant_mux.v: -------------------------------------------------------------------------------- 1 | /* 2 | mem = 00 3 | gpio = 01 4 | timer = 10 5 | testcon = 11 6 | */ 7 | module servant_mux 8 | ( 9 | input wire i_clk, 10 | input wire i_rst, 11 | input wire [31:0] i_wb_cpu_adr, 12 | input wire [31:0] i_wb_cpu_dat, 13 | input wire [3:0] i_wb_cpu_sel, 14 | input wire i_wb_cpu_we, 15 | input wire i_wb_cpu_cyc, 16 | output wire [31:0] o_wb_cpu_rdt, 17 | output reg o_wb_cpu_ack, 18 | 19 | output wire o_wb_gpio_dat, 20 | output wire o_wb_gpio_we, 21 | output wire o_wb_gpio_cyc, 22 | input wire i_wb_gpio_rdt, 23 | 24 | output wire [31:0] o_wb_timer_dat, 25 | output wire o_wb_timer_we, 26 | output wire o_wb_timer_cyc, 27 | input wire [31:0] i_wb_timer_rdt); 28 | 29 | parameter sim = 0; 30 | 31 | wire [1:0] s = i_wb_cpu_adr[31:30]; 32 | 33 | assign o_wb_cpu_rdt = s[1] ? i_wb_timer_rdt : {31'd0,i_wb_gpio_rdt}; 34 | 35 | always @(posedge i_clk) begin 36 | o_wb_cpu_ack <= 1'b0; 37 | if (i_wb_cpu_cyc & !o_wb_cpu_ack) 38 | o_wb_cpu_ack <= 1'b1; 39 | if (i_rst) 40 | o_wb_cpu_ack <= 1'b0; 41 | end 42 | 43 | assign o_wb_gpio_dat = i_wb_cpu_dat[0]; 44 | assign o_wb_gpio_we = i_wb_cpu_we; 45 | assign o_wb_gpio_cyc = i_wb_cpu_cyc & !s[1]; 46 | 47 | assign o_wb_timer_dat = i_wb_cpu_dat; 48 | assign o_wb_timer_we = i_wb_cpu_we; 49 | assign o_wb_timer_cyc = i_wb_cpu_cyc & s[1]; 50 | 51 | endmodule 52 | -------------------------------------------------------------------------------- /servant/servant_orangecrab.v: -------------------------------------------------------------------------------- 1 | `default_nettype none 2 | module servant_orangecrab 3 | ( 4 | input wire clk, 5 | input wire btn, 6 | output wire r, 7 | output wire g, 8 | output wire b, 9 | output wire tx 10 | ); 11 | 12 | parameter memfile = "zephyr_hello.hex"; 13 | parameter memsize = 8192; 14 | 15 | wire wb_clk; 16 | wire pll_locked; 17 | EHXPLLL #( 18 | .CLKI_DIV(6), 19 | .CLKFB_DIV(4), 20 | .CLKOP_DIV(15), 21 | .CLKOS_DIV(8), 22 | .CLKOS2_DIV(8), 23 | .CLKOS3_DIV(8), 24 | .CLKOP_ENABLE("ENABLED"), 25 | .CLKOS_ENABLE("DISABLED"), 26 | .CLKOS2_ENABLE("DISABLED"), 27 | .CLKOS3_ENABLE("DISABLED"), 28 | .CLKOP_CPHASE(0), 29 | .CLKOS_CPHASE(0), 30 | .CLKOS2_CPHASE(0), 31 | .CLKOS3_CPHASE(0), 32 | .CLKOP_FPHASE(0), 33 | .CLKOS_FPHASE(0), 34 | .CLKOS2_FPHASE(0), 35 | .CLKOS3_FPHASE(0), 36 | .FEEDBK_PATH("CLKOP"), 37 | .CLKOP_TRIM_POL("RISING"), 38 | .CLKOP_TRIM_DELAY(0), 39 | .CLKOS_TRIM_POL("RISING"), 40 | .CLKOS_TRIM_DELAY(0), 41 | .OUTDIVIDER_MUXA("DIVA"), 42 | .OUTDIVIDER_MUXB("DIVB"), 43 | .OUTDIVIDER_MUXC("DIVC"), 44 | .OUTDIVIDER_MUXD("DIVD"), 45 | .PLL_LOCK_MODE(0), 46 | .PLL_LOCK_DELAY(200), 47 | .STDBY_ENABLE("DISABLED"), 48 | .REFIN_RESET("DISABLED"), 49 | .SYNC_ENABLE("DISABLED"), 50 | .INT_LOCK_STICKY("ENABLED"), 51 | .DPHASE_SOURCE("DISABLED"), 52 | .PLLRST_ENA("DISABLED"), 53 | .INTFB_WAKE("DISABLED") 54 | ) uPLL ( 55 | .CLKI(clk), // ref input 56 | .CLKFB(wb_clk), // ext fb input 57 | .PHASESEL1(0), // msbit phs adj select 58 | .PHASESEL0(0), // lsbit phs adj select 59 | .PHASEDIR(0), // phs adj dir 60 | .PHASESTEP(0), // phs adj step 61 | .PHASELOADREG(0), // load phs adj 62 | .STDBY(0), // power down pll 63 | .PLLWAKESYNC(0), // int/ext fb switching @ wakeup 64 | .RST(0), // pll reset 65 | .ENCLKOP(1), // primary output enable 66 | .ENCLKOS(0), // secondary output enable 67 | .ENCLKOS2(0), // secondary output enable 68 | .ENCLKOS3(0), // secondary output enable 69 | .CLKOP(wb_clk), // primary output 70 | .CLKOS(), // secondary output 71 | .CLKOS2(), // secondary output 72 | .CLKOS3(), // secondary output 73 | .LOCK(pll_locked), // lock indicator 74 | .INTLOCK(), // internal lock indicator 75 | .REFCLK(), // output of ref select mux 76 | .CLKINTFB() // internal fb 77 | ); 78 | 79 | reg wb_rst; 80 | always @(posedge wb_clk) 81 | wb_rst <= ~pll_locked; 82 | 83 | wire q; 84 | servant 85 | #(.memfile (memfile), 86 | .memsize (memsize)) 87 | servant 88 | (.wb_clk (wb_clk), 89 | .wb_rst (wb_rst), 90 | .q (q)); 91 | 92 | assign r = q; 93 | assign g = q; 94 | assign b = q; 95 | assign tx = q; 96 | endmodule 97 | -------------------------------------------------------------------------------- /servant/servant_pf.v: -------------------------------------------------------------------------------- 1 | `default_nettype none 2 | 3 | module servant_pf ( 4 | input wire i_clk, 5 | input wire resetb, 6 | output wire o_led1, 7 | output wire o_led2, 8 | output wire o_led3 = 1'b0, 9 | output wire o_led4 = 1'b0, 10 | output wire o_led5 = 1'b0, 11 | output wire o_led6 = 1'b0, 12 | output wire o_led7 = 1'b0, 13 | output wire o_led8 = 1'b0, 14 | output wire o_uart_tx); 15 | 16 | parameter memfile = "zephyr_hello.hex"; 17 | parameter memsize = 8192; 18 | 19 | wire clk; 20 | wire rst; 21 | wire q; 22 | wire CLKINT_0_Y; 23 | reg heartbeat; 24 | 25 | CLKINT CLKINT_0( 26 | .A (i_clk), 27 | .Y (CLKINT_0_Y) 28 | ); 29 | 30 | servant_pf_clock_gen #( 31 | .refclk(50), 32 | .frequency(32) 33 | ) clock_gen ( 34 | .i_clk (CLKINT_0_Y), 35 | .o_clk (clk) 36 | ); 37 | 38 | servant #( 39 | .memfile (memfile), 40 | .memsize (memsize) 41 | ) servant ( 42 | .wb_clk (clk), 43 | .wb_rst (rst), 44 | .q (q) 45 | ); 46 | 47 | // heartbeat LED 48 | reg [$clog2(32000000)-1:0] count = 0; 49 | always @(posedge clk) begin 50 | if (rst) begin 51 | count <= 0; 52 | heartbeat <= 0; 53 | end else 54 | count <= count + 1; 55 | if (count == 32000000-1) begin 56 | heartbeat <= !heartbeat; 57 | count <= 0; 58 | end 59 | end 60 | 61 | assign rst = ~resetb; 62 | assign o_led1 = q; 63 | assign o_led2 = heartbeat; 64 | assign o_uart_tx = q; 65 | 66 | endmodule 67 | -------------------------------------------------------------------------------- /servant/servant_pf_clock_gen.v: -------------------------------------------------------------------------------- 1 | `timescale 1 ns/100 ps 2 | 3 | module servant_pf_clock_gen( 4 | input wire i_clk, 5 | output wire o_clk, 6 | output reg o_lock); 7 | 8 | // for documentation 9 | parameter refclk = 50; 10 | parameter frequency = 32; 11 | 12 | // PLL in internal Post-VCO Feedback mode 13 | localparam [11:0] fbdiv = 12'b100111000000; // 2496 14 | localparam [5:0] rfdiv = 6'b011001; // 25; 15 | localparam vco = 4992; // refclk * fbdiv / rfdiv; 16 | localparam [6:0] odiv = 7'b0100111; // vco / (4 * frequency); 17 | 18 | wire gnd_net, vcc_net, pll_inst_0_clkint_0; 19 | wire nc0, nc1, nc2, nc3, nc4, nc5, nc6, nc7, nc8, nc9, nc10, nc11, nc12, 20 | nc13, nc14, nc15, nc16, nc17, nc18, nc19, nc20, nc21, nc22, nc23, 21 | nc24, nc25, nc26, nc27, nc28, nc29, nc30, nc31, nc32, nc33, nc34, 22 | nc35, nc36, nc37, nc38, nc39, nc40; 23 | 24 | VCC vcc_inst (.Y(vcc_net)); 25 | GND gnd_inst (.Y(gnd_net)); 26 | 27 | PLL #( 28 | .VCOFREQUENCY(vco), 29 | .DELAY_LINE_SIMULATION_MODE(""), 30 | .DATA_RATE(0.0), 31 | .FORMAL_NAME(""), 32 | .INTERFACE_NAME(""), 33 | .INTERFACE_LEVEL(3'b0), 34 | .SOFTRESET(1'b0), 35 | .SOFT_POWERDOWN_N(1'b1), 36 | .RFDIV_EN(1'b1), 37 | .OUT0_DIV_EN(1'b1), 38 | .OUT1_DIV_EN(1'b0), 39 | .OUT2_DIV_EN(1'b0), 40 | .OUT3_DIV_EN(1'b0), 41 | .SOFT_REF_CLK_SEL(1'b0), 42 | .RESET_ON_LOCK(1'b1), 43 | .BYPASS_CLK_SEL(4'b0), 44 | .BYPASS_GO_EN_N(1'b1), 45 | .BYPASS_PLL(4'b0), 46 | .BYPASS_OUT_DIVIDER(4'b0), 47 | .FF_REQUIRES_LOCK(1'b0), 48 | .FSE_N(1'b0), 49 | .FB_CLK_SEL_0(2'b00), 50 | .FB_CLK_SEL_1(1'b0), 51 | .RFDIV(rfdiv), 52 | .FRAC_EN(1'b0), 53 | .FRAC_DAC_EN(1'b0), 54 | .DIV0_RST_DELAY(3'b000), 55 | .DIV0_VAL(odiv), 56 | .DIV1_RST_DELAY(3'b0), 57 | .DIV1_VAL(7'b1), 58 | .DIV2_RST_DELAY(3'b0), 59 | .DIV2_VAL(7'b1), 60 | .DIV3_RST_DELAY(3'b0), 61 | .DIV3_VAL(7'b1), 62 | .DIV3_CLK_SEL(1'b0), 63 | .BW_INT_CTRL(2'b0), 64 | .BW_PROP_CTRL(2'b01), 65 | .IREF_EN(1'b1), 66 | .IREF_TOGGLE(1'b0), 67 | .LOCK_CNT(4'b1000), 68 | .DESKEW_CAL_CNT(3'b110), 69 | .DESKEW_CAL_EN(1'b1), 70 | .DESKEW_CAL_BYPASS(1'b0), 71 | .SYNC_REF_DIV_EN(1'b0), 72 | .SYNC_REF_DIV_EN_2(1'b0), 73 | .OUT0_PHASE_SEL(3'b000), 74 | .OUT1_PHASE_SEL(3'b0), 75 | .OUT2_PHASE_SEL(3'b0), 76 | .OUT3_PHASE_SEL(3'b0), 77 | .SOFT_LOAD_PHASE_N(1'b1), 78 | .SSM_DIV_VAL(6'b1), 79 | .FB_FRAC_VAL(24'b0), 80 | .SSM_SPREAD_MODE(1'b0), 81 | .SSM_MODULATION(5'b00101), 82 | .FB_INT_VAL(fbdiv), 83 | .SSM_EN_N(1'b1), 84 | .SSM_EXT_WAVE_EN(2'b0), 85 | .SSM_EXT_WAVE_MAX_ADDR(8'b0), 86 | .SSM_RANDOM_EN(1'b0), 87 | .SSM_RANDOM_PATTERN_SEL(3'b0), 88 | .CDMUX0_SEL(2'b0), 89 | .CDMUX1_SEL(1'b1), 90 | .CDMUX2_SEL(1'b0), 91 | .CDELAY0_SEL(8'b0), 92 | .CDELAY0_EN(1'b0), 93 | .DRI_EN(1'b1) 94 | ) pll_inst_0 ( 95 | .LOCK(o_lock), 96 | .SSCG_WAVE_TABLE_ADDR({ 97 | nc0, nc1, nc2, nc3, nc4, nc5, nc6, nc7 98 | }), 99 | .DELAY_LINE_OUT_OF_RANGE(), 100 | .POWERDOWN_N(vcc_net), 101 | .OUT0_EN(vcc_net), 102 | .OUT1_EN(gnd_net), 103 | .OUT2_EN(gnd_net), 104 | .OUT3_EN(gnd_net), 105 | .REF_CLK_SEL(gnd_net), 106 | .BYPASS_EN_N(vcc_net), 107 | .LOAD_PHASE_N(vcc_net), 108 | .SSCG_WAVE_TABLE({ 109 | gnd_net, gnd_net, gnd_net, gnd_net, gnd_net, gnd_net, gnd_net, 110 | gnd_net 111 | }), 112 | .PHASE_DIRECTION(gnd_net), 113 | .PHASE_ROTATE(gnd_net), 114 | .PHASE_OUT0_SEL(gnd_net), 115 | .PHASE_OUT1_SEL(gnd_net), 116 | .PHASE_OUT2_SEL(gnd_net), 117 | .PHASE_OUT3_SEL(gnd_net), 118 | .DELAY_LINE_MOVE(gnd_net), 119 | .DELAY_LINE_DIRECTION(gnd_net), 120 | .DELAY_LINE_WIDE(gnd_net), 121 | .DELAY_LINE_LOAD(vcc_net), 122 | .REFCLK_SYNC_EN(gnd_net), 123 | .REF_CLK_0(i_clk), 124 | .REF_CLK_1(gnd_net), 125 | .FB_CLK(gnd_net), 126 | .OUT0(pll_inst_0_clkint_0), 127 | .OUT1(), 128 | .OUT2(), 129 | .OUT3(), 130 | .DRI_CLK(gnd_net), 131 | .DRI_CTRL({ 132 | gnd_net, gnd_net, gnd_net, gnd_net, gnd_net, gnd_net, gnd_net, 133 | gnd_net, gnd_net, gnd_net, gnd_net 134 | }), 135 | .DRI_WDATA({ 136 | gnd_net, gnd_net, gnd_net, gnd_net, gnd_net, gnd_net, gnd_net, 137 | gnd_net, gnd_net, gnd_net, gnd_net, gnd_net, gnd_net, gnd_net, 138 | gnd_net, gnd_net, gnd_net, gnd_net, gnd_net, gnd_net, gnd_net, 139 | gnd_net, gnd_net, gnd_net, gnd_net, gnd_net, gnd_net, gnd_net, 140 | gnd_net, gnd_net, gnd_net, gnd_net, gnd_net 141 | }), 142 | .DRI_ARST_N(vcc_net), 143 | .DRI_RDATA({ 144 | nc8, nc9, nc10, nc11, nc12, nc13, nc14, nc15, nc16, nc17, nc18, 145 | nc19, nc20, nc21, nc22, nc23, nc24, nc25, nc26, nc27, nc28, nc29, 146 | nc30, nc31, nc32, nc33, nc34, nc35, nc36, nc37, nc38, nc39, 147 | nc40 148 | }), 149 | .DRI_INTERRUPT() 150 | ); 151 | 152 | CLKINT clkint_0 ( 153 | .A(pll_inst_0_clkint_0), 154 | .Y(o_clk) 155 | ); 156 | 157 | endmodule 158 | -------------------------------------------------------------------------------- /servant/servant_ram.v: -------------------------------------------------------------------------------- 1 | `default_nettype none 2 | module servant_ram 3 | #(//Memory parameters 4 | parameter depth = 256, 5 | parameter aw = $clog2(depth), 6 | parameter RESET_STRATEGY = "", 7 | parameter memfile = "") 8 | (input wire i_wb_clk, 9 | input wire i_wb_rst, 10 | input wire [aw-1:2] i_wb_adr, 11 | input wire [31:0] i_wb_dat, 12 | input wire [3:0] i_wb_sel, 13 | input wire i_wb_we, 14 | input wire i_wb_cyc, 15 | output reg [31:0] o_wb_rdt, 16 | output reg o_wb_ack); 17 | 18 | wire [3:0] we = {4{i_wb_we & i_wb_cyc}} & i_wb_sel; 19 | 20 | reg [31:0] mem [0:depth/4-1] /* verilator public */; 21 | 22 | wire [aw-3:0] addr = i_wb_adr[aw-1:2]; 23 | 24 | always @(posedge i_wb_clk) 25 | if (i_wb_rst & (RESET_STRATEGY != "NONE")) 26 | o_wb_ack <= 1'b0; 27 | else 28 | o_wb_ack <= i_wb_cyc & !o_wb_ack; 29 | 30 | always @(posedge i_wb_clk) begin 31 | if (we[0]) mem[addr][7:0] <= i_wb_dat[7:0]; 32 | if (we[1]) mem[addr][15:8] <= i_wb_dat[15:8]; 33 | if (we[2]) mem[addr][23:16] <= i_wb_dat[23:16]; 34 | if (we[3]) mem[addr][31:24] <= i_wb_dat[31:24]; 35 | o_wb_rdt <= mem[addr]; 36 | end 37 | 38 | initial 39 | if(|memfile) begin 40 | `ifndef ISE 41 | `ifndef CCGM 42 | $display("Preloading %m from %s", memfile); 43 | `endif 44 | `endif 45 | $readmemh(memfile, mem); 46 | end 47 | 48 | endmodule 49 | -------------------------------------------------------------------------------- /servant/servant_ram_quartus.sv: -------------------------------------------------------------------------------- 1 | `default_nettype none 2 | module servant_ram 3 | #(//Memory parameters 4 | parameter depth = 256, 5 | parameter aw = $clog2(depth), 6 | parameter RESET_STRATEGY = "", 7 | parameter memfile = "") 8 | (input wire i_wb_clk, 9 | input wire i_wb_rst, 10 | input wire [aw-1:2] i_wb_adr, 11 | input wire [31:0] i_wb_dat, 12 | input wire [3:0] i_wb_sel, 13 | input wire i_wb_we, 14 | input wire i_wb_cyc, 15 | output reg [31:0] o_wb_rdt, 16 | output reg o_wb_ack); 17 | 18 | wire we = i_wb_we & i_wb_cyc; 19 | 20 | logic [3:0][7:0] mem[0:depth/4-1]; 21 | 22 | wire [aw-3:0] addr = i_wb_adr[aw-1:2]; 23 | 24 | always @(posedge i_wb_clk) 25 | if (i_wb_rst & (RESET_STRATEGY != "NONE")) 26 | o_wb_ack <= 1'b0; 27 | else 28 | o_wb_ack <= i_wb_cyc & !o_wb_ack; 29 | 30 | always_ff @(posedge i_wb_clk) begin 31 | if(we) begin 32 | if(i_wb_sel[0]) mem[addr][0] <= i_wb_dat[7:0]; 33 | if(i_wb_sel[1]) mem[addr][1] <= i_wb_dat[15:8]; 34 | if(i_wb_sel[2]) mem[addr][2] <= i_wb_dat[23:16]; 35 | if(i_wb_sel[3]) mem[addr][3] <= i_wb_dat[31:24]; 36 | end 37 | o_wb_rdt <= mem[addr]; 38 | end 39 | 40 | initial 41 | if(|memfile) begin 42 | $display("Preloading %m from %s", memfile); 43 | $readmemh(memfile, mem); 44 | end 45 | 46 | endmodule 47 | -------------------------------------------------------------------------------- /servant/servant_te0802.v: -------------------------------------------------------------------------------- 1 | `default_nettype none 2 | module servant_te0802 3 | ( 4 | input wire i_clk, 5 | output wire o_uart_tx, 6 | output wire o_led_0 7 | ); 8 | 9 | parameter memfile = "zephyr_hello.hex"; 10 | parameter memsize = 8192; 11 | 12 | wire clk; 13 | wire rst; 14 | wire q; 15 | 16 | assign o_uart_tx = q; 17 | assign o_led_0 = q; 18 | 19 | servant_te0802_clock_gen 20 | clock_gen 21 | (.i_clk (i_clk), 22 | .o_clk (clk), 23 | .o_rst (rst)); 24 | 25 | servant 26 | #(.memfile (memfile), 27 | .memsize (memsize)) 28 | servant 29 | (.wb_clk (clk), 30 | .wb_rst (rst), 31 | .q (q)); 32 | 33 | endmodule 34 | -------------------------------------------------------------------------------- /servant/servant_te0802_clock_gen.v: -------------------------------------------------------------------------------- 1 | `default_nettype none 2 | module servant_te0802_clock_gen 3 | (input wire i_clk, 4 | output wire o_clk, 5 | output reg o_rst); 6 | 7 | wire clkfb; 8 | wire locked; 9 | reg locked_r; 10 | 11 | // Generate a 32 MHz clock from the 25MHz clock input 12 | MMCME4_ADV 13 | #(.DIVCLK_DIVIDE (1), 14 | .CLKFBOUT_MULT_F (48.000), 15 | .CLKOUT0_DIVIDE_F (37.5), 16 | .CLKIN1_PERIOD (40.0), //25MHz 17 | .STARTUP_WAIT ("FALSE")) 18 | mmcm 19 | (.CLKFBOUT (clkfb), 20 | .CLKFBOUTB (), 21 | .CLKOUT0 (o_clk), 22 | .CLKOUT0B (), 23 | .CLKOUT1 (), 24 | .CLKOUT1B (), 25 | .CLKOUT2 (), 26 | .CLKOUT2B (), 27 | .CLKOUT3 (), 28 | .CLKOUT3B (), 29 | .CLKOUT4 (), 30 | .CLKOUT5 (), 31 | .CLKOUT6 (), 32 | .CLKIN1 (i_clk), 33 | .CLKIN2 (1'b0), 34 | .CLKINSEL (1'b1), 35 | .LOCKED (locked), 36 | .PWRDWN (1'b0), 37 | .RST (1'b0), 38 | .CLKFBIN (clkfb)); 39 | 40 | always @(posedge o_clk) begin 41 | locked_r <= locked; 42 | o_rst <= !locked_r; 43 | end 44 | 45 | endmodule 46 | -------------------------------------------------------------------------------- /servant/servant_timer.v: -------------------------------------------------------------------------------- 1 | `default_nettype none 2 | module servant_timer 3 | #(parameter WIDTH = 16, 4 | parameter RESET_STRATEGY = "", 5 | parameter DIVIDER = 0) 6 | (input wire i_clk, 7 | input wire i_rst, 8 | output reg o_irq, 9 | input wire [31:0] i_wb_dat, 10 | input wire i_wb_we, 11 | input wire i_wb_cyc, 12 | output reg [31:0] o_wb_dat); 13 | 14 | localparam HIGH = WIDTH-1-DIVIDER; 15 | 16 | reg [WIDTH-1:0] mtime; 17 | reg signed [HIGH:0] mtimecmp; 18 | 19 | wire signed [HIGH:0] mtimeslice = mtime[WIDTH-1:DIVIDER]; 20 | 21 | always @(mtimeslice) begin 22 | o_wb_dat = 32'd0; 23 | o_wb_dat[HIGH:0] = mtimeslice; 24 | end 25 | 26 | always @(posedge i_clk) begin 27 | if (i_wb_cyc & i_wb_we) 28 | mtimecmp <= i_wb_dat[HIGH:0]; 29 | mtime <= mtime + 'd1; 30 | o_irq <= (mtimeslice - mtimecmp >= 0); 31 | if (RESET_STRATEGY != "NONE") 32 | if (i_rst) begin 33 | mtime <= 0; 34 | mtimecmp <= 0; 35 | end 36 | end 37 | endmodule 38 | -------------------------------------------------------------------------------- /servant/servant_upduino2.v: -------------------------------------------------------------------------------- 1 | `default_nettype none 2 | module servant_upduino2 3 | ( 4 | output wire g, 5 | output wire b, 6 | output wire r, 7 | output wire q); 8 | 9 | parameter memfile = "zephyr_hello.hex"; 10 | parameter memsize = 8192; 11 | parameter PLL = "NONE"; 12 | 13 | wire clk; 14 | wire clk48; 15 | wire locked; 16 | 17 | SB_HFOSC inthosc 18 | ( 19 | .CLKHFPU(1'b1), 20 | .CLKHFEN(1'b1), 21 | .CLKHF(clk48)); 22 | 23 | SB_PLL40_CORE 24 | #( 25 | .FEEDBACK_PATH("SIMPLE"), 26 | .DIVR(4'b0010), 27 | .DIVF(7'b0111111), 28 | .DIVQ(3'b110), 29 | .FILTER_RANGE(3'b001)) 30 | pll 31 | (.LOCK(locked), 32 | .RESETB(1'b1), 33 | .BYPASS(1'b0), 34 | .REFERENCECLK(clk48), 35 | .PLLOUTCORE(clk)); 36 | 37 | SB_RGBA_DRV 38 | #( 39 | .CURRENT_MODE ("0b1"), 40 | .RGB0_CURRENT ("0b000111"), 41 | .RGB1_CURRENT ("0b000111"), 42 | .RGB2_CURRENT ("0b000111")) 43 | RGBA_DRIVER 44 | ( 45 | .CURREN(1'b1), 46 | .RGBLEDEN(1'b1), 47 | .RGB0PWM(q), 48 | .RGB1PWM(q), 49 | .RGB2PWM(q), 50 | .RGB0(g), 51 | .RGB1(b), 52 | .RGB2(r)); 53 | 54 | reg rst = 1'b1; 55 | 56 | /* 57 | //Delayed reset 58 | reg [25:0] cnt; 59 | always @(posedge clk) begin 60 | if (!cnt[25]) 61 | cnt <= cnt + 1; 62 | rst <= !cnt[25]; 63 | end 64 | */ 65 | 66 | always @(posedge clk) 67 | rst <= !locked; 68 | 69 | servant 70 | #(.memfile (memfile), 71 | .memsize (memsize)) 72 | servant 73 | (.wb_clk (clk), 74 | .wb_rst (rst), 75 | .q (q)); 76 | 77 | endmodule 78 | -------------------------------------------------------------------------------- /servant/servax.v: -------------------------------------------------------------------------------- 1 | `default_nettype none 2 | module servax // top level for nexys 2 (Xilinx's Spartan-3E based) target board 3 | ( 4 | input wire i_clk, 5 | output wire q); 6 | 7 | parameter memfile = "zephyr_hello.hex"; 8 | parameter memsize = 8192; 9 | parameter PLL = "NONE"; 10 | 11 | wire wb_clk; 12 | wire wb_rst; 13 | 14 | servax_clock_gen 15 | clock_gen 16 | (.i_clk (i_clk), 17 | .o_clk (wb_clk), 18 | .o_rst (wb_rst)); 19 | 20 | servant 21 | #(.memfile (memfile), 22 | .memsize (memsize)) 23 | servant 24 | (.wb_clk (wb_clk), 25 | .wb_rst (wb_rst), 26 | .q (q)); 27 | 28 | endmodule -------------------------------------------------------------------------------- /servant/servax_clock_gen.v: -------------------------------------------------------------------------------- 1 | `default_nettype none 2 | module servax_clock_gen 3 | (input wire i_clk, 4 | output wire o_clk, 5 | output reg o_rst); 6 | 7 | wire locked; 8 | reg locked_r; 9 | 10 | 11 | DCM_SP #( 12 | .CLKFX_DIVIDE(25), // Can be any integer from 1 to 32 13 | .CLKFX_MULTIPLY(8), // Can be any integer from 2 to 32 14 | .CLKIN_PERIOD(20.0) //50Mhz 15 | ) 16 | DCM_SP_inst ( 17 | .CLKFX(o_clk), // DCM CLK synthesis out (M/D) 18 | .CLKFX180(), // 180 degree CLK synthesis out 19 | .LOCKED(locked), // DCM LOCK status output 20 | .STATUS(), // 8-bit DCM status bits output 21 | .CLKFB(), // DCM clock feedback 22 | .CLKIN(i_clk), // Clock input 23 | .RST(1'b0) // DCM asynchronous reset input 24 | ); 25 | 26 | always @(posedge o_clk) begin 27 | locked_r <= locked; 28 | o_rst <= !locked_r; 29 | end 30 | 31 | endmodule -------------------------------------------------------------------------------- /servant/servclone10.v: -------------------------------------------------------------------------------- 1 | `default_nettype none 2 | module servclone10 3 | ( 4 | input wire i_clk, 5 | input wire i_rst, 6 | output wire q, 7 | output wire uart_txd); 8 | 9 | parameter memfile = "zephyr_hello.hex"; 10 | parameter memsize = 8192; 11 | 12 | wire wb_clk; 13 | wire wb_rst; 14 | 15 | assign uart_txd = q; 16 | 17 | servclone10_clock_gen clock_gen 18 | (.i_clk (i_clk), 19 | .i_rst (i_rst), 20 | .o_clk (wb_clk), 21 | .o_rst (wb_rst)); 22 | 23 | servant 24 | #(.memfile (memfile), 25 | .memsize (memsize)) 26 | servant 27 | (.wb_clk (wb_clk), 28 | .wb_rst (wb_rst), 29 | .q (q)); 30 | 31 | endmodule 32 | -------------------------------------------------------------------------------- /servant/servclone10_clock_gen.v: -------------------------------------------------------------------------------- 1 | `default_nettype none 2 | module servclone10_clock_gen 3 | (input wire i_clk, 4 | input wire i_rst, 5 | output wire o_clk, 6 | output wire o_rst); 7 | 8 | wire [4:0] clk; 9 | 10 | wire clk_fb; 11 | 12 | wire locked; 13 | reg [9:0] r; 14 | 15 | assign o_clk = clk[0]; 16 | 17 | assign o_rst = r[9]; 18 | 19 | always @(posedge o_clk) 20 | if (locked) 21 | r <= {r[8:0],1'b0}; 22 | else 23 | r <= 10'b1111111111; 24 | 25 | cyclone10lp_pll 26 | #(.bandwidth_type ("auto"), 27 | .clk0_divide_by (6), 28 | .clk0_duty_cycle (50), 29 | .clk0_multiply_by (16), 30 | .clk0_phase_shift ("0"), 31 | .compensate_clock ("clk0"), 32 | .inclk0_input_frequency (83333), 33 | .operation_mode ("normal"), 34 | .pll_type ("auto"), 35 | .lpm_type ("cyclone10lp_pll")) 36 | pll 37 | (.activeclock (), 38 | .areset (i_rst), 39 | .clk (clk), 40 | .clkbad (), 41 | .fbin (clk_fb), 42 | .fbout (clk_fb), 43 | .inclk (i_clk), 44 | .locked (locked), 45 | .phasedone (), 46 | .scandataout (), 47 | .scandone (), 48 | .vcooverrange (), 49 | .vcounderrange ()); 50 | endmodule 51 | -------------------------------------------------------------------------------- /servant/servde1_soc_revF.v: -------------------------------------------------------------------------------- 1 | `default_nettype none 2 | module servde1_soc_revF 3 | ( 4 | input wire i_clk, 5 | input wire i_rst_n, 6 | output wire q, 7 | output wire uart_txd); 8 | 9 | parameter memfile = "zephyr_hello.hex"; 10 | parameter memsize = 8192; 11 | 12 | wire wb_clk; 13 | wire wb_rst; 14 | 15 | assign uart_txd = q; 16 | 17 | servde1_soc_revF_clock_gen clock_gen 18 | (.i_clk (i_clk), 19 | .i_rst (!i_rst_n), 20 | .o_clk (wb_clk), 21 | .o_rst (wb_rst)); 22 | 23 | servant 24 | #(.memfile (memfile), 25 | .memsize (memsize)) 26 | servant 27 | (.wb_clk (wb_clk), 28 | .wb_rst (wb_rst), 29 | .q (q)); 30 | 31 | endmodule 32 | -------------------------------------------------------------------------------- /servant/servde1_soc_revF_clock_gen.v: -------------------------------------------------------------------------------- 1 | `default_nettype none 2 | module servde1_soc_revF_clock_gen 3 | (input wire i_clk, 4 | input wire i_rst, 5 | output wire o_clk, 6 | output wire o_rst); 7 | 8 | wire locked; 9 | reg [9:0] r; 10 | 11 | assign o_rst = r[9]; 12 | 13 | always @(posedge o_clk) 14 | if (locked) 15 | r <= {r[8:0],1'b0}; 16 | else 17 | r <= 10'b1111111111; 18 | 19 | wire [5:0] clk; 20 | 21 | assign o_clk = clk[0]; 22 | 23 | altpll 24 | #(.operation_mode ("NORMAL"), 25 | .clk0_divide_by (25), 26 | .clk0_multiply_by (8), 27 | .inclk0_input_frequency (20000)) 28 | pll 29 | (.areset (i_rst), 30 | .inclk ({1'b0, i_clk}), 31 | .clk (clk), 32 | .locked (locked)); 33 | 34 | endmodule 35 | -------------------------------------------------------------------------------- /servant/service.v: -------------------------------------------------------------------------------- 1 | `default_nettype none 2 | module service 3 | ( 4 | input wire i_clk, 5 | output wire q); 6 | 7 | parameter memfile = "zephyr_hello.hex"; 8 | parameter memsize = 8192; 9 | parameter PLL = "NONE"; 10 | 11 | wire wb_clk; 12 | wire wb_rst; 13 | 14 | service_clock_gen #(.PLL (PLL)) 15 | clock_gen 16 | (.i_clk (i_clk), 17 | .o_clk (wb_clk), 18 | .o_rst (wb_rst)); 19 | 20 | servant 21 | #(.memfile (memfile), 22 | .memsize (memsize)) 23 | servant 24 | (.wb_clk (wb_clk), 25 | .wb_rst (wb_rst), 26 | .q (q)); 27 | 28 | endmodule 29 | -------------------------------------------------------------------------------- /servant/service_clock_gen.v: -------------------------------------------------------------------------------- 1 | `default_nettype none 2 | module service_clock_gen 3 | ( 4 | input wire i_clk, 5 | output wire o_clk, 6 | output wire o_rst); 7 | 8 | parameter [79:0] PLL = "NONE"; 9 | 10 | generate 11 | if ((PLL == "ICE40_CORE") || (PLL == "ICE40_PAD")) begin 12 | ice40_pll #(.PLL (PLL)) pll 13 | (.i_clk (i_clk), 14 | .o_clk (o_clk), 15 | .o_rst (o_rst)); 16 | end else begin 17 | assign o_clk = i_clk; 18 | 19 | reg [4:0] rst_reg = 5'b11111; 20 | 21 | always @(posedge o_clk) 22 | rst_reg <= {1'b0, rst_reg[4:1]}; 23 | assign o_rst = rst_reg[0]; 24 | end 25 | endgenerate 26 | endmodule 27 | -------------------------------------------------------------------------------- /servant/service_go_board.v: -------------------------------------------------------------------------------- 1 | `default_nettype none 2 | module service_go_board 3 | (input wire i_clk, 4 | output wire o_led1, 5 | output wire o_led2 = 1'b0, 6 | output wire o_led3 = 1'b0, 7 | output wire o_led4 = 1'b0, 8 | output wire o_uart_tx); 9 | 10 | parameter memfile = "blinky.hex"; 11 | parameter memsize = 512; 12 | 13 | // Assert reset for 64 clock cycles. Use the 7th bit as the reset signal. 14 | reg [6:0] rst_count; 15 | wire rst_r = !rst_count[6]; 16 | 17 | always @(posedge i_clk) begin 18 | if (rst_r == 1) begin 19 | rst_count <= rst_count + 1; 20 | end 21 | end 22 | 23 | wire q; 24 | servant 25 | #(.memfile (memfile), 26 | .memsize (memsize)) 27 | servant 28 | (.wb_clk (i_clk), 29 | .wb_rst (rst_r), 30 | .q (q)); 31 | assign o_led1 = q; 32 | assign o_uart_tx = q; 33 | 34 | endmodule 35 | -------------------------------------------------------------------------------- /servant/servis.v: -------------------------------------------------------------------------------- 1 | `default_nettype none 2 | module servis 3 | ( 4 | input wire i_clk, 5 | output wire q); 6 | 7 | parameter memfile = "zephyr_hello.hex"; 8 | parameter memsize = 8192; 9 | parameter PLL = "NONE"; 10 | 11 | wire wb_clk; 12 | wire wb_rst; 13 | 14 | servis_clock_gen 15 | clock_gen 16 | (.i_clk (i_clk), 17 | .o_clk (wb_clk), 18 | .o_rst (wb_rst)); 19 | 20 | servant 21 | #(.memfile (memfile), 22 | .memsize (memsize)) 23 | servant 24 | (.wb_clk (wb_clk), 25 | .wb_rst (wb_rst), 26 | .q (q)); 27 | 28 | endmodule 29 | -------------------------------------------------------------------------------- /servant/servis_clock_gen.v: -------------------------------------------------------------------------------- 1 | `default_nettype none 2 | module servis_clock_gen 3 | (input wire i_clk, 4 | output wire o_clk, 5 | output reg o_rst); 6 | 7 | wire clkfb; 8 | wire locked; 9 | reg locked_r; 10 | 11 | PLL_BASE 12 | #(.BANDWIDTH("OPTIMIZED"), 13 | .CLKFBOUT_MULT(16), 14 | .CLKIN_PERIOD(20.0), //50MHz 15 | .CLKOUT1_DIVIDE(50), //16MHz 16 | .DIVCLK_DIVIDE(1)) 17 | PLL_BASE_inst 18 | (.CLKOUT1(o_clk), 19 | .CLKOUT2(), 20 | .CLKOUT3(), 21 | .CLKOUT4(), 22 | .CLKOUT5(), 23 | .CLKFBOUT(clkfb), 24 | .LOCKED(locked), 25 | .CLKIN(i_clk), 26 | .RST(1'b0), 27 | .CLKFBIN(clkfb)); 28 | 29 | always @(posedge o_clk) begin 30 | locked_r <= locked; 31 | o_rst <= !locked_r; 32 | end 33 | 34 | endmodule 35 | -------------------------------------------------------------------------------- /servant/servive.v: -------------------------------------------------------------------------------- 1 | `default_nettype none 2 | module servive 3 | ( 4 | input wire i_clk, 5 | input wire i_rst_n, 6 | output wire q, 7 | output wire uart_txd); 8 | 9 | parameter memfile = "zephyr_hello.hex"; 10 | parameter memsize = 8192; 11 | 12 | wire wb_clk; 13 | wire wb_rst; 14 | 15 | assign uart_txd = q; 16 | 17 | servive_clock_gen clock_gen 18 | (.i_clk (i_clk), 19 | .i_rst (!i_rst_n), 20 | .o_clk (wb_clk), 21 | .o_rst (wb_rst)); 22 | 23 | servant 24 | #(.memfile (memfile), 25 | .memsize (memsize)) 26 | servant 27 | (.wb_clk (wb_clk), 28 | .wb_rst (wb_rst), 29 | .q (q)); 30 | 31 | endmodule 32 | -------------------------------------------------------------------------------- /servant/servive_clock_gen.v: -------------------------------------------------------------------------------- 1 | `default_nettype none 2 | module servive_clock_gen 3 | (input wire i_clk, 4 | input wire i_rst, 5 | output wire o_clk, 6 | output wire o_rst); 7 | 8 | wire locked; 9 | reg [9:0] r; 10 | 11 | assign o_rst = r[9]; 12 | 13 | always @(posedge o_clk) 14 | if (locked) 15 | r <= {r[8:0],1'b0}; 16 | else 17 | r <= 10'b1111111111; 18 | 19 | wire [5:0] clk; 20 | 21 | assign o_clk = clk[0]; 22 | 23 | altpll 24 | #(.operation_mode ("NORMAL"), 25 | .clk0_divide_by (25), 26 | .clk0_multiply_by (8), 27 | .inclk0_input_frequency (20000)) 28 | pll 29 | (.areset (i_rst), 30 | .inclk ({1'b0, i_clk}), 31 | .clk (clk), 32 | .locked (locked)); 33 | 34 | endmodule 35 | -------------------------------------------------------------------------------- /servant/servix.v: -------------------------------------------------------------------------------- 1 | `default_nettype none 2 | module servix 3 | ( 4 | input wire i_clk, 5 | `ifdef WITH_RESET 6 | input wire i_rst_n, 7 | `endif 8 | output wire q); 9 | 10 | parameter frequency = 32; 11 | parameter memfile = "zephyr_hello.hex"; 12 | parameter memsize = 8192; 13 | parameter PLL = "NONE"; 14 | 15 | wire wb_clk; 16 | wire wb_rst; 17 | 18 | servix_clock_gen 19 | #(.frequency (frequency)) 20 | clock_gen 21 | (.i_clk (i_clk), 22 | `ifdef WITH_RESET 23 | .i_rst (!i_rst_n), 24 | `else 25 | .i_rst (1'b0), 26 | `endif 27 | .o_clk (wb_clk), 28 | .o_rst (wb_rst)); 29 | 30 | servant 31 | #(.memfile (memfile), 32 | .memsize (memsize)) 33 | servant 34 | (.wb_clk (wb_clk), 35 | .wb_rst (wb_rst), 36 | .q (q)); 37 | 38 | endmodule 39 | -------------------------------------------------------------------------------- /servant/servix_clock_gen.v: -------------------------------------------------------------------------------- 1 | `default_nettype none 2 | module servix_clock_gen 3 | (input wire i_clk, 4 | input wire i_rst, 5 | output wire o_clk, 6 | output reg o_rst); 7 | 8 | parameter frequency = 32; 9 | 10 | wire clkfb; 11 | wire locked; 12 | reg locked_r; 13 | 14 | PLLE2_BASE 15 | #(.BANDWIDTH("OPTIMIZED"), 16 | .CLKFBOUT_MULT(16), 17 | .CLKIN1_PERIOD(10.0), //100MHz 18 | .CLKOUT0_DIVIDE((frequency == 32) ? 50 : 100), 19 | .DIVCLK_DIVIDE(1), 20 | .STARTUP_WAIT("FALSE")) 21 | PLLE2_BASE_inst 22 | (.CLKOUT0(o_clk), 23 | .CLKOUT1(), 24 | .CLKOUT2(), 25 | .CLKOUT3(), 26 | .CLKOUT4(), 27 | .CLKOUT5(), 28 | .CLKFBOUT(clkfb), 29 | .LOCKED(locked), 30 | .CLKIN1(i_clk), 31 | .PWRDWN(1'b0), 32 | .RST(i_rst), 33 | .CLKFBIN(clkfb)); 34 | 35 | always @(posedge o_clk) begin 36 | locked_r <= locked; 37 | o_rst <= !locked_r; 38 | end 39 | 40 | endmodule 41 | -------------------------------------------------------------------------------- /servant/servix_ebaz4205.v: -------------------------------------------------------------------------------- 1 | `default_nettype none 2 | module servix_ebaz4205 3 | ( 4 | input wire i_clk, 5 | output wire q); 6 | 7 | parameter frequency = 32; 8 | parameter memfile = "zephyr_hello.hex"; 9 | parameter memsize = 8192; 10 | parameter PLL = "NONE"; 11 | 12 | wire wb_clk; 13 | wire wb_rst; 14 | 15 | servix_ebaz4205_clock_gen 16 | #(.frequency (frequency)) 17 | clock_gen 18 | (.i_clk (i_clk), 19 | .o_clk (wb_clk), 20 | .o_rst (wb_rst)); 21 | 22 | servant 23 | #(.memfile (memfile), 24 | .memsize (memsize)) 25 | servant 26 | (.wb_clk (wb_clk), 27 | .wb_rst (wb_rst), 28 | .q (q)); 29 | 30 | endmodule 31 | -------------------------------------------------------------------------------- /servant/servix_ebaz4205_clock_gen.v: -------------------------------------------------------------------------------- 1 | `default_nettype none 2 | module servix_ebaz4205_clock_gen 3 | (input wire i_clk, 4 | output wire o_clk, 5 | output reg o_rst); 6 | 7 | parameter frequency = 32; 8 | 9 | wire clkfb; 10 | wire locked; 11 | reg locked_r; 12 | 13 | // (33.333 * 48) / 50 => 31.9996 MHz 14 | PLLE2_BASE 15 | #(.BANDWIDTH("OPTIMIZED"), 16 | .CLKFBOUT_MULT(48), 17 | .CLKIN1_PERIOD(30.000300003), // 33.333 MHz 18 | .CLKOUT0_DIVIDE((frequency == 32) ? 50 : 100), 19 | .DIVCLK_DIVIDE(1), 20 | .STARTUP_WAIT("FALSE")) 21 | PLLE2_BASE_inst 22 | (.CLKOUT0(o_clk), 23 | .CLKOUT1(), 24 | .CLKOUT2(), 25 | .CLKOUT3(), 26 | .CLKOUT4(), 27 | .CLKOUT5(), 28 | .CLKFBOUT(clkfb), 29 | .LOCKED(locked), 30 | .CLKIN1(i_clk), 31 | .PWRDWN(1'b0), 32 | .RST(1'b0), 33 | .CLKFBIN(clkfb)); 34 | 35 | always @(posedge o_clk) begin 36 | locked_r <= locked; 37 | o_rst <= !locked_r; 38 | end 39 | 40 | endmodule 41 | -------------------------------------------------------------------------------- /servant/servus.v: -------------------------------------------------------------------------------- 1 | `default_nettype none 2 | module servus 3 | (input wire i_clk_p, 4 | input wire i_clk_n, 5 | output wire o_uart_tx, 6 | output wire q); 7 | 8 | parameter memfile = "zephyr_hello.hex"; 9 | parameter memsize = 8192; 10 | 11 | wire i_clk; 12 | wire clk; 13 | wire rst; 14 | 15 | assign o_uart_tx = q; 16 | 17 | IBUFDS ibufds 18 | (.I (i_clk_p), 19 | .IB (i_clk_n), 20 | .O (i_clk)); 21 | 22 | servus_clock_gen 23 | clock_gen 24 | (.i_clk (i_clk), 25 | .o_clk (clk), 26 | .o_rst (rst)); 27 | 28 | servant 29 | #(.memfile (memfile), 30 | .memsize (memsize)) 31 | servant 32 | (.wb_clk (clk), 33 | .wb_rst (rst), 34 | .q (q)); 35 | 36 | endmodule 37 | -------------------------------------------------------------------------------- /servant/servus_clock_gen.v: -------------------------------------------------------------------------------- 1 | `default_nettype none 2 | module servus_clock_gen 3 | (input wire i_clk, 4 | output wire o_clk, 5 | output reg o_rst); 6 | 7 | wire clkfb; 8 | wire locked; 9 | reg locked_r; 10 | 11 | MMCME4_ADV 12 | #(.DIVCLK_DIVIDE (5), 13 | .CLKFBOUT_MULT_F (48.000), 14 | .CLKOUT0_DIVIDE_F (75.0), 15 | .CLKIN1_PERIOD (8.0), //125MHz 16 | .STARTUP_WAIT ("FALSE")) 17 | mmcm 18 | (.CLKFBOUT (clkfb), 19 | .CLKFBOUTB (), 20 | .CLKOUT0 (o_clk), 21 | .CLKOUT0B (), 22 | .CLKOUT1 (), 23 | .CLKOUT1B (), 24 | .CLKOUT2 (), 25 | .CLKOUT2B (), 26 | .CLKOUT3 (), 27 | .CLKOUT3B (), 28 | .CLKOUT4 (), 29 | .CLKOUT5 (), 30 | .CLKOUT6 (), 31 | .CLKIN1 (i_clk), 32 | .CLKIN2 (1'b0), 33 | .CLKINSEL (1'b1), 34 | .LOCKED (locked), 35 | .PWRDWN (1'b0), 36 | .RST (1'b0), 37 | .CLKFBIN (clkfb)); 38 | 39 | always @(posedge o_clk) begin 40 | locked_r <= locked; 41 | o_rst <= !locked_r; 42 | end 43 | 44 | endmodule 45 | -------------------------------------------------------------------------------- /servile.core: -------------------------------------------------------------------------------- 1 | CAPI=2: 2 | 3 | name : ::servile:1.3.0 4 | 5 | description: Convenience wrapper for SERV 6 | 7 | filesets: 8 | rtl: 9 | files: 10 | - servile/servile_rf_mem_if.v 11 | - servile/servile_mux.v 12 | - servile/servile_arbiter.v 13 | - servile/servile.v 14 | file_type: verilogSource 15 | depend : [serv] 16 | 17 | targets: 18 | default: 19 | filesets: [rtl] 20 | 21 | lint: 22 | description: Run static code checks (linting) 23 | filesets: [rtl] 24 | flow: lint 25 | flow_options: 26 | tool: verilator 27 | toplevel: servile 28 | -------------------------------------------------------------------------------- /servile/servile_arbiter.v: -------------------------------------------------------------------------------- 1 | /* 2 | * servile_arbiter.v : I/D arbiter for the servile convenience wrapper. 3 | * Relies on the fact that not ibus and dbus are active at the same time. 4 | * 5 | * SPDX-FileCopyrightText: 2024 Olof Kindgren 6 | * SPDX-License-Identifier: Apache-2.0 7 | */ 8 | 9 | module servile_arbiter 10 | ( 11 | input wire [31:0] i_wb_cpu_dbus_adr, 12 | input wire [31:0] i_wb_cpu_dbus_dat, 13 | input wire [3:0] i_wb_cpu_dbus_sel, 14 | input wire i_wb_cpu_dbus_we, 15 | input wire i_wb_cpu_dbus_stb, 16 | output wire [31:0] o_wb_cpu_dbus_rdt, 17 | output wire o_wb_cpu_dbus_ack, 18 | 19 | input wire [31:0] i_wb_cpu_ibus_adr, 20 | input wire i_wb_cpu_ibus_stb, 21 | output wire [31:0] o_wb_cpu_ibus_rdt, 22 | output wire o_wb_cpu_ibus_ack, 23 | 24 | output wire [31:0] o_wb_mem_adr, 25 | output wire [31:0] o_wb_mem_dat, 26 | output wire [3:0] o_wb_mem_sel, 27 | output wire o_wb_mem_we, 28 | output wire o_wb_mem_stb, 29 | input wire [31:0] i_wb_mem_rdt, 30 | input wire i_wb_mem_ack); 31 | 32 | assign o_wb_cpu_dbus_rdt = i_wb_mem_rdt; 33 | assign o_wb_cpu_dbus_ack = i_wb_mem_ack & !i_wb_cpu_ibus_stb; 34 | 35 | assign o_wb_cpu_ibus_rdt = i_wb_mem_rdt; 36 | assign o_wb_cpu_ibus_ack = i_wb_mem_ack & i_wb_cpu_ibus_stb; 37 | 38 | assign o_wb_mem_adr = i_wb_cpu_ibus_stb ? i_wb_cpu_ibus_adr : i_wb_cpu_dbus_adr; 39 | assign o_wb_mem_dat = i_wb_cpu_dbus_dat; 40 | assign o_wb_mem_sel = i_wb_cpu_dbus_sel; 41 | assign o_wb_mem_we = i_wb_cpu_dbus_we & !i_wb_cpu_ibus_stb; 42 | assign o_wb_mem_stb = i_wb_cpu_ibus_stb | i_wb_cpu_dbus_stb; 43 | 44 | 45 | endmodule 46 | -------------------------------------------------------------------------------- /servile/servile_mux.v: -------------------------------------------------------------------------------- 1 | /* 2 | * servile_mux.v : Simple Wishbone mux for the servile convenience wrapper. 3 | * 4 | * SPDX-FileCopyrightText: 2024 Olof Kindgren 5 | * SPDX-License-Identifier: Apache-2.0 6 | */ 7 | 8 | module servile_mux 9 | #(parameter [0:0] sim = 1'b0, //Enable simulation features 10 | parameter [31:0] sim_sig_adr = 32'h80000000, 11 | parameter [31:0] sim_halt_adr = 32'h90000000) 12 | ( 13 | input wire i_clk, 14 | input wire i_rst, 15 | 16 | input wire [31:0] i_wb_cpu_adr, 17 | input wire [31:0] i_wb_cpu_dat, 18 | input wire [3:0] i_wb_cpu_sel, 19 | input wire i_wb_cpu_we, 20 | input wire i_wb_cpu_stb, 21 | output wire [31:0] o_wb_cpu_rdt, 22 | output wire o_wb_cpu_ack, 23 | 24 | output wire [31:0] o_wb_mem_adr, 25 | output wire [31:0] o_wb_mem_dat, 26 | output wire [3:0] o_wb_mem_sel, 27 | output wire o_wb_mem_we, 28 | output wire o_wb_mem_stb, 29 | input wire [31:0] i_wb_mem_rdt, 30 | input wire i_wb_mem_ack, 31 | 32 | output wire [31:0] o_wb_ext_adr, 33 | output wire [31:0] o_wb_ext_dat, 34 | output wire [3:0] o_wb_ext_sel, 35 | output wire o_wb_ext_we, 36 | output wire o_wb_ext_stb, 37 | input wire [31:0] i_wb_ext_rdt, 38 | input wire i_wb_ext_ack); 39 | 40 | wire sig_en; 41 | wire halt_en; 42 | reg sim_ack; 43 | 44 | wire ext = (i_wb_cpu_adr[31:30] != 2'b00); 45 | 46 | assign o_wb_cpu_rdt = ext ? i_wb_ext_rdt : i_wb_mem_rdt; 47 | assign o_wb_cpu_ack = i_wb_ext_ack | i_wb_mem_ack | sim_ack; 48 | 49 | assign o_wb_mem_adr = i_wb_cpu_adr; 50 | assign o_wb_mem_dat = i_wb_cpu_dat; 51 | assign o_wb_mem_sel = i_wb_cpu_sel; 52 | assign o_wb_mem_we = i_wb_cpu_we; 53 | assign o_wb_mem_stb = i_wb_cpu_stb & !ext & !(sig_en|halt_en); 54 | 55 | assign o_wb_ext_adr = i_wb_cpu_adr; 56 | assign o_wb_ext_dat = i_wb_cpu_dat; 57 | assign o_wb_ext_sel = i_wb_cpu_sel; 58 | assign o_wb_ext_we = i_wb_cpu_we; 59 | assign o_wb_ext_stb = i_wb_cpu_stb & ext & !(sig_en|halt_en); 60 | 61 | generate 62 | if (sim) begin 63 | 64 | integer f = 0; 65 | 66 | assign sig_en = |f & i_wb_cpu_we & (i_wb_cpu_adr == sim_sig_adr); 67 | assign halt_en = i_wb_cpu_we & (i_wb_cpu_adr == sim_halt_adr); 68 | 69 | reg [1023:0] signature_file; 70 | 71 | initial 72 | /* verilator lint_off WIDTH */ 73 | if ($value$plusargs("signature=%s", signature_file)) begin 74 | $display("Writing signature to %0s", signature_file); 75 | f = $fopen(signature_file, "w"); 76 | end 77 | /* verilator lint_on WIDTH */ 78 | 79 | always @(posedge i_clk) begin 80 | sim_ack <= 1'b0; 81 | if (i_wb_cpu_stb & !sim_ack) begin 82 | sim_ack <= sig_en|halt_en; 83 | if (sig_en & (f != 0)) 84 | $fwrite(f, "%c", i_wb_cpu_dat[7:0]); 85 | else if(halt_en) begin 86 | $display("Test complete"); 87 | $finish; 88 | end 89 | end 90 | if (i_rst) 91 | sim_ack <= 1'b0; 92 | end 93 | end else begin 94 | assign sig_en = 1'b0; 95 | assign halt_en = 1'b0; 96 | initial sim_ack = 1'b0; 97 | end 98 | endgenerate 99 | 100 | endmodule 101 | -------------------------------------------------------------------------------- /servile/servile_rf_mem_if.v: -------------------------------------------------------------------------------- 1 | /* 2 | * 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. 3 | * 4 | * SPDX-FileCopyrightText: 2024 Olof Kindgren 5 | * SPDX-License-Identifier: Apache-2.0 6 | */ 7 | 8 | `default_nettype none 9 | module servile_rf_mem_if 10 | #(//Memory parameters 11 | parameter depth = 256, 12 | //RF parameters 13 | parameter rf_regs = 32, 14 | //Internally calculated. Do not touch 15 | parameter rf_depth = $clog2(rf_regs*4), 16 | parameter aw = $clog2(depth)) 17 | ( 18 | input wire i_clk, 19 | input wire i_rst, 20 | input wire [rf_depth-1:0] i_waddr, 21 | input wire [7:0] i_wdata, 22 | input wire i_wen, 23 | input wire [rf_depth-1:0] i_raddr, 24 | output wire [7:0] o_rdata, 25 | input wire i_ren, 26 | 27 | output wire [aw-1:0] o_sram_waddr, 28 | output wire [7:0] o_sram_wdata, 29 | output wire o_sram_wen, 30 | output wire [aw-1:0] o_sram_raddr, 31 | input wire [7:0] i_sram_rdata, 32 | output wire o_sram_ren, 33 | 34 | input wire [aw-1:2] i_wb_adr, 35 | input wire [31:0] i_wb_dat, 36 | input wire [3:0] i_wb_sel, 37 | input wire i_wb_we, 38 | input wire i_wb_stb, 39 | output wire [31:0] o_wb_rdt, 40 | output reg o_wb_ack); 41 | 42 | reg [1:0] bsel; 43 | 44 | wire wb_en = i_wb_stb & !i_wen & !o_wb_ack; 45 | 46 | wire wb_we = i_wb_we & i_wb_sel[bsel]; 47 | 48 | wire [aw-1:0] rf_waddr = ~{{aw-rf_depth{1'b0}},i_waddr}; 49 | wire [aw-1:0] rf_raddr = ~{{aw-rf_depth{1'b0}},i_raddr}; 50 | 51 | assign o_sram_waddr = wb_en ? {i_wb_adr[aw-1:2],bsel} : rf_waddr; 52 | assign o_sram_wdata = wb_en ? i_wb_dat[bsel*8+:8] : i_wdata; 53 | assign o_sram_wen = wb_en ? wb_we : i_wen; 54 | assign o_sram_raddr = wb_en ? {i_wb_adr[aw-1:2],bsel} : rf_raddr; 55 | assign o_sram_ren = wb_en ? !i_wb_we : i_ren; 56 | 57 | reg [23:0] wb_rdt; 58 | assign o_wb_rdt = {i_sram_rdata, wb_rdt}; 59 | 60 | reg regzero; 61 | always @(posedge i_clk) begin 62 | 63 | if (wb_en) bsel <= bsel + 2'd1; 64 | o_wb_ack <= wb_en & &bsel; 65 | if (bsel == 2'b01) wb_rdt[7:0] <= i_sram_rdata; 66 | if (bsel == 2'b10) wb_rdt[15:8] <= i_sram_rdata; 67 | if (bsel == 2'b11) wb_rdt[23:16] <= i_sram_rdata; 68 | if (i_rst) begin 69 | bsel <= 2'd0; 70 | o_wb_ack <= 1'b0; 71 | end 72 | regzero <= &i_raddr[rf_depth-1:2]; 73 | end 74 | 75 | assign o_rdata = regzero ? 8'd0 : i_sram_rdata; 76 | 77 | endmodule 78 | -------------------------------------------------------------------------------- /serving.core: -------------------------------------------------------------------------------- 1 | CAPI=2: 2 | 3 | name : ::serving:1.3.0 4 | description: SERV-based subsystem for FPGAs 5 | 6 | filesets: 7 | rtl: 8 | files: 9 | - serving/serving_ram.v 10 | - serving/serving.v 11 | file_type : verilogSource 12 | depend : [servile] 13 | 14 | targets: 15 | default: 16 | filesets : [rtl] 17 | 18 | lint: 19 | default_tool : verilator 20 | description: Run static code checks (linting) 21 | filesets : [rtl] 22 | tools: 23 | verilator: 24 | mode : lint-only 25 | toplevel : serving 26 | -------------------------------------------------------------------------------- /serving/serving.v: -------------------------------------------------------------------------------- 1 | /* serving.v : Top-level for the serving SoC 2 | * 3 | * ISC License 4 | * 5 | * Copyright (C) 2020 Olof Kindgren 6 | * 7 | * Permission to use, copy, modify, and/or distribute this software for any 8 | * purpose with or without fee is hereby granted, provided that the above 9 | * copyright notice and this permission notice appear in all copies. 10 | * 11 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 12 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 13 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 14 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 15 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 16 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 17 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 18 | */ 19 | 20 | `default_nettype none 21 | module serving 22 | ( 23 | input wire i_clk, 24 | input wire i_rst, 25 | input wire i_timer_irq, 26 | 27 | output wire [31:0] o_wb_adr, 28 | output wire [31:0] o_wb_dat, 29 | output wire [3:0] o_wb_sel, 30 | output wire o_wb_we , 31 | output wire o_wb_stb, 32 | input wire [31:0] i_wb_rdt, 33 | input wire i_wb_ack); 34 | 35 | parameter memfile = ""; 36 | parameter memsize = 8192; 37 | parameter sim = 1'b0; 38 | parameter RESET_STRATEGY = "NONE"; 39 | parameter WITH_CSR = 1; 40 | localparam regs = 32+WITH_CSR*4; 41 | 42 | localparam rf_width = 8; 43 | 44 | wire [31:0] wb_mem_adr; 45 | wire [31:0] wb_mem_dat; 46 | wire [3:0] wb_mem_sel; 47 | wire wb_mem_we; 48 | wire wb_mem_stb; 49 | wire [31:0] wb_mem_rdt; 50 | wire wb_mem_ack; 51 | 52 | wire [6+WITH_CSR:0] rf_waddr; 53 | wire [rf_width-1:0] rf_wdata; 54 | wire rf_wen; 55 | wire [6+WITH_CSR:0] rf_raddr; 56 | wire [rf_width-1:0] rf_rdata; 57 | wire rf_ren; 58 | 59 | wire [$clog2(memsize)-1:0] sram_waddr; 60 | wire [rf_width-1:0] sram_wdata; 61 | wire sram_wen; 62 | wire [$clog2(memsize)-1:0] sram_raddr; 63 | wire [rf_width-1:0] sram_rdata; 64 | wire sram_ren; 65 | 66 | serving_ram 67 | #(.memfile (memfile), 68 | .depth (memsize)) 69 | ram 70 | (// Wishbone interface 71 | .i_clk (i_clk), 72 | .i_waddr (sram_waddr), 73 | .i_wdata (sram_wdata), 74 | .i_wen (sram_wen), 75 | .i_raddr (sram_raddr), 76 | .o_rdata (sram_rdata)/*, 77 | .i_ren (rf_ren)*/); 78 | 79 | servile_rf_mem_if 80 | #(.depth (memsize), 81 | .rf_regs (regs)) 82 | rf_mem_if 83 | (// Wishbone interface 84 | .i_clk (i_clk), 85 | .i_rst (i_rst), 86 | 87 | .i_waddr (rf_waddr), 88 | .i_wdata (rf_wdata), 89 | .i_wen (rf_wen), 90 | .i_raddr (rf_raddr), 91 | .o_rdata (rf_rdata), 92 | .i_ren (rf_ren), 93 | 94 | .o_sram_waddr (sram_waddr), 95 | .o_sram_wdata (sram_wdata), 96 | .o_sram_wen (sram_wen), 97 | .o_sram_raddr (sram_raddr), 98 | .i_sram_rdata (sram_rdata), 99 | .o_sram_ren (sram_ren), 100 | 101 | .i_wb_adr (wb_mem_adr[$clog2(memsize)-1:2]), 102 | .i_wb_stb (wb_mem_stb), 103 | .i_wb_we (wb_mem_we) , 104 | .i_wb_sel (wb_mem_sel), 105 | .i_wb_dat (wb_mem_dat), 106 | .o_wb_rdt (wb_mem_rdt), 107 | .o_wb_ack (wb_mem_ack)); 108 | 109 | servile 110 | #(.reset_pc (32'h0000_0000), 111 | .reset_strategy (RESET_STRATEGY), 112 | .rf_width (rf_width), 113 | .sim (sim), 114 | .with_csr (WITH_CSR)) 115 | servile 116 | ( 117 | .i_clk (i_clk), 118 | .i_rst (i_rst), 119 | .i_timer_irq (i_timer_irq), 120 | //Memory interface 121 | .o_wb_mem_adr (wb_mem_adr), 122 | .o_wb_mem_dat (wb_mem_dat), 123 | .o_wb_mem_sel (wb_mem_sel), 124 | .o_wb_mem_we (wb_mem_we), 125 | .o_wb_mem_stb (wb_mem_stb), 126 | .i_wb_mem_rdt (wb_mem_rdt), 127 | .i_wb_mem_ack (wb_mem_ack), 128 | 129 | //Extension interface 130 | .o_wb_ext_adr (o_wb_adr), 131 | .o_wb_ext_dat (o_wb_dat), 132 | .o_wb_ext_sel (o_wb_sel), 133 | .o_wb_ext_we (o_wb_we), 134 | .o_wb_ext_stb (o_wb_stb), 135 | .i_wb_ext_rdt (i_wb_rdt), 136 | .i_wb_ext_ack (i_wb_ack), 137 | 138 | //RF IF 139 | .o_rf_waddr (rf_waddr), 140 | .o_rf_wdata (rf_wdata), 141 | .o_rf_wen (rf_wen), 142 | .o_rf_raddr (rf_raddr), 143 | .o_rf_ren (rf_ren), 144 | .i_rf_rdata (rf_rdata)); 145 | 146 | 147 | endmodule 148 | -------------------------------------------------------------------------------- /serving/serving_ram.v: -------------------------------------------------------------------------------- 1 | /* serving_ram.v : I/D SRAM for the serving SoC 2 | * 3 | * ISC License 4 | * 5 | * Copyright (C) 2020 Olof Kindgren 6 | * 7 | * Permission to use, copy, modify, and/or distribute this software for any 8 | * purpose with or without fee is hereby granted, provided that the above 9 | * copyright notice and this permission notice appear in all copies. 10 | * 11 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 12 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 13 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 14 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 15 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 16 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 17 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 18 | */ 19 | 20 | `default_nettype none 21 | module serving_ram 22 | #(//Memory parameters 23 | parameter depth = 256, 24 | parameter aw = $clog2(depth), 25 | parameter memfile = "") 26 | (input wire i_clk, 27 | input wire [aw-1:0] i_waddr, 28 | input wire [7:0] i_wdata, 29 | input wire i_wen, 30 | input wire [aw-1:0] i_raddr, 31 | output reg [7:0] o_rdata); 32 | 33 | reg [7:0] mem [0:depth-1] /* verilator public */; 34 | 35 | always @(posedge i_clk) begin 36 | if (i_wen) mem[i_waddr] <= i_wdata; 37 | o_rdata <= mem[i_raddr]; 38 | end 39 | 40 | initial 41 | if(|memfile) begin 42 | $display("Preloading %m from %s", memfile); 43 | $readmemh(memfile, mem); 44 | end 45 | endmodule 46 | -------------------------------------------------------------------------------- /sw/Makefile: -------------------------------------------------------------------------------- 1 | TOOLCHAIN_PREFIX?=riscv64-unknown-elf- 2 | 3 | %.elf: %.S link.ld 4 | $(TOOLCHAIN_PREFIX)gcc -nostartfiles -nostdlib -march=rv32i_zicsr -mabi=ilp32 -Tlink.ld -o$@ $< 5 | %.bin: %.elf 6 | $(TOOLCHAIN_PREFIX)objcopy -O binary $< $@ 7 | %.hex: %.bin 8 | python3 makehex.py $< > $@ 9 | 10 | clean: 11 | rm -f *.elf *.bin *.hex 12 | -------------------------------------------------------------------------------- /sw/blinky.S: -------------------------------------------------------------------------------- 1 | /* 2 | * LED Blinker 3 | * Assuming that GPIO_BASE is mapped to a GPIO core, which in turn is 4 | * connected to LEDs, this will light the LEDs one at a time. 5 | * Useful as smoke test to see that serv is running correctly 6 | */ 7 | #ifndef GPIO_BASE 8 | #define GPIO_BASE 0x40000000 9 | #endif 10 | 11 | #ifndef DELAY 12 | #define DELAY 0x100000 /* Loop 100000 times before inverting the LED */ 13 | #endif 14 | 15 | /* 16 | a0 = GPIO Base address 17 | t0 = Value 18 | t1 = Timer max value 19 | t2 = Current timer value 20 | 21 | */ 22 | 23 | .globl _start 24 | _start: 25 | /* Load GPIO base address to a0 */ 26 | lui a0, %hi(GPIO_BASE) 27 | addi a0, a0, %lo(GPIO_BASE) 28 | 29 | /* Set timer value to control blink speed */ 30 | li t1, DELAY 31 | 32 | /* Clear t0 */ 33 | addi t0, zero, 0 34 | bl1: 35 | /* Write to LEDs */ 36 | sb t0, 0(a0) 37 | 38 | /* invert LED */ 39 | xori t0, t0, 1 40 | 41 | /* Reset timer */ 42 | and t2, zero, zero 43 | 44 | /* Delay loop */ 45 | time1: 46 | addi t2, t2, 1 47 | bne t1, t2, time1 48 | j bl1 49 | -------------------------------------------------------------------------------- /sw/blinky.hex: -------------------------------------------------------------------------------- 1 | 40000537 2 | 00050513 3 | 00100337 4 | 00000293 5 | 00550023 6 | 0012C293 7 | 000073B3 8 | 00138393 9 | FE731EE3 10 | FEDFF06F 11 | 00000000 12 | -------------------------------------------------------------------------------- /sw/hello_uart.S: -------------------------------------------------------------------------------- 1 | #define GPIO_ADDR 0x40000000 2 | #define HALT_ADDR 0x90000000 3 | 4 | /* 5 | a0 = GPIO address 6 | a1 = String address 7 | t0 = Character to write 8 | */ 9 | 10 | .globl _start 11 | _start: 12 | /* Load gpio address to a0 */ 13 | li a0, GPIO_ADDR 14 | 15 | /* Set GPIO high initially */ 16 | addi t0, zero, 1 17 | sb t0, 0(a0) 18 | 19 | /* Load string address to a1 */ 20 | la a1, str 21 | 22 | next_char: 23 | /* Read char from string */ 24 | lbu t0, 0(a1) 25 | 26 | /* If zero, we reached end of string and will exit the simulation */ 27 | beqz t0, halt 28 | 29 | /* Bitbanged UART loop */ 30 | ori t0, t0, 0x100 31 | slli t0, t0, 1 32 | 1: sb t0, 0(a0) 33 | srli t0, t0, 1 34 | 35 | /* 36 | * Adding delay nops to achieve an approximate 37 | * baud rate of 57600 at 16MHz 38 | */ 39 | nop 40 | nop 41 | bnez t0, 1b 42 | 43 | /* Increase address to next char in string */ 44 | addi a1, a1, 1 45 | 46 | j next_char 47 | 48 | /* Writing anything to HALT_ADDR will exit simulation */ 49 | halt: li t0, HALT_ADDR 50 | sw zero, 0(t0) 51 | /* 52 | * Loop to prevent PC from keep reading memory in case 53 | * we run on real HW and not in simulation 54 | */ 55 | j halt 56 | str: 57 | .section .data 58 | .string "Hi, I'm Servant!\n" 59 | -------------------------------------------------------------------------------- /sw/hello_uart.hex: -------------------------------------------------------------------------------- 1 | 40000537 2 | 00100293 3 | 00550023 4 | 00000597 5 | 04058593 6 | 0005C283 7 | 02028463 8 | 1002E293 9 | 00129293 10 | 00550023 11 | 0012D293 12 | 00000013 13 | 00000013 14 | FE0298E3 15 | 00158593 16 | FD9FF06F 17 | 900002B7 18 | 0002A023 19 | FF9FF06F 20 | 202C6948 21 | 206D2749 22 | 76726553 23 | 21746E61 24 | 0000000A 25 | -------------------------------------------------------------------------------- /sw/link.ld: -------------------------------------------------------------------------------- 1 | OUTPUT_ARCH( "riscv" ) 2 | ENTRY(_start) 3 | 4 | SECTIONS 5 | { 6 | . = 0x00000000; 7 | .text : { *(.text) } 8 | .data : { *(.data) } 9 | .bss : { *(.bss) } 10 | } 11 | -------------------------------------------------------------------------------- /sw/makehex.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # 3 | # This is free and unencumbered software released into the public domain. 4 | # 5 | # Anyone is free to copy, modify, publish, use, compile, sell, or 6 | # distribute this software, either in source code form or as a compiled 7 | # binary, for any purpose, commercial or non-commercial, and by any 8 | # means. 9 | 10 | import sys 11 | 12 | with open(sys.argv[1], "rb") as f: 13 | cnt = 3 14 | s = ["00"]*4 15 | while True: 16 | data = f.read(1) 17 | if not data: 18 | print(''.join(s)) 19 | exit(0) 20 | s[cnt] = "{:02X}".format(data[0]) 21 | if cnt == 0: 22 | print(''.join(s)) 23 | s = ["00"]*4 24 | cnt = 4 25 | cnt -= 1 26 | -------------------------------------------------------------------------------- /verif/Readme.md: -------------------------------------------------------------------------------- 1 | # SERV Verification using RISCOF 2 | SERV uses the [RISCOF](https://riscof.readthedocs.io/en/stable/index.html) which is python-based standard RISC-V Architectural Compliance Test Framework. This framework runs the Compliance tests in real-time on DUT and Reference and compare the signature results generated by both to decide if the tests are passed. 3 | In our case, DUT is SERV core and reference is the [sail-riscv](https://github.com/riscv/sail-riscv), which is the golden model for the formal specification of RISC-V architecture. 4 | 5 | 6 | ## Prerequisites 7 | 8 | > :warning: Make sure to complete all the steps described in [Getting Started](/README.md). Once it's done, start setting up the following tools. 9 | 10 | - [RISC-V GCC Toolchain](https://github.com/riscv-collab/riscv-gnu-toolchain) - Install toolchain by running following command. 11 | 12 | sudo apt-get install -y gcc-riscv64-unknown-elf 13 | > :bulb: By default, RISCOF plugins uses [RV32](https://github.com/riscv-collab/riscv-gnu-toolchain#:~:text=To%20build%20the%2032%2Dbit%20RV32GC%20toolchain%2C%20use%3A) toolchain for compiling native `rv32` code. For SERV, this dependency has been removed from the plugin as RV64 is sufficient for 32-bit systems as well. 14 | 15 | - [SAIL-RISCV](https://github.com/riscv/sail-riscv) - The reference model can be built by following [these](https://riscof.readthedocs.io/en/stable/installation.html#install-plugin-models) instructions. The pre-built binaries of sail-riscv is available in [`bin`](/verif/bin/) directory. Extract the tarball somewhere and add the directory containing `riscv_sim_RV32` to your PATH 16 | 17 | - [RISCOF](https://riscof.readthedocs.io/en/stable/installation.html#install-python) - If you have installed [Python](https://riscof.readthedocs.io/en/stable/installation.html#install-python), run the following command to [install RISCOF](https://riscof.readthedocs.io/en/stable/installation.html#). 18 | 19 | pip3 install riscof 20 | 21 | - [riscv-arch-tests](https://github.com/riscv-non-isa/riscv-arch-test) - Compliance tests are installed into the workspace by running: 22 | 23 | $ riscof arch-test --clone 24 | 25 | or alternatively 26 | 27 | $ riscof arch-test --update 28 | 29 | if the tests are already installed and just needs to be updated. 30 | 31 | > Make sure to have the directory structure that looks like this. 32 | 33 | 34 | 35 | . 36 | | 37 | ├── fusesoc.conf 38 | ├── fusesoc_libraries 39 | | ├── fusesoc_cores 40 | | │   └── ... 41 | | ├── mdu 42 | | │   └── ... 43 | | └── serv 44 | | ├── ... 45 | | ├── verif 46 | | | ├── bin 47 | | | | └── ... 48 | | |   ├── config.ini 49 | | |   ├── plugin-sail_cSim 50 | | | | └── ... 51 | | |   ├── plugin-serv 52 | | | | └── ... 53 | | └── ... 54 | ├── riscv-arch-test 55 | └── ... 56 | 57 | ## Running Compliance tests 58 | After completing all the steps in [Getting started](/README.md) followed by the [Prerequisites](#prerequisites), we are all set to run the compliance tests. 59 | 60 | :o: All the RISCOF commands will be run from the workspace 61 | 62 | riscof run --config=$SERV/verif/config.ini \ 63 | --suite=riscv-arch-test/riscv-test-suite/rv32i_m/I \ 64 | --env=riscv-arch-test/riscv-test-suite/env 65 | 66 | - `--config` - Configuration file is passed using this flag which contains the paths and the names of DUT and Reference plugins. 67 | - `--suite` - The arch-tests are passed to RISCOF using this flag. In the above command, it points `I` test directory. We can change path to `M`, `C`, `privilege` or `Zifencei` directories to run the respective tests. 68 | - `--env` - The header files of test framework are passed using this flag. 69 | 70 | > :bulb: Other optional arguments of RISCOF command can be found [here](https://riscof.readthedocs.io/en/stable/commands.html#run) 71 | 72 | When RISCOF run command successfully executed: an `html` report is generated which depicts the results of the tests. And a directory named `riscof_work` is created in the workspace which contains all the log files, signatures, executables for Reference model and/or DUT. -------------------------------------------------------------------------------- /verif/bin/Readme.md: -------------------------------------------------------------------------------- 1 | # Pre-build SAIL RISC-V Model Binaries 2 | 3 | SAIL RISC-V is the Golden reference model simulator for the formal specification of the RISC-V Architecture. The binaries are build by following the [instructions](https://riscof.readthedocs.io/en/stable/installation.html#install-plugin-models) available in RISCOF documentation. 4 | 5 | These binaries are build for both 32-bit and 64-bit architecture: 6 | 7 | - `riscv_sim_RV32` 8 | - `riscv_sim_RV64` 9 | 10 | > :warning: SAIL model binaries must be available in the `$PATH` variable. To do that: 11 | - Extract `sail-riscv.tar.gz` using 12 | 13 | tar -xzf sail-riscv.tar.gz sail-riscv 14 | - Binaries will be extracted in the directory named `sail-riscv`. Export the path of this directory to `$PATH` variable 15 | 16 | export PATH=/path/to/sail-riscv:$PATH -------------------------------------------------------------------------------- /verif/bin/sail-riscv.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/olofk/serv/a72c1e8737d424c31bf6ff909795acc37aa4cc90/verif/bin/sail-riscv.tar.gz -------------------------------------------------------------------------------- /verif/config.ini: -------------------------------------------------------------------------------- 1 | [RISCOF] 2 | ReferencePlugin=sail_cSim 3 | ReferencePluginPath=plugin-sail_cSim 4 | DUTPlugin=serv 5 | DUTPluginPath=plugin-serv 6 | 7 | [serv] 8 | pluginpath=plugin-serv 9 | ispec=plugin-serv/serv_isa.yaml 10 | pspec=plugin-serv/serv_platform.yaml 11 | target_run=1 12 | 13 | [sail_cSim] 14 | pluginpath=plugin-sail_cSim 15 | -------------------------------------------------------------------------------- /verif/plugin-sail_cSim/env/link.ld: -------------------------------------------------------------------------------- 1 | OUTPUT_ARCH( "riscv" ) 2 | ENTRY(rvtest_entry_point) 3 | 4 | SECTIONS 5 | { 6 | . = 0x80000000; 7 | .text.init : { *(.text.init) } 8 | . = ALIGN(0x1000); 9 | .tohost : { *(.tohost) } 10 | . = ALIGN(0x1000); 11 | .text : { *(.text) } 12 | . = ALIGN(0x1000); 13 | .data : { *(.data) } 14 | .data.string : { *(.data.string)} 15 | .bss : { *(.bss) } 16 | _end = .; 17 | } 18 | 19 | -------------------------------------------------------------------------------- /verif/plugin-sail_cSim/env/model_test.h: -------------------------------------------------------------------------------- 1 | #ifndef _COMPLIANCE_MODEL_H 2 | #define _COMPLIANCE_MODEL_H 3 | 4 | #define RVMODEL_DATA_SECTION \ 5 | .pushsection .tohost,"aw",@progbits; \ 6 | .align 8; .global tohost; tohost: .dword 0; \ 7 | .align 8; .global fromhost; fromhost: .dword 0; \ 8 | .popsection; \ 9 | .align 8; .global begin_regstate; begin_regstate: \ 10 | .word 128; \ 11 | .align 8; .global end_regstate; end_regstate: \ 12 | .word 4; 13 | 14 | //RV_COMPLIANCE_HALT 15 | #define RVMODEL_HALT \ 16 | li x1, 1; \ 17 | write_tohost: \ 18 | sw x1, tohost, t5; \ 19 | j write_tohost; 20 | 21 | #define RVMODEL_BOOT 22 | 23 | //RV_COMPLIANCE_DATA_BEGIN 24 | #define RVMODEL_DATA_BEGIN \ 25 | RVMODEL_DATA_SECTION \ 26 | .align 4;\ 27 | .global begin_signature; begin_signature: 28 | 29 | //RV_COMPLIANCE_DATA_END 30 | #define RVMODEL_DATA_END \ 31 | .align 4; .global end_signature; end_signature: 32 | 33 | //RVTEST_IO_INIT 34 | #define RVMODEL_IO_INIT 35 | //RVTEST_IO_WRITE_STR 36 | #define RVMODEL_IO_WRITE_STR(_R, _STR) 37 | //RVTEST_IO_CHECK 38 | #define RVMODEL_IO_CHECK() 39 | //RVTEST_IO_ASSERT_GPR_EQ 40 | #define RVMODEL_IO_ASSERT_GPR_EQ(_S, _R, _I) 41 | //RVTEST_IO_ASSERT_SFPR_EQ 42 | #define RVMODEL_IO_ASSERT_SFPR_EQ(_F, _R, _I) 43 | //RVTEST_IO_ASSERT_DFPR_EQ 44 | #define RVMODEL_IO_ASSERT_DFPR_EQ(_D, _R, _I) 45 | 46 | #define RVMODEL_SET_MSW_INT 47 | 48 | #define RVMODEL_CLEAR_MSW_INT 49 | 50 | #define RVMODEL_CLEAR_MTIMER_INT 51 | 52 | #define RVMODEL_CLEAR_MEXT_INT 53 | 54 | 55 | #endif // _COMPLIANCE_MODEL_H 56 | -------------------------------------------------------------------------------- /verif/plugin-serv/env/link.ld: -------------------------------------------------------------------------------- 1 | OUTPUT_ARCH( "riscv" ) 2 | ENTRY(rvtest_entry_point) 3 | 4 | SECTIONS 5 | { 6 | . = 0x00000000; 7 | .text.init : { *(.text.init) } 8 | .tohost : { *(.tohost) } 9 | .text : { *(.text) } 10 | .data : { *(.data) } 11 | .data.string : { *(.data.string)} 12 | .bss : { *(.bss) } 13 | _end = .; 14 | } 15 | 16 | -------------------------------------------------------------------------------- /verif/plugin-serv/env/model_test.h: -------------------------------------------------------------------------------- 1 | #ifndef _COMPLIANCE_MODEL_H 2 | #define _COMPLIANCE_MODEL_H 3 | 4 | #define RVMODEL_HALT \ 5 | la a0, begin_signature; \ 6 | la a1, end_signature; \ 7 | li a2, 0x80000000; \ 8 | compliance_halt_loop: \ 9 | beq a0, a1, compliance_halt_break; \ 10 | addi a3, a0, 4; \ 11 | compliance_halt_loop2: \ 12 | addi a3, a3, -1; \ 13 | \ 14 | lb a4, 0 (a3); \ 15 | srai a5, a4, 4; \ 16 | andi a5, a5, 0xF; \ 17 | li a6, 10; \ 18 | blt a5, a6, notLetter; \ 19 | addi a5, a5, 39; \ 20 | notLetter: \ 21 | addi a5, a5, 0x30; \ 22 | sw a5, 0 (a2); \ 23 | \ 24 | srai a5, a4, 0; \ 25 | andi a5, a5, 0xF; \ 26 | li a6, 10; \ 27 | blt a5, a6, notLetter2; \ 28 | addi a5, a5, 39; \ 29 | notLetter2: \ 30 | addi a5, a5, 0x30; \ 31 | sw a5, 0 (a2); \ 32 | bne a0, a3,compliance_halt_loop2; \ 33 | addi a0, a0, 4; \ 34 | \ 35 | li a4, '\n'; \ 36 | sw a4, 0 (a2); \ 37 | j compliance_halt_loop; \ 38 | j compliance_halt_break; \ 39 | compliance_halt_break:; \ 40 | lui a0,0x90000000>>12; \ 41 | sw a3,0(a0); 42 | 43 | 44 | #define RVMODEL_DATA_BEGIN \ 45 | .align 4; .global begin_signature; begin_signature: \ 46 | 47 | #define RVMODEL_DATA_END \ 48 | .align 4; .global end_signature; end_signature: \ 49 | 50 | 51 | #define RVMODEL_BOOT 52 | 53 | #define LOCAL_IO_WRITE_STR(_STR) RVMODEL_IO_WRITE_STR(x31, _STR) 54 | #define RVMODEL_IO_WRITE_STR(_SP, _STR) 55 | #define LOCAL_IO_PUSH(_SP) 56 | #define LOCAL_IO_POP(_SP) 57 | #define RVMODEL_IO_ASSERT_GPR_EQ(_SP, _R, _I) 58 | #define RVMODEL_IO_ASSERT_SFPR_EQ(_F, _R, _I) 59 | #define RVMODEL_IO_ASSERT_DFPR_EQ(_D, _R, _I) 60 | 61 | #define RVMODEL_SET_MSW_INT 62 | #define RVMODEL_CLEAR_MSW_INT 63 | #define RVMODEL_CLEAR_MTIMER_INT 64 | #define RVMODEL_CLEAR_MEXT_INT 65 | 66 | #endif // _COMPLIANCE_MODEL_H 67 | -------------------------------------------------------------------------------- /verif/plugin-serv/riscof_serv.py: -------------------------------------------------------------------------------- 1 | import os 2 | import logging 3 | 4 | import riscof.utils as utils 5 | from riscof.pluginTemplate import pluginTemplate 6 | 7 | logger = logging.getLogger() 8 | 9 | class serv(pluginTemplate): 10 | __model__ = "serv" 11 | __version__ = "1.3.0" 12 | 13 | def __init__(self, *args, **kwargs): 14 | sclass = super().__init__(*args, **kwargs) 15 | config = kwargs.get('config') 16 | config_dir = kwargs.get('config_dir') 17 | if config is None: 18 | print("Please enter input file paths in configuration.") 19 | raise SystemExit(1) 20 | self.pluginpath=os.path.join(config_dir, config['pluginpath']) 21 | self.isa_spec = os.path.join(config_dir, config['ispec']) 22 | self.platform_spec = os.path.join(config_dir, config['pspec']) 23 | if 'target_run' in config and config['target_run']=='0': 24 | self.target_run = False 25 | else: 26 | self.target_run = True 27 | return sclass 28 | 29 | def initialise(self, suite, work_dir, archtest_env): 30 | self.work_dir = work_dir 31 | self.suite_dir = suite 32 | self.compile_cmd = 'riscv64-unknown-elf-gcc -march={0} \ 33 | -static -mcmodel=medany -fvisibility=hidden -nostdlib -nostartfiles -g\ 34 | -T '+self.pluginpath+'/env/link.ld\ 35 | -I '+self.pluginpath+'/env/\ 36 | -I ' + archtest_env + ' {1} -o {2} {3}' 37 | 38 | add_mdu = 'fusesoc library add mdu https://github.com/zeeshanrafique23/mdu' 39 | utils.shellCommand(add_mdu).run() 40 | 41 | build_serv = 'fusesoc run --target=verilator_tb --flag=mdu\ 42 | --build --build-root=servant_test servant\ 43 | --memsize=8388608 --compressed=1' 44 | utils.shellCommand(build_serv).run() 45 | 46 | def build(self, isa_yaml, platform_yaml): 47 | ispec = utils.load_yaml(isa_yaml)['hart0'] 48 | self.xlen = ('64' if 64 in ispec['supported_xlen'] else '32') 49 | self.isa = 'rv' + self.xlen 50 | if "I" in ispec["ISA"]: 51 | self.isa += 'i' 52 | if "M" in ispec["ISA"]: 53 | self.isa += 'm' 54 | if "C" in ispec["ISA"]: 55 | self.isa += 'c' 56 | self.compile_cmd = self.compile_cmd+' -mabi='+('lp64 ' if 64 in ispec['supported_xlen'] else 'ilp32 ') 57 | 58 | def runTests(self, testList): 59 | for testentry in testList.values(): 60 | test = testentry['test_path'] 61 | test_dir = testentry['work_dir'] 62 | file_name = os.path.basename(test)[:-2] 63 | 64 | elf = file_name+'.elf' 65 | compile_macros= ' -D' + " -D".join(testentry['macros']) 66 | marchstr = testentry['isa'].lower() 67 | 68 | compile_run = self.compile_cmd.format(marchstr, test, elf, compile_macros) 69 | utils.shellCommand(compile_run).run(cwd=test_dir) 70 | 71 | objcopy_run = f'riscv64-unknown-elf-objcopy -O binary {elf} {file_name}.bin' 72 | utils.shellCommand(objcopy_run).run(cwd=test_dir) 73 | 74 | self.makehex(f"{test_dir}/{file_name}.bin", f"{test_dir}/{file_name}.hex") 75 | 76 | #The behavior of --build-root in FuseSoC has changed since version 2.2.1 77 | #Check first for executable model in the new location and else fall back 78 | #to the old one 79 | exe = 'servant_test/verilator_tb/Vservant_sim' 80 | if not os.path.exists(exe): 81 | exe = 'servant_test/servant_1.3.0/verilator_tb/Vservant_sim' 82 | 83 | sigdump_run = [exe, 84 | "+timeout=1000000000", 85 | f"+signature={test_dir}/DUT-serv.signature", 86 | f"+firmware={test_dir}/{file_name}.hex"] 87 | 88 | utils.shellCommand(' '.join(sigdump_run)).run() 89 | if not self.target_run: 90 | raise SystemExit 91 | 92 | def makehex(self, binfile, hexfile): 93 | with open(binfile, "rb") as f, open(hexfile, "w") as fout: 94 | cnt = 3 95 | s = ["00"]*4 96 | while True: 97 | data = f.read(1) 98 | if not data: 99 | fout.write(''.join(s)+'\n') 100 | return 101 | s[cnt] = "{:02X}".format(data[0]) 102 | if cnt == 0: 103 | fout.write(''.join(s)+'\n') 104 | s = ["00"]*4 105 | cnt = 4 106 | cnt -= 1 107 | -------------------------------------------------------------------------------- /verif/plugin-serv/serv_isa.yaml: -------------------------------------------------------------------------------- 1 | hart_ids: [0] 2 | hart0: 3 | ISA: RV32IMCZicsr_Zifencei 4 | physical_addr_sz: 32 5 | User_Spec_Version: '2.3' 6 | supported_xlen: [32] 7 | misa: 8 | reset-val: 0x40001104 9 | rv32: 10 | accessible: true 11 | mxl: 12 | implemented: true 13 | type: 14 | warl: 15 | dependency_fields: [] 16 | legal: 17 | - mxl[1:0] in [0x1] 18 | wr_illegal: 19 | - Unchanged 20 | extensions: 21 | implemented: true 22 | type: 23 | warl: 24 | dependency_fields: [] 25 | legal: 26 | - extensions[25:0] bitmask [0x0001104, 0x0000000] 27 | wr_illegal: 28 | - Unchanged 29 | 30 | -------------------------------------------------------------------------------- /verif/plugin-serv/serv_platform.yaml: -------------------------------------------------------------------------------- 1 | nmi: 2 | label: nmi_vector 3 | reset: 4 | label: reset_vector 5 | -------------------------------------------------------------------------------- /west.yml: -------------------------------------------------------------------------------- 1 | manifest: 2 | remotes: 3 | - name: zephyrproject-rtos 4 | url-base: https://github.com/zephyrproject-rtos 5 | projects: 6 | - name: zephyr 7 | remote: zephyrproject-rtos 8 | revision: v4.0.0 9 | import: true 10 | -------------------------------------------------------------------------------- /zephyr/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2020 Olof Kindgren 2 | # SPDX-License-Identifier: Apache-2.0 3 | 4 | add_subdirectory(drivers) 5 | -------------------------------------------------------------------------------- /zephyr/Kconfig: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2020 Olof Kindgren 2 | # SPDX-License-Identifier: Apache-2.0 3 | 4 | menu "SweRVolf" 5 | 6 | rsource "drivers/Kconfig" 7 | 8 | endmenu 9 | -------------------------------------------------------------------------------- /zephyr/boards/riscv/service/Kconfig.board: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2020 Olof Kindgren 2 | # 3 | # SPDX-License-Identifier: Apache-2.0 4 | 5 | config BOARD_SERVICE 6 | bool "servant SoC for iCE40" 7 | depends on SOC_RISCV32_SERVANT 8 | -------------------------------------------------------------------------------- /zephyr/boards/riscv/service/Kconfig.defconfig: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2020 Olof Kindgren 2 | # 3 | # SPDX-License-Identifier: Apache-2.0 4 | 5 | config BOARD 6 | default "service" 7 | depends on BOARD_SERVICE 8 | -------------------------------------------------------------------------------- /zephyr/boards/riscv/service/board.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020 Olof Kindgren 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | */ 6 | 7 | #ifndef __INC_BOARD_H 8 | #define __INC_BOARD_H 9 | 10 | #include 11 | 12 | #endif /* __INC_BOARD_H */ 13 | -------------------------------------------------------------------------------- /zephyr/boards/riscv/service/service.dts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020 Olof Kindgren 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | */ 6 | 7 | /dts-v1/; 8 | 9 | #include 10 | 11 | / { 12 | chosen { 13 | zephyr,sram = &ram; 14 | zephyr,console = &uart0; 15 | }; 16 | 17 | ram: memory@0 { 18 | compatible = "mmio-sram"; 19 | reg = <0x0 0x8000>; 20 | }; 21 | 22 | soc { 23 | compatible = "olofk,serv"; 24 | #address-cells = <1>; 25 | #size-cells = <1>; 26 | 27 | uart0: serial@0 { 28 | reg = <0x0 0x1>; 29 | compatible = "olofk,serial"; 30 | }; 31 | }; 32 | }; 33 | 34 | -------------------------------------------------------------------------------- /zephyr/boards/riscv/service/service.yaml: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2020 Olof Kindgren 2 | # 3 | # SPDX-License-Identifier: Apache-2.0 4 | 5 | identifier: service 6 | name: servant SoC for iCE40 7 | type: mcu 8 | arch: riscv32 9 | toolchain: 10 | - zephyr 11 | ram: 32 12 | vendor: olofk 13 | testing: 14 | ignore_tags: 15 | - net 16 | - bluetooth 17 | -------------------------------------------------------------------------------- /zephyr/boards/riscv/service/service_defconfig: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2020 Olof Kindgren 2 | # 3 | # SPDX-License-Identifier: Apache-2.0 4 | 5 | CONFIG_BOARD_SERVICE=y 6 | CONFIG_CONSOLE=y 7 | CONFIG_SERIAL=y 8 | CONFIG_UART_BITBANG=y 9 | 10 | CONFIG_UART_CONSOLE=y 11 | 12 | CONFIG_XIP=n 13 | -------------------------------------------------------------------------------- /zephyr/drivers/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2020 Olof Kindgren 2 | # SPDX-License-Identifier: Apache-2.0 3 | 4 | add_subdirectory_ifdef(CONFIG_SERIAL_HAS_DRIVER serial) 5 | add_subdirectory_ifdef(CONFIG_SYS_CLOCK_EXISTS timer) 6 | 7 | -------------------------------------------------------------------------------- /zephyr/drivers/Kconfig: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2020 Olof Kindgren 2 | # SPDX-License-Identifier: Apache-2.0 3 | 4 | menu "Device Drivers" 5 | 6 | rsource "serial/Kconfig" 7 | 8 | rsource "timer/Kconfig" 9 | 10 | endmenu 11 | -------------------------------------------------------------------------------- /zephyr/drivers/serial/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2020 Olof Kindgren 2 | # SPDX-License-Identifier: Apache-2.0 3 | 4 | set(ZEPHYR_CURRENT_LIBRARY drivers__serial) 5 | 6 | zephyr_library_sources_ifdef(CONFIG_UART_BITBANG uart_bitbang.c) 7 | -------------------------------------------------------------------------------- /zephyr/drivers/serial/Kconfig: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2020 Olof Kindgren 2 | # SPDX-License-Identifier: Apache-2.0 3 | 4 | if SERIAL 5 | 6 | menuconfig UART_BITBANG 7 | bool "SERV bitbang serial driver" 8 | select SERIAL_HAS_DRIVER 9 | help 10 | Enables the SERV bitbang serial driver. 11 | Hardcoded to send at ~57600 baud rate with a 16MHz clock 12 | 13 | endif 14 | -------------------------------------------------------------------------------- /zephyr/drivers/serial/uart_bitbang.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020 Olof Kindgren 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | */ 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #define DT_DRV_COMPAT olofk_serial 14 | 15 | #define reg_uart_data (*(volatile uint32_t*)UART_BITBANG_BASE) 16 | 17 | static struct k_spinlock lock; 18 | 19 | static void uart_bitbang_poll_out(const struct device *dev, unsigned char c) 20 | { 21 | ARG_UNUSED(dev); 22 | 23 | k_spinlock_key_t key = k_spin_lock(&lock); 24 | 25 | int cout = (c|0x100) << 1; 26 | do { 27 | reg_uart_data = cout; 28 | cout >>= 1; 29 | __asm__ __volatile__ ("nop"); 30 | __asm__ __volatile__ ("nop"); 31 | } while (cout); 32 | 33 | k_spin_unlock(&lock, key); 34 | } 35 | 36 | static int uart_bitbang_poll_in(const struct device *dev, unsigned char *c) 37 | { 38 | ARG_UNUSED(dev); 39 | 40 | *c = reg_uart_data; 41 | return 0; 42 | } 43 | 44 | static int uart_bitbang_init(const struct device *dev) 45 | { 46 | ARG_UNUSED(dev); 47 | reg_uart_data = 1; 48 | return 0; 49 | } 50 | 51 | static const struct uart_driver_api uart_bitbang_driver_api = { 52 | .poll_in = uart_bitbang_poll_in, 53 | .poll_out = uart_bitbang_poll_out, 54 | .err_check = NULL, 55 | }; 56 | 57 | struct my_dev_data { 58 | 59 | }; 60 | 61 | struct my_dev_cfg { 62 | 63 | }; 64 | 65 | #define CREATE_MY_DEVICE(inst) \ 66 | static struct my_dev_data my_data_##inst = { \ 67 | }; \ 68 | static const struct my_dev_cfg my_cfg_##inst = { \ 69 | }; \ 70 | DEVICE_DT_INST_DEFINE(inst, \ 71 | uart_bitbang_init, \ 72 | NULL, \ 73 | &my_data_##inst, \ 74 | &my_cfg_##inst, \ 75 | PRE_KERNEL_1, CONFIG_SERIAL_INIT_PRIORITY, \ 76 | &uart_bitbang_driver_api); 77 | 78 | DT_INST_FOREACH_STATUS_OKAY(CREATE_MY_DEVICE) 79 | -------------------------------------------------------------------------------- /zephyr/drivers/timer/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2020 Olof Kindgren 2 | # SPDX-License-Identifier: Apache-2.0 3 | 4 | zephyr_library_sources_ifdef(CONFIG_SERV_TIMER serv_timer.c) 5 | 6 | -------------------------------------------------------------------------------- /zephyr/drivers/timer/Kconfig: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2020 Olof Kindgren 2 | # SPDX-License-Identifier: Apache-2.0 3 | 4 | config SERV_TIMER 5 | bool "SERV Timer" 6 | select TICKLESS_CAPABLE 7 | help 8 | This module implements a kernel device driver for the SERV 9 | timer driver. It provides the standard "system clock driver" interfaces. 10 | -------------------------------------------------------------------------------- /zephyr/drivers/timer/serv_timer.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020 Olof Kindgren 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | */ 6 | 7 | /* 8 | This is basically a 32-bit version of riscv_machine_timer.c for Zephyr 9 | */ 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | #define CYC_PER_TICK ((uint32_t)((uint32_t)sys_clock_hw_cycles_per_sec() \ 17 | / (uint32_t)CONFIG_SYS_CLOCK_TICKS_PER_SEC)) 18 | #define MAX_CYC 0xffffffffu 19 | #define MAX_TICKS ((MAX_CYC - CYC_PER_TICK) / CYC_PER_TICK) 20 | #define MIN_DELAY 1000 21 | 22 | #define TICKLESS IS_ENABLED(CONFIG_TICKLESS_KERNEL) 23 | 24 | static struct k_spinlock lock; 25 | static uint32_t last_count; 26 | 27 | static ALWAYS_INLINE void set_mtimecmp(uint32_t time) 28 | { 29 | sys_write32(time, SERV_TIMER_BASE); 30 | } 31 | 32 | static ALWAYS_INLINE uint32_t mtime(void) 33 | { 34 | return sys_read32(SERV_TIMER_BASE); 35 | } 36 | 37 | static void timer_isr(void *arg) 38 | { 39 | ARG_UNUSED(arg); 40 | 41 | k_spinlock_key_t key = k_spin_lock(&lock); 42 | uint32_t now = mtime(); 43 | uint32_t dticks = ((now - last_count) / CYC_PER_TICK); 44 | 45 | last_count += dticks * CYC_PER_TICK; 46 | 47 | if (!TICKLESS) { 48 | uint32_t next = last_count + CYC_PER_TICK; 49 | 50 | if ((int32_t)(next - now) < MIN_DELAY) { 51 | next += CYC_PER_TICK; 52 | } 53 | set_mtimecmp(next); 54 | } 55 | 56 | k_spin_unlock(&lock, key); 57 | sys_clock_announce(IS_ENABLED(CONFIG_TICKLESS_KERNEL) ? dticks : 1); 58 | } 59 | 60 | int sys_clock_driver_init() 61 | { 62 | IRQ_CONNECT(RISCV_MACHINE_TIMER_IRQ, 0, timer_isr, NULL, 0); 63 | last_count = mtime(); 64 | set_mtimecmp(last_count + (uint32_t)CYC_PER_TICK); 65 | irq_enable(RISCV_MACHINE_TIMER_IRQ); 66 | return 0; 67 | } 68 | 69 | void sys_clock_set_timeout(int32_t ticks, bool idle) 70 | { 71 | ARG_UNUSED(idle); 72 | 73 | #if defined(CONFIG_TICKLESS_KERNEL) 74 | /* RISCV has no idle handler yet, so if we try to spin on the 75 | * logic below to reset the comparator, we'll always bump it 76 | * forward to the "next tick" due to MIN_DELAY handling and 77 | * the interrupt will never fire! Just rely on the fact that 78 | * the OS gave us the proper timeout already. 79 | */ 80 | if (idle) { 81 | return; 82 | } 83 | 84 | ticks = ticks == K_TICKS_FOREVER ? MAX_TICKS : ticks; 85 | ticks = MAX(MIN(ticks - 1, (int32_t)MAX_TICKS), 0); 86 | 87 | k_spinlock_key_t key = k_spin_lock(&lock); 88 | uint32_t now = mtime(); 89 | uint32_t adj, cyc = ticks * CYC_PER_TICK; 90 | 91 | /* Round up to next tick boundary. */ 92 | adj = (now - last_count) + (CYC_PER_TICK - 1); 93 | if (cyc <= MAX_CYC - adj) { 94 | cyc += adj; 95 | } else { 96 | cyc = MAX_CYC; 97 | } 98 | cyc = (cyc / CYC_PER_TICK) * CYC_PER_TICK; 99 | 100 | if ((int32_t)(cyc + last_count - now) < MIN_DELAY) { 101 | cyc += CYC_PER_TICK; 102 | } 103 | 104 | set_mtimecmp(cyc + last_count); 105 | k_spin_unlock(&lock, key); 106 | #endif 107 | } 108 | 109 | uint32_t sys_clock_elapsed(void) 110 | { 111 | if (!IS_ENABLED(CONFIG_TICKLESS_KERNEL)) { 112 | return 0; 113 | } 114 | 115 | k_spinlock_key_t key = k_spin_lock(&lock); 116 | uint32_t ret = (mtime() - last_count) / CYC_PER_TICK; 117 | 118 | k_spin_unlock(&lock, key); 119 | return ret; 120 | } 121 | 122 | uint32_t sys_timer_cycle_get_32(void) 123 | { 124 | return mtime(); 125 | } 126 | 127 | SYS_INIT(sys_clock_driver_init, PRE_KERNEL_2, 128 | CONFIG_SYSTEM_CLOCK_INIT_PRIORITY); 129 | -------------------------------------------------------------------------------- /zephyr/dts/riscv/serv.dtsi: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020 Olof Kindgren 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | */ 6 | 7 | / { 8 | #address-cells = <1>; 9 | #size-cells = <1>; 10 | compatible = "olofk,servant"; 11 | 12 | cpus { 13 | #address-cells = <1>; 14 | #size-cells = <0>; 15 | 16 | cpu0: cpu@0 { 17 | compatible = "olofk,serv"; 18 | riscv,isa = "rv32i_zicsr"; 19 | reg = <0>; 20 | device_type = "cpu"; 21 | }; 22 | }; 23 | }; 24 | -------------------------------------------------------------------------------- /zephyr/module.yml: -------------------------------------------------------------------------------- 1 | build: 2 | settings: 3 | board_root: zephyr 4 | dts_root: zephyr 5 | soc_root: zephyr 6 | -------------------------------------------------------------------------------- /zephyr/soc/riscv/servant/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2020 Olof Kindgren 2 | # SPDX-License-Identifier: Apache-2.0 3 | 4 | zephyr_sources( 5 | soc_irq.S 6 | vector.S 7 | cpu_idle.c 8 | irq.c) 9 | -------------------------------------------------------------------------------- /zephyr/soc/riscv/servant/Kconfig.defconfig: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2020 Olof Kindgren 2 | # SPDX-License-Identifier: Apache-2.0 3 | 4 | if SOC_RISCV32_SERVANT 5 | 6 | config SOC 7 | string 8 | default "servant" 9 | 10 | config SYS_CLOCK_HW_CYCLES_PER_SEC 11 | int 12 | default 16000000 13 | 14 | config RISCV_SOC_INTERRUPT_INIT 15 | bool 16 | default y 17 | 18 | config NUM_IRQS 19 | int 20 | default 8 21 | 22 | config SERV_TIMER 23 | bool 24 | default y 25 | 26 | config ARCH_HAS_CUSTOM_CPU_IDLE 27 | bool 28 | default y 29 | 30 | config ARCH_HAS_CUSTOM_CPU_ATOMIC_IDLE 31 | bool 32 | default y 33 | 34 | config RISCV_SOC_EXCEPTION_FROM_IRQ 35 | bool 36 | default y 37 | 38 | endif # SOC_RISCV32_SERVANT 39 | -------------------------------------------------------------------------------- /zephyr/soc/riscv/servant/Kconfig.soc: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2020 Olof Kindgren 2 | # SPDX-License-Identifier: Apache-2.0 3 | 4 | config SOC_RISCV32_SERVANT 5 | bool "servant SoC" 6 | select RISCV 7 | select ATOMIC_OPERATIONS_C 8 | select RISCV_ISA_EXT_ZICSR 9 | -------------------------------------------------------------------------------- /zephyr/soc/riscv/servant/cpu_idle.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | // Override arch_cpu_idle() and arch_cpu_atomic_idle() to prevent insertion 5 | // of `wfi` instructions, which lock up our system. This was introduced in 6 | // Zephyr 3.6.0 with commit 5fb6e267f629dedb8382da6bcad8018b1bb8930a. 7 | // 8 | // This is probably a hardware bug in SERV. This issue is tracked as #131. 9 | // https://github.com/olofk/serv/issues/131 10 | 11 | void arch_cpu_idle(void) 12 | { 13 | sys_trace_idle(); 14 | irq_unlock(MSTATUS_IEN); 15 | } 16 | 17 | void arch_cpu_atomic_idle(unsigned int key) 18 | { 19 | sys_trace_idle(); 20 | irq_unlock(key); 21 | } 22 | 23 | -------------------------------------------------------------------------------- /zephyr/soc/riscv/servant/irq.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017 Jean-Paul Etienne 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | */ 6 | 7 | /** 8 | * @file 9 | * @brief interrupt management code for riscv SOCs supporting the riscv 10 | privileged architecture specification 11 | */ 12 | #include 13 | 14 | void arch_irq_enable(unsigned int irq) 15 | { 16 | uint32_t mie; 17 | 18 | /* 19 | * CSR mie register is updated using atomic instruction csrrs 20 | * (atomic read and set bits in CSR register) 21 | */ 22 | __asm__ volatile ("csrrs %0, mie, %1\n" 23 | : "=r" (mie) 24 | : "r" (1 << irq)); 25 | } 26 | 27 | void arch_irq_disable(unsigned int irq) 28 | { 29 | uint32_t mie; 30 | 31 | /* 32 | * Use atomic instruction csrrc to disable device interrupt in mie CSR. 33 | * (atomic read and clear bits in CSR register) 34 | */ 35 | __asm__ volatile ("csrrc %0, mie, %1\n" 36 | : "=r" (mie) 37 | : "r" (1 << irq)); 38 | }; 39 | 40 | int arch_irq_is_enabled(unsigned int irq) 41 | { 42 | uint32_t mie; 43 | 44 | __asm__ volatile ("csrr %0, mie" : "=r" (mie)); 45 | 46 | return !!(mie & (1 << irq)); 47 | } 48 | 49 | #if defined(CONFIG_RISCV_SOC_INTERRUPT_INIT) 50 | void soc_interrupt_init(void) 51 | { 52 | /* ensure that all interrupts are disabled */ 53 | (void)irq_lock(); 54 | 55 | __asm__ volatile ("csrwi mie, 0\n" 56 | "csrwi mip, 0\n"); 57 | } 58 | #endif 59 | -------------------------------------------------------------------------------- /zephyr/soc/riscv/servant/linker.ld: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 Antmicro 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | */ 6 | 7 | #include 8 | -------------------------------------------------------------------------------- /zephyr/soc/riscv/servant/soc.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020 Olof Kindgren 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | */ 6 | 7 | #ifndef __RISCV32_SERVANT_SOC_H_ 8 | #define __RISCV32_SERVANT_SOC_H_ 9 | 10 | #include 11 | 12 | /* Bitbang UART configuration */ 13 | #define UART_BITBANG_BASE 0x40000000 14 | 15 | /* Timer configuration */ 16 | #define SERV_TIMER_BASE 0x80000000 17 | #define SERV_TIMER_IRQ 7 18 | 19 | #endif /* __RISCV32_SERVANT_SOC_H_ */ 20 | -------------------------------------------------------------------------------- /zephyr/soc/riscv/servant/soc_common.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017 Jean-Paul Etienne 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | */ 6 | 7 | /** 8 | * @file configuration macros for riscv SOCs supporting the riscv 9 | * privileged architecture specification 10 | */ 11 | 12 | #ifndef __SOC_COMMON_H_ 13 | #define __SOC_COMMON_H_ 14 | 15 | /* IRQ numbers */ 16 | #define RISCV_MACHINE_SOFT_IRQ 3 /* Machine Software Interrupt */ 17 | #define RISCV_MACHINE_TIMER_IRQ 7 /* Machine Timer Interrupt */ 18 | #define RISCV_MACHINE_EXT_IRQ 11 /* Machine External Interrupt */ 19 | 20 | /* ECALL Exception numbers */ 21 | #define SOC_MCAUSE_ECALL_EXP 11 /* Machine ECALL instruction */ 22 | #define SOC_MCAUSE_USER_ECALL_EXP 8 /* User ECALL instruction */ 23 | 24 | /* SOC-specific MCAUSE bitfields */ 25 | #ifdef CONFIG_64BIT 26 | /* Interrupt Mask */ 27 | #define SOC_MCAUSE_IRQ_MASK (1 << 63) 28 | /* Exception code Mask */ 29 | #define SOC_MCAUSE_EXP_MASK 0x7FFFFFFFFFFFFFFF 30 | #else 31 | /* Interrupt Mask */ 32 | #define SOC_MCAUSE_IRQ_MASK (1 << 31) 33 | /* Exception code Mask */ 34 | #define SOC_MCAUSE_EXP_MASK 0x7FFFFFFF 35 | #endif 36 | 37 | /* SOC-Specific EXIT ISR command */ 38 | #define SOC_ERET mret 39 | 40 | #ifndef _ASMLANGUAGE 41 | 42 | #if defined(CONFIG_RISCV_SOC_INTERRUPT_INIT) 43 | void soc_interrupt_init(void); 44 | #endif 45 | 46 | #if defined(CONFIG_RISCV_HAS_PLIC) 47 | void riscv_plic_irq_enable(uint32_t irq); 48 | void riscv_plic_irq_disable(uint32_t irq); 49 | int riscv_plic_irq_is_enabled(uint32_t irq); 50 | void riscv_plic_set_priority(uint32_t irq, uint32_t priority); 51 | int riscv_plic_get_irq(void); 52 | #endif 53 | 54 | #endif /* !_ASMLANGUAGE */ 55 | 56 | #endif /* __SOC_COMMON_H_ */ 57 | -------------------------------------------------------------------------------- /zephyr/soc/riscv/servant/soc_irq.S: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017 Jean-Paul Etienne 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | */ 6 | 7 | /* 8 | * common interrupt management code for riscv SOCs supporting the riscv 9 | * privileged architecture specification 10 | */ 11 | #include 12 | #include 13 | #include 14 | 15 | /* exports */ 16 | GTEXT(__soc_handle_irq) 17 | 18 | /* 19 | * SOC-specific function to handle pending IRQ number generating the interrupt. 20 | * Exception number is given as parameter via register a0. 21 | */ 22 | SECTION_FUNC(exception.other, __soc_handle_irq) 23 | /* Clear exception number from CSR mip register */ 24 | li t1, 1 25 | sll t0, t1, a0 26 | csrrc t1, mip, t0 27 | 28 | /* Return */ 29 | jalr x0, ra 30 | 31 | /* 32 | * __soc_is_irq is defined as .weak to allow re-implementation by 33 | * SOCs that does not truly follow the riscv privilege specification. 34 | */ 35 | WTEXT(__soc_is_irq) 36 | 37 | /* 38 | * SOC-specific function to determine if the exception is the result of a 39 | * an interrupt or an exception 40 | * return 1 (interrupt) or 0 (exception) 41 | * 42 | */ 43 | SECTION_FUNC(exception.other, __soc_is_irq) 44 | /* Read mcause and check if interrupt bit is set */ 45 | csrr t0, mcause 46 | li t1, SOC_MCAUSE_IRQ_MASK 47 | and t0, t0, t1 48 | 49 | /* If interrupt bit is not set, return with 0 */ 50 | addi a0, x0, 0 51 | beqz t0, not_interrupt 52 | addi a0, a0, 1 53 | 54 | not_interrupt: 55 | /* return */ 56 | jalr x0, ra 57 | -------------------------------------------------------------------------------- /zephyr/soc/riscv/servant/vector.S: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017 Jean-Paul Etienne 3 | * Contributors: 2018 Antmicro 4 | * 5 | * SPDX-License-Identifier: Apache-2.0 6 | */ 7 | 8 | #include 9 | 10 | /* exports */ 11 | GTEXT(__start) 12 | 13 | /* imports */ 14 | GTEXT(__initialize) 15 | GTEXT(_isr_wrapper) 16 | 17 | SECTION_FUNC(vectors, __start) 18 | .option norvc; 19 | 20 | /* 21 | * Set mtvec (Machine Trap-Vector Base-Address Register) 22 | * to __isr_wrapper. 23 | */ 24 | la t0, _isr_wrapper 25 | csrw mtvec, t0 26 | 27 | /* Jump to __initialize */ 28 | tail __initialize 29 | --------------------------------------------------------------------------------