# PL 端自定义外设参考手册

## 存储器和总线架构

### 系统架构

PL端主要由4个外设组成，分别时**风扇控制器**(FAN)，**编码和分频控制器**(ENCODER)，**先入先出队列**(FIFO)和**阀板控制器**(VALVE)。其中阀板控制器没有提供AXI接口，因此并没有映射寄存器，软件也无法进行控制。各个控制器的连接关系如下图所示。

![system_arch](pl_reference_mannual.assets/system_arch.png)

4个外设由统一的同步时钟驱动，时钟源来自PS端，为200MHz，软件不可修改。外部编码器信号输入**编码和分频控制器**，控制器根据软件设置的阀触发分频值和相机触发分频值对编码器信号进行分频。为同步触发相机和移出队列，**先入先出队列**在相机触发同时输出一个数据，即**先入先出队列**读信号和相机触发共用同一个信号。而由于电磁阀的物理特性导致电磁阀无法以触发相机的频率进行开关，因此**阀板控制器**对先入先出队列输出总线上的数据进行重采样，即按照**编码和分频控制器**输出的阀触发信号更新并转换为阀板协议，输出电磁阀的状态。

具体的硬件设计和信号说明见[doc/hardware_description.md](hardware_description.md)

各控制器的边界地址和所属总线等信息如下表所示

| 边界地址                | 外设             | 总线      |
| ----------------------- | ---------------- | --------- |
| 0x43c00000 - 0x43c0ffff | 先入先出队列     | M_AXI_GP0 |
| 0x43c10000 - 0x43c1ffff | 编码和分频控制器 | M_AXI_GP0 |
| 0x43c20000 - 0x43c2ffff | 风扇控制器       | M_AXI_GP0 |

## 风扇控制器 (FAN)

### FAN简介

FAN模块用于控  制散热风扇的启停以及通过PWM调整风扇速度。通过对寄存器写入值，该模块能正常启停散热风扇，但由于代码与硬件兼容问题，导致无法观察到调速现象。

### FAN主要特性

- 能控制风扇的启停
- 自定义占空比，调整风扇转速

### FAN功能说明

<img src="pl_reference_mannual.assets/fan_block.svg" alt="fan_block" style="zoom:20%;" />

通过将开启使能拉高，开启风扇。通过向风速寄存器写入PWM占空值，控制风扇减少或提高风速。

### FAN寄存器说明

FAN模块寄存器主要包括控制寄存器 (FAN_CR)、风速寄存器 (FAN_SPDR)。控制寄存器 (FAN_CR)用于控制风扇开启或关闭的状态，风速寄存器 (FAN_SPDR)通过PWM技术设置风扇转动的速度。

**Base Address: 0x43c20000**  

#### FAN控制寄存器 (FAN_CR)

偏移地址: 0x00<br/>复位值: 0x0000 0000

![fan_cr](pl_reference_mannual.assets/fan_cr.png)

| **Field**    | **Description**                                              |
| :----------- | :----------------------------------------------------------- |
| 位31:16 保留 | 必须保持复位值                                               |
| 位0 **EN**   | 内部触发信号 (Virtual Triggle Signal)<br />    0: 停止风扇<br/>    1: 开启风扇 |

#### FAN风速寄存器 (FAN_SPDR)

偏移地址: 0x04<br/>复位值: 0x0000 0000

![fan_spdr](pl_reference_mannual.assets/fan_spdr.png)

| **Field**      | **Description**                                              |
| :------------- | :----------------------------------------------------------- |
| 位31:0 **SPD** | 该寄存器值表示设置的风扇PWM占空值，占空比转换公式如下。<br />占空比% = SPD / (2 ^ 32 - 1) * 100% |

#### FAN寄存器映射

FAN寄存器可映射为32位可寻址寄存器，如下表所述：

![fan_regs](pl_reference_mannual.assets/fan_regs.png)

## 编码和分频控制器 (ENCODER)

### ENCODER简介

ENCODER模块主要用于实现编码器计数以及对编码器脉冲进行分频，分频后的脉冲信号输出给相机和阀板，并且能控制FIFO模块的读操作，将数据加载到AXI数据总线上。该模块包括1个控制寄存器 (ENCODER_CR)、阀触发分频寄存器 (ENCODER_VDIVR)、相机触发分频寄存器 (ENCODER_CDIVR)。

### ENCODER主要特性

- 独立设置对相机和喷阀的分频系数
- 内外两种触发模式选择
- 清空功能

### ENCODER功能说明

下图给出了ENCODER的主要信号：

<img src="pl_reference_mannual.assets/encoder_block.svg" alt="图片1" style="zoom: 20%;" />

ENCODER模块接收编码器脉冲信号，通过设置的相机和喷阀分频系数，生成对应的触发信号。编码器脉冲信号可由内部或外部触发模式产生。

### ENCODER寄存器说明

ENCODER模块的寄存器主要有控制寄存器 (ENCODER_CR)、阀触发分频寄存器 (ENCODER_VDIVR)和相机触发分频寄存器 (ENCODER_CDIVR)。控制寄存器 (ENCODER_CR)用于进行触发模式选择以及复位清空，阀触发分频寄存器 (ENCODER_VDIVR)用于寄存输入的分频系数，将编码器脉冲除以分频系数得到触发脉冲。

**Base Address: 0x43c10000**

#### ENCODER控制寄存器 (ENCODER_CR)

偏移地址: 0x00<br/>复位值: 0x0000 0000

![ ](pl_reference_mannual.assets/encoder_cr.svg)

| **Field**   | **Description**                                              |
| :---------- | :----------------------------------------------------------- |
| 位31:3 保留 | 必须保持复位值                                               |
| 位2 **VTS** | 内部触发信号 (Virtual Triggle Signal)<br />    **MOD**位置1时，由软件写入，将该位信号直接充当触发信号<br />    0: 低电平<br />    1: 高电平 |
| 位1 **MOD** | 模式选择 (Mode)<br />    0: 外部触发模式，外部触发编码器转动<br />    1: 内部触发模式，软件模拟触发信号 |
| 位0 **CLR** | 清除缓存 (Clear)<br />   0: 正常工作 <br />   1: 清除编码和分频控制器内部的分频计数值，不影响VDIV和CDIV<br /> 注意: 程序置位该位后后需再写入0，使计数器退出清零状态，正常工作 |

#### ENCODER阀触发分频寄存器 (ENCODER_VDIVR)

偏移地址: 0x04<br/>复位值: 0x0000 0000

![image-20220613202916591](pl_reference_mannual.assets/encoder_vdivr.svg)

| **Field**       | **Description**                                              |
| :-------------- | :----------------------------------------------------------- |
| 位31:0 **VDIV** | 阀触发分频值<br />    阀控制器重采样频率和编码器脉冲的分频值， 写入数据后编码和分频控制器自动清除缓存并应用新的数值 <br />    注意：0表示不间断触发，即PL端每个时钟周期均触发阀模块 |

#### ENCODER相机触发分频寄存器 (ENCODER_CDIVRx)  (x=A...D) 

用于设定相机A到相机D的分频系数，各相机可独立设置

偏移地址: 0x08<br/>复位值: 0x0000 0000

![image-20220613202916591](pl_reference_mannual.assets/encoder_cdivrx.svg)

| **Field**       | **Description**                                              |
| :-------------- | :----------------------------------------------------------- |
| 位31:0 **CDIV** | 相机触发分频值<br />    写入数据后编码和分频控制器自动清除缓存并应用新的数值 <br />    注意：0表示不间断触发，即PL端每个时钟周期均触发相机 |

#### ENCODER寄存器映射

ENCODER寄存器可映射为32位可寻址寄存器，如下表所述：

![encoder_regs](pl_reference_mannual.assets/encoder_regs.svg)

## 先入先出队列 (FIFO)

### FIFO简介

FIFO模块为下位机的核心模块，用于接收控制喷阀的信号，以先入先出原则，按顺序由encoder模块控制输出给阀板。

### FIFO主要特性

- 384bit数据位宽，最大4096深度
- 实时计算存储数据数量，提供队列满，队列空等信号
- 指示队列输出状态
- 清空功能

### FIFO功能说明

下图给出了FIFO的主要信号：

<img src="pl_reference_mannual.assets/fifo_block.svg" alt="fifo_block" style="zoom: 20%;" />

FIFO模块在写同步信号拉高后接收用于控制喷阀的384bit位宽的数据，并在读使能拉高后将数据加载到AXI数据总线上，当队列读空后，empty信号拉高，不输出有效数据，表示关闭喷阀。复位信号拉高后将整个队列清空。COUNT信号表示当前在FIFO内存在多少个有效数据。

### FIFO寄存器说明

FIFO模块寄存器主要包括数据寄存器x (FIFO_DATx)(x=0...11) 、状态寄存器 (FIFO_SR) 、控制寄存器 (FIFO_CR) 。数据寄存器x (FIFO_DATx)(x=0...11) 用于寄存写入的384bit数据，并保持该数据。状态寄存器 (FIFO_SR)用于反映FIFO内部数据的寄存状态，标志FIFO是否被读空、写满以及FIFO内当前存在多少有效数据。控制寄存器 (FIFO_CR) 用于控制AXI总线上的数据被写入FIFO，以及实现复位清空操作。

**Base Address: 0x43c00000**

#### FIFO数据寄存器x (FIFO_DATx)  (x=0...11) 

FIFO的写宽度为384bit，因此需12个32位寄存器**FIFO_DAT0**-**FIFO_DAT11**，按小端字节序共同组成384bit位宽。将数据写入这12个寄存器后，应对位**WS**写入1，此时数据寄存器组中的数据写入到FIFO中。

偏移地址: 0x00...0x2C<br/>复位值: 0x0000 0000

![image-20220613202916591](pl_reference_mannual.assets/fifo_datx.png)

| **Field**                       | **Description**                                              |
| :------------------------------ | :----------------------------------------------------------- |
| 位31:0 **DTIN[x\*32+31:x\*32]** | FIFO数据寄存器x写入数据位[x\*32+31:x\*32]<br />写入数据后该寄存器将保持写入的值，直到对**WS**位写入1，数据才会进入FIFO队列。不要读取该寄存器。结合VALVE外设可得 <br />    0: 对应喷阀关闭 <br />    1: 对应喷阀打开 |



#### FIFO状态寄存器 (FIFO_SR) 

状态寄存器指示FIFO的内部状态，数据数量等，为只读寄存器，不可写

偏移地址: 0x30<br/>复位值: 0x0000 0000

![image-20220613203939644](pl_reference_mannual.assets/fifo_sr.png)

| **Field**      | **Description**                                              |
| :------------- | :----------------------------------------------------------- |
| 位31:17 保留   | 必须保持复位值                                               |
| 位16 **VLD**   | 数据输出有效标志 (Valid)<br />    0: 当前无有效输出，输出保持上一状态<br />    1: 当前队列正在输出有效数据 |
| 位15 **AMEM**  | 队列将空标志 (Almost Empty)<br />    0: 队列没有被读空<br />    1: 队列在一个读时钟周期后会被读空 |
| 位14 **EM**    | 队列空标志 (Empty)<br />    0: 队列中存在有效数据，没有被读空<br />    1: 队列中已经没有有效数据 |
| 位13 **AMFU**  | 队列将满标志 (Almost Full)<br />    0: 队列没有被写满<br />    1: 队列在一个写时钟周期后会被写满 |
| 位12 **FU**    | 队列满标志 (Almost Full)<br />    0: 队列中的有效数据小于FIFO数据深度<br />    1: 队列中的有效数据达到FIFO数据深度 |
| 位11:0 **CNT** | 队列数据数量 (Data Count)<br />该值指示队列中的数据数量<br />注意：一个数据为384位宽 |

#### FIFO空计数寄存器 (FIFO_ECR) 

队列为空后被读的次数

偏移地址: 0x34<br/>复位值: 0x0000 0000

![image-20220613212701816](pl_reference_mannual.assets/fifo_ecr.png)

| **Field**      | **Description**                                              |
| :------------- | :----------------------------------------------------------- |
| 位31:0 **CNT** | 队列为空读次数 (Empty Count)<br />该值指示队列为空后被读的次数<br />注意：改寄存器只读，仅在FIFO复位时自动清零 |

#### FIFO控制寄存器 (FIFO_CR) 

偏移地址: 0x38<br/>复位值: 0x0000 00xx

![image-20220613212701816](pl_reference_mannual.assets/fifo_cr.png)

| **Field**   | **Description**                                              |
| :---------- | :----------------------------------------------------------- |
| 位31:2 保留 | 必须保持复位值                                               |
| 位1 **CLR** | 清空队列 (Clear)<br />对该位写入1，队列将清空，同时队列输出为全0。<br />注意：不要写入除1以外的任何值。 |
| 位0 **WS**  | 写入同步 (Write Synchronization)<br />对该位写入1，**FIFO_DATx**的数据按字节小端序进入队列。<br />注意：不要写入除1以外的任何值。 |

#### FIFO寄存器映射

FIFO寄存器可映射为32位可寻址寄存器，如下表所述：

<img src="pl_reference_mannual.assets/fifo_regs.png"/>
