Verilog中always块并行测试
FPGA的特色是并行执行的,尤其是在多个always块,并行执行时,要考虑一下变量值的变化。本文使用两个always块,第一个在clk上升沿到来时,更新a的值;第二个always块在clk上升沿到来时,将a的值赋给q,到底q的值是a更新前的值还是 更新后的值,需要进行仿真验证。
下面是使用QuartusII编写的源文件和测试文件。
module Fsm(
input clk,
input rst_n,
output reg [3:0] a,
output reg [3:0] q
);
//*****************************************************
//** main code
//*****************************************************
//a值更新模块
always @ (posedge clk or negedge rst_n)
begin
if(!rst_n)
a<=0;
else
begin
if(a<10)
a<=a+1;
else
a<=a;
end
end
//q值更新模块
always @ (posedge clk or negedge rst_n)
begin
if(!rst_n)
q<=0;
else
q<=a; //务必注意a的赋值必须在前面的always块中
end
endmodule
`timescale 1 ns/ 1 ns
module Fsm_vlg_tst();
wire [3:0] a,q;
reg clk,rst_n;
Fsm u0_Fsm(
.clk(clk),
.rst_n(rst_n),
.a(a),
.q(q)
);
initial // fork join是并行运行的 begin end是顺序执行的
begin
clk=0;rst_n=0;
#10 clk=1;
#5 rst_n=1;
#5 clk=0;
#10 clk=1;
#10 clk=0;
#10 clk=1;
#10 clk=0;
#10 clk=1;
#10 clk=0;
#10 clk=1;
#10 clk=0;
#10 clk=1;
#10 clk=0;
#10 clk=1;
#10 clk=0;
#20 $stop;
end
endmodule
下面是源文件中对a使用非阻塞性赋值(即a<=a+1)时的时序图
下面是源文件中对a使用阻塞性赋值(即a=a+1)时的时序图
对比两个时序图可以发现,当a使用非阻塞性赋值时,q的值得到是a更新前的数值,而当a使用阻塞性赋值时,q的值得到是a更新后的数值。此处注意:如果将a的赋值always块放到q的赋值always块后面,将会发生错误。