目录
三段式状态机
第一段(第一个进程)
always @(posedge clk or negedge rst_n) begin
if (rst_n == 0)
state_c <= IDLE;
else
state_c <= state_n;
end
第二段
always @(*) begin
case (state_c)
IDLE :begin
if (idl2s1_start == 1)
state_n = S1;
esle if (idl2s2_start ==1)
state_n = S2;
else
state_n = state_c;
end
S1 :begin
if (s12s2_start == 1)
state_n = S2;
else
state_n = state_c;
end
S2 :begin
if (s22s3_start == 1)
state_n = S3;
else
state_n = state_c;
end
default:begin
state_n = state_c;
end
endcase
end
assign idl2s1_start = (state_c == IDLE)&& ;
assign idl2s2_start = (state_c == IDLE)&& ;
assign s12s2_start = (state_c == S1)&& ;
assign s22s3_start = (state_c == S2)&& ;
state_n <= state_c作用是状态保持不变且不会生成锁存器。
第三段
always @(posedge clk or negedge rst_n) begin
if (rst_n == 0)
out <= 0;
else if (state_n == s1)
out <= 1;
else
out <= 0;
end
根据状态选择输出。(利用state_n输出)
两段式状态机
第一段(第二进程)
always @(posedge clk or negedge rst_n) begin
if (rst_n == 0)
state_c <= IDLE;
else
state_c <= state_n;
end
第二段(第一进程)
always @(*) begin
case (state_c)
IDLE :begin
IDLE_out;
if (idl2s1_start == 1)
state_n <= S1;
else
state_n <= state_c;
end
S1 :begin
S1_out;
if (s12s2_start == 1)
state_n <= S2;
else
state_n <= state_c;
end
S2 :begin
S2_out;
if (s22s3_start == 1)
state_n <= S3;
else
state_n <= state_c;
end
default:begin
default_out;
state_n <= state_c;
end
endcase
end
task IDLE_out;
out=1;
endtask
task S1_out;
out=0;
endtask
task S2_out;
out=1;
endtask
task default_out;
out=0;
endtask
assign idl2s1_start = (state_c == IDLE)&& ;
assign s12s2_start = (state_c == s1)&& ;
assign s22s3_start = (state_c == s2)&& ;
相比较三段式out的输出也采用了组合逻辑。(利用state_c输出)
两段式FSM描述方法弱点其输出一般使用组合逻辑描述,而组合逻辑易产生毛刺等不稳定因素。
两段式FSM描述方法FSM 的组合逻辑输出如果时序允许插入一个额外的时钟节拍寄存器寄存一个节拍有效地消除毛刺。
如果设计并不允许额外的节拍插入就使用三段式FSM描述方法。
两段式建模和三段式建模的关系
两段式建模:用状态寄存器分割了两部分组合逻辑,状态转移条件组合逻辑,输出组合逻辑,电路时序路径较短,可以获得较高的性能;
三段式建模 :从输入到寄存器状态输出的路径上要经过两部分组合逻辑,状态转移条件组合逻辑,输出组合逻辑,从时序上,这两部分组合逻辑完全可以看为一体这条路径的组合逻辑就比较繁杂,该路径的时序相对紧张
两段式计数器
always @(posedge clk or negedge rst_n) begin
if (rst_n == 1)begin
cnt <= 0;
end
else if (add_cnt) begin
if (end_cnt == 1) begin
cnt <= 0;
end
else
cnt <= cnt+1;
end
else
cnt <= cnt;
end
assign add_cnt = ();
assign end_cnt = add_cnt&&(cnt == y-1);