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主机驱动和外设驱 ...
随机推荐
- Mac eclipse找不到source的解决办法
因为要搞hadoop,最终还是逃不过写java的命运... eclipse里想查具体函数源代码时,如果报错说找不到源: 试试ls -l which java,在这个目录周围看看能不能找到src.zip ...
- 解决Spring+Quartz无法自动注入bean问题
问题 我们有时需要执行一些定时任务(如数据批处理),比较常用的技术框架有Spring + Quartz中.无奈此方式有个问题:Spring Bean无法自动注入. 环境:Spring3.2.2 + Q ...
- Domain Space
Bluehost Register Page http://www.bluehost.com/track/weipengp
- WPF RichTextBox设置文本颜色
//追加 txtResult.Document.Blocks.Add(new Paragraph(new Run("add by run") { Foreground = Brus ...
- Linux中vi显示中文乱码的问题
由于在windows下默认是gb编码,而我的vim默认是utf-8(gedit默认也是utf-8),所以打开会成乱码.修改了一下配置文件,使vi支持gb编码就好了.$vi ~/.vimrclet &a ...
- 再探 Ext JS 6 (sencha touch/ext升级版) 变化篇 (编译命令、滚动条、控制层、模型层、路由)
从sencha touch 2.4.2升级到ext js 6,cmd版本升级到6.0之后发生了很多变化 首先从cmd说起,cmd 6 中sencha app build package不能使用了,se ...
- linux samba 服务配置及日志管理
2012-01-16 安装samba共需3个rpm包 samba-common-3.0.23c-2.i386.rpm samba-3.0.23c-2.i386.rpm samba-cli ...
- BIEE安装文件下载地址
Repository Creation Utility 下载地址 http://www.oracle.com/technetwork/middleware/bi-enterprise-edition/ ...
- 聊聊 if else 那些事
从这周起,公司技术部每周五组织一次内部的技术分享,日常工作中,发现大家对if掌握的不是很好,今天先来聊聊if. 一.场景 简历的价格是根据专业的父Id设定的,下面根据简历Id获取简历的价格. /// ...
- 技术总结之SpringIOC
1)SpringIOC核心模拟实现 思路:初始化Spring容器时,从配置文件中读取定义好的Bean的信息,根据配置属性初始化后存入Spring容器中. 当需要某个Bean时,直接从容器中通过id获取 ...