直接上源碼:
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 }