“=”, “<=”, "always"执行前后的问题
对于下面ise代码。
module buffer(
input clk,
input in,
output reg out = 0
);
reg buff = 0;
always @(posedge clk) begin
buff <= in;
out <= buff;
end
endmodule
module buffer_tb;
reg clk;
reg in;
wire out;
buffer uut(
.clk(clk),
.in(in),
.out(out)
);
initial begin
clk = 1;
in = 0;
#10;
in = 1;
#10;
in = 0;
#10;
in = 1;
end
always #5 clk = ~clk;
endmodule
该图片为代码实现的波形图,in和out波形相同但是相差1个clk周期
根据提示:如果你在ISim中进行试验就会发现,testbench中=和<=在时钟上升沿的临界状态下,行为是不同的。假如赋值和always块在同一个时钟上升沿发生,=会在always块之前运行,从而影响alway块的赋值;<=可以视为和always块并行运行,且本次不对always块中的<=的所有右值产生影响。
修改最后三个 in 阻塞赋值为非阻塞赋值
#10;
in <= 1;
#10;
in <= 0;
#10;
in <= 1;
波形图如下
in 和 out 相差两个 clk 周期
数的默认符号类型已经相关运算
在Verilog HDL中,wire、reg等数据类型默认都是无符号的。当你希望做符号数的操作时,你需要使用$signed()。
wire res;
reg [3:0] a, b;
assign res = a > b;
当a,b均为正数时,没有问题,但当出现负数时,结果与预期不相符。
将比较代码修改为assign res = $signed(a) > $signed(b);
程序即可达到预期结果。
值得一提的是,在对无符号数和符号数同时操作时,Verilog会自动地做数据类型匹配,将符号数向无符号数转化。同样使用上面的例子,将代码修改为assign res = a > $signed(b);
,这样得到的结果仍然是错误的,因为在执行a > $signed(b)时,a是无符号数,b是符号数,Verilog默认向无符号类型转化,得到的结果仍是无符号数的比较结果。
此外,对于移位运算符,其右侧的操作数总是被视为无符号数,并且不会对运算结果的符号性产生任何影响。结果的符号由运算符左侧的操作数和表达式的其余部分共同决定。
Verilog生成testbanch仿真
Verilog生成testbanch仿真的时候一定记得最后加时钟always #5 clk = ~clk
不然时钟不变。
赋值
Verilog的always块中切忌对同一个变量同时多次非阻塞赋值,当一定要用这种写法时,需要保证个时钟周期内这样的多次非阻塞赋值只有一个是被选择的(有效的),否则可能产生于所期望逻辑不符合的错误(赋值被覆盖)。