我正在创建一个寄存器文件,该文件有4个空的4位寄存器,每个时钟周期,寄存器获得一个值,然后使用7段解码器显示该值。如果寄存器为空,则不应该有显示,但是一旦将值加载到寄存器,则应该有显示。我尝试编写7段解码器的verilog代码,如果En = 1,应该只有一个输出。我的问题是,7段解码器将显示零,直到将一个值添加到寄存器,在哪种情况下,解码器将显示加载的值。这是verilog代码。
module seven_seg_decoder(S, Z, Y, X, W,En);
input Z,Y,X,W,En;
output [6:0] S;
reg [6:0] S;
always @(En)
begin
case({Z,Y,X,W,En})
5'b00001: S = 'b0000001;
5'b00011: S = 'b1001111;
5'b00101: S = 'b0010010;
5'b00111: S = 'b0000110;
5'b01001: S = 'b1001100;
5'b01011: S = 'b0100100;
5'b01101: S = 'b0100000;
5'b01111: S = 'b0001111;
5'b10001: S = 'b0000000;
5'b10011: S = 'b0000100;
5'b10101: S = 'b0001000;
5'b10111: S = 'b1100000;
5'b11001: S = 'b0110001;
5'b11011: S = 'b1000010;
5'b11101: S = 'b0110000;
5'b11111: S = 'b0111000;
endcase
end
endmodule
当寄存器加载了一个值时,我有一个输出来自寄存器,表示它已被加载,并且用作此解码器上启用的输入
答案 0 :(得分:1)
查看您列举的{Z, Y, X, W, En}
的可能编码:
5'b00001: S = 'b0000001;
5'b00011: S = 'b1001111;
5'b00101: S = 'b0010010;
5'b00111: S = 'b0000110;
5'b01001: S = 'b1001100;
5'b01011: S = 'b0100100;
5'b01101: S = 'b0100000;
5'b01111: S = 'b0001111;
5'b10001: S = 'b0000000;
5'b10011: S = 'b0000100;
5'b10101: S = 'b0001000;
5'b10111: S = 'b1100000;
5'b11001: S = 'b0110001;
5'b11011: S = 'b1000010;
5'b11101: S = 'b0110000;
5'b11111: S = 'b0111000;
// ^ Look here
En
的所有值均为1
!如果En
为0
,您从未告诉模块该怎么做。它不知道消隐显示器。在这种情况下,你需要给它一些事情。
您有几个选择:
简单解决方案
您可以添加一个默认子句,在未枚举的所有情况下使显示空白:
default: S = 'b0000000; //change to whatever means "turn everything off"
不必要的复杂解决方案
使用5' bxxxx0作为子句和casex
语句可以更精确:
casex ({Z,Y,X,W,En})
// all other enumerated cases
5'bxxxx0: S = 'b0000000; //change to "everything off"
default: S = 'b0000000; //change to "everything off"
但是要知道casex
存在一些潜在的陷阱,这些陷阱可能会使其难以正确使用并导致令人惊讶的行为。另请注意,这最终与第一个简单的解决方案相同。我暂时不会这样做。
(我的)首选解决方案
这与前两个实际上是一样的,但我认为意图要清楚得多:
always @(*)
begin
if (!En)
S = 'b0000000; // change to "everything off"
else
case({Z,Y,X,W,En})
5'b00001: S = 'b0000001;
5'b00011: S = 'b1001111;
5'b00101: S = 'b0010010;
5'b00111: S = 'b0000110;
5'b01001: S = 'b1001100;
5'b01011: S = 'b0100100;
5'b01101: S = 'b0100000;
5'b01111: S = 'b0001111;
5'b10001: S = 'b0000000;
5'b10011: S = 'b0000100;
5'b10101: S = 'b0001000;
5'b10111: S = 'b1100000;
5'b11001: S = 'b0110001;
5'b11011: S = 'b1000010;
5'b11101: S = 'b0110000;
5'b11111: S = 'b0111000;
default: S = 'b0000000; // change to some error code
endcase
end
此解决方案的优势在于您的代码的目标更加明确:如果En
不正确,那么其余信号就不重要了。我们清除显示。其他解决方案也会发生这种情况,但这种结构使得发生的事情变得更加明显。
此处的default
案例在技术上并非必要。在En
为真的情况下,不应该枚举任何情况。但是要输入很多数字。如果您输入了拼写错误,在这种情况下,有一个强制显示错误的默认值(可能只是7seg显示的中心线?)将帮助您识别错误。
其他几点说明:
您应该避免使用X
和Z
作为变量名称。他们可能会因为“不在乎”而感到困惑。和"高阻抗"。它使代码更难以遵循它。
我已更改了您的敏感度列表。 Greg correctly pointed out如果您希望在输入W
,X
,Y
和Z
发生变化时正确更新输出,则需要always
阻止在他们改变时被触发。 *
运算符将告诉Verilog编译器根据always
块的内容推断出正确的敏感度列表。 (请注意,这不会查看决定灵敏度列表的任务或功能。)
我强烈建议您将所有位模式放在parameters中,以使您的代码更具可读性。