FIFOD.bsv
上传用户:aoptech
上传日期:2014-09-22
资源大小:784k
文件大小:5k
源码类别:

3G开发

开发平台:

Others

  1. //----------------------------------------------------------------------//
  2. // The MIT License 
  3. // 
  4. // Copyright (c) 2007 Alfred Man Cheuk Ng, mcn02@mit.edu 
  5. // 
  6. // Permission is hereby granted, free of charge, to any person 
  7. // obtaining a copy of this software and associated documentation 
  8. // files (the "Software"), to deal in the Software without 
  9. // restriction, including without limitation the rights to use,
  10. // copy, modify, merge, publish, distribute, sublicense, and/or sell
  11. // copies of the Software, and to permit persons to whom the
  12. // Software is furnished to do so, subject to the following conditions:
  13. // 
  14. // The above copyright notice and this permission notice shall be
  15. // included in all copies or substantial portions of the Software.
  16. // 
  17. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  18. // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
  19. // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  20. // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
  21. // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
  22. // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  23. // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  24. // OTHER DEALINGS IN THE SOFTWARE.
  25. //----------------------------------------------------------------------//
  26. import EHRReg::*;
  27. import Vector::*;
  28. interface FIFOD#(numeric type sz,   // buffer size
  29.  numeric type i_sz, // input size
  30.  numeric type o_sz, // output size
  31.  type data_t);
  32.       method Action enq(Vector#(i_sz, data_t) msg);
  33.       method Vector#(o_sz, data_t) first();
  34.       method Action deq();
  35.       method Action clear();
  36.       method Bool notEmpty(); // means have enough elements to deq
  37.       method Bool notFull();  // means have enough spaces to enq
  38. endinterface
  39. typedef struct{
  40.   Bit#(1)  header; 
  41.   Bit#(sz) index; 
  42. } FIFODIndex#(numeric type sz) deriving (Bits, Eq);
  43. function Bit#(sz1) getUsage(Integer fifo_sz,
  44.     FIFODIndex#(sz) head,
  45.     FIFODIndex#(sz) tail)
  46.   provisos (Add#(sz,xxA,sz1));
  47.       let isSameHeader = head.header == tail.header;
  48.       Bit#(sz1) fifoSz = fromInteger(fifo_sz);
  49.       Bit#(sz1) headIdx = zeroExtend(head.index);
  50.       Bit#(sz1) tailIdx = zeroExtend(tail.index);
  51.       Bit#(sz1) res = isSameHeader ?
  52.       tailIdx - headIdx :
  53.       fifoSz - (headIdx - tailIdx);
  54.       return res;
  55. endfunction // Bool
  56. function FIFODIndex#(sz) incrFIFODIndex(Integer fifo_sz,
  57. Integer incr_sz,
  58. FIFODIndex#(sz) fifoIdx);
  59.       Bit#(sz) maxIdx = fromInteger(fifo_sz - incr_sz);
  60.       Bit#(sz) incr = ((fifo_sz - incr_sz) == 0) ? 0 : 
  61.       fromInteger(incr_sz);
  62.       FIFODIndex#(sz) res = (fifoIdx.index == maxIdx) ?
  63.     FIFODIndex{ header: ~fifoIdx.header,
  64. index: 0} :
  65.     FIFODIndex{ header: fifoIdx.header,
  66. index: fifoIdx.index + incr};
  67.       return res;
  68. endfunction // FIFODIndex
  69. module mkFIFOD(FIFOD#(sz, i_sz, o_sz, data_t))
  70.   provisos (Mul#(i_sz, xxA, sz),
  71.     Mul#(o_sz, xxB, sz),
  72.     Bits#(Vector#(sz,data_t), xxC),
  73.     Log#(sz,idx_sz),
  74.     Add#(sz,1,szp1),
  75.     Log#(szp1,usage_sz),
  76.     Add#(idx_sz,xxD,usage_sz));
  77.    FIFODIndex#(idx_sz) initIdx = FIFODIndex{ header: 0,
  78.      index: 0};
  79.    Reg#(Vector#(sz, data_t)) buffer <- mkRegU;
  80.    EHRReg#(2, FIFODIndex#(idx_sz)) head <- mkEHRReg(initIdx);
  81.    EHRReg#(2, FIFODIndex#(idx_sz)) tail <- mkEHRReg(initIdx);
  82.    Integer fifo_sz       = valueOf(sz);
  83.    Integer incr_head     = valueOf(o_sz);
  84.    Integer incr_tail     = valueOf(i_sz);
  85.    let tail0 = (tail[0]);
  86.    let tail1 = (tail[1]);
  87.    let head0 = (head[0]);
  88.    let head1 = (head[1]);
  89.    Bit#(usage_sz) usage0 = getUsage(fifo_sz, head0, tail0);
  90.    Bit#(usage_sz) usage1 = getUsage(fifo_sz, head1, tail1);
  91.    let canDeq = usage0 >= fromInteger(incr_head);
  92.    let canEnq = usage1 <= fromInteger(fifo_sz - incr_tail);
  93.    method Action enq(Vector#(i_sz, data_t) msg) if (canEnq);
  94.       Vector#(sz,data_t) newBuffer = buffer;
  95.       tail[1] <= incrFIFODIndex(fifo_sz, incr_tail, tail1);
  96.       for (Integer i = 0; i < valueOf(i_sz); i = i + 1)
  97.      newBuffer[tail1.index+fromInteger(i)] = msg[i];
  98.       buffer <= newBuffer;
  99. //      $display("enq: usage1 = %d",usage1);      
  100.    endmethod
  101.    method Vector#(o_sz, data_t) first() if (canDeq);
  102.       let bufferVec = buffer;
  103.       Vector#(o_sz, data_t) outVec = newVector;
  104.       for (Integer i = 0; i < valueOf(o_sz); i = i + 1)
  105. outVec[i] = bufferVec[head0.index+fromInteger(i)];
  106.       return outVec;
  107.    endmethod
  108.      
  109.    method Action deq() if (canDeq);
  110.       head[0] <= incrFIFODIndex(fifo_sz, incr_head, head0);
  111. //      $display("deq: usage0 = %d",usage0);
  112.    endmethod
  113.    method Action clear();
  114.       head[0] <= initIdx;
  115.       tail[0] <= initIdx;
  116.    endmethod
  117.    
  118.    method Bool notEmpty();
  119.       return canDeq;
  120.    endmethod
  121.    
  122.    // note that this can be different from canEnq
  123.    method Bool notFull();
  124.       return usage0 <= fromInteger(fifo_sz - incr_tail);
  125.    endmethod
  126. endmodule // mkDiffFIFO
  127. (* synthesize *)
  128. module mkTestFIFOD(Empty);
  129.    FIFOD#(12,3,4,Bit#(1)) dFifo <- mkFIFOD;
  130.    Reg#(Bit#(3)) counter <- mkReg(0);
  131.    Reg#(Bit#(32) ) clockCnt <- mkReg(0);
  132.  
  133.    rule enqData(True);
  134.       counter <= counter + 1;
  135.       dFifo.enq(unpack(counter));
  136.       $display("enq: %b",counter);
  137.    endrule
  138.    rule deqData(True);
  139.       let data = dFifo.first;
  140.       dFifo.deq;
  141.       $display("deq: %b",pack(data));
  142.    endrule
  143.    rule advClock(True);
  144.       clockCnt <= clockCnt + 1;
  145.       $display("clock: %d",clockCnt);
  146.       $display("notEmpty: %d",dFifo.notEmpty);
  147.       $display("notFull: %d",dFifo.notFull);      
  148.    endrule
  149. endmodule // TestDiffFIFO