当前位置:文档之家› 数字逻辑电路(数电)课程设计_电子秒表_VHDL实现(含完整源代码!!)

数字逻辑电路(数电)课程设计_电子秒表_VHDL实现(含完整源代码!!)

电子科技大学UNIVERSITY OF ELECTRONIC SCIENCE AND TECHNOLOGY OF CHINA数字逻辑设计实验报告实验题目:电子秒表学生姓名:指导老师:一、实验内容利用FPGA设计一个电子秒表,计时范围00.00 ~ 99.00秒,最多连续记录3个成绩,由两键控制。

二、实验要求1、实现计时功能:域值范围为00.00 ~ 99.00秒,分辨率0.01秒,在数码管上显示。

2、两键控制与三次记录:1键实现“开始”、“记录”等功能,2键实现“显示”、“重置”等功能。

系统上电复位后,按下1键“开始”后,开始计时,记录的时间一直显示在数码管上;按下1键“记录第一次”,次按1键“记录第二次”,再按1键“记录第三次”,分别记录三次时间。

其后按下2键“显示第一次”,次按2键“显示第二次”,再按2键“显示第三次”,数码管上分别显示此前三次记录的时间;显示完成后,按2键“重置”,所有数据清零,此时再按1键“开始”重复上述计时功能。

三、设计思路1、整体设计思路先对按键进行去抖操作,以正确的得到按键信息。

同时将按键信息对应到状态机中,状态机中的状态有:理想状态、开始状态、3次记录、3次显示、以及其之间的7次等待状态。

因为需要用数码管显示,故显示的过程中需要对数码管进行片选和段选,因此要用到4输入的多路选择器。

在去抖、计时、显示的过程中,都需要用到分频,从而得到理想频率的时钟信号。

2、分频设计该实验中有3个地方需要用到分频操作,即去抖分频(需得到200HZ时钟)、计时分频(需得到100HZ时钟)和显示分频(需得到25kHZ时钟)。

分频的具体实现很简单,需首先算出系统时钟(50MHZ)和所需始终的频率比T,并定义一个计数变量count,当系统时钟的上升沿每来到一次,count就加1,当count=T时就将其置回1。

这样只要令count=1~T/2时clk=‘0’,count=T/2+1~T时clk=‘1’即可。

3、去抖设计由于用按键为机械弹性开关,故当机械触点断开、闭合时,按键开关在闭合时不会马上稳定地接通,在断开时也不会马上断开,而是在闭合及断开的瞬间发生一系列的抖动,时间一般为5ms~10ms,如下图所示:故应考虑对按键时进行去抖操作。

这里去抖用到了一个状态机,具体如下:其中,按键按下时为低电平,松开后为高电平。

去抖用的频率为200HZ,当连续两次采样都为低电平时,认为按键稳定按下,在按键稳定按下后,采样到按键为高电平时,认为按键释放。

4、状态机设计(1)状态转移:当按下key1或者key2且检测到时间上升沿到来,状态机中将发生状态转移,且不论在什么状态,按下reset键时都将回到idle状态。

这里在记录状态和显示状态之间加入了一些“中间状态”,其目的是为了避免一次按键时间过长而导致认为其进行了多次按键的情况。

状态转移图如下所示:其中,a表示第一个按键(开始、记录),b表示第二个按键(显示、复位),idle为理想状态也是初始状态,r1、r2、r3为三个记录状态,d1、d2、d3为三个显示状态,m1~m7为7个中间状态。

(2)计时与监视:在“开始状态”之后,若没有按下reset键,都将一直进行计时,且记录的过程中数码管需要一直显示当前计时,于是数码管需要对当前时间进行不停得“监视”。

监视的过程中就涉及到计时,这里计时其实是用计数器来实现的,即每当分频后(这里分频为100mHZ,即0.01s)的时钟上升沿到来时,就使数码管最低位(即0.01位)加一,以此来实现计时。

5、数码管的显示:由于数码管的四个数字采用同一组控制开关,即共阴极、共阳极,所以如果直接开启数码管显示则四个管子的显示将完全相同,原理图如下所示:故这里用“扫描”的方式来控制数码管,当扫描速度很快时人眼将无法区分,故会认为四个数码管都在一直显示。

这里的扫描的频率选取为25kHz,四个数码管的选取通过4输入多路选择器来实现。

四、程序设计1、顶层:library IEEE;use IEEE.STD_LOGIC_1164.ALL;USE IEEE.STD_LOGIC_TEXTIO.ALL;USE STD.TEXTIO.ALL;USE IEEE.STD_LOGIC_UNSIGNED.ALL;USE IEEE.STD_LOGIC_ARITH.ALL;USE IEEE.NUMERIC_STD.ALL;entity main isPort ( clk : in STD_LOGIC;reset : in STD_LOGIC;key1 : in STD_LOGIC;key2 : in STD_LOGIC;led : out STD_LOGIC_VECTOR(0 to 6);led_com : out STD_LOGIC_VECTOR(3 downto 0);point : out STD_LOGIC);end main;architecture Behavioral of main isCOMPONENT debouncePORT(clk_deb : IN std_logic;reset : IN std_logic;keyi : IN std_logic;keyo : OUT std_logic);END COMPONENT;COMPONENT freq_div_debouncePORT(clk : IN std_logic;clk_out : OUT std_logic);END COMPONENT;COMPONENT freq_div_displayPORT(clk : IN std_logic;clk_out : OUT std_logic);END COMPONENT;COMPONENT freq_div_timePORT(clk : IN std_logic;clk_out : OUT std_logic);END COMPONENT;COMPONENT muxPORT(clk_dis : IN std_logic;num1 : IN std_logic_vector(3 downto 0);num2 : IN std_logic_vector(3 downto 0);num3 : IN std_logic_vector(3 downto 0);num4 : IN std_logic_vector(3 downto 0);led: OUT std_logic_vector(0 to 6);led_com : OUT std_logic_vector(3 downto 0);point : OUT std_logic);END COMPONENT;COMPONENT state_machinePORT(clk_t : IN std_logic;a : IN std_logic;b : IN std_logic;reset : IN std_logic;out1 : OUT std_logic_vector(3 downto 0);out2 : OUT std_logic_vector(3 downto 0);out3 : OUT std_logic_vector(3 downto 0);out4 : OUT std_logic_vector(3 downto 0));END COMPONENT;signal o,o1,o2,o3,o4:std_logic_vector(3 downto 0);signal k1,k2,clk_debounce,clk_time,clk_display:std_logic;begin--分频--div1: freq_div_debounce PORT MAP(clk,clk_debounce);div2: freq_div_time PORT MAP(clk,clk_time);div3: freq_div_display PORT MAP(clk,clk_display);--去抖--deb1: debounce PORT MAP(clk_debounce,reset,key1,k1);deb2: debounce PORT MAP(clk_debounce,reset,key2,k2);--状态机--s: state_machine PORT MAP(clk_time,k1,k2,reset,o1,o2,o3,o4);--多路选择器--m: mux PORT MAP(clk_display,o1,o2,o3,o4,led,led_com,point); end Behavioral;2、分频:(1)去抖分频:entity freq_div_debounce isPort ( clk: in STD_LOGIC;clk_out: out STD_LOGIC);end freq_div_debounce;architecture Behavioral of freq_div_debounce is signal count :integer range 1 to 250000 :=1; --赋初值beginprocess(clk)beginif (clk ' event and clk='1') thenif count=250000 thencount<=1;elsecount<=count+1;end if;end if;end process;process(count)beginif count<=125000 thenclk_out<='0';elseclk_out<='1';end if;end process;end Behavioral;(2)计时分频:entity freq_div_time isPort ( clk : in STD_LOGIC;clk_out : out STD_LOGIC);end freq_div_time;architecture Behavioral of freq_div_time issignal count :integer range 1 to 500000 :=1; --赋初值beginprocess(clk)beginif (clk ' event and clk='1') thenif count=500000 thencount<=1;elsecount<=count+1;end if;end if;end process;process(count)beginif count<=250000 thenclk_out<='0';elseclk_out<='1';end if;end process;end Behavioral;(3)显示分频:entity freq_div_display isPort ( clk : in STD_LOGIC;clk_out : out STD_LOGIC);end freq_div_display;architecture Behavioral of freq_div_display is signal count :integer range 1 to 2500 :=1; --赋初值beginprocess(clk)beginif (clk ' event and clk='1') thenif count=2500 thencount<=1;elsecount<=count+1;end if;end if;end process;process(count)beginif count<=1250 thenclk_out<='0';elseclk_out<='1';end if;end process;end Behavioral;3、去抖:entity debounce isPort ( clk_deb : in STD_LOGIC; --200HZreset : in STD_LOGIC;keyi : in STD_LOGIC;keyo : out STD_LOGIC);end debounce;architecture Behavioral of debounce istype state_type is (idle,d1,d2);signal state: state_type :=idle;beginprocess(clk_deb,reset,keyi)beginif (reset='0') thenstate<=idle; --初始状态keyo<='1';elsif (clk_deb' event and clk_deb='1') then --时钟上升沿来到case state iswhen idle =>keyo<='1';if keyi='0' thenstate<=d1;elsestate<=idle;end if;when d1 =>keyo<='1';if keyi='0' thenstate<=d2;elsestate<=idle;end if;when d2 =>keyo<='0';if keyi='1' thenstate<=idle;elsestate<=d2;end if;end case;end if;end process;end Behavioral;4、状态机:entity state_machine isPort ( clk_t : in STD_LOGIC; --100HZa : in STD_LOGIC;b : in STD_LOGIC;reset : in STD_LOGIC;out1 : out STD_LOGIC_VECTOR(3 DOWNTO 0);out2 : out STD_LOGIC_VECTOR(3 DOWNTO 0);out3 : out STD_LOGIC_VECTOR(3 DOWNTO 0);out4 : out STD_LOGIC_VECTOR(3 DOWNTO 0)); end state_machine;architecture Behavioral of state_machine istype statetype is (idle,start,r1,r2,r3,d1,d2,d3,m1,m2,m3,m4,m5,m6,m7); signal state : statetype :=idle;--记录1--signal r1_led1 :std_logic_vector (3 downto 0); --最低位signal r1_led2 :std_logic_vector (3 downto 0);signal r1_led3 :std_logic_vector (3 downto 0);signal r1_led4 :std_logic_vector (3 downto 0); --最高位--记录2--signal r2_led1 :std_logic_vector (3 downto 0); --最低位signal r2_led2 :std_logic_vector (3 downto 0);signal r2_led3 :std_logic_vector (3 downto 0);signal r2_led4 :std_logic_vector (3 downto 0); --最高位--记录3--signal r3_led1 :std_logic_vector (3 downto 0); --最低位signal r3_led2 :std_logic_vector (3 downto 0);signal r3_led3 :std_logic_vector (3 downto 0);signal r3_led4 :std_logic_vector (3 downto 0); --最高位--计时--signal t_led1 :std_logic_vector (3 downto 0); --最低位signal t_led2 :std_logic_vector (3 downto 0);signal t_led3 :std_logic_vector (3 downto 0);signal t_led4 :std_logic_vector (3 downto 0); --最高位begin--状态转移--process(clk_t,reset,a,b)beginif (clk_t' event and clk_t='1') thenif (reset='0') thenstate<=idle;elsecase state iswhen idle => if a='0' then state<= start; else state<= idle;end if;when start=> if a='1' then state<= m1; else state<= start;end if;when m1=> if a='0' then state<=r1;else state<=m1;end if;when r1=> if a='1' then state<=m2;else state<=r1;end if;when m2=> if a='0' then state<=r2;else state<=m2;end if;when r2=> if a='1' then state<=m3;else state<=r2;end if;when m3=> if a='0' then state<=r3;else state<=m3;end if;when r3=> if a='1' then state<=m4;else state<=r3;end if;when m4=> if b='0' then state<=d1;else state<=m4;end if;when d1=> if b='1' then state<=m5;else state<=d1;end if;when m5=> if b='0' then state<=d2;else state<=m5;end if;when d2=> if b='1' then state<=m6;else state<=d2;end if;when m6=> if b='0' then state<=d3;else state<=m6;end if;when d3=> if b='1' then state<=m7;else state<=d3;end if;when m7=> if b='0' then state<=idle;else state<=m7;end if;end case;end if;end if;end process;--计时(监视)--process(clk_t,reset,state)beginif (clk_t' event and clk_t='1') thenif reset='0' then --复位t_led1<="0000";t_led2<="0000";t_led3<="0000";t_led4<="0000";elsecase state iswhen idle => --初始状态t_led1<="0000";t_led2<="0000";t_led3<="0000";t_led4<="0000";when others =>if t_led1="1001" then --如果等于9,则清0,且进位t_led1<="0000";if t_led2="1001" thent_led2<="0000";if t_led3="1001" thent_led3<="0000";if t_led4="1001" thent_led4<="0000";elset_led4<=t_led4+1;end if;elset_led3<=t_led3+1;end if;elset_led2<=t_led2+1;end if;elset_led1<=t_led1+1;end if;end case;end if;end if;end process;--记录--process(clk_t,state)beginif (clk_t' event and clk_t='1') thencase state iswhen idle =>r1_led1<="0000";r1_led2<="0000";r1_led3<="0000";r1_led4<="0000";r2_led1<="0000";r2_led2<="0000";r2_led3<="0000";r2_led4<="0000";r3_led1<="0000";r3_led2<="0000";r3_led3<="0000";r3_led4<="0000";when r1 =>r1_led1<=t_led1;r1_led3<=t_led3;r1_led4<=t_led4;when r2 =>r2_led1<=t_led1;r2_led2<=t_led2;r2_led3<=t_led3;r2_led4<=t_led4;when r3=>r3_led1<=t_led1;r3_led2<=t_led2;r3_led3<=t_led3;r3_led4<=t_led4;when others => NULL;end case;end if;end process;--数码管数字--process(clk_t,reset,state)beginif (clk_t' event and clk_t='1') thencase state iswhen idle =>out1<= "0000";out2<= "0000";out3<= "0000";out4<= "0000";when d1|m5 =>out1<= r1_led1;out2<= r1_led2;out3<= r1_led3;out4<= r1_led4;when d2|m6 =>out1<= r2_led1;out2<= r2_led2;out3<= r2_led3;out4<= r2_led4;when d3|m7 =>out1<= r3_led1;out2<= r3_led2;out4<= r3_led4;when others =>out1<= t_led1;out2<= t_led2;out3<= t_led3;out4<= t_led4;end case;end if;end process;end Behavioral;5、多路选择器:entity mux isPort ( clk_dis : in STD_LOGIC; --25kHZnum1 : in STD_LOGIC_VECTOR(3 downto 0); --最低位num2 : in STD_LOGIC_VECTOR(3 downto 0);num3 : in STD_LOGIC_VECTOR(3 downto 0);num4 : in STD_LOGIC_VECTOR(3 downto 0); --最高位led :out STD_LOGIC_VECTOR (0 to 6); --a to gled_com : out STD_LOGIC_VECTOR(3 downto 0); --最高位downto 最低位point : out STD_LOGIC);end mux;architecture Behavioral of mux issignal count:integer range 1 to 4 :=1;signal num : std_logic_vector(3 downto 0);beginprocess(clk_dis) --计数beginif (clk_dis' event and clk_dis='1') thenif count=4 thencount<=1;elsecount<=count+1;end if;end if;end process;process(clk_dis,count,num1,num2,num3,num4) --选择begincase count iswhen 1 => num<=num1;led_com<="1110";point<='1';when 2 => num<=num2;led_com<="1101";point<='1';when 3 => num<=num3;led_com<="1011";point<='0';when 4 => num<=num4;led_com<="0111";point<='1';end case;end process;process(num) --数码管显示begincase num iswhen "0000" => led<="0000001"; --0,数码管:a-gwhen "0001" => led<="1001111";when "0010" => led<="0010010";when "0011" => led<="0000110";when "0100" => led<="1001100";when "0101" => led<="0100100";when "0110" => led<="0100000";when "0111" => led<="0001111";when "1000" => led<="0000000";when "1001" => led<="0000100"; --9when others => led<="0000000"; --其他end case;end process;end Behavioral;五、仿真与硬件调试1、仿真(1)顶层仿真1.仿真文件:ENTITY test_STOPWATCH ISEND test_STOPWA TCH;ARCHITECTURE behavior OF test_STOPWATCH IS-- Component Declaration for the Unit Under Test (UUT)COMPONENT mainPORT(clk : IN std_logic;reset : IN std_logic;key1 : IN std_logic;key2 : IN std_logic;led : OUT std_logic_vector(6 downto 0);led_com : OUT std_logic_vector(3 downto 0);point : OUT std_logic);END COMPONENT;--Inputssignal clk : std_logic := '0';signal reset : std_logic := '1';signal key1 : std_logic := '1';signal key2 : std_logic := '1';--Outputssignal led : std_logic_vector(6 downto 0);signal led_com : std_logic_vector(3 downto 0);signal point : std_logic;BEGIN-- Instantiate the Unit Under Test (UUT)uut: main PORT MAP (clk => clk,reset => reset,key1 => key1,key2 => key2,led => led,led_com => led_com,point => point);-- Clock process definitionsprocessbeginclk<='0';wait for 10 ns;clk<='1';wait for 10 ns;end process;-- Stimulus processstim_proc: processbeginkey1 <= '1';key2 <= '1';wait for 25 ms;key1 <= '0';key2 <= '1';wait for 25 ms;key1 <= '1';key2 <= '1';wait for 25 ms;key2 <= '1';wait for 25 ms; key1 <= '1'; key2 <= '1';wait for 25 ms; key1 <= '0'; key2 <= '1';wait for 25 ms; key1 <= '0'; key2 <= '1';wait for 25 ms; key1 <= '1'; key2 <= '1';wait for 25 ms; key1 <= '0'; key2 <= '1';wait for 25 ms; key1 <= '1'; key2 <= '1';wait for 25 ms; key1 <= '1'; key2 <= '0';wait for 25 ms; key1 <= '1'; key2 <= '1';wait for 25 ms; key1 <= '1'; key2 <= '0';wait for 25 ms; key1 <= '1'; key2 <= '0';wait for 25 ms; key1 <= '1'; key2 <= '0';wait for 25 ms;key2 <= '1';wait for 25 ms;key1 <= '1';key2 <= '0';wait for 25 ms;key1 <= '1';key2 <= '1';wait for 25 ms;key1 <= '1';key2 <= '0';wait for 25 ms;key1 <= '1';key2 <= '1';-- insert stimulus herewait;end process;END;2.仿真结果:(2)分频仿真1.仿真文件:LIBRARY ieee;USE ieee.std_logic_1164.ALL;ENTITY text_freq_div_debounce ISEND text_freq_div_debounce;ARCHITECTURE behavior OF text_freq_div_debounce IS-- Component Declaration for the Unit Under Test (UUT)COMPONENT freq_div_debouncePORT(clk : IN std_logic;clk_out : OUT std_logic);END COMPONENT;--Inputssignal clk : std_logic := '0';--Outputssignal clk_out : std_logic;BEGIN-- Instantiate the Unit Under Test (UUT)uut: freq_div_debounce PORT MAP (clk => clk,clk_out => clk_out);processbeginwait for 10 ns;clk<='1';wait for 10 ns;clk<='0';end process;END;2.仿真结果:2、硬件调试(1)管脚配置:NET "clk" LOC = P128;NET "reset" LOC = P47; #sw_3 NET "key1" LOC = P38; #sw_1 NET "key2" LOC = P41; #sw_2NET "led[0]" LOC = P52; #a NET "led[1]" LOC = p75;NET "led[2]" LOC = p58;NET "led[3]" LOC = p76;NET "led[4]" LOC = p77;NET "led[5]" LOC = p54;NET "led[6]" LOC = p53; #g NET "point" LOC = p66; #pointNET "led_com[0]" LOC = p81; NET "led_com[1]" LOC = p85; NET "led_com[2]" LOC = p83; NET "led_com[3]" LOC = p82;(2)调试结果:上图为初始状态,即尚未开始计时,此时显示为“00.00”。

相关主题