├── .github ├── dependabot.yml └── workflows │ └── main.yml ├── .gitignore ├── .gitmodules ├── LICENSE ├── README.md ├── sim ├── Makefile ├── iverilog_sim.sh ├── testbench.v └── uart_sim_receiver.v └── src ├── convert.sh └── neorv32_verilog_wrapper.vhd /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: gitsubmodule 4 | directory: / 5 | commit-message: 6 | prefix: '[Dependabot]' 7 | schedule: 8 | interval: weekly 9 | time: '04:00' 10 | open-pull-requests-limit: 99 11 | -------------------------------------------------------------------------------- /.github/workflows/main.yml: -------------------------------------------------------------------------------- 1 | name: 'neorv32-verilog check' 2 | 3 | on: 4 | push: 5 | pull_request: 6 | schedule: 7 | - cron: '0 0 * * 5' 8 | workflow_dispatch: 9 | 10 | 11 | jobs: 12 | 13 | convert: 14 | name: '♻️ Convert to Verilog' 15 | runs-on: ubuntu-latest 16 | 17 | steps: 18 | 19 | - name: '📂 Repository Checkout' 20 | uses: actions/checkout@v4 21 | with: 22 | fetch-depth: 0 23 | submodules: recursive 24 | 25 | - name: '📦 Install GHDL' 26 | uses: ghdl/setup-ghdl@v1 27 | with: 28 | version: nightly 29 | backend: mcode 30 | 31 | - name: '⚙️ Run conversion' 32 | run: /bin/bash -c "chmod u+x $GITHUB_WORKSPACE/src/convert.sh && $GITHUB_WORKSPACE/src/convert.sh" 33 | 34 | - name: '📤 Archive generated Verilog code' 35 | if: always() 36 | uses: actions/upload-artifact@v4 37 | with: 38 | name: neorv32_verilog_wrapper 39 | path: src/neorv32_verilog_wrapper.v 40 | 41 | 42 | sim_iverilog: 43 | name: '🖥️ Simulation - Icarus Verilog' 44 | needs: convert 45 | runs-on: ubuntu-latest 46 | 47 | steps: 48 | 49 | - name: '📂 Repository Checkout' 50 | uses: actions/checkout@v4 51 | with: 52 | fetch-depth: 0 53 | submodules: recursive 54 | 55 | - name: '📂 Checkout Conversion Artifact' 56 | uses: actions/download-artifact@v4 57 | with: 58 | name: neorv32_verilog_wrapper 59 | path: src 60 | 61 | - name: '📦 Install Icarus Verilog' 62 | run: sudo apt install iverilog 63 | 64 | - name: '⚙️ Run Simulation' 65 | run: | 66 | cd $GITHUB_WORKSPACE 67 | ls -al src 68 | make -C sim SIM=icarus | tee iverilog.log 69 | grep 'Simulation successful!' iverilog.log 70 | 71 | 72 | sim_verilator: 73 | name: '🖥️ Simulation - Verilator' 74 | needs: convert 75 | runs-on: ubuntu-latest 76 | 77 | steps: 78 | 79 | - name: '📂 Repository Checkout' 80 | uses: actions/checkout@v4 81 | with: 82 | fetch-depth: 0 83 | submodules: recursive 84 | 85 | - name: '📂 Checkout Conversion Artifact' 86 | uses: actions/download-artifact@v4 87 | with: 88 | name: neorv32_verilog_wrapper 89 | path: src 90 | 91 | - name: '📦 Install Verilator' 92 | run: sudo apt install verilator 93 | 94 | - name: '⚙️ Run Simulation' 95 | run: | 96 | cd $GITHUB_WORKSPACE 97 | ls -al src 98 | make -C sim SIM=verilator | tee verilator.log 99 | grep 'Simulation successful!' verilator.log 100 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | sim/neorv32-verilog-sim 2 | obj_dir 3 | *.log 4 | src/build 5 | src/*.v 6 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "neorv32"] 2 | path = neorv32 3 | url = https://github.com/stnolting/neorv32 4 | ignore = dirty 5 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | BSD 3-Clause License 2 | 3 | Copyright (c) 2024, Stephan Nolting 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | 1. Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | 2. Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | 3. Neither the name of the copyright holder nor the names of its 17 | contributors may be used to endorse or promote products derived from 18 | this software without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # NEORV32 _in_ Verilog 2 | 3 | [![neorv32-verilog](https://img.shields.io/github/actions/workflow/status/stnolting/neorv32-verilog/main.yml?branch=main&longCache=true&style=flat-square&label=neorv32-verilog%20check&logo=Github%20Actions&logoColor=fff)](https://github.com/stnolting/neorv32-verilog/actions/workflows/main.yml) 4 | [![License](https://img.shields.io/github/license/stnolting/neorv32-verilog?longCache=true&style=flat-square&label=License)](https://github.com/stnolting/neorv32-verilog/blob/main/LICENSE) 5 | 6 | 1. [Prerequisites](#prerequisites) 7 | 2. [Configuration](#configuration) 8 | 3. [Conversion](#conversion) 9 | 4. [Simulation](#simulation) 10 | 5. [Evaluation](#evaluation) 11 | 12 | This repository shows how to convert a complex **VHDL** design into a single, synthesizable, **plain-Verilog module** using 13 | [GHDL's](https://github.com/ghdl/ghdl) synthesis feature. The example in this repository is based on the 14 | [NEORV32 RISC-V Processor](https://github.com/stnolting/neorv32), which is written in _platform-independent_ VHDL. 15 | The resulting Verilog module can be instantiated within an all-Verilog design and can be successfully simulated and 16 | synthesized - tested with Xilinx Vivado and Intel Quartus (see section [Evaluation](#evaluation)). 17 | 18 | Detailed information regarding GHDL's synthesis feature can be found in the 19 | [GHDL synthesis documentation](https://ghdl.github.io/ghdl/using/Synthesis.html). 20 | 21 | > [!NOTE] 22 | > The [verification workflow](https://github.com/stnolting/neorv32-verilog/actions/workflows/main.yml) 23 | converts a pre-configured setup of the latest NEORV32 version to Verilog and tests the result by running 24 | an [Icarus Verilog](https://github.com/steveicarus/iverilog) simulation. 25 | The generated Verilog code for the default processor configuration can be downloaded as 26 | [CI Workflow artifact](https://github.com/stnolting/neorv32-verilog/actions). 27 | 28 | 29 | ## Prerequisites 30 | 31 | 1. Clone this repository recursively to include the NEORV32 submodule. 32 | 33 | 2. Install GHDL. On a Linux machine GHDL can be installed easily via the package manager. 34 | :warning: **Make sure to install a version with `--synth` option enabled (should be enabled by default). 35 | GHDL version 3.0.0 or higher is required.** 36 | 37 | ``` 38 | $ sudo apt-get install ghdl 39 | ``` 40 | 41 | 42 | 3. Test the GHDL installation and check the version. 43 | 44 | ``` 45 | $ ghdl -v 46 | GHDL 4.0.0-dev (3.0.0.r823.g9e2b6fc95) [Dunoon edition] 47 | Compiled with GNAT Version: 9.4.0 48 | static elaboration, mcode code generator 49 | Written by Tristan Gingold. 50 | 51 | Copyright (C) 2003 - 2023 Tristan Gingold. 52 | GHDL is free software, covered by the GNU General Public License. There is NO 53 | warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 54 | ``` 55 | 56 | [[back to top](#neorv32-in-verilog)] 57 | 58 | 59 | ## Configuration 60 | 61 | GHDL's `synth` option is used to convert the whole NEORV32 processor - including all peripherals, memories 62 | and memory images - into a single plain-Verilog module file. 63 | 64 | > [!WARNING] 65 | > The output of the GHDL synthesis is a _post-elaboration_ result. Therefore, all the processor's configuration 66 | options (i.e. VHDL generics) are resolved _before_ the actual output is generated (see the GHDL 67 | [internals documentation](http://ghdl.github.io/ghdl/internals/index.html)). 68 | 69 | To ease configuration and customization a minimal VHDL wrapper 70 | [`src/neorv32_verilog_wrapper.vhd`](https://github.com/stnolting/neorv32-verilog/blob/main/src/neorv32_verilog_wrapper.vhd) 71 | is provided. This wrapper can be used to configure the processor setup according to the requirements. 72 | The default wrapper from this repository only implements a minimal subset of the available configuration options 73 | and interfaces - just enough to run the processor's built-in bootloader. 74 | 75 | Have a look at the original [processor top entity (`neorv32_top.vhd`)](https://github.com/stnolting/neorv32/blob/main/rtl/core/neorv32_top.vhd) 76 | and just copy the generics and ports that you would like to use for the Verilog setup. 77 | Note that all NEORV32 interface inputs and configuration generics do provide _default values_. 78 | 79 | [[back to top](#neorv32-in-verilog)] 80 | 81 | 82 | ## Conversion 83 | 84 | The actual conversion is conducted by a conversion shell script, which analyzes all the processor's sources and finally 85 | calls GHDL `synth` to create the final Verilog code `neorv32-verilog/src/neorv32_verilog_wrapper.v`. 86 | 87 | ```bash 88 | neorv32-verilog/src$ sh convert.sh 89 | ``` 90 | 91 | After conversion, the interface of the resulting `neorv32_verilog_wrapper` Verilog 92 | module is shown in the console. This can be used as instantiation template. 93 | 94 | ``` 95 | ------ neorv32_verilog_wrapper interface ------ 96 | module neorv32_verilog_wrapper 97 | (input clk_i, 98 | input rstn_i, 99 | input uart0_rxd_i, 100 | output uart0_txd_o); 101 | ----------------------------------------------- 102 | ``` 103 | 104 | ### Notes 105 | 106 | * GHDL synthesis generates an unoptimized plain Verilog code without any (technology-specific) primitives. 107 | However, optimizations will be performed by the synthesis tool (e.g. mapping to FPGA primitives like block RAMs). 108 | * The interface of the resulting NEORV32 Verilog module lists all inputs first followed by all outputs. 109 | * The original NEORV32 module hierarchy is preserved as well as most (all?) signal names, which allows easy inspection and debugging 110 | of simulation waveforms and synthesis results. 111 | * Custom VHDL interface types and records are collapsed into linear arrays. 112 | 113 | [[back to top](#neorv32-in-verilog)] 114 | 115 | 116 | ## Simulation 117 | 118 | This repository provides a simple [Verilog testbench](https://github.com/stnolting/neorv32-verilog/blob/main/sim/testbench.v) 119 | that can be used to simulate the default NEORV32 configuration. The testbench includes a UART receiver, which is driven by the 120 | processor UART0. It outputs received characters to the simulator console. 121 | 122 | A pre-configured simulation script based on either [Icarus Verilog](https://github.com/steveicarus/iverilog) or [Verilator](https://www.veripool.org/verilator/) can be used to simulate 123 | the Verilog setup (takes several minutes to complete with Icarus; few seconds after the compilation stage with Verilator): 124 | 125 | ```bash 126 | cd neorv32-verilog/sim 127 | # run the makefile: Icarus is the default simulator 128 | make 129 | # or with Verilator 130 | SIM=verilator make 131 | ``` 132 | ``` 133 | neorv32-verilog verification testbench 134 | 135 | 136 | 137 | 138 | << NEORV32 139 | Simulation successful! 140 | ./testbench.v:79: $finish called at 95372250 (100ps) 141 | ``` 142 | 143 | The simulation is terminated automatically as soon as the string "`NEORV32`" has been received from the processor's bootloader. 144 | In this case `Simulation successful!` is printed to the console. If `Simulation terminated!` appears in the simulator console 145 | the simulation has failed. 146 | 147 | [![Check_iverilog](https://img.shields.io/github/actions/workflow/status/stnolting/icarus-verilog-prebuilt/check_iverilog.yml?branch=main&longCache=true&style=flat&label=Check%20iverilog%20packages&logo=Github%20Actions&logoColor=fff)](https://github.com/stnolting/icarus-verilog-prebuilt/actions/workflows/check_iverilog.yml) 148 | \ 149 | Prebuilt Icarus Verilog binaries for Linux can be downloaded from 150 | [stnolting/icarus-verilog-prebuilt](https://github.com/stnolting/icarus-verilog-prebuilt). 151 | 152 | [[back to top](#neorv32-in-verilog)] 153 | 154 | 155 | ## Evaluation 156 | 157 | It's time for a "quality" evaluation of the auto-generated Verilog. Therefore, 158 | two projects were created: a pure Verilog one using the auto-generated `src/neorv32_verilog_wrapper.v` file and a 159 | pure VHDL one using the provided `src/neorv32_verilog_wrapper.vhd` file. For both projects a simple top entity was 160 | created (again, a Verilog and a VHDL version) that instantiate the according `neorv32_verilog_wrapper` module 161 | together with a PLL for providing clock (100MHz) and reset. 162 | 163 | The default configuration of the wrapper was used: 164 | 165 | * Memories: 16kB IMEM (RAM), 8kB DMEM (RAM), 4kB internal bootloader ROM 166 | * CPU: `rv32imc_Zicsr_Zicntr_Zifencei` 167 | * Peripherals: UART0, GPIO, MTIME 168 | 169 | Both setups were synthesized for an Intel Cyclone IV E FPGA (EP4CE22F17C6) using Intel Quartus Prime 21.1.0 170 | with default settings ("balanced" implementation). The timing analyzer's "Slow 1200mV 0C Model" was used to 171 | evaluate the maximum operating frequency f_max. Additionally, both setups were (successfully! :tada:) tested 172 | on a Terasic DE0-nano FPGA board. 173 | 174 | | NEORV32 [v1.7.6.0](https://github.com/stnolting/neorv32/blob/main/CHANGELOG.md) | All-Verilog | All-VHDL | 175 | |:---------------------|:-----------:|:--------:| 176 | | Total logic elements | 3697 | 3287 | 177 | | Total registers | 1436 | 1450 | 178 | | Total pins | 4 | 4 | 179 | | Total memory bits | 230400 | 230400 | 180 | | Embedded multiplier | 0 | 0 | 181 | | f_max [MHz] | 115.3 | 122.2 | 182 | | Operational | yes | yes | 183 | 184 | [[back to top](#neorv32-in-verilog)] 185 | -------------------------------------------------------------------------------- /sim/Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: run clean 2 | 3 | all: run 4 | 5 | SIM ?= icarus 6 | SRC_FOLDER ?= ../src 7 | SIM_FOLDER ?= . 8 | 9 | SRC_FILES = $(SIM_FOLDER)/testbench.v $(SIM_FOLDER)/uart_sim_receiver.v $(SRC_FOLDER)/neorv32_verilog_wrapper.v 10 | VERILATOR_ARGS = -Wno-fatal --binary --trace 11 | 12 | __run_icarus: 13 | iverilog -o neorv32-verilog-sim $(SRC_FILES) 14 | vvp neorv32-verilog-sim 15 | 16 | __run_verilator: 17 | verilator $(VERILATOR_ARGS) $(SRC_FILES) 18 | ./obj_dir/Vtestbench 19 | 20 | run: 21 | @echo "Running simulation with $(SIM)" 22 | ifeq ($(SIM), icarus) 23 | $(MAKE) __run_icarus 24 | else ifeq ($(SIM), verilator) 25 | $(MAKE) __run_verilator 26 | else 27 | $(error Unsupported simulator: $(SIM)) 28 | endif 29 | 30 | clean: 31 | @rm -rf ./neorv32-verilog-sim obj_dir 32 | -------------------------------------------------------------------------------- /sim/iverilog_sim.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e 4 | 5 | cd $(dirname "$0") 6 | 7 | SRC_FOLDER=${SRC_FOLDER:-../src} 8 | SIM_FOLDER=${SIM_FOLDER:-.} 9 | 10 | iverilog -o "$SIM_FOLDER"/neorv32-verilog-sim "$SIM_FOLDER"/testbench.v "$SIM_FOLDER"/uart_sim_receiver.v "$SRC_FOLDER"/neorv32_verilog_wrapper.v 11 | vvp "$SIM_FOLDER"/neorv32-verilog-sim 12 | -------------------------------------------------------------------------------- /sim/testbench.v: -------------------------------------------------------------------------------- 1 | // simple testbench to check the default NEORV32 Verilog wrapper 2 | // checks for the initial UART output of the bootloader ("NEORV32") 3 | 4 | // (c) 2024 by Stephan Nolting, BSD 3-Clause License 5 | // https://github.com/stnolting/neorv32-verilog 6 | 7 | `timescale 1 ns/100 ps // time-unit = 1 ns, precision = 100 ps 8 | 9 | module neorv32_verilog_tb; 10 | 11 | reg clk, nrst; // generators 12 | wire uart_txd; // serial TX line (default baud rate is 19200) 13 | wire [7:0] char_data; // character detected by the UART receiver 14 | wire char_valid; // valid character 15 | 16 | // generator setup 17 | initial begin 18 | $display ("neorv32-verilog verification testbench\n"); 19 | clk = 0; 20 | nrst = 0; 21 | #100; // active reset for 100 * timescale = 100 ns 22 | nrst = 1; 23 | #15_000_000; 24 | // if we reach this the simulation has failed 25 | $display("Simulation terminated (time out)!"); 26 | $finish; // terminate 27 | end 28 | 29 | // clock generator 30 | always begin 31 | #5 clk = !clk; // T = 2*5ns -> f = 100MHz 32 | end 33 | 34 | // unit under test: minimal NEORV32 Verilog wrapper 35 | // note that there are NO parameters available - the configuration has to be done 36 | // in the NEORV32 VHDL wrapper *before* synthesizing the generated Verilog code 37 | neorv32_verilog_wrapper neorv32_verilog_inst ( 38 | .clk_i (clk), 39 | .rstn_i (nrst), 40 | .uart0_rxd_i (1'b0), 41 | .uart0_txd_o (uart_txd) 42 | ); 43 | 44 | // simulation UART receiver - outputs all received characters to the simulator console 45 | uart_sim_receiver #( 46 | .CLOCK_FREQ (100000000), // clock frequency of the core 47 | .BAUD_RATE (19200) // default baud rate of the NEORV32 bootloader 48 | ) uart_sim_receiver_inst( 49 | .clk_i (clk), 50 | .txd_i (uart_txd), 51 | .data_o (char_data), 52 | .valid_o (char_valid) 53 | ); 54 | 55 | // buffer the processor's UART data in a small FIFO-like queue 56 | reg [7:0] char_buffer [0:6]; 57 | integer i; 58 | 59 | always @(posedge clk) begin 60 | // update "FIFO" 61 | if (char_valid == 1'b1) begin 62 | // top-to-bottom shift 63 | for (i=6; i>0; i=i-1) begin 64 | char_buffer[i-1] <= char_buffer[i]; 65 | end 66 | char_buffer[6] <= char_data; 67 | end 68 | // check for result string: "NEORV32" is sent by the default bootloader right after reset 69 | if ((char_buffer[0] == "N") && 70 | (char_buffer[1] == "E") && 71 | (char_buffer[2] == "O") && 72 | (char_buffer[3] == "R") && 73 | (char_buffer[4] == "V") && 74 | (char_buffer[5] == "3") && 75 | (char_buffer[6] == "2")) begin 76 | // simulation was successful 77 | $display (""); // force line break 78 | $display("Simulation successful!"); 79 | $finish; // terminate 80 | end 81 | end 82 | 83 | endmodule 84 | -------------------------------------------------------------------------------- /sim/uart_sim_receiver.v: -------------------------------------------------------------------------------- 1 | // Simulation UART receiver 2 | // Outputs printable characters to the simulator console; uses Linux-style line breaks 3 | // Character data is also returned to the top entity for further processing 4 | 5 | // by Stephan Nolting, BSD 3-Clause License 6 | // https://github.com/stnolting/neorv32-verilog 7 | 8 | module uart_sim_receiver 9 | #( 10 | parameter CLOCK_FREQ = 100000000, // clock frequency of in Hz 11 | parameter BAUD_RATE = 19200 // target baud rate 12 | ) 13 | ( 14 | input wire clk_i, // clock input, triggering on rising edge 15 | input wire txd_i, // UART transmit data 16 | output wire [7:0] data_o, // character data 17 | output wire valid_o // character data valid when set 18 | ); 19 | 20 | // duration of a single bit 21 | localparam UART_BAUD_VAL = CLOCK_FREQ / BAUD_RATE; 22 | 23 | reg [4:0] uart_rx_sync; // synchronizer shift register 24 | reg uart_rx_busy; // busy flag 25 | reg [8:0] uart_rx_sreg; // de-serializer 26 | integer uart_rx_baud_cnt; // bit-sample counter for baud rate 27 | integer uart_rx_bitcnt; // bit counter: 8 data bits, 1 start bit 28 | wire [7:0] char = uart_rx_sreg[8:1]; // character data 29 | 30 | // initialize because we don't have a real reset 31 | initial begin 32 | uart_rx_sync = 5'b11111; 33 | uart_rx_busy = 1'b0; 34 | uart_rx_sreg = 9'b000000000; 35 | uart_rx_baud_cnt = UART_BAUD_VAL / 2; 36 | uart_rx_bitcnt = 0; 37 | end 38 | 39 | // UART receiver 40 | always @(posedge clk_i) begin 41 | // synchronizer 42 | uart_rx_sync <= {uart_rx_sync[3:0], txd_i}; 43 | // arbiter 44 | if (!uart_rx_busy) begin // idle 45 | uart_rx_busy <= 0; 46 | uart_rx_baud_cnt <= UART_BAUD_VAL / 2; 47 | uart_rx_bitcnt <= 9; 48 | if (uart_rx_sync[4:1] == 4'b1100) begin // start bit (falling edge)? 49 | uart_rx_busy <= 1; 50 | end 51 | end else begin 52 | if (uart_rx_baud_cnt == 0) begin 53 | if (uart_rx_bitcnt == 1) begin 54 | uart_rx_baud_cnt <= UART_BAUD_VAL / 2; 55 | end else begin 56 | uart_rx_baud_cnt <= UART_BAUD_VAL; 57 | end 58 | // sample 8 data bits and 1 start bit 59 | if (uart_rx_bitcnt == 0) begin 60 | uart_rx_busy <= 1'b0; // done 61 | if ((char >= 32) && (char <= 127)) begin // is a printable char? 62 | $write("%c", char); 63 | end else if (char == 10) begin // Linux line break? 64 | $display(""); // force terminal line break 65 | end 66 | end else begin 67 | uart_rx_sreg <= {uart_rx_sync[4], uart_rx_sreg[8:1]}; 68 | uart_rx_bitcnt <= uart_rx_bitcnt - 1; 69 | end 70 | end else begin 71 | uart_rx_baud_cnt <= uart_rx_baud_cnt - 1; 72 | end 73 | end 74 | end 75 | 76 | // character output 77 | assign data_o = char; // character data 78 | assign valid_o = ((uart_rx_baud_cnt == 0) && (uart_rx_bitcnt == 0)) ? 1'b1 : 1'b0; // character valid 79 | 80 | endmodule // uart_sim_receiver 81 | -------------------------------------------------------------------------------- /src/convert.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e 4 | 5 | cd $(dirname "$0") 6 | 7 | # NEORV32 home folder 8 | NEORV32_HOME=${NEORV32_RTL:-../neorv32} 9 | # Additional sources (i.e. the top unit) 10 | SRC_FOLDER=${SRC_FOLDER:-.} 11 | # Name of the top unit 12 | TOP=neorv32_verilog_wrapper 13 | 14 | mkdir -p build 15 | 16 | # show NEORV32 version 17 | echo "NEORV32 Version:" 18 | grep -rni $NEORV32_HOME/rtl/core/neorv32_package.vhd -e 'hw_version_c' 19 | echo "" 20 | sleep 2 21 | 22 | # Import and analyze sources 23 | ghdl -i --std=08 --work=neorv32 --workdir=build -Pbuild $NEORV32_HOME/rtl/core/*.vhd $SRC_FOLDER/$TOP.vhd 24 | ghdl -m --std=08 --work=neorv32 --workdir=build $TOP 25 | # Synthesize Verilog 26 | ghdl synth --std=08 --work=neorv32 --workdir=build -Pbuild --out=verilog $TOP > $SRC_FOLDER/$TOP.v 27 | 28 | # Show interface of generated Verilog module 29 | echo "" 30 | echo "-----------------------------------------------" 31 | echo "Verilog instantiation prototype" 32 | echo "-----------------------------------------------" 33 | sed -n "/module $TOP/,/);/p" $SRC_FOLDER/$TOP.v 34 | echo "-----------------------------------------------" 35 | echo "" 36 | -------------------------------------------------------------------------------- /src/neorv32_verilog_wrapper.vhd: -------------------------------------------------------------------------------- 1 | -- ================================================================================ -- 2 | -- NEORV32 Wrapper for Verilog Conversion -- 3 | -- -------------------------------------------------------------------------------- -- 4 | -- The NEORV32 RISC-V Processor - https://github.com/stnolting/neorv32 -- 5 | -- Copyright (c) NEORV32 contributors. -- 6 | -- Copyright (c) 2020 - 2025 Stephan Nolting. All rights reserved. -- 7 | -- Licensed under the BSD-3-Clause license, see LICENSE for details. -- 8 | -- SPDX-License-Identifier: BSD-3-Clause -- 9 | -- ================================================================================ -- 10 | 11 | library ieee; 12 | use ieee.std_logic_1164.all; 13 | 14 | library neorv32; 15 | use neorv32.neorv32_package.all; 16 | 17 | entity neorv32_verilog_wrapper is 18 | port ( -- [note] add ports as required; generics cannot be used 19 | -- Global control -- 20 | clk_i : in std_ulogic; -- global clock, rising edge 21 | rstn_i : in std_ulogic; -- global reset, low-active, async 22 | -- UART0 -- 23 | uart0_txd_o : out std_ulogic; -- UART0 send data 24 | uart0_rxd_i : in std_ulogic -- UART0 receive data 25 | ); 26 | end entity; 27 | 28 | architecture neorv32_verilog_wrapper_rtl of neorv32_verilog_wrapper is 29 | 30 | begin 31 | 32 | -- The core of the problem ---------------------------------------------------------------- 33 | -- ------------------------------------------------------------------------------------------- 34 | neorv32_top_inst: neorv32_top 35 | generic map ( -- [note] add configuration options as required 36 | -- Processor Clocking -- 37 | CLOCK_FREQUENCY => 100_000_000, -- clock frequency of clk_i in Hz 38 | -- Boot Configuration -- 39 | BOOT_MODE_SELECT => 0, -- boot via internal bootloader 40 | -- On-Chip Debugger (OCD) -- 41 | OCD_EN => true, -- implement on-chip debugger 42 | OCD_AUTHENTICATION => true, -- implement on-chip debugger authentication 43 | -- RISC-V CPU Extensions -- 44 | RISCV_ISA_C => true, -- implement compressed extension 45 | RISCV_ISA_M => true, -- implement mul/div extension 46 | RISCV_ISA_U => true, -- implement user mode extension 47 | RISCV_ISA_Zaamo => true, -- implement atomic memory operations extension 48 | RISCV_ISA_Zba => true, -- implement shifted-add bit-manipulation extension 49 | RISCV_ISA_Zbb => true, -- implement basic bit-manipulation extension 50 | RISCV_ISA_Zbkb => true, -- implement bit-manipulation instructions for cryptography 51 | RISCV_ISA_Zbkc => true, -- implement carry-less multiplication instructions 52 | RISCV_ISA_Zbkx => true, -- implement cryptography crossbar permutation extension 53 | RISCV_ISA_Zbs => true, -- implement single-bit bit-manipulation extension 54 | RISCV_ISA_Zfinx => true, -- implement 32-bit floating-point extension 55 | RISCV_ISA_Zicntr => true, -- implement base counters 56 | RISCV_ISA_Zicond => true, -- implement integer conditional operations 57 | RISCV_ISA_Zihpm => true, -- implement hardware performance monitors 58 | RISCV_ISA_Zknd => true, -- implement cryptography NIST AES decryption extension 59 | RISCV_ISA_Zkne => true, -- implement cryptography NIST AES encryption extension 60 | RISCV_ISA_Zknh => true, -- implement cryptography NIST hash extension 61 | RISCV_ISA_Zksed => true, -- implement ShangMi block cipher extension 62 | RISCV_ISA_Zksh => true, -- implement ShangMi hash extension 63 | RISCV_ISA_Zxcfu => true, -- implement custom (instr.) functions unit 64 | -- Tuning Options -- 65 | CPU_FAST_MUL_EN => true, -- use DSPs for M extension's multiplier 66 | CPU_FAST_SHIFT_EN => true, -- use barrel shifter for shift operations 67 | -- Physical Memory Protection (PMP) -- 68 | PMP_NUM_REGIONS => 4, -- number of regions (0..16) 69 | PMP_MIN_GRANULARITY => 4, -- minimal region granularity in bytes, has to be a power of 2, min 4 bytes 70 | PMP_TOR_MODE_EN => true, -- implement TOR mode 71 | PMP_NAP_MODE_EN => true, -- implement NAPOT/NA4 modes 72 | -- Hardware Performance Monitors (HPM) -- 73 | HPM_NUM_CNTS => 6, -- number of implemented HPM counters (0..13) 74 | HPM_CNT_WIDTH => 40, -- total size of HPM counters (0..64) 75 | -- Internal Instruction memory (IMEM) -- 76 | IMEM_EN => true, -- implement processor-internal instruction memory 77 | IMEM_SIZE => 16*1024, -- size of processor-internal instruction memory in bytes 78 | -- Internal Data memory (DMEM) -- 79 | DMEM_EN => true, -- implement processor-internal data memory 80 | DMEM_SIZE => 8*1024, -- size of processor-internal data memory in bytes 81 | -- CPU Caches -- 82 | ICACHE_EN => true, -- implement instruction cache (i-cache) 83 | ICACHE_NUM_BLOCKS => 4, -- i-cache: number of blocks (min 1), has to be a power of 2 84 | DCACHE_EN => true, -- implement data cache (d-cache) 85 | DCACHE_NUM_BLOCKS => 4, -- d-cache: number of blocks (min 1), has to be a power of 2 86 | CACHE_BLOCK_SIZE => 64, -- i-cache/d-cache: block size in bytes (min 4), has to be a power of 2 87 | -- External bus interface (XBUS) -- 88 | XBUS_EN => true, -- implement external memory bus interface? 89 | XBUS_TIMEOUT => 256, -- cycles after a pending bus access auto-terminates (0 = disabled) 90 | XBUS_REGSTAGE_EN => true, -- add XBUS register stage 91 | -- Processor peripherals -- 92 | IO_CLINT_EN => true, -- implement core local interruptor (CLINT)? 93 | IO_UART0_EN => true, -- implement primary universal asynchronous receiver/transmitter (UART0)? 94 | IO_UART0_RX_FIFO => 64, -- RX FIFO depth, has to be a power of two, min 1 95 | IO_UART0_TX_FIFO => 64, -- TX FIFO depth, has to be a power of two, min 1 96 | IO_SPI_EN => true, -- implement serial peripheral interface (SPI)? 97 | IO_TWI_EN => true, -- implement two-wire interface (TWI)? 98 | IO_TWD_EN => true, -- implement two-wire device (TWD)? 99 | IO_PWM_NUM_CH => 2, -- number of PWM channels to implement (0..16) 100 | IO_WDT_EN => true, -- implement watch dog timer (WDT)? 101 | IO_NEOLED_EN => true, -- implement NeoPixel-compatible smart LED interface (NEOLED)? 102 | IO_GPTMR_EN => true, -- implement general purpose timer (GPTMR)? 103 | IO_ONEWIRE_EN => true, -- implement 1-wire interface (ONEWIRE)? 104 | IO_DMA_EN => true, -- implement direct memory access controller (DMA)? 105 | IO_SLINK_EN => true -- implement stream link interface (SLINK)? 106 | ) 107 | port map ( -- [note] add ports as required 108 | -- Global control -- 109 | clk_i => clk_i, -- global clock, rising edge 110 | rstn_i => rstn_i, -- global reset, low-active, async 111 | -- primary UART0 (available if IO_UART0_EN = true) -- 112 | uart0_txd_o => uart0_txd_o, -- UART0 send data 113 | uart0_rxd_i => uart0_rxd_i -- UART0 receive data 114 | ); 115 | 116 | end architecture; 117 | --------------------------------------------------------------------------------