Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Initial Verilator Support #3

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,3 +62,7 @@ https://www.avnet.com/shop/us/products/avnet-engineering-services/aes-s6mb-lx9-g
### Upduino 2

http://www.gnarlygrey.com/

### ULX3S

https://github.com/emard/ulx3s
40 changes: 40 additions & 0 deletions bench/blinky_tb.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
#include <verilatedos.h>
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <time.h>
#include <sys/types.h>
#include <signal.h>
#include "verilated.h"
#include "Vblinky.h"
#include "testb.h"

int main(int argc, char **argv) {
Verilated::commandArgs(argc, argv);
TESTB<Vblinky> *tb = new TESTB<Vblinky>;

// See if we have a +vcd=something command-line option.
// If so, create the trace.vcd file
const char *vcd = Verilated::commandArgsPlusMatch("vcd=");
if (vcd[0]) {
printf("Creating trace.vcd\n");
tb->opentrace("trace.vcd");
}

// Run the simulation for 100_000 ticks
int old_q=0;
for (int i=0; i < 100000; i++) {
tb->tick();

// Print out if the q output has changed
if (tb->m_core->q != old_q) {
printf("LED: %d\n", tb->m_core->q);

// and save the old q value for later comparison
old_q= tb->m_core->q;
}
}

printf("Simulation complete\n");
}
99 changes: 99 additions & 0 deletions bench/testb.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
////////////////////////////////////////////////////////////////////////////////
//
// Filename: testb.h
//
// Project: Verilog Tutorial Example file
//
// Purpose: A wrapper providing a common interface to a clocked FPGA core
// being exercised by Verilator.
//
// Creator: Dan Gisselquist, Ph.D.
// Gisselquist Technology, LLC
//
////////////////////////////////////////////////////////////////////////////////
//
// Written and distributed by Gisselquist Technology, LLC
//
// This program is hereby granted to the public domain.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
////////////////////////////////////////////////////////////////////////////////
//
//
#ifndef TESTB_H
#define TESTB_H

#include <stdio.h>
#include <stdint.h>
#include <verilated_vcd_c.h>

#define TBASSERT(TB,A) do { if (!(A)) { (TB).closetrace(); } assert(A); } while(0);

template <class VA> class TESTB {
public:
VA *m_core;
VerilatedVcdC* m_trace;
uint64_t m_tickcount;

TESTB(void) : m_trace(NULL), m_tickcount(0l) {
m_core = new VA;
Verilated::traceEverOn(true);
m_core->clk = 0;
eval(); // Get our initial values set properly.
}
virtual ~TESTB(void) {
closetrace();
delete m_core;
m_core = NULL;
}

virtual void opentrace(const char *vcdname) {
if (!m_trace) {
m_trace = new VerilatedVcdC;
m_core->trace(m_trace, 99);
m_trace->open(vcdname);
}
}

virtual void closetrace(void) {
if (m_trace) {
m_trace->close();
delete m_trace;
m_trace = NULL;
}
}

virtual void eval(void) {
m_core->eval();
}

virtual void tick(void) {
m_tickcount++;

// Make sure we have our evaluations straight before the top
// of the clock. This is necessary since some of the
// connection modules may have made changes, for which some
// logic depends. This forces that logic to be recalculated
// before the top of the clock.
eval();
if (m_trace) m_trace->dump((vluint64_t)(10*m_tickcount-2));
m_core->clk = 1;
eval();
if (m_trace) m_trace->dump((vluint64_t)(10*m_tickcount));
m_core->clk = 0;
eval();
if (m_trace) {
m_trace->dump((vluint64_t)(10*m_tickcount+5));
m_trace->flush();
}
}

unsigned long tickcount(void) {
return m_tickcount;
}
};

#endif
29 changes: 29 additions & 0 deletions blinky.core
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,22 @@ filesets:
tinyfpga_bx:
files: [tinyfpga_bx/pinout.pcf : {file_type : PCF}]

ulx3s:
files:
- ulx3s/ulx3s_empty.config : {file_type : user, copyto : ulx3s_empty.config}
- ulx3s/ulx3s_v20.lpf : {file_type : LPF, copyto : ulx3s_v20.lpf}

upduino2:
files:
- upduino2/blinky_upduino2.v : {file_type : verilogSource}
- upduino2/pinout.pcf : {file_type : PCF}

verilator_tb:
files:
- bench/blinky_tb.cpp : {file_type : cppSource}
- bench/testb.h : {file_type : user}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be specified as {file_type : cppSource, is_include_file : true} so that the backend knows to include the directory of the file in the include path



targets:
default:
filesets : [rtl]
Expand Down Expand Up @@ -77,6 +88,15 @@ targets:
pnr: next
toplevel : blinky

ulx3s:
default_tool : trellis
filesets : [rtl, proginfo, ulx3s]
parameters : [clk_freq_hz=25000000]
tools:
trellis:
nextpnr_options : [--45k --basecfg ulx3s_empty.config --lpf ulx3s_v20.lpf]
toplevel : blinky

upduino2:
default_tool : icestorm
filesets : [rtl, proginfo, upduino2]
Expand All @@ -88,6 +108,15 @@ targets:
pnr: next
toplevel : blinky_upduino2

verilator:
default_tool: verilator
filesets : [rtl, verilator_tb]
tools:
verilator:
verilator_options : [--trace]
parameters : [clk_freq_hz=10000]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just checked that VCD generation works just fine if you create a new parameter (by adding an entry under the parameters section near the end of the core file) that looks like this

  vcd:
    datatype : bool
    paramtype : plusarg

add then add the newly created vcd parameter to the list of parameters for the target (i.e. change the line above to parameters : [clk_freq_hz=10000, vcd]

toplevel : blinky

parameters:
clk_freq_hz:
datatype : int
Expand Down
2 changes: 2 additions & 0 deletions blinky.v
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@ module blinky

always @(posedge clk) begin
count <= count + 1;
/* verilator lint_off WIDTH */
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will add a proper fix for this

if (count == clk_freq_hz-1) begin
/* verilator lint_on WIDTH */
q <= !q;
count <= 0;
end
Expand Down
Loading