目录

银杏科技有限公司旗下技术文档发布平台
技术支持电话0379-69926675-801
技术支持邮件Gingko@vip.163.com
版本 日期 作者 修改内容
V1.0 2020-02-26 gingko 初次建立

实验十六:串口通信实验——基于FPGA实现UART通信

一、 实验目的与意义

  1. 掌握UART协议及实现方法。
  2. 掌握QuartusII的使用方法。

二、 实验设备及平台

  1. iCore4T 双核心板。
  2. iCore4T 底板(杜邦线一套)。
  3. iTool3(串口TTL)。
  4. Blaster(或相同功能)仿真器。
  5. Micro USB线缆。
  6. Keil MDK 开发平台。
  7. Quartus开发平台。
  8. 电脑一台。

三、 实验原理

四、 代码讲解

/*************************************************/
//接收模块
always @ (posedge pll_1_8m or negedge rst_n)
    begin
        if(!rst_n)
            begin
                rx_cnt <= 8'd0;;
                uart_rdata_r <= 8'd0;
                uart_rdata <= 8'd0;
                parity_bit <= 1'd0;
                receive_over_r <= 1'd0;
            end
        else 
            begin
                case(rx_cnt)
                    //判断信号线是否有变化(信号线正常情况下位高电平,有低电平表示信号有变化)
                    8'd0:begin
                        if(!rxd)
                            begin
                                rx_cnt <= rx_cnt + 1'd1;
                            end
                        else
                            begin
                                rx_cnt <= rx_cnt;
                            end             
                    end
                    //判断信号线变化是否为数据起始位(信号线稳定后仍为低电平,表示为真正的数据起始位)
                    8'd8:begin
                        if(!rxd)
                            begin
                                rx_cnt <= rx_cnt + 1'd1;
                            end
                        else
                            begin
                                rx_cnt <= 8'd0;
                            end
                    end
                    //接收数据0位
                    8'd24:begin
                        uart_rdata_r[0] <= rxd;
                        rx_cnt <= rx_cnt + 1'd1;
                    end
                    //接收数据1位
                    8'd40:begin
                        uart_rdata_r[1] <= rxd;
                        rx_cnt <= rx_cnt + 1'd1;
                    end
                    //接收数据2位
                    8'd56:begin
                        uart_rdata_r[2] <= rxd;
                        rx_cnt <= rx_cnt + 1'd1;
                    end
                    //接收数据3位
                    8'd72:begin
                        uart_rdata_r[3] <= rxd;
                        rx_cnt <= rx_cnt + 1'd1;
                    end
                    //接收数据4位
                    8'd88:begin
                        uart_rdata_r[4] <= rxd;
                        rx_cnt <= rx_cnt + 1'd1;
                    end
                    //接收数据5位
                    8'd104:begin
                        uart_rdata_r[5] <= rxd;
                        rx_cnt <= rx_cnt + 1'd1;
                    end
                    //接收数据6位
                    8'd120:begin
                        uart_rdata_r[6] <= rxd;
                        rx_cnt <= rx_cnt + 1'd1;
                    end
                    //接收数据7位
                    8'd136:begin
                        uart_rdata_r[7] <= rxd;
                        rx_cnt <= rx_cnt + 1'd1;
                    end
                    //接收校验位(无校验)
                    8'd152:begin
                        parity_bit <= rxd;
                        rx_cnt <= rx_cnt + 1'd1;
                    end
                    //接收停止位
                    8'd168:begin
                        rx_cnt <= rx_cnt + 1'd1;
                        uart_rdata <= uart_rdata_r;
                    end
 
                    //接收完成标志拉高两个时钟
                    8'd175:begin
                        receive_over_r <= 1'd1;
                        rx_cnt <= rx_cnt + 1'd1;
                    end
                    8'd177:begin
                        receive_over_r <= 1'd0;
                        rx_cnt <= rx_cnt + 1'd1;
                    end
                    //判断是否发送完成
                    8'd178:begin
                        if(send_over)
                            begin
                                rx_cnt <= 8'd0;
                            end
                        else
                            begin
                                rx_cnt <= rx_cnt;
                            end
                    end
                    default:begin
                        rx_cnt <= rx_cnt + 1'd1;                    
                    end
                endcase
            end
    end
/*************************************************/
/*************************************************/
//发送模块
always @ (posedge pll_1_8m or negedge rst_n)
begin
    if(!rst_n)
        begin
            tx_cnt <= 8'd255;
            tx_r <= 1'd1;
            send_over_r <= 1'd0;
        end
    else 
        begin
            case(tx_cnt)
                8'd255:begin
                    if(receive_over)
                        begin
                            tx_cnt <= tx_cnt + 1'd1;
                        end
                    else
                        begin
                            tx_cnt <= tx_cnt;
                        end
                end
                8'd0:begin
                    tx_cnt <= tx_cnt + 1'd1;
                    tx_r <= 1'd0;//发送起始位
                end
                8'd16:begin                                                         
                    tx_cnt <= tx_cnt + 1'd1;
                    tx_r <= tx_data[0];//发送数据0位
                end
                8'd32:begin
                    tx_cnt <= tx_cnt + 1'd1;
                    tx_r <= tx_data[1];//发送数据1位
                end
                8'd48:begin
                    tx_cnt <= tx_cnt + 1'd1;
                    tx_r <= tx_data[2];//发送数据2位
                end
                8'd64:begin
                    tx_cnt <= tx_cnt + 1'd1;
                    tx_r <= tx_data[3];//发送数据3位
                end 
                8'd80:begin
                    tx_cnt <= tx_cnt + 1'd1;
                    tx_r <= tx_data[4];//发送数据4位
                end
                8'd96:begin
                    tx_cnt <= tx_cnt + 1'd1;
                    tx_r <= tx_data[5];//发送数据5位
                end
                8'd112:begin
                    tx_cnt <= tx_cnt + 1'd1;
                    tx_r <= tx_data[6];//发送数据6位
                end
                8'd128:begin
                    tx_cnt <= tx_cnt + 1'd1;
                    tx_r <= tx_data[7];//发送数据7位
                end
                8'd144:begin
                    tx_cnt <= tx_cnt + 1'd1;
                    tx_r <= 1'bz;       //发送校验位               
                end
                8'd160:begin
                    tx_cnt <= tx_cnt + 1'd1;
                    tx_r <= 1'd1;//发送停止位
                end 
                8'd168:begin
                    tx_cnt <= tx_cnt + 8'd1;
                    tx_r <= 1'd1;           //一帧数据发送结束   
                end
                8'd175:begin
                    tx_cnt <= tx_cnt + 8'd1;
                    send_over_r <= 1'd1;
                end
                8'd177:begin
                    tx_cnt <= 8'd255;
                    send_over_r <= 1'd0;
                end
                default:begin
                    tx_cnt <= tx_cnt + 8'd1;
                    tx_r <= tx_r;
                end
            endcase
        end
end
/*************************************************/

五、 实验步骤及实验结果

1、将硬件正确连接,如图16.3所示。
2、将编写好的代码进行编译,并下载到开发板中;
3、打开串口调试工具,波特率设置为115200,并打开对应端口,如图16.4所示; 4、在串口调试工具的发送区输入发送数据,FPGA会自动将接收到的数据发送至串口,显示在串口调试工具的接收区,如图16.5所示。

六、 拓展实验