一 设计要求
1、 按键控制数码管显示,当按下S2时,Q4数码管显示1;再次按下S2,Q4数码管显示2;
2、 第三次按下S2,Q4数码管显示3;第四次按下S2时,Q4数码管显示4.第五次按下S2时Q4又从1开始显示,如此反复。
3、 检测按键按下需要消抖。
二 代码实现
按键控制数码管显示
LIBRARY IEEE;
USE IEEE.std_logic_1164.ALL;
USE IEEE.std_logic_unsigned.ALL;
USE IEEE.std_logic_arith.ALL;
ENTITY keykzstate IS
PORT( clk: IN std_logic;
sw: IN std_logic;
--seg:out std_logic;
seven_seg_led: out std_logic_vector(15 DOWNTO 0)
);
END ENTITY;
ARCHITECTURE behav OF keykzstate IS
SIGNAL key_rst: std_logic;
SIGNAL key_rst_r: std_logic;
SIGNAL key_rst_an:std_logic;
SIGNAL low_sw: std_logic;
SIGNAL low_sw_r: std_logic;
SIGNAL low_sw_an: std_logic;
SIGNAL mtime:integer range 0 TO 9;
SIGNAL cnt: std_logic_vector(19 DOWNTO 0);
-- five state
type state_type is (s0, s1, s2, s3, s4);
SIGNAL pre_state, nx_state:state_type; --dingyi xiantai he citai
---------------------------------------------------------
BEGIN
--seg <= '0';
PROCESS(clk)
BEGIN
if(rising_edge(clk)) then
key_rst <= sw;
end if;
END PROCESS;
---------------------------------------------------------
PROCESS(clk)
begin
if(rising_edge(clk)) then
key_rst_r <= key_rst;
end if;
END PROCESS;
key_rst_an <= key_rst_r and not key_rst; --xiaodou
PROCESS(clk)
begin
if(rising_edge(clk)) then
if key_rst_an = '0' then
cnt <= cnt+1;
else cnt <= (others=>'0');
end if;
end if;
END PROCESS;
---------------------------------------------------------
PROCESS(clk)
begin
if(rising_edge(clk)) then
if cnt = "11111111111111111111" then
low_sw <= sw;
else null;
end if;
end if;
END PROCESS;
PROCESS(clk)
begin
if(rising_edge(clk)) then
low_sw_r <= low_sw;
end if;
END PROCESS;
low_sw_an <= low_sw_r and not low_sw;
---------------------------------------------------------
-- seq process:create state
seq:PROCESS(clk)
begin
if(rising_edge(clk)) then
pre_state <= nx_state;
end if;
end process seq;
---------------------------------------------------------
-- com process:create next state and output logic
com:PROCESS(pre_state, low_sw_an)
begin
case pre_state is
when s0=>
mtime <= 0;
seven_seg_led <= conv_std_logic_vector(mtime,16);
if low_sw_an = '1' then nx_state <= s1;
else nx_state <= s0;
end if;
when s1=>
mtime <= 1;
seven_seg_led <= conv_std_logic_vector(mtime,16);
if low_sw_an = '1' then nx_state <= s2;
else nx_state <= s1;
end if;
when s2=>
mtime <= 2;
seven_seg_led <= conv_std_logic_vector(mtime,16);
if low_sw_an = '1' then nx_state <= s3;
else nx_state <= s2;
end if;
when s3=>
mtime <= 3;
seven_seg_led <= conv_std_logic_vector(mtime,16);
if low_sw_an = '1' then nx_state <= s4;
else nx_state <= s3;
end if;
when s4=>
mtime <= 4;
seven_seg_led <= conv_std_logic_vector(mtime,16);
if low_sw_an = '1' then nx_state <= s1;
else nx_state <= s4;
end if;
end case;
end process com;
end behav;
八段数码管驱动模块描述(Verilog 描述)
module seg(
clk,rst_n,en,
idis_data,
ds_stcp,ds_shcp,ds_data
);
input clk; //25M??????
input rst_n; //??????????
input en;
input [15:0] idis_data ;
output ds_stcp; //74HC595????????????????????????
output ds_shcp; //74HC595?????????????????????
output ds_data; //74HC595???????
//????? 0~F ??????
parameter SEG_NUM0 = 8'hc0,
SEG_NUM1 = 8'hf9,
SEG_NUM2 = 8'ha4,
SEG_NUM3 = 8'hb0,
SEG_NUM4 = 8'h99,
SEG_NUM5 = 8'h92,
SEG_NUM6 = 8'h82,
SEG_NUM7 = 8'hF8,
SEG_NUM8 = 8'h80,
SEG_NUM9 = 8'h90,
SEG_NUMA = 8'h88,
SEG_NUMB = 8'h83,
SEG_NUMC = 8'hc6,
SEG_NUMD = 8'ha1,
SEG_NUME = 8'h86,
SEG_NUMF = 8'h8e;
//????? 0~7????
parameter SEG_WE0 = 8'b1111_1110,
SEG_WE1 = 8'b1111_1101,
SEG_WE2 = 8'b1111_1011,
SEG_WE3 = 8'b1111_0111;
// SEG_WE4 = 8'b1110_1111,
// SEG_WE5 = 8'b1101_1111,
// SEG_WE6 = 8'b1011_1111,
// SEG_WE7 = 8'b0111_1111;
wire en;
reg clk_div_2;
reg clk1;
always@(en) //use enable siganl to break the module
begin
if (en==1)
clk1<=clk;
else clk1<=clk1;
end
always@(posedge clk1 or negedge rst_n)
if(!rst_n)
clk_div_2<=1'b0;
else
clk_div_2<=~clk_div_2;
//-------------------------------------------------
reg[3:0] seg_num; //??????
reg[7:0] seg_duan; //7???????????????8??
reg[7:0] seg_wei; //7????????
reg[7:0] cnt_4; //?????
always @(posedge clk_div_2 or negedge rst_n)
if(!rst_n) cnt_4 <= 8'd0;
else cnt_4 <= cnt_4+1'b1;
always @(posedge clk_div_2 or negedge rst_n)
if(!rst_n) seg_num <= 8'h00;
else
case(cnt_4[7:6])
2'b00: seg_num <= idis_data[3:0];
2'b01: seg_num <= idis_data[7:4];
2'b10: seg_num <= idis_data[11:8];
2'b11: seg_num <= idis_data[15:12];
default: ;
endcase
reg flag;
always @(posedge clk_div_2 or negedge rst_n)
if(!rst_n) begin seg_duan <= 8'hff;
// flag<=1'b0;
end
//else if(flag) begin seg_duan<=8'hff;
// flag<=~flag;
// end
else
case(seg_num)
4'h0: seg_duan <= SEG_NUM0;
4'h1: seg_duan <= SEG_NUM1;
4'h2: seg_duan <= SEG_NUM2;
4'h3: seg_duan <= SEG_NUM3;
4'h4: seg_duan <= SEG_NUM4;
4'h5: seg_duan <= SEG_NUM5;
4'h6: seg_duan <= SEG_NUM6;
4'h7: seg_duan <= SEG_NUM7;
4'h8: seg_duan <= SEG_NUM8;
4'h9: seg_duan <= SEG_NUM9;
4'ha: seg_duan <= SEG_NUMA;
4'hb: seg_duan <= SEG_NUMB;
4'hc: seg_duan <= SEG_NUMC;
4'hd: seg_duan <= SEG_NUMD;
4'he: seg_duan <= SEG_NUME;
4'hf: seg_duan <= SEG_NUMF;
default: ;
endcase
//????
always @(cnt_4[7:6])
case(cnt_4[7:6])
2'b00: seg_wei <= SEG_WE0;
2'b01: seg_wei <= SEG_WE1;
2'b10: seg_wei <= SEG_WE2;
2'b11: seg_wei <= SEG_WE3;
default: seg_wei <= 8'b0000_0000;
endcase
//-------------------------------------------------
//74HC95????
reg ds_stcpr; //74HC595????????????????????????
reg ds_shcpr; //74HC595?????????????????????
reg ds_datar; //74HC595???????
always @(posedge clk_div_2 or negedge rst_n)
if(!rst_n) ds_shcpr <= 1'b0;
else if((cnt_4 > 8'h02 && cnt_4 <= 8'h22) || (cnt_4 > 8'h24 && cnt_4 <= 8'h44)
|| (cnt_4 > 8'h46 && cnt_4 <= 8'h66) || (cnt_4 > 8'h68 && cnt_4 <= 8'h88)
|| (cnt_4 > 8'h90 && cnt_4 <= 8'hb0) || (cnt_4 > 8'hb2 && cnt_4 <= 8'hd2)
|| (cnt_4 > 8'hd4 && cnt_4 <= 8'hf4))
ds_shcpr <= ~ds_shcpr;
else ds_shcpr<=1'b0;
always @(posedge clk_div_2 or negedge rst_n)
if(!rst_n) ds_datar <= 1'b0;
else
case(cnt_4)
8'h02,8'h46,8'h90,8'hd4: ds_datar <= seg_duan[7];
8'h04,8'h48,8'h92,8'hd6: ds_datar <= seg_duan[6];
8'h06,8'h4a,8'h94,8'hd8: ds_datar <= seg_duan[5];
8'h08,8'h4c,8'h96,8'hda: ds_datar <= seg_duan[4];
8'h0a,8'h4e,8'h98,8'hdc: ds_datar <= seg_duan[3];
8'h0c,8'h50,8'h9a,8'hde: ds_datar <= seg_duan[2];
8'h0e,8'h52,8'h9c,8'he0: ds_datar <= seg_duan[1];
8'h10,8'h54,8'h9e,8'he2: ds_datar <= seg_duan[0];
8'h12,8'h56,8'ha0,8'he4: ds_datar <= seg_wei[0];
8'h14,8'h58,8'ha2,8'he6: ds_datar <= seg_wei[1];
8'h16,8'h5a,8'ha4,8'he8: ds_datar <= seg_wei[2];
8'h18,8'h5c,8'ha6,8'hea: ds_datar <= seg_wei[3];
8'h1a,8'h5e,8'ha8,8'hec: ds_datar <= seg_wei[4];
8'h1c,8'h60,8'haa,8'hee: ds_datar <= seg_wei[5];
8'h1e,8'h62,8'hac,8'hf0: ds_datar <= seg_wei[6];
8'h20,8'h64,8'hae,8'hf2: ds_datar <= seg_wei[7];
8'h24,8'h68,8'hb2,: ds_datar <= 1;
8'h26,8'h6a,8'hb4,: ds_datar <= 1;
8'h28,8'h6c,8'hb6,: ds_datar <= 1;
8'h2a,8'h6e,8'hb8,: ds_datar <= 1;
8'h2c,8'h70,8'hba,: ds_datar <= 1;
8'h2e,8'h72,8'hbc,: ds_datar <= 1;
8'h30,8'h74,8'hbe,: ds_datar <= 1;
8'h32,8'h76,8'hc0,: ds_datar <= 1;
8'h34,8'h78,8'hc2,: ds_datar <= 1;
8'h36,8'h7a,8'hc4,: ds_datar <= 1;
8'h38,8'h7c,8'hc6,: ds_datar <= 1;
8'h3a,8'h7e,8'hc8,: ds_datar <= 1;
8'h3c,8'h80,8'hca,: ds_datar <= 1;
8'h3e,8'h82,8'hcc,: ds_datar <= 1;
8'h40,8'h84,8'hce,: ds_datar <= 1;
8'h42,8'h86,8'hd0,: ds_datar <= 1;
default: ds_datar <= seg_duan[0];
endcase
always @(posedge clk1 or negedge rst_n)
if(!rst_n) ds_stcpr <= 1'b0;
else if((cnt_4 == 8'h02) || (cnt_4 == 8'h23) || (cnt_4 == 8'h45) || (cnt_4 == 8'h67) || (cnt_4 == 8'h89)|| (cnt_4 == 8'hb1)|| (cnt_4 == 8'hd3)) ds_stcpr <= 1'b0;
else if((cnt_4 == 8'h22) || (cnt_4 == 8'h44) || (cnt_4 == 8'h66) || (cnt_4 == 8'h88) || (cnt_4 == 8'hb0)|| (cnt_4 == 8'hd2)|| (cnt_4 == 8'hf4)) ds_stcpr <= 1'b1;
wire ds_stcp = ds_stcpr;
wire ds_shcp = ds_shcpr;
wire ds_data = ds_datar;
endmodule
三 整机电路图
四 仿真结果
五 实验结果
(a) 第0次按下SW2
(b) 第1次按下SW2
© 第2次按下SW2
(d) 第3次按下SW2
(e) 第4次按下SW2
(f) 第5次按下SW2
(g) 第6次按下SW2
(h) 第7次按下SW2
(i) 第8次按下SW2
分析图 9(a)到(i)可以知道,实验设计的电路符合如下要求:
按键控制数码管显示,当按下S2时,Q4数码管显示1;再次按下S2,Q4数码管显示2;第三次按下S2,Q4数码管显示3;第四次按下S2时,Q4数码管显示4.第五次按下S2时Q4又从1开始显示,如此反复。