2024/1/21学习记录

串口学习

  1. 设计思路

      实验任务:通过电脑端的串口调试助手向FPGA发送数据,FPGA通过串口接收数据并将接受到的数据发送给上位机,实现串口回环功能。

            接收模块(RX):通过检测起始位来表示数据传输的开始,在波特率中间时刻去采样总线上的数据,最后将数据进行串并转换。

            发送模块(TX):将并行数据转换成串行数据,然后在串行数据帧头加上起始位,帧尾加上停止位,发送给上位机。

  2. 编写tx模块和rx模块,并进行验证。

  3. /*===============================*
        filename    : uart_tx.v
        description : 串口发送模块
        time        : 2024-1-20 
        author      : 
    *================================*/
     
    module uart_tx(
        input         clk      ,//时钟  50MHZ
        input         rst_n    ,//复位
     
        input  [2:0]  baud_sel ,//波特率选择
        input  [7:0]  pi_data  ,//数据
        input         pi_flag  ,//数据使能
     
        output  reg   uart_tx   //tx数据线
    );
     
    //参数定义
    parameter   SCLK = 50_000_000;//系统时钟  50MHZ
     
    //波特率选择
    parameter   BAUD_9600   = SCLK/9600  ,
                BAUD_19200  = SCLK/19200 ,
                BAUD_38400  = SCLK/38400 ,
                BAUD_57600  = SCLK/57600 ,
                BAUD_115200 = SCLK/115200;
     
    //信号定义
    reg            work_en    ;//工作使能
     
    reg   [15:0]   cnt_baud   ;//波特率计数器
    reg   [15:0]   BAUD_NUM   ;
     
    reg            bit_flag   ;//bit标志信号
    reg   [3:0]    cnt_bit    ;//bit计数器
     
     
    //work_en
    always @(posedge clk or negedge rst_n)begin
        if(!rst_n)begin
            work_en <= 1'b0;
        end
        else if(pi_flag == 1'b1)begin
            work_en <= 1'b1;
        end
        else if((cnt_bit == 4'd9) && (bit_flag == 1'b1))begin
            work_en <= 1'b0;
        end
    end
     
    //cnt_baud
    always @(posedge clk or negedge rst_n)begin
        if(!rst_n)begin
            cnt_baud <= 16'd0;
        end
        else if((work_en == 1'b0) || (cnt_baud == BAUD_NUM - 1))begin
            cnt_baud <= 16'd0;
        end
        else if(work_en == 1'b1)begin
            cnt_baud <= cnt_baud + 1'b1;
        end
    end
    //BAUD_NUM
    always @(*)begin
        case(baud_sel)
            3'd0 : BAUD_NUM = BAUD_9600  ;
            3'd1 : BAUD_NUM = BAUD_19200 ;
            3'd2 : BAUD_NUM = BAUD_38400 ;
            3'd3 : BAUD_NUM = BAUD_57600 ;
            3'd4 : BAUD_NUM = BAUD_115200;
            default : BAUD_NUM = BAUD_115200;
        endcase
    end
     
    //bit_flag 
    always @(posedge clk or negedge rst_n)begin
        if(!rst_n)begin
            bit_flag <= 1'b0;
        end
        else if(cnt_baud == 16'd1)begin
            bit_flag <= 1'b1;
        end
        else begin
            bit_flag <= 1'b0;
        end
    end
     
    //cnt_bit
    always @(posedge clk or negedge rst_n) begin
        if(!rst_n)begin
            cnt_bit <= 4'd0;
        end
        else if((cnt_bit == 4'd9)&&(bit_flag == 1'b1))begin
            cnt_bit <= 4'd0;
        end
        else if((work_en == 1'b1)&&(bit_flag == 1'b1))begin
            cnt_bit <= cnt_bit + 1'b1;
        end
    end
    //输出  uart_tx
    always @(posedge clk or negedge rst_n)begin
        if(!rst_n)begin
            uart_tx <= 1'b1;
        end
        else if(bit_flag == 1'b1)begin
            case(cnt_bit)
                0 : uart_tx <= 1'b0;//起始位
                1 : uart_tx <= pi_data[0];
                2 : uart_tx <= pi_data[1];
                3 : uart_tx <= pi_data[2];
                4 : uart_tx <= pi_data[3];
                5 : uart_tx <= pi_data[4];
                6 : uart_tx <= pi_data[5];
                7 : uart_tx <= pi_data[6];
                8 : uart_tx <= pi_data[7];
                9 : uart_tx <= 1'b1;//停止位
                default : uart_tx <= 1'b1;
            endcase
        end
    end
     
     
    endmodule
    工程记录
    /*===============================*
        filename    : uart_rx.v
        description : 串口接收模块
        time        : 2024-1-20 
        author      : 
    *================================*/
     
    module uart_rx(
        input              clk       ,//时钟  50MHZ
        input              rst_n     ,//复位
     
        input              uart_rx   ,//rx数据线
        input       [2:0]  baud_sel  ,//波特率选择
     
        output reg  [7:0]  po_data   ,//接收的数据
        output reg         po_flag    //数据使能
    );
     
    //参数定义
    parameter   SCLK = 50_000_000;//系统时钟  50MHZ
     
    //波特率选择
    parameter   BAUD_9600   = SCLK/9600  ,
                BAUD_19200  = SCLK/19200 ,
                BAUD_38400  = SCLK/38400 ,
                BAUD_57600  = SCLK/57600 ,
                BAUD_115200 = SCLK/115200;
     
    //信号定义
    reg           uart_rx_1    ;//同步、打拍
    reg           uart_rx_2    ;
    wire          rx_nedge     ;//下降沿检测
     
    reg           start_flag   ;//起始标志
    reg           work_en      ;//工作使能
     
    reg   [15:0]  cnt_baud     ;//波特率计数器
    reg   [15:0]  BAUD_NUM     ;
     
    reg           bit_flag     ;//接收数据使能
    reg   [3:0]   cnt_bit      ;//bit计数器
     
    reg   [7:0]   rx_data      ;//数据
    reg           rx_flag      ;//数据标志
     
     
    //同步、打拍  检测下降沿
    always @(posedge clk or negedge rst_n)begin
        if(!rst_n)begin
            uart_rx_1 <= 1'b1;
            uart_rx_2 <= 1'b1;
        end
        else begin
            uart_rx_1 <= uart_rx;
            uart_rx_2 <= uart_rx_1;
        end
    end
    assign rx_nedge = uart_rx_2 && ~uart_rx_1;
     
    //start_flag  
    always @(posedge clk or negedge rst_n)begin
        if(!rst_n)begin
            start_flag <= 1'b0;
        end
        else if(rx_nedge && work_en == 1'b0)begin
            start_flag <= 1'b1;
        end
        else begin
            start_flag <= 1'b0;
        end
    end
     
    //work_en
    always @(posedge clk or negedge rst_n)begin
        if(!rst_n)begin
            work_en <= 1'b0;
        end
        else if(start_flag == 1'b1)begin
            work_en <= 1'b1;
        end
        else if(cnt_bit == 4'd8 && bit_flag == 1'b1)begin
            work_en <= 1'b0;
        end
        else begin
            work_en <= work_en;
        end
    end
     
    //cnt_baud
    always @(posedge clk or negedge rst_n)begin
        if(!rst_n)begin
            cnt_baud <= 16'd0;
        end
        else if((cnt_baud == BAUD_NUM - 1) || (work_en == 1'b0))begin
            cnt_baud <= 16'd0;
        end
        else if(work_en == 1'b1)begin
            cnt_baud <= cnt_baud + 1'b1;
        end
    end
    //BAUD_NUM
    always @(*)begin
        case(baud_sel)
            3'd0 : BAUD_NUM = BAUD_9600  ;
            3'd1 : BAUD_NUM = BAUD_19200 ;
            3'd2 : BAUD_NUM = BAUD_38400 ;
            3'd3 : BAUD_NUM = BAUD_57600 ;
            3'd4 : BAUD_NUM = BAUD_115200;
            default : BAUD_NUM = BAUD_115200;
        endcase
    end
     
    //bit_flag
    always @(posedge clk or negedge rst_n)begin
        if(!rst_n)begin
            bit_flag <= 1'b0;
        end
        else if(cnt_baud == (BAUD_NUM >> 1) - 1)begin
            bit_flag <= 1'b1;
        end
        else begin
            bit_flag <= 1'b0;
        end
    end
    //cnt_bit
    always @(posedge clk or negedge rst_n)begin
        if(!rst_n)begin
            cnt_bit <= 4'd0;
        end
        else if((cnt_bit == 4'd8) && (bit_flag == 1'b1))begin
            cnt_bit <= 4'd0;
        end
        else if(bit_flag == 1'b1)begin
            cnt_bit <= cnt_bit + 1'b1;
        end
    end
    //rx_data
    always @(posedge clk or negedge rst_n)begin
        if(!rst_n)begin
            rx_data <= 8'b0;
        end
        else if((cnt_bit>=4'd1)&&(cnt_bit<=4'd8)&&(bit_flag==1'b1))begin
            rx_data <= {uart_rx_2,rx_data[7:1]};
        end
    end
     
    //rx_flag
    always @(posedge clk or negedge rst_n)begin
        if(!rst_n)begin
            rx_flag <= 1'b0;
        end
        else if((cnt_bit == 4'd8) && (bit_flag == 1'b1))begin
            rx_flag <= 1'b1;
        end
        else begin
            rx_flag <= 1'b0;
        end
    end
    //输出
    //po_data
    always @(posedge clk or negedge rst_n)begin
        if(!rst_n)begin
            po_data <= 8'b0;
        end
        else if(rx_flag == 1'b1)begin
            po_data <= rx_data;
        end
    end
    //po_flag
    always @(posedge clk or negedge rst_n)begin
        if(!rst_n)begin
            po_flag <= 1'b0;
        end
        else begin
            po_flag <= rx_flag;
        end
    end
     
     
    endmodule

    下周学习计划

  4. 学习调用IP核PLL;
  5. 学习AD采集代码编写;

        学习资源

  1. 开发板
  2. 找别人的代码来看

  • 19
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值