20 February, 2011

Experimenting with Verilator (counter)

Verilator is a open source Verilog HDL simulator. It is very fast since it translates Verilog code into optimized C++. But it as also quiet different from other Verilog simulators like Icarus Verilog and commercial ones, it only supports synthesizable RTL language constructs.

This are my first successful Verilator experiments. I was looking for a counter example, but was not able to find one, so I decided to write one myself and publish it. The instructions are for Ubuntu.

First write a verilog RTL counter. This example has two registers, one running at clock posedge, the other on negedge. I just wished to check if using both clock edges still qualifies as synthesizable RTL.


module counter #(
  parameter WIDTH = 8
)(
  // system signals
  input  wire             clk,
  input  wire             rst,
  // counter signas
  input  wire             cen,  // counter enable
  input  wire             wen,  // write enable
  input  wire [WIDTH-1:0] dat,  // input data
  output reg  [WIDTH-1:0] o_p,  // output value (posedge counter)
  output reg  [WIDTH-1:0] o_n   // output value (negedge counter)
);


always @ (posedge clk, posedge rst)
if (rst) o_p <= {WIDTH{1'b0}};
else     o_p <= wen ? dat : o_p + {{WIDTH-1{1'b0}}, cen};


always @ (negedge clk, posedge rst)
if (rst) o_n <= {WIDTH{1'b0}};
else     o_n <= wen ? dat : o_n + {{WIDTH-1{1'b0}}, cen};


endmodule


Than write a C++ testbench. C++ is used for the bench since non synthesizable Verilog features would be needed to write a proper Verilog bench. Anoter option would be to use SystemC, but due to licensing issues it is very difficult to get a package for Linux distributions. The bench will toggle the clock and provide input values.


#include "Vcounter.h"
#include "verilated.h"
#include "verilated_vcd_c.h"


int main(int argc, char **argv, char **env) {
  int i;
  int clk;
  Verilated::commandArgs(argc, argv);
  // init top verilog instance
  Vcounter* top = new Vcounter;
  // init trace dump
  Verilated::traceEverOn(true);
  VerilatedVcdC* tfp = new VerilatedVcdC;
  top->trace (tfp, 99);
  tfp->open ("counter.vcd");
  // initialize simulation inputs
  top->clk = 1;
  top->rst = 1;
  top->cen = 0;
  top->wen = 0;
  top->dat = 0x55;
  // run simulation for 100 clock periods
  for (i=0; i<20; i++) {
    top->rst = (i < 2);
    // dump variables into VCD file and toggle clock
    for (clk=0; clk<2; clk++) {
      tfp->dump (2*i+clk);
      top->clk = !top->clk;
      top->eval ();
    }
    top->cen = (i > 5);
    top->wen = (i == 10);
    if (Verilated::gotFinish())  exit(0);
  }
  tfp->close();
  exit(0);
}


Now run the next script or copy-paste line by line into the command line.


#!/bin/sh


# cleanup
rm -rf obj_dir
rm -f  counter.vcd


# run Verilator to translate Verilog into C++, include C++ testbench
verilator -Wall --cc --trace counter.v --exe counter_tb.cpp
# build C++ project
make -j -C obj_dir/ -f Vcounter.mk Vcounter
# run executable simulation
obj_dir/Vcounter


# view waveforms
gtkwave counter.vcd counter.sav &


The script will automatically launch GTKWave and open the waveform.







Release for sockit_owm

1-wire (onewire) master written in Verilog HDL sockit_owm has been released.

The source code is available here:

RTL features:
  • small RTL, should fit into a CPLD
  • Avalon MM bus, Wishbone compatible with a simple adapter
  • timed reset, presence, write/read bit transfers
  • overdrive
  • power supply (strong pull-up)

Altera SOPC Builder integration

Altera Nios II EDS integration:
  • port of the 1-wire open domain kit version 3.10b
  • interrup driven or polling driver
  • uCOS-II support (only partially tested)

Detailed documentation is provided inside the package. Please read it, it covers almost anything, that can be said about the project.

The module was developed using open source tools (Icarus Verilog, GTKWave) but it was tested on the Terasic DE1 board (a demo for the board is included in the package).