用FPGA设计UART协议

UART介绍:

是一种串行、异步、全双工的通信协议,在UART通信协议中信号线上的状态为高电平时代表‘1’,信号线上的状态为低电平时代表‘0’。串行通信是指利用一条传输线将数据一位位地顺序传送,也可以用两个信号线组成全双工通信,如rs232。特点是通信线路简单,利用简单的线缆就可实现通信,

接线图:

时序图:

实验目的:设计一个回传数据的UART模块

(本实验以rs232进行设计)

模块框图:

(本实验参考了野火的UART)

链接:5. 串口rs232 — [野火]FPGA Verilog开发实战指南——基于Altera EP4CE10 征途Pro开发板 文档 (embedfire.com)

uart_rx模块代码

module uart_rx
(
    input   wire        clk_50Mhz       , //系统时钟50Mhz 
    input   wire        rst_n           , //全局复位
    input   wire        rx              , //输入uart_rx信号

    output  reg         flag            , //输出一个字节处理完成的标志
    output  reg [7:0]   data              //输出一个字节的uart_rx并行数据

);

//定义波特率
parameter       UART_BPS        =   'd9600           ;
parameter       CLK_FPEQ        =   'd50_000_000     ;

parameter       BAUD_CNT_MAX    =   CLK_FPEQ/UART_BPS;   

reg rx1;
reg rx2;

reg            start_flag;//数据处理标志
reg            work_en;

reg     [12:0] baud_cnt;//延时计数 
reg            bit_flag;

reg     [3:0]  bit_cnt;
reg     [7:0]  rx_data;
reg            rx_flag;


//对输入信号进行时钟同步
always@(posedge clk_50Mhz or negedge rst_n) begin
    if(rst_n==1'b0) begin
        rx1<=1'b0;
    end
    else begin
        rx1<=rx;
    end    
end

//对rx1信号进行同步,防止亚稳态现象
always@(posedge clk_50Mhz or negedge rst_n) begin
    if(rst_n==1'b0) begin
        rx2<=1'b0;
    end
    else begin
        rx2<=rx1;
    end    
end

//产生数据处理开始标志
always@(posedge clk_50Mhz or negedge rst_n) begin
    if(rst_n == 1'b0) begin
        start_flag <=1'b0;
    end
    else if ((rx2 == 1'b1)&&(rx1 == 1'b0) 
            &&(work_en == 1'b0)) begin
        start_flag <=1'b1;        
    end  
    else begin
        start_flag <=1'b0;
    end   
end

//产生工作使能信号
always@(posedge clk_50Mhz or negedge rst_n) begin
    if(rst_n == 1'b0) begin
        work_en <= 1'b0;
    end
    else if(start_flag==1'b1) begin
        work_en <= 1'b1;
    end
    else if((bit_cnt==4'd8)&&(bit_flag==1'b1)) begin
        work_en <= 1'b0;
    end
    else begin
        work_en <= work_en;
    end        
end

//计数到对应波特率的bit产生一次内部触发信号
always@(posedge clk_50Mhz or negedge rst_n) begin
    if(rst_n == 1'b0) begin
        baud_cnt <= 13'd0;
    end
    else if((baud_cnt == BAUD_CNT_MAX -1)
            ||(work_en ==1'b0)) begin
        baud_cnt <= 13'd0;       
    end
    else begin
        baud_cnt <= baud_cnt +1'b1;
    end      
end


//产生一个bit的触发信号
always@(posedge clk_50Mhz or negedge rst_n) begin
    if(rst_n == 1'b0) begin
        bit_flag <=1'b0;
    end
    else if(baud_cnt==BAUD_CNT_MAX/2-1) begin
        bit_flag <=1'b1;
    end
    else begin
        bit_flag <=1'b0;
    end       
end

//计数bit信号的个数
always@(posedge clk_50Mhz or negedge rst_n) begin
    if(rst_n == 1'b0) begin
        bit_cnt <=4'b0;
    end
    else if((bit_cnt == 4'd8)&&(bit_flag==1'b1)) begin
        bit_cnt <=4'd0;
    end
    else if(bit_flag == 1'b1) begin
        bit_cnt <=bit_cnt + 1'b1;
    end
    else begin
        bit_cnt <=bit_cnt;
    end  
end


//得到并行数据
always@(posedge clk_50Mhz or negedge rst_n) begin
    if(rst_n == 1'b0) begin
        rx_data <=8'd0;
    end
    else if ((bit_cnt>=4'd1)&&(bit_cnt<=4'd8)&&(bit_flag==1'b1)) begin
        rx_data <= {rx2,rx_data[7:1]};
    end
    else begin
        rx_data <= rx_data;
    end         
end

//得到数据处理结束标志   
always@(posedge clk_50Mhz or negedge rst_n) begin
    if(rst_n == 1'b0) begin
        rx_flag <=1'b0;
    end  
    else if((bit_cnt==4'd8)&&(bit_flag==1'b1)) begin
        rx_flag <=1'b1;
    end
    else begin
        rx_flag <=1'b0;
    end        
end

//对数据输出
always@(posedge clk_50Mhz or negedge rst_n) begin
    if(rst_n == 1'b0) begin
        data <=8'd0;
    end 
    else if(rx_flag==1'b1) begin
        data <=rx_data;
    end
    else begin
        data <=data;
    end    
end

//对数据输出数据处理结束标志       
always@(posedge clk_50Mhz or negedge rst_n) begin
    if(rst_n == 1'b0) begin
        flag <=1'b0;
    end
    else begin
        flag <=rx_flag;
    end
            
end

endmodule

uart_tx模块代码

module uart_tx
(
    input   wire        clk_50Mhz           , //系统时钟50Mhz 
    input   wire        rst_n               , //全局复位
    input   wire [7:0]  data                , //输入一个字节的uart_rx并行数据
    input   wire        flag                , //输入一个字节处理开始的标志                                

    output  reg         tx                    //输出一个字节的uart_tx串行信号
);

//定义波特率
parameter       UART_BPS        =   'd9600          ;
parameter       CLK_FPEQ        =   'd50_000_000    ;

parameter       BAUD_CNT_MAX    =   CLK_FPEQ/UART_BPS;    

reg     bit_flag          ,//数据处理标志
        work_en           ;
        
reg[12:0]  baud_cnt        ;//延时计数 

reg[3:0]   bit_cnt         ;//数据处理计数

//产生工作使能信号
always@(posedge clk_50Mhz or negedge rst_n) begin
    if(rst_n==1'b0) begin
        work_en <=1'b0;
    end
    else if (flag ==1'b1) begin
        work_en <=1'b1;
    end
    else if((bit_cnt ==4'd9)&&(bit_flag == 1'b1)) begin
        work_en <=1'b0;
    end
    else begin
        work_en <=work_en;
    end    
end

//计数到对应波特率的bit产生一次内部触发信号
always@(posedge clk_50Mhz or negedge rst_n) begin
    if(rst_n==1'b0) begin
        baud_cnt <= 13'd0;
    end
    else if((baud_cnt ==BAUD_CNT_MAX-1)||(work_en ==1'b0)) begin
        baud_cnt <=13'd0;
    end
    else if(work_en ==1'b1) begin
        baud_cnt <=baud_cnt +1'b1;
    end
    else begin
        baud_cnt <= baud_cnt;
    end    
end

//产生一个bit的触发信号
always@(posedge clk_50Mhz or negedge rst_n) begin
    if(rst_n==1'b0) begin
        bit_flag <=1'b0;
    end
    else if((work_en==1'b1)&&(baud_cnt==13'd0)) begin
        bit_flag <=1'b1;
    end
    else begin
        bit_flag <=1'b0;
    end
end

//计数bit信号的个数
always@(posedge clk_50Mhz or negedge rst_n) begin
    if(rst_n==1'b0) begin
        bit_cnt <=4'b0;
    end 
    else if((bit_cnt ==4'd9)&&(bit_flag ==1'b1)) begin
        bit_cnt <=4'b0;
    end
    else if((work_en ==1'b1)&&(bit_flag ==1'b1)) begin
        bit_cnt <=bit_cnt + 1'b1;
    end
    else begin
        bit_cnt <=bit_cnt;
    end   
end

//输出串行信号
always@(posedge clk_50Mhz or negedge rst_n) begin
    if(rst_n==1'b0) begin
        tx <=1'b1;
    end
    else if(bit_flag ==1'b1) begin
        case(bit_cnt)
            0  : tx <= 1'b0;
            1  : tx <= data[0];
            2  : tx <= data[1];
            3  : tx <= data[2];
            4  : tx <= data[3];
            5  : tx <= data[4];
            6  : tx <= data[5];
            7  : tx <= data[6];
            8  : tx <= data[7];
            9  : tx <= 1'b1;
            default :tx <=1'b1;
        endcase         
    end
end

endmodule    

uart232模块代码


module  uart232(
        input   wire        clk_50Mhz          ,//系统时钟50Mhz 
        input   wire        rst_n              ,//全局复位
        input   wire        rx                 ,//输入uart_rx信号

        output  wire        tx                  //输出uart_tx信号
);

wire    [7:0]   data;
wire            flag;


uart_rx uart_rx_inst
(
    .clk_50Mhz   (clk_50Mhz)    , //系统时钟50Mhz 
    .rst_n       (rst_n)        , //全局复位
    .rx          (rx)           , //输入uart_rx信号
 
    .flag       (flag)          , //输出一个字节处理完成的标志
    .data       (data)            //输出一个字节的uart_rx并行数据

);


uart_tx uart_tx_inst
(
    .clk_50Mhz   (clk_50Mhz)    , //系统时钟50Mhz 
    .rst_n       (rst_n)        , //全局复位
    .data        (data)         , //输入一个字节的uart_rx并行数据
    .flag        (flag)         , //输入一个字节处理开始的标志                                        
    .tx          (tx)             //输出一个字节的uart_tx串行信号
);



endmodule

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值