Computer Laboratory

Course pages 2013–14

Advanced Computer Design

Example FibServer

/*****************************************************************************
 Examples of Fibonnaci servers for lecture 2
 
 Copyright (c) Simon Moore, January 2010
 *****************************************************************************/

import FIFO::*;
import GetPut::*;
import ClientServer::*;
import Vector::*;

/*****************************************************************************/

// specialisation of Server interface for Fib
typedef Server#(UInt#(width), UInt#(TMul#(width,4)))
   FibServerT#(numeric type width);

module mkFibServer(FibServerT#(width))
   provisos (Add#(width,TMul#(width,3),TMul#(width,4)));

   Reg#(UInt#(TMul#(width,4)))  a <- mkRegU;
   Reg#(UInt#(TMul#(width,4)))  b <- mkRegU;
   Reg#(UInt#(TMul#(width,4)))  j <- mkRegU;
   Reg#(Bool)      active      <- mkReg(False);
   FIFO#(UInt#(TMul#(width,4))) result_fifo <- mkLFIFO;
   
   rule loop (active && (j>1));
      a <= a+b;
      b <= a;
      j <= j-1;
   endrule
   
   rule the_end (active && (j==1));
      result_fifo.enq(a);
      active <= False;
   endrule
   
   rule n_is_zero (active && (j==0));
      result_fifo.enq(0);
      active <= False;
   endrule
   
// new interfaces
   interface Put request;
      method Action put(n) if (!active);
	 j      <= extend(n);
	 a      <= 1;
	 b      <= 0;
	 active <= True;
      endmethod
   endinterface
   
   interface response = toGet(result_fifo);

endmodule
   
module mkTestFibServer(Empty);
   
   FibServerT#(8)  fib    <- mkFibServer;
   Reg#(UInt#(8))  n      <- mkReg(0);
   FIFO#(UInt#(8)) inputs <- mkSizedFIFO(4);
   
   rule loop (n<10);
      n <= n+1;
      fib.request.put(n);
      inputs.enq(n);
   endrule
   
   rule display_results;
      let r <- fib.response.get();
      inputs.deq;
      $display("%05t: result of fib(%1d)=%d",
	 $time, inputs.first, r);
   endrule
   
endmodule


/*****************************************************************************/

function Integer fib_func(Integer n);
   if(n<2) return n;
      else return fib_func(n-1)+fib_func(n-2);
endfunction

module mkTestFibFunc(Empty);
   
   rule do_fib;
      $display("Output fib results on one cycle");
      for(Integer n=0; n<10; n=n+1)
	 begin
	    Integer f = fib_func(n);
	    $display("%05t: result of fib(%1d)=%d",
	       $time, n, fromInteger(f));
	 end
      $finish();
   endrule

endmodule


/*****************************************************************************/

module mkFibServerROM(FibServerT#(width))
   provisos (Add#(width,TMul#(width,3),TMul#(width,4)));
   
   Vector#(TExp#(width), Wire#(UInt#(TMul#(width,4)))) rom <- replicateM(mkBypassWire);
   FIFO#(UInt#(TMul#(width,4))) result_fifo <- mkLFIFO;
   UInt#(width) index=0;

   rule init_rom;
      for(Integer n=0; inLiteralRange(index,n); n=n+1)
	 rom[fromInteger(n)] <= fromInteger(fib_func(n));
   endrule
   
   interface Put request;
      method Action put(n);
	 result_fifo.enq(rom[n]);
      endmethod
   endinterface
   
   interface response = toGet(result_fifo);
   
endmodule


module mkTestFibServerROM(Empty);
   
   FibServerT#(4)  fib    <- mkFibServerROM;
   Reg#(UInt#(4))  n      <- mkReg(1);
   FIFO#(UInt#(4)) inputs <- mkSizedFIFO(4);
   
   rule loop (n!=0);
      n <= n+1;
      fib.request.put(n);
      inputs.enq(n);
   endrule
   
   rule display_results;
      let r <- fib.response.get();
      inputs.deq;
      $display("%05t: result of fib(%2d)=%d",
	 $time, inputs.first, r);
   endrule
   
endmodule


// a synthesizable version if you want to have a look at the Verilog produced

(* synthesize *)
module mkFibServerROM4(FibServerT#(4));
   FibServerT#(4) fibserver <- mkFibServerROM;
   interface request = fibserver.request;
   interface response = fibserver.response;
endmodule