一、
testbench:
`timescale 1ns /1ps
module test;
reg clk;
reg a, b, c;
initial begin
clk = 1'b0;
a = 1'b0;
b = 1'b0;
c = 1'b0;
end
always begin
#10 clk = ~clk;
end
// block1
always @(posedge clk) begin
a <= ~a;
if(a)
b <= ~b;
end
// block2
always @(a) begin
if(a)
c <= ~c;
end
endmodule
仿真波形:
分析:
1、第一个block描述的是always块中存在独立if语句之外的语句的情景,也就是这样子:
always @(...) begin
statement;
if(...)
else if(..)
else
end
这个时候的执行顺序是什么样的呢?从第一个block块的仿真结果可以看出它的执行是这样的:当时钟沿到来时,先判断if的条件是否成立,if判断条件用的是时钟沿到来前变量的值。因为第一个时钟沿到来前那一刻a为0,所以if条件不成立,所以只执行a=~a。第二个时钟沿到来前那一刻a为1,所以if判断条件成立,此时always块相当于
always @(posedge clk) begin
a = ~a;
b = ~b;
end
这个例子体现的是非阻塞赋值的特性。
2、第二个block是为了比较两个分频时钟的特点。通过波形可以看出a信号是时钟信号的二分频,b信号和c信号是时钟信号的四分频,但是b信号比c信号延迟了一个时钟。
二、
testbench
`timescale 1ns /1ps
module test;
reg clk;
reg a, b, c;
initial begin
clk = 1'b0;
a = 1'b0;
b = 1'b0;
c = 1'b1;
end
always begin
#10 clk = ~clk;
end
// block1
always @(posedge clk) begin
a <= 1'b1;
if(c) begin
b <= ~b;
a <= 1'b0;
end
end
/*
// block2
always @(posedge clk) begin
if(c) begin
b <= ~b;
a <= 1'b0;
end
a <= 1'b1;
end
*/
endmodule
仿真波形
block1
block2
分析:
我在阅读opencores上的代码时发现类似上面testbench的写法,也就是在条件判断之外对信号进行了赋值,然后在条件判断又对这个信号进行了一次赋值,如图在case外面对shift赋值为0,然后在case的ST_WRITE状态下又将shift赋值为1:
我好奇最后这个变量会是什么值,仿真结果说明如果同时对一个变量进行赋值,以最靠近end的语句为准。