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

8-verilog-串口接收与发送模块

verilog-串口接收与发送模块

1.串口接收

module uart_recv_parity(input          sys_clk,          // 系统时钟input          sys_rst_n,        // 系统复位,低电平有效input          uart_rxd,         // UART接收端口output reg     uart_done,        // 接收一帧数据完成标志信号output reg     frame_error,      // 帧错误(停止位不为1)output reg     parity_error,     // 奇偶校验错误output reg [7:0] uart_data       // 接收的数据
);// 参数定义
parameter  CLK_FREQ = 50000000;      // 系统时钟频率
parameter  UART_BPS = 9600;          // 串口波特率
parameter  PARITY   = "ODD";         // 校验类型:"NONE", "ODD", "EVEN"
localparam BPS_CNT  = CLK_FREQ/UART_BPS;  // 每个波特率周期的时钟数
localparam BPS_CNT_HALF = BPS_CNT/2; // 半位周期时钟数// 寄存器定义
reg [1:0]  uart_rxd_sync;           // 同步寄存器
reg [15:0] clk_cnt;                 // 波特率时钟计数器
reg [3:0]  rx_cnt;                  // 接收位计数器
reg        rx_flag;                 // 接收过程标志
reg [7:0]  rxdata;                  // 接收数据寄存器
reg        parity_bit;              // 计算的奇偶校验位
reg        received_parity;         // 接收到的校验位// 检测起始位下降沿
wire start_flag = (uart_rxd_sync == 2'b10); // 同步输入信号,防止亚稳态
always @(posedge sys_clk or negedge sys_rst_n) begin if (!sys_rst_n) uart_rxd_sync <= 2'b11;else uart_rxd_sync <= {uart_rxd_sync[0], uart_rxd};
end// 接收过程控制
always @(posedge sys_clk or negedge sys_rst_n) begin         if (!sys_rst_n)                                  rx_flag <= 1'b0;else if(start_flag)                       // 检测到起始位rx_flag <= 1'b1;                     // 开始接收else if((rx_cnt == 4'd9 && PARITY == "NONE") || (rx_cnt == 4'd10 && PARITY != "NONE"))if(clk_cnt == BPS_CNT_HALF)rx_flag <= 1'b0;                 // 接收完成
end// 波特率时钟计数器和接收位计数器
always @(posedge sys_clk or negedge sys_rst_n) begin         if (!sys_rst_n) begin                             clk_cnt <= 16'd0;                                  rx_cnt  <= 4'd0;end                                                      else if(rx_flag) begin                   // 接收过程中if(clk_cnt < BPS_CNT - 1)clk_cnt <= clk_cnt + 1'b1;else beginclk_cnt <= 16'd0;rx_cnt  <= rx_cnt + 1'b1;endendelse begin                              // 非接收过程clk_cnt <= 16'd0;rx_cnt  <= 4'd0;end
end// 计算奇偶校验位
always @(posedge sys_clk or negedge sys_rst_n) beginif (!sys_rst_n) beginparity_bit <= 1'b0;endelse if (rx_flag && (rx_cnt == 4'd8) && (clk_cnt == BPS_CNT_HALF)) beginif (PARITY == "ODD")parity_bit <= ^rxdata;          // 奇校验else if (PARITY == "EVEN")parity_bit <= ~^rxdata;         // 偶校验end
end// 接收校验位
always @(posedge sys_clk or negedge sys_rst_n) beginif (!sys_rst_n) beginreceived_parity <= 1'b0;endelse if (rx_flag && (rx_cnt == 4'd9) && (clk_cnt == BPS_CNT_HALF) beginreceived_parity <= uart_rxd_sync[1];end
end// 数据位采样
always @(posedge sys_clk or negedge sys_rst_n) begin if(!sys_rst_n)  rxdata <= 8'd0;                                     else if(rx_flag && (clk_cnt == BPS_CNT_HALF)) begincase(rx_cnt)4'd1: rxdata[0] <= uart_rxd_sync[1];4'd2: rxdata[1] <= uart_rxd_sync[1];4'd3: rxdata[2] <= uart_rxd_sync[1];4'd4: rxdata[3] <= uart_rxd_sync[1];4'd5: rxdata[4] <= uart_rxd_sync[1];4'd6: rxdata[5] <= uart_rxd_sync[1];4'd7: rxdata[6] <= uart_rxd_sync[1];4'd8: rxdata[7] <= uart_rxd_sync[1];default: rxdata <= rxdata;endcaseend
end// 输出数据和状态
always @(posedge sys_clk or negedge sys_rst_n) begin        if(!sys_rst_n) beginuart_data   <= 8'd0;                               uart_done   <= 1'b0;frame_error <= 1'b0;parity_error <= 1'b0;endelse if(((rx_cnt == 4'd9) && (PARITY == "NONE")) || ((rx_cnt == 4'd10) && (PARITY != "NONE"))) beginif(clk_cnt == BPS_CNT_HALF) beginuart_data <= rxdata;            // 输出接收数据uart_done <= 1'b1;              // 接收完成信号// 检查停止位(总是第9/10位,取决于是否有校验)if(PARITY == "NONE")frame_error <= ~uart_rxd_sync[1];  // 检查停止位是否为1elseframe_error <= ~uart_rxd_sync[1];  // 检查停止位是否为1// 检查校验位if(PARITY != "NONE")parity_error <= (received_parity != parity_bit);elseparity_error <= 1'b0;endendelse beginuart_done <= 1'b0;               // 完成信号只持续一个周期end    
endendmodule

2.串口发送

在这里插入代码片
http://www.dtcms.com/a/313011.html

相关文章:

  • Python切片命名技术详解:提升代码可读性与维护性的专业实践
  • linux下jvm之jstack的使用
  • 洛谷——P1048 [NOIP 2005 普及组] 采药
  • 【openlayers框架学习】九:openlayers中的交互类(select和draw)
  • GaussDB SQL执行计划详解
  • Rust: 获取 MAC 地址方法大全
  • Zama的使命
  • 【读论文】KAG-Thinker:升级版RAG 框架
  • 推荐系统学习笔记(九)曝光过滤 Bloom Filter
  • 【DL学习笔记】感受野(Receptive Field)
  • 映射网络驱动器后,重启映射就没了
  • 王之凝视 免安中文 离线运行版
  • 【Bluetooth】【Transport层篇】第四章 基于基础UART的蓝牙硬件发送协议 UART H4 Transport详解
  • wordpress登陆前登陆后显示不同的顶部菜单
  • 前后端交流
  • Go语言声明变量
  • mybatis实现固定三层树形结构的嵌套查询
  • 怎么修改论文格式呢?提供一份论文格式模板
  • 【ProtoBuf】初识ProtoBuf
  • 【UE5医学影像可视化】读取本地Dicom生成VolumeTexture,实现2D显示和自动翻页
  • 关于记录一下“bug”,在做图片上传的时候出现的小问题
  • B3953 [GESP202403 一级] 找因数
  • 大模型智能体(Agent)技术全景:架构演进、协作范式与应用前沿
  • Python Dash 全面讲解
  • 使用 Vuepress + GitHub Pages 搭建项目文档
  • io_getevents系统调用及示例
  • Android 之 图片加载(Fresco/Picasso/Glide)
  • 第四章:OSPF 协议
  • Docker环境离线安卓安装指南
  • Android 之 存储(Assets目录,SharedPreferences,数据库,内部存储等)