Xilinx FPGA:vivado实现串口的接收端

补充一些串口里用到的数值的相关知识点

接收端串口时序图:

程序设计:

`timescale 1ns / 1ps
/串口接收端    串行转并行
module uart_rx(
    input                  sys_clk ,
    input                  rst_n    ,
    input                  rx_data   ,  //输入串行数据
    output    reg[7:0]     uart_data , // 输出并行数据
    output    reg          rx_done     //数据传输完成结束信号      

    );
    
    parameter         SYSCLK =   50_000_000  ;
    parameter         Baud   =   115200      ;
    parameter         COUNT  =   SYSCLK/Baud ;//434   传输1比特所需要的时钟周期
    parameter         MID    =   COUNT/2     ;
    
    ///产生开始信号(检测下降沿-----二级寄存)
    reg           rx_reg1     ;
    reg           rx_reg2     ;
    
    wire          start_flag    ;  开始信号
    reg           rx_flag       ;
    reg    [3:0]   cnt_bit      ;///0~9
    reg    [9:0]   cnt          ;///434
    reg    [7:0]   data_reg     ;
    
    always@(posedge sys_clk)
          if(!rst_n)begin
          rx_reg1 <= 1 ;  //处于空闲位  数据线上无数据
          rx_reg2 <= 1 ;  //处于空闲位  数据线上无数据
          end
          else
              begin
                  rx_reg1 <= rx_data  ;
                  rx_reg2 <= rx_reg1  ;
              end
     assign start_flag = ~rx_reg1 & rx_reg2  ;  
     //rx_flag
     always@(posedge sys_clk )
           if(!rst_n)
              rx_flag <= 0 ;
           else if (start_flag)
              rx_flag <= 1 ;
           else if ( cnt_bit == 9 && cnt == MID -1 )
              rx_flag <= 0 ;
           else
              rx_flag <= rx_flag ;
   cnt 434  
     always@(posedge sys_clk )
           if(!rst_n)
              cnt <= 0;
           else if ( rx_flag == 1 )begin
                if ( cnt == COUNT -1) ///一定要减一,如果不减一,实际会计到435次,反算回去波特率就不是115200了
                    cnt <= 0;
                else
                    cnt <= cnt +1 ;
           end
           else
               cnt <= 0 ;
   
   /计数器
      always@(posedge sys_clk )
           if(!rst_n)
              cnt_bit <= 0 ;
           else if ( rx_flag )begin
                if ( cnt == COUNT -1)begin
                    if(cnt_bit == 9)
                    cnt_bit <= 0 ;
                    else
                    cnt_bit <= cnt_bit +1 ;
                    end
                else
                cnt_bit <= cnt_bit     ;
                end
           else
           cnt_bit <= 0 ;
           
    [7:0]uart_data
    /*
    cnt_bit = 0 起始位
    cnt_bit = 1-8 数据位
    cnt_bit = 9 停止位
    但是  [7:0]uart_data   没有uart[8]
    所以
    if ( cnt == MID -1 && cnt_bit > 0 && cnt_bit < 9 )
         uart_data[cnt_bit -1] <= rx_data ;
    */
//    always@(posedge sys_clk )
//          if(!rst_n)
//          uart_data <= 0 ;
//          else if ( rx_flag )begin
//                if ( cnt == MID -1 && cnt_bit > 0 && cnt_bit < 9 )
//                uart_data[cnt_bit -1] <= rx_data ; //这里uart_data是不断随着cnt_bit变化的,只有在第九位的时候才有正确的最终值
//                else
//                uart_data <= uart_data ;
//          end
//          else
//          uart_data <= 0 ;
    因为这里要让uart_data只在rx_done的时候有值,所以定义一个中间寄存器data_reg
     always@(posedge sys_clk )
          if(!rst_n)
          data_reg <= 0 ;
          else if ( rx_flag )begin
                if ( cnt == MID -1 && cnt_bit > 0 && cnt_bit < 9 )
                data_reg[cnt_bit -1] <= rx_data ; //这里uart_data是不断随着cnt_bit变化的,只有在第九位的时候才有正确的最终值
                else
                data_reg <= data_reg ;
          end
          else
          data_reg <= 0 ;
//  其他赋值方法1
//      always@(posedge sys_clk )
//          if(!rst_n)
//             uart_data <= 0;
//          else if (cnt == MID -1)begin
//             case(cnt_bit)
//             0:  uart_data  <= 0  ;
//             1:  uart_data [0] <= rx_data  ;
//             2:  uart_data [1] <= rx_data  ;
//             3:  uart_data [2] <= rx_data  ;
//             4:  uart_data [3] <= rx_data  ;
//             5:  uart_data [4] <= rx_data  ;
//             6:  uart_data [5] <= rx_data  ;
//             7:  uart_data [6] <= rx_data  ;
//             8:  uart_data [7] <= rx_data  ;
//             9:  uart_data  <= uart_data  ;  ///停止位的时候数据传完,保持
//             endcase
//             end
//           else
//             uart_data  <= uart_data  ;
   
//   其他赋值方法2
//    always@(posedge sys_clk )
//          if(!rst_n)
//          uart_data <= 0 ;
//          else if (cnt == MID -1 && cnt_bit > 0 && cnt_bit < 9)
//               uart_data <= {rx_data,uart_data[7:1]} ;
//          else
//               uart_data <= uart_data ;
          
   给uart_data赋值
     always@(posedge sys_clk )
          if(!rst_n)     
             uart_data <= 0 ;   
          else if (rx_flag)begin
               if (cnt_bit == 9 && cnt == MID/4 -1)
               uart_data <= data_reg ;
               else
               uart_data <= uart_data ;
          end
          else
          uart_data <= uart_data ; 可以保持到下一个数据到来
          uart_data <= 0 ;  只保持在rx_done处于高电平的时候
  /rx_done
     always@(posedge sys_clk )
          if(!rst_n)           
            rx_done <= 0 ;
          else if (rx_flag)begin
               if ( cnt_bit == 9 && cnt == MID/2 -1)
                   rx_done <= 1 ;
               else
                   rx_done <= 0 ;       
          end
          else
            rx_done <= 0 ;  
      
endmodule

仿真程序

`timescale 1ns / 1ps
module test_bench(  );

    reg                  sys_clk    ;
    reg                  rst_n      ;
    reg                  rx_data    ;  //输入串行数据
    wire[7:0]            uart_data  ; // 输出并行数据
    wire                 rx_done    ;//数据传输完成结束信号      

    parameter         SYSCLK =   50_000_000  ;
    parameter         Baud   =   115200      ;
    parameter         COUNT  =   SYSCLK/Baud ;//434   传输1比特所需要的时钟周期
    parameter         MID    =   COUNT/2     ;
    
initial
      begin
           sys_clk = 0 ;
           rst_n   = 0 ;
           #10
           rst_n   = 1 ;
      end
  always #1 sys_clk = ~sys_clk ; //2ns
  
  initial
        begin
            uart_out (8'h34);
            uart_out (8'hef);
            uart_out (8'h98);
            uart_out (8'h70);
            uart_out (8'h14);
        end
  
  
  //任务函数
  task     uart_out   ;
     input      [7:0]    DATA   ;
         begin
              rx_data = 1 ;///空闲位初始
              #20 
              rx_data = 0 ;///起始位
               ///传输1bit的计时次数*1周期时间=总时间
               #(COUNT*2)  rx_data = DATA[0] ;///数据位第一位
               #(COUNT*2)  rx_data = DATA[1] ;///数据位第二位
               #(COUNT*2)  rx_data = DATA[2] ;
               #(COUNT*2)  rx_data = DATA[3] ;
               #(COUNT*2)  rx_data = DATA[4] ;
               #(COUNT*2)  rx_data = DATA[5] ;
               #(COUNT*2)  rx_data = DATA[6] ;
               #(COUNT*2)  rx_data = DATA[7] ;
               #(COUNT*2)  rx_data = 1       ;
               #(COUNT*2)                    ;//停止位也需要时间
         end
  
  
  
  endtask



 
 uart_rx  uart_rx1(
          .    sys_clk    (sys_clk  )   ,
          .    rst_n      (rst_n    )   ,
          .    rx_data    (rx_data  )   ,  //输入串行数据
          .    uart_data  (uart_data)   ,  // 输出并行数据
          .    rx_done    (rx_done  )      //数据传输完成结束信号      

    );
endmodule

仿真波形

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/748292.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

导出excel带图片

文章目录 前言一、根据图片路径转为图片总结 前言 列表数据导出,带图片,图片为 http://xxxxx/1.jpg 这种 如何处理图片就是重点 一、根据图片路径转为图片 废话不多说,直接上代码 书接上文: 通用导出 // 多个sheetfor (Sheet sheet : writer.getSheets()) {// 循环每一条数据…

构建网络图 (JavaScript)

前序&#xff1a;在工作中难免有一些千奇百怪的需求&#xff0c;如果你遇到构建网络图&#xff0c;或者学习应对未来&#xff0c;请看这边文章&#xff0c;本文以代码为主。 网络图是数据可视化中实用而有效的工具&#xff0c;特别适用于说明复杂系统内的关系和连接。这些图表…

等保1.0与2.0:物理环境安全的演进之路

在信息安全的大厦中&#xff0c;物理环境安全是那坚实的基础&#xff0c;承载着整个信息系统的稳定与安全。随着时间的推移&#xff0c;我国的信息安全等级保护标准也在不断地进化与完善&#xff0c;从等保1.0到等保2.0&#xff0c;不仅仅是数字上的递增&#xff0c;更是对物理…

【黑龙江哪些行业需要做等保?】

黑龙江等保测评是衡量企业网络安全水平的一项主要指标&#xff0c;包括&#xff1a;金融&#xff0c;能源&#xff0c;电信&#xff0c;医疗&#xff0c;教育&#xff0c;交通&#xff0c;制造&#xff0c;电商等。 等保测评是黑龙江省信息化建设的重要组成部分&#xff0c;也…

Qt篇——获取Windows系统上插入的串口设备的物理序号

先右键【此电脑-管理- 设备管理器-端口&#xff08;COM和LPT&#xff09;】中找到我们插入的某个设备的物理序号&#xff0c;如下图红色矩形框出的信息&#xff0c;这个就是已插入设备的物理序号&#xff08;就是插在哪个USB口的意思&#xff09;。 在Linux下我们可以通过往/et…

linux下安装kkFileView4

kkFileView为文件文档在线预览解决方案&#xff0c;该项目使用流行的spring boot搭建&#xff0c;易上手和部署&#xff0c;基本支持主流办公文档的在线预览&#xff0c;如doc,docx,xls,xlsx,ppt,pptx,pdf,txt,zip,rar,图片,视频,音频等等 安装kkFileView前需要安装LibreOffic…

螺栓常用的防松方法

螺栓防松原理可以分为三种:摩擦防松、机械防松和永久防松。摩擦防松与机械防松为可拆卸防松&#xff0c;而永久防松为不可拆卸防松。 永久防松平常接触较少&#xff0c;这里只简单介绍一下常用的永久防松方法有:点焊、铆接、粘合等。这些方法在拆卸时大多要破坏螺纹紧固件&…

SAP ERP公有云(全称 SAP S/4HANA Cloud Public Edition),赋能企业成为智能可持续的企业

在数字化浪潮中&#xff0c;每一家企业都需要应对快速的市场变化&#xff0c;不断追求降本增效&#xff0c;为创新提供资源&#xff0c;发展新的业务模式&#xff0c;安全无忧地完成关键任务系统的转型。 10年前&#xff0c;SAP进入云领域&#xff0c;用云ERP和覆盖全线业务的云…

【C++题解】1714. 输出满足条件的整数4

问题:1714. 输出满足条件的整数4 类型&#xff1a;简单循环 题目描述&#xff1a; 输出 1∼n 中含有数字 3 或者含有数字 5 &#xff0c;且因数有 2 &#xff08;即能被 2 整除&#xff09;的所有整数。&#xff08;n<1000&#xff09; 输入&#xff1a; 从键盘输入一个…

使用深度远程启动管理器配置BMC DHCP管理地址的方法

目录 1.请确保服务器BMC是DHCP状态&#xff0c;才可以使用深度工具分配地址&#xff1b;若BMC配置过静态地址&#xff0c;请使用静态地址登录&#xff1b; 2.配置好自己笔记本的 ip&#xff08;例如&#xff1a;192.168.78.1&#xff09;&#xff0c;用网线与 ipmi 独立管理口…

结构冒险,控制冒险,数据冒险实例分析

目录 1.结构冒险&#xff1a; 2.数据冒险&#xff1a; 3.控制冒险&#xff1a; 指令执行过程&#xff1a; 取指(IF)&#xff1a;从指令存储器或 Cache 中取指令。 译码/读寄存器(ID)&#xff1a;操作控制器对指令进行译码&#xff0c;同时从寄存器堆中取操作数。 执行/计算地…

获取个人免费版Ubuntu Pro

首先上官网地址&#xff1a;Ubuntu Pro | Ubuntu 点击页面中的"Get Ubuntu Pro now" 将用途选为“Myself”&#xff0c;在此页面中Ubuntu说明了该版本只面向个人开发者&#xff0c;且最终只允许5台设备免费使用&#xff1b;因而部署设备的抉择就不得不慎重考虑了&am…

39 - 安全技术与防火墙

39、安全技术和防火墙 一、安全技术 入侵检测系统&#xff1a;特点是不阻断网络访问&#xff0c;主要是提供报警和事后监督。不主动介入&#xff0c;默默看着你&#xff08;监控&#xff09;。 入侵防御系统&#xff1a;透明模式工作&#xff0c;数据包&#xff0c;网络监控…

Linux常见操作问题

1、登录刚创建的用户&#xff0c;无法操作。 注&#xff1a;etc/passwd文件是Linux操作系统中存储用户账户信息的文本文件&#xff0c;包含了系统中所有用户的基本信息&#xff0c;比如用户名、用户ID、用户组ID、用户家目录路径。 注&#xff1a;etc: 这个目录存放所有的系统…

Linux 命令:iftop

1. 写在前面 本文主要介绍 Linux iftop&#xff08;Interface TOP&#xff09; 命令&#xff1a;iftop 是一款小巧、免费且功能强大的网卡实时流量监控工具。监控指定网卡的实时流量、端口连接信息、反向解析 IP 等&#xff0c;还可以精确显示本机网络流量及网络内各主机和本机…

记录待办事项的便签软件哪个好用?

在快节奏的现代生活中&#xff0c;我们经常需要处理各种各样的待办事项&#xff0c;为了更好地管理时间&#xff0c;许多人选择使用便签软件来记录自己的待办事项。那么&#xff0c;记录待办事项的便签软件哪个好用&#xff1f;市面上众多的便签软件中&#xff0c;哪一个才是最…

HashMap第5讲——resize方法扩容源码分析及细节

put方法的源码和相关的细节已经介绍完了&#xff0c;下面我们进入扩容功能的讲解。 一、为什么需要扩容 这个也比较好理解。假设现在HashMap里的元素已经很多了&#xff0c;但是链化比较严重&#xff0c;即便树化了&#xff0c;查询效率也是O(logN)&#xff0c;肯定没有O(1)好…

Proxmox VE(PVE)上手配置指南

Proxmox VE&#xff08;PVE&#xff09;是一款开源虚拟化管理平台&#xff0c;集成了KVM和LXC技术&#xff0c;支持虚拟机和容器管理。它提供了一个基于Web的用户界面&#xff0c;支持高可用性集群、备份和恢复、实时迁移等功能&#xff0c;适用于企业级虚拟化环境。. 以下为安…

安装GroudingDINO RuntimeError: Error compiling objects for extension,如何解决?

&#x1f3c6;本文收录于「Bug调优」专栏&#xff0c;主要记录项目实战过程中的Bug之前因后果及提供真实有效的解决方案&#xff0c;希望能够助你一臂之力&#xff0c;帮你早日登顶实现财富自由&#x1f680;&#xff1b;同时&#xff0c;欢迎大家关注&&收藏&&…

VCS编译bug汇总

‘typedef’ is not expected to be used in this contex 注册前少了分号。 Scope resolution error resolution : 声明指针时 不能与类名同名&#xff0c;即 不能声明为adapter. cannot find member "type_id" 忘记注册了 拼接运算符使用 关键要加上1b&#xff0…