本题要求完成另一种串行通信协议,该协议每个数据字节都与起始位和停止位一起发送,以帮助接收者从位流中划分字节。具体为使用一个起始位 (0)、8 个数据位和 1 个停止位 (1)。当数据线上没有传输任何内容(空闲)时,默认为高(idle)。
要求设计一个有限状态机。它需要识别起始位,等待所有8个数据位,然后验证停止位是否正确。注意:如果停止位未按预期出现,则 FSM 必须等到找到停止位后再尝试接收下一个字节。
思路:建立一个状态机,初始处在idle状态,当接收到到起始位的时候,开始接收数据,当接收完8个数据之后判断结束位有没有到来,如果到来重新进入idle状态,如果没有到来的话进入error状态,error状态的时候当重新识别到结束位的时候再进入idle 状态,重新同步。
重点:停止位未按照预期到来的时候需要一个额外的状态去重新捕获停止位,而不是直接跳转idle
module top_module(
input clk,
input in,
input reset, // Synchronous reset
output done
);
parameter IDLE = 3'd0;
parameter DATA = 3'd1;
parameter STOP = 3'd2;
parameter ERROR = 3'd3;
reg [2:0] curr_state;
reg [2:0] next_state;
reg [2:0] dat_cnt;
reg done_r1;
wire done_r;
always @(posedge clk) begin
if(reset==1'b1) begin
curr_state <= IDLE;
end
else begin
curr_state <= next_state;
end
end
always @(*) begin
case(curr_state)
IDLE:begin
if(in == 1'b0) begin
next_state = DATA;
end
else begin
next_state = IDLE;
end
end
DATA:begin
if(dat_cnt == 3'd7) begin
next_state = STOP;
end
else begin
next_state = DATA;
end
end
STOP:begin
if( in == 1'b1) begin
next_state = IDLE;
end
else begin
next_state = ERROR;
end
end
ERROR: begin
if( in == 1'b1) begin
next_state = IDLE;
end
else begin
next_state = ERROR;
end
end
default: next_state= IDLE;
endcase
end
always @(posedge clk) begin
if(reset == 1'b1) begin
dat_cnt <= 3'd0;
end
else if(curr_state == DATA) begin
dat_cnt <= dat_cnt + 1'b1;
end
else begin
dat_cnt <= 3'd0;
end
end
always @(posedge clk) begin
if(reset == 1'b1) begin
done_r <= 1'b0;
end
else begin
done_r <= (curr_state == STOP) && (in == 1'b1);
end
end
assign done = done_r;
endmodule