4. 使用串口发送5个数据到电脑——基于FPGA的串口发送数据实验

发布时间 2023-09-25 09:37:20作者: daqiaobugong

1. 使用串口发送5个数据到电脑

  • 对于变化的位数(原8)位进行的设计,5个数据即40位。
  • UART规定发送的数据位只能是6、7、8。

1.1 设计思路

  • 对于12位的数据,发送两个字节,高四位变0即可。例如12'h123,按照8'h23和8'h01发送。
  • 两种可能出现的情况:1. 空闲状态,还没有开始发送(上一次的发送已经完成,新的请求Trans_Go还没有出现);2. Trans_Go信号到来;3. 发送数据中。

1.2 设计方案

  1. 情况1时,等待传输信号的到来Trans_Go

  2. 情况2时,Data40 给到模块Uart_Byte_TxData,同时产生Send_Go信号,发送第一个8字节数据。

  3. 情况3时,需要等待Tx_Done信号发送下一个8位的数据。

    • 此时分为两种情况,根据40位发完了没有进行判断:1. 发完,回到情况1;2. 没发完,发送下一个8位。
  • 变量设置

    • Clk 时钟输入
    • Reset_N 复位
    • Data40 外部输入的40位数据
    • Trans_Go 发送信号
    • Uart_Tx 输出信号
    • state 状态信号(0的情况对应第一个字节)
    • Trans_Done 全部40位数据传输完毕信号
  • 通过对状态的控制来分阶段传输5次

  • 状态机思维代码

module Uart_Tx_Data(
    Clk,
    Reset_N,
    Data40,
    Trans_Go,
    Trans_Done,
    Uart_Tx
    );
    
    input Clk;
    input Reset_N;
    input [39:0]Data40;
    input Trans_Go;
    output reg Trans_Done;
    output Uart_Tx;
    reg [7:0]Data;
    reg Send_Go;
    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 [3:0]state;
    always@(posedge Clk or negedge Reset_N)
        if(!Reset_N)begin
            Data <= 0;
            Send_Go <= 0;
            state <= 0;
        end
        else if(state == 0)begin
            Trans_Done <= 0;
            if(Trans_Go)begin
                Data <= Data40[7:0];
                Send_Go <= 1'b1;
                state <= 1'b1;
            end
            else begin
                Data <= Data;
                Send_Go <= 0;
                state <= 0;
            end
        end
         else if(state == 1)begin
            if(Tx_Done)begin
                Data <= Data40[15:8];
                Send_Go <= 1'b1;
                state <= 2'd2;
            end
            else begin
                Data <= Data;
                Send_Go <= 0;
                state <= 1'b1;
            end
         end
         else if(state == 2)begin
            if(Tx_Done)begin
                Data <= Data40[23:16];
                Send_Go <= 1'b1;
                state <= 2'd3;
            end
            else begin
                Data <= Data;
                Send_Go <= 0;
                state <= 2'd2;
            end
         end
         else if(state == 3)begin
            if(Tx_Done)begin
                Data <= Data40[31:24];
                Send_Go <= 1'b1;
                state <= 3'd4;
            end
            else begin
                Data <= Data;
                Send_Go <= 0;
                state <= 2'd3;
            end
         end
         else if(state == 4)begin
            if(Tx_Done)begin
                Data <= Data40[39:32];
                Send_Go <= 1'b1;
                state <= 3'd5;
            end
            else begin
                Data <= Data;
                Send_Go <= 0;
                state <= 3'd4;
            end
         end
         else if(state == 5)begin
            if(Tx_Done)begin
                Send_Go <= 0;
                state <= 0;
                Trans_Done <= 1;
            end
            else begin
                Data <= Data;
                Send_Go <= 0;
                state <= 3'd5;
            end
         end
endmodule

1.3 第二种设计(使用case)

代码

module Uart_Tx_Data2(
    Clk,
    Reset_N,
    Data40,
    Trans_Go,
    Trans_Done,
    Uart_Tx
    );
    
    input Clk;
    input Reset_N;
    input [39:0]Data40;
    input Trans_Go;
    output reg Trans_Done;
    output Uart_Tx;
    reg [7:0]Data;
    reg Send_Go;
    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 [3:0]state;
    always@(posedge Clk or negedge Reset_N)
        if(!Reset_N)begin
            Data <= 0;
            Send_Go <= 0;
            state <= 0;
        end
        else 
        case(state)
            0:begin
                    Trans_Done <= 0;
                    if(Trans_Go)begin
                        Data <= Data40[7:0];
                        Send_Go <= 1'b1;
                        state <= 1'b1;
                    end
                    else begin
                        Data <= Data;
                        Send_Go <= 0;
                        state <= 0;
                    end
                end
             1:begin
                    if(Tx_Done)begin
                        Data <= Data40[15:8];
                        Send_Go <= 1'b1;
                        state <= 2'd2;
                    end
                    else begin
                        Data <= Data;
                        Send_Go <= 0;
                        state <= 1'b1;
                    end
             end
             2:begin
                    if(Tx_Done)begin
                        Data <= Data40[23:16];
                        Send_Go <= 1'b1;
                        state <= 2'd3;
                    end
                    else begin
                        Data <= Data;
                        Send_Go <= 0;
                        state <= 2'd2;
                    end
             end
             3:begin
                    if(Tx_Done)begin
                        Data <= Data40[31:24];
                        Send_Go <= 1'b1;
                        state <= 3'd4;
                    end
                    else begin
                        Data <= Data;
                        Send_Go <= 0;
                        state <= 2'd3;
                    end
             end
             4:begin
                    if(Tx_Done)begin
                        Data <= Data40[39:32];
                        Send_Go <= 1'b1;
                        state <= 3'd5;
                    end
                    else begin
                        Data <= Data;
                        Send_Go <= 0;
                        state <= 3'd4;
                    end
             end
             5:begin
                    if(Tx_Done)begin
        //                Data <= Data40[39:32];
                        Send_Go <= 0;
                        state <= 0;
                        Trans_Done <= 1;
                    end
                    else begin
                        Data <= Data;
                        Send_Go <= 0;
                        state <= 3'd5;
                    end
             end
             default:begin
                        Data <= Data;
                        Send_Go <= 0;
                        state <= 0;
                    end
        endcase
endmodule

1.4 后续任务

  • 优化状态机,实现只要2个或3个状态实现发送的功能,并且易于修改为发送任意字节的数据。
  • 征集不适用状态机的思想来实现本任务的方案。