|
一、按键控制数码管循环显示的概念:
就是通过两个按键控制计数器里面的数据的加减,然后把计数器里面的数据转换成十进制,最后通过数码管把这个十进制显示出来。
二、电路原理
整个电路共有6个模块组成,两个按键检测模块,一个计数模块,一个二进制转十进制模块,一个分频模块以及一个数码管控制模块。按键检测模块主要是用于检测按键有没有被按下以及对被按下的键进行消抖操作。按键消抖的原理是检测它的电平,当检测到低电平后延时5ms-10ms仍有低电平说按键按下稳定,此时即可输出检测信号,这就实现了按键的检测与消抖。当按键模块检测到按键被按下时就会输出一个flag信号,并将此信号传给计数模块。计数模块在接受到flah信号时就对寄存器进行加1或减1操作,当加到255时,就把计数器清零,当减到零时就把寄存器置为255,这样就实现了计数器的循环计数。由于计数器里面的数据是二进制的,所以还要把计数器里的数据输出,传给二进制转十进制模块,进行二进制转十进制。转换得到的数据再传给数码管控制模块,并将数据显示出来。
三、架构图设计:
四、建模与验证:
1. 按键检测模块代码
module key_check (clk, rst_n, key_in, flag);
input clk;
input rst_n;
input key_in;
outputreg flag;
reg[31:0] count;
reg state;
`define T 50_000_000/100 //延时10ms的参数
// `define T 5 //fang zhen shi yong
always@(posedge clk ornegedge rst_n)
begin
if(!rst_n)
begin
flag <=0;
count <=0;
state <=0;
end
else
begin
case(state)
0:begin
if(!key_in)
begin
if(count <`T-1)
begin
count <= count +1'b1;
end
else
begin
count <=0;
flag <=1;
state <=1;
end
end
else
begin
count <=0;
flag <=0;
state <=0;
end
end
1: begin
flag <=0;
if(key_in)
begin
if(count <`T-1)
count <= count +1'b1;
else
begin
count <=0;
flag <=0;
state <=0;
end
end
else
begin
count <=0;
state <=1;
end
end
endcase
end
end
endmodule
2. 计数模块代码
module count(clk, rst_n, flag1, flag2, cnt_num);
input clk;
input rst_n;
input flag1, lag2;
outputreg[7:0] cnt_num;
always@(posedge clk ornegedge rst_n)
begin
if(!rst_n)
begin
cnt_num <=8'd0;
end
else
begin
if(cnt_num <0)
cnt_num <=8'd255;
elseif(cnt_num >255)
cnt_num <=8'd0;
else
if(flag1)
cnt_num <= cnt_num +1'b1;
else
if(flag2)
cnt_num <= cnt_num -1'b1;
else cnt_num <= cnt_num;
end
end
endmodule
3. 二进制转十进制模块代码
module bin_bcd_2(bin_data, bcd_data);
input[7:0] bin_data;
outputreg[11:0]bcd_data;
always@(*)
begin
bcd_data[3:0]= bin_data%10;
bcd_data[7:4]=(bin_data/10)%10;
bcd_data[11:8]=(bin_data/100)%10;
end
endmodule
4. 分频模块代码
module devide(clk, rst_n, clk_out);
input clk;
input rst_n;
outputreg clk_out;
parameter HW =24_999;
reg[15:0] count;
always@(posedge clk ornegedge rst_n)
begin
if(!rst_n)
begin
clk_out <=0;
count <=0;
end
else
begin
if(count < HW -1)
count <= count +1'b1;
else
begin
count <=0;
clk_out <=~clk_out;
end
end
end
endmodule
5. 数码管模块代码
module seg_state(clk,rst_n,data_in,sel,seg);
input clk;
input rst_n;
input[11:0]data_in;
outputreg[2:0] sel;
outputreg[7:0] seg;
reg[1:0] state;
reg[3:0] data_temp;
parameter s0 =2'd0;
parameter s1 =2'd1;
parameter s2 =2'd2;
// parameter s3 = 2'd3;
// parameter s4 = 2'd4;
// parameter s5 = 2'd5;
always@(posedge clk ornegedge rst_n)
begin
if(!rst_n)
begin
state <= s0;
sel <=3'b111;
data_temp <=4'd0;
end
else
begin
case(state)
s0 :
begin
sel <=3'b011;
data_temp <= data_in[11:8];
state <= s1;
end
s1 :
begin
sel <=3'b100;
data_temp <= data_in[7:4];
state <= s2;
end
s2 :
begin
sel <=3'b101;
data_temp <= data_in[3:0];
state <= s0;
end
default: state <= s0;
endcase
end
end
always@(*)
begin
if(!rst_n)
begin
seg <=8'b0111_1111;
end
else
begin
case(data_temp)
// case (data_in)
4'd0: seg <=8'hc0; //0
4'd1: seg <=8'hf9; //1
4'd2: seg <=8'ha4; //2
4'd3: seg <=8'hb0; //3
4'd4: seg <=8'h99; //4
4'd5: seg <=8'h92; //5
4'd6: seg <=8'h82; //6
4'd7: seg <=8'hf8; //7
4'd8: seg <=8'h80; //8
4'd9: seg <=8'h90; //9
4'd10: seg <=8'h88; //a
4'd11: seg <=8'h83; //b
4'd12: seg <=8'hc6; //c
4'd13: seg <=8'ha1; //d
4'd14: seg <=8'h86; //e
4'd15: seg <=8'h8e; //f
default: seg <=8'b0111_1111;
endcase
end
end
endmodule
6. RTL级视图
7. 仿真结果图
总结:在把代码下板后,通过按键可以看到数码管显示的数据,当到了255后加1就变为0,当到了0后减1就是255,这就达到了我们循环显示的目的。本次的设计是一个比较综合的设计,把前面所学的按键,数码管,二进制转十进制都结合了起来。涉及的东西比较的多,过程相对比较多而复杂,但通过分成多个模块来解决问题,就变简单了许多,这就体现了FPGA至顶而下的设计思路。
|
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有账号?我要注册
x
|