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
