当前位置:网站首页>【FPGA】UART串口_V1.1
【FPGA】UART串口_V1.1
2022-06-27 05:04:00 【li_lys】
之前的串口用得有些不稳定所以弄了这个串口,这个串口适用于各种常见得波特率设置,这里不讲解串口原理,直接代码分享和输入输出讲解。
一、代码
1.UART_RX
`timescale 1ns / 1ps
module uart_rx
#(parameter BPS =5208)
(
input clk ,
input rst_n ,
input din ,
output reg[7:0] dout /* synthesis syn_keep=1 */,
output reg dout_vld
);
//parameter BPS = 434;//115200 5208; //9600波特率
reg [14:0] cnt0 ;
wire add_cnt0 ;
wire end_cnt0 ;
reg [ 3:0] cnt1 ;
wire add_cnt1 ;
wire end_cnt1 ;
reg rx0 ;
reg rx1 ;
reg rx2 ;
wire rx_en/* synthesis syn_keep=1 */;
reg flag_add ;
//对数据的跨时钟处理,防止出现亚稳态
always @ (posedge clk or negedge rst_n) begin
if(!rst_n) begin
rx0 <= 1'b1;
rx1 <= 1'b1;
rx2 <= 1'b1;
end
else begin
rx0 <= din;
rx1 <= rx0;
rx2 <= rx1;
end
end
assign rx_en = rx2 & ~rx1;
//检测到下降沿,即空闲位从1置为0,数据传输开始
always @(posedge clk or negedge rst_n)begin
if(!rst_n)begin
cnt0 <= 15'd0;
end
else if(add_cnt0)begin
if(end_cnt0)
cnt0 <= 15'd0;
else
cnt0 <= cnt0 + 15'd1;
end
end
assign add_cnt0 = flag_add;
assign end_cnt0 = add_cnt0 && cnt0==(BPS-15'd1);
always @(posedge clk or negedge rst_n)begin
if(!rst_n)begin
cnt1 <= 4'd0;
end
else if(add_cnt1)begin
if(end_cnt1)
cnt1 <= 4'd0;
else
cnt1 <= cnt1 + 4'd1;
end
end
assign add_cnt1 = end_cnt0;
assign end_cnt1 = add_cnt1 && cnt1==4'd9-4'd1 ; //由于是接收程序,此处也不设校验位,所以只需要接收数据就可以,后面的第10位必然位停止位,可以不理,节省资源
always @ (posedge clk or negedge rst_n)begin
if(!rst_n) begin
flag_add <= 1'b0;
end
else if(rx_en && flag_add==1'b0) begin
flag_add <= 1'b1;
end
else if(end_cnt1) begin
flag_add <= 1'b0;
end
end
always @ (posedge clk or negedge rst_n)begin
if(!rst_n) begin
dout <= 8'd0;
end
else if(add_cnt0 && cnt0==(BPS/2-1) && cnt1!=0) begin //在中间时刻采样,此时的数据比较稳定,从低位到高位依次采样
case(cnt1)
4'd1:dout[0]<=rx2;
4'd2:dout[1]<=rx2;
4'd3:dout[2]<=rx2;
4'd4:dout[3]<=rx2;
4'd5:dout[4]<=rx2;
4'd6:dout[5]<=rx2;
4'd7:dout[6]<=rx2;
4'd8:dout[7]<=rx2;
default:
;
endcase
end
else
;
end
//传输完数据信号
always @ (posedge clk or negedge rst_n)begin
if(!rst_n) begin
dout_vld <= 1'b0;
end
else if(end_cnt1) begin
dout_vld <= 1'b1;
end
else begin
dout_vld <= 1'b0;
end
end
endmodule
模块接口说明
uart_rx
| 引脚 | 位宽 | 方向 | 说明 |
|---|---|---|---|
| clk | 1 | IN | 模块时钟50M |
| rst_n | 1 | IN | 复位信号低位有效 |
| din | 1 | IN | RX数据输入 |
| dout | 8 | OUT | 数据输出 |
| dout_vld | 1 | OUT | 数据输出有效 |
2.UART_TX
下面展示一些 内联代码片。
`timescale 1ns / 1ps
module uart_tx
#(parameter BPS =5208)
(
input clk ,
input rst_n ,
input [7:0] din ,
input din_vld,
output reg rdy ,
output byte_1 ,
output reg dout
);
//parameter BPS = 434;
reg [7:0] tx_data_tmp;
reg flag_add ;
reg [14:0] cnt0 ;
wire add_cnt0 ;
wire end_cnt0 ;
reg [ 3:0] cnt1 ;
wire add_cnt1 ;
wire end_cnt1 ;
wire [ 9:0] data ;
always @(posedge clk or negedge rst_n)begin
if(rst_n==1'b0)begin
flag_add <= 1'b0;
end
else if(flag_add==1'b0 && din_vld)begin
flag_add <= 1'b1;
end
else if(end_cnt1)begin
flag_add <= 1'b0;
end
end
always @(posedge clk or negedge rst_n)begin
if(!rst_n)begin
cnt0 <= 15'd0;
end
else if(add_cnt0)begin
if(end_cnt0)
cnt0 <= 15'd0;
else
cnt0 <= cnt0 + 15'd1;
end
end
assign add_cnt0 = flag_add;
assign end_cnt0 = add_cnt0 && cnt0==(BPS-15'd1);
always @(posedge clk or negedge rst_n)begin
if(!rst_n)begin
cnt1 <= 4'd0;
end
else if(add_cnt1)begin
if(end_cnt1)
cnt1 <= 4'd0;
else
cnt1 <= cnt1 + 4'd1;
end
end
assign add_cnt1 = end_cnt0;
assign end_cnt1 = add_cnt1 && cnt1==4'd10-4'd1 ;
always @ (posedge clk or negedge rst_n) begin
if(!rst_n) begin
tx_data_tmp <=8'd0;
end
else if(flag_add==1'b0 && din_vld) begin
tx_data_tmp <= din;
end
end
always @ (posedge clk or negedge rst_n) begin
if(!rst_n) begin
dout <= 1'b1;
end
else if(add_cnt0 && cnt0==1-1)begin
dout<= data[cnt1];
end
end
assign data = {
1'b1,tx_data_tmp,1'b0}; //传输时是从低到高 data = {停止位,数据[7],数据[6] ~ 数据[0],起始位};
always @( * )begin
if(din_vld || flag_add)
rdy = 1'b0;
else
rdy = 1'b1;
end
assign byte_1 = end_cnt1;
endmodule
模块接口说明
uart_tx
| 引脚 | 位宽 | 方向 | 说明 |
|---|---|---|---|
| clk | 1 | IN | 模块时钟50M |
| rst_n | 1 | IN | 复位信号低位有效 |
| din | 8 | IN | 发送数据输入 |
| din_vld | 1 | IN | 发送数据输入有效 |
| rdy | 1 | OUT | busy信号 1:不忙 0:忙 |
| byte_1 | 1 | OUT | 一字节传输完成标志 |
| dout | 1 | OUT | TX数据输出 |
二、总结注意
波特率分频系数设置
parameter BPS =5208
常用波特率 50M时钟分频系数
BAUD_9600 5208
BAUD_19200 2604
BAUD_38400 1302
BAUD_115200 434
busy信号注意
always @( * )begin
if(din_vld || flag_add)
rdy = 1'b0;
else
rdy = 1'b1;
end
该处使用组合逻辑将数据有效赋值给busy信号忙状态,建议使用时序逻辑给数据输入有效赋值,或使用组合逻辑试将代码这里的有效位移除。
边栏推荐
- [station B up dr_can learning notes] Kalman filter 2
- 021 basics of C language: recursion, variable parameters
- STM32关闭PWM输出时,让IO输出固定高或低电平的方法。
- 高等数学(第七版)同济大学 习题1-10 个人解答
- Tri rapide (non récursif) et tri de fusion
- Vue学习笔记(五)Vue2页面跳转问题 | vue-router路由概念、分类与使用 | 编程式路由导航 | 路由组件的缓存 | 5种路由导航守卫 | 嵌套路由 | Vue2项目的打包与部署
- RTP sending PS stream tool (open source)
- 【Unity】UI交互组件之按钮Button&可选基类总结
- Penetration test - directory traversal vulnerability
- 关于元器件封装的一些文章和一下我的体会
猜你喜欢

Remapping (STM32)

Penetration test - directory traversal vulnerability

齐纳二极管 稳压二极管 SOD123封装 正负区分

pycharm 如何安装 package
![[station B up dr_can learning notes] Kalman filter 1](/img/18/ee21d31f6a118e4e4ad466b55361cc.gif)
[station B up dr_can learning notes] Kalman filter 1

微服务系统设计——消息缓存服务设计

Qchart note 2: add rollover display

Pycharm 中 Terminal 无法进入 venv 环境的问题

流媒体协议初探(MPEG2-TS、RTSP、RTP、RTCP、SDP、RTMP、HLS、HDS、HSS、MPEG-DASH)

微服务系统设计——分布式事务服务设计
随机推荐
清华大学开源软件镜像站网址
020 C语言基础:C语言强制类型转换与错误处理
1.5 use of CONDA
The most detailed download tutorial of MySQL
010 C language foundation: C function
[BJDCTF2020]The mystery of ip
021 basics of C language: recursion, variable parameters
Epics record reference 5 -- array analog input recordarray analog input (AAI)
pycharm 如何安装 package
jq怎么获取倒数的元素
Laptop does not have WiFi option solution
Penetration test - file upload / download / include
013 C语言基础:C指针
第2章 关键技术介绍
Cultural tourism night tour | stimulate tourists' enthusiasm with immersive visual experience
【B站UP DR_CAN学习笔记】Kalman滤波3
微服务系统设计——微服务调用设计
010 C语言基础:C函数
017 basics of C language: bit field and typedef
[station B up dr_can learning notes] Kalman filter 3