|
module johnson(
clk,
rst_n,
key_1,
key_2,
key_3,
key_4,
led
);
input clk;
input rst_n;
input key_1;
input key_2;
input key_3;
input key_4;
output reg [7:0] led;
//------------------------------------------------------------------------
// 按鍵檢測
reg [3:0] key_r_1; // 鎖存按鍵輸入信號4拍
reg [3:0] key_r_2;
reg [3:0] key_r_3;
reg [3:0] key_r_4;
always @ (posedge clk or negedge rst_n)
if(!rst_n)
begin
key_r_1 <= 4'b1111;
key_r_2 <= 4'b1111;
key_r_3 <= 4'b1111;
key_r_4 <= 4'b1111;
end
else
begin
key_r_1 <= {key_r_1[2:0],key_1};
key_r_2 <= {key_r_2[2:0],key_2};
key_r_3 <= {key_r_3[2:0],key_3};
key_r_4 <= {key_r_4[2:0],key_4};
end
wire key_pos_1 = key_r_1[2] & ~key_r_1[3]; // 產生按鍵上升沿和下降沿標志位
wire key_neg_1 = ~key_r_1[2] & key_r_1[3];
wire key_pos_2 = key_r_2[2] & ~key_r_2[3];
wire key_neg_2 = ~key_r_2[2] & key_r_2[3];
wire key_pos_3 = key_r_3[2] & ~key_r_3[3];
wire key_neg_3 = ~key_r_3[2] & key_r_3[3];
wire key_pos_4 = key_r_4[2] & ~key_r_4[3];
wire key_neg_4 = ~key_r_4[2] & key_r_4[3];
//------------------------------------------------------------------------
// 19位計數器,用于計時20ms消抖
reg [19:0] cnt;
always @ (posedge clk or negedge rst_n)
if(!rst_n)
cnt <= 20'd0;
else if((key_pos_1 || key_neg_1) || (key_pos_2 || key_neg_2) || (key_pos_3 || key_neg_3) || (key_pos_4 || key_neg_4))
cnt <= 20'd0;
else if(cnt<20'd999_999)
cnt <= cnt + 1'b1;
else
cnt <= 20'd0;
reg [1:0] key_value_1;
reg [1:0] key_value_2;
reg [1:0] key_value_3;
reg [1:0] key_value_4;
always @ (posedge clk or negedge rst_n)
if(!rst_n)
begin
key_value_1[0] <= 1'b1;
key_value_2[0] <= 1'b1;
key_value_3[0] <= 1'b1;
key_value_4[0] <= 1'b1;
end
else if(cnt == 20'd999_999)
begin
key_value_1[0] <= key_r_1[3];
key_value_2[0] <= key_r_2[3];
key_value_3[0] <= key_r_3[3];
key_value_4[0] <= key_r_4[3];
end
always @ (posedge clk or negedge rst_n)
if(!rst_n)
begin
key_value_1[1] <= 1'b1;
key_value_2[1] <= 1'b1;
key_value_3[1] <= 1'b1;
key_value_4[1] <= 1'b1;
end
else if(cnt == 20'd999_999)
begin
key_value_1[1] <= key_value_1[0];
key_value_2[1] <= key_value_2[0];
key_value_3[1] <= key_value_3[0];
key_value_4[1] <= key_value_4[0];
end
wire led_star = ~key_value_1[0] & key_value_1[1];
wire led_stop = ~key_value_2[0] & key_value_2[1];
wire led_lfsh = ~key_value_3[0] & key_value_3[1];
wire led_rgsh = ~key_value_4[0] & key_value_4[1];
//------------------------------------------------------------------------
// 左移,右移控制
reg led_en;
reg led_dir;
always @ (posedge clk or negedge rst_n)
if(!rst_n)
begin
led_en <= 1'b0;
led_dir <= 1'b0;
end
else if(led_star)
led_en <= 1'b1;
else if(led_stop)
led_en <= 1'b0;
else if(led_lfsh)
led_dir <= 1'b0;
else if(led_rgsh)
led_dir <= 1'b1;
//------------------------------------------------------------------------
// 延時
reg [23:0] delay;
always @ (posedge clk or negedge rst_n)
if(!rst_n)
delay <= 24'd0;
else
delay <= delay + 1'b1;
//------------------------------------------------------------------------
always @ (posedge clk or negedge rst_n)
if(!rst_n)
led <= 8'b00000001;
else if((delay == 24'h3fffff)&&(led_en))
begin
case(led_dir)
1'b0 : led <= {led[6:0],led[7]}; // 左移
1'b1 : led <= {led[0],led[7:1]}; // 右移
default: ;
endcase
end
else ;
endmodule

|
|