直接上源码:
1 module key_led( 2 input sys_clk , //50Mhz系统时钟 3 input sys_rst_n, //系统复位,低有效 4 input [3:0] key, //按键输入信号 5 output reg [3:0] led //LED输出信号 6 ); 7 8 //reg define 9 reg [23:0] cnt; 10 reg [1:0] led_control; 11 12 //用于计数0.2s的计数器 13 always @ (posedge sys_clk or negedge sys_rst_n) begin 14 if(!sys_rst_n) 15 cnt<=24'd9_999_999; 16 else if(cnt<24'd9_999_999) 17 cnt<=cnt+1; 18 else 19 cnt<=0; 20 end 21 22 //用于led灯状态的选择 23 always @(posedge sys_clk or negedge sys_rst_n) begin 24 if (!sys_rst_n) 25 led_control <= 2'b00; 26 else if(cnt == 24'd9_999_999) 27 led_control <= led_control + 1'b1; 28 else 29 led_control <= led_control; 30 end 31 32 //识别按键,切换显示模式 33 always @(posedge sys_clk or negedge sys_rst_n) begin 34 if(!sys_rst_n) begin 35 led<=4'b 0000; 36 end 37 else if(key[0]== 0) //按键1按下时,从右向左的流水灯效果 38 case (led_control) 39 2'b00 : led<=4'b1000; 40 2'b01 : led<=4'b0100; 41 2'b10 : led<=4'b0010; 42 2'b11 : led<=4'b0001; 43 default : led<=4'b0000; 44 endcase 45 else if (key[1]==0) //按键2按下时,从左向右的流水灯效果 46 case (led_control) 47 2'b00 : led<=4'b0001; 48 2'b01 : led<=4'b0010; 49 2'b10 : led<=4'b0100; 50 2'b11 : led<=4'b1000; 51 default : led<=4'b0000; 52 endcase 53 else if (key[2]==0) //按键3按下时,LED闪烁 54 case (led_control) 55 2'b00 : led<=4'b1111; 56 2'b01 : led<=4'b0000; 57 2'b10 : led<=4'b1111; 58 2'b11 : led<=4'b0000; 59 default : led<=4'b0000; 60 endcase 61 else if (key[3]==0) //按键4按下时,LED全亮 62 led=4'b1111; 63 else 64 led<=4'b0000; //无按键按下时,LED熄灭 65 end 66 67 endmodule
这个代码注释很清晰。
从这个例子能看出,代码中三个always控制的句子功能都是判断是重新复位了,还是来得时晶振的高电平。就是判断是重新工作还是,正常工作着。并列执行:1. 计数器 +1 ; 2. 如果到了0.2s,则更改一次 led 状态;3. 按键 x 按下,则调用相应的流水灯。其实这个流水灯是0.2s改变led状态个改变的,每一个case下面有四个句子,一次进入只能执行一个。0.2s后执行下一个,形成流水灯。
本例子和前一个在计数器计数部分,差了1,其实无所谓,时间很少,但是精确地说应该是计数到 24'd1000_0000 时,正好是到0.2s。16行应该写成 :
else if(cnt<24'd9_999_999)
上面的case代码相当于C语言的switch-case,写成C语言如下:
1 switch(led_control) 2 { 3 case 0 : 4 led = 0x8;
........................ 5 default : 6 led = 0x0; 7 }