美文网首页
Verilog学习笔记(一)wire与reg

Verilog学习笔记(一)wire与reg

作者: lanFeng666 | 来源:发表于2020-01-12 10:06 被阅读0次

    Verilog基本语法学习笔记

    两个重要的基本类型

    类型 说明
    wire wire就是数字电路中的信号线
    reg reg就是数字电路中的D触发器

    从这个地方就可以明显看出两个类型的区别了,这也是为什么有以下的语句

    
    module a_and_b(
        input wire             a,
        input wire             b,
        output wire            c,
        output reg             d
    );
    
    assign c = a & b;
    
    always @(posedge clk)
        d <= a & b;
    
    endmodule
    

    上面的模块中,c作为一根输出的线,说白了,就是 a 和 b 这两根线连到了与门的输入端,然后 c 连到了输出端

    而在下面的代码中

    always @(posedge clk)
        d <= a & b;
    

    d是一个D触发器,clk作为了D触发器的时钟,连接到了d触发器上,a 和 b 连了个与门,然后将与门的输出接到了触发器D的数据输入端上。

    从上面,就可以看出,在Verilog中,always中的赋值语句中的被赋值变量(例如 d )只能是reg类型的,因为,它还要接时钟呢(虽然,always也可以综合出组合逻辑,通过一些写法让综合器把触发器给优化掉,但笔者不建议这么写)

    激励文件(TestBench)的注意事项

    出现这种情况,主要是如何利用Modelsim仿真软件的问题。假设对a_and_b模块进行如下仿真:

    module tb_test();
    
    reg clk;
    reg rst_n;
    reg a,b;
    
    wire cr,dr;
    
    a_and_b ab(
        .clk(clk),
        .rst_n(rst_n),
        .a(a),
        .b(b),
        .c(cr),
        .d(dr)
    );
    
    initial begin
        clk =0;
        rst_n =0;
        a ={$random}; // 这一行
        b ={$random}; // 还有这一行,是有问题的
        #20 
        rst_n =1;
    end
    
    always #5 clk = ~clk;
    
    always #10 a ={$random};
    
    always #15 b ={$random};
    
    endmodule
    

    就会得到这样的结果:

    有问题的时序变化.png

    这张图是明显不对的,因为它根本不能反映D触发器的特性,在画红圈的地方,D触发器在时钟上升的时候,应该只能读到这一时刻之前的值,但这张图上,它却跟着组合逻辑一起跳变了

    为了让仿真的结果更加正常,可以使用如下方案:

    module tb_test();
    
    reg clk;
    reg rst_n;
    reg a,b;
    // 这里的输出,只能是wire
    wire cr,dr;
    wire[7:0] numr;
    
    a_and_b ab(
        .clk(clk),
        .rst_n(rst_n),
        .a(a),
        .b(b),
        .num(numr),
        .c(cr),
        .d(dr)
    );
    
    initial begin
        clk =0;
        rst_n <=0;
        a <={$random};
        b <={$random};
        #20 
        rst_n <=1;
    end
    
    always #5 clk = ~clk;
    
    always #10 a <={$random}; //这儿改成非阻塞赋值
    
    always #15 b <={$random};
    
    endmodule
    

    两个激励文件的唯一区别是,后者的除了时钟信号意外,其他的所有信号都是阻塞式赋值,这样,在仿真的时候,可以将它们的赋值稍慢时钟一点。这个程序得到的结果是:

    没有问题的时序变化.png

    相关文章

      网友评论

          本文标题:Verilog学习笔记(一)wire与reg

          本文链接:https://www.haomeiwen.com/subject/zqyiactx.html