搜索
bottom↓
回复: 29

verilog 程序编译问题

[复制链接]

出0入0汤圆

发表于 2009-12-27 11:19:56 | 显示全部楼层 |阅读模式
我要实现fre初值为10000,若按一下复位开关add,则fre*2;若按一下dec,则fre/2的操作,仿真出不来,如果减少一个敏感信号就可以,不知为啥,那位高手赐教,不胜感激

module fre_set(add,dec,fre);
input add,dec;
output reg[25:0] 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

阿莫论坛20周年了!感谢大家的支持与爱护!!

一只鸟敢站在脆弱的枝条上歇脚,它依仗的不是枝条不会断,而是自己有翅膀,会飞。

出0入0汤圆

 楼主| 发表于 2009-12-27 11:25:07 | 显示全部楼层
我换了一种方法改成这样 也不行
module fre_set(add,dec,fre);
input add,dec;
output reg [12:0] fre;
reg [3:0] num=0;
reg [1:0] 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

出0入0汤圆

发表于 2009-12-27 14:30:07 | 显示全部楼层
先把 add 和 dec检测上升沿,然后
然后再时钟的上升沿去对计数器进行×和除  乘除就用就直接取高位移动就可以

出0入0汤圆

 楼主| 发表于 2009-12-27 15:55:18 | 显示全部楼层
回复【2楼】Fourier00
-----------------------------------------------------------------------

具体程序怎样写啊? 我试了n多个方法,不是编译出错就是编译通过但没效果,感觉用单片机C51写就简简单单几句话的事到了verilog好难啊!!

出0入0汤圆

发表于 2009-12-27 16:02:46 | 显示全部楼层
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

出0入0汤圆

 楼主| 发表于 2009-12-27 16:31:33 | 显示全部楼层
回复【4楼】Fourier00
-----------------------------------------------------------------------

嗯 谢谢 这个我知道  
现在我的问题就是只能实现一个按键的操作(只能乘或只能除),仿真也是,把两个键综合在一起就不行了  很是郁闷!

出0入0汤圆

发表于 2009-12-27 16:57:04 | 显示全部楼层
那你知道,那写出来的是时序逻辑还是组合逻辑,你知道你写的是什么电路吗

出0入0汤圆

发表于 2009-12-27 16:58:00 | 显示全部楼层
always@(negedge add or negedge dec)
begin
if(~add) num1=num1+1;
if(~dec) num2=num2+1;
num=num1-num2;
end
你能画一些这个电路吗?

出0入0汤圆

 楼主| 发表于 2009-12-27 17:13:36 | 显示全部楼层
应该属于时序逻辑啊   感觉我写verilog还没从c51的思维转换过来 都是用单片机的思想 呵呵!

出0入0汤圆

发表于 2009-12-27 22:09:23 | 显示全部楼层
回复【8楼】mowenhui28
-----------------------------------------------------------------------

你的程序,组合逻辑和时序逻辑混杂在一起,下降沿写的是时序,
后面又是组合逻辑
还有你的按钮根据按下就硬件高低电平的变化检测边沿,最好是用两个寄存器

出0入0汤圆

发表于 2009-12-27 22:24:44 | 显示全部楼层
if(~add) fre=fre*2;  
if(~dec) fre=fre/2; 这个地方为什么要这样写呢?一般都这样写:
if(add==1'b0) fre=fre*2;  
if(dec==1'b0) fre=fre/2;

出0入0汤圆

发表于 2009-12-27 22:32:27 | 显示全部楼层
【10楼】 msdy

没觉得那么写有啥问题啊……

出0入0汤圆

发表于 2009-12-27 22:39:39 | 显示全部楼层
除号不可综合。自己写除法器。

出0入0汤圆

 楼主| 发表于 2009-12-28 08:53:04 | 显示全部楼层
回复【10楼】msdy
-----------------------------------------------------------------------

回复【12楼】ngzhang 兽哥
-----------------------------------------------------------------------

乘法用左移<<  除法用右移>> 也可以呀

出0入0汤圆

 楼主| 发表于 2009-12-28 08:57:46 | 显示全部楼层
回复【9楼】edwin
-----------------------------------------------------------------------

两个寄存器的我改成这样了  但编译通过,仿真、实际也都没出来啊!崩溃!!  哪里有问题么?

module fre_set(clk,add,dec,fre);
input clk,add,dec;
output reg[12:0] fre;
reg [12:0] 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

出0入0汤圆

发表于 2009-12-29 12:17:04 | 显示全部楼层
回复【14楼】mowenhui28
-----------------------------------------------------------------------

module fre_set(clk,add,dec,fre,rst);  
input clk,add,dec,rst;  
output [12:0] fre;
reg[12:0] fre,fre_p;
reg  add_p, dec_p;

//reg [12:0] 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 or  dec 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


我仿真可以,试试这个

出0入0汤圆

 楼主| 发表于 2009-12-29 14:00:47 | 显示全部楼层
奇怪 我按这个编译都报错啊  而且你同一个fre_p怎么能在两个always里赋值呢? 我把
if(rst) begin  fre_p<=40;
               add_p<=0;
               dec_p<=0;
          end
这段放到initial里去了 编译通过 但仿真输出却是出 X(未知状态)

出0入0汤圆

发表于 2009-12-29 20:02:29 | 显示全部楼层
组合逻辑要和时序逻辑分开  
我编译都通过了 仿真也可以啊
估计是你的TEST BENCH 的赋值有不确定的状态

出0入0汤圆

 楼主| 发表于 2009-12-30 08:47:24 | 显示全部楼层
回复【16楼】mowenhui28
-----------------------------------------------------------------------


(原文件名:QQ截图未命名.png)

奇怪!

出0入0汤圆

发表于 2009-12-30 09:02:39 | 显示全部楼层
几个疑点:

1:initial   不能被综合吧?

2:除法和乘法不能直接用吧?可不像在单片机里面写C程序。。。。。。。

出0入0汤圆

发表于 2009-12-30 12:03:54 | 显示全部楼层
【19楼】 ygxycp
FPGA里面的initial如果用来赋初值或者加载RAM之类是可以综合的,但是请注意根据场合使用!

出0入0汤圆

 楼主| 发表于 2009-12-30 13:08:47 | 显示全部楼层
还是不行 我现在只能用另外的方式了  就是用dec做拨码,拨1时按复位开关add做乘法,拨0时按add做除法,先只能这样了
看似简单的操作在verilog里还真麻烦

出0入0汤圆

发表于 2009-12-30 14:41:11 | 显示全部楼层
initial 不能被综合
乘法可以 除法不行

上次代码发的有点问题


module fre_set(clk,add,dec,fre,rst);  
input clk,add,dec,rst;  
output [12:0] fre;

reg[12:0] fre,fre_p;
reg  add_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

出0入0汤圆

发表于 2009-12-30 14:43:45 | 显示全部楼层
测试TB如下

module fre_tb;

        // Inputs
        reg clk;
        reg add;
        reg dec;
        reg rst;

        // Outputs
        wire [12:0] fre;

        // Instantiate the Unit Under Test (UUT)
        fre_set uut (
                .clk(clk),
                .add(add),
                .dec(dec),
                .fre(fre),
                .rst(rst)
        );
always  #5  clk=~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

出0入0汤圆

 楼主| 发表于 2009-12-31 15:59:48 | 显示全部楼层
OK! 可以啦  按edwin的方法这个问题终于解决啦   不过测试TB那段是干啥的没看懂  初学呵呵   
不过你说initial不能综合  但我加进去是可以的啊  initial fre=40;

相当感谢 edwin 以及其他热心帮助我的朋友  谢谢你们!!

出0入0汤圆

发表于 2009-12-31 21:05:11 | 显示全部楼层
那段就是仿真用的啊 ,你不用的啊?
那你怎么知道可以了不?

出0入0汤圆

 楼主| 发表于 2010-1-2 14:57:33 | 显示全部楼层
我是直接用波形仿真的啊  硬件也实现啦   没用到测试TB啊

出0入0汤圆

发表于 2010-1-2 16:22:31 | 显示全部楼层
对于FPGA,initial一般是可以综合的,但是需要根据情况使用。

比如面向ASIC的时候就不能在可综合代码里面用initial来初始化,不过如果只是面向FPGA,确实有这个需要的话,
用initial是可以的。

出0入0汤圆

发表于 2010-1-2 18:49:18 | 显示全部楼层
不要在任何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代码里。

出0入0汤圆

发表于 2010-1-2 18:53:39 | 显示全部楼层
关注
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-5-16 13:15

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表