实验3、Verilog里费解的概念

教程

这次实验没有教程,直接练习起来吧!如有问题,请学会自行网上搜索/问LLM。


练习

1、阻塞与非阻塞赋值

程序1:

module test;

reg en;
reg [7:0] a,b,i;
reg clk;

initial clk = 0;
always #1 clk = ~clk;

initial begin
    a = 0;
    b = 0;
    i = 0;
    en = 1;
    #100 $finish;
end

initial begin
    $monitor("a=%d, b=%d, i=%d", a, b, i);
    
end

always @(posedge clk) begin
if(i<=8'd16) begin
    i <= i+1; 
    a <= i;
    b <= a;
end
end

endmodule

程序2:

module test;

reg en;
reg [7:0] a,b,i;
reg clk;

initial clk = 0;
always #1 clk = ~clk;

initial begin
    a = 0;
    b = 0;
    i = 0;
    en = 1;
    #100 $finish;
end

initial begin
    $monitor("a=%d, b=%d, i=%d", a, b, i);
    
end

always @(posedge clk) begin
if(i<=8'd16) begin
//与程序1唯一的不同:换成了阻塞赋值
    i = i+1;
    a = i;
    b = a;
end
end

endmodule

Note

[问题1] 写出两个段程序的运行结果,运行Verilog仿真验证,并加以解释为什么会这样。

2、一个变量不能在两个always块里赋值

程序3:

module test;

reg [7:0] counter;
reg rst;
reg clk;

initial clk = 0;
always #1 clk = ~clk;

initial begin
    rst = 0;
    #10 rst = 1
    #10 rst = 0;
    #100 $finish;
end

initial begin
    $monit(counter);
end

always @(posedge rst) begin
    counter <= 0;
end

always @(posedge clk) begin
    counter <= counter + 1;
end

endmodule

Note

[问题2]
2.1 程序3运行起来会出什么错?请实验验证,解释为什么会这样。
2.2 要想实现程序3的功能,请把程序改对。

3、“Verilog”是一门并行执行的语言?

程序4:

module test;

reg en;
reg [7:0] a,b,i;
reg clk;

initial clk = 0;
always #1 clk = ~clk;

initial begin
    a = 0;
    b = 0;
    i = 0;
    en = 1;
    #100 $finish;
end

initial begin
    $monitor("a=%d, b=%d, i=%d", a, b, i);
end

always @(posedge clk) begin
if(i<=8'd16) begin
    i = i+1;
    b = a+1;
    a = i;
end
end

endmodule

程序5:

module test;

reg en;
reg [7:0] a,b,i;
reg clk;

initial clk = 0;
always #1 clk = ~clk;

initial begin
    a = 0;
    b = 0;
    i = 0;
    en = 1;
    #100 $finish;
end

initial begin
    $monitor("a=%d, b=%d, i=%d", a, b, i);
    
end

always @(posedge clk) begin
if(i<=8'd16) begin
    i = i+1;
    a = i;
    b = a+1;
end
end

endmodule

程序6:

module test;

reg [3:0] counter;
reg rst;
reg clk;
wire [1:0] led;

initial clk = 0;
always #1 clk = ~clk;

initial begin
    rst = 0;
    #10 rst = 1;
    #10 counter = 4'd8;
    #10 rst = 0;
    #100 $finish;
end

initial begin
    $monitor(counter);
end

always @(posedge clk) begin
    counter <= counter + 1 + led;
end

assign led = counter[1]+1;

endmodule

Note

[问题3]
3.1 对比程序4与程序5,实验运行一下展示区别,并解释为什么会这样。
3.2 程序6中,请手画波形图,注意led信号是什么时候发生变化。

提示:

  1. “begin…end”里的是按顺序执行,除非是fork语句

  2. 不同的always块、assign语句之间是并行运行,确切地说不是并行执行,而它们只是电路之前的连接。

  3. 其实Verilog并非并行语言,它只是对于电路结构的描述;电路是多模块同时工作的,所以显得Verilog像是并行执行的语言一样。

总结

Verilog里看起来很费解的上面这些概念,其实本质是在用DFF搭建电路,Verilog HDL如其名只是在描述DFF的行为。