羽蒙 发表于 2014-7-13 16:51:19

FPGA实现UART收发器


module UART ( rst,clk50M,send_en,rev_en,TXD,TXD_data,RXD,RXD_data);
input rst,clk50M,RXD,send_en,rev_en;
input TXD_data;
output TXD;
reg TXD;
reg TXD_cnt;

output RXD_data;
reg RXD_data;
reg RXD_cnt;

parameter baud=9600;      //any baud is OK;
//frediv = fclk/(16*baud)
//e.g. fclk=50M,9600 baud,frediv=326
/*parity check
even parity:1'b0 XOR d ~ d;
odd parity :1'b1 XOR d ~ d;
*/
reg fre_cnt;
reg clk_baud;
always@(negedge rst or posedge clk50M)
      if(!rst)
                fre_cnt<=1'b0;
      else
                if(clk50M)                                                
                        if(fre_cnt==(50000000/(16*baud)))
                              fre_cnt<=1'b0;
                        else
                              begin
                              fre_cnt<=fre_cnt+1'b1;
                              if(fre_cnt<=(50000000/(16*baud))/2)
                                        clk_baud<=1'b1;
                              else
                                        clk_baud<=1'b0;
                              end
                              
always@(negedge rst or posedge clk_baud)
      if(!rst)
                begin
                TXD_cnt<=1'd0;
                TXD<=1'b1;
                end
      else
                if(clk_baud)
                        begin
                        if(send_en)
                              case(TXD_cnt)
                                        8'd0      :      begin
                                                                TXD<=1'b0;
                                                                TXD_cnt<=TXD_cnt+8'd1;
                                                                end
                                        8'd16      :         begin
                                                                TXD<=TXD_data;
                                                                TXD_cnt<=TXD_cnt+8'd1;
                                                                end
                                        8'd32      :         begin
                                                                TXD<=TXD_data;
                                                                TXD_cnt<=TXD_cnt+8'd1;
                                                                end                        
                                        8'd48      :         begin
                                                                TXD<=TXD_data;
                                                                TXD_cnt<=TXD_cnt+8'd1;
                                                                end
                                        8'd64      :         begin
                                                                TXD<=TXD_data;
                                                                TXD_cnt<=TXD_cnt+8'd1;
                                                                end
                                        8'd80      :         begin
                                                                TXD<=TXD_data;
                                                                TXD_cnt<=TXD_cnt+8'd1;
                                                                end
                                        8'd96      :         begin
                                                                TXD<=TXD_data;
                                                                TXD_cnt<=TXD_cnt+8'd1;
                                                                end
                                        8'd112      :         begin
                                                                TXD<=TXD_data;
                                                                TXD_cnt<=TXD_cnt+8'd1;
                                                                end
                                        8'd128      :         begin
                                                                TXD<=TXD_data;
                                                                TXD_cnt<=TXD_cnt+8'd1;
                                                                end
                                        8'd144      :         begin
                                                                TXD<=1'b1;
                                                                TXD_cnt<=TXD_cnt+8'd1;
                                                                end
                                        8'd160      :      TXD_cnt<=8'd0;
                                        default      :      TXD_cnt<=TXD_cnt+8'd1;
                              endcase
                        else
                              begin
                              TXD<=1'b1;
                              TXD_cnt<=8'd0;
                              end
                end
                              
      
always@(negedge rst or posedge clk_baud)
      if(!rst)               
                RXD_cnt<=1'd0;               
      else
                if(clk_baud)
                        begin
                        if(rev_en)                        
                              case(RXD_cnt)
                                        8'd0      :      if(!RXD)
                                                                        RXD_cnt<=RXD_cnt+8'd1;
                                                                else
                                                                        RXD_cnt<=8'd0;                                                      
                                        8'd16      :         begin
                                                                RXD_data<=RXD;
                                                                RXD_cnt<=RXD_cnt+8'd1;
                                                                end
                                        8'd32      :         begin
                                                                RXD_data<=RXD;
                                                                RXD_cnt<=RXD_cnt+8'd1;
                                                                end                        
                                        8'd48      :         begin
                                                                RXD_data<=RXD;
                                                                RXD_cnt<=RXD_cnt+8'd1;
                                                                end
                                        8'd64      :         begin
                                                                RXD_data<=RXD;
                                                                RXD_cnt<=RXD_cnt+8'd1;
                                                                end
                                        8'd80      :         begin
                                                                RXD_data<=RXD;
                                                                RXD_cnt<=RXD_cnt+8'd1;
                                                                end
                                        8'd96      :         begin
                                                                RXD_data<=RXD;
                                                                RXD_cnt<=RXD_cnt+8'd1;
                                                                end
                                        8'd112      :         begin
                                                                RXD_data<=RXD;
                                                                RXD_cnt<=RXD_cnt+8'd1;
                                                                end
                                        8'd128      :         begin
                                                                RXD_data<=RXD;
                                                                RXD_cnt<=RXD_cnt+8'd1;
                                                                end
                                        8'd144      :         if(RXD)
                                                                        RXD_cnt<=RXD_cnt+8'd1;
                                                                else
                                                                        RXD_cnt<=8'd144;
                                        8'd160      :      RXD_cnt<=8'd0;
                                        default      :      RXD_cnt<=RXD_cnt+8'd1;
                              endcase
                        else
                              RXD_cnt<=8'd0;
                end
                              
endmodule

zhiweiqiang33 发表于 2014-7-15 17:13:17

多谢分享 很实用
页: [1]
查看完整版本: FPGA实现UART收发器