当前位置: 首页 > news >正文

FPGA中UART串口模块

本文本质为学习笔记的总结

基本原理不在赘述。

下面是串口读模块,用串口uart_rxd将外部输入的串行数据转换为并行数据由uart_data输出。

module UART_get( input sys_clk,//系统时钟 input sys_rst_n,//系统复位,低电平有效 input uart_rxd,//数据输入端口,将此端口传入的串行数据转化为并行数据存在uart_data中 output reg [7:0] uart_data,//存储串行数据转换后的并行数据 output reg uart_done//数据接收完毕标志信号,当数据接收完后变为高电平 ); //********************只需修改下面参数即可移植******************************** parameter CLK=50_000_000;//频率 parameter BPS=115200;//波特率 //************************************************************************* parameter Baud=CLK/BPS;//计数次数 reg uart_rxd_d0;//用于消除起始信号的亚稳态 reg uart_rxd_d1;//用于消除起始信号的亚稳态 reg rx_flag;//数据帧标志位(接收),当起始信号出现后被拉为高电平,数据可以开始接收 reg [3:0]rx_cnt;//数据位计数,0位是起始位,1--8为数据位,9可以为校验位(但这里没有设置校验位) reg [15:0]clk_cnt;//波特率计数 reg [7:0]rx_data;//用于寄存串转并的数据 wire start_flag;//下降沿检测标志位 always@(posedge sys_clk or negedge sys_rst_n)begin//消除亚稳态 if(sys_rst_n==0)begin//复位置为高电平,表示数据位未开始 uart_rxd_d0<=1; uart_rxd_d1<=1; end else begin uart_rxd_d0<=uart_rxd; uart_rxd_d1<=uart_rxd_d0; end end assign start_flag=uart_rxd_d1&&(~uart_rxd_d0);//检测uart_rxd下降沿,uart_rxd下降沿表示起始位 always@(posedge sys_clk or negedge sys_rst_n)begin//数据帧标志位设置 if(sys_rst_n==0)rx_flag<=0;//复位清零 else if(start_flag==1)rx_flag<=1;//uart_rxd下降沿检测标志位为真,开启数据帧标志位,开始数据接受 else if((rx_cnt==4'd9)&&(clk_cnt==Baud/2))rx_flag<=0;//表示数据接收完毕后的一半波特率时将数据帧标志位关闭 else rx_flag<=rx_flag;//其它情况数据帧标志位不变 end always@(posedge sys_clk or negedge sys_rst_n)begin//波特率计数 if(sys_rst_n==0)clk_cnt<=0;//复位清零 else if(rx_flag==1)begin//在开启数据帧标志位的情况下开始计数 if(clk_cnt<Baud)clk_cnt<=clk_cnt+1;//计数不到一个波特率周期就继续计数 else clk_cnt<=0;//否则计数清零 end else clk_cnt<=0;//数据帧标志位未开启的情况下计数始终为0 end always@(posedge sys_clk or negedge sys_rst_n)begin//数据位计数 if(sys_rst_n==0)rx_cnt<=0;//复位清零 else if(rx_flag==1)begin//在开启数据帧标志位的情况下开始计数 if(clk_cnt==Baud-1)begin//并且每到一个波特率周期进行一次计数 if(rx_cnt==9)rx_cnt<=0;//计数完就清零 else rx_cnt<=rx_cnt+1;//否则继续计数 end end else rx_cnt<=0;//数据帧标志位未开启的情况下计数始终为0 end always@(posedge sys_clk or negedge sys_rst_n)begin//接收数据,并进行串转并 if(sys_rst_n==0)rx_data<=0;//复位清零 else if(rx_flag==1)begin//在开启数据帧标志位的情况下开始接收数据,并进行串转并 if(clk_cnt==Baud/2)begin//计数一半时串口uart_rxd_d1的数据相对要更稳定,此时读取串口上的数据更稳妥 case(rx_cnt) 4'd1:rx_data[0]<=uart_rxd_d1; 4'd2:rx_data[1]<=uart_rxd_d1; 4'd3:rx_data[2]<=uart_rxd_d1; 4'd4:rx_data[3]<=uart_rxd_d1; 4'd5:rx_data[4]<=uart_rxd_d1; 4'd6:rx_data[5]<=uart_rxd_d1; 4'd7:rx_data[6]<=uart_rxd_d1; 4'd8:rx_data[7]<=uart_rxd_d1; default:rx_data<=0; endcase end end end always@(posedge sys_clk or negedge sys_rst_n)begin//数据接收完的情况处理 if(sys_rst_n==0)begin uart_done<=0;//复位将数据接收完的标志位置零 uart_data<=0;//接收在寄存器中的数据清零 end else if(rx_cnt==4'd9)begin//计数到第9位说明数据已经接收完毕 uart_done<=1;//将数据接收完的标志位置1,数据帧标志位将被关闭,数据接收将停止 uart_data<=rx_data;//将寄存器中完整的数据转移并保存到uart_data中 end else begin uart_done<=0;//其它情况数据接收完的标志位置零 uart_data<=uart_data;//数据保持 end end endmodule

下面是串口写模块,输入并行数据uart_din,并串转换后由串口uart_txd输出。

module UART_put( input sys_clk,//系统时钟 input sys_rst_n,//系统复位,低电平有效 input uart_en,//发送使能信号,高电平有效 output reg uart_txd,//数据发送端口 input [7:0] uart_din//需要发送的数据 ); parameter CLK=50_000_000;//频率 parameter BPS=115200;//波特率 parameter Baud=CLK/BPS;//计数次数 reg uart_en_d0;//用于消除起始信号的亚稳态 reg uart_en_d1;//用于消除起始信号的亚稳态 reg tx_flag;//数据帧标志位(发送) reg [3:0]tx_cnt;//数据位计数,0位是起始位,1--8为数据位,9为停止位10可以为校验位(但这里没有设置校验位) reg [15:0]clk_cnt;//波特率计数 reg [7:0]tx_data;//寄存器,将需要发送的数据寄存一下 wire en_flag;//下降沿检测标志位 always@(posedge sys_clk or negedge sys_rst_n)begin//消除亚稳态 if(sys_rst_n==0)begin uart_en_d0<=1; uart_en_d1<=1; end else begin uart_en_d0<=uart_en; uart_en_d1<=uart_en_d0; end end assign en_flag=uart_en_d0&&(~uart_en_d1);//检测上升沿,即使能信号传输过来的瞬间的下降沿 always@(posedge sys_clk or negedge sys_rst_n)begin if(sys_rst_n==0)tx_data<=0;//复位清零 else if(en_flag==1)tx_data<=uart_din;//下降沿出现瞬间将需要发送的数据寄存 else tx_data<=tx_data;//其余时间保持寄存器的数据 end always@(posedge sys_clk or negedge sys_rst_n)begin if(sys_rst_n==0)tx_flag<=0;//复位清零 else if(en_flag==1)tx_flag<=1;//当检测到使能信号的下降沿后,en_flag会被拉高,从而开启数据帧标志位 else if((tx_cnt==4'd9)&&(clk_cnt==Baud/2))tx_flag<=0;//当数据传输完毕后的半个波特率后数据帧标志位关闭 else tx_flag<=tx_flag; //其余时间里数据帧标志位保持不变 end always@(posedge sys_clk or negedge sys_rst_n)begin//波特率计数 if(sys_rst_n==0)clk_cnt<=0;//复位清零 else if(tx_flag==1)begin//在开启数据帧标志位的情况下开始计数 if(clk_cnt<Baud)clk_cnt<=clk_cnt+1;//计数不到一个波特率周期就继续计数 else clk_cnt<=0;//计数完就清零 end else clk_cnt<=0;//数据帧标志位未开启的情况下计数始终为0 end always@(posedge sys_clk or negedge sys_rst_n)begin if(sys_rst_n==0)tx_cnt<=0;//复位清零 else if(tx_flag==1)begin//在开启数据帧标志位的情况下开始计数 if(clk_cnt==Baud-1)begin//并且每到一个波特率周期进行一次计数 if(tx_cnt==9)tx_cnt<=0;//计数完就清零 else tx_cnt<=tx_cnt+1;//否则继续计数 end end else tx_cnt<=0;//数据帧标志位未开启的情况下计数始终为0 end always@(posedge sys_clk or negedge sys_rst_n)begin if(sys_rst_n==0)uart_txd<=1;//复位发送端拉高 else if(tx_flag==1)begin//在开启数据帧标志位的情况下开始发送数据 if(clk_cnt==0)begin//每个波特率周期发送一次 case(tx_cnt) 4'd0:uart_txd<=0;//起始位 4'd1:uart_txd<=tx_data[0]; 4'd2:uart_txd<=tx_data[1]; 4'd3:uart_txd<=tx_data[2]; 4'd4:uart_txd<=tx_data[3]; 4'd5:uart_txd<=tx_data[4]; 4'd6:uart_txd<=tx_data[5]; 4'd7:uart_txd<=tx_data[6]; 4'd8:uart_txd<=tx_data[7]; 4'd9:uart_txd<=1;//停止位 default:uart_txd<=0;//发送结束,数据帧标志位将被关闭 endcase end end end endmodule

下面是顶层模块,将读写模块合并。

module UART( input sys_clk, //系统时钟 input sys_rst_n, //系统复位,低电平有效 output [7:0] get_data, //通过串口向外读取到的数据 input uart_rxd, //数据接收端口 input [7:0] put_data, //通过串口向外输出的数据 output uart_txd //数据发送端口 ); wire uart_done;//接停止标志,这里作为发送的起始信号 UART_put UART_put( .sys_clk (sys_clk), .sys_rst_n (sys_rst_n), .uart_en (uart_done), .uart_txd (uart_txd), .uart_din (put_data) ); UART_get UART_get( .sys_clk (sys_clk), .sys_rst_n (sys_rst_n), .uart_rxd (uart_rxd), .uart_data (get_data), .uart_done (uart_done) ); endmodule

综合后的Schematic 视图.

http://www.jsqmd.com/news/1302059/

相关文章:

  • 目前口碑出众的机器人视觉识别系统都有哪几款值得我们参考选择 - 甄选测评馆
  • 转大模型后,我为什么把权限和日志写得比 Prompt 还仔细
  • Anthropic 承认 Claude 在隔离测试中黑入三家组织:和 OpenAI 接连翻车,AI 安全测试的威胁模型正在失效
  • 阜阳专科毕业升本科,如何比较机构的服务完整度 - 精彩城市
  • 重庆钻石回收迈入“全域直通时代”!行情一站透明无差价,7家合规门店开通钻石鉴定回收专线 - 二奢分享官
  • 闲置克罗心首饰别放着贬值!专业渠道盘活潮流珠宝,告别估价悬殊烦恼 - 全国二奢机构参考
  • 免费获取百度文库文档:终极指南与完整教程
  • Stability AI生成式模型:从2D到4D的视觉革命
  • 技术债务的偿还策略:如何说服业务方投资数据库架构升级
  • 2026年国内酒店用品厂家排行 适配不同酒店采购需求 - 甄选测评馆
  • 技术探秘:Windows 10上实现Android应用生态桥接的完整指南
  • 美丽蓝天大气治理补贴申报技术要点与落地解决方案 —— 越华环保一体化申报服务体系
  • 2026年武汉地区上上电缆代理厂家排行 适配多场景采购需求 - 甄选测评馆
  • 从MOD到MP3:OpenMPT音频导出全流程教程
  • 1688找工厂名片AI大改版:从7星到10星,商家该如何应对
  • 2026年绵阳装修公司挑选攻略:铭典装饰等优质企业实测梳理 - 比奇堡111
  • 2026深圳名包回收优选名录:7家正规机构实测对 - 全国二奢机构参考
  • 长沙买猫避坑指南!实测多家黑店,认准这家正规连锁猫舍 - 资讯报道
  • 本地大模型部署与API调用实战:LM Studio指南
  • 太仓淋浴房哪家性价比高?之江国际实体门店|欧卫特淋浴房靠谱优选 - 甄选测评馆
  • 零延迟流媒体革命:go2rtc终极摄像头接入解决方案 [特殊字符]
  • 30KG重载机器人分析:柔性力控与恒力打磨,越疆智能架构构筑优势
  • 5分钟快速上手:Kafka-UI可视化监控平台的完整使用指南
  • 【单片机课程设计/毕业设计】基于嵌入式技术的室内安防多传感一体化监测系统 基于 STM32 的燃气检测温控风扇人体照明控制系统(015601)
  • Illustrator脚本大全:从入门到精通的自动化设计指南
  • UnityShader Linear01Depth和LinearEyeDepth函数
  • 5分钟学会CartoonGAN-Test-Pytorch-Torch:简单命令行实现图片卡通化
  • 跨境电商指纹浏览器选型:AdsPower替代方案如何比较功能、成本与迁移条件
  • 众岸公考客观测评|打破地域误区:不止适配山东,全国考生均可选择 - 互联网科技品牌测评
  • 苏州买猫避坑指南!实测多家黑店,认准这家正规连锁猫舍 - 资讯报道