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

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 Controls::*;
  27. import Complex::*;
  28. import CORDIC::*;
  29. import DataTypes::*;
  30. import FIFO::*;
  31. import FIFOF::*;
  32. import FixedPoint::*;
  33. import FixedPointLibrary::*;
  34. import Interfaces::*;
  35. import Preambles::*;
  36. import ShiftRegs::*;
  37. import SParams::*;
  38. import SynchronizerLibrary::*;
  39. import Vector::*;
  40. import FPComplex::*;
  41. import GetPut::*;
  42. import Parameters::*;
  43. //`define debug_mode True // uncomment this line for displaying text 
  44. typedef struct{
  45.   ctrlT   control;  // estimate postion
  46.   data1T  data1;     // data1
  47.   data2T  data2;     // data2
  48. } SyncData#(type ctrlT, type data1T, type data2T) deriving (Bits, Eq);
  49. typedef enum{
  50.   Dump = 0,          // useless data, don't output
  51.   Idle = 1,          // don't do estimation
  52.   Collect = 2,       // collect correlation and calculate moving average
  53.   ShortSync = 3,     // make coarse estimation
  54.   LongSync = 4,      // make fine estimation
  55.   TimeOut = 5        // timeout reset
  56. } ControlType deriving (Bits, Eq);
  57. typedef enum{
  58.   SNormal = 0,
  59.   STrans = 1,
  60.   LNormal = 2,
  61.   LTrans = 3
  62. } TimeState deriving (Bits, Eq);
  63. // type definitions for the input of timing and frequency synchronizer
  64. // defintion of CorrPipeT: control = tell timing sync what to do, data1 = original input, data2 = rotated input
  65. typedef SyncData#(TimeState, FPComplex#(SyncIntPrec,SyncFractPrec), FPComplex#(SyncIntPrec,SyncFractPrec)) CorrPipeT;
  66. // defintion of FineTimeInT: data1 = original input, data2 = rotated input
  67. typedef SyncData#(ControlType, FPComplex#(SyncIntPrec,SyncFractPrec), FPComplex#(SyncIntPrec,SyncFractPrec)) FineTimeInT;
  68. // definition of FreqEstInT: data1 = original input, data2 = auto correlation result
  69. typedef SyncData#(ControlType, FPComplex#(SyncIntPrec,SyncFractPrec), FPComplex#(CorrIntPrec, SyncFractPrec)) FreqEstInT;
  70. // definition of FreqRotInT: data1 = original input, data2 = angle to be rotated
  71. typedef SyncData#(ControlType, FPComplex#(SyncIntPrec,SyncFractPrec), FixedPoint#(SyncIntPrec, SyncFractPrec)) FreqRotInT;
  72. // timing synchronizer interface (used for both coarse and fine estimations)
  73. interface TimeEstimator;
  74.    // inputs
  75.    method Action putCoarTimeIn(FPComplex#(SyncIntPrec,SyncFractPrec) coarTimeIn);
  76.    method Action putFineTimeIn(FineTimeInT fineTimeIn);
  77.    // output
  78.    method ActionValue#(FreqEstInT) getFreqEstIn();
  79. endinterface
  80. // carrier frequency offset estimator (used for both coarse and fine estimations) 
  81. interface FreqEstimator;
  82.    // inputs
  83.    method Action putFreqEstIn(FreqEstInT freqEstIn);
  84.    // output
  85.    method ActionValue#(FreqRotInT) getFreqRotIn();
  86. endinterface
  87. // carrier frequency offset compensator
  88. interface FreqRotator;
  89.    // inputs
  90.    method Action putFreqRotIn(FreqRotInT freqRotIn);
  91.    // output
  92.    method ActionValue#(FineTimeInT) getFineTimeIn();
  93. endinterface
  94. interface AutoCorrelator;
  95.    // inputs
  96.    method Action putInput(FPComplex#(SyncIntPrec,SyncFractPrec) x);
  97.    method Action setMode(Bool isShortMode);
  98.    // outputs
  99.    method ActionValue#(CorrType) getCorrelation();
  100. endinterface
  101. (* synthesize *)
  102. module mkAutoCorrelator(AutoCorrelator);
  103.    // output buffer
  104.    FIFO#(CorrType) outQ <- mkFIFO;
  105.    // delay queues
  106.    ShiftRegs#(SSLen, FPComplex#(SyncIntPrec,SyncFractPrec))             delayIn <- mkAutoCorr_DelayIn;
  107.    ShiftRegs#(SSLen, FPComplex#(MulIntPrec,SyncFractPrec))              corrSub <- mkAutoCorr_CorrSub;
  108.    
  109.    ShiftRegs#(LSLSSLen, FPComplex#(SyncIntPrec,SyncFractPrec))          extDelayIn <- mkAutoCorr_ExtDelayIn;
  110.    ShiftRegs#(LSLSSLen, FPComplex#(MulIntPrec,SyncFractPrec))           extCorrSub <- mkAutoCorr_ExtCorrSub;
  111.    // accumulator
  112.    Reg#(CorrType)                                          corr <- mkReg(cmplx(0,0));
  113.    // mode
  114.    Reg#(Bool)     isShort <- mkReg(True);     
  115.    method Action putInput(FPComplex#(SyncIntPrec,SyncFractPrec) x);
  116.    begin
  117.       let conjDelayIn = cmplxConj(delayIn.first); // conjugate of delayed input
  118.       let curIn = x;
  119.       FPComplex#(MulIntPrec,SyncFractPrec) corrAdd = fpcmplxTruncate(fpcmplxMult(curIn,conjDelayIn)); 
  120.       let newCorr = corr + 
  121.     fpcmplxSignExtend(corrAdd) - 
  122.     fpcmplxSignExtend(corrSub.first);
  123.       corr <= newCorr;
  124.       outQ.enq(newCorr);
  125.       if (isShort)
  126. begin
  127.    delayIn.enq(curIn);
  128.    corrSub.enq(corrAdd);
  129.    `ifdef debug_mode
  130.       $display("AutoCorr.putInput: isShort");
  131.    `endif
  132. end
  133.       else
  134. begin
  135.    extDelayIn.enq(curIn);
  136.    delayIn.enq(extDelayIn.first);
  137.    extCorrSub.enq(corrAdd);
  138.    corrSub.enq(extCorrSub.first);
  139.    `ifdef debug_mode
  140.       $display("AutoCorr.putInput: isLong");
  141.    `endif
  142. end // else: !if(isShort)
  143.    end
  144.    endmethod
  145.    method Action setMode(Bool isShortMode);
  146.    begin
  147.       // reset accumulator and shiftregs
  148.       delayIn.clear;
  149.       corrSub.clear;
  150.       extDelayIn.clear;
  151.       extCorrSub.clear;
  152.       corr <= cmplx(0,0);
  153.       isShort <= isShortMode;
  154.       `ifdef debug_mode
  155.          $display("AutoCorr.setMode: %d",isShortMode);
  156.       `endif
  157.    end
  158.    endmethod
  159.    method ActionValue#(CorrType) getCorrelation();
  160.    begin
  161.       outQ.deq;
  162.       `ifdef debug_mode
  163.          $write("AutoCorr.getCorrelation:");
  164.          cmplxWrite("("," + ","i)",fxptWrite(7),outQ.first);
  165.          $display("");
  166.       `endif
  167.       return outQ.first;
  168.    end
  169.    endmethod
  170.      
  171. endmodule
  172. (* synthesize *)
  173. module mkTimeEstimator(TimeEstimator);
  174.    // constants
  175.    Integer lSStart = valueOf(LSStart);
  176.    Integer signalStart = valueOf(SignalStart);
  177.    Integer lSyncPos = valueOf(LSyncPos);
  178.    Integer freqMeanLen = valueOf(FreqMeanLen);
  179.    Integer coarTimeCorrPos = valueOf(CoarTimeCorrPos);
  180.    Integer coarResetPos = valueOf(TimeResetPos);
  181.    Integer coarTimeAccumDelaySz = valueOf(CoarTimeAccumDelaySz);
  182.    let fullLongPreambles = insertCP0(getLongPreSigns()); // constant known 160-long preambles
  183.    Vector#(FineTimeCorrSz, Complex#(Bit#(1))) longPreambles = take(fullLongPreambles);      
  184.    Bit#(FineTimeCorrFullResSz)  maxFineTimePowSq = cmplxModSq(singleBitCrossCorrelation(longPreambles,longPreambles)) >> 1; // last maxFineTimeSignal 
  185.    
  186.    // states
  187.    // autocorrelator
  188.    AutoCorrelator          autoCorr <- mkAutoCorrelator;
  189.    // input buffers
  190.    FIFO#(FPComplex#(SyncIntPrec,SyncFractPrec)) coarTimeInQ <- mkFIFO; // the buffer should be large enough (> whole latency of synchronizer)
  191.    FIFOF#(FineTimeInT)     fineTimeInQ <- mkFIFOF;
  192.    FIFO#(TimeState) timeStatePipeQ <- mkSizedFIFO(2);
  193.    FIFO#(FPComplex#(SyncIntPrec,SyncFractPrec)) coarInPipeQ <- mkSizedFIFO(2);
  194.    FIFO#(FPComplex#(SyncIntPrec,SyncFractPrec)) fineInPipeQ <- mkSizedFIFO(2);
  195.    FIFO#(FixedPoint#(CoarTimeAccumIntPrec,SyncFractPrec)) coarPowQ <- mkSizedFIFO(2);
  196.    FIFO#(Bit#(FineTimeCorrFullResSz)) fineTimeCorrQ <- mkSizedFIFO(2);
  197.    
  198.    // output buffer
  199.    FIFO#(FreqEstInT) outQ <- mkFIFO;
  200.    // delay queues
  201.    ShiftRegs#(SSLen, FixedPoint#(MulIntPrec,SyncFractPrec))             coarPowSub <- mkTimeEst_CoarPowSub;
  202.    ShiftRegs#(CoarTimeAccumDelaySz, Bool)                  coarTimeSub <- mkTimeEst_CoarTimeSub;
  203.    
  204.    ShiftRegs#(FineTimeCorrDelaySz, Complex#(Bit#(1)))      fineDelaySign <- mkTimeEst_FineDelaySign;
  205.    //accumulators
  206.    Reg#(FixedPoint#(CoarTimeAccumIntPrec,SyncFractPrec))   coarPow <- mkReg(0);
  207.    Reg#(Bit#(CoarTimeAccumIdx))                            coarTime <- mkReg(0); // at most add up to 144
  208.    //other regs
  209.    Reg#(Bit#(CounterSz))                                   coarPos <- mkReg(0);
  210.    Reg#(Bool)                                             coarDet <- mkReg(False);
  211.    
  212.    Reg#(Bit#(CounterSz))                                   finePos <- mkReg(0);
  213.    Reg#(Bool)             fineDet <- mkReg(False);
  214.    Reg#(Bool)     isProlog <- mkReg(True); // setup at the beginning
  215.    Reg#(TimeState)     status <- mkReg(SNormal);
  216.    
  217.    rule procProlog(isProlog); // initial setup
  218.    begin
  219.       if (fineTimeInQ.notEmpty) // finish
  220. begin
  221.    isProlog <= False;
  222. end
  223.       else // not yet fill up pipeline, keep sending
  224. begin
  225.    outQ.enq(FreqEstInT{control: Dump,
  226.        data1: ?,
  227.        data2: ?});    
  228. end
  229.       `ifdef debug_mode
  230.          $display("TimeEst.procProlog");
  231.       `endif
  232.    end
  233.    endrule
  234.    rule procAutoCorrSN(!isProlog && status == SNormal);
  235.    begin
  236.       let curIn = coarTimeInQ.first;
  237.       coarTimeInQ.deq;
  238.       fineTimeInQ.deq;
  239.       coarInPipeQ.enq(curIn);
  240.       if (fineTimeInQ.first.control == ShortSync)
  241. begin
  242.    status <= LNormal;
  243.    autoCorr.setMode(False);
  244.    timeStatePipeQ.enq(STrans);
  245. end
  246.       else
  247. begin
  248.    FixedPoint#(MulIntPrec,SyncFractPrec) coarPowAdd = fxptTruncate(fpcmplxModSq(curIn));
  249.    let newCoarPow = coarPow +
  250.     fxptZeroExtend(coarPowAdd) -
  251.     fxptZeroExtend(coarPowSub.first);
  252.    coarPow <= newCoarPow;
  253.    coarPowQ.enq(newCoarPow);
  254.    coarPowSub.enq(coarPowAdd);
  255.    autoCorr.putInput(curIn);
  256.    timeStatePipeQ.enq(SNormal);
  257. end // else: !if(fineTimeInQ.first.control == ShortSync)
  258.       `ifdef debug_mode
  259.          $display("TimeEst.procAutoCorrSN");
  260.       `endif
  261.    end
  262.    endrule
  263.    rule  procAutoCorrLN(!isProlog && status == LNormal);
  264.    begin
  265.       let fineSign = toSingleBitCmplx(fineTimeInQ.first.data2);
  266.       let fineTimeCorrIn = append(fineDelaySign.getVector(), cons(fineSign,nil));
  267.       let newFineTimeCorrPow = cmplxModSq(singleBitCrossCorrelation(fineTimeCorrIn, longPreambles));
  268.       fineDelaySign.enq(fineSign);
  269.       fineTimeCorrQ.enq(newFineTimeCorrPow);
  270.       coarTimeInQ.deq;
  271.       fineTimeInQ.deq;
  272.       autoCorr.putInput(fineTimeInQ.first.data2);
  273.       timeStatePipeQ.enq(LNormal);
  274.       coarInPipeQ.enq(coarTimeInQ.first);
  275.       fineInPipeQ.enq(fineTimeInQ.first.data1);
  276.       `ifdef debug_mode
  277.          $write("TimeEst.procAutoCorrLN: fineSign: %d + %di,",fineSign.rel,fineSign.img);
  278.          $write("input: ");
  279.          cmplxWrite("("," + ","i), ",fxptWrite(7),fineTimeInQ.first.data2);
  280.          $display("");
  281.          $display("TimeEst.procAutoCorrLN: fineTimeCorrIn:%h, ",fineTimeCorrIn);
  282.          $display("TimeEst.procAutoCorrLN: longPreSigns:%h, ",longPreambles);
  283.       `endif
  284.    end
  285.    endrule
  286.    rule procAutoCorrLT(!isProlog && status == LTrans);
  287.    begin
  288.       fineTimeInQ.deq;
  289.       timeStatePipeQ.enq(LTrans);
  290.       fineInPipeQ.enq(fineTimeInQ.first.data1);
  291.       if (fineTimeInQ.first.control == LongSync || fineTimeInQ.first.control == TimeOut)
  292. begin
  293.    status <= SNormal;
  294.    autoCorr.setMode(True);
  295. end
  296.       `ifdef debug_mode
  297.          $display("TimeEst.procAutCorrLT");
  298.       `endif
  299.    end
  300.    endrule
  301.    rule procTimeEstSN(!isProlog && timeStatePipeQ.first == SNormal);
  302.    begin
  303.       //variables
  304.       ControlType outControl = Idle;
  305.       FPComplex#(SyncIntPrec,SyncFractPrec) outData = coarInPipeQ.first;
  306.       CorrType outCorr = ?;
  307.       Bit#(CounterSz) newCoarPos;
  308.       let newCorr <- autoCorr.getCorrelation;
  309.       let newCoarPow = coarPowQ.first;
  310.       if (coarDet)
  311. begin
  312.    newCoarPos = coarPos + 1;
  313. end
  314.       else
  315. begin
  316.    FPComplex#(CoarTimeAccumIntPrec, SyncFractPrec) newCoarCorr = fpcmplxTruncate(newCorr);
  317.    let newCoarCorrPow = fpcmplxModSq(newCoarCorr);
  318.    let newCoarPowSq = fxptZeroExtend(fxptMult(newCoarPow,newCoarPow));
  319.    let coarTimeAdd = newCoarCorrPow > (newCoarPowSq >> 1);
  320.    let newCoarTime = coarTime +
  321.      zeroExtend(pack(coarTimeAdd)) -
  322.      zeroExtend(pack(coarTimeSub.first));
  323.    newCoarPos = zeroExtend(newCoarTime) +
  324.         fromInteger(coarTimeCorrPos - 1);
  325.    if (newCoarTime == fromInteger(coarTimeAccumDelaySz)) // coar detected
  326.      begin
  327. coarDet <= True;
  328. coarTime <= 0;     // reset coarTime
  329. coarTimeSub.clear; // clear coarTimeSub shiftreg
  330.      end
  331.    else
  332.      begin
  333. coarTimeSub.enq(coarTimeAdd);
  334. coarTime <= newCoarTime;
  335.      end
  336. end // else: !if(coarDet)
  337.       
  338.       // common state transitions
  339.       timeStatePipeQ.deq;
  340.       coarPowQ.deq;
  341.       coarInPipeQ.deq;
  342.       coarPos <= newCoarPos;
  343.       //setup output data
  344.       if (newCoarPos < fromInteger(lSStart - freqMeanLen) || newCoarPos > fromInteger(lSStart - 1))
  345. begin
  346.    outControl = Idle;
  347.    outCorr = ?;
  348. end
  349.       else
  350. begin
  351.    outControl = ((newCoarPos == fromInteger(lSStart - 1)) ? 
  352.  ShortSync:
  353.  Collect);
  354.    outCorr = newCorr;
  355. end // else: !if(newCoarPos < fromInteger(lSStart - freqMeanLen) || newCoarPos > fromInteger(lSStart - 1))
  356.       outQ.enq(FreqEstInT{control: outControl,
  357.   data1: outData,
  358.   data2: outCorr});
  359.       `ifdef debug_mode
  360.          $display("TimeEst.procTimeEstSN: coarPos:%d",newCoarPos);
  361.       `endif
  362.    end
  363.    endrule
  364.    rule procTimeEstST(!isProlog && timeStatePipeQ.first == STrans);
  365.    begin
  366.       timeStatePipeQ.deq;
  367.       coarInPipeQ.deq;
  368.       coarPos <= coarPos + 1;
  369.       outQ.enq(FreqEstInT{control: Idle,
  370.   data1: coarInPipeQ.first,
  371.   data2: ?});
  372.       `ifdef debug_mode
  373.          $display("TimeEst.procTimeEstST: coarPos:%d",coarPos + 1);
  374.       `endif
  375.    end
  376.    endrule
  377.    rule procTimeEstLN(!isProlog && timeStatePipeQ.first == LNormal);
  378.    begin
  379.       Bit#(CounterSz) newCoarPos = coarPos;
  380.       Bit#(CounterSz) newFinePos = finePos;
  381.       ControlType outControl = Idle;
  382.       FPComplex#(SyncIntPrec,SyncFractPrec) outData = ?;
  383.       CorrType outCorr = ?;
  384.       let newCorr <- autoCorr.getCorrelation;
  385.       let newFineTimeCorrPow = fineTimeCorrQ.first;
  386.       if (status == LTrans)
  387. begin
  388.    outControl = Idle;
  389.    outData = fineInPipeQ.first; // send  outData as fineInPipeQ.first
  390.    outCorr = ?;
  391. end
  392.       else
  393. begin
  394.    if (fineDet)
  395.      begin
  396. newFinePos = finePos + 1; 
  397.      end
  398.    else
  399.      begin
  400. if (newFineTimeCorrPow > maxFineTimePowSq)
  401.   begin
  402.      newFinePos = fromInteger(lSyncPos); 
  403.      fineDet <= True;
  404.   end
  405. else
  406.   begin
  407.      newCoarPos = coarPos + 1;
  408.   end
  409.                 `ifdef debug_mode
  410.    $display("TimeEst.procTimeEstLN: newFineTimePowCorr:%d, maxFineTimePosSq:%d",newFineTimeCorrPow, maxFineTimePowSq);
  411. `endif
  412.      end // else: !if(fineDet)
  413.    
  414.    coarInPipeQ.deq;
  415.    finePos <= newFinePos;
  416.    coarPos <= newCoarPos;
  417.    outData = coarInPipeQ.first;
  418.    outCorr = newCorr;
  419.       
  420.    if (newFinePos == fromInteger(signalStart - 1) || newCoarPos == fromInteger(coarResetPos))
  421.      begin
  422. status <= LTrans;
  423. outControl = (newCoarPos == fromInteger(coarResetPos)) ? TimeOut : LongSync;        
  424.      end
  425.    else
  426.      begin
  427. outControl = Collect;        
  428.      end
  429. end
  430.       
  431.       timeStatePipeQ.deq;
  432.       fineTimeCorrQ.deq;
  433.       fineInPipeQ.deq;      
  434.       outQ.enq(FreqEstInT{control: outControl,
  435.   data1: outData,
  436.   data2: outCorr});
  437.       `ifdef debug_mode
  438.          $display("TimeEst.procTimeEstLN: coarPos:%d, finePos:%d",newCoarPos,newFinePos);
  439.       `endif
  440.    end // else: !if(status == LTrans)
  441.    endrule
  442.    rule procTimeEstLT(!isProlog && timeStatePipeQ.first == LTrans);
  443.    begin
  444.       coarPos <= 0;
  445.       finePos <= 0;
  446.       coarDet <= False;
  447.       fineDet <= False; // reset everything
  448.       fineInPipeQ.deq;
  449.       timeStatePipeQ.deq;
  450.       outQ.enq(FreqEstInT{control: Idle,
  451.   data1: fineInPipeQ.first,
  452.   data2: ?});
  453.       `ifdef debug_mode
  454.          $display("TimeEst.procTimeEstLT");
  455.       `endif
  456.    end // case: LTrans
  457.    endrule
  458.    method Action putCoarTimeIn(FPComplex#(SyncIntPrec,SyncFractPrec) coarTimeIn);
  459.    begin
  460.       coarTimeInQ.enq(coarTimeIn);
  461.       `ifdef debug_mode
  462.          $display("TimeEst.putCoarTimeIn");   
  463.       `endif
  464.    end
  465.    endmethod
  466.    method Action putFineTimeIn(FineTimeInT fineTimeIn);
  467.    begin
  468.       fineTimeInQ.enq(fineTimeIn);
  469.       `ifdef debug_mode
  470.          $display("TimeEst.putFineTimeIn");
  471.       `endif
  472.    end
  473.    endmethod
  474.      
  475.    method ActionValue#(FreqEstInT) getFreqEstIn();
  476.    begin
  477.       outQ.deq;
  478.       `ifdef debug_mode
  479.          $display("TimeEst.getFreqEstIn");
  480.       `endif
  481.       return outQ.first;
  482.    end
  483.    endmethod   
  484. endmodule   
  485. (* synthesize *)
  486. module [Module] mkFreqEstimator(FreqEstimator);
  487.    // Constants
  488.    Integer cordicPipe = valueOf(CORDICPipe);
  489.    Integer cordicIter = valueOf(CORDICIter);
  490.    Integer cordicStep = cordicIter/cordicPipe; // how many stages perform per cycle
  491.    Bit#(RotAngCounterSz) rotAngCounterReset = fromInteger(valueOf(SymbolLen) - 1);
  492.    Nat coarFreqOffAccumRShift = fromInteger(valueOf(CoarFreqOffAccumRShift));
  493.    Nat fineFreqOffAccumRShift = fromInteger(valueOf(FineFreqOffAccumRShift));
  494.    
  495.    // states
  496.    // fifo buffer
  497.    FIFO#(FreqEstInT) pipeQ <- mkSizedFIFO(cordicPipe+2);
  498.    FIFO#(FreqRotInT) outQ <- mkFIFO;
  499.    // shift registers
  500.    ShiftRegs#(FreqMeanLen, FixedPoint#(SyncIntPrec,SyncFractPrec)) freqOffAccumSub <- mkFreqEst_FreqOffAccumSub;  
  501.    // accumulators
  502.    Reg#(FixedPoint#(FreqOffAccumIntPrec,SyncFractPrec))   freqOffAccum <- mkReg(0);     // freq offset accumulators
  503.    Reg#(FixedPoint#(SyncIntPrec,SyncFractPrec))               freqOff <- mkReg(0);           // combined coar and fine freq off.
  504.    Reg#(FixedPoint#(SyncIntPrec,SyncFractPrec))               rotAng <- mkReg(0);            // the angle freq rot. should rotate for this sample
  505.    // counters
  506.    Reg#(Bit#(RotAngCounterSz))                        rotAngCounter <- mkReg(0);
  507.    // cordic
  508.    ArcTan#(CorrIntPrec,SyncFractPrec,SyncIntPrec,SyncFractPrec) cordic <- mkArcTan_Pipe(cordicIter,cordicStep); // cos and sin
  509.    rule procIdle(pipeQ.first.control == Idle || pipeQ.first.control == Dump);
  510.    begin
  511.       let reset = rotAngCounter == rotAngCounterReset;
  512.       let newRotAng = reset ? 0 : rotAng + freqOff;
  513.       pipeQ.deq;
  514.       rotAngCounter <= reset ? 0 : rotAngCounter +  1;
  515.       rotAng <= newRotAng;
  516.       outQ.enq(FreqRotInT{control: pipeQ.first.control,
  517.   data1: pipeQ.first.data1,
  518.   data2: rotAng});
  519.    end
  520.    endrule
  521.    rule procNotIdle(pipeQ.first.control != Idle && pipeQ.first.control != Dump);
  522.    begin
  523.       let cordicResult <- cordic.getArcTan;
  524.       let freqOffAccumAdd = negate(cordicResult); // get freq offset
  525.       let newFreqOffAccum = freqOffAccum + 
  526.     fxptSignExtend(freqOffAccumAdd) -
  527.     fxptSignExtend(freqOffAccumSub.first);
  528.       pipeQ.deq;
  529.       outQ.enq(FreqRotInT{control: pipeQ.first.control,
  530.   data1: pipeQ.first.data1,
  531.   data2: rotAng});
  532.       if (pipeQ.first.control != Collect)
  533. begin
  534.    let isShortSync = pipeQ.first.control == ShortSync;
  535.    let newFreqOff = isShortSync ? 
  536.     fxptTruncate(newFreqOffAccum >> coarFreqOffAccumRShift) : // reset to coar estimation
  537.     freqOff + fxptTruncate(newFreqOffAccum >> fineFreqOffAccumRShift); // combine coar and fine estimation
  538.    freqOff <= newFreqOff;
  539.    rotAng <= 0; // next sample rotate by 0
  540.    rotAngCounter <= 0;
  541.    freqOffAccum <= 0;     // clear
  542.    freqOffAccumSub.clear; // clear
  543. end
  544.       else
  545. begin
  546.    freqOffAccumSub.enq(freqOffAccumAdd);
  547.    rotAng <= rotAng + freqOff;
  548.    freqOffAccum <= newFreqOffAccum;
  549. end
  550.    end
  551.    endrule
  552.    method Action putFreqEstIn(FreqEstInT freqEstIn);
  553.    begin
  554.       pipeQ.enq(freqEstIn);
  555.       if (freqEstIn.control != Idle && freqEstIn.control != Dump)
  556. cordic.putXY(freqEstIn.data2.rel, freqEstIn.data2.img); // use cordic
  557.    end
  558.    endmethod
  559.      
  560.    method ActionValue#(FreqRotInT) getFreqRotIn;
  561.    begin
  562.       outQ.deq;
  563.       `ifdef debug_mode
  564.          $write("FreqEst.getFreqRotIn: control:%d, ",outQ.first.control);
  565.          cmplxWrite("data:("," + ","i), ",fxptWrite(7),outQ.first.data1);
  566.          $write("angle:");
  567.          fxptWrite(7, rotAng);
  568.          $display("");
  569.       `endif
  570.       return outQ.first;
  571.    end
  572.    endmethod
  573. endmodule
  574. (* synthesize *)
  575. module [Module] mkFreqRotator(FreqRotator);
  576.    // Integer constants
  577.    Integer cordicPipe = valueOf(CORDICPipe);
  578.    Integer cordicIter = valueOf(CORDICIter);
  579.    Integer cordicStep = cordicIter/cordicPipe; // how many stages perform per cycle
  580.    
  581.    // states
  582.        
  583.    // fifo buffers
  584.    FIFO#(FreqRotInT)  pipeQ <- mkSizedFIFO(cordicPipe+2);
  585.    FIFO#(FineTimeInT) outQ <- mkFIFO;
  586.    // cordic
  587.    CosAndSin#(SyncIntPrec,SyncFractPrec,SyncIntPrec,SyncFractPrec) cordic <- mkCosAndSin_Pipe(cordicIter,cordicStep); // cos and sin
  588.    
  589.    rule procRot(True);
  590.    begin
  591.       let freqRotIn = pipeQ.first;
  592.       let control = freqRotIn.control;
  593.       let inCmplx = freqRotIn.data1;
  594.       let rotAng = freqRotIn.data2;
  595.       let rotCosSinPair <- cordic.getCosSinPair;
  596.       FPComplex#(SyncIntPrec,SyncFractPrec) rotCmplx = fpcmplxTruncate(cmplx(rotCosSinPair.cos, rotCosSinPair.sin));
  597.       FPComplex#(SyncIntPrec,SyncFractPrec) outCmplx = fpcmplxTruncate(fpcmplxMult(inCmplx, rotCmplx));
  598.       pipeQ.deq;
  599.       outQ.enq(FineTimeInT{control: control,
  600.    data1: inCmplx,
  601.    data2: outCmplx});
  602.       `ifdef debug_mode
  603.          $write("FreqRot.procRot:");
  604.          fxptWrite(7, rotAng);
  605.          $display("");         
  606.          cmplxWrite("inputCmplx:("," + ","i)",fxptWrite(7),inCmplx);
  607.          $display("");
  608.          cmplxWrite("outCmplx:("," + ","i)",fxptWrite(7),outCmplx);
  609.          $display("");
  610.       `endif
  611.    end
  612.    endrule
  613.    
  614.    method Action putFreqRotIn(FreqRotInT freqRotIn);
  615.    begin
  616.       pipeQ.enq(freqRotIn);
  617.       let rotAng = freqRotIn.data2;    
  618.       cordic.putAngle(rotAng);
  619.    end
  620.    endmethod
  621.      
  622.    method ActionValue#(FineTimeInT) getFineTimeIn();
  623.    begin
  624.       outQ.deq;
  625.       return outQ.first;
  626.    end
  627.    endmethod   
  628. endmodule   
  629. (* synthesize *)
  630. module [Module] mkSynchronizer(Synchronizer#(SyncIntPrec,SyncFractPrec));
  631.    //input and output buffers
  632.    FIFO#(SynchronizerMesg#(SyncIntPrec,SyncFractPrec)) inQ <- mkLFIFO;
  633.    FIFO#(UnserializerMesg#(SyncIntPrec,SyncFractPrec)) outQ <- mkSizedFIFO(2);
  634.    // modules
  635.    TimeEstimator      timeEst <- mkTimeEstimator;
  636.    FreqEstimator      freqEst <- mkFreqEstimator;
  637.    FreqRotator        freqRot <- mkFreqRotator;
  638.    // register
  639.    Reg#(Bool)    lastLongSync <- mkReg(False); // set if the last output is longsync
  640.    rule inQToTimeEst(True);
  641.    begin
  642.       inQ.deq;
  643.       timeEst.putCoarTimeIn(inQ.first);
  644.    end
  645.    endrule
  646.    rule timeEstToFreqEst(True);
  647.    begin
  648.       let freqEstIn <- timeEst.getFreqEstIn;
  649.       freqEst.putFreqEstIn(freqEstIn);
  650.    end
  651.    endrule
  652.    rule freqEstToFreqRot(True);
  653.    begin
  654.       let freqRotIn <- freqEst.getFreqRotIn;
  655.       freqRot.putFreqRotIn(freqRotIn);
  656.    end
  657.    endrule
  658.    rule freqRotToTimeEst(True);
  659.    begin
  660.       let fineTimeIn <- freqRot.getFineTimeIn;
  661.       timeEst.putFineTimeIn(fineTimeIn);
  662.       lastLongSync <= (fineTimeIn.control == LongSync);
  663.       if (fineTimeIn.control != Dump)
  664.  begin
  665.     let syncCtrl = SyncCtrl{isNewPacket: lastLongSync,
  666.     cpSize: CP0};
  667.     outQ.enq(UnserializerMesg{control: syncCtrl,
  668.       data: fineTimeIn.data2});
  669.  end
  670.    end
  671.    endrule
  672.    
  673.    interface in = fifoToPut(inQ);
  674.    interface out = fifoToGet(outQ);
  675. endmodule