张sir 发表于 2013-4-24 16:18:02

Verilog代码中if else语句占用资源问题

现在在用Alter FPGA做一个波形发生器,芯片型号EP2C5Q208C8,中间要用8个按键设置波形的一些参数,现在问题是加入下面这段键盘处理代码后,Quartus编译报告指出所用的用于实现组合逻辑的单元超出了芯片的资源,错误如下:
Error: Design contains 5638 blocks of type combinational node.However, device contains only 4608.
Compilation Report -Flow Summary截图如下

代码如下:
//其中h2l,h2l,h2l,h2l……等是键盘检测模块的输出,按键按下输出一个脉冲。//------------键盘响应--------------------------------
//----------------------------------------------------
always@(posedge clk,negedge rst_n)
if(!rst_n)begin
        alter<=0;//0-静止1-刷新
        rang<=0;//幅度 0-不加倍 1-加倍
        ft<=100;//频率初始值
        mode<=0;//0-工作,1-测试
        wtype<=0;//0-正弦波,1-三角波,2-方波,3-正锯齿波,4-负锯齿波
        val<=0;//测试初始值
        channel<=0;//通道
        led1<=1;
        {
        d, d,   d, d,   d, d,   d, d,   d, d,   d,d,d,d,d,d,
        d,d,d,d,d,d,d,d,d,d,d,d,d,d,d,d,
        d,d,d,d,d,d,d,d,d,d,d,d,d,d,d,d,
        d,d,d,d,d,d,d,d,d,d,d,d,d,d,d,d
        }<=tab_cn;
end
else if(h2l)//切换工作模式,
begin
        led1<=~led1;
        if(mode)begin
                {d,d,d,d}<="工作";
                mode<=0;
                end
        else begin
                {d,d,d,d}<="测试";
                mode<=1;
                end
        alter<=1;
end
else if(h2l)//改变波形
begin
        led1<=~led1;
        case(wtype)
        3'd0:begin
                {d,d,d,d,d,d,d}<="三角波 ";
                wtype<=3'd1;
                end
        3'd1:begin
                {d,d,d,d,d,d,d}<="方波   ";
                wtype<=3'd2;
                end
        3'd2:begin
                {d,d,d,d,d,d,d}<="锯齿波A";
                wtype<=3'd3;
                end
        3'd3:begin
                {d,d,d,d,d,d,d}<="锯齿波B";
                wtype<=3'd4;
                end
        3'd4:begin
                {d,d,d,d,d,d,d}<="正弦波 ";
                wtype<=3'd0;
                end
        endcase
        alter<=1;
end
else if(h2l)//递增测试模式时输入给DA的数值
begin
        led1<=~led1;
        val<=val+1;
        d<=val/100+8'h30;
        d<=val%100/10+8'h30;
        d<=val%10+8'h30;
        alter<=1;
end
else if(h2l)//递减测试模式时输入给DA的数值
begin
        led1<=~led1;
        val<=val-1;
        d<=val/100+8'h30;
        d<=val%100/10+8'h30;
        d<=val%10+8'h30;
        alter<=1;       
end
else if(h2l)//递增频率
begin
        led1<=~led1;
        ft<=ft+1;
        d<=ft/1000000%10+8'h30;       
        d<=ft/100000%10+8'h30;
        d<=ft/10000%10+8'h30;
        d<=ft/1000%10+8'h30;       
        d<=ft/100%10+8'h30;
        d<=ft/10%10+8'h30;
        d<=ft/1%10+8'h30;
        alter<=1;       
end
else if(h2l)//递减频率
begin
        led1<=~led1;
        ft<=ft-1;
        d<=ft/1000000%10+8'h30;       
        d<=ft/100000%10+8'h30;
        d<=ft/10000%10+8'h30;
        d<=ft/1000%10+8'h30;       
        d<=ft/100%10+8'h30;
        d<=ft/10%10+8'h30;
        d<=ft/1%10+8'h30;
        alter<=1;       
end
else if(h2l)//改变输出电压幅度
begin
        led1<=~led1;
        rang<=~rang;
        if(rang)begin
                {d,d,d}<="2.5";
        end
        else begin
                {d,d,d}<="5.0";
        end
        alter<=1;
end
else if(h2l)//切换输出
begin
        led1<=~led1;
        case(channel)
        2'b00:begin
                        d<="B";
                        channel<=3'd1;
                end
        2'b01:begin
                        d<="C";
                        channel<=3'd2;
                end
        2'b10:begin
                        d<="D";
                        channel<=3'd3;
                end
        2'b11:begin
                        d<="A";
                        channel<=3'd0;
                end
        endcase
        alter<=1;
end
else begin
        alter<=0;
end
================尝试解决之后结果==========================================
经过查资料发现应该是键盘处理这一块 if else 语句嵌套太多造成的,于是采用case语句,主要思路是每个时钟沿先进行keyval={h2l,h2l,h2l,h2l,h2l,h2l,h2l,h2l};然后case(keyval),但是编译结果还是说资源不够,错误如下:
Error: Design contains 5644 blocks of type combinational node.However, device contains only 4608.
Compilation Report -Flow Summary截图如下:

修改后代码如下:always@(posedge clk,negedge rst_n)
if(!rst_n)begin
        alter<=0;//0-静止1-刷新
        rang<=0;//幅度 0-不加倍 1-加 ?
        ft<=100;
        mode<=0;//0-工作,1-测试
        wtype<=0;//0-正弦波,1-三角波,2-方波,3-正锯齿波,4-负锯齿波
        val<=0;
        channel<=0;
        led1<=1;
        {
        d, d,   d, d,   d, d,   d, d,   d, d,   d,d,d,d,d,d,
        d,d,d,d,d,d,d,d,d,d,d,d,d,d,d,d,
        d,d,d,d,d,d,d,d,d,d,d,d,d,d,d,d,
        d,d,d,d,d,d,d,d,d,d,d,d,d,d,d,d
        }<=tab_cn;
        keyval<=0;
end
else begin
        keyval={h2l,h2l,h2l,h2l,h2l,h2l,h2l,h2l};
        case(keyval)
                8'h80:begin
                        led1<=~led1;
                        case(channel)
                        2'b00:begin
                                        d<="B";
                                        channel<=3'd1;
                                end
                        2'b01:begin
                                        d<="C";
                                        channel<=3'd2;
                                end
                        2'b10:begin
                                        d<="D";
                                        channel<=3'd3;
                                end
                        2'b11:begin
                                        d<="A";
                                        channel<=3'd0;
                                end
                        endcase
                        alter<=1;
                end
                8'h40:begin
                        led1<=~led1;
                        ft<=ft-1;
                        d<=ft/1000000%10+8'h30;       
                        d<=ft/100000%10+8'h30;
                        d<=ft/10000%10+8'h30;
                        d<=ft/1000%10+8'h30;       
                        d<=ft/100%10+8'h30;
                        d<=ft/10%10+8'h30;
                        d<=ft/1%10+8'h30;
                        alter<=1;       
                end
                8'h20:begin
                        led1<=~led1;
                        val<=val-1;
                        d<=val/100+8'h30;
                        d<=val%100/10+8'h30;
                        d<=val%10+8'h30;
                        alter<=1;       
                end
                8'h10:begin
                        led1<=~led1;
                        case(wtype)
                        3'd0:begin
                                {d,d,d,d,d,d,d}<="三角波 ";
                                wtype<=3'd1;
                                end
                        3'd1:begin
                                {d,d,d,d,d,d,d}<="方波   ";
                                wtype<=3'd2;
                                end
                        3'd2:begin
                                {d,d,d,d,d,d,d}<="锯齿波A";
                                wtype<=3'd3;
                                end
                        3'd3:begin
                                {d,d,d,d,d,d,d}<="锯齿波B";
                                wtype<=3'd4;
                                end
                        3'd4:begin
                                {d,d,d,d,d,d,d}<="正弦波 ";
                                wtype<=3'd0;
                                end
                        endcase
                        alter<=1;
                end
                8'h08:begin
                                led1<=~led1;
                                rang<=~rang;
                                if(rang)begin
                                        {d,d,d}<="2.5";
                                end
                                else begin
                                        {d,d,d}<="5.0";
                                end
                                alter<=1;
                end
                8'h04:begin
                        led1<=~led1;
                        ft<=ft+1;
                        d<=ft/1000000%10+8'h30;       
                        d<=ft/100000%10+8'h30;
                        d<=ft/10000%10+8'h30;
                        d<=ft/1000%10+8'h30;       
                        d<=ft/100%10+8'h30;
                        d<=ft/10%10+8'h30;
                        d<=ft/1%10+8'h30;
                        alter<=1;       
                        end
                8'h02:begin
                        led1<=~led1;
                        val<=val+1;
                        d<=val/100+8'h30;
                        d<=val%100/10+8'h30;
                        d<=val%10+8'h30;
                        alter<=1;
                end
                8'h01:begin
                        led1<=~led1;
                        if(mode)begin
                                {d,d,d,d}<="工作";
                                mode<=0;
                                end
                        else begin
                                {d,d,d,d}<="测试";
                                mode<=1;
                                end
                        alter<=1;
                end
                default:alter<=0;
        endcase
end
===========================================================================
如果把上面那一段代码屏蔽掉,能编译通过,Compilation Report -Flow Summary截图如下:

===========================================================================
想知道这该怎么办,把键盘加进去的思路应该是怎样的?

tangkuan660 发表于 2013-4-24 16:22:35

你上面的代码中:
   d<=ft/1000000%10+8'h30;      
                        d<=ft/100000%10+8'h30;
                        d<=ft/10000%10+8'h30;
                        d<=ft/1000%10+8'h30;      
                        d<=ft/100%10+8'h30;
                        d<=ft/10%10+8'h30;
                        d<=ft/1%10+8'h30;
这些,FPGA是很难用逻辑资源实现的,你当FPGA是单片机啊?

张sir 发表于 2013-4-24 16:24:52

tangkuan660 发表于 2013-4-24 16:22 static/image/common/back.gif
你上面的代码中:
   d

我以前都是那么做的,没出问题,所以没深入了解。我试试,一会反馈结果。

significance201 发表于 2013-4-24 16:39:49

现在好久不高这个了,建议你用数据产生法做。。

张sir 发表于 2013-4-24 16:46:32

tangkuan660 发表于 2013-4-24 16:22 static/image/common/back.gif
你上面的代码中:
   d

确实是这里的问题,注释掉下面的代码就能编译通过,TE占用55%
//        d<=ft/1000000%10+8'h30;       
//        d<=ft/100000%10+8'h30;
//        d<=ft/10000%10+8'h30;
//        d<=ft/1000%10+8'h30;       
//        d<=ft/100%10+8'h30;
//        d<=ft/10%10+8'h30;
//        d<=ft/1%10+8'h30;
但是这段代码的功能该怎么实现呢?我这里要实现的就是按键改变ft的值,然后12864点阵屏显示出ft的值,这样就必须对ft进行拆分,如果不这么拆分该怎样实现拆分?在博客园找了一篇文章(百度“ Verilog 拆分一个数”,不让发链接,刚才编辑的回复失败了。)说是用IP核实现,但是看完不是很明白。有没有拆分一个数的资料或者相关思路,谢谢你的回复。

流氓马 发表于 2013-4-24 16:52:40

很好奇你代码里怎么会有中文。
另外建议你可以用查表法生成相应的波形,把需要的各种波形数据提前建立好,存入rom里,需要用的时候就通过计数器查相应的地址就ok了

张sir 发表于 2013-4-24 16:53:36

significance201 发表于 2013-4-24 16:39 static/image/common/back.gif
现在好久不高这个了,建议你用数据产生法做。。

“数据产生法”?能不能再具体一点

zjykwym 发表于 2013-4-24 16:56:20

移位做除法

significance201 发表于 2013-4-24 16:57:16

我发过一个自己做的帖子。
你可以看看
就是说把要产生的波形的数据模拟出来,让后输出,通过AD转换,就可以了。

张sir 发表于 2013-4-24 16:57:43

流氓马 发表于 2013-4-24 16:52 static/image/common/back.gif
很好奇你代码里怎么会有中文。
另外建议你可以用查表法生成相应的波形,把需要的各种波形数据提前建立好, ...

代码用notepad编辑就可以用中文注释啊。
数据就是提前采样好用ROM存储的,但现在问题不是这个,现在是如何拆分那个ft,就是实现下面代码的功能,将ft拆分成个,十,百,千……然后转换为ASCII显示在液晶屏上,下面的这种写法很耗资源。。。。
      d<=ft/1000000%10+8'h30;      
      d<=ft/100000%10+8'h30;
      d<=ft/10000%10+8'h30;
      d<=ft/1000%10+8'h30;      
      d<=ft/100%10+8'h30;
      d<=ft/10%10+8'h30;
      d<=ft/1%10+8'h30;

significance201 发表于 2013-4-24 16:58:12

还有什么问题的话,你继续问,待会可能就不在了

张sir 发表于 2013-4-24 17:02:39

significance201 发表于 2013-4-24 16:58 static/image/common/back.gif
还有什么问题的话,你继续问,待会可能就不在了

怎么看你的发的帖子,我的权限不够啊,只能看见“抱歉!由于 significance201 的隐私设置,您不能访问当前内容”

significance201 发表于 2013-4-24 17:03:58

张sir 发表于 2013-4-24 17:02 static/image/common/back.gif
怎么看你的发的帖子,我的权限不够啊,只能看见“抱歉!由于 significance201 的隐私设置,您不能访问当 ...

哦,这样的话。。。。

significance201 发表于 2013-4-24 17:04:37

你们是干什么东西呢?

significance201 发表于 2013-4-24 17:06:12

本帖最后由 significance201 于 2013-4-24 17:08 编辑

我的那个仅供铲靠,看了你的要求,我做没有那么全压

significance201 发表于 2013-4-24 17:14:46

东西我发给你吧。。

aworker 发表于 2013-4-24 17:17:12

张sir 发表于 2013-4-24 16:57 static/image/common/back.gif
代码用notepad编辑就可以用中文注释啊。
数据就是提前采样好用ROM存储的,但现在问题不是这个,现在是如 ...

8楼不是说移位做除法么?

张sir 发表于 2013-4-24 17:36:25

aworker 发表于 2013-4-24 17:17 static/image/common/back.gif
8楼不是说移位做除法么?

我正在查看移位除法相关的资料,弄明白了再来回复

jlhgold 发表于 2013-4-24 21:05:07

http://www.amobbs.com/forum.php?mod=viewthread&tid=5526405
帮楼上的那个哥们转的

jlhgold 发表于 2013-4-24 21:05:38

还有 我这是第一次看到这种写法 单片机做多了吧 哈哈

sky_prince 发表于 2013-4-24 21:15:09

/,%好像都很占资源。

Fourier00 发表于 2013-4-24 22:08:18

lz这种代码能综合出什么电路啊a

redroof 发表于 2013-4-24 22:34:39

综合出一大堆除法器啊!
这种用途应该交给单片机做,要不弄个嵌入软核也好。不过a家没有超小型的,只有x家有。。。

tennokoe 发表于 2013-4-24 22:51:58

液晶显示部分用NIOS做吧

redroof 发表于 2013-4-25 07:33:19

张sir 发表于 2013-4-24 17:36 我正在查看移位除法相关的资料,弄明白了再来回复

重要的不是怎么写除法器,而是怎么复用除法器。如果你只用一个除法器,就算你写个除号,综合器给你生成一个无流水的高速除法器也装得下。
叫你用个软核就是方便复用除法器。不然你得费很多脑筋来写一个复杂的状态机,以便只用一个除法器把整数拆成每一位。。。
省资源的除法器是每个时钟除一位的,其实你没必要自己从头发明轮子,各种除法器在那厂家库里都有,你用ip核向导生成一个就行了。

redroof 发表于 2013-4-25 07:52:03

tennokoe 发表于 2013-4-24 22:51 液晶显示部分用NIOS做吧

nios对小fpga显得太重量级了一点,只为处理键盘显示太浪费。
还是x家好啊,嵌一个PicoBlaze的8位核心,只要96个slice,干这种事情很合算。

张sir 发表于 2013-4-25 10:32:54

significance201 发表于 2013-4-24 17:14 static/image/common/back.gif
东西我发给你吧。。

我的权限太低,1个小时只能回复5次。。。昨天到后面没法回复了。谢谢你的帮助。

wildone 发表于 2013-4-25 10:42:51

FPGA做乘法除法这些,会消耗极其多的资源

redroof 发表于 2013-4-25 10:51:54

wildone 发表于 2013-4-25 10:42 static/image/common/back.gif
FPGA做乘法除法这些,会消耗极其多的资源

乘法不耗资源,都有硬乘法器了。FPGA的一个很重要的应用方向就是用它的硬乘法器做信号处理~
除法嘛,只能自己想方法了。。。
纯硬逻辑根本就不适合干这种显示拆数的事。相当于用高射炮打蚊子,费力不讨好
最好的方法是用高射炮里面的一小部分资源做出一个蚊子拍,呵呵,一下就搞定。。。
如果你是A家,没有小的蚊子拍,更好的做法是用个一两块钱的外置蚊子拍去打蚊子,留着高射炮的资源做更重要的事情{:lol:}
如果板上没有外置的蚊子拍,那就花高射炮里面很大一部分资源做一个大型的nios牌的蚊子拍吧,也能用{:tongue:}

张sir 发表于 2013-4-25 10:53:36

感谢路上各位的提示和回复,现在问题已经解决,使用移位除法的思路处理的,话说那个什么IP我不会用(只用过ROM,PLL之类的),只好自己写一个module,参考了CSDN上的一篇文章,百度“用+,-,移位实现除法运算”就能看到(被催的我权限不够发链接只能这样了),那个是用C语言写的,思路很容易看明白。我没有写那种完全的除法模块,就是一个拆分模块,比如把20‘d1048575拆分成1、0、4、8、5、7、5,然后就可以加上0x30转换成ASCII了。。以前确实是经常写单片机的代码,遇到这种情况就想当然写了。。模块中的思路就是做减法,比如将328拆分就先用328减去100,判断结果和100的关系,并累加cnt_subtr,直到结果小于100时,则cnt_subtr就是百位,具体到这个例子中只需减2次就停止了,后面的情况类推。模块通过en_divid的脉冲触发开始转换,转换完毕done会输出脉冲,只能转换reg范围的数字,添加这个模块之前和之后Quartus编译结果中LE分别是2510(54%)2819(61%)。下面附上代码,仿真截图等方便自己也方便有需要的人
==========================拆分模块==============================================module divider(
input clk,rst_n,en_divid,
input dividend,//an impulse start the exchange
output reg q6,        //q6=dividend/1000000%10
output reg q5,        //q5=dividend/100000%10
output reg q4,        //q4=dividend/10000%10
output reg q3,        //q3=dividend/1000%10
output reg q2,        //q2=dividend/100%10
output reg q1,        //q1=dividend/10%10
output reg q0,        //q0=dividend/1%10
output reg done        //finished flag,when exchange finished an impulse will occur
);

parameter base_0=10;
parameter base_1=100;
parameter base_2=1000;
parameter base_3=10000;
parameter base_4=100000;
parameter base_5=1000000;
parameter base_6=10000000;

reg left_num; //store the remained number
reg state,cnt_subtr;

always@(posedge clk,negedge rst_n)
if(!rst_n)
begin
state<=0;
cnt_subtr<=0;
left_num<=0;
q6<=0;
q5<=0;
q4<=0;
q3<=0;
q2<=0;
q1<=0;
q0<=0;
done<=0;
end
else begin
case(state)
    0:begin//
      if(en_divid)begin
      state<=8;
      left_num<=dividend;
      end
      done<=0;
      cnt_subtr<=0;
    end
    1:begin
      q0<=left_num;
      cnt_subtr<=cnt_subtr+1;
      if(cnt_subtr)begin
      done<=1;      
      state<=state-1;//wait for one clock
      end
    end
    2:begin//
      if(left_num<base_0)begin
          q1<=cnt_subtr;
          state<=state-1;
          cnt_subtr<=0;
      end
      else begin
          left_num<=left_num-base_0;
          cnt_subtr<=cnt_subtr+1;   
      end      
    end
    3:begin//
      if(left_num<base_1)begin
          q2<=cnt_subtr;
          state<=state-1;
          cnt_subtr<=0;
      end
      else begin
          left_num<=left_num-base_1;
          cnt_subtr<=cnt_subtr+1;   
      end
    end
    4:begin//
      if(left_num<base_2)begin
          q3<=cnt_subtr;
          state<=state-1;
          cnt_subtr<=0;
      end
      else begin
          left_num<=left_num-base_2;
          cnt_subtr<=cnt_subtr+1;   
      end   
    end
    5:begin//
      if(left_num<base_3)begin
          q4<=cnt_subtr;
          state<=state-1;
          cnt_subtr<=0;
      end
      else begin
          left_num<=left_num-base_3;
          cnt_subtr<=cnt_subtr+1;   
      end
    end
    6:begin//
      if(left_num<base_4)begin
          q5<=cnt_subtr;
          state<=state-1;
          cnt_subtr<=0;
      end
      else begin
          left_num<=left_num-base_4;
          cnt_subtr<=cnt_subtr+1;   
      end   
    end
    7:begin//
      if(left_num<base_5)begin
          q6<=cnt_subtr;
          state<=state-1;
          cnt_subtr<=0;
      end
      else begin
          left_num<=left_num-base_5;
          cnt_subtr<=cnt_subtr+1;   
      end   
    end
    8:begin//
      if(left_num<base_6)begin
          //q6<=cnt_subtr;
          state<=state-1;
          cnt_subtr<=0;
      end
      else begin
          left_num<=left_num-base_6;
          cnt_subtr<=cnt_subtr+1;   
      end
    end
    endcase
end

endmodule
   
==========================测试文件==============================================`timescale 1ps/1ps
module divide_T;
reg clk,rst_n,en_divid;
reg dividend;
wire q6,q5,q4,q3,q2,q1,q0;
wire done;
divider UT_divid(
    clk,rst_n,en_divid,
    dividend,
    q6,q5,q4,q3,q2,q1,q0,done
);
always #1 clk=~clk;
initial
begin
clk<=0;
rst_n<=1;
en_divid<=0;
dividend<=20'd1048575;
#5 rst_n<=0;
#5 rst_n<=1;
#10;
en_divid<=1;
#3 en_divid<=0;
#90;
dividend<=20'd924187;
en_divid<=1;
#3 en_divid<=0;
end
endmodule
==========================仿真结果==============================================
页: [1]
查看完整版本: Verilog代码中if else语句占用资源问题