OpenRisc is an open source microprocessor architecture; being it open source, one of the key benefits is the possibility to examine it, compile it and make it work. OpenCores provides an environment to compile the Verilog RTL description of a OpenRisc system (called ORPSoC) and run tests using Icarus Verilog, that is a quite mature FLOSS Verilog compiler and event-driven simulator. Here is what I did to set up the simulation environment, following the guidelines in the ORPSoCv2 page:
- Download the OpenRisc toolchain and install it using the provided script
- Download the Orpsocv2 system from Subversion repository
- Install Icarus Verilog and GTKWave (using “sudo apt-get install verilog gtkwave” on my Ubuntu box)
- Open a terminal and setup the environment, which consists only in adding the “or32-elf/bin” directory to the PATH environment variable (export PATH=”${HOME}/src/openrisc/or32-elf/bin:${PATH}”)
With the environment ready, I got into the directory “orpsocv2/sim/run” and run:
make rtl-tests TESTS=uart-nocache UART_PRINTF=1 VCD=1
the command launches the “uart-nocache” test, printing on the terminal the bytes coming from the UART and dumping the waveforms into a VCD format file. The following is the output on-screen of the simulation:
Beginning loop that will complete the following tests: uart-nocache ################################################################################ #### Current test: uart-nocache #### #### Compiling software #### make[1]: Entering directory `/home/francesco/src/openrisc/orpsocv2/sw/uart' or32-elf-gcc -O2 -mhard-mul -g -DUART_PRINTF uart.c -c -o uart.o In file included from uart.c:1: ../support/support.h:18: warning: conflicting types for built-in function ‘printf’ or32-elf-gcc -mhard-mul -g -DUART_PRINTF -T ../support/orp.ld uart.o ../support/reset-nocache.o ../support/libsupport.a ../support/except.o -o uart-nocache.or32 or32-elf-objcopy -O binary uart-nocache.or32 uart-nocache.bin ../utils/bin2hex uart-nocache.bin 1 -size_word > uart-nocache-twobyte-sizefirst.hex ../utils/bin2vmem uart-nocache.bin > uart-nocache.vmem make[1]: Leaving directory `/home/francesco/src/openrisc/orpsocv2/sw/uart' #### Compiling RTL #### /home/francesco/src/openrisc/orpsocv2/sim/run/../../rtl/verilog/components/or1200r2/or1200_cfgr.v:185: warning: Numeric constant truncated to 3 bits. #### Beginning simulation #### Starting RTL simulation of uart-nocache test VCD in /home/francesco/src/openrisc/orpsocv2/sim/run/../../sim/results/uart-nocache.vcd VCD info: dumpfile /home/francesco/src/openrisc/orpsocv2/sim/run/../../sim/results/uart-nocache.vcd opened for output. Hello World. real 40.16 user 39.58 sys 0.52 #### #### Test uart-nocache PASSED #### #### Test results: 1 out of 1 tests passed
What happened? Here is a diagram:
A test program (uart.c) is compiled using the OpenRisc toolchain (or32-elf-gcc), and a memory image is generated (uart-nocache.vmem); the program takes a string “Hello World.\n” and sends it through the UART one byte at a time. The program image is used in simulation to fill the RAM. The Verilog RTL sources, including the OpenRisc core, the UART and the testbench that checks the results, are compiled and then simulated; the software runs and the simulator prints the characters composing “Hello World.” that have been sent to the serial port. It is shown that the simulation took about 40 seconds to run.
After the simulation is completed, it is possible to examine the waveforms of the digital circuit using the graphical software GTKWave to open “../results/uart-nocache.vcd“; this is a screenshot of a part of the simulation (click it to enlarge):
In the image it is captured the printing of the “H” character, that in ASCII is coded as 0×48. The red vertical line shows the instant in which the OpenRisc writes 0×48 to the UART. The “Signals” panel shows that “dwb_dat_o” contains the hexadecimal value “48480048“ written in the hexadecimal address “dwb_adr_o = 9000000” that is the zone of memory that contains the UART. The byte is then transmitted serially (and slooowly) up to the most external signal which is “uart0_stx_o“, that can be seen as an external pin of a microchip. This signal is read by a dedicated UART decoder whose purpose is to construct the transmitted data into the “tx_byte” register and print the character to the terminal. Rightmost in the window , in the last line, the character “H” can be seen completely reconstructed, and it will be printed on-screen.
I think that these simulations can be really interesting for those who want to learn about digital electronics, hardware description languages and embedded software development. It is quite easy, and absolutely free, to start toying with this environment, but the concepts are very similar to the digital design of real chips. I can picture students using this as a base for a thesis about hardware IP design, or verification methodology, or optimization of simulators.


Entries
Eric Smith
2009/12/17
I do most of my work in VHDL, so I compile for simulation with GHDL, and then use GTKWave. Recently I designed a CDP1802-compatible processor core, and went through almost exactly the process you describe for debugging the core and its interaction with a UART.
You can do this kind of debugging directly on a Xilinx FPGA using ChipScope, but unless the design is very large it is usually easier to do it in simulation.