相关阅读Verilog基础https://blog.csdn.net/weixin_45791458/category_12263729.html?spm1001.2014.3001.5482仿真时x信号的产生信号爆x也许是所有IC人的噩梦满屏的红色波形常让人头疼不已但x信号的产生原因却常常只有几种只要遵循一定的代码规范就可以避免产生信号中出现x的问题。最常见问题就是使用了未初始化的reg型变量因为reg型变量在被创建后使用默认值x。如果在初始化变量之前在其他地方提前使用了便有可能造成x态的传播。为了避免可以给所有时序逻辑中用到的reg型变量赋初值不可综合但更为推荐的是为所有时序逻辑中使用到的reg型变量添加复位逻辑可综合并确保复位如下所示。对于组合逻辑中使用到的reg型变量只需要确保始终有正确的驱动即可。reg a 0; reg b; always(posedge clk, negedge rst_n)begin if(rst_n) b 0; else b ***; end连续赋值语句也可能会导致x信号的产生在连续赋值语句对wire型线网赋值时如果出现了多个驱动源同时驱动为不同的值并且强度一致除z外因为z看做没有驱动时会显示为不定态直到多个驱动不冲突如下所示。//一个很幼稚的例子 assign a 1b0; assign a 1b1; //赋值冲突所以a的值为x //一个依旧很幼稚的例子 initial begin b 1b0; c 1b1; end assign a b; assign a c; //同样是赋值冲突所以a的值为x //一个复杂一点的例子 wire a; reg b, c; initial begin b 1b0; c 1b0; #5 c 1b1; #5 c 1b0; #5 c 1b1; #5 c 1b0; end assign a b; assign a c; //因为有时冲突有时不冲突所以a的值交替为0和x最后为0 //一个迷惑一点的例子 wire a; reg b, c; initial begin b 1b0; c 1b0; #25; #5 c 1b1; #5 c 1b0; #5 c 1b1; #5 c 1b0; end assign a b; assign #20 a c; //因为连续赋值有延迟而25ns后每次c改变的脉冲都小于20ns所以没有进行赋值最后的c值为0因此a的值一直是0向量的位选、域选当位选超出界限时结果为1bx。当域选超出界限时超出的部分在返回时会用x值填充。当数组索引超出界限时结果为全x值如例12所示。关于向量的位选、域选的详情参考操作数的位选和域选。​# 例12 module test; reg [2:0]b; reg [2:0]c[1:0]; initial begin b 3b111; $display(result is %b,b[3]); //结果为x b 3b111; $display(result is %b,b[4:2]); //结果为xx1 $display(result is %b,c[2]); //结果为xxx end endmodulex信号对于各运算符的特性有些运算也可能会产生x信号下面简单介绍但需要注意的是它们大多只是x信号的传播者而不是x信号的制造者。算数运算符对于算术运算符当操作数中出现了x信号时即使结果能全部或部分确认结果为全x值如例1所示。# 例1 module test; reg [2:0]a, b; initial begin a 3b001; b 3bx01; $display(result is %b,ab); //结果为xxx a 3b001; b 3bx01; $display(result is %b,a-b); //结果为xxx a 3bx01; b 3b000; $display(result is %b,a*b); //结果为xxx a 3b000; b 3bx01; $display(result is %b,a/b); //结果为xxx a 3b000; b 3bx01; $display(result is %b,a%b); //结果为xxx a 3b000; b 3bx01; $display(result is %b,a**b); //结果为xxx end endmodule如果除法运算符的第二个操作数为0结果为全x值如果乘方运算符的第一个操作数为0而第二个操作数为负数结果为全x值如例2所示。# 例2 module test(); reg [2:0]a,b; initial begin a 3b001; b 3b000; $display(result is %b,a/b); //结果为xxx a 3b000; b -3b001; $display(result is %b,a ** b); //结果应为xxx但遗憾的是似乎没有仿真器遵守了这一点结果为000 end endmodule关系运算符对于关系运算符当操作数中出现了x信号时即使结果能确定结果为1bx如例3所示。​# 例3 module test; reg [2:0]a, b; initial begin a 3b001; b 3b1x1; $display(result is %b,ab); //结果为x a 3b001; b 3b1x1; $display(result is %b,ab); //结果为x a 3bx01; b 3b000; $display(result is %b,ab); //结果为x a 3bx01; b 3b000; $display(result is %b,ab); //结果为x end endmodule相等运算符对于逻辑相等和不相等运算符即和!当操作数中出现了x信号时如果结果能确定则结果正常输出如果结果不能确定结果为1bx如例4所示。​# 例4 module test; reg [2:0]a, b; initial begin a 3b001; b 3b1x1; $display(result is %b,a!b); //结果为1 a 3b001; b 3b0x1; $display(result is %b,a!b); //结果为x a 3b001; b 3b1x1; $display(result is %b,ab); //结果为0 a 3b001; b 3b0x1; $display(result is %b,ab); //结果为x end endmodule对于精确相等和精确不相等运算符即和!它类似于case语句种的比较操作数中的x信号必须精确相等因此结果只能是0或1如例5所示。​# 例5 module test; reg [2:0]a, b; initial begin a 3b101; b 3b1x1; $display(result is %b,ab); //结果为0 a 3b1x1; b 3b1x1; $display(result is %b,ab); //结果为1 a 3b101; b 3b1x1; $display(result is %b,a!b); //结果为1 a 3b1x1; b 3b1x1; $display(result is %b,a!b); //结果为0 end endmodule逻辑运算符对于逻辑运算符当操作数中出现了x信号时如果结果能确定则结果正常输出如果结果不能确定结果为1bx如例6所示。​# 例6 module test; reg [2:0]a, b; initial begin a 3b101; b 3bx00; $display(result is %b,a||b); //结果为1 a 3bx00; b 3bx00; $display(result is %b,a||b); //结果为x a 3bx01; b 3bx01; $display(result is %b,ab); //结果为1 a 3bxx0; b 3bxx0; $display(result is %b,ab); //结果为x a 3b1x1; $display(result is %b,!a); //结果为0 a 3b00x; $display(result is %b,!a); //结果为x end endmodule位运算运算符位运算符按位对操作数进行操作注意对于这些运算符某位的x值不会影响其他非x位的结果。x与1结果为xx与0结果为0x或1结果为1x或0结果为xx异或、同或和取反结果为x如下表和例7所示。​# 例7 module test; reg [2:0]a, b; initial begin a 3b11x; b 3bx1x; $display(result is %b,ab); //结果为x1x a 3bxxx; b 3b10x; $display(result is %b,a|b); //结果为1xx a 3bx0x; b 3bxx1; $display(result is %b,a^b); //结果为xxx a 3bx0x; b 3bxx1; $display(result is %b,a~^b); //结果为xxx a 3b1x0; $display(result is %b,~a); //结果为0x1 end endmodule规约运算符对于规约与运算符如果操作数中存在0结果为0不管是否含有x值对于规约或运算符|如果操作数中存在1结果为1不管是否含有x值。其他情况下如果操作数中有x值则结果为1bx。如例8所示。​# 例8 module test; reg [2:0]a, b; initial begin a 3b10x; $display(result is %b,a); //结果为0 a 3b1xx; $display(result is %b,a); //结果为x a 3b10x; $display(result is %b,|a); //结果为1 a 3b00x; $display(result is %b,|a); //结果为x a 3b1xx; $display(result is %b,^a); //结果为x end endmodule移位运算符对于逻辑移位运算符即和是补0移位对于算数移位运算符即和当作用于有符号的操作数算数右移时会在高位补符号位最高位其他情况下逻辑移位和算数移位效果一样。当移位运算符的右操作数中有x值时结果为全x值。如例9所示。​# 例9 module test; reg signed [2:0]b; initial begin b 3b1x1; $display(result is %b,b1); //结果为01x b 3b1x1; $display(result is %b,b1); //结果为x10 b 3bx01; $display(result is %b,b1); //结果为xx0 b 3bx01; $display(result is %b,b1); //结果为010 end endmodule条件运算符?:对于条件运算符?:当第一个操作数种出现x值时会对第二个和第三个操作数每一位按照以下规则进行检测并给出结果。如例10所示。​# 例10 module test; reg [2:0]a, b; reg c; initial begin a 3b1x0; b 3b100; c 1bx; $display(result is %b,c?a:b); # 结果为1x0 end endmodule连接运算符对于连接运算符某一位的x值不会影响其它位如例11所示。​# 例11 module test; initial begin $display(result is %b,{1bx,3b111}); //结果为x111 end endmodule