Verilog语言中,关于always的详细介绍

       always @(*) 在仿真开始时必然执行一次,无论信号是否变化。 always语句在0时刻初始运行前,vivado编译器先遍历一下,读出其中的各信号的值(若testbench没有在0时刻输入激励,那么reg采用默认的X值)。

        而时序的always @(posedge clk)则不会,需要有满足的上升沿才会进入。

module Latch1(
    input               data,
    input               en,
    output reg          q
);

always @(*) begin
    if (en) begin
        q = data;
    end
end
endmodule
`timescale 1ns/1ns
module sim_test();

reg data, en;
wire q;

initial begin
    #10            //先延时,再赋值
    en <= 1;
    data <= 1;
end

Latch1      u_test(
    .data   (data),
    .en     (en),
    .q      (q)
);
endmodule

        通过上面的波形图可以观察到:在10ns之前,由于en和data没有输入有效激励,导致采用了reg型的默认值x进行输入,相对应的输出q也是x;而10ns之后,由于en从X跳变到1,从而进入了always和if里,data把值传递给q。


        下面是取消延时的波形图:

        不延时输入激励信号,可以看到在0时刻后立马直接是q为1。

        当时我会深究这个现象问题,是因为我认为,既然always的敏感变量在0时刻的初始值就是1,没有电平变化(甚至持续数ns),那么按理来说就不会进入always内,更不会执行q的赋值操作,那么reg型q就没有存储任何值,那就应该是默认的X。

        但真实情况是q的值和data的值一样,那就表明我的认为是错的,在0时刻之前或许就已经进入了always内。

        于是我才用打印输出的方式进行更直观的验证。


        为了更加充分的验证,我们在代码内添加打印,进行更加直观的查看。

        在延时后,如果按照我错误的想法,q的值应该为X,但实际上可以很明显的看出,在0时刻的时候q的取值是en为X的情况,也就是进入了else内。也就说明:在0时刻的节拍到来之前程序就已经被执行了一次,寄存器内就已经有值了。


        下面我们把初始延时取消。

        延时取消,观察0时刻的情况。可以看到0时刻打印了两次,其中第一次en为X进入else,第二次是en为0进入else。


        通过上面的对比,反映出一个现象:那就是在0时刻之前,vivado会先遍历一下always里面各信号的值,值由testbench提供,没有就是默认值。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值