Giter Club home page Giter Club logo

neorv32-verilog's Introduction

NEORV32 in Verilog

neorv32-verilog License

  1. Prerequisites
  2. Configuration
  3. Conversion
  4. Simulation
  5. Evaluation

This repository shows how to convert a complex VHDL design into a single, synthesizable, plain-Verilog module using GHDL's synthesis feature. The example in this repository is based on the NEORV32 RISC-V Processor, which is written in platform-independent VHDL. The resulting Verilog module can be instantiated within an all-Verilog design and can be successfully simulated and synthesized - tested with Xilinx Vivado and Intel Quartus (see section Evaluation).

Detailed information regarding GHDL's synthesis feature can be found in the GHDL synthesis documentation.

Note

The verification workflow converts a pre-configured setup of the latest NEORV32 version to Verilog and tests the result by running an Icarus Verilog simulation. The generated Verilog code for the default processor configuration can be downloaded as CI Workflow artifact.

Prerequisites

  1. Clone this repository recursively to include the NEORV32 submodule.

  2. Install GHDL. On a Linux machine GHDL can be installed easily via the package manager. :warning: Make sure to install a version with --synth option enabled (should be enabled by default). GHDL version 3.0.0 or higher is required.

$ sudo apt-get install ghdl
  1. Test the GHDL installation and check the version.
$ ghdl -v
GHDL 4.0.0-dev (3.0.0.r823.g9e2b6fc95) [Dunoon edition]
 Compiled with GNAT Version: 9.4.0
 static elaboration, mcode code generator
Written by Tristan Gingold.

Copyright (C) 2003 - 2023 Tristan Gingold.
GHDL is free software, covered by the GNU General Public License.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

[back to top]

Configuration

GHDL's synth option is used to convert the whole NEORV32 processor - including all peripherals, memories and memory images - into a single plain-Verilog module file.

Warning

The output of the GHDL synthesis is a post-elaboration result. Therefore, all the processor's configuration options (i.e. VHDL generics) are resolved before the actual output is generated (see the GHDL internals documentation).

To ease configuration and customization a minimal VHDL wrapper src/neorv32_verilog_wrapper.vhd is provided. This wrapper can be used to configure the processor setup according to the requirements. The default wrapper from this repository only implements a minimal subset of the available configuration options and interfaces - just enough to run the processor's built-in bootloader.

Have a look at the original processor top entity (neorv32_top.vhd) and just copy the generics and ports that you would like to use for the Verilog setup. Note that all NEORV32 interface inputs and configuration generics do provide default values.

[back to top]

Conversion

The actual conversion is conducted by a conversion shell script, which analyzes all the processor's sources and finally calls GHDL synth to create the final Verilog code neorv32-verilog/src/neorv32_verilog_wrapper.v.

neorv32-verilog/src$ sh convert.sh

After conversion, the interface of the resulting neorv32_verilog_wrapper Verilog module is shown in the console. This can be used as instantiation template.

------ neorv32_verilog_wrapper interface ------
module neorv32_verilog_wrapper
  (input  clk_i,
   input  rstn_i,
   input  uart0_rxd_i,
   output uart0_txd_o);
-----------------------------------------------

Notes

  • GHDL synthesis generates an unoptimized plain Verilog code without any (technology-specific) primitives. However, optimizations will be performed by the synthesis tool (e.g. mapping to FPGA primitives like block RAMs).
  • The interface of the resulting NEORV32 Verilog module lists all inputs first followed by all outputs.
  • The original NEORV32 module hierarchy is preserved as well as most (all?) signal names, which allows easy inspection and debugging of simulation waveforms and synthesis results.
  • Custom VHDL interface types and records are collapsed into linear arrays.

[back to top]

Simulation

This repository provides a simple Verilog testbench that can be used to simulate the default NEORV32 configuration. The testbench includes a UART receiver, which is driven by the processor UART0. It outputs received characters to the simulator console.

A pre-configured simulation script based on Icarus Verilog can be used to simulate the Verilog setup (takes several minutes to complete):

neorv32-verilog/sim$ sh iverilog_sim.sh
neorv32-verilog verification testbench




<< NEORV32
Simulation successful!
./testbench.v:79: $finish called at 95372250 (100ps)

The simulation is terminated automatically as soon as the string "NEORV32" has been received from the processor's bootloader. In this case Simulation successful! is printed to the console. If Simulation terminated! appears in the simulator console the simulation has failed.

Check_iverilog
Prebuilt Icarus Verilog binaries for Linux can be downloaded from stnolting/icarus-verilog-prebuilt.

[back to top]

Evaluation

It's time for a "quality" evaluation of the auto-generated Verilog. Therefore, two projects were created: a pure Verilog one using the auto-generated src/neorv32_verilog_wrapper.v file and a pure VHDL one using the provided src/neorv32_verilog_wrapper.vhd file. For both projects a simple top entity was created (again, a Verilog and a VHDL version) that instantiate the according neorv32_verilog_wrapper module together with a PLL for providing clock (100MHz) and reset.

The default configuration of the wrapper was used:

  • Memories: 16kB IMEM (RAM), 8kB DMEM (RAM), 4kB internal bootloader ROM
  • CPU: rv32imc_Zicsr_Zicntr_Zifencei
  • Peripherals: UART0, GPIO, MTIME

Both setups were synthesized for an Intel Cyclone IV E FPGA (EP4CE22F17C6) using Intel Quartus Prime 21.1.0 with default settings ("balanced" implementation). The timing analyzer's "Slow 1200mV 0C Model" was used to evaluate the maximum operating frequency f_max. Additionally, both setups were (successfully! 🎉) tested on a Terasic DE0-nano FPGA board.

NEORV32 v1.7.6.0 All-Verilog All-VHDL
Total logic elements 3697 3287
Total registers 1436 1450
Total pins 4 4
Total memory bits 230400 230400
Embedded multiplier 0 0
f_max [MHz] 115.3 122.2
Operational yes yes

[back to top]

neorv32-verilog's People

Contributors

dependabot[bot] avatar stnolting avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

neorv32-verilog's Issues

Unable to run on Ubuntu 20.04

Hi,

I have just cloned the repo and installed the latest version of https://github.com/YosysHQ/oss-cad-suite-build (2022-09-25). I am able to run convert.sh correctly, but when I run iverilog_sim.sh I get the following error (trimmed as it is basically the same thing over and over):

$ ./iverilog_sim.sh
../src/neorv32_verilog_wrapper.v:20290: error: Could not find variable ``n1647_oport['sd1023]'' in ``neorv32_verilog_tb.uut.neorv32_top_inst.neorv32_boot_rom_inst_true_neorv32_boot_rom_inst''
../src/neorv32_verilog_wrapper.v:20291: error: Could not find variable ``n1647_oport['sd1022]'' in ``neorv32_verilog_tb.uut.neorv32_top_inst.neorv32_boot_rom_inst_true_neorv32_boot_rom_inst''
../src/neorv32_verilog_wrapper.v:20292: error: Could not find variable ``n1647_oport['sd1021]'' in ``neorv32_verilog_tb.uut.neorv32_top_inst.neorv32_boot_rom_inst_true_neorv32_boot_rom_inst''
../src/neorv32_verilog_wrapper.v:20293: error: Could not find variable ``n1647_oport['sd1020]'' in ``neorv32_verilog_tb.uut.neorv32_top_inst.neorv32_boot_rom_inst_true_neorv32_boot_rom_inst''
../src/neorv32_verilog_wrapper.v:20294: error: Could not find variable ``n1647_oport['sd1019]'' in ``neorv32_verilog_tb.uut.neorv32_top_inst.neorv32_boot_rom_inst_true_neorv32_boot_rom_inst''

...

../src/neorv32_verilog_wrapper.v:21303: error: Could not find variable ``n1647_oport['sd10]'' in ``neorv32_verilog_tb.uut.neorv32_top_inst.neorv32_boot_rom_inst_true_neorv32_boot_rom_inst''
../src/neorv32_verilog_wrapper.v:21304: error: Could not find variable ``n1647_oport['sd9]'' in ``neorv32_verilog_tb.uut.neorv32_top_inst.neorv32_boot_rom_inst_true_neorv32_boot_rom_inst''
../src/neorv32_verilog_wrapper.v:21305: error: Could not find variable ``n1647_oport['sd8]'' in ``neorv32_verilog_tb.uut.neorv32_top_inst.neorv32_boot_rom_inst_true_neorv32_boot_rom_inst''
../src/neorv32_verilog_wrapper.v:21306: error: Could not find variable ``n1647_oport['sd7]'' in ``neorv32_verilog_tb.uut.neorv32_top_inst.neorv32_boot_rom_inst_true_neorv32_boot_rom_inst''
../src/neorv32_verilog_wrapper.v:21307: error: Could not find variable ``n1647_oport['sd6]'' in ``neorv32_verilog_tb.uut.neorv32_top_inst.neorv32_boot_rom_inst_true_neorv32_boot_rom_inst''
../src/neorv32_verilog_wrapper.v:21308: error: Could not find variable ``n1647_oport['sd5]'' in ``neorv32_verilog_tb.uut.neorv32_top_inst.neorv32_boot_rom_inst_true_neorv32_boot_rom_inst''
../src/neorv32_verilog_wrapper.v:21309: error: Could not find variable ``n1647_oport['sd4]'' in ``neorv32_verilog_tb.uut.neorv32_top_inst.neorv32_boot_rom_inst_true_neorv32_boot_rom_inst''
../src/neorv32_verilog_wrapper.v:21310: error: Could not find variable ``n1647_oport['sd3]'' in ``neorv32_verilog_tb.uut.neorv32_top_inst.neorv32_boot_rom_inst_true_neorv32_boot_rom_inst''
../src/neorv32_verilog_wrapper.v:21311: error: Could not find variable ``n1647_oport['sd2]'' in ``neorv32_verilog_tb.uut.neorv32_top_inst.neorv32_boot_rom_inst_true_neorv32_boot_rom_inst''
../src/neorv32_verilog_wrapper.v:21312: error: Could not find variable ``n1647_oport['sd1]'' in ``neorv32_verilog_tb.uut.neorv32_top_inst.neorv32_boot_rom_inst_true_neorv32_boot_rom_inst''
../src/neorv32_verilog_wrapper.v:21313: error: Could not find variable ``n1647_oport['sd0]'' in ``neorv32_verilog_tb.uut.neorv32_top_inst.neorv32_boot_rom_inst_true_neorv32_boot_rom_inst''
1024 error(s) during elaboration.
./neorv32-verilog-sim: Unable to open input file.

Could you please help me understand what I am doing wrong? I also tried to run the check.sh script from the github CI but it gives the same output.

Some other details:

uname -a:

Linux emu 5.15.0-48-generic #54~20.04.1-Ubuntu SMP Thu Sep 1 16:17:26 UTC 2022 x86_64 x86_64 x86_64 GNU/Linux

iverilog -v:

Icarus Verilog version 12.0 (devel) (s20150603-1609-gfd69d4e09)

...

ghdl -v:

GHDL 2.0.0-dev (tarball) [Dunoon edition] open-tool-forge.nightly-20210921
 Compiled with GNAT Version: 9.3.0
 mcode code generator

...

CPU_EXTENSION_RISCV_B NOT enabled in neorv32_verilog_wrapper.vhd

In the wrapper file for the example processor config the FAST_SHIFT_EN is set true while the CPU_EXTENSION_RISCV_B is not existent in this file. Is this just a "typo" or what is the reasoning behind it? If there is any I would like to understand that.

Is it the idea hey the fast barrel shifter dedicated hardware unit is used also in the execution of other instructions that the ones contained in the RISCV_B extension?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.