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

以上程序笔者亲测可行。

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