fpga串口通信的verilog驱动

  串口的全程为串行接口,也称为串行通信接口,是采用串行通信方式的扩展接口。与串口对应的并行接口,例如高速AD和DA,

这些都是用的并行接口,而且在编程也简单一些。

  串口有一下特点:

  (1)通信线路简单,只要一对传输线就可以实现双向通信。

  (2)布线简单,成本低。

  (3)通信距离长,可以实现数米到数千米的通信距离。

  (4)传输速率慢。

  常见的串口速率如4800 , 9600 , 115200bps,代表每秒钟发送多少bit数据,例如9600bps就代表1秒内发送9600bit数据。 

  串口协议 : 协议比较简单,一般都是10位数据,1个起始位 低电平 ,然后八个数据位,低位在前,一个奇偶校验位,平时

一般不用,最后是一位停止位高电平,这样一帧数据发送结束。

  下面介绍一下我的程序框架:

    整体框架分为两个部分:一个是串口驱动部分 另一个是串口数据控制部分。串口驱动部分负责串口驱动和波特率的选择,串口数据控制模块

  负责控制数据内容的控制和发送速度的控制。

从上面时序图可以看出,每10ms发送一帧数据,这里data_en负责波特率驱动使能,uart_tx_end有两个功能,一个是关闭data_en使能,另一个是给10ms计数器

清零。

/*-----------------------------------------------------------------------

Date                :        2017-09-03
Description            :        Design for uart_driver.

-----------------------------------------------------------------------*/

module uart_tx_driver
(
    //global clock
    input                    clk            ,        //system clock
    input                    rst_n        ,         //sync reset
    
    //uart interface
    output    reg                uart_tx        ,

    //user interface
    input            [1:0]    bps_select    ,        //波特率选择
    input            [7:0]    uart_data    ,        
    input                    data_en        ,        //发送数据使能
    output    reg                uart_tx_end    
); 


//--------------------------------
//Funtion :    参数定义

parameter            BPS_4800    =    14'd10417    ,
                    BPS_9600    =    14'd5208    ,
                    BPS_115200    =    14'd434        ;

reg            [13:0]        cnt_bps_clk                ;
reg            [13:0]        bps                        ;
reg                        bps_clk_en                ;    //bps使能时钟
reg            [3:0]        bps_cnt                    ;
wire        [13:0]        BPS_CLK_V = bps >> 1    ;
//--------------------------------
//Funtion :    波特率选择          

always @(posedge clk or negedge rst_n)
begin
    if(!rst_n)
        bps <= 1'd0;
    else if(bps_select == 2'd0)
        bps <= BPS_115200;
    else if(bps_select == 2'd1)
        bps <= BPS_9600;
    else
        bps <= BPS_4800;
end

//--------------------------------
//Funtion :    波特率计数

always @(posedge clk or negedge rst_n)
begin
    if(!rst_n)
        cnt_bps_clk <= 1'd0;
    else if(cnt_bps_clk >= bps - 1 && data_en == 1'b0)
        cnt_bps_clk <= 1'd0;
    else
        cnt_bps_clk <= cnt_bps_clk + 1'd1;
end
 
//--------------------------------
//Funtion :    波特率使能时钟

always @(posedge clk or negedge rst_n)
begin
    if(!rst_n)
        bps_clk_en <= 1'd0;
    else if(cnt_bps_clk == BPS_CLK_V - 1)
        bps_clk_en <= 1'd1;
    else
        bps_clk_en <= 1'd0;
end

//--------------------------------
//Funtion :    波特率帧计数

always @(posedge clk or negedge rst_n)
begin
    if(!rst_n)
        bps_cnt <= 1'd0;
    else if(bps_cnt == 11)
        bps_cnt <= 1'd0;
    else if(bps_clk_en)
        bps_cnt <= bps_cnt + 1'd1;
end

//--------------------------------
//Funtion :    uart_tx_end

always @(posedge clk or negedge rst_n)
begin
    if(!rst_n)
        uart_tx_end <= 1'd0;
    else if(bps_cnt == 11)
        uart_tx_end <= 1'd1;
    else
        uart_tx_end <= 1'd0;
end


//--------------------------------
//Funtion :       发送数据

always @(posedge clk or negedge rst_n)
begin
    if(!rst_n)
        uart_tx <= 1'd1;
    else case(bps_cnt)
        4'd0     : uart_tx <= 1'd1; 
        
        4'd1     : uart_tx <= 1'd0; //begin
        4'd2     : uart_tx <= uart_data[0];//data
        4'd3     : uart_tx <= uart_data[1];
        4'd4     : uart_tx <= uart_data[2];
        4'd5     : uart_tx <= uart_data[3];
        4'd6     : uart_tx <= uart_data[4];
        4'd7    : uart_tx <= uart_data[5];
        4'd8     : uart_tx <= uart_data[6];
        4'd9     : uart_tx <= uart_data[7];
        
        4'd10     : uart_tx <= 1; //stop
        default : uart_tx <= 1;    
    endcase
end




endmodule
    
/*-----------------------------------------------------------------------

Date                :        2017-XX-XX
Description            :        Design for .

-----------------------------------------------------------------------*/

module uart_tx_control
(
    //global clock
    input                    clk                ,            //system clock
    input                    rst_n            ,             //sync reset
    
    //user interface
    output    reg        [7:0]    uart_data        ,
    output    reg                data_en            ,
    input                    uart_tx_end
    
); 


//--------------------------------
//Funtion :  参数定义

parameter            DELAY_10MS        =        500_000                ;
reg        [31:0]        cnt_10ms            ;
wire                delay_10ms_done        ;             


//data    define
reg        [31:0]        cnt_1s;                        


//--------------------------------
//Funtion :  cnt_10ms

always @(posedge clk or negedge rst_n)
begin
    if(!rst_n)
        cnt_10ms <= 1'd0;
    else if(cnt_10ms == DELAY_10MS - 1 && uart_tx_end == 1'd1)
        cnt_10ms <= 1'd0;
    else 
        cnt_10ms <= cnt_10ms + 1'd1;
end

assign        delay_10ms_done    =    (cnt_10ms == DELAY_10MS - 1) ? 1'd1 : 1'd0;



//--------------------------------
//Funtion :  data_en

always @(posedge clk or negedge rst_n)
begin
    if(!rst_n)
        data_en <= 1'd0;
    else if(delay_10ms_done)
        data_en <= 1'd1;
    else if(uart_tx_end)
        data_en <= 1'd0;
end


///////////////////////数据测试/////////////////////////////
//--------------------------------
//Funtion :  cnt_1s

always @(posedge clk or negedge rst_n)
begin
    if(!rst_n)
        cnt_1s <= 1'd0;
    else if(cnt_1s == 49_999_999)
        cnt_1s <= 1'd0;
    else    
        cnt_1s <= cnt_1s + 1'd1;
end

//--------------------------------
//Funtion : uart_data

always @(posedge clk or negedge rst_n)
begin
    if(!rst_n)
        uart_data <= 1'd0;
    else if(uart_data >= 10)
        uart_data <= 1'd0;
    else if(cnt_1s == 49_999_999)
        uart_data <= uart_data + 1'd1;
end




endmodule
    
原文地址:https://www.cnblogs.com/bixiaopengblog/p/6048300.html