当前位置:网站首页>【FPGA】day15-串口协议uart回环工程
【FPGA】day15-串口协议uart回环工程
2022-06-10 01:15:00 【春风浅作序】
目录
一、项目概述
1、实验要求

2、串行通信基础
串口通信概念
串口通信方式
串行通信的传输方向
常见的串行通信接口
3、UART通信原理
UART概念
通信协议
LSB:权重最低位
MSB:权重最高位
以1010_1100为例,传输的数据位从左到右依次为0-0-1-1-0-1-0-1
传输速率
电平标准
标准逻辑
4、需求与设计分析
(1)模块草图

(2)发送端时序图

(3)接收端时序图

二、项目实现
1、建立文件体系

2、顶层模块
module uart (
input clk ,
input rst_n ,
input rx , //接收——串行数据(上位机)
output tx //发送——串行数据(FPGA内部)
);
//信号定义
wire [7:0] dout ;
wire dout_vld ;
uart_rx u_uart_rx( //将接收到的串行数据转换成并行数据
.clk (clk ) ,
.rst_n (rst_n ) ,
.rx (rx ) , //串行数据
.dout (dout ) , //并行数据
.dout_vld (dout_vld )
);
uart_tx u_uart_tx( //将要发送的并行数据转换成串行数据传输
.clk (clk ) ,
.rst_n (rst_n ) ,
.din (dout ) ,
.din_vld (dout_vld ) ,
.tx (tx ) //串行数据
)
endmodule
3、发送模块
module uart_tx (
input clk ,
input rst_n ,
input [7:0] din ,
input din_vld ,
output reg tx
);
//参数定义
parameter BPS_115200 = 433 ; //1bit数据传输所需的时钟周期
//信号定义
reg [9:0] data ; //锁存din_vld时的有效输出
reg flag ;
reg [8:0] cnt_bps ;
wire add_cnt_bps ;
wire end_cnt_bps ;
reg [3:0] cnt_bit ;
wire add_cnt_bit ;
wire end_cnt_bit ;
//数据锁存
always @(posedge clk or negedge rst_n) begin
if(!rst_n)begin
data <= 1'b0;
end
else if(din_vld)begin
data <= {
1'b1,din,1'b0}; //锁存数据 停止位,数据,起始位
end
end
always @(posedge clk or negedge rst_n) begin
if(!rst_n)begin
tx <= 1'b1;
end
else if(flag || din_vld)begin //发送数据
tx <= data[cnt_bit];
end
end
always @(posedge clk or negedge rst_n) begin
if(!rst_n)begin
flag <= 1'b0;
end
else if(din_vld)begin //开启计数器
flag <= 1'b1;
end
else if(end_cnt_bit) begin
flag <= 1'b0;
end
end
//波特率计数器,计数每bit数据传输时间
always @(posedge clk or negedge rst_n) begin
if(!rst_n)begin
cnt_bps <= 1'd0;
end
else if(add_cnt_bps)begin
if(end_cnt_bps)begin
cnt_bps <= 1'd0;
end
else begin
cnt_bps <= cnt_bps + 1'd1;
end
end
end
assign add_cnt_bps = flag;
assign end_cnt_bps = add_cnt_bps && cnt_bps == BPS_115200 - 1 ;
//所需传输的比特数
always @(posedge clk or negedge rst_n) begin
if(!rst_n)begin
cnt_bit <= 1'd0;
end
else if(add_cnt_bit)begin
if(end_cnt_bit)begin
cnt_bit <= 1'd0;
end
else begin
cnt_bit <= cnt_bit + 1'd1;
end
end
end
assign add_cnt_bit = end_cnt_bps;
assign end_cnt_bit = add_cnt_bit && cnt_bit == 10 - 1 ;
endmodule
4、接收模块
module uart_rx ( //将接收到的串行数据转化成并行数据
input clk ,
input rst_n ,
input rx , //串行数据
output reg [7:0] dout , //并行数据
output reg dout_vld //输出数据有效信号
);
//参数定义
parameter BPS_115200 = 434 ; //1bit数据传输所需要的时钟周期
//信号定义
reg rx_r0 ;
reg rx_r1 ;
reg rx_r2 ;
wire nedge ;
reg flag ; //接收数据标志
reg [9:0] data_r ; //数据接收缓存
reg [8:0] cnt_bps ;
wire add_cnt_bps ;
wire end_cnt_bps ;
reg [3:0] cnt_bit ;
wire add_cnt_bit ;
wire end_cnt_bit ;
//数据同步
always @(posedge clk or negedge rst_n) begin
if(!rst_n)begin
rx_r0 <= 1'b1;
end
else begin
rx_r0 <= rx ;
end
end
//数据打拍
always @(posedge clk or negedge rst_n) begin
if(!rst_n)begin
rx_r1 <= 1'b1;
rx_r2 <= 1'b1;
end
else begin
rx_r1 <= rx_r0;
rx_r2 <= rx_r1;
end
end
assign nedge = rx_r2 & ~rx_r1 ; //下降沿检测
always @(posedge clk or negedge rst_n) begin
if(!rst_n)begin
flag <= 1'b0;
end
else if(nedge)begin
flag <= 1'b1;
end
else if(end_cnt_bit) begin
flag <= 1'b0;
end
end
always @(posedge clk or negedge rst_n) begin
if(!rst_n)begin
cnt_bps <= 1'd0;
end
else if(add_cnt_bps)begin
if(end_cnt_bps)begin
cnt_bps <= 1'd0;
end
else begin
cnt_bps <= cnt_bps + 1'd1;
end
end
end
assign add_cnt_bps = flag;
assign end_cnt_bps = add_cnt_bps && cnt_bps == BPS_115200 - 1 ;
always @(posedge clk or negedge rst_n) begin
if(!rst_n)begin
cnt_bit <= 1'd0;
end
else if(add_cnt_bit)begin
if(end_cnt_bit)begin
cnt_bit <= 1'd0;
end
else begin
cnt_bit <= cnt_bit + 1'd1;
end
end
end
assign add_cnt_bit = end_cnt_bps;
assign end_cnt_bit = add_cnt_bit && cnt_bit == 9 ;
always @(posedge clk or negedge rst_n) begin
if(!rst_n)begin
data_r <= 1'b0;
end
else if(cnt_bps == (BPS_115200 >> 1))begin //数据采样
data_r[cnt_bit] <= rx_r2 ;
end
end
always @(posedge clk or negedge rst_n) begin
if(!rst_n)begin
dout <= 1'b0;
end
else if(end_cnt_bit)begin //截取数据位
dout <= data_r[8:1];
end
end
always @(posedge clk or negedge rst_n) begin
if(!rst_n)begin
dout_vld <= 1'b0;
end
else if(end_cnt_bit)begin //给发送模块锁存数据产生数据有效信号
dout_vld <= 1'b1;
end
else begin
dout_vld <= 1'b0;
end
end
endmodule
三、功能仿真
1、发送端uart_tx仿真
(1)仿真代码
`timescale 1ns/1ps
module uart_tx_tb ();
reg clk ;
reg rst_n ;
reg [7:0] din ;
reg din_vld ;
wire tx ;
//参数定义
parameter CYCLE = 20 ;
uart_tx u_uart_tx(
.clk (clk ) ,
.rst_n (rst_n ) ,
.din (din ) ,
.din_vld (din_vld ) ,
.tx (tx )
);
always #(CYCLE/2) clk = ~clk ;
initial begin
clk = 1'b1 ;
rst_n = 1'b1 ;
#(CYCLE*5);
rst_n = 1'b0 ;
din = 0 ;
din_vld = 0 ;
#(CYCLE*5);
rst_n = 1'b1 ;
#2;
repeat(3)begin
#(CYCLE*10);
din = {
$random};
din_vld = 1'b1 ;
#(CYCLE*1);
din_vld = 1'b0 ;
#(CYCLE*5000);
end
//Send(8'b1010_1100);
//Send(8'hfa);
$stop;
end
/*task Send; input [7:0] send_data ; begin #(CYCLE*10); din = send_data ; din_vld = 1'b1 ; #(CYCLE*1); din_vld = 1'b0 ; #(CYCLE*5000); end endtask*/
endmodule
(2)仿真波形

2、顶层仿真
(1)仿真代码
实例化uart_tx一次,将其作为外部的输出端。
`timescale 1ns/1ps
module uart_tb ();
reg clk ;
reg rst_n ;
reg [7:0] din ;
reg din_vld ;
wire rx_r ;
wire tx ;
//参数定义
parameter CYCLE = 20 ;
uart_tx u_uart_tx(
.clk (clk ) ,
.rst_n (rst_n ) ,
.din (din ) ,
.din_vld (din_vld ) ,
.tx (rx_r )
);
uart u_uart(
.clk (clk ) ,
.rst_n (rst_n ) ,
.rx (rx_r ) , //接收——串行数据(上位机)
.tx (tx ) //发送——串行数据(FPGA内部)
);
always #(CYCLE/2) clk = ~clk ;
initial begin
clk = 1'b1 ;
rst_n = 1'b1 ;
#(CYCLE*5);
rst_n = 1'b0 ;
din = 0 ;
din_vld = 0 ;
#(CYCLE*5);
rst_n = 1'b1 ;
#2;
repeat(3)begin
#(CYCLE*10);
din = {
$random};
din_vld = 1'b1 ;
#(CYCLE*1);
din_vld = 1'b0 ;
#(CYCLE*5000);
end
//Send(8'b1010_1100);
//Send(8'hfa);
$stop;
end
/*task Send; input [7:0] send_data ; begin #(CYCLE*10); din = send_data ; din_vld = 1'b1 ; #(CYCLE*1); din_vld = 1'b0 ; #(CYCLE*5000); end endtask*/
endmodule
(2)仿真波形

边栏推荐
- CocosCreator旧活新整-合成大粽子
- Alleviate and repair Android studio Caton, kotlin code prompt is slow
- 【LeetCode】338. 比特位计数
- Disorder of flinksql
- Luogu p1220 turn off street light problem solving section DP
- Never far away, five programming languages that may be doomed to decline
- 软件工程期末复习
- 【神经网络】(22) ConvMixer 代码复现,网络解析,附TensorFlow完整代码
- Short video live broadcast source code, customize the circular playback of pictures or videos
- What if win11 returns win10 without a return option?
猜你喜欢

0基础入行软件测试只靠自学可行吗?看完这篇不迷茫....

TRichView and ScaleRichView 设置默认中文

电脑系统怎么修改图片格式

From the perspective of advanced automated testing, one article with 7 stages and 5000 words will give you a comprehensive understanding of automated testing

【ICLR 2022】Towards Continual Knowledge Learning of Language Models

地图瓦片数据的多种利用形式以及瓦片数据的浏览显示

Application scheme of residual pressure monitoring system in a high-rise residential building

Batch downloading of pictures + mosaic of pictures: multiple pictures constitute the Dragon Boat Festival Ankang

【无标题】416. 分割等和子集

TensorFlow新文档发布:新增CLP、DTensor...最先进的模型已就绪
随机推荐
【LeetCode】剑指 Offer II 016. 不含重复字符的最长子字符串
图片批量下载 +图片马赛克:多张图片组成端午安康!
The gradient decline triggered a "heated debate" among AI bulls. Netizen: everyone's answer is worth seeing
从转载阿里开源项目 Egg.js 技术文档引发的“版权纠纷”,看宽松的 MIT 许可该如何用?
From the perspective of advanced automated testing, one article with 7 stages and 5000 words will give you a comprehensive understanding of automated testing
孙宇晨等收购Poloniex,公链交易所双轮驱动波场生态
Node red series (26): use the dashboard node to develop common table search layouts
Don't build the wheel again. It is recommended to use Google guava open source tool class library. It is really powerful!
JVM -- class compilation process
实验三 字符类型及其操作(新)
【webrtc】PCF和PC的构建、会话与媒体协商 流程
沪漂大专程序员,一边跟刘畊宏健身,一边拿22k的offer
Spent two hours experiencing the latest epic skin of idea
【ACL 2022】Hallucinated but Factual! Inspecting the Factuality of Hallucinations
What is the difference between encryptors and database encryption products?
【图像分类案例】(10) Vision Transformer 动物图像三分类,附Pytorch完整代码
Thingsboard tutorial (18): overview of TB rule engine
Short video live broadcast source code, customize the circular playback of pictures or videos
RHCSA第七天
Various utilization forms of map tile data and browsing display of tile data