题目
地址:HDLBits-Exams/2013 q2bfsm
介绍:花了好长时间写的,可惜还是没想出来如何减去最后一个状态E的使用。
更新:状态图画得不好,导致用来打拍的寄存器量加起来比用来表示多个状态的寄存器变量还要多。具体状态图可以参考别人的做法。
代码
module top_module (
input clk,
input resetn, // active-low synchronous reset
input x,
input y,
output f,
output g
);
localparam [2:0] A=3'b000,B=3'b001,C=3'b010,D=3'b011,E=3'b100;
reg [2:0] current_state,next_state;
reg rst_flag1;
// rst_flag1 states that last cycle is reset cycle;
// state transition logic
always @(*) begin
case (current_state)
A: next_state = x?B:A; // ready to detect x
B: next_state = x?B:C; // get 1
C: next_state = x?D:A; // get 10
D: next_state = E; // get 101
E: next_state = E; // already get 101
default: next_state = A;
endcase
end
always @(posedge clk) begin
if (~resetn) begin
rst_flag1 <= 1'b1;
end
else begin
rst_flag1 <= 1'b0;
end
end
always @(posedge clk) begin
if (~resetn) begin
current_state <= A;
end
else if (rst_flag1|f) begin
current_state <= A;
// state A can detect x only after that output f goes from 1 to 0
end
else begin
current_state <= next_state;
end
end
// output f
always @(posedge clk) begin
if (~resetn)
f <= 1'b0;
else if (rst_flag1) // if last cycle is reset and this not,the next cycle f goes to 1
f <= 1'b1;
else
f <= 1'b0;
end
reg y_flag1,y_flag2; // y_flag1 states the 1st cyle after state D, y_flag2 states the 2nd
always @(posedge clk) begin
if (~resetn) begin
y_flag1 <= 1'b0;
end
else if (next_state==D)
y_flag1 <= 1'b1;
else
y_flag1 <= 1'b0;
end
always @(posedge clk) begin
if (~resetn)
y_flag2 <= 1'b0;
else if (y_flag1)
y_flag2 <= 1'b1;
else
y_flag2 <= 1'b0;
end
reg flag_1, flag_0; // flag_1 states the g=1 permenantly, flag_0 state g=0 permenantly
always @(posedge clk) begin
if (~resetn) begin
flag_1 <= 1'b0;
flag_0 <= 1'b0;
end
else begin
if ((y_flag1||y_flag2)&&y)
flag_1 <= 1'b1;
else if (~flag_1&&y_flag2&&~y)
flag_0 <= 1'b1;
else begin
flag_1 <= flag_1;
flag_0 <= flag_0;
end
end
end
always @(posedge clk) begin
if (~resetn)
g <= 1'b0;
// flag_1 will not be 1 if first y is 0, so need to add (y_flag2&&y)
// next_state==D,g=1 and will keep for two cycles
else if (next_state==D|flag_1|y_flag1|(y_flag2&&y))
g <= 1'b1;
else if (flag_0)
g <= 1'b0;
else
g <= 1'b0;
end
endmodule