Verilog学习笔记(一)wire与reg

2020-01-12  本文已影响0人  lanFeng666

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
上一篇 下一篇

猜你喜欢

热点阅读