使用Testbench验证Encoder模块时输出未随输入变化的问题排查
编码器模块仿真输出异常问题排查
问题现象
编写了4输入优先级编码器模块及测试平台,仿真时无论输入哪种带z的信号,输出pos始终为001(对应第一个输入的结果),无法得到预期的对应输出。
原代码
Encoder模块
module encoder ( input [3:0] in, output reg [2:0] pos ); always @(*) begin casez (in) 4'bzzz1: pos = 1; 4'bzz1z: pos = 2; 4'bz1zz: pos = 3; 4'b1zzz: pos = 4; default: pos = 0; endcase end endmodule
Testbench
module main(); reg [3:0] in; wire [2:0] pos; encoder e(in,pos); initial begin #5 in = 4'bzzz1; #5 in = 4'bzz1z; #5 in = 4'bz1zz; #5 in = 4'b1zzz; #20; $finish; end initial $monitor($time,"in=%b, pos=%b",in ,pos); endmodule
问题分析
核心问题出在**casez对含z输入的匹配逻辑**:
casez的规则是忽略模式中的z位(即该位无需匹配输入值),但输入中的z是实际的高阻态逻辑值,会参与模式中非z位的比较。- 当输入为
4'bzz1z时,输入的bit0是z,与第一个case模式4'bzzz1的bit0(1)比较结果为未知态x,因此不匹配第一个case;但第二个case模式4'bzz1z的bit1是1,输入的bit1也是1,理论上应匹配第二个case。 - 但部分仿真工具对
reg变量赋值z的处理存在差异,或z参与比较时的未知态导致匹配逻辑异常,最终始终匹配第一个case或出现非预期结果。
另外,你的Testbench时间线理解有误:输入的切换时间点应为5、10、15、20,而非全部在5时刻。
解决方案
方案1:使用确定逻辑值测试(推荐先验证核心逻辑)
修改Testbench,用0代替z,使用明确的单bit高电平输入测试:
initial begin #5 in = 4'b0001; #5 in = 4'b0010; #5 in = 4'b0100; #5 in = 4'b1000; #20; $finish; end
此方式可排除z带来的不确定性,验证编码器的优先级逻辑是否正常。
方案2:改用优先级判断逻辑(更稳定可靠)
替换casez为if-else优先级判断,避免z带来的匹配问题,逻辑更直观:
module encoder ( input [3:0] in, output reg [2:0] pos ); always @(*) begin if (in[0]) pos = 3'b001; else if (in[1]) pos = 3'b010; else if (in[2]) pos = 3'b011; else if (in[3]) pos = 3'b100; else pos = 3'b000; end endmodule
该逻辑仅当对应bit为明确的1时才触发赋值,z或x不会触发条件,完全符合优先级编码需求。
方案3:调整casez模式写法
若坚持使用casez,可将模式中的z替换为?(两者语义一致,但部分工具对?的支持更稳定):
always @(*) begin casez (in) 4'b???1: pos = 1; 4'b??1?: pos = 2; 4'b?1??: pos = 3; 4'b1???: pos = 4; default: pos = 0; endcase end
内容的提问来源于stack exchange,提问作者余昌翰
相关产品推荐
相关产品推荐

