module liushuideng
(
clk,rst_n,led_0,sw1_n,sw2_n,sw3_n
);
input clk; //時鍾信號,50MHZ
input rst_n; //復位信號,低電平有效
input sw1_n,sw2_n,sw3_n; //三個獨立按鍵,低表示按下
output[3:0] led_0; //流水燈,0--滅,1--不滅
//--------------------------------------------------------
reg led_dir; //0--right,1--left
reg led_on; //0--off,1--on
reg[23:0] cnt;
always @(posedge clk or negedge rst_n) //計數
if(!rst_n)
cnt <=24'd0;
else
cnt <= cnt+1'b1;
reg[3:0] led_move;
always @(posedge clk or negedge rst_n) //流水燈
if(!rst_n)
led_move <= 4'b1;
else if(cnt == 24'hffffff && led_on)
begin
if(led_dir)
led_move <= {led_move[2:0],led_move[3]}; //left
else
led_move <= {led_move[0],led_move[3:1]}; //right
end
//---------------------------------------------------------
reg [2:0] key_rst;
always @(posedge clk or negedge rst_n)
if (!rst_n)
key_rst <= 3'b111;
else
key_rst <= {sw3_n,sw2_n,sw1_n}; //每個時鍾周期都會把按鍵值賦給key_rst
reg[2:0] key_rst_r; //每個時鍾周期的上升沿將low_sw信號鎖存到low_sw_r
always @ (posedge clk or negedge rst_n)
if(!rst_n)
key_rst_r <= 3'b111;
else
key_rst_r <= key_rst; //第二級寄存器,將之前鎖存的按鍵值給key_rst_r
wire[2:0] key_an = key_rst_r & ( ~key_rst );//當寄存器key_rst由1變為0時,led_an的值變為高,維持一個時鍾周期
//------------------------------------------------------
reg[23:0] cnt_cn;//計數寄存器
always @ (posedge clk or negedge rst_n)
if (!rst_n)
cnt_cn <= 24'd0; //異步復位
else if(key_an)
cnt_cn <=24'd0;
else
cnt_cn <= cnt_cn + 1'b1;
reg[2:0] low_sw;
always @ (posedge clk or negedge rst_n)
if (!rst_n)
low_sw <= 3'b111;
else if(cnt_cn == 24'hffffff) //滿20ms,將按鍵值鎖存到寄存器low_sw中
low_sw <= {sw3_n,sw2_n,sw1_n}; //每個20ms執行一次
//------------------------------------------------------
reg[2:0] low_sw_r;
always @ ( posedge clk or negedge rst_n )
if (!rst_n)
low_sw_r <= 3'b111;
else
low_sw_r <= low_sw; //每個時鍾周期采一次
/*
low_sw 111 111 111 110 110 110
~low_sw 000 000 000 001 001 001
low_sw_r 111 111 111 110 110 110
led_ctr1 000 000 000 001 000 000
*/
//當寄存器low_sw由1變為0時,led_ctrl的值變為高,維持一個時鍾周期
wire[2:0] led_ctrl = low_sw_r[2:0] & ( ~low_sw[2:0]);
always @ (posedge clk or negedge rst_n)
if(!rst_n)
begin
led_on <= 1'b0;
led_dir <= 1'b0;
end
else
begin //某個按鍵值變化時,LED將做亮滅、左移或右移操作
if ( led_ctrl[0] ) led_on <= ~led_on;
if ( led_ctrl[1] ) led_dir <= 1'b1;
if ( led_ctrl[2] ) led_dir <= 1'b0;
end
assign led_0 = led_dir; //LED
endmodule