Wednesday, March 5, 2008

Some Verilog Tips & Tricks

I thought I'd share a few Verilog tips & tricks I discovered recently that help when you're trying to build a simulation that doesn't care where it's run from in your directory structure.

Gather Files & Environmental Variables

Gather files are list of simulator commands that are included using the -f flag. You know this, but you may have a different name for them. In these gather files I list all the Verilog module files that I'm using in the simulation, as well as the include directories needed. I specify each file relatively (eg ../../../) from a simulation base directory ($BASEDIR). I actively avoid absolute paths: this gives designers the freedom to set up their simulations anywhere; and the simulations can be run from any of our company's sites. So long, of course, if the designer checks the code out from our versioning system...

run_sim.sh:
#! /usr/bin/sh
export BASEDIR="../../../" # setenv in csh

simulator -f "${BASEDIR}/config/sim.gather"


${BASEDIR}/config/sim.gather:
//
// TITLE: A Simulation Gather File
//
+incdir+${BASEDIR}/block1
${BASEDIR}/block1/rtl/module1.v
${BASEDIR}/block1/rtl/module2.v
${BASEDIR}/block2/rtl/module1.v
${BASEDIR}/block2/rtl/module2.v

The magic here is the 'export' command in the shell script. For best results, the script calling the simulator can calculate what this should be based on the current working directory ($PWD). Verilog & Debussy will correctly substitute any environmental variables it sees in gather files. Our designs are fairly complicated, and I've used nested gather files sucessfully to mimic Verilog-2001's 'Configurations'. But don't get me started on using Verilog configurations with NC-Verilog and Debussy...

Specifying bitmap files for $readmemb and $readmemh

The next problem is making any bitmap files for $readmem tasks portable. The main problem here is that macros are not expanded within strings, nor are you allowed to split strings with them. For example, the code below won't work:

`define BASEDIR ../../../
`define BASEDIR_STR "../../../ // may not even get this far...

module test();
reg [3:0] mem [3:0];

initial begin
$readmemh("`BASEDIR/rom.dat"); // macro won't be expanded
$readmemb(`BASEDIR_STR.rom.dat"); // won't be accepted by simulator - split over string
end

endmodule

I came up with a solution using a reg vector to hold a strings and then using $sformat, but it seemed ugly and I thought there must be a better way. And I found it using concatenations.
module test();
reg [3:0] mem [3:0];

initial begin
$readmemb({`BASEDIR_STR,"/rom.dat"}); // string literal concatenation!
end

endmodule


This works like a charm so long as `BASEDIR_STR is a string literal - "../" is ok but just ../ is not. To keep things directory-agnostic, I pass the base directory string as an argument to the simulator, eg (escaping the quotes is important here to get the path passed to the simulator as a string literal):

run_sim.sh:
#! /usr/bin/sh
export BASEDIR="../../../" # setenv in csh

simulator -f \
"${BASEDIR}/config/sim.gather" \
+define+BASEDIR_STR=\"${BASEDIR}\"