片上SOC系统详解与VHDL编程(基于APB2总线)

        大量的SOC系统都是FPGA挂在MCU的APB总线或AHB总线上进行通讯,本文是基于APB2总线的片上SOC系统讲解。

1. 引言:当SoC遇见APB2总线​

​1.1 SoC的核心价值​

        SoC(System on Chip)通过集成CPU、存储器、外设接口等模块于单芯片,实现了性能、功耗与体积的完美平衡。在智能家居(如语音控制设备)和工业控制(如PLC控制器)中,SoC通过APB总线管理低速外设(如UART、SPI),而AHB总线则处理高速数据流(如DMA传输)。通俗一点说SOC(片上系统)就是一个自带MCU的FPGA,其中FPGA与MCU的通讯部分已经封装好了。

1.2 APB总线层级定位​

在AMBA总线家族中,APB2作为​​低速外设专用总线​​,通过总线桥与AHB/AXI互联,形成三级架构:

  • ​AHB​​:连接CPU、DMA等高带宽模块(如视频编解码器)。
  • ​APB​​:挂接GPIO、定时器等低功耗外设(如温度传感器)、
    这种分层设计既降低了系统复杂度,又实现了功耗优化(APB功耗仅为AHB的1/5)。

                                                                某国产SOC片内结构

2、结构解析

        一般的SOC结构包含MCU内核通常是M3、M4等,本例使用的是M3(官网查看对应产品的结构图等)

对于用户来说,与操作标准库步骤大致一致,只不过需要写两份代码,一份对应MCU,一份对应FPGA。下面是MCU部分:

官方会给出各个子模块的内存映射也就是我们常说的地址,这些功能都可以通过FPGA来实现,但是注意,此时功能的实现端再MCU,FPGA仅负责IO功能。

总线地址如下:

        需要注意的是,在MCU端,是不需要配置APB2总线的相关设置的,只需要知道总线基地址,按顺序为结构体赋值就行了,因此没有paddr,pwrite,pwdata,psel1等寄存器,他们都是由M3内核自动分配,配置到FPGA中,只有在FPGA中才需要对上述的总线信号进行处理。

        根据官网下载对应的库函数,添加。

注意重点来了:自己新建功能时要注意对应的总线地址,下面时一个加法器的demo(功能实现在FPGA,数据在MCU)下面时.c与.h文件。



#ifndef MULTIPLE_H
#define MULTIPLE_H

/* Includes ------------------------------------------------------------------*/
#include "gw1ns4c.h"

/* Definitions ------------------------------------------------------------------*/
//type definition
typedef struct
{
  __IO   uint32_t  MULTIPLIER;        /* Offset: 0x000 (R/W) [7:0] */
  __IO   uint32_t  MULTIPLICAND;      /* Offset: 0x004 (R/W) [7:0] */
  __IO   uint32_t  CMD;               /* Offset: 0x008 (R/W) [1:0] */
  __I    uint32_t  RESULT;            /* Offset: 0x00C (R/ ) [15:0] */
}MULTIPLE_TypeDef;

//base address
#define MULTIPLE_BASE   (APB2PERIPH_BASE + 0x400)

//mapping
#define MULTIPLE        ((MULTIPLE_TypeDef   *) MULTIPLE_BASE)

//bit definition
#define MUL_MULTIPLIER		((uint32_t) 0x000000FF)
#define MUL_MULTIPLICAND	((uint32_t) 0x000000FF)
#define CMD_START					((uint32_t) 0x00000001)
#define STATUS_FINISHED		((uint32_t) 0x00000010)
#define MUL_RESULT				((uint32_t) 0x0000FFFF)

typedef enum
{
	FINISHED_STATUS = 0x0,
	NO_FINISHED_STATUS = 0x1
}STATUS;

/* Declarations ------------------------------------------------------------------*/
void setMultiplier(uint32_t multi);
uint32_t getMultiplier(void);
void setMultiplicand(uint32_t multi);
uint32_t getMultiplicand(void);
uint32_t getMultipleResult(void);
void startMultiple(void);
void finishMultiple(void);
STATUS getFinishStatus(void);
uint32_t getMultipleCmd(void);

#endif
#include "multiple.h"

/* Functions ------------------------------------------------------------------*/
void setMultiplier(uint32_t multi)
{
	MULTIPLE->MULTIPLIER = multi & MUL_MULTIPLIER;
}

uint32_t getMultiplier(void)
{
	return MULTIPLE->MULTIPLIER & MUL_MULTIPLIER;
}

void setMultiplicand(uint32_t multi)
{
	MULTIPLE->MULTIPLICAND = multi & MUL_MULTIPLICAND;
}

uint32_t getMultiplicand(void)
{
	return MULTIPLE->MULTIPLICAND & MUL_MULTIPLICAND;
}

uint32_t getMultipleResult(void)
{
	return MULTIPLE->RESULT & MUL_RESULT;
}

void startMultiple(void)
{
	MULTIPLE->CMD |= CMD_START;
}

void finishMultiple(void)
{
	MULTIPLE->CMD = 0;
}

uint32_t getMultipleCmd(void)
{
	return MULTIPLE->CMD;
}

STATUS getFinishStatus(void)
{
	if(((MULTIPLE->CMD&STATUS_FINISHED)>>1))
	{
		return FINISHED_STATUS;
	}
	else
	{
		return NO_FINISHED_STATUS;
	}
}

        主函数只需要调用即可,此处不过多赘述。

FPGA部分较为简单,选择对应的总线的IP核调用即可,只需要注意对应的信号功能进行编程:

下面是对各个信号的解释:
•    master_pclk: APB主控器的时钟信号。所有在APB上的操作都与时钟信号同步。
•    master_rst: 复位信号。当此信号激活时(通常为高电平或低电平,取决于具体设计),系统会复位到初始状态。
•    master_penable: 使能信号。这个信号表明当前地址和控制信号是有效的。在传输周期中,它会在第二个PCLK上升沿被置位以指示从设备进行数据传输。
•    master_paddr[7:0]: 地址总线。指定了要访问的外设寄存器的地址。宽度为8位,意味着它可以访问256个不同的地址位置。
•    master_pwrite: 读写控制信号。如果该信号为高电平,则表示执行写操作;如果为低电平,则表示执行读操作。
•    master_pwdata[31:0]: 写数据总线。这是在写周期期间发送到外设的数据。宽度为32位。
•    master_pstrb[3:0]: 字节选通信号。用来标识master_pwdata中的哪些字节是有效的。每个位对应于master_pwdata中的一个字节(4个字节总共)。例如,如果master_pstrb为4'b1100,那么只有master_pwdata的最高有效两个字节被认为是有效的。
•    master_pprot[2:0]: 保护控制信号。提供了关于传输的安全性和缓冲需求的信息。
•    master_psel1: 器件选择信号。表明特定的外设已被选中进行通信。这里的“1”可能表示这是第一个外设或者特定编号的外设。
•    master_prdata1[31:0]: 读数据总线。这是在外设响应读请求时返回的数据。宽度为32位。
•    master_pready1: 就绪信号。由外设发出,表示它已经完成了当前传输并且可以接受下一个传输。这允许外设有时间处理请求而不会丢失数据。
•    psel_valid_es1: 这似乎是一个自定义信号名称,可能是用来验证master_psel1是否有效,或者是外部逻辑的一部分,用于控制或监测master_psel1的状态。


3、功能验证

        FPGA配置了乘法器,MCU通过APB2总线传输乘数和被乘数,FPGA计算结果以后再通过APB2总线返回结果。

配置了乘数和被乘数分别为20和40。FPGA计算以后把结果传回MCU,再通过串口打印出来。由图可见,结果正确,功能正常。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值