FPGA串口接收代码分享

来源:互联网 发布:服务器80端口被占用 编辑:程序博客网 时间:2024/06/05 03:41

module uart_rx(

    clk,            /*时钟信号*/

    rst_n,      /*复位信号*/

    baud_set,   /*波特率设置*/

    rs232_rx,   /*串行数据输入*/

   

    data_byte,  /*并行数据输出*/

    rx_down     /*接收完成信号*/

    );

 

    inputclk,rst_n;      /*时钟,复位信号输入*/

    input[2:0]baud_set;/*波特率设置*/

    inputrs232_rx;  /*串行数据输入*/

   

    output reg[7:0]data_byte;/*并行数据输出*/

    output regrx_down; /*接收完成信号*/

   

    reg [2:0]r_data_byte[7:0]; /*数据接收*/

   

    regs0_rs232_rx,s1_rs232_rx;    /*同步寄存器*/

    regtemp0_rs232_rx,temp1_rs232_rx;  /*数据寄存器*/

   

    reguart_state; /*发送状态*/

   

    reg[15:0]bps_DR;   /*分频计数最大值*/

    reg[15:0]div_cnt;/*分频计数器*/

    reg bps_clk;        /*待接收一字节bit位计数器控制器*/

    reg[7:0]bps_cnt; /*待接收一字节bit位计数器*/

   

    reg [2:0]START_BIT,STOP_BIT;/*起始位停止位 */

   

    wire nedege;    /*时钟沿状态判断*/

    /*************************波特率设置部分******************/

    /*波特率设置*/

    always@(posedgeclk,negedge rst_n)begin

        if(!rst_n)begin /*如果系统复位*/

            bps_DR<= 16'd324;  /*9600*/

        end

        elsebegin

            case(baud_set)

                0:bps_DR<= 16'd324;    /*9600*/

                1:bps_DR<= 16'd162; /*19200*/

                2:bps_DR<= 16'd80; /*38400*/

                3:bps_DR<= 16'd80; /*57600*/

                4:bps_DR<= 16'd26; /*115200*/

                default:bps_DR<= 16'd324;  /*9600*/

            endcase

        end

    end

   

    /*波特率分频计数值控制*/

    always@(posedgeclk,negedge rst_n)begin

        if(!rst_n)begin /*如果系统复位*/

            div_cnt<= 16'd0;   /*分频计数器清零*/

        end

        elseif(uart_state)begin    /*如果处于发送状态*/

            if(div_cnt== bps_DR)begin/*分频计数达到设置波特率计数最大值*/

                div_cnt<= 16'd0;   /*分频计数器清零*/

            end

            elsebegin

                div_cnt<= div_cnt + 1'b1;/*分频计数器计数值加加*/

            end

        end

        elsebegin

            div_cnt<= 16'd0;   /*分频计数器清零*/

        end

    end

   

    /*************一字节数据接收驱动部分*************/

    /*同步寄存器消除亚稳态*/

    always@(posedgeclk,negedge rst_n)begin

        if(!rst_n)begin /*如果系统复位*/

            s0_rs232_rx<= 1'b0;  /*同步寄存器清零*/

            s1_rs232_rx<= 1'b0;  /*同步寄存器清零*/

        end

        else begin

            s0_rs232_rx<= rs232_rx;        /*把串口接收的数据存到s0接收寄存器*/

            s1_rs232_rx<= s0_rs232_rx; /*把原s0的数据移位到s1接收寄存器*/

        end

    end

 

    always@(posedgeclk,negedge rst_n)begin

        if(!rst_n)begin /*如果系统复位*/

            temp0_rs232_rx<= 1'b0;  /*同步寄存器清零*/

            temp1_rs232_rx<= 1'b0;  /*同步寄存器清零*/

        end

        elsebegin  /*s1_rs232_rx 为稳态数据*/

            temp0_rs232_rx<= s1_rs232_rx;      /*把寄存器s1的数据存到temp0*/

            temp1_rs232_rx<= temp0_rs232_rx;   /*temp0的数据存到temp1*/

        end

    end

   

    assign nedege= !temp0_rs232_rx & temp1_rs232_rx; /*判断时钟沿 下降沿 !0-->0*/

   

    /*接收一字节数据bit计数器的控制器*/

    always@(posedgeclk,negedge rst_n)begin

        if(!rst_n)begin /*如果系统复位*/

            bps_clk<= 1'b0;    /*接收一字节数据bit计数器控制器置0*/

        end

        elseif(div_cnt == 16'd1)begin/*如果分频计数器值为1*/

            bps_clk<= 1'b1;    /*接收一字节数据bit计数器控制器置1*/

        end

        elsebegin

            bps_clk<= 1'b0;    /*接收一字节数据bit计数器控制器置0*/

        end

    end

   

    /*待接收一字节bit位计数器*/

    always@(posedgeclk,negedge rst_n)begin

        if(!rst_n)begin

            bps_cnt<= 8'd0;    /*待接收bit位计数器置零*/

        end

        elseif(bps_cnt == 8'd159 | (bps_cnt == 8'd12 &&(START_BIT>2)))begin/*一个字节接收完毕或者起始位未到来*/

            bps_cnt<= 8'd0;    /*待接收bit位计数器置零*/

        end    

        elseif(bps_clk)begin   /*接收一字节数据bit计数器控制器置1*/

            bps_cnt<= bps_cnt + 1'b1;/*待接收一字节bit位计数器加加*/

        end

        elsebegin

            bps_cnt<= bps_cnt; /*状态保持*/

        end

    end

   

    /*接收是否结束控制*/

    always@(posedgeclk,negedge rst_n)begin

        if(!rst_n)begin     /*如果复位*/

            rx_down<= 1'b0;    /*接收未完成*/

        end

        elseif(bps_cnt == 8'd159)begin /*如果一个字节接收计数器计数完成*/

            rx_down<= 1'b1;  /*接收完成*/

        end

        else begin

            rx_down<= 1'b0;    /*接收未完成*/

        end

    end

   

    /*接收状态控制*/

    always@(posedgeclk,negedge rst_n)begin

        if(!rst_n)begin /*如果复位*/

            uart_state<= 1'b0;         /*未接收状态*/

        end

        elseif(nedege)begin                /*下降沿*/

            uart_state<= 1'b1;         /*接收状态*/

        end

        elseif(rx_down || (bps_cnt == 8'd12 &&(START_BIT >2)))begin /*如果发送完成起始位未到来*/

            uart_state<= 1'b0;         /*未接收状态*/     

        end

        elsebegin

            uart_state<= uart_state;   /*状态保持*/

        end

    end

   

    /*接收数据*/

    always@(posedgeclk,negedge rst_n)begin

        if(!rst_n)begin         /*如果复位*/

            START_BIT<= 3'd0;      /*起始位置0*/

            r_data_byte[0]<= 3'd0;

            r_data_byte[1]<= 3'd0;

            r_data_byte[2]<= 3'd0;

            r_data_byte[3]<= 3'd0;

            r_data_byte[4]<= 3'd0;

            r_data_byte[5]<= 3'd0;

            r_data_byte[6]<= 3'd0;

            r_data_byte[7]<= 3'd0;

            STOP_BIT<= 3'd0;       /*停止位置0*/

        end

        elseif(bps_clk)begin   /*接收一字节数据bit计数器控制器置1*/

            case(bps_cnt)

                0:begin

                        START_BIT<= 3'd0;      /*起始位置0*/

                        r_data_byte[0]<= 3'd0;

                        r_data_byte[1]<= 3'd0;

                        r_data_byte[2]<= 3'd0;

                        r_data_byte[3]<= 3'd0;

                        r_data_byte[4]<= 3'd0;

                        r_data_byte[5]<= 3'd0;

                        r_data_byte[6]<= 3'd0;

                        r_data_byte[7]<= 3'd0;

                        STOP_BIT<= 3'd0;       /*停止位置0*/

                    end

                6,7,8,9,10,11:         START_BIT <= START_BIT +s1_rs232_rx;       /*起始位6次采样*/

                22,23,24,25,26,27:      r_data_byte[0] <= r_data_byte[0] +s1_rs232_rx;

                38,39,40,41,42,43:      r_data_byte[1] <= r_data_byte[1] +s1_rs232_rx;

                54,55,56,57,58,59:      r_data_byte[2] <= r_data_byte[2] +s1_rs232_rx;

                70,71,72,73,74,75:      r_data_byte[3] <= r_data_byte[3] +s1_rs232_rx;

                86,87,88,89,90,91:      r_data_byte[4] <= r_data_byte[4] +s1_rs232_rx;

                102,103,104,105,106,107:r_data_byte[5]<= r_data_byte[5] + s1_rs232_rx;

                118,119,120,121,122,123:r_data_byte[6]<= r_data_byte[6] + s1_rs232_rx;

                134,135,136,137,138,139:r_data_byte[7]<= r_data_byte[7] + s1_rs232_rx;

                150,151,152,153,154,155:STOP_BIT<= STOP_BIT + s1_rs232_rx;        /*停止位6次采样*/

                default:begin

                                START_BIT= START_BIT;      /*起始位保持*/ 

                                r_data_byte[0]<= r_data_byte[0];

                                r_data_byte[1]<= r_data_byte[1];

                                r_data_byte[2]<= r_data_byte[2];

                                r_data_byte[3]<= r_data_byte[3];

                                r_data_byte[4]<= r_data_byte[4];

                                r_data_byte[5]<= r_data_byte[5];

                                r_data_byte[6]<= r_data_byte[6];

                                r_data_byte[7]<= r_data_byte[7];

                                STOP_BIT= STOP_BIT;            /*结束位保持*/

                            end

            endcase

        end

    end

   

    /*一字节数据提取*/

    always@(posedgeclk ,negedge rst_n)begin

        if(!rst_n)begin /*如果复位*/

            data_byte<= 8'd0;  /*数据输出置0*/

        end

        elseif(bps_cnt == 8'd159)begin /*如果一个字节接收计数器计数完成*/

            data_byte[0]= r_data_byte[0][2]; /*判断r_data_byte的最高位*/

            data_byte[1]= r_data_byte[1][2]; /*最高位是1则为1否则0*/

            data_byte[2]= r_data_byte[2][2];

            data_byte[3]= r_data_byte[3][2];

            data_byte[4]= r_data_byte[4][2];

            data_byte[5]= r_data_byte[5][2];

            data_byte[6]= r_data_byte[6][2];

            data_byte[7]= r_data_byte[7][2];

        end

    end

   

endmodule