AG32:MCU和CPLD交互实操指南

本文档介绍了AG32开发中,MCU与CPLD交互的具体方式以及例子。

一、MCU和CPLD直接交互

cpld工程创建及编译的操作流程,参考文档《AG32fpgacpld的使用入门》

图片

在工程中,用户逻辑部分编写是从analog_ip.v的接口下开始的。

mcucpld之间的交互,可以分为:

1. mcu传递信号给cpld;(如mcugpio传递高低信号到cpld

2. cpld传递信号给mcu;(如:对mcu产生中断信号)

3. mcu读写数据到cpld

4. 不建议,cpld做为主设备对mcu写。

也就是说,在mcucpld交互中,cpld更像一个外设。

其中,前两种较为简单。后两种要使用AHB总线来操作。

下边针对四种情况分别说明:

1. mcu传递信号给cpld

这种使用较简单。步骤如下:

ve中定义信号:

GPIO4_1iocvt_chn:OUTPUT

表示,用mcugpiogpio4_1)来输入信号到cpld

然后,prepare LOGIC工程后,可以看到analog_ip.v接口中的信号:

input             iocvt_chn_out_data,

input             iocvt_chn_out_en,

这里的iocvt_chn_out_data,就是对接到mcugpio4_1的信号。

当控制mcugpio4_1高低切换时,cpld中的iocvt_chn_out_data,会对应来变化。

具体样例,可以参考网盘“logic样例\3.mcu信号到cpldpin”的样例,该样例中,展示了mcu控制cpld继续控制led的过程。

除了gpio信号输出到cpld,其他比如pwm输出信号等,都可以输入到cpld

2. cpld传递信号给mcu

这种方式和1相近,只不过是反向。

可以在mcu中定义gpio4_2为输入并使能中断,则cpld中设置信号高低时,将触发 mcu的中断。

VE中定义信号:

GPIO4_2iocvt_chn:INPUT

表示,用mcugpiogpio4_2)信号来源于cpldiocvt_chn

然后,prepare LOGIC工程后,可以看到analog_ip.v接口中的信号:

output             iocvt_chn_in_data,

这里的iocvt_chn_in_data,就是对接到mcugpio4_2的信号。

cpld中控制iocvt_chn_in_data信号高低时,mcu中的gpio4_2对应变化。

这里不再举例。

3. mcu读写数据到cpld

在地址设计中,cpld的地址区间是:0x60000000 ~0x7FFFFFFF

mcu对这个区间内的地址访问时,相当于访问了cpld的“寄存器”。

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

cpldint cpRdReg = *((int *)0x60000000);

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

Mcu端读写cpld较为简单,直接通过上述语句就可以了。

mcu读写动作发生时,cpld端是如何反应的?

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

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

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

图片

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

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

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

这部分是遵循标准的AHB总线协议的。如果对AHB总线印象不深,请自行百度。

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

Ahb_htrans: 当前传输类型(00: IDLE01: BUSY10: NONSEQ11: SEQ

Ahb_readymcu读时要mcu要准备好cpld才会写

Ahb_hwrite: 要读还是要写(1为写,0为读)

Ahb_haddr[32]: 要操作的地址

Ahb_hsizetransfer的大小,以字节为单位

Ahb_hburst:批量传输

Ahb_hwdata[32]:写的数据,32

Ahb_hreadyout:输出信号,mcu写时cpld是否准备好

Ahb_hresp:输出信号,响应信号(OKretryerrorsplit

Ahb_hrdata[32]:读的数据,32

根据AHB时序,在一次传输中,cpldslave端)会先拿到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 &&                           //masterready,可以给数据线写入了

  !mem_ahb_hwrite &&                 //0 读,1 写)

  mem_ahb_haddr[23:0] == 'h04)         //读地址为0x60000004cpld用相对偏移)

begin

hrdata_reg <=hwdata_reg;              //把另一准备好的数据给到hrdata_reg

end