发送:
module clkdiv(clk_50m, clk_out, reset_n);
input clk_50m;
output clk_out;
input reset_n;
reg clk_out;
reg [15:0] counter;
always @(posedge clk_50m or negedge reset_n)
begin
if (!reset_n)
begin
clk_out <= 0;
counter <= 0;
end
else if (counter == 16'd162)
begin
clk_out <= 1;
counter <= counter + 1;
end
else if (counter == 16'd325)
begin
clk_out <= 0;
counter <= 0;
end
else
begin
counter <= counter + 1 ;
end
end
endmodule
module test_uart(clk,reset_n,DATA_out,WriteSignal);
input clk;
input reset_n;
output [7:0] DATA_out;
output WriteSignal;
reg [7:0] DATA_out;
reg WriteSignal;
reg [7:0] counter;
always @(posedge clk or negedge reset_n)
begin
if (!reset_n)
begin
counter <= 0;
WriteSignal <= 0;
end
else
begin
if (counter ==254)
begin
DATA_out <= DATA_out + 1;
WriteSignal <= 1;
counter <= 0;
end
else
begin
WriteSignal <= 0;
counter = counter + 1;
end
end
end
endmodule
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Module Name: uarttx
// 说明:16个clock发送一个bit, 一个起始位,8个数据位,一个校验位,一个停止位
//////////////////////////////////////////////////////////////////////////////////
module uarttx(clk, rst_n, datain, wrsig, idle, tx);
input clk; //UART时钟
input rst_n; //系统复位
input [7:0] datain; //需要发送的数据
input wrsig; //发送命令,上升沿有效
output idle; //线路状态指示,高为线路忙,低为线路空闲
output tx; //发送数据信号
reg idle, tx;
reg send;
reg wrsigbuf, wrsigrise;
reg presult;
reg[7:0] cnt; //计数器
parameter paritymode = 1'b0;
////////////////////////////////////////////////////////////////
//检测发送命令wrsig的上升沿
////////////////////////////////////////////////////////////////
always @(posedge clk)
begin
wrsigbuf <= wrsig;
wrsigrise <= (~wrsigbuf) & wrsig;
end
////////////////////////////////////////////////////////////////
//启动串口发送程序
////////////////////////////////////////////////////////////////
always @(posedge clk)
begin
if (wrsigrise && (~idle)) //当发送命令有效且线路为空闲时,启动新的数据发送进程
begin
send <= 1'b1;
end
else if(cnt == 8'd168) //一帧数据发送结束
begin
send <= 1'b0;
end
end
////////////////////////////////////////////////////////////////
//串口发送程序, 16个时钟发送一个bit
////////////////////////////////////////////////////////////////
always @(posedge clk or negedge rst_n)
begin
if (!rst_n) begin
tx <= 1'b0;
idle <= 1'b0;
cnt<=8'd0;
presult<=1'b0;
end
else if(send == 1'b1) begin
case(cnt) //产生起始位
8'd0: begin
tx <= 1'b0;
idle <= 1'b1;
cnt <= cnt + 8'd1;
end
8'd16: begin
tx <= datain[0]; //发送数据0位
presult <= datain[0]^paritymode;
idle <= 1'b1;
cnt <= cnt + 8'd1;
end
8'd32: begin
tx <= datain[1]; //发送数据1位
presult <= datain[1]^presult;
idle <= 1'b1;
cnt <= cnt + 8'd1;
end
8'd48: begin
tx <= datain[2]; //发送数据2位
presult <= datain[2]^presult;
idle <= 1'b1;
cnt <= cnt + 8'd1;
end
8'd64: begin
tx <= datain[3]; //发送数据3位
presult <= datain[3]^presult;
idle <= 1'b1;
cnt <= cnt + 8'd1;
end
8'd80: begin
tx <= datain[4]; //发送数据4位
presult <= datain[4]^presult;
idle <= 1'b1;
cnt <= cnt + 8'd1;
end
8'd96: begin
tx <= datain[5]; //发送数据5位
presult <= datain[5]^presult;
idle <= 1'b1;
cnt <= cnt + 8'd1;
end
8'd112: begin
tx <= datain[6]; //发送数据6位
presult <= datain[6]^presult;
idle <= 1'b1;
cnt <= cnt + 8'd1;
end
8'd128: begin
tx <= datain[7]; //发送数据7位
// presult <= datain[7]^presult;
idle <= 1'b1;
cnt <= cnt + 8'd1;
end
8'd144: begin
tx <= presult; //发送奇偶校验位
presult <= datain[0]^paritymode;
idle <= 1'b1;
cnt <= cnt + 8'd1;
end
8'd160: begin
tx <= 1'b1; //发送停止位
idle <= 1'b1;
cnt <= cnt + 8'd1;
end
8'd168: begin
tx <= 1'b1;
idle <= 1'b0; //一帧数据发送结束
cnt <= cnt + 8'd1;
end
default: begin
cnt <= cnt + 8'd1;
end
endcase
end
else begin
tx <= 1'b1;
cnt <= 8'd0;
idle <= 1'b0;
end
end
endmodule
(原理图文件)顶层:
结果:
接收:
module uartrx(clock,reset_n,rx,DATAout,ReadSignal,idle,DataError,FrameError);
input clock;
input reset_n;
input rx;
output DATAout;
output ReadSignal;
output DataError;
output FrameError;
output idle;
reg [7:0] DATAout;
reg ReadSignal,DataError,FrameError;
reg [7:0] counter;
reg ReceiveBuffer,ReceiveFall,receive;
reg presult,idle;
parameter paritymode = 1'b0;
//检测接受命令rx的下降沿
always @(posedge clock)
begin
ReceiveBuffer <= rx;
ReceiveFall <= ReceiveBuffer &(~rx);
end
//接收状态的表示
always @(posedge clock)
begin
if(ReceiveFall && (~idle))
begin
receive <= 1'b1;
end
else if (counter == 8'd168)
begin
receive <= 1'b0;
end
end
//串口接收,每16个clock接收同一个bit
always @(posedge clock or negedge reset_n )
begin
if (!reset_n)
begin
idle <= 1'b0;
counter <= 8'b0;
ReadSignal <= 1'b0;
FrameError <= 1'b0;
DataError <= 1'b0;
presult <= 1'b0;
end
else if(receive == 1'b1)
begin
case(counter)
8'd0 :begin
idle <= 1'b1;
counter <= counter + 8'b1;
ReadSignal <= 1'b0;
end
8'd24:begin
idle <= 1'b1;
DATAout[0] <= rx;
presult <= paritymode ^ rx;
counter <= counter + 8'd1;
ReadSignal <= 1'b0;
end
8'd40 :begin
idle <= 1'b1;
DATAout[1] <= rx;
presult <= presult ^rx;
counter <= counter + 8'b1;
ReadSignal <= 1'b0;
end
8'd56 :begin
idle <= 1'b1;
DATAout[2] <= rx;
presult <= presult ^rx;
counter <= counter + 8'b1;
ReadSignal <= 1'b0;
end
8'd72 :begin
idle <= 1'b1;
DATAout[3] <= rx ;
presult <= presult ^ rx;
counter <= counter +8'b1;
ReadSignal <= 1'b0;
end
8'd88:begin
idle <= 1'b1;
DATAout[4] <= rx;
presult <= presult ^ rx;
counter <= counter + 8'b1;
ReadSignal <= 1'b0;
end
8'd104:begin
idle <= 1'b1;
DATAout[5] <= rx;
presult <= presult ^ rx;
counter <= counter + 8'b1;
ReadSignal <= 1'b0;
end
8'd120:begin
idle <= 1'b1;
DATAout[6] <= rx;
presult <= presult ^ rx;
counter <= counter + 8'b1;
ReadSignal <= 1'b0;
end
8'd136:begin
idle <= 1'b1;
DATAout[7] <= rx;
presult <= presult ^rx;
counter <= counter + 8'b1;
ReadSignal <= 1'b0;
end
8'd152:begin
idle <= 1'b1;
if (presult == rx)
DataError <= 1'b0;
else
DataError <= 1'b1;
counter <= counter + 8'b1;
ReadSignal <= 1'b1;
end
8'd168:begin
idle <= 1'b1;
if(1'b1 == rx)
FrameError <= 1'b0;
else
FrameError <= 1'b1;
counter <= counter + 8'b1;
ReadSignal <= 1'b1;
end
default:begin
counter <= counter + 8'b1;
end
endcase
end
else
begin
counter <= 8'd0;
idle <= 1'b0;
ReadSignal <= 1'b0;
end
end
endmodule
原理图文件(顶层):
结果:
使用锁相环来加速或者放缓UART的传输速度:
c0是25MHz,c1是100MHz,不知为何无法在串口助手中无结果显示。