Computer Laboratory

Bluepsec Examples

Divider Server

Example of a simple iterative divider wrapped in a Server interface (i.e. a Put to start the divide and a Get to consume the result.)

package DividerServer;

import FIFO::*;
import SpecialFIFOs::*;
import GetPut::*;
import ClientServer::*;

typedef struct {
	 UInt#(width) numerator;
	 UInt#(width) denominator;
	 } DivOperandsT#(numeric type width) deriving(Bits);


// define type for the DividerServer interface, specialising the Server interface
typedef Server#(DivOperandsT#(width),Maybe#(UInt#(width)))
    DividerServerT#(numeric type width);


module mkDividerServer(DividerServerT#(width))
      provisos(Add#(width,width,doublewidth));

   Reg#(Int#(doublewidth)) n <- mkRegU; // numerator
   Reg#(Int#(doublewidth)) d <- mkRegU; // denominator
   Reg#(UInt#(width))      r <- mkRegU; // result
   Reg#(UInt#(TAdd#(TLog#(width),1))) ctr <- mkReg(0); // loop counter
   FIFO#(Maybe#(UInt#(width))) result_fifo <- mkBypassFIFO; // output fifo
   
   let active = (ctr!=0);  // N.B. "active" works a bit like a Verilog wire
   
   rule run(active);
      let sub = n-d;
      d <= d>>1;
      ctr <= ctr-1;
      UInt#(width) nextr;
      if(sub>=0)
	 begin
	    nextr = (r<<1) | 1;
	    n <= sub;
	 end
      else
	 nextr = r<<1;
      r <= nextr;
      if(ctr==1) result_fifo.enq(tagged Valid nextr);
   endrule
   
   interface Put request;
      method Action put(op) if (!active);
	 if(op.denominator==0)
	    result_fifo.enq(Invalid);
	 else
	    begin
	       n <= zeroExtend(unpack(pack(op.numerator)));
	       d <= zeroExtend(unpack(pack(op.denominator)))<<(valueOf(width)-1);
	       r <= 0;
	       ctr <= fromInteger(valueOf(width));
	    end
      endmethod
   endinterface

   interface response = toGet(result_fifo);
endmodule


endpackage

Link to the DividerServer.bsv source