目录
15.1 Simple FSM 1 (asynchronous reset)
15.2 Simple FSM 1 (synchronous reset)
15.3 Simple FSM 2 (asynchronous reset)
15.4 Simple FSM 2 (synchronous reset)
15.5 Simple state transitions 3
15.6 Simple one-hot state transitions 3
15.7 Simple FSM 3 (asynchronous reset)
15.8 Simple FSM 3 (synchronous reset)
15.16 PS/2 packer parser and datapath
15.18 Serial receiver and datapath
15.19 Serial receiver with parity checking
15.22 Serial two's complementer(Moore FSM)
15.23 Serial two's complementer(Mealy FSM)
15.28 FSM one-hot next-state logic
15 Finite State Machines
15.1 Simple FSM 1 (asynchronous reset)
module top_module (
input clk,
input areset,
input in,
output out
);
parameter A = 1'b0,
B = 1'b1;
reg current_state,next_state;
always @(posedge clk or posedge areset)begin
if(areset)
current_state <= B;
else
current_state <= next_state;
end
always @(*)begin
case(current_state)
B:begin
if(in==1'b1)
next_state <= B;
else
next_state <= A;
end
A:begin
if(in==1'b1)
next_state <= A;
else
next_state <= B;
end
endcase
end
always @(*)begin
case(current_state)
B:out <= 1'b1;
A:out <= 1'b0;
endcase
end
endmodule
15.2 Simple FSM 1 (synchronous reset)
module top_module (
input clk,
input areset,
input in,
output out
);
parameter A = 1'b0,
B = 1'b1;
reg current_state,next_state;
always @(posedge clk)begin
if(reset)
current_state <= B;
else
current_state <= next_state;
end
always @(*)begin
case(current_state)
B:begin
if(in==1'b1)
next_state <= B;
else
next_state <= A;
end
A:begin
if(in==1'b1)
next_state <= A;
else
next_state <= B;
end
endcase
end
always @(posedge clk)
if(reset)
out <= 1'b1;
else begin
case(next_state)
B:out <= 1'b1;
A:out <= 1'b0;
endcase
end
endmodule
15.3 Simple FSM 2 (asynchronous reset)
module top_module (
input clk,
input areset,
input j,k,
output reg out
);
parameter OFF = 1'b0,
ON = 1'b1;
reg current_state,next_state;
always @(posedge clk or posedge areset)begin
if(areset)
current_state <= OFF;
else
current_state <= next_state;
end
always @(*)begin
case(current_state)
OFF:begin
if(j==1'b0)
next_state <= OFF;
else
next_state <= ON;
end
ON:begin
if(k==1'b0)
next_state <= ON;
else
next_state <= OFF;
end
endcase
end
always @(*)begin
case(current_state)
OFF:out <= 1'b0;
ON :out <= 1'b1;
endcase
end
endmodule
15.4 Simple FSM 2 (synchronous reset)
module top_module (
input clk,
input reset,
input j,k,
output reg out
);
parameter OFF = 1'b0,
ON = 1'b1;
reg current_state,next_state;
always @(posedge clk)begin
if(reset)
current_state <= OFF;
else
current_state <= next_state;
end
always @(*)begin
case(current_state)
OFF:begin
if(j==1'b0)
next_state <= OFF;
else
next_state <= ON;
end
ON:begin
if(k==1'b0)
next_state <= ON;
else
next_state <= OFF;
end
endcase
end
always @(*)begin
case(current_state)
OFF:out <= 1'b0;
ON :out <= 1'b1;
endcase
end
endmodule
15.5 Simple state transitions 3
module top_module (
input in,
input [1:0]state,
output [1:0]next_state,
output out
);
parameter A = 2'b00,
B = 2'b01,
C = 2'b10,
D = 2'b11;
always @(*)begin
case(state)
A:begin
if(in==1'b0)
next_state <= A;
else
next_state <= B;
end
B:begin
if(in==1'b0)
next_state <= C;
else
next_state <= B;
end
C:begin
if(in==1'b0)
next_state <= A;
else
next_state <= D;
end
D:begin
if(in==1'b0)
next_state <= C;
else
next_state <= B;
end
endcase
end
always @(*)begin
case(state)
A:out <= 1'b0;
B:out <= 1'b0;
C:out <= 1'b0;
D:out <= 1'b1;
endcase
end
endmodule
15.6 Simple one-hot state transitions 3
module top_module (
input in,
input [3:0]state,
output [3:0]next_state,
output out
);
parameter A = 2'b00,
B = 2'b01,
C = 2'b10,
D = 2'b11;
assign next_state[A]= state[A] & (~in) | state[C] &(~in);
assign next_state[B]= state[B] & in | state[D] & in | state[A] & in;
assign next_state[C]= state[B] & (~in) | state[D] & (~in);
assign next_state[D]= state[C] & in;
assign out = state[3];
endmodule
15.7 Simple FSM 3 (asynchronous reset)
module top_module (
input in,
input clk,
input areset,
output out
);
parameter A = 2'b00,
B = 2'b01,
C = 2'b10,
D = 2'b11;
reg [1:0]current_state,next_state;
always @(posedge clk or posedge areset)
if(areset)
current_state <= A;
else
current_state <= next_state;
always @(*)begin
case(current_state)
A:begin
if(in==1'b0)
next_state <= A;
else
next_state <= B;
end
B:begin
if(in==1'b0)
next_state <= C;
else
next_state <= B;
end
C:begin
if(in==1'b0)
next_state <= A;
else
next_state <= D;
end
D:begin
if(in==1'b0)
next_state <= C;
else
next_state <= B;
end
endcase
end
always@(*)begin
case(current_state)
A:out <= 1'b0;
B:out <= 1'b0;
C:out <= 1'b0;
D:out <= 1'b1;
endcase
end
endmodule
15.8 Simple FSM 3 (synchronous reset)
module top_module (
input in,
input clk,
input reset,
output out
);
parameter A = 2'b00,
B = 2'b01,
C = 2'b10,
D = 2'b11;
reg [1:0]current_state,next_state;
always @(posedge clk)
if(reset)
current_state <= A;
else
current_state <= next_state;
always @(*)begin
case(current_state)
A:begin
if(in==1'b0)
next_state <= A;
else
next_state <= B;
end
B:begin
if(in==1'b0)
next_state <= C;
else
next_state <= B;
end
C:begin
if(in==1'b0)
next_state <= A;
else
next_state <= D;
end
D:begin
if(in==1'b0)
next_state <= C;
else
next_state <= B;
end
endcase
end
always@(*)begin
case(current_state)
A:out <= 1'b0;
B:out <= 1'b0;
C:out <= 1'b0;
D:out <= 1'b1;
endcase
end
endmodule
15.9 Design a Moore FSM
module top_module (
input clk,
input reset,
input [3:1]s,
output fr3,
output fr2,
output fr1,
output dfr
);
parameter A = 2'b00,
B = 2'b01,
C = 2'b10,
D = 2'b11;
reg [1:0]current_state,next_state;
always @(posedge clk)
if(reset)
current_state <= 2'b0;
else
current_state <= next_state;
always @(*)begin
case(current_state)
A:begin
case(s)
3'b001:next_state <= B;
3'b011:next_state <= C;
3'b111:next_state <= D;
default : next_state <= A;
endcase
end
B:begin
case(s)
3'b001:next_state <= B;
3'b011:next_state <= C;
3'b111:next_state <= D;
default : next_state <= A;
endcase
end
C:begin
case(s)
3'b001:next_state <= B;
3'b011:next_state <= C;
3'b111:next_state <= D;
default : next_state <= A;
endcase
end
D:begin
case(s)
3'b001:next_state <= B;
3'b011:next_state <= C;
3'b111:next_state <= D;
default : next_state <= A;
endcase
end
default :next_state <= A;
endcase
end
always@(*)begin
case(current_state)
A:{fr1,fr2,fr3} <= 3'b111;
B:{fr1,fr2,fr3} <= 3'b110;
C:{fr1,fr2,fr3} <= 3'b100;
D:{fr1,fr2,fr3} <= 3'b000;
default:{fr1,fr2,fr3} <= 3'b0;
endcase
end
always@(posedge clk)begin
if(reset)
dfr <= 1'b1;
else if(next_state < current_state)
dfr <= 1'b1;
else if(next_state > current_state)
dfr <= 1'b0;
else
dfr <=dfr;
end
endmodule
15.10 Lemmings 1
module top_module (
input clk,
input areset,
input bump_left,
input bump_right,
output walk_left,
output walk_right
);
reg current_state,next_state;
parameter W_L = 1'b0,
W_R = 1'b1;
always @(posedge clk or posedge areset)begin
if(areset)
current_state <= W_L;
else
current_state <= next_state;
end
always @(*)begin
case(current_state)
W_L:begin
if(bump_left)
next_state <= W_R;
else
next_state <= W_L;
end
W_R:begin
if(bump_right)
next_state <= W_L;
else
next_state <= W_R;
end
endcase
end
always @(*)begin
case(current_state)
W_L : begin
walk_left <= 1'b1;
walk_right <= 1'b0;
end
W_R : begin
walk_left <= 1'b0;
walk_right <= 1'b1;
end
endcase
end
endmodule
15.11 Lemmings 2
module top_module (
input clk,
input areset,
input bump_left,
input bump_right,
input ground,
output walk_left,
output walk_right,
output aaah
);
reg [1:0]current_state,next_state;
parameter W_L = 2'b00,
W_R = 2'b01,
G_L = 2'b10,
G_R = 2'b11;
always @(posedge clk or posedge areset)begin
if(areset)
current_state <= W_L;
else
current_state <= next_state;
end
always @(*)begin
case(current_state)
W_L:begin
if(ground)begin
if(bump_left)
next_state <= W_R;
else
next_state <= W_L;
end
else
next_state <= G_L;
end
W_R:begin
if(ground)begin
if(bump_right)
next_state <= W_L;
else
next_state <= W_R;
end
else
next_state <= G_R;
end
G_L:begin
if(ground)
next_state <= W_L;
else
next_state <= G_L;
end
G_R:begin
if(ground)
next_state <= W_R;
else
next_state <= G_R;
end
//default : next_state <= W_L;
endcase
end
always @(posedge clk or posedge areset)
if(areset)
aaah <= 1'b0;
else if(!ground)
aaah <= 1'b1;
else
aaah <= 1'b0;
always @(*)begin
case(current_state)
W_L : begin
walk_left <= 1'b1;
walk_right <= 1'b0;
end
W_R : begin
walk_left <= 1'b0;
walk_right <= 1'b1;
end
default : begin
walk_left <= 1'b0;
walk_right <= 1'b0;
end
endcase
end
endmodule
15.12 Lemmings 3
module top_module (
input clk,
input areset,
input bump_left,
input bump_right,
input ground,
input dig,
output walk_left,
output walk_right,
output aaah,
output digging
);
reg [5:0]current_state,next_state;
parameter W_L = 6'b000001,
W_R = 6'b000010,
G_L = 6'b000100,
G_R = 6'b001000,
D_L = 6'b010000,
D_R = 6'b100000;
always @(posedge clk or posedge areset)begin
if(areset)
current_state <= W_L;
else
current_state <= next_state;
end
always @(*)begin
case(current_state)
W_L:begin
if(ground)begin
if(!dig)begin
if(bump_left)
next_state <= W_R;
else
next_state <= W_L;
end
else
next_state <= D_L;
end
else
next_state <= G_L;
end
W_R:begin
if(ground)begin
if(!dig)begin
if(bump_right)
next_state <= W_L;
else
next_state <= W_R;
end
else
next_state <= D_R;
end
else
next_state <= G_R;
end
G_L:begin
if(ground)
next_state <= W_L;
else
next_state <= current_state;
end
G_R:begin
if(ground)
next_state <= W_R;
else
next_state <= current_state;
end
D_L:begin
if(ground)
next_state <= current_state;
else
next_state <= G_L;
end
D_R:begin
if(ground)
next_state <= current_state;
else
next_state <= G_R;
end
default : next_state <= W_L;
endcase
end
always @(posedge clk or posedge areset)begin
if(areset)
aaah <= 1'b0;
else if(!ground)
aaah <= 1'b1;
else
aaah <= 1'b0;
end
always @(*)begin
case(current_state)
W_L : begin
walk_left <= 1'b1;
walk_right <= 1'b0;
digging <= 1'b0;
end
W_R : begin
walk_left <= 1'b0;
walk_right <= 1'b1;
digging <= 1'b0;
end
D_L : begin
walk_left <= 1'b0;
walk_right <= 1'b0;
digging <= 1'b1;
end
D_R : begin
walk_left <= 1'b0;
walk_right <= 1'b0;
digging <= 1'b1;
end
default : begin
walk_left <= 1'b0;
walk_right <= 1'b0;
digging <= 1'b0;
end
endcase
end
endmodule
15.13 Lemmings 4
module top_module (
input clk,
input areset,
input bump_left,
input bump_right,
input ground,
input dig,
output walk_left,
output walk_right,
output aaah,
output digging
);
reg [8:0]current_state,next_state;
parameter W_L = 8'b0000_0001,
W_R = 8'b0000_0010,
G_L = 8'b0000_0100,
G_R = 8'b0000_1000,
D_L = 8'b0001_0000,
D_R = 8'b0010_0000,
SPLATTER = 8'b0100_0000,
A_H = 8'b1000_0000;
reg [5:0]cnt;
always @(posedge clk or posedge areset)begin
if(areset)
cnt <= 6'b0;
else if(next_state == G_L || next_state == G_R)
cnt <= cnt+1'b1;
else
cnt <= 6'b0;
end
always @(posedge clk or posedge areset)begin
if(areset)
current_state <= W_L;
else
current_state <= next_state;
end
always @(*)begin
case(current_state)
W_L:begin
if(ground)begin
if(!dig)begin
if(bump_left)
next_state <= W_R;
else
next_state <= W_L;
end
else
next_state <= D_L;
end
else
next_state <= G_L;
end
W_R:begin
if(ground)begin
if(!dig)begin
if(bump_right)
next_state <= W_L;
else
next_state <= W_R;
end
else
next_state <= D_R;
end
else
next_state <= G_R;
end
G_L:begin
if(ground)
next_state <= W_L;
else if(cnt == 6'd20)
next_state <= SPLATTER;
else
next_state <= current_state;
end
G_R:begin
if(ground)
next_state <= W_R;
else if(cnt == 6'd20)
next_state <= SPLATTER;
else
next_state <= current_state;
end
D_L:begin
if(ground)
next_state <= current_state;
else
next_state <= G_L;
end
D_R:begin
if(ground)
next_state <= current_state;
else
next_state <= G_R;
end
SPLATTER : begin
if(ground)
next_state <= A_H;
else
next_state <= current_state;
end
A_H : begin
next_state <= A_H;
end
default : next_state <= W_L;
endcase
end
always @(*)begin
case(current_state)
W_L : begin
walk_left <= 1'b1;
walk_right <= 1'b0;
aaah <= 1'b0;
digging <= 1'b0;
end
W_R : begin
walk_left <= 1'b0;
walk_right <= 1'b1;
aaah <= 1'b0;
digging <= 1'b0;
end
G_L : begin
walk_left <= 1'b0;
walk_right <= 1'b0;
aaah <= 1'b1;
digging <= 1'b0;
end
G_R : begin
walk_left <= 1'b0;
walk_right <= 1'b0;
aaah <= 1'b1;
digging <= 1'b0;
end
D_L : begin
walk_left <= 1'b0;
walk_right <= 1'b0;
aaah <= 1'b0;
digging <= 1'b1;
end
D_R : begin
walk_left <= 1'b0;
walk_right <= 1'b0;
aaah <= 1'b0;
digging <= 1'b1;
end
SPLATTER : begin
walk_left <= 1'b0;
walk_right <= 1'b0;
aaah <= 1'b1;
digging <= 1'b0;
end
default : begin
walk_left <= 1'b0;
walk_right <= 1'b0;
aaah <= 1'b0;
digging <= 1'b0;
end
endcase
end
endmodule
15.14 One-hot FSM
module top_module (
input in,
input [9:0]state,
output [9:0]next_state,
output out1,
output out2
);
parameter S0 = 4'd0,
S1 = 4'd1,
S2 = 4'd2,
S3 = 4'd3,
S4 = 4'd4,
S5 = 4'd5,
S6 = 4'd6,
S7 = 4'd7,
S8 = 4'd8,
S9 = 4'd9;
assign next_state[S0] = (state[S0] | state[S1] | state[S2] | state[S3] | state[S4] | state[S7] | state[S8] | state[S9]) & (~in);
assign next_state[S1] = (state[S0] | state[S8] | state[S9]) & in;
assign next_state[S2] = state[S1] & in;
assign next_state[S3] = state[S2] & in;
assign next_state[S4] = state[S3] & in;
assign next_state[S5] = state[S4] & in;
assign next_state[S6] = state[S5] & in;
assign next_state[S7] = (state[S6] | state[7]) & in;
assign next_state[S8] = state[S5] & (~in);
assign next_state[S9] = state[S6] & (~in);
assign out1 = state[S8] | state[S9];
assign out2 = state[S9] | state[S7];
endmodule
15.15 PS/2 packer parser
module top_module (
input clk,
input [7:0]in,
input reset,
output done
);
parameter S1 = 4'b0001, //bit3
S2 = 4'b0010, //bit2
S3 = 4'b0100, //bit1
S4 = 4'b1000; //传输完成
reg [3:0]current_state,next_state;
always @(posedge clk)begin
if(reset)
current_state <= S1;
else
current_state <= next_state;
end
always@(*)begin
case(current_state)
S1:begin
if(in[3])
next_state <= S2;
else
next_state <= S1;
end
S2:begin
next_state <= S3;
end
S3:begin
next_state <= S4;
end
S4:begin
if(in[3])
next_state <= S2;
else
next_state <= S1;
end
default : next_state <= S1;
endcase
end
assign done = (current_state == S4);
endmodule
15.16 PS/2 packer parser and datapath
module top_module (
input clk,
input [7:0]in,
input reset,
output [23:0]out_bytes,
output done
);
parameter S1 = 4'b0001, //bit3
S2 = 4'b0010, //bit2
S3 = 4'b0100, //bit1
S4 = 4'b1000; //传输完成
reg [3:0]current_state,next_state;
always @(posedge clk)begin
if(reset)
current_state <= S1;
else
current_state <= next_state;
end
always@(*)begin
case(current_state)
S1:begin
if(in[3])
next_state <= S2;
else
next_state <= S1;
end
S2:begin
next_state <= S3;
end
S3:begin
next_state <= S4;
end
S4:begin
if(in[3])
next_state <= S2;
else
next_state <= S1;
end
default : next_state <= S1;
endcase
end
assign done = (current_state == S4);
always @(posedge clk)
if(reset)
out_bytes <= 24'd0;
else
out_bytes <= {out_bytes[15:0],in};
endmodule
15.17 Serial receiver
module top_module (
input clk,
input in,
input reset,
output done
);
parameter START = 5'd0,
BIT1 = 5'd1,
BIT2 = 5'd2,
BIT3 = 5'd3,
BIT4 = 5'd4,
BIT5 = 5'd5,
BIT6 = 5'd6,
BIT7 = 5'd7,
BIT8 = 5'd8,
END = 5'd9,
DONE = 5'd10,
WAIT = 5'd11;
reg [4:0]current_state,next_state;
always @(posedge clk)begin
if(reset)
current_state <= START;
else
current_state <= next_state;
end
always@(*)begin
case(current_state)
START : begin
if(!in)
next_state <= BIT1;
else
next_state <= START;
end
BIT1 : begin
next_state <= BIT2;
end
BIT2 : begin
next_state <= BIT3;
end
BIT3 : begin
next_state <= BIT4;
end
BIT4 : begin
next_state <= BIT5;
end
BIT5 : begin
next_state <= BIT6;
end
BIT6 : begin
next_state <= BIT7;
end
BIT7 : begin
next_state <= BIT8;
end
BIT8 : begin
next_state <= END;
end
END : begin
if(in)
next_state <= DONE;
else
next_state <= WAIT;
end
DONE : begin
if(in)
next_state <= START;
else
next_state <= BIT1;
end
WAIT : begin
if(in)
next_state <= START;
else
next_state <= WAIT;
end
default next_state <= START;
endcase
end
assign done = (current_state == DONE);
endmodule
15.18 Serial receiver and datapath
module top_module (
input clk,
input in,
input reset,
output done,
output [7:0]out_byte
);
parameter START = 5'd0,
BIT1 = 5'd1,
BIT2 = 5'd2,
BIT3 = 5'd3,
BIT4 = 5'd4,
BIT5 = 5'd5,
BIT6 = 5'd6,
BIT7 = 5'd7,
BIT8 = 5'd8,
END = 5'd9,
DONE = 5'd10,
WAIT = 5'd11;
reg [4:0]current_state,next_state;
reg [7:0]r_out_byte;
always @(posedge clk)begin
if(reset)
current_state <= START;
else
current_state <= next_state;
end
always@(*)begin
case(current_state)
START : begin
if(!in)
next_state <= BIT1;
else
next_state <= START;
end
BIT1 : begin
next_state <= BIT2;
r_out_byte[0] <= in;
end
BIT2 : begin
next_state <= BIT3;
r_out_byte[1] <= in;
end
BIT3 : begin
next_state <= BIT4;
r_out_byte[2] <= in;
end
BIT4 : begin
next_state <= BIT5;
r_out_byte[3] <= in;
end
BIT5 : begin
next_state <= BIT6;
r_out_byte[4] <= in;
end
BIT6 : begin
next_state <= BIT7;
r_out_byte[5] <= in;
end
BIT7 : begin
next_state <= BIT8;
r_out_byte[6] <= in;
end
BIT8 : begin
next_state <= END;
r_out_byte[7] <= in;
end
END : begin
if(in)
next_state <= DONE;
else
next_state <= WAIT;
end
DONE : begin
if(in)
next_state <= START;
else
next_state <= BIT1;
end
WAIT : begin
if(in)
next_state <= START;
else
next_state <= WAIT;
end
default next_state <= START;
endcase
end
assign done = (current_state == DONE);
assign out_byte = (current_state==DONE) ? r_out_byte : 8'b0
endmodule