這次的任務相對上次來說代碼書寫的更爲規範和簡潔
任務一、籃球計分器
功能:按照籃球賽賽制進行設計。須具有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;
//數碼管特殊狀態閃爍計數器模塊
always@(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倒計時
always@(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
//計分和計時顯示切換
always@(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 div(ext_clk_25m,ext_rst_n,mclk
);
input ext_clk_25m ;//輸入時鐘
input ext_rst_n ;//復位端口
output reg mclk ;//輸出1Hz
reg [23:0] cnt ;//存放計數器的值
parameter TIME= 24'd1250_0000;//時鐘25MHz
//分頻模塊,使得輸入時鐘爲25MHz輸出時鐘爲1Hz
always@ (posedge ext_clk_25m or negedge ext_rst_n)begin
if(!ext_rst_n)begin
mclk <=1'b0;
cnt <=24'd0;
end
else if(cnt ==TIME-1'b1)begin
mclk <=~mclk;
cnt <=1'b0;
end
else begin
cnt <=cnt + 1'b1;
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;
always@ (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)
always@(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)
always@(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
//計數器模塊高位 秒計時
always@(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
//計數器模塊低位 秒計時
always@(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);
//計數器模塊高位 分鐘計時
always@(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
//計數器模塊低位 分鐘計時
always@(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
//計數器模塊高位 秒計時
always@(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
//計數器模塊低位 秒計時
always@(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;
always@(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;
always@(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;
//定時採取按鍵值
always@(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;
always@(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指示模塊
always@(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;
always@(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;
always@(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 ;//延時計數器計數位
//延時計數器模塊
always@ (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