RISC_V_LAB hinzugefügt

This commit is contained in:
muellerlu 2026-06-09 08:33:18 +02:00
commit 3c0ec38544
233 changed files with 90271 additions and 0 deletions

BIN
.cleanup_lukas.sh.swp Normal file

Binary file not shown.

Binary file not shown.

File diff suppressed because one or more lines are too long

16
cleanup.sh Executable file
View File

@ -0,0 +1,16 @@
#!/bin/sh
rm -rf oasys.cmd*
rm -rf oasys.dbg*
rm -rf oasys.log*
rm -rf output
mkdir output
mkdir output/odb
mkdir output/db
mkdir output/logs
rm -rf `find . -type f -name "oasys.*"`
echo "\n-------------------------------------"
echo "\nCleanup Complete"
echo "\n-------------------------------------\n"

7
commands_help.txt Normal file
View File

@ -0,0 +1,7 @@
To find the address:
$which tool_name
To run a script:
$source scripts_counter/1_read_design.tcl

BIN
constraints/.riscv.sdc.swp Normal file

Binary file not shown.

29
constraints/define_regions.def Executable file
View File

@ -0,0 +1,29 @@
#
# Created by Oasys-RTL -- (c) Mentor Graphics Corporation
#
VERSION 5.8 ;
NAMESCASESENSITIVE ON ;
DIVIDERCHAR "/" ;
BUSBITCHARS "[]" ;
DESIGN demo_chip ;
UNITS DISTANCE MICRONS 2000 ;
PROPERTYDEFINITIONS
END PROPERTYDEFINITIONS
DIEAREA ( 0 0 ) ( 2834850 2834850 ) ;
REGIONS 2 ;
- __r__6 ( 64840 50430 ) ( 1549550 1203580 ) ;
- __r__7 ( 1254060 1513530 ) ( 2803620 2767590 ) ;
END REGIONS
COMPONENTS 352 ;
- i_cpu_sys cpu_sys
+ REGION __r__6
;
- i_usbf usb_sys
+ REGION __r__7
;
END COMPONENTS
END DESIGN

76
constraints/riscv.sdc Normal file
View File

@ -0,0 +1,76 @@
# =============================================================================
# Constraints File: cpu.sdc
# Project: BCDC Microtec Academy - RISC-V CPU
# Top Module: cpu
# =============================================================================
# -----------------------------------------------------------------------------
# 1. Primary Clock - 25 MHz input clock
# -----------------------------------------------------------------------------
create_clock -name clk_25mhz \
-period 40.000 \
-waveform {0 20} \
[get_ports clk_25mhz]
# -----------------------------------------------------------------------------
# 2. Generated Clock - 12.5 MHz (divided by 2 inside always_ff)
# -----------------------------------------------------------------------------
#create_generated_clock -name clk_12p5 \
-source [get_ports clk_25mhz] \
-divide_by 2 \
[get_pins thePC/clk]
# -----------------------------------------------------------------------------
# 3. Clock Uncertainty & Transition
# -----------------------------------------------------------------------------
set_clock_uncertainty -setup 0.5 [get_clocks clk_25mhz]
set_clock_uncertainty -hold 0.2 [get_clocks clk_25mhz]
set_clock_transition 0.1 [get_clocks clk_25mhz]
# -----------------------------------------------------------------------------
# 4. Input Delays (btn pins - relative to clk_25mhz)
# -----------------------------------------------------------------------------
set_input_delay -clock clk_25mhz -max 2.0 [get_ports {btn[*]}]
set_input_delay -clock clk_25mhz -min 0.5 [get_ports {btn[*]}]
# -----------------------------------------------------------------------------
# 5. Output Delays (led pins)
# -----------------------------------------------------------------------------
set_output_delay -clock clk_25mhz -max 2.0 [get_ports {led[*]}]
set_output_delay -clock clk_25mhz -min 0.5 [get_ports {led[*]}]
# -----------------------------------------------------------------------------
# 6. False Paths
# -----------------------------------------------------------------------------
# Reset is async and driven from a button - no timing analysis needed
set_false_path -from [get_ports {btn[0]}]
# LED outputs driven from combinational/slow logic - relax if needed
# set_false_path -to [get_ports {led[*]}]
# -----------------------------------------------------------------------------
# 7. Clock Domain Crossing
# -----------------------------------------------------------------------------
# clk12p5 is derived from clk_25mhz via FF division - set as async crossing
# to prevent hold violations across the two domains
#set_clock_groups -asynchronous \
-group [get_clocks clk_25mhz] \
-group [get_clocks clk_12p5]
# -----------------------------------------------------------------------------
# 8. Drive Strength & Load (adjust to your target technology)
# -----------------------------------------------------------------------------
#set_driving_cell -lib_cell <YOUR_INPUT_BUF> [get_ports {btn[*]}]
set_driving_cell -lib_cell BUF_X1_HVT -library NangateOpenCellLibrary_45nm_HVT_0p85 [get_ports {btn[*]}]
set_load 0.05 [get_ports {led[*]}]
# -----------------------------------------------------------------------------
# 9. Max Fanout & Transition
# -----------------------------------------------------------------------------
set_max_fanout 20 [current_design]
set_max_transition 0.5 [current_design]

16
docs/LICENSE_Nangate.txt Executable file
View File

@ -0,0 +1,16 @@
The Open Cell Library is intended for use by universities, other research activities, educational programs and Si2.org members.
However allowed, the Open Cell Library is not intended for commercial use. If you use the Open Cell Library for demonstration of commercial EDA tools
it is required to mention, indicate that the library was developped by Nangate.
If you have questions or concerns then please contact us at openlibrary@nangate.com
The Open Cell Library is provided by Nangate under the following License:
Nangate Open Cell Library License, Version 1.0. February 20, 2008
Permission is hereby granted, free of charge, to any person or organization obtaining a copy of the Open Cell Library and accompanying documentation (the "Library") covered by this license to use, reproduce, display, distribute, execute, and transmit the Library, and to prepare derivative works of the Library, and to permit third-parties to whom the Library is furnished to do so, all subject to the following:
The copyright notices in the Library and this entire statement, including the above license grant, this restriction and the following disclaimer, must be included in all copies of the Library, in whole or in part, and all derivative works of the Library, unless such copies or derivative works are solely in the form of machine-executable object code generated by a source language processor. The library has been generated using a non-optimized open PDK and is not suited for any commercial purpose. Measuring or benchmarking the Library against any other library or standard cell set is prohibited. Any meaningful library benchmarking must be done in collaboration with Nangate or other providers of optimized and production-ready PDKs.
THE LIBRARY IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE LIBRARY BE LIABLE FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE LIBRARY OR THE USE OR OTHER DEALINGS IN THE LIBRARY.

Binary file not shown.

35
libs/MemGen_16_10.memlib Normal file
View File

@ -0,0 +1,35 @@
Core (MemGen_16_10) {
Memory {
Port (clock) {
Function = Clock;
}
Port (chip_en) {
Function = Select;
Polarity = activeHigh;
}
Port (rd_en) {
Function = ReadEnable;
Polarity = activeHigh;
}
Port (wr_en) {
Function = WriteEnable;
Polarity = activeHigh;
}
Port (addr[9:0]) {
Function = Address;
}
Port (wr_data[15:0]) {
Function = Data;
Direction = Input;
}
Port (rd_data[15:0]) {
Function = Data;
Direction = Output;
}
AddressCounter {
Function (address) {
CountRange = [0 1023];
}
}
}
}

6777
libs/NCSU_FreePDK_45nm.ptf Executable file

File diff suppressed because it is too large Load Diff

43
libs/fastscan/IO.fslib Executable file
View File

@ -0,0 +1,43 @@
library_format_version = 9;
array_delimiter = "[]";
//
// ***********************************************************************
// *********** Models holding Liberty information ******************
// ***********************************************************************
//
model PADBID
(C, I, OEN, PAD)
(
model_source = liberty_cell;
cell_type = pad;
input (I) ( pad_to_pad; )
input (OEN) ( pad_enable_low; )
inout (PAD) ( pad_pad_io; )
output (C) ( pad_from_pad; )
(
primitive = _buf (PAD, C);
primitive = _tsl (I, OEN, PAD);
)
) // end model PADBID
model PADCLK
(C, PAD)
(
model_source = liberty_cell;
cell_type = pad;
simulation_function = buffer;
input (PAD) ( pad_from_io; )
output (C) ( pad_from_pad; )
(
primitive = _buf (PAD, C);
)
) // end model PADCLK

View File

@ -0,0 +1,583 @@
//
// ***********************************************************************
// Copyright Mentor Graphics Corporation
// All Rights Reserved
// For use only with Mentor Graphics Tessent tools
// ***********************************************************************
// File Type: Tessent Cell Library
// Generated by: Tessent Shell -- write_cell_library
// Tool Version: 2019.4
// Tool Build Date: Wed Nov 20 21:14:16 GMT 2019
// ***********************************************************************
// Library Created : Local Time = Tue Jun 30 00:33:32 2020
// GMT = Tue Jun 30 07:33:32 2020
library_format_version = 9;
array_delimiter = "[]";
//
// ***********************************************************************
// *********** Models holding Liberty information ******************
// ***********************************************************************
//
model AON_BUF_X1
(A, Z)
(
model_source = liberty_cell;
cell_type = buffer;
simulation_function = buffer;
input (A) ( )
output (Z) ( )
(
primitive = _buf (A, Z);
)
) // end model AON_BUF_X1
model AON_BUF_X2
(A, Z)
(
model_source = liberty_cell;
cell_type = buffer;
simulation_function = buffer;
input (A) ( )
output (Z) ( )
(
primitive = _buf (A, Z);
)
) // end model AON_BUF_X2
model AON_BUF_X4
(A, Z)
(
model_source = liberty_cell;
cell_type = buffer;
simulation_function = buffer;
input (A) ( )
output (Z) ( )
(
primitive = _buf (A, Z);
)
) // end model AON_BUF_X4
model AON_INV_X1
(A, Z)
(
model_source = liberty_cell;
cell_type = inverter;
simulation_function = inverter;
input (A) ( )
output (Z) ( )
(
primitive = _inv (A, Z);
)
) // end model AON_INV_X1
model AON_INV_X2
(A, Z)
(
model_source = liberty_cell;
cell_type = inverter;
simulation_function = inverter;
input (A) ( )
output (Z) ( )
(
primitive = _inv (A, Z);
)
) // end model AON_INV_X2
model AON_INV_X4
(A, Z)
(
model_source = liberty_cell;
cell_type = inverter;
simulation_function = inverter;
input (A) ( )
output (Z) ( )
(
primitive = _inv (A, Z);
)
) // end model AON_INV_X4
model HEADER_OE_X1
(SLEEP, SLEEPOUT)
(
model_source = liberty_cell;
cell_type = buffer;
simulation_function = buffer;
input (SLEEP) ( )
output (SLEEPOUT) ( )
(
primitive = _buf (SLEEP, SLEEPOUT);
)
) // end model HEADER_OE_X1
model HEADER_OE_X2
(SLEEP, SLEEPOUT)
(
model_source = liberty_cell;
cell_type = buffer;
simulation_function = buffer;
input (SLEEP) ( )
output (SLEEPOUT) ( )
(
primitive = _buf (SLEEP, SLEEPOUT);
)
) // end model HEADER_OE_X2
model HEADER_OE_X4
(SLEEP, SLEEPOUT)
(
model_source = liberty_cell;
cell_type = buffer;
simulation_function = buffer;
input (SLEEP) ( )
output (SLEEPOUT) ( )
(
primitive = _buf (SLEEP, SLEEPOUT);
)
) // end model HEADER_OE_X4
model HEADER_X1
(SLEEP)
(
model_source = liberty_cell;
cell_type = prohibited;
input (SLEEP) ( )
(
// Empty Model
)
) // end model HEADER_X1
model HEADER_X2
(SLEEP)
(
model_source = liberty_cell;
cell_type = prohibited;
input (SLEEP) ( )
(
// Empty Model
)
) // end model HEADER_X2
model HEADER_X4
(SLEEP)
(
model_source = liberty_cell;
cell_type = prohibited;
input (SLEEP) ( )
(
// Empty Model
)
) // end model HEADER_X4
model ISO_FENCE0N_X1
(A, EN, Z)
(
model_source = liberty_cell;
cell_type = prohibited;
simulation_function = and;
input (A) ( )
input (EN) ( )
output (Z) ( )
(
primitive = _and (A, EN, Z);
)
) // end model ISO_FENCE0N_X1
model ISO_FENCE0N_X2
(A, EN, Z)
(
model_source = liberty_cell;
cell_type = prohibited;
simulation_function = and;
input (A) ( )
input (EN) ( )
output (Z) ( )
(
primitive = _and (A, EN, Z);
)
) // end model ISO_FENCE0N_X2
model ISO_FENCE0N_X4
(A, EN, Z)
(
model_source = liberty_cell;
cell_type = prohibited;
simulation_function = and;
input (A) ( )
input (EN) ( )
output (Z) ( )
(
primitive = _and (A, EN, Z);
)
) // end model ISO_FENCE0N_X4
model ISO_FENCE0_X1
(A, EN, Z)
(
model_source = liberty_cell;
cell_type = prohibited;
simulation_function = nor;
input (A) ( )
input (EN) ( )
output (Z) ( )
(
primitive = _inv (net_0, Z);
primitive = _or (A, EN, net_0);
)
) // end model ISO_FENCE0_X1
model ISO_FENCE0_X2
(A, EN, Z)
(
model_source = liberty_cell;
cell_type = prohibited;
simulation_function = nor;
input (A) ( )
input (EN) ( )
output (Z) ( )
(
primitive = _inv (net_0, Z);
primitive = _or (A, EN, net_0);
)
) // end model ISO_FENCE0_X2
model ISO_FENCE0_X4
(A, EN, Z)
(
model_source = liberty_cell;
cell_type = prohibited;
simulation_function = nor;
input (A) ( )
input (EN) ( )
output (Z) ( )
(
primitive = _inv (net_0, Z);
primitive = _or (A, EN, net_0);
)
) // end model ISO_FENCE0_X4
model ISO_FENCE1N_X1
(A, EN, Z)
(
model_source = liberty_cell;
cell_type = prohibited;
simulation_function = nand;
input (A) ( )
input (EN) ( )
output (Z) ( )
(
primitive = _inv (net_0, Z);
primitive = _and (A, EN, net_0);
)
) // end model ISO_FENCE1N_X1
model ISO_FENCE1N_X2
(A, EN, Z)
(
model_source = liberty_cell;
cell_type = prohibited;
simulation_function = nand;
input (A) ( )
input (EN) ( )
output (Z) ( )
(
primitive = _inv (net_0, Z);
primitive = _and (A, EN, net_0);
)
) // end model ISO_FENCE1N_X2
model ISO_FENCE1N_X4
(A, EN, Z)
(
model_source = liberty_cell;
cell_type = prohibited;
simulation_function = nand;
input (A) ( )
input (EN) ( )
output (Z) ( )
(
primitive = _inv (net_0, Z);
primitive = _and (A, EN, net_0);
)
) // end model ISO_FENCE1N_X4
model ISO_FENCE1_X1
(A, EN, Z)
(
model_source = liberty_cell;
cell_type = prohibited;
simulation_function = or;
input (A) ( )
input (EN) ( )
output (Z) ( )
(
primitive = _or (A, EN, Z);
)
) // end model ISO_FENCE1_X1
model ISO_FENCE1_X2
(A, EN, Z)
(
model_source = liberty_cell;
cell_type = prohibited;
simulation_function = or;
input (A) ( )
input (EN) ( )
output (Z) ( )
(
primitive = _or (A, EN, Z);
)
) // end model ISO_FENCE1_X2
model ISO_FENCE1_X4
(A, EN, Z)
(
model_source = liberty_cell;
cell_type = prohibited;
simulation_function = or;
input (A) ( )
input (EN) ( )
output (Z) ( )
(
primitive = _or (A, EN, Z);
)
) // end model ISO_FENCE1_X4
model LS_HLEN_X1
(A, ISOLN, Z)
(
model_source = liberty_cell;
cell_type = and;
simulation_function = and;
input (A) ( )
input (ISOLN) ( )
output (Z) ( )
(
primitive = _and (A, ISOLN, Z);
)
) // end model LS_HLEN_X1
model LS_HLEN_X2
(A, ISOLN, Z)
(
model_source = liberty_cell;
cell_type = and;
simulation_function = and;
input (A) ( )
input (ISOLN) ( )
output (Z) ( )
(
primitive = _and (A, ISOLN, Z);
)
) // end model LS_HLEN_X2
model LS_HLEN_X4
(A, ISOLN, Z)
(
model_source = liberty_cell;
cell_type = and;
simulation_function = and;
input (A) ( )
input (ISOLN) ( )
output (Z) ( )
(
primitive = _and (A, ISOLN, Z);
)
) // end model LS_HLEN_X4
model LS_HL_X1
(A, Z)
(
model_source = liberty_cell;
cell_type = buffer;
simulation_function = buffer;
input (A) ( )
output (Z) ( )
(
primitive = _buf (A, Z);
)
) // end model LS_HL_X1
model LS_HL_X2
(A, Z)
(
model_source = liberty_cell;
cell_type = buffer;
simulation_function = buffer;
input (A) ( )
output (Z) ( )
(
primitive = _buf (A, Z);
)
) // end model LS_HL_X2
model LS_HL_X4
(A, Z)
(
model_source = liberty_cell;
cell_type = buffer;
simulation_function = buffer;
input (A) ( )
output (Z) ( )
(
primitive = _buf (A, Z);
)
) // end model LS_HL_X4
model LS_LHEN_X1
(A, ISOLN, Z)
(
model_source = liberty_cell;
cell_type = and;
simulation_function = and;
input (A) ( )
input (ISOLN) ( )
output (Z) ( )
(
primitive = _and (A, ISOLN, Z);
)
) // end model LS_LHEN_X1
model LS_LHEN_X2
(A, ISOLN, Z)
(
model_source = liberty_cell;
cell_type = and;
simulation_function = and;
input (A) ( )
input (ISOLN) ( )
output (Z) ( )
(
primitive = _and (A, ISOLN, Z);
)
) // end model LS_LHEN_X2
model LS_LHEN_X4
(A, ISOLN, Z)
(
model_source = liberty_cell;
cell_type = and;
simulation_function = and;
input (A) ( )
input (ISOLN) ( )
output (Z) ( )
(
primitive = _and (A, ISOLN, Z);
)
) // end model LS_LHEN_X4
model LS_LH_X1
(A, Z)
(
model_source = liberty_cell;
cell_type = buffer;
simulation_function = buffer;
input (A) ( )
output (Z) ( )
(
primitive = _buf (A, Z);
)
) // end model LS_LH_X1
model LS_LH_X2
(A, Z)
(
model_source = liberty_cell;
cell_type = buffer;
simulation_function = buffer;
input (A) ( )
output (Z) ( )
(
primitive = _buf (A, Z);
)
) // end model LS_LH_X2
model LS_LH_X4
(A, Z)
(
model_source = liberty_cell;
cell_type = buffer;
simulation_function = buffer;
input (A) ( )
output (Z) ( )
(
primitive = _buf (A, Z);
)
) // end model LS_LH_X4

View File

@ -0,0 +1,583 @@
//
// ***********************************************************************
// Copyright Mentor Graphics Corporation
// All Rights Reserved
// For use only with Mentor Graphics Tessent tools
// ***********************************************************************
// File Type: Tessent Cell Library
// Generated by: Tessent Shell -- write_cell_library
// Tool Version: 2019.4
// Tool Build Date: Wed Nov 20 21:14:16 GMT 2019
// ***********************************************************************
// Library Created : Local Time = Tue Jun 30 00:33:32 2020
// GMT = Tue Jun 30 07:33:32 2020
library_format_version = 9;
array_delimiter = "[]";
//
// ***********************************************************************
// *********** Models holding Liberty information ******************
// ***********************************************************************
//
model AON_BUF_X1
(A, Z)
(
model_source = liberty_cell;
cell_type = buffer;
simulation_function = buffer;
input (A) ( )
output (Z) ( )
(
primitive = _buf (A, Z);
)
) // end model AON_BUF_X1
model AON_BUF_X2
(A, Z)
(
model_source = liberty_cell;
cell_type = buffer;
simulation_function = buffer;
input (A) ( )
output (Z) ( )
(
primitive = _buf (A, Z);
)
) // end model AON_BUF_X2
model AON_BUF_X4
(A, Z)
(
model_source = liberty_cell;
cell_type = buffer;
simulation_function = buffer;
input (A) ( )
output (Z) ( )
(
primitive = _buf (A, Z);
)
) // end model AON_BUF_X4
model AON_INV_X1
(A, Z)
(
model_source = liberty_cell;
cell_type = inverter;
simulation_function = inverter;
input (A) ( )
output (Z) ( )
(
primitive = _inv (A, Z);
)
) // end model AON_INV_X1
model AON_INV_X2
(A, Z)
(
model_source = liberty_cell;
cell_type = inverter;
simulation_function = inverter;
input (A) ( )
output (Z) ( )
(
primitive = _inv (A, Z);
)
) // end model AON_INV_X2
model AON_INV_X4
(A, Z)
(
model_source = liberty_cell;
cell_type = inverter;
simulation_function = inverter;
input (A) ( )
output (Z) ( )
(
primitive = _inv (A, Z);
)
) // end model AON_INV_X4
model HEADER_OE_X1
(SLEEP, SLEEPOUT)
(
model_source = liberty_cell;
cell_type = buffer;
simulation_function = buffer;
input (SLEEP) ( )
output (SLEEPOUT) ( )
(
primitive = _buf (SLEEP, SLEEPOUT);
)
) // end model HEADER_OE_X1
model HEADER_OE_X2
(SLEEP, SLEEPOUT)
(
model_source = liberty_cell;
cell_type = buffer;
simulation_function = buffer;
input (SLEEP) ( )
output (SLEEPOUT) ( )
(
primitive = _buf (SLEEP, SLEEPOUT);
)
) // end model HEADER_OE_X2
model HEADER_OE_X4
(SLEEP, SLEEPOUT)
(
model_source = liberty_cell;
cell_type = buffer;
simulation_function = buffer;
input (SLEEP) ( )
output (SLEEPOUT) ( )
(
primitive = _buf (SLEEP, SLEEPOUT);
)
) // end model HEADER_OE_X4
model HEADER_X1
(SLEEP)
(
model_source = liberty_cell;
cell_type = prohibited;
input (SLEEP) ( )
(
// Empty Model
)
) // end model HEADER_X1
model HEADER_X2
(SLEEP)
(
model_source = liberty_cell;
cell_type = prohibited;
input (SLEEP) ( )
(
// Empty Model
)
) // end model HEADER_X2
model HEADER_X4
(SLEEP)
(
model_source = liberty_cell;
cell_type = prohibited;
input (SLEEP) ( )
(
// Empty Model
)
) // end model HEADER_X4
model ISO_FENCE0N_X1
(A, EN, Z)
(
model_source = liberty_cell;
cell_type = prohibited;
simulation_function = and;
input (A) ( )
input (EN) ( )
output (Z) ( )
(
primitive = _and (A, EN, Z);
)
) // end model ISO_FENCE0N_X1
model ISO_FENCE0N_X2
(A, EN, Z)
(
model_source = liberty_cell;
cell_type = prohibited;
simulation_function = and;
input (A) ( )
input (EN) ( )
output (Z) ( )
(
primitive = _and (A, EN, Z);
)
) // end model ISO_FENCE0N_X2
model ISO_FENCE0N_X4
(A, EN, Z)
(
model_source = liberty_cell;
cell_type = prohibited;
simulation_function = and;
input (A) ( )
input (EN) ( )
output (Z) ( )
(
primitive = _and (A, EN, Z);
)
) // end model ISO_FENCE0N_X4
model ISO_FENCE0_X1
(A, EN, Z)
(
model_source = liberty_cell;
cell_type = prohibited;
simulation_function = nor;
input (A) ( )
input (EN) ( )
output (Z) ( )
(
primitive = _inv (net_0, Z);
primitive = _or (A, EN, net_0);
)
) // end model ISO_FENCE0_X1
model ISO_FENCE0_X2
(A, EN, Z)
(
model_source = liberty_cell;
cell_type = prohibited;
simulation_function = nor;
input (A) ( )
input (EN) ( )
output (Z) ( )
(
primitive = _inv (net_0, Z);
primitive = _or (A, EN, net_0);
)
) // end model ISO_FENCE0_X2
model ISO_FENCE0_X4
(A, EN, Z)
(
model_source = liberty_cell;
cell_type = prohibited;
simulation_function = nor;
input (A) ( )
input (EN) ( )
output (Z) ( )
(
primitive = _inv (net_0, Z);
primitive = _or (A, EN, net_0);
)
) // end model ISO_FENCE0_X4
model ISO_FENCE1N_X1
(A, EN, Z)
(
model_source = liberty_cell;
cell_type = prohibited;
simulation_function = nand;
input (A) ( )
input (EN) ( )
output (Z) ( )
(
primitive = _inv (net_0, Z);
primitive = _and (A, EN, net_0);
)
) // end model ISO_FENCE1N_X1
model ISO_FENCE1N_X2
(A, EN, Z)
(
model_source = liberty_cell;
cell_type = prohibited;
simulation_function = nand;
input (A) ( )
input (EN) ( )
output (Z) ( )
(
primitive = _inv (net_0, Z);
primitive = _and (A, EN, net_0);
)
) // end model ISO_FENCE1N_X2
model ISO_FENCE1N_X4
(A, EN, Z)
(
model_source = liberty_cell;
cell_type = prohibited;
simulation_function = nand;
input (A) ( )
input (EN) ( )
output (Z) ( )
(
primitive = _inv (net_0, Z);
primitive = _and (A, EN, net_0);
)
) // end model ISO_FENCE1N_X4
model ISO_FENCE1_X1
(A, EN, Z)
(
model_source = liberty_cell;
cell_type = prohibited;
simulation_function = or;
input (A) ( )
input (EN) ( )
output (Z) ( )
(
primitive = _or (A, EN, Z);
)
) // end model ISO_FENCE1_X1
model ISO_FENCE1_X2
(A, EN, Z)
(
model_source = liberty_cell;
cell_type = prohibited;
simulation_function = or;
input (A) ( )
input (EN) ( )
output (Z) ( )
(
primitive = _or (A, EN, Z);
)
) // end model ISO_FENCE1_X2
model ISO_FENCE1_X4
(A, EN, Z)
(
model_source = liberty_cell;
cell_type = prohibited;
simulation_function = or;
input (A) ( )
input (EN) ( )
output (Z) ( )
(
primitive = _or (A, EN, Z);
)
) // end model ISO_FENCE1_X4
model LS_HLEN_X1
(A, ISOLN, Z)
(
model_source = liberty_cell;
cell_type = and;
simulation_function = and;
input (A) ( )
input (ISOLN) ( )
output (Z) ( )
(
primitive = _and (A, ISOLN, Z);
)
) // end model LS_HLEN_X1
model LS_HLEN_X2
(A, ISOLN, Z)
(
model_source = liberty_cell;
cell_type = and;
simulation_function = and;
input (A) ( )
input (ISOLN) ( )
output (Z) ( )
(
primitive = _and (A, ISOLN, Z);
)
) // end model LS_HLEN_X2
model LS_HLEN_X4
(A, ISOLN, Z)
(
model_source = liberty_cell;
cell_type = and;
simulation_function = and;
input (A) ( )
input (ISOLN) ( )
output (Z) ( )
(
primitive = _and (A, ISOLN, Z);
)
) // end model LS_HLEN_X4
model LS_HL_X1
(A, Z)
(
model_source = liberty_cell;
cell_type = buffer;
simulation_function = buffer;
input (A) ( )
output (Z) ( )
(
primitive = _buf (A, Z);
)
) // end model LS_HL_X1
model LS_HL_X2
(A, Z)
(
model_source = liberty_cell;
cell_type = buffer;
simulation_function = buffer;
input (A) ( )
output (Z) ( )
(
primitive = _buf (A, Z);
)
) // end model LS_HL_X2
model LS_HL_X4
(A, Z)
(
model_source = liberty_cell;
cell_type = buffer;
simulation_function = buffer;
input (A) ( )
output (Z) ( )
(
primitive = _buf (A, Z);
)
) // end model LS_HL_X4
model LS_LHEN_X1
(A, ISOLN, Z)
(
model_source = liberty_cell;
cell_type = and;
simulation_function = and;
input (A) ( )
input (ISOLN) ( )
output (Z) ( )
(
primitive = _and (A, ISOLN, Z);
)
) // end model LS_LHEN_X1
model LS_LHEN_X2
(A, ISOLN, Z)
(
model_source = liberty_cell;
cell_type = and;
simulation_function = and;
input (A) ( )
input (ISOLN) ( )
output (Z) ( )
(
primitive = _and (A, ISOLN, Z);
)
) // end model LS_LHEN_X2
model LS_LHEN_X4
(A, ISOLN, Z)
(
model_source = liberty_cell;
cell_type = and;
simulation_function = and;
input (A) ( )
input (ISOLN) ( )
output (Z) ( )
(
primitive = _and (A, ISOLN, Z);
)
) // end model LS_LHEN_X4
model LS_LH_X1
(A, Z)
(
model_source = liberty_cell;
cell_type = buffer;
simulation_function = buffer;
input (A) ( )
output (Z) ( )
(
primitive = _buf (A, Z);
)
) // end model LS_LH_X1
model LS_LH_X2
(A, Z)
(
model_source = liberty_cell;
cell_type = buffer;
simulation_function = buffer;
input (A) ( )
output (Z) ( )
(
primitive = _buf (A, Z);
)
) // end model LS_LH_X2
model LS_LH_X4
(A, Z)
(
model_source = liberty_cell;
cell_type = buffer;
simulation_function = buffer;
input (A) ( )
output (Z) ( )
(
primitive = _buf (A, Z);
)
) // end model LS_LH_X4

View File

@ -0,0 +1,583 @@
//
// ***********************************************************************
// Copyright Mentor Graphics Corporation
// All Rights Reserved
// For use only with Mentor Graphics Tessent tools
// ***********************************************************************
// File Type: Tessent Cell Library
// Generated by: Tessent Shell -- write_cell_library
// Tool Version: 2019.4
// Tool Build Date: Wed Nov 20 21:14:16 GMT 2019
// ***********************************************************************
// Library Created : Local Time = Tue Jun 30 00:33:33 2020
// GMT = Tue Jun 30 07:33:33 2020
library_format_version = 9;
array_delimiter = "[]";
//
// ***********************************************************************
// *********** Models holding Liberty information ******************
// ***********************************************************************
//
model AON_BUF_X1
(A, Z)
(
model_source = liberty_cell;
cell_type = buffer;
simulation_function = buffer;
input (A) ( )
output (Z) ( )
(
primitive = _buf (A, Z);
)
) // end model AON_BUF_X1
model AON_BUF_X2
(A, Z)
(
model_source = liberty_cell;
cell_type = buffer;
simulation_function = buffer;
input (A) ( )
output (Z) ( )
(
primitive = _buf (A, Z);
)
) // end model AON_BUF_X2
model AON_BUF_X4
(A, Z)
(
model_source = liberty_cell;
cell_type = buffer;
simulation_function = buffer;
input (A) ( )
output (Z) ( )
(
primitive = _buf (A, Z);
)
) // end model AON_BUF_X4
model AON_INV_X1
(A, Z)
(
model_source = liberty_cell;
cell_type = inverter;
simulation_function = inverter;
input (A) ( )
output (Z) ( )
(
primitive = _inv (A, Z);
)
) // end model AON_INV_X1
model AON_INV_X2
(A, Z)
(
model_source = liberty_cell;
cell_type = inverter;
simulation_function = inverter;
input (A) ( )
output (Z) ( )
(
primitive = _inv (A, Z);
)
) // end model AON_INV_X2
model AON_INV_X4
(A, Z)
(
model_source = liberty_cell;
cell_type = inverter;
simulation_function = inverter;
input (A) ( )
output (Z) ( )
(
primitive = _inv (A, Z);
)
) // end model AON_INV_X4
model HEADER_OE_X1
(SLEEP, SLEEPOUT)
(
model_source = liberty_cell;
cell_type = buffer;
simulation_function = buffer;
input (SLEEP) ( )
output (SLEEPOUT) ( )
(
primitive = _buf (SLEEP, SLEEPOUT);
)
) // end model HEADER_OE_X1
model HEADER_OE_X2
(SLEEP, SLEEPOUT)
(
model_source = liberty_cell;
cell_type = buffer;
simulation_function = buffer;
input (SLEEP) ( )
output (SLEEPOUT) ( )
(
primitive = _buf (SLEEP, SLEEPOUT);
)
) // end model HEADER_OE_X2
model HEADER_OE_X4
(SLEEP, SLEEPOUT)
(
model_source = liberty_cell;
cell_type = buffer;
simulation_function = buffer;
input (SLEEP) ( )
output (SLEEPOUT) ( )
(
primitive = _buf (SLEEP, SLEEPOUT);
)
) // end model HEADER_OE_X4
model HEADER_X1
(SLEEP)
(
model_source = liberty_cell;
cell_type = prohibited;
input (SLEEP) ( )
(
// Empty Model
)
) // end model HEADER_X1
model HEADER_X2
(SLEEP)
(
model_source = liberty_cell;
cell_type = prohibited;
input (SLEEP) ( )
(
// Empty Model
)
) // end model HEADER_X2
model HEADER_X4
(SLEEP)
(
model_source = liberty_cell;
cell_type = prohibited;
input (SLEEP) ( )
(
// Empty Model
)
) // end model HEADER_X4
model ISO_FENCE0N_X1
(A, EN, Z)
(
model_source = liberty_cell;
cell_type = prohibited;
simulation_function = and;
input (A) ( )
input (EN) ( )
output (Z) ( )
(
primitive = _and (A, EN, Z);
)
) // end model ISO_FENCE0N_X1
model ISO_FENCE0N_X2
(A, EN, Z)
(
model_source = liberty_cell;
cell_type = prohibited;
simulation_function = and;
input (A) ( )
input (EN) ( )
output (Z) ( )
(
primitive = _and (A, EN, Z);
)
) // end model ISO_FENCE0N_X2
model ISO_FENCE0N_X4
(A, EN, Z)
(
model_source = liberty_cell;
cell_type = prohibited;
simulation_function = and;
input (A) ( )
input (EN) ( )
output (Z) ( )
(
primitive = _and (A, EN, Z);
)
) // end model ISO_FENCE0N_X4
model ISO_FENCE0_X1
(A, EN, Z)
(
model_source = liberty_cell;
cell_type = prohibited;
simulation_function = nor;
input (A) ( )
input (EN) ( )
output (Z) ( )
(
primitive = _inv (net_0, Z);
primitive = _or (A, EN, net_0);
)
) // end model ISO_FENCE0_X1
model ISO_FENCE0_X2
(A, EN, Z)
(
model_source = liberty_cell;
cell_type = prohibited;
simulation_function = nor;
input (A) ( )
input (EN) ( )
output (Z) ( )
(
primitive = _inv (net_0, Z);
primitive = _or (A, EN, net_0);
)
) // end model ISO_FENCE0_X2
model ISO_FENCE0_X4
(A, EN, Z)
(
model_source = liberty_cell;
cell_type = prohibited;
simulation_function = nor;
input (A) ( )
input (EN) ( )
output (Z) ( )
(
primitive = _inv (net_0, Z);
primitive = _or (A, EN, net_0);
)
) // end model ISO_FENCE0_X4
model ISO_FENCE1N_X1
(A, EN, Z)
(
model_source = liberty_cell;
cell_type = prohibited;
simulation_function = nand;
input (A) ( )
input (EN) ( )
output (Z) ( )
(
primitive = _inv (net_0, Z);
primitive = _and (A, EN, net_0);
)
) // end model ISO_FENCE1N_X1
model ISO_FENCE1N_X2
(A, EN, Z)
(
model_source = liberty_cell;
cell_type = prohibited;
simulation_function = nand;
input (A) ( )
input (EN) ( )
output (Z) ( )
(
primitive = _inv (net_0, Z);
primitive = _and (A, EN, net_0);
)
) // end model ISO_FENCE1N_X2
model ISO_FENCE1N_X4
(A, EN, Z)
(
model_source = liberty_cell;
cell_type = prohibited;
simulation_function = nand;
input (A) ( )
input (EN) ( )
output (Z) ( )
(
primitive = _inv (net_0, Z);
primitive = _and (A, EN, net_0);
)
) // end model ISO_FENCE1N_X4
model ISO_FENCE1_X1
(A, EN, Z)
(
model_source = liberty_cell;
cell_type = prohibited;
simulation_function = or;
input (A) ( )
input (EN) ( )
output (Z) ( )
(
primitive = _or (A, EN, Z);
)
) // end model ISO_FENCE1_X1
model ISO_FENCE1_X2
(A, EN, Z)
(
model_source = liberty_cell;
cell_type = prohibited;
simulation_function = or;
input (A) ( )
input (EN) ( )
output (Z) ( )
(
primitive = _or (A, EN, Z);
)
) // end model ISO_FENCE1_X2
model ISO_FENCE1_X4
(A, EN, Z)
(
model_source = liberty_cell;
cell_type = prohibited;
simulation_function = or;
input (A) ( )
input (EN) ( )
output (Z) ( )
(
primitive = _or (A, EN, Z);
)
) // end model ISO_FENCE1_X4
model LS_HLEN_X1
(A, ISOLN, Z)
(
model_source = liberty_cell;
cell_type = and;
simulation_function = and;
input (A) ( )
input (ISOLN) ( )
output (Z) ( )
(
primitive = _and (A, ISOLN, Z);
)
) // end model LS_HLEN_X1
model LS_HLEN_X2
(A, ISOLN, Z)
(
model_source = liberty_cell;
cell_type = and;
simulation_function = and;
input (A) ( )
input (ISOLN) ( )
output (Z) ( )
(
primitive = _and (A, ISOLN, Z);
)
) // end model LS_HLEN_X2
model LS_HLEN_X4
(A, ISOLN, Z)
(
model_source = liberty_cell;
cell_type = and;
simulation_function = and;
input (A) ( )
input (ISOLN) ( )
output (Z) ( )
(
primitive = _and (A, ISOLN, Z);
)
) // end model LS_HLEN_X4
model LS_HL_X1
(A, Z)
(
model_source = liberty_cell;
cell_type = buffer;
simulation_function = buffer;
input (A) ( )
output (Z) ( )
(
primitive = _buf (A, Z);
)
) // end model LS_HL_X1
model LS_HL_X2
(A, Z)
(
model_source = liberty_cell;
cell_type = buffer;
simulation_function = buffer;
input (A) ( )
output (Z) ( )
(
primitive = _buf (A, Z);
)
) // end model LS_HL_X2
model LS_HL_X4
(A, Z)
(
model_source = liberty_cell;
cell_type = buffer;
simulation_function = buffer;
input (A) ( )
output (Z) ( )
(
primitive = _buf (A, Z);
)
) // end model LS_HL_X4
model LS_LHEN_X1
(A, ISOLN, Z)
(
model_source = liberty_cell;
cell_type = and;
simulation_function = and;
input (A) ( )
input (ISOLN) ( )
output (Z) ( )
(
primitive = _and (A, ISOLN, Z);
)
) // end model LS_LHEN_X1
model LS_LHEN_X2
(A, ISOLN, Z)
(
model_source = liberty_cell;
cell_type = and;
simulation_function = and;
input (A) ( )
input (ISOLN) ( )
output (Z) ( )
(
primitive = _and (A, ISOLN, Z);
)
) // end model LS_LHEN_X2
model LS_LHEN_X4
(A, ISOLN, Z)
(
model_source = liberty_cell;
cell_type = and;
simulation_function = and;
input (A) ( )
input (ISOLN) ( )
output (Z) ( )
(
primitive = _and (A, ISOLN, Z);
)
) // end model LS_LHEN_X4
model LS_LH_X1
(A, Z)
(
model_source = liberty_cell;
cell_type = buffer;
simulation_function = buffer;
input (A) ( )
output (Z) ( )
(
primitive = _buf (A, Z);
)
) // end model LS_LH_X1
model LS_LH_X2
(A, Z)
(
model_source = liberty_cell;
cell_type = buffer;
simulation_function = buffer;
input (A) ( )
output (Z) ( )
(
primitive = _buf (A, Z);
)
) // end model LS_LH_X2
model LS_LH_X4
(A, Z)
(
model_source = liberty_cell;
cell_type = buffer;
simulation_function = buffer;
input (A) ( )
output (Z) ( )
(
primitive = _buf (A, Z);
)
) // end model LS_LH_X4

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

57
libs/fastscan/PLL.fslib Executable file
View File

@ -0,0 +1,57 @@
library_format_version = 9;
array_delimiter = "[]";
//
// ***********************************************************************
// *********** Models holding Liberty information ******************
// ***********************************************************************
//
model PLL
(BYPASS, DIVF0, DIVF1, DIVF2,
DIVF3, DIVF4, DIVF5, DIVF6,
DIVF7, DIVQ0, DIVQ1, DIVQ2,
DIVR0, DIVR1, DIVR2, DIVR3,
DIVR4, DIVR5, FB, FSE,
LOCK, PLLOUT, RANGE0, RANGE1,
RANGE2, REF, RESET)
(
model_source = liberty_cell;
cell_type = prohibited;
input (BYPASS) ( )
input (DIVF0) ( )
input (DIVF1) ( )
input (DIVF2) ( )
input (DIVF3) ( )
input (DIVF4) ( )
input (DIVF5) ( )
input (DIVF6) ( )
input (DIVF7) ( )
input (DIVQ0) ( )
input (DIVQ1) ( )
input (DIVQ2) ( )
input (DIVR0) ( )
input (DIVR1) ( )
input (DIVR2) ( )
input (DIVR3) ( )
input (DIVR4) ( )
input (DIVR5) ( )
input (FB) ( )
input (FSE) ( )
input (RANGE0) ( )
input (RANGE1) ( )
input (RANGE2) ( )
input (REF) ( )
input (RESET) ( )
output (LOCK) ( )
output (PLLOUT) ( )
(
// Empty Model
)
) // end model PLL

BIN
libs/nangate_mvt.odb Normal file

Binary file not shown.

276
riscv_rtl/README.md Normal file
View File

@ -0,0 +1,276 @@
# [RISC-V Desgin in an Open_Source Design Flow](https://microtec-academy.de/produkt/risc-v-design-in-an-open-source-design-flow/)
A RISC-V design course, where you learn about the the RISC-V theory and then use it to build your own RISC-V processor.
This project has the full solution for the course exercises. It is able to simulate the Decoder or CPU as DUTs (device under tests). The simulation executes a SW test from a designated Hex file on the DUT.
In this README you will learn about ...
* what **prerequisites** you need to get this project running
* how the project is **organised**
* how to **run simulations**
## Background
This course is a part of the initiative [*Bavarian Chip Design Center (BCDC)*](https://www.iis.fraunhofer.de/en/ff/sse/bavarian-chip-design-center.html), which aims to develop and improve the IC-Design workforce in Bavaria.
This course is an adaptation of the code-base developed at [Lund University](https://www.lth.se/) by Per Andersson as part of the effort to develop and improve education in Digital System Design. You can find the original source-code under [this repository](https://github.com/PalePrime/single_cycle).
## Prerequisites
Bash Shell Terminal
* Windows: you need to install gitbash or use something similar
* MacOS/Linux: bash is preinstalled
GCC Compiler
* Installation details [here](https://gcc.gnu.org/install/)
Verilator
* If not installed, you can find the installation [here](https://verilator.org/guide/latest/install.html). It is highly recommended to install through a package manager for all operating systems.
* For Linux use apt package manager. Info under [verilator install guide](https://verilator.org/guide/latest/install.html#package-manager-quick-install).
* For MacOS the package manager is [homebrew](https://brew.sh/).
* For Windows an package manager option is [pacman](https://gist.github.com/AndreSteenveld/cb6662c93c8323795c5fd347defb8976) (untested).
* Export the *VERILATOR* environment variable. Make sure to use your Verilator install directory -> `export VERILATOR=</path/to/verilator>/bin/verilator`
Surfer Waveform Viewer
* If not installed, you can find the installation [here](https://surfer-project.org/)
* Export the *WAVE_VIEWER* environment variables. Make sure to use your Surfer install directory -> `export WAVE_VIEWER=</path/to/surfer>/surfer`
IDE (optional)
* Any IDE of your choosing will make it easy to view and manage the files
## Project Organisation
### Resources
Path: `doc`
* Module diagrams
* RISC-V Cards
* RISC-V ISM
* RISC-V ASM
### RTL source code
Path: `hw/rtl`
### File lists of SV code
Path: `hw/file_lists`
* RTL file list
* Testbench file list
### Verification source code
#### SV testbenches used in EDA playground
Path: `hw/dv/rtl`
#### Verilator environment
Path: `hw/dv/verilator/`
* SV Toplevel harnesses
* Decoder
* CPU
* C++ testbenches
* Decoder
* CPU
* Makefile
### Software and Hex programs used for testing
Path: `sw/risc-v`
* Main Memory: Hex code
* Decoder:
* Assembly code
* Hex code from assembeled assembly code
* Fibonacci Series/Hello World/Prime Factors:
* C Code
* Assembly code from compiled C code
* Simplified assembly code from assembly code (not available for Fibonacci Series)
* Hex code from assembeled assembly or simplified assembly code
## Running Simulations
### Quick start
Run the two commands below
```
cd hw/dv/verilator
```
```
make clean all run wave
```
This will convert the RTL into C++, compile the model, create the simulation binary, run the simulation, and start the waveform viewer. The output of the simulation should be the following:
```
*** Running simulation...
Creating model...
Registered DPI-C functions:
scopesDump:
SCOPE 0x55616d28b940: TOP.cpu_harness
DPI-EXPORT 0x556136cc8f77: enable
DPI-EXPORT 0x556136cc8f89: getLed
DPI-EXPORT 0x556136cc8fda: getMem
DPI-EXPORT 0x556136cc9006: getReg
DPI-EXPORT 0x556136cc9242: loadRAM
DPI-EXPORT 0x556136cdcc19: printMem
DPI-EXPORT 0x556136cdcd88: printReg
DPI-EXPORT 0x556136cc8fab: setBtn
DPI-EXPORT 0x556136cc8f68: setClk
DPI-EXPORT 0x556136cc8f78: setInitial
DPI-EXPORT 0x556136cc8fea: setMem
DPI-EXPORT 0x556136cc8fc9: setReset
Initializing SRAM memory from ../../../sw/risc-v/hello_world/helloWorld.hex
program set to helloWorld
Starting model...
Resetting...
Starting CPU...
Running for 500 clock cycles...
Printing evaluation for helloWorld program!
T=3960: Hex ASCII
Value at RAM[1024]: 0x68000000 : h
Value at RAM[1025]: 0x00000000 :
Value at RAM[1026]: 0x00000000 :
Value at RAM[1027]: 0x00000000 :
T=6840: Hex ASCII
Value at RAM[1024]: 0x68650000 : he
Value at RAM[1025]: 0x00000000 :
Value at RAM[1026]: 0x00000000 :
Value at RAM[1027]: 0x00000000 :
T=9720: Hex ASCII
Value at RAM[1024]: 0x68656c00 : hel
Value at RAM[1025]: 0x00000000 :
Value at RAM[1026]: 0x00000000 :
Value at RAM[1027]: 0x00000000 :
T=12600: Hex ASCII
Value at RAM[1024]: 0x68656c6c : hell
Value at RAM[1025]: 0x00000000 :
Value at RAM[1026]: 0x00000000 :
Value at RAM[1027]: 0x00000000 :
T=15480: Hex ASCII
Value at RAM[1024]: 0x68656c6c : hell
Value at RAM[1025]: 0x6f000000 : o
Value at RAM[1026]: 0x00000000 :
Value at RAM[1027]: 0x00000000 :
T=18360: Hex ASCII
Value at RAM[1024]: 0x68656c6c : hell
Value at RAM[1025]: 0x6f200000 : o
Value at RAM[1026]: 0x00000000 :
Value at RAM[1027]: 0x00000000 :
T=21240: Hex ASCII
Value at RAM[1024]: 0x68656c6c : hell
Value at RAM[1025]: 0x6f207700 : o w
Value at RAM[1026]: 0x00000000 :
Value at RAM[1027]: 0x00000000 :
T=24120: Hex ASCII
Value at RAM[1024]: 0x68656c6c : hell
Value at RAM[1025]: 0x6f20776f : o wo
Value at RAM[1026]: 0x00000000 :
Value at RAM[1027]: 0x00000000 :
T=27000: Hex ASCII
Value at RAM[1024]: 0x68656c6c : hell
Value at RAM[1025]: 0x6f20776f : o wo
Value at RAM[1026]: 0x72000000 : r
Value at RAM[1027]: 0x00000000 :
T=29880: Hex ASCII
Value at RAM[1024]: 0x68656c6c : hell
Value at RAM[1025]: 0x6f20776f : o wo
Value at RAM[1026]: 0x726c0000 : rl
Value at RAM[1027]: 0x00000000 :
T=32760: Hex ASCII
Value at RAM[1024]: 0x68656c6c : hell
Value at RAM[1025]: 0x6f20776f : o wo
Value at RAM[1026]: 0x726c6400 : rld
Value at RAM[1027]: 0x00000000 :
T=35640: Hex ASCII
Value at RAM[1024]: 0x68656c6c : hell
Value at RAM[1025]: 0x6f20776f : o wo
Value at RAM[1026]: 0x726c6421 : rld!
Value at RAM[1027]: 0x00000000 :
Done, closing simulation.
```
**Important:** The makefile reads the file lists `hw/file_lists/rtl_flist.f` and `hw/file_lists/tb_flist.f`. The make process does not recognize RTL or TB file changes, so it is required to run `make clean` after RTL or TB changes, otherwise the changed files will not be compiled.
### Makefile details
By default, the hex-file `sw/risc-v/hello_world.hex` is loaded into the Main Memory before starting the simulation, and the simulation is run for 500 clock cycles. This behavior can by overriden by specifying *PROG* and *NCYCLES* environment variables, which will load the specified hex file and run for the specified number of clock cycles.
```
make run PROG=/path/to/myprog.hex NCYCLES=2000
```
You can also combine the different make targets.
```
make clean all run wave PROG=/path/to/myprog.hex NCYCLES=2000
```
**Important:** If the simulation is not showing the full expected result, make sure that the number of cycles are sufficient for the CPU to finish executing the program (check if the last instruction executed is the *jump to halt* instruction)
Available Make targets (commands)
* **make clean** - remove old files
* **make** - build and compile the RTL simulator using Verilator and GCC (alias for `make all`)
* **make run** - run the simulation (requires built and compiled RTL)
* **make wave** - show the waveform in Surfer
* **make clean all run wave** - runs all the make targets (order is important)
It is not necessary to close the Surfer viewer if the simulation is run again. Just reload the Surfer window after the new run.
### Things you need/can change
* In the *Makefile*
* **PROG** - variable holding the hex file path of the program to be loaded
* **NCYCLES** - Variable for the number of cycles the CPU is going to run for
* **TOPMODULE** - Variable with the module name of the harness
* Int the *tb_flist.f*
* Add new harnesses you have created
### Things you can do
* You can run the exact same tests you ran on EDA Playground and you should get the same results. However, the test here will be using verilator.
* You can create your own harness and C++ testbenches for modules other than Decoder and CPU to get familiar with verilator testbenches
* Compare Icarus and Verilator output (uninitialised memory locations are set to 'x' when using Icarus and '0' when using verilator)

View File

@ -0,0 +1,131 @@
<mxfile host="65bd71144e">
<diagram name="Page-1" id="6TD31-tx4YeMT5SjUeEL">
<mxGraphModel dx="796" dy="265" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="827" pageHeight="1169" math="0" shadow="0">
<root>
<mxCell id="0"/>
<mxCell id="1" parent="0"/>
<mxCell id="fx5yl9cXGPLrq4qI7ClV-1" value="" style="group" parent="1" vertex="1" connectable="0">
<mxGeometry x="370" y="345.16" width="152.95000000000005" height="118.00999999999999" as="geometry"/>
</mxCell>
<mxCell id="fx5yl9cXGPLrq4qI7ClV-2" value="" style="group" parent="fx5yl9cXGPLrq4qI7ClV-1" vertex="1" connectable="0">
<mxGeometry y="4.839999999999975" width="152.95000000000005" height="113.17000000000002" as="geometry"/>
</mxCell>
<mxCell id="fx5yl9cXGPLrq4qI7ClV-3" style="edgeStyle=none;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.75;exitDx=0;exitDy=0;startArrow=none;startFill=0;endArrow=none;endFill=0;" parent="fx5yl9cXGPLrq4qI7ClV-2" edge="1">
<mxGeometry relative="1" as="geometry">
<mxPoint x="150" y="75.66836734693868" as="targetPoint"/>
<mxPoint x="118.95000000000005" y="75.50000000000011" as="sourcePoint"/>
</mxGeometry>
</mxCell>
<mxCell id="fx5yl9cXGPLrq4qI7ClV-4" value="eqFlag" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" parent="fx5yl9cXGPLrq4qI7ClV-3" vertex="1" connectable="0">
<mxGeometry x="-0.8665" relative="1" as="geometry">
<mxPoint x="21" y="7" as="offset"/>
</mxGeometry>
</mxCell>
<mxCell id="fx5yl9cXGPLrq4qI7ClV-5" value="" style="shape=image;verticalLabelPosition=bottom;labelBackgroundColor=default;verticalAlign=top;aspect=fixed;imageAspect=0;image=data:image/png,iVBORw0KGgoAAAANSUhEUgAAAE8AAACjCAYAAADLskN/AAAAAXNSR0IArs4c6QAAAIRlWElmTU0AKgAAAAgABQESAAMAAAABAAEAAAEaAAUAAAABAAAASgEbAAUAAAABAAAAUgEoAAMAAAABAAIAAIdpAAQAAAABAAAAWgAAAAAAAABIAAAAAQAAAEgAAAABAAOgAQADAAAAAQABAACgAgAEAAAAAQAAAE+gAwAEAAAAAQAAAKMAAAAAHJ2haQAAAAlwSFlzAAALEwAACxMBAJqcGAAAB9pJREFUeAHt3clS3EYYB/BhGFPeFxhsfEI8gMFgs93mJYwHigOVSvIIPpixy0tSyUPY46pszp5H4BovcZaqnOGWeDdgBrzgyfdX1K5Bo0atae39qcoItdQt9W96rEb61CoUCgWL/vHUoUBz375931Beq8P8RmdrLi4ubh07duzFgQMHbjNisLbQxLS8vNys1WqvgHjw4MFvqYhKsGLM3NrGEz+AeOPGja3e3t7Vw4cPf8eIuzcK4bZjDsSbN2++AuKRI0e+Z0RvxB1o7gUH8XVfX98aI7YDur08lx3EN0Ck1vgjt8T/IT2xZIlArNfrb8vl8jpB/mQ6osxp13QHcRuI/f39P5uKuCuS30qBSIAvjx8//otpiH4+SuuBeOvWrXenTp16SF2ce6YgKuGobiQQh4eHH9HZ+X7eEVVdAm0nEEdGRh4fPXr0t7wiBkIJurGD2Dx9+vQT+tPvQd4Qg3p0tH0L4tO9e/f+kxfEjjB0MtGJpTk6OvqMLoX9m3VEHQetvEA8c+bMiywjagGEkRmIZ8+eXd2/f//DrLXEMOofShlAHB8fX3MQFwgy9VMoFQ+zkKWlpcwghlnvUMsC4sTExDrdHnhETXAhjc0w1ApHUZiD+JJuDzwmwCtpQoyivpGUib7i5OTkBhCLxeLVNCBGUtEoCwXi1NRU49ChQ09KpdK1JBGjrGekZQNxenp6M0nESCsYR+ECkS6FPe3u7v4izpYYR/1i2QcQq9XqBhD37NnzZRyIsVQszp0AcXZ2thEHYpz1inVfApEuyj7r6en5KoqWGGuFktgZEOfm5rboouxzuhz2NSFaYUEmUZ9E9gnEixcvNsJETKQiSe4UiBQZtomgJt3wuiTrkei+HUSt8LpEK5CGnQNRRIYFDa9Lw/Gn4hiAKCLDqJujFF6XigNP00EIRAQ1+UWGpem4U3UsDqIdGUZn6B+oe1Nxd3FSdcBpPBiBiKCm1vC6LpLE8bpBedlDYGVlpUAXZrcvXLiw2Wg0/mY8DyS/JCAODQ0VGM9PSrK+q6urUJSs42QFAcZTQJJtwngyGYV0xlNAkm3CeDIZhXTGU0CSbcJ4MhmFdMZTQJJtwngyGYV0xlNAkm3CeDIZhXTGU0CSbcJ4MhmFdMZTQJJtwngyGYV0xlNAkm3CeDIZhXTGU0CSbcJ4MhmFdMZTQJJtwngyGYV0Gw+30ngKLlCkMPyPx8bGVi9fvrwdPDvngIBFiHcHBgY28agST/4CZNYWZrGAR5MQSY74DJ7kAl54diuksKrPEV5Fz7++k2c3e40MD4CYLAzpgUc2+avc3lDIp+1ra6u1/qAnaT7AwyDz8/Ov24swN0UJz4G0ECFJY0Vt4FF2nuyYPP+W19oK6fcKAf41MzOzZvoJJUjLazVEt+YjPMNw6dKlt6a2wk7xBKRFz/7fMbVvqIsnEI3sG4aFB0R8lT8zqW8YJh4AMRnTN6S6Bj7b2kJ+P0zoG0aG5+BaeAQJY4nmsW8YNZ5ooBUC/BNDeeSpbxgXHhAtGlzrwzz1DYGH5zDinCq0s6XBwcFC1q9ex/ocBloe4Oivku2sw8Xa2jAeHv+fF5BcnG3zeD2QKKLr56HwPF8DjAKvIq4+56lb4nXlKFQ8/G2LAk257xEWXgUF4Y6b1yeU1zRdPPt6HgaLzuMJwe9D7xiPxmP6BJn5SjIpBJgqeeyz+bUyr/Vkpt5VEXfPTPyKdoyHa3NQznOfzQvHL82v5RnTZ/OD8lovxUOsClaa0mfzwvFL88KrING0PpsflNf6Vjw7Po+CHJ/zCcGLqj3NxuM+WzuMSgrw7BF96I/4gmVZtMyTqgCuJPNwSKparu1ivQzv2ncuFvk5DI2PkfEYT0NAIyu3PMbTENDIyi2P8TQENLJyy2M8DQGNrNzyGE9DQCMrtzzG0xDQyMotj/E0BDSycstjPA0Bjazc8hhPQ0AjK7c8xtMQ0MjKLS8gHuJ3cNuR4hTvIKvKDXLjt0EULKwI7VeaW/TPnoyH2Q1AoDnvPbMcs/ez3fIau47Q3pBQExGxNLfea7l+MRbIq+K1Wu01+TSddz1K0YShVxlGpeFpJUJ7BTTnLaO+aMbjAY1eErwFNBoj5rYACTI3qpWhsg7aJtCcNysH8dqxrTF4QMM7vcNAE4K5xwMa3iYPNOdt8qLu2vPc4gENwelAo87tp9pSHgXkDq8VzYm59qh2OEm5wQNatVrdIBZ8PfFwYeRT5vHw+MP58+fXMTxnT0/P9cjFWnaQWTygYRRJesr8SalUutZSp9h+zRyeg7aaJJr4dDKDB7Rz5869wEDYxWLxqqhAkvPU4wGNxmt+CTSCupIklnvfqcVz0Nbp785HdNAL7gNPw3Lq8LKAJj641OABbXx8fA3jGNDBLYgDTPM8cTygnTx5cgsDWGcFTXygieEJNIzsmDW0xPCAhsGpy+XyH1lFix2P7nk2T5w40ejt7f0962ix4Qk0GjP0QV7QIsfD3XW0NAwLRzuriB3maR76CQNoeHcG3fO8n1c00QBCwxNodGnoXt7RQsOr1+t4Z1qTrnLcpbklCjZh3nHLE2h4L4ZpaKJhBMYjNM+IIVGgSXNlPBEx5A6zMgnLXVdfPIEmC7NyF2jSshRPNczKJCx3XdvwgoZZuQs0adnGwz3PTsOsTMJy11U7zMpdoEnL2mFWJmFxXUMS+A+AHlfjWfSaUAAAAABJRU5ErkJggg==;" parent="fx5yl9cXGPLrq4qI7ClV-2" vertex="1">
<mxGeometry x="70" y="10" width="48.95" height="101" as="geometry"/>
</mxCell>
<mxCell id="fx5yl9cXGPLrq4qI7ClV-6" value="&lt;span style=&quot;color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: center; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; white-space: normal; background-color: rgb(251, 251, 251); text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial; float: none; display: inline !important;&quot;&gt;ALU&lt;/span&gt;" style="text;whiteSpace=wrap;html=1;" parent="fx5yl9cXGPLrq4qI7ClV-2" vertex="1">
<mxGeometry x="88.94999999999999" y="45.5" width="30" height="30" as="geometry"/>
</mxCell>
<mxCell id="fx5yl9cXGPLrq4qI7ClV-7" style="rounded=0;orthogonalLoop=1;jettySize=auto;html=1;verticalAlign=middle;endArrow=none;endFill=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;strokeWidth=2;" parent="fx5yl9cXGPLrq4qI7ClV-2" edge="1">
<mxGeometry relative="1" as="geometry">
<mxPoint x="108.36999999999988" y="8" as="targetPoint"/>
<mxPoint x="108.36999999999999" y="29" as="sourcePoint"/>
</mxGeometry>
</mxCell>
<mxCell id="fx5yl9cXGPLrq4qI7ClV-8" value="aluOp" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" parent="fx5yl9cXGPLrq4qI7ClV-7" vertex="1" connectable="0">
<mxGeometry x="0.1579" relative="1" as="geometry">
<mxPoint y="-17" as="offset"/>
</mxGeometry>
</mxCell>
<mxCell id="fx5yl9cXGPLrq4qI7ClV-9" value="" style="endArrow=none;html=1;rounded=0;" parent="fx5yl9cXGPLrq4qI7ClV-2" edge="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="104.52000000000002" y="23" as="sourcePoint"/>
<mxPoint x="112.52000000000002" y="13" as="targetPoint"/>
</mxGeometry>
</mxCell>
<mxCell id="fx5yl9cXGPLrq4qI7ClV-10" value="&lt;span style=&quot;font-size: 9px;&quot;&gt;3&lt;/span&gt;" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" parent="fx5yl9cXGPLrq4qI7ClV-2" vertex="1">
<mxGeometry x="99.99999999999999" y="5" width="30" height="30" as="geometry"/>
</mxCell>
<mxCell id="fx5yl9cXGPLrq4qI7ClV-11" style="edgeStyle=none;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.25;exitDx=0;exitDy=0;endArrow=none;endFill=0;strokeWidth=2;" parent="fx5yl9cXGPLrq4qI7ClV-2" edge="1">
<mxGeometry relative="1" as="geometry">
<mxPoint x="148.95000000000016" y="50.70270270270271" as="targetPoint"/>
<mxPoint x="118.94999999999999" y="50.625" as="sourcePoint"/>
</mxGeometry>
</mxCell>
<mxCell id="fx5yl9cXGPLrq4qI7ClV-12" value="result" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" parent="fx5yl9cXGPLrq4qI7ClV-11" vertex="1" connectable="0">
<mxGeometry x="0.1333" relative="1" as="geometry">
<mxPoint x="2" y="-14" as="offset"/>
</mxGeometry>
</mxCell>
<mxCell id="fx5yl9cXGPLrq4qI7ClV-13" value="" style="endArrow=none;html=1;rounded=0;" parent="fx5yl9cXGPLrq4qI7ClV-2" edge="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="128.95" y="56" as="sourcePoint"/>
<mxPoint x="136.95" y="46" as="targetPoint"/>
</mxGeometry>
</mxCell>
<mxCell id="fx5yl9cXGPLrq4qI7ClV-14" style="edgeStyle=none;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.25;exitDx=0;exitDy=0;endArrow=none;endFill=0;strokeWidth=2;" parent="fx5yl9cXGPLrq4qI7ClV-2" edge="1">
<mxGeometry relative="1" as="geometry">
<mxPoint x="70.00000000000011" y="29.702702702702766" as="targetPoint"/>
<mxPoint x="40" y="30.000000000000057" as="sourcePoint"/>
</mxGeometry>
</mxCell>
<mxCell id="fx5yl9cXGPLrq4qI7ClV-15" value="" style="endArrow=none;html=1;rounded=0;" parent="fx5yl9cXGPLrq4qI7ClV-2" edge="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="50" y="35.00000000000006" as="sourcePoint"/>
<mxPoint x="58" y="25.000000000000057" as="targetPoint"/>
</mxGeometry>
</mxCell>
<mxCell id="fx5yl9cXGPLrq4qI7ClV-16" value="&lt;span style=&quot;font-size: 9px;&quot;&gt;32&lt;/span&gt;" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" parent="fx5yl9cXGPLrq4qI7ClV-2" vertex="1">
<mxGeometry x="44" y="23.000000000000057" width="30" height="30" as="geometry"/>
</mxCell>
<mxCell id="fx5yl9cXGPLrq4qI7ClV-17" value="op1" style="text;strokeColor=none;align=center;fillColor=none;html=1;verticalAlign=middle;whiteSpace=wrap;rounded=0;" parent="fx5yl9cXGPLrq4qI7ClV-2" vertex="1">
<mxGeometry x="5" y="19.500000000000057" width="40" height="20" as="geometry"/>
</mxCell>
<mxCell id="fx5yl9cXGPLrq4qI7ClV-18" style="edgeStyle=none;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.25;exitDx=0;exitDy=0;endArrow=none;endFill=0;strokeWidth=2;" parent="fx5yl9cXGPLrq4qI7ClV-2" edge="1">
<mxGeometry relative="1" as="geometry">
<mxPoint x="70.00000000000011" y="89.87270270270272" as="targetPoint"/>
<mxPoint x="40" y="90.17000000000002" as="sourcePoint"/>
</mxGeometry>
</mxCell>
<mxCell id="fx5yl9cXGPLrq4qI7ClV-19" value="" style="endArrow=none;html=1;rounded=0;" parent="fx5yl9cXGPLrq4qI7ClV-2" edge="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="50" y="95.17000000000002" as="sourcePoint"/>
<mxPoint x="58" y="85.17000000000002" as="targetPoint"/>
</mxGeometry>
</mxCell>
<mxCell id="fx5yl9cXGPLrq4qI7ClV-20" value="&lt;span style=&quot;font-size: 9px;&quot;&gt;32&lt;/span&gt;" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" parent="fx5yl9cXGPLrq4qI7ClV-2" vertex="1">
<mxGeometry x="44" y="83.17000000000002" width="30" height="30" as="geometry"/>
</mxCell>
<mxCell id="fx5yl9cXGPLrq4qI7ClV-21" value="op2" style="text;strokeColor=none;align=center;fillColor=none;html=1;verticalAlign=middle;whiteSpace=wrap;rounded=0;" parent="fx5yl9cXGPLrq4qI7ClV-2" vertex="1">
<mxGeometry x="5" y="79.67000000000002" width="40" height="20" as="geometry"/>
</mxCell>
<mxCell id="fx5yl9cXGPLrq4qI7ClV-22" value="&lt;font style=&quot;font-size: 9px;&quot;&gt;32&lt;/font&gt;" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" parent="fx5yl9cXGPLrq4qI7ClV-2" vertex="1">
<mxGeometry x="122.95000000000005" y="41.58000000000004" width="30" height="30" as="geometry"/>
</mxCell>
<mxCell id="80" style="edgeStyle=none;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;endArrow=none;endFill=0;" edge="1" parent="fx5yl9cXGPLrq4qI7ClV-2">
<mxGeometry relative="1" as="geometry">
<mxPoint x="99.94999999999999" y="94.67000000000002" as="targetPoint"/>
<mxPoint x="100" y="110" as="sourcePoint"/>
</mxGeometry>
</mxCell>
<mxCell id="81" value="aluNegAr" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" vertex="1" connectable="0" parent="80">
<mxGeometry x="0.0744" relative="1" as="geometry">
<mxPoint y="18" as="offset"/>
</mxGeometry>
</mxCell>
<mxCell id="fx5yl9cXGPLrq4qI7ClV-23" style="edgeStyle=none;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;endArrow=none;endFill=0;" parent="fx5yl9cXGPLrq4qI7ClV-1" edge="1">
<mxGeometry relative="1" as="geometry">
<mxPoint x="85" as="targetPoint"/>
<mxPoint x="85" y="22.840000000000032" as="sourcePoint"/>
</mxGeometry>
</mxCell>
<mxCell id="fx5yl9cXGPLrq4qI7ClV-24" value="aluBypass" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" parent="fx5yl9cXGPLrq4qI7ClV-23" vertex="1" connectable="0">
<mxGeometry x="0.0744" relative="1" as="geometry">
<mxPoint y="-21" as="offset"/>
</mxGeometry>
</mxCell>
</root>
</mxGraphModel>
</diagram>
</mxfile>

View File

@ -0,0 +1,77 @@
<svg host="65bd71144e" xmlns="http://www.w3.org/2000/svg" style="background: transparent; background-color: transparent;" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="573px" height="359px" viewBox="-0.5 -0.5 573 359" content="&lt;mxfile scale=&quot;2&quot; border=&quot;0&quot;&gt;&lt;diagram name=&quot;Page-1&quot; id=&quot;Dras1X57W6EPz2KZu20U&quot;&gt;5Vdtb9sgEP41lrYPqWyIU+djm75sXSdVi9R1nyoaU5vOBg+TxN6v32FwbJKsydp1mzopUriH4+DuHh5kD0/y6lySIv0oYpp5yI8rD594CB0i5OmfH9cGwGhogESy2EBBB0zZd2pB36JzFtPScVRCZIoVLjgTnNOZcjAipVi6bvcic3ctSEI3gOmMZJvoZxar1KAROuzwd5QlabtzMBqbmZy0zjaTMiWxWPYgfOrhiRRCmVFeTWima9fWxaw7+8ns6mCScrXPghPCBqT208uL24vkw4M/u59OBigyYRYkm9uM7WlV3ZZASUZ4oq3jZcoUnRZkpqeW0HDAUpVnYAUwlEIRxQQHczD2AbhnWTYRmZCAcMF1iFJJ8ZW2oIdwhO7waAQz0EJFGKca14s3E7Q5L6hUtOpBNuFzKnKqZA0udhZFoVmyYp9txrLrZcu0tN9GixHLnmQVuSswDGyNf6HeGG+p9yiDbY9jtoBhoprMDVQWhDu9GH2ba7pAqZryHcGkTO7ewGnhOH7797YJAVznalA2N0o7BqioTGwbpN3t03s42DV4TISk7daQndndPRHAzjnXqCLFnMc0tg3cwRZ9Pnvhg2Fr21jBdvK8BEVC36FIEG1SJNpGkfClONJqyyu9k8PAvZNoS8H/6J0cjjbKS2N4BKwppEpFIjjJTjv02GV653MpRGEr/0CVqi3ByVwJty+0YuqmN/6iQx2E1jqpbOTGqFuDQ743faO3Spvdssaqd3WtFHM5o4/plS26IjKhag9h05V7lAWSZsDHhfu8butps/RISlL3HArBuCp7ka800CPX2L3N7e0+29Mf7/BfveZP9EdhuMZXk2HH3lWpnvHI+BsCksMlvs1p/hoUG0drNQ32U+zoxQQk/KsCcuD7rohgPHySjKBdOqKjXFHJoGy7G7pbW/C+2uL/bm15XruDf6vd4Xj8pHYf/jft3q7NGK/pyDh0Q5iU7Ko10jwq02B233XGvfs4xqc/AA==&lt;/diagram&gt;&lt;/mxfile&gt;">
<defs/>
<g>
<g>
<path d="M 144 280 L 164 290 L 144 300 Z" fill="none" stroke="#82b366" stroke-width="2" stroke-miterlimit="10" transform="rotate(-90,154,290)" pointer-events="all" style="stroke: light-dark(rgb(130, 179, 102), rgb(68, 110, 44));"/>
</g>
<g>
<rect x="74" y="0" width="160" height="300" fill="none" stroke="#000000" stroke-width="2" pointer-events="all" style="stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));"/>
</g>
<g>
<g transform="translate(-0.5 -0.5)scale(2)">
<switch>
<foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility">
<div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 75px; margin-left: 38px;">
<div style="box-sizing: border-box; font-size: 0; text-align: center; color: #000000; ">
<div style="display: inline-block; font-size: 14px; font-family: &quot;Helvetica&quot;; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; font-weight: bold; white-space: normal; word-wrap: normal; ">
<div>
<span style="color: light-dark(rgb(0, 0, 0), rgb(237, 237, 237)); font-size: 12px;">
RISC-V Core
</span>
</div>
</div>
</div>
</div>
</foreignObject>
<text x="77" y="79" fill="light-dark(#000000, #ffffff)" font-family="&quot;Helvetica&quot;" font-size="14px" text-anchor="middle" font-weight="bold">
RISC-V Core
</text>
</switch>
</g>
</g>
<g>
<path d="M 404 200 L 424 210 L 404 220 Z" fill="none" stroke="#82b366" stroke-width="2" stroke-miterlimit="10" transform="rotate(-90,414,210)" pointer-events="all" style="stroke: light-dark(rgb(130, 179, 102), rgb(68, 110, 44));"/>
</g>
<g>
<path d="M 494 140 L 554 140 L 554 340 L 14 340 L 14 150.03 L 61.26 150.01" fill="none" stroke="#000000" stroke-width="2" stroke-miterlimit="10" pointer-events="stroke" style="stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));"/>
<path d="M 71.76 150 L 57.77 157.01 L 61.26 150.01 L 57.76 143.01 Z" fill="#000000" stroke="#000000" stroke-width="2" stroke-miterlimit="10" pointer-events="all" style="fill: light-dark(rgb(0, 0, 0), rgb(255, 255, 255)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));"/>
</g>
<g>
<rect x="334" y="60" width="160" height="160" fill="none" stroke="#000000" stroke-width="2" pointer-events="all" style="stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));"/>
</g>
<g>
<g transform="translate(-0.5 -0.5)scale(2)">
<switch>
<foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility">
<div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 70px; margin-left: 168px;">
<div style="box-sizing: border-box; font-size: 0; text-align: center; color: #000000; ">
<div style="display: inline-block; font-size: 14px; font-family: &quot;Helvetica&quot;; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; font-weight: bold; white-space: normal; word-wrap: normal; ">
main_mem
</div>
</div>
</div>
</foreignObject>
<text x="207" y="74" fill="light-dark(#000000, #ffffff)" font-family="&quot;Helvetica&quot;" font-size="14px" text-anchor="middle" font-weight="bold">
main_mem
</text>
</switch>
</g>
</g>
<g>
<path d="M 234.16 100.2 L 284.03 100.23 L 321.26 100.06" fill="none" stroke="#000000" stroke-width="2" stroke-miterlimit="10" pointer-events="stroke" style="stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));"/>
<path d="M 331.76 100.01 L 317.8 107.07 L 321.26 100.06 L 317.73 93.07 Z" fill="#000000" stroke="#000000" stroke-width="2" stroke-miterlimit="10" pointer-events="all" style="fill: light-dark(rgb(0, 0, 0), rgb(255, 255, 255)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));"/>
</g>
<g>
<path d="M 234.16 179.7 L 284.03 179.61 L 321.26 179.9" fill="none" stroke="#000000" stroke-width="2" stroke-miterlimit="10" pointer-events="stroke" style="stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));"/>
<path d="M 331.76 179.98 L 317.71 186.87 L 321.26 179.9 L 317.82 172.87 Z" fill="#000000" stroke="#000000" stroke-width="2" stroke-miterlimit="10" pointer-events="all" style="fill: light-dark(rgb(0, 0, 0), rgb(255, 255, 255)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));"/>
</g>
</g>
<switch>
<g requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"/>
<a transform="translate(0,-5)" xlink:href="https://www.drawio.com/doc/faq/svg-export-text-problems" target="_blank">
<text text-anchor="middle" font-size="10px" x="50%" y="100%">
Text is not SVG - cannot display
</text>
</a>
</switch>
</svg>

After

Width:  |  Height:  |  Size: 7.3 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 136 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 18 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 89 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 144 KiB

View File

@ -0,0 +1,163 @@
<mxfile host="Electron" agent="Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/26.2.2 Chrome/134.0.6998.178 Electron/35.1.2 Safari/537.36" version="26.2.2">
<diagram name="Page-1" id="vqPtpfTpDl2-zyb6y6Gk">
<mxGraphModel dx="2152" dy="1262" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="1169" pageHeight="827" math="0" shadow="0">
<root>
<mxCell id="0" />
<mxCell id="1" parent="0" />
<mxCell id="QNMoGRvylN2gnaf27AE2-2" value="" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#f5f5f5;fontColor=#333333;strokeColor=default;" parent="1" vertex="1">
<mxGeometry x="200" y="270" width="680" height="340" as="geometry" />
</mxCell>
<mxCell id="QNMoGRvylN2gnaf27AE2-1" value="" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#f8cecc;strokeColor=default;" parent="1" vertex="1">
<mxGeometry x="250" y="480" width="540" height="80" as="geometry" />
</mxCell>
<mxCell id="QNMoGRvylN2gnaf27AE2-3" value="" style="shape=flexArrow;endArrow=classic;html=1;rounded=0;entryX=0.47;entryY=1;entryDx=0;entryDy=0;entryPerimeter=0;exitX=0.683;exitY=0.008;exitDx=0;exitDy=0;exitPerimeter=0;" parent="1" edge="1" source="QNMoGRvylN2gnaf27AE2-24">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="650.4" y="435" as="sourcePoint" />
<mxPoint x="649.9999999999999" y="355" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="QNMoGRvylN2gnaf27AE2-4" value="" style="shape=flexArrow;endArrow=classic;html=1;rounded=0;exitX=0.588;exitY=0.999;exitDx=0;exitDy=0;exitPerimeter=0;entryX=0.489;entryY=0.019;entryDx=0;entryDy=0;entryPerimeter=0;" parent="1" edge="1" target="QNMoGRvylN2gnaf27AE2-23">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="579.7999999999997" y="354.99999999999994" as="sourcePoint" />
<mxPoint x="579.96" y="435.16" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="QNMoGRvylN2gnaf27AE2-5" value="" style="endArrow=classic;html=1;rounded=0;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.118;entryY=0.001;entryDx=0;entryDy=0;entryPerimeter=0;" parent="1" edge="1" source="QNMoGRvylN2gnaf27AE2-7">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="299.7999999999998" y="400" as="sourcePoint" />
<mxPoint x="299.7999999999998" y="480.0799999999999" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="QNMoGRvylN2gnaf27AE2-6" value="" style="endArrow=classic;html=1;rounded=0;entryX=0.118;entryY=0.001;entryDx=0;entryDy=0;entryPerimeter=0;exitX=0.5;exitY=1;exitDx=0;exitDy=0;" parent="1" edge="1" source="QNMoGRvylN2gnaf27AE2-8">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="370" y="360" as="sourcePoint" />
<mxPoint x="369.8" y="480" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="QNMoGRvylN2gnaf27AE2-7" value="setClk()" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#fff2cc;strokeColor=default;" parent="1" vertex="1">
<mxGeometry x="270" y="325" width="60" height="30" as="geometry" />
</mxCell>
<mxCell id="QNMoGRvylN2gnaf27AE2-8" value="setReset()" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#fff2cc;strokeColor=default;" parent="1" vertex="1">
<mxGeometry x="340" y="325" width="60" height="30" as="geometry" />
</mxCell>
<mxCell id="QNMoGRvylN2gnaf27AE2-9" value="enable()" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#fff2cc;strokeColor=default;" parent="1" vertex="1">
<mxGeometry x="410" y="325" width="60" height="30" as="geometry" />
</mxCell>
<mxCell id="QNMoGRvylN2gnaf27AE2-10" value="setInitial()" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#fff2cc;strokeColor=default;" parent="1" vertex="1">
<mxGeometry x="480" y="325" width="60" height="30" as="geometry" />
</mxCell>
<mxCell id="QNMoGRvylN2gnaf27AE2-11" value="setBtn()" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#fff2cc;strokeColor=default;" parent="1" vertex="1">
<mxGeometry x="550" y="325" width="60" height="30" as="geometry" />
</mxCell>
<mxCell id="QNMoGRvylN2gnaf27AE2-12" value="getLed()" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#fff2cc;strokeColor=default;" parent="1" vertex="1">
<mxGeometry x="620" y="325" width="60" height="30" as="geometry" />
</mxCell>
<mxCell id="QNMoGRvylN2gnaf27AE2-13" value="loadRAM" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#fff2cc;strokeColor=default;" parent="1" vertex="1">
<mxGeometry x="690" y="325" width="60" height="30" as="geometry" />
</mxCell>
<mxCell id="QNMoGRvylN2gnaf27AE2-14" value="dumpRAM()" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#fff2cc;strokeColor=default;" parent="1" vertex="1">
<mxGeometry x="760" y="325" width="70" height="30" as="geometry" />
</mxCell>
<mxCell id="QNMoGRvylN2gnaf27AE2-15" value="cpu_harness" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" parent="1" vertex="1">
<mxGeometry x="790" y="580" width="90" height="30" as="geometry" />
</mxCell>
<mxCell id="QNMoGRvylN2gnaf27AE2-20" value="cpu (device under test)" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" parent="1" vertex="1">
<mxGeometry x="650" y="530" width="140" height="30" as="geometry" />
</mxCell>
<mxCell id="QNMoGRvylN2gnaf27AE2-21" value="clk" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" parent="1" vertex="1">
<mxGeometry x="280" y="480" width="40" height="30" as="geometry" />
</mxCell>
<mxCell id="QNMoGRvylN2gnaf27AE2-22" value="rst" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" parent="1" vertex="1">
<mxGeometry x="345" y="480" width="40" height="30" as="geometry" />
</mxCell>
<mxCell id="QNMoGRvylN2gnaf27AE2-23" value="btn[6:0]" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" parent="1" vertex="1">
<mxGeometry x="550" y="480" width="60" height="30" as="geometry" />
</mxCell>
<mxCell id="QNMoGRvylN2gnaf27AE2-24" value="led[7:0]" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" parent="1" vertex="1">
<mxGeometry x="610" y="480" width="60" height="30" as="geometry" />
</mxCell>
<mxCell id="QNMoGRvylN2gnaf27AE2-25" value="DPI-C tasks and functions" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" parent="1" vertex="1">
<mxGeometry x="500" y="295" width="160" height="30" as="geometry" />
</mxCell>
<mxCell id="QNMoGRvylN2gnaf27AE2-26" value="" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=default;" parent="1" vertex="1">
<mxGeometry x="200" y="80" width="680" height="160" as="geometry" />
</mxCell>
<mxCell id="QNMoGRvylN2gnaf27AE2-27" value="tb_cpu_harness" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" parent="1" vertex="1">
<mxGeometry x="780" y="210" width="110" height="30" as="geometry" />
</mxCell>
<mxCell id="QNMoGRvylN2gnaf27AE2-28" value="" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#fff2cc;strokeColor=default;" parent="1" vertex="1">
<mxGeometry x="610" y="100" width="130" height="110" as="geometry" />
</mxCell>
<mxCell id="QNMoGRvylN2gnaf27AE2-29" value="&lt;b&gt;class cpu&lt;/b&gt;&lt;div&gt;cpu::tick()&lt;/div&gt;&lt;div&gt;cpu::setReset()&lt;/div&gt;&lt;div&gt;cpu::waitClocks()&lt;/div&gt;&lt;div&gt;cpu::loadRAM()&lt;/div&gt;&lt;div&gt;...&lt;/div&gt;" style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" parent="1" vertex="1">
<mxGeometry x="630" y="110" width="110" height="100" as="geometry" />
</mxCell>
<mxCell id="QNMoGRvylN2gnaf27AE2-30" value="" style="endArrow=classic;html=1;rounded=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;exitX=0.052;exitY=0.966;exitDx=0;exitDy=0;exitPerimeter=0;flowAnimation=0;shadow=0;dashed=1;" parent="1" source="QNMoGRvylN2gnaf27AE2-28" target="QNMoGRvylN2gnaf27AE2-7" edge="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="940" y="260" as="sourcePoint" />
<mxPoint x="500" y="400" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="QNMoGRvylN2gnaf27AE2-31" value="" style="endArrow=classic;html=1;rounded=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;exitX=0.138;exitY=1.004;exitDx=0;exitDy=0;exitPerimeter=0;dashed=1;" parent="1" source="QNMoGRvylN2gnaf27AE2-28" target="QNMoGRvylN2gnaf27AE2-8" edge="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="557" y="216" as="sourcePoint" />
<mxPoint x="310" y="335" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="QNMoGRvylN2gnaf27AE2-32" value="" style="endArrow=classic;html=1;rounded=0;exitX=0.834;exitY=1.006;exitDx=0;exitDy=0;exitPerimeter=0;entryX=0.603;entryY=0.068;entryDx=0;entryDy=0;entryPerimeter=0;dashed=1;" parent="1" source="QNMoGRvylN2gnaf27AE2-29" target="QNMoGRvylN2gnaf27AE2-14" edge="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="-20" y="450" as="sourcePoint" />
<mxPoint x="30" y="400" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="QNMoGRvylN2gnaf27AE2-33" value="&lt;b&gt;&lt;font style=&quot;font-size: 19px;&quot;&gt;...&lt;/font&gt;&lt;/b&gt;" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" parent="1" vertex="1">
<mxGeometry x="650" y="200" width="40" height="40" as="geometry" />
</mxCell>
<mxCell id="QNMoGRvylN2gnaf27AE2-34" value="&lt;blockquote style=&quot;margin: 0 0 0 40px; border: none; padding: 0px;&quot;&gt;&lt;b&gt;main()&lt;/b&gt;&lt;div&gt;create cpu instance&lt;/div&gt;&lt;div&gt;cpu.loadRam(&quot;hexfile&quot;);&lt;/div&gt;&lt;div&gt;cpu.reset(10);&lt;/div&gt;&lt;div&gt;cpu.start();&lt;/div&gt;&lt;div&gt;...&lt;/div&gt;&lt;div&gt;cpu.stop();&lt;/div&gt;&lt;div&gt;cpu.delete();&lt;/div&gt;&lt;/blockquote&gt;" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#fff2cc;strokeColor=default;align=left;" parent="1" vertex="1">
<mxGeometry x="260" y="95" width="210" height="130" as="geometry" />
</mxCell>
<mxCell id="QNMoGRvylN2gnaf27AE2-35" value="" style="shape=flexArrow;endArrow=classic;startArrow=classic;html=1;rounded=0;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=-0.002;entryY=0.547;entryDx=0;entryDy=0;entryPerimeter=0;fillColor=#bac8d3;strokeColor=default;" parent="1" source="QNMoGRvylN2gnaf27AE2-34" target="QNMoGRvylN2gnaf27AE2-28" edge="1">
<mxGeometry width="100" height="100" relative="1" as="geometry">
<mxPoint x="440" y="250" as="sourcePoint" />
<mxPoint x="530" y="160" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="QNMoGRvylN2gnaf27AE2-36" value="&lt;font style=&quot;font-size: 20px;&quot;&gt;&lt;b&gt;C++&lt;/b&gt;&lt;/font&gt;" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;rotation=-90;" parent="1" vertex="1">
<mxGeometry x="930" y="140" width="60" height="40" as="geometry" />
</mxCell>
<mxCell id="QNMoGRvylN2gnaf27AE2-37" value="&lt;font style=&quot;font-size: 20px;&quot;&gt;&lt;b&gt;SystemVerilog&lt;/b&gt;&lt;/font&gt;" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;rotation=-90;" parent="1" vertex="1">
<mxGeometry x="880" y="394" width="160" height="40" as="geometry" />
</mxCell>
<mxCell id="QNMoGRvylN2gnaf27AE2-39" value="" style="endArrow=none;html=1;rounded=0;" parent="1" edge="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="960" y="120" as="sourcePoint" />
<mxPoint x="960" y="80" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="QNMoGRvylN2gnaf27AE2-40" value="" style="endArrow=none;html=1;rounded=0;" parent="1" edge="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="959.66" y="240" as="sourcePoint" />
<mxPoint x="959.66" y="200" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="QNMoGRvylN2gnaf27AE2-41" value="" style="endArrow=none;html=1;rounded=0;exitX=0.996;exitY=0.511;exitDx=0;exitDy=0;exitPerimeter=0;" parent="1" source="QNMoGRvylN2gnaf27AE2-37" edge="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="959.66" y="325" as="sourcePoint" />
<mxPoint x="959.66" y="285" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="QNMoGRvylN2gnaf27AE2-42" value="" style="endArrow=none;html=1;rounded=0;" parent="1" target="QNMoGRvylN2gnaf27AE2-37" edge="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="959.66" y="560" as="sourcePoint" />
<mxPoint x="959.66" y="520" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="CcVjRRQ9gQZcIWVMXx_5-1" value="" style="rounded=0;whiteSpace=wrap;html=1;fillColor=none;" vertex="1" parent="1">
<mxGeometry x="160" y="40" width="890" height="620" as="geometry" />
</mxCell>
<mxCell id="CcVjRRQ9gQZcIWVMXx_5-2" value="Text" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" vertex="1" parent="1">
<mxGeometry x="1105" y="548" width="50" height="30" as="geometry" />
</mxCell>
</root>
</mxGraphModel>
</diagram>
</mxfile>

View File

@ -0,0 +1,160 @@
<mxfile host="65bd71144e">
<diagram name="Page-1" id="vqPtpfTpDl2-zyb6y6Gk">
<mxGraphModel dx="1708" dy="882" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="1169" pageHeight="827" math="0" shadow="0">
<root>
<mxCell id="0"/>
<mxCell id="1" parent="0"/>
<mxCell id="QNMoGRvylN2gnaf27AE2-2" value="" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#f5f5f5;fontColor=#333333;strokeColor=default;" parent="1" vertex="1">
<mxGeometry x="200" y="270" width="680" height="340" as="geometry"/>
</mxCell>
<mxCell id="QNMoGRvylN2gnaf27AE2-1" value="" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#f8cecc;strokeColor=default;" parent="1" vertex="1">
<mxGeometry x="250" y="480" width="540" height="80" as="geometry"/>
</mxCell>
<mxCell id="QNMoGRvylN2gnaf27AE2-3" value="" style="shape=flexArrow;endArrow=classic;html=1;rounded=0;entryX=0.47;entryY=1;entryDx=0;entryDy=0;entryPerimeter=0;exitX=0.683;exitY=0.008;exitDx=0;exitDy=0;exitPerimeter=0;" parent="1" source="QNMoGRvylN2gnaf27AE2-24" edge="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="650.4" y="435" as="sourcePoint"/>
<mxPoint x="649.9999999999999" y="355" as="targetPoint"/>
</mxGeometry>
</mxCell>
<mxCell id="QNMoGRvylN2gnaf27AE2-4" value="" style="shape=flexArrow;endArrow=classic;html=1;rounded=0;exitX=0.588;exitY=0.999;exitDx=0;exitDy=0;exitPerimeter=0;entryX=0.489;entryY=0.019;entryDx=0;entryDy=0;entryPerimeter=0;" parent="1" target="QNMoGRvylN2gnaf27AE2-23" edge="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="579.7999999999997" y="354.99999999999994" as="sourcePoint"/>
<mxPoint x="579.96" y="435.16" as="targetPoint"/>
</mxGeometry>
</mxCell>
<mxCell id="QNMoGRvylN2gnaf27AE2-5" value="" style="endArrow=classic;html=1;rounded=0;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.118;entryY=0.001;entryDx=0;entryDy=0;entryPerimeter=0;" parent="1" source="QNMoGRvylN2gnaf27AE2-7" edge="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="299.7999999999998" y="400" as="sourcePoint"/>
<mxPoint x="299.7999999999998" y="480.0799999999999" as="targetPoint"/>
</mxGeometry>
</mxCell>
<mxCell id="QNMoGRvylN2gnaf27AE2-6" value="" style="endArrow=classic;html=1;rounded=0;entryX=0.118;entryY=0.001;entryDx=0;entryDy=0;entryPerimeter=0;exitX=0.5;exitY=1;exitDx=0;exitDy=0;" parent="1" source="QNMoGRvylN2gnaf27AE2-8" edge="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="370" y="360" as="sourcePoint"/>
<mxPoint x="369.8" y="480" as="targetPoint"/>
</mxGeometry>
</mxCell>
<mxCell id="QNMoGRvylN2gnaf27AE2-7" value="setClk()" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#fff2cc;strokeColor=default;" parent="1" vertex="1">
<mxGeometry x="270" y="325" width="60" height="30" as="geometry"/>
</mxCell>
<mxCell id="QNMoGRvylN2gnaf27AE2-8" value="setReset()" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#fff2cc;strokeColor=default;" parent="1" vertex="1">
<mxGeometry x="340" y="325" width="60" height="30" as="geometry"/>
</mxCell>
<mxCell id="QNMoGRvylN2gnaf27AE2-9" value="enable()" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#fff2cc;strokeColor=default;" parent="1" vertex="1">
<mxGeometry x="410" y="325" width="60" height="30" as="geometry"/>
</mxCell>
<mxCell id="QNMoGRvylN2gnaf27AE2-10" value="setInitial()" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#fff2cc;strokeColor=default;" parent="1" vertex="1">
<mxGeometry x="480" y="325" width="60" height="30" as="geometry"/>
</mxCell>
<mxCell id="QNMoGRvylN2gnaf27AE2-11" value="setBtn()" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#fff2cc;strokeColor=default;" parent="1" vertex="1">
<mxGeometry x="550" y="325" width="60" height="30" as="geometry"/>
</mxCell>
<mxCell id="QNMoGRvylN2gnaf27AE2-12" value="getLed()" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#fff2cc;strokeColor=default;" parent="1" vertex="1">
<mxGeometry x="620" y="325" width="60" height="30" as="geometry"/>
</mxCell>
<mxCell id="QNMoGRvylN2gnaf27AE2-13" value="loadRAM" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#fff2cc;strokeColor=default;" parent="1" vertex="1">
<mxGeometry x="690" y="325" width="60" height="30" as="geometry"/>
</mxCell>
<mxCell id="QNMoGRvylN2gnaf27AE2-14" value="dumpRAM()" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#fff2cc;strokeColor=default;" parent="1" vertex="1">
<mxGeometry x="760" y="325" width="70" height="30" as="geometry"/>
</mxCell>
<mxCell id="QNMoGRvylN2gnaf27AE2-15" value="cpu_harness" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" parent="1" vertex="1">
<mxGeometry x="790" y="580" width="90" height="30" as="geometry"/>
</mxCell>
<mxCell id="QNMoGRvylN2gnaf27AE2-20" value="cpu (device under test)" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" parent="1" vertex="1">
<mxGeometry x="645" y="530" width="150" height="30" as="geometry"/>
</mxCell>
<mxCell id="QNMoGRvylN2gnaf27AE2-21" value="clk" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" parent="1" vertex="1">
<mxGeometry x="280" y="480" width="40" height="30" as="geometry"/>
</mxCell>
<mxCell id="QNMoGRvylN2gnaf27AE2-22" value="rst" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" parent="1" vertex="1">
<mxGeometry x="345" y="480" width="40" height="30" as="geometry"/>
</mxCell>
<mxCell id="QNMoGRvylN2gnaf27AE2-23" value="btn[6:0]" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" parent="1" vertex="1">
<mxGeometry x="550" y="480" width="60" height="30" as="geometry"/>
</mxCell>
<mxCell id="QNMoGRvylN2gnaf27AE2-24" value="led[7:0]" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" parent="1" vertex="1">
<mxGeometry x="610" y="480" width="60" height="30" as="geometry"/>
</mxCell>
<mxCell id="QNMoGRvylN2gnaf27AE2-25" value="DPI-C tasks and functions" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" parent="1" vertex="1">
<mxGeometry x="500" y="295" width="160" height="30" as="geometry"/>
</mxCell>
<mxCell id="QNMoGRvylN2gnaf27AE2-26" value="" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=default;" parent="1" vertex="1">
<mxGeometry x="200" y="80" width="680" height="160" as="geometry"/>
</mxCell>
<mxCell id="QNMoGRvylN2gnaf27AE2-27" value="tb_cpu_harness" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" parent="1" vertex="1">
<mxGeometry x="780" y="210" width="110" height="30" as="geometry"/>
</mxCell>
<mxCell id="QNMoGRvylN2gnaf27AE2-28" value="" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#fff2cc;strokeColor=default;" parent="1" vertex="1">
<mxGeometry x="610" y="100" width="130" height="110" as="geometry"/>
</mxCell>
<mxCell id="QNMoGRvylN2gnaf27AE2-29" value="&lt;b&gt;class cpu&lt;/b&gt;&lt;div&gt;cpu::tick()&lt;/div&gt;&lt;div&gt;cpu::setReset()&lt;/div&gt;&lt;div&gt;cpu::waitClocks()&lt;/div&gt;&lt;div&gt;cpu::loadRAM()&lt;/div&gt;&lt;div&gt;...&lt;/div&gt;" style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" parent="1" vertex="1">
<mxGeometry x="630" y="110" width="110" height="100" as="geometry"/>
</mxCell>
<mxCell id="QNMoGRvylN2gnaf27AE2-30" value="" style="endArrow=classic;html=1;rounded=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;exitX=0.052;exitY=0.966;exitDx=0;exitDy=0;exitPerimeter=0;flowAnimation=0;shadow=0;dashed=1;" parent="1" source="QNMoGRvylN2gnaf27AE2-28" target="QNMoGRvylN2gnaf27AE2-7" edge="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="940" y="260" as="sourcePoint"/>
<mxPoint x="500" y="400" as="targetPoint"/>
</mxGeometry>
</mxCell>
<mxCell id="QNMoGRvylN2gnaf27AE2-31" value="" style="endArrow=classic;html=1;rounded=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;exitX=0.138;exitY=1.004;exitDx=0;exitDy=0;exitPerimeter=0;dashed=1;" parent="1" source="QNMoGRvylN2gnaf27AE2-28" target="QNMoGRvylN2gnaf27AE2-8" edge="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="557" y="216" as="sourcePoint"/>
<mxPoint x="310" y="335" as="targetPoint"/>
</mxGeometry>
</mxCell>
<mxCell id="QNMoGRvylN2gnaf27AE2-32" value="" style="endArrow=classic;html=1;rounded=0;exitX=0.834;exitY=1.006;exitDx=0;exitDy=0;exitPerimeter=0;entryX=0.603;entryY=0.068;entryDx=0;entryDy=0;entryPerimeter=0;dashed=1;" parent="1" source="QNMoGRvylN2gnaf27AE2-29" target="QNMoGRvylN2gnaf27AE2-14" edge="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="-20" y="450" as="sourcePoint"/>
<mxPoint x="30" y="400" as="targetPoint"/>
</mxGeometry>
</mxCell>
<mxCell id="QNMoGRvylN2gnaf27AE2-33" value="&lt;b&gt;&lt;font style=&quot;font-size: 19px;&quot;&gt;...&lt;/font&gt;&lt;/b&gt;" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" parent="1" vertex="1">
<mxGeometry x="650" y="200" width="40" height="40" as="geometry"/>
</mxCell>
<mxCell id="QNMoGRvylN2gnaf27AE2-34" value="&lt;blockquote style=&quot;margin: 0 0 0 40px; border: none; padding: 0px;&quot;&gt;&lt;b&gt;main()&lt;/b&gt;&lt;div&gt;create cpu instance&lt;/div&gt;&lt;div&gt;cpu.loadRam(&quot;hexfile&quot;);&lt;/div&gt;&lt;div&gt;cpu.reset(10);&lt;/div&gt;&lt;div&gt;cpu.start();&lt;/div&gt;&lt;div&gt;...&lt;/div&gt;&lt;div&gt;cpu.stop();&lt;/div&gt;&lt;div&gt;cpu.delete();&lt;/div&gt;&lt;/blockquote&gt;" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#fff2cc;strokeColor=default;align=left;" parent="1" vertex="1">
<mxGeometry x="260" y="95" width="210" height="130" as="geometry"/>
</mxCell>
<mxCell id="QNMoGRvylN2gnaf27AE2-35" value="" style="shape=flexArrow;endArrow=classic;startArrow=classic;html=1;rounded=0;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=-0.002;entryY=0.547;entryDx=0;entryDy=0;entryPerimeter=0;fillColor=#bac8d3;strokeColor=default;" parent="1" source="QNMoGRvylN2gnaf27AE2-34" target="QNMoGRvylN2gnaf27AE2-28" edge="1">
<mxGeometry width="100" height="100" relative="1" as="geometry">
<mxPoint x="440" y="250" as="sourcePoint"/>
<mxPoint x="530" y="160" as="targetPoint"/>
</mxGeometry>
</mxCell>
<mxCell id="QNMoGRvylN2gnaf27AE2-36" value="&lt;font style=&quot;font-size: 20px;&quot;&gt;&lt;b&gt;C++&lt;/b&gt;&lt;/font&gt;" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;rotation=-90;" parent="1" vertex="1">
<mxGeometry x="930" y="140" width="60" height="40" as="geometry"/>
</mxCell>
<mxCell id="QNMoGRvylN2gnaf27AE2-37" value="&lt;font style=&quot;font-size: 20px;&quot;&gt;&lt;b&gt;SystemVerilog&lt;/b&gt;&lt;/font&gt;" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;rotation=-90;" parent="1" vertex="1">
<mxGeometry x="880" y="394" width="160" height="40" as="geometry"/>
</mxCell>
<mxCell id="QNMoGRvylN2gnaf27AE2-39" value="" style="endArrow=none;html=1;rounded=0;" parent="1" edge="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="960" y="120" as="sourcePoint"/>
<mxPoint x="960" y="80" as="targetPoint"/>
</mxGeometry>
</mxCell>
<mxCell id="QNMoGRvylN2gnaf27AE2-40" value="" style="endArrow=none;html=1;rounded=0;" parent="1" edge="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="959.66" y="240" as="sourcePoint"/>
<mxPoint x="959.66" y="200" as="targetPoint"/>
</mxGeometry>
</mxCell>
<mxCell id="QNMoGRvylN2gnaf27AE2-41" value="" style="endArrow=none;html=1;rounded=0;exitX=0.996;exitY=0.511;exitDx=0;exitDy=0;exitPerimeter=0;" parent="1" source="QNMoGRvylN2gnaf27AE2-37" edge="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="959.66" y="325" as="sourcePoint"/>
<mxPoint x="959.66" y="285" as="targetPoint"/>
</mxGeometry>
</mxCell>
<mxCell id="QNMoGRvylN2gnaf27AE2-42" value="" style="endArrow=none;html=1;rounded=0;" parent="1" target="QNMoGRvylN2gnaf27AE2-37" edge="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="959.66" y="560" as="sourcePoint"/>
<mxPoint x="959.66" y="520" as="targetPoint"/>
</mxGeometry>
</mxCell>
<mxCell id="2" value="" style="rounded=0;whiteSpace=wrap;html=1;fillColor=none;" vertex="1" parent="1">
<mxGeometry x="160" y="40" width="890" height="620" as="geometry"/>
</mxCell>
</root>
</mxGraphModel>
</diagram>
</mxfile>

Binary file not shown.

After

Width:  |  Height:  |  Size: 89 KiB

Binary file not shown.

View File

@ -0,0 +1,25 @@
// MemGen_16_10_stub.sv
// Behavioral stub - ports matched from MemGen_32_11.sv instantiation
module MemGen_16_10 #(
parameter ADDR_WIDTH = 10,
parameter DATA_WIDTH = 16
)(
input logic chip_en,
input logic clock,
input logic [ADDR_WIDTH-1:0] addr,
input logic rd_en,
output logic [DATA_WIDTH-1:0] rd_data,
input logic wr_en,
input logic [DATA_WIDTH-1:0] wr_data
);
logic [DATA_WIDTH-1:0] mem [0:(2**ADDR_WIDTH)-1];
always_ff @(posedge clock) begin
if (chip_en) begin
if (wr_en)
mem[addr] <= wr_data;
else if (rd_en)
rd_data <= mem[addr];
end
end
endmodule

View File

@ -0,0 +1,112 @@
// *********************************************************************************************
// Project Version : v1.0
// Project : [BCDC] Microtec Academy Course: Building a RISC-V CPU with SystemVerilog
// -----
// Copyright (c) : 2025 Fraunhofer IIS, Department IDS
// Created : 15.Oct.2025 by Bomin Kim
// Last Modified : 23.Oct.2025 by Bomin Kim [commit 2f8f03d]
// -----
// HISTORY : Date By Comments
// ----------- --------- -------------------------------------------------
// *********************************************************************************************
`timescale 1ns/1ns
module alu_tb();
// Local Signals
logic[2:0] aluOp;
logic aluNegAr;
logic aluBypass;
logic[31:0] op1;
logic[31:0] op2;
logic[31:0] result;
logic eqFlag;
// Toplevel instance (DUT)
alu u_alu (
.aluOp(aluOp),
.aluNegAr(aluNegAr),
.aluBypass(aluBypass),
.op1(op1),
.op2(op2),
.result(result),
.eqFlag(eqFlag)
);
// list of aluOp
localparam logic[2:0] f3add = 3'b000;
localparam logic[2:0] f3sl = 3'b001;
localparam logic[2:0] f3slt = 3'b010;
localparam logic[2:0] f3sltU = 3'b011;
localparam logic[2:0] f3xor = 3'b100;
localparam logic[2:0] f3sr = 3'b101;
localparam logic[2:0] f3or = 3'b110;
localparam logic[2:0] f3and = 3'b111;
// Initialize and run simulation
initial begin
dumpWave("wave.vcd");
// Initialize inputs
aluOp = 0;
aluNegAr = 0;
aluBypass = 0;
op1 = 0;
op2 = 0;
#10
// Set op1 and op2
op1 = 32'hDEAD_BEEF; op2 = 32'h0000_0001; #70
$display("\nTime = %0dns \t : op1 = %h, op2 = %h", $time, op1, op2);
$display("\nTime = %0dns \t : Is op1 and op2 equal?; eqFlag = %d", $time, eqFlag);
aluBypass = 1; #70
$display("\nTime = %0dns \t : AluBypass is set; result = %h", $time, result);
aluBypass = 0; aluOp = f3add; #70
$display("\nTime = %0dns \t : Alu operates addition; result = %h", $time, result);
aluNegAr = 1; #70
$display("\nTime = %0dns \t : Alu operates subtraction; result = %h", $time, result);
aluNegAr = 0; aluOp = f3sl; #70
$display("\nTime = %0dns \t : Alu operates shift left; result = %h", $time, result);
aluOp = f3slt; #70
$display("\nTime = %0dns \t : Alu operates set less than; result = %h", $time, result);
aluOp = f3sltU; #70
$display("\nTime = %0dns \t : Alu operates set less than (unsigned); result = %h", $time, result);
aluOp = f3xor; #70
$display("\nTime = %0dns \t : Alu operates bit-wise XOR; result = %h", $time, result);
aluOp = f3sr; aluNegAr = 1; #70
$display("\nTime = %0dns \t : Alu operates arithmetic right shift; result = %h", $time, result);
aluNegAr = 0; #70
$display("\nTime = %0dns \t : Alu operates logical right shift; result = %h", $time, result);
aluOp = f3or; #70
$display("\nTime = %0dns \t : Alu operates bit-wise OR; result = %h", $time, result);
aluOp = f3and; #70
$display("\nTime = %0dns \t : Alu operates bit-wise AND; result = %h", $time, result);
$finish;
end
// Wave Dump Helper Task
task dumpWave(string fileName);
// Open wave file and dump all signals (2D arrays not included)
$display("\nTime = %0dns \t : Opening wave file '%s'", $time, fileName);
$dumpfile(fileName);
$display("Time = %0dns \t : Dumping all %s signals in wave file (2D arrays not included)", $time, "alu_tb");
$dumpvars(0, alu_tb);
endtask: dumpWave
endmodule

View File

@ -0,0 +1,164 @@
// *********************************************************************************************
// Project Version : v1.0
// Project : [BCDC] Microtec Academy Course: Building a RISC-V CPU with SystemVerilog
// -----
// Copyright (c) : 2025 Fraunhofer IIS, Department IDS
// Created : 15.Oct.2025 by Hussein Elzomor
// Last Modified : 23.Oct.2025 by Hussein Elzomor [commit 2f8f03d]
// -----
// HISTORY : Date By Comments
// ----------- --------- -------------------------------------------------
// 15.Oct.2025 H.Elzomor Renamed file and module from soc_tb to cpu_tb
// *********************************************************************************************
// `define fibonacci
// `define helloWorld
// `define primeFactors
`timescale 1ns/1ns
module cpu_tb ();
// local signals
logic[7:0] led;
logic[6:0] btn;
logic reset;
logic clk;
// Toplevel instance (DUT)
cpu u_cpu (
.led(led),
.btn(btn),
.clk_25mhz(clk)
);
// Tie reset signal to the reset button
assign btn[0] = reset;
// Clock generation
always #20 clk = ~clk;
// Initialize and run simulation
initial begin
dumpWave("wave.vcd");
`ifdef fibonacci
loadMem("fibonacci.hex");
`elsif helloWorld
loadMem("helloWorld.hex");
`elsif primeFactors
loadMem("primeFactors.hex");
`endif
clk = 0;
$display("\nTime = %0dns \t : Resetting the CPU", $time);
reset = 0; #100;
$display("\nTime = %0dns \t : Reset released", $time);
reset = 1; #500000;
$finish;
end
// Fibonacci Program Monitor
`ifdef fibonacci
localparam int fibonacciStartLoc = 2027;
localparam int fibonacciLengthInWords = 10;
always_comb begin: Monitor_Fibonacci_Series_Calculation
$display("\nTime =%5dns\t\t\t Hex \t Dec", $time);
$display("Value at RAM[%0d]: 0x%h : %0d",fibonacciStartLoc+0, u_cpu.theMem.RAM[fibonacciStartLoc+0], u_cpu.theMem.RAM[fibonacciStartLoc+0]);
$display("Value at RAM[%0d]: 0x%h : %0d",fibonacciStartLoc+1, u_cpu.theMem.RAM[fibonacciStartLoc+1], u_cpu.theMem.RAM[fibonacciStartLoc+1]);
$display("Value at RAM[%0d]: 0x%h : %0d",fibonacciStartLoc+2, u_cpu.theMem.RAM[fibonacciStartLoc+2], u_cpu.theMem.RAM[fibonacciStartLoc+2]);
$display("Value at RAM[%0d]: 0x%h : %0d",fibonacciStartLoc+3, u_cpu.theMem.RAM[fibonacciStartLoc+3], u_cpu.theMem.RAM[fibonacciStartLoc+3]);
$display("Value at RAM[%0d]: 0x%h : %0d",fibonacciStartLoc+4, u_cpu.theMem.RAM[fibonacciStartLoc+4], u_cpu.theMem.RAM[fibonacciStartLoc+4]);
$display("Value at RAM[%0d]: 0x%h : %0d",fibonacciStartLoc+5, u_cpu.theMem.RAM[fibonacciStartLoc+5], u_cpu.theMem.RAM[fibonacciStartLoc+5]);
$display("Value at RAM[%0d]: 0x%h : %0d",fibonacciStartLoc+6, u_cpu.theMem.RAM[fibonacciStartLoc+6], u_cpu.theMem.RAM[fibonacciStartLoc+6]);
$display("Value at RAM[%0d]: 0x%h : %0d",fibonacciStartLoc+7, u_cpu.theMem.RAM[fibonacciStartLoc+7], u_cpu.theMem.RAM[fibonacciStartLoc+7]);
$display("Value at RAM[%0d]: 0x%h : %0d",fibonacciStartLoc+8, u_cpu.theMem.RAM[fibonacciStartLoc+8], u_cpu.theMem.RAM[fibonacciStartLoc+8]);
$display("Value at RAM[%0d]: 0x%h : %0d",fibonacciStartLoc+9, u_cpu.theMem.RAM[fibonacciStartLoc+9], u_cpu.theMem.RAM[fibonacciStartLoc+9]);
$display("");
end
// Hello World Program Monitor
`elsif helloWorld
localparam int helloWorldStartLoc = 1024;
localparam int helloWorldLengthInWords = 4;
always_comb begin: Monitor_Hello_World_Printing
$display("\nTime =%5dns\t\t Hex \t\t ASCII", $time);
$display("Value at RAM[%0d]: 0x%h : %0s", helloWorldStartLoc+0, u_cpu.theMem.RAM[helloWorldStartLoc+0], u_cpu.theMem.RAM[helloWorldStartLoc+0]);
$display("Value at RAM[%0d]: 0x%h : %0s", helloWorldStartLoc+1, u_cpu.theMem.RAM[helloWorldStartLoc+1], u_cpu.theMem.RAM[helloWorldStartLoc+1]);
$display("Value at RAM[%0d]: 0x%h : %0s", helloWorldStartLoc+2, u_cpu.theMem.RAM[helloWorldStartLoc+2], u_cpu.theMem.RAM[helloWorldStartLoc+2]);
$display("Value at RAM[%0d]: 0x%h : %0s", helloWorldStartLoc+3, u_cpu.theMem.RAM[helloWorldStartLoc+3], u_cpu.theMem.RAM[helloWorldStartLoc+3]);
$display("");
end
// Prime Factors Program Monitor
`elsif primeFactors
localparam int primeNumberReg = 16;
always_comb begin: Monitor_Factorization_Number
if(u_cpu.theRegisters.registers[primeNumberReg] > 1)
$display("\nTime =%5dns \t : Register [%0d] updated - Finding the prime factors of %0d", $time,primeNumberReg, u_cpu.theRegisters.registers[primeNumberReg]);
end
localparam int primeFactorsReg = 17;
always_comb begin: Monitor_Prime_Number
if(u_cpu.theRegisters.registers[primeFactorsReg] > 1)
$display("Time =%5dns \t : Register [%0d] updated - %0d is a prime factor", $time,primeFactorsReg, u_cpu.theRegisters.registers[primeFactorsReg]);
end
`endif
// Wave Dump Helper Task
int i;
task dumpWave(string fileName);
// Open wave file and dump all signals (2D arrays not included)
$display("\nTime = %0dns \t : Opening wave file '%s'", $time, fileName);
$dumpfile(fileName);
$display("Time = %0dns \t : Dumping all %s signals in wave file (2D arrays not included)", $time, "cpu_tb");
$dumpvars(0, cpu_tb);
// Dump Memory in wave file
$display("\nTime = %0dns \t : Dumping Memory in wave file", $time);
for (i = 0; i < 100; i++) begin $dumpvars(0, cpu_tb.u_cpu.theMem.RAM[i]); end // A part of the Instruction Memory
for (i = 1024; i < 1124; i++) begin $dumpvars(0, cpu_tb.u_cpu.theMem.RAM[i]); end // A part of the Data Memory
for (i = 1968; i < 2048; i++) begin $dumpvars(0, cpu_tb.u_cpu.theMem.RAM[i]); end // A part of the Stack
// Dump registers in wave file
$display("\nTime = %0dns \t : Dumping Registers in wave file", $time);
$dumpvars(0, cpu_tb.u_cpu.theRegisters.registers[1]);
$dumpvars(0, cpu_tb.u_cpu.theRegisters.registers[2]);
$dumpvars(0, cpu_tb.u_cpu.theRegisters.registers[3]);
$dumpvars(0, cpu_tb.u_cpu.theRegisters.registers[4]);
$dumpvars(0, cpu_tb.u_cpu.theRegisters.registers[5]);
$dumpvars(0, cpu_tb.u_cpu.theRegisters.registers[6]);
$dumpvars(0, cpu_tb.u_cpu.theRegisters.registers[7]);
$dumpvars(0, cpu_tb.u_cpu.theRegisters.registers[8]);
$dumpvars(0, cpu_tb.u_cpu.theRegisters.registers[9]);
$dumpvars(0, cpu_tb.u_cpu.theRegisters.registers[10]);
$dumpvars(0, cpu_tb.u_cpu.theRegisters.registers[11]);
$dumpvars(0, cpu_tb.u_cpu.theRegisters.registers[12]);
$dumpvars(0, cpu_tb.u_cpu.theRegisters.registers[13]);
$dumpvars(0, cpu_tb.u_cpu.theRegisters.registers[14]);
$dumpvars(0, cpu_tb.u_cpu.theRegisters.registers[15]);
$dumpvars(0, cpu_tb.u_cpu.theRegisters.registers[16]);
$dumpvars(0, cpu_tb.u_cpu.theRegisters.registers[17]);
$dumpvars(0, cpu_tb.u_cpu.theRegisters.registers[18]);
$dumpvars(0, cpu_tb.u_cpu.theRegisters.registers[19]);
$dumpvars(0, cpu_tb.u_cpu.theRegisters.registers[20]);
$dumpvars(0, cpu_tb.u_cpu.theRegisters.registers[21]);
$dumpvars(0, cpu_tb.u_cpu.theRegisters.registers[22]);
$dumpvars(0, cpu_tb.u_cpu.theRegisters.registers[23]);
$dumpvars(0, cpu_tb.u_cpu.theRegisters.registers[24]);
$dumpvars(0, cpu_tb.u_cpu.theRegisters.registers[25]);
$dumpvars(0, cpu_tb.u_cpu.theRegisters.registers[26]);
$dumpvars(0, cpu_tb.u_cpu.theRegisters.registers[27]);
$dumpvars(0, cpu_tb.u_cpu.theRegisters.registers[28]);
$dumpvars(0, cpu_tb.u_cpu.theRegisters.registers[29]);
$dumpvars(0, cpu_tb.u_cpu.theRegisters.registers[30]);
$dumpvars(0, cpu_tb.u_cpu.theRegisters.registers[31]);
endtask: dumpWave
// Load hex file into memory
task loadMem (string fileName);
$display("\nTime = %0dns \t : Loading '%s' into Memory", $time, fileName);
$readmemh(fileName, cpu_tb.u_cpu.theMem.RAM);
endtask: loadMem
endmodule

View File

@ -0,0 +1,150 @@
// *********************************************************************************************
// Project Version : v1.0
// Project : [BCDC] Microtec Academy Course: Building a RISC-V CPU with SystemVerilog
// -----
// Copyright (c) : 2025 Fraunhofer IIS, Department IDS
// Created : 15.Oct.2025 by Hussein Elzomor
// Last Modified : 23.Oct.2025 by Hussein Elzomor [commit 2f8f03d]
// -----
// HISTORY : Date By Comments
// ----------- --------- -------------------------------------------------
// *********************************************************************************************
`timescale 1ns/1ns
module decoder_tb ();
// local Parameters
localparam MEM_SIZE = 37;
localparam REG_FILE_SIZE = 32;
// local signals
logic clk;
int counter;
logic[31:0] mem [MEM_SIZE-1:0];
logic[31:0] regFile [REG_FILE_SIZE-1:0];
// PC
logic[31:0] CurrentPC;
logic[31:0] JumpOrBranchPC;
logic JumpOrBranch;
logic[31:0] NextPC;
// Memory
logic[31:0] DAddr;
logic[31:0] WData;
logic[31:0] RData;
logic[31:0] Instruction;
logic WrMem;
logic[1:0] DWidth;
// Register File;
logic[4:0] Rs1;
logic[4:0] Rs2;
logic[4:0] Rd;
logic[31:0] RRs1;
logic[31:0] RRs2;
logic[31:0] WRd;
logic WrReg;
// Protection
logic Illegal;
// Toplevel instance (DUT)
decoder u_decoder (
// PC
.CurrentPC(CurrentPC),
.JumpOrBranchPC(JumpOrBranchPC),
.JumpOrBranch(JumpOrBranch),
// Memory
.DAddr(DAddr),
.WData(WData),
.RData(RData),
.Instruction(Instruction),
.WrMem(WrMem),
.DWidth(DWidth),
// Register File
.Rs1(Rs1),
.Rs2(Rs2),
.Rd(Rd),
.RRs1(RRs1),
.RRs2(RRs2),
.WRd(WRd),
.WrReg(WrReg),
// Protection
.Illegal(Illegal)
);
// Clock generation
always begin
clk = ~clk; #1;
end
// Load a new instruction every cycle
always_ff @(posedge clk) begin: increment_instruction_and_print_info
if (counter < MEM_SIZE) begin
if (counter > 0) printInfo();
Instruction = mem[counter++];
end
end
// Return the value of the RegFile
always_comb begin: reg_file_assignment
RRs1 = regFile[Rs1];
RRs2 = regFile[Rs2];
end
// Initialize and run simulation
initial begin
dumpWave("wave.vcd");
loadMem("decoder.hex");
clk = 1;
counter = 0;
CurrentPC = 32'hdeadbeef;
RData = 32'hbeefdead;
for(int i=0; i<REG_FILE_SIZE; i++) begin
regFile[i] = i;
end
while (counter < MEM_SIZE) #1;
printInfo();
#1 $finish;
end
// Functions
// Wave Dump Helper Task
task dumpWave(string fileName);
// Open wave file and dump all signals (2D arrays not included)
$display("\nTime = %0dns \t : Opening wave file '%s'", $time, fileName);
$dumpfile(fileName);
$display("Time = %0dns \t : Dumping all %s signals in wave file (2D arrays not included)", $time, "decoder_tb");
$dumpvars(0, decoder_tb);
endtask: dumpWave
// Load hex file into memory
task loadMem (string fileName);
$display("\nTime = %0dns \t : Loading '%s' into Memory", $time, fileName);
$readmemh(fileName, mem);
endtask: loadMem
// Print decoder signals
task printInfo();
$displayh("\n(cycle %0d) Decoder (I/O) \tDecoder (Internal Signals) \tALU" , counter );
$displayh(" -------------------------- \t--------------------------------------------- \t---------------------" );
$displayh(" CurrentPC : 0x%h OpCode : 0b%b aluOp : 0b%b" , CurrentPC , u_decoder.theOp , u_decoder.aluOp );
$displayh(" JumpOrBranchPC: 0x%h theFunct3: 0b%b aluNegAr : 0b%b" , JumpOrBranchPC, u_decoder.theFunct3, u_decoder.aluNegAr );
$displayh(" JumpOrBranch : 0b%b \ttheFunct7: 0b%b aluBypass: 0b%b", JumpOrBranch , u_decoder.theFunct7, u_decoder.aluBypass);
$displayh(" DAddr : 0x%h i_imm : 0b%b op1 : 0x%h" , DAddr , u_decoder.i_imm , u_decoder.op1 );
$displayh(" WData : 0x%h s_imm : 0b%b op2 : 0x%h" , WData , u_decoder.s_imm , u_decoder.op2 );
$displayh(" RData : 0x%h b_imm : 0b%b result : 0x%h" , RData , u_decoder.b_imm , u_decoder.result );
$displayh(" Instruction : 0x%h u_imm : 0b%b eqFlag : 0b%b" , Instruction , u_decoder.u_imm , u_decoder.eqFlag );
$displayh(" WrMem : 0b%b \tj_imm : 0b%b" , WrMem , u_decoder.j_imm );
$displayh(" DWidth : 0b%b" , DWidth );
$displayh(" Rs1 : %0d " , Rs1 );
$displayh(" Rs2 : %0d " , Rs2 );
$displayh(" Rd : 0x%h" , Rd );
$displayh(" RRs1 : %0d " , RRs1 );
$displayh(" RRs2 : %0d " , RRs2 );
$displayh(" WRd : 0x%h" , WRd );
$displayh(" WrReg : 0b%b" , WrReg );
$displayh(" Illegal : 0b%b" , Illegal );
endtask: printInfo
endmodule

View File

@ -0,0 +1,238 @@
// *********************************************************************************************
// Project Version : v1.0
// Project : [BCDC] Microtec Academy Course: Building a RISC-V CPU with SystemVerilog
// -----
// Copyright (c) : 2025 Fraunhofer IIS, Department IDS
// Created : 20.Oct.2025 by Aliakbar Merchant
// Last Modified : 24.Oct.2025 by Aliakbar Merchant [commit 89a5087]
// -----
// HISTORY : Date By Comments
// ----------- --------- -------------------------------------------------
// *********************************************************************************************
`timescale 1ns/1ns
module main_mem_tb ();
// local Parameters
localparam string MEM_INIT_FILE = "main_mem.hex";
// Helpers for addressing width
localparam logic[1:0] _byte = 2'b00; // byte: 8 bits
localparam logic[1:0] _half = 2'b01; // half: 16 bits
localparam logic[1:0] _word = 2'b10; // word: 32 bits
// Local Signals
// clk and reset
logic clk;
logic reset;
// Memory
logic[31:0] DAddr;
logic[31:0] IAddr;
logic[31:0] DWData;
logic[31:0] DRData;
logic[31:0] IRData;
logic DWE;
logic[1:0] DWidth;
// Helpers for display results purpose
logic[31:0] value_at_0;
logic[31:0] value_at_1;
logic[31:0] value_at_2;
logic[31:0] value_at_3;
logic[31:0] value_at_1024;
logic[31:0] value_at_1025;
logic[31:0] value_at_1026;
logic[31:0] value_at_1027;
// Toplevel instance (DUT)
main_mem u_main_mem (
.clk (clk ),
.reset (reset ),
.DAddr (DAddr ),
.IAddr (IAddr ),
.DWData (DWData ),
.DRData (DRData ),
.IRData (IRData ),
.DWE (DWE ),
.DWidth (DWidth )
);
// Clock generation
always #1 clk = ~clk;
// Initialize and run simulation
initial begin
loadMem(MEM_INIT_FILE);
value_at_0 = main_mem_tb.u_main_mem.RAM[0];
value_at_1 = main_mem_tb.u_main_mem.RAM[1];
value_at_2 = main_mem_tb.u_main_mem.RAM[2];
value_at_3 = main_mem_tb.u_main_mem.RAM[3];
value_at_1024 = main_mem_tb.u_main_mem.RAM[1024];
value_at_1025 = main_mem_tb.u_main_mem.RAM[1025];
value_at_1026 = main_mem_tb.u_main_mem.RAM[1026];
value_at_1027 = main_mem_tb.u_main_mem.RAM[1027];
clk = 0;
DAddr = 32'd4096;
IAddr = 0;
DWData = 0;
DWidth = 0;
reset = 1; DWE=1; #7;
DWE = 0;
reset = 0; #2;
test_scenario1(); #30;
$finish;
end
// Test scenario 1
task test_scenario1();
fork
read_inst_mem(15);
display_inst_read_results();
write_data_mem(4096);
join
display_write_results();
fork
display_read_results();
read_data_mem(4096);
join
endtask: test_scenario1
// Intruction memory read transactions and results display
task read_inst_mem(int unsigned n = 1);
repeat(n) begin
cycles_pe(1);
IAddr = IAddr+4;
end
endtask:read_inst_mem
task display_inst_read_results();
$display("\n----------------------------------------------------------------------------------" );
$display("Instruction MEMORY READ RESULTS" );
$display("15 instruction are read by testbench starting at adrress 0x0000 i.e at (RAM[0]) but only 4 displyed for simplicity" );
$display("----------------------------------------------------------------------------------" );
cycles_pe(2);
$display("Time = %0dns \t : IAddr = 0x0000(RAM[0]): Expected value = 0x%h Actual Value at IRData: 0x%h" , $time, value_at_0, IRData );
cycles_pe(1);
$display("Time = %0dns \t : IAddr = 0x0004(RAM[1]): Expected value = 0x%h Actual Value at IRData: 0x%h" , $time, value_at_1, IRData );
cycles_pe(1);
$display("Time = %0dns \t : IAddr = 0x0008(RAM[2]): Expected value = 0x%h Actual Value at IRData: 0x%h" , $time, value_at_2, IRData );
cycles_pe(1);
$display("Time = %0dns \t : IAddr = 0x000c(RAM[3]): Expected value = 0x%h Actual Value at IRData: 0x%h" , $time, value_at_3, IRData );
endtask:display_inst_read_results
// Data memory write transaction and results display
task write_data_mem(logic [31:0] daddr_init=32'd4096);
cycles_pe(1);
DWE = 1;
DWidth = 0;
DAddr = daddr_init+0;
DWData = 32'hDEADBEEF;
cycles_pe(1);
DWE = 1;
DWidth = 1;
DAddr = daddr_init+4;
DWData = 32'hDEADBEEF;
cycles_pe(1);
DWE = 1;
DWidth = 2;
DAddr = daddr_init+8;
DWData = 32'hDEADBEEF;
cycles_pe(1);
DWE = 1;
DWidth = 3;
DAddr = daddr_init+12;
DWData = 32'hDEADBEEF;
cycles_pe(1);
DWE = 0;
endtask:write_data_mem
task display_write_results();
$display("\n----------------------------------------------------------------------------------" );
$display("DATA MEMORY WRITE RESULTS" );
$display("4 Write transaction are being done by testbench starting at adrress 0x1000 i.e at (RAM[1024]) with all 4 combination of DWidth" );
$display("Data written is always 0xDEADBEEF i.e DWData = DEADBEEF" );
$display("----------------------------------------------------------------------------------" );
$display("Time = %0dns \t : DWidth = 0 DAddr = 0x1000(RAM[1024]): Start value at RAM[1024] = 0x%h Expected value at RAM[1024]= 0xef%h Actual Value at RAM[1024]: 0x%h" , $time, value_at_1024,value_at_1024[23:0], getMem(1024) );
$display("Time = %0dns \t : DWidth = 1 DAddr = 0x1004(RAM[1025]): Start value at RAM[1025] = 0x%h Expected value at RAM[1025]= 0xbeef%h Actual Value at RAM[1025]: 0x%h" , $time, value_at_1025,value_at_1025[15:0], getMem(1025) );
$display("Time = %0dns \t : DWidth = 2 DAddr = 0x1008(RAM[1026]): Start value at RAM[1026] = 0x%h Expected value at RAM[1026]= 0xdeadbeef Actual Value at RAM[1026]: 0x%h" , $time, value_at_1026, getMem(1026) );
$display("Time = %0dns \t : DWidth = 3 DAddr = 0x100c(RAM[1027]): Start value at RAM[1027] = 0x%h Expected value at RAM[1027]= 0x%h Actual Value at RAM[1027]: 0x%h" , $time, value_at_1027,value_at_1027, getMem(1027) );
endtask:display_write_results
// Data Memory read transaction and results display
task read_data_mem(logic [31:0] daddr_init=32'd4096);
cycles_pe(1);
DWidth = 0;
DAddr = daddr_init+0;
cycles_pe(1);
DWidth = 1;
DAddr = daddr_init+4;
cycles_pe(1);
DWidth = 2;
DAddr = daddr_init+8;
cycles_pe(1);
DWidth = 3;
DAddr = daddr_init+12;
cycles_pe(1);
DWidth = 2;
DAddr = daddr_init+0;
cycles_pe(1);
DWidth = 2;
DAddr = daddr_init+4;
cycles_pe(1);
DWidth = 2;
DAddr = daddr_init+8;
cycles_pe(1);
DWidth = 2;
DAddr = daddr_init+12;
endtask:read_data_mem
task display_read_results();
$display("\n----------------------------------------------------------------------------------" );
$display("DATA MEMORY READ RESULTS" );
$display("8 Read transaction are being done by testbench starting at adrress 0x1000 i.e at (RAM[1024])" );
$display("----------------------------------------------------------------------------------" );
cycles_pe(2);
$display("Time = %0dns \t : DWidth = 0 DAddr = 0x1000(RAM[1024]): Expected value = 0x000000ef Actual Value at DRData: 0x%h" , $time, DRData );
cycles_pe(1);
$display("Time = %0dns \t : DWidth = 1 DAddr = 0x1004(RAM[1025]): Expected value = 0x0000beef Actual Value at DRData: 0x%h" , $time, DRData );
cycles_pe(1);
$display("Time = %0dns \t : DWidth = 2 DAddr = 0x1008(RAM[1026]): Expected value = 0xdeadbeef Actual Value at DRData: 0x%h" , $time, DRData );
cycles_pe(1);
$display("Time = %0dns \t : DWidth = 3 DAddr = 0x100c(RAM[1027]): Expected value = 0xdeadbeef Actual Value at DRData: 0x%h" , $time, DRData );
cycles_pe(1);
$display("Time = %0dns \t : DWidth = 2 DAddr = 0x1000(RAM[1024]): Expected value = 0xef%h Actual Value at DRData: 0x%h" , $time, value_at_1024[23:0], DRData );
cycles_pe(1);
$display("Time = %0dns \t : DWidth = 2 DAddr = 0x1004(RAM[1025]): Expected value = 0xbeef%h Actual Value at DRData: 0x%h" , $time, value_at_1025[15:0], DRData );
cycles_pe(1);
$display("Time = %0dns \t : DWidth = 2 DAddr = 0x1008(RAM[1026]): Expected value = 0xdeadbeef Actual Value at DRData: 0x%h" , $time, DRData );
cycles_pe(1);
$display("Time = %0dns \t : DWidth = 2 DAddr = 0x100c(RAM[1027]): Expected value = 0x%h Actual Value at DRData: 0x%h" , $time, value_at_1027, DRData );
endtask:display_read_results
// Helper tasks
// Memory
function int getMem(int location);
getMem = u_main_mem.RAM[location];
endfunction: getMem
task cycles_pe(int unsigned N = 1);
repeat(N) @(posedge clk);
endtask: cycles_pe
task cycles_ne(int unsigned N = 1);
repeat(N) @(negedge clk);
endtask: cycles_ne
// Load hex file into memory
task loadMem (string fileName);
$display("\nTime = %0dns \t : Loading '%s' into Memory", $time, fileName);
$readmemh(fileName, main_mem_tb.u_main_mem.RAM);
endtask: loadMem
endmodule

View File

@ -0,0 +1,68 @@
// *********************************************************************************************
// Project Version : v1.0
// Project : [BCDC] Microtec Academy Course: Building a RISC-V CPU with SystemVerilog
// -----
// Copyright (c) : 2025 Fraunhofer IIS, Department IDS
// Created : 15.Oct.2025 by Bomin Kim
// Last Modified : 23.Oct.2025 by Bomin Kim [commit 2f8f03d]
// -----
// HISTORY : Date By Comments
// ----------- --------- -------------------------------------------------
// *********************************************************************************************
`timescale 1ns/1ns
module pc_tb ();
// Local Signals
logic[31:0] CurrentPC;
logic[31:0] JumpOrBranchPC;
logic JumpOrBranch;
logic[31:0] NextPC;
logic reset;
logic clk;
// Toplevel instance (DUT)
pc u_pc (
.CurrentPC(CurrentPC),
.JumpOrBranchPC(JumpOrBranchPC),
.JumpOrBranch(JumpOrBranch),
.NextPC(NextPC),
.reset(reset),
.clk(clk)
);
// Clock generation
always #20 clk = ~clk;
// Initialization and run simulation
initial begin
dumpWave("wave.vcd");
clk = 0;
JumpOrBranchPC = 32'h8;
JumpOrBranch = 0;
reset = 0; #100;
reset = 1; #100;
reset = 0; #490;
JumpOrBranch = 1; #60;
JumpOrBranch = 0; #500;
$finish;
end
// NextPC Monitor
initial begin
$monitor("time=%0t clk=%b reset=%b JumpOrBranch=%0h CurrentPC=%0h NextPC=%0h", $time, clk, reset, JumpOrBranch, CurrentPC, NextPC);
end
// Wave Dump Helper Task
task dumpWave(string fileName);
// Open wave file and dump all signals (2D arrays not included)
$display("\nTime = %0dns \t : Opening wave file '%s'", $time, fileName);
$dumpfile(fileName);
$display("Time = %0dns \t : Dumping all %s signals in wave file (2D arrays not included)", $time, "pc_tb");
$dumpvars(0, pc_tb);
endtask: dumpWave
endmodule

View File

@ -0,0 +1,137 @@
// *********************************************************************************************
// Project Version : v1.0
// Project : [BCDC] Microtec Academy Course: Building a RISC-V CPU with SystemVerilog
// -----
// Copyright (c) : 2025 Fraunhofer IIS, Department IDS
// Created : 15.Oct.2025 by Bomin Kim
// Last Modified : 23.Oct.2025 by Bomin Kim [commit 2f8f03d]
// -----
// HISTORY : Date By Comments
// ----------- --------- -------------------------------------------------
// *********************************************************************************************
`timescale 1ns/1ns
module reg_file_tb ();
// Local Signals
logic[4:0] Rs1;
logic[4:0] Rs2;
logic[4:0] Rd;
logic[31:0] RRs1;
logic[31:0] RRs2;
logic[31:0] WRd;
logic WrReg;
logic reset;
logic clk;
// Toplevel instance (DUT)
reg_file u_reg_file (
.Rs1(Rs1),
.Rs2(Rs2),
.Rd(Rd),
.RRs1(RRs1),
.RRs2(RRs2),
.WRd(WRd),
.WrReg(WrReg),
.reset(reset),
.clk(clk)
);
// Clock generation
always #20 clk = ~clk;
// Initialization and run simulation
initial begin
dumpWave("wave.vcd");
// Initialize inputs
clk = 0;
Rs1 = 0; Rs2 = 0; Rd = 0;
WRd = 0; WrReg = 0; // Read
reset = 1;
#50
reset = 0;
#50 // Write 0xDEADBEEF to reg21
Rd = 5'd21;
WrReg = 1; // Write
WRd = 32'hDEADBEEF;
#50; WrReg = 0;
#50
Rs1 = 5'd21; // read reg21 into RRs1
Rs2 = 5'd0;
#50 // Write 0x12345678 to reg5
Rd = 5'd5;
WrReg = 1; // Write
WRd = 32'h12345678;
#50; WrReg = 0;
#50
Rs1 = 5'd5; // read reg10 into RRs1
#50
Rs1 = 5'd0; // read zero register
#50
Rd = 5'd0; // attempt to write 0xCAFEBABE to zero register
WRd = 32'hCAFEBABE;
WrReg = 1; // Write
#50; WrReg = 0;
#50
Rs1 = 5'd5; // Read from reg5
#200
$finish;
end
// Wave Dump Helper Task
task dumpWave(string fileName);
// Open wave file and dump all signals (2D arrays not included)
$display("\nTime = %0dns \t : Opening wave file '%s'", $time, fileName);
$dumpfile(fileName);
$display("Time = %0dns \t : Dumping all %s signals in wave file (2D arrays not included)", $time, "reg_file_tb");
$dumpvars(0, reg_file_tb);
// Dump registers in wave file
$display("\nTime = %0dns \t : Dumping Registers in wave file", $time);
$dumpvars(0, reg_file_tb.u_reg_file.registers[1]);
$dumpvars(0, reg_file_tb.u_reg_file.registers[2]);
$dumpvars(0, reg_file_tb.u_reg_file.registers[3]);
$dumpvars(0, reg_file_tb.u_reg_file.registers[4]);
$dumpvars(0, reg_file_tb.u_reg_file.registers[5]);
$dumpvars(0, reg_file_tb.u_reg_file.registers[6]);
$dumpvars(0, reg_file_tb.u_reg_file.registers[7]);
$dumpvars(0, reg_file_tb.u_reg_file.registers[8]);
$dumpvars(0, reg_file_tb.u_reg_file.registers[9]);
$dumpvars(0, reg_file_tb.u_reg_file.registers[10]);
$dumpvars(0, reg_file_tb.u_reg_file.registers[11]);
$dumpvars(0, reg_file_tb.u_reg_file.registers[12]);
$dumpvars(0, reg_file_tb.u_reg_file.registers[13]);
$dumpvars(0, reg_file_tb.u_reg_file.registers[14]);
$dumpvars(0, reg_file_tb.u_reg_file.registers[15]);
$dumpvars(0, reg_file_tb.u_reg_file.registers[16]);
$dumpvars(0, reg_file_tb.u_reg_file.registers[17]);
$dumpvars(0, reg_file_tb.u_reg_file.registers[18]);
$dumpvars(0, reg_file_tb.u_reg_file.registers[19]);
$dumpvars(0, reg_file_tb.u_reg_file.registers[20]);
$dumpvars(0, reg_file_tb.u_reg_file.registers[21]);
$dumpvars(0, reg_file_tb.u_reg_file.registers[22]);
$dumpvars(0, reg_file_tb.u_reg_file.registers[23]);
$dumpvars(0, reg_file_tb.u_reg_file.registers[24]);
$dumpvars(0, reg_file_tb.u_reg_file.registers[25]);
$dumpvars(0, reg_file_tb.u_reg_file.registers[26]);
$dumpvars(0, reg_file_tb.u_reg_file.registers[27]);
$dumpvars(0, reg_file_tb.u_reg_file.registers[28]);
$dumpvars(0, reg_file_tb.u_reg_file.registers[29]);
$dumpvars(0, reg_file_tb.u_reg_file.registers[30]);
$dumpvars(0, reg_file_tb.u_reg_file.registers[31]);
endtask: dumpWave
endmodule

View File

@ -0,0 +1,79 @@
# OpenFile ./cpu_tb.sv
ls
# alu_tb.sv decoder_tb.sv pc_tb.sv transcript
# cpu_tb.sv main_mem_tb.sv reg_file_tb.sv work
vsim compile.tcl
# vsim compile.tcl
# Start time: 11:01:25 on Nov 28,2025
# ** Error (suppressible): (vsim-19) Failed to access library 'compile' at "compile".
# No such file or directory. (errno = ENOENT)
# Error loading design
# End time: 11:01:25 on Nov 28,2025, Elapsed time: 0:00:00
# Errors: 1, Warnings: 0
ls
# alu_tb.sv decoder_tb.sv pc_tb.sv transcript
# cpu_tb.sv main_mem_tb.sv reg_file_tb.sv work
cd ..
ls
# rtl verilator wave_configs
cd ..
pwd
# C:/PhD/RISC-V Design Course Material/RISC-V Desgin Course - Complete Source Code/riscv_in3days-public/hw
cd ..
ls
# README.md doc hw sw
cd ..
ls
# riscv_in3days-public
cd ..
ls
# Course Introduction & Closing - Public.pdf
# Day 1
# Day 2
# Day 3
# Day 4
# RISC-V Desgin Course - Complete Source Code
# References
cd ..
cd ..
la
# ambiguous command name "la": label labelframe langOf lappend lassign lattice_edition layout
ls
# Drivers Program Files (x86) inetpub
# DumpStack.log Steam_Community_Markt intelFPGA
# Lukas Users intelFPGA_lite
# PhD Windows vfcompat.dll
# ProcLogs appverifUI.dll
# Program Files flexlm
pwd
# C:/
ls
# Drivers Program Files (x86) inetpub
# DumpStack.log Steam_Community_Markt intelFPGA
# Lukas Users intelFPGA_lite
# PhD Windows vfcompat.dll
# ProcLogs appverifUI.dll
# Program Files flexlm
cd PhD
ls
# Code compile.tcl
# RISC-V Design Course Material
cd RISC-V Design Course Material
# wrong # args: should be "cd ?dirName?"
ls
# Code compile.tcl
# RISC-V Design Course Material
ls
# Code compile.tcl
# RISC-V Design Course Material
cd RISC-V Design Course Material
# wrong # args: should be "cd ?dirName?"
ls
# Code compile.tcl
# RISC-V Design Course Material
run compile.tcl
# No Design Loaded!
compile.tcl
# couldn't execute ".\compile.tcl": no such file or directory
run compile.tcl
# No Design Loaded!

View File

@ -0,0 +1,10 @@
m255
K4
z2
13
!s112 1.1
!i10d 8192
!i10e 25
!i10f 100
cModel Technology
dC:/PhD/RISC-V Design Course Material/RISC-V Desgin Course - Complete Source Code/riscv_in3days-public/hw/dv/rtl

Binary file not shown.

Binary file not shown.

View File

Binary file not shown.

View File

@ -0,0 +1,78 @@
export PRJ_ROOT = ../../..
# directroy containig syrinx application programs
SWDIR = $(PRJ_ROOT)/sw/risc-v
DVDIR = $(PRJ_ROOT)/hw/dv
# toplevel syrinx file list
RTL_FLIST = $(PRJ_ROOT)/hw/file_lists/rtl_flist.f
TB_FLIST = $(PRJ_ROOT)/hw/file_lists/tb_flist.f
# if we have multiple file list, we combine them here
FLIST = -f $(RTL_FLIST) -f $(TB_FLIST)
# Default number of simulation cycles
NCYCLES ?= 500
# Standard boot loader and dummy application to be used if nothing else is specified
PROG ?= $(SWDIR)/hello_world/helloWorld.hex
# top module name
TOPMODULE = cpu_harness
# NUmber of GCC parallel threads
COMPILE_THREADS = 32
# Verilator CPU usage, should be adapated to simulation host
SIM_THREADS = 4
TRACE_THREADS = 1
EXTRA_ARGS += --trace-fst --trace-structs --trace-max-array 2048 --trace-threads $(TRACE_THREADS) --threads $(SIM_THREADS)
EXTRA_ARGS += --clk clk --no-timing
# EXTRA_ARGS += -O2
# Used by some code constructs
VDEFS = +define+SIMULATION
all: ./obj_dir/V$(TOPMODULE)
wave: wavedump.fst
@echo
@echo "*** Starting waveform viewer..."
$(WAVE_VIEWER) wavedump.fst -s $(DVDIR)/wave_configs/verilator_wave.surf.ron
run:
@echo
@echo "*** Running simulation..."
@./obj_dir/V$(TOPMODULE) $(NCYCLES) $(PROG)
./obj_dir/V$(TOPMODULE): .stamp.verilate
@echo
@echo "*** Building simulator..."
make -C obj_dir -f V$(TOPMODULE).mk V$(TOPMODULE) -j $(COMPILE_THREADS)
.stamp.verilate: src/tb_$(TOPMODULE).cpp
@echo "*** Generating C++ model..."
$(VERILATOR) --trace $(EXTRA_ARGS) $(VDEFS) -cc $(FLIST) --top-module $(TOPMODULE) --exe src/tb_$(TOPMODULE).cpp
@touch .stamp.verilate
lint:$(VERILOG_SOURCES)
$(VERILATOR) --lint-only $(INCLUDES) $(VERILOG_SOURCES) --top-module $(TOPMODULE)
paths:
@echo $(PRJ_ROOT)/$(APB)
clean:
rm -rf .stamp.*;
rm -rf ./obj_dir
rm -rf wavedump.fst*
rm -rf *.dasm

View File

@ -0,0 +1,148 @@
// *********************************************************************************************
// Description : Verilator simulation harness
// Project Version : v1.0
// Project : [BCDC] Microtec Academy Course: Building a RISC-V CPU with SystemVerilog
// -----
// Copyright (c) : 2025 Fraunhofer IIS, Department IDS
// Created : 12.Aug.2025 by Marcus Bednara
// Last Modified : 15.Oct.2025 by Hussein Elzomor [commit d0452cd]
// -----
// HISTORY : Date By Comments
// ----------- --------- -------------------------------------------------
// 15.Oct.2025 H.Elzomor Renamed file and module from soc_harness to cpu_harness
// 15.Oct.2025 H.Elzomor Added getMem function, setMem task and printMem task
// *********************************************************************************************
timeunit 1ps;
timeprecision 1ps;
module cpu_harness;
// local signals
logic clk,
rst;
logic [7:0] led;
logic [6:0] btn;
// toplevel instance (DUT)
cpu u_cpu (
.led (led),
.btn ({btn[6:1], rst}),
.clk_25mhz (clk)
); // u_cpu
`ifdef VERILATOR
// Declare all functions with DPI-C interface to make them accessible from the C++ testbench
export "DPI-C" task setClk;
export "DPI-C" task enable;
export "DPI-C" task loadRAM;
// export "DPI-C" task dumpSRAM;
export "DPI-C" task setInitial;
export "DPI-C" function getLed;
export "DPI-C" task setBtn;
export "DPI-C" task setReset;
export "DPI-C" function getMem;
export "DPI-C" task setMem;
export "DPI-C" task printMem;
export "DPI-C" function getReg;
export "DPI-C" task printReg;
// Clocking is controlled from C++ testbench
task setClk (input logic val);
clk = val;
endtask: setClk
`else
// If not using verilator, generate clock here
const realtime clk_PERIOD = 1.0ns;
initial begin: clock_driver
clk = '1;
forever begin
#(clk_PERIOD/2.0);
clk <= ~clk;
end
end: clock_driver
task wait_clk_cycles(int unsigned n);
repeat(n) @(posedge clk);
endtask
`endif
// Remaining tasks are identical for Verilator and other simulators
task loadRAM (input string fileName);
$display ("Initializing SRAM memory from %s", fileName);
$readmemh(fileName, u_cpu.theMem.RAM);
endtask: loadRAM
/* Some helper stuff */
task enable(int val);
// nothing to do, we have no fetch enable in this design
endtask: enable
task setInitial();
btn = 7'b0;
rst = 'b0;
endtask: setInitial
function int getLed;
getLed = {24'b0, led};
endfunction: getLed
task setBtn(int val);
btn[6:1] = val[5:0];
endtask: setBtn
task setReset (input int val);
rst = (val==1);
endtask: setReset
function int getMem(int location);
getMem = u_cpu.theMem.RAM[location];
endfunction: getMem
task setMem(int location, int value);
u_cpu.theMem.RAM[location] = value;
endtask: setMem
task printMem (int location, string prog);
case (prog)
"fibonacci" :$display("Value at RAM[%0d]: 0x%h : %0d", location, getMem(location), getMem(location));
"helloWorld" :$display("Value at RAM[%0d]: 0x%h : %s" , location, getMem(location), getMem(location));
default :$display("Value at RAM[%0d]: 0x%h : %0d", location, getMem(location), getMem(location));
endcase
endtask: printMem
function int getReg(int location);
getReg = u_cpu.theRegisters.registers[location];
endfunction: getReg
task printReg (int location, string prog);
case (prog)
"primeNumber" :$display("Time =%5dns \t : Register [%0d] updated - Finding the prime factors of %0d", $time, location, getReg(location));
"primeFactors":$display("Time =%5dns \t : Register [%0d] updated - %0d is a prime factor", $time, location, getReg(location));
default :$display("Time =%5dns \t : Value at Reg[%0d]: 0x%h", $time, location, getReg(location));
endcase
endtask: printReg
endmodule: cpu_harness

View File

@ -0,0 +1,173 @@
// *********************************************************************************************
// Description : Verilator simulation harness
// Project Version : v1.0
// Project : [BCDC] Microtec Academy Course: Building a RISC-V CPU with SystemVerilog
// -----
// Copyright (c) : 2025 Fraunhofer IIS, Department IDS
// Created : 15.Oct.2025 by Hussein Elzomor
// Last Modified : 15.Oct.2025 by Hussein Elzomor
// -----
// HISTORY : Date By Comments
// ----------- --------- -------------------------------------------------
// *********************************************************************************************
timeunit 1ps;
timeprecision 1ps;
module decoder_harness;
// local Parameters
localparam MEM_SIZE = 37;
localparam REG_FILE_SIZE = 32;
// local signals
logic clk;
int counter;
logic[31:0] mem [MEM_SIZE-1:0];
logic[31:0] regFile [REG_FILE_SIZE-1:0];
// PC
logic[31:0] CurrentPC;
logic[31:0] JumpOrBranchPC;
logic JumpOrBranch;
logic[31:0] NextPC;
// Memory
logic[31:0] DAddr;
logic[31:0] WData;
logic[31:0] RData;
logic[31:0] Instruction;
logic WrMem;
logic[1:0] DWidth;
// Register File;
logic[4:0] Rs1;
logic[4:0] Rs2;
logic[4:0] Rd;
logic[31:0] RRs1;
logic[31:0] RRs2;
logic[31:0] WRd;
logic WrReg;
// Protection
logic Illegal;
// toplevel instance (DUT)
decoder u_decoder (
// PC
.CurrentPC(CurrentPC),
.JumpOrBranchPC(JumpOrBranchPC),
.JumpOrBranch(JumpOrBranch),
// Memory
.DAddr(DAddr),
.WData(WData),
.RData(RData),
.Instruction(Instruction),
.WrMem(WrMem),
.DWidth(DWidth),
// Register File
.Rs1(Rs1),
.Rs2(Rs2),
.Rd(Rd),
.RRs1(RRs1),
.RRs2(RRs2),
.WRd(WRd),
.WrReg(WrReg),
// Protection
.Illegal(Illegal)
); // u_decoder
// Special Verilator specific tasks
`ifdef VERILATOR
// Declare all functions with DPI-C interface to make them accessible from the C++ testbench
// Setters
export "DPI-C" task setClk;
export "DPI-C" task enable;
export "DPI-C" task loadRAM;
export "DPI-C" task setInitial;
export "DPI-C" task printInfo;
// Clocking is controlled from C++ testbench
task setClk (input logic val);
clk = val;
endtask: setClk
`else
// If not using verilator, generate clock here
const realtime clk_PERIOD = 1.0ns;
initial begin: clock_driver
clk = '1;
forever begin
#(clk_PERIOD/2.0);
clk <= ~clk;
end
end: clock_driver
task wait_clk_cycles(int unsigned n);
repeat(n) @(posedge clk);
endtask
`endif
// Load a new instruction every cycle
always_ff @(posedge clk) begin: increment_instruction_and_print_info
if (counter < MEM_SIZE) begin
if (counter > 0) printInfo();
Instruction = mem[counter++];
end
end
// Return the value of the RegFile
always_comb begin: reg_file_assignment
RRs1 = regFile[Rs1];
RRs2 = regFile[Rs2];
end
// Remaining tasks are identical for Verilator and other simulators
task enable(int val);
// nothing to do, we have no fetch enable in this design
endtask: enable
// Load data into memory
task loadRAM (input string fileName);
$display ("Initializing SRAM memory from %s", fileName);
$readmemh(fileName, mem);
endtask: loadRAM
// Set initial values
task setInitial();
Instruction = mem[0];
counter = 0;
CurrentPC = 32'hdeadbeef;
RData = 32'hbeefdead;
for(int i=0; i<REG_FILE_SIZE; i++) begin
regFile[i] = i;
end
endtask: setInitial
// Print decoder signals
task printInfo();
$displayh("(cycle %0d) Decoder (I/O) \tDecoder (Internal Signals) \tALU" , counter );
$displayh(" -------------------------- \t--------------------------------------------- \t---------------------" , );
$displayh(" CurrentPC : 0x%h OpCode : 0b%b aluOp : 0b%b" , CurrentPC , u_decoder.theOp , u_decoder.aluOp );
$displayh(" JumpOrBranchPC: 0x%h theFunct3: 0b%b aluNegAr : 0b%b", JumpOrBranchPC, u_decoder.theFunct3, u_decoder.aluNegAr );
$displayh(" JumpOrBranch : 0b%b \ttheFunct7: 0b%b aluBypass: 0b%b", JumpOrBranch , u_decoder.theFunct7, u_decoder.aluBypass);
$displayh(" DAddr : 0x%h i_imm : 0b%b op1 : 0x%h" , DAddr , u_decoder.i_imm , u_decoder.op1 );
$displayh(" WData : 0x%h s_imm : 0b%b op2 : 0x%h" , WData , u_decoder.s_imm , u_decoder.op2 );
$displayh(" RData : 0x%h b_imm : 0b%b result : 0x%h" , RData , u_decoder.b_imm , u_decoder.result );
$displayh(" Instruction : 0x%h u_imm : 0b%b eqFlag : 0b%b" , Instruction , u_decoder.u_imm , u_decoder.eqFlag );
$displayh(" WrMem : 0b%b \tj_imm : 0b%b" , WrMem , u_decoder.j_imm );
$displayh(" DWidth : 0b%b" , DWidth );
$displayh(" Rs1 : %0d " , Rs1 );
$displayh(" Rs2 : %0d " , Rs2 );
$displayh(" Rd : 0x%h" , Rd );
$displayh(" RRs1 : %0d " , RRs1 );
$displayh(" RRs2 : %0d " , RRs2 );
$displayh(" WRd : 0x%h" , WRd );
$displayh(" WrReg : 0b%b" , WrReg );
$displayh(" Illegal : 0b%b" , Illegal );
$displayh("");
endtask: printInfo
endmodule: decoder_harness

View File

@ -0,0 +1,328 @@
// *********************************************************************************************
// Description : Verilator tb
// Project Version : v1.0
// Project : [BCDC] Microtec Academy Course: Building a RISC-V CPU with SystemVerilog
// -----
// Copyright (c) : 2025 Fraunhofer IIS, Department IDS
// Created : 12.Aug.2025 by Marcus Bednara
// Last Modified : 15.Oct.2025 by Hussein Elzomor [commit d0452cd]
// -----
// HISTORY : Date By Comments
// ----------- --------- -------------------------------------------------
// 15.Oct.2025 H.Elzomor Renamed modules from *soc* to *cpu*
// 15.Oct.2025 H.Elzomor Added evalText function
// *********************************************************************************************
using namespace std;
#include <stdlib.h>
#include <iostream>
#include <verilated.h>
#include <verilated_fst_c.h>
#include "Vcpu_harness.h"
#include "Vcpu_harness__Dpi.h"
// only required for accessing model internal memory ressources via the rootp pointer.
// Bad style, better use systemverilog harness with tasks and functions to do that.
// #include "Vcpu_harness___024root.h"
// #include "svdpi.h"
#define SOC_CLK_PERIOD 40
//--------------------------------------------------------------
/// @brief Simulation environment class for the cpu model.
/// Contains a set of high level methods for controlling the model from test environment.
class cpu
{
private:
Vcpu_harness *dut;
VerilatedFstC *mTrace;
vluint64_t T;
uint32_t cpuClkState;
bool running;
string program;
public:
//--------------------------------------------------------------
/// @brief Constructor
cpu (int argc, char** argv)
{
// setup verilator stuff
T = 0;
dut = new Vcpu_harness();
Verilated::commandArgs(argc, argv);
Verilated::traceEverOn(true);
mTrace = new VerilatedFstC;
dut->trace(mTrace, 5);
mTrace->open("wavedump.fst");
cout << "Registered DPI-C functions:\n";
Verilated::scopesDump();
const svScope scope = svGetScopeFromName("TOP.cpu_harness");
assert(scope); // Check for nullptr if scope not found
svSetScope(scope);
running = false;
// initialize all input signals
initSignals();
} // swirl()
//--------------------------------------------------------------
/// @brief simulation tick, advances the simulation time and calls the eval() function of the model on every active clock edge
void tick ()
{
int do_eval;
if (T%SOC_CLK_PERIOD==0) {
dut->setClk(cpuClkState);
cpuClkState = 1-cpuClkState;
do_eval = 1;
}
// Other clock domains must be generated the same way
// if (T%OTHER_CLK_PERIOD==0) {
// dut->setOtherClk(otherClkState);
// otherClkState = 1-otherClkState;
// do_eval = 1;
// }
if (do_eval) {
dut->eval();
// evaluate the LED status in each clock cycle if the CPU is running (i.e., after reset)
if (running && program == "unknown") evalLed();
// evaluate the Fibonacci Series location in stack (starting at 2027) and print value if it has changed
if (running && program == "fibonacci") evalFibonacci();
// evaluate the 'hello world!' location in the DataMem in each clock cycle if the CPU is running (i.e., after reset)
if (running && program == "helloWorld") evalHelloWorld();
// evaluate the Prime Factors location in RegFile (x17) and print value if it has changed
if (running && program == "primeFactors") evalPrimeFactors();
mTrace->dump(T);
do_eval = 0;
}
T++;
} // tick()
//--------------------------------------------------------------
/// @brief Initialize all input signals of the hardware model to a defined value
void initSignals()
{
dut->setInitial();
} // initSignals()
//--------------------------------------------------------------
/// @brief Wait for a number of active edges of clk signal
/// @param numEdges number of rising edges
/// @param active active 1=rising 0=falling edge
void waitClocks (int numEdges=1, int activeEdge=1)
{
int clk_d;
for (int j=0; j<numEdges; ++j) {
while (1) {
clk_d = cpuClkState;
tick();
if (clk_d==1-activeEdge && cpuClkState==activeEdge) break;
}
} // for
} // waitClocks()
//--------------------------------------------------------------
/// @brief Toggle the reset signal active (low)
/// @param numEdges number of clock cyles keeping the reset active
void reset (int numEdges=1)
{
dut->setReset(0); // reset is active low
waitClocks (numEdges);
dut->setReset(1);
} // reset();
//--------------------------------------------------------------
/// @brief load the cpu memory from vmem formatted file
void loadRAM (char* vmemFile)
{
dut->loadRAM(vmemFile);
} // loadRAM()
/// @brief check the LED status and print value if it has change
void evalLed ()
{
static uint8_t oldLedStatus=0xff;
uint8_t currentLedStatus;
currentLedStatus=dut->getLed();
if (currentLedStatus!=oldLedStatus) {
cout << "T=" << T << ": LED=" << std::bitset<8>(currentLedStatus) << endl;
oldLedStatus = currentLedStatus;
}
} // evalLed()
/// @brief check Fibonacci Series location in stack (starting at 2027) and print value if it has changed
void evalFibonacci()
{
int memStartLoc = 2027;
const int memLengthInBytes = 40;
const int memLengthInWords = ceil(memLengthInBytes / 4.0);
static uint32_t oldValue[memLengthInWords];
uint32_t vlaue[memLengthInWords];
bool update = 0;
for (int i = 0; i < memLengthInWords; i++)
{
vlaue[i] = dut->getMem(memStartLoc + i);
if (oldValue[i] != vlaue[i])
update = 1;
}
if (update)
{
cout << endl
<< "T=" << T << ": \t Hex \t Dec" << endl;
for (int i = 0; i < memLengthInWords; i++)
{
dut->printMem(memStartLoc + i, "fibonacci");
oldValue[i] = vlaue[i];
}
cout << endl;
}
} // evalFibonacci()
/// @brief check 'hello world' location in DataMem (starting at 1024) and print value if it has changed
void evalHelloWorld()
{
int memStartLoc = 1024;
const int memLengthInBytes = 13;
const int memLengthInWords = ceil(memLengthInBytes / 4.0);
static uint32_t oldValue[memLengthInWords];
uint32_t vlaue[memLengthInWords];
bool update = 0;
for (int i = 0; i < memLengthInWords; i++)
{
vlaue[i] = dut->getMem(memStartLoc + i);
if (oldValue[i] != vlaue[i])
update = 1;
}
if (update)
{
cout << endl
<< "T=" << T << ": \t Hex \t ASCII" << endl;
for (int i = 0; i < memLengthInWords; i++)
{
dut->printMem(memStartLoc + i, "helloWorld");
oldValue[i] = vlaue[i];
}
cout << endl;
}
} // evalHelloWorld()
/// @brief check Prime Factors location in RegFile (x17) and print value if it has changed
void evalPrimeFactors()
{
// Number to be factorised
int regLoc_Number = 16;
static uint32_t oldValue_Number;
uint32_t value_Number;
value_Number = dut->getReg(regLoc_Number);
if (oldValue_Number != value_Number & value_Number > 1) dut->printReg(regLoc_Number, "primeNumber");
oldValue_Number = value_Number;
// Prime Factors
int regLoc_PrimeFactor = 17;
static uint32_t oldValue_PrimeFactor;
uint32_t value_PrimeFactor;
value_PrimeFactor = dut->getReg(regLoc_PrimeFactor);
if (oldValue_PrimeFactor != value_PrimeFactor & value_PrimeFactor > 1) dut->printReg(regLoc_PrimeFactor, "primeFactors");
oldValue_PrimeFactor = value_PrimeFactor;
} // evalPrimeFactors()
//--------------------------------------------------------------
/// @brief start the DUT
void start()
{
running = true;
dut->enable(1);
} // start()
//--------------------------------------------------------------
/// @brief close the trace file and delete the Verilator object
void stop()
{
dut->enable(0);
mTrace->close();
delete dut;
} // stop()
//--------------------------------------------------------------
/// @brief Set the program name
void setProgram(string prog)
{
if (prog.find("fibonacci") != string::npos) program = "fibonacci";
else if (prog.find("helloWorld") != string::npos) program = "helloWorld";
else if (prog.find("primeFactors") != string::npos) program = "primeFactors";
else program = "unknown";
cout << "program set to " << program << endl;
} // setProgram()
//--------------------------------------------------------------
/// @brief Get the program name
string getProgram()
{
return program;
} // getProgram()
}; // class cpu
int main (int argc, char** argv)
{
uint32_t nCycles;
char* program_path = new char[strlen(argv[2])]();
// Get number of simulation cycles
nCycles = atoi(argv[1]);
// Get the program
program_path = argv[2];
string program_path_str = program_path;
cout << "\nCreating model...\n";
cpu *m = new cpu(argc, argv);
m->loadRAM(program_path);
m->setProgram(program_path_str);
cout << "\nStarting model...\n";
cout << "\nResetting...\n";
m->reset(10);
cout << "Starting CPU...\n" << std::flush;
m->start();
cout << "Running for " << nCycles << " clock cycles...\n\n" << std::flush;
cout << "Printing evaluation for " << m->getProgram() << " program!\n" << std::flush;
m->waitClocks(nCycles);
cout << "\nDone, closing simulation.\n\n\n" << std::flush;
m->stop();
delete m;
exit(EXIT_SUCCESS);
}

View File

@ -0,0 +1,185 @@
// *********************************************************************************************
// Description : Verilator tb
// Project Version : v1.0
// Project : [BCDC] Microtec Academy Course: Building a RISC-V CPU with SystemVerilog
// -----
// Copyright (c) : 2025 Fraunhofer IIS, Department IDS
// Created : 15.Oct.2025 by Hussein Elzomor
// Last Modified : 15.Oct.2025 by Hussein Elzomor
// -----
// HISTORY : Date By Comments
// ----------- --------- -------------------------------------------------
// *********************************************************************************************
using namespace std;
#include <stdlib.h>
#include <iostream>
#include <verilated.h>
#include <verilated_fst_c.h>
#include "Vdecoder_harness.h"
#include "Vdecoder_harness__Dpi.h"
// only required for accessing model internal memory ressources via the rootp pointer.
// Bad style, better use systemverilog harness with tasks and functions to do that.
// #include "Vdecoder_harness___024root.h"
// #include "svdpi.h"
#define DECODER_CLK_PERIOD 40
//--------------------------------------------------------------
/// @brief Simulation environment class for the decoder model.
/// Contains a set of high level methods for controlling the model from test environment.
class decoder
{
private:
Vdecoder_harness *dut;
VerilatedFstC *mTrace;
vluint64_t T;
uint32_t decoderClkState;
bool running;
public:
//--------------------------------------------------------------
/// @brief Constructor
decoder (int argc, char** argv)
{
// setup verilator stuff
T = 0;
dut = new Vdecoder_harness();
Verilated::commandArgs(argc, argv);
Verilated::traceEverOn(true);
mTrace = new VerilatedFstC;
dut->trace(mTrace, 5);
mTrace->open("wavedump.fst");
cout << "Registered DPI-C functions:\n";
Verilated::scopesDump();
const svScope scope = svGetScopeFromName("TOP.decoder_harness");
assert(scope); // Check for nullptr if scope not found
svSetScope(scope);
running = false;
// initialize all input signals
initSignals();
} // swirl()
//--------------------------------------------------------------
/// @brief simulation tick, advances the simulation time and calls the eval() function of the model on every active clock edge
void tick ()
{
int do_eval;
if (T%DECODER_CLK_PERIOD==0) {
dut->setClk(decoderClkState);
decoderClkState = 1-decoderClkState;
do_eval = 1;
}
if (do_eval) {
dut->eval();
mTrace->dump(T);
do_eval = 0;
}
T++;
} // tick()
//--------------------------------------------------------------
/// @brief Initialize all input signals of the hardware model to a defined value
void initSignals()
{
dut->setInitial();
} // initSignals()
//--------------------------------------------------------------
/// @brief Wait for a number of active edges of clk signal
/// @param numEdges number of rising edges
/// @param active active 1=rising 0=falling edge
void waitClocks (int numEdges=1, int activeEdge=1)
{
int clk_d;
for (int j=0; j<numEdges; ++j) {
while (1) {
clk_d = decoderClkState;
tick();
if (clk_d==1-activeEdge && decoderClkState==activeEdge) break;
}
} // for
} // waitClocks()
//--------------------------------------------------------------
/// @brief load the decoder memory from vmem formatted file
void loadRAM(char *vmemFile)
{
dut->loadRAM(vmemFile);
} // loadRAM()
//--------------------------------------------------------------
/// @brief start the DUT
void start()
{
running = true;
dut->enable(1);
} // start()
//--------------------------------------------------------------
/// @brief close the trace file and delete the Verilator object
void stop()
{
dut->enable(0);
mTrace->close();
delete dut;
} // stop()
//--------------------------------------------------------------
/// @brief print signal info
void printInfo()
{
dut->printInfo();
}
}; // class decoder
int main (int argc, char** argv)
{
uint32_t nCycles;
int r;
// Get number of simulation cycles
nCycles = atoi(argv[1]);
cout << "\nCreating model...\n";
decoder *m = new decoder(argc, argv);
m->loadRAM(argv[2]);
cout << "Starting DECODER simulation...\n" << std::flush;
m->start();
cout << "Running for " << nCycles << " clock cycles...\n" << std::flush;
m->waitClocks(nCycles);
m->printInfo();
cout << "\nDone, closing simulation.\n\n\n" << std::flush;
m->stop();
delete m;
exit(EXIT_SUCCESS);
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,19 @@
// *********************************************************************************************
// Project Version : v1.0
// Project : [BCDC] Microtec Academy Course: Building a RISC-V CPU with SystemVerilog
// -----
// Copyright (c) : 2025 Fraunhofer IIS, Department IDS
// Created : 12.Aug.2025 by Marcus Bednara
// Last Modified : 01.Nov.2025 by Hussein Elzomor
// ------
// Notes : All ${}-variables must be provided by shell or Makefile {using export}
// *********************************************************************************************
${PRJ_ROOT}/hw/rtl/pc.sv
${PRJ_ROOT}/hw/rtl/reg_file.sv
${PRJ_ROOT}/hw/rtl/alu.sv
${PRJ_ROOT}/hw/rtl/main_mem.sv
${PRJ_ROOT}/hw/rtl/decoder.sv
${PRJ_ROOT}/hw/rtl/cpu.sv

View File

@ -0,0 +1,24 @@
// *********************************************************************************************
// Project Version : v1.0
// Project : [BCDC] Microtec Academy Course: Building a RISC-V CPU with SystemVerilog
// -----
// Copyright (c) : 2025 Fraunhofer IIS, Department IDS
// Created : 12.Aug.2025 by Marcus Bednara
// Last Modified : 01.Nov.2025 by Hussein Elzomor
// ------
// Notes : All ${}-variables must be provided by shell or Makefile {using export}
// *********************************************************************************************
// Used with verilator
${PRJ_ROOT}/hw/dv/verilator/rtl/decoder_harness.sv
${PRJ_ROOT}/hw/dv/verilator/rtl/cpu_harness.sv
// Used with other compilers and simulators (eg. Icarus)
// ${PRJ_ROOT}/hw/dv/rtl/pc_tb.sv
// ${PRJ_ROOT}/hw/dv/rtl/reg_file_tb.sv
// ${PRJ_ROOT}/hw/dv/rtl/alu_tb.sv
// ${PRJ_ROOT}/hw/dv/rtl/main_mem_tb.sv
// ${PRJ_ROOT}/hw/dv/rtl/decoder_tb.sv
// ${PRJ_ROOT}/hw/dv/rtl/cpu_tb.sv

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
riscv_rtl/hw/rtl/.pc.sv.swp Normal file

Binary file not shown.

View File

@ -0,0 +1,60 @@
module MemGen_32_11 #(
parameter data_width = 32,
parameter addr_width = 11,
parameter mem_depth = 2048
)(
input chip_en,
input clock,
input [addr_width-1:0]addr,
output reg [data_width-1:0]rd_data,
input rd_en,
input wr_en,
input [data_width-1:0]wr_data
);
// Bank selection: 1 bit selects one of 2 banks
reg [1:0] mem_sel ;
wire [31:0] mem_data_out [1:0];
// Address decoder and output multiplexer
always @(*)
begin
if ( chip_en == 1'b1 )
case (addr[10])
1'b0 : begin mem_sel = 2'b01; rd_data = mem_data_out[0]; end
1'b1 : begin mem_sel = 2'b10; rd_data = mem_data_out[1]; end
endcase
else
begin
mem_sel = 2'b00;
rd_data = 32'h00000000;
end
end
genvar i;
// Instantiate 2 banks, each with 2 halves (low + high 16 bits)
generate
for (i = 0; i < 2; i = i + 1) begin
MemGen_16_10 U_lo (
.chip_en(mem_sel[i]),
.clock(clock),
.addr(addr[9:0]),
.rd_en(rd_en),
.rd_data(mem_data_out[i][15:0]),
.wr_en(wr_en),
.wr_data(wr_data[15:0])
);
MemGen_16_10 U_hi (
.chip_en(mem_sel[i]),
.clock(clock),
.addr(addr[9:0]),
.rd_en(rd_en),
.rd_data(mem_data_out[i][31:16]),
.wr_en(wr_en),
.wr_data(wr_data[31:16])
);
end
endgenerate
endmodule

52
riscv_rtl/hw/rtl/alu.sv Normal file
View File

@ -0,0 +1,52 @@
// *********************************************************************************************
// Project Version : v1.0
// Project : [BCDC] Microtec Academy Course: Building a RISC-V CPU with SystemVerilog
// -----
// Copyright (c) : 2025 Fraunhofer IIS, Department IDS
// Created : 12.Jun.2025 by Lund University [commit 5b1e415]
// Last Modified : 23.Oct.2025 by Bomin Kim [commit 2f8f03d]
// -----
// HISTORY : Date By Comments
// ----------- --------- -------------------------------------------------
// 15.Oct.2025 Bomin Kim Refactored ALU logic from decoder into this file
// *********************************************************************************************
module alu (
input logic[2:0] aluOp,
input logic aluNegAr,
input logic aluBypass,
input logic[31:0] op1,
input logic[31:0] op2,
output logic[31:0] result,
output logic eqFlag
);
// Local parameters; list of aluOp
localparam logic[2:0] f3add = 3'b000;
localparam logic[2:0] f3sl = 3'b001;
localparam logic[2:0] f3slt = 3'b010;
localparam logic[2:0] f3sltU = 3'b011;
localparam logic[2:0] f3xor = 3'b100;
localparam logic[2:0] f3sr = 3'b101;
localparam logic[2:0] f3or = 3'b110;
localparam logic[2:0] f3and = 3'b111;
// ALU logic
always_comb begin : ALU
eqFlag = op1 == op2;
if (aluBypass) result = op1;
else case(aluOp)
f3add: result = aluNegAr ? op1 - op2 : op1 + op2;
f3sl: result = op1 << op2[4:0];
f3slt: result = {31'b0, $signed(op1) < $signed(op2)};
f3sltU: result = {31'b0, $unsigned(op1) < $unsigned(op2)};
f3xor: result = op1 ^ op2;
f3sr: result = aluNegAr ? $signed(op1) >>> op2[4:0] : $signed(op1) >> op2[4:0];
f3or: result = op1 | op2;
f3and: result = op1 & op2;
endcase
end
endmodule

135
riscv_rtl/hw/rtl/cpu.sv Normal file
View File

@ -0,0 +1,135 @@
// *********************************************************************************************
// Project Version : v1.0
// Project : [BCDC] Microtec Academy Course: Building a RISC-V CPU with SystemVerilog
// -----
// Copyright (c) : 2025 Fraunhofer IIS, Department IDS
// Created : 12.Jun.2025 by Lund University [commit 5b1e415]
// Last Modified : 23.Oct.2025 by Hussein Elzomor [commit 2f8f03d]
// -----
// HISTORY : Date By Comments
// ----------- --------- -------------------------------------------------
// 15.Oct.2025 H.Elzomor Renamed file and module from soc to cpu
// 15.Oct.2025 H.Elzomor Added an initial condition for clk_12p5
// *********************************************************************************************
module cpu (
output logic[7:0] led,
input logic[6:0] btn,
input logic clk_25mhz,
input logic scan_mode //for defining if we are in scan or in functional mode
);
// Local Signals
// Clock & Reset
logic clk;
logic clk12p5;
logic reset;
// PC
logic[31:0] CurrentPC;
logic[31:0] JumpOrBranchPC;
logic JumpOrBranch;
logic[31:0] NextPC;
// Memory
logic[31:0] DAddr;
logic[31:0] WData;
logic[31:0] RData;
logic[31:0] Instruction;
logic WrMem;
logic[1:0] DWidth;
// Register File;
logic[4:0] Rs1;
logic[4:0] Rs2;
logic[4:0] Rd;
logic[31:0] RRs1;
logic[31:0] RRs2;
logic[31:0] WRd;
logic WrReg;
// Protection
logic Illegal;
// Logic
// Clock (12.5MHz)
//assign clk = scan_mode ? clk_25mhz : clk12p5;
assign clk = clk_25mhz;
// always_ff @(posedge clk_25mhz) begin
// if (reset)
// clk12p5 <= 1'b0;
// else if (!scan_mode)
// clk12p5 <= ~clk12p5;
// end
// Reset
assign reset = ~btn[0];
// LED
assign led[0] = Illegal;
assign led[1] = WrMem;
assign led[7:2] = NextPC[7:2];
// Module Instantiation
// Decoder
decoder theDecoder (
// PC
.CurrentPC(CurrentPC),
.JumpOrBranchPC(JumpOrBranchPC),
.JumpOrBranch(JumpOrBranch),
// Memory
.DAddr(DAddr),
.WData(WData),
.RData(RData),
.Instruction(Instruction),
.WrMem(WrMem),
.DWidth(DWidth),
// Register File
.Rs1(Rs1),
.Rs2(Rs2),
.Rd(Rd),
.RRs1(RRs1),
.RRs2(RRs2),
.WRd(WRd),
.WrReg(WrReg),
// Protection
.Illegal(Illegal)
);
// Register File
reg_file theRegisters (
.Rs1(Rs1),
.Rs2(Rs2),
.Rd(Rd),
.RRs1(RRs1),
.RRs2(RRs2),
.WRd(WRd),
.WrReg(WrReg),
.reset(reset),
.clk(clk)
);
// PC
pc thePC (
.CurrentPC(CurrentPC),
.JumpOrBranchPC(JumpOrBranchPC),
.JumpOrBranch(JumpOrBranch),
.NextPC(NextPC),
.reset(reset),
.clk(clk)
);
// Main Memory
main_mem #(
.MEM_INIT_FILE("") // Memory loading driven from the TB
) theMem (
.DAddr(DAddr),
.IAddr(NextPC),
.DWData(WData),
.DRData(RData),
.IRData(Instruction),
.DWE(WrMem),
.DWidth(DWidth),
.reset(reset),
.clk(clk)
);
endmodule

231
riscv_rtl/hw/rtl/decoder.sv Normal file
View File

@ -0,0 +1,231 @@
// *********************************************************************************************
// Project Version : v1.0
// Project : [BCDC] Microtec Academy Course: Building a RISC-V CPU with SystemVerilog
// -----
// Copyright (c) : 2025 Fraunhofer IIS, Department IDS
// Created : 12.Jun.2025 by Lund University [commit 5b1e415]
// Last Modified : 23.Oct.2025 by Hussein Elzomor [commit 2f8f03d]
// -----
// HISTORY : Date By Comments
// ----------- --------- -------------------------------------------------
// 15.Oct.2025 H.Elzomor Moved PC and ALU logic to their respective files
// 15.Oct.2025 H.Elzomor Absorbed the branching logic into the decoder logic
// *********************************************************************************************
module decoder (
// PC
input logic[31:0] CurrentPC,
output logic[31:0] JumpOrBranchPC,
output logic JumpOrBranch,
// Memory
output logic[31:0] DAddr,
output logic[31:0] WData,
input logic[31:0] RData,
input logic[31:0] Instruction,
output logic WrMem,
output logic[1:0] DWidth,
// Register File
output logic[4:0] Rs1,
output logic[4:0] Rs2,
output logic[4:0] Rd,
input logic[31:0] RRs1,
input logic[31:0] RRs2,
output logic[31:0] WRd,
output logic WrReg,
// Protection
output logic Illegal
);
// Local Parameters
// OpCode: set a local parameter for each operation
localparam logic[6:0] opLd = 7'b0000011;
localparam logic[6:0] opAluImm = 7'b0010011;
localparam logic[6:0] opUpPC = 7'b0010111;
localparam logic[6:0] opSt = 7'b0100011;
localparam logic[6:0] opAlu = 7'b0110011;
localparam logic[6:0] opUpImm = 7'b0110111;
localparam logic[6:0] opBranch = 7'b1100011;
localparam logic[6:0] opJALR = 7'b1100111;
localparam logic[6:0] opJAL = 7'b1101111;
// Func7: set a local parameter for each function 7
localparam logic[6:0] f7neg = 7'b0100000;
// Func3: set a local parameter for each function 3
// Load/Store
localparam logic[2:0] f3byte = 3'b000;
localparam logic[2:0] f3half = 3'b001;
localparam logic[2:0] f3word = 3'b010;
localparam logic[2:0] f3byteU = 3'b100;
localparam logic[2:0] f3halfU = 3'b101;
// ALU
localparam logic[2:0] f3add = 3'b000;
localparam logic[2:0] f3sl = 3'b001;
localparam logic[2:0] f3slt = 3'b010;
localparam logic[2:0] f3sltU = 3'b011;
localparam logic[2:0] f3xor = 3'b100;
localparam logic[2:0] f3sr = 3'b101;
localparam logic[2:0] f3or = 3'b110;
localparam logic[2:0] f3and = 3'b111;
// Branch
localparam logic[2:0] f3beq = 3'b000;
localparam logic[2:0] f3bne = 3'b001;
localparam logic[2:0] f3blt = 3'b100;
localparam logic[2:0] f3bge = 3'b101;
localparam logic[2:0] f3bltU = 3'b110;
localparam logic[2:0] f3bgeU = 3'b111;
// Local Signals
// Instruction breakdown (excluding I/O)
logic[6:0] theOp;
logic[2:0] theFunct3;
logic[6:0] theFunct7;
logic[31:0] i_imm;
logic[31:0] s_imm;
logic[31:0] b_imm;
logic[31:0] u_imm;
logic[31:0] j_imm;
// ALU
logic[2:0] aluOp;
logic aluNegAr;
logic aluBypass;
logic[31:0] op1;
logic[31:0] op2;
logic[31:0] result;
logic eqFlag;
// Instruction breakdown: assign values
// OpCode and functions 3/7
assign theOp = Instruction[6:0];
assign theFunct3 = Instruction[14:12];
assign theFunct7 = Instruction[31:25];
// Registers
assign Rs1 = Instruction[19:15];
assign Rs2 = Instruction[24:20];
assign Rd = Instruction[11:7];
// Immediates
always_comb begin : Immediate_Generator
i_imm = {{21{Instruction[31]}}, Instruction[30:20]};
s_imm = {{21{Instruction[31]}}, Instruction[30:25], Instruction[11:7]};
b_imm = {{20{Instruction[31]}}, Instruction[7], Instruction[30:25], Instruction[11:8], 1'b0};
u_imm = {Instruction[31:12], 12'b0};
j_imm = {{12{Instruction[31]}}, Instruction[19:12], Instruction[20], Instruction[30:21], 1'b0};
end
// Decoder Logic
always_comb begin : Main_Decoder
// Factored port/signal values
JumpOrBranch = '0;
JumpOrBranchPC = '0;
DAddr = '0;
WData = RRs2;
WrMem = '0;
DWidth = f3word[1:0];
WrReg = '1;
Illegal = '0;
aluOp = theFunct3;
aluNegAr = '0;
aluBypass = '0;
op1 = RRs1;
op2 = RRs2;
// OpCode Cases
case(theOp)
opLd: begin
DAddr = RRs1 + i_imm;
DWidth = theFunct3[1:0];
aluBypass = '1;
op1 = RData;
case(theFunct3)
f3byte: op1[31:8] = {24{RData[7]}};
f3byteU: op1[31:8] = {24{1'b0}};
f3half: op1[31:16] = {16{RData[15]}};
f3halfU: op1[31:16] = {16{1'b0}};
f3word: ;
default: begin
Illegal = '1;
WrReg = '0;
JumpOrBranch = '1;
JumpOrBranchPC = CurrentPC;
end
endcase
end
opAluImm: begin
op2 = i_imm;
aluOp = theFunct3;
aluNegAr = (theFunct7 == f7neg) & (theFunct3 == f3sr);
end
opUpPC: begin
op1 = u_imm;
op2 = CurrentPC;
aluOp = f3add;
end
opSt: begin
WrReg = '0;
WrMem = '1;
DAddr = RRs1 + s_imm;
DWidth = theFunct3[1:0];
end
opAlu: begin
aluOp = theFunct3;
aluNegAr = (theFunct7 == f7neg) & ((theFunct3 == f3add) | (theFunct3 == f3sr));
end
opUpImm: begin
op1 = u_imm;
aluBypass = '1;
end
opBranch: begin
WrReg = '0;
JumpOrBranchPC = CurrentPC + b_imm;
aluOp = f3slt;
case(theFunct3)
f3beq : begin JumpOrBranch = ( eqFlag)? '1 : '0; end
f3bne : begin JumpOrBranch = (~eqFlag)? '1 : '0; end
f3blt : begin JumpOrBranch = ( result[0])? '1 : '0; end
f3bge : begin JumpOrBranch = (~result[0])? '1 : '0; end
f3bltU: begin aluOp = f3sltU; JumpOrBranch = ( result[0])? '1 : '0; end
f3bgeU: begin aluOp = f3sltU; JumpOrBranch = (~result[0])? '1 : '0; end
default: begin
Illegal = '1;
JumpOrBranch = '1;
JumpOrBranchPC = CurrentPC;
end
endcase
end
opJALR: begin
JumpOrBranch = '1;
JumpOrBranchPC = (RRs1 + i_imm) & 32'hFFFFFFFE;
op1 = CurrentPC;
op2 = 4;
aluOp = f3add;
end
opJAL: begin
JumpOrBranch = '1;
JumpOrBranchPC = CurrentPC + j_imm;
op1 = CurrentPC;
op2 = 4;
aluOp = f3add;
end
default: begin
Illegal = '1;
WrReg = '0;
JumpOrBranch = '1;
JumpOrBranchPC = CurrentPC;
end
endcase
end
// ALU module instantiation
alu theALU (
.aluOp(aluOp),
.aluNegAr(aluNegAr),
.aluBypass(aluBypass),
.op1(op1),
.op2(op2),
.result(result),
.eqFlag(eqFlag)
);
assign WRd = result;
endmodule

View File

@ -0,0 +1,117 @@
// *********************************************************************************************
// Project Version : v1.0
// Project : [BCDC] Microtec Academy Course: Building a RISC-V CPU with SystemVerilog
// -----
// Copyright (c) : 2025 Fraunhofer IIS, Department IDS
// Created : 12.Jun.2025 by Lund University [commit 5b1e415]
// Last Modified : 23.Oct.2025 by Aliakbar Merchant [commit 2f8f03d]
// -----
// HISTORY : Date By Comments
// ----------- ---------- -------------------------------------------------
// 22.Oct.2025 A.Merchant Added reset handling condition for Instr. read logic
// 22.Oct.2025 A.Merchant Added reset handling condition for data write logic
// *********************************************************************************************
module main_mem #(
parameter int ABits = 3 // Number of address bits
//parameter string MEM_INIT_FILE = "" // Optional memory initializations file
)(
input logic clk, // Clock
input logic reset, // Active high sync reset
input logic[31:0] DAddr, // Data Address
input logic[31:0] IAddr, // Instruction Address
input logic[31:0] DWData, // Data to write
output logic[31:0] DRData, // Data read
output logic[31:0] IRData, // Instruction read
input logic DWE, // Data write enable, 1=Write
input logic [1:0] DWidth // Access width (byte, half word, word)
);
// Local Parameter
localparam logic[1:0] _byte = 2'b00; // byte: 8 bits
localparam logic[1:0] _half = 2'b01; // half: 16 bits
localparam logic[1:0] _word = 2'b10; // word: 32 bits
// Local Signals
logic[31:0] RAM[2**(ABits-2)-1:0]; // Memory array 8KB(8192): ignores lowest 2 bits as 32bit-word
logic[31:0] drTmp; // Temporary register to hold the data read from RAM.
// memory initilizations
// initial begin
//if (MEM_INIT_FILE != "") begin
// $readmemh(MEM_INIT_FILE, RAM);
//end
// end
//---------------------------------------------------------------------------//
//--------------------------- DATA WRITE LOGIC ---------------------------//
//---------------------------------------------------------------------------//
always_ff @(negedge clk) begin
if (!reset) begin
if (DWE) begin
// RAM[DAddr[(ABits-1):2]] <= DWData;
case (DWidth)
_word:
RAM[DAddr[(ABits-1):2]] <= DWData;
_half:
case (DAddr[1])
1'b0: RAM[DAddr[(ABits-1):2]][31:16] <= DWData[15:0];
1'b1: RAM[DAddr[(ABits-1):2]][15: 0] <= DWData[15:0];
endcase
_byte:
case (DAddr[1:0])
2'b00: RAM[DAddr[(ABits-1):2]][31:24] <= DWData[7:0];
2'b01: RAM[DAddr[(ABits-1):2]][23:16] <= DWData[7:0];
2'b10: RAM[DAddr[(ABits-1):2]][15: 8] <= DWData[7:0];
2'b11: RAM[DAddr[(ABits-1):2]][ 7: 0] <= DWData[7:0];
endcase
default: ;
endcase
end
end
end
//---------------------------------------------------------------------------//
//--------------------------- DATA READ LOGIC ----------------------------//
//---------------------------------------------------------------------------//
always_ff @(negedge clk) begin
drTmp <= RAM[DAddr[(ABits-1):2]];
end
always_comb begin
case (DWidth)
_word:
DRData = drTmp;
_half:
case (DAddr[1])
1'b0: DRData = {16'b0, drTmp[31:16]};
1'b1: DRData = {16'b0, drTmp[15: 0]};
endcase
_byte:
case (DAddr[1:0])
2'b00: DRData = {24'b0, drTmp[31:24]};
2'b01: DRData = {24'b0, drTmp[23:16]};
2'b10: DRData = {24'b0, drTmp[15: 8]};
2'b11: DRData = {24'b0, drTmp[ 7: 0]};
endcase
default: ;
endcase
end
//---------------------------------------------------------------------------//
//----------------------- INSTRUCTION READ LOGIC -------------------------//
//---------------------------------------------------------------------------//
//
//fetch intrcution from memory into IRData
always_ff @(posedge clk) begin
if (reset)
IRData <= RAM[0];
else
IRData <= RAM[IAddr[(ABits-1):2]];
end
endmodule

37
riscv_rtl/hw/rtl/pc.sv Normal file
View File

@ -0,0 +1,37 @@
// *********************************************************************************************
// Project Version : v1.0
// Project : [BCDC] Microtec Academy Course: Building a RISC-V CPU with SystemVerilog
// -----
// Copyright (c) : 2025 Fraunhofer IIS, Department IDS
// Created : 12.Jun.2025 by Lund University [commit 5b1e415]
// Last Modified : 23.Oct.2025 by Bomin Kim [commit 2f8f03d]
// -----
// HISTORY : Date By Comments
// ----------- --------- -------------------------------------------------
// 15.Oct.2025 Bomin Kim Moved NextPC logic from decoder into PC
// 15.Oct.2025 Bomin Kim Removed reset condition from combinational logic
// *********************************************************************************************
module pc (
output logic[31:0] CurrentPC,
input logic[31:0] JumpOrBranchPC,
input logic JumpOrBranch,
output logic[31:0] NextPC,
input logic reset,
input logic clk
);
// NextPC logic; next-state function
always_comb begin : Next_PC
if (JumpOrBranch) NextPC = JumpOrBranchPC;
else NextPC = CurrentPC + 4;
end
// CurrentPC logic; state register
always_ff @(posedge clk) begin
if (reset) CurrentPC <= '0;
else CurrentPC <= NextPC;
end
endmodule

View File

@ -0,0 +1,44 @@
// *********************************************************************************************
// Project Version : v1.0
// Project : [BCDC] Microtec Academy Course: Building a RISC-V CPU with SystemVerilog
// -----
// Copyright (c) : 2025 Fraunhofer IIS, Department IDS
// Created : 12.Jun.2025 by Lund University [commit 5b1e415]
// Last Modified : 23.Oct.2025 by Bomin Kim [commit 2f8f03d]
// -----
// HISTORY : Date By Comments
// ----------- --------- -------------------------------------------------
// 15.Oct.2025 Bomin Kim Added reset handling condition
// *********************************************************************************************
module reg_file (
input logic[4:0] Rs1,
input logic[4:0] Rs2,
input logic[4:0] Rd,
output logic[31:0] RRs1,
output logic[31:0] RRs2,
input logic[31:0] WRd,
input logic WrReg,
input logic reset,
input logic clk
);
// Define the registers array
logic[31:0] registers[31:1];
// Register file reading
assign RRs1 = Rs1 == 0 ? '0 : registers[Rs1];
assign RRs2 = Rs2 == 0 ? '0 : registers[Rs2];
// Register file writing
always_ff @(posedge clk) begin
if (reset) begin
for (int i=1; i<32; i++)
registers[i] <= '0;
end else begin
if (WrReg & Rd != 0) registers[Rd] <= WRd;
end
end
endmodule

18
riscv_rtl/rtl_flist.f Normal file
View File

@ -0,0 +1,18 @@
// *********************************************************************************************
// Project Version : v1.0
// Project : [BCDC] Microtec Academy Course: Building a RISC-V CPU with SystemVerilog
// -----
// Copyright (c) : 2025 Fraunhofer IIS, Department IDS
// Created : 12.Aug.2025 by Marcus Bednara
// Last Modified : 01.Nov.2025 by Hussein Elzomor
// ------
// Notes : All ${}-variables must be provided by shell or Makefile {using export}
// *********************************************************************************************
hw/rtl/pc.sv
hw/rtl/reg_file.sv
hw/rtl/alu.sv
hw/rtl/MemGen_32_11.sv
hw/rtl/main_mem.sv
hw/rtl/decoder.sv
hw/rtl/cpu.sv

17
riscv_rtl/run.do Normal file
View File

@ -0,0 +1,17 @@
if [file exists "work"] {vdel -all}
vlib work
# Comment out either the SystemVerilog or VHDL DUT.
# There can be only one!
# VHDL DUT
#vcom -f rtl_flist.f
vlog -sv dummz_memgen_16.sv
# SystemVerilog DUT
vlog -sv -lint -pedanticerrors -f rtl_flist.f
vopt work.cpu -o cpu_opt +acc -pedanticerrors
quit

View File

@ -0,0 +1,37 @@
001080B3
40210133
0031C1B3
00426233
0052F2B3
00631333
0073D3B3
40845433
0094A4B3
00A53533
00B58593
00C64613
00D6E693
00E77713
00F79793
01085813
4118D893
01292913
0139B993
014A0A03
015A9A83
016B2B03
017BCB83
018C5C03
019C8CA3
01AD1D23
01BDADA3
01CE0E63
01CE1E63
01EF4F63
01EF5F63
00216163
00217163
0040026F
00420267
000052B7
00006317

View File

@ -0,0 +1,65 @@
// *********************************************************************************************
// Description : Assembly instructions for decoder test
// Project Version : v1.0
// Project : [BCDC] Microtec Academy Course: Building a RISC-V CPU with SystemVerilog
// -----
// Copyright (c) : 2025 Fraunhofer IIS, Department IDS
// Created : 15.Oct.2025 by Hussein Elzomor
// Last Modified : 15.Oct.2025 by Hussein Elzomor
// -----
// HISTORY : Date By Comments
// ----------- --------- -------------------------------------------------
// *********************************************************************************************
# Iteration over all implemented instructions to test decoder
# R-instruction # Hex # bin f7 rs2 rs1 f3 rd opcode
add x1 , x1 , x1 # 0x001080B3 # 0b 0000000 00001 00001 000 00001 0110011
sub x2 , x2 , x2 # 0x40210133 # 0b 0100000 00010 00010 000 00010 0110011
xor x3 , x3 , x3 # 0x0031C1B3 # 0b 0000000 00011 00011 100 00011 0110011
or x4 , x4 , x4 # 0x00426233 # 0b 0000000 00100 00100 110 00100 0110011
and x5 , x5 , x5 # 0x0052F2B3 # 0b 0000000 00101 00101 111 00101 0110011
sll x6 , x6 , x6 # 0x00631333 # 0b 0000000 00110 00110 001 00110 0110011
srl x7 , x7 , x7 # 0x0073D3B3 # 0b 0000000 00111 00111 101 00111 0110011
sra x8 , x8 , x8 # 0x40845433 # 0b 0100000 01000 01000 101 01000 0110011
slt x9 , x9 , x9 # 0x0094A4B3 # 0b 0000000 01001 01001 010 01001 0110011
sltu x10, x10, x10 # 0x00A53533 # 0b 0000000 01010 01010 011 01010 0110011
# I-instruction # Hex # bin imm rs1 f3 rd opcode
addi x11, x11, 11 # 0x00B58593 # 0b 000000001011 01011 000 01011 0010011
xori x12, x12, 12 # 0x00C64613 # 0b 000000001100 01100 100 01100 0010011
ori x13, x13, 13 # 0x00D6E693 # 0b 000000001101 01101 110 01101 0010011
andi x14, x14, 14 # 0x00E77713 # 0b 000000001110 01110 111 01110 0010011
slli x15, x15, 15 # 0x00F79793 # 0b 000000001111 01111 001 01111 0010011
srli x16, x16, 16 # 0x01085813 # 0b 000000010000 10000 101 10000 0010011
srai x17, x17, 17 # 0x4118D893 # 0b 010000010001 10001 101 10001 0010011
slti x18, x18, 18 # 0x01292913 # 0b 000000010010 10010 010 10010 0010011
sltiu x19, x19, 19 # 0x0139B993 # 0b 000000010011 10011 011 10011 0010011
lb x20, 20(x20) # 0x014A0A03 # 0b 000000010100 10100 000 10100 0000011
lh x21, 21(x21) # 0x015A9A83 # 0b 000000010101 10101 001 10101 0000011
lw x22, 22(x22) # 0x016B2B03 # 0b 000000010110 10110 010 10110 0000011
lbu x23, 23(x23) # 0x017BCB83 # 0b 000000010111 10111 100 10111 0000011
lhu x24, 24(x24) # 0x018C5C03 # 0b 000000011000 11000 101 11000 0000011
# S-instruction # Hex # bin imm rs2 rs1 f3 imm opcode
sb x25, 25(x25) # 0x019C8CA3 # 0b 0000000 11001 11001 000 11001 0100011
sh x26, 26(x26) # 0x01AD1D23 # 0b 0000000 11010 11010 001 11010 0100011
sw x27, 27(x27) # 0x01BDADA3 # 0b 0000000 11011 11011 010 11011 0100011
# B-instruction # Hex # bin imm rs2 rs1 f3 imm opcode
beq x28, x28, 28 # 0x01CE0E63 # 0b 0000000 11100 11100 000 11100 1100011
bne x28, x28, 28 # 0x01CE1E63 # 0b 0000000 11100 11100 001 11100 1100011
blt x30, x30, 30 # 0x01EF4F63 # 0b 0000000 11110 11110 100 11110 1100011
bge x30, x30, 30 # 0x01EF5F63 # 0b 0000000 11110 11110 101 11110 1100011
bltu x2 , x2 , 2 # 0x00216163 # 0b 0000000 00010 00010 110 00010 1100011
bgeu x2 , x2 , 2 # 0x00217163 # 0b 0000000 00010 00010 111 00010 1100011
# J-instruction # Hex # bin f7 rd opcode
jal x4 , 4 # 0x0040026F # 0b 00000000010000000000 00100 1101111
jalr x4 , x4, 4 # 0x00420267 # 0b 00000000010000100000 00100 1100111
# U-instruction # Hex # bin f7 rd opcode
lui x5 , 5 # 0x000052B7 # 0b 00000000000000000101 00101 0110111
auipc x6 , 6 # 0x00006317 # 0b 00000000000000000110 00110 0010111

View File

@ -0,0 +1,29 @@
// *********************************************************************************************
// Description : C Program to calculate the Fibonacci numbers until a given number of terms
// File : v1.0
// Project Version : [BCDC] Microtec Academy Course: Building a RISC-V CPU with SystemVerilog
// Project : RISCV_IN3DAYS
// -----
// Copyright (c) : 2025 Fraunhofer IIS, Department IDS
// Created : 13.Oct.2025, 11:00:00 by Fuad Mammadzada (fuad.mammadzada@fau.de)
// -----
// HISTORY : Date By Comments
// ----------- --------- -------------------------------------------------
// *********************************************************************************************
asm(".global _start, halt; _start: lui sp 2; addi sp sp -4; jal x0 main");
int main() {
int n = 10; // count of Fibonacci numbers to be evaluated
int fib_number[20];
fib_number[0] = 0;
fib_number[1] = 1;
for (int i = 2; i < n; i++) {
fib_number[i] = fib_number[i-1] + fib_number[i-2];
}
asm("j halt");
}

Some files were not shown because too many files have changed in this diff Show More