vhdl实现脉冲按键电话按键显示电路

在这里插入图片描述
顶层文件telphone.vhd

LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;

ENTITY telphone IS 
 PORT(DIN1: IN STD_LOGIC_VECTOR(6 DOWNTO 0);
	clk3:in std_logic;
	CLK1,CLEAR,DIAL,RE_DIAL,delete:IN STD_LOGIC;
	KEYOUT:OUT STD_LOGIC;
	SEG71:OUT STD_LOGIC_VECTOR(7 DOWNTO 0);
	SEG8:OUT STD_LOGIC_VECTOR(7 DOWNTO 0);
	timebegin:in std_logic;
	botong:out std_logic;
	reset1:in std_logic
 );
 END ENTITY;
 
 ARCHITECTURE ART OF telphone IS
COMPONENT SET_NUM IS 
 PORT(DIN:IN STD_LOGIC_VECTOR(6 DOWNTO 0);
	  clk3:in std_logic;
	  CLK,CLEAR,DIAL,RE_DIAL,delete:IN STD_LOGIC;
	  KEYOUT:OUT STD_LOGIC;
	  SET:OUT STD_LOGIC_VECTOR(3 DOWNTO 0);
	  SEG8:OUT STD_LOGIC_VECTOR(7 DOWNTO 0);
	  timebegin:in std_logic;
	  botong:out std_logic;
	  reset1:in std_logic
  );
END COMPONENT;

COMPONENT DISPLAY IS
PORT(BCD1:IN STD_LOGIC_VECTOR(3 DOWNTO 0);
SEG7:OUT STD_LOGIC_VECTOR(7 DOWNTO 0));
END COMPONENT;

SIGNAL SET_1:STD_LOGIC_VECTOR(3 DOWNTO 0);
BEGIN
U1:SET_NUM PORT MAP(DIN1,clk3,CLK1,CLEAR,DIAL,RE_DIAL,delete,KEYOUT,SET_1,SEG8,timebegin,botong,reset1);
U2:DISPLAY PORT MAP(SET_1,SEG71);
END ART;

DISPLAY.vhd

LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
ENTITY DISPLAY IS
 PORT(
 BCD1:IN STD_LOGIC_VECTOR(3 DOWNTO 0);
 SEG7:OUT STD_LOGIC_VECTOR(7 DOWNTO 0));
 END ENTITY;
 
 ARCHITECTURE ONE OF DISPLAY IS
 BEGIN
 PROCESS(BCD1) IS
 BEGIN 
  CASE BCD1 IS
	WHEN"0000"=>SEG7<="00111111";
	WHEN"0001"=>SEG7<="00000110";
	WHEN"0010"=>SEG7<="01011011";
	WHEN"0011"=>SEG7<="01001111";
	WHEN"0100"=>SEG7<="01100110";
	WHEN"0101"=>SEG7<="01101101";
	WHEN"0110"=>SEG7<="01111101";
	WHEN"0111"=>SEG7<="00000111";
	WHEN"1000"=>SEG7<="01111111";
	WHEN"1001"=>SEG7<="01101111";
	when"1010"=>seg7<="10000000";--小数点
	when"1011"=>seg7<="00000000";--全灭
	WHEN OTHERS=>SEG7<="00000000";
  END CASE;
END PROCESS;
END ONE;

SET_NUM.vhd

LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_ARITH.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;

ENTITY SET_NUM IS
  PORT(DIN:IN STD_LOGIC_VECTOR(6 DOWNTO 0);
  clk3:in std_logic;
  CLK,CLEAR,DIAL,RE_DIAL,delete:IN STD_LOGIC;
  KEYOUT:OUT STD_LOGIC;
  SET:OUT STD_LOGIC_VECTOR(3 DOWNTO 0);
  SEG8:OUT STD_LOGIC_VECTOR(7 DOWNTO 0);
  testpins:out std_logic;
  timebegin:in std_logic;
  botong:out std_logic;
  reset1:in std_logic
  );
  END SET_NUM;
  
 ARCHITECTURE ONE OF SET_NUM IS


 SUBTYPE TEN IS STD_LOGIC_VECTOR(3 DOWNTO 0);
 SIGNAL BCD:TEN;
 TYPE NUMBER1 IS ARRAY(7 DOWNTO 0)OF STD_LOGIC_VECTOR(3 DOWNTO 0);
 SIGNAL NUMBER:STD_LOGIC_VECTOR(31 DOWNTO 0):="00000000000000000000000000000000";
 SIGNAL KEY,KEY1,KEY2,CLK1,DIAL1,RE_DIAL1:STD_LOGIC:='0';
 SIGNAL COUNT:STD_LOGIC_VECTOR(3 DOWNTO 0):="0000";
 SIGNAL COUNT1:STD_LOGIC_VECTOR(3 DOWNTO 0);
 SIGNAL COUNT2:STD_LOGIC_VECTOR(2 DOWNTO 0);
 SIGNAL DIN1:STD_LOGIC_VECTOR(6 DOWNTO 0);
 SIGNAL LOCK:STD_LOGIC_VECTOR(31 DOWNTO 0); 
 signal count3,count4,count5,count6,count7,count8,count9,count10,count11:integer;
 signal clktimes:STD_LOGIC_VECTOR(22 DOWNTO 0):="00000000000000000000000";
 signal second,min:integer range 0 to 59:=0;
 signal hour:integer range 0 to 24:=0;
 signal storage:std_logic:='0';
 signal botong1:std_logic:='0';
 signal wanbi:std_logic:='0';
 signal shanshuo:std_logic;
 signal jieshu:std_logic:='0';
 signal count12:std_logic_vector(3 downto 0):="1010";
 signal weijieting:std_logic:='0';  
 

 BEGIN
 process(clk3)--clk3连接pin125 频率为100000HZ
    begin
		if (clk3'event and clk3='1') then--拨通信号灯的判断
			if wanbi='1' and jieshu='0'  then
				botong1<='1';
			elsif dial='1' and wanbi='1' and shanshuo='0' and jieshu='0' then
				botong1<='0';
			elsif jieshu='1' and shanshuo='0' and wanbi='1' then--10s内未接通自动挂断  
				botong1<='0';
			elsif  wanbi='0' then
				botong1<='0';  
			elsif timebegin='0' and dial='1' and jieshu='1'  then--对方挂断
				botong1<='0';
			elsif timebegin='1' and dial='0' and jieshu='1'  then--我方挂断
				botong1<='0';
			elsif timebegin='0' and dial='0' and jieshu='1' then
                 botong1<='0';
			elsif jieshu='1' and shanshuo='1' and wanbi='1'  then--10s内接通指示灯闪烁
				if count3<100000 then
					count3<=count3+1;
				else 
					count3<=0;
					botong1<=not botong1;
				end if;	
			end if;
		end if;
        
	if (clk3'event and clk3='1') then--双方都挂断重置
        if reset1='1' then
			shanshuo<='0';
		end if;
	end if;
	
	if (clk3'event and clk3='1') then--判断对方是否应答
		if jieshu='1' then
			if weijieting='1' then 
				shanshuo<='0';--
			else 
				shanshuo<='1';
			end if;
		end if;
    end if;
 --以下为7个按键消抖
    if(clk3'event and clk3='1') then
		if(DIN(0)='0') then
			count4<=count4+1;
			if(count4=2000) then
				DIN1(0)<='1';
			else
				DIN1(0)<='0';
			end if;
		else
			count4<=0;
		end if;
    end if;
    
    if(clk3'event and clk3='1') then 
		if(DIN(1)='0') then
			count5<=count5+1;
			if(count5=2000) then
				DIN1(1)<='1';
			else
				DIN1(1)<='0';
			end if;
		else
			count5<=0;
		end if;
    end if;
    
    if(clk3'event and clk3='1') then 
		if(DIN(2)='0') then
			count6<=count6+1;
			if(count6=2000) then
				DIN1(2)<='1';
			else
				DIN1(2)<='0';
			end if;
		else
			count6<=0;
		end if;
    end if;
    
    if(clk3'event and clk3='1') then 
		if(DIN(3)='0') then
			count7<=count7+1;
			if(count7=2000) then
				DIN1(3)<='1';
			else
				DIN1(3)<='0';
			end if;
		else
			count7<=0;
		end if;
    end if;
    
    if(clk3'event and clk3='1') then 
		if(DIN(4)='0') then
			count8<=count8+1;
			if(count8=2000) then
				DIN1(4)<='1';
			else
				DIN1(4)<='0';
			end if;
		else
			count8<=0;
		end if;
    end if;
    
    if(clk3'event and clk3='1') then 
		if(DIN(5)='0') then
			count9<=count9+1;
			if(count9=2000) then
				DIN1(5)<='1';
			else
				DIN1(5)<='0';
			end if;
		else
			count9<=0;
		end if;
    end if;
    
    if(clk3'event and clk3='1') then 
		if(DIN(6)='0') then
			count10<=count10+1;
			if(count10=2000) then
				DIN1(6)<='1';
			else
				DIN1(6)<='0';
			end if;
		else
			count10<=0;
		end if;
    end if;
    
    
    if(clk3'event and clk3='1') then 
		if(RE_DIAL='0') then
			count11<=count11+1;
			if(count11=2000) then
				RE_DIAL1<='1';
			else
				RE_DIAL1<='0';
			end if;
		else
			count11<=0;
		end if;
    end if; 
    end process;
         
 

 PROCESS(CLK) IS
 BEGIN
 IF RISING_EDGE(CLK) THEN--上升沿触发
 DIAL1<=DIAL;--拨号键赋值给DIAL1
 botong<=botong1;--botong1赋值给拨通指示灯
 END IF;
 END PROCESS;

 KEY<=(DIN1(0) OR DIN1(1) OR DIN1(2) OR DIN1(3) OR DIN1(4) OR DIN1(5) OR DIN1(6));--一旦有键按下则KEY为1

 PROCESS(CLK,wanbi) IS --clk连接pin55 频率为6000000HZ
 variable count1:integer range 0 to 20000;
 variable count2:integer range 0 to 2000;
 variable suo:boolean:=false;
 BEGIN
	   IF FALLING_EDGE(CLK) THEN --下降沿有效\十秒倒计时  
		 if reset1='1' then--双方都挂断重置
			jieshu<='0';
			count12<="1010";
			weijieting<='0';			
		 end if;
		if timebegin='0' then
			if wanbi='1' then
				if (not suo) then
					if count12="0000" then
						suo:=true;
						jieshu<='1';
						weijieting<='1';
					else 
						count1:=count1+1;
							if count1=20000 then
								count1:=0;
								count2:=count2+1;
								if count2=300 then  --300为1秒
									count2:=0;
									count12<=count12-1;
								end if;
							end if;
					end if;
				end if;
			end if;
		 else 
		   jieshu<='1';
		 end if;
		
		if  CLEAR='0' AND RE_DIAL1='0' and timebegin='0' and delete='0'and dial='0' then--初始状态
			KEY1<='1';
			min<=0;
			second<=0;
		elsif CLEAR='0' AND RE_DIAL1='0' and timebegin='0' and delete='0'and dial='1' THEN--拨号键按下,数字输入,从低位向高位显示
			KEY1<=KEY;
			KEY2<='0';
			min<=0;
			second<=0;
		ELSIF CLEAR='1' AND RE_DIAL1='0' and timebegin='0'and delete='0' and dial='1'THEN--删除键按下,数字从低位删除
			KEY1<=CLEAR;
			KEY2<=clear;
		ELSIF CLEAR='0' AND RE_DIAL1='0' and timebegin='0'and delete='1' and dial='1'THEN--清除键按下,清楚数码管显示
			KEY1<=delete;
			KEY2<=delete;
		elsif  CLEAR='0' AND RE_DIAL1='0' and timebegin='1' and delete='0' and dial='1'  then--对方应答,开始计时
			if clktimes="10110111000110110000000" then
				key1<='1';
				clktimes<="00000000000000000000000";
				if second=59 then
					if min<60 then
						min<=min+1;
					end if;
				second<=0;
				else
					second<=second+1;
				end if;
			else 
				key1<='0';
				clktimes<=clktimes+1;
			end if;
		ELSif clear='0' and RE_DIAL1='1' and timebegin='0' and delete='0' and dial='1' then --拿起话筒,重拨键按下
			KEY1<=RE_DIAL1;
		END IF;
	end if;
 END PROCESS;

 PROCESS(DIN1) IS--如果按键有变化
 BEGIN
 IF    DIN1(6)='1' THEN BCD<="0110";
 ELSIF DIN1(5)='1' THEN BCD<="0101";
 ELSIF DIN1(4)='1' THEN BCD<="0100";
 ELSIF DIN1(3)='1' THEN BCD<="0011";
 ELSIF DIN1(2)='1' THEN BCD<="0010";
 ELSIF DIN1(1)='1' THEN BCD<="0001";
 ELSIF DIN1(0)='1' THEN BCD<="0000";
 ELSE BCD<="0000";--0123456对应的BCD码
 END IF;
 END PROCESS;

KEYOUT<=KEY2;--删除键或清除键按下指示灯亮灭
PROCESS(KEY1)IS
variable m,m2:integer;
BEGIN
 if RISING_EDGE(KEY1) THEN--key1上升沿检测
                         
	if reset1='1' then--双方都挂断重置
		wanbi<='0';
	elsif CLEAR='0' AND RE_DIAL1='0' and timebegin='0' and delete='0'and dial='0' THEN--初始状态
		NUMBER(31 DOWNTO 0)<="10111011101110111011101110111011";
	elsif CLEAR='0' AND RE_DIAL1='0' and timebegin='0' and delete='0'and dial='1' THEN--输入数字,实现数字从低位向高位移动
		NUMBER(31 DOWNTO 28)<=NUMBER(27 DOWNTO 24);
		NUMBER(27 DOWNTO 24)<=NUMBER(23 DOWNTO 20);
		NUMBER(23 DOWNTO 20)<=NUMBER(19 DOWNTO 16);
		NUMBER(19 DOWNTO 16)<=NUMBER(15 DOWNTO 12);
		NUMBER(15 DOWNTO 12)<=NUMBER(11 DOWNTO 8);
		NUMBER(11 DOWNTO 8)<=NUMBER(7 DOWNTO 4);
		NUMBER(7 DOWNTO 4)<=NUMBER(3 DOWNTO 0); 
		NUMBER(3 DOWNTO 0)<=BCD;
		if number(27 downto 24)/="1011" then--判断八位数字是否输入完毕
				LOCK(31 DOWNTO 28)<=NUMBER(31 DOWNTO 28);
				LOCK(27 DOWNTO 24)<=NUMBER(27 DOWNTO 24);
				LOCK(23 DOWNTO 20)<=NUMBER(23 DOWNTO 20);
				LOCK(19 DOWNTO 16)<=NUMBER(19 DOWNTO 16);
				LOCK(15 DOWNTO 12)<=NUMBER(15 DOWNTO 12);
				LOCK(11 DOWNTO 8)<=NUMBER(11 DOWNTO 8);
				LOCK(7 DOWNTO 4)<=NUMBER(7 DOWNTO 4);
				LOCK(3 DOWNTO 0)<=NUMBER(3 DOWNTO 0);
			    wanbi<='1';			 
		end if;
	ELSIF CLEAR='1' AND RE_DIAL1='0' and timebegin='0' and delete='0' and dial='1'THEN --按下删除键,数字从高位向低位移动
	NUMBER(31 DOWNTO 28)<="1011";
	NUMBER(27 DOWNTO 24)<=NUMBER(31 DOWNTO 28);
	NUMBER(23 DOWNTO 20)<=NUMBER(27 DOWNTO 24);
	NUMBER(19 DOWNTO 16)<=NUMBER(23 DOWNTO 20);
	NUMBER(15 DOWNTO 12)<=NUMBER(19 DOWNTO 16);
	NUMBER(11 DOWNTO 8)<=NUMBER(15 DOWNTO 12);
	NUMBER(7 DOWNTO 4)<=NUMBER(11 DOWNTO 8);
	NUMBER(3 DOWNTO 0)<=NUMBER(7 DOWNTO 4);
	ELSIF CLEAR='0' AND RE_DIAL1='0' and timebegin='0' and delete='1' and dial='1' THEN--清除键按下,清楚数码管显示
		number(31 downto 0)<="10111011101110111011101110111011";
	elsif  CLEAR='0' AND RE_DIAL1='0' and timebegin='1' and delete='0' and dial='1'  then----对方应答,开始计时
		number(31 downto 24)<="00000000";
		number(23 downto 20)<="1010";
		m:=min rem 10;
		number(19 downto 16)<=conv_std_logic_vector((min-m)/10,4);
		number(15 downto 12)<=conv_std_logic_vector(m,4);
		  number(11 downto 8)<="1010";
		m2:=second rem 10;
		NUMBER(7 DOWNTO 4)<=conv_std_logic_vector((second-m2)/10,4);
		NUMBER(3 DOWNTO 0)<=conv_std_logic_vector(m2,4);
	ELSif clear='0' and RE_DIAL1='1' and timebegin='0' and delete='0'and dial='1' then  ----重拨键按下
		NUMBER(31 DOWNTO 28)<=LOCK(31 DOWNTO 28);
		NUMBER(27 DOWNTO 24)<=LOCK(27 DOWNTO 24);
		NUMBER(23 DOWNTO 20)<=LOCK(23 DOWNTO 20);
		NUMBER(19 DOWNTO 16)<=LOCK(19 DOWNTO 16);
		NUMBER(15 DOWNTO 12)<=LOCK(15 DOWNTO 12);
		NUMBER(11 DOWNTO 8)<=LOCK(11 DOWNTO 8);
		NUMBER(7 DOWNTO 4)<=LOCK(7 DOWNTO 4);
		NUMBER(3 DOWNTO 0)<=LOCK(3 DOWNTO 0);
		wanbi<='1';
   end if;
end if;
END PROCESS;
   
   PROCESS(CLK) IS--为动态扫描数码管提供频率
   BEGIN
    IF RISING_EDGE(CLK) THEN
		COUNT<=COUNT+1;
    END IF;
    END PROCESS;
    
   PROCESS(COUNT)IS--动态扫描数码管
   BEGIN 
	CASE COUNT IS--片选,选择数码管
	   WHEN"0001"=>SET<=NUMBER(31 DOWNTO 28);SEG8<="01111111";
	   WHEN"0011"=>SET<=NUMBER(27 DOWNTO 24);SEG8<="10111111";
	   WHEN"0101"=>SET<=NUMBER(23 DOWNTO 20);SEG8<="11011111" ;
	   WHEN"0111"=>SET<=NUMBER(19 DOWNTO 16);SEG8<="11101111" ;
	   WHEN"1001"=>SET<=NUMBER(15 DOWNTO 12);SEG8<="11110111" ;
	   WHEN"1011"=>SET<=NUMBER(11 DOWNTO 8);SEG8<="11111011" ;
	   WHEN"1101"=>SET<=NUMBER(7 DOWNTO 4);SEG8<="11111101" ;
	   WHEN"1111"=>SET<=NUMBER(3 DOWNTO 0);SEG8<="11111110" ;  
	   WHEN OTHERS=>NULL;
   END CASE;
   END PROCESS; 
END ONE;

板载为EPF10K20TC144-3
pins:
在这里插入图片描述

bug:
1.重置需要拨动reset1开关,置于1,再拨动dial置为1,在置为0,关闭reset即可拨动dial按键拨打电话
2.重置后10s倒计时失效
3.重拨键少一位

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值