# Arbiter 功能规范文档

## 1. 概述

Arbiter（仲裁器）是一个前瞻式、轮询的可参数化仲裁器，用于管理多个请求者对共享资源的访问。它根据请求信号决定哪个请求者获得资源访问权限，并通过grant信号指示授权结果。

## 2. 模块接口

### 2.1 端口定义

| 端口名称 | 方向 | 位宽 | 描述 |
|----------|------|------|------|
| clk | 输入 | 1位 | 时钟信号 |
| rst | 输入 | 1位 | 复位信号，高电平有效 |
| request | 输入 | [NUM_PORTS-1:0]位 | 请求信号，每个请求者占1位，高电平表示请求 |
| grant | 输出 | [NUM_PORTS-1:0]位 | 授权信号，每个请求者占1位，高电平表示获得授权 |
| select | 输出 | [SEL_WIDTH-1:0]位 | 选择信号，以二进制形式表示获得授权的请求者索引 |
| active | 输出 | 1位 | 活动信号，当有请求者获得授权时输出高电平 |

### 2.2 参数定义

| 参数名称 | 默认值 | 描述 |
|----------|--------|------|
| NUM_PORTS | 6 | 端口数量，表示仲裁器支持的请求者数量 |
| SEL_WIDTH | $clog2(NUM_PORTS)（当NUM_PORTS > 1时）否则为1 | 选择信号宽度，默认为NUM_PORTS的对数向上取整，当NUM_PORTS为1时为1 |

### 2.3 内部信号

| 信号名称 | 类型 | 位宽 | 描述 |
|----------|------|------|------|
| token | 寄存器 | [NUM_PORTS-1:0]位 | 内部令牌信号，用于实现轮询机制，只有一位为 1 |
| token_wrap | 线网 | [WRAP_LENGTH-1:0]位 | 令牌信号的包装（token重复两次），用于前瞻机制，WRAP_LENGTH = 2*NUM_PORTS |
| token_lookahead | 线网数组 | [NUM_PORTS][NUM_PORTS]位 | 前瞻令牌信号数组，token_lookahead[i] = token_wrap[i +: NUM_PORTS] |
| order | 线网 | [NUM_PORTS-1:0]位 | 顺序信号，order[i] 表示从位置 i 开始是否有请求 |
| next | 线网 | 1位 | 控制信号，当当前token位置无请求时为高电平，触发令牌更新 |

## 3. 功能描述

### 3.1 基本仲裁功能

#### 3.1.1 单个请求处理
- 当只有一个请求者发出请求时，仲裁器应将该请求者标记为授权状态
- 授权信号(grant)中对应的位应为高电平
- 选择信号(select)应反映获得授权的请求者索引

#### 3.1.2 多个请求处理
- 当多个请求者同时发出请求时，仲裁器根据其内部算法选择一个请求者进行授权
- 在任意时刻最多只有一个请求者被授权（grant信号中最多只有一位为高电平）
- 选择信号(select)应反映被选中的请求者索引

#### 3.1.3 无请求处理
- 当没有请求者发出请求时，授权信号(grant)应为全零
- 活动信号(active)应为低电平
- 选择信号(select)可为任意值，但通常为零

### 3.2 轮询机制

#### 3.2.1 令牌管理
- 仲裁器使用内部令牌(token)实现轮询机制
- token 是 NUM_PORTS 位的寄存器，只有一位为 1，表示当前授权位置
- 复位后，令牌(token)初始化为 'b1（即最低位为 1）
- 令牌更新逻辑：当 next 为高时，根据 order 信号找到第一个有请求的位置，使用对应的 token_lookahead 更新 token

#### 3.2.2 前瞻机制
- 仲裁器采用前瞻式算法，在每个时钟周期检查是否有匹配的请求
- 使用 token_wrap（token 重复两次）生成前瞻信号：token_wrap[xx +: NUM_PORTS] 表示从位置 xx 开始的 NUM_PORTS 位
- 通过 generate 块生成 NUM_PORTS 个 token_lookahead 信号，每个对应从不同位置开始的 token 视图
- order[i] = |(token_lookahead[i] & request) 表示从位置 i 开始是否有请求

### 3.2.3 令牌更新
- 当 next 信号为高（即当前 token 位置无请求）时，触发令牌更新
- 遍历 order 数组，找到第一个 order[i] 为 1 的位置（即第一个有请求的位置）
- 使用对应的 token_lookahead[i] 更新 token，确保轮询到下一个有请求的端口

### 3.3 授权生成

#### 3.3.1 授权逻辑
- 授权信号(grant)在时钟上升沿同步更新
- 授权值 = token & request
- 复位时 grant 清零
- 只有当令牌位置和请求信号位置都为高电平时，授权信号对应位置才为高电平

#### 3.3.2 单一授权保证
- 在任意时刻，授权信号(grant)中最多只有一位为高电平
- 确保共享资源在同一时间只被一个请求者访问

### 3.4 二进制选择

#### 3.4.1 选择信号生成
- 选择信号(select)通过独立的 gnt2bin 模块将授权信号(grant)转换为二进制索引
- gnt2bin 模块使用 Find First 1 算法：从 LSB 到 MSB 遍历，找到第一个为 1 的位，返回其索引值
- select 信号在时钟上升沿同步更新，确保时序正确

#### 3.4.2 无授权状态
- 当没有请求者被授权时，gnt2bin 输出为 0，select 信号为 0

### 3.5 活动状态

#### 3.5.1 活动信号逻辑
- 活动信号(active)由授权信号(grant)的按位或运算生成
- 即：active = |(token & request)
- 当有任何请求者被授权时(active为高电平)，表示资源正在被使用

### 3.6 控制功能

#### 3.6.1 复位控制
- 当复位信号(rst)为高电平时，仲裁器恢复到初始状态
- 授权信号(grant)被清零
- 活动信号(active)被清零
- 选择信号(select)被清零
- 内部令牌(token)被初始化为1

#### 3.6.2 时钟控制
- 仲裁器在时钟信号(clk)的上升沿更新状态
- 所有寄存器型信号在时钟上升沿更新
- 请求信号在时钟周期内被采样处理

### 3.7 参数化功能

#### 3.7.1 端口数量参数
- NUM_PORTS参数决定仲裁器支持的请求者数量
- 影响request和grant信号的位宽
- 默认值为6，可根据需要进行配置

#### 3.7.2 选择宽度参数
- SEL_WIDTH参数决定选择信号(select)的位宽
- 默认计算方式为：$clog2(NUM_PORTS)（当NUM_PORTS > 1时），否则为1
- 确保选择信号有足够的位宽来表示所有可能的请求者索引

## 4. API 功能接口

### 4.1 请求接口
- `api_arbiter_request(env, request_mask, max_cycles)`: 向仲裁器发送请求并获取授权结果
- 参数验证：检查request_mask是否在NUM_PORTS范围内
- 返回：授权结果、选择结果和活动状态

### 4.2 单端口请求接口
- `api_arbiter_single_request(env, port_index, max_cycles)`: 向指定端口发送单个请求
- 参数验证：检查端口索引是否在有效范围内
- 返回：授权结果、选择结果和活动状态

### 4.3 多端口请求接口
- `api_arbiter_multi_request(env, port_indices, max_cycles)`: 向多个指定端口发送请求
- 参数验证：检查所有端口索引是否在有效范围内
- 返回：授权结果、选择结果和活动状态

### 4.4 复位接口
- `api_arbiter_reset(env, max_cycles)`: 复位仲裁器到初始状态
- 设置复位信号为高电平，推进时钟周期，然后清除复位信号

### 4.5 状态查询接口
- `api_arbiter_get_status(env, max_cycles)`: 获取仲裁器当前状态
- 返回：请求、授权、选择和活动状态信息

### 4.6 配置接口
- `api_arbiter_configure(env, num_ports, max_cycles)`: 配置仲裁器参数
- 注意：NUM_PORTS是编译时参数，运行时不可修改

## 5. 设计约束

### 5.1 仲裁约束
- 在任意时刻，最多只有一个请求者被授权
- 仲裁器应保证公平性，通过轮询机制避免请求者被无限期忽略

### 5.2 时序约束
- 所有输出信号在时钟上升沿更新
- 请求信号应在时钟周期内保持稳定

### 5.3 参数约束
- NUM_PORTS必须大于0
- SEL_WIDTH应至少为1，以支持至少一个请求者

## 6. 验证点

### 6.1 功能验证点
- 单个请求处理：验证单个请求者获得授权
- 多个请求处理：验证正确的仲裁策略
- 无请求处理：验证无请求时的正确状态
- 复位功能：验证复位信号的正确响应
- 轮询机制：验证轮询算法的正确实现

### 6.2 时序验证点
- 时钟边沿响应：验证在时钟上升沿更新状态
- 信号稳定性：验证信号在时钟周期内的稳定性

### 6.3 参数化验证点
- 不同NUM_PORTS值：验证不同端口数量的正确实现
- SEL_WIDTH计算：验证选择宽度的正确计算