From 2991b5025a5afefaa73f6af59460cc71c1688f30 Mon Sep 17 00:00:00 2001 From: JorgenA Date: Fri, 23 Feb 2024 16:40:18 +0100 Subject: [PATCH 1/2] Add Led_blinker example --- examples/Led_blinker/Led_blinker.sv | 94 +++++++++++++++++++++++++++++ examples/Led_blinker/makefile | 6 ++ examples/Led_blinker/sim.cpp | 28 +++++++++ 3 files changed, 128 insertions(+) create mode 100644 examples/Led_blinker/Led_blinker.sv create mode 100644 examples/Led_blinker/makefile create mode 100644 examples/Led_blinker/sim.cpp diff --git a/examples/Led_blinker/Led_blinker.sv b/examples/Led_blinker/Led_blinker.sv new file mode 100644 index 0000000..0ead1b4 --- /dev/null +++ b/examples/Led_blinker/Led_blinker.sv @@ -0,0 +1,94 @@ +module Led_blinker + ( + i_clock, + i_enable, + i_switch_1, + i_switch_2, + o_led_drive + ); + + input i_clock; + input i_enable; + input i_switch_1; + input i_switch_2; + output o_led_drive; + + parameter c_CNT_100HZ = 125; + parameter c_CNT_50HZ = 250; + parameter c_CNT_10HZ = 1250; + parameter c_CNT_1HZ = 12500; + + reg [31:0] r_CNT_100HZ = 0; + reg [31:0] r_CNT_50HZ = 0; + reg [31:0] r_CNT_10HZ = 0; + reg [31:0] r_CNT_1HZ = 0; + + reg r_TOGGLE_100HZ = 1'b0; + reg r_TOGGLE_50HZ = 1'b0; + reg r_TOGGLE_10HZ = 1'b0; + reg r_TOGGLE_1HZ = 1'b0; + + reg r_LED_SELECT; + //wire w_LED_SELECT; + + + + always @(posedge i_clock) + begin + if (c_CNT_100HZ == c_CNT_100HZ - 1) + begin + r_TOGGLE_100HZ <= !r_TOGGLE_100HZ; + r_TOGGLE_100HZ <= 0; + end + else + r_CNT_100HZ <= r_CNT_100HZ + 1; + end + + always @(posedge i_clock) + begin + if (c_CNT_50HZ == c_CNT_50HZ - 1) + begin + r_TOGGLE_50HZ <= !r_TOGGLE_50HZ; + r_TOGGLE_50HZ <= 0; + end + else + r_CNT_50HZ <= r_CNT_50HZ + 1; + end + + always @(posedge i_clock) + begin + if (c_CNT_10HZ == c_CNT_10HZ - 1) + begin + r_TOGGLE_10HZ <= !r_TOGGLE_10HZ; + r_TOGGLE_10HZ <= 0; + end + else + r_CNT_10HZ <= r_CNT_10HZ + 1; + end + + always @(posedge i_clock) + begin + if (c_CNT_1HZ == c_CNT_1HZ - 1) + begin + r_TOGGLE_1HZ <= !r_TOGGLE_1HZ; + r_TOGGLE_1HZ <= 0; + end + else + r_CNT_1HZ <= r_CNT_1HZ + 1; + end + + always @(*) begin + case ({i_switch_1, i_switch_2}) + /* verilator lint_off COMBDLY */ + 2'b11 : r_LED_SELECT <= r_TOGGLE_1HZ; + 2'b10 : r_LED_SELECT <= r_TOGGLE_10HZ; + 2'b01 : r_LED_SELECT <= r_TOGGLE_50HZ; + 2'b00 : r_LED_SELECT <= r_TOGGLE_100HZ; + /* verilator lint_on COMBDLY */ + endcase + end + + assign o_led_drive = r_LED_SELECT & i_enable; + + +endmodule \ No newline at end of file diff --git a/examples/Led_blinker/makefile b/examples/Led_blinker/makefile new file mode 100644 index 0000000..a8950ba --- /dev/null +++ b/examples/Led_blinker/makefile @@ -0,0 +1,6 @@ +VERILATOR_ROOT := ../.. +PROJECT_NAME := Led_blinker +SOURCES := *.sv +SIMFILES := *.cpp + +include $(VERILATOR_ROOT)/verilator.mk diff --git a/examples/Led_blinker/sim.cpp b/examples/Led_blinker/sim.cpp new file mode 100644 index 0000000..f2276a5 --- /dev/null +++ b/examples/Led_blinker/sim.cpp @@ -0,0 +1,28 @@ +#include "VLed_blinker.h" +#include "verilated.h" + +#include +#include +#include + +int main(int argc, char** argv) { + VLed_blinker* top = new VLed_blinker; + Verilated::commandArgs(argc, argv); + + int stimuli_a[] = { 2, -1, 1, -6 }; + int stimuli_b[] = { 4, 5, 2, 7 }; + + for (int i = 0; i < sizeof(stimuli_a) / sizeof(stimuli_a[0]); i++) { + if (Verilated::gotFinish()) break; + + top->a = stimuli_a[i]; + top->b = stimuli_b[i]; + + top->eval(); + + assert(top->c == (stimuli_a[i] + stimuli_b[i])); + } + + delete top; + return 0; +} From 809b4ba9734a5d76eb1ef971438f0602ce97c21a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Magnus=20M=C3=A6hlum?= Date: Wed, 13 Mar 2024 18:00:15 +0100 Subject: [PATCH 2/2] Add config.gtkw which has most useful signals; fix some bugs in the .sv code and implement (at the moment, non-functional) simulation. --- examples/Led_blinker/Led_blinker.sv | 44 +++++++++----- examples/Led_blinker/config.gtkw | 32 ++++++++++ examples/Led_blinker/sim.cpp | 92 +++++++++++++++++++++++++---- 3 files changed, 143 insertions(+), 25 deletions(-) create mode 100644 examples/Led_blinker/config.gtkw diff --git a/examples/Led_blinker/Led_blinker.sv b/examples/Led_blinker/Led_blinker.sv index 0ead1b4..84d87e1 100644 --- a/examples/Led_blinker/Led_blinker.sv +++ b/examples/Led_blinker/Led_blinker.sv @@ -1,6 +1,7 @@ module Led_blinker ( i_clock, + i_reset, i_enable, i_switch_1, i_switch_2, @@ -8,6 +9,7 @@ module Led_blinker ); input i_clock; + input i_reset; input i_enable; input i_switch_1; input i_switch_2; @@ -19,26 +21,39 @@ module Led_blinker parameter c_CNT_1HZ = 12500; reg [31:0] r_CNT_100HZ = 0; - reg [31:0] r_CNT_50HZ = 0; - reg [31:0] r_CNT_10HZ = 0; - reg [31:0] r_CNT_1HZ = 0; + reg [31:0] r_CNT_50HZ = 0; + reg [31:0] r_CNT_10HZ = 0; + reg [31:0] r_CNT_1HZ = 0; reg r_TOGGLE_100HZ = 1'b0; reg r_TOGGLE_50HZ = 1'b0; reg r_TOGGLE_10HZ = 1'b0; reg r_TOGGLE_1HZ = 1'b0; - reg r_LED_SELECT; - //wire w_LED_SELECT; + reg r_LED_SELECT = 1'b0; + always @(posedge i_clock) + begin + if (i_reset == 1) + begin + r_CNT_100HZ <= 0; + r_CNT_50HZ <= 0; + r_CNT_10HZ <= 0; + r_CNT_1HZ <= 0; + r_TOGGLE_100HZ <= 0; + r_TOGGLE_50HZ <= 0; + r_TOGGLE_10HZ <= 0; + r_TOGGLE_1HZ <= 0; + end + end always @(posedge i_clock) begin - if (c_CNT_100HZ == c_CNT_100HZ - 1) + if (r_CNT_100HZ == c_CNT_100HZ - 1) begin r_TOGGLE_100HZ <= !r_TOGGLE_100HZ; - r_TOGGLE_100HZ <= 0; + r_CNT_100HZ <= 0; end else r_CNT_100HZ <= r_CNT_100HZ + 1; @@ -46,10 +61,10 @@ module Led_blinker always @(posedge i_clock) begin - if (c_CNT_50HZ == c_CNT_50HZ - 1) + if (r_CNT_50HZ == c_CNT_50HZ - 1) begin r_TOGGLE_50HZ <= !r_TOGGLE_50HZ; - r_TOGGLE_50HZ <= 0; + r_CNT_50HZ <= 0; end else r_CNT_50HZ <= r_CNT_50HZ + 1; @@ -57,10 +72,10 @@ module Led_blinker always @(posedge i_clock) begin - if (c_CNT_10HZ == c_CNT_10HZ - 1) + if (r_CNT_10HZ == c_CNT_10HZ - 1) begin r_TOGGLE_10HZ <= !r_TOGGLE_10HZ; - r_TOGGLE_10HZ <= 0; + r_CNT_10HZ <= 0; end else r_CNT_10HZ <= r_CNT_10HZ + 1; @@ -68,10 +83,10 @@ module Led_blinker always @(posedge i_clock) begin - if (c_CNT_1HZ == c_CNT_1HZ - 1) + if (r_CNT_1HZ == c_CNT_1HZ - 1) begin r_TOGGLE_1HZ <= !r_TOGGLE_1HZ; - r_TOGGLE_1HZ <= 0; + r_CNT_1HZ <= 0; end else r_CNT_1HZ <= r_CNT_1HZ + 1; @@ -90,5 +105,4 @@ module Led_blinker assign o_led_drive = r_LED_SELECT & i_enable; - -endmodule \ No newline at end of file +endmodule diff --git a/examples/Led_blinker/config.gtkw b/examples/Led_blinker/config.gtkw new file mode 100644 index 0000000..f905271 --- /dev/null +++ b/examples/Led_blinker/config.gtkw @@ -0,0 +1,32 @@ +[*] +[*] GTKWave Analyzer v3.3.104 (w)1999-2020 BSI +[*] Fri Mar 8 17:16:35 2024 +[*] +[dumpfile] "/home/magnus/ntnu/orbit/biosat-electronics-FPGA/electronics-verilator/examples/Led_blinker/trace.vcd" +[dumpfile_mtime] "Fri Mar 8 17:13:28 2024" +[dumpfile_size] 49174 +[savefile] "/home/magnus/ntnu/orbit/biosat-electronics-FPGA/electronics-verilator/examples/Led_blinker/config.gtkw" +[timestart] 0 +[size] 1850 1016 +[pos] -51 -51 +*0.000000 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 +[treeopen] TOP. +[sst_width] 233 +[signals_width] 166 +[sst_expanded] 1 +[sst_vpaned_height] 289 +@28 +TOP.Led_blinker.i_clock +TOP.Led_blinker.i_enable +TOP.Led_blinker.i_reset +TOP.Led_blinker.i_switch_1 +TOP.Led_blinker.i_switch_2 +TOP.Led_blinker.o_led_drive +@22 +TOP.Led_blinker.r_CNT_1HZ[31:0] +TOP.Led_blinker.r_CNT_10HZ[31:0] +TOP.Led_blinker.r_CNT_50HZ[31:0] +@23 +TOP.Led_blinker.r_CNT_100HZ[31:0] +[pattern_trace] 1 +[pattern_trace] 0 diff --git a/examples/Led_blinker/sim.cpp b/examples/Led_blinker/sim.cpp index f2276a5..1d3a528 100644 --- a/examples/Led_blinker/sim.cpp +++ b/examples/Led_blinker/sim.cpp @@ -1,28 +1,100 @@ #include "VLed_blinker.h" #include "verilated.h" +// Needed for waveform generation +#include + #include #include #include +void toggle_clk(VLed_blinker* top, VerilatedVcdC *trace, uint32_t *tickcount) { + top->i_clock = 0; + top->eval(); + trace->dump(10 * (*tickcount)++); + top->i_clock = 1; + top->eval(); + trace->dump(10 * (*tickcount)++); +} + +void print_top(VLed_blinker *top) { + printf("i_enable: %i\n", top->i_enable); + printf("i_clock: %i\n", top->i_clock); + printf("i_switch_1: %i\n", top->i_switch_1); + printf("i_switch_2: %i\n", top->i_switch_2); + printf("o_led_drive: %i\n", top->o_led_drive); +} + int main(int argc, char** argv) { VLed_blinker* top = new VLed_blinker; Verilated::commandArgs(argc, argv); + + // For waveform generation + uint32_t tickcount = 0; + Verilated::traceEverOn(true); + + // Initialization of trace + VerilatedVcdC *trace = new VerilatedVcdC; + top->trace(trace, 99); + trace->open("trace.vcd"); - int stimuli_a[] = { 2, -1, 1, -6 }; - int stimuli_b[] = { 4, 5, 2, 7 }; + // Set initial values + top->i_enable = 1; + top->i_reset = 0; + top->i_clock = 0; + top->i_switch_1 = 0; + top->i_switch_2 = 0; + top->eval(); + + int ret = 0; + uint32_t count_limits[] = { + 125, + 250, + 1250, + 12500 + }; + uint32_t count = 0; - for (int i = 0; i < sizeof(stimuli_a) / sizeof(stimuli_a[0]); i++) { + for (int i = 0; i < sizeof(count_limits) / sizeof(count_limits[0]); i++) { if (Verilated::gotFinish()) break; - - top->a = stimuli_a[i]; - top->b = stimuli_b[i]; - - top->eval(); - assert(top->c == (stimuli_a[i] + stimuli_b[i])); + top->i_switch_1 = (i & 0b01) ? 1 : 0; + top->i_switch_2 = (i & 0b10) ? 1 : 0; + top->i_reset = 0; + + uint32_t count_limit = count_limits[i]; + bool led_signal_expect = false; + for (int j = 0; j < 2*count_limit; j++) { + if (count == count_limit) { + led_signal_expect = true; + printf("Expect led signal high\n"); + } else if (count == 2*count_limit) { + led_signal_expect = false; + printf("Expect led signal low\n"); + } + + if (top->o_led_drive != led_signal_expect) { + printf("top->o_led_drive: Got %i when %i expected\n", top->o_led_drive, led_signal_expect); + toggle_clk(top, trace, &tickcount); + ret = 1; + goto out; + } + + toggle_clk(top, trace, &tickcount); + printf("\nit: %i\n", j); + print_top(top); + fflush(stdout); + count++; + } + + printf("Toggled clock %i times. Reset\n", 2*count); + fflush(stdout); } + +out: + trace->close(); + delete trace; delete top; - return 0; + return ret; }