题解 | #根据状态转移写状态机-三段式#
根据状态转移写状态机-三段式
http://www.nowcoder.com/practice/d8394a6d31754e73ace8c394e9465e2a
Tips
注意,新手写三段式的时候第一次会犯的错误就是,在三段式状态机的第二段没有用。记住,是用于组合逻辑,组合逻辑只需要根据模块内的变量综合确定触发条件,不需要根据时钟信号来确定触发条件。
另外,如果第三段基于的是,则输出波形会整体提前一个时钟信号周期,因此必须基于。
Verilog Code
`timescale 1ns/1ns
module fsm1(
input wire clk ,
input wire rst ,
input wire data ,
output reg flag
);
//*************code***********//
//行为描述
reg [1:0] state_cur = 2'b00, state_next = 2'b00;
parameter S0 = 2'b00, S1 = 2'b01, S2 = 2'b10, S3 = 2'b11;
parameter ZERO = 1'b0, ONE = 1'b1;
//状态流转
always @(posedge clk or negedge rst)begin
if(~rst)begin
state_cur <= S0;
end
else begin
state_cur <= state_next;
end
end
//状态切换
always @(*)begin
if(~rst)begin
state_next = S0;
end
else begin
case(state_cur)
S0:begin
if(data == ZERO)begin
state_next = S0;
end
else if(data == ONE)begin
state_next = S1;
end
end
S1:begin
if(data == ZERO)begin
state_next = S1;
end
else if(data == ONE)begin
state_next = S2;
end
end
S2:begin
if(data == ZERO)begin
state_next = S2;
end
else if(data == ONE)begin
state_next = S3;
end
end
S3:begin
if(data == ZERO)begin
state_next = S3;
end
else if(data == ONE)begin
state_next = S0;
end
end
default:begin
state_next = S0;
end
endcase
end
end
//状态输出
always @(posedge clk or negedge rst)begin
if(~rst)begin
flag <= ZERO;
end
else begin
case(state_cur)
S0:begin
if(data == ZERO)begin
flag <= ZERO;
end
else if(data == ONE)begin
flag <= ZERO;
end
end
S1:begin
if(data == ZERO)begin
flag <= ZERO;
end
else if(data == ONE)begin
flag <= ZERO;
end
end
S2:begin
if(data == ZERO)begin
flag <= ZERO;
end
else if(data == ONE)begin
flag <= ZERO;
end
end
S3:begin
if(data == ZERO)begin
flag <= ZERO;
end
else if(data == ONE)begin
flag <= ONE;
end
end
default:begin
flag <= ZERO;
end
endcase
end
end
//*************code***********//
endmodule
Testbench Code
`timescale 1ns/1ns
module testbench();
reg clk = 1'b1;
always #5 clk = ~clk; // Create clock with period=10
// A testbench
reg rst = 1'b0, data = 1'b0;
wire flag;
fsm1 t(.clk(clk),
.rst(rst),
.data(data),
.flag(flag)
);
initial begin
#10 rst = 1'b1;
#20 data = 1'b1;
#10 data = 1'b0;
#10 data = 1'b1;
#30 data = 1'b0;
#10 data = 1'b1;
#50 data = 1'b0;
#10 data = 1'b1;
#20 data = 1'b0;
#20 $finish();
end
//end
initial begin
$dumpfile("out.vcd");
// This will dump all signal, which may not be useful
//$dumpvars;
// dumping only this module
//$dumpvars(1, testbench);
// dumping only these variable
// the first number (level) is actually useless
$dumpvars(0, testbench);
end
endmodule