蓝桥杯FPGA赛道积分赛
一、第一期部分题目
代码如下:
module led(
input wire clk,
input wire rst,
input wire key1,
output wire [7:0]led
);/*
always @(posedge clk or negedge rst)beginif(!rst)beginled<=8'b1111_1111;end else beginif(key1==0)led<=8'b0101_0101;end
end
*/assign led=(key1==0)?8'b0101_0101:8'b1111_1111;
endmodule
//状态机实现
module seg(
input wire clk,
input wire rst,
input wire [3:0]key,
output reg led1,
output wire [7:0]seg,
output wire [7:0]scl
);wire [3:0] key_value;reg [31:0] dsp_data;//状态定义localparam IDLE=2'b00;localparam ON=2'b01;localparam OFF=2'b10;//状态切换的条件wire IDLE_ON;wire ON_OFF;wire OFF_ON;reg [1:0]cstatus;reg [1:0]nstatus;key key_inst(.sys_clk(clk),.sys_rst(rst),.key_in(key),.key_data(key_value)
);segdisplay segdisplay_inst
(.clk(clk) ,.rst(rst) ,.seg_number_in(dsp_data) ,.seg_number(seg) ,.seg_choice(scl)
);
assign IDLE_ON=(cstatus==IDLE&&key_value==4'b0001);
assign ON_OFF=(cstatus==ON&&key_value==4'b0001);
assign OFF_ON=(cstatus==OFF&&key_value==4'b0001);
//初始状态
always @(posedge clk or negedge rst)beginif(!rst)cstatus<=IDLE;elsecstatus<=nstatus;
end
//状态切换
always @(*)begincase(cstatus)IDLE:begin if(IDLE_ON) nstatus<=ON ;else nstatus<=cstatus ; end ON:begin if(ON_OFF) nstatus<=OFF ;else nstatus<=cstatus ;end OFF:begin if(OFF_ON) nstatus<=ON ;else nstatus<=cstatus ; end default:nstatus<=IDLE;endcase
end
always @(*)begincase(cstatus)IDLE:begin dsp_data<={4'd10,4'd10,4'd10,4'd10,4'd10,4'd10,4'd10,4'd10}; led1<=1;end ON:begin dsp_data<={4'd10,4'd10,4'd10,4'd10,4'd10,4'd10,4'd10,4'd1}; led1<=0; end OFF:begin dsp_data<={4'd10,4'd10,4'd10,4'd10,4'd10,4'd10,4'd10,4'd0}; led1<=1; end default:dsp_data<={4'd10,4'd10,4'd10,4'd10,4'd10,4'd10,4'd10,4'd10};endcase
end
endmodule
按键驱动
module key(input wire sys_clk,input wire sys_rst,input wire [3:0] key_in,output reg [3:0] key_data
);//按键键值定义
localparam KEY_VAL_S1 =4'b0001;
localparam KEY_VAL_S2 =4'b0010;
localparam KEY_VAL_S3 =4'b0100;
localparam KEY_VAL_S4=4'b1000;
localparam KEY_VAL_NL=4'b1111;localparam KEY_COUNT_MAX =20'd500000;
//按键状态定义
localparam IDLE =3'd0;//无按键
localparam PRESS =3'd1;//有按键,确定哪个按键
localparam RELEASE =3'd2;//按键弹起//按键扫描计数器,每隔0.01秒扫描一次按键
reg [19:0] key_count;
//寄存器的定义用来存储不同的状态
reg [3:0] key_status;//按键计数更新
always@(posedge sys_clk or negedge sys_rst) beginif(sys_rst==1'b0)key_count <=0;else beginif(key_count == KEY_COUNT_MAX-1)beginkey_count <= 0;end elsekey_count = key_count + 1; endend//按键状态更新
always@(posedge sys_clk or negedge sys_rst)beginif(sys_rst==1'b0)begin//复位key_data <= KEY_VAL_NL;key_status<=IDLE;end else beginif(key_data == KEY_VAL_NL) begin//无按键if(key_count==KEY_COUNT_MAX-1)begin//消抖10ms//无按键,初始状态if(key_status==IDLE)begin//无按键按下,初始状态if(key_in!=4'b1111)//有按键动作产生(无按键时,IO信号:1111,)key_status<=PRESS;//按键处于按下状态end else if(key_status==PRESS)begin//有按键动作产生,需要根据IO状态,并且判断哪一个按键按下,按键状态:下一个状态case(key_in)4'b1110: begin key_data <=KEY_VAL_S1; key_status <=RELEASE; end //S1按下4'b1101: begin key_data <=KEY_VAL_S2; key_status <=RELEASE; end4'b1011: begin key_data <=KEY_VAL_S3; key_status <=RELEASE; end4'b0111: begin key_data <=KEY_VAL_S4; key_status <=RELEASE; end default: begin key_data <=KEY_VAL_NL; key_status <=IDLE; end endcase//按键是否弹起,无任何按键按下,IO->1111 end else begin if(key_in == 4'b1111)key_status <=IDLE;endendend elsekey_data <=KEY_VAL_NL;//清零键值(清零键值)end end
endmodule
二、第二期的部分题目
代码如下
module led(
input clk,
input rst,
input [3:0]key_in,
output reg [7:0] led
);
reg [7:0]count;
wire [3:0]key_value;always @(posedge clk or negedge rst)beginif(!rst)begincount<=0;end elsecase(key_value)4'b0001:begin if(count<255)count<=count+1;elsecount<=0;end 4'b0010:beginif(count>0)count<=count-1;elsecount<=255;end default:count<=count;endcase
end
//1->0000_0001取反->1111_1110
always @(posedge clk or negedge rst)beginif(!rst)beginled<=8'b1111_1111;end elseled<=~count;
end
key key_inst(.sys_clk(clk),.sys_rst(rst),.key_in(key_in),.key_data(key_value)
);endmodule
按键驱动
module key(input wire sys_clk,input wire sys_rst,input wire [3:0] key_in,output reg [3:0] key_data
);//按键键值定义
localparam KEY_VAL_S1 =4'b0001;
localparam KEY_VAL_S2 =4'b0010;
localparam KEY_VAL_S3 =4'b0100;
localparam KEY_VAL_S4=4'b1000;
localparam KEY_VAL_NL=4'b1111;localparam KEY_COUNT_MAX =20'd500000;
//按键状态定义
localparam IDLE =3'd0;//无按键
localparam PRESS =3'd1;//有按键,确定哪个按键
localparam RELEASE =3'd2;//按键弹起//按键扫描计数器,每隔0.01秒扫描一次按键
reg [19:0] key_count;
//寄存器的定义用来存储不同的状态
reg [3:0] key_status;//按键计数更新
always@(posedge sys_clk or negedge sys_rst) beginif(sys_rst==1'b0)key_count <=0;else beginif(key_count == KEY_COUNT_MAX-1)beginkey_count <= 0;end elsekey_count = key_count + 1; endend//按键状态更新
always@(posedge sys_clk or negedge sys_rst)beginif(sys_rst==1'b0)begin//复位key_data <= KEY_VAL_NL;key_status<=IDLE;end else beginif(key_data == KEY_VAL_NL) begin//无按键if(key_count==KEY_COUNT_MAX-1)begin//消抖10ms//无按键,初始状态if(key_status==IDLE)begin//无按键按下,初始状态if(key_in!=4'b1111)//有按键动作产生(无按键时,IO信号:1111,)key_status<=PRESS;//按键处于按下状态end else if(key_status==PRESS)begin//有按键动作产生,需要根据IO状态,并且判断哪一个按键按下,按键状态:下一个状态case(key_in)4'b1110: begin key_data <=KEY_VAL_S1; key_status <=RELEASE; end //S1按下4'b1101: begin key_data <=KEY_VAL_S2; key_status <=RELEASE; end4'b1011: begin key_data <=KEY_VAL_S3; key_status <=RELEASE; end4'b0111: begin key_data <=KEY_VAL_S4; key_status <=RELEASE; end default: begin key_data <=KEY_VAL_NL; key_status <=IDLE; end endcase//按键是否弹起,无任何按键按下,IO->1111 end else begin if(key_in == 4'b1111)key_status <=IDLE;endendend elsekey_data <=KEY_VAL_NL;//清零键值(清零键值)end end
endmodule
代码如下:
顶层文件
module led(
input clk,
input rst,
input [3:0]key_in,
output reg [7:0] led,
output wire [7:0]seg,
output wire [7:0]sel
);
//按键键值
wire [3:0]key_value;
//数码管显示的数据
reg [31:0]data;
//计数值最大值
parameter [25:0] MS_MAX=26'd50_000_000;
//1秒计数值
reg [25:0] timer;
//计数值
reg [8:0] count;parameter [3:0]STARTCOUNT=1;
parameter [3:0]STOPCOUNT=2;
parameter [3:0]COUNT_0=3;
reg [3:0] status_count;//1s计时
always @(posedge clk or negedge rst)beginif(!rst)begintimer<=0;end else beginif(status_count==STARTCOUNT)beginif(timer==MS_MAX-1)timer<=0;elsetimer<=timer+1;end else timer<=timer;end
end
//计数值加1
always @(posedge clk or negedge rst)beginif(!rst)begincount<=0;end else beginif(status_count==STARTCOUNT)begin if(timer==MS_MAX-1)beginif(count<80)count<=count+1;elsecount<=0; end elsecount<=count;end else if(status_count==STOPCOUNT)begincount<=count;end elsecount<=0;end
end//always @(posedge clk or negedge rst)beginif(!rst)beginstatus_count<=STOPCOUNT;end elsecase(key_value)4'b0001:begin status_count<=STARTCOUNT;end 4'b0010:beginstatus_count<=STOPCOUNT;end 4'b0100:beginstatus_count<=COUNT_0;end default:status_count<=status_count;endcase
end
always @(posedge clk or negedge rst)beginif(!rst)beginled<=8'b1111_1111; end begincase(count)0:led<=8'b1111_1111;10:led<=8'b1111_1110;20:led<=8'b1111_1100;30:led<=8'b1111_1000;40:led<=8'b1111_0000;50:led<=8'b1110_0000;60:led<=8'b1100_0000;70:led<=8'b1000_0000;80:led<=8'b0000_0000;default:led<=8'b1111_1111;endcaseend
end always @(posedge clk or negedge rst)beginif(!rst)begindata<={4'd10,4'd11,4'd11,4'd11,4'd11,4'd11,4'd0,4'd0};end else begin data[7:4]<=count/10;data[3:0]<=count%10;end
endkey key_inst(.sys_clk(clk),.sys_rst(rst),.key_in(key_in),.key_data(key_value)
);seg seg_inst
(
.clk(clk) ,
.rst(rst) ,
.dsp_data(data) ,
.seg(seg) ,//段选端
.sel(sel) //位选段
);endmodule
按键驱动
module key(input wire sys_clk,input wire sys_rst,input wire [3:0] key_in,output reg [3:0] key_data
);//按键键值定义
localparam KEY_VAL_S1 =4'b0001;
localparam KEY_VAL_S2 =4'b0010;
localparam KEY_VAL_S3 =4'b0100;
localparam KEY_VAL_S4=4'b1000;
localparam KEY_VAL_NL=4'b1111;localparam KEY_COUNT_MAX =20'd500000;
//按键状态定义
localparam IDLE =3'd0;//无按键
localparam PRESS =3'd1;//有按键,确定哪个按键
localparam RELEASE =3'd2;//按键弹起//按键扫描计数器,每隔0.01秒扫描一次按键
reg [19:0] key_count;
//寄存器的定义用来存储不同的状态
reg [3:0] key_status;//按键计数更新
always@(posedge sys_clk or negedge sys_rst) beginif(sys_rst==1'b0)key_count <=0;else beginif(key_count == KEY_COUNT_MAX-1)beginkey_count <= 0;end elsekey_count = key_count + 1; endend//按键状态更新
always@(posedge sys_clk or negedge sys_rst)beginif(sys_rst==1'b0)begin//复位key_data <= KEY_VAL_NL;key_status<=IDLE;end else beginif(key_data == KEY_VAL_NL) begin//无按键if(key_count==KEY_COUNT_MAX-1)begin//消抖10ms//无按键,初始状态if(key_status==IDLE)begin//无按键按下,初始状态if(key_in!=4'b1111)//有按键动作产生(无按键时,IO信号:1111,)key_status<=PRESS;//按键处于按下状态end else if(key_status==PRESS)begin//有按键动作产生,需要根据IO状态,并且判断哪一个按键按下,按键状态:下一个状态case(key_in)4'b1110: begin key_data <=KEY_VAL_S1; key_status <=RELEASE; end //S1按下4'b1101: begin key_data <=KEY_VAL_S2; key_status <=RELEASE; end4'b1011: begin key_data <=KEY_VAL_S3; key_status <=RELEASE; end4'b0111: begin key_data <=KEY_VAL_S4; key_status <=RELEASE; end default: begin key_data <=KEY_VAL_NL; key_status <=IDLE; end endcase//按键是否弹起,无任何按键按下,IO->1111 end else begin if(key_in == 4'b1111)key_status <=IDLE;endendend elsekey_data <=KEY_VAL_NL;//清零键值(清零键值)end end
endmodule
数码管驱动
module seg
(input wire clk ,input wire rst ,input wire [31:0] dsp_data ,output reg [7:0] seg ,//段选端output reg [7:0] sel //位选段
);localparam [7:0] DIGIT0 =8'b1100_0000 ;//16精制C0
localparam [7:0] DIGIT1 =8'b1111_1001 ;//F9
localparam [7:0] DIGIT2 =8'b1010_0100;//A4
localparam [7:0] DIGIT3 =8'b1011_0000;//B0
localparam [7:0] DIGIT4 =8'b1001_1001;//99
localparam [7:0] DIGIT5 =8'b1001_0010;//92
localparam [7:0] DIGIT6 =8'b1000_0010;//82
localparam [7:0] DIGIT7 =8'b1111_1000;//F8
localparam [7:0] DIGIT8 =8'b1000_0000;//80
localparam [7:0] DIGIT9 =8'b1001_0000 ;//90
localparam [7:0] DIGITX =8'b1011_1111 ;//
localparam [7:0] DIGOFF =8'b1111_1111 ;//FF
localparam [7:0] DIGITC =8'hC6 ;
localparam DSP_COUNT = 20'd50000; //reg [19:0] dsp_count ;
reg [3:0] bits ;
reg [3:0] bcd ;//1ms的计数器
always @(posedge clk or negedge rst)begin if(!rst)dsp_count <= 20'd0;else begin if (dsp_count == DSP_COUNT-1) begin dsp_count <= 20'd0;end else dsp_count <= dsp_count + 20'd1;end
end
//位选端
always @(posedge clk or negedge rst) begin if(!rst)beginsel <= 8'b1111_1111;bits <=4'd0;end else begin if(dsp_count==DSP_COUNT-1)begin//每一毫秒更新一次if(bits==4'd8)bits <=4'd0;elsebits<=bits+4'd1;case(bits)4'd0: begin sel<=8'b1111_1110;bcd<=dsp_data[31:28] ;end4'd1: begin sel<=8'b1111_1101;bcd<=dsp_data[27:24] ;end4'd2: begin sel<=8'b1111_1011;bcd<=dsp_data[23:20] ;end4'd3: begin sel<=8'b1111_0111;bcd<=dsp_data[19:16] ;end4'd4: begin sel<=8'b1110_1111;bcd<=dsp_data[15:12] ;end4'd5: begin sel<=8'b1101_1111;bcd<=dsp_data[11:8] ;end4'd6: begin sel<=8'b1011_1111;bcd<=dsp_data[7:4] ;end4'd7: begin sel<=8'b0111_1111;bcd<=dsp_data[3:0] ;enddefault:sel<=8'b1111_1111;endcaseend end
end
//段选端
always @(posedge clk or negedge rst)beginif(!rst)seg<=DIGOFF;else begin case(bcd)4'd0: seg<=DIGIT0;4'd1: seg<=DIGIT1;4'd2: seg<=DIGIT2;4'd3: seg<=DIGIT3;4'd4: seg<=DIGIT4;4'd5: seg<=DIGIT5;4'd6: seg<=DIGIT6;4'd7: seg<=DIGIT7;4'd8: seg<=DIGIT8;4'd9: seg<=DIGIT9;4'd10:seg<=DIGITC;//4'ha: seg<=DIGOFF;//4'hb: seg<=DIGITX;default: seg<=DIGOFF;endcaseend
end
endmodule
声明:本代码借鉴网络资料,如有侵权和错误请联系作者删除。
三、蓝桥杯备赛总结
我是从寒假开始备赛的,由于我基础不行,备赛过程中也是混混呃呃的,备赛效率不高,总体来说备赛不认真,有点拖拉,但是最后我也坚持备赛到了今天,在备赛过程中,即复习了旧的东西,也学到了新的东西,总结起来还是有点收获的,后天北京、天津、河北地区就要进行省赛了,我会全力以赴,不管结果怎么样,尽力就好,最后祝大家都能取到好成绩,也感谢大家对我写的博客文章的支持,接下来我会努力创造出更好的博客文章,大家一起共同进步。