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截图如下:
===========================================================================
想知道这该怎么办,把键盘加进去的思路应该是怎样的? 你上面的代码中:
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是单片机啊? tangkuan660 发表于 2013-4-24 16:22 static/image/common/back.gif
你上面的代码中:
d
我以前都是那么做的,没出问题,所以没深入了解。我试试,一会反馈结果。 现在好久不高这个了,建议你用数据产生法做。。 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核实现,但是看完不是很明白。有没有拆分一个数的资料或者相关思路,谢谢你的回复。 很好奇你代码里怎么会有中文。
另外建议你可以用查表法生成相应的波形,把需要的各种波形数据提前建立好,存入rom里,需要用的时候就通过计数器查相应的地址就ok了 significance201 发表于 2013-4-24 16:39 static/image/common/back.gif
现在好久不高这个了,建议你用数据产生法做。。
“数据产生法”?能不能再具体一点 移位做除法 我发过一个自己做的帖子。
你可以看看
就是说把要产生的波形的数据模拟出来,让后输出,通过AD转换,就可以了。 流氓马 发表于 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 static/image/common/back.gif
还有什么问题的话,你继续问,待会可能就不在了
怎么看你的发的帖子,我的权限不够啊,只能看见“抱歉!由于 significance201 的隐私设置,您不能访问当前内容” 张sir 发表于 2013-4-24 17:02 static/image/common/back.gif
怎么看你的发的帖子,我的权限不够啊,只能看见“抱歉!由于 significance201 的隐私设置,您不能访问当 ...
哦,这样的话。。。。 你们是干什么东西呢?
本帖最后由 significance201 于 2013-4-24 17:08 编辑
我的那个仅供铲靠,看了你的要求,我做没有那么全压 东西我发给你吧。。 张sir 发表于 2013-4-24 16:57 static/image/common/back.gif
代码用notepad编辑就可以用中文注释啊。
数据就是提前采样好用ROM存储的,但现在问题不是这个,现在是如 ...
8楼不是说移位做除法么? aworker 发表于 2013-4-24 17:17 static/image/common/back.gif
8楼不是说移位做除法么?
我正在查看移位除法相关的资料,弄明白了再来回复 http://www.amobbs.com/forum.php?mod=viewthread&tid=5526405
帮楼上的那个哥们转的 还有 我这是第一次看到这种写法 单片机做多了吧 哈哈 /,%好像都很占资源。 lz这种代码能综合出什么电路啊a 综合出一大堆除法器啊!
这种用途应该交给单片机做,要不弄个嵌入软核也好。不过a家没有超小型的,只有x家有。。。 液晶显示部分用NIOS做吧 张sir 发表于 2013-4-24 17:36 我正在查看移位除法相关的资料,弄明白了再来回复
重要的不是怎么写除法器,而是怎么复用除法器。如果你只用一个除法器,就算你写个除号,综合器给你生成一个无流水的高速除法器也装得下。
叫你用个软核就是方便复用除法器。不然你得费很多脑筋来写一个复杂的状态机,以便只用一个除法器把整数拆成每一位。。。
省资源的除法器是每个时钟除一位的,其实你没必要自己从头发明轮子,各种除法器在那厂家库里都有,你用ip核向导生成一个就行了。
tennokoe 发表于 2013-4-24 22:51 液晶显示部分用NIOS做吧
nios对小fpga显得太重量级了一点,只为处理键盘显示太浪费。
还是x家好啊,嵌一个PicoBlaze的8位核心,只要96个slice,干这种事情很合算。 significance201 发表于 2013-4-24 17:14 static/image/common/back.gif
东西我发给你吧。。
我的权限太低,1个小时只能回复5次。。。昨天到后面没法回复了。谢谢你的帮助。 FPGA做乘法除法这些,会消耗极其多的资源 wildone 发表于 2013-4-25 10:42 static/image/common/back.gif
FPGA做乘法除法这些,会消耗极其多的资源
乘法不耗资源,都有硬乘法器了。FPGA的一个很重要的应用方向就是用它的硬乘法器做信号处理~
除法嘛,只能自己想方法了。。。
纯硬逻辑根本就不适合干这种显示拆数的事。相当于用高射炮打蚊子,费力不讨好
最好的方法是用高射炮里面的一小部分资源做出一个蚊子拍,呵呵,一下就搞定。。。
如果你是A家,没有小的蚊子拍,更好的做法是用个一两块钱的外置蚊子拍去打蚊子,留着高射炮的资源做更重要的事情{:lol:}
如果板上没有外置的蚊子拍,那就花高射炮里面很大一部分资源做一个大型的nios牌的蚊子拍吧,也能用{:tongue:} 感谢路上各位的提示和回复,现在问题已经解决,使用移位除法的思路处理的,话说那个什么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]