FPGA串口数据接收

2015-02-067219
AI 快速预览详细 收起
本文介绍了如何在FPGA中通过虚拟串口实现9600bps波特率的串口数据接收。文章详细讲解了起始位检测、数据采样和停止位处理的具体方法。通过脉冲下降沿检测起始位,并在数据中间位置进行采样,确保数据接收的准确性。这些方法可以帮助你在FPGA项目中实现高效的串口通信。

FPGA由于没有串口,只能通过虚拟串口的方式接收和发送数据。串口数据传输的格式和波特率按照串口通用格式进行时序控制。

     本文以一位起始位,八位数据位,两位停止位的数据11 0 10101100 11传输为例,波特率设定为9600bps。当检测到起始位0,开始依次在数据的中间位置对各位数据进行采样,并依次将采样数据传输给rx_data。

起始位的检测利用脉冲下降沿检测,当检测到脉冲下降沿将neg_rx拉高,并使能数据接收位rx_en,当接收到数据停止位即连续接收11位(1位起始位+8位数据位+2位停止位)后将rx_en拉低,数据接收完毕,依次循环。rx_stop为数据传输结束标志位。

数据接收时序如下图:

FPGA串口数据接收图1

串口接收源代码:

module uart(

                clk,rst_n,

                rx_bit,

                rx_data );

input clk;

input rst_n;

input rx_bit; //串口数据输入

output [7:0]rx_data;

parameter buad_rate = 5207;   //设置波特率为9600

parameter bit_samp = 2603;   //设置数据采样率

reg [12:0]cnt; //时钟计数

always@(posedge clk or negedge rst_n)

begin

    if(!rst_n)

        cnt <= 13'd0;

    else if(rx_en == 1)

    begin

        cnt <= cnt + 1'b1;

       if(cnt == buad_rate)

            cnt <= 13'd0;

    end

    else if(rx_en == 0)

        cnt <= 13'd0;  

end

reg bit_data; //采样数据

always@(posedge clk)

begin

    if(cnt == bit_samp)

        bit_data <= 1'b1;

    else

       bit_data <= 1'b0;

end

/*检测串口数据下降沿*/

reg rx_bit1,rx_bit2,rx_bit3,rx_bit4;

wire neg_rx;

always@(posedge clk or negedge rst_n)

begin

    if(!rst_n)

        begin

            rx_bit1 <= 0;

            rx_bit2 <= 0;

            rx_bit3 <= 0;

            rx_bit4 <= 0;

        end

    else

        begin

            rx_bit1 <= rx_bit;

            rx_bit2 <= rx_bit1;

            rx_bit3 <= rx_bit2;

            rx_bit4 <= rx_bit3;

        end

end

assign neg_rx =  rx_bit4 & rx_bit3 & ~rx_bit2 & ~rx_bit1 ;

reg rx_en; //接收数据高电平使能

always@(posedge clk or negedge rst_n)

begin

    if(!rst_n)

        rx_en   <= 1'b0;

   else if(neg_rx == 1)

        rx_en <= 1;

    else if(rx_stop ==1)

    begin

        rx_en <= 0;

    end

end

reg rx_stop; //停止标志位

reg [3:0]bit_num; //串口数据位计数

reg [8:0]rx_data_temp; //存储接收到的数据

reg [7:0]rx_data;

always@(posedge clk or negedge rst_n)

begin

    if(!rst_n)

        begin

        rx_data_temp <= 9'b111111111; //初始值设定

        bit_num <= 4'b0;

        rx_stop <= 0;

        end

    else if(bit_num == 4'd11)

    begin

         rx_stop <=1;

        bit_num <= 0;

    end            

   else if(bit_data == 1)

            begin

                bit_num <= bit_num + 1'b1;

            case(bit_num)

            4'd0:   rx_data_temp[0] <= rx_bit; //起始位

            4'd1:   rx_data_temp[1] <= rx_bit;

            4'd2:   rx_data_temp[2] <= rx_bit;

            4'd3:   rx_data_temp[3] <= rx_bit;

            4'd4:   rx_data_temp[4] <= rx_bit;

            4'd5:   rx_data_temp[5] <= rx_bit;

            4'd6:   rx_data_temp[6] <= rx_bit;

            4'd7:   rx_data_temp[7] <= rx_bit;

            4'd8:   rx_data_temp[8] <= rx_bit;

            default: ;

            endcase

            end

    else

        rx_stop <= 0;

rx_data <= rx_data_temp[8:1];

end


endmodule


创作许可协议

本项目采用 None(不开放任何权利,保留所有权利) 进行许可。

评论(2)
Holiday
Holiday
好厉害的感觉。。
phoebe.wang40
phoebe.wang40
楼主,这是拿啥语言编的呢?
Holiday
Holiday回复phoebe.wang40
给FPGA编程的语言,大学时我们也学过,和C很像的
- 没有更多了 -