❀工信工实验参考——《VHDL实验4—— 多功能秒表》

一般来说,我贴上来的代码都是能直接跑的,如果不行可以邮箱交流[email protected]

仅供参考,微机的老师讲的很好,所以请还是要先自己完成咯。
免责声明,本人菜只因一只,内容仅供参考,错了不负责哈

在此鸣谢康莉老师、雁姐和蔡宝,我这次的作业是从他们那里东拼西凑来的hhh 

实验四  多功能秒表

          点:

    31     楼

  314 房;

实验台号:

实验日期与时间:

    分:

预习检查纪录:

批改教师:

报告内容:

一、实验要求:

1. 知识点掌握

(1) 掌握数字系统设计方法;

(2) 掌握时序逻辑电路设计的方法;

(3) 进一步熟悉vhdl语言的编写以及Quartur软件的使用。

2. 能力培养

(1) 利用VHDL语言对硬件电路建模的能力;

(2) 利用Quartus平台进行数字系统设计的能力。

(3) 利用多学科知识进行智能产品开发的能力

重点

  1. 利用模块划分的思想进行秒表的设计;
  2. 利用多学科知识进行智慧健康手表开发的能力;

二、实验内容:

秒表与智慧健康手表

  1. 基础内容:设计一个可以顺计时和倒计时的秒表。要求计时的范围为00.0S~99.9S,用三位数码管显示;   
  2. 拓展内容:

智慧健康手表,除了包含基本计时功能,还包括但不限于以下内容

i支持多种运动模式

ii计步、里程统计、卡路里计算

iii支持体温检测,心率,血压,血氧,睡眠全套健康监测。

iv 24H连续实时动态心率。

v支持音乐控制功能、多国字符显示

基础内容要求

设计一个可以顺计时和倒计时的秒表。要求计时的范围为00.0S~99.9S,用三位数码管显示。

1) 倒计时:通过小键盘可以实现设定计时时间(以秒为单位,最大计时时间为99.9秒)。通过键盘实现计时开始、计时结束。当所设定的倒计时间到达0.00S后,自动停止倒计时,同时响铃。

2) 顺计时:初始值为0.00S,通过键盘实现开始计时和结束计时功能。计时结束后,显示记录的时间。

3) 用三个发光二极管正确显示以下状态:倒计时状态、顺计时状态、待机状态。

4) 每当接收到有效按键时,蜂鸣器发出提示声。

注意:以上各项功能的功能键设置自定,不作统一规定,以简单且使用灵活方便操作为原则。

三、实验设计原理

1divider模块

       与实验2、3中的分频器实现原理基本一致。唯一不同是实验2、3中分频器输出的频率是1HZ,而该实验需要输出10HZ。因此我们计算得到需要将实验三中分频器中的参数“24999999”改为“2499999”,便可实现10HZ的分频输出。

2clock模块

这是计时的核心模块,主要结构为三进程状态机,共有四个状态分别为状态0,1,2,3。状态0是开机后初始化并等待命令的状态;状态1是开始正数计时;

状态2是倒计时设置状态;状态3开始倒计时状态。

       接下来具体分析三个进程的编程实现。

进程1:

seq:process(clk_div,rst_n)
	begin
		if(rst_n='0')then
			present_state<=s0;
		elsif(rising_edge(clk_div))then
			present_state<=next_state;
		end if;
	end process seq;

该进程是套用模板,在时钟到来时要跳到下一个进程,比较简单不再赘述。

进程2:

ns:process(present_state,key1,key2,key3)
	begin
		case present_state is
			when s0=>
				if(key1='0')then
					next_state<=s1;
				elsif( key2='0' )then
					next_state<=s2;
				else
					next_state<=s0;
				end if;
			when s1=>
				if(count1=x"9" and count2=x"9" and count3=x"9")then
					next_state<=s0;
				else
					next_state<=s1;
				end if;
			when s2=>
				if( key2='0')then
					next_state<=s3;
				else
					next_state<=s2;
				end if;
			when s3=>
				if(count1=x"0" and count2=x"0" and count3=x"0")then
					next_state<=s0;
				else
					next_state<=s3;
				end if;
			when OTHERS=>
				next_state <= s0;
		end case;
	end process ns;

具体过程为:在初始化时便为状态0,如果不进行任何按键操作则一直在状态0循环;如果使用者按下key1,则跳到状态1。在状态1中会一直正数计数(在进程3中递增),在数到99.9时,跳回状态0;如果使用者按下key2,则跳到状态2,在状态2中如果按下key2则跳至状态3开始倒计时,如果按下key3则给倒计时增加10s,在倒计时结束时会跳回状态0,等待再次操作。

我们可以由上述过程画出状态转移图:

❀工信工实验参考——《VHDL实验4—— 多功能秒表》_第1张图片

图1 实验4状态转移图

(写实验报告的时候极懒,就直接手画了)

进程3:

 

op:process(present_state,rst_n,clk_div,key2,key3)
	begin	
		if(rst_n='0')then
			led0<='0';
			led1<='0';
			led2<='0';
			led3<='0';
			--count<=x"000";
			count1<="0000";
			count2<="0000";
			count3<="0000";
		elsif(rising_edge(clk_div))then
			case present_state is
				when s0=>
					led1<='1';led2<='0';led3<='0';
					count1<=x"0";count2<=x"0";count3<=x"0";
					
				when s1=>
					led1<='0';led2<='1';led3<='0';
						count1<=count1+1;
						if(count1="1001")then
							count2<=count2+1;
							count1<="0000";
							if (count2="1001")then
								count3<=count3+1;
								count2<="0000";
							else
								count3<=count3;
							end if;
						else
							count2<=count2;
						end if;
					--end if;
				when s2=>
					led1<='1';led2<='0';led3<='1';
					if(key3='1' )then
						count3<=count3+1;
					else
						count1<=count1;count2<=count2;count3<=count3;
					end if;
				when s3=>
					led1<='0';led2<='0';led3<='1';
					--count<=count - 1;
					
					if(count1="0000")then
						if(count2="0000")then
							if(count3="0000")then
								count3<=count3;
							else
								count3<=count3-1;
								count2<=x"9";
								count1<=x"9";
							end if;
						else
							count2<=count2-1;
							count1<=x"9";
						end if;
					else
						count1<=count1-1;
					end if;
			end case;
		end if;

		num(15 downto 12)<="0000";
		num(11 downto 8)<=count3;
		num(7 downto 4)<=count2;
		num(3 downto 0)<=count1;
	end process op;
end behav;

进程3中为计数的详细过程。正数计数时用两个if嵌套完成:首先是最低位一直递增,直到最低位为9(“1001”),则清空最低位并将中间位加一。同理,在中间位一直加到9后中间位也清零,最高位加一。一次循环往复,加到999后会在第二个进程中跳回状态零。倒计时是同样的原理,在此不再赘述。

3seg模块

       该模块与第二三次实验的seg模块基本一致,唯一的差别是该实验要在最低位和中间位之间加一个小数点。代码实现不难,加一个判断:若为第二位数码管则加一个小数点,具体代码如下:

elsif(rising_edge(clk))then
  case(cnt_4(7 downto 6))is     --若为第二位数码管,则多送一个小数点

4、实例化:

1、顶层实体功能

图2 顶层功能

2、子模块:

将上述代码设为顶层实体,并且create symbol files for current file来创立元件,在新建的bpf文件中可直接使用。下图为三个实例化元件:

❀工信工实验参考——《VHDL实验4—— 多功能秒表》_第2张图片

图3 10HZ分频器

❀工信工实验参考——《VHDL实验4—— 多功能秒表》_第3张图片

图4 计数器

❀工信工实验参考——《VHDL实验4—— 多功能秒表》_第4张图片

图5 数码管接口模块

并且最后按照对应线路将其连接完整,如图6所示:

❀工信工实验参考——《VHDL实验4—— 多功能秒表》_第5张图片

图6 完整接线图

5、烧录至开发板

       我们将bpf文件设为顶层文件并且编译,编译成功后,按照图7分配引脚后再次编译,并将文件烧录至正点原子新起点V2开发板。

❀工信工实验参考——《VHDL实验4—— 多功能秒表》_第6张图片

图7 实验总体流程图

五、实验结果和分析

1:正向计时

❀工信工实验参考——《VHDL实验4—— 多功能秒表》_第7张图片

图8 正向计时1

❀工信工实验参考——《VHDL实验4—— 多功能秒表》_第8张图片

图9 正向计时2

我们可以看到数码管清晰地显示时间并逐渐递增,并且LED灯会亮中LED3表示正向计时。

2:倒计时设置

❀工信工实验参考——《VHDL实验4—— 多功能秒表》_第9张图片

图10 倒计时设置实物图

倒计时设置即状态2中,LED灯亮LED1与LED3,且每按一下KEY3会加10秒的倒计时。如图10我们已经按了两下,因此此时是倒计时20s。

3:倒计时

❀工信工实验参考——《VHDL实验4—— 多功能秒表》_第10张图片

图11 倒计时实物图

       设置完之后再按下key2可以开始倒计时,此时LED1,2,3都闪烁,且数码管显示依次递减,该图为倒数至2.5s的图示。

 

源代码:

seg.vhd

LIBRARY IEEE;
USE IEEE.std_logic_1164.ALL;
USE IEEE.std_logic_unsigned.ALL;
ENTITY seg IS
PORT(clk:in std_logic;
     rst_n:in std_logic;
   idis_data:in std_logic_vector(15 downto 0);
   seg_duan:out std_logic_vector(7 downto 0);
   seg_wei:out std_logic_vector(5 downto 0));
END seg;
ARCHITECTURE behav OF seg IS
constant SEG_NUM0:std_logic_vector(7 downto 0):=x"c0";
constant SEG_NUM1:std_logic_vector(7 downto 0):=x"f9";
constant SEG_NUM2:std_logic_vector(7 downto 0):=x"a4";
constant SEG_NUM3:std_logic_vector(7 downto 0):=x"b0";
constant SEG_NUM4:std_logic_vector(7 downto 0):=x"99";
constant SEG_NUM5:std_logic_vector(7 downto 0):=x"92";
constant SEG_NUM6:std_logic_vector(7 downto 0):=x"82";
constant SEG_NUM7:std_logic_vector(7 downto 0):=x"F8";
constant SEG_NUM8:std_logic_vector(7 downto 0):=x"80";
constant SEG_NUM9:std_logic_vector(7 downto 0):=x"90";
constant SEG_WE0:std_logic_vector(5 downto 0):="111110";                          
constant SEG_WE1:std_logic_vector(5 downto 0):="111101";
constant SEG_WE2:std_logic_vector(5 downto 0):="111011";
constant SEG_WE3:std_logic_vector(5 downto 0):="110111";
constant SEG_WE4:std_logic_vector(5 downto 0):="101111";
constant SEG_WE5:std_logic_vector(5 downto 0):="011111";
constant SEG_NUM00:std_logic_vector(7 downto 0):=x"40";
constant SEG_NUM11:std_logic_vector(7 downto 0):=x"79";
constant SEG_NUM22:std_logic_vector(7 downto 0):=x"24";
constant SEG_NUM33:std_logic_vector(7 downto 0):=x"30";
constant SEG_NUM44:std_logic_vector(7 downto 0):=x"19";
constant SEG_NUM55:std_logic_vector(7 downto 0):=x"12";
constant SEG_NUM66:std_logic_vector(7 downto 0):=x"02";
constant SEG_NUM77:std_logic_vector(7 downto 0):=x"78";
constant SEG_NUM88:std_logic_vector(7 downto 0):=x"00";
constant SEG_NUM99:std_logic_vector(7 downto 0):=x"10";
signal seg_num:std_logic_vector(3 downto 0);
signal cnt_4:std_logic_vector(7 downto 0);
signal count2:std_logic_vector(7 downto 0);
begin
process(clk,rst_n)
begin
if(rst_n='0')then
   cnt_4 <= "00000000";
   count2 <= "00000000";
elsif(rising_edge(clk))then
   cnt_4 <= cnt_4 + "00000001";
   count2 <= count2 + "00000001";
end if;
end process;


process(clk,rst_n)
begin
if(rst_n='0')then
   seg_num <= "0000";
elsif(rising_edge(clk))then
   case(cnt_4(7 downto 6))is
     when "00" =>seg_num <= idis_data(3 downto 0);
   when "01" =>seg_num <= idis_data(7 downto 4);
   when "10" =>seg_num <= idis_data(11 downto 8);
   when "11" =>seg_num <= idis_data(15 downto 12);
     when others =>null;
 end case;
end if;
end process;

process(clk,rst_n)
begin
if(rst_n='0')then
  seg_duan <="11111111";
elsif(rising_edge(clk))then
  case(cnt_4(7 downto 6))is     --若为第二位数码管,则多送一个小数点
  when"00"=>
      case(seg_num)is
          when"0000" =>seg_duan <= SEG_NUM0;
          when"0001" =>seg_duan <= SEG_NUM1;
          when"0010" =>seg_duan <= SEG_NUM2;
          when"0011" =>seg_duan <= SEG_NUM3;
          when"0100" =>seg_duan <= SEG_NUM4;
          when"0101" =>seg_duan <= SEG_NUM5;
          when"0110" =>seg_duan <= SEG_NUM6;
          when"0111" =>seg_duan <= SEG_NUM7;
          when"1000" =>seg_duan <= SEG_NUM8;
          when"1001" =>seg_duan <= SEG_NUM9;
          when others =>seg_duan <= "11111111";
      end case;
 when"01"=>
     case(seg_num)is
          when"0000" =>seg_duan <= SEG_NUM00;
          when"0001" =>seg_duan <= SEG_NUM11;
          when"0010" =>seg_duan <= SEG_NUM22;
          when"0011" =>seg_duan <= SEG_NUM33;
          when"0100" =>seg_duan <= SEG_NUM44;
          when"0101" =>seg_duan <= SEG_NUM55;
          when"0110" =>seg_duan <= SEG_NUM66;
          when"0111" =>seg_duan <= SEG_NUM77;
          when"1000" =>seg_duan <= SEG_NUM88;
          when"1001" =>seg_duan <= SEG_NUM99;
          when others =>seg_duan <= "11111111";
      end case;
 when"10"=>
     case(seg_num)is
          when"0000" =>seg_duan <= SEG_NUM0;
          when"0001" =>seg_duan <= SEG_NUM1;
          when"0010" =>seg_duan <= SEG_NUM2;
          when"0011" =>seg_duan <= SEG_NUM3;
when"0100" =>seg_duan <= SEG_NUM4;
          when"0101" =>seg_duan <= SEG_NUM5;
          when"0110" =>seg_duan <= SEG_NUM6;
          when"0111" =>seg_duan <= SEG_NUM7;
          when"1000" =>seg_duan <= SEG_NUM8;
          when"1001" =>seg_duan <= SEG_NUM9;
          when others =>seg_duan <= "11111111";
      end case;
 when others=>null;
 end case;
end if;
end process;

process(cnt_4(7 downto 6))
begin
        case(cnt_4(7 downto 6))is
         when "00" =>seg_wei <= SEG_WE0;
     when "01" =>seg_wei <= SEG_WE1;
     when "10" =>seg_wei <= SEG_WE2;
     when others =>seg_wei <="111111";
end case;
end process;                    
end behav;

clock.vhd

library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
--use ieee.std_logic_arith.all;
entity clock is
	port(
	clk_div:in std_logic;
	clk:in std_logic;
	rst_n:in std_logic;
	count_up_eli:in std_logic; --sw1
	count_down_eli: in std_logic; --sw2
	count_down_set_eli:in std_logic; --sw3
	led0:out std_logic;
	led1:out std_logic;
	led2:out std_logic;
	led3:out std_logic;
	--rke:out std_logic;
	num:out std_logic_vector(15 downto 0)
	);
end entity;

architecture behav of clock is
type state_type is(s0,s1,s2,s3);
signal present_state,next_state:state_type;
--signal count:std_logic_vector(11 downto 0);
--signal count:integer range 0 to 999;
signal count1:std_logic_vector(3 downto 0);
signal count2:std_logic_vector(3 downto 0);
signal count3:std_logic_vector(3 downto 0);
signal key1:std_logic;
signal key2:std_logic;
signal key3:std_logic;
--signal nkey1:std_logic;
--signal nkey2:std_logic;
--signal nkey3:std_logic;
--signal rkey1:std_logic;
--signal rkey2:std_logic;
--signal rkey3:std_logic;

begin
	--seq
	seq:process(clk_div,rst_n)
	begin
		if(rst_n='0')then
			present_state<=s0;
		elsif(rising_edge(clk_div))then
			present_state<=next_state;
		end if;
	end process seq;
	
	--next_state
	ns:process(present_state,key1,key2,key3)
	begin
		case present_state is
			when s0=>
				if(key1='0')then
					next_state<=s1;
				elsif( key2='0' )then
					next_state<=s2;
				else
					next_state<=s0;
				end if;
			when s1=>
				if(count1=x"9" and count2=x"9" and count3=x"9")then
					next_state<=s0;
				else
					next_state<=s1;
				end if;
			when s2=>
				if( key2='0')then
					next_state<=s3;
				else
					next_state<=s2;
				end if;
			when s3=>
				if(count1=x"0" and count2=x"0" and count3=x"0")then
					next_state<=s0;
				else
					next_state<=s3;
				end if;
			when OTHERS=>
				next_state <= s0;
		end case;
	end process ns;
	
	op:process(present_state,rst_n,clk_div,key2,key3)
	begin	
		if(rst_n='0')then
			led0<='0';
			led1<='0';
			led2<='0';
			led3<='0';
			--count<=x"000";
			count1<="0000";
			count2<="0000";
			count3<="0000";
		elsif(rising_edge(clk_div))then
		--else
			case present_state is
				when s0=>
					led1<='1';led2<='0';led3<='0';
					count1<=x"0";count2<=x"0";count3<=x"0";
					
				when s1=>
					led1<='0';led2<='1';led3<='0';
					--if(key2='1' )then --stop
						--count<=count;
					--	count1<=count1;
					--	count2<=count2;
					--	count3<=count3;
				--	else
						--count<=count + 1;	
					--鏁版嵁杞崲
						count1<=count1+1;
						if(count1="1001")then
							count2<=count2+1;
							count1<="0000";
							if (count2="1001")then
								count3<=count3+1;
								count2<="0000";
							else
								count3<=count3;
							end if;
						else
							count2<=count2;
						end if;
					--end if;
				when s2=>
					led1<='1';led2<='0';led3<='1';
					if(key3='1' )then
						count3<=count3+1;
					else
						count1<=count1;count2<=count2;count3<=count3;
					end if;
				when s3=>
					led1<='0';led2<='0';led3<='1';
					--count<=count - 1;
					
					if(count1="0000")then
						if(count2="0000")then
							if(count3="0000")then
								count3<=count3;
							else
								count3<=count3-1;
								count2<=x"9";
								count1<=x"9";
							end if;
						else
							count2<=count2-1;
							count1<=x"9";
						end if;
					else
						count1<=count1-1;
					end if;
			end case;
		end if;
		
		--num(11 downto 0)<=count;
		num(15 downto 12)<="0000";
		num(11 downto 8)<=count3;
		num(7 downto 4)<=count2;
		num(3 downto 0)<=count1;
		--num<=conv_std_logic_vector(count,num'length);
	end process op;
	
	
end behav;

divider.vhd

library ieee;
use ieee.std_logic_1164.all;

entity divider is

port(
	clk:in std_logic;
	rst_n:in std_logic;
	clk_div:out std_logic
);

end entity;


architecture behav of divider is
signal clk_1hz:std_logic;

begin
	process(clk)
	VARIABLE count:integer:=0;
	begin
		if(rising_edge(clk) and count<2499999)then
			count:=count+1;
		elsif(rising_edge(clk) and count=2499999)then
			clk_1hz<= not clk_1hz;
			count:=0;
		end if;
	end process;
----------------------------------------------------------
clk_div<=clk_1hz;


end behav;

我没记错的话,这一套代码应该是可以跑而且现象没有大问题的,如果有问题的话就再de一下bug咯,应该差的不远。然后如果条件允许的话建议还是先提前到实验室做一下以免真正考试的时候脑子瓦特写不出来hhh。

你可能感兴趣的:(VHDL实验,学习方法,经验分享,fpga开发,嵌入式硬件)