verilog 程序编译问题
我要实现fre初值为10000,若按一下复位开关add,则fre*2;若按一下dec,则fre/2的操作,仿真出不来,如果减少一个敏感信号就可以,不知为啥,那位高手赐教,不胜感激module fre_set(add,dec,fre);
input add,dec;
output reg fre;
initial fre=1000000;
always@(negedge add or negedge dec)
begin
if(~add) fre=fre*2;
if(~dec) fre=fre/2;
else fre=fre;
end
endmodule 我换了一种方法改成这样 也不行
module fre_set(add,dec,fre);
input add,dec;
output reg fre;
reg num=0;
reg num1=0,num2=0;
initial fre=40;
always@(negedge add or negedge dec)
begin
if(~add) num1=num1+1;
if(~dec) num2=num2+1;
num=num1-num2;
end
always @(num)
begin
case(num)
-1: begin fre=fre/2;num=0; end
0:begin fre=fre;num=0; end
1:begin fre=fre*2;num=0; end
endcase
end
endmodule 先把 add 和 dec检测上升沿,然后
然后再时钟的上升沿去对计数器进行×和除乘除就用就直接取高位移动就可以 回复【2楼】Fourier00
-----------------------------------------------------------------------
具体程序怎样写啊? 我试了n多个方法,不是编译出错就是编译通过但没效果,感觉用单片机C51写就简简单单几句话的事到了verilog好难啊!! verilog比c语言简单多了记住这点你就可以写出好代码了
组合逻辑成这样
always@(*)
begin
yyy = zzzz zzzz
end
时序逻辑写成这样
always@(posedge clk or negedge rst_n)
begin
if(rst_n == 1'b0)
xxx <= xx'd0
else
xxx <=yyy
end 回复【4楼】Fourier00
-----------------------------------------------------------------------
嗯 谢谢 这个我知道
现在我的问题就是只能实现一个按键的操作(只能乘或只能除),仿真也是,把两个键综合在一起就不行了很是郁闷! 那你知道,那写出来的是时序逻辑还是组合逻辑,你知道你写的是什么电路吗 always@(negedge add or negedge dec)
begin
if(~add) num1=num1+1;
if(~dec) num2=num2+1;
num=num1-num2;
end
你能画一些这个电路吗? 应该属于时序逻辑啊 感觉我写verilog还没从c51的思维转换过来 都是用单片机的思想 呵呵! 回复【8楼】mowenhui28
-----------------------------------------------------------------------
你的程序,组合逻辑和时序逻辑混杂在一起,下降沿写的是时序,
后面又是组合逻辑
还有你的按钮根据按下就硬件高低电平的变化检测边沿,最好是用两个寄存器 if(~add) fre=fre*2;
if(~dec) fre=fre/2; 这个地方为什么要这样写呢?一般都这样写:
if(add==1'b0) fre=fre*2;
if(dec==1'b0) fre=fre/2; 【10楼】 msdy
没觉得那么写有啥问题啊…… 除号不可综合。自己写除法器。 回复【10楼】msdy
-----------------------------------------------------------------------
回复【12楼】ngzhang 兽哥
-----------------------------------------------------------------------
乘法用左移<<除法用右移>> 也可以呀 回复【9楼】edwin
-----------------------------------------------------------------------
两个寄存器的我改成这样了但编译通过,仿真、实际也都没出来啊!崩溃!!哪里有问题么?
module fre_set(clk,add,dec,fre);
input clk,add,dec;
output reg fre;
reg fre_add,fre_dec;
reg num1,num2;
initial fre=40;
always@(negedge add)
begin
if(~add) begin fre_add=fre*2;num1=1;end
else begin fre_add=fre_add;num1=0;end
end
always@(negedge dec)
begin
if(~dec) begin fre_dec=fre_dec/2;num2=1;end
else begin fre_dec=fre_dec;num2=0;end
end
always@(posedge clk)
begin
case({num1,num2})
2'b10:fre=fre_add;
2'b01:fre=fre_dec;
default:fre=fre;
endcase
end
endmodule 回复【14楼】mowenhui28
-----------------------------------------------------------------------
module fre_set(clk,add,dec,fre,rst);
input clk,add,dec,rst;
output fre;
reg fre,fre_p;
regadd_p, dec_p;
//reg fre_add,fre_dec;
//reg num1,num2;
//initial fre=40;
always@(posedge clk)//negedge add)
begin
if(rst) begin fre_p<=40;
add_p<=0;
dec_p<=0;
end
else begin fre<=fre_p;
add_p<=add;
dec_p<=dec;
end
end
always@(add or add_p ordec or dec_p or fre_p)
begin
//fre_p=fre;
if ( add_p ==1 && add ==0)
fre_p=fre_p*2;
else fre_p=fre_p;
if ( dec_p ==1 && dec ==0)
fre_p=(fre_p>>1);
else fre_p=fre_p;
end
/*
if(~dec) begin fre_dec=fre_dec/2;num2=1;end
else begin fre_dec=fre_dec;num2=0;end
end
always@(posedge clk)
begin
case({num1,num2})
2'b10:fre=fre_add;
2'b01:fre=fre_dec;
default:fre=fre;
endcase
end
*/
endmodule
我仿真可以,试试这个 奇怪 我按这个编译都报错啊而且你同一个fre_p怎么能在两个always里赋值呢? 我把
if(rst) beginfre_p<=40;
add_p<=0;
dec_p<=0;
end
这段放到initial里去了 编译通过 但仿真输出却是出 X(未知状态) 组合逻辑要和时序逻辑分开
我编译都通过了 仿真也可以啊
估计是你的TEST BENCH 的赋值有不确定的状态 回复【16楼】mowenhui28
-----------------------------------------------------------------------
http://cache.amobbs.com/bbs_upload782111/files_24/ourdev_520507.png
(原文件名:QQ截图未命名.png)
奇怪! 几个疑点:
1:initial 不能被综合吧?
2:除法和乘法不能直接用吧?可不像在单片机里面写C程序。。。。。。。 【19楼】 ygxycp
FPGA里面的initial如果用来赋初值或者加载RAM之类是可以综合的,但是请注意根据场合使用! 还是不行 我现在只能用另外的方式了就是用dec做拨码,拨1时按复位开关add做乘法,拨0时按add做除法,先只能这样了
看似简单的操作在verilog里还真麻烦 initial 不能被综合
乘法可以 除法不行
上次代码发的有点问题
module fre_set(clk,add,dec,fre,rst);
input clk,add,dec,rst;
output fre;
reg fre,fre_p;
regadd_p, dec_p;
always@(posedge clk)
begin
if(rst==1) begin
fre<=40;
add_p<=0;
dec_p<=0;
end
else begin fre<=fre_p;
add_p<=add;
dec_p<=dec;
end
end
always@(*)
begin
fre_p=fre;
//fre_p=fre;
if ( add_p ==1 && add ==0)
fre_p=fre_p*2;
else fre_p=fre_p;
if ( dec_p ==1 && dec ==0)
fre_p=(fre_p>>1);
else fre_p=fre_p;
end
endmodule 测试TB如下
module fre_tb;
// Inputs
reg clk;
reg add;
reg dec;
reg rst;
// Outputs
wire fre;
// Instantiate the Unit Under Test (UUT)
fre_set uut (
.clk(clk),
.add(add),
.dec(dec),
.fre(fre),
.rst(rst)
);
always#5clk=~clk ;
initial begin
// Initialize Inputs
clk = 0;
add = 0;
dec = 0;
rst = 0;
// Wait 100 ns for global reset to finish
#100;
rst = 1;
#100;
rst = 0;
add=1;
#100;
add=0;
#100;
dec=1;
#100;
dec=0;
#1000;
// Add stimulus here
end
endmodule OK! 可以啦按edwin的方法这个问题终于解决啦 不过测试TB那段是干啥的没看懂初学呵呵
不过你说initial不能综合但我加进去是可以的啊initial fre=40;
相当感谢 edwin 以及其他热心帮助我的朋友谢谢你们!! 那段就是仿真用的啊 ,你不用的啊?
那你怎么知道可以了不? 我是直接用波形仿真的啊硬件也实现啦 没用到测试TB啊 对于FPGA,initial一般是可以综合的,但是需要根据情况使用。
比如面向ASIC的时候就不能在可综合代码里面用initial来初始化,不过如果只是面向FPGA,确实有这个需要的话,
用initial是可以的。 不要在任何RTL代码中使用initail语句。该语句的使用会造成很多未知的问题。另外,大部分综合工具也不支持或对initail语句的综合的行为不好确定。包括:
ISE 11.3中的 XST,synplify pro 9.6.1,altera qantas2 。
以synplify pro 9.6.1来举例,如果在RTL代码中使用initail语句,工具会做出如下提示:
Initial statement will only initialize memories through the usage of $readmemh and $readmemb. Everything else is ignored
意思就是写了也白写。
在XST中,使用initial来赋初值,与直接写出逻辑复位的作用是不同的,如果目的是为了省掉复位逻辑,那我劝你不要这样做,往往会把时序电路变成含有latch的东西。
最后的建议就是,如果像我一样,自认为赶不上27楼的水平,就别让initial这个关键字出现在自己的rtl代码里。 关注
页:
[1]