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

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

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

画出秒表的状态图:
在这里插入图片描述
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 ;
  • 5
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
首先,我们需要定义串口的波特率、数据位、停止位和校验位等参数。然后,我们可以使用状态机来实现串口的收发功能。 以下是一个基于VHDL的串口状态机的实现: ```vhdl library ieee; use ieee.std_logic_1164.all; entity uart_rx is port ( clk: in std_logic; reset: in std_logic; rx: in std_logic; data: out std_logic_vector(7 downto 0); valid: out std_logic ); end entity; architecture rtl of uart_rx is -- 定义状态机的状态 type state_type is (IDLE, START, BITS, STOP, PARITY, VALID); signal state: state_type; -- 定义计数器和寄存器 signal cnt: integer range 0 to 15 := 0; signal reg: std_logic_vector(7 downto 0); begin -- 状态机的行为 process (clk, reset) begin if reset = '1' then state <= IDLE; cnt <= 0; reg <= (others => '0'); valid <= '0'; elsif rising_edge(clk) then case state is when IDLE => if rx = '0' then state <= START; cnt <= 0; reg <= (others => '0'); end if; when START => if cnt = 0 then if rx = '0' then cnt <= cnt + 1; else state <= IDLE; end if; else state <= BITS; end if; when BITS => if cnt < 8 then reg(cnt) <= rx; cnt <= cnt + 1; else state <= PARITY; end if; when PARITY => if cnt = 8 then cnt <= cnt + 1; else if cnt = 9 then state <= STOP; else if rx = '0' then reg(cnt-1) <= '1'; else reg(cnt-1) <= '0'; end if; cnt <= cnt + 1; end if; end if; when STOP => if cnt = 10 then state <= VALID; else state <= IDLE; end if; when VALID => data <= reg; valid <= '1'; state <= IDLE; end case; end if; end process; end architecture; ``` 该状态机包含以下状态: - IDLE:空闲状态,等待接收到起始位。 - START:接收到起始位后,开始接收数据位。 - BITS:接收数据位。 - PARITY:接收校验位。 - STOP:接收停止位。 - VALID:接收到完整的数据帧,输出数据和有效信号。 该状态机使用计数器和寄存器来存储接收到的数据。当接收到完整的数据帧时,将数据和有效信号输出。在接收过程中,如果接收到错误的数据,则会重新回到空闲状态等待下一帧的接收。 需要注意的是,该状态机仅实现了串口的接收功能。如果需要实现串口的发送功能,可以采用类似的状态机设计,并在相应的状态下输出发送的数据。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值