Verilog学习笔记简单功能实现(三)...............同步有限状态机
在Verilog中可以采用多种方法来描述有限状态机最常见的方法就是用always和case语句。如下图所示的状态转移图就表示了一个简单的有限状态机:

图中:图表示了一个四状态的状态机,输入为A和Reset,同步时钟为clk,输出信号是K1和K2,状态机只能在信号的上升沿发生。
(A)下面是可综合的Verilog模块设计状态机的典型方法:(格雷码表示状态)
module fsm(A,Reset,K2,K1,clk,state);
input A,Reset,clk;
output K2,K1;
output [:]state;
reg K2,K1;
reg [:]state;
parameter Idel='b00,
start='b01,
stop='b10,
clear='b11;
always @(posedge clk)
if (!Reset)
begin
state<=Idel;
K2<=;
K1<=;
end
else
case(state)
Idel:if (A)
begin
state<=start;
K1<=;
end
else
begin
state<=Idel;
K2<=;
K1<=;
end
start:if(!A) state<=stop;
else state<=start;
stop: if(A)
begin
state<=clear;
K2<=;
end
else
begin
state<=stop;
K2<=;
K1<=;
end
clear:if(!A)
begin
state<=Idel;
K2<=;
K1<=;
end
else
begin
state<=clear;
K2<=;
K1<=;
end
default:state<='bxx;
endcase
endmodule
(B)用可以综合的Verilog模块设计、用独热码表示状态的状态机
独热码,在英文文献中称做 one-hot code, 直观来说就是有多少个状态就有多少比特,而且只有一个比特为1,其他全为0的一种码制。
module fsm(A,Reset,K2,K1,clk,state);
input A,Reset,clk;
output K2,K1;
output [:]state;
reg K2,K1;
reg [:]state;
parameter Idel='b1000,
start='b0100,
stop='b0010,
clear='b0001;
always @(posedge clk)
if (!Reset)
begin
state<=Idel;
K2<=;
K1<=;
end
else
case(state)
Idel:if (A)
begin
state<=start;
K1<=;
end
else
begin
state<=Idel;
K2<=;
K1<=;
end
start:if(!A) state<=stop;
else state<=start;
stop: if(A)
begin
state<=clear;
K2<=;
end
else
begin
state<=stop;
K2<=;
K1<=;
end
clear:if(!A)
begin
state<=Idel;
K2<=;
K1<=;
end
else
begin
state<=clear;
K2<=;
K1<=;
end
default:state<=Idel;
endcase
endmodule
二进制编码、格雷码编码使用最少的触发器,消耗较多的组合逻辑,而独热码编码反之。独热码编码的最大优势在于状态比较时仅仅需要比较一个位,从而一定程度上简化了译码逻辑。虽然在需要表示同样的状态数时,独热编码占用较多的位,也就是消耗较多的触发器,但这些额外触发器占用的面积可与译码电路(组合电路)省下来的面积相抵消。并且采用独热码可以使电路的速度和可靠性有显著提高,而总的单元数并无增加。
(C)用可以综合的Verilog模块设计,用状态码直接作为输出
module fsm(A,Reset,K2,K1,clk,state);
input A,Reset,clk;
output K2,K1;
output [:]state;
reg [:]state;
assign K2=state[];
assign K1=state[];
parameter Idel = 'b0_000_0,
start = 'b0_010_0,
stop = 'b0_010_0,
stoptoclear='b1_100_0,
clear = 'b0_101_0,
cleartoIdel='b0_011_1;
always @(posedge clk)
if (!Reset)
begin
state<=Idel;
end
else
case(state)
Idel: if (A) state<=start;
else state<=Idel;
start:if(!A) state<=stop;
else state<=start;
stop: if(A) state<=stoptoclear;
else state<=stop;
stoptoclear: state<=clear;
clear:if(!A) state<=cleartoIdel;
else state<=clear;
cleartoIdel: state<=Idel;
default:state<=Idel;
endcase
endmodule
利用状态机的状态直接作为输出可以提升信号的开关速度并节省电路器件,但是开关的维持时间必须与状态的维持时间一致,如果要实现上述的例子必须增加状态才能实现。
在这里state[4],state[0]分别表示前面的K2和K1。
(D)用可以综合的Verilog模块设计,设计复杂多输出状态机时常用的方法
module fsm(A,Reset,K2,K1,clk,state);
input A,Reset,clk;
output K2,K1;
output [:]state;
reg K2,K1;
reg [:]state,nextstate;
parameter Idel = 'b00,
start = 'b01,
stop = 'b10,
clear = 'b11;
always @(posedge clk) //没一个时钟沿产生一次可能的变化
if (!Reset)
state<=Idel;
else
state<=nextstate;
always @(state or A) //产生下一状态的组合逻辑F
case(state)
Idel: if (A) nextstate=start;
else nextstate=Idel;
start:if(!A) nextstate=stop;
else nextstate=start;
stop: if(A) nextstate=clear;
else nextstate=stop;
clear:if(!A) nextstate=Idel;
else nextstate=clear;
default: nextstate='bxx;
endcase
always @(state or Reset or A) //产生输出K1的组合逻辑
if(!Reset) K1=;
else if(state==clear&&!A) K1=; //由clear转向Idel,因为state为非阻塞赋值,所以此时state的状态还是clear
else K1=;
always @(state or Reset or A) //产生输出K2的组合逻辑
if(!Reset) K2=;
else if(state==stop&&A) K2=; //由stop转向clear,因为state为非阻塞赋值,所以此时state的状态还是stop
else K2=;
endmodule
在比较复杂的状态机设计过程中,往往把状态的变化与输出开关的控制分为两部分,就像前面的Mealy型状态机输出部分的组合逻辑一样。为了调试方便还将每一个输出的开关写成一个个的独立的always块以方便调试。在设计复杂的多输出状态及时建议采用这种方法。
因为大多数的FPGA内部的触发器数目相当多,又加上独热码状态机(one hot code machine)的译码逻辑最为简单,所以在FPGA实现状态机时,往往采用独热码状态机(即每个状态只有一个寄存器置位的状态机)。建议采用case语句来建立状态机的模型,因为这些语句表达清晰明了,可以方便的由当前状态转向下一个状态并设置输出。记得:不要忘记在case语句的最后写上default分支,并将状态设置为'bx这就等于告诉综合器case语句已经指定了所有的状态。这样综合器就可以删除不必要的译码电路使生成的电路简洁。
如果将默认的状态设置为某一确定值的状态可不可以呢?
这样会导致,虽然综合器产生的逻辑和设置default:state=’bx;相同,但是状态机的Verilog模型综合前和综合后的仿真结果不一致。因为启动仿真器时,状态机的所有状态都不确定,因此立即进入default状态。这时便会导致开始的状态为state1,但是实际的硬件电路在通电以后,进入的状态是不确定的,很可能不是state1的状态,因此'bx更切合实际一些。但是再有多余状态的情况下,可以通过哦综合指令(高级教程)将默认状态设置为某一确定的有效状态,因为这样能够使得状态机在偶然进入多余状态后,仍能在下一时钟跳变沿返回正常工作状态,否则引起死锁。
目前大多数综合其往往不支持在一个always快中由多个事件触发的状态机(隐含状态机,implicit state machine),为了能综合出有效的电路,用Verilog描述的状态机应明确的由唯一时钟触发。如果比需要用到不同时钟触发的状态机,可以采用以下程序:编写另一个模块,并采用第二种时钟触发;然后用适中调用的方法再领一个模块中将它们连接起来。为了使设计更简单,调试更加容易,通常使得两个状态机的周期由一定的关系。
在Verilog中状态必须明确赋值,使用参数parameter和define都可以实现:
参数定义:parameter state1=2'0,state2=2'1;
...
current_state=state1;
宏定义:`define state1=2'b0,state2=2'b1;
....
current_state=`state2;
Verilog学习笔记简单功能实现(三)...............同步有限状态机的更多相关文章
- Verilog学习笔记简单功能实现(八)...............同步FIFO
Part 1,功能定义: 用16*8 RAM实现一个同步先进先出(FIFO)队列设计.由写使能端控制该数据流的写入FIFO,并由读使能控制FIFO中数据的读出.写入和读出的操作(高电平有效)由时钟的上 ...
- Verilog学习笔记简单功能实现(二)...............全加器
先以一位全加器为例:Xi.Yi代表两个加数,Cin是地位进位信号,Cout是向高位的进位信号.列表有: Xi Yi Cin Sum Cout 0 0 0 0 0 0 0 1 1 0 ...
- Verilog学习笔记简单功能实现(六)...............计数分频电路
在分频器电路中最重要的概念有两个:1)奇分频/偶分频:2)占空比. A)其中最简单的就是二分频电路,占空比为50%,其Verilog程序为 module half_clk(clr,clk_in,clk ...
- Verilog学习笔记简单功能实现(五)...............序列检测设计
这里采用夏宇闻教授第十五章的序列检测为例来学习; 从以上的状态转换图可以写出状态机的程序: module seqdet(x,out,clk,rst); input x,clk,rst; output ...
- Verilog学习笔记简单功能实现(一)...............D触发器
module D_flop(data,clk,clr,q,qb); input data,clk,clr; output q,qb; wire a,b,c,d,e,f,ndata,nclk; nand ...
- Verilog学习笔记简单功能实现(八)...............异步FIFO
基本原理: 1.读写指针的工作原理 写指针:总是指向下一个将要被写入的单元,复位时,指向第1个单元(编号为0). 读指针:总是指向当前要被读出的数据,复位时,指向第1个单元(编号为0). ...
- Verilog学习笔记简单功能实现(四)...............译码器和编码器
这里以简单的3-8译码器和8-3编码器为例: module decoder3_8(a,out); :]a; :]out; 'b1<<a;/*把最低位的1左移in位(根据in口输入的值)并赋 ...
- Verilog学习笔记简单功能实现(七)...............接口设计(并行输入串行输出)
利用状态机实现比较复杂的接口设计: 这是一个将并行数据转换为串行输出的变换器,利用双向总线输出.这是由EEPROM读写器的缩减得到的,首先对I2C总线特征介绍: I2C总线(inter integra ...
- IIC驱动学习笔记,简单的TSC2007的IIC驱动编写,测试
IIC驱动学习笔记,简单的TSC2007的IIC驱动编写,测试 目的不是为了编写TSC2007驱动,是为了学习IIC驱动的编写,读一下TSC2007的ADC数据进行练习,, Linux主机驱动和外设驱 ...
随机推荐
- Spring3系列7- 自动扫描组件或Bean
Spring3系列7- 自动扫描组件或Bean 一. Spring Auto Scanning Components —— 自动扫描组件 1. Declares Component ...
- GitHub使用简单记录
根据<GotGitHub>[1]所做的一些整理 1. 浏览托管项目 在GitHub的页面中可以使用键盘快捷键 (1)按下问号(?)会在弹出窗口显示当前页面可用的快捷键. (2)在项目的代码 ...
- VS2005 / windows sdk7.1配置
VS2005工程需要调用一些后期VS带的库 1. VS2005 安装顺序 1.vs20052.msdn(optional)3.VS80sp1-KB926601-X86-ENU_SP1.exe4.VS8 ...
- 【MongoDB】windows平台搭建Mongo数据库复制集(类似集群)(转)
原文链接:[MongoDB]windows平台搭建Mongo数据库复制集(类似集群)(一) Replica Sets(复制集)是在mongodDB1.6版本开始新增的功能,它可以实现故障自动切换和自 ...
- 【cs229-Lecture17】离散与维数灾难
主要内容: 解决MDP问题的算法: 离散化: 模型MDP的同化型: (model/similator) 拟合值迭代算法: Q函数: 近似政策迭代: 笔记转自:http://blog.csdn.net/ ...
- Linux高级编程--04.GDB调试程序(设置断点)
调试已运行的程序 在UNIX下用ps查看正在运行的程序的PID(进程ID),然后用gdb PID格式挂接正在运行的程序. 先用gdb 关联上源代码,并进行gdb,在gdb中用attach命令来挂接进程 ...
- WCF配置工具及服务调试工具
配置工具 C:\Program Files\Microsoft SDKs\Windows\v7.0A\bin\SvcConfigEditor.exe WCF调试客户端工具 C:\Program F ...
- 去掉NSString中的HTML标签
经常出现字符串带有html标签.下面有个方法一步到位去掉HTML标签 <span style="font-family: 'comic sans ms', sans-serif; co ...
- [Matlab.Matrix] reshape
a=[1,2,3;4,5,6;7,8,9]; a=reshape(a,1,9); a=[1,4,7,2,5,8,3,6,9]; a=reshape(a,9,1); a=[1;4;7;2;5;8;3;6 ...
- intellij 调试方法
intellij 调试方法 转自 http://www.th7.cn/Program/net/201410/296492.shtml