在许多(较旧的)串行通信协议中,每个数据字节都与一个起始位和一个停止位一起发送,以帮助接收器从位流中划定字节。一种常见的方案是使用 1 个起始位 (0)、8 个数据位和 1 个停止位 (1)。当没有传输任何内容(空闲)时,该线路也处于逻辑 1。
设计一个有限状态机,当给定比特流时,它将识别何时正确接收到字节。它需要识别起始位,等待所有 8 个数据位,然后验证停止位是否正确。如果停止位未按预期出现,则 FSM 必须等到找到停止位后再尝试接收下一个字节。
一些时序图
无错误:
未找到停止位。第一个字节被丢弃:
module top_module(
input clk,
input in,
input reset, // Synchronous reset
output done
);
parameter R=4'd0,S0=4'd1,S1=4'd2,S2=4'd3,S3=4'd4,S4=4'd5,S5=4'd6,S6=4'd7,S7=4'd8,S8=4'd9,S9=4'd10,E=4'd11;
reg [3:0]state,next_state,temp_state;
always @(posedge clk) begin
if(reset)
state<=R;
else
state<=next_state;
end
always @(*) begin
case (state)
R:begin
if(in)
next_state<=R;
else
next_state<=S0;
end
S0:next_state<=S1;
S1:next_state<=S2;
S2:next_state<=S3;
S3:next_state<=S4;
S4:next_state<=S5;
S5:next_state<=S6;
S6:next_state<=S7;
S7:next_state<=S8;
S8:begin
if(in)
next_state<=S9;
else
next_state<=E;
end
E:begin
if(in)
next_state<=S9;
else
next_state<=E;
end
S9:begin
if(in)
next_state<=R;
else
next_state<=S0;
end
endcase
end
always@(posedge clk)begin
temp_state<=state;
end
always@(*)begin
if((temp_state==E)&(state==S9))
done=0;
else if(state==S9)
done=1;
else
done=0;
end
endmodule
状态转移没有问题,但输出逻辑总是写不对,在输出逻辑的设计上总是花费很长时间