按键控制的状态机设计
一 设计要求
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)) thenkey_rst <= sw;end if;END PROCESS;
---------------------------------------------------------PROCESS(clk)beginif(rising_edge(clk)) thenkey_rst_r <= key_rst;end if;END PROCESS;
key_rst_an <= key_rst_r and not key_rst; --xiaodouPROCESS(clk)beginif(rising_edge(clk)) thenif key_rst_an = '0' then cnt <= cnt+1;else cnt <= (others=>'0');end if;end if;END PROCESS;
---------------------------------------------------------PROCESS(clk)beginif(rising_edge(clk)) thenif cnt = "11111111111111111111" thenlow_sw <= sw;else null;end if;end if;END PROCESS;PROCESS(clk)begin if(rising_edge(clk)) thenlow_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)
beginif(rising_edge(clk)) thenpre_state <= nx_state;end if;
end process seq;
---------------------------------------------------------
-- com process:create next state and output logic
com:PROCESS(pre_state, low_sw_an)
begincase 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
beginif (en==1)clk1<=clk;else clk1<=clk1;
endalways@(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;// endelsecase(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开始显示,如此反复。
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
