Intel FPGA (4):状态机

news2024/11/28 7:26:40

Intel FPGA (4):状态机

前提摘要

  1. 个人说明:

    • 限于时间紧迫以及作者水平有限,本文错误、疏漏之处恐不在少数,恳请读者批评指正。意见请留言或者发送邮件至:“Email:noahpanzzz@gmail.com”
    • 本博客的工程文件均存放在:GitHub:https://github.com/panziping。
    • 本博客的地址:CSDN:https://blog.csdn.net/ZipingPan
  2. 参考:

    • 芯片型号:Intel EP4CE10F17C8(Cyclone IV E)
    • 《数字电子技术基础》-阎石
    • 《FPGA自学笔记—设计与验证》袁玉卓,曾凯锋,梅雪松
    • 《Verilog 数字系统设计教程》夏宇闻
    • 《Verilog HDL 高级数字设计》Michael D.Ciletti
    • 《Intel FPGA/CPLD设计》(基础篇)王欣 王江宏等
    • 《Intel FPGA/CPLD设计》(高级篇)王江宏 蔡海宁等
    • 《综合与时序分析的设计约束 Synopsys设计约束(SDC)实用指南》Sridhar Gangadharan
  3. 日期:

    • 2024-01-01

正文

理论基础

状态机简写为FSM(Finite State Machine),也称为同步有限状态机,一般简称为状态机,之所以说“同步”是因为状态机中所有的状态跳转都是在时钟的作用下进行的,而“有限”则是说状态的个数是有限的。

状态机根据影响输出的原因分为两大类,即Moore型状态机和Mealy型状态机,其共同点 是:状态的跳转都只和输入有关。区别主要是在输出的时候:若最后的输出只和当前状态有关而与输入无关则称为Moore型状态机;若最后的输出不仅和当前状态有关还和输入有关则称为Mealy型状态机。而输入信号可能在一个时钟周期内任意时刻变化,这使得Mealy型状态机对输入的响应发生在当前时钟周期,比Moore有限状态机对输入信号的响应要早一个周期。因此,输入信号的噪声可能影响在输出的信号。

Moore型状态机和Mealy型状态机的区别 :

  1. Moore型状态机:输出信号只取决于当前状态。
  2. Mealy型状态机:输出信号不仅取决于当前状态,还取决于输入信号的值。

它们的区别就在于输出信号是否与输入信号有关,造成的结果是:

实现相同功能时,Moore型状态机需要比Mealy型状态机多一个状态,且Moore型状态机的输出比Mealy型延后一个时钟周期。

状态机是时序逻辑电路中非常重要的一个应用,常在大型复杂的系统中使用较多。

在这里插入图片描述

状态机的主要写法有一段式、二段式和三段式。

  • 一段式指的是在一段状态机中使用时序逻辑既描述状态的转移,也描述数据的输出;

  • 二段式指在第一段状态机中使用时序逻辑描述状态转移,在第二段状态机中使用组合逻辑描述数据的输出;

  • 三段式指在第一段状态机中采用时序逻辑描述状态转移,在第二段在状态机中采用组合逻辑判断状态转移条件描述状态转移规律,在第三段状态机中描述状态输出,可以用组合电路输出,也可以时序电路输出。

优缺点:

  • 一段式在描述大型状态机时会比较困难,会使整个系统显得十分臃肿,不够清晰;
  • 二段式状态机的好处是其结构和理想的理论模型完全吻合,即不会有附加的结构存在,比较精简,但是由于二段状态机的第二段是组合逻辑描述数据的输出,所以有一些情况是无法描述的,比如输出时需要类似计 数的累加情况,这种情况在组合逻辑中会产生自迭代,自迭代在组合逻辑电路中是严格禁止的,而且第二段状态机主要是描述数据的输出,输出时使用组合逻辑往往会产生更多的毛刺,所以并不推荐。
  • 所以衍生出三段式状态机,三段状态机的输出就可是时序逻辑了,但是其结构并不是最精简的了。

所以就衍生出一种新的二段式状态机。

三段式状态机的第一段状态机是用时序逻辑 描述当前状态,第二段状态机是用组合逻辑描述下一状态,如果把这两个部分进行合并而第三段状态机保持不变,就是现在最新的二段式状态机了。这种新的写法在现在不同综合器中都可以被识别出来,这样既消除了组合逻辑可能产生的毛刺,又减小了代码量,还更加容易上手,不必再去关心理论模型是怎样的,仅仅根据状态转移图就 非常容易实现。

按键控制LED

硬件资源

在这里插入图片描述

按下按键S2控制4个LED左移,按下按键S3控制4个LED右移。

当按键按下时,由于按键的硬件原因,需要消除按键带来的抖动问题,主要途径有两种:硬件消抖(RC滤波)和软件消抖(软件延时)。本文采用的是软件消抖,通过检测到按下按键之后,延迟20ms检测此时按键的状态判断按键是否按下;同时按键松开也同样进行消抖操作。

状态转移图为:

在这里插入图片描述

状态转移条件为:

在这里插入图片描述

按键消抖程序:

module key_filter(
	clk,
	rst_n,
	key,
	key_state_valid_go	//1:push on;0:no push.
);

	input clk;
	input rst_n;
	input key;
	output reg key_state_valid_go;

	
	
	
	//--------key wave----------//
	//---|___________|----------//
	//**************************//

	reg [2:0] r_key_sync;
	always@(posedge clk) begin
		if(!rst_n) 
			r_key_sync <= 'd0;
		else 
			r_key_sync <= {r_key_sync[1:0],key};
	end
	
	assign w_key_pedge  = (r_key_sync[2:1]  == 2'b01);
	assign w_key_nedge  = (r_key_sync[2:1]  == 2'b10);
	
	
	localparam S_IDLE 		= 4'b0001;
	localparam S_FILTER0 	= 4'b0010;
	localparam S_DONE		 	= 4'b0100; 	
	localparam S_FILTER1 	= 4'b1000;

	reg [3:0] r_state;
	
	
	
	
	/*---------------------------------state----------------------------------------------*/
	// S_IDLE    -> S_FILTER0 : w_key_nedge == 1'b1										  //
	// S_FILTER0 -> S_IDLE    : w_key_pedge == 1'b1										  //
	// S_FILTER0 -> S_DONE	  : r_timer_cnt == TIMER_CNT_MAX - 1 && r_key_sync[2] == 1'b0 //
	// S_DONE	 -> S_FILTER1 : w_key_pedge == 1'b1										  //
	// S_FILTER1 -> S_DONE    : w_key_nedge == 1'b1										   //
	// s_FILTER1 -> S_IDLE	  : r_timer_cnt == TIMER_CNT_MAX - 1 && r_key_sync[2] == 1'b1 Z//
	
	/*---------------------------------state----------------------------------------------*/
	
	
	
	localparam TIMER_CNT_MAX = 20_000_000 / 20;//20ms
	reg [19:0] r_timer_cnt;
	reg r_cnt_en;
	
	always@(posedge clk)
	begin
		if(!rst_n)
			r_timer_cnt <= 'd0;
		else if(r_cnt_en == 1'b1)
			r_timer_cnt <= r_timer_cnt + 1'b1;
		else
			r_timer_cnt <= 'd0;
	end
	
	
	always@(posedge clk) begin
		if(!rst_n) begin
			r_state <= S_IDLE;
			r_cnt_en <= 1'b0;
			key_state_valid_go <= 1'd0;
		end
		else begin
			case(r_state)
			S_IDLE: begin
				if(w_key_nedge == 1'b1) begin
					r_state <= S_FILTER0;
					r_cnt_en <= 1'b1;
				end
				else begin
					r_state <= S_IDLE;
					r_cnt_en <= 1'b0;
					key_state_valid_go <= 1'd0;
				end
			end
			S_FILTER0: begin
				if(w_key_pedge == 1'b1) begin
					r_state <= S_IDLE;
					r_cnt_en <= 1'b0;
				end
				else if(r_timer_cnt == TIMER_CNT_MAX - 1 && r_key_sync[2] == 1'b0) begin
					r_state <= S_DONE;
					r_cnt_en <= 1'b0;
				end
				else begin
					r_state <= S_FILTER0;
					r_cnt_en <= r_cnt_en;
				end
			end
			S_DONE: begin
				if(w_key_pedge == 1'b1) begin
					r_state <= S_FILTER1;
					r_cnt_en <= 1'd1;
				end
				else begin
					r_state <= S_DONE;
					r_cnt_en <= 1'b0;
				end
			end
			S_FILTER1: begin
				if(w_key_nedge == 1'b1) begin
					r_state <= S_DONE;
					r_cnt_en <= 1'b0;
				end
				else if(r_timer_cnt == TIMER_CNT_MAX - 1 && r_key_sync[2] == 1'b1) begin
					r_state <= S_IDLE;
					r_cnt_en <= 1'b0;
					key_state_valid_go <= 1'd1;
				end
				else begin
					r_state <= S_FILTER1;
					r_cnt_en <= r_cnt_en;
				end 
			end 
			default: begin
				r_state <= S_IDLE;
				r_cnt_en <= 1'b0;
			end 
			endcase
		end 
	end
	

endmodule

顶层文件:

`timescale 1ns/1ns
//function:key0 push on,led left shift.key1 push on ,led right shift.
module led(			
	clk,
	rst_n,
	key,
	led
);


	input clk;
	input rst_n;
	input [1:0] key;
	output reg [3:0] led;

	reg [31:0] r_led_cnt;
	
	localparam LED_CNT_MAX = 500_000_000/20;	//500ms
	

	always@(posedge clk or negedge rst_n)
	begin
		if(!rst_n)
			r_led_cnt <= 'd0;
		else if(r_led_cnt == LED_CNT_MAX - 1)
			r_led_cnt <= 'd0;
		else
			r_led_cnt <= r_led_cnt + 1'd1;
	end

	
	wire [1:0] w_key_state_valid_go;
	
key_filter key_filter1(	//left shift
	.clk(clk),
	.rst_n(rst_n),
	.key(key[0]),
	.key_state_valid_go(w_key_state_valid_go[0])	//1:push on;0:no push.
);	


key_filter key_filter2(	// right shift
	.clk(clk),
	.rst_n(rst_n),
	.key(key[1]),
	.key_state_valid_go(w_key_state_valid_go[1])	//1:push on;0:no push.
);
	
	reg r_shift_en;
	always@(posedge clk)
	begin
		if(!rst_n)
			r_shift_en <= 1'd0;
		else if(w_key_state_valid_go[0] == 1'b1)	
			r_shift_en <= 1'd1;
		else if(w_key_state_valid_go[1] == 1'b1)
			r_shift_en <= 1'd0;
		else
			r_shift_en <= r_shift_en; 
	end
	
	always@(posedge clk or negedge rst_n)
	begin
		if(!rst_n)
			led <= 4'b1110;
		else if(r_shift_en) begin
			if(r_led_cnt == LED_CNT_MAX - 1)
				led <= {led[0],led[3:1]};
			else
				led <= led;
		end
		else begin
			if(r_led_cnt == LED_CNT_MAX - 1)
				led <= {led[2:0],led[3]};
			else
				led <= led;
		end
	end
	
endmodule
	

总结

本工程名为led,如有需要请至github仓库查看!!!


本文均为原创,欢迎转载,请注明文章出处:CSDN:https://blog.csdn.net/ZipingPan。百度和各类采集站皆不可信,搜索请谨慎鉴别。技术类文章一般都有时效性,本人习惯不定期对自己的博文进行修正和更新,因此请访问出处以查看本文的最新版本。

非原创博客会在文末标注出处,由于时效原因,可能并不是原创作者地址(已经无法溯源)。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1562545.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

学习Linux推荐的书籍

我记得有人曾经说过&#xff0c;征服一个男人最好的途径就是抓住他的胃。 ‍‍‍‍ 学习Linux&#xff0c;最重要的就是要先搞懂Linux是啥&#xff0c;有啥&#xff0c;为啥&#xff1f;‍‍‍‍‍‍‍‍‍‍‍‍‍ 所以&#xff0c;我推荐的第一本书就是-《Unix编程艺术》。…

力扣热题100_链表_142_环形链表 II

文章目录 题目链接解题思路解题代码 题目链接 142. 环形链表 II 给定一个链表的头节点 head &#xff0c;返回链表开始入环的第一个节点。 如果链表无环&#xff0c;则返回 null。 如果链表中有某个节点&#xff0c;可以通过连续跟踪 next 指针再次到达&#xff0c;则链表中…

深度学习_NLP常用库报错问题解决

1、SpaCy can‘t find model ‘zh_core_web_sm‘. It doesn‘t seem to be a python package or a valid path to a data 或者 can‘t find model ‘en_core_web_sm‘. It doesn‘t seem to be a python package or a valid path to a data 安装最新的版本&#xff1a; en_…

PE 系统收集 (下一次何至于慌忙乱)

简介 介绍一些PE系统, 还有就是多种烧录PE到U盘方式。 PE 1. Hikari PE Hikari PE 官网说明 当电脑无法制作启动盘时可以使用Android收集制作

家庭网络防御系统搭建-配置流量镜像到NDR系统

由于需要将家庭网络中的全部流量送到NDR分析系统进行分析&#xff0c;因此需要一个具备流量镜像功能的交换机或者路由器。在前面文章所提及的家庭网络架构中&#xff0c;需要一台交换机即可拷贝东西向流量以及南北向流量。当然如果家庭中的路由器或者其他设备具备交换机镜像功能…

OpenCV 4.9使用通用内部函数对代码进行矢量化

返回&#xff1a;OpenCV系列文章目录&#xff08;持续更新中......&#xff09; 上一篇&#xff1a;OpenCV使用通用内部函数对代码进行矢量化 下一篇&#xff1a;OpenCV系列文章目录&#xff08;持续更新中......&#xff09; ​ 目标 本教程的目标是提供使用通用内部函数功…

VSCode必备插件,创建运行JS、Html

这里介绍如何用vscode来创建一下.js文件和.html文件&#xff0c;然后正确的运行他们 一、首先安装两个插件 第一个插件 open in browser (就是我们运行.html文件,把html通过浏览器给它打开) 第二个插件 Code Runner (就是我们运行.js文件&#xff0c;就是直接运行.js文件…

咪咕打造体育元宇宙

9月23日20点&#xff0c;第19届亚运会在杭州开幕。主火炬点燃环节&#xff0c;超过1亿的「数字火炬手」汇聚成具象的数字火炬手&#xff0c;从钱塘江踏着浪花一步步来到「大莲花」上空&#xff0c;和线下的六棒火炬手共同点燃主火炬。 云上观众通过咪咕视频的AR交互界面&#…

Oracle+11g+笔记(1)-SQL语言基础

Oracle11g笔记(1)-SQL语言基础 1、SQL语言基础 1.1 SQL语言的功能 数据定义功能&#xff1a;DDL(CREATE、DROP、ALERT)。 数据查询功能&#xff1a;DQL(Select)。 数据操作功能&#xff1a;DML(INDERT、UPDATE、DELETE)。 数据控制功能&#xff1a;DCL(GRANT、REVOKE、COM…

基于SSM的校园订餐系统

一、功能实现 前台模块 前台主要功能有&#xff1a;用户注册、用户登录、我的购物车、我的订单、商品评论、校园资讯后台模块 后台主要功能有&#xff1a;用户管理、商品管理、订单管理、评论管理、资讯管理等 二、技术选型 2.1 后台技术选型 SpringBoot(Spring、SpringMVC…

ssm015基于java的健身房管理系统的设计与实现+vue

健身房管理系统设计与实现 摘 要 现代经济快节奏发展以及不断完善升级的信息化技术&#xff0c;让传统数据信息的管理升级为软件存储&#xff0c;归纳&#xff0c;集中处理数据信息的管理方式。本健身房管理系统就是在这样的大环境下诞生&#xff0c;其可以帮助管理者在短时间…

win11下,RTMP流媒体服务器保姆级教程

本片博客将详细介绍如何搭建一个RTMP流媒体服务器,包含源码下载&#xff0c;编译常见问题解决方法以及流媒体测试&#xff0c;最后讲解了如何利用obs软件实现推流。 服务器&#xff1a;SRS 3.0(Simple Realtime Server&#xff0c;支持RTMP、HTTP-FLV、HLS、WebRTC) 推流端&…

蓝桥杯刷题day13——自助餐【算法赛】

一、问题描述 食堂最近推出了自助取餐功能&#xff0c;可以通过盘子的形状自动计算费用。你参与到自助计算价格的项目工作中。视觉组的同学已经帮你通过图像识别把盘子图片转换为了字符串&#xff0c;你只需要计算具体的价格即可。 餐盘的费用如下表所示: 你将会得到n 个字符…

【css】文本过长溢出一行不换行普通css以及antd实现

.text-box { white-space: nowrap; /* 防止文字换行 */ overflow: hidden; /* 隐藏超出div的内容 */ text-overflow: ellipsis; /* 当内容超出时&#xff0c;显示省略号 */ max-width: calc(100% - 80px); /* 假设按钮宽度为80px&#xff0c;则设置div的最大宽度为容器宽度…

强化基础-Java-集合

这块的知识点比较零碎也是看到了就过来记录一点&#xff0c;可能是之前没有特别注意的&#xff0c;会持续补充 集合 1 通用实现 ListSetSortedSet&#xff08;如果表达是有序的,返回签名使用有序set来表达&#xff09;NavigableSet(since 1.6)Queue (since 1.5)Deque(since …

2024 年最值得阅读的 ChatGPT 书籍

自ChatGPT问市以来&#xff0c;其全球风靡之势标志着生成式人工智能新纪元的到来。尽管在ChatGPT之前&#xff0c;大型语言模型(LLM)已存在&#xff0c;但其便捷访问和用户友好界面无疑将LLM的应用推向了新高度。至2024年&#xff0c;ChatGPT持续作为热门话题&#xff0c;本文旨…

Qt加载.css/.qss文件设置控件的QSS样式(支持程序运行时修改且立即生效类似换肤效果)

初学Qt时要想通过QSS修改控件QWidget&#xff0c;QPushButton等原生基础控件的样式&#xff0c;一般都是直接在.ui文件中直接添加qss&#xff0c;或者在代码中通过setStyleSheet(QString qss)来设置。当程序很大时&#xff0c;很多地方需要复用样式时会非常麻烦&#xff0c;qss…

CCIE-12-IPSec-VPN-RemoteAccess

目录 实验条件网络拓朴实验目的 开始配置1. R2 Ping R3确定基础网络是通的2. 配置R23. 配置R53. 验证 实验条件 网络拓朴 实验目的 为R2和R3建立IPSec VPN R4可以ping通R5 开始配置 R2&#xff1a;模拟需要远程访问网络的网关 R4&#xff1a;模拟需要远程访问网络内的目标主…

问题2-前端json数组数据转换成csv文件

代码 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>将 JSON 数据导出为 CSV 文件</title> …

node.js的模块化 与 CommonJS规范

一、node.js的模块化 (1)什么是模块化&#xff1f; 将一个复杂的程序文件依据一定的规则拆分成为多个文件的过程就是模块化 在node.js中&#xff0c;模块化是指把一个大文件拆分成独立并且相互依赖的多个小模块&#xff0c;将每个js文件被认为单独的一个模块&#xff1b;模块…