OpenCores
URL https://opencores.org/ocsvn/cryptosorter/cryptosorter/trunk

Subversion Repositories cryptosorter

[/] [cryptosorter/] [trunk/] [memocodeDesignContest2008/] [sort/] [BRAMLevelFIFOMuxes/] [BRAMVLevelFIFO.bsv] - Rev 6

Compare with Previous | Blame | View Log

// import standard library
import FIFO::*;
import RegFile::*;
import StmtFSM::*;
import Vector::*;

// import self-made library
import BRAM::*;
import VLevelFIFO::*;
 
// implementation of VLevelFIFO with BRAM
module mkBRAMVLevelFIFO (VLevelFIFO#(no_fifo, fifo_sz, data_t))
   provisos (Bits#(data_t,data_sz),
             Add#(TLog#(no_fifo),TLog#(fifo_sz),bram_idx_sz));   

   // instantiate an unguarded 1 cycle latency bram (i.e. the read response will only valid for 1 cycle)  
   UGBRAM#(Bit#(bram_idx_sz), data_t)           ugbram <- mkBypassUGBRAM_Full();
   
   RegFile#(Bit#(TLog#(no_fifo)),Bit#(TLog#(fifo_sz)))  head <- mkRegFileFull();
   RegFile#(Bit#(TLog#(no_fifo)),Bit#(TLog#(fifo_sz)))  tail <- mkRegFileFull();
   Reg#(Bit#(TLog#(no_fifo))) i <- mkReg(0);
   Reg#(Bool)                 finishInit <- mkReg(False);
   
   Reg#(Vector#(no_fifo,Bit#(TLog#(TAdd#(fifo_sz,1)))))  usedReg <- mkReg(replicate(0));
   Wire#(Vector#(no_fifo,Bit#(TLog#(TAdd#(fifo_sz,1))))) usedW   <- mkDWire(replicate(0));
   
   Reg#(Vector#(no_fifo,Bit#(TLog#(TAdd#(fifo_sz,1)))))  freeReg <- mkReg(replicate(fromInteger(valueOf(fifo_sz))));
   
   Wire#(Maybe#(Bit#(TLog#(no_fifo)))) enqIdx <- mkDWire(tagged Invalid);
   Wire#(data_t)                       enqVal <- mkDWire(?);
   
   Wire#(Maybe#(Bit#(TLog#(no_fifo)))) deqIdx <- mkDWire(tagged Invalid);

   Wire#(Maybe#(Bit#(TLog#(no_fifo)))) firstIdx <- mkDWire(tagged Invalid);
   
   Wire#(Maybe#(Bit#(TLog#(no_fifo)))) decrFreeIdx <- mkDWire(tagged Invalid);
      
   let enqIdxVal         = fromMaybe(0,enqIdx);
   let deqIdxVal         = fromMaybe(0,deqIdx);
   let firstIdxVal       = fromMaybe(0,firstIdx);
   let decrFreeIdxVal    = fromMaybe(0,decrFreeIdx);
   let deqIdxNEQFirstIdx = deqIdxVal != firstIdxVal;  
   let readResp          = ugbram.read_resp();
   
   // start the initialization processor
   rule initialization(!finishInit);
      head.upd(i,0);
      tail.upd(i,0);
      i <= i + 1;
      if (i == fromInteger(valueOf(no_fifo)-1))
         finishInit <= True;
   endrule
   
   rule updateUsedReg(finishInit && (isValid(enqIdx) || isValid(deqIdx)));
      Vector#(no_fifo,Bit#(TLog#(TAdd#(fifo_sz,1)))) newUsedReg = newVector();
      
      for (Integer i = 0; i < valueOf(no_fifo); i = i + 1)
         newUsedReg[i] = usedReg[i];
      
      if (isValid(enqIdx))
         newUsedReg[enqIdxVal] = usedReg[enqIdxVal] + 1;

      if (isValid(deqIdx))
         newUsedReg[deqIdxVal] = newUsedReg[deqIdxVal] - 1;

      usedReg <= newUsedReg;
      usedW <= newUsedReg;

//      $display("updateUsedReg");
   endrule
   
   rule updateUsedW(finishInit && !(isValid(enqIdx) || isValid(deqIdx)));
      usedW <= usedReg;
   endrule
   
   rule updateFreeReg(finishInit && (isValid(decrFreeIdx) || isValid(deqIdx)));
      Vector#(no_fifo,Bit#(TLog#(TAdd#(fifo_sz,1)))) newFreeReg = newVector();

      for (Integer i = 0; i < valueOf(no_fifo); i = i + 1)
         newFreeReg[i] = freeReg[i];               

      if (isValid(decrFreeIdx))
         newFreeReg[decrFreeIdxVal] = freeReg[decrFreeIdxVal] - 1;

      if (isValid(deqIdx))
         newFreeReg[deqIdxVal] = newFreeReg[deqIdxVal] + 1;               

      freeReg <= newFreeReg;

//      $display("updateFreeReg");
   endrule
   
   rule processEnq(finishInit && isValid(enqIdx));
      let tailVal = tail.sub(enqIdxVal);
      tail.upd(enqIdxVal, (tailVal + 1));
      ugbram.write({enqIdxVal,tailVal},enqVal);

//      $display("enq data %d to fifo %d with tailVal %d",data,idx,tailVal);
   endrule
   
   rule processFirstReq(finishInit && isValid(firstIdx));
      let headVal = head.sub(firstIdxVal);
      if (deqIdxNEQFirstIdx || !isValid(deqIdx))
         begin
            ugbram.read_req({firstIdxVal,headVal});
            //$display("first read idx %d headVal %d",firstIdxVal,headVal);
         end
      else // the fifo is dequeued at that cycle, we should read the next head
         begin
            ugbram.read_req({firstIdxVal,headVal+1});
            //$display("first read idx %d headVal+1 %d",firstIdxVal,headVal+1);
         end
   endrule

   rule processDeq(finishInit && isValid(deqIdx));
      let headVal = head.sub(deqIdxVal);
      head.upd(deqIdxVal, (headVal + 1));      
   endrule
   
   // enq is unguarded here, we expect the user to check it before they enq
   method Action enq(Bit#(TLog#(no_fifo)) idx, data_t data) if (finishInit);
      enqIdx <= tagged Valid idx;
      enqVal <= data;      
   endmethod
   
   // deq is unguarded here, we expect the user to check it before they deq
   method Action deq(Bit#(TLog#(no_fifo)) idx) if (finishInit);
      deqIdx <= tagged Valid idx;
      
//      $display("deq fifo %d",idx);
   endmethod
   
   method Action firstReq(Bit#(TLog#(no_fifo)) idx) if (finishInit);
      firstIdx <= tagged Valid idx;
   endmethod
   
   // first is unguarded here, we expecte the user to check it before they call first
   method data_t firstResp() if (finishInit);
      return readResp;
   endmethod
   
   method Action clear() if (finishInit);
      noAction;
   endmethod
   
   // return the usage of each fifo at the beginning of the cycle
   method Vector#(no_fifo,Bit#(TLog#(TAdd#(fifo_sz,1)))) used() if (finishInit);
      return usedReg;
   endmethod
   
   // return the usage of each fifo at the end of the cycle
   method Vector#(no_fifo,Bit#(TLog#(TAdd#(fifo_sz,1)))) used2() if (finishInit);
      return usedW;
   endmethod
   
   // return enq credit token available for each fifo
   method Vector#(no_fifo,Bit#(TLog#(TAdd#(fifo_sz,1)))) free() if (finishInit);
      return freeReg;
   endmethod
   
   // get credit token to enq fifo idx in the future
   // this method is unguarded (i.e. user need to call method free 
   // and check for token availability before calling this action)
   method Action decrFree(Bit#(TLog#(no_fifo)) idx) if (finishInit);
      decrFreeIdx <= tagged Valid idx;
   endmethod
   
endmodule

(* synthesize *)
module mkBRAMVLevelFIFOInstance(VLevelFIFO#(32, 16, Bit#(129)));
   let fifo <- mkBRAMVLevelFIFO();
   return fifo;
endmodule

/*
(* synthesize *)
module mkBRAMVLevelFIFOTest(Empty);
   let fifo <- mkBRAMVLevelFIFOInstance();
   Reg#(Bit#(8)) enqIdx <- mkReg(0);
   Reg#(Bit#(129)) enqData <- mkReg(0);
   Reg#(Bit#(8)) firstIdx <- mkReg(0);
   FIFO#(Bit#(0)) reqQ <- mkFIFO();
   Reg#(Bit#(8)) deqIdx <- mkReg(0);
   Reg#(Bit#(32)) cycleCnt <- mkReg(0);
   let used = fifo.used();
   let free = fifo.free();

   rule enqFifo(free[enqIdx[7:2]] > 0);      
      enqIdx <= enqIdx + 1;
      enqData <= enqData + 1;
      fifo.enq(enqIdx[7:2],enqData);
      fifo.decrFree(enqIdx[7:2]);
      
      $display("enq fifo %d with data %d",enqIdx[7:2],enqData);
   endrule
   
   rule firstFifo(used[deqIdx[7:2]] > 0);
      firstIdx <= firstIdx + 1;
      fifo.firstReq(firstIdx[7:2]);
      reqQ.enq(?);
      
      $display("first req fifo %d",firstIdx[7:2]);
   endrule
   
   rule deqFifo(True);
      reqQ.deq();
      if (used[deqIdx[7:2]] > 0)
         begin
            deqIdx <= deqIdx + 1;
            let deqData = fifo.firstResp();
            fifo.deq(deqIdx[7:2]);
            
            $display("deq fifo %d with data %d",deqIdx[7:2],deqData);
         end
      else
        $display("last first req is not reading valid data");
   endrule
   
   rule displayStat(True);
      for (Integer i = 0; i < 64; i = i + 1)
         $display("%d: used %d, free %d",i,used[i],free[i]);
   endrule
   
   rule countCycle(True);
      cycleCnt <= cycleCnt + 1;
      $display("cycle %d",cycleCnt);
      if (cycleCnt == 5000)
         $finish();
   endrule
   
endmodule
 */

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.