一个序列检测器的问题
我写了一个10010序列检测器,每检测有一串10010就输输出一个1。我写出了代码,仿真不对,希望大大们帮我分析一下
代码如下
`timescale 1ns / 1ps
module test8_fsm(x,z,clk,rst,
state_out );
input x,clk,rst;
output z;
output [2:0]state_out;
wire z;
reg[2:0] state,nextstate;
parameter idle=3'b000,
s1=3'b001,
s10=3'b010,
s100=3'b011,
s1001=3'b100,
s10010=3'b101;
assign state_out=state;
always@(posedge clk)
if(rst)
state<=idle;
else
state<=nst;
always@( posedge clk )
case(state)
idle: if(x) nextstate=s1;//小弟编了6个装备,空闲0,按10010输入的顺序,S1,S10,S100,S1001,S10010
else nextstate=idle;
s1: if(!x) nextstate=s10;
else nextstate=s1;
s10:
if(!x ) nextstate=s100;
else nextstate=s1;
s100:if(x) nextstate=s1001;
else nextstate=idle;
s1001:if(!x) nextstate=s10010;
else nextstate=s1;
s10010:if(x) nextstate=s1;
else nextstate=s100;
default:nextstate=3'bxxx;
endcase
assign z=(state==s10010)?1:0;
endmodule
仿真激励如下
`timescale 1ns / 1ps
module time_test8;
wire x;
reg clk;
reg rst;
reg [23:0]data;
wire z;
wire [2:0]state_out;
test8_fsm uut (
.x(x),
.z(z),
.clk(clk),
.rst(rst),
.state_out(state_out)
);
assign x=data[23];
always #10clk=~clk;
always@(posedge clk)
data<={data[22:0],data[23]};
initial
begin
clk = 1;
rst = 0;
data=24'b1100_1001_0000_10010_0100_1010;
#10rst=1;
#100rst=0;
#1000 rst=1;
#1000 rst=0;
#2000 rst=1;
#1000 rst=0;
#5000 $stop;
end
endmodule
错误的仿真结果如下··


麻烦看看我写的 问题出在了哪儿··谢谢各位了!
看下状态机方面的资料吧,状态转换和输入的always块改写为组合逻辑电路。
问题不少
nst没有声明过
nextstate=3'bxxx; 改成3'b000; 哪有自己把状态导向不可知的
给nextstate赋值的always 改成组合逻辑 always @* 这个应该是造成你状态机不能正常转移的关键问题
Have you compiled the code successfully?
it is no neccessary to finish this function by means of fsm,in fact.
you can use a shifter to realize the same function.
If you do finish the funciton in your own way, i suggest that you should learn how to finish function in fsm
你好,谢谢你的耐心和热心!我那个NST就是NEXTSTATE```之前复制时这个没替换到,不好意思!
主要问题就出在always@()里的触发条件噢,如果改为always@(*)的话 ,假如输入为连续两个低电平,X不跳变,这样状态会不会发生转移·····?
我后来又改了一下 ,把状态跳转改成阻塞赋值了 ,结果可以出正常结果了,可是结果总是慢两个时钟,大大您看一下,这是为什么呢?
原先是 always@(posedge clk)
if(rst)
state<=idle;
else
state<=nextstate;
改后 always@(posedge clk)
if(rst)
state=idle;
else
state=nextstate;
这样能出结果了 ,就是慢了两个周期才出!仿真图如下
恩,目前正在学习。!但有时遇到问题解决不了确实蛮难受的·
我现在就在学习如何用三段式状态机写法来写代码啊···我用两段式写出来的没问题,但三段式总是有问题,现在就是自己发现不了问题!盯着这段代码看了好久好久,也换东西仿真,但还是····哎,谢谢各位能热情的点开这个求助帖!
大大!如你所眼我把always@(posedge clk)改成always@(*)后,仿真了一下 ,能行了!
谢谢你!但是我还想问一下为什么会这样,我每个上升沿采集一下X然后判定一次状态转移感觉上时行的,可实际上为什么行不通呢?
而且如我楼上那个回复,为什么把非阻塞改为阻塞后 ,也可以?只是慢了两个时钟
慢慢学会debug,,楼上已经说了,可以用移位寄存器和FSM来实现此功能,FSM写法很重要
不知异或后就和检测是不是更方便。
@*包含的敏感信号不止x, 还有state, 第二个0来的时候state已经转移过,会再次触发always.
可能是小弟没有表达清楚,是这样的,有一连串的数据到来,只要里面有一次10010的数据 就报一次1。因我也是个初学者,这样用位移寄存器的思路是怎么样的呢~我现在就是先借这个练习一下状态机~
恩,谢谢大大!我有种豁然开朗的感觉,谢谢你!
只用state,不用nextstate,应该没有问题的。
用你的代码仿真了一下
代码改了一下, 把nextstate去掉了.
在modelsim 10.1a se 下仿真
结果正确
用移位寄存器会比较简单,可以尝试一下。
恩,我试着用不同的方法写一下!谢谢你
额,,其实你们说用位移寄存器写,我头脑中都没有思路该如何利用位移寄存器。新手慢慢学的过程中··用移位寄存器的大概思路是咋样的呢?
建议你分清组合逻辑和时序逻辑以及代码和电路的对应关系,如果这些都清楚了的话,modelsim是可以跟踪每一个信号的,什么时候应该输出啥,结果输出啥也就一目了然了
状态转移的时候要看原来的状态state跟输入x,always(*)即always(state or x) state改变或者x改变都能触发,然后产生下一状态
