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 多谢分享 很实用
页:
[1]