1、设计想法

原理与之前的串口发送模块一样,1位的数据位和8位的数据位再加上1位的停止位。唯一不同的是在接收的时候要考虑到有干扰的情况下,为了避免干扰,我们对每位数据进行多次采样,按出现概率大的值为该数据位的值。

如果按照通常想法在每bits位中间取值的话,bit3位出现图中的干扰很有可能会读出错误的值。所以需要对每位进行多次抽样进行判断。

每位要抽8次的话,那需要将每个波特段分成9等分。

2、状态机设定

3、模块代码

`timescale 1ns / 1ps//////////////////////////////////////////////////////////////////////////////////// Company: // Engineer: Lclone// // Create Date: 2022/12/16 15:37:44// Design Name: uart_byte_rx// Module Name: uart_byte_rx// Project Name: uart_byte_rx// Target Devices: // Tool Versions: // Description: 8位串口发送模块// // Dependencies: // // Revision:// Revision 0.01 - File Created// Additional Comments:// //////////////////////////////////////////////////////////////////////////////////module uart_byte_rx  # (        parameter   RX_BAUD  = 9600,//波特率        parameter   CLK_FQC  = 50_000_000,//模块时钟频率        parameter   BAUD_CNT = CLK_FQC/RX_BAUD)//模块每波特需要计数的次数(设置此端口方便仿真用)    (        input               Clk,//时钟频率接口        input               Rst_n,//复位接口        input               Uart_rx,//串口接收接口        output  reg  [7:0]  Data//接收到的数据接口    );        reg            uart_rx_r;//延一拍    reg            uart_rx_rr;//延两拍    reg            receiv_begin;//接收开始信号    reg            receiv_flag;//接收状态信号    reg   [ 3:0]   state;//状态机寄存器    reg   [15:0]   baud_cnt;//波及计数器    reg   [ 3:0]   sampel_cnt;//采样计数器    reg            sampel_en;//采样使能    reg            sampel_ref;//样本寄存器    reg   [ 3:0]   acc;//累加寄存器    reg   [ 3:0]   bit_cnt;//数据位寄存器        always @(posedge Clk) begin   //下降沿捕获        uart_rx_r <= Uart_rx;        uart_rx_rr <= uart_rx_r;    end        always @(posedge Clk or negedge Rst_n) begin//接收信号发生        if(Rst_n == 0)            receiv_begin <= 0;        else if(state == 0 & uart_rx_rr & ~uart_rx_r)            receiv_begin <= 1'b1;        else            receiv_begin <= 0;                end        always @(posedge Clk or negedge Rst_n) begin//状态机        if(Rst_n == 0) begin            state <= 0;            sampel_ref <= 8'b0;            acc <= 8'b0;            Data <= 8'b0;        end        else case(state)            0: //空闲状态                if(receiv_begin == 1)                    state <= 3'd1;                else                    state <= 0;                        1: begin//抽样状态                    if(sampel_en == 1) begin                           sampel_ref <= Uart_rx;                           state <= 3'd2;                    end                    else                        state <= 3'b1;               end                                   2: begin//数据判断状态                    acc = 4)                            begin Data[7] <= 1'b1; state <= 3'd3;acc <= 8'b0; end                        else                            begin Data[7] <= 0; state <= 3'd3;acc <= 8'b0; end                    end                                        else                        state <= 3'd1;               end                                        3: begin//数据移位状态                    if(bit_cnt < 8) begin                        Data > 1;                        state <= 3'd1;                     end                                        else                         state <= 0;            end                        default:;       endcase    end        always @(posedge Clk or negedge Rst_n) begin//接收进行标志        if(Rst_n == 0)            receiv_flag <= 0;        else if(receiv_begin == 1)            receiv_flag <= 1'b1;        else if(bit_cnt == 9 & baud_cnt == BAUD_CNT - 1)            receiv_flag <= 1'b0;    end        always @(posedge Clk or negedge Rst_n) begin//波特计数        if(Rst_n == 0)                 baud_cnt <= 0;        else if(receiv_flag == 1) begin            if(baud_cnt == BAUD_CNT - 1)                baud_cnt <= 0;            else                baud_cnt <= baud_cnt + 1'b1;            end        else            baud_cnt <= 0;          end        always @(posedge Clk or negedge Rst_n) begin//采样计数        if(Rst_n == 0) begin            sampel_cnt <= 0;            sampel_en <= 0;        end        else if(receiv_flag == 1) begin            case(baud_cnt)                BAUD_CNT/9*1-1 : begin sampel_cnt <= 0; sampel_en <=1; end                BAUD_CNT/9*2-1 : begin sampel_cnt <= 1; sampel_en <=1; end                BAUD_CNT/9*3-1 : begin sampel_cnt <= 2; sampel_en <=1; end                BAUD_CNT/9*4-1 : begin sampel_cnt <= 3; sampel_en <=1; end                BAUD_CNT/9*5-1 : begin sampel_cnt <= 4; sampel_en <=1; end                BAUD_CNT/9*6-1 : begin sampel_cnt <= 5; sampel_en <=1; end                BAUD_CNT/9*7-1 : begin sampel_cnt <= 6; sampel_en <=1; end                BAUD_CNT/9*8-1 : begin sampel_cnt <= 7; sampel_en <=1; end                BAUD_CNT/9*9-1 : sampel_cnt <= 0;                default:sampel_en <=0;            endcase        end    end        always @(posedge Clk or negedge Rst_n) begin//数据位计数        if(Rst_n == 0)            bit_cnt <= 0;        else if(bit_cnt == 9 & baud_cnt == BAUD_CNT - 1)            bit_cnt <= 0;        else if(baud_cnt == BAUD_CNT - 1)            bit_cnt <= bit_cnt + 1'b1;    endendmodule

4、仿真验证(1)仿真激励文件

`timescale 1ns / 1ps//////////////////////////////////////////////////////////////////////////////////// Company: // Engineer: // // Create Date: 2022/12/16 21:36:04// Design Name: // Module Name: uart_byte_rx_tb// Project Name: // Target Devices: // Tool Versions: // Description: // // Dependencies: // // Revision:// Revision 0.01 - File Created// Additional Comments:// //////////////////////////////////////////////////////////////////////////////////module uart_byte_rx_tb();        reg        CLK_50M;    reg        RST_N;    wire [7:0] Data;        reg        Uart_rx;    reg  [7:0] test_data;    uart_byte_rx   # (        .RX_BAUD   (9600),        .CLK_FQC   (50_000_000),        .BAUD_CNT  (50))    uart_byte_rx_inst    (        .Clk        (CLK_50M),        .Rst_n      (RST_N),        .Uart_rx    (Uart_rx),        .Data       (Data)    );            always #10 CLK_50M  <= ~CLK_50M;        initial begin    CLK_50M <= 1'b0;    RST_N   <= 1'b0;    Uart_rx <= 1'b1;    test_data <= 8'h0;    #100    RST_N   <= 1'b1;    #20        test_data <= 8'haf;        #1000        Uart_rx <= 1'b0;        #1000                     Uart_rx <= test_data[0];        #1000                     Uart_rx <= test_data[1];        #1000                     Uart_rx <= test_data[2];        #1000                     Uart_rx <= test_data[3];        #1000                     Uart_rx <= test_data[4];        #1000                     Uart_rx <= test_data[5];        #1000                     Uart_rx <= test_data[6];        #1000                     Uart_rx <= test_data[7];        #1000                     Uart_rx <= 1'b1;     #1000        test_data <= 8'h56;        #1000        Uart_rx <= 1'b0;        #1000                     Uart_rx <= test_data[0];        #1000                     Uart_rx <= test_data[1];        #1000                     Uart_rx <= test_data[2];        #1000                     Uart_rx <= test_data[3];        #1000                     Uart_rx <= test_data[4];        #1000                     Uart_rx <= test_data[5];        #1000                     Uart_rx <= test_data[6];        #1000                     Uart_rx <= test_data[7];        #1000                     Uart_rx <= 1'b1;    #1000    $stop;    end        endmodule

(2)仿真结果