3. 设计数据采集模块——基于FPGA的串口发送数据实验

发布时间 2023-09-22 20:38:07作者: daqiaobugong

1. 设计数据采集模块

  • 基于Send_en的可控设计。使得使用外部信号Data_done来启动数据发送成为可能。放弃使用Tx_done控制的做法。因此把控制Send_en的逻辑放到内部去完成。这样设计更加符合应用。

1.1 设计要求

  1. Send_en的控制部分放到模块内部去,使用Send_Go作为输入信号
  2. 可能会出现端口的值出现变化,要确保发送的是当Send_Go出现的时刻时,端口中的数据。

1.2 设计思路

1.2.1 针对要求1的设计

  1. Send_en受到Send_Go的控制部分放到模块Uart_Byte_Tx当中,并把Uart_Byte_Tx中的参数Send_en改为Send_Go
  2. 在模块Uart_Tx中每10ms持续产生Send_Go信号,且Send_Go不受Tx_Done信号控制。

1.2.1 针对要求2的设计

  1. 每当接收到Send_Go信号时,缓存Data到变量r_Data当中。

2. 仿真结果

图2-1

  • 可以观察到数据正常发送

3. 最终代码

  • Uart_Byte_Tx代码
module Uart_Byte_Tx(
    Clk,
    Reset_N,
    Data,
    Send_Go,
    Baud_Set,
    Uart_Tx,
    Tx_Done
);

    input Clk;
    input Reset_N;
    input [7:0]Data;
    input Send_Go;
    input [2:0]Baud_Set;
    reg Send_En;
    output reg Uart_Tx;
    output reg Tx_Done;
    
    reg [12:0]Bps_Dr;
    always@(*)
        case(Baud_Set)
            0: Bps_Dr <= 1000000000 / 9600 / 20;
            1: Bps_Dr <= 1000000000 / 19200 / 20;
            2: Bps_Dr <= 1000000000 / 38400 / 20;
            3: Bps_Dr <= 1000000000 / 57600 / 20;
            4: Bps_Dr <= 1000000000 / 115200 / 20;
            default: Bps_Dr <= 1000000000 / 9600 / 20;
        endcase
    
    always@(posedge Clk or negedge Reset_N)
        if(!Reset_N)
            Send_En <= 0;
        else if(Send_Go)
            Send_En <= 1'b1;
        else if(Tx_Done)
            Send_En <= 0;

    reg [7:0]r_Data;
    always@(posedge Clk or negedge Reset_N)
        if(!Reset_N)
            r_Data <= 0;
        else if(Send_Go)
            r_Data <= Data;
        else
            r_Data <= r_Data;
    
    reg [12:0]Div_cnt;
    always@(posedge Clk or negedge Reset_N)
        if(!Reset_N)
            Div_cnt <= 0;
        else if(Send_En)
            if(Div_cnt == Bps_Dr - 1)
                Div_cnt <= 0;
            else
                Div_cnt <= Div_cnt + 1'b1;
        else
            Div_cnt <= 0;
    
    reg [3:0]Bps_cnt;
    wire Bps_Clk;
    assign Bps_Clk = (Div_cnt == 1);
    always@(posedge Clk or negedge Reset_N)
        if(!Reset_N)
            Bps_cnt <= 0;
        else if(Send_En)begin
            if(Bps_Clk)begin
                if(Bps_cnt == 11)
                    Bps_cnt <= 0;
                else
                    Bps_cnt <= Bps_cnt + 1'b1;
            end
        end
        else
            Bps_cnt <= 0;
    
    always@(posedge Clk or negedge Reset_N)
        if(!Reset_N)begin
            Uart_Tx <= 1'b1;
            Tx_Done <= 0;
        end
        else
        case(Bps_cnt)
            1: Uart_Tx <= 0;
            2: Uart_Tx <= r_Data[0];
            3: Uart_Tx <= r_Data[1];
            4: Uart_Tx <= r_Data[2];
            5: Uart_Tx <= r_Data[3];
            6: Uart_Tx <= r_Data[4];
            7: Uart_Tx <= r_Data[5];
            8: Uart_Tx <= r_Data[6];
            9: Uart_Tx <= r_Data[7];
            10: Uart_Tx <= 1'b1;
            11: Uart_Tx <= 1'b1;
            default: Uart_Tx <= 1'b1;
        endcase
            
    always@(posedge Clk or negedge Reset_N)
        if(!Reset_N)
            Tx_Done <= 0;
        else if((Bps_cnt == 10) && Bps_Clk)
            Tx_Done <= 1'b1;
        else
            Tx_Done <= 0;
endmodule
  • Uart_Tx代码
module Uart_Tx(
    Clk,
    Reset_N,
    Uart_Tx
    );
    
    input Clk;
    input Reset_N;
    reg Send_Go;
    output Uart_Tx;
    reg [7:0]Data;
    reg Send_En;
    wire Tx_Done;
    
    Uart_Byte_Tx Uart_Byte_Tx(
        .Clk(Clk),
        .Reset_N(Reset_N),
        .Data(Data),
        .Send_Go(Send_Go),
        .Baud_Set(3'd4),
        .Uart_Tx(Uart_Tx),
        .Tx_Done(Tx_Done)
    );
    
    reg [18:0]cnt;
    always@(posedge Clk or negedge Reset_N)
        if(!Reset_N)
            cnt <= 0;
        else if(cnt == 499999)
            cnt <= 0;
        else
            cnt <= cnt + 1'b1;

    always@(posedge Clk or negedge Reset_N)
        if(!Reset_N)
            Send_Go <= 0;
        else if(cnt == 1)
            Send_Go <= 1;
        else
            Send_Go <= 0;

    always@(posedge Clk or negedge Reset_N)
        if(!Reset_N)
            Data <= 0;
        else if(Tx_Done)
            Data <= Data + 1'b1;
        else
            Data <= Data;
endmodule