Verilog之串口(UART)通信

0:起始位,低电平;1~8:数据位;9:校验位,高电平;10:停止位,高电平。

波特率 “9600bps”表示每秒可以传输9600位。  

波特率定时计数器由时钟频率除以波特率。

采集1~8位,忽略0、9、10位。

发送“0、8位数据、1、1”

串口传输数据,从最低位开始,到最高位结束。

串口发送:

module tx_bps_module            
(            
    CLK, RSTn,            
     Count_Sig,         
     BPS_CLK        
);            
            
    input CLK;            
     input RSTn;        
     input Count_Sig;        
     output BPS_CLK;        
             
     /***************************/        
             
     reg [12:0]Count_BPS;        
             
     always @ ( posedge CLK or negedge RSTn )        
        if( !RSTn )        
             Count_BPS <= 13'd0;    
         else if( Count_BPS == 13'd5207 )    
             Count_BPS <= 13'd0;    
         else if( Count_Sig )    
             Count_BPS <= Count_BPS + 1'b1;    
         else    
             Count_BPS <= 13'd0;    
              
     /********************************/        
            
    assign BPS_CLK = ( Count_BPS == 13'd2604 ) ? 1'b1 : 1'b0;            
            
    /*********************************/            
            
endmodule            
module tx_control_module                                
(                                
    CLK, RSTn,                                
     TX_En_Sig, TX_Data, BPS_CLK,                             
    TX_Done_Sig, TX_Pin_Out                                
                                 
);                                
                                
    input CLK;                                
     input RSTn;                            
                                 
     input TX_En_Sig;                            
     input [7:0]TX_Data;                            
     input BPS_CLK;                            
                                 
     output TX_Done_Sig;                            
     output TX_Pin_Out;                            
                                 
     /********************************************************/                            
                                
     reg [3:0]i;                            
     reg rTX;                            
     reg isDone;                            
                                
     always @ ( posedge CLK or negedge RSTn )                            
         if( !RSTn )                            
              begin                        
                  i <= 4'd0;                        
                     rTX <= 1'b1;            
                     isDone     <= 1'b0;        
                end                
          else if( TX_En_Sig )                        
              case ( i )                        
                                
                   4'd0 :                    
                     if( BPS_CLK ) begin i <= i + 1'b1; rTX <= 1'b0; end            
                                 
                     4'd1, 4'd2, 4'd3, 4'd4, 4'd5, 4'd6, 4'd7, 4'd8 :            
                     if( BPS_CLK ) begin i <= i + 1'b1; rTX <= TX_Data[ i - 1 ]; end            
                                 
                     4'd9 :            
                     if( BPS_CLK ) begin i <= i + 1'b1; rTX <= 1'b1; end            
                                  
                     4'd10 :            
                     if( BPS_CLK ) begin i <= i + 1'b1; rTX <= 1'b1; end            
                                 
                     4'd11 :            
                     if( BPS_CLK ) begin i <= i + 1'b1; isDone <= 1'b1; end            
                                 
                     4'd12 :            
                     begin i <= 4'd0; isDone <= 1'b0; end            
                                 
                endcase                
                                
    /********************************************************/                                
                                 
     assign TX_Pin_Out = rTX;                            
     assign TX_Done_Sig = isDone;                            
                                 
     /*********************************************************/                            
                                 
endmodule                                
module tx_module            
(            
    CLK, RSTn,            
     TX_Data, TX_En_Sig,        
     TX_Done_Sig, TX_Pin_Out        
);            
             
     input CLK;            
      input RSTn;        
      input [7:0]TX_Data;        
      input TX_En_Sig;        
      output TX_Done_Sig;        
      output TX_Pin_Out;        
              
              
      /********************************/        
              
      wire BPS_CLK;        
              
      tx_bps_module U1        
      (        
          .CLK( CLK ),        
            .RSTn( RSTn ),
            .Count_Sig( TX_En_Sig ),    // input - from U2
            .BPS_CLK( BPS_CLK )         // output - to U2
      );        
              
      /*********************************/        
              
      tx_control_module U2        
      (        
          .CLK( CLK ),        
            .RSTn( RSTn ),
            .TX_En_Sig( TX_En_Sig ),    // input - from top
            .TX_Data( TX_Data ),        // input - from top
            .BPS_CLK( BPS_CLK ),        // input - from U2
            .TX_Done_Sig( TX_Done_Sig ),  // output - to top
            .TX_Pin_Out( TX_Pin_Out )     // output - to top
      );        
              
      /***********************************/        
            
endmodule            

串口接受

module detect_module                     
(                    
    CLK, RSTn,                    
     RX_Pin_In,                
     H2L_Sig                
);                    
    input CLK;                    
     input RSTn;                
     input RX_Pin_In;                
     output H2L_Sig;                
                     
     /******************************/                
                     
     reg H2L_F1;                
     reg H2L_F2;                
                     
     always @ ( posedge CLK or negedge RSTn )                
         if( !RSTn )                
              begin            
                    H2L_F1 <= 1'b1;    
                     H2L_F2 <= 1'b1;
                end    
          else            
              begin            
                    H2L_F1 <= RX_Pin_In;    
                     H2L_F2 <= H2L_F1;
                end    
                    
    /***************************************/                
                    
    assign H2L_Sig = H2L_F2 & !H2L_F1;                
                    
    /***************************************/                
                    
endmodule                    
module rx_control_module                        
(                        
    CLK, RSTn,                        
     H2L_Sig, RX_Pin_In, BPS_CLK, RX_En_Sig,                    
    Count_Sig, RX_Data, RX_Done_Sig                        
                         
);                        
                        
    input CLK;                        
     input RSTn;                    
                         
     input H2L_Sig;                    
     input RX_En_Sig;                    
     input RX_Pin_In;                    
     input BPS_CLK;                    
                         
     output Count_Sig;                    
     output [7:0]RX_Data;                    
     output RX_Done_Sig;                    
                         
                         
     /********************************************************/                    
                        
     reg [3:0]i;                    
     reg [7:0]rData;                    
     reg isCount;                    
     reg isDone;                    
                        
     always @ ( posedge CLK or negedge RSTn )                    
         if( !RSTn )                    
              begin                 
                  i <= 4'd0;                
                     rData <= 8'd0;    
                     isCount <= 1'b0;    
                     isDone <= 1'b0;     
                end        
          else if( RX_En_Sig )                
              case ( i )                
                        
                   4'd0 :            
                     if( H2L_Sig ) begin i <= i + 1'b1; isCount <= 1'b1; end         /*进入第0位,同时驱动bps_module开始计数。又以bps_module驱动状态1~11*/
                         
                     4'd1 :     
                     if( BPS_CLK ) begin i <= i + 1'b1; end                          /*第0位中部,BPS_CLK发出第一个脉冲,忽略第0位*/
                         
                     4'd2, 4'd3, 4'd4, 4'd5, 4'd6, 4'd7, 4'd8, 4'd9 :    
                     if( BPS_CLK ) begin i <= i + 1'b1; rData[ i - 2 ] <= RX_Pin_In; end    
                         
                     4'd10 :    
                     if( BPS_CLK ) begin i <= i + 1'b1; end    
                         
                     4'd11 :    
                     if( BPS_CLK ) begin i <= i + 1'b1; end    
                         
                     4'd12 :    
                     begin i <= i + 1'b1; isDone <= 1'b1; isCount <= 1'b0; end    
                         
                     4'd13 :    
                     begin i <= 4'd0; isDone <= 1'b0; end    
                         
                endcase        
                        
    /********************************************************/                        
                         
     assign Count_Sig = isCount;                    
     assign RX_Data = rData;                    
     assign RX_Done_Sig = isDone;                    
                         
                         
     /*********************************************************/                    
                         
endmodule                        
module rx_bps_module            
(            
    CLK, RSTn,            
     Count_Sig,         
     BPS_CLK        
);            
            
    input CLK;            
     input RSTn;        
     input Count_Sig;        
     output BPS_CLK;        
             
     /***************************/        
             
     reg [12:0]Count_BPS;        
             
     always @ ( posedge CLK or negedge RSTn )        
        if( !RSTn )        
             Count_BPS <= 13'd0;    
         else if( Count_BPS == 13'd5207 )    
             Count_BPS <= 13'd0;    
         else if( Count_Sig )    
             Count_BPS <= Count_BPS + 1'b1;    
         else    
             Count_BPS <= 13'd0;    
              
     /********************************/        
            
    assign BPS_CLK = ( Count_BPS == 12'd2604 ) ? 1'b1 : 1'b0;            /*周期中间开始采集数据*/
            
    /*********************************/            
            
endmodule            
module rx_module        
(        
    CLK, RSTn,        
    RX_Pin_In, RX_En_Sig,        
     RX_Done_Sig, RX_Data    
);        
        
    input CLK;        
     input RSTn;    
         
     input RX_Pin_In;    
     input RX_En_Sig;    
         
     output [7:0]RX_Data;    
     output RX_Done_Sig;    
         
         
     /**********************************/    
         
     wire H2L_Sig;    
         
     detect_module U1    
     (    
         .CLK( CLK ),    
          .RSTn( RSTn ),
          .RX_Pin_In( RX_Pin_In ),    // input - from top
          .H2L_Sig( H2L_Sig )         // output - to U3
     );    
         
     /**********************************/    
         
     wire BPS_CLK;    
         
     rx_bps_module U2    
     (    
         .CLK( CLK ),    
          .RSTn( RSTn ),
          .Count_Sig( Count_Sig ),   // input - from U3
          .BPS_CLK( BPS_CLK )        // output - to U3
     );    
         
     /**********************************/    
         
     wire Count_Sig;    
         
     rx_control_module U3    
     (    
         .CLK( CLK ),    
          .RSTn( RSTn ),
          
          .H2L_Sig( H2L_Sig ),      // input - from U1
          .RX_En_Sig( RX_En_Sig ),  // input - from top
          .RX_Pin_In( RX_Pin_In ),  // input - from top
          .BPS_CLK( BPS_CLK ),      // input - from U2
          
          .Count_Sig( Count_Sig ),    // output - to U2
          .RX_Data( RX_Data ),        // output - to top
          .RX_Done_Sig( RX_Done_Sig ) // output - to top
          
     );    
         
     /************************************/    
         
        
endmodule        
原文地址:https://www.cnblogs.com/shaogang/p/4107818.html