• 发文章

  • 发资料

  • 发帖

  • 提问

  • 发视频

创作活动
0
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
返回

电子发烧友 电子发烧友

  • 全文搜索
    • 全文搜索
    • 标题搜索
  • 全部时间
    • 全部时间
    • 1小时内
    • 1天内
    • 1周内
    • 1个月内
  • 默认排序
    • 默认排序
    • 按时间排序
  • 全部板块
    • 全部板块
大家还在搜
  • 这次你说了算!先楫半导体开发者生态技术日

    HPM为开发者量身打造的生态活动正在规划中! 赶紧动动发财的小手填个小问卷,告诉我们你关心的话题和期待的场景,我们会认真阅读每一份问卷,听取大家的宝贵建议,期待您的反馈哈!

    2025-07-10 11:21

  • 这次你说了算!先楫半导体开发者生态技术日规划中,调查问卷等你来填

    HPM为开发者量身打造的生态活动正在规划中! 赶紧动动发财的小手填个小问卷,告诉我们你关心的话题和期待的场景,我们会认真阅读每一份问卷,听取大家的宝贵建议,期待您的反馈哈!

    2025-07-10 11:10

  • 【RK3568+PG2L50H开发板实验例程】FPGA部分 | 以太网传输实验例程

    ​本原创文章由深圳市小眼睛科技有限公司创作,版权归本公司所有,如需转载,需授权并注明出处(www.meyesemi.com) 1.实验简介 实验目的: 完成 DDR3 的读写测试。 实验环境: Window11 PDS2022.2-SP6.4 芯片型号: PG2L50H-484 2.实验原理 2.1. 开发板以太网接口简介 开发板使用裕泰微的裕太微电子的 YT8521SH-CA 实现了一个 10/100/1000 以太网端口。使用时需要用到光电转换模块,通过网线连接电脑的网口和光电转换模块的电口即可完成通信。 2.2. 以太网协议简介 2.2.1. 以太网帧格式 ​ 前导码(Preamble):8 字节,连续 7 个 8’h55 加 1 个 8’hd5,表示一个帧的开始,用于双方;设备数据的同步。 目的 MAC 地址:6 字节,存放目的设备的物理地址,即 MAC 地址;源 MAC 地址:6 字节,存放发送端设备的物理地址; 类型:2 字节,用于指定协议类型,常用的有 0800 表示 IP 协议,0806 表示 ARP 协议, 8035 表示 RARP 协议; 数据:46 到 1500 字节,最少 46 字节,不足需要补全 46 字节,例如 IP 协议层就包含在数据部分,包括其 IP 头及数据。 FCS:帧尾,4 字节,称为帧校验序列,采用 32 位 CRC 校验,对目的 MAC 地址字段到数据字段进行校验。 进一步扩展,以 UDP 协议为例,可以看到其结构如下,除了以太网首部的 14 字节,数据部分包含 IP 首部,UDP 首部,应用数据共 46~1500 字节。 ​ 2.2.2. ARP 数据报格式 ARP 地址解析协议,即 ARP(Address Resolution Protocol),根据 IP 地址获取物理地址。主机发送包含 目的 IP 地址的 ARP 请求广播(MAC 地址为 48’hff_ff_ff_ff_ff_ff)到网络上的主机,并接收返回消息,以此确 定目标的物理地址,收到返回消息后将 IP 地址和物理地址保存到缓存中,并保留一段时间,下次请求时直接查 询 ARP 缓存以节约资源。下图为 ARP 数据报格式。 ​ 帧类型:ARP 帧类型为两字节 0806; 硬件类型:指链路层网络类型,1 为以太网; 协议类型:指要转换的地址类型,采用 0x0800 IP 类型,之后的硬件地址长度和协议地址长度分别对应 6 和 4; OP 字段中 1 表示 ARP 请求,2 表示 ARP 应答 例如:|ff ff ff ff ff ff|00 0a 35 01 fe c0|08 06|00 01|08 00|06|04|00 01|00 0a 35 01 fe c0|c0 a8 00 02| ff ff ff ff ff ff|c0 a8 00 03| 表示向 192.168.0.3 地址发送 ARP 请求。 |00 0a 35 01 fe c0 | 60 ab c1 a2 d5 15 |08 06|00 01|08 00|06|04|00 02| 60 ab c1 a2 d5 15|c0 a8 00 03|00 0a 35 01 fe c0|c0 a8 00 02| 表示向 192.168.0.2 地址发送 ARP 应答。 2.2.3. IP 数据包格式 因为 UDP 协议包只是 IP 包中的一种, 所以我们来介绍一下 IP 包的数据格式。下图为 IP分组的报文头格式,报文头的前 20 个字节是固定的,后面的可变 ​ 版本:占 4 位,指 IP 协议的版本目前的 IP 协议版本号为 4 (即 IPv4); 首部长度:占 4 位,可表示的最大数值是 15 个单位(一个单位为 4 字节)因此 IP 的首部 长度的最大值是 60 字节; 区分服务:占 8 位,用来获得更好的服务,在旧标准中叫做服务类型,但实际上一直未被使用过 1998 年这个字段改名为区分服务。只有在使用区分服务(DiffServ)时,这个字段才起作用。一般的情况下都不使用这个字段; 总长度:占 16 位,指首部和数据之和的长度,单位为字节,因此数据报的最大长度为 65535 字节总长度必须不超过最大传送单元 MTU 标识:占 16 位,它是一个计数器,用来产生数据报的标识 标志(flag):占 3 位,目前只有前两位有意义 MF 标志字段的最低位是 MF (More Fragment),MF=1 表示后面“还有分片”。MF=0 表示最后一个分片; DF 标志字段中间的一位是 DF (Don\'t Fragment),只有当 DF=0 时才允许分片。 片偏移:占 12 位,指较长的分组在分片后某片在原分组中的相对位置.片偏移以 8 个字节为偏移单位; 生存时间;占 8 位,记为 TTL (Time To Live) 数据报在网络中可通过的路由器数的最大值,TTL 字段是由发送端初始设置一个 8 bit 字段.推荐的初始值由分配数字 RFC 指定,当前值为 64.发送 ICMP 回显应答时经常把 TTL 设为最大值 255; 协议;占 8 位,指出此数据报携带的数据使用何种协议以便目的主机的 IP 层将数据部分上交给哪个处理过程, 1 表示为 ICMP 协议, 2 表示为 IGMP 协议, 6 表示为 TCP 协议, 17 表示为 UDP 协议; 首部检验和:占 16 位,只检验数据报的首部不检验数据部分,采用二进制反码求和,即将16 位数据相加后,再将进位与低 16 位相加,直到进位为 0,最后将 16 位取反; 源地址和目的地址:都各占 4 字节,分别记录源地址和目的地址; 2.2.4. UDP 协议 UDP 是 User Datagram Protocol(用户数据报协议)的英文缩写。UDP 只提供一种基本的、低延迟的被称 为数据报的通讯。所谓数据报,就是一种自带寻址信息,从发送端走到接收端的数据包。UDP 协议经常用于图像 传输、网络监控数据交换等数据传输速度要求比较高的场合。 UDP 协议的报头格式: UDP 报头由 4 个域组成,其中每个域各占用 2 个字节,具体如下: ​ UDP 源端口号 目标端口号 数据报长度 校验和 UDP 协议使用端口号为不同的应用保留其各自的数据传输通道。数据发送一方将 UDP 数据报通过源端口 发送出去,而数据接收一方则通过目标端口接收数据。 数据报的长度是指包括报头和数据部分在内的总字节数。因为报头的长度是固定的,所以该域主要被用来计 算可变长度的数据部分(又称为数据负载)。数据报的最大长度根据操作环境的不同而各异。从理论上说,包含报 头在内的数据报的最大长度为 65535 字节。 不过,一些实际应用往往会限制数据报的大小,有时会降低到 8192 字节。 UDP 协议使用报头中的校验值来保证数据的安全。校验值首先在数据发送方通过特殊的算法计算得出,在传递到接收方之后,还需要再重新计算。如果某个数据报在传输过程中被第三方篡改或者由于线路噪音等原因受 到损坏,发送和接收方的校验计算值将不会相符,由此 UDP 协议可以检测是否出错。虽然 UDP 提供警告信息。 2.2.5. Ping功能 UDP 协议使用报头中的校验值来保证数据的安全。校验值首先在数据发送方通过特殊的算法计算得出,在 传递到接收方之后,还需要再重新计算。如果某个数据报在传输过程中被第三方篡改或者由于线路噪音等原因受 到损坏,发送和接收方的校验计算值将不会相符,由此 UDP 协议可以检测是否出错。虽然 UDP 提供有错误检测, 但检测到错误时,错误校正,只是简单地把损坏的消息段扔掉,或者给应用程序提供警告信息。 ​ ​ 3.SMI(MDC/MDIO)总线接口 串行管理接口( Serial Management Interface ),也被称作 MII 管理接口( MII ManagementInterface), 包括 MDC 和 MDIO 两条信号线。MDIO 是一个 PHY 的管理接口,用来读/写 PHY 的寄存器,以控制 PHY 的 行为或获取 PHY 的状态,MDC 为 MDIO 提供时钟,由 MAC 端提供,在本实验中也就是 FPGA 端。在 RTL8211EG 文档里可以看到 MDC 的周期最小为 400ns,也就是最大时钟为 2.5MHz。 ​ 3.1. SMI 帧格式 如下图,为 SMI 的读写帧格式: ​ 3.2. 读时序 ​ 可以看到在 Turn Around 状态下,第一个周期 MDIO 为高阻态,第二个周期由 PHY 端拉低。 3.3. 写时序 为了保证能够正确采集到数据,在 MDC 上升沿之前就把数据准备好,在本实验中为下降沿发送数据,上升沿接收数据。 4.实验设计 本实验以千兆以太网 RGMII 通信为例来设计 verilog 程序,会先发送预设的 UDP 数据到网络,每秒钟发 送一次.程序分为两部分,分别为发送和接收,实现了 ARP,UDP 功能。 4.1. 发送部分 4.1.1. MAC 层发送 发送部分中,mac_tx.v 为 MAC 层发送模块,首先在 SEND_START 状态,等待 mac_tx_ready 信号,如果 有效,表明 IP 或 ARP 的数据已经准备好,可以开始发送。再进入发送前导码状态,结束时发送 mac_data_req, 请求 IP 或 ARP 的数据,之后进入发送数据状态,最后进入发送 CRC 状态。在发送数据过程中,需要同时进行 CRC 校验。前导码完成后就将上层协议数据发送出去, 这个时候同样把这些上层数据放到 CRC32 模块中做序列生成,上层协议会给一个数据输出完成标志信号,这个 时候 mac_tx 知道数据发送完成了,需要结束 CRC32 的序列生成,这个时候就开始提取 FCS,衔接数据之后发 送出去。这样就连接了前导码---数据(Mac 帧)----FCS。之后跳转到结束状态,再回到 IDLE 状态,等待下一次的发送请求。 ​ 4.1.2. MAC 发送模式 工程中的 mac_tx_mode.v 为发送模式选择,根据发送模式是 IP 或 ARP 选择相应的信号与数据。 ​ ​ 4.1.3. ARP 发送 发送部分中,arp_tx.v 为 ARP 发送模块, 在 IDLE 状态下,等待 ARP 发送请求或 ARP 应答请求信号, 之后进入请求或应答等待状态,并通知 MAC 层,数据已经准备好,等待 mac_data_req 信号,之后进入请求或 应答数据发送状态。由于数据不足 46 字节,需要补全 46 字节发送。 ​ ​ ​ 4.1.4. IP 层发送 在发送部分,ip_tx.v 为 IP 层发送模块,在 IDLE 状态下,如果 ip_tx_req 有效,也就是 UDP 或 ICMP 发 送请求信号,进入等待发送数据长度状态,之后进入产生校验和状态,校验和是将 IP 首部所有数据以 16 位相 加,最后将进位再与低 16 位相加,直到进入为 0,再将低 16 位取反,得出校验和结果。 在生成校验和之后,等待 MAC 层数据请求,开始发送数据,并在即将结束发送 IP 首部后请求 UDP 或 ICMP 数据。等发送完,进入 IDLE 状态。 ​ ​ 4.1.5. IP 发送模式 工程中的 ip_tx_mode.v 为发送模式选择,根据发送模式是 UDP 或 ICMP 选择相应的信号与数据。 ​ ​ 4.1.6. UDP 发送 发送部分中,udp_tx.v 为 UDP 发送模块。 ​ 4.2. 接收部分 4.2.1. MAC 层接收 在接收部分,其中 mac_rx.v 为 mac 层接收文件,首先在 IDLE 状态下当 rx_en 信号为高,进入 REC_PREAMBLE 前导码状态,接收前导码。之后进入接收 MAC 头部状态,即目的 MAC 地址,源 MAC 地址, 类型,将它们缓存起来,并在此状态判断前导码是否正确,错误则进入REC_ERROR 错误状态,在 REC_IDENTIFY 状态判断类型是 IP(8’h0800)或 ARP(8’h0806)。然后进入接 收数据状态,将数据传送到 IP 或 ARP 模块,等待 IP 或 ARP 数据接收完毕,再接收 CRC 数据。并在接收数 据的过程中对接收的数据进行 CRC 处理,将结果与接收到的 CRC 数据进行对比,判断数据是否接收正确,正确 则结束,错误则进入 ERROR 状态。 ​ 4.2.2. ARP 接收 工程中的 arp_rx.v 为 ARP 接收模块,实现 ARP 数据接收,在 IDLE 状态下,接收到从 MAC 层发来的 arp_rx_req 信号,进入 ARP 接收状态,在此状态下,提取出目的 MAC 地址,源 MAC 地址,目的 IP 地址,源 IP 地址,并判断操作码 OP 是请求还是应答。如果是请求,则判断接收到的目的 IP 地址是否为本机地址,如果是, 发送应答请求信号 arp_reply_req,如果不是,则忽略。如果 OP 是应答,则判断接收到的目的 IP 地址及目的 MAC 地址是否与本机一致,如果是,则拉高 arp_found 信号,表明接收到了对方的地址。并将对方的 MAC 地 址及 IP 地址存入 ARP 缓存中。 ​ 4.2.3. IP 层接收模块 在工程中,ip_rx 为 IP 层接收模块,实现 IP 层的数据接收,信息提取,并进行校验和检查。首先在 IDLE 状 态下,判断从 MAC 层发过来的 ip_rx_req 信号,进入接收 IP 首部状态,先在 REC_HEADER0 提取出首部长 度及 IP 总长度,进入 REC_HEADER1 状态,在此状态提取出目的 IP 地址,源 IP 地址,协议类型,根据协议类 型发送 udp_rx_req 或 icmp_rx_req。在接收首部的同时进行校验和的检查,将首部接收的所有数据相加,存入 32 位寄存器,再将高 16 位与低 16 位相加,直到高 16 位为 0 ,再将低 16 位取反,判断其是否为 0,如果是 0,则检验正确,否则 错误,进入 IDLE 状态,丢弃此帧数据,等待下次接收。 ​ ​ 4.2.4. UDP 接收 在工程中,udp_rx.v 为 UDP 接收模块,在此模块首先接收 UDP 首部,再接收数据部分,在接收的同时进 行 UDP 校验和检查,如果 UDP 数据是奇数个字节,在计算校验和时,在最后一个字节后加上 8’h00,并进行校 验和计算。校验方法与 IP 校验和一样,如果校验正确,将拉高 udp_rec_data_valid 信号,表明接收的 UDP 数 据有效,否则无效,等待下次接收。 ​ 4.3. 其他部分 4.3.1. ICMP 应答 在工程中,icmp_reply.v 实现 ping 功能,首先接收其他设备发过来的 icmp 数据,判断类型是否是回送 请求(ECHO REQUEST),如果是,将数据存入 RAM,并计算校验和,判断校验和是否正确,如果正确则进入发送 状态,将数据发送出去。 ​ 4.3.2. ARP 缓存 在工程中,arp_cache.v 为 arp 缓存模块,将接收到的其他设备 IP 地址和 MAC 地址缓存,在发送数据之 前,查询目的地址是否存在,如果不存在,则向目的地址发送 ARP 请求,等待应答。在设计文件中,只做了一个缓 存空间,如果有需要,可扩展。 ​ ​ 4.3.3. CRC 校验模块(crc.v) CRC32 校验是在目标 MAC 地址开始计算的,一直计算到一个包的最后一个数据为止。一些网站可以自动 生成 CRC 算法的 verilog 文件:https://bues.ch/cms/hacking/crcgen.html ​ 5.实验现象 用光电转换模块插入 SFP 口,再用一根网线和 PC 端网口相连; 设置接收端(PC 端)IP 地址为 192.168.0.3,开发板的 IP 地址为 192.168.0.2 如下图 ​ 通过命令提示符,输入 arp -a,可以查到 IP:192.168.0.2 MAC:a0_b1_c2_d3_e1_e1; ​ 通过 Wireshark 软件抓包验证数据链路是否正常连接以及数据传输是否正常。资料包中 PC 端打开 Wireshark 软件,烧录重新后进行捕获数据报可以看到如下所示的交互过程。 成功建立连接后会持续发送数据报“www.meyesemi.com”。如下所示: ​ ​ Ping 功能测试,由上图可知,ping 基本不丢包。 ​

    2025-07-10 10:57

  • 【RK3568+PG2L50H开发板实验例程】FPGA部分 | 光纤通信测试实验例程

    ​本原创文章由深圳市小眼睛科技有限公司创作,版权归本公司所有,如需转载,需授权并注明出处(www.meyesemi.com) 1.实验简介 实验目的: 完成 DDR3 的读写测试。 实验环境: Window11 PDS2022.2-SP6.4 芯片型号: PG2L50H-484 2.实验原理 PG2L100H 内置了线速率高达 6.6Gbps 高速串行接口模块,即 HSSTLP,包含 1 个 HSSTLP 共 4 个全双工收发 LANE,除了 PMA,HSSTLP 还集成了丰富的 PCS 功能,可灵活应用于各种串行协议标准。在产品内部,每个 HSST 支持 1~4 个全双工收发 LANE。HSST 主要特性包括: 支持 DataRate 速率:0.6Gbps-6.6Gbps 灵活的参考时钟选择方式 发送通道和接收通道数据率可独立配置 可编程输出摆幅和去加重 接收端自适应线性均衡器 Logos2 系列 FPGA 器件数据手册 PMA Rx 支持 SSC 数据通道支持数据位宽:8bit only,10bit only,8b10b,16bit only,20bit only,32bit only,40bit only,64b66b/64b67b 等模式 可灵活配置的 PCS,可支持 PCI Express GEN1, PCI Express GEN2,XAUI,千兆以太 网,CPRI,SRIO 等协议 灵活的 Word Alignment 功能 支持 RxClock Slip 功能以保证固定的 Receive Latency 支持协议标准 8b10b 编码解码 支持协议标准 64b66b/64b67b 数据适配功能 灵活的 CTC 方案 支持 x2 和 x4 的 Channel Bonding HSSTLP 的配置支持动态修改 近端环回和远端环回模式 内置 PRBS 功能* 自适应 3.工程说明 3.1. 安装 HSST IP 核 PDS 安装后,需手动添加 HSST IP,请按以下步骤完成: (1)HSST IP 文件:选择 1_9.iar ​ (2)IP 安装步骤:请查看 “工具使用篇\\\\03_IP 核安装与查看用户指南” ​ 3.2. 光纤通信测试例程 打开PDS软件,新建工程hsst_test,点开如下图标,打开IPCompiler; ​ 选择 HSST IP,取名,然后点击 Customize; ​ 在 HSST 设置界面中 Protocol and Rate 按照如下设置,Channel0、 Channel1、Channel3 为 DISABLE, Channel2 设置为 Fullduplex(全双工), Protocol(协议) 选择CUSTOMERIZEDX1 (自定义模式),**TX Line Rate **和 RX Line Rate 均选择 6.25Gbps,**Encoder **均选择 8B10B,Data Width 选择 32bit,时钟选择 Diff_REFCK0,选择 125MHZ。 ​ Alignment and CTC 按照如下设置,Word Align Mode 选择 CUSTOMERIZED_MODE。控制字(COMMA code-group select)选择 K28.5,CTC_MODE 选择 Bypassed。 Misc 按照如下设置,时钟选择 25MHZ,其余保持默认,然后点击 Generate 可生成 HSST IP; ​ 关闭本工程,按此路径打开 Example 工程: hsst_test\\\\hsst_test\\\\ipcore\\\\hsst_test\\\\pnr\\\\example_design ​ 为了能在开发板上运行,需对顶层文件 hsst_test_dut_top 的复位进行修改,详情请查看例程顶层文件: ​ 上图是修改前的顶层文件。 下图是修改后的顶层文件。tx_disable 需要拉低才能打开 SFP 发射功能。 ​ ​ 上图为部分管脚约束,具体需要查看工程的 fdc 文件,注意图中红色方框部分是 hsst_lane 和 hsst_pll 的位置约束,是必须要添加的,差分数据管脚可以不用约束,提供给 hsst 的参考时钟必须约束即(i_p_refckn_0 和 i_p_refckp_0)。 ​ 为了观察收发数据是否有误,需要进行 Debugger 插核操作。 ​ 时钟选择 o_p_clk2core_tx_2。 可按以下方式查看 IP 核的用户指南,了解 Example 模块组成; ​ 4.实验现象 注:例程位置:hsst_test\\\\hsst_test\\\\ipcore\\\\hsst_test\\\\pnr\\\\example_design ​ 编辑 把光纤两端接入 SFP 口(用户需购买光模块),进行 Debugger 在线调试,可看到窗口中发送和接收的数据是一致的。 ​ 观察 tx_data 和 rx0_data_align,两者一样说明收发没有问题。 ​

    2025-07-10 10:51

  • 【RK3568+PG2L50H开发板实验例程】FPGA部分 | DDR3 读写实验例程

    ​ 本原创文章由深圳市小眼睛科技有限公司创作,版权归本公司所有,如需转载,需授权并注明出处(www.meyesemi.com) 1.实验简介 实验目的: 完成 DDR3 的读写测试。 实验环境: Window11 PDS2022.2-SP6.4 芯片型号: PG2L50H-484 2.实验原理 开发板集成 1 颗 4Gbit(512MB)DDR3 芯片,型号为 MT41K256M16。DDR3 的总线宽度共为 16bit。DDR3 SDRAM 的最高数据速率 1066Mbps。 2.1. DDR3 控制器简介 PG2L50H 为用户提供一套完整的 DDR memory 控制器解决方案,配置方式比较灵活,采用软核实现 DDR memory 的控制,有如下特点: 支持 DDR3 支持 x8、x16 Memory Device 最大位宽支持 32 bit 支持精简的 AXI4 总线协议 一个 AXI4 256 bit Host Port 支持 Self_refresh,Power down 支持 Bypass DDRC 支持 DDR3 Write Leveling 和 DQS Gate Training DDR3 最快速率达 1066 Mbps 3.工程说明 PDS 安装后,需手动添加 DDR3 IP,请按以下步骤完成: DDR3 IP 文件:PG2L_IP\\\\PG2L_IP\\\\DDR3\\\\ips2l_hmic_s_v1_10.iar ​ 3.1. DDR3 读写 Example 工程 打开 PDS 软件,新建工程 ddr3_test,点开如下图标,打开 IP Compiler; ​ 选择 DDR3 IP,取名 ddr3_test,然后点击 Customize; ​ 在 DDR3 设置界面中 Step1 按照如下设置: ​ Step2 按照如下设置,需要自己新建 DDR3 模型,选择 MT41K256M16XX 为模板,并保持Timing parameters 和地址以及 Drive Options 和下图设置的一致。 ​ Step3 按照如下设置,勾选 Custom Control/Address Group,管脚约束参考原理图: ​ ​ 提醒: 在设置 IP 核时,step 3:pin/bank options 中,管脚设置中的 Group Number 与原理图的对应关系如下图: ​ R5 表示 BANK5,G1 表示 Group Nmuber 为 1。 ​ Step4 为概要,点击 Generate 可生成 DDR3 IP; ​ 关闭本工程,按此路径打开 Example 工程: ​ 打开顶层文件,需要对顶层文件进行修改,具体参考详细代码。下图是经过修改后的顶层文件。 ​ 对“Step3 已做管脚约束”外的其他管脚,对照原理图使用 UCE 工具进行修改,移植的话可以直接参考工程的 fdc 文件进行移植。​ 以下管脚可约束在 LED,方便观察实验现象; ​ 可按以下方式查看 IP 核的用户指南,了解 Example 模块组成; ​ 4.实验现象 下载程序,可以看到 LED1 常亮,LED3 闪烁, LED4 闪烁,LED5 常亮; ​ 提醒:Heart_beat_led 信号闪烁表示 ddrphy 系统时钟正常。 ​ err_flag_led 信号闪烁说明数据检测无错误。可在 IP 核数据手册中找到。 ​ 如果正常的话,err_flag_led 闪烁的速度快于 heart_beat_led 的闪烁速度。 ​

    2025-07-10 10:46

  • 迅为RK3568开发板基本工程目录-工程级目录

    FA 模型和 Stage 模型的工程目录是存在差异的,接下来我们以之前新建的工程—— helloworld 为例,介绍一下 ArkTS 工程目录结构(Stage 模型)。 工程的目录结构如下图所示: 从上往下依次来了解下。 .hvigor 目录是编译构建脚本生成目录。 .idea 目录用于存储项目的配置信息,包括历史记录,版本控制信息等,是由开发工具自动生成的,一般情况下不需要进行修改。 AppScope 目录中存放应用全局所需要的资源文件。在 AppScope,其中有 resources 文件夹和配置文件 app.json5。AppScope>resources>base 中包含 element 和 media 两个文件夹,其中 element 文件夹主要存放公共的字符串、布局文件等资源。media 存放全局公共的多媒体资源文件。 entry 目录是应用的主模块,存放 OpenHarmony 应用的代码资源等等。 hvigor 目录存放的是一些配置文件的信息 oh_modules 目录用于存放三方库依赖信息。 .gitgnore 文件是在做代码版本管理的时候需要用到的一个文件,这个文件是做一些代码提交或者代码更新时候的忽略文件。 build-profile.json5 文件包括了应用级配置信息,包括签名、产品配置等。 接下来是三个文件 hvigorfiles.ts、hvigorw、hvigorw.bat 。hvigorfiles.ts 脚本是用来编译和构建任务的 TS 脚本。hvigorw.bat 和 hvigorw 其实是同一个文件,只是运行在不同的系统上, 这俩个文件是用来做 OHPM 的编译构建工具。 local.properties:这个文件是 DevEco Studio 自动生成的,保存了 SDK 路径,不需要修改这个文件。 最后两个文件是分别叫 oh-package.json5,那实际上这里面是依赖的一些配置。当然还包括你当前这个项目的一些配置,包括项目的名字、第三方包的一些依赖。有了这些依赖关系的话。那我们就可以基于这个依赖关系了,来生成一棵树形的依赖树。oh-package-lock.json5就是一个树形的依赖树。

    2025-07-10 10:45

  • 【RK3568+PG2L50H开发板实验例程】FPGA部分 | ROM、RAM、FIFO 的使用

    ​ 本原创文章由深圳市小眼睛科技有限公司创作,版权归本公司所有,如需转载,需授权并注明出处(www.meyesemi.com) 1.实验简介 实验目的: 掌握紫光平台的 RAM、ROM、FIFO IP 的使用 实验环境: Window11 PDS2022.2-SP6.4 芯片型号: PG2L50H-484 2.实验原理 不管是 Logos 系列或者是 Logos2 系列,其 IP 配置以及模式和功能均一致,不会像 PLL 那样有动态配置以及内部反馈选项的选择等之间的差异,所以是 RAM、ROM、FIFO 是通用的。 2.1. RAM 介绍 RAM 即随机存取存储器。它可以在运行过程中把数据写进任意地址,也可以把数据从任意地址中读出。其作用可以拿来做数据缓存,也可以跨时钟,也可以存放算法中间的运算结果等。 注意,PDS的IP配置工具中提供两种不同的RAM,一种是Distributed RAM(分布式RAM) 另一种是 DRM Based RAM,分布式 RAM 用的是 LUT(查找表)资源去构成的 RAM,这种 RAM 会消耗大量 LUT 资源,因此通常在一些比较小的存储才会用到这种 RAM,以节省 DRM 资源。而 DRM Based RAM 是利用片内的 DRM 资源去构成的 RAM,不占用逻辑资源,而且速度快, 通常设计中均使用 DRM Based RAM。 RAM 分为三种,如下表所示: RAM类型 特点 单端口 RAM 只有一个端口可以读写,只有一个读写口和地址口 伪双端口 RAM 有 wr 和 rd 两个端口,顾名思义,wr 只能写,rd 只能读 真双端口 RAM 提供 A 和 B 两个端口,两个端口均可以独立进行读写 注意,当使用真双端口时,要避免出现同时读写同个地址,这会造成写入失败,在逻辑设计上需要避开这个情况。 以下给出比较常用的 RAM 的配置作为介绍,通常我们比较常用伪双端口 RAM 来设计, 如图所示: ​ 下图为 IP 配置: ​ 注意,如果勾选 Enable Output Register(输出寄存),输出数据会延迟一个时钟周期。具体每个端口的含义这里参考官方手册,大家也可以自行查看 IP 手册,如下图所示: ​ DRM Resource Type:用于配置所建 RAM IP 核用的是哪种资源,不同芯片型号可选资源是不一样的,有的是 9K,有的是 18K,有的是 36K,如果没有特殊情况,直接 AUTO 即可。 2.1.1. RAM 的读写时序 配置成不同模式的时候,RAM 的读写时序是不一样的,真双端口和单端口的 RAM 配置均有三种模式,而伪双端口只有一种。由于真双端口和单端口的配置是一样的,这里以真双端口为例子。 分为 NORMAL_WRITE( 正 常 模 式 ) 、 TRANSPARENT_WRITE( 直 写 ) 、 READ_BEFORE_WRITE(读优先模式)三种模式。 ​ 而伪双端口不属于上面三种模式,有它独特的模式。这几种模式的差异就在于读写时序的不同,接下来,我们来分析读写时序。 以下时序图均来自官方 IP 手册,并且均未使能输出寄存。注意 wr_en 为 1 时表示写数据, 为 0 表示读数据。 2.1.1.1.NORMAL_WRITE ​ 在 NORMAL_WRITE 这种模式下,可以看到,当时钟的上升沿到来,且 clk_en 和 wr_en均为高电平时,就会把数据写到对应的地址里面,如图中的 1 时刻。然后看读数据端口,当wr_en 不为 0 的时候,a_rd_data 一直为 Don’t Care 状态,而当时钟上升沿到来,且 clk_en为高电平,wr_en 为低电平时,a_rd_data 输出当前 a_addr 里的数据,即 Mem(ADDR1)和 ADDR0 里的 D0。 2.1.1.2.READ_BEFORE_WRITE ​ 在 READ_BEFORE_WRITE 这种模式下,可以看到在 1 的时刻,时钟上升沿到来,且clk_en 和 wr_en 均为高电平,D0 写进了 ADDR0 里面,但是注意看此时的 a_rd_data 和a_addr,可以发现,此时 a_wr_en 并不为 0,可 a_rd_data 还是输出了上一刻 ADDR0 的数据(因为不是输出 D0)。之后,a_wr_en 拉低,此时才是读数据,在 3 时刻,把 ADDR0 的数据读出来,a_rd_data 才输出了 D0。 所以总结一下,这个模式其实就是进行写操作时,读端口会把当前写的地址的原始数据输出,因此叫读优先模式很合情合理对吧,顾名思义,就是我优先把原来的数据读出来。 2.1.1.3.Transparent_Write ​ 在 Transparent_Write 这种模式下,可以看到在 1 的时刻,时钟上升沿到来, 且clk_en 和 wr_en 均为高电平,D0 写进了 ADDR0 里面,但是注意看此时的 a_rd_data 和a_addr,可以发现,此时 a_wr_en 并不为 0,可 a_rd_data 居然直接输出了 D0,之后 a_wr_en拉低,进入读状态,在 2 时刻,再一次把 ADDR0 的数据读出来,输出了 D0。 分析总结一下,根据 1 时刻的情况,我们可以得出结论,在这种模式下,当我们进行写操作时,读端口会马上输出我们写入的数据。所以叫直写模式。 2.1.1.4. 伪双端口的读写时序 注意:wr_en 为 1 时是写操作,为 0 是读操作。 伪双端口的读写时序与上面三种都不同,我们看图 8 的时序来分析: ​ 注意看 1 时刻,此时 wr_en 和 wr_clk_en 均为高电平,所以是写操作,所以 1 时刻就是往地址 ADDR0 里写入 D0,注意此时的 rd_addr 和 rd_data,可以看到这一时刻 rd_addr 是 ADDR2,然后进行写操作时,rd_data 同样输出了 ADDR2 里的数据,而此时 wr_en 还是高电平。接下来看 2 和 3 时刻,此时 wr_en 为 0,rd_clk_en 是高电平,所以是读操作,此时分别读出 ADDR1 和 ADDR0 里的数据,之后 rd_clk_en 变成低电平,读时钟无效,可以看到rd_data 保持 D0 输出。 分析总结一下,主要是 1 时刻,大家可以看到 1 时刻往 ADDR0 写入了 D0,读端口却输出了 ADDR2 中的数据。仔细观察可以得出结论:伪双端口 RAM 在进行写操作的时候,会把当前读端口指向的地址的数据输出。是不是有点像直写?只不过直写是输出写入的数据,而伪双端口是输出读端口指向的地址的数据。 具体大家可以结合视频讲解。 2.2 ROM 介绍 ROM 即只读存储器,在程序的运行过程中他只能被读取,无法被写入,因此我们应该在初始化的时候就给他配置初值,一般是在生成 IP 的时候通过导入.dat 文件对其进行初值配置。 注意,PDS的 IP配置工具中提供两种不同的 ROM,一种是 Distributed ROM(分布式 ROM)另一种是 DRM Based ROM,分布式 ROM 用的是 LUT(查找表)资源去构成的 ROM,这种 ROM会消耗大量 LUT 资源,因此通常在一些比较小的存储才会用到这种 RAM,以节省 DRM 资源。而 DRM Based ROM 是利用片内的 DRM 资源去构成的 ROM,不占用逻辑资源,而且速度快,通常设计中均使用 DRM Based ROM。 以下给出比较常用的 ROM 的配置作为介绍,由于只能读,因此其均为单端口 ROM 如图所示: ​ 下图为 IP 配置: ​ 注意,如果勾选 Enable Output Register(输出寄存),输出数据会延迟一个时钟周期。 同时,可以看到 Enable Init 选项是默认勾选的,并且不可取消。 导入的数据的格式只能为二进制或者是十六进制,demo 选择十六进制。 具体每个端口的含义这里参考官方手册,大家也可以自行查看 IP 手册,如图所示: ​ 可以看到图中给出的是完整的接口列表,一般我们只需要 addr、rd_data、clk、rst这四个信号即可。 以下时序图均来自官方 IP 手册,并且均未使能输出寄存。 2.2.1. ROM 的读时序 ​ 可以看到该时序是非常简单的,比如在 TI 时刻,当 clk 上升沿到来时,且 clk_en 为高电平时,给出要读出的地址,rd_data 就会输出数据,在不勾选输出使能寄存的情况下,rd_data的输出会有延迟,具体时间可以从仿真里看到,所以我们在下个时钟周期的上升沿即 T2 时刻的上升沿才能获取到 ROM 读出的值。 所以整体时序非常简单,如果勾选了 clk_en 信号,就要给 clke_en 高电平才能读数据,如果不勾选 clk_en 信号,就一直根据地址读取 ROM 数据。 2.3. FIFO 介绍 FIFO 即先入先出,在 FPGA 中,FIFO 的作用就是对存储进来的数据具有一个先入先出特性的一个缓存器,经常用作数据缓存或者进行数据跨时钟域传输。FIFO 和 RAM 最大的区别就是 FIFO 不需要地址,采用的是顺序写入,顺序读出。 在紫光的 IP 工具中又分为 Distribute FIFO 和 DRM FIFO,其实就是用不同的资源去构成,前者 Distribute FIFO 也就是分布式 FIFO,使用的是片上的 LUT 资源去构成,而 DRM FIFO 使用的是片上的 DRM 资源去构成,DRM 构成的 FIFO 其性能大于 LUT 资源构成的,不仅容量更大,且可配置更多功能。 本章着重介绍 DRM Based FIFO。 注意:FIFO 写满后禁止继续写入数据,否则将会写溢出。 注意:FIFO 读空后禁止继续读数据,否则将会读溢出。 以下给出常用的 FIFO 的配置作为介绍。 ​ ​ 注意,如果勾选 Enable Output Register(输出寄存),输出数据会延迟一个时钟周期。 FIFO Type 有 SYNC 和 ASYNC 两种,第一种是同步 FIFO,读写端口共用一个时钟和复位,另一种是异步 FIFO,读写时钟和复位均独立。在平常设计中,比较常用的是异步 FIFO,因为同步 FIFO 和异步 FIFO 的读写时序一模一样,只有读写端口的时钟复位有差异,当异步 FIFO 的读写端口使用相同的时钟和复位,此时异步 FIFO 和同步 FIFO 基本是一致的。 Reset Type 也可以选择 SYNC 和 ASYNC 两种,SYNC 模式下需要时钟的上升沿采样到复位有效才会复位,而在 ASYNC 模式下,复位一旦有,FIFO 立即复位。 其余端口说明引用官方 IP 手册,如图所示: ​ 其中 rd_water_level 和 wr_water_level 分别代表”可读的数据量”和”已写入的数据量”,其含义与 Xilinx 的 FIFO 的 wr_data_count 和 rd_data_count 是一致的。 ​ 当我们将 Enable Almost Full Water Level 和 Enable Almost Empty Water Level 勾选上,才能看到 rd_water_level 和 wr_water_level,而下面的 Almost Full Numbers 的设置是表示当写入 1020 个数据时,Almost Full 信号就会拉高,Almost Empty Numbers 的设置表示当可读数据剩下 4 个时 Almost Empty 信号就会拉高。 同时 FIFO 支持混合位宽,例如写端口 16bit,读端口 8bit。如果写入 16’h0102,那么读出来会是 8’h02,8’h01,会先读出低位。 如果写端口 8bit,读端口 16bit。当写入 8’h01,8’h02 时,读出来是 16’h0201,先写入的数据存放在低位。 2.3.1.FIFO的读写时序 因为同步 FIFO 和异步 FIFO 的读写时序一致,这里用异步 FIFO 的读写时序图来做介绍。 注意:复位时高电平有效。读出数据均未勾选 Enable Output Register(输出寄存)。 2.3.1.1.FIFO 未满时的写时序 ​ 可以看到在 1 时刻,复位信号时低电平,处于工作状态,此时在 wr_clk 的上升沿且 wr_en 为高电平时将数据 D0 写入 FIFO,wr_water_level 也从 0 变 1,表示已经写入了一个数据,此时注意看读端口的 empty 信号,在 3 时刻 empty 信号从高变低,意味着读端口已经有数据可以读了,FIFO不再为空,而注意看,rd_clk和 wr_clk是不一样的,从 1写入到 3时刻 empty 拉低时,经过了 3 个 rd_clk。 所以这里我们可以得出结论:rd_water_level 要滞后 wr_water_level 三个 rd_clk。 2.3.1.2.FIFO 将满时的写时序 ​ 将满时主要分析 full 和 almost_full 信号。假设 Almost Full Numbers 设置为 N-2,在 1时刻,此时已经写入了 N-6 个数据,意味着再写 6 个数据 FIFO 就满了,从 1 时刻到 2 时刻一共写入了 4 个数据,因此当 wr_water_level 变成 N-2 时,满足条件,可以看到 Almost Full信号拉高,再写两个数据 FIFO 就满了,所以再经过两个时钟周期后,Full 信号拉高。 2.3.1.3.FIFO 在满状态下的读时序 ​ 在满状态下,FIFO 已经有 N 个数据了,此时在 1 状态下,rd_clk 的上升沿,且 rd_en 为 高 电 平 时 ,此 时 从 FIFO 里 读 出 数 据 (数 据 的 输 出 有 延 时 ,仿 真 中 延 时 0.2ns) 。此时 rd_water_level 变成 N-1,rd_data 输出 D0。然后看 2 时刻,full 信号拉低,此时可以看以下,在 1 时刻到 2 时刻期间一共经过了 3 个 wr_clk 写端口才能判断到此时数据量已经不为满。 所以我们可以得出结论,wr_water_level 要滞后 rd_water_level 三个 wr_clk。 2.3.1.4.FIFO 将空时的读时序 ​ 在 1 时刻,可读的数据量剩下 4,假设 Almost Empty Number 设为 2,在 1 时刻和 2 时刻分别读出了两个数据,所以在 2 时刻下,可读数据量剩下两个,达到 Almost Empty Number 触发条件,因此 almost_empty 信号拉高,再过两个时钟周期,即再读两个数据,FIFO 将变成空状态,也就是状态 3,此时 empty 信号拉高。 2.4. 接口列表 该部分介绍每个顶层模块的接口。 ram_test_top.v ​ rom_test_top.v ​ fifo_test_top.v ​ 3.代码仿真说明 本次的顶层模块实际就是例化 IP,然后把端口引出而已,主要代码都在 testbench 里面,所以我们直接介绍仿真代码。 3.1. RAM 仿真测试 `timescale 1ns/1ns module ram_test_tb(); reg sys_clk; reg rd_clk; reg rst_n; reg rw_en; //读写使能信号 reg [7:0] wr_data; reg [4:0] wr_addr; reg [4:0] rd_addr; wire [7:0] rd_data; reg [1:0] state; initial begin rst_n <= 1\'d0; sys_clk <= 1\'d0; rd_clk <= 1\'d0; #20 rst_n <= 1\'d1; end //读写控制 always@(posedge sys_clk or negedge rst_n) begin if(!rst_n) begin state <= 2\'d0; wr_data <= 8\'d0; rw_en <= 1\'d0; wr_addr <= 8\'d0; rd_addr <= 8\'d0; end else begin case(state) 2\'d0: begin rw_en <= 1\'d1; state <= 2\'d1; end 2\'d1: begin if(wr_addr == 5\'d31) begin rw_en <= 1\'d0; state <= 2\'d2; wr_data <= 8\'d0; wr_addr <= 5\'d0; rd_addr <= 5\'d0; end else begin state <= 2\'d1; wr_data <= wr_data+1\'b1; rd_addr <= rd_addr+1\'b1; wr_addr <= wr_addr+1\'b1; end end 2\'d2: begin if(rd_addr == 5\'d31) begin state <= 2\'d3; rd_addr <= 5\'d0; end else begin state <= 2\'d2; rd_addr <= rd_addr+1\'b1; end end 2\'d3: begin state <= 2\'d0; end default: state <= 2\'d0; endcase end end //50MHZ always #10 sys_clk = ~sys_clk; GTP_GRS GRS_INST( .GRS_N(1\'b1) ); ram_test_top u_ram_test_top( .wr_clk (sys_clk), .rd_clk (sys_clk), .rst_n (rst_n), .rw_en (rw_en), .wr_addr (wr_addr), .rd_addr (rd_addr), .wr_data (wr_data), .rd_data (rd_data) ); endmodule 涉及到 tb 的一些基础操作这里就不再详细讲解,只关注重点逻辑部分。从代码的 27 行到 80 行是 ram 的读写控制状态机。主要用来控制读写地址的生成和使能以及写入的数据。这里只讲解主要实现的功能,首先代码的 38-42 行,也就是 state=0 的时候,拉高 rw_en,并跳转到状态 1,此时进入写操作(没有使能 clk_en,可以不管),下个时钟周期开始写入数据(注意是时序逻辑,边沿采样,所以是下个时钟周期才开始写数据),即 state=1 的时候是一直在往 ram 里面写数据,在代码的 44 到 60 行就是写操作了,可以看到,当 wr_addr 不等于 31 的时候,wr_data 和 wr_addr 不断加 1(rd_addr 这里+1,可以看视频讲解,主要为了验证伪双端口的时序),当 wr_addr 等于 31 的时候,在下个时钟周期把数据清 0,状态跳转,在当前时钟周期下还会再往地址 31 里面写入数据,所以在该时钟周期,一共写入了 32 个数据(从地址 0 写到地址 31)。即状态 1 完成写入 32 个数据后跳转到 state=2 的逻辑。代码的 61-72 行,也就是 state=2 的时候,在每个周期的上升沿让 rd_addr 不断累加,直到 rd_addr=31 的时候,在下个时钟周期清空地址并让状态跳转的操作,而在当前时钟周期会继续把地址 31 的数据读出来,完成读取地址 0-31 的数据,一共 32 个数据,所以该状态主要完成读取 32 个数据,然后在下个时钟周期就跳转到 state=3。state=3 可以看到其主要作用就是等待一个时钟周期,然后跳转回去 state=0 下,起到一个延时作用。 ​ 上图为写数据的波形,数据从 0 开始递增到 31,地址也是从 0 到 31。 ​ 上图为读数据波形,从地址 0-31 读出了 0-31 个数据。 具体波形大家可以看视频仿真,或者自己尝试仿真,根据波形来看代码。因为这里是时序逻辑,所以如果是初学者,纯看文字可能会对 rd_addr=31 这一时刻还会再读一个数据感到疑惑,建议直接仿真,或者观看视频讲解的仿真部分,可以帮助快速理解。 可以总结出一句话就是 时序逻辑的赋值总在下一个时钟周期才生效。 所以在rd_addr=31 时执行的操作要在下一个时钟周期才会被采样生效。所以当前时钟还是会再从RAM 读出一个数据。 仿真代码的讲解到此结束,大家要注意时序逻辑的特点,具体的内容请看视频讲解。 3.2. ROM 仿真测试 `timescale 1ns/1ns module rom_test_tb(); reg sys_clk; reg rst_n; reg [9:0] rd_addr; wire [63:0] rd_data; initial begin rst_n <= 1\'d0; sys_clk <= 1\'d0; #20 rst_n <= 1\'d1; end //50MHZ always #10 sys_clk = ~sys_clk; GTP_GRS GRS_INST( .GRS_N(1\'b1) ); always@(posedge sys_clk or negedge rst_n) begin if(!rst_n) rd_addr <= 10\'d0; else rd_addr <= #2 rd_addr + 1\'b1; end rom_test_top u_rom_test_top( .rd_clk (sys_clk), .rst_n (rst_n), .rd_addr (rd_addr), .rd_data (rd_data) ); endmodule 代码 31-36 行例化了 ROM 的顶层模块,该模块里面其实就是调用了 ROM IP,然后把信号引出端口,没有任何逻辑操作。 代码 24-29 行通过一个 always 块不断生成地址,任何给到 ROM IP,将数据读出,由于没勾选 clk_en 信号,所以数据在 ROM 复位完成后就会不断读出。所以并没有复杂的逻辑,就是让地址从 0 不断累加,把数据读出。 ​ 上图为读出数据的波形图,可以看到读出的数据和 dat 文件里的数据一致。 ​ 仿真代码的讲解到此结束,大家要注意时序逻辑的特点,具体的内容请看视频讲解。 3.3. FIFO 仿真测试 `timescale 1ns/1ns module fifo_test_tb(); reg sys_clk; reg rst_n; reg [7:0] wr_data; reg wr_en; reg rd_en; reg rd_state; //读状态 reg wr_state; wire [7:0] rd_data; reg [7:0] rd_cnt; wire [7:0] rd_water_level; wire [7:0] wr_water_level; initial begin rst_n <= 1\'d0; sys_clk <= 1\'d0; #20 rst_n <= 1\'d1; end always #10 sys_clk = ~sys_clk; //50MHZ always@(posedge sys_clk or negedge rst_n) begin if(!rst_n) begin wr_state <= 1\'d0; wr_en <= 1\'d0; wr_data <= 8\'d0; end else begin case(wr_state) 1\'d0: if(wr_water_level == 127) //128 个数据 begin wr_en <= #2 1\'d0; wr_data <= #2 8\'d0; wr_state <= #2 1\'d1; end else begin wr_en <= #2 1\'d1; wr_data <= #2 wr_data+1\'b1; wr_state <= #2 1\'d0; end 1\'d1: if(rd_cnt == 127) wr_state <= #2 1\'d0; default: wr_state <= 1\'d0; endcase end end always@(posedge sys_clk or negedge rst_n) begin if(!rst_n) begin rd_state <= 1\'d0; rd_en <= 1\'d0; rd_cnt <= 8\'d0; end else begin case(rd_state) 1\'d0: if(rd_water_level >= 8\'d128) //等待 128 个数据 begin rd_state <= #2 1\'d1; rd_en <= #2 1\'d1; end else begin rd_cnt <= #2 8\'d0; rd_state <= #2 1\'d0; end 1\'d1: begin rd_cnt <= #2 rd_cnt + 1\'b1; if(rd_cnt == 127) begin rd_en <= #2 1\'d0; rd_state <= #2 1\'d0; end end default: rd_state <= 1\'d0; endcase end end GTP_GRS GRS_INST( .GRS_N(1\'b1) ); fifo_test_top u_fifo_test_top( .sys_clk (sys_clk), .rst_n (rst_n), .wr_data (wr_data), .wr_en (wr_en), .rd_en (rd_en), .wr_water_level (wr_water_level), .rd_water_level (rd_water_level), .rd_data (rd_data) ); endmodule 涉及到 tb 的一些基础操作这里就不再详细讲解,只关注重点逻辑部分。整个设计分为读写两个状态的控制。分别完成了写入 128 个数据,和读出 128 个数据,由于 FIFO 不需要地址,所以只需要产生使能信号即可。 首先看写状态,在 wr_state=0 时,拉高写使能,并让 wr_data 不断累加,往 FIFO 里面写数据,当 wr_water_level=127 的时候,拉低写使能,写数据置 0,写状态跳转到 1,注意此时还会再写入一个数据,所以到此一个写入了 128 个数据。至于拉低写使能,写数据置 0,写状态跳转到 1 这些操作将在下一个时钟周期才会被采样生效。之后,在 wr_state=1 时,不断等待 rd_cnt,该条件就是判断当读出 128 个数据的时候,wr_state 跳转到 0 状态。 接下来看读状态,在 rd_state=0 的时候,一旦可读的数据量超过 128 个(包括 128),状态跳转到 rd_state=1 下,然后开始读出数据,同时在 rd_state=1 下用变量 rd_cnt 对我们的读出数据也进行计数,rd_cnt 从 0 开始计数,当 rd_cnt=127 的时候会再往 FIFO 读出一个数据,所以此时就一共读出了 128 个数据,下一个时钟周期 rd_en 和 rd_state 都将置 0。 ​ 写数据的波形如上所示,一共写入 128 个数据,从 1 写到 128。 ​ 读数据的波形如上所示,一共读出 128 个数据,从 1 读到 128。 具体波形大家可以看视频仿真,或者自己尝试仿真,根据波形来看代码。因为这里是时序逻辑,所以如果是初学者,纯看文字可能会对 rd_cnt=127 这一时刻还会再读一个数据感到疑惑,建议直接仿真,或者观看视频讲解的仿真部分,可以帮助快速理解。 可以总结出一句话就是 时序逻辑的赋值总在下一个时钟周期才生效 ,所以在 rd_cnt=127 时执行的操作要在下一个时钟周期才会被采样生效。所以当前时钟 rd_en 还是 为 1,会再从 FIFO 读出一个数据。 仿真代码的讲解到此结束,具体的内容请看视频讲解。 ​

    2025-07-10 10:37

  • 请问一下这个恒压恒流工作原理

    2025-07-10 10:34

  • 【RK3568+PG2L50H开发板实验例程】FPGA部分 | Pango 的时钟资源——锁相环

    ​本原创文章由深圳市小眼睛科技有限公司创作,版权归本公司所有,如需转载,需授权并注明出处(www.meyesemi.com) 1.实验简介 实验目的: 了解 PLL IP 的基本使用方法。 实验环境: Window11 PDS2022.2-SP6.4 芯片型号: PG2L50H-484 2.实验原理 2.1. PLL 介绍 锁相环作为一种反馈控制电路,其特点是利用外部输入的参考信号来控制环路内部震荡信号的频率和相位。因为锁相环可以实现输出信号频率对输入信号频率的自动跟踪,所以锁相环通常用于闭环跟踪电路。锁相环在工作的过程中,当输出信号的频率与输入信号的频率相等时,输出电压与输入电压保持固定的相位差值,即输出电压与输入电压的相位被锁住,这就是锁相环名称的由来。 锁相环拥有强大的性能,可以对输入到 FPGA 的时钟信号进行任意分频、倍频、 相位调整、占空比调整,从而输出一个期望时钟;除此之外,在一些复杂的工程中, 哪怕我们不需要修改任何时钟参数,也常常会使用 PLL 来优化时钟抖动,以此得到一个更为稳定的时钟信号。正是因为 PLL 的这些性能都是我们在实际设计中所需要的,并且是通过编写代码无法实现的,所以 PLL IP 核才会成为程序设计中最常用 IP 核之一。 PLL IP 是紫光同创基于 PLL 及时钟网络资源设计的 IP,通过不同的参数配置,可实 现时钟信号的调频、调相、同步、频率综合等功能。 2.2. IP 配置 首先点击快捷工具栏的“IP”图标,进入 IP 例化设置 ​ 然后在 IP 目录处选择 PLL,在 Instance name 处为本次实例化的 IP 取一个名字,接着点击 Customise 进入 IP 配置页面。操作示意图如下: ​ PLL 的使用可选择 Basic 和 Advanced 两种模式,Advanced 模式下 PLL 的内部参数配置完全开放,需要自己填写输入分频系数、输出分频系数、占空比、相位、反馈分频系数等才能正确配置。Basic 模式下用户无需关心 PLL 的内部参数配置,只需输入期望的频率值、相位值、占空比等,IP 将自动计算,得到最佳的配置参数。如果没有特殊应用,建议使用 Basic 模式配置 PLL。本次实验我们选择 Basic Configuration。 ​ 接下来进行基础配置: 在 Public Configurations 一栏将输入时钟频率设置为 25MHZ。 在 Clockout0 Configurations 选项卡下,勾选使能 clkout0,将输出频率设置为 50MHZ。 在 Clockout1 Configurations 选项卡下,勾选使能 clkout1,将输出频率设置为 100MHZ。 在 Clockout2 Configurations 选项卡下,勾选使能 clkout2,将输出频率设置为 100MHZ,并设置相位偏移为 180 度。 其他选项可以使用默认设置,若有其他需求可以查阅 IP 手册了解,本实验我们暂介绍 IP 基本的使用方法: ​ 点击左上角 generate 生成 IP。 ​ 3.代码设计 模块接口列表如下所示: 表 1- 3- 1 PLL IP 使用实验模块接口表 端口 I/O 位宽 描述 sys_clk input 1 系统时钟 clkout0 output 1 54MHZ 时钟 clkout1 output 1 81MHZ 时钟 clkout2 output 1 81MHZ 时钟,相位偏移 180 度 lock output 1 时钟锁定信号,当为高电平时, 代表 IP 核输出时钟稳定 PLL_TEST 顶层代码: module PLL_TEST( inputsys_clk , outputclkout0 , outputclkout1 , outputclkout2 , outputlock ); PLL PLL_U0 ( .clkout0(clkout0 ),// output .clkout1(clkout1 ),// output .clkout2(clkout2 ),// output .lock(lock ),// output .clkin1 (sys_clk )// input ); endmodule 该模块的功能是例化 PLL IP 核,功能简单,在此不做说明。 PLL_tb 测试代码: timescale 1ns / 1ps module PLL_tb(); reg sys_clk ; wireclkout0 ; wireclkout1 ; wireclkout2 ; wirelock ; initial begin #2 sys_clk <= 0 ; end parameter CLK_FREQ = 25;//Mhz always # ( 1000/CLK_FREQ/2 ) sys_clk = ~sys_clk ; PLL_TEST u_PLL_TEST( .sys_clk(sys_clk), .clkout0(clkout0), .clkout1(clkout1), .clkout2(clkout2), .lock(lock) ); endmodule timescale 定义了模块仿真的时间单位和时间精度。时间单位是 1 纳秒,精度是 1 皮秒。 initial 块负责初始化系统时钟。在仿真启动后的 2 纳秒,系统时钟 sys_clk 被设置为 0。这是为了在仿真开始时定义一个已知的初始状态。 代码定义了一个时钟频率参数 CLK_FREQ 为 25 MHz,并使用一个 always 块来翻转系统时钟信号。always 块中的逻辑使得 sys_clk 每 40 纳秒翻转一次,从而生成一个 25MHz 的方波时钟信号。这种时钟信号用于驱动被测试的 PLL_TEST 模块。 最后,将测试平台的各个信号连接到 PLL_TEST 模块。这包括将生成的系统时钟 sys_clk 连接到 PLL_TEST 的时钟输入端,并将 PLL_TEST 的输出信号 clkout0、clkout1、 clkout2 和 lock 使用 wire 引出观察。 4.PDS 与 Modelsim 联合仿真 PDS 支持与 Modelsim 或 QuestaSim 等第三方仿真器的联合仿真,而 Modelsim 是较为常用的仿真器,使用 PDS 与 Modelsim 来进行联合仿真。 接下来选择 Project->Project Setting,打开工程设置,准备设置联合仿真。 ​ 选择 Simulation 选项卡,红框 1 选择刚才编译生成的仿真库的路径,红框 2 选择 Modelsim 的启动路径,之后点击 OK。 右键仿真的文件,选择 Run Behavior Simulation 开始行为仿真。 ​ 运行后会自动打开 Modelsim。并执行仿真,如果没有任何报错,则表示成功。如果出现错误,请检测 PDS 与 Modelsim 的配置。 ​ 5.实验现象 点击 Wave 观察 PLL 输出信号: ​ 使用标尺测量 clkout0,发现其一个时钟周期是 20ns,也就是 50MHZ。 ​ 可以看到 clkout1 的时钟频率是 100MHZ,且和 clkout2 相位偏差 180°,符合设置。需要注意 PLL 的输出时钟应该在时钟锁定信号 lock 有效之后才能使用,lock 信号拉高之前输出 的时钟是不确定的。 ​

    2025-07-10 10:28

  • CES Asia 2025同期低空智能感知与空域管理技术论坛即将启幕

    在低空经济蓬勃发展的大背景下,CES Asia 2025亚洲消费电子展备受瞩目,同期举办的低空智能感知与空域管理技术论坛更是引发行业内外高度关注。此次论坛聚焦低空通信导航监视技术、无人机反制与空域安全、UTM/UAM管理系统发展与互操作性、人工智能在空域动态管理中的应用等前沿议题,将汇聚全球顶尖专家、企业代表,共同探索低空领域的未来发展方向。 低空通信导航监视技术作为低空飞行的关键支撑,直接关系到飞行器的安全与高效运行。随着5G、卫星通信等技术的不断发展,低空通信正朝着高速率、低延迟的方向迈进,而高精度的导航与实时的监视技术,也为低空飞行器的精准定位与全程监控提供了保障。在本次论坛中,专家们将分享最新的技术研究成果,探讨如何进一步优化通信导航监视技术,以满足日益增长的低空飞行需求。 无人机的广泛应用在带来便利的同时,也对空域安全提出了挑战。无人机反制与空域安全议题的设置十分必要。行业内专业人士将围绕无人机非法入侵、干扰正常航空秩序等问题展开深入探讨,分享先进的无人机反制技术和空域安全管理经验,共同研究构建全方位、多层次的空域安全防护体系,确保低空空域的安全与稳定。 UTM(无人机交通管理系统)和UAM(城市空中交通)管理系统的发展,是实现低空交通有序运行的核心。它们的互操作性对于构建一体化的低空交通管理网络至关重要。论坛上,相关企业和研究机构将展示UTM/UAM管理系统的最新进展,探讨如何打破系统间的壁垒,实现不同系统之间的信息共享与协同工作,为未来城市空中交通的大规模商业化运营奠定基础。 人工智能技术的飞速发展,为空域动态管理带来了新的机遇。在这一议题下,与会者将深入探讨如何利用人工智能算法实现对空域态势的实时感知、智能预测和动态调控。通过对海量飞行数据的分析,人工智能能够优化飞行路径规划、提高空域利用率,同时及时发现并处理潜在的飞行冲突,提升空域管理的智能化水平和运行效率。 CES Asia 2025亚洲消费电子展同期举办的低空智能感知与空域管理技术论坛,将为低空领域的技术交流、产业合作搭建重要平台,有望推动低空经济在技术创新与安全管理方面取得新的突破,引领行业迈向更加规范、高效、智能的发展新阶段。我们期待这场思想与技术的盛宴,为低空经济的发展注入新的活力。

    2025-07-10 10:16