module UART ( rst,clk50M,send_en,rev_en,TXD,TXD_data,RXD,RXD_data);
input rst,clk50M,RXD,send_en,rev_en;
input [7:0] TXD_data;
output TXD;
reg TXD;
reg [7:0] TXD_cnt;
output [7:0] RXD_data;
reg [7:0] RXD_data;
reg [7:0] 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[0] ~ d[7];
odd parity :1'b1 XOR d[0] ~ d[7];
*/
reg [11:0] 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[0];
TXD_cnt<=TXD_cnt+8'd1;
end
8'd32 : begin
TXD<=TXD_data[1];
TXD_cnt<=TXD_cnt+8'd1;
end
8'd48 : begin
TXD<=TXD_data[2];
TXD_cnt<=TXD_cnt+8'd1;
end
8'd64 : begin
TXD<=TXD_data[3];
TXD_cnt<=TXD_cnt+8'd1;
end
8'd80 : begin
TXD<=TXD_data[4];
TXD_cnt<=TXD_cnt+8'd1;
end
8'd96 : begin
TXD<=TXD_data[5];
TXD_cnt<=TXD_cnt+8'd1;
end
8'd112 : begin
TXD<=TXD_data[6];
TXD_cnt<=TXD_cnt+8'd1;
end
8'd128 : begin
TXD<=TXD_data[7];
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[0]<=RXD;
RXD_cnt<=RXD_cnt+8'd1;
end
8'd32 : begin
RXD_data[1]<=RXD;
RXD_cnt<=RXD_cnt+8'd1;
end
8'd48 : begin
RXD_data[2]<=RXD;
RXD_cnt<=RXD_cnt+8'd1;
end
8'd64 : begin
RXD_data[3]<=RXD;
RXD_cnt<=RXD_cnt+8'd1;
end
8'd80 : begin
RXD_data[4]<=RXD;
RXD_cnt<=RXD_cnt+8'd1;
end
8'd96 : begin
RXD_data[5]<=RXD;
RXD_cnt<=RXD_cnt+8'd1;
end
8'd112 : begin
RXD_data[6]<=RXD;
RXD_cnt<=RXD_cnt+8'd1;
end
8'd128 : begin
RXD_data[7]<=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 |