在FPGA上总结许多东西的最佳方法

时间:2013-09-19 15:38:32

标签: verilog fpga

我在Virtex6上有一段代码,可以同时汇总一大堆东西。我继承了代码,看起来比我想象的要困难得多,但我被告知这是快速总结的最好方法。

基本上,如果我有一系列需要添加的值(比如16个),我们当前正在添加它们是多个级别(summedOutput和additionOverflow是两个函数来执行签名添加和检测溢出):< / p>

    tmpSig_0_0 <= summedOutput(inSig_0, inSig_1);
    tmpSig_0_1 <= summedOutput(inSig_2, inSig_3);
    tmpSig_0_2 <= summedOutput(inSig_4, inSig_5);
    tmpSig_0_3 <= summedOutput(inSig_6, inSig_7);
    tmpSig_0_4 <= summedOutput(inSig_8, inSig_9);
    tmpSig_0_5 <= summedOutput(inSig_10, inSig_11);
    tmpSig_0_6 <= summedOutput(inSig_12, inSig_13);
    tmpSig_0_7 <= summedOutput(inSig_14, inSig_15);
    overflow_stage0 <= (| {overflow_input,additionOverflow(inSig_0,inSig_1,inSig_0+inSig_1),additionOverflow(inSig_2,inSig_3,inSig_2+inSig_3),additionOverflow(inSig_4,inSig_5,inSig_4+inSig_5),additionOverflow(inSig_6,inSig_7,inSig_6+inSig_7),additionOverflow(inSig_8,inSig_9,inSig_8+inSig_9),additionOverflow(inSig_10,inSig_11,inSig_10+inSig_11),additionOverflow(inSig_12,inSig_13,inSig_12+inSig_13),additionOverflow(inSig_14,inSig_15,inSig_14+inSig_15)});    

    tmpSig_1_0 <= summedOutput(tmpSig_0_0, tmpSig_0_1);
    tmpSig_1_1 <= summedOutput(tmpSig_0_2, tmpSig_0_3);
    tmpSig_1_2 <= summedOutput(tmpSig_0_4, tmpSig_0_5);
    tmpSig_1_3 <= summedOutput(tmpSig_0_6, tmpSig_0_7);
    overflow_stage1 <= (| {overflow_stage0, additionOverflow(tmpSig_0_0,tmpSig_0_1,tmpSig_0_0+tmpSig_0_1), additionOverflow(tmpSig_0_2,tmpSig_0_3,tmpSig_0_2+tmpSig_0_3), additionOverflow(tmpSig_0_4,tmpSig_0_5,tmpSig_0_4+tmpSig_0_5), additionOverflow(tmpSig_0_6,tmpSig_0_7,tmpSig_0_6+tmpSig_0_7)});

    tmpSig_2_0 <= summedOutput(tmpSig_1_0, tmpSig_1_1);
    tmpSig_2_1 <= summedOutput(tmpSig_1_2, tmpSig_1_3);
    overflow_stage2 <= (| {overflow_stage1, additionOverflow(tmpSig_1_0,tmpSig_1_1,tmpSig_1_0+tmpSig_1_1), additionOverflow(tmpSig_1_2,tmpSig_1_3,tmpSig_1_2+tmpSig_1_3)});

    outSig <= summedOutput(tmpSig_2_0, tmpSig_2_1);
    overflow <= (| {overflow_stage2, additionOverflow(tmpSig_2_0, tmpSig_2_1, tmpSig_2_0+tmpSig_2_1)});

我被告知这将导致4级添加(这是有道理的),并且如果我刚刚完成,则比16级要好得多:

outSig <= inSig_0 + inSig_1 + inSig_2 + inSig_3 .... inSig_14 + inSig_15;

我的问题是,如果我想扩展内容,这是一个非常手动的过程,并不是很适应。这样做比我做的更聪明吗?最好的是一系列基于参数大小添加内容的for循环,但是我基本上会得到上面的第二个例子,这可能会非常深。

2 个答案:

答案 0 :(得分:2)

现有代码(长代码)和单行解决方案之间的主要区别在于现有代码被流水线化为4个时钟周期来计算结果,而您的单行解决方案旨在将所有数字添加到单个时钟周期。

根据这些inSig的宽度,可能无法满足尝试一次性添加它们的时间。您当然可以进行试验并用您的建议替换该代码,但是您应该尝试综合和P&amp; R并查看您的时间报告的样子。如果它符合您所需的定时频率,那么您可以继续安全地更换您的解决方案。

或者你可以尝试制作一个更清洁的浅管道(你可以在一个时钟周期中添加4个信号而不是2个吗?)

tmpSig_0 <= insig_0 + insig_1 + insig_2 + insig_3;
tmpSig_1 <= insig_4 + insig_5 + insig_6 + insig_7;
tmpSig_2 <= insig_8 + insig_9 + insig_10 + insig_11;
tmpSig_3 <= insig_12 + insig_13 + insig_14 + insig_15;

outSig   <= tmpSig_0 + tmpSig_1 + tmpSig_2 + tmpSig_3;

这将是一个5行,2阶段的管道,而不是更复杂的代码,但你需要检查它是否符合时序要求。

答案 1 :(得分:0)

生成循环如何?我没有测试过这段代码片段,但我在这里注意它是为了说明。

parameter num_of_additions = 16
genvar i,j,k;
generate
  begin 
  for (k=0;k<(num_of_additions>>3);k=k+1)
     begin : adder_l3
        tmp_sig_l3[k] = summedOutput(tmp_sig_l2[k], tmp_sig_l2[k+1));
        oflw_l3[k] = {additionOverflow (tmp_sig_l2[k*2],tmp_sig_l2[(k*2)+1],
                                        tmp_sig_l2[(k*2)]+tmp_sig_l2[(k*2)+1])};
     end : adder_l3

   for (j=0;j<(num_of_additions>>2);j=j+1)
     begin : adder_l2
        tmp_sig_l2[j] = summedOutput(tmp_sig_l1[j], tmp_sig_l1[j+1));
        oflw_l2[j] = {additionOverflow (tmp_sig_l1[j*2],tmp_sig_l1[(j*2)+1],
                                        tmp_sig_l1[(j*2)]+tmp_sig_l1[(j*2)+1])};
     end : adder_l2

   for (i=0;i<(num_of_additions >> 1);i=i+1)
      begin : adder_l1
        tmp_sig_l1[i] = summedOutput(inSig[i], inSig[i+1);
        oflw_l1[i] = {additionOverflow (inSig[i*2],inSig[(i*2)+1],
                                        inSig[(i*2)]+inSig[(i*2)+1])}
      end : adder_l1

   end


endgenerate


//this is not parameterized
assign outSig <= summedOutput(tmp_sig_l3[0], tmp_sig_l3[1]);
overflow <= (| {oflw_l3,oflw_l2,oflw_l1, additionOverflow(tmp_sig_l3[0],tmp_sig_l3[1],
                                                          tmp_sig_l3[0]+tmp_sig_l3[1])};
相关问题