按键控制的状态机设计

一 设计要求
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开始显示,如此反复。

猜你喜欢

转载自blog.csdn.net/weixin_43789635/article/details/112979409