求解析7位LED流水灯(Chaser)的Verilog代码运行逻辑
先把代码整理成标准Verilog格式:
led <= (led == 7'b1000000) ? 7'b0000001 : (led <= 7'b0000001) ? 7'b0000010 : (led <= 7'b0000010) ? 7'b0000100 : (led <= 7'b0000100) ? 7'b0001000 : (led <= 7'b0001000) ? 7'b0010000 : (led <= 7'b0010000) ? 7'b0100000 : (led <= 7'b0100000) ? 7'b1000000 : 7'b0000000;
核心运行原理
这段代码用条件运算符(三目运算符?:)实现单比特LED的循环左移,属于时序逻辑的一部分(必然搭配时钟触发的always块,每个时钟周期更新一次led状态)。条件运算符是短路求值的:从左到右依次判断条件,只要某个条件成立,就执行对应的赋值,后面的条件不再检查。
逐分支解析
第一个分支:
(led == 7'b1000000) ? 7'b0000001
当led的最高位(第7位)点亮时,下一个状态直接切换到最低位(第1位)点亮,完成流水灯的循环。第二个分支:
(led <= 7'b0000001) ? 7'b0000010
只有第一个分支不成立(即led不是1000000)时才会走到这里。因为合法状态下led始终是单比特亮,7'b0000001对应十进制1,其他合法状态的值都大于1,所以这个条件等价于led == 7'b0000001,触发后将LED切换到第2位亮。后续的
(led <= 7'bxxxxxxx) ? 7'bxxxxxxx分支
逻辑和第二个分支完全一致:每个分支对应led的上一个合法状态(单比特亮),触发后将LED的点亮位左移一位。比如led <= 7'b0000010(第2位亮)时,切换到7'b0000100(第3位亮),以此类推,直到切换到最高位1000000。最后默认分支:
7'b0000000
如果led处于非法状态(比如多比特亮、全灭),会被重置为全灭。正常运行时不会触发这个分支,因为合法状态会被前面的分支完全覆盖。
整体流程总结
每个时钟周期,led的状态按以下顺序循环:0000001 → 0000010 → 0000100 → 0001000 → 0010000 → 0100000 → 1000000 → 0000001 → ...
实现LED从最右侧到最左侧逐个点亮,循环往复的流水灯效果。
内容的提问来源于stack exchange,提问作者Russell

