1、在许多(较旧的)串行通信协议中,每个数据字节与一个开始位和一个停止位一起发送,以帮助接收器从比特流中划分字节。一种常见的方案是使用一个起始位(0)、8个数据位和1个停止位(1)。当无任何传输(空闲)时,线路也处于逻辑1。
设计一个有限状态机,当给定一个比特流时,它将识别何时正确接收字节。它需要识别起始位,等待所有8个数据位,然后验证停止位是否正确。如果停止位未按预期出现,FSM必须等待找到停止位,然后再尝试接收下一个字节。
这里我设置了五种状态变化:
(1)默认态idel,in=0时到data,=1时保持 (2)数据输入data,维持8个clk 到stop0(3)停止信号的接收判断态stop0,in=1时到done(接收到停止态,完成输出),=0时到 stop1(继续等待停止信号);(4) 完成态done, in=1时到idel,=0时到data (5)未接收到停止信号时的判断态stop1,in=1时到idel(接收到停止信号,等待开始信号in=0),=0时保持。
这一题想了好久,状态图一定要画出来才明确一些。
module top_module(
input clk,
input in,
input reset, // Synchronous reset
output done
);
reg [2:0] state,next_state;
//一定记得设置足够的位,好几次在修改过程中把bit写小了导致错误
reg [3:0] cout;
parameter idel=0,data=1,stop0=2,stop1=3,done0=4;
always @(*)
begin
case(state)
//五种状态变化:
//(1)默认态idel (2)数据输入data (3)停止信号接收判断态stop0
// (4) 完成态done (5)未接收到停止信号时的判断态stop1
idel : next_state<=(in)? idel:data;
data : next_state<=(cout==4'd7)?stop0:data;
stop0: next_state<=(in)? done0:stop1;
done0: next_state <= (!in)? data:idel;
stop1: next_state <= (in)? idel:stop1;
endcase
end
always @(posedge clk)
begin
if(reset)
state<=idel;
else
begin
state<=next_state;
if(state==data) cout<=cout+1;
else cout<=0;
end
end
assign done = (state==done0);
//一开始没有设置done0状态,是在state==stop0时为1。但不匹配实际情况,应该是在state==idel且上一状态时stop0时,done=1;(在stop0时,要当in=1才算收到截至信号)
endmodule
折磨了一晚上终于弄明白了/(ㄒoㄒ)/~~