module uart_rx(
input clk_50m,
input rst_n,
input data_in,
output reg[7:0] rx_data,
output reg rx_done
);localparam
clk_frequency = 50_000_000,
baud_rate = 9600,
bps_cnt = clk_frequency / baud_rate;
wire start_flag;
reg rx_d0;
reg rx_d1;
reg rx_flag;
reg[15:0] clk_cnt;
reg bps_clk;
reg[ 3:0] baud_cnt;
reg[ 7:0] data_buff;
//通過檢測下降沿判斷起始位,空閒時資料線為高電平,起始位為低電平
assign start_flag = ( !rx_d0 ) & rx_d1;
always @ ( posedge clk_50m or negedge rst_n ) begin
if( !rst_n ) begin
rx_d0 <= 1'b0;
rx_d1 <= 1'b0;
endelse begin
rx_d0 <= data_in;
rx_d1 <= rx_d0;
endend//產生接收標誌位
always @ ( posedge clk_50m or negedge rst_n ) begin
if( !rst_n )
rx_flag <= 1'b0;
else if( start_flag )
rx_flag <= 1'b1;
else if( (baud_cnt == 4'd10) && ( clk_cnt == bps_cnt / 2) )//這裡為什麼不能寫else if( baud_cnt == 4'd10 )?
rx_flag <= 1'b0;
else
rx_flag <= rx_flag;
end//係數時鐘計數
always @ ( posedge clk_50m or negedge rst_n ) begin
if( !rst_n )
clk_cnt <= 16'd0;
else if( rx_flag ) begin
if( clk_cnt < bps_cnt )
clk_cnt <= clk_cnt + 1'b1;
else
clk_cnt <= 16'd0;
endelse
clk_cnt <= 16'd0;
end//產生波特率時鐘
always @ ( posedge clk_50m or negedge rst_n ) begin
if( !rst_n )
bps_clk <= 1'b0;
else if( rx_flag ) begin
if( clk_cnt == 16'd1 ) //這裡可以是0~bps_cnt任意乙個數,但是為了減少延時,選擇16'd1
bps_clk <= 1'b1;
else
bps_clk <= 1'b0;
endelse
bps_clk <= 1'b0;
end//對波特率時鐘計數
always @ ( posedge clk_50m or negedge rst_n ) begin
if( !rst_n )
baud_cnt <= 4'd0;
else if( bps_clk )
baud_cnt <= baud_cnt + 1'b1;
else if( baud_cnt == 4'd11)
baud_cnt <= 4'd1; //這裡不能寫baud_cnt <= 4'd0;否則導致資料位和baud_cnt位置出錯,從而接收不正確
else
baud_cnt <= baud_cnt;
end//接收資料並快取
always @ ( posedge clk_50m or negedge rst_n ) begin
if( !rst_n )
data_buff <= 8'd0;
else if( rx_flag ) begin
if( clk_cnt == bps_cnt / 2 ) //每個波特率時鐘中間獲取資料,確保資料準確
case( baud_cnt )
4'd2 : data_buff[0] <= data_in; //其中baud_cnt=4』d1對應著起始位,也就是1'd0
4'd3 : data_buff[1] <= data_in;
4'd4 : data_buff[2] <= data_in;
4'd5 : data_buff[3] <= data_in;
4'd6 : data_buff[4] <= data_in;
4'd7 : data_buff[5] <= data_in;
4'd8 : data_buff[6] <= data_in;
4'd9 : data_buff[7] <= data_in;
default : ;
endcase
else
data_buff <= data_buff;
endelse
data_buff <= 8'd0;
end//資料快取輸出
always @ ( posedge clk_50m or negedge rst_n )
if(!rst_n)
rx_data <= 8'd0;
else if(baud_cnt == 4'd10) //
rx_data <= data_buff;
else
rx_data <= rx_data;
//接收完成標誌位輸出
always @ ( posedge clk_50m or negedge rst_n )
if(!rst_n)
rx_done <= 1'b0;
else if( baud_cnt == 4'd10 )
rx_done <= 1'b1;
else
rx_done <= 1'b0;
endmodule
FPGA 串列埠接收不準確,有誤碼
協議 1位起始位,8位資料位,1位停止位 fpga的串列埠接收設計,由於 在串列埠傳輸8bit資料時需要10bit 才可以,在接收bit位時,將8bit資料接收完成後,還有1bit 的停止位,如果在接收時嚴格的等待結束位完成之後再去檢測起始位的下降沿,或者是檢測起始位的開始位,在這種情況下 如果傳送...
串列埠資料接收處理
串列埠接收函式只需要管理資料的接收就行了,不必管理相應資料接收的是什麼,還有順序對不對,真正尋找資料的地方是在資料處理的地方。void usart2 irqhandler void 資料處理端,函式來自於onenet麒麟板程式 if dataptr null num atoi const char ...
arduino串列埠接收資料報 串列埠通訊
常見的通訊介面有usart can usb ethernet。最常見 用的最多的就是usart,下面主要對串列埠通訊協議的物理層及協議層進行講解。物理層 串列埠通訊的物理層有很多標準及變種,主要講解rs 232標準,rs 232標準主要規定了訊號的用途 通訊介面以及訊號的電平標準。使用rs 232標...