FPGA 學習筆記(十二) 如何用串口發送32位數據?

在筆者之前所用的串口中,串口一次只能發送數據爲8位,這跟串口通信的協議方式有關係。而最近筆者的項目中需要用到一次發送32位的數據。筆者最開始想到的是32位數據發送4次。
爲了不改動原來的串口通信協議驅動,筆者設計瞭如下發送方式:
設計四個狀態state,每個狀態發送8位數據,發送完畢使能信號txd_flag送給state加一繼續發送下一組8位數據,依次將32位數據發送完畢;

always@(posedge clk or negedge rst_n)
begin 
 if(!rst_n)
        begin
            state<=0;
        end
 else if(txd_flag)
    if(state < 4'd4)
           state<=state+1;
    else
          state<=0;
 else 
            state<=state;
end

檢測state變化,state的每個變化的狀態代表串口輸入的數據不同:
即 state爲0發送32位數據的低8爲,state爲1發送32爲數據的後8位,依次類推;

    if(state==4'd1)
            data<=txd_data[7:0];   
    else if(state==4'd2)
            data<=txd_data[15:8];
    else if(state==4'd3)
            data<=txd_data[23:16];  
    else if(state==4'd4)
            data<=txd_data[31:24];

然後調用原來的串口驅動程序即可


`timescale 1ns/1ns
module uart_transfer
(
    //gobal clock
    input               clk,
    input               rst_n,

    //uart interface
    input               clken_16bps,//clk_bps * 16
    output  reg         txd,        //uart txd interface

    //user interface
    input               txd_en,     //uart data transfer enable
    input       [7:0]   txd_data,   //uart transfer data
    output  reg txd_flag    //uart data transfer done
);

/**************************************************************************
..IDLE...Start...............UART DATA........................End...IDLE...
________                                                     ______________
        |____< D0 >< D1 >< D2 >< D3 >< D4 >< D5 >< D6 >< D7 >
        Bit0  Bit1  Bit2  Bit3  Bit4  Bit5  Bit6  Bit7  Bit8  Bit9
**************************************************************************/
//---------------------------------------
//parameter of uart transfer
localparam  T_IDLE  =   2'b0;   //test the flag to transfer data
localparam  T_SEND  =   2'b1;   //uart transfer data
reg [1:0]   txd_state;          //uart transfer state
reg [3:0]   smp_cnt;            //16 * clk_bps, the center for sample
reg [3:0]   txd_cnt;            //txd data counter
localparam  SMP_TOP     =   4'd15;
localparam  SMP_CENTER  =   4'd7;
always@(posedge clk or negedge rst_n)
begin
    if(!rst_n)
        begin
        smp_cnt <= 0;
        txd_cnt <= 0;   
        txd_state <= T_IDLE;
        end
    else
        begin
        case(txd_state)
        T_IDLE:     
            begin
            smp_cnt <= 0;
            txd_cnt <= 0;
            if(txd_en == 1)
                txd_state <= T_SEND;
            else
                txd_state <= T_IDLE;
            end 
        T_SEND: 
            begin
            if(clken_16bps == 1)
                begin
                smp_cnt <= smp_cnt + 1'b1;
                if(smp_cnt == SMP_TOP)
                    begin
                    if(txd_cnt < 4'd9)
                        begin
                        txd_cnt <= txd_cnt + 1'b1;
                        txd_state <= T_SEND;
                        end
                    else
                        begin
                        txd_cnt <= 0;
                        txd_state <= T_IDLE;
                        end
                    end
                else
                    begin
                    txd_cnt <= txd_cnt;
                    txd_state <= txd_state;
                    end
                end 
            else
                begin
                txd_cnt <= txd_cnt;
                txd_state <= txd_state;
                end
            end     
        endcase
        end
end


//--------------------------------------
//uart 8 bit data transfer
always@(*)
begin
    if(txd_state == T_SEND)
        case(txd_cnt)
        4'd0:   txd = 0;
        4'd1:   txd = txd_data[0];
        4'd2:   txd = txd_data[1];
        4'd3:   txd = txd_data[2];
        4'd4:   txd = txd_data[3];
        4'd5:   txd = txd_data[4];
        4'd6:   txd = txd_data[5];
        4'd7:   txd = txd_data[6];
        4'd8:   txd = txd_data[7];
        4'd9:   txd = 1;
        default:txd = 1;
        endcase
    else
        txd = 1'b1; //default state
end


//-------------------------------------
//Capture the falling of data transfer over
always@(posedge clk or negedge rst_n)
begin
    if(!rst_n)
        txd_flag <= 0;
    else if(clken_16bps == 1 &&  txd_cnt == 4'd9 && smp_cnt == SMP_TOP) //Totally 8 data is done
        txd_flag <= 1;
    else
        txd_flag <= 0;
end

endmodule

以上程序筆者親測可行。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章