Skip to content

Commit beda2ac

Browse files
authored
Merge pull request #1 from dark-tree/verilog-project-setup
core: Project setup and configuration, with a basic flip-flop example.
2 parents 94b2c47 + 3a3f63a commit beda2ac

File tree

10 files changed

+546
-0
lines changed

10 files changed

+546
-0
lines changed

README.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
# microarch
2+
3+
**microarch** is a minimalistic, 8-bit, extensible, RISC, Harvard, load-store computer architecture intended for small low-power (or power constrained) microcontrollers.
4+
5+
It offers 8-bit data address space and up to 16-bit instruction address space, allowing for up to 256 bytes of directly addressable data memory and up to 64kB of directly addressable program memory.
6+
7+
The microarch processor has 8 registers available to the programmer with a powerful, unique register addressing system.
8+
9+
10+
##### Navigation
11+
12+
- ```README.md``` - You are here.
13+
- ```LICENSE``` - License in place for the project.
14+
- ```microarch-ISA.pdf``` - Full ISA documentation for the architecture.
15+
- ```base-core/``` - WORK IN PROGRESS: A Verilog design of an example MicroArch core, with a Verilator/SystemC testbench (this part of the project has its own readme file).

base-core/.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
obj_dir/*
2+
tracedump/*

base-core/Makefile

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
2+
VERILOG_DESIGN_FILES = \
3+
design/top.v \
4+
design/flip_flop.v
5+
6+
default: run
7+
8+
clean:
9+
@echo "-- Cleaning build directories --"
10+
rm -rf obj_dir/*
11+
rm -rf tracedump/*
12+
13+
waves:
14+
@echo "Launching GTK waveform visualizer"
15+
flatpak run io.github.gtkwave.GTKWave
16+
17+
run: build_main
18+
@echo "-- Running the microarch BaseCore SystemC main testbanch simulation --"
19+
@echo "Running the simulation..."
20+
obj_dir/Vtop +trace
21+
@echo "Launching GTK waveform visualizer"
22+
flatpak run io.github.gtkwave.GTKWave tracedump/traces.fst
23+
24+
unit_tests: build_tests
25+
@echo "-- Running the microarch BaseCore SystemC unit tests --"
26+
@echo "Running the simulation..."
27+
obj_dir/Vtop +trace
28+
29+
build_main: verilate_main
30+
@echo "-- Building microarch BaseCore testbench and verilated design --"
31+
@echo "Building from generated Makefile..."
32+
make -j -C obj_dir -f Vtop.mk
33+
34+
build_tests: verilate_tests
35+
@echo "-- Building microarch BaseCore testbench and verilated design --"
36+
@echo "Building from generated Makefile..."
37+
make -j -C obj_dir -f Vtop.mk
38+
39+
verilate_main:
40+
@echo "-- Verilating microarch BaseCore design simulation --"
41+
@echo "Generating object files..."
42+
@echo "Generating Makefile..."
43+
verilator -sc -exe -Wall --trace-fst $(VERILOG_DESIGN_FILES) --top top testbench/sc_main.cpp
44+
45+
verilate_tests:
46+
@echo "-- Verilating microarch BaseCore tests --"
47+
@echo "Generating object files..."
48+
@echo "Generating Makefile..."
49+
verilator -sc -exe -Wall --trace-fst $(VERILOG_DESIGN_FILES) --top top testbench/sc_unit_tests.cpp

base-core/README.md

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
# microarch BaseCore
2+
3+
**BaseCore** is a simple CPU core implementing the **microarch** ISA, designed in Verilog, with a testbench based on Verilator and SystemC.
4+
5+
6+
##### Navigation
7+
8+
- ```README.md``` - You are here.
9+
- ```Makefile``` - Build script for the project. See the **Building and running the testbench** section for details.
10+
- ```tracedump/``` - Directory for trace files from testbench simulations in FST format (can be opened with GTKWave). NOTE: Trace files will only appear in the directory after building and running the testbench - they are not included in the git repository.
11+
- ```traces.fst``` - Trace file from the main testbench simulation.
12+
- ```traces_<module_name>_<test_name>.fst``` - Trace file from last execution of a specific test case.
13+
- ```obj_dir/``` - Directory for temporary build files.
14+
- ```design/``` - Directory for Verilog design files of the core itself.
15+
- ```top.v``` - Top Verilog module.
16+
- ```flip_flop.v``` - A simple D flip-flop design, used to test the testbench.
17+
- ```testbench``` - SystemC testbench for testing the core.
18+
- ```sc_main.cpp``` - Main testbench simulation - for ad-hoc development and testing of modules.
19+
- ```sc_unit_tests.cpp``` - A set of unit tests for Verilog modules.
20+
- ```test_runner.h``` - A simple system for running unit tests, used by ```sc_unit_tests.cpp```.
21+
22+
##### Building and running the testbench
23+
24+
###### Dependencies:
25+
26+
- ```verilator```
27+
- ```SystemC library from Accellera```
28+
- ```make```
29+
- ```GTKWave FlatPak package```
30+
- ```g++ compiler```
31+
32+
###### Cleaning the build directory:
33+
34+
If something does not work, try a clean build by running ```make clean```
35+
36+
Note: this will delete all trace files from ```tracedump/```
37+
38+
###### Running the main simulation:
39+
40+
The main testbench simulation source is located in the ```sc_main.cpp``` file (that's where you can manipulate the inputs).
41+
To start it, execute:
42+
43+
```make run```
44+
45+
After the simulation completes, a ```GTKWave``` window will open (displaying traces, ie. a timeline of value changes on all inputs/outputs of the design). Note: To see the traces you need to select the module from a drop-down menu on the left and then select I/O ports by double-clicking them.
46+
47+
###### Running unit tests:
48+
49+
To run the unit tests, execute:
50+
51+
```make unit_tests```
52+
53+
Information will be printed, on which tests passed and which did not pass.
54+
55+
You can view trace files generated by the tests with ```GTKWave```.
56+
To quickly launch ```GTKWave``` run:
57+
58+
```make waves```
59+
60+
Code for unit tests is located in ```sc_unit_tests.cpp``` file.
61+
62+
You can write your own test file. **Test file format:**
63+
64+
```
65+
// Include the unit test system
66+
#include "test_runner.h"
67+
68+
TESTS;
69+
70+
// Declaring a test:
71+
TEST(module1, my_test)
72+
// Creating a signal:
73+
SET_SIGNAL(signal_name);
74+
// Optioonally you may also create a clock - with period and delay in given in nanoseconds
75+
SET_CLOCK(my_clock, 10, 3);
76+
//Make sure, that clock and signal names match names from the Verilog module
77+
START_SIMULATION;
78+
// Assign binary value to a signal.
79+
signal_name = true;
80+
// Run simulation for a given number of nanoseconds.
81+
STEP(4);
82+
// Assert value of the signal (if the assertion fails, the test will be marked as failed and failed assertion will be printed
83+
signal_assert(true, signal_name, "my nice assertion");
84+
END_SIMULATION;
85+
86+
// Declaring another test:
87+
TEST(module1, another_test)
88+
// Initialize signals/clocks here
89+
START_SIMULATION;
90+
// Run the test here
91+
END_SIMULATION;
92+
93+
// Declaring another test for a different module
94+
TEST(module2, another_test)
95+
// Initialize signals/clocks here
96+
START_SIMULATION;
97+
// Run the test here
98+
END_SIMULATION;
99+
100+
END_TESTS;
101+
```

base-core/design/flip_flop.v

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
module flip_flop
2+
(
3+
input clk,
4+
input reset,
5+
input D,
6+
output reg Q
7+
);
8+
9+
always @(posedge clk or posedge reset)
10+
begin
11+
if(reset == 1'b1)
12+
Q <= '0;
13+
else
14+
Q <= D;
15+
end
16+
endmodule

base-core/design/top.v

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
module top
2+
(
3+
input clk,
4+
input reset,
5+
input D,
6+
output reg Q
7+
);
8+
9+
always @(posedge clk or posedge reset)
10+
begin
11+
if(reset == 1'b1)
12+
Q <= '0;
13+
else
14+
Q <= D;
15+
end
16+
endmodule
17+
18+
19+

base-core/testbench/sc_main.cpp

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
#include <systemc>
2+
#include <verilated.h>
3+
#include <verilated_fst_sc.h>
4+
#include <memory>
5+
6+
7+
8+
#include "Vtop.h"
9+
10+
using namespace sc_core;
11+
using namespace sc_dt;
12+
13+
14+
int sc_main(int argc, char* argv[]) {
15+
Verilated::debug(0); //Debug level
16+
Verilated::traceEverOn(true); //We need to tell verilator, that tracing will be used
17+
Verilated::randReset(2); //Reset randomization policy
18+
Verilated::commandArgs(argc, argv); //Passing command args (required)
19+
20+
sc_clock clk{
21+
"clk", // Name
22+
10, // Period
23+
SC_NS, // Unit of the period
24+
0.5, // Duty cycle
25+
3, // Delay (time until first edge)
26+
SC_NS, // Unit of delay
27+
true // Is the rising edge first
28+
};
29+
30+
const std::unique_ptr<Vtop> top{new Vtop{"top"}};
31+
sc_signal<bool> reset;
32+
sc_signal<bool> D;
33+
sc_signal<bool> Q;
34+
35+
36+
top->clk(clk);
37+
top->reset(reset);
38+
top->Q(Q);
39+
top->D(D);
40+
41+
sc_start(SC_ZERO_TIME);
42+
43+
auto tfp = new VerilatedFstSc;
44+
top->trace(tfp, 99); //Telling SystemC to trace up to 99 levels of hierarchy.
45+
tfp->open("tracedump/traces.fst");
46+
47+
for(int i = 0; i<100;i++)
48+
{
49+
if (sc_time_stamp() > sc_time(28, SC_NS) && sc_time_stamp() < sc_time(30, SC_NS)) {
50+
reset = true;
51+
} else {
52+
reset = false;
53+
}
54+
if (sc_time_stamp() > sc_time(15, SC_NS) && sc_time_stamp() < sc_time(50, SC_NS)) {
55+
D = true;
56+
} else {
57+
D = false;
58+
}
59+
60+
61+
sc_start(1, SC_NS);
62+
63+
64+
}
65+
66+
top->final();
67+
68+
tfp->close();
69+
70+
return 0;
71+
72+
}

base-core/testbench/sc_unit_tests.cpp

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
#include "test_runner.h"
2+
3+
TESTS;
4+
5+
TEST(top, test)
6+
SET_CLOCK(clk, 10, 3);
7+
SET_SIGNAL(reset);
8+
SET_SIGNAL(D);
9+
SET_SIGNAL(Q);
10+
START_SIMULATION;
11+
D = false;
12+
reset = false;
13+
STEP(10)
14+
reset = true;
15+
STEP(1)
16+
reset = false;
17+
STEP(10)
18+
assert_signal(false, Q, "reset");
19+
D = true;
20+
for(int i = 0; i<5;i++)
21+
{
22+
STEP(1)
23+
if(clk == false)
24+
{
25+
assert_signal(false, Q, "bef edge");
26+
}
27+
else
28+
{
29+
assert_signal(true, Q, "after edge");
30+
}
31+
}
32+
END_SIMULATION;
33+
34+
35+
TEST(flip_flop, test_manual_clock)
36+
SET_SIGNAL(clk)
37+
SET_SIGNAL(reset);
38+
SET_SIGNAL(D);
39+
SET_SIGNAL(Q);
40+
START_SIMULATION;
41+
clk = false;
42+
reset = false;
43+
44+
D = true;
45+
STEP(10)
46+
assert_signal(false, Q, "bef edge 1");
47+
clk = true;
48+
STEP(10)
49+
clk = false;
50+
assert_signal(true, Q, "after edge 1");
51+
52+
reset = true;
53+
STEP(1)
54+
reset = false;
55+
STEP(10)
56+
assert_signal(false, Q, "reset");
57+
STEP(10)
58+
assert_signal(false, Q, "bef edge 2");
59+
clk = true;
60+
STEP(1)
61+
assert_signal(true, Q, "after edge 2");
62+
D = false;
63+
64+
END_SIMULATION;
65+
66+
67+
TEST(flip_flop, test)
68+
SET_CLOCK(clk, 10, 3);
69+
SET_SIGNAL(reset);
70+
SET_SIGNAL(D);
71+
SET_SIGNAL(Q);
72+
START_SIMULATION;
73+
D = false;
74+
reset = false;
75+
STEP(10)
76+
reset = true;
77+
STEP(1)
78+
reset = false;
79+
STEP(10)
80+
assert_signal(false, Q, "reset");
81+
D = true;
82+
for(int i = 0; i<5;i++)
83+
{
84+
STEP(1)
85+
if(clk == false)
86+
{
87+
assert_signal(false, Q, "bef edge");
88+
}
89+
else
90+
{
91+
assert_signal(true, Q, "after edge");
92+
}
93+
}
94+
END_SIMULATION;
95+
96+
97+
END_TESTS;

0 commit comments

Comments
 (0)