FPGA UART

上板验证图片

顶层仿真图片

头文件

//head.v
//UART参数设置
`define  UART_CLK     50_000_000
`define  UART_BPS     115200

 

顶层代码

`include "head.v"
module uart_top
//========================< 绔彛 >==========================================
(
input  wire                 clk                 , //鏃堕挓锛0Mhz
input  wire                 rst_n               , //澶嶄綅锛屼綆鐢靛钩鏈夋晥
input  wire                 rx             , //FPGA閫氳繃涓插彛鎺ユ敹鐨勬暟鎹
output wire                 tx               //FPGA閫氳繃涓插彛鍙戦€佺殑鏁版嵁
);

//========================< 杩炵嚎 >==========================================
wire [7:0]                  data                ;
wire                        data_vld            ;
wire                        tx_status           ;

//==========================================================================
//==    妯″潡渚嬪寲
//==========================================================================
uart_rx
 #(
   .CLK              (`UART_CLK) ,
   .BPS                    (`UART_BPS)   
 )
 
uart_rx_dut
 //========================< 绔彛 >==========================================

(
    .clk(clk)                 , //鏃堕挓锛0Mhz
    .rst_n(rst_n)               , //澶嶄綅锛屼綆鐢靛钩鏈夋晥
    .rx(rx)                 , //杈撳叆鏁版嵁
    .dout(data)                , //杈撳嚭鏁版嵁
    .dout_flag(data_vld)              //杈撳嚭鏁版嵁鐨勬湁鏁堟寚绀
                    );



uart_tx
 #(
   .CLK                 (`UART_CLK) ,
   .BPS                    (`UART_BPS) 
 )
 uart_tx_dut
 //========================< 绔彛 >==========================================

(
    .clk(clk)                , //鏃堕挓锛0Mhz
    .rst_n(rst_n)              , //澶嶄綅锛屼綆鐢靛钩鏈夋晥
    .din(data)                , //闇€瑕佸彂閫佺殑鏁版嵁
    .tx_en(data_vld)              ,//鍙戦€佸厑璁
    .tx(tx)                 , //鍙戦€佸紩鑴
    .tx_status(tx_status)            //鍙戦€佺姸鎬
                    
                    );
                    



endmodule

 

顶层仿真代码

module  uart_top_tb;
//========================< 端口 >==========================================

reg clk;
reg rst_n;
reg rx ;
wire tx;

always #10     clk=~clk;

initial begin
            clk=0;
            rx=1;
            rst_n=0;
            #8681;
            rst_n=1;
            rx=1;
            #8681;

            rx=0;//开始位
            #8681;

            rx=0;//0
            #8681;

            rx=1;//1
            #8681;

            rx=0;//2
            #8681;

            rx=1;//3
            #8681;

            rx=0;//4
            #8681;

            rx=1;//5
            #8681;

            rx=0;//6
            #8681;

            rx=1;//7
            #8681;

            rx=1;//停止位
            #8681;
            #86810;

            rx=0;//开始位
            #8681;

            rx=1;//0
            #8681;

            rx=1;//1
            #8681;

            rx=0;//2
            #8681;

            rx=1;//3
            #8681;

            rx=0;//4
            #8681;

            rx=1;//5
            #8681;

            rx=0;//6
            #8681;

            rx=1;//7
            #8681;

            rx=1;//停止位
            #8681;
            #86810;
            $stop;
end    

uart_top   uart_top_dut(
                       .clk(clk)                 , //时钟,50Mhz
                       .rst_n(rst_n)               , //复位,低电平有效
                       .rx(rx)             , //FPGA通过串口接收的数据
                       .tx (tx)              //FPGA通过串口发送的数据
                         );


endmodule

 

UART RX 代码

module uart_rx
 #(
 parameter  CLK              = 50_000_000        , //系统时钟,50Mhz
 parameter  BPS              = 115200              , //波特率
 parameter  BPS_CNT          = CLK/BPS             //波特率计数
 )
 //========================< 端口 >==========================================

(
                    input   wire                clk                 , //时钟,50Mhz
                    input   wire                rst_n               , //复位,低电平有效
                    input   wire                rx                 , //输入数据
                    output  reg   [7:0]         dout                , //输出数据
                    output  reg                 dout_flag              //输出数据的有效指示
                    );

reg [0:0]   rx1=0,rx2=0,rx3=0;
reg [15:0]  cnt=0;
reg [0:0]   rx_flag=0;
reg [0:0]   rxm_flag=0;
reg [3:0]   bit_cnt=0;

wire [0:0]  rx_en;


assign rx_en=rx3&&~rx2 ;

always @(posedge clk or negedge rst_n)
            begin
                if(rst_n==0)
                        begin
                            rx1<=1'b1;
                            rx2<=1'b1;
                            rx3<=1'b1;
                        end
                else
                        begin
                            rx1<=rx;
                            rx2<=rx1;
                            rx3<=rx2;  
                        end
            end
            
            
always @(posedge clk or negedge rst_n)//开始接收标志
            begin
                if(rst_n==0)                       
                       rx_flag<=1'b0; 
                else if(rx_en==1'b1)
                            rx_flag<=1'b1;
                     else if(bit_cnt>=4'd9)
                                 rx_flag<=1'b0;
                           else
                                 rx_flag<=rx_flag;
            end            

always @ (posedge clk or negedge rst_n  )//比特记数
            begin
                if(rst_n==0)
                    cnt<=16'b0;
                else if(cnt>=BPS_CNT-1'b1)
                        cnt<=16'b0;
                else  if(rx_flag==1'b1)
                        cnt<=cnt+1'b1;
                else
                        cnt<=16'b0;
                      
            end
            
always @ (posedge clk or negedge rst_n  )  //位记数
            begin
                if(rst_n==0)
                    bit_cnt<=4'd0;
                else if(bit_cnt>=4'd9)
                        bit_cnt<=4'd0;
                else if(cnt>=BPS_CNT-1'b1)
                        bit_cnt<=bit_cnt+4'd1;
                     else
                        bit_cnt<=bit_cnt;                
            end 
            
            
always @ (posedge clk or negedge rst_n  )//BIT中间取数标志
            begin
                if(rst_n==0)
                    rxm_flag<=1'b0;
                else if(cnt==BPS_CNT/2-1'b1)
                        rxm_flag<=1'b1;
                else  
                        rxm_flag<=1'b0;           
                      
            end


always @ (posedge clk or negedge rst_n  )//捕获数据
            begin
                if(rst_n==0)
                    dout<=8'b0;
                else if(rxm_flag==1'b1)
                        dout<={rx,dout[7:1]};
                else  
                        dout<=dout;          
                      
            end        
always @ (posedge clk or negedge rst_n  )//8位数据收集完成标志
            begin
                if(rst_n==0)
                    dout_flag<=1'b0;
                else if(bit_cnt>=4'd9)
                        dout_flag<=1'b1;
                else  
                        dout_flag<=1'b0;          
                      
            end   
                 
endmodule

 

UART RX 仿真代码

`include "head.v"
`timescale 1ns/1ns

module uart_rx_tb;

reg     clk               ;
reg     rst_n             ;
reg     rx                ;
wire    [7:0]         dout  ;
wire    dout_flag    ;

always #10     clk=~clk;

initial begin
clk=0;
rst_n=0;
rx=1;
#8681;
rst_n=1;
rx=1;
#8681;

rx=0;//开始位
#8681;

rx=0;//0
#8681;

rx=1;//1
#8681;

rx=0;//2
#8681;

rx=1;//3
#8681;

rx=0;//4
#8681;

rx=1;//5
#8681;

rx=0;//6
#8681;

rx=1;//7
#8681;

rx=1;//停止位
#8681;


rx=0;//开始位
#8681;

rx=1;//0
#8681;

rx=1;//1
#8681;

rx=0;//2
#8681;

rx=1;//3
#8681;

rx=0;//4
#8681;

rx=1;//5
#8681;

rx=0;//6
#8681;

rx=1;//7
#8681;

rx=1;//停止位
#8681;

$stop;
end    

uart_rx   
#( 
   .CLK(`UART_CLK) ,
   .BPS(`UART_BPS)
    )//仿真用
DUT 
(
.clk(clk)                 , //时钟,50Mhz
.rst_n(rst_n)               , //复位,低电平有效
.rx(rx)                 , //输入数据
.dout(dout)                , //输出数据
.dout_flag(dout_flag)              //输出数据的有效指示
                    );
endmodule        

 

UART RX 仿真图片

UART TX 代码

module uart_tx
 #(
 parameter  CLK              = 50_000_000        , //FPGA时钟频率是50MHZ
 parameter  BPS              = 115200              , //娉㈢壒鐜
 parameter  BPS_CNT          = CLK/BPS             //娉㈢壒鐜囪鏁
 )
 //========================< 绔彛 >==========================================

(
    input   wire                clk                ,//FPGA时钟频率是50MHZ
    input   wire                rst_n              ,//澶嶄綅锛屼綆鐢靛钩鏈夋晥
    input   wire   [7:0]        din                ,//闇€瑕佸彂閫佺殑鏁版嵁
    input   wire                tx_en              ,//鍙戦€佸厑璁
    output  reg                 tx                 , //鍙戦€佸紩鑴
    output  reg                 tx_status            //鍙戦€佺姸鎬
                    
                    );
                    
                    
reg [7:0] txdata;
reg [15:0] cnt;
reg [3:0]  bit_cnt;
                    
always @ (posedge clk or negedge rst_n )    //鎺ユ敹闇€瑕佸彂閫佺殑鏁版嵁
            begin
                if(rst_n==0)
                    txdata<=8'b0;
                else  if(tx_en==1  && tx_status==0)
                        txdata<=din;
                else 
                        txdata<=txdata;
                    
            end                
                    
always @ (posedge clk or negedge rst_n )    //鐢熸垚姝e湪鍙戦€佺姸鎬
            begin
                if(rst_n==0)
                    tx_status<=1'b0;
                else  if(tx_en==1)
                        tx_status<=1'b1;
                else  if (bit_cnt>=4'd9)
                          tx_status<=1'b0;
                      else
                          tx_status<=tx_status;
                    
            end    
            
always @ (posedge clk or negedge rst_n )    //璁℃暟鍣
            begin
                if(rst_n==0)
                    cnt<=16'b0; 
                else if(tx_status==1'b1)
                         begin
                               if(cnt>=BPS_CNT-1'b1)
                                        cnt<=16'b0;
                               else
                                        cnt<=cnt+1'b1;                               
                         end
                     else
                        cnt<=16'b0;   
                    
            end       
                     
always @ (posedge clk or negedge rst_n )    //浣嶈鏁板櫒
            begin
                if(rst_n==0)
                     bit_cnt<=4'd0; 
                else if(bit_cnt>=4'd9)
                        bit_cnt<=4'd0;
                else if(cnt>=BPS_CNT-1'b1)
                        bit_cnt<=bit_cnt+4'd1;
                     else
                        bit_cnt<=bit_cnt; 
                        
         
                
            end
            
            
always @ (posedge clk or negedge rst_n )    //鍙戦€佹暟鎹
            begin
                if(rst_n==0)
                     tx<=1'b1; 
                else if(tx_status==1'b1)
                       begin
                            case(bit_cnt)
                                4'd0: tx<=1'b0;
                                4'd1: tx<=txdata[0];
                                4'd2: tx<=txdata[1];
                                4'd3: tx<=txdata[2];
                                4'd4: tx<=txdata[3];
                                4'd5: tx<=txdata[4];
                                4'd6: tx<=txdata[5];
                                4'd7: tx<=txdata[6];
                                4'd8: tx<=txdata[7];
                                4'd9: tx<=1'b1;
                            default :  tx<=1'b1;
                            endcase
                   
                       end
               else                       
                   tx<=1'b1;                    
                     
            end 
                    

                    
endmodule

 

UART TX 仿真代码

`include "head.v"
`timescale 1ns/1ns

module uart_tx_tb;
 
reg clk;
reg rst_n;
reg [7:0] din;
reg tx_en;

wire tx;
wire tx_status; 



initial begin
   clk=0;
   rst_n=0;
   din=16'h00;
   tx_en=0;
   #8681;
   rst_n=1;
   din=16'haa;
   tx_en=1;
   #20;
   tx_en=0; 
   #86810;
   #8681;
   din=16'hab;
   tx_en=1;
   #20;
   tx_en=0;
   #86810;
   #8681;
   $stop;

end 


always #10 clk=~clk;
 
uart_tx 
 #(
   .CLK(`UART_CLK) ,
   .BPS(`UART_BPS)
 )
tx_dut
 //========================< 端口 >==========================================

(
    .clk (clk)               , //时钟,50Mhz
    .rst_n(rst_n)              , //复位,低电平有效
    .din (din)               , //需要发送的数据
    .tx_en(tx_en)              ,//发送允许
    .tx   (tx)              , //发送引脚
    .tx_status(tx_status)            //发送状态
                    
                    );
                    
                    
endmodule

 

UART TX 仿真图片

posted @ 2020-11-27 15:14  xgj_0817  阅读(116)  评论(0编辑  收藏  举报