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主机驱动和外设驱 ...
随机推荐
- BlazeMeter发布chrome扩展插件,支持JMeter脚本创建
BlazeMeter发布chrome扩展插件,支持JMeter脚本创建http://www.automationqa.com/forum.php?mod=viewthread&tid=3898 ...
- dWebBrowser常用知识点
1.webbrowser调用的就是本机IE,并且webbrowser默认就是运行在IE7 mode下,除非你改变它. 2.不装IE,无法用webbrowser. 3.设置WebBrowser在IE9 ...
- 如何将 Microsoft Bot Framework 链接至微信公共号
说到 Microsoft Bot Framework 其实微软发布了已经有一段时间了,有很多朋友可能还不太了解,微软Bot的功能今天我给大家简单的介绍一下,Bot Framework的开发基础以及如何 ...
- 在内核中异步请求设备固件firmware的测试代码
在内核中异步请求设备固件firmware的测试代码 static void ghost_load_firmware_callback(const struct firmware *fw, void * ...
- VR是TAA的终结者吗?
在刚刚发布的Unreal Engine 4.14中,其第一个重要的特性就是增加了在VR开发中对Forward Shading的支持.我们都知道在很多方面Deferred Shading都优于Forwa ...
- PowerShell 启动应用程序【转】
当你在PowerShell中,启动带参数启动可执行应用程序时,可能会碰到参数解析的错误.最好的方式是使用命令 Start-Process,该命令有两个优点: 程序的路径和程序参数分开,可以使用-Fil ...
- JsonView Tool
- Routine Problem(数学)
Routine Problem time limit per test 1 second memory limit per test 256 megabytes input standard inp ...
- JavaScript备忘录(2)——闭包
语句 JavaScript是解释型语言,解释器是按照顺序逐句执行的(除了进行一些少量预处理,如将函数声明提前). 顺序是由流程控制语句来控制的,常用的流程控制语句包括: 条件控制语句:if...els ...
- Apk去签名校验详解
某些apk为了防止重打包,使用了签名校验.所以在破解的时候我们需要破解签名校验.在定位签名校验位置时常用的关键词有sign,signature,checkSign,signCheck,getPacka ...