0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

UART的发送数据模块及Verilog代码

FPGA之家 ? 来源:AriesOpenFPGA ? 作者:AriesOpenFPGA ? 2021-05-27 18:05 ? 次阅读
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

代码注释有些匆忙,如有错误注释还请批评,仅作参考

UART

Uart比较简单,所以仅对tx作比较详细的注释,但里面一些内容还是值得新手学习的

1开始位(低电平)+8位数据+1停止位(高电平,这里选的是一个周期高电平,也可两个)(无校验位)

1、prescale是完成一个bit需要主时钟计数的次数(其和主时钟以及波特率之间的关系参考网上文章)

2、进入uart模块的异步信号,最好使用提供的同步器同步

3、异步复位信号最好使用提供的同步器同步

4、波特率任意选,只要时钟够大,能够符合误码率计算即可,这里使用的是125Mhz

5、基本的思想就是移位

6、传输条件就是握手

7、如果使用Xlinx的片子,建议使用全局时钟资源(IBUFG后面连接BUFG的方法是最基本的全局时钟资源的使用方法)

8、这个完整的代码就是使用IBUFG+BUFG

9、传输虽然简单,但对于新手来讲,还是有挺多的知识点值得学习的点

10、公众号只是对代码进行了简单注释

UART的发送数据模块

// 代码注释有些匆忙,如有错误注释还请批评,仅作参考// UART// 1开始位+8位数据+1停止位(无校验)// prescale是完成一个bit需要主时钟计数的次数(其和主时钟以及波特率之间的关系参考网上文章)// 进入uart模块的异步信号,最好使用提供的同步器同步// 异步复位信号最好使用提供的同步器同步// 波特率任意选,只要时钟够大,能够符合误码率计算即可,这里使用的是125M// 基本的思想就是移位// 传输条件就是握手// 如果使用Xlinx的片子,建议使用全局时钟资源(IBUFG后面连接BUFG的方法是最基本的全局时钟资源的使用方法)// 这个完整的代码就是使用IBUFG+BUFG// 传输虽然简单,但对于新手来讲,还是有挺多的知识点值得学习的// 公众号只是对代码进行了简单注释`timescale 1ns / 1ps/* AXI4-Stream UART */module uart_tx #( parameter DATA_WIDTH = 8)( input wire clk, // 系统时钟 input wire rst, // 复位信号

/* AXI input */ input wire [DATA_WIDTH-1:0] s_axis_tdata, // 输入到这个模块准备发送出去的数据 input wire s_axis_tvalid, // 有数据要输入到这个模块 output wire s_axis_tready, // 该模块准备好接收数据

output wire txd, // UART interface output wire busy, // Status 线忙 input wire [15:0] prescale // Configuration 预分度);

reg s_axis_tready_reg = 0;reg txd_reg = 1;reg busy_reg = 0;

reg [DATA_WIDTH:0] data_reg = 0;reg [18:0] prescale_reg = 0;reg [3:0] bit_cnt = 0;

assign s_axis_tready = s_axis_tready_reg;assign txd = txd_reg;assign busy = busy_reg;

always @(posedge clk) begin if (rst) begin s_axis_tready_reg 《= 0; // 从机没有准备好发送 txd_reg 《= 1; // 发送线拉高 prescale_reg 《= 0; // bit_cnt 《= 0; // 位计数器初始化为0 busy_reg 《= 0; // 复位后为不忙状态 end else begin if (prescale_reg 》 0) begin s_axis_tready_reg 《= 0; prescale_reg 《= prescale_reg - 1; end else if (bit_cnt == 0) //比特计数器为0 begin s_axis_tready_reg 《= 1; // 从机把ready信号拉高 busy_reg 《= 0; // 忙信号拉低无效 if (s_axis_tvalid) // 如果从机准备好接收数据 begin s_axis_tready_reg 《= !s_axis_tready_reg; // prescale_reg 《= (prescale 《《 3)-1; // bit_cnt 《= DATA_WIDTH+1; // 一共10次计数 data_reg 《= {1‘b1, s_axis_tdata}; // txd_reg 《= 0; // 起始位0(起始位tx拉低,停止位拉高) busy_reg 《= 1; // 开始传输后,传输线进入忙状态 end end else begin if (bit_cnt 》 1) // begin bit_cnt 《= bit_cnt - 1; prescale_reg 《= (prescale 《《 3)-1; // 经过(prescale 《《 3)-1次的系统时钟计数,完成一位的移位 {data_reg, txd_reg} 《= {1’b0, data_reg}; // 移位操作 end else if (bit_cnt == 1) begin bit_cnt 《= bit_cnt - 1; prescale_reg 《= (prescale 《《 3); txd_reg 《= 1; // 停止位1 end end end end

endmodule

UART的接收模块(不详细讲解)

// Language: Verilog 2001

`timescale 1ns / 1ps

/* * AXI4-Stream UART */module uart_rx #( parameter DATA_WIDTH = 8)( input wire clk, input wire rst,

/* AXI output */ output wire [DATA_WIDTH-1:0] m_axis_tdata, output wire m_axis_tvalid, input wire m_axis_tready, /* UART interface */ input wire rxd, /* Status */ output wire busy, output wire overrun_error, output wire frame_error, /* Configuration */ input wire [15:0] prescale

);

reg [DATA_WIDTH-1:0] m_axis_tdata_reg = 0;reg m_axis_tvalid_reg = 0;

reg rxd_reg = 1;

reg busy_reg = 0;reg overrun_error_reg = 0;reg frame_error_reg = 0;

reg [DATA_WIDTH-1:0] data_reg = 0;reg [18:0] prescale_reg = 0;reg [3:0] bit_cnt = 0;

assign m_axis_tdata = m_axis_tdata_reg;assign m_axis_tvalid = m_axis_tvalid_reg;

assign busy = busy_reg;assign overrun_error = overrun_error_reg;assign frame_error = frame_error_reg;

always @(posedge clk) begin if (rst) // 初始化各种参数 begin m_axis_tdata_reg 《= 0; m_axis_tvalid_reg 《= 0; rxd_reg 《= 1; prescale_reg 《= 0; bit_cnt 《= 0; busy_reg 《= 0; overrun_error_reg 《= 0; frame_error_reg 《= 0; end else begin rxd_reg 《= rxd; overrun_error_reg 《= 0; frame_error_reg 《= 0;

if (m_axis_tvalid && m_axis_tready) // 准备有数据要发以及准被好发 begin m_axis_tvalid_reg 《= 0; end

if (prescale_reg 》 0) // begin prescale_reg 《= prescale_reg - 1; end else if (bit_cnt 》 0) begin if (bit_cnt 》 DATA_WIDTH+1) begin if (!rxd_reg) // 实际的read为0时,开始计数bit begin bit_cnt 《= bit_cnt - 1; prescale_reg 《= (prescale 《《 3)-1; //prescale是16位移3位减1位,因为prescale_reg end else begin bit_cnt 《= 0; prescale_reg 《= 0; end end else if (bit_cnt 》 1) begin bit_cnt 《= bit_cnt - 1; prescale_reg 《= (prescale 《《 3)-1; data_reg 《= {rxd_reg, data_reg[DATA_WIDTH-1:1]}; end else if (bit_cnt == 1) begin bit_cnt 《= bit_cnt - 1; if (rxd_reg) begin m_axis_tdata_reg 《= data_reg; m_axis_tvalid_reg 《= 1; overrun_error_reg 《= m_axis_tvalid_reg; end else begin frame_error_reg 《= 1; end end end else begin busy_reg 《= 0; if (!rxd_reg) begin prescale_reg 《= (prescale 《《 2)-2; bit_cnt 《= DATA_WIDTH + 2; data_reg 《= 0; busy_reg 《= 1; end end endendendmodule

UART顶层

// Language: Verilog 2001

`timescale 1ns / 1ps

/* * AXI4-Stream UART */module uart #( parameter DATA_WIDTH = 8)( input wire clk, input wire rst,

/* * AXI input */ input wire [DATA_WIDTH-1:0] s_axis_tdata, input wire s_axis_tvalid, output wire s_axis_tready,

/* * AXI output */ output wire [DATA_WIDTH-1:0] m_axis_tdata, output wire m_axis_tvalid, input wire m_axis_tready,

/* * UART interface */ input wire rxd, output wire txd,

/* * Status */ output wire tx_busy, output wire rx_busy, output wire rx_overrun_error, output wire rx_frame_error,

/* * Configuration */ input wire [15:0] prescale

);

uart_tx #( .DATA_WIDTH(DATA_WIDTH))uart_tx_inst ( .clk(clk), .rst(rst), // axi input .s_axis_tdata(s_axis_tdata), .s_axis_tvalid(s_axis_tvalid), .s_axis_tready(s_axis_tready), // output .txd(txd), // status .busy(tx_busy), // configuration .prescale(prescale));

uart_rx #( .DATA_WIDTH(DATA_WIDTH))uart_rx_inst ( .clk(clk), .rst(rst), // axi output .m_axis_tdata(m_axis_tdata), .m_axis_tvalid(m_axis_tvalid), .m_axis_tready(m_axis_tready), // input .rxd(rxd), // status .busy(rx_busy), .overrun_error(rx_overrun_error), .frame_error(rx_frame_error), // configuration .prescale(prescale));

endmodule

同步(异步复位)模块

// Language: Verilog-2001// 很常用的模块`timescale 1 ns / 1 ps

/* * Synchronizes an active-high asynchronous reset signal to a given clock by * using a pipeline of N registers. */module sync_reset #( parameter N=2 // depth of synchronizer)( input wire clk, input wire rst, output wire sync_reset_out);

reg [N-1:0] sync_reg = {N{1‘b1}};

assign sync_reset_out = sync_reg[N-1];

always @(posedge clk or posedge rst) begin if (rst) sync_reg 《= {N{1’b1}}; else sync_reg 《= {sync_reg[N-2:0], 1‘b0};end

endmodule

同步(异步信号)模块

// Language: Verilog-2001// 很常用的模块`timescale 1 ns / 1 ps

/* * Synchronizes an asyncronous signal to a given clock by using a pipeline of * two registers. */module sync_signal #( parameter WIDTH=1, // width of the input and output signals parameter N=2 // depth of synchronizer)( input wire clk, input wire [WIDTH-1:0] in, output wire [WIDTH-1:0] out);

reg [WIDTH-1:0] sync_reg[N-1:0];

/* * The synchronized output is the last register in the pipeline. */assign out = sync_reg[N-1];

integer k;

always @(posedge clk) begin sync_reg[0] 《= in; for (k = 1; k 《 N; k = k + 1) begin sync_reg[k] 《= sync_reg[k-1]; endend

endmodule

原文标题:Uart协议及Verilog代码

文章出处:【微信公众号:FPGA之家】欢迎添加关注!文章转载请注明出处。

责任编辑:haq

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • Verilog
    +关注

    关注

    30

    文章

    1367

    浏览量

    112537
  • 代码
    +关注

    关注

    30

    文章

    4907

    浏览量

    71225

原文标题:Uart协议及Verilog代码

文章出处:【微信号:zhuyandz,微信公众号:FPGA之家】欢迎添加关注!文章转载请注明出处。

收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    XMC7100 F100K4160AA Uart2 dma实例程序无法运行,使用hal驱动发送丢字符并且无法接收怎么解决?

    2.dma_tx初始化代码 uart2.dma_tx发送代码 问题3:按tx同样的方式配置SCB2 dma_rx,只能在初始化完成触发一次CYHAL_DMA_TRANSFER_COM
    发表于 08-13 06:23

    2025年热门UART射频模块品牌与应用案例

    。在众多射频模块中,支持UART(通用异步收发传输器)接口的模块因其简单、可靠的特性,广泛应用于数据传输和设备通信。 以下是2025年值得关注的UA
    的头像 发表于 07-22 09:42 ?110次阅读
    2025年热门<b class='flag-5'>UART</b>射频<b class='flag-5'>模块</b>品牌与应用案例

    verilog模块的调用、任务和函数

    在做模块划分时,通常会出现这种情形,某个大的模块中包含了一个或多个功能子模块verilog是通过模块调用或称为
    的头像 发表于 05-03 10:29 ?796次阅读
    <b class='flag-5'>verilog</b><b class='flag-5'>模块</b>的调用、任务和函数

    为什么无法使用Lpuart_Uart_Ip_ 发送任何数据回调中的AsyncSend?

    我已经实现了基于 LPUART 的 DMA ,我可以发送使用 Lpuart_Uart_Ip_ 接收的数据同步发送 in lpuart_6_callback , 但是,我无法
    发表于 04-11 07:51

    UART、MCXA142实现ISP通信的主机端,发送Ping数据包并收到预期的响应,发送和接收数据包的典型顺序是什么?

    我想为 UART、MCXA142 实现 ISP 通信的主机端。我发送 Ping 数据包并收到预期的响应。发送和接收数据包的典型顺序是什么?
    发表于 04-03 08:05

    开源直接用!UDP-UART数据透传来了

    UDP连接将数据发送到远程设备,然后将这些数据通过UART接口发送到本地设备。 这种通信方式在需要将远程设备的
    的头像 发表于 02-05 17:14 ?398次阅读
    开源直接用!UDP-<b class='flag-5'>UART</b><b class='flag-5'>数据</b>透传来了

    Verilog 与 ASIC 设计的关系 Verilog 代码优化技巧

    Verilog与ASIC设计的关系 Verilog作为一种硬件描述语言(HDL),在ASIC设计中扮演着至关重要的角色。ASIC(Application Specific Integrated
    的头像 发表于 12-17 09:52 ?1130次阅读

    Verilog 测试平台设计方法 Verilog FPGA开发指南

    Verilog设计的仿真需求。 编写测试文件 : 编写Verilog测试文件,对设计的各个模块进行测试。测试文件应覆盖各种情况,包括正
    的头像 发表于 12-17 09:50 ?1223次阅读

    Verilog与VHDL的比较 Verilog HDL编程技巧

    Verilog 与 VHDL 比较 1. 语法和风格 VerilogVerilog 的语法更接近于 C 语言,对于有 C 语言背景的工程师来说,学习曲线较平缓。它支持结构化编程,代码
    的头像 发表于 12-17 09:44 ?1910次阅读

    如何自动生成verilog代码

    介绍几种自动生成verilog代码的方法。
    的头像 发表于 11-05 11:45 ?1173次阅读
    如何自动生成<b class='flag-5'>verilog</b><b class='flag-5'>代码</b>

    Verilog硬件描述语言参考手册

    一. 关于 IEEE 1364 标准二. Verilog简介三. 语法总结四. 编写Verilog HDL源代码的标准五. 设计流程
    发表于 11-04 10:12 ?4次下载

    Verilog语法中运算符的用法

    verilog语法中使用以下两个运算符可以简化我们的位选择代码
    的头像 发表于 10-25 15:17 ?2756次阅读
    <b class='flag-5'>Verilog</b>语法中运算符的用法

    uart波特率和传输频率的关系 UART串口的常用波特率为多少

    ) :是衡量UART通信速度的单位,表示每秒传输的比特数(bits per second,bps)。它反映了UART设备在发送和接收数据时使用的传输
    的头像 发表于 10-06 16:12 ?7535次阅读
    <b class='flag-5'>uart</b>波特率和传输频率的关系 <b class='flag-5'>UART</b>串口的常用波特率为多少

    怎么样提高verilog代码编写水平?

    优秀代码:在网上查找开源的、经过验证的高质量 Verilog 代码,学习他人的编程风格、代码结构和设计思路。 实践项目:尝试自己设计和实现一些较为复杂的项目,如复杂的控制器、
    发表于 09-25 20:05

    FPGA Verilog HDL代码如何debug?

    monitor 语句,在关键位置输出一些关键变量或中间结果的值,以便了解代码执行过程中的数据变化。 分模块调试:将复杂的设计分解为较小的模块,分别对每个
    发表于 09-24 19:16