在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学习笔记简单功能实现(三)...............同步有限状态机的更多相关文章

  1. Verilog学习笔记简单功能实现(八)...............同步FIFO

    Part 1,功能定义: 用16*8 RAM实现一个同步先进先出(FIFO)队列设计.由写使能端控制该数据流的写入FIFO,并由读使能控制FIFO中数据的读出.写入和读出的操作(高电平有效)由时钟的上 ...

  2. Verilog学习笔记简单功能实现(二)...............全加器

    先以一位全加器为例:Xi.Yi代表两个加数,Cin是地位进位信号,Cout是向高位的进位信号.列表有:   Xi     Yi    Cin Sum Cout 0 0 0 0 0 0 0 1 1 0 ...

  3. Verilog学习笔记简单功能实现(六)...............计数分频电路

    在分频器电路中最重要的概念有两个:1)奇分频/偶分频:2)占空比. A)其中最简单的就是二分频电路,占空比为50%,其Verilog程序为 module half_clk(clr,clk_in,clk ...

  4. Verilog学习笔记简单功能实现(五)...............序列检测设计

    这里采用夏宇闻教授第十五章的序列检测为例来学习; 从以上的状态转换图可以写出状态机的程序: module seqdet(x,out,clk,rst); input x,clk,rst; output ...

  5. 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 ...

  6. Verilog学习笔记简单功能实现(八)...............异步FIFO

    基本原理:       1.读写指针的工作原理 写指针:总是指向下一个将要被写入的单元,复位时,指向第1个单元(编号为0). 读指针:总是指向当前要被读出的数据,复位时,指向第1个单元(编号为0). ...

  7. Verilog学习笔记简单功能实现(四)...............译码器和编码器

    这里以简单的3-8译码器和8-3编码器为例: module decoder3_8(a,out); :]a; :]out; 'b1<<a;/*把最低位的1左移in位(根据in口输入的值)并赋 ...

  8. Verilog学习笔记简单功能实现(七)...............接口设计(并行输入串行输出)

    利用状态机实现比较复杂的接口设计: 这是一个将并行数据转换为串行输出的变换器,利用双向总线输出.这是由EEPROM读写器的缩减得到的,首先对I2C总线特征介绍: I2C总线(inter integra ...

  9. IIC驱动学习笔记,简单的TSC2007的IIC驱动编写,测试

    IIC驱动学习笔记,简单的TSC2007的IIC驱动编写,测试 目的不是为了编写TSC2007驱动,是为了学习IIC驱动的编写,读一下TSC2007的ADC数据进行练习,, Linux主机驱动和外设驱 ...

随机推荐

  1. TSPL学习笔记(3):排序算法练习

    快速排序 快排的详细介绍见,简单的说就是取输入序列中的首元素m,然后将除首元素m以外的其它元素分成两组,小于等于m的一组和大于m的一组.将3组元素组合成输入队列:小于等于m + m + 大于m. 下面 ...

  2. worksteal thread pool

    worksteal的场景 对于一个线程池,每个线程有一个队列,想象这种场景,有的线程队列中有大量的比较耗时的任务堆积,而有的线程队列却是空的,现象就是有的线程处于饥饿状态,而有的线程处于消化不良的状态 ...

  3. MySql 数据操作类

    /// <summary> /// MySqlHelper 的摘要说明. /// </summary> public class MySqlHelper { public st ...

  4. cocos2dx的lua绑定

    一.cocos2dx对tolua++绑定的修正 A.c对lua回调函数的引用 在使用cocos2dx编写游戏时,我们经常会设置一些回调函数(时钟.菜单选择等).如果采用脚本方式编写游戏的话,这些回调函 ...

  5. LintCode-- Remove Linked List Elements

    Remove all elements from a linked list of integers that have valueval. 样例 Given 1->2->3->3- ...

  6. 转载 jquery $(document).ready() 与window.onload的区别

    Jquery中$(document).ready()的作用类似于传统JavaScript中的window.onload方法,不过与window.onload方法还是有区别的. 1.执行时间 windo ...

  7. 明天去FDUSC报道了,GOD BLESS ALL OF US

    @lrb @tellmewtf @proverbs

  8. Windows Storage Server 2008 R2 Standard(64位)之ASM(Automated Storage Manager)管理

    一.服务器管理器之LUN管理 服务器管理器的LUN管理,右键可删除(注意别删了系统分区在的LUN) 二.ASM(Automated Storage Manager) view 高级信息,请不要修改相关 ...

  9. Python单元测试框架之pytest -- 生成测试报告

    继续pytest单元测试框架的学习,pytest可以生成多种类型的测试报告.这一节就来学习pytest如何生成测试报告. 创建test_calss.py 测试用例文件,这里以测试该文件为例. #cod ...

  10. Dewey – 标记和搜索 Chrome 浏览器书签

    Dewey 是一个 Chrome 应用程序,用于标记,搜索和排序你的 Chrome 浏览器书签.借助 Dewey,您可以添加自定义标签,生成你的书签截图,灵活快捷的方式进行搜索和排序. 您可能感兴趣的 ...