
本文档演示,如何将example_cpldAhbTxRxReg的CPLD和MCU代码嵌入已有的设计中。
首先阅读《样例说明-ahb.txt》:
这个样例,展示了 mcu端如何读写cpld寄存器(即:0x60000000地址开始)
样例基于SDK1.7.0.
样例中,
muc的for循环中,先写0x60000000寄存器,然后读0x60000004寄存器的值并打印。
cpld中,对0x60000000写进来的值进行缓存,然后做为0x60000004的值返回给mcu。
这里只是***简单的访问样例,如果要实现更***的复杂功能,请自行研究ahb总线协议来调整。
简要说明:
1. 在user_ip.v中:
module的接口部分添加代码如下:
=======================================
//mcu的写操作响应
//mcu端用C语言:*((int *)0x60000000) = value;
reg [31:0] hwdata_reg; //定义32位的hwdata_reg
always @(posedge sys_clock or negedge resetn) begin //clk上升沿触发
if (!resetn) begin
hreadyout_reg <= 1'b1;
end else if(mem_ahb_htrans == 2'b10 && hreadyout_reg) begin //写地址为0x60000000(cpld内部用相对偏移)。
hreadyout_reg <= 1'b0;
end else if(!hreadyout_del && //cpld已ready状态,ahb上数据可以写过来了
mem_ahb_hwrite && //写 (0 读,1 写)
mem_ahb_haddr[23:0] == 'h00) begin
hwdata_reg <= mem_ahb_hwdata; //把收到的数据给到hwdata_reg
hreadyout_reg <= 1'b1;
end else begin
hreadyout_reg <= 1'b1;
end
end
always @ (posedge sys_clock or negedge resetn) begin
if (!resetn) begin
hreadyout_del <= 1'b1;
end else begin
hreadyout_del <= hreadyout_reg;
end
end
//这个过程,是把mcu写进来的数据收到hwdata_reg中
//mcu的读操作响应
//mcu端用C语言:int value = *((int *)0x60000004);
reg [31:0] hrdata_reg; //定义32位的hrdata_reg
always @(posedge sys_clock or negedge resetn) begin //clk上升沿触发
if (!resetn) begin
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_reg
end
end
assign mem_ahb_hrdata = hrdata_reg; //绑定hrdata_reg到读的数据线上
//实验思路:
//展示mcu来读写cpld寄存器时,cpld如何响应。
//mcu的C代码里,给0x60000000写入一个数,然后cpld中对这个数据进行缓存。
//mcu的C代码里,读0x60000004,cpld就把缓存的数,返回给mcu。
=======================================
2. 在mcu代码里:
添加代码如下:
=======================================
int wValue = 0, rValue = 0;
while (1)
{
//write register 0x60000000
*((int *)0x60000000) = wValue;
UTIL_IdleUs(1);
//read register 0x60000004
rValue = *((int *)0x60000004);
printf('Test reg value, write [%d], read [%d]\r\n', wValue, rValue);
wValue++;
UTIL_IdleUs(1000e3);
}
=======================================
可以看到随着for循环的增加,输出的值在不断累加。
***********************************************
注意:
这里的mcu+cpld工程,不要直接使用!!!
1. mcu部分的代码 可以 直接使用。
2. cpld工程 不能 直接使用!
cpld工程 不能 直接使用:
因为cpld工程跟本地环境有关。(样例是基于别的环境,只是给出来看个样子,换环境是不行的)
使用样例的正确方式:
1. 样例解压到自己的目录下;
2. 将样例里的 logic文件夹(即:cpld工程的文件夹)重命名(比如,重命名为logic_bak);
3. 参考《AG32下cpld的使用入门.pdf》中描述的步骤:
文档里有详细描述,这里给出概要过程:
a. 先在VSCode里prepare LOGIC(生成新的cpld工程到logic目录下)
b. 用quartus打开新生成的logic空工程,点 tcl script 进行“工程转换”;
c. 然后把 logic_bak 里 user_ip.v 中有用的代码,复制到现在logic里的user_ip.v中去,重新编译quartus工程;
d. 再用supra工具打开logic工程,***终编译出logic.bin;
4. ***在VSCode下Upload logic(烧录上边编译出来的logic.bin),Upload(烧录mcu端的code.bin)
【上边的过程,mcu端不用动,cpld工程需要建立“本地工程”】
以下是正式开始操作的步骤。

一、 先在VSCode里prepare LOGIC(生成新的cpld工程到logic目录下)
打开对应的例程文件夹: Project diretory: D:\AGMWork2510\AgRV_pio\platforms\AgRV\examples\example 编译一下,确认是SUCCESS。 在 platformio.ini 中打开以下两项: ip_name = analog_ip logic_dir = logic 注意:这两行去掉注释的时候,前边不要留空格。要顶格写。 

保存,然后重新点build.

点击上述Prepare LOGIC.

成功。

二、用quartus打开新生成的logic空工程,点 tcl script 进行“工程转换”;



点击RUN.

切换到SUPRA,打开对应的工程。

上述窗口点击打开,弹出的小对话框点OK。然后,点击【左上角Tool】-> 【Compile】。



成功编译生成烧录文件,说明流程OK。

三、 然后把 logic_bak 里 user_ip.v 中有用的代码,复制到现在logic里的user_ip.v中去,重新编译quartus工程;

将logic文件夹复制,改名后粘贴到对应目录下。

打开以下的文件:

将上述user_ip.v的代码,覆盖已有的 user_ip.v文件内容:

复制粘贴后,点击综合按钮,成功后如下。

后面继续完成到supra软件的操作,生成CPLD的烧录文件,这里不再重复。

四、 切换回到VSOCDE.
1. 在mcu代码里, 添加代码如下: //======MCU Function code =================================== int wValue = 0, rValue = 0; while (1) { //write register 0x60000000 *((int *)0x60000000) = wValue; UTIL_IdleUs(1); //read register 0x60000004 rValue = *((int *)0x60000004); printf('Test reg value, write [%d], read [%d]\r\n', wValue, rValue); wValue++; UTIL_IdleUs(1000e3); } //====================================== //--可以看到随着for循环的增加,输出的值在不断累加。 如下图所示:

保存后点击Build. 成功后提示SUCCESS.

流程演示完成。
如需了解更多资讯,欢迎联系海振远科技销售人员获取支持。
联系海振远科技
电话:0755-2780 9180; 15323895320;
邮箱: tech@hizyuan.com
Lucy@hizyuan.com