文章目录
x态带来的问题
仿真代码时,如果模块输出信号或内部某些关键寄存器出现x态需要及时检测。
我个人常用的对比dut和ref输出信号的语句为:
wire Error;
reg [31:0] Error_Cnt;
//--------------------------
assign Error = !(dut.data_o==ref.data_o);
always@(posedge clk) begin
if(Error) Error_Cnt <= Error_Cnt+1'b1;
end
initial begin
wait(tb_case.complete); // 代码中没有体现tb_case的内容,该信号指示仿真结束。
if(Error_Cnt>0) $display("/n === Failed === /n");
else $display("/n === Passed === /n");
#10 $finish;
end
但当dut.data_o中有部分或全部bit为x态时,Error=1’bx,但此时Error_Cnt不会加1,这导致仿真结束后会打印Passed标志仿真成功。
解决办法
x态信号的一些特征:
比较运算符<、<=、>、>=、===、!==、==、!=
对于<、<=、>、>=、==、!=,它们的比较结果是0或1,但是如果操作数中存在x,比较结果为x。
对于===、!==,它们严格比较两个操作数中的x,因此结果只能为0或1。
b = 3'b111;
c = 3'b0x1;
$display("result is %b",b<c);//结果为x
b = 3'b0x1;
c = 3'b0x1;
$display("result is %b",b===c);//结果为1
位运算操作符&、|、^、~^、~
位运算符按位对操作数进行操作,注意对于这些运算符,某位的x不会影响其他非x位的结果。且x与1为x,x与0为0,x或1为1,x或0为x。对于异或、同或和取反运算,x位的结果是x。
b = 3'b0x1;
c = 3'bx11;
$display("result is %b",b&c);//结果为0x1
b = 3'b0x1;
c = 3'bx11;
$display("result is %b",b^c);//结果为xx0
x和z的逻辑运算真值表
有效判断x态输出
- 有ref的情况下:
wire Error;
reg [31:0] Error_Cnt;
//--------------------------
assign Error = !(dut.data_o===ref.data_o);
always@(posedge clk) begin
if(Error) Error_Cnt <= Error_Cnt+1'b1;
end
initial begin
wait(tb_case.complete);
if(Error_Cnt>0) $display("/n === Failed === /n");
else $display("/n === Passed === /n");
#10 $finish;
end
- 没有ref的情况下:
wire Data_Xor;
wire Data_IsX;
integer file;
//--------------------------
assign Data_Xor = ^dut.data_o;
assign Data_IsX = Data_Xor !==0 && Data_Xor !==1;
initial file = $fopen("./Data_IsX.log","w");
initial begin
while(start_en) begin // 代码中未体现start_en信号,该信号指示仿真开始
if(Data_IsX) begin
$fdisplay(file,"Data_o is X!"); // 将信息写入文件file中
#10 $fclose(file);
#10 $finish; // 如果输出信号出现x态,则停止仿真
end
end
end