状态机-重叠序列检测
`timescale 1ns/1ns
module sequence_test2(
input wire clk ,
input wire rst ,
input wire data ,
output reg flag
);
//*************code***********//
parameter S0=0, S1=1, S2=2, S3=3, S4=4;
reg [2:0] state, nstate;
always@(posedge clk or negedge rst) begin
if(~rst)
state <= S0;
else
state <= nstate;
end
always@(*) begin
if(~rst)
nstate <= S0;
else
case(state)
S0 : nstate <= data? S1: S0;
S1 : nstate <= data? S1: S2;
S2 : nstate <= data? S3: S0;
S3 : nstate <= data? S4: S2;
S4 : nstate <= data? S1: S2;
default: nstate <= S0;
endcase
end
always@(posedge clk or negedge rst) begin
if(~rst)
flag <= 0;
else
flag <= state==S4;
end
//*************code***********//
endmodule
状态机-非重叠的序列检测
只检测一次的序列,这才是真正的不用考虑其它的,匹配就行,不用考虑不匹配的
`timescale 1ns/1ns
module sequence_test1(
input wire clk ,
input wire rst ,
input wire data ,
output reg flag
);
parameter idle=0,s1=1,s2=2,s3=3,s4=4,s5=5;
reg[2:0]cs;
reg[2:0]ns;
always@(posedge clk,negedge rst)begin
if(!rst)begin
cs<=idle;
end
else begin
cs<=ns;
end
end
always@(*)begin
case(cs)
idle:ns=(data==1)?s1:idle;
s1:ns=(data==0)?s2:idle;
s2:ns=(data==1)?s3:idle;
s3:ns=(data==1)?s4:idle;
s4:ns=(data==1)?s5:idle;
default:ns=idle;
endcase
end
always@(posedge clk,negedge rst)begin
if(!rst)begin
flag<=0;
end
else begin
flag<=ns==s5;
end
end
endmodule
不重叠序列检测
状态机
这种还是用状态机比较方便,对于序列检测,就是根据特点选方法,最简便的是MOORE型,到底慢不慢一拍,直接在输出判断时更改CS,NS,要慢就CS,不慢就NS
nS的MOORE和MEALY型是一样的同步
不重叠的话,不匹配时就直接回到初始状态,都不用Kmp匹配了
移位寄存器
在移位寄存器的基础上,加了一个CNT限制’
`timescale 1ns/1ns
module sequence_detect(
input clk,
input rst_n,
input data,
output reg match,
output reg not_match
);
reg[2:0]cnt;
reg[5:0]ram;
always@(posedge clk,negedge rst_n)begin
if(!rst_n)
cnt<=0;
else
cnt<=cnt==5?0:cnt+1;
end
always@(posedge clk,negedge rst_n)begin
if(!rst_n)
ram<=0;
else
ram<={ram[4:0],data};
end
always@(posedge clk,negedge rst_n)begin
if(!rst_n)begin
match<=0;
not_match<=0;
end
else begin
match<=(cnt==5)&&({ram[4:0],data}==6'b011100);
not_match<=(cnt==5)&&({ram[4:0],data}!=6'b011100);
end
end
endmodule
含有无关项的序列检测
移位寄存器
用两个信号判断左右两侧是不是满足要求的,都满足了就输出1
`timescale 1ns/1ns
module sequence_detect(
input clk,
input rst_n,
input a,
output match
);
reg[8:0]temp;
always@(posedge clk,negedge rst_n)begin
if(!rst_n)begin
temp<=9'b0;
end
else begin
temp<={temp[7:0],a};
end
end
reg ma;
reg mb;
always@(posedge clk,negedge rst_n)begin
if(!rst_n)begin
ma<='b0;
end
else begin
if(temp[8:6]==3'b011)
ma<=1'b1;
else
ma<=1'b0;
end
end
always@(posedge clk,negedge rst_n)begin
if(!rst_n)begin
mb<='b0;
end
else begin
if(temp[2:0]==3'b110)
mb<=1'b1;
else
mb<=1'b0;
end
end
assign match=ma&mb;
endmodule
输入序列连续的序列检测
移位寄存器
这个移位寄存器,是直接判断寄存器存的,即寄存器当前状态,所以是MOORE状态机
`timescale 1ns/1ns
module sequence_detect(
input clk,
input rst_n,
input a,
output reg match
);
reg[7:0]atemp;
always@(posedge clk,negedge rst_n)begin
if(!rst_n)begin
atemp<=8'b0;
end
else
atemp<={atemp[6:0],a};
end
always@(posedge clk,negedge rst_n)begin
if(!rst_n)begin
match=1'b0;
end
else begin
if(atemp==8'b0111_0001)
match=1'b1;
else
match='b0;
end
end
endmodule
状态机
`timescale 1ns/1ns
module sequence_detect(
input clk,
input rst_n,
input a,
output reg match
);
parameter idle=0,s1=1,s2=2,s3=3,s4=4,s5=5,s6=6,s7=7,s8=8;
reg[3:0]cs;
reg[3:0]ns;
always@(posedge clk,negedge rst_n)begin
if(!rst_n)
cs<=idle;
else
cs<=ns;
end
always@(*)begin
case(cs)
idle:begin
ns=(a==0)?s1:idle;
end
s1:begin
ns=(a==1)?s2:s1;
end
s2:begin
ns=(a==1)?s3:s1;
end
s3:begin
ns=(a==1)?s4:s1;
end
s4:begin
ns=(a==0)?s5:idle;
end
s5:begin
ns=(a==0)?s6:s2;
end
s6:begin
ns=(a==0)?s7:s2;
end
s7:begin
ns=(a==1)?s8:s1;
end
s8:begin
ns=(a==1)?s3:s1;
end
default:ns=idle;
endcase
end
always@(posedge clk,negedge rst_n)begin
if(!rst_n)
match<=0;
else
match<=(cs==s8)?1:0;
end
endmodule
MOORE机中判断的是现态,所以慢一拍
MOORE机中判断次态时,与MEALY机一样,是同步输出的
输入序列不连续的序列检测
移位寄存器(同一周期内输出,MEALY型)
在输出判断时,由现态与输入信号共同决定
就是在有效时进行移位,然后还要注意,由于是要在同一拍里输出信号,由于移位的更新是在下一位里才进行,所以这个周期里更新的ram,会在下个周期里进行判断,所以就会导致延后,所以输出的判断要结合现态,即MEALY型
`timescale 1ns/1ns
module sequence_detect(
input clk,
input rst_n,
input data,
input data_valid,
output reg match
);
reg[3:0]ram;
always@(posedge clk,negedge rst_n)begin
if(!rst_n)begin
ram=4'b0;
end
else if(data_valid)begin
ram<={ram[2:0],data};
end
else begin
ram<=ram;
end
end
always@(posedge clk,negedge rst_n)begin
if(!rst_n)begin
match<=0;
end
else begin
match<=(ram[2:0]==3'b011)&&data&&data_valid;
end
end
endmodule
状态机(MOORE型)
MOORE型的话,只与现态有关,所以输出判断时,用的是ns==,即次态等于什么
而如果是MEALY,就是现态加上输入
`timescale 1ns/1ns
module sequence_detect(
input clk,
input rst_n,
input data,
input data_valid,
output reg match
);
parameter idle=0,s0=1,s1=2,s2=3,s3=4;
reg[2:0]cs;
reg[2:0]ns;
always@(posedge clk,negedge rst_n)begin
if(!rst_n)begin
cs<=idle;
end
else begin
cs<=ns;
end
end
always@(*)begin
case(cs)
idle:begin
if(data_valid)
ns=(data==1)?idle:s0;
else
ns=idle;
end
s0:begin
if(data_valid)
ns=(data==1)?s1:s0;
else
ns=s0;
end
s1:begin
if(data_valid)
ns=(data==1)?s2:s0;
else
ns=s1;
end
s2:begin
if(data_valid)
ns=(data==0)?s3:idle;
else
ns=s2;
end
s3:begin
if(data_valid)
ns=(data==0)?s0:idle;
end
endcase
end
always@(posedge clk,negedge rst_n)begin
if(!rst_n)begin
match<=0;
end
else begin
match<=(ns==s3)?1:0;
end
end
endmodule
状态机
需要注意,判断次态的MOORE机不满一拍,真正判断那个现态的才是满一拍的
moore机要比Mealy机多一个状态,这个状态表示初始状态
Moore机的输出由当前状态确定,mealy机的输出由当前状态与输入信号共同决定
最后的输出控制由现态单独控制,因此为摩尔机
蓝色代表输出,摩尔机最后添加了状态S4,从状态转移上看输出节拍会晚一拍,但由于是组合逻辑输出,因此实际上并没有晚一拍
(这个就是说判断次态的MOORE机和MEALY机是一样的输出,即在同一周期内输出,而只有那种真是判断现态的MOORE机才会确实慢一个周期)
摩尔机和米勒机的区别:主要区别在于状态机的输出与当前的状态是否有关,下面用两段式来描述两者的区别。
需要注意的是,如果使用三段式描述法,两者的区别主要聚焦于第三段的判断是基于现态还是次态。
摩尔状态机要比米勒状态机少一个状态,摩尔状态机慢一个周期;米勒状态机使用当前输入和当前状态共同判断,摩尔状态机不需要当前输入。
如果要为moore机的话,那么在输出中,只能判断为次态,即次态是什么;
如果是要mealy机的话,在输出中,要判断为现态与输入信号相结合
这种为Mealy机 ,因为在输出时,输出信号由现态与输入一起控制
二段式
所谓二段式,实际上就是专门针对MOORE机的写法,因为MOORE机的输出仅取决于现态,然后就是判断现态即可,就判断次态是什么,会晚一个周期输出,而二段式,就是省略了最后一段输出,把它揉进了状态转换里
因为是MOORE机,所以在输出里判断的是次态,不如就直接在状态转换里,确定次态时就确定好了输出
三段式
次态到现态,用posedge,
在状态转换时,用always@(*)
输出的时候,也用posedge
在第一个和第二个进程中,由于都是同步时序,所以都用<=,在第二个进程里用=
`timescale 1ns/1ns
module fsm1(
input wire clk ,
input wire rst ,
input wire data ,
output reg flag
);
parameter S0 = 'd0, S1 = 'd1, S2 = 'd2, S3 = 'd3 ;
reg [2:0] current_state;
reg [2:0] next_state;
always@(posedge clk or negedge rst)begin
if(rst == 1'b0)begin
current_state <= S0;
end
else begin
current_state <= next_state;
end
end
always@(*)begin
case(current_state)
S0:begin
next_state = data ? S1 : S0;
end
S1:begin
next_state = data ? S2 : S1;
end
S2:begin
next_state = data ? S3 : S2;
end
S3:begin
next_state = data ? S0 : S3;
end
default:begin next_state = S0; end
endcase
end
always@(posedge clk or negedge rst)begin
if(rst == 1'b0)begin
flag <= 1'b0;
end
else begin
if(current_state == S3)begin
if (data) flag <= 1'b1;
else flag <= 1'b0;
end
else begin
flag <= 1'b0;
end
end
end
endmodule
这是一个mealy机,