【问题标题】:How to Synthesize While Loop in Verilog?如何在 Verilog 中合成 While 循环?
【发布时间】:2013-09-27 18:03:22
【问题描述】:

我尝试设计一个 Booth 乘法器,它在所有编译器中运行良好,包括:

Modelsim、Verilogger Extreame、Aldec Active Hdl 和 Xilinx 的 Isim。.....

我知道模拟和综合是两个不同的过程,只有少数具有各种限制的 Verilog 结构可用于综合。但我不知道在我的程序中发生了什么 While loopSynopsys Synplify 9.6 以及 Xilinx ise 14.2 中不起作用。

当我尝试合成时 Synopsys"loop iteration limit 2000 exceeded"Xilinx' XST 说“This Xilinx application has run out of memory or has encountered a memory conflict"

我在下面附上了我的代码。 我也写了这个 其中 Synthesizer 由于 while loop 产生错误......

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////Author/Coder-Shrikant Vaishnav///////////////////////////////////////////////
/////////////////////////////////////////Design-Booth Algorithm Demonstration////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


module booth_synt(input wire [4:0]a,input wire [4:0]b,output reg signed[9:0] g);
reg signed[10:0]c;// One extra bit for sign bit.....I mean 11th bit.
//We used Signed Reg bcoz ASR fill vacant bit with MSB and then shift other for unsigned reg they fill it with zeros and then shift.. 
reg[4:0]d;
reg [4:0]e;
reg [2:0]count1; 
reg [2:0]count2; 
reg [2:0]count3; 
reg [2:0]count4; 

//Always start whenever any changes happens

always@(a,b)
 begin :close



//If's for sign bit check...
//Then 2's Complement...

count1=3'b000; //Initialize Counter
count2=3'b000;
count3=3'b000;
count4=3'b000;

//For negative
if(a[4]==1'b1) //Internal checking
  begin
  if(a==5'b10000)
    begin
     g[9:0]=10'b0000000000;
    end
  else
  begin
  d=~{1'b0,a[3],a[2],a[1],a[0]};  //we place 1'b0 because its inversion is 1   
  d=d+5'b00001;  //2's Complement we use additional register d for data holding.....bcoz wire not hold data
     if(d[4]==1'b0)//This "if" is used bcoz if due to calculation if accidently d[5]==1'b0 then this changs sign bit and thus ans
    begin
    d[4]=1'b1;
    end
    c[5:1]=d;
  end
  end

 if(b[4]==1'b1)
  begin 

   if(b==5'b10000)
    begin
     g[9:0]=10'b0000000000;
     disable close;
    end
  else
   begin
   e=~{1'b0,b[3],b[2],b[1],b[0]}; //we place 1'b0 because its inversion is 1
   e=e+5'b00001;
   if(e[4]==1'b0)//This "if" is used bcoz if due to calculation if accidently e[4]==1'b0 then this changs sign bit and thus ans
    begin
   e[4]=1'b1;
    end
   end
  end


//For positive 
if(b[4]==1'b0)
begin
e[4:0]=b[4:0];

end

if(a[4]==1'b0)
begin

c[1]=a[0];
c[2]=a[1]; //"a" is multiplier while "b" is multiplicand...
c[3]=a[2];
c[4]=a[3];
c[5]=a[4];

end



//Initialization of Output ........
c[0]=1'b0;

//All MSB's are Initially set to Zeros
c[6]=1'b0;
c[7]=1'b0;
c[8]=1'b0;
c[9]=1'b0;
c[10]=1'b0;



//Four Different Conditions Checking......
case({c[1],c[0]})

2'b00:begin   //Case 1

       while(count1<3'b101)  **<-------"Error Generated Here due to this while loop"**
      begin


         if({c[1],c[0]}==2'b10) //cond1 for 10
            begin
             c[10:6]=(c[10:6]-e[4:0]);
              c=c>>>1;
              count1=count1+1'b1;


            if(count1==3'b101)// Counter value check
             begin
               if(c[10]==1)
                 begin
                 c=~{1'b0,c[9],c[8],c[7],c[6],c[5],c[4],c[3],c[2],c[1],c[0]};//we place 1'b0 because its inversion is 1
                 c=c+10'b0000000010;
                 c[10]=1'b1; //Again giving 1 for surity
                 g[9:0]=c[10:1];

                 end

                 if(c[10]==0)
                 begin
                 c[10]=1'b0;
                 g[9:0]=c[10:1];

                 end
            end //end if==4
          end
          if(({c[1],c[0]}==2'b00) || ({c[1],c[0]}==2'b11))      //cond 2 in it we describe both 00 and11.........Arithemetic Right Shift operation
             begin
              c=c>>>1;     
              count1=count1+1'b1;                    


             if(count1==3'b101) // Counter value check
               begin
                if(c[10]==1)
                 begin
                 c=~{1'b0,c[9],c[8],c[7],c[6],c[5],c[4],c[3],c[2],c[1],c[0]};//we place 1'b0 because its inversion is 1
                 c=c+10'b0000000010;
                 c[10]=1'b1; //Again giving 1 for surity
                 g[9:0]=c[10:1];

                 end

                 if(c[10]==0)
                 begin
                 c[10]=1'b0;
                 g[9:0]=c[10:1];

                 end

              end
              end   

           if({c[1],c[0]}==2'b01) //cond3 for 01
            begin
             c[10:6]=(c[10:6]+e[4:0]);
              c=c>>>1;
              count1=count1+1'b1;


             if(count1==3'b101) // Counter value check
               begin
                if(c[10]==1)
                 begin
                 c=~{1'b0,c[9],c[8],c[7],c[6],c[5],c[4],c[3],c[2],c[1],c[0]};//we place 1'b0 because its inversion is 1
                 c=c+10'b0000000010;
                 c[10]=1'b1; //Again giving 1 for surity
                 g[9:0]=c[10:1];

                 end

                 if(c[10]==0)
                 begin
                 c[10]=1'b0;
                 g[9:0]=c[10:1];

             end
              end
              end
     end  

   end//while's end


 //Case2
 2'b11:begin
      while(count2<3'b101) **<-------"Error Generated Here due to this while loop"**
      begin



         if({c[1],c[0]}==2'b10) //cond1 for 10
            begin
             c[10:6]=(c[10:6]-e[4:0]);
              c=c>>>1;
              count2=count2+1'b1;


             if(count2==3'b101) // Counter value check
               begin
                if(c[10]==1)
                 begin
                 c=~{1'b0,c[9],c[8],c[7],c[6],c[5],c[4],c[3],c[2],c[1],c[0]};//we place 1'b0 because its inversion is 1
                 c=c+10'b0000000010;
                 c[10]=1'b1; //Again giving 1 for surity
                 g[9:0]=c[10:1];

                 end

                 if(c[10]==0)
                 begin
                 c[10]=1'b0;
                 g[9:0]=c[10:1];

              end
              end
              end

          if(({c[1],c[0]}==2'b00)||({c[1],c[0]}==2'b11))//cond 2 in it we describe both 00 and11.........Arithemetic Right Shift operation
             begin
              c=c>>>1;     
              count2=count2+1'b1;                    


             if(count2==3'b101)// Counter value check
               begin
                if(c[10]==1)
                 begin
                 c=~{1'b0,c[9],c[8],c[7],c[6],c[5],c[4],c[3],c[2],c[1],c[0]};//we place 1'b0 because its inversion is 1
                 c=c+10'b0000000010;
                 c[10]=1'b1; //Again giving 1 for surity  
                 g[9:0]=c[10:1];

                 end

                 if(c[10]==0)
                 begin
                 c[10]=1'b0;
                g[9:0]=c[10:1];

             end
              end
              end   

           if({c[1],c[0]}==2'b01) //cond3 for 01
            begin
            c[10:6]=(c[10:6]+e[4:0]);
              c=c>>>1;
              count2=count2+1'b1;


             if(count2==3'b101)// Counter value check
               begin
                 if(c[10]==1)
                 begin
                 c=~{1'b0,c[9],c[8],c[7],c[6],c[5],c[4],c[3],c[2],c[1],c[0]};//we place 1'b0 because its inversion is 1
                 c=c+10'b0000000010;
                 c[10]=1'b1; //Again giving 1 for surity 
                 g[9:0]=c[10:1];

                 end

                 if(c[10]==0)
                 begin
                 c[10]=1'b0;
                 g[9:0]=c[10:1];

              end
              end
             end
           end 
          end //while's end



  //Case 3
  2'b10:begin
     while(count3<3'b101) **<-------"Error Generated Here due to this while loop"**
      begin

     if({c[1],c[0]}==2'b10) //Cond1 for 10
            begin
             c[10:6]=(c[10:6]-e[4:0]);

              c=c>>>1;
              count3=count3+1'b1;


             if(count3==3'b101)// Counter value check
               begin
                if(c[10]==1)
                 begin
                 c=~{1'b0,c[9],c[8],c[7],c[6],c[5],c[4],c[3],c[2],c[1],c[0]};//we place 1'b0 because its inversion is 1
                 c=c+10'b0000000010;
                 c[10]=1'b1; //Again giving 1 for surity 
                 g[9:0]=c[10:1];

                 end

                 if(c[10]==0)
                 begin
                 c[10]=1'b0;
                 g[9:0]=c[10:1];

              end
              end
              end

          if(({c[1],c[0]}==2'b00)||({c[1],c[0]}==2'b11))//cond 2 in it we describe both 00 and11.........Arithemetic Right Shift operation
             begin
              c=c>>>1;     

              count3=count3+1'b1;                    


             if(count3==3'b101)// Counter value check
               begin
                if(c[10]==1)
                 begin
                 c=~{1'b0,c[9],c[8],c[7],c[6],c[5],c[4],c[3],c[2],c[1],c[0]};//we place 1'b0 because its inversion is 1
                 c=c+10'b0000000010;
                 c[10]=1'b1; //Again giving 1 for surity 
                 g[9:0]=c[10:1];

                 end

                 if(c[10]==0)
                 begin
                 c[10]=1'b0;
                 g[9:0]=c[10:1];

               end
              end
              end   

           if({c[1],c[0]}==2'b01) //cond3 for 01
            begin
             c[10:6]=(c[10:6]+e[4:0]); 

              c=c>>>1;
              count3=count3+1'd1;

             if(count3==3'b101)// Counter value check
               begin
                if(c[10]==1)
                 begin
                 c=~{1'b0,c[9],c[8],c[7],c[6],c[5],c[4],c[3],c[2],c[1],c[0]};//we place 1'b0 because its inversion is 1
                 c=c+10'b0000000010;
                 c[10]=1'b1; //Again giving 1 for surity 
                 g[9:0]=c[10:1];

                 end

                 if(c[10]==0)
                 begin
                 c[10]=1'b0;
                 g[9:0]=c[10:1];

                 end

               end
             end
           end 
          end //while's end



  //Case 4
  2'b01:begin
         while(count4<3'b101) **<-------"Error Generated Here due to this while loop"**
          begin

         if({c[1],c[0]}==2'b10) //cond1 for 10
            begin
             c[10:6]=(c[10:6]-e[4:0]);
              c=c>>>1;
              count4=count4+1'b1;


             if(count4==3'b101)// Counter value check
               begin
                if(c[10]==1)
                 begin
                 c=~{1'b0,c[9],c[8],c[7],c[6],c[5],c[4],c[3],c[2],c[1],c[0]};//we place 1'b0 because its inversion is 1
                 c=c+10'b0000000010;
                 c[10]=1'b1; //Again giving 1 for surity 
                 g[9:0]=c[10:1];

                 end

                 if(c[10]==0)
                 begin
                 c[10]=1'b0;
                 g[9:0]=c[10:1];

              end
              end
              end

          if(({c[1],c[0]}==2'b00)||({c[1],c[0]}==2'b11))//cond 2 in it we describe both 00 and11.........Arithemetic Right Shift operation
             begin
              c=c>>>1;     
              count4=count4+1'b1;                    


             if(count4==3'b101)// Counter value check
               begin
                if(c[10]==1)
                 begin
                 c=~{1'b0,c[9],c[8],c[7],c[6],c[5],c[4],c[3],c[2],c[1],c[0]};//we place 1'b0 because its inversion is 1
                 c=c+10'b0000000010;
                 c[10]=1'b1; //Again giving 1 for surity 
                 g[9:0]=c[10:1];

                 end

                 if(c[10]==0)
                 begin
                 c[10]=1'b0;
                 g[9:0]=c[10:1];

              end
              end
              end   

           if({c[1],c[0]}==2'b01) //cond3 for 01
            begin
             c[10:6]=(c[10:6]+e[4:0]);
              c=c>>>1;
              count4<=count4+1'b1;


             if(count4==3'b101)
               begin
                if(c[10]==1)
                 begin
                 c=~{1'b0,c[9],c[8],c[7],c[6],c[5],c[4],c[3],c[2],c[1],c[0]};//we place 1'b0 because its inversion is 1
                 c=c+10'b0000000010;
                 c[10]=1'b1; //Again giving 1 for surity 
                 g[9:0]=c[10:1];

                 end

                 if(c[10]==0)
                 begin
                 c[10]=1'b0;
                 g[9:0]=c[10:1];

                  end
                end
               end
              end  //while's end

          end//01's end  

   endcase //case end


end       //always end
endmodule

【问题讨论】:

  • 请尝试缩短您的代码以隔离问题。您更有可能得到答案。
  • 先生,请检查我的代码,我编辑了它,我还写了这个“由于这个 while 循环而在此处生成的错误”,其中错误是由合成器生成的(Synopsys Synplify 和 Xilinx 的 XST)...... .

标签: verilog system-verilog


【解决方案1】:

这是写得很糟糕的代码。你把它写得像一个计算机程序。 Verilog 是一种硬件描述语言,而不是一种编程语言。在您的情况下,合成器正在尝试在 case 语句的 while 循环内复制逻辑。

  • 在将硬件转换为 HDL 之前在纸上设计硬件
  • 在编码之前确定设计中的组合逻辑和时序逻辑。
  • 想想合成器将使用什么逻辑来实现您编写的逻辑。

【讨论】:

  • 为您尝试实现的逻辑绘制一个门/块级电路,并将其作为图像上传到您的问题。那我应该可以帮你。
【解决方案2】:

这里有一些提示:

  • 卸下闩锁:
    • c[5:1] 是一个锁存器,因为它没有在 if(a==5'b10000) 分支中初始化。
    • d 未在 if(a==5'b10000) 中定义,根据合成器优化功能可能是一个潜在的锁存器。
    • e 未在 if(b==5'b10000) 中定义,可能是像 d 这样的潜在闩锁。
    • 在always块的开头,确保所有的组合逻辑都有初始值。
  • 尽量避免使用disable 来合成代码。请改用 if-else 语句。
    • 注意:这是一个指导方针,而不是规则。
  • 有很多冗余且组织不善的代码:
    • case 语句中的所有分支都相同。应统一清理。
    • while 循环内有更适合循环外的代码(例如 if(count*==3'b101) 块)
  • 如果while 循环出现问题,请尝试for 循环。

【讨论】:

  • 格雷格先生为什么我不使用 For 而不是 While 因为在我的代码中,每当操作完成时,它们必须在那个时候增加......但是如果我使用 for 循环那么它是如何可能,如果我错了,请描述我如何使用 for 而不是 while...
  • 摩根在他的回答中很好地解释了while vs for 循环。
【解决方案3】:

While 循环往往暗示着一些动态的东西,比如检查一个条件。这不是用于综合的 verilog 的良好用途。 For 可以静态展开的循环更常用于缩短编写的代码。

如果您需要更动态的东西,则应编写专用状态机。

回答 cmets 中提出的一些问题:

组合逻辑使用assign 或包含在always @* 中,这是不断评估的,所有并行运行都认为AND、OR、NOR 门。

顺序逻辑将包含在always @( posedge clk ) 中,它在时钟的每个上升沿执行。其中使用的寄存器或内存元素通常代表触发器。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-11-03
    • 2022-06-14
    • 1970-01-01
    • 1970-01-01
    • 2015-11-22
    • 2016-11-27
    • 1970-01-01
    相关资源
    最近更新 更多