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

AG32mcu通过寄存器方式操作cpld

从这个案例开始,需要了解AHB总线的基础知识了。如果对AHB总线不是很了解,可以自行百度再学习下。这里有个比较好的讲解:AMBA总线—AHB总线协议详解_ahb协议-CSDN博客

这里只描述用到的部分:

在AG32芯片内部,可以认为:cpu、ram、cpld、dma,这四个部分是挂在ahb总线下的。其他的外设都是挂在apb总线下的。

挂在ahb下的4部分,cpu、dma、cpld 这3个会成为master端,可能来抢占ahb总线。

在真实使用中,cpld经常被用于slave端,有点类似于“外设”,但却是挂在ahb下的。既然cpld是挂在ahb下的,那么它的接口就是要符合标准ahb访问协议的。

那么,当mcu来访问cpld的数据时,cpld就要根据这个接口来做对应的处理。

整个访问过程分为两部分:

1. mcu如何访问cpld的“寄存器”;

2. 当mcu访问时,cpld如何判别及响应;

分别描述。

1. mcu如何访问cpld

这部分很简单。

AG32在对地址编码中,cpld的地址区间设定为:0x60000000 ~ 0x7FFFFFFF

就像ram的地址区间是 0x20000000 ~ 0x20020000,flash的地址区间是0x80000000 ~ 0x800x0000 一样。

当mcu对大于0x60000000这个区间内的地址访问时,解码器会自动丢给cpld的接口。这时mcu就相当于访问了cpld的“寄存器”。

mcu是全局寻址,对这个空间的访问和对ram(0x20000000起)空间的访问是一样的方式,在C代码中,可以这样写:

读cpld:int cpRdReg = *((int *)0x60000000);

写cpld:*((int *)0x60000004) = cpWtReg;

Mcu端读写cpld,直接通过上述语句就可以了。理解和操作上都比较简单。

2. cpld如何判别及响应

这部分描述起来比较麻烦。总体是:cpld被ahb总线接口触发,并且回应要遵循ahb总线协议。

当上述mcu读写动作发生时,AHB总线会把动作拆解为读写信号,传递到analog_ip.v(新版本是user_ip.v)的接口,用户cpld程序需要响应该信号。

以下,以写动作 *((int *)0x60000004) = cpWtReg 为例,描述cpld端会发生的事情。

回顾下analog_ip.v中的接口部分:

其中slave_ahb_开头的一组信号,是cpld作为主端时用的,暂时不用理会。

Mem_ahb_开头的一组信号,是cpld作为从端使用的。

当mcu有读写操作时,mem_ahb_这组信号将发生变化

几个信号的概述(更详细的讲解请自行百度):

  • Ahb_htrans: 当前传输类型(00: IDLE、01: BUSY、10: NONSEQ、11: SEQ)
  • Ahb_ready:mcu读时要mcu要准备好cpld才会写
  • Ahb_hwrite: 要读还是要写(1为写,0为读)
  • Ahb_haddr[32]: 要操作的地址
  • Ahb_hsize:transfer的大小,以字节为单位
  • Ahb_hburst:批量传输
  • Ahb_hwdata[32]:写的数据,32位
  • Ahb_hreadyout:输出信号,mcu写时cpld是否准备好
  • Ahb_hresp:输出信号,响应信号(OK、retry、error、split)
  • Ahb_hrdata[32]:读的数据,32位

根据AHB时序,在一次传输中,cpld(slave端)会先拿到addr地址,读/写的标记,然后交互ready信号后,开始数据传输。

大致如下图(无等待类型的图):

比如,mcu要读0x60000004的寄存器:

mcu端直接C语言这样调用:int cpRdReg = *((int *)0x60000004);

cpld端,可以根据以上信号做如下处理:

----------------------------------------------

//mcu的读操作响应
//mcu端用C语言:int value = *((int *)0x60000004);
reg [31:0] hrdata_reg; //定义32位的hrdata_reg
always @(posedge sys_clock) begin //clk上升沿触发
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_reg
end
end
assign mem_ahb_hrdata = hrdata_reg; //绑定hrdata_reg到读的数据线上

-----------------------------------------------

以上代码,加入到analog_ip.v的module下,就可以完成cpld对mcu读动作的响应。

比如,mcu要写0x60000000的寄存器:

mcu端直接C语言这样调用:*((int *)0x60000000) = value;

cpld端,可以根据以上信号做如下处理:

----------------------------------------------

//mcu的写操作响应

//mcu端用C语言:*((int *)0x60000000) = value;

reg [0:0] isNewAction = 0;

reg [31:0] hwdata_reg; //定义32位的hwdata_reg
always @(posedge sys_clock) begin //clk上升沿触发
if (mem_ahb_htrans == 2'b10) //NONSEQ状态,第一次传输
begin
isNewAction <= 1;
end
if (mem_ahb_htrans == 2'b00 && //IDLE状态,真正开始写
isNewAction && //新动作
mem_ahb_hwrite && //写 (0 读,1 写)
mem_ahb_haddr[23:0] == 'h00) //写地址为0x60000000(cpld内部用相对偏移)。
begin
hwdata_reg <= mem_ahb_hwdata; //把收到的数据给到hwdata_reg
isNewAction <= 0;
end
end

//这个过程,是把mcu写进来的数据收到hwdata_reg中

-----------------------------------------------

这部分的实例代码,请参考网盘上获取:

链接:百度网盘 请输入提取码 里边的 \cpld-fpga文档\logic样例\5.mcu读写cpld寄存器

注意:这里展示的,仅仅是基于AHB总线上的数据交互。

在实际应用中,比如要实现一个串口之类的,往往是慢速设备,这些是要挂载到apb上的。慢速设备要经过ahb到apb的bridge,才能最终使用。请继续往下看。

http://www.dtcms.com/a/311655.html

相关文章:

  • linux ssh公钥移除办法
  • K8S部署ELK(三):部署Elasticsearch搜索引擎
  • accept函数及示例
  • CMake指令:mark_as_advanced
  • Django 日志配置详解
  • gbase8s 常见表约束介绍
  • 数字化转型驱动中小制造企业的质量管理升级
  • 技术面试知识点详解 - 从电路到编程的全栈面经
  • 【密码学】5. 公钥密码
  • 【Python修仙编程】(二) Python3灵源初探(11)
  • Noob靶机
  • 集成电路学习:什么是CMSIS微控制器软件接口标准
  • 用键盘快速移动Word和WPS文字中的选中段落
  • K8S部署ELK(二):部署Kafka消息队列
  • 计算机分类大全
  • 【学习笔记】MySQL技术内幕InnoDB存储引擎——第9章 性能调优
  • Android 13/14/15 默认授权应用权限的实现方法
  • 广告牌+序列帧的Shader效果
  • rocky\centos安装docker镜像的命令
  • 深入理解C++中的list容器:介绍、使用与实现
  • Flutter dart运算符
  • mini-swe-agent源码解读(进行中)
  • Redis 7 哈希(Hash)使用指南
  • 细分推广场景,让推客推广更贴合用户当下需求
  • 存储过程的介绍、基本语法、delimiter的使用
  • 未来交通:元宇宙技术重塑出行体验
  • 用Unity结合VCC更改人物模型出现的BUG
  • WebSocket断线重连机制:保障实时通信的高可用性
  • 疯狂星期四文案网第27天运营日记
  • 井云科技2D交互数字人:让智能服务触手可及的实用方案