Computer Laboratory

ECAD and Architecture Practical Classes

Bluespec SystemVerilog

I have mentioned Bluespec SystemVerilog a couple of times during ECAD lectures. For those feeling adventerous (!), you might like to have a go with Bluespec that I've installed on the PWF Linux here:


Before using the tools a few environment variables need to be setup which is easily achived by sourcing a bash script:

   source /ux/clteach/swm11/bluespec/setup.bash

Examples and Tutorials

The MPhil Advanced Computer Design course uses Bluespec and you might find the notes and lab sessions to be of interest. Design examples can be found on the PWF Linux here:


Many are also available open source from

Finally, the official Bluespec SystemVerilog documentation is available here (please do not redistribute over the web):


Thacker's Tiny Computer in Bluespec

I've created a Bluespec version of Thacker's Tiny Comptuer.

Quick start

Below is a copy of me running the tools in a shell. Note that there are a few comments (look for the # prefix).

soup:~$ source /ux/clteach/swm11/bluespec/setup.bash
soup:~$ mkdir MyFirstBluespec
soup:~$ cd MyFirstBluespec/
soup:MyFirstBluespec$ cp /ux/clteach/swm11/bluespec/DividerExample/Divider.bsv .
soup:MyFirstBluespec$ cat Divider.bsv 
import FIFO::*;

interface DividerIfc;
   method Action start(UInt#(16) a, UInt#(16) b);
   method ActionValue#(UInt#(16)) get_result;

(* synthesize *)
module mkDivider(DividerIfc);
   Reg#(UInt#(16)) ra <- mkReg(0);
   Reg#(UInt#(16)) rb <- mkReg(0);
   Reg#(UInt#(16)) d  <- mkReg(0);
   Reg#(Bool) running <- mkReg(False);
   FIFO#(UInt#(16)) result_fifo <- mkLFIFO;

   // horibly inefficient divider implementation!   
   rule do_division (running && (ra>=rb));
      let new_ra = ra - rb;
      let new_d = d+1;
      ra <= new_ra;
      d <= new_d;
      $display("%05t: do_division... ra=%d rb=%d d=%d",$time,ra,rb,d);
      if(new_ra < rb)
            $display("%05t: do_division enq'd result early",$time);
            running <= False;
   rule do_ending (running && (ra<rb));
      running <= False;
      $display("%05t: do_division enq'd result",$time);
   method Action start(UInt#(16) a, UInt#(16) b) if (!running);
      ra <= a;
      rb <= b;
      d <= 0;
      running <= True;
   method ActionValue#(UInt#(16)) get_result;
      return result_fifo.first;

module mkTestBench(Empty);
   Reg#(UInt#(16)) a <- mkReg(13);
   DividerIfc div <- mkDivider;
   rule do_init (a>=5);
      a <= a-5;
      $display("%05t: started division",$time);
   rule read_result;
      let r <- div.get_result();
      $display("%05t: result = %d",$time,r);
soup:MyFirstBluespec$ # now create a makefile to do simulate the testbench
soup:MyFirstBluespec$ makemakefile Divider.bsv mkTestBench
Creating Makefile with top-level package "Divider.bsv" and top-level module "mkTestBench"
soup:MyFirstBluespec$ make run
bsc -keep-fires -cross-info -sim -g mkTestBench -u Divider.bsv
checking package dependencies
compiling Divider.bsv
code generation for mkDivider starts
Elaborated module file created:
code generation for mkTestBench starts
Elaborated module file created:
All packages are up to date.
bsc -keep-fires -cross-info -sim -o mkTestBench  -e mkTestBench
Bluesim object created: mkTestBench.{h,o}
Bluesim object created: mkDivider.{h,o}
Bluesim object created: schedule.{h,o}
Simulation shared library created:
Simulation executable created: mkTestBench
./mkTestBench -m 1500
   10: started division
   20: do_division... ra=   13 rb=    3 d=    0
   30: do_division... ra=   10 rb=    3 d=    1
   40: do_division... ra=    7 rb=    3 d=    2
   50: do_division... ra=    4 rb=    3 d=    3
   50: do_division enq'd result early
   60: result =     4
   60: started division
   70: do_division... ra=    8 rb=    3 d=    0
   80: do_division... ra=    5 rb=    3 d=    1
   80: do_division enq'd result early
   90: result =     2
soup:MyFirstBluespec$ # note that the following C++ files were created and then compiled to form the executable cycle accurate simulation:
soup:MyFirstBluespec$ ls *.cxx
mkDivider.cxx  mkTestBench.cxx  schedule.cxx
soup:MyFirstBluespec$ make clean
rm -f  *.bi *.bo *.ba *.info *.sched *.c *.h *.o *.so  mk*.v  *~ mkTestBench v95/* >/dev/null
soup:MyFirstBluespec$ # now lets synthesis the Verilog by specifying ModelSim as the simulator (i.e. a Verilog simulator)
soup:MyFirstBluespec$ makemakefile Divider.bsv mkTestBench modelsim
Makefile exists, ok to overwrite? (y/N) y
Creating Makefile with top-level package "Divider.bsv" and top-level module "mkTestBench"
soup:MyFirstBluespec$ # the following verilog files were created:
soup:MyFirstBluespec$ ls -l *.v
-rw-r--r-- 1 swm11 swm11 6411 2010-11-08 11:36 mkDivider.v
-rw-r--r-- 1 swm11 swm11 2750 2010-11-08 11:36 mkTestBench.v