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

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 FIFO::*;
  27. import Monad::*;
  28. import Traceback::*;
  29. import Vector::*;
  30. import VParams::*;
  31. import VRegFile::*;
  32. import Parameters::*;
  33. //`define isDebug True // uncomment this line to display error
  34. // useful integers definitions
  35. Integer radix_sz = valueOf(RadixSz);
  36. Integer no_states = valueOf(VTotalStates);
  37. Integer fwd_steps = valueOf(FwdSteps);
  38. Integer fwd_entry_sz = valueOf(FwdEntrySz);
  39. Integer conv_in_sz = valueOf(ConvInSz);
  40. Integer conv_out_sz = valueOf(ConvOutSz);
  41. Integer vregs_out_sz = valueOf(VRegsOutSz);
  42. Integer half_max_metric_sum = valueOf(TExp#(TLog#(TAdd#(VMaxMetricSum,1))));
  43. Integer no_tbstage = valueOf(NoOfTBStage);
  44. //////////////////////////////////////////////////////////
  45. // begin of interface definitions
  46. /////////////////////////////////////////////////////////
  47. interface IViterbi;
  48.   method Action putData (VInType dataIn);
  49.   method ActionValue#(VOutType) getResult ();
  50. endinterface
  51. /////////////////////////////////////////////////////////
  52. // Begin of library functions and modules
  53. /////////////////////////////////////////////////////////
  54. function VState getNextState(VState state, Bit#(ConvInSz) nextBits);
  55.   let tmp = {nextBits, state};
  56.   return tpl_1(split(tmp)); // drop LSBs
  57. endfunction
  58. function VState getPrevState(VState state, Bit#(ConvInSz) prevBits);
  59.   let tmp = {state, prevBits};
  60.   return tpl_2(split(tmp)); // drop MSBs
  61. endfunction // ViterbiState
  62. function Vector#(ConvOutSz, Bit#(KSz)) getConvVec();
  63.       Vector#(ConvOutSz, Bit#(KSz)) outVec = newVector();
  64.       outVec[0] = convEncoderG1;
  65.       outVec[1] = convEncoderG2;
  66.       return outVec;
  67. endfunction // Vector
  68. // get the output of the convolutional encoder. convention is
  69. // {b, a} - meaning a is the low bit and b is the high bit
  70. function Vector#(ConvOutSz, Bit#(1)) getConvEncOutput (VState state, 
  71.        Bit#(ConvInSz) inBits);
  72.       Vector#(ConvOutSz, Bit#(KSz)) convVec = getConvVec();
  73.       Bit#(KSz) temp = {inBits, state};
  74.       Vector#(ConvOutSz, Bit#(1)) outVec = replicate(0);      
  75.       for(Integer idx = 0; idx < valueOf(ConvOutSz); idx = idx + 1)
  76. for(Integer bitNum = 0; bitNum < valueOf (KSz); bitNum = bitNum + 1)
  77.   outVec[idx] = outVec[idx] + (temp[bitNum] & convVec[idx][bitNum]);
  78.       return outVec;
  79. endfunction
  80. // this is used to calculate the index of data that i need to read
  81. function Vector#(sz, Integer) getIdxLUT (Integer conv_in_sz, Integer stage);
  82.       Integer v_sz = valueOf(sz);
  83.       Integer shift_sz = conv_in_sz * stage;
  84.       Integer mul_val = exp(2, shift_sz);
  85.       Integer div_val = v_sz / mul_val; 
  86.       Vector#(sz, Integer) outVec = newVector;
  87.       for (Integer i = 0; i < v_sz; i = i + 1)
  88.    outVec[i] = ((i % div_val) * mul_val) + (i / div_val); // performing a circular right shift
  89.       return outVec;
  90. endfunction
  91. // this actually perform the permutation
  92. function Vector#(sz, val_t) vPermute (Integer conv_in_sz, Integer stage, Vector#(sz, val_t) inVec);
  93.       
  94.       return map(select(inVec), getIdxLUT(conv_in_sz, stage));
  95. endfunction // Vector
  96. // this actually perform the reverse permutation 
  97. function Vector#(sz, val_t) reverseVPermute (Integer conv_in_sz, Integer stage, Vector#(sz, val_t) inVec);
  98.       Integer v_sz = valueOf(sz);      
  99.       Vector#(sz, val_t) outVec = newVector;
  100.       Vector#(sz, Integer) lut = getIdxLUT(conv_in_sz, stage);
  101.       for (Integer i = 0; i < v_sz; i = i + 1)
  102. outVec[lut[i]] = inVec[i];
  103.       return outVec;
  104. endfunction // Vector
  105. // this function is passed as a parameter to mkVRegFile
  106. function Vector#(out_sz, value_T) readSelect (Integer conv_in_sz,
  107.       Integer stage,
  108.       Bit#(sub_idx_sz) sidx, 
  109.       Vector#(row_sz, value_T) inVec)
  110.   provisos (Log#(out_sz, out_idx_sz),
  111.     Log#(row_sz, row_idx_sz),
  112.     Add#(sub_idx_sz, out_idx_sz, row_idx_sz));
  113.       Vector#(out_sz, value_T) outVec = newVector;
  114.       Vector#(row_sz, value_T) newInVec = vPermute(conv_in_sz, stage, inVec);
  115.       Nat shiftN = fromInteger(valueOf(out_idx_sz));
  116.       for (Integer i = 0; i < valueOf(out_sz); i = i + 1)
  117. begin
  118.    Bit#(out_idx_sz) idx1 = fromInteger(i);
  119.    Bit#(row_idx_sz) idx2 = zeroExtend(idx1) + (zeroExtend(sidx) << shiftN);
  120.    outVec[idx1] = newInVec[idx2];
  121. end
  122.       return outVec;
  123. endfunction
  124. // this function is passed as a parameter to mkVRegFile
  125. function Vector#(row_sz, value_T) reverseReadSelect (Integer conv_in_sz,
  126.      Integer stage,
  127.      Bit#(sub_idx_sz) sidx, 
  128.      Vector#(out_sz, value_T) inVec)
  129.   provisos (Log#(out_sz, out_idx_sz),
  130.     Log#(row_sz, row_idx_sz),
  131.     Add#(sub_idx_sz, out_idx_sz, row_idx_sz));
  132.       Vector#(row_sz, value_T) outVec = newVector;
  133.       Nat shiftN = fromInteger(valueOf(out_idx_sz));
  134.       for (Integer i = 0; i < valueOf(out_sz); i = i + 1)
  135. begin
  136.    Bit#(out_idx_sz) idx1 = fromInteger(i);
  137.    Bit#(row_idx_sz) idx2 = zeroExtend(idx1) + (zeroExtend(sidx) << shiftN);
  138.    outVec[idx2] = inVec[idx1];
  139. end
  140.       outVec = reverseVPermute(conv_in_sz, stage, outVec);      
  141.       return outVec;
  142. endfunction
  143. // this function passed as a parameter to mkVRegFile
  144. function Vector#(row_sz, value_T) writeSelect (Bit#(sub_idx_sz) sidx, 
  145.        Vector#(row_sz, value_T) inVec1,
  146.        Vector#(out_sz, value_T) inVec2)
  147.   provisos (Log#(out_sz, out_idx_sz),
  148.     Log#(row_sz, row_idx_sz),
  149.     Add#(sub_idx_sz, out_idx_sz, row_idx_sz));
  150.       Vector#(row_sz, value_T) outVec = inVec1;
  151.       Nat shiftN = fromInteger(valueOf(out_idx_sz));
  152.       for (Integer i = 0; i < valueOf(out_sz); i = i + 1)
  153. begin
  154.    Bit#(out_idx_sz) idx1 = fromInteger(i);
  155.    Bit#(row_idx_sz) idx2 = zeroExtend(idx1) + (zeroExtend(sidx) << shiftN);
  156.    outVec[idx2] = inVec2[idx1];
  157. end
  158.       return outVec;
  159. endfunction
  160. (* synthesize *)
  161. module mkMetricSums (VRegFile#(VRegsSubIdxSz,VRegsOutSz,VMetricSum));
  162.    
  163.    let vRegFile <- mkVRegFile(readSelect(conv_in_sz, fwd_steps),writeSelect, 0);
  164.    return vRegFile;
  165. endmodule // mkVRegFileFull
  166. (* synthesize *)
  167. module mkTrellis (VRegFile#(VRegsSubIdxSz,VRegsOutSz,VTrellisEntry));
  168.    let vRegFile <- mkVRegFile(readSelect(conv_in_sz, fwd_steps),writeSelect, 0);
  169.    return vRegFile;
  170. endmodule // mkVRegFileFull
  171. function VMetric getMetric(Bit#(1) in);
  172.       return ((in == 0) ? 0 : maxBound);
  173. endfunction // Metric
  174.       
  175. // generate the metric look up table
  176. // table index = {nextState, prevStateSuffix}
  177. (* noinline *)
  178. function MetricLUT getMetricLUT();
  179.       
  180.       MetricLUT outVec = newVector;
  181.       for (Integer next_state = 0; next_state < no_states; next_state = next_state + 1)
  182. begin
  183.    VState nextState = fromInteger(next_state);
  184.    Tuple2#(Bit#(ConvInSz), Bit#(TSub#(VStateSz, ConvInSz))) nsTup = split(nextState);
  185.    Bit#(ConvInSz) inBits = tpl_1(nsTup);
  186.    Bit#(TSub#(VStateSz, ConvInSz)) prevStatePrefix = tpl_2(nsTup);
  187.    for (Integer prev_state_suffix = 0; prev_state_suffix < radix_sz; prev_state_suffix = prev_state_suffix + 1)
  188.      begin
  189. Bit#(ConvInSz) prevStateSuffix = fromInteger(prev_state_suffix);
  190. VState prevState = {prevStatePrefix, prevStateSuffix};
  191. Vector#(ConvOutSz, Bit#(1)) convOut = getConvEncOutput(prevState, inBits);
  192. outVec[next_state*radix_sz + prev_state_suffix] = map(getMetric, convOut);
  193.      end
  194. end // for (Integer next_state = 0; next_state < no_states; next_state = next_state + 1)
  195.       return outVec;
  196. endfunction      
  197. function PrimEntry#(tEntry_T) chooseMin (PrimEntry#(tEntry_T) in1, 
  198.  PrimEntry#(tEntry_T) in2);
  199.       
  200.       return ((tpl_2(in1) - tpl_2(in2) < fromInteger(half_max_metric_sum)) ? in2 : in1); 
  201. endfunction // Tuple3
  202. // used for create a TB path
  203. function VTrellisEntry getNextTrellisEntry (VState prevState,
  204.     VState nextState,
  205.     VTrellisEntry oldTEntry);
  206.       Bit#(ConvInSz) inBit = tpl_1(split(nextState));
  207.       return tpl_1(split({inBit, oldTEntry})); // shift out LSBs
  208. endfunction // VTrellisEntry
  209. // used for create a TB col, MSB = oldest column
  210. function Bit#(VStateSuffixSz) getNextTB (VState prevState,
  211.  VState nextState,
  212.  Bit#(VStateSuffixSz) oldTEntry);
  213.       Bit#(ConvInSz) inBit = tpl_2(split(prevState));
  214.       return tpl_1(split({inBit, oldTEntry})); // shift out LSBs
  215. endfunction // VTrellisEntry
  216. function RadixEntry#(tEntry_T) radixCompute(RadixEntry#(tEntry_T) inVec,
  217.     Vector#(ConvOutSz, VMetric) inMetrics,
  218.     function tEntry_T getNextTEntry(VState prevState,
  219.     VState nextState,
  220.     tEntry_T oldTEntry));
  221.       function VMetricSum calcVMetricSum (VMetricSum inSum,
  222.   Vector#(ConvOutSz, Bit#(1)) expBits,
  223.   Vector#(ConvOutSz, VMetric) recMetrics);
  224.            Vector#(ConvOutSz, VMetricSum) addMetrics = newVector;
  225.            for (Integer i = 0; i < conv_out_sz; i = i + 1)
  226.      addMetrics[i] = zeroExtend(getMetric(expBits[i]) ^ recMetrics[i]); // |expMetric[i] - recMetrics[i]|
  227.            return inSum + fold(+ , addMetrics);
  228.       endfunction
  229.       
  230.       RadixEntry#(tEntry_T) outVec = newVector;
  231. //      MetricLUT metricLUT = getMetricLUT;
  232.       Bit#(TSub#(VStateSz, ConvInSz)) prevStatePrefix = tpl_1(split(tpl_1(inVec[0]))); // all input states must have the same prefix
  233.       RadixEntry#(tEntry_T) sumVec = newVector; // for calculating next result      
  234.       for (Integer in_bits = 0; in_bits < radix_sz; in_bits = in_bits + 1)
  235. begin
  236.    Bit#(ConvInSz) inBits = fromInteger(in_bits);
  237.    VState nextState = {inBits, prevStatePrefix};
  238.    for (Integer prev_state_suffix = 0; prev_state_suffix < radix_sz; prev_state_suffix = prev_state_suffix + 1)
  239.      begin
  240. // Bit#(KSz) lutIdx = (zeroExtend(nextState) << fromInteger(conv_in_sz)) + fromInteger(prev_state_suffix);
  241. sumVec[prev_state_suffix] = tuple3(tpl_1(inVec[prev_state_suffix]),  // same
  242.    calcVMetricSum(tpl_2(inVec[prev_state_suffix]),
  243.   getConvEncOutput(tpl_1(inVec[prev_state_suffix]), inBits),
  244. //   metricLUT[lutIdx],
  245.   inMetrics), // add 
  246.    tpl_3(inVec[prev_state_suffix])); // same
  247.      end
  248.    let minRadix = fold(chooseMin, sumVec);
  249.    let nextSum = tpl_2(minRadix);
  250.    let nextT = getNextTEntry(tpl_1(minRadix), nextState, tpl_3(minRadix));
  251.    outVec[in_bits] = tuple3(nextState, nextSum, nextT);
  252. end // for (Integer in_bits = 0; in_bits < radix_sz; in_bits = in_bits + 1)
  253.       return outVec;
  254. endfunction // unmatched end(function|task|module|primitive)
  255.       
  256. function FwdEntry#(tEntry_T) fwdCompute(FwdEntry#(tEntry_T) inVec,
  257. VInType inMetricsV,
  258. function tEntry_T getNextTEntry(VState prevState,
  259. VState nextState,
  260. tEntry_T oldTEntry));
  261.       
  262.       FwdEntry#(tEntry_T) outVec = inVec;
  263.       Integer no_radix = fwd_entry_sz / radix_sz; 
  264.       for (Integer stage = 0; stage < fwd_steps; stage = stage + 1)
  265. begin
  266.    RadixEntry#(tEntry_T) radixVec = newVector;
  267.    if (stage != 0)
  268.      outVec = readSelect(conv_in_sz, stage, 0, outVec); // permute if not the first step
  269.    for (Integer radix_idx = 0; radix_idx < no_radix; radix_idx = radix_idx + 1)
  270.      begin
  271. for (Integer k = 0; k < radix_sz; k = k + 1)
  272.   radixVec[k] = outVec[radix_idx*radix_sz+k];
  273.         radixVec = radixCompute(radixVec, inMetricsV[stage], getNextTEntry);
  274. for (Integer k = 0; k < radix_sz; k = k + 1)
  275.   outVec[radix_idx*radix_sz+k] = radixVec[k];
  276.      end // for (Integer j = 0; j < noOfRadix; j = j + 1)
  277.    if (stage != 0)
  278.      outVec = reverseReadSelect(conv_in_sz, stage, 0, outVec); // reverse the permutation if not the first step
  279. end // for (Integer i = 0; i < fwd_steps; i = i + 1)
  280.       return outVec;
  281.       
  282. endfunction // ForwardEntry
  283. // output the state with the minimum value and the new outentry
  284. function Tuple3#(VState, tEntry_T, VRegsOutEntry#(tEntry_T)) vRegsOutCompute(VRegsOutEntry#(tEntry_T) inVec,
  285.      VInType inMetricsV,
  286.      function tEntry_T getNextTEntry(VState prevState,
  287.      VState nextState,
  288.      tEntry_T oldTEntry));
  289.       
  290.       VRegsOutEntry#(tEntry_T) outVec = newVector;
  291.       Integer no_fwd_unit = vregs_out_sz / fwd_entry_sz;
  292.       FwdEntry#(tEntry_T) fwdVec = newVector;
  293.       for (Integer fwd_idx = 0; fwd_idx < no_fwd_unit; fwd_idx = fwd_idx + 1)
  294. begin
  295.    for (Integer k = 0; k < fwd_entry_sz; k = k + 1)
  296.      fwdVec[k] = inVec[fwd_idx * fwd_entry_sz + k];
  297.    fwdVec = fwdCompute(fwdVec, inMetricsV, getNextTEntry);
  298.    for (Integer k = 0; k < fwd_entry_sz; k = k + 1)
  299.      outVec[fwd_idx * fwd_entry_sz + k] = fwdVec[k];
  300. end // for (Integer j = 0; j < noOfRadix; j = j + 1)
  301.       let minPrimEntry = fold(chooseMin, outVec);
  302.       VState minState = tpl_1(minPrimEntry);
  303.       tEntry_T minTEntry = tpl_3(minPrimEntry);
  304.       return tuple3(minState, minTEntry, outVec);
  305.       
  306. endfunction // ForwardEntry
  307. (* noinline *)
  308. function Tuple3#(VState, VTrellisEntry, VRegsOutEntry#(VTrellisEntry)) vRegsOutComputeTBPath(VRegsOutEntry#(VTrellisEntry) inVec,
  309.      VInType inMetricsV);
  310.       
  311.       return vRegsOutCompute(inVec, inMetricsV, getNextTrellisEntry);
  312.       
  313. endfunction
  314. (* noinline *)
  315. function Tuple3#(VState, VTBEntry, VRegsOutEntry#(VTBEntry)) vRegsOutComputeTB(VRegsOutEntry#(VTBEntry) inVec,
  316.        VInType inMetricsV);
  317.       
  318.       return vRegsOutCompute(inVec, inMetricsV, getNextTB);
  319.       
  320. endfunction
  321. function Vector#(VRegsOutSz, VState) getNextStates(Bit#(VRegsSubIdxSz) stage);
  322.       Vector#(VRegsOutSz, VState) outVec = newVector;
  323.       VState subIdx = zeroExtend(stage) << fromInteger(valueOf(VRegsOutIdxSz));
  324.       for (Integer i = 0; i < valueOf(VRegsOutSz); i = i + 1)
  325. outVec[i] = subIdx + fromInteger(i);
  326.       return outVec;
  327.       
  328. endfunction // Vector
  329.       
  330.       
  331. /////////////////////////////////////////////////////////
  332. // Begin of Viterbi Module 
  333. /////////////////////////////////////////////////////////
  334. (*synthesize*)
  335. module mkIViterbiTBPath (IViterbi);
  336.    // states
  337.    FIFO#(VInType) inQ <- mkLFIFO;
  338.    FIFO#(VOutType) outQ <- mkSizedFIFO(2);
  339.    VRegFile#(VRegsSubIdxSz,VRegsOutSz,VMetricSum) metricSums <- mkMetricSums;
  340.    VRegFile#(VRegsSubIdxSz,VRegsOutSz,VTrellisEntry) trellis <- mkTrellis;
  341.    Reg#(Bit#(VRegsSubIdxSz)) stage <- mkReg(0);
  342.    Reg#(Bit#(1)) colIdx <- mkReg(0);
  343.    Reg#(VState)  curMinState <- mkReg(0);
  344.    Reg#(VTrellisEntry) curMinPath <- mkRegU;
  345.    Reg#(TBStageIdx)   tbStage <- mkReg(0); // keep track of whether we can output TB result yet
  346.    
  347.    rule processInput(True);
  348.    begin
  349.       let nextMSums = metricSums.sub(colIdx, stage);
  350.       let nextTrellis = trellis.sub(colIdx, stage);
  351.       let nextStates = getNextStates(stage);
  352.       let vRegsOutEntry = zip3(nextStates, nextMSums, nextTrellis);
  353.       let vRegsOutNew = vRegsOutComputeTBPath(vRegsOutEntry, inQ.first);
  354.       let minState = tpl_1(vRegsOutNew);
  355.       let minPath = tpl_2(vRegsOutNew);
  356.       let newMinState = (stage == 0 || minState < curMinState) ? minState : curMinState;
  357.       let newMinPath = (stage == 0 || minState < curMinState) ? minPath : curMinPath;
  358.       let newMSums = map(tpl_2, tpl_3(vRegsOutNew));
  359.       let newTrellis = map(tpl_3, tpl_3(vRegsOutNew));
  360.       Bit#(VStateSuffixSz) out = tpl_2(split(newMinPath));
  361.       VOutType vOut = unpack(out);
  362.       curMinState <= newMinState; // new min
  363.       curMinPath <= newMinPath;
  364.       stage <= stage + 1;
  365.       metricSums.upd(colIdx+1, stage, newMSums);
  366.       trellis.upd(colIdx+1, stage, newTrellis);
  367.       `ifdef isDebug
  368.          $display ("viterbi return: colIdx=%d stage=%d newMinState=%d, newMinPath=%h", colIdx, stage, newMinState, newMinPath);
  369.          $write ("viterbi return: newMSums=");
  370.          for (Integer i = 0; i < no_states; i = i + 1)
  371.    begin
  372.       $write ("%d: %d ", tpl_1(tpl_3(vRegsOutNew)[i]), newMSums[i]);
  373.    end
  374.          $display ("");
  375.          $write ("viterbi return: newTrellis=");
  376.  for (Integer i = 0; i < no_states; i = i + 1)
  377.    begin
  378.       $write ("%d: %h ", tpl_1(tpl_3(vRegsOutNew)[i]), newTrellis[i]);
  379.    end
  380.  $display ("");
  381.       `endif
  382.       if (stage == maxBound) // last stage, output trace back
  383. begin
  384.    inQ.deq;
  385.    if (tbStage == fromInteger(no_tbstage-1))
  386.      outQ.enq(vOut);
  387.    else
  388.      tbStage <= tbStage + 1;
  389.    colIdx <= colIdx + 1;
  390. end
  391.    end
  392.    endrule
  393.    
  394.    method Action putData (VInType dataIn);
  395.       inQ.enq(dataIn);
  396.    endmethod
  397.    method ActionValue#(VOutType) getResult ();
  398.       outQ.deq;
  399.       return outQ.first;
  400.    endmethod
  401.    
  402. endmodule
  403. (*synthesize*)
  404. module mkIViterbiTB (IViterbi);
  405.    // states
  406.    FIFO#(VInType) inQ <- mkLFIFO;
  407.    FIFO#(VOutType) outQ <- mkSizedFIFO(2);
  408.    VRegFile#(VRegsSubIdxSz,VRegsOutSz,VMetricSum) metricSums <- mkMetricSums;
  409.    Reg#(Vector#(VTotalStates, Bit#(1))) tbcol <- mkRegU; // save tb col
  410.    Reg#(Bit#(VRegsSubIdxSz)) stage <- mkReg(0);
  411.    Reg#(Bit#(1)) colIdx <- mkReg(0);
  412.    Reg#(VState)  curMinState <- mkReg(0);
  413.    Reg#(TBStageIdx)   tbStage <- mkReg(0); // keep track of whether we can output TB result yet
  414.    Traceback  tbu <- mkTraceback;
  415.    rule performACS(True);
  416.    begin
  417.       let nextMSums = metricSums.sub(colIdx, stage);
  418.       let nextTBEntry = newVector;
  419.       let nextStates = getNextStates(stage);
  420.       let vRegsOutEntry = zip3(nextStates, nextMSums, nextTBEntry);
  421.       let vRegsOutNew = vRegsOutComputeTB(vRegsOutEntry, inQ.first);
  422.       let minState = tpl_1(vRegsOutNew);
  423.       let newMinState = (stage == 0 || minState < curMinState) ? minState : curMinState;
  424.       let newMSums = map(tpl_2, tpl_3(vRegsOutNew));
  425.       let newTBEntry = map(tpl_3, tpl_3(vRegsOutNew));
  426.       let newTBCol = writeSelect(stage, tbcol, newTBEntry);
  427.       curMinState <= newMinState; // new min
  428.       stage <= stage + 1;
  429.       metricSums.upd(colIdx+1, stage, newMSums);
  430.       tbcol <= newTBCol; 
  431.       `ifdef isDebug
  432.          $display ("viterbi return: colIdx=%d stage=%d newMinState=%d", colIdx, stage, newMinState);
  433.          $write ("viterbi return: newMSums=");
  434.          for (Integer i = 0; i < no_states; i = i + 1)
  435.    begin
  436.       $write ("%d: %d ", tpl_1(tpl_3(vRegsOutNew)[i]), newMSums[i]);
  437.    end
  438.          $display ("");
  439.          $write ("viterbi return: newTBEntry=");
  440.  for (Integer i = 0; i < no_states; i = i + 1)
  441.    begin
  442.       $write ("%d: %h ", tpl_1(tpl_3(vRegsOutNew)[i]), newTBEntry[i]);
  443.    end
  444.  $display ("");
  445.       `endif
  446.       if (stage == maxBound) // last stage, output trace back
  447. begin
  448.    inQ.deq;
  449.    colIdx <= colIdx + 1;
  450.    tbu.updateMemory(vPermute(conv_in_sz, fwd_steps, newTBCol), newMinState); // put to traceback
  451. end
  452.    end
  453.    endrule
  454.    rule performTB(True);
  455.    begin
  456.       let result <- tbu.getDecodedOutput; //get result from tb
  457.       outQ.enq(unpack(pack(result)));
  458.    end
  459.    endrule
  460.    
  461.    method Action putData (VInType dataIn);
  462.       inQ.enq(dataIn);
  463.    endmethod
  464.    method ActionValue#(VOutType) getResult ();
  465.       outQ.deq;
  466.       return outQ.first;
  467.    endmethod
  468.    
  469. endmodule