📄 uart_my.txt
字号:
/**********************************************************************
**
**-------------------------------------------文件信息----------------------------------------------------------
** 文件名称: uart_test.v
** 创建者:
** 创建日期: 2008
** 版本号: V3.0
** 功能描述: 串口通信顶层模块
**
**--------------------------------------修改文件的相关信息--------------------------------------------------
** 修改人:
** 修改日期:
** 版本号:
** 修改内容:
**
*******************************************************************************/
module uart_test(
clock, //系统时钟
RXD, //uart接收引脚
TXD //uart发送引脚
);
input clock; //系统时钟(48MHz)
input RXD; //uart接收引脚
output TXD; //uart发送引脚
reg [7:0] senddata; //发送一个字节的数据缓存区
reg WR_R1,WR_R2,WR_R3; //控制产生一个发送的写信号
wire [7:0]recdata; //接收缓存区
wire RI,TI,WR; //接收、发送中断以及写控制信号
wire clksend,clkrec; //发送和接收的时钟频率
wire clk100M;
/********************************************************************************
** 模块名称:
** 功能描述:通过RI接收中断产生一个写信号,维持时间为1个Clk
********************************************************************************/
always@(posedge clksend)
begin
WR_R1 <= RI;
WR_R2 <= WR_R1;
WR_R3 <= WR_R2;
end
assign WR = (~WR_R3)&(WR_R2)&(WR_R1); //控制写信号
/********************************************************************************
** 模块名称:
** 功能描述:当接收了一个数据后,把数据加1后发回PC机
********************************************************************************/
always@(posedge RI)
begin
senddata <= recdata+8'd1;
end
rec uartrec( //实例化一个uart接收模块
.clk(clock),
.clkout(clkrec),
.dataout(recdata),
.RXD(RXD),
.RI(RI)
);
send uartsend( //实例化一个uart的发送模块
.clk(clock),
.clkout(clksend),
.datain(senddata),
.TXD(TXD),
.TI(TI),
. WR(WR)
);
endmodule
发送模块:
/**********************************************************************
**
**-------------------------------------------文件信息----------------------------------------------------------
** 文件名称: send.v
** 创建者:
** 创建日期: 2008
** 版本号: V3.0
** 功能描述: UART的发送模块
**
**--------------------------------------修改文件的相关信息--------------------------------------------------
** 修改人:
** 修改日期: 2008
** 版本号: V3.0
** 修改内容: 整理
**
*******************************************************************************/
module send(
clk, //时钟
clkout, //输出
datain, //需要发送的一个字节数据
TXD, //uart发送引脚
TI, //发送中断
WR, //写控制信号
rst //复位
);
input rst;
input clk; //输入时钟
input WR; //写信号
input [7:0] datain; //发送的一字节数据
output clkout; //输出时钟
output TXD,TI; //串行数据,发送中断
reg [9:0] datainbuf,datainbuf2; //发送数据缓存
reg WR_ctr,TI,TXD_reg; //写标志、中断标志、一位发送寄存器
reg [3:0] bincnt; //发送数据计数器
reg [15:0] cnt; //计数器
wire clk_equ; //分频时钟
parameter cout = 5000; //根据具体的时钟来设定分频系数
//这里是48M时钟,波特率选择是9600,所以分频系数为48000000/9600= 5000;
/********************************************************************************
** 模块名称:
** 功能描述:波特率发生进程
********************************************************************************/
always@(posedge clk)
begin
if(rst)
cnt <= 16'd0;
else
if(clk_equ)
cnt <= 16'd0;
else
cnt<=cnt+1'b1;
end
assign clk_equ = (cnt == cout);
assign clkout = clk_equ;
/********************************************************************************
** 模块名称:
** 功能描述:读数据到缓存进程
********************************************************************************/
always@(posedge clk)
begin
if(rst)
begin
datainbuf <= 10'd0;
WR_ctr <= 1'b0;
end
else
if(WR)
begin
datainbuf <= {1'b1,datain[7:0],1'b0}; //读入数据,并把缓存组成一帧数据,10位 datain[7:0]
WR_ctr <= 1'b1; //置开始标志位
end
else if(TI==0)
WR_ctr <= 1'b0;
end
/********************************************************************************
** 模块名称:
** 功能描述:主程序进程
********************************************************************************/
always@(posedge clk)
begin
if(rst)
begin
TXD_reg <= 1'b1;
TI <= 1'b1;
bincnt <= 4'd0;
end
else if(clk_equ) //发送条件判断,保证发送数据的完整性
begin
if(WR_ctr==1||TI==0)
if(bincnt<4'd10)
begin
TXD_reg <= datainbuf>>bincnt; //移位输出
bincnt <= bincnt + 4'd1; //发送数据位计数
TI <= 1'b0;
end
else
begin
bincnt <= 4'd0;
TI <= 1'b1;
TXD_reg <= 1'b1;
end
end
end
assign TXD = TXD_reg; //TXD连续输出
endmodule
接收模块:
/********************************
**
**
**-------------------------------------------文件信息----------------------------------------------------------
** 文件名称: rec.v
** 创建者:
** 创建日期: 2008
** 版本号: V3.0
** 功能描述: UART的接收模块
**
**--------------------------------------修改文件的相关信息--------------------------------------------------
** 修改人:
** 修改日期: 2008
** 版本号: V3.0
** 修改内容: 整理
**
*******************************************************************************/
module rec(
clk,
clkout,
dataout,
RXD,
RI,
rst
);
input rst;
input clk,RXD; //时钟与数据输入
output clkout,RI; //时钟输入、接收中断输出
output [7:0] dataout; //并行数据输出
reg StartF,RI; //开始与接收中断标志
reg [9:0] UartBuff; //接收缓存区
reg [3:0] count,count_bit; //位接收计数器
reg [15:0] cnt; //时钟节拍计数器
reg [2:0] bit_collect; //采集数据缓存区
wire clk_equ,bit1,bit2,bit3,bit4; //连线
parameter cout = 312; //时钟是48M所以16*9600的分频数为312.5,这里取整数
/********************************************************************************
** 模块名称:
** 功能描述:波特率发生进程
********************************************************************************/
always@(posedge clk) //时钟节拍计数器
begin
if(rst)
cnt <= 16'd0;
else
begin
if(clk_equ)
cnt <= 16'd0;
else
cnt <= cnt + 1'b1;
end
end
assign clk_equ = (cnt == cout); //采样时钟
assign clkout = clk_equ;
assign bit1 = bit_collect[0]&bit_collect[1]; //对采样数据进行判断
assign bit2 = bit_collect[1]&bit_collect[2]; //对采样数据进行判断
assign bit3 = bit_collect[0]&bit_collect[2]; //对采样数据进行判断
assign bit4 = bit1|bit2|bit3; //对采样数据进行判断,只要有两次相同就可以
/********************************************************************************
** 模块名称:
** 功能描述:UART的接收模块,接收采样率为波特率的16倍
********************************************************************************/
always@(posedge clk)
begin
if(rst)
begin
count <= 4'd0;
RI <= 1'b1;
StartF <= 1'b0;
bit_collect <= 3'd0;
UartBuff <= 10'd0;
end
else
begin
if(clk_equ)
begin
if(!StartF) //是否处于接收状态
begin
if(!RXD)
begin
count <= 4'b0; //复位计数器
count_bit <= 4'b0;
RI <= 1'b0;
StartF <= 1'b1;
end
else RI <= 1'b1;
end
else
begin
count <= count+1'b1; //位接收状态加1
if(count==4'd6)
bit_collect[0] <= RXD; //数据采集
if(count==4'd7)
bit_collect[1] <= RXD; //数据采集
if(count==4'd8)
begin
bit_collect[2] <= RXD; //数据采集
UartBuff[count_bit] <= bit4;
count_bit <= count_bit+1'b1; //位计数器加1
if((count_bit==4'd1)&&(UartBuff[0]==1'b1)) //判断开始位是否为0
begin
StartF <= 1'b0; //标志开始接收
end
RI <= 1'b0; //中断标志位低
end
if(count_bit>4'd9) //检测是否接收结束
begin
RI <= 1'b1; //中断标志为高标志转换结束
StartF <= 1'b0;
end
end
end
end
end
assign dataout = UartBuff[8:1]; //取出数据位
endmodule
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -