FSM之三--代码风格
FSM设计之一http://www.cnblogs.com/qiweiwang/archive/2010/11/28/1890244.html
Moore型状态机与mealy型状态机相比,由于其状态输出仅与当前状态有关,而与输入无关,所以它可以避免由输入信号引起的毛刺,因此建议采用Moore型状态机。但是在实际的应用中,我们只需要对状态输出进行寄存,即在outputs后面加上一级输出寄存,就可以有效地避免毛刺的传播。
Binary、gray-code编码使用最少的触发器,较多的组合逻辑。而one-hot 编码反之。由于CPLD更多的提供组合逻辑资源,而FPGA更多的提供触发器资源,所以CPLD 多使用gray-code,而FPGA 多使用one-hot编码。 另一方面,对于小型设计使用gray-code和binary编码更有效,而大型状态机使用one-hot更高效。
看synplicity的文档,推荐在24个状态以上会用格雷码,在5~24个状态会用独热码,在4个状态以内用二进制码,肯定独热码比二进制码在实现FSM部分会占更多资源,但是译码输出控制简单,所以如果状态不是太多,独热码较好。状态太少译码不会太复杂,二进制就可以了。状态太多,前面独热码所占资源太多,综合考虑就用格雷码了。
编码风格:
1. 避免生成锁存器
一个完备的状态机(健壮性强)应该具备初始化(reset)状态和默认(default)状态。 当芯片加电或者复位后,状态机应该能够自动将所有判断条件复位,并进入初始化状态。需要注
明的一点是,大多数FPGA有GSR(Global Set/Reset)信号,当FPGA加电后,GSR信号拉高,对所有的寄存器,RAM等单元复位/置位,这时配置于FPGA的逻辑并未生效,所以不能保证正确的进入初始化状态。所以使用 GSR进入FPGA的初始化状态,常常会产生种种不必一定的麻烦。一般简单方便的方法是采用异步复位信号,当然也可以使用同步复位,但是要注意同步复位的逻辑设计。
状态机也应该有一个默认(default)状态,当转移条件不满足,或者状态发生了突变时,要能保证逻辑不会陷入“死循环”。这是对状态机健壮性的一个重要要求,也就是常说的要具备“自恢复”功能。对应于编码就是对 case,if-else 语句要特别注意,要写完备的条件判断语句。VHDL 中,当使用CASE语句的时候,要使用“When Others”建立默认状态。使用“IF...THEN...ELSE”语句的时候,要用在“ELSE”指定默认状态。 Verilog中, 使用“case”语句的时候要用“default”建立默认状态, 使用“if...else”语句的注意事项相似。
另外有一个技巧:大多数综合器都支持 Verilog 编码状态机的完备状态属性--“full case”。
2. 参数定义用 parameter
状态的定义用 parameter 定义,不推荐使用`define 宏定义的方式,因为‘define 宏定义在编译时自动替换整个设计中所定义的宏,而 parameter 仅仅定义模块内部的参数,定义的参数不会与模块外的其他状态机混淆。
3. 一定要使用”<=”非阻塞赋值方式
采用非阻塞赋值方式消除很多竞争冒险的隐患。
(
input clk,
input rst_n,
input a,
outputreg y
);
//
parameter s0 =2'b00,
s1 =2'b01,
s2 =2'b10,
s3 =2'b11;
//
reg [1:0] current_state;
reg [1:0] next_state;
//状态转移
always @ (posedge clk,negedge rst_n)
begin
if(!rst_n)
current_state <= s0;
else
current_state <= next_state;
end
//状态译码逻辑
always @ (a or current_state)
begin
case(cs)
s0:
if(a==1'b1)
next_state =s1;
else
next_state=s0;
s1:
next_state = s2;
s2:
next_state = s3;
s3:
next_state = s0;
default:
next_state =s0;
endcase
end
//状态寄存输出
always @ (posedge clk,negedge rst_n)
begin
if(!rst_n)
y <=1'b0;
elseif(next_state==s3)//输出与next_state有关
y <=!a;
else
y <=1'b0;
end
endmodule
one-hot编码
one-hot顾名思义,指任何时候一个nbit的寄存器组中有且仅有1bit为1,其他n-1个寄存器值均为0。在状态机编码的范畴中,它就像是“一个萝卜一个坑”,每个状态都占用一个寄存器,该位为1时表示状态机进入该状态,为0时表示状态机不在该状态。因此,每个状态只用1bit即可表示出来。在进入一个新状态时,将原状态对应的寄存器位置0、新状态对应的寄存器位置1,以保证“one-hot”。
在电路面积和速度方面,one-hot编码方式所占用的DFF资源要比binary编码多一些,n个状态要用n个DFF;但是这种编码方式由在状态译码的时候只需要用1bit参与状态译码,译码逻辑较小,生成的组合逻辑相应的较小。总体来说,在FPGA设计中,采用one-hot编码方式往往消耗的资源要比binary编码少。
那么为什么one-hot编码方式在译码的时候只需要有1bit参与译码呢?我们知道,需要多少位参与状态译码和状态的表示方式很有关系,也就是说和何种方式去标识一个状态很有关系,如果一个状态用4bit表示,那么它在译码的时候就要用4bit,但是如果只有一个状态用1bit表示,则它参与译码时只需要1bit即可,所以,one-hot这种“一个萝卜一个坑”的结构决定了它在译码时每个状态只需要用一位参与译码。
one-hot编码方式通常分为两类:一种是非index编码方式;一种是index编码方式。
(
input clk,
input rst_n,
input [1:0] a,
output y
);
//
parameter U_DLY =1;
parameter s0 =10'b00_0000_0001,
s1 =10'b00_0000_0010,
s2 =10'b00_0000_0100,
s3 =10'b00_0000_1000,
s4 =10'b00_0001_0000,
s5 =10'b00_0010_0000,
s6 =10'b00_0100_0000,
s7 =10'b00_1000_0000,
s8 =10'b01_0000_0000,
s9 =10'b10_0000_0000;
//
reg [9:0] current_state;
reg [9:0] next_state;
reg [5:0] cnt;
//
always @ (posedge clk,negedge rst_n)
begin
if(!rst_n)
current_state <= s0;
else
current_state <= #U_DLY next_state;
end
//
always @ (a,cnt,current_state)
begin
case(current_state)
s0:
case(a)
2'b00: next_state = s1;
2'b01: next_state = s2;
2'b10: next_state = s3;
2'b11: next_state = s4;
endcase
s1:
next_state = s9;
s2:
next_state = s5;
s3:
next_state = s6;
s4:
next_state = s8;
s5:
next_state = s6;
s6:
next_state = s7;
s7:
begin
if(cnt==6'h2f)
next_state = s9;
else
next_state = s7;
end
s8:
next_state = s9;
s9:
begin
if(cnt ==6'h3f)
next_state = s0;
else
next_state = s9;
end
default:
next_state = s0;
endcase
end
//
always @ (posedge clk,negedge rst_n)
begin
if(!rst_n)
cnt <=6'b0;
elseif(next_state == s9)
cnt <= #U_DLY cnt+1'b1;
else
cnt <= #U_DLY 6'b0;
end
assign y = current_state[8];
endmodule
index编码方式:
input clk,
input rst_n,
input [1:0] a,
output y
);
//
parameter U_DLY =1;
parameter s0 =0,
s1 =1,
s2 =2,
s3 =3,
s4 =4,
s5 =5,
s6 =6,
s7 =7,
s8 =8,
s9 =9;
//
reg [9:0] current_state;
reg [9:0] next_state;
reg [5:0] cnt;
//
always @ (posedge clk,negedge rst_n)
begin
if(!rst_n)
state <=10'b0;
state[s0] <= 1'b1;//because the coding of IDLE is 10'b1
else
current_state <= #U_DLY next_state;
end
//
always @ (a,cnt,current_state)
begin
next_state <=10'b0;//给next_state这样赋默认值综合后不会出现锁存器
case(1'b1)//synthesis parallel_case full_case
current_state[s0]:
case(a)
2'b00: next_state[s1] = 1'b1;
2'b01: next_state[s2] = 1'b1;
2'b10: next_state[s3] = 1'b1;
2'b11: next_state[s4] = 1'b1;
endcase
current_state[s1]:
next_state[s9] =1'b1;
current_state[s2]:
next_state[s5] =1'b1;
current_state[s3]:
next_state[s6] =1'b1;
current_state[s4]:
next_state[s8] =1'b1;
current_state[s5]:
next_state[s6] =1'b1;
current_state[s6]:
next_state[s7] =1'b1;
current_state[s7]:
begin
if(cnt==6'h2f)
next_state[s9] =1'b1;
else
next_state[s7] =1'b1;
end
current_state[s8]:
next_state[s9] =1'b1;
current_state[s9]:
begin
if(cnt ==6'h3f)
next_state[s0] =1'b1;
else
next_state[s9] =1'b1;
end
endcase
end
//
always @ (posedge clk,negedge rst_n)
begin
if(!rst_n)
cnt <=6'b0;
elseif(next_state[s9] ==1'b1)
cnt <= #U_DLY cnt+1'b1;
else
cnt <= #U_DLY 6'b0;
end
assign y = current_state[s8];//在使用one-hot状态机某些情况下,可以将状态信号直接作为输出,从而节约逻辑资源,提供电路速度
endmodule
由上面的例子分析可知,非index编码的状态机在状态译码时使用了10位参与状态译码,index编码时只用了一位参与状态译码。而由前面的分析知道,one-hot编码的本质就是一个状态用一位表示,因此,index编码才能真正地反映出one-hot的本质。
非index编码的状态机由于译码逻辑过多,在消耗资源级Fmax这两个指标上都不如index编码,因此,在使用one-hot编码时,推荐使用index编码的方式。
FSM之三--代码风格的更多相关文章
- Python 代码风格
1 原则 在开始讨论Python社区所采用的具体标准或是由其他人推荐的建议之前,考虑一些总体原则非常重要. 请记住可读性标准的目标是提升可读性.这些规则存在的目的就是为了帮助人读写代码,而不是相反. ...
- .NET 项目代码风格要求
原文:http://kb.cnblogs.com/page/179593/ 项目代码风格要求 PDF版下载:项目代码风格要求V1.0.pdf 代码风格没有正确与否,重要的是整齐划一,这是我拟的一份&l ...
- AngularJS之代码风格36条建议【一】(九)
前言 其实在新学一门知识时,我们应该注意下怎么书写代码更加规范,从开始就注意养成一个良好的习惯无论是对于bug的查找还是走人后别人熟悉代码都是非常好的,利人利己的事情何乐而不为呢,关于AngularJ ...
- Visual Studio Code 使用 ESLint 增强代码风格检查
前言 在团队协作开发中,为了统一代码风格,避免一些低级错误,应该设有团队成员统一遵守的编码规范.很多语言都提供了Lint工具来实现这样的功能,JavaScript也有类似的工具:ESLint.除了可以 ...
- plain framework 1 参考手册 入门指引之 代码风格
代码风格 介绍 介绍 框架自身采用了google的C++风格,作者也鼓励在你的应用中使用此风格,有关此风格你可以查阅相关资料了解.下面是一段plain framework中的代码,以便大家参考: 你可 ...
- 对 JimmyZhang 老师的文章《项目代码风格要求》的一些个人观点
Jimmy Zhang 老师是博客园中我最佩服的人之一,今天看了他的文章<项目代码风格要求>觉得大部分地方我都很认同,工作中也是强迫自己也要按照规范来编程.下面是我的一些个人观点,想贴出来 ...
- python代码风格-PEP8
转载自http://www.douban.com/note/134971609/ Python 的代码风格由 PEP 8 描述.这个文档描述了 Python 编程风格的方方面面.在遵守这个文档的条件下 ...
- Google HTML/CSS代码风格指南(中文版)
原文链接:http://wncbl.cn/posts/c8e10815/ 看一下没什么印象,那就写一遍吧. 背景 本文档定义了HTML/CSS的编写格式和风格规则.它旨在提高合作和代码质量,并使其支持 ...
- .Net 项目代码风格要求小结
代码风格没有正确与否,重要的是整齐划一,这是我拟的一份<.Net 项目代码风格要求>,供大家参考. 1. C# 代码风格要求1.1注释 类型.属性.事件.方法.方法参数,根据需要添加注释. ...
随机推荐
- eclipse历史版本下载地址
http://wiki.eclipse.org/Older_Versions_Of_Eclipse
- NOIp模拟赛二十九
又是受虐的一天呢~接下来四天都要打模拟赛QAQ 今日分数:0(100)+100+0=100 A题O(读入)结论题判断结果时没return 0被subtask卡成0分,喜提fstQAQ,B题DP,C题不 ...
- BZOJ 3376 [Usaco2004 Open]Cube Stacking 方块游戏(带权并查集)
题解 #include<iostream> #include<cstring> #include<cstdio> #include<cmath> #in ...
- Python ftplib 模块关于 ftp的下载
import ftplib import os import socket import sys HOST='192.168.216.193' DIRN='c:\\ftp\FTP.123' FILE= ...
- 【BZOJ 1452】 [JSOI2009]Count
[链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 维护一百个二维树状数组. 二维区间求和. [代码] #include <bits/stdc++.h> #define L ...
- [terry笔记]11gR2_DataGuard搭建_primary零停机
11gR2搭建dataguard环境,此篇文章是利用rman搭建dataguard,这样的好处是primary不用停机,当然,前提条件是primary已经开启归档. 相对于可以停机,零停机传送数据文件 ...
- tomcat怎样禁止显示文件夹和文件列表
查看原文:http://www.ibloger.net/article/300.html Tomcat禁止显示文件夹和文件列表 打开 tomcat的安装文件夹/conf/web.xml 文件 &l ...
- zzulioj--1832--贪吃的松鼠(位运算好题)
1832: 贪吃的松鼠 Time Limit: 3 Sec Memory Limit: 2 MB Submit: 43 Solved: 7 SubmitStatusWeb Board Descri ...
- 7. 关于IntelliJ IDEA删除项目
转自:https://www.cnblogs.com/zhangqian27/p/7698148.html 刚开始使用IDEA . 自己创建项目玩,结果发现IDEA无法删除,我也是醉了,Eclipse ...
- 28.STL常用算法
#include <algorithm> 算法 常用版本 描述 返回Type std::find() find(_InIt _Fisrt,_InIt _Last, _Ty& _Va ...