使用AGRV2KL64和AG32VF407RGT6总结

最近尝试了下遨格芯微(AGM)的器件,分别是AGRV2KL48和AG32VF407RGT6
自己做了2个开发板(AG32VF407RGT6开发板的丝印写错了),并进行初步的试用,下面分享一下心得:
微信图片_20261102163533

AGRV2KL48是纯CPLD,资源2K,按照官方说法,现在开发只需要supra,不需要quartua了。
AG32VF407RGT6是异构soc,RISC-V 32 位单核,最高 248MHz,带 FPU/DSP + CPLD资源也是2K,开发依然需要vscode+plantformio+surpa+qurtus
有点zynq的味道,器件很便宜,LQFP焊接方便,对于想了解下异构soc的同学真是非常好的入门选择。

文档非常散,也是网友一起吐槽的,我认为这几个入门挺重要的文档和网页在下面:
C41397168_可编程逻辑器件(CPLD-FPGA)_AGRV2KL48_规格书_WJ1227841.PDF
C5336267_单片机(MCU-MPU-SOC)_AG32VF407RGT6_规格书_WJ1670449.PDF
AG32开发板使用入门.pdf
AG32下cpld的使用入门.pdf
AG32驱动的使用.pdf

网页:
http://www.tcx-micro.com/doc_25499579.html 安装AGRV_pio
http://www.tcx-micro.com/doc_28856565.html AG32 mcu+cpld 联合交互编程(案例和描述)第二部分(手把手教程)

官方网站大家多看看,冷不丁某个重要信息可能就在某个角落里。

初步跑了一些用例,说下我的一些理解和感受:
1.CPLD,资源2k,对比altera的同规模MAXII,性价比高,但是AGM的cpld的架构有点像FPGA,对于延时的控制不如altera
同等规模下,CPLD的价格一般都是大于FPGA,价格优势也就可以理解了。
2.重点说下异构soc:
a. ve文件很重要,它让你可以自己定义管脚该如何映射,这个是在FPGA/CPLD开发中才会有的概念,普通的MCU管脚定义是固定的。
b. 下载需要2次,因为需要下载2个bin文件,一个是code.bin(来自c代码),一个是logic.bin(来自verilog代码)
c. code.bin和logic.bin通过这段地址0x6000 0000 - 0x7FFF FFFF进行关联的。下面会细讲
d. 如果只修改了c文件,只有code.bin更新,那么只重新下载code.bin即可
e. 如果只修改管脚映射(ve文件),可以省略quartua综合,重新Prepare LOGIC,使用supra编新的logic.bin并下载即可
f. 如果ve没变,verilog功能变了,不用Prepare LOGIC,quartua综合+supra布局布线,编新的logic.bin并下载
g. ve,verilog都变, Prepare LOGIC,quartua综合+supra布局布线
h. 只使用mcu或者只使用CPLD的话,工具也会自动生成另一个bin
i. 第一次使用芯片,先下载logic.bin,再下载code.bin
j. module analog_ip的接口是自动根据ve生成的,自己写的verilog逻辑放在module analog_ip中。

能想到的先写这么多,下面讲下mcu怎么和verilog交互的:
image
参考一个官方的用例 6.UartTx例程,通过注释应该就能理解交互过程:
c代码:

#define RD_STATE_BUSY  0x01
#define RD_STATE_TC    0x02
typedef struct
{
  __IO uint32_t DAT; // 0x00 要写的数据
  __IO uint32_t STA; // 0x04 读取的状态
} UARTOWN_TypeDef;

#define UART ((UARTOWN_TypeDef *) 0x60006000) //cpld中该“外设”的地址

main中:
      while((UART->STA) & RD_STATE_BUSY);
      UART->DAT = i;  //发送一个字节

verilog代码:

parameter UART_ADDR = 'h6000;		//对应mcu里的0x60006000, cpld中仅用相对偏移
//如果cpld下要挂多个外设,可以从这里的分段来区分不同设备,使用“片选”的概念。

parameter ADDR_UART_DATA = 'h00;	//写的寄存器
parameter ADDR_UART_STAT = 'h04;	//读的寄存器,最低位为busy位,倒数第二位为tc位。

// 将APB过来的数据通过串口发送出去
always @ (posedge apb_clock or negedge resetn) begin
  if (!resetn) //开始
    begin
      uart_reset <= 0;
      uart_start <= 0;
	end 
  //mcu的写操作。
  //mcu端用C语言:*((int *)0x60006000) = value;
  else if (apb_data_phase && apb_pwrite && apb_paddr == UART_ADDR + ADDR_UART_DATA) //收到mcu写过来的数据
    begin
      TestLedCtrl <= 0;					//led测试,低为led亮
      uart_write <= apb_pwdata[7:0];	//只传低8位。uart_write线路会连到uart_tx模块,靠uart_tx模块真正根据时序往外发。
      uart_start <= 1;
      uart_reset <= 1;
    end
  //mcu的读操作响应
  //mcu端用C语言:int value = *((int *)0x60006004);
  else if (apb_data_phase && !apb_pwrite && apb_paddr == UART_ADDR + ADDR_UART_STAT) //收到mcu读取state寄存器,将UART的状态通过APB返回回去
    begin
      prdata <= {30'b0, tx_complete, tx_busy};  //最低位为busy位,倒数第二位为tc位,高30位无效
		if (tx_complete == 1) TestLedCtrl <= 1; //led测试
		//TestLedCtrl <= 1; //led测试
    end
  else 
    begin  
      uart_start <= 0;
    end
end
posted @ 2026-10-14 10:45  pch126  阅读(19)  评论(0)    收藏  举报