login
欢迎访问QkqBeer博客园!

FPGA实现串口接收

功能实现:所有的疑惑都在注释中有解释!

`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date:    14:26:20 01/04/2022 
// Design Name: 
// Module Name:    uart_rx_01 
// Project Name: 
// Target Devices: 
// Tool versions: 
// Description: 
//
// Dependencies: 
//
// Revision: 
// Revision 0.01 - File Created
// Additional Comments: 
//
//////////////////////////////////////////////////////////////////////////////////



//设计思想如下:
//传输的数据里面包含:一个起始位,八个数据位,一个停止位
//每一个传输位:分为十六个采集数据点,每个数据采集点在其片段的中点位置,十六位中取其中七位为有效采集数据位前五后四不取,将其中七位数据位进行计算得出来该位为高还是低

module uart_rx_01(
    clk,
    Reset_n,
    uart_rx,
    Bund_set,
    Data,
    Rx_Done
    );
     
     
    input clk;
    input Reset_n;
    input uart_rx;
    input [2:0]Bund_set;
    
    output reg [7:0]Data;
    output reg Rx_Done;
    
    
    reg [1:0] uart_rx_r;
    always@(posedge clk)begin
        uart_rx_r[0] <= uart_rx;
        uart_rx_r[1] <= uart_rx_r[0];    
    end
    
    wire pedge_uart_rx;//上升沿
    //assign pedge_uart_rx = ((uart_rx_r[1] == 0) && (uart_rx_r[0] == 1)) //与下面的功能类似
    assign pedge_uart_rx = (uart_rx_r == 2'b01);
    
    wire nedge_uart_rx;//下降沿
    assign nedge_uart_rx = (uart_rx_r == 2'b10);
    
    //下降沿作为分频计数的开始
    reg RX_EN;
    always@(posedge clk or negedge Reset_n)
    if(!Reset_n)
        RX_EN <= 0;
    else if(nedge_uart_rx) //一开始理解有问题,觉得其他的数据中可能存在下降沿会影响RX_EN的使能,多虑了。只需要控制好RX_EN置为0的条件就ok
        RX_EN <= 1;
    else if(Rx_Done || (sta_bit >= 4)) //数据发送结束或者(起始位传输不对,错误的起始位)
        RX_EN <= 0;
        
    //基本的分频计数器
    reg [8:0] div_cnt;
    
    always@(posedge clk or negedge Reset_n)
    if(!Reset_n)
        div_cnt <= 0;
    else if(RX_EN)begin
        if(div_cnt == bund_dr - 1)
            div_cnt <= 0;
        else
            div_cnt <= div_cnt + 1'b1;
    end
    else
        div_cnt <= 0;
    
    //波特率转换为计数值门限
    reg [8:0] bund_dr;    
    always@(*)
        //1000000000为一秒钟, 16是将每个数据分为16个采集点, 20为每个时钟周期为20ns
        case(Bund_set)
        0: bund_dr <= 1000000000/16/20/9600;
        1: bund_dr <= 1000000000/16/20/19200;
        2: bund_dr <= 1000000000/16/20/38400;
        3: bund_dr <= 1000000000/16/20/57600;
        4: bund_dr <= 1000000000/16/20/115200;
        default: bund_dr <= 1000000000/16/20/9600;
        endcase
        
        
    //每次什么时候进行采集样本,发出一个上升沿信号
    wire bps_clk_16x;
    assign bps_clk_16x = (div_cnt == (bund_dr - 1) /2);
    
    //二级计数器,计数采集样本的总次数(十个数据需要总共160次)
    reg[7:0] bps_cnt;
    always@(posedge clk or negedge Reset_n)
    if(!Reset_n)
        bps_cnt <= 0;
    else if(RX_EN)begin
        if(bps_clk_16x)begin
            if(bps_cnt == 160)
                bps_cnt <= 0;
            else
                bps_cnt <= bps_cnt + 1'b1;
        end
        else
            bps_cnt <= bps_cnt;
    end
    else
        bps_cnt <= 0;
    
    reg [3:0]data_r[7:0];
    reg [3:0]sta_bit;
    reg [3:0]sto_bit;
    always@(posedge clk or negedge Reset_n)
    if(!Reset_n)begin    
        sta_bit <= 0;
        data_r[0] <= 0;
        data_r[1] <= 0;
        data_r[2] <= 0;
        data_r[3] <= 0;
        data_r[4] <= 0;
        data_r[5] <= 0;
        data_r[6] <= 0;
        data_r[7] <= 0;    
        sto_bit <= 0;
    end
    else if(bps_clk_16x)begin
        case(bps_cnt)
        0:begin
        sta_bit <= 0;
        data_r[0] <= 0;
        data_r[1] <= 0;
        data_r[2] <= 0;
        data_r[3] <= 0;
        data_r[4] <= 0;
        data_r[5] <= 0;
        data_r[6] <= 0;
        data_r[7] <= 0;    
        sto_bit <= 0;
        end
        5,6,7,8,9,10,11: sta_bit <= sta_bit + uart_rx;
        21,22,23,24,25,26,27:data_r[0] <= data_r[0] + uart_rx;
        37,38,39,40,41,42,43:data_r[1] <= data_r[1] + uart_rx;
        53,54,55,56,57,58,59:data_r[2] <= data_r[2] + uart_rx;
        69,70,71,72,73,74,75:data_r[3] <= data_r[3] + uart_rx;
        85,86,87,88,89,90,91:data_r[4] <= data_r[4] + uart_rx;
        101,102,103,104,105,106,107:data_r[5] <= data_r[5] + uart_rx;
        117,118,119,120,121,122,123:data_r[6] <= data_r[6] + uart_rx;
        133,134,135,136,137,138,139:data_r[7] <= data_r[7] + uart_rx;
        149,150,151,152,153,154,155: sto_bit <= sto_bit + uart_rx;
        default:;
        endcase
        end
        
        //将数据输出到Data上,进行判断,判断其七次累加的结果
    always@(posedge clk or negedge Reset_n)
    if(!Reset_n)
        Data <= 0;
    else if(bps_clk_16x && (bps_cnt == 160))begin
        Data[0] <= (data_r[0] >= 4)? 1'b1:1'b0;
        Data[1] <= (data_r[1] >= 4)? 1'b1:1'b0;
        Data[2] <= (data_r[2] >= 4)? 1'b1:1'b0;
        Data[3] <= (data_r[3] >= 4)? 1'b1:1'b0;
        Data[4] <= (data_r[4] >= 4)? 1'b1:1'b0;
        Data[5] <= (data_r[5] >= 4)? 1'b1:1'b0;
        Data[6] <= (data_r[6] >= 4)? 1'b1:1'b0;
        Data[7] <= (data_r[7] >= 4)? 1'b1:1'b0;
    
    end
    
    //Rx_Done信号的处理
    always@(posedge clk or negedge Reset_n)
    if(!Reset_n)
        Rx_Done <= 0;
    else if((div_cnt == (bund_dr - 1)/2) && (bps_cnt == 160))
        Rx_Done <= 1;
    else
        Rx_Done <= 0;
    
endmodule

测试激励

`timescale 1ns / 1ps

////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer:
//
// Create Date:   21:30:47 01/05/2022
// Design Name:   uart_rx_01
// Module Name:   E:/FPGA_WORKSPACE/uart_rx/uart_rx_01_test.v
// Project Name:  uart_rx
// Target Device:  
// Tool versions:  
// Description: 
//
// Verilog Test Fixture created by ISE for module: uart_rx_01
//
// Dependencies:
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
////////////////////////////////////////////////////////////////////////////////

module uart_rx_01_test;

    // Inputs
    reg clk;
    reg Reset_n;
    reg uart_rx;
    wire [2:0] Bund_set;

    // Outputs
    wire [7:0] Data;
    wire Rx_Done;

    assign Bund_set = 4;
    // Instantiate the Unit Under Test (UUT)
    uart_rx_01 uut (
        .clk(clk), 
        .Reset_n(Reset_n), 
        .uart_rx(uart_rx), 
        .Bund_set(Bund_set), 
        .Data(Data), 
        .Rx_Done(Rx_Done)
    );
    initial clk = 1;
    always #10 clk = !clk;
    
    initial begin
        // Initialize Inputs
        Reset_n = 0;
        uart_rx = 0;

        // Wait 100 ns for global reset to finish
        #201;
        Reset_n = 1;
        #200;
        uart_tx_data(8'h5a);
        @(posedge Rx_Done);
        #5000;
        uart_tx_data(8'ha5);
        @(posedge Rx_Done);
        #5000;
        uart_tx_data(8'h56);
        @(posedge Rx_Done);
        #5000;
        
        // Add stimulus here

    end
    task uart_tx_data;
        input [7:0]tx_data;
        begin
            uart_rx = 1;
            #20;
            uart_rx = 0;
            #8680;
            uart_rx = tx_data[0];
            #8680;
            uart_rx = tx_data[1];
            #8680;
            uart_rx = tx_data[2];
            #8680;
            uart_rx = tx_data[3];
            #8680;
            uart_rx = tx_data[4];
            #8680;
            uart_rx = tx_data[5];
            #8680;
            uart_rx = tx_data[6];
            #8680;
            uart_rx = tx_data[7];
            #8680;
            uart_rx = 1;
            #8000;
        end
    endtask
      
endmodule

 

`timescale 1ns / 1ps//////////////////////////////////////////////////////////////////////////////////// Company: // Engineer: // // Create Date:    14:26:20 01/04/2022 // Design Name: // Module Name:    uart_rx_01 // Project Name: // Target Devices: // Tool versions: // Description: //// Dependencies: //// Revision: // Revision 0.01 - File Created// Additional Comments: ////////////////////////////////////////////////////////////////////////////////////


//设计思想如下://传输的数据里面包含:一个起始位,八个数据位,一个停止位//每一个传输位:分为十六个采集数据点,每个数据采集点在其片段的中点位置,十六位中取其中七位为有效采集数据位前五后四不取,将其中七位数据位进行计算得出来该位为高还是低
module uart_rx_01(clk,Reset_n,uart_rx,Bund_set,Data,Rx_Done    );  input clk;input Reset_n;input uart_rx;input [2:0]Bund_set;output reg [7:0]Data;output reg Rx_Done;reg [1:0] uart_rx_r;always@(posedge clk)beginuart_rx_r[0] <= uart_rx;uart_rx_r[1] <= uart_rx_r[0];endwire pedge_uart_rx;//上升沿//assign pedge_uart_rx = ((uart_rx_r[1] == 0) && (uart_rx_r[0] == 1)) //与下面的功能类似assign pedge_uart_rx = (uart_rx_r == 2'b01);wire nedge_uart_rx;//下降沿assign nedge_uart_rx = (uart_rx_r == 2'b10);//下降沿作为分频计数的开始reg RX_EN;always@(posedge clk or negedge Reset_n)if(!Reset_n)RX_EN <= 0;else if(nedge_uart_rx) //一开始理解有问题,觉得其他的数据中可能存在下降沿会影响RX_EN的使能,多虑了。只需要控制好RX_EN置为0的条件就okRX_EN <= 1;else if(Rx_Done || (sta_bit >= 4)) //数据发送结束或者(起始位传输不对,错误的起始位)RX_EN <= 0;//基本的分频计数器reg [8:0] div_cnt;always@(posedge clk or negedge Reset_n)if(!Reset_n)div_cnt <= 0;else if(RX_EN)beginif(div_cnt == bund_dr - 1)div_cnt <= 0;elsediv_cnt <= div_cnt + 1'b1;endelsediv_cnt <= 0;//波特率转换为计数值门限reg [8:0] bund_dr;always@(*)    //1000000000为一秒钟, 16是将每个数据分为16个采集点, 20为每个时钟周期为20nscase(Bund_set)0: bund_dr <= 1000000000/16/20/9600;1: bund_dr <= 1000000000/16/20/19200;2: bund_dr <= 1000000000/16/20/38400;3: bund_dr <= 1000000000/16/20/57600;4: bund_dr <= 1000000000/16/20/115200;default: bund_dr <= 1000000000/16/20/9600;endcase//每次什么时候进行采集样本,发出一个上升沿信号wire bps_clk_16x;assign bps_clk_16x = (div_cnt == (bund_dr - 1) /2);//二级计数器,计数采集样本的总次数(十个数据需要总共160次)reg[7:0] bps_cnt;always@(posedge clk or negedge Reset_n)if(!Reset_n)bps_cnt <= 0;else if(RX_EN)beginif(bps_clk_16x)beginif(bps_cnt == 160)bps_cnt <= 0;elsebps_cnt <= bps_cnt + 1'b1;endelsebps_cnt <= bps_cnt;endelsebps_cnt <= 0;reg [3:0]data_r[7:0];reg [3:0]sta_bit;reg [3:0]sto_bit;always@(posedge clk or negedge Reset_n)if(!Reset_n)beginsta_bit <= 0;data_r[0] <= 0;data_r[1] <= 0;data_r[2] <= 0;data_r[3] <= 0;data_r[4] <= 0;data_r[5] <= 0;data_r[6] <= 0;data_r[7] <= 0;sto_bit <= 0;endelse if(bps_clk_16x)begincase(bps_cnt)0:beginsta_bit <= 0;data_r[0] <= 0;data_r[1] <= 0;data_r[2] <= 0;data_r[3] <= 0;data_r[4] <= 0;data_r[5] <= 0;data_r[6] <= 0;data_r[7] <= 0;sto_bit <= 0;end5,6,7,8,9,10,11: sta_bit <= sta_bit + uart_rx;21,22,23,24,25,26,27:data_r[0] <= data_r[0] + uart_rx;37,38,39,40,41,42,43:data_r[1] <= data_r[1] + uart_rx;53,54,55,56,57,58,59:data_r[2] <= data_r[2] + uart_rx;69,70,71,72,73,74,75:data_r[3] <= data_r[3] + uart_rx;85,86,87,88,89,90,91:data_r[4] <= data_r[4] + uart_rx;101,102,103,104,105,106,107:data_r[5] <= data_r[5] + uart_rx;117,118,119,120,121,122,123:data_r[6] <= data_r[6] + uart_rx;133,134,135,136,137,138,139:data_r[7] <= data_r[7] + uart_rx;149,150,151,152,153,154,155: sto_bit <= sto_bit + uart_rx;default:;endcaseend//将数据输出到Data上,进行判断,判断其七次累加的结果always@(posedge clk or negedge Reset_n)if(!Reset_n)Data <= 0;else if(bps_clk_16x && (bps_cnt == 160))beginData[0] <= (data_r[0] >= 4)? 1'b1:1'b0;Data[1] <= (data_r[1] >= 4)? 1'b1:1'b0;Data[2] <= (data_r[2] >= 4)? 1'b1:1'b0;Data[3] <= (data_r[3] >= 4)? 1'b1:1'b0;Data[4] <= (data_r[4] >= 4)? 1'b1:1'b0;Data[5] <= (data_r[5] >= 4)? 1'b1:1'b0;Data[6] <= (data_r[6] >= 4)? 1'b1:1'b0;Data[7] <= (data_r[7] >= 4)? 1'b1:1'b0;end//Rx_Done信号的处理always@(posedge clk or negedge Reset_n)if(!Reset_n)Rx_Done <= 0;else if((div_cnt == (bund_dr - 1)/2) && (bps_cnt == 160))Rx_Done <= 1;elseRx_Done <= 0;endmodule

 

posted @ 2022-01-06 15:05  BeerQkq  阅读(169)  评论(0编辑  收藏  举报