基于2x4解码器的4x16解码器Verilog实现输出异常求助
Verilog 4x16解码器输出异常问题排查与解决
问题背景
基于2x4解码器搭建4x16解码器,测试平台运行后输出结果异常,需定位并修复代码问题。
故障代码
4x16解码器顶层模块
module decoder4x16_with_2x4(Y, d, e); output [15:0] Y; input [3:0] d; input e; wire [3:0] w; decoder2_to_4 De0(.F({w[3],w[2],w[1],w[0]}), .i({d[1],d[0]}), .e(e)), De1(.F({Y[3],Y[2],Y[1],Y[0]}), .i({d[3],d[2]}), .e(w[0])), De2(.F({Y[7],Y[6],Y[5],Y[4]}), .i({d[3],d[2]}), .e(w[1])), De3(.F({Y[11],Y[10],Y[9],Y[8]}), .i({d[3],d[2]}), .e(w[2])), De4(.F({Y[15],Y[14],Y[13],Y[12]}), .i({d[3],d[2]}), .e(w[3]))); endmodule
测试平台模块
module decoder4x16_with_2x4_tb(); reg [3:0] i; wire [15:0] f; decoder4x16_with_2x4 muxi(.Y(f), .d(i), .e(1'b1)); initial begin $monitor("d = %b --> Y = %b", i, f); repeat(10) begin i = $random; #1; end end endmodule
2x4解码器模块
module decoder2_to_4(F, i, e); output reg [3:0] F; input [1:0] i; input e; always@(i) begin if (e == 1'b1) begin case(i) 2'b00 : F = 4'b0001; 2'b01 : F = 4'b0010; 2'b10 : F = 4'b0100; 2'b11 : F = 4'b1000; default : $display("Invalid data received!!"); endcase end else begin F = 1'b0; end end endmodule
测试输出异常示例
# d = 0100 --> Y = 0000000000000000 # d = 0001 --> Y = 0000000000000001 # d = 1001 --> Y = 0000000001000000 # d = 0011 --> Y = 0000000000010000 # d = 1101 --> Y = 1000000000000000 # d = 0101 --> Y = 0000000000100000 # d = 0010 --> Y = 0000000000010000 # d = 0001 --> Y = 0000000000010000 # d = 1101 --> Y = 0000000010000000
问题分析
输入位序完全颠倒:
- 顶层模块中,用于选通下层解码器的De0应接收输入
d的高两位d[3:2],实际接了低两位d[1:0]; - 下层4个2x4解码器(De1~De4)应接收输入
d的低两位d[1:0]选择组内输出位,实际接了高两位d[3:2],导致选通逻辑完全错误。
- 顶层模块中,用于选通下层解码器的De0应接收输入
敏感列表缺失使能信号:
decoder2_to_4模块的always块仅监听输入i,未包含使能信号e。当e变化时(如选通信号切换),不会触发输出更新,导致输出状态异常。
使能无效时赋值错误:
decoder2_to_4模块中,当e=0时赋值F=1'b0,但F是4位寄存器,此赋值仅将最低位设为0,高3位保持原值,导致输出残留错误电平。
修复方案
修改后的2x4解码器模块
module decoder2_to_4(F, i, e); output reg [3:0] F; input [1:0] i; input e; // 敏感列表添加e信号,确保e变化时触发更新 always@(i or e) begin if (e == 1'b1) begin case(i) 2'b00 : F = 4'b0001; 2'b01 : F = 4'b0010; 2'b10 : F = 4'b0100; 2'b11 : F = 4'b1000; default : $display("Invalid data received!!"); endcase end else begin // 赋值4位全0,避免残留电平 F = 4'b0000; end end endmodule
修改后的4x16解码器顶层模块
module decoder4x16_with_2x4(Y, d, e); output [15:0] Y; input [3:0] d; input e; wire [3:0] w; // De0接收高两位d[3:2],选通对应的下层解码器 decoder2_to_4 De0(.F(w), .i(d[3:2]), .e(e)), // 下层解码器接收低两位d[1:0],选择组内输出位 De1(.F(Y[3:0]), .i(d[1:0]), .e(w[0])), De2(.F(Y[7:4]), .i(d[1:0]), .e(w[1])), De3(.F(Y[11:8]), .i(d[1:0]), .e(w[2])), De4(.F(Y[15:12]), .i(d[1:0]), .e(w[3]))); endmodule
验证结果
修改后运行测试平台,输出将符合4x16解码器的预期逻辑:每个4位输入d对应唯一的1位高电平输出。例如:
d=0100对应Y=0000000000010000d=1001对应Y=0000000010000000
内容的提问来源于stack exchange,提问作者Ankit Kumar Singh
相关产品推荐
相关产品推荐

