Learning BSV‎ > ‎Advanced Bluespec‎ > ‎Import BVI‎ > ‎

DesignWare Divider


Practically speaking, a user may want to import any hardmarco or preexisting module into BSV, but a DesignWare by Synopsys is a good example... Fundumentally, it is not much different than any other import bvi example: You define some methods in an interface, and then specify how those method arguments connect to each pin of the verilog file. At the lowest level, the file imported is verilog, so you can add the necessary DesignWare instantiation or comment directives as needed.

In this case, the main interesting feature is that there are no registers.. This particular divider:


has no registers, so it has combinational paths from input to outputs.. The compiler wants to know this as well as knowing how to schedule the methods so that it may generate proper logic around it..

Additionally, I have added a basic bluespec compatible "ready/enable" signal pair so that the outputs are not ready to be read if the inputs have not been driving (for all the reasons we use implicit conditions in bluespec :)

We don't have a DesignWare license in house, but using the actual low level component call is a simple exercise, left to the reader (it's just a simple verilog file at that point).. Set it up once and add it to your library!

Here is the verilog file I used as the base component:

// wrap a designware divider
module div( CLK, CLK_GATE,
a, b,
quotient, remainder, divide_by_zero,
en, rdy );
parameter WIDTH = 1;

// we don't use the clock, many blocks do..
input CLK, CLK_GATE;

// these are the signals needed by the block itself
input [WIDTH-1:0] a,b;

output [WIDTH-1:0] quotient, remainder;
reg [WIDTH-1:0] quotient, remainder;
output divide_by_zero;
reg divide_by_zero;

// add ready enable to make this a true bsv block
input en;
output rdy;
reg rdy;

always @(a or b) begin
if (en) begin
// place your designware comments here, etc
divide_by_zero <= (b == 0);
quotient <= a / b;
remainder <= a % b;

// might as well add bluespec rdy, enable
// after all, it's what we do, and it will
// save us bugs later
rdy <= 1;
else begin
rdy <= 0;

Now the actual import bvi code. Essentially, we create an interface to be used by callers (as with any other bluespec module's interface), but the module definition is detailed to match the verilog block (as defined further in the reference manual)..

interface DwDiv#(type tp);
// drive inputs via action method
// both a/b need to be driven at the same time
method Action start( tp a, tp b );

// might be useful to be able to read each output individually
method tp quot();
method tp rem();
method Bool zero();

import "BVI" div =
module mkDwDiv( DwDiv#(UInt#(n)) ); // use this just for UInt#(sizeN) for now
// no_clock

// allow the width to be parameterized on with width of the BSV input
parameter WIDTH = valueof(n);

// make signals in verilog to method arguments
method start( a, b ) enable(en);
method quotient quot() ready(rdy);
method remainder rem() ready(rdy);
method divide_by_zero zero() ready(rdy);

// tell the compiler all the combinational paths from input to output
path (a,quotient);
path (a,remainder);
path (b,quotient);
path (b,remainder);
path (b,divide_by_zero);
path (en,rdy);

// these are the defaults, but might as well get rid of the warnings
schedule (start) SB (quot,rem,zero);
schedule (start) C (start);
schedule (quot,rem,zero) CF (quot,rem,zero);

And now the energetic person could create a very small testbench (as I generally do just to make sure connections are okay, etc)..

import StmtFSM::*;

import DwDiv::*;
typedef UInt#(16) TD;

(* synthesize *)
module mkTB();

// here is the divider
DwDiv#(TD) div <- mkDwDiv;

// just step through a few divides
Stmt test =
div.start( 10, 2 );
div.start( 10, 3 );
div.start( 12, 6 );
div.start( 10, 0 );
div.start( 50, 3 );

mkAutoFSM( test );

// just display data when it is available
rule showResults;
$display("q=%x r=%x z=%x", div.quot, div.rem, div.zero);


Finally, you can build and run with most verilog simulators with this make file (a simple one I often use for test cases like this)

# compile it
bsc -u -verilog \
-vdir obj -bdir obj -simdir obj -p .:obj:+ \
-unspecified-to x TB.bsv

make run

# run it
bsc -vsim iverilog -e mkTB -o obj/mkTB.exe div.v obj/*.v

rm -fR obj

And running this with iverilog (can be run with vcs, modelsim, ncverilog, iverilog, cver, or feel free to use your own command line... it's just verilog)... The simulation output shows basic functionality:

q=0003 r=0001 z=0
q=0002 r=0000 z=0
q=xxxx r=xxxx z=1
q=0010 r=0002 z=0
q=xxxx r=xxxx z=x
q=xxxx r=xxxx z=x