关于串口数据接收出错问的问题(RS232、RS422、UART)

这两天调试串口驱动,串口驱动应该是很简单的啊,但是发现数据接收的时候,总是偶尔会出现错误,经过不断的排查,终于找到了问题的关键所在。
一段串口的verilog代码如下:

    module uart_rx(
	input		clk,
	input		uart_rx_i,
	.....
	);
parameter state_idle = 2'b01;
parameter state_data = 2'b10;

reg		uart_rx_i_r;

reg		state;

always @(posedge clk)
	uart_rx_i_r <= uart_rx_i;
......
always @(posedge clk)
....
   if(uart_rx_i_r&! uart_rx_i)//采集串口的下降沿
   	state <= state_data;//当检测到串口的下降沿时,进入数据接收状态
.....
endmodule

如果采样上面的方式对串口数据进行接收,就会发现串口数据总是偶尔出现个别的数据接收出错。通过ila抓波形,发现有如下图一的异常情况出现,这个时候uart_rx_i已经拉低了,但是却没有检测到下降沿,就会导致数据接收出错,这是由于亚稳态所带来的危害,特权同学有一本书里有讲到亚稳态是特别需要注意的。正常的是如下图二的图片所示。

关于串口数据接收出错问的问题(RS232、RS422、UART)_第1张图片

关于串口数据接收出错问的问题(RS232、RS422、UART)_第2张图片

正确的做法应该是将uart_rx_i打两拍再判断下降沿,如下:

   module uart_rx(
	input		clk,
	input		uart_rx_i,
	.....
	);
parameter state_idle = 2'b01;
parameter state_data = 2'b10;

reg		uart_rx_i_r;
reg		uart_rx_i_rr;
reg		uart_rx_i_rrr;

reg		state;

always @(posedge clk) begin 
	uart_rx_i_r  <= uart_rx_i;
	uart_rx_i_rr <= uart_rx_i_r ;
	uart_rx_i_rrr<= uart_rx_i_rr;
end
......
always @(posedge clk)
....
   if(uart_rx_i_rrr&! uart_rx_i_rr)//采集串口的下降沿
   	state <= state_data;//当检测到串口的下降沿时,进入数据接收状态
.....
endmodule

你可能感兴趣的:(付费专栏,uart,rs232,rs422,串口)