mooremealy状态机区分(附例⼦代码)三段式描述⽅式
在状态机部分,moore和mealy也算是⽼⽣常谈了吧。
什么是状态?
说⽩了就是通过时钟信号不断改变当前的状态,可能是根据输⼊的数据,也可能是⾃⾝发⽣改变(⽐如⼀些计时器),所以少不了触发器,虽然我们有功能⼗分多的JK,有RS,但是我们⼀般采⽤的触发器类型都是D触发器。
状态机的设计
实际电路的设计和verilog设计还不⼤相同。因为verilog好⽍还不是那么底层,不需要⾃⼰进⾏搭线(除⾮采⽤结构化描述),也就是我们可以省略⼀些步骤。
老师来家访唯一爱好好了么,基本上省了很多了,只需要将状态找出来,进⾏分配,然后给出状态转移情况即可。
moore和mealy的区分
很明显了,mealy的输出不但有当前的Q,还有input的参与,再看看moore就没有这么多事,直接受现态Q的控制。
相互转化?
说是这么说,但是不真正给⼀个例⼦分析⼀下,就这样⼝嗨很难看懂的,⽽看不懂就很难明⽩为什么两者可以相互转换。
例⼦:从⼋位拨码开关检测序列01011的存在(别问为什么都是并⾏输⼊了还需要使⽤状态机)
⾸先,我们先给出⼀个个的状态:
(⼀般是默认0为S0,1为S1)
状态内容输出
S000矮小的近义词
S110
S2010
S30100
机械能守恒定律S401010
S5010111
我们可以看出来,上⾯那组输出是只和状态有关,⽽和输⼊⽆关(因为根本就没有给出输⼊情况)
所以这个的状态分配就是moore型了
状态转换:
那么mealy是什么样的呢?
状态输⼊0/输出输⼊1/输出内容S0S0/0S2/00 S1S0/0S1/01 S2S3/0S1/001 S3S0/0S4/0010 S4S3/0S1/10101可以看出,输出不但和状态有关,也看输⼊的内容(S4+输⼊1才能输出Z = 1)
我们可以发现,在Moore和mealy中,状态的个数是不同的,其实在⼀些情况下,两者的状态种类都是不⼀样的。(如⾃动贩卖机
中,Moore是投⼊的总硬币价值,mealy是每次投⼊硬币的价值)
抓住问题的本质,才能设计出Moore和mealy型的状态。
实现
我们的例⼦还没完呢,我们现在只是得到了基本的状态,还没有进⾏分配并实现。
状态分配很简单,Si = i即可。
在实现的过程中,我们就不得不提⼀下三段式的问题了。
这⾥声明⼀下,因为被检测串的第⼀位是0,所以这⾥采⽤001状态(S1)为起始状态。(如果采⽤0为
起始状态,会将1011检测为正确)三段式
在数字逻辑设计中,我们知道时序电路有三个重要的⽅程:输⼊⽅程、驱动⽅程和输出⽅程,不论怎么叫,本质上就是:确定触发器的输⼊端内容
确定触发器的次态
确定整体的输出。这⾥注意,看的是现态⽽不是次态!
⽽这三个⽅程我们分别使⽤三个always块来实现,这就是三段式。这种描述⽅法思路更加清晰、便于维护,并且输出变量由时序逻辑控制,不会产⽣⽑刺现象。
接着叙述我们的题⽬:
利⽤拨码开关输⼊8位数,按下s0进⾏数据输⼊,使⽤状态机判断8位中是否存在01011字串,如果有,led灯亮;没有则熄灭。另外我们还有⼀个异步复位按键,将状态机状态归零并熄灭led灯。
我们先实现Moore型的
有⼀说⼀这个例⼦不太好,看⼀下三段式的写法即可,就别cv了。(其实虽然实现了,但代码不是很完美)
细节:
我们在每⼀个输⼊只能改变状态⼀次:我们采⽤按时钟周期输⼊的⽅式来解决问题;
在输⼊结束后,我们需要保持led灯的情况,也就是要保持判断,所以在输出always块中选择如果输出为真则⼀直为真这样⼀个分⽀(除⾮是有t或者rst信号)
我们需要在输⼊结束将state状态改为001,也就是起始状态,⽽我们在控制计数器开始时有⼀个时钟信号(该信号覆盖了整个状态转移的过程),刚好我们可以使⽤这个信号来实现。
输⼊:t、rst、时钟信号和8位拨码开关输⼊
输出:led灯使能信号detect_o
代码:
`timescale 1ns /1ps
module moor_top(
input rst_n_i,//异步复位&状态机回到初始状态,⾼电平有效
input t_i,//同步使能端,⾼电平有效
input clk_i,
input [7:0]data,
output reg detect_o
);
reg x=1'b0;//输⼊
reg [7:0]in=8'b0000_0000;//存储⼋位
reg [3:0]number=4'b0000;//计数器
reg [2:0]state=3'b000;//当前状态
reg if_in=1'b0;//判断是否停⽌计数
南沙群岛
//当前状态的状态寄存器
always @(podge clk_i)
begin
if(t_i)//有效输⼊
begin
in <= data;
if_in <=1'b1;//开始计数
end
el if(if_in)
begin
if(number !=4'b1000)
begin
x <= in[number];
number <= number +1;
end
el//结束计数
begin
number <=0;
if_in <=1'b0;
end
end
el;
end
/
/描述下⼀状态的状态寄存器
always @(podge clk_i)
begin
if(rst_n_i)//复位
begin
state <=3'b001;
end
el if(!if_in)//输⼊结束,不需要状态转移,直接归零 state <=3'b001;
el
ca({x,state})
4'b0000:state <= 3'b000;
4'b0001:state <= 3'b000;
4'b0010:state <= 3'b011;
4'b0011:state <= 3'b000;
4'b0100:state <= 3'b011;
4'b0101:state <= 3'b000;
4'b1000:state <= 3'b010;
4'b1001:state <= 3'b001;
4'b1010:state <= 3'b001;
4'b1011:state <= 3'b100;
4'b1100:state <= 3'b101;
4'b1101:state <= 3'b001;
default;
endca园艺专业学什么
end
//描述输出
always @(*)
begin
if(t_i || rst_n_i)//再次输⼊&重置
begin
detect_o =1'b0;
end
el if(detect_o ==1'b1)//保持亮
detect_o =1'b1;
el
begin
if(state ==3'b101)
begin
detect_o =1'b1;
如果当时end
el
begin
detect_o =1'b0;
旋转楼梯效果图end
end