VHDL实验:基于有限状态机实现秒表

题目要求:
利用有限状态机实现实现一个具有启动、停止、清零功能的秒表,显示格式:分:秒:十分秒。启动、停止、清零由一个按键控制,按键按下时,功能按启动、停止、清零顺序循环。

思路分析:
参考知乎上的这篇文章FPGA | Finite State Machine 有限状态机,对比两种状态机:
1.Mealy型状态机
VHDL实验:基于有限状态机实现秒表_第1张图片
2.Moore型状态机:
VHDL实验:基于有限状态机实现秒表_第2张图片
从这两张图上看,这两种状态机的唯一区别在于决定输出的是什么,在本实验中,最终的输出是数码管上的显示结果,题目中说“启动、停止、清零由一个按键控制,按键按下时,功能按启动、停止、清零顺序循环”也就是说按键的次数会影响到数码管的显示,因此本实验采用Mealy型状态机。

画出秒表的状态图:
VHDL实验:基于有限状态机实现秒表_第3张图片
S1: 0状态,所有数码管显示为0
S2:计时并显示
S3:停止计时,显示不变动
状态之间的“0”代表按键输入,本项目所用的开发板在不按动的情况下产生高电位,按动了就产生低电位,由于开发板的按键使用了施密特触发电路,因此在代码中就不做消抖了。

我在硬件设计代码里使用枚举类型来表示这3个状态,综合器在综合时,会自动对它们四个编码,将状态表示为二进制码的形式。

本项目用3个process,1s = 1000000000 ns

刚刚编译的时候出现了一条警告信息:

Warning (10631): VHDL Process Statement warning at Second.vhd(46): inferring latch(es) for signal or variable "current_state", which holds its previous value in one or more paths through the process

参考了http://www.itdaan.com/blog/2012/05/28/171e7e47cea3348ae9b125dc8154ecb3.html
看到的说法是:
解释:信号被综合成了latch,锁存器的EN和数据输入端口存在一个竞争的问题

好了,我的代码如下:

library ieee ;
use ieee.std_logic_1164.all ;
use ieee.std_logic_unsigned.all ;
use ieee.std_logic_arith.all ;

entity Second is
port (
		clk : in std_logic ;	-- the signal from 50MHZ clock
		key : in std_logic ;	-- the signal from key3 on development board
		hex7 : out std_logic_vector(0 to 6) ;
		hex6 : out std_logic_vector(0 to 6)	;
		hex5 : out std_logic_vector(0 to 6) ;
		hex4 : out std_logic_vector(0 to 6) ;
		hex3 : out std_logic_vector(0 to 6) ;
		hex2 : out std_logic_vector(0 to 6) ;
		hex1 : out std_logic_vector(0 to 6) ;
		hex0 : out std_logic_vector(0 to 6)	;	-- the result to output
		separate1 : out std_logic ;
		separate2 : out std_logic ;
		separate3 : out std_logic ;
		separate4 : out std_logic ;
		separate5 : out std_logic 		-- to separate hour, minute, second.
	 ) ;
end Second ;

architecture Timer of Second is
	constant matrix_num : integer := 9 ;
	constant MAX_INT : integer := 2147483647 ;
	TYPE Number is array (0 to matrix_num) of std_logic_vector(0 to 6);
	signal initial : Number := (('0', '0', '0', '0', '0', '0', '1'),		-- 0
							   ('1', '0', '0', '1', '1', '1', '1'),			-- 1
							   ('0', '0', '1', '0', '0', '1', '0'),			-- 2
							   ('0', '0', '0', '0', '1', '1', '0'),			-- 3
							   ('1', '0', '0', '1', '1', '0', '0'),			-- 4
							   ('0', '1', '0', '0', '1', '0', '0'),			-- 5
							   ('0', '1', '0', '0', '0', '0', '0'),			-- 6
							   ('0', '0', '0', '1', '1', '1', '1'),			-- 7
							   ('0', '0', '0', '0', '0', '0', '0'),			-- 8
							   ('0', '0', '0', '0', '1', '0', '0')			-- 9
							  ) ;
	TYPE state_type is (s1, s2, s3) ;		-- how many states does the circuit have?
	signal current_state : state_type ;
begin
	
	process(key)					-- to decide to change
		variable num : integer := 0 ;			-- how many times does user press the key?
	begin
		if falling_edge(key) then
			num := (num + 1) MOD 3 ;
		end if ;
		if (num = 0) then
			current_state <= s1 ;
		elsif (num = 1) then
			current_state <= s2 ;
		elsif (num = 2) then
			current_state <= s3 ;
		end if ;
	end process ;
	
	process(clk, current_state, initial)
		variable jump : integer ;				-- store the times the clock rising
		variable tenth : integer ;
		variable i : integer ;
	begin
		if (current_state = s1) then
			jump := 0 ;
			tenth := 0 ;
		elsif (current_state = s2) then
			if rising_edge(clk) then
				jump := jump + 1 ;
				if (jump = 5000000) then
					tenth := (tenth + 1) MOD MAX_INT ;
					jump := 0 ;
				end if ;
			end if ;
		end if ;
		hex7 <= initial((tenth/36000)/10) ;
		hex6 <= initial((tenth/36000) MOD 10) ;
		hex5 <= initial(((tenth MOD 36000) / 600) / 10) ;
		hex4 <= initial(((tenth MOD 36000) / 600) MOD 10) ;
		hex3 <= initial((((tenth MOD 36000) MOD 600) / 10) / 10) ;
		hex2 <= initial((((tenth MOD 36000) MOD 600) / 10) MOD 10) ;
		hex1 <= initial(((tenth MOD 36000) MOD 600) mod 10);
		hex0 <= ('1', '1', '1', '1', '1', '1', '1') ;
		separate1 <= '1' ;
		separate2 <= '1' ;
		separate3 <= '1' ;
		separate4 <= '1' ;
		separate5 <= '1' ;
	end process ;
end Timer ;

你可能感兴趣的:(FPGA,fpga开发,VHDL)