题目:使用状态机检测“1101”,串行输入的测试序列为“11101101011010”,输出信号为valid有效信号,检测到时输出高,否则为低,考虑序列叠加情况,比如“1101101”,则有两个“1101”。
(不考虑重叠情况的话只是状态转移图有点变化,状态机的写法相似)
本文使用3段式状态机,参考西南交大邸志雄老师课程中第三章第7节关于状态机的写法。
有两个关键点:
两段式状态机:第一个always块采用同步时序描述状态转移;第二个always块组合逻辑判断状态转移条件,描述状态转移规律,并输出结果(组合逻辑输出)。
三段式状态机:第一个always块采用同步时序描述状态转移;第二个always块组合逻辑判断状态转移条件,描述状态转移规律;第三个always块时序逻辑输出结果(寄存器输出)。
同时,需要注意的是,无论二段还是三段,第二段描述状态转移规律用的都是CS(当前状态),三段式状态机的第三段寄存器输出所用状态为NS(下一状态),个中缘由请参考上述 邸志雄老师课程中的讲解,请大家细细体会。
该题目的状态转移图如下所示:
仿真结果如图所示:
附verilog代码:
module fsm_sequence_detection(
input clk,
input rst_n,
input din,
output dout
);
//one hot 编码
parameter IDLE = 5'b00001;
parameter S1 = 5'b00010;
parameter S2 = 5'b00100;
parameter S3 = 5'b01000;
parameter S4 = 5'b10000;
reg dout_r;
assign dout = dout_r;
reg [4:0] CS,NS;
// 第一段 时序逻辑 描述状态转移
always@(posedge clk )
begin
if(!rst_n)
CS <= IDLE;
else
CS <= NS;
end
// 第二段 组合逻辑 判断状态转移条件,描述状态转移规律 ,注意case里是CS
always@(*)
begin
NS <= 5'bx;
case(CS)
IDLE: if(din==1) NS <= S1; else NS <= IDLE;
S1 : if(din==1) NS <= S2; else NS <= IDLE;
S2 : if(din==0) NS <= S3; else NS <= S2;
S3 : if(din==1) NS <= S4; else NS <= IDLE;
S4 : if(din==1) NS <= S2; else NS <= IDLE;
default: NS <= IDLE;
endcase
end
// 第三段 时序逻辑 寄存器输出 注意里面是NS。如果输出结果比较多样就用case(NS)选择输出结果
always@(posedge clk )
begin
if(!rst_n)
dout_r <= 0;
else if(NS == S4)
dout_r <= 1;
else
dout_r <= 0;
end
endmodule
仿真代码:
module fsm_test();
reg clk ;
reg rst_n ;
wire din ;
wire dout ;
initial begin
clk = 0;
rst_n = 0;
#18
rst_n =1;
end
reg [7:0] seq = 8'b01101101;
assign din = seq[7];
always #5 clk = ~clk;
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
seq <=8'b01101101;
else
seq<= {seq[6:0],seq[7]};
end
fsm_sequence_detection uut(
.clk (clk ),
.rst_n (rst_n ),
.din (din ),
.dout (dout )
);
endmodule
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)