FPGA-13-籃球計分計時器的設計
阿新 • • 發佈:2018-12-19
這次的任務相對上次來說程式碼書寫的更為規範和簡潔
任務一、籃球計分器 功能:按照籃球賽賽制進行設計。須具有24秒倒計時功能,十二分鐘計時功能,暫停功能,進球計分功能(1分,2分,3分)等。可再自由發揮。 要求:比分與計時須在數碼管實時顯示,顯示狀態可通過按鍵或者撥碼開關切換,計分可通過按鍵進行設計(不限制)。
設計:
sw1 暫停
sw2 24秒倒計時
sw3 顯示計時或者得分
key0 1分
key1 2分
key2 3分
key4計分切換
頂層模組:
module top(ext_clk_25m,ext_rst_n, switch1,switch2,switch3, key_left,key_entr,key_righ,key_down, dtube_cs_n,dtube_data,led ); input ext_clk_25m ;//輸入時鐘 input ext_rst_n ;//復位訊號 input switch1 ;//暫停開關 input switch2 ;//24s使能開關 input switch3 ;//顯示切換位 input key_left ;//1分 input key_entr ;//2分 input key_righ ;//3分 input key_down ;//切換記分 output [3:0] dtube_cs_n ;//位選資料位 output [6:0] dtube_data ;//段選資料位 output [3:0] led ; wire clk ;//中間變數 wire [15:0] times_24s ; wire [15:0] times_12m ; wire [15:0] times_sore ; wire en_cnt ; wire en_seg ; wire en_24s ; wire en_sor ; //分頻25MHZ變為1HZ div d1( .ext_clk_25m(ext_clk_25m), .ext_rst_n(ext_rst_n), .mclk(clk) ); //控制電路 control con1( .ext_clk_25m(ext_clk_25m), .ext_rst_n(ext_rst_n), .switch1(switch1), .switch2(switch2), .switch3(switch3), .en_cnt(en_cnt), .en_seg(en_seg), .en_24s(en_24s), .en_sore(en_sor) ); //計分模組 soring so1( .ext_clk_25m(ext_clk_25m), .ext_rst_n(ext_rst_n), .key_down(key_down), .key_left(key_left), .key_entr(key_entr), .key_righ(key_righ), .en_sore(en_sor), .sore(times_sore), .led(led[3:2]) ); //12分鐘倒計時模組 counter_12min c1( .ext_clk_25m(ext_clk_25m), .mclk(clk), .ext_rst_n(ext_rst_n), .en_24s(en_24s), .en_cnt(en_cnt), .times_12m(times_12m), .led(led[0]) ); //24分鐘倒計時模組 counter_24 c2( .ext_clk_25m(ext_clk_25m), .mclk(clk), .ext_rst_n(ext_rst_n), .en_24s(en_24s), .en_cnt(en_cnt), .times_24s(times_24s), .led(led[1]) ); //數碼管顯示模組 seg s1( .ext_clk_25m(ext_clk_25m), .ext_rst_n(ext_rst_n), .times_24s(times_24s), .times_12m(times_12m), .times_sore(times_sore), .en_24s(en_24s), .en_seg(en_seg), .en_sore(en_sor), .dtube_cs_n(dtube_cs_n), .dtube_data(dtube_data) );
module control(ext_clk_25m,ext_rst_n,switch1,switch2,switch3,en_cnt,en_seg,en_24s,en_sore
);
input ext_clk_25m; //輸入時鐘
input ext_rst_n ; //復位訊號
input switch1 ; //暫停開關
input switch2 ; //24s使能開關
input switch3 ; //顯示切換位
output reg en_cnt ; //暫停計數使能位
output reg en_seg ; //數碼管顯示使能位
output reg en_24s ; //24s使能位
output reg en_sore ; //計分使能位
reg [24:0] cnt ; //存放計數器的值
parameter TIME = 25'd2500_0000;
//數碼管特殊狀態閃爍計數器模組
[email protected](posedge ext_clk_25m or negedge ext_rst_n)begin
if(ext_rst_n==1'b0)begin
cnt <=25'd0;
end
else if(cnt ==TIME-1'b1)begin
cnt <=1'b0;
end
else begin
cnt <=cnt + 1'b1;
end
end
//數碼管閃爍模組
always @(posedge ext_clk_25m or negedge ext_rst_n)begin
if(ext_rst_n==1'b0)begin
en_seg<=1'b0;
end
else if(switch1==1'b0)begin
if(cnt<(TIME/2-1'b1))begin
en_seg<=1'b1;
end
else begin
en_seg<=1'b0;
end
end
else begin
en_seg<=1'b0;
end
end
//停止計數器計時模組
always @(posedge ext_clk_25m or negedge ext_rst_n)begin
if(ext_rst_n==1'b0)begin
en_cnt<=1'b0;
end
else if(switch1==1'b0)begin
en_cnt<=1'b1;
end
else begin
en_cnt<=1'b0;
end
end
//開啟24s倒計時
[email protected](posedge ext_clk_25m or negedge ext_rst_n)begin
if(ext_rst_n==1'b0)begin
en_24s <=1'b0;
end
else if(switch2==1'b0)begin
en_24s <=1'b1;
end
else begin
en_24s <=1'b0;
end
end
//計分和計時顯示切換
[email protected](posedge ext_clk_25m or negedge ext_rst_n)begin
if(ext_rst_n==1'b0)begin
en_sore <=1'b0;
end
else if(switch3==1'b0)begin
en_sore <=1'b1;
end
else begin
en_sore <=1'b0;
end
end
endmodule
module counter_24(ext_clk_25m,mclk,ext_rst_n,en_24s,en_cnt,times_24s,led
);
input ext_clk_25m ;//系統時鐘
input mclk ;//時鐘訊號
input ext_rst_n ;//復位訊號
input en_24s ;//24s使能位
input en_cnt ;//計數器停止使能位
output reg [15:0] times_24s ;
output led ;//led指示狀態
assign led =(times_24s==16'h0000);
reg [24:0] cnt ;//存放計數器的值
parameter TIME= 25'd2500_0000;
[email protected] (posedge ext_clk_25m or negedge ext_rst_n)begin
if(!ext_rst_n)begin
cnt <=25'd0;
end
else if(cnt ==TIME-1'b1)begin
cnt <=1'b0;
end
else begin
cnt <=cnt + 1'b1;
end
end
//計數器模組高位 秒計時(99)
[email protected](posedge ext_clk_25m or negedge ext_rst_n)begin
if(!ext_rst_n)begin
times_24s[7:4] <=4'h9;
end
else if(en_24s==1'b0)begin
times_24s[7:4] <=4'h9;
end
else if(en_cnt==1'b1)begin
times_24s[7:4] <=times_24s[7:4];
end
else if(cnt%25'd25_0000==0)begin
if({times_24s[7:4],times_24s[3:0]}==8'h00)begin
if({times_24s[15:12],times_24s[11:8]}==8'h00)begin
times_24s[7:4] <=4'h0;
end
else begin
times_24s[7:4] <=4'h9;
end
end
else if(times_24s[3:0]==4'h0)begin
times_24s[7:4] <=times_24s[7:4]-1'b1;
end
else begin
times_24s[7:4] <=times_24s[7:4];
end
end
else begin
times_24s[7:4] <=times_24s[7:4];
end
end
//計數器模組低位 秒計時(99)
[email protected](posedge ext_clk_25m or negedge ext_rst_n)begin
if(!ext_rst_n)begin
times_24s[3:0] <=4'h9;
end
else if(en_24s==1'b0)begin
times_24s[3:0] <=4'h9;
end
else if(en_cnt==1'b1)begin
times_24s[3:0] <=times_24s[3:0];
end
else if(cnt%25'd25_0000==0)begin
if({times_24s[7:4],times_24s[3:0]}==8'h00) begin
if({times_24s[15:12],times_24s[11:8]}==8'h00)begin
times_24s[3:0] <=4'h0;
end
else begin
times_24s[3:0] <=4'h9;
end
end
else if(times_24s[3:0]==4'h0)begin
times_24s[3:0] <=4'h9;
end
else begin
times_24s[3:0] <=times_24s[3:0]-1'b1;
end
end
else begin
times_24s[3:0] <=times_24s[3:0];
end
end
//計數器模組高位 秒計時
[email protected](posedge mclk or negedge ext_rst_n)
begin
if(!ext_rst_n)begin
times_24s[15:12] <=4'h2;
end
else if(en_24s==1'b0)begin
times_24s[15:12] <=4'h2;
end
else if(en_cnt==1'b1)begin
times_24s[15:12] <=times_24s[15:12];
end
else if({times_24s[15:12],times_24s[11:8]}==8'h00)begin
times_24s[15:12] <=4'h0;
end
else if(times_24s[11:8]==4'h0)begin
times_24s[15:12] <=times_24s[15:12]-1'b1;
end
else begin
times_24s[15:12] <=times_24s[15:12];
end
end
//計數器模組低位 秒計時
[email protected](posedge mclk or negedge ext_rst_n)begin
if(!ext_rst_n)begin
times_24s[11:8] <=4'h3;
end
else if(en_24s==1'b0)begin
times_24s[11:8] <=4'h3;
end
else if(en_cnt==1'b1)begin
times_24s[11:8] <=times_24s[11:8];
end
else if({times_24s[15:12],times_24s[11:8]}==8'h00) begin
times_24s[11:8] <=4'h0;
end
else if(times_24s[11:8]==4'h0)begin
times_24s[11:8] <=4'h9;
end
else begin
times_24s[11:8] <=times_24s[11:8]-1'b1;
end
end
endmodule
module counter_12min(ext_clk_25m,mclk,ext_rst_n,en_24s,en_cnt,times_12m,led
);
input ext_clk_25m ;//系統時鐘
input mclk ;//時鐘訊號
input ext_rst_n ;//復位訊號
input en_24s ;//24s使能位
input en_cnt ;//計數器停止使能位
output reg[15:0]times_12m ;//15-12分高位 11-8 分低位 7-4秒高位 3-0秒低位
output led ;//led指示狀態
assign led =(times_12m==16'h0000);
//計數器模組高位 分鐘計時
[email protected](posedge mclk or negedge ext_rst_n)begin
if(!ext_rst_n)begin
times_12m[15:12] <=4'h1;
end
else if(en_24s==1'b1)begin
times_12m[15:12] <=4'h1;
end
else if(en_cnt==1'b1)begin
times_12m[15:12] <=times_12m[15:12];
end
else if({times_12m[15:12],times_12m[11:8]}==8'h00)begin
times_12m[15:12] <=4'h0;
end
else if({times_12m[7:4],times_12m[3:0]}==8'h00) begin
if(times_12m[11:8]==4'h0)begin
times_12m[15:12] <=times_12m[15:12]-1'b1;
end
else begin
times_12m[15:12] <=times_12m[15:12];
end
end
else begin
times_12m[15:12] <=times_12m[15:12];
end
end
//計數器模組低位 分鐘計時
[email protected](posedge mclk or negedge ext_rst_n)begin
if(!ext_rst_n)begin
times_12m[11:8] <=4'h1;
end
else if(en_24s==1'b1)begin
times_12m[11:8] <=4'h1;
end
else if(en_cnt==1'b1)begin
times_12m[11:8] <=times_12m[11:8];
end
else if({times_12m[15:12],times_12m[11:8]}==8'h00)begin
times_12m[11:8] <=4'h0;
end
else if({times_12m[7:4],times_12m[3:0]}==8'h00) begin
if(times_12m[11:8]==4'h0)begin
times_12m[11:8] <=4'h9;
end
else begin
times_12m[11:8] <=times_12m[11:8]-1'b1;
end
end
else begin
times_12m[11:8] <=times_12m[11:8];
end
end
//計數器模組高位 秒計時
[email protected](posedge mclk or negedge ext_rst_n)
begin
if(!ext_rst_n)begin
times_12m[7:4] <=4'h5;
end
else if(en_24s==1'b1)begin
times_12m[7:4] <=4'h5;
end
else if(en_cnt==1'b1)begin
times_12m[7:4] <=times_12m[7:4];
end
else if({times_12m[7:4],times_12m[3:0]}==8'h00)begin
if({times_12m[15:12],times_12m[11:8]}==8'h00)begin
times_12m[7:4] <=4'h0;
end
else begin
times_12m[7:4] <=4'h5;
end
end
else if(times_12m[3:0]==4'h0)begin
times_12m[7:4] <=times_12m[7:4]-1'b1;
end
else begin
times_12m[7:4] <=times_12m[7:4];
end
end
//計數器模組低位 秒計時
[email protected](posedge mclk or negedge ext_rst_n)begin
if(!ext_rst_n)begin
times_12m[3:0] <=4'h9;
end
else if(en_24s==1'b1)begin
times_12m[3:0] <=4'h9;
end
else if(en_cnt==1'b1)begin
times_12m[3:0] <=times_12m[3:0];
end
else if({times_12m[7:4],times_12m[3:0]}==8'h00) begin
if({times_12m[15:12],times_12m[11:8]}==8'h00)begin
times_12m[3:0] <=4'h0;
end
else begin
times_12m[3:0] <=4'h9;
end
end
else if(times_12m[3:0]==4'h0)begin
times_12m[3:0] <=4'h9;
end
else begin
times_12m[3:0] <=times_12m[3:0]-1'b1;
end
end
endmodule
module soring(ext_clk_25m,ext_rst_n,key_down,key_left,key_entr,key_righ,en_sore,sore,led
);
input ext_clk_25m ;//時鐘訊號
input ext_rst_n ;//復位訊號
input key_down ;//切換記分
input key_left ;//1分
input key_entr ;//2分
input key_righ ;//3分
input en_sore ;//積分使能位
output [15:0] sore ;//15-8 7-0分別為兩個隊的分數
output reg [1:0] led ;//
//按鍵抖動判斷邏輯
wire key; //所有的按鍵相與的結果,用於按鍵觸發判斷
reg[3:0]keyr ; //按鍵值key的緩衝暫存器
assign key =key_down & key_entr&key_left&key_righ;
[email protected](posedge ext_clk_25m or negedge ext_rst_n)begin
if(!ext_rst_n)begin
keyr <=4'b1111;
end
else begin
keyr <={keyr[2:0],key};
end
end
wire key_neg;
wire key_pos;
assign key_neg=~keyr[2] &keyr [3];//有按鍵被按下
assign key_pos=keyr[2] &~keyr [3];//有按鍵被釋放
//定時器計數邏輯,用於對按鍵的消抖的判斷
reg [19:0] cnt;
[email protected](posedge ext_clk_25m or negedge ext_rst_n)begin
if(!ext_rst_n)begin
cnt <=20'd0;
end
else if(key_pos||key_neg)begin
cnt <=20'd0;
end
else if(cnt <20'd999_999)begin
cnt <= cnt +1'b1;
end
else begin
cnt <=20'd0;
end
end
reg[3:0]key_value_c;
reg[3:0]key_value_n;
//定時採取按鍵值
[email protected](posedge ext_clk_25m or negedge ext_rst_n)begin
if(!ext_rst_n)begin
key_value_c <=4'b1111;
key_value_n <=4'b1111;
end
else begin
if(cnt ==20'd999_999)begin
key_value_c <={key_down,key_righ,key_entr,key_left};
end
else begin
key_value_n <=key_value_c;
end
end
end
wire [3:0]key_press =key_value_n & ~key_value_c;
//計分標誌模組
reg sore_f;
[email protected](posedge ext_clk_25m or negedge ext_rst_n)begin
if(ext_rst_n==1'b0)begin
sore_f<=1'b0;
end
else if(en_sore==1'b0)begin
sore_f<=1'b0;
end
else if(key_press[3]==1'b1)begin
sore_f<=~sore_f;
end
else begin
sore_f<=sore_f;
end
end
//led指示模組
[email protected](posedge ext_clk_25m or negedge ext_rst_n)begin
if(ext_rst_n==1'b0)begin
led<=2'b11;
end
else if(en_sore==1'b0)begin
led<=led;
end
else if(sore_f==1'b0)begin
led<=2'b10;
end
else begin
led<=2'b01;
end
end
//第一隊比分
reg [7:0] sore_1;
assign sore[15:12]=sore_1/10;
assign sore[11:8]=sore_1%10;
[email protected](posedge ext_clk_25m or negedge ext_rst_n)begin
if(ext_rst_n==1'b0)begin
sore_1<=8'h00;
end
else if(en_sore==1'b0)begin
sore_1<=sore_1;
end
else if(sore_1==8'd99)begin
sore_1<=8'h00;
end
else if(key_press[0]==1'b1&&sore_f==1'b0)begin
sore_1<=sore_1+1'b1;
end
else if(key_press[1]==1'b1&&sore_f==1'b0)begin
sore_1<=sore_1+2'b10;
end
else if(key_press[2]==1'b1&&sore_f==1'b0)begin
sore_1<=sore_1+2'b11;
end
else begin
sore_1<=sore_1;
end
end
//第二隊比分
reg [7:0] sore_2;
assign sore[7:4]=sore_2/10;
assign sore[3:0]=sore_2%10;
[email protected](posedge ext_clk_25m or negedge ext_rst_n)begin
if(ext_rst_n==1'b0)begin
sore_2<=8'h00;
end
else if(en_sore==1'b0)begin
sore_2<=sore_2;
end
else if(sore_2==8'd99)begin
sore_2<=8'h00;
end
else if(key_press[0]==1'b1&&sore_f==1'b1)begin
sore_2<=sore_2+1'b1;
end
else if(key_press[1]==1'b1&&sore_f==1'b1)begin
sore_2<=sore_2+2'b10;
end
else if(key_press[2]==1'b1&&sore_f==1'b1)begin
sore_2<=sore_2+2'b11;
end
else begin
sore_2<=sore_2;
end
end
endmodule
module seg( ext_clk_25m,ext_rst_n,
times_24s,times_12m,times_sore,
en_24s,en_seg,en_sore,
dtube_cs_n,dtube_data
);
input ext_clk_25m ;//時鐘訊號25MHz
input ext_rst_n ;//復位訊號
input [15:0] times_24s ;//24秒倒計時顯示位
input [15:0] times_12m ;//12分倒計時顯示位
input [15:0] times_sore ;//分數顯示資料
input en_24s ;//24秒倒計時使能端
input en_seg ;//顯示使能端
input en_sore ;//積分使能端
output [ 3:0] dtube_cs_n ;//段選資料位
output [ 6:0] dtube_data ;//位選資料位
reg [ 3:0] dtube_cs_n ;
reg [ 6:0] dtube_data ;
reg [ 3:0] display_num ;//當前顯示資料
reg [16:0] div_cnt ;//延時計數器計數位
//延時計數器模組
[email protected] (posedge ext_clk_25m or negedge ext_rst_n)begin
if(!ext_rst_n) begin
div_cnt <= 8'd0;
end
else if(div_cnt==17'd80000)begin
div_cnt <= 8'd0;
end
else begin
div_cnt <= div_cnt+1'b1;
end
end
//顯示當前的資料模組
always @(posedge ext_clk_25m or negedge ext_rst_n)begin
if(!ext_rst_n)begin
display_num <= 4'h0;
end
else if(div_cnt < 17'd20000)begin
if(en_24s==1'b1)begin
display_num <= times_24s[3:0];
end
else if(en_sore==1'b1)begin
display_num <= times_sore[3:0];
end
else begin
display_num <= times_12m[3:0];
end
end
else if((div_cnt>17'd20000)&(div_cnt <17'd40000))begin
if(en_24s==1'b1)begin
display_num <= times_24s[7:4];
end
else if(en_sore==1'b1)begin
display_num <= times_sore[7:4];
end
else begin
display_num <= times_12m[7:4];
end
end
else if((div_cnt>17'd40000)&(div_cnt < 17'd60000))begin
if(en_24s==1'b1)begin
display_num <= times_24s[11:8];
end
else if(en_sore==1'b1)begin
display_num <= times_sore[11:8];
end
else begin
display_num <= times_12m[11:8];
end
end
else begin
if(en_24s==1'b1)begin
display_num <= times_24s[15:12];
end
else if(en_sore==1'b1)begin
display_num <= times_sore[15:12];
end
else begin
display_num <= times_12m[15:12];
end
end
end
//段選資料譯碼模組(共陰數碼管)
always @(*)begin
if(!ext_rst_n)begin
dtube_data <= 8'h00;
end
else begin
case(display_num)
4'h0: dtube_data <= 8'h3f;
4'h1: dtube_data <= 8'h06;
4'h2: dtube_data <= 8'h5b;
4'h3: dtube_data <= 8'h4f;
4'h4: dtube_data <= 8'h66;
4'h5: dtube_data <= 8'h6d;
4'h6: dtube_data <= 8'h7d;
4'h7: dtube_data <= 8'h07;
4'h8: dtube_data <= 8'h7f;
4'h9: dtube_data <= 8'h6f;
default:dtube_data <= 8'h00;
endcase
end
end
//位選選譯模組
always @(posedge ext_clk_25m or negedge ext_rst_n)begin
if(!ext_rst_n) begin
dtube_cs_n <= 4'b1111;
end
else if(en_seg==1'b1)begin
dtube_cs_n <= 4'b1111;
end
else if(div_cnt <= 17'd20000)begin
dtube_cs_n <= 4'b1110;
end
else if((div_cnt>17'd20000)&(div_cnt <=17'd40000))begin
dtube_cs_n <= 4'b1101;
end
else if((div_cnt>17'd40000)&(div_cnt <=17'd60000))begin
dtube_cs_n <= 4'b1011;
end
else if((div_cnt>17'd60000)&(div_cnt <=17'd80000))begin
dtube_cs_n <=4'b0111;
end
else begin
dtube_cs_n <= 4'b1111;
end
end
endmodule