01 module key_scan_flctek(clk, rst_n,key_in, key_n);
02
03 inputclk;
04 inputrst_n;
05 inputkey_in;
06 outputreg key_n;
07
08 regtemp;
09 reg[31:0] count;
10 regstate;
11
12 localparam MASK_tiME = 1000000;
13
14 always@(posedge clk or negedge rst_n)
15 begin
16 if(!rst_n)
17 begin
18 state<= 0;
19 temp<= 1;
20 count<= 0;
21 key_n<= 1;
22 end
23 else
24 case(state)
25 0 : begin
26 if(key_in== temp)
27 state <= 0;
28 else begin
29 state <= 1;
30 temp<= key_in;
31 end
32 end
33 1: begin
34 if(key_in == temp)
35 if(count < MASK_TIME-1)
36 begin
37 count<= count + 1;
38 state<= 1;
39 end
40 else
41 begin
42 key_n<= temp;
43 count<= 0;
44 state<= 0;
45 end
46 else
47 begin
48 temp<= key_in;
49 count <=0;
50 state<= 1;
51 end
52 end
53 endcase
54 end
55
56 endmodule
计数模块程序
01 modulecount_key(rst_n, key_n, count_key);
02
03 inputkey_n,rst_n;
04 output reg [19:0] count_key;
05
06 //此处必须以按键状态为时钟不能采用组合逻辑以按键状态为判断条件做判断,
07 //这样的话当按键状态为低电平时计数器会一直计数
08 //而实际的要求是如果按键按下则计一次数相背。
09 always @(posedge key_n or negedge rst_n)
10 begin
11 if(!rst_n)
12 begin
13 count_key= 0;
14 end
15 else if((count_key < 20'd999999))
16 count_key= count_key + 1;
17 else
18 count_key= count_key;
19
20
21 end
22
23 endmodule
二进制转BCD部分(采用“大四加三”法)
给大家来个例子说明一下例如输入的二进制数是8’b1111_1111,经过逐步移位的方法最终得到的BCD码为:12’b1_0101_0101,其对应的十进制百位,十位,个位,分别是:2,5,5.这种移位的方法首先设计者必须清楚的是被转换的二进制数的位宽,和最终转换为BCD码的位宽,由于中间用到一个移位寄存器此移位寄存器的位宽等于被转的二进制数位宽加上最终转换的BCD码的位宽。所以本例中的移位寄存器位宽为20,采用这种方法移位的此处比位修正的次数多一次,即就是最后一次只进行移位操作,而不进行位修正计数(每位所对应的4位BCD码如果大于四必须进行加三操作)。应用这种方法移完即可得到对应的BCD码。本例子的以为过程及修正如下表所示:
二进制转BCD代码部分
01 moduleb_BCD(count_key, data_out);
02
03 input[19:0] count_key;
04 output[23:0] data_out;
05
06 wire[43:0] shift_reg [19:0];
07
08 assignshift_reg[19] = {23'b0, count_key, 1'b0};
09
10
11 bcd_modify b19(.data_in(shift_reg[19]), .data_out(shift_reg[18]));
12 bcd_modify b18(.data_in(shift_reg[18]), .data_out(shift_reg[17]));
13 bcd_modify b17(.data_in(shift_reg[17]), .data_out(shift_reg[16]));
14 bcd_modify b16(.data_in(shift_reg[16]), .data_out(shift_reg[15]));
15 bcd_modify b15(.data_in(shift_reg[15]), .data_out(shift_reg[14]));
16 bcd_modify b14(.data_in(shift_reg[14]), .data_out(shift_reg[13]));
17 bcd_modify b13(.data_in(shift_reg[13]), .data_out(shift_reg[12]));
18 bcd_modify b12(.data_in(shift_reg[12]), .data_out(shift_reg[11]));
19 bcd_modify b11(.data_in(shift_reg[11]), .data_out(shift_reg[10]));
20 bcd_modify b10(.data_in(shift_reg[10]), .data_out(shift_reg[9]));
21 bcd_modify b9(.data_in(shift_reg[9]), .data_out(shift_reg[8]));
22 bcd_modify b8(.data_in(shift_reg[8]), .data_out(shift_reg[7]));
23 bcd_modify b7(.data_in(shift_reg[7]), .data_out(shift_reg[6]));
24 bcd_modify b6(.data_in(shift_reg[6]), .data_out(shift_reg[5]));
25 bcd_modify b5(.data_in(shift_reg[5]), .data_out(shift_reg[4]));
26 bcd_modify b4(.data_in(shift_reg[4]), .data_out(shift_reg[3]));
27 bcd_modify b3(.data_in(shift_reg[3]), .data_out(shift_reg[2]));
28 bcd_modify b2(.data_in(shift_reg[2]), .data_out(shift_reg[1]));
29 bcd_modify b1(.data_in(shift_reg[1]), .data_out(shift_reg[0]));
30
31
32 assigndata_out = shift_reg[0][43:20];//取出data_out的高24位即为所求的BCD码
33
34 endmodule
01 modulebcd_modify(data_in, data_out);
02
03 input[43:0] data_in;
04 output[43:0] data_out;
05
06 wire[43:0] reg_out;
07
08 bcd_sigle_modifybcd_6(.data_in(data_in[43:40]), .data_out(reg_out[43:40]));
09 bcd_sigle_modifybcd_5(.data_in(data_in[39:36]), .data_out(reg_out[39:36]));
10 bcd_sigle_modifybcd_4(.data_in(data_in[35:32]), .data_out(reg_out[35:32]));
11 bcd_sigle_modifybcd_3(.data_in(data_in[31:28]), .data_out(reg_out[31:28]));
12 bcd_sigle_modifybcd_2(.data_in(data_in[27:24]), .data_out(reg_out[27:24]));
13 bcd_sigle_modifybcd_1(.data_in(data_in[23:20]), .data_out(reg_out[23:20]));
14
15
16 assignreg_out[19:0] = data_in[19:0]; //相当于将每次只做高24位的修正地位不做修正,低20位的数据
17 assign data_out = {reg_out[42:0],1'b0};
18
19 endmodule
01 module bcd_sigle_modify(data_in,data_out);
02
03 input[3:0] data_in;
04 outputreg [3:0] data_out;
05
06 always@ (data_in)
07 begin
08 if(data_in> 4)
09 data_out = data_in + 3;
10 else
11 data_out = data_in;
12 end
13
14 endmodule
数码管显示部分程序
01 module seg_n(clk, rst_n, data_in, sel,seg);
02
03 inputclk;
04 inputrst_n;
05 input[23:0] data_in;
06 outputreg [2:0] sel;
07 outputreg [7:0] seg;
08
09 wireclk_en; //数码管显示时钟标志高电平有效
10 reg[31:0] count;
11
12
13 always@(posedgeclk or negedge rst_n)
14 begin
15 if(!rst_n) begin
16 count<= 0;
17 end
18 elseif(count < 24999)
19 count<= count + 1'b1;
20 elsebegin
21 count <= 0;
22 end
23 end
24
25 assignclk_en = (count == 24999)? 1'b1 : 1'b0;
26
27//产生片选信号
28 always@(posedgeclk or negedge rst_n)
29 begin
30 if(!rst_n)
31 sel<= 3'b101;
32 elseif(clk_en)
33 begin
34 if((0< sel)&&(sel <= 5))
35 sel<= sel- 1'b1;
36 elsesel <= 3'b101;
37 end else
38 sel<= sel;
39 end
40
41 reg[3:0] data_n;
42//获取所要显示的数据
43 always@(*)
44 begin
45 if(!rst_n)
46 data_n<= 24'hfffff0;
47 elsecase(sel)
48 0:data_n <= data_in [23:20];
49 1:data_n <= data_in [19:16];
50 2:data_n <= data_in [15:12];
51 3:data_n <= data_in [11:8];
52 4:data_n <= data_in [7:4];
53 5:data_n <= data_in [3:0];
54 default:data_n <=0;
55 endcase
56 end
57//进行译码操作
58 always@(*)
59 begin
60 if(!rst_n)
61 seg<= 8'hff;
62 elsecase(data_n)
63 0:seg = 8'hc0;
64 1:seg = 8'hf9;
65 2:seg = 8'ha4;
66 3:seg = 8'hb0;
67 4:seg = 8'h99;
68 5:seg = 8'h92;
69 6:seg = 8'h82;
70 7:seg = 8'hf8;
71 8:seg = 8'h80;
72 9:seg = 8'h90;
73 10: seg = 8'h8f;
74 11: seg = 8'hbf;
75 12: seg = 8'h89;
76 13: seg = 8'had;
77 14: seg = 8'hb7;
78 15: seg = 8'hff;
79 endcase
80 end
81 endmodule
系统顶层程序
module key_seg_top(clk, rst_n, key_in, sel,seg);
inputclk;
inputrst_n;
inputkey_in;
output[2:0] sel;
output[7:0] seg;
wirekey_n;
wire[19:0] count_key;
wire[23:0] data_in ;
key_scan_flctekkey_scan_flctek_inst(.clk(clk), .rst_n(rst_n), .key_in(key_in),.key_n(key_n)); //该模块主要是用来进行按键检测及按键消抖用的
count_keycount_key_inst(.rst_n(rst_n), .key_n(key_n), .count_key(count_key));//此模块主要是实现按键次数的计数
b_BCDb_BCD_inst(.count_key(count_key), .data_out(data_in)); //此模块主要实现将按键次数的计数值转化为BCD码,然后将转化的数值发送给数码管显示模块
seg_nseg_inst(.clk(clk), .rst_n(rst_n), .data_in(data_in), .sel(sel), .seg(seg));//实现数码管显示模块
endmodule
测试模块程序
`timescale 1ns/1ns
module key_seg_top_tb;
regclk;
regrst_n;
regkey_in;
wire[2:0] sel;
wire[7:0] seg;
key_seg_topkey_seg_top_inst(.clk(clk), .rst_n(rst_n), .key_in(key_in), .sel(sel),.seg(seg));
initial begin
clk = 1;
rst_n= 0;
key_in = 1;
#20.1 rst_n = 1;
#200
key_in= 0;
//抬起小于10拍
#400
key_in= 1;
#10
key_in= 0;
#20
key_in= 1;
#80
key_in= 0;
//一直抬起
key_in= 1;
#200
key_in= 0;
//抬起小于10拍
#400
key_in= 1;
#10
key_in= 0;
#20
key_in= 1;
#80
key_in= 0;
//一直抬起
key_in= 1;
#200
key_in= 0;
//抬起小于10拍
#400
key_in= 1;
#10
key_in= 0;
#20
key_in= 1;
#80
key_in= 0;
//一直抬起
key_in= 1;
#200
key_in= 0;
//抬起小于10拍
#400
key_in= 1;
#10
key_in= 0;
#20
key_in= 1;
#80
key_in= 0;
//一直抬起
key_in= 1;
#200
key_in= 0;
//抬起小于10拍
#400
key_in= 1;
#10
key_in= 0;
#20
key_in= 1;
#80
key_in= 0;
//一直抬起
key_in= 1;
#200
key_in= 0;
//抬起小于10拍
#400
key_in= 1;
#10
key_in= 0;
#20
key_in= 1;
#80
key_in= 0;
//一直抬起
key_in= 1;
#200
key_in= 0;
//抬起小于10拍
#400
key_in= 1;
#10
key_in= 0;
#20
key_in= 1;
#80
key_in= 0;
//一直抬起
key_in= 1;
#200
key_in= 0;
//抬起小于10拍
#400
key_in= 1;
#10
key_in= 0;
#20
key_in= 1;
#80
key_in= 0;
//一直抬起
key_in= 1;
#200
key_in= 0;
//抬起小于10拍
#400
key_in= 1;
#10
key_in= 0;
#20
key_in= 1;
#80
key_in= 0;
//一直抬起
key_in= 1;
#200
key_in= 0;
//抬起小于10拍
#400
key_in= 1;
#10
key_in= 0;
#20
key_in= 1;
#80
key_in= 0;
//一直抬起
key_in= 1;
#200
key_in= 0;
//抬起小于10拍
#400
key_in= 1;
#10
key_in= 0;
#20
key_in= 1;
#80
key_in= 0;
//一直抬起
key_in= 1;
#200
key_in= 0;
//抬起小于10拍
#400
key_in= 1;
#10
key_in= 0;
#20
key_in= 1;
#80
key_in= 0;
//一直抬起
key_in= 1;
#200
key_in= 0;
//抬起小于10拍
#400
key_in= 1;
#10
key_in= 0;
#20
key_in= 1;
#80
key_in= 0;
//一直抬起
key_in= 1;
#200
key_in= 0;
//抬起小于10拍
#400
key_in= 1;
#10
key_in= 0;
#20
key_in= 1;
#80
key_in= 0;
//一直抬起
key_in= 1;
#200
key_in= 0;
//抬起小于10拍
#400
key_in= 1;
#10
key_in= 0;
#20
key_in= 1;
#80
key_in= 0;
//一直抬起
key_in= 1;
#200
key_in= 0;
//抬起小于10拍
#400
key_in= 1;
#10
key_in= 0;
#20
key_in= 1;
#80
key_in= 0;
//一直抬起
key_in= 1;
#200
key_in= 0;
//抬起小于10拍
#400
key_in= 1;
#10
key_in= 0;
#20
key_in= 1;
#80
key_in= 0;
//一直抬起
key_in= 1;
#200
key_in= 0;
//抬起小于10拍
#400
key_in= 1;
#10
key_in = 0;
#20
key_in= 1;
#80
key_in= 0;
//一直抬起
key_in= 1;
#200
key_in= 0;
//抬起小于10拍
#400
key_in= 1;
#10
key_in= 0;
#20
key_in= 1;
#80
key_in= 0;
//一直抬起
key_in= 1;
#200
key_in= 0;
//抬起小于10拍
#400
key_in= 1;
#10
key_in= 0;
#20
key_in= 1;
#80
key_in= 0;
//一直抬起
key_in= 1;
#200
key_in= 0;
//抬起小于10拍
#400
key_in= 1;
#10
key_in= 0;
#20
key_in= 1;
#80
key_in= 0;
//一直抬起
key_in= 1;
#200
key_in= 0;
//抬起小于10拍
#400
key_in= 1;
#10
key_in= 0;
#20
key_in= 1;
#80
key_in= 0;
//一直抬起
key_in= 1;
#200
key_in= 0;
//抬起小于10拍
#400
key_in= 1;
#10
key_in= 0;
#20
key_in= 1;
#80
key_in= 0;
//一直抬起
key_in= 1;
#200
key_in= 0;
//抬起小于10拍
#400
key_in= 1;
#10
key_in= 0;
#20
key_in= 1;
#80
key_in= 0;
//一直抬起
key_in= 1;
end
always#10 clk = ~clk;
endmodule