Consider a finite state machine with inputs s and w. Assume that the FSM begins in a reset state called A, as depicted below. The FSM remains in state A as long as s = 0, and it moves to state B when s = 1. Once in state B the FSM examines the value of the input w in the next three clock cycles. If w = 1 in exactly two of these clock cycles, then the FSM has to set an output z to 1 in the following clock cycle. Otherwise z has to be 0. The FSM continues checking w for the next three clock cycles, and so on. The timing diagram below illustrates the required values of z for different values of w.
Use as few states as possible. Note that the s input is used only in state A, so you need to consider just the w input.
當s為0時,進入B狀態,然後會檢查w的值,如果在接下來的三個週期中w值有兩個週期都為1,那麼z輸出1,否則z輸出0。注意,這裡隱含的條件是不重疊檢測,意味著每三個週期檢查一次,週期與週期之間不重疊。
首先,我按照題目中給出的狀態轉移圖寫了基礎的狀態機模組;接著,用一個計數器進行計數,在狀態B時,counter計數三次清零,然後迴圈;然後,我使用了類似邊沿檢測的方法,將w打了兩拍,判定條件為三拍中兩拍為高,如果滿足條件,z輸出1,否則輸出0。
初始狀態為A,當檢測到s=1時,則跳轉到B狀態。進入B狀態後,3個週期為一個迴圈,在3個週期中檢測到兩次w=1,則在第三個週期輸出z=1,其他時候輸出z=0。
module top_module (
input clk,
input reset, // Synchronous reset
input s,
input w,
output z
);
parameter A = 1'b0, B = 1'b1;
reg current_state;
reg next_state;
always@(posedge clk)begin
if(reset)begin
current_state <= A;
end
else begin
current_state <= next_state;
end
end
always@(*)begin
case(current_state)
A:begin
next_state = s ? B : A;
end
B:begin
next_state = B;
end
endcase
end
reg w_reg1;
reg w_reg2;
always@(posedge clk)begin
if(reset)begin
w_reg1 <= 1'b0;
w_reg2 <= 1'b0;
end
else if(next_state == B)begin
w_reg1 <= w;
w_reg2 <= w_reg1;
end
else begin
w_reg1 <= 1'b0;
w_reg2 <= 1'b0;
end
end
always@(posedge clk)begin
if(reset)begin
z <= 1'b0;
end
else if(current_state == B && counter == 2'd0)begin
if(~w & w_reg1 & w_reg2 | w & ~w_reg1 & w_reg2 | w & w_reg1 & ~w_reg2)begin //3個週期為一個迴圈,在3個週期中檢測到兩次w=1,則在第三個週期輸出z=1,其他時候輸出z=0。
z <= 1'b1;
end
else begin
z <= 1'b0;
end
end
else begin
z <= 1'b0;
end
end
reg [1:0] counter;
always@(posedge clk)begin
if(reset)begin
counter <= 2'd0;
end
else if(counter == 2'd2)begin
counter <= 2'd0;
end
else if(next_state == B)begin
counter <= counter + 1'b1;
end
end
endmodule
module top_module (
input clk,
input reset, // Synchronous reset
input s,
input w,
output z
);
parameter [1:0] A = 2'b01;
parameter [1:0] B = 2'b10;
reg [1:0] cs, ns;
always @(posedge clk)begin
if(reset)
cs <= A;
else
cs <= ns;
end
always @(*)begin
ns = A;
case(cs)
A: ns = s? B:A;
B: ns = B;
default: ns = A;
endcase
end
reg [1:0] cnt,cnt_w;
wire add_cnt,end_cnt;
always @(posedge clk)begin
if(reset)begin
cnt <= 2;
cnt_w <= 0;
end
else if(add_cnt)begin
if(end_cnt)begin
cnt <= 0;
cnt_w <= w;
end
else begin
cnt <= cnt + 1;
cnt_w <= cnt_w + w;
end
end
end
assign add_cnt = (cs==B);
assign end_cnt = add_cnt && (cnt==2);
assign z = end_cnt && (cnt_w==2);
endmodule
沒有留言:
張貼留言