Verilog HDL 阻塞赋值语句和非阻塞赋值语句

      阻塞赋值语句和非阻塞赋值语句都属于过程赋值语句,是用来对寄存器型变量赋值的方法。阻塞赋值使用“=”为变量赋值,在赋值结束以前不可以进行其它操作,在赋值结束后继续后面的操作。这个过程好像阻断了程序的运行,因而被称为阻塞赋值。连续的阻塞赋值操作是顺序完成的;非阻塞赋值使用“<=”为变量赋值,在执行到赋值语句时,仅仅对“<=”右侧的表达式的值进行评估,但并不马上执行赋值,然后继续执行后面的操作。这个过程好像没有阻断程序的运行,因而被称为非阻塞赋值。连续的非阻塞赋值操作是同时完成的。
     多条阻塞赋值语句是顺序执行的,而多条非阻塞赋值语句是并行执行的,这就是两者的区别。下面列出了有关阻塞赋值和非阻塞赋值在使用上的一些注意事项,只要在设计中坚持做到下面列出的注意事项,就可以基本上避免由于使用阻塞赋值和非阻塞赋值 不当而引起的错误。
    1)在使用always块描述组合逻辑时使用阻塞赋值,在使用always块描述时序逻辑时使用非阻塞赋值。可以理解为在电平敏感的always块内使用阻塞赋值,在边沿敏感的always块内使用非阻塞赋值。
    2)不用再同一个always块内同时使用阻塞赋值和非阻塞赋值。
    3)无论是使用阻塞赋值或者非阻塞赋值,不要在不同的always块内为同一个变量赋值。
    例如:
    module wrong_assign(
            clk,    //时钟输入信号
            sel,    //选择信号,当sel==1时,输出din1的值;当sel==0
                //时,输出din2的值
            din1,    //数据输入信号
            din2,    //数据输入信号
            dout    //数据输出信号
            );
   
    input        clk;
    input        sel;
    input        din1,din2;
    output        dout;

    wire         clk;
    wire        sel;
    wire        din1,din2;
    reg        dout;

    //下面两个always块中都为dout赋了值,但似乎不会引起冲突
    always @(posedge clk)
        if(sel==1)     dout<=din1;
       
    always @(posedge clk)
        if(sel==0)     dout<=din2;

    endmodule
   
    在上例中两个always块内都为变量dout赋了值,并且似乎没有引起赋值的冲突。因为表明看来,当sel==1时,第1个always块生效;而当sel==0时,第2个always块生效。这是高级语言中的思路,在硬件描述语言中完全行不通。当clk的上升沿到来时,如果sel信号的值为1,第1个always块执行结果是将din1赋予dout,而第2个always块 并不是不执行,在不满足将din2的值赋予dout的条件下,第2个always块试图保持dout的值不变。由于这两个always块又是同时执行的,因而就有可能造成赋值冲突。所以如果想通过sel信号的控制实现而选一功能,可以将代码写成如下。
    module wrong_assign(
            clk,    //时钟输入信号
            sel,    //选择信号,当sel==1时,输出din1的值;当sel==0
                //时,输出din2的值
            din1,    //数据输入信号
            din2,    //数据输入信号
            dout    //数据输出信号
            );
   
    input        clk;
    input        sel;
    input        din1,din2;
    output        dout;

    wire         clk;
    wire        sel;
    wire        din1,din2;
    reg        dout;

    //在同一个always块内为同一个变量赋值
    always @(posedge sel)
    begin
        if(sel==1)
            dout<=din1;    //当sel==1时,将din1的值赋予dout
        else
            dout<=din2;    //当sel==0时,将din2的值赋予dout
    end

    endmodule


    4)在程序中不要使用0延时。0延时指的是在值语句前面添加上“#0”,有的设计人员想用这种方法来排列两条赋值语句的执行顺序,但实际上这样做有可能会导致错误。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值