本帖最后由 fpgaw 于 2010-11-19 06:38 编辑
在《设计与验证--Verilog HDL》一书中写到:三段式建模描述FSM的状态机输出时,只需指定case敏感表为次态寄存器,然后直接在每个次态的case分支中描述该状态的输出即可,根本不用考虑状态转移条件。
我的问题是:有的情况下状态的输出不是唯一的,要根据该状态当前的输入,那么在判断下一状态的输出要根据下一状态的输入,但在当前前状态不能够预先知道下一状态的输入。还有,书中的例子为什么说是米勒型的,而不是摩尔型?因为为每个状态的输出都是预先知道的。但如果输出要根据输入判断呢?书中例子的输出是这样的:(即westor兄上传得《 第6章 如何写好状态机》中)
//3rd always block, the sequential FSM output
always @ (posedge clk or negedge nrst)
if (!nrst)
{o1,o2,err} <= 3'b000;
else
begin
{o1,o2,err} <= 3'b000;
case (NS)
IDLE: {o1,o2,err}<=3'b000;
S1: {o1,o2,err}<=3'b100;
S2: {o1,o2,err}<=3'b010;
ERROR: {o1,o2,err}<=3'b111;
endcase
end
另外,在《Verilog HDL高级数字设计中》有一个串并转换的例子:
module serial_to_parallel(done,dout,din,start,clk,rst);
output[3:0] dout;
output done;
input din,start,clk,rst;
reg [3:0] dout;
parameter s0=0,s1=1;
reg NS,CS;
reg shift,inc;
reg[1:0] cnt;
wire done=(cnt==3);
always@(posedge clk or posedge rst )
if(rst) CS<=s0;
else CS<=NS;
always@(CS or start or done)
begin
NS=s0;shift=0;inc=0;
case(CS)
s0: if(start) begin NS=s1;shift=1;end
s1: if(!done)begin shift=1;inc=1;NS=s1;end
else if(start) begin shift=1;inc=1;NS=s1;end
else begin NS=s0;inc=1;end
default:NS=s0;
endcase
end
always@(posedge clk or posedge rst)
if(rst) begincnt<=0;dout<=1;end
else begin
if(inc) cnt<=cnt+1;
if(shift) dout<={din,dout[3:1]};
end
endmodule
这个例子是两段式的,怎么改写成书中推荐的三段式?状态s1的输出要根据当前的done 和start判断。
还有就是状态转移中如: s0:if(start) begin NS=s1;shift=1;end
是否有必要加上 else NS=s0;来强调完备性? 即若当前状态不改变用不再加一句来保证该状态不变呢?若不加,如我在s1中没有指明 s1:if(!done) NS=s1;在modelsim中会有问题。 |