实验较为简单,考虑到的情况不多。经验仅供参考。如果发现反例,欢迎评论一起探讨
最近在做关于FPGA原型验证,不清楚代码中的高阻z和不定态x会被映射成什么样的电路。会不会导致前仿真和综合后仿真的结果不一致。所以自己做了个验证。
先附上用来验证的源代码和仿真代码。
代码结构比较简单, e n _ z en\_z en_z信号就是我们要验证的信号。
源代码
module top(
input clk,
input rst_n,
input en,
output wire[2:0] led,
output wire[1:0] cnt
);
chip rita(
.clk(clk),
.rst_n(rst_n),
.en(en),
.led(led)
);
endmodule
module chip(
input clk,
input rst_n,
input en,
inout pad,
output reg [2:0]led,
output reg [1:0]cnt
);
wire en_z;
assign pad=1'bz;
assign en_z=1'bz;
always@(posedge clk or negedge rst_n)begin
if(!rst_n) led <= 0;
else led <= {en_z, en, en_z & en};
end
always@(posedge clk or negedge rst_n)begin
if(!rst_n) cnt <= 0;
else cnt <= cnt+~en_z;
end
endmodule
仿真代码
module tb_top( );
reg clk = 0;
always #10 clk = ~clk;
reg rst_n;
reg en;
initial begin
rst_n = 0;
en = 0;
#50 rst_n =1;
#50 en = 1;
end
wire [2:0]led;
wire [1:0]cnt;
top u_top(
.clk(clk),
.rst_n(rst_n),
.en(en),
.led(led),
.cnt(cnt)
);
endmodule
电路内信号的状态只有0或1,看 l e d [ 2 ] _ I N S T _ 0 led[2]\_INST\_0 led[2]_INST_0和 e n z _ 0 _ I N S T _ 0 enz\_0\_INST\_0 enz_0_INST_0 信号直接接地,此处信号被综合成0;但是后面, l e d _ O B U F [ 2 ] _ i n s t led\_OBUF[2]\_inst led_OBUF[2]_inst这是一个三态输出BUF。
至于 c n t cnt cnt寄存器因为忘了引出来则直接被优化掉了,通过输出BUF直接输出。
注意 l e d [ 0 ] led[0] led[0]是不定态。后面要对比。
对比两次仿真的结果,可以发现后仿真中不存在不定态。可以理解,毕竟要生成具体的电路所有的信号都要确定下来。
此时 l e d [ 0 ] led[0] led[0]变为1。结合代码,高组态和高电平想与,综合后的结果是高电平。
cnt寄存器因为被优化,默认高阻态。
所有vivado 对于高阻态的优化是非常智能的。前仿真中确定是高阻态的输出的,会直接优化相关逻辑输出高阻态。前仿真时不定态的,会在综合后确定电路的状态,但是这个不定态如何确定请看第二节。
和前面的代码相比,主要增加了与或非几个不同的操作。
源代码
module top(
input clk,
input rst_n,
input en,
output wire[6:0] led,
output wire[1:0] cnt
);
chip rita(
.clk(clk),
.rst_n(rst_n),
.en(en),
.led(led)
);
endmodule
module chip(
input clk,
input rst_n,
input en,
inout pad,
output reg [6:0]led,
output reg [1:0]cnt
);
wire en_z;
assign pad=1'bz;
assign en_z=1'bx;
always@(posedge clk or negedge rst_n)begin
if(!rst_n) led <= 0;
else led <= {en_z,en, en_z&en,en_z|en, en_z & ~en, en_z|~en,~en_z};
end
always@(posedge clk or negedge rst_n)begin
if(!rst_n) cnt <= 0;
else cnt <= cnt+~en_z;
end
endmodule
仿真代码
module tb_top(
);
reg clk = 0;
always #10 clk = ~clk;
reg rst_n;
reg en;
initial begin
rst_n = 0;
en = 0;
#50 rst_n =1;
#50 en = 1;
#50 en = 0;
#50 en = 1;
end
wire [6:0]led;
wire [1:0]cnt;
top u_top(
.clk(clk),
.rst_n(rst_n),
.en(en),
.led(led),
.cnt(cnt)
);
endmodule
后仿真不包含不定态,也符合预期。关键是不定态怎么消失的。
根据代码
可知,假定不定态和信号a进行逻辑操作。如果a不变化,结果为0保持不变。
当a变化后,结果发生变化。单独游逻辑X导致的,例如led[6]和led[0]会输出0;
x和信号a进行&和|操作,结果会和x信号a保持一致,就相当于没有进行&和|操作。
不定态在后仿真中会被消除。单纯由不定态导致的输出,会变成0;和其他信号进行逻辑操作后的结果和其他信号保持一致。
后面又做了其他的实验,高阻态和其他逻辑操作的结果也是和其他信号保持一致。
上面两个实验的代码中除了led外,还有cnt。cnt的行为似乎不符合我说的逻辑,其实是因为我代码写的时候。top里面例化chip的时候忘记把cnt引出来。。。。。。。大家无视它就好。