AG32 MCU与CPLD通过AHB总线交互

MCU与CPLD可以通过AHB或APB总线进行数据交互。APB总线通常连接低速设备,如串口,而AHB总线则用于连接高速设备,如RAM等。由于我们需要高速采集大量数据,因此选择使用AHB总线与CPLD进行交互。

地址范围

在地址设计中,CPLD的地址区间设定为:0x60000000 ~ 0x7FFFFFFF。当MCU访问这个地址区间时,实际上是在访问CPLD内部的寄存器。

AHB介绍

https://blog.csdn.net/weixin_46022434/article/details/104987905

REG <-> MCU

MCU侧读写操作

MCU通过全局寻址机制来访问CPLD,其读写CPLD寄存器的方式与访问RAM(例如地址为0x20000000)相同。在C代码中,CPLD的访问操作可以通过如下方式实现

  • 读CPLD寄存器:
    int cpRdReg = *((int *)0x60000000);
    
  • 写CPLD寄存器:
    *((int *)0x60000004) = cpWtReg;
    

MCU侧的读写非常简便,直接使用上述方式即可完成操作。

CPLD侧读写

相关信号定义

assign slave_ahb_hready  = 1'b1;
reg hreadyout_reg;
reg hreadyout_del;
assign mem_ahb_hreadyout = hreadyout_reg;

信号hreadyout_del是信号hreadyout_reg延迟一个时钟周期的状态,主要用于协调AHB总线握手过程中的写操作。它确保从设备在准备好接收数据时进行操作,避免竞争条件的发生,从而确保数据正确写入hwdata_reg寄存器。

CPLD从AHB读数据

MCU执行写操作时,C代码示例如下:

*((int *)0x60000000) = value;

CPLD中相应的硬件逻辑如下:

//mcu的写操作响应
//mcu端用C语言:*((int *)0x60000000) = value;
reg [7:0] hwdata_reg;                                         //定义32位的hwdata_reg
always @(posedge sys_clock or negedge resetn) begin          //clk上升沿触发if (!resetn) begin//led3reg <= 1'b1;hreadyout_reg <= 1'b1;end else if(mem_ahb_htrans == 2'b10 && hreadyout_reg) begin //写地址为0x60000000(cpld内部用相对偏移)。hreadyout_reg <= 1'b0;//led3reg <= 1'b0;end else if(!hreadyout_del &&                          //cpld已ready状态,ahb上数据可以写过来了mem_ahb_hwrite &&                        //写 (0 读,1 写)mem_ahb_haddr[23:0] == 'h00) beginhwdata_reg <= mem_ahb_hwdata;        //把收到的数据给到hwdata_reghreadyout_reg <= 1'b1;//led3reg <= 1'b1;end else beginhreadyout_reg <= 1'b1;end
endalways @ (posedge sys_clock or negedge resetn) beginif (!resetn) beginhreadyout_del <= 1'b1;end else beginhreadyout_del <= hreadyout_reg;end
end

通过这些代码,我们确保了MCU写入0x60000000的数据能够准确地传输到CPLD。

CPLD向AHB写数据

MCU的读操作C代码如下:

int value = *((int *)0x60000004);

CPLD中对应的逻辑如下:

//mcu的读操作响应
//mcu端用C语言:int value = *((int *)0x60000004);
reg [7:0] hrdata_reg;                                         //定义32位的hrdata_reg
always @(posedge sys_clock or negedge resetn) begin          //clk上升沿触发if (!resetn) begin//led4reg <= 1'b1;end else if (mem_ahb_htrans == 2'b10 &&          //NONSEQ状态,第一次传输mem_ahb_hready &&                                  //master已ready,可以给数据线写入了!mem_ahb_hwrite &&                        //读 (0 读,1 写)mem_ahb_haddr[23:0] == 'h04)         //读地址为0x60000004(cpld内部用相对偏移)。beginhrdata_reg <= hwdata_reg;                //把另一准备好的数据给到hrdata_reg//led4reg <= 1'b0;end
end
assign mem_ahb_hrdata = hrdata_reg;        //绑定hrdata_reg到读的数据线上

通过这些代码,我们确保了MCU能够从CPLD准确读取0x60000004的数据。

FIFO IP <-> AHB

我们在设计中创建了一个FIFO IP核,并将其挂载到AHB总线上,以实现MCU对FIFO的读写访问。

FIFO IP配置

FIFO是先入先出,设计如下:

FIFO的设计为先入先出队列,配置如下:

  • 位宽设置为8位
  • 存储深度设置为4096,以充分利用4个M9K存储块
  • 其余参数保持默认配置,不使用emptyusedw信号。

值得注意的是,FIFO的读写时序上,读取数据时输出会滞后一个时钟周期。
在这里插入图片描述

FPGA代码设计

参考cpld-fpga文档中的5.mcu读写cpld寄存器

这里的设计需要参考AHB的时序图,由于AHB总在线上升沿进行数据读写操作,而FIFO也是在上升沿进行操作,因此我们将系统时钟反相后输入FIFO,以确保时序的一致性。

此外,AHB在传输数据时,数据与地址并非处于同一时钟周期内,数据会滞后一个时钟周期,因此我们给hreadyout 一个时钟周期的延时,从而确保AHB传输过来的数据被正确接收。此外,由于FIFO是在sys_clk下降沿进行数据读写,所以会滞后AHB数据读取一个周期,因此需要对wr_en进行一个周期的延时操作。

而在读取FIFO数据时,不需要hreadyout,FIFO的数据输出直接提供给AHB总线。

module user_ip (input              sys_clock,input              bus_clock,input              resetn,input              stop,input       [1:0]  mem_ahb_htrans,input              mem_ahb_hready,input              mem_ahb_hwrite,input       [31:0] mem_ahb_haddr,input       [2:0]  mem_ahb_hsize,input       [2:0]  mem_ahb_hburst,input       [31:0] mem_ahb_hwdata,output tri1        mem_ahb_hreadyout,output tri0        mem_ahb_hresp,output tri0 [31:0] mem_ahb_hrdata,output tri0        slave_ahb_hsel,output tri1        slave_ahb_hready,input              slave_ahb_hreadyout,output tri0 [1:0]  slave_ahb_htrans,output tri0 [2:0]  slave_ahb_hsize,output tri0 [2:0]  slave_ahb_hburst,output tri0        slave_ahb_hwrite,output tri0 [31:0] slave_ahb_haddr,output tri0 [31:0] slave_ahb_hwdata,input              slave_ahb_hresp,input       [31:0] slave_ahb_hrdata,output tri0 [3:0]  ext_dma_DMACBREQ,output tri0 [3:0]  ext_dma_DMACLBREQ,output tri0 [3:0]  ext_dma_DMACSREQ,output tri0 [3:0]  ext_dma_DMACLSREQ,input       [3:0]  ext_dma_DMACCLR,input       [3:0]  ext_dma_DMACTC,output tri0 [3:0]  local_int
);assign slave_ahb_hready  = 1'b1; reg hreadyout_reg;
reg hreadyout_del;assign mem_ahb_hreadyout = hreadyout_reg;// Internal signals
reg [7:0] data_in;
wire [7:0] data_out;
reg wr_en;
reg wr_en_del;
reg rd_en;assign mem_ahb_hrdata = {24'b0, data_out}; // Zero-padding upper bitsreg [1:0] state;//addr phase 00:idel 01:write 10:read// AHB state machine
always @(posedge sys_clock or negedge resetn) begin          //clk上升沿触发if (!resetn) beginhreadyout_reg <= 1'b1;wr_en <= 1'b0;end else if(mem_ahb_htrans == 2'b10 && hreadyout_reg) begin //写地址为0x60000000(cpld内部用相对偏移)。hreadyout_reg <= 1'b0;//led3reg <= 1'b0;end else if(!hreadyout_del &&                          //cpld已ready状态,ahb上数据可以写过来了mem_ahb_hwrite &&                        //写 (0 读,1 写)mem_ahb_haddr[23:0] == 'h00)beginhreadyout_reg <= 1'b1;data_in <= mem_ahb_hwdata[7:0];wr_en <= 1'b1;end else beginhreadyout_reg <= 1'b1;wr_en <= 1'b0;end
endalways @ (posedge sys_clock or negedge resetn) beginif (!resetn) beginhreadyout_del <= 1'b1;wr_en_del <= 1'b0;end else beginhreadyout_del <= hreadyout_reg;wr_en_del <=wr_en;end
end//mcu的读操作响应
//mcu端用C语言:int value = *((int *)0x60000004);
//reg [7:0] hrdata_reg;                                         //定义32位的hrdata_reg
always @(posedge sys_clock or negedge resetn) begin          //clk上升沿触发if (!resetn) beginrd_en <= 1'b0;end else if (mem_ahb_htrans == 2'b10 &&          //NONSEQ状态,第一次传输mem_ahb_hready &&                                  //master已ready,可以给数据线写入了!mem_ahb_hwrite &&                        //读 (0 读,1 写)mem_ahb_haddr[23:0] == 'h04)         //读地址为0x60000004(cpld内部用相对偏移)。begin//hrdata_reg <= hwdata_reg;                //把另一准备好的数据给到hrdata_regrd_en <= 1'b1;end else beginrd_en <= 1'b0;end
end
//assign mem_ahb_hrdata = hrdata_reg;        //绑定hrdata_reg到读的数据线上fifo_ip        fifo_ip_inst (.clock (~sys_clock),.data ( data_in ),.rdreq ( rd_en ),.wrreq ( wr_en_del ),.full ( full_sig ),.q ( data_out ));endmodule

最后综合出来的rtl网表如下图所示:
在这里插入图片描述

MCU代码

为了测试FIFO是否能正常工作,我们通过USB串口写入16个数据,然后读取并验证数据是否正确:

if ( tud_cdc_available() ){// read dataunsigned char buf[16] = {0};uint32_t count = tud_cdc_read(buf, sizeof(buf));(void) count;for(int i = 0; i < 16; i++){*((char *)0x60000000) = buf[i];//asm("nop");}unsigned char buf2[16] = {0};for(int i = 0; i < 16; i++){buf2[i] = *((char *)0x60000004);//asm("nop");}cdc_transfer(buf2, 16);}

从输出结果可以看到,接收到的数据与我们写入的数据完全一致,说明FIFO功能正常。
在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

【学习笔记】PT协程-未完待续

单线程编程-协程 单线程&#xff0c;所有协程都是共享栈–换句话说&#xff1a;裸机 代码结构 十分精简 lc 有两个版本 文件说明lc-addrlabels.h使用GCC扩展语法实现的协程基础lc-switch.h使用switch语句实现的协程基础lc.h用于选择GCC语法还是switch语句实现pt.h基于lc.h实…

【python系列】python内置函数print()和input()

1.前言 正式开始学习python编程基础知识&#xff0c;首先要建立正确的学习姿势&#xff0c;什么姿势呢&#xff0c;当然不是躺着。首先要学会看语法&#xff0c;学习每一个内置函数都要先把语法和语义理解&#xff0c;再结合勤于练习。有些同学可能英语不太好&#xff0c;这里…

并发基础:(淘宝笔试题)三个线程分别打印 A,B,C,要求这三个线程一起运行,打印 n 次,输出形如“ABCABCABC....”的字符串

🚀 博主介绍:大家好,我是无休居士!一枚任职于一线Top3互联网大厂的Java开发工程师! 🚀 🌟 在这里,你将找到通往Java技术大门的钥匙。作为一个爱敲代码技术人,我不仅热衷于探索一些框架源码和算法技巧奥秘,还乐于分享这些宝贵的知识和经验。 💡 无论你是刚刚踏…

字节、快手、Vidu“打野”升级,AI视频小步快跑

文&#xff5c;白 鸽 编&#xff5c;王一粟 继9月份版本更新之后&#xff0c;光锥智能从生数科技联合创始人兼CEO唐家渝朋友圈获悉&#xff0c;Vidu大模型将于本周再次进行版本升级&#xff0c;Vidu-1.5版本即将上线。 此版本更新方向仍是重点延伸大模型的泛化能力和主体…

redis实现消息队列的几种方式

一、了解 众所周知&#xff0c;redis是我们日常开发过程中使用最多的非关系型数据库&#xff0c;也是消息中间件。实际上除了常用的rabbitmq、rocketmq、kafka消息队列&#xff08;大家自己下去研究吧~模式都是通用的&#xff09;&#xff0c;我们也能使用redis实现消息队列。…

JVM(一、基础知识)

JVM虚拟机的灵魂三问 JVM是什么&#xff1f; 广义上是一种规范&#xff0c;狭义上的是JDK中的JVM虚拟机&#xff0c;虚拟机模拟计算机的组成部分&#xff0c;可以运行我们写的应用程序&#xff0c;是对操作系统的一层抽象&#xff0c;把我们的应用程序和操作系统解耦&#xff0…

问题分析与解决:Android开机卡动画问题分析

1. 问题背景及描述 在一个android设备的开发的项目中遇到了一个比较典型的问题:在主板贴片完成后,首次刷入androdi固件验证时,遇到了按键出发开机后,系统启动到android动画界阶段时一直循环卡在此阶段,无法进入桌面。如下如所示: 此问题在许多android项目的首次点亮阶段均…

视频会议接入GB28181视频指挥调度,语音对讲方案

传统的视频会议指挥调度系统目前主流的互联网会议大部分都是私有协议&#xff0c;功能都很独立。目前主流的视频监控国标都最GB平台&#xff0c;新的需求要求融合平台要接入监控等设备&#xff0c;并能实现观看监控接入会议&#xff0c;实时语音设备指挥现场工作人员办公实施。…

跟着尚硅谷学vue2—进阶版1.0—组件化编程

2. Vue 组件化编程 1. 传统方式和使用组件方式编写的对比 1. 传统方式编写应用 2. 使用组件方式编写应用 2. 模块与组件、模块化与组件化 1. 模块 理解: 向外提供特定功能的 js 程序, 一般就是一个 js 文件为什么: js 文件很多很复杂作用: 复用 js, 简化 js 的编写, 提高 j…

WebRTC视频 01 - 视频采集整体架构

一、前言&#xff1a; 我们从1对1通信说起&#xff0c;假如有一天&#xff0c;你和你情敌使用X信进行1v1通信&#xff0c;想象一下画面是不是一个大画面中有一个小画面&#xff1f;这在布局中就叫做PIP&#xff08;picture in picture&#xff09;&#xff1b;这个随手一点&am…

【大数据学习 | HBASE高级】rowkey的设计,hbase的预分区和压缩

1. rowkey的设计 ​ RowKey可以是任意字符串&#xff0c;最大长度64KB&#xff0c;实际应用中一般为10~100bytes&#xff0c;字典顺序排序&#xff0c;rowkey的设计至关重要&#xff0c;会影响region分布&#xff0c;如果rowkey设计不合理还会出现region写热点等一系列问题。 …

Spring Boot编程训练系统:架构设计与实现技巧

1系统概述 1.1 研究背景 随着计算机技术的发展以及计算机网络的逐渐普及&#xff0c;互联网成为人们查找信息的重要场所&#xff0c;二十一世纪是信息的时代&#xff0c;所以信息的管理显得特别重要。因此&#xff0c;使用计算机来管理编程训练系统的相关信息成为必然。开发合适…

刘知远LLM——大模型微调:prompt-learningdelta tuning

文章目录 背景&概览Prompt-learningdelta tuning增量式指定式重参数化式 OpenPrompt工具包 对应视频P41-P57 如何高效使用大模型&#xff1f;涉及到NLP的前沿技术&#xff0c;如prompt-learning&delta tuning。 prompt-learning对学习大模型范式的改变&#xff0c;del…

Spring Boot编程训练系统:性能优化实践

摘要 随着信息技术在管理上越来越深入而广泛的应用&#xff0c;管理信息系统的实施在技术上已逐步成熟。本文介绍了编程训练系统的开发全过程。通过分析编程训练系统管理的不足&#xff0c;创建了一个计算机管理编程训练系统的方案。文章介绍了编程训练系统的系统分析部分&…

电子应用产品设计方案-4:基于物联网和人工智能的温度控制器设计方案

一、概述 本温度控制器旨在提供高精度、智能化、远程可控的温度调节解决方案&#xff0c;适用于各种工业和民用场景。 二、系统组成 1. 传感器模块 - 采用高精度的数字式温度传感器&#xff0c;如 TMP117&#xff0c;能够提供精确到 0.01C 的温度测量。 - 配置多个传感器分布在…

如何在 Ubuntu 24.04 上安装和配置 Fail2ban ?

确保你的 Ubuntu 24.04 服务器的安全是至关重要的&#xff0c;特别是如果它暴露在互联网上。一个常见的威胁是未经授权的访问尝试&#xff0c;特别是通过 SSH。Fail2ban 是一个强大的工具&#xff0c;可以通过自动阻止可疑活动来帮助保护您的服务器。 在本指南中&#xff0c;我…

同三维T610UDP-4K60 4K60 DP或HDMI或手机信号采集卡

1路DP/HDMI/TYPE-C&#xff08;手机/平板等&#xff09;视频信号输入1路MIC1路LINE OUT,带1路HDMI环出&#xff0c;USB免驱&#xff0c;分辨率4K60&#xff0c;可采集3路信号中其中1路&#xff0c;按钮切换&#xff0c;可采集带TYPE-C接口的各品牌手机/平板/笔记本电脑等 同三维…

Kafka--关于broker的夺命连环问

目录 1、zk在kafka集群中有何作用 2、简述kafka集群中的Leader选举机制 3、kafka是如何处理数据乱序问题的。 4、kafka中节点如何服役和退役 4.1 服役新节点 1&#xff09;新节点准备 2&#xff09;执行负载均衡操作 4.2 退役旧节点 5、Kafka中Leader挂了&#xff0c;…

Web项目版本更新及时通知

背景 单页应用&#xff0c;项目更新时&#xff0c;部分用户会出更新不及时&#xff0c;导致异常的问题。 技术方案 给出版本号&#xff0c;项目每次更新时通知用户&#xff0c;版本已经更新需要刷新页面。 版本号更新方案版本号变更后通知用户哪些用户需要通知&#xff1f;…

Android音视频直播低延迟探究之:WLAN低延迟模式

Android WLAN低延迟模式 Android WLAN低延迟模式是 Android 10 引入的一种功能&#xff0c;允许对延迟敏感的应用将 Wi-Fi 配置为低延迟模式&#xff0c;以减少网络延迟&#xff0c;启动条件如下&#xff1a; Wi-Fi 已启用且设备可以访问互联网。应用已创建并获得 Wi-Fi 锁&a…