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