FPGA實現資料的串列埠接收

2021-09-26 13:37:51 字數 3286 閱讀 8502

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標...