Skip to content

Instantly share code, notes, and snippets.

@miyo
Created May 6, 2020 06:56
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save miyo/6f9d76802164391697c032554dbee95b to your computer and use it in GitHub Desktop.
Save miyo/6f9d76802164391697c032554dbee95b to your computer and use it in GitHub Desktop.
Verilatorでvcdファイルを生成する (http://zipcpu.com/blog/2017/06/21/looking-at-verilator.html を 試してみる)
module counter
(
input wire clk,
input wire reset,
output wire q
);
logic [31:0] d = 32'h0;
assign q = d[20];
always_ff @(posedge clk) begin
d <= d + 1;
end
endmodule // counter
#!/bin/sh
verilator --cc counter.sv --trace --exe tb.cpp
make -C obj_dir -f Vcounter.mk
./obj_dir/Vcounter
#include <iostream>
#include <verilated.h>
#include "Vcounter.h"
#include "testbench.h"
int main(int argc, char** argv) {
Verilated::commandArgs(argc, argv);
TESTBENCH<Vcounter> *tb = new TESTBENCH<Vcounter>();
tb->opentrace("trace.vcd");
while(tb->m_tickcount < 500){
std::cout << tb->m_tickcount << std::endl;
tb->tick();
}
}
#include <verilated_vcd_c.h>
template<class MODULE> class TESTBENCH {
public:
unsigned long m_tickcount;
MODULE *m_core;
VerilatedVcdC *m_trace;
TESTBENCH(void) {
m_core = new MODULE();
m_tickcount = 0l;
// According to the Verilator spec, you *must* call
// traceEverOn before calling any of the tracing functions
// within Verilator.
Verilated::traceEverOn(true);
}
virtual ~TESTBENCH(void) {
delete m_core;
m_core = NULL;
}
virtual void reset(void) {
m_core->reset = 1;
// Make sure any inheritance gets applied
this->tick();
m_core->reset = 0;
}
// Open/create a trace file
virtual void opentrace(const char *vcdname) {
if (!m_trace) {
m_trace = new VerilatedVcdC;
m_core->trace(m_trace, 99);
m_trace->open(vcdname);
}
}
// Close a trace file
virtual void close(void) {
if (m_trace) {
m_trace->close();
m_trace = NULL;
}
}
virtual void tick(void) {
// Increment our own internal time reference
m_tickcount++;
// Make sure any combinatorial logic depending upon
// inputs that may have changed before we called tick()
// has settled before the rising edge of the clock.
m_core->clk = 0;
m_core->eval();
if(m_trace) m_trace->dump(10*m_tickcount-2);
// Repeat for the positive edge of the clock
m_core->clk = 1;
m_core->eval();
if(m_trace) m_trace->dump(10*m_tickcount);
// Now the negative edge
m_core->clk = 0;
m_core->eval();
if (m_trace) {
// This portion, though, is a touch different.
// After dumping our values as they exist on the
// negative clock edge ...
m_trace->dump(10*m_tickcount+5);
//
// We'll also need to make sure we flush any I/O to
// the trace file, so that we can use the assert()
// function between now and the next tick if we want to.
m_trace->flush();
}
}
virtual bool done(void) { return (Verilated::gotFinish()); }
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment