跳到主要内容

1.4.8避免生成锁存器

假设你正在为一个游戏构建一个电路,用于处理来自PS/2键盘的扫描码。根据接收到的最后两个字节的扫描码,你需要判断键盘上的某个箭头键是否已被按下。这涉及到一个相当简单的映射,可以通过带有四个情况的case语句(或if-elseif)来实现。

Scancode [15:0]Arrow key
16'he06bleft arrow
16'he072down arrow
16'he074right arrow
16'he075up arrow
Anything elsenone

你的电路有一个16位输入,以及四个输出。构建这个电路,以识别这四个扫描码并正确地触发相应的输出。

为了避免产生锁存器,所有输出在所有可能的条件下都必须被赋予一个值(参见1.4.4 always_if2)。仅仅有一个default case是不够的。你必须在这四个case和default case中为所有四个输出分配一个值。这可能涉及大量的冗余输入。解决这个问题的一个简单方法是在case语句之前为输出分配一个"默认值":

always @(*) begin
up = 1'b0; down = 1'b0; left = 1'b0; right = 1'b0;
case (scancode)
... // Set to 1 as necessary.
endcase
end

这种编码风格确保了在所有可能的情况下输出都被赋予了一个值(0),除非case语句覆盖了这个赋值。这也意味着default: case项变得不必要了。

提醒: 逻辑综合器生成的组合电路在行为上等同于代码描述的那样。硬件并不会"顺序执行"代码的每一行。

模块声明

// synthesis verilog_input_version verilog_2001
module top_module (
input [15:0] scancode,
output reg left,
output reg down,
output reg right,
output reg up );

做题区