sync chunk 11/12
This commit is contained in:
@@ -0,0 +1,437 @@
|
||||
# CSI040 控制模块 Datasheet
|
||||
|
||||
## 1. 概述
|
||||
|
||||
`csi040_ctrl` 是用于控制 CSI040 ASIC 的 PL 侧控制模块。模块对上层软件暴露一组 32 bit BRAM 风格寄存器,并把软件写寄存器的动作转换为 CSI040 SPI 总线访问。
|
||||
|
||||
该模块主要完成:
|
||||
|
||||
- CSI040 ASIC 控制寄存器写入
|
||||
- 16 通道 enable 配置
|
||||
- 单通道参数寄存器写入
|
||||
- DCS/Test 模式 key 序列写入
|
||||
- Direct SPI 读写
|
||||
- ASIC reset/trigger 引脚直接控制
|
||||
- SPI busy/done/error 状态反馈
|
||||
|
||||
相关 RTL 文件:
|
||||
|
||||
- `c64_pro.srcs/sources_1/rtl/csi040/csi040_ctrl.v`
|
||||
- `c64_pro.srcs/sources_1/rtl/csi040/csi040_spi_master.v`
|
||||
- `c64_pro.srcs/sources_1/rtl/csi040/csi040_ctrl_tb.v`
|
||||
|
||||
## 2. 模块框图
|
||||
|
||||
```text
|
||||
+------------------------------+
|
||||
BRAM register | | SPI command
|
||||
access -------->| csi040_ctrl |----------------+
|
||||
| | |
|
||||
| register map / shadow regs | v
|
||||
| sequence engine | +--------------------+
|
||||
| busy/done/error status | | csi040_spi_master |
|
||||
+------------------------------+ +---------+----------+
|
||||
| | |
|
||||
| | direct pins | SPI pins
|
||||
v v v
|
||||
asic_rst_n asic_trig asic_csn/asic_sck/asic_si/asic_so
|
||||
```
|
||||
|
||||
## 3. 主要特性
|
||||
|
||||
| 项目 | 规格 |
|
||||
| --- | --- |
|
||||
| 软件接口 | 32 bit BRAM 风格寄存器接口 |
|
||||
| BRAM 地址宽度 | 13 bit |
|
||||
| 支持写类型 | 仅支持 `bram_we == 4'hF` 的整字写 |
|
||||
| 支持读类型 | `bram_en == 1` 且 `bram_we == 4'h0` |
|
||||
| ASIC 地址宽度 | 默认 16 bit |
|
||||
| SPI 地址字节数 | 默认 2 byte |
|
||||
| Direct SPI 最大 payload | 默认 4 byte,由 `MAX_BURST_BYTES` 决定 |
|
||||
| SPI SCK 极性 | idle low |
|
||||
| SPI CSN 极性 | active low |
|
||||
| SPI 输出位序 | opcode/address/data 均 MSB first 按帧发送;payload byte0 来自低 8 bit |
|
||||
| 忙保护 | 忙时写命令寄存器不会启动新命令,并置位 `error_busy` |
|
||||
| 复位 | `rst_n` 异步低有效 |
|
||||
|
||||
## 4. 参数
|
||||
|
||||
### 4.1 `csi040_ctrl` 参数
|
||||
|
||||
| 参数 | 默认值 | 说明 |
|
||||
| --- | ---: | --- |
|
||||
| `VERSION` | `32'h04040001` | 模块版本号,读 `0x0000` 返回 |
|
||||
| `SPI_CLK_DIV` | `50` | SPI SCK 半周期分频,`f_sck = f_clk / (2 * SPI_CLK_DIV)` |
|
||||
| `REG_ADDR_WIDTH` | `16` | ASIC 寄存器地址宽度 |
|
||||
| `SPI_ADDR_BYTES` | `2` | SPI 帧中地址字段字节数 |
|
||||
| `MAX_BURST_BYTES` | `4` | Direct SPI 最大 payload 字节数 |
|
||||
| `SPI_OPCODE_WRITE` | `8'h00` | SPI 写 opcode |
|
||||
| `SPI_OPCODE_READ` | `8'h80` | SPI 读 opcode |
|
||||
| `CSI_REG_CONTROL` | `16'h0002` | CSI040 control register 地址 |
|
||||
| `CSI_REG_CH_ENABLE1` | `16'h0007` | channel 0-7 enable 地址 |
|
||||
| `CSI_REG_CH_ENABLE2` | `16'h0008` | channel 8-15 enable 地址 |
|
||||
| `CSI_REG_TEST_DCS_KEY` | `16'h0009` | DCS/Test key register 地址 |
|
||||
| `CSI_CH_BASE` | `16'h0010` | 通道寄存器基地址 |
|
||||
| `CSI_CH_STRIDE` | `16'h0010` | 通道寄存器地址步进 |
|
||||
| `CSI_REG_STIM_TRIGGER` | `16'h0110` | stimulation trigger register 地址 |
|
||||
| `CSI_REG_PART_ID` | `16'h011D` | part ID register 地址 |
|
||||
| `CSI_REG_REVISION` | `16'h011E` | revision register 地址 |
|
||||
|
||||
### 4.2 `MAX_BURST_BYTES` 说明
|
||||
|
||||
`MAX_BURST_BYTES` 同时影响以下信号宽度和行为:
|
||||
|
||||
| 位置 | 影响 |
|
||||
| --- | --- |
|
||||
| `spi_cmd_wdata` | 宽度为 `8 * MAX_BURST_BYTES` |
|
||||
| `spi_cmd_rdata` | 宽度为 `8 * MAX_BURST_BYTES` |
|
||||
| SPI master 内部 frame | 最大帧长为 `8 * (1 + SPI_ADDR_BYTES + MAX_BURST_BYTES)` |
|
||||
| Direct SPI 长度 | `SPI_CTRL[15:8]` 超过 `MAX_BURST_BYTES` 时会被截断 |
|
||||
|
||||
高层命令序列目前都只发 1 byte payload;`MAX_BURST_BYTES` 主要服务于 Direct SPI burst 访问。
|
||||
|
||||
## 5. 端口说明
|
||||
|
||||
### 5.1 时钟复位
|
||||
|
||||
| 信号 | 方向 | 位宽 | 说明 |
|
||||
| --- | --- | ---: | --- |
|
||||
| `clk` | input | 1 | 主时钟,模块内部逻辑均使用此时钟 |
|
||||
| `rst_n` | input | 1 | 异步低有效复位 |
|
||||
| `bram_clk` | input | 1 | 当前 RTL 未使用,保留接口 |
|
||||
| `bram_rst` | input | 1 | 当前 RTL 未使用,保留接口 |
|
||||
|
||||
注意:当前实现中 `bram_clk/bram_rst` 未参与逻辑,BRAM 访问必须与 `clk` 同步。
|
||||
|
||||
### 5.2 BRAM 寄存器接口
|
||||
|
||||
| 信号 | 方向 | 位宽 | 说明 |
|
||||
| --- | --- | ---: | --- |
|
||||
| `bram_addr` | input | 13 | BRAM 字节地址 |
|
||||
| `bram_din` | input | 32 | 写数据 |
|
||||
| `bram_dout` | output reg | 32 | 读数据 |
|
||||
| `bram_en` | input | 1 | BRAM 访问使能 |
|
||||
| `bram_we` | input | 4 | 写 strobe;仅 `4'hF` 识别为写,`4'h0` 识别为读 |
|
||||
|
||||
### 5.3 状态输出
|
||||
|
||||
| 信号 | 方向 | 位宽 | 说明 |
|
||||
| --- | --- | ---: | --- |
|
||||
| `busy` | output | 1 | 模块忙。为 1 时不要写命令寄存器 |
|
||||
| `spi_done` | output | 1 | SPI master 完成脉冲,持续 1 个 `clk` |
|
||||
| `error_busy` | output reg | 1 | 忙时启动命令产生的粘滞错误标志 |
|
||||
|
||||
### 5.4 ASIC 引脚
|
||||
|
||||
| 信号 | 方向 | 位宽 | 说明 |
|
||||
| --- | --- | ---: | --- |
|
||||
| `asic_rst_n` | output reg | 1 | ASIC reset 引脚,软件通过 `PIN_CTRL[0]` 控制 |
|
||||
| `asic_trig` | output reg | 1 | ASIC trig 引脚,软件通过 `PIN_CTRL[1]` 控制 |
|
||||
| `asic_csn` | output | 1 | SPI CSN,低有效 |
|
||||
| `asic_sck` | output | 1 | SPI SCK,空闲低 |
|
||||
| `asic_si` | output | 1 | SPI master 输出到 ASIC |
|
||||
| `asic_so` | input | 1 | ASIC 输出到 SPI master |
|
||||
|
||||
## 6. BRAM 寄存器映射
|
||||
|
||||
| 地址 | 名称 | 访问 | 说明 |
|
||||
| ---: | --- | --- | --- |
|
||||
| `13'h0000` | `VERSION` | R | 返回 `VERSION` |
|
||||
| `13'h0004` | `STATUS` | R/W1C | 状态寄存器;写 bit0 清 done,写 bit1 清 error |
|
||||
| `13'h0008` | `SPI_ADDR` | R/W | Direct SPI 目标 ASIC 地址 |
|
||||
| `13'h000C` | `SPI_WDATA` | R/W | Direct SPI 写数据 |
|
||||
| `13'h0010` | `SPI_CTRL` | W | Direct SPI 启动控制 |
|
||||
| `13'h0014` | `SPI_RDATA` | R | 最近一次 SPI 读回数据 |
|
||||
| `13'h0018` | `PIN_CTRL` | R/W | 直接控制 `asic_rst_n/asic_trig` |
|
||||
| `13'h001C` | `LAST_ADDR` | R | 最近一次完成 SPI 操作的 ASIC 地址 |
|
||||
| `13'h0020` | `CONTROL` | R/W | 写 CSI040 control register |
|
||||
| `13'h0024` | `CH_ENABLE` | R/W | 写 channel enable1/2 |
|
||||
| `13'h0028` | `TRIGGER` | W | 向 ASIC trigger register 写 `8'hAA` |
|
||||
| `13'h002C` | `SEQ_CMD` | W | 特殊序列命令 |
|
||||
| `13'h0040` | `CH_INDEX` | R/W | 选择通道编号 |
|
||||
| `13'h0044` | `CH_MISC` | W | 当前通道 offset `0x0` |
|
||||
| `13'h0048` | `CH_CUR_A` | W | 当前通道 offset `0x1` |
|
||||
| `13'h004C` | `CH_CUR_B` | W | 当前通道 offset `0x2` |
|
||||
| `13'h0050` | `CH_CUR_C` | W | 当前通道 offset `0x3` |
|
||||
| `13'h0054` | `CH_CUR_D` | W | 当前通道 offset `0x4` |
|
||||
| `13'h0058` | `CH_STIM_PW` | W | 当前通道 offset `0x5` |
|
||||
| `13'h005C` | `CH_DZ0` | W | 当前通道 offset `0x6` |
|
||||
| `13'h0060` | `CH_DZ1` | W | 当前通道 offset `0x7` |
|
||||
| `13'h0064` | `CH_SKIP_AB` | W | 当前通道 offset `0x8` |
|
||||
| `13'h0068` | `CH_SKIP_CD` | W | 当前通道 offset `0x9` |
|
||||
| `13'h006C` | `CH_STIM_NUM` | W | 当前通道 offset `0xA` |
|
||||
| `13'h0070` | `CH_DZ2` | W | 当前通道 offset `0xB` |
|
||||
| `13'h0074` | `CH_THERAPY_DELAY` | W | 当前通道 offset `0xC` |
|
||||
| `13'h0078` | `CH_THERAPY_NUM` | W | 当前通道 offset `0xD` |
|
||||
| `13'h007C` | `CH_DZ3` | W | 当前通道 offset `0xE` |
|
||||
| `13'h0080` | `CH_MASTER_NUM` | W | 当前通道 offset `0xF` |
|
||||
|
||||
## 7. 寄存器位定义
|
||||
|
||||
### 7.1 `STATUS` 寄存器
|
||||
|
||||
`STATUS` 读回值由 RTL 拼接得到:
|
||||
|
||||
```verilog
|
||||
{16'd0, seq_id, seq_step, error_busy, done_latched, spi_cmd_ready, ctrl_busy}
|
||||
```
|
||||
|
||||
赋值给 32 bit `bram_dout` 时左侧补 0。软件可按以下位使用:
|
||||
|
||||
| 位 | 名称 | 说明 |
|
||||
| ---: | --- | --- |
|
||||
| `[5]` | `ctrl_busy` | 当前模块忙 |
|
||||
| `[6]` | `spi_cmd_ready` | SPI master 空闲可接收命令 |
|
||||
| `[7]` | `done_latched` | 至少完成过一次 SPI 操作 |
|
||||
| `[8]` | `error_busy` | 忙时写命令错误 |
|
||||
| `[11:9]` | `seq_step` | 当前序列步骤 |
|
||||
| `[15:12]` | `seq_id` | 当前序列编号 |
|
||||
|
||||
写 `STATUS` 清除粘滞位:
|
||||
|
||||
| 写 bit | 行为 |
|
||||
| ---: | --- |
|
||||
| `[0] = 1` | 清除 `done_latched` |
|
||||
| `[1] = 1` | 清除 `error_busy` |
|
||||
|
||||
### 7.2 `SPI_CTRL` 寄存器
|
||||
|
||||
| 位 | 名称 | 说明 |
|
||||
| ---: | --- | --- |
|
||||
| `[0]` | `direct_write` | 1:Direct SPI 写;0:Direct SPI 读 |
|
||||
| `[15:8]` | `direct_len` | payload 字节数;0 会被转换为 1 |
|
||||
| 其他 | 保留 | 当前未使用 |
|
||||
|
||||
`direct_len` 最终会在 SPI master 内限制到 `1..MAX_BURST_BYTES`。
|
||||
|
||||
### 7.3 `PIN_CTRL` 寄存器
|
||||
|
||||
| 位 | 名称 | 说明 |
|
||||
| ---: | --- | --- |
|
||||
| `[0]` | `asic_rst_n` | 直接驱动 ASIC reset_n |
|
||||
| `[1]` | `asic_trig` | 直接驱动 ASIC trig |
|
||||
| 其他 | 保留 | 当前读回为 0 |
|
||||
|
||||
### 7.4 `SEQ_CMD` 寄存器
|
||||
|
||||
| 位 | 命令 | SPI 行为 |
|
||||
| ---: | --- | --- |
|
||||
| `[0]` | DCS unlock | 向 `0x0009` 依次写 `55h, B3h, 0Ah` |
|
||||
| `[1]` | Test unlock | 向 `0x0009` 依次写 `AAh, 4Ch, F5h` |
|
||||
| `[2]` | Mode exit | 向 `0x0009` 写 `F9h` |
|
||||
| `[3]` | Control quick write | 设置 `control_shadow = 8'h10` 并写 `0x0002` |
|
||||
| `[4]` | Control quick write | 设置 `control_shadow = 8'h08` 并写 `0x0002` |
|
||||
|
||||
若多个 bit 同时为 1,优先级从 bit0 到 bit4。
|
||||
|
||||
## 8. 命令行为
|
||||
|
||||
### 8.1 `CONTROL`
|
||||
|
||||
写 `BRAM_ADDR_CONTROL`:
|
||||
|
||||
```text
|
||||
control_shadow <= bram_din[7:0]
|
||||
SPI write addr 0x0002, data control_shadow, len 1
|
||||
```
|
||||
|
||||
### 8.2 `CH_ENABLE`
|
||||
|
||||
写 `BRAM_ADDR_CH_ENABLE`:
|
||||
|
||||
```text
|
||||
ch_enable_shadow <= bram_din[15:0]
|
||||
step0: SPI write addr 0x0007, data ch_enable_shadow[7:0]
|
||||
step1: SPI write addr 0x0008, data ch_enable_shadow[15:8]
|
||||
```
|
||||
|
||||
### 8.3 通道参数写
|
||||
|
||||
通道参数地址计算:
|
||||
|
||||
```text
|
||||
asic_addr = CSI_CH_BASE + CH_INDEX * CSI_CH_STRIDE + channel_offset
|
||||
```
|
||||
|
||||
默认:
|
||||
|
||||
```text
|
||||
asic_addr = 0x0010 + CH_INDEX * 0x0010 + channel_offset
|
||||
```
|
||||
|
||||
示例:
|
||||
|
||||
```text
|
||||
CH_INDEX = 3
|
||||
写 CH_CUR_A = 0x7F
|
||||
channel_offset = 0x1
|
||||
asic_addr = 0x0041
|
||||
```
|
||||
|
||||
### 8.4 Direct SPI
|
||||
|
||||
Direct SPI 使用 `SPI_ADDR/SPI_WDATA/SPI_CTRL`:
|
||||
|
||||
```text
|
||||
1. 写 SPI_ADDR 设置 ASIC 地址
|
||||
2. 写 SPI_WDATA 设置写数据
|
||||
3. 写 SPI_CTRL 启动 direct transfer
|
||||
4. 读操作完成后,从 SPI_RDATA 取数据
|
||||
```
|
||||
|
||||
## 9. SPI 时序规格
|
||||
|
||||
### 9.1 SCK 频率
|
||||
|
||||
```text
|
||||
f_sck = f_clk / (2 * SPI_CLK_DIV)
|
||||
```
|
||||
|
||||
示例:
|
||||
|
||||
| `f_clk` | `SPI_CLK_DIV` | `f_sck` |
|
||||
| ---: | ---: | ---: |
|
||||
| 100 MHz | 50 | 1 MHz |
|
||||
| 100 MHz | 25 | 2 MHz |
|
||||
| 100 MHz | 10 | 5 MHz |
|
||||
| 100 MHz | 5 | 10 MHz |
|
||||
|
||||
### 9.2 SPI 帧格式
|
||||
|
||||
默认 `SPI_ADDR_BYTES = 2`:
|
||||
|
||||
```text
|
||||
byte0 opcode
|
||||
byte1 address high byte
|
||||
byte2 address low byte
|
||||
byte3.. payload byte0..N
|
||||
```
|
||||
|
||||
写 1 byte 示例:
|
||||
|
||||
```text
|
||||
opcode = 0x02
|
||||
addr = 0x0002
|
||||
data = 0x10
|
||||
frame = 0x02_0002_10
|
||||
```
|
||||
|
||||
### 9.3 SPI bit 数
|
||||
|
||||
```text
|
||||
frame_bits = 8 * (1 + SPI_ADDR_BYTES + payload_len)
|
||||
```
|
||||
|
||||
默认地址 2 byte 时:
|
||||
|
||||
| payload_len | frame_bits |
|
||||
| ---: | ---: |
|
||||
| 1 | 32 |
|
||||
| 2 | 40 |
|
||||
| 3 | 48 |
|
||||
| 4 | 56 |
|
||||
|
||||
### 9.4 传输时间估算
|
||||
|
||||
不计状态机少量额外周期时:
|
||||
|
||||
```text
|
||||
transfer_time ≈ frame_bits * 2 * SPI_CLK_DIV * clk_period
|
||||
```
|
||||
|
||||
100 MHz、`SPI_CLK_DIV = 50`、1 byte payload:
|
||||
|
||||
```text
|
||||
frame_bits = 32
|
||||
transfer_time ≈ 32 * 2 * 50 * 10 ns = 32 us
|
||||
```
|
||||
|
||||
## 10. 软件推荐流程
|
||||
|
||||
### 10.1 写普通命令
|
||||
|
||||
```text
|
||||
1. 轮询 STATUS[5] == 0,确认不忙
|
||||
2. 写目标命令寄存器
|
||||
3. 轮询 STATUS[7] == 1,确认完成
|
||||
4. 写 STATUS[0] = 1,清除 done_latched
|
||||
5. 若 STATUS[8] == 1,记录错误并写 STATUS[1] = 1 清除
|
||||
```
|
||||
|
||||
### 10.2 Direct read 示例
|
||||
|
||||
读取 CSI040 Part ID:
|
||||
|
||||
```text
|
||||
write SPI_ADDR = 0x0000011D
|
||||
write SPI_CTRL = 0x00000100 // bit0=0 read, len=1
|
||||
wait done
|
||||
read SPI_RDATA[7:0]
|
||||
```
|
||||
|
||||
testbench 中 ASIC 模型返回 `8'h28`。
|
||||
|
||||
### 10.3 Direct write 示例
|
||||
|
||||
向 ASIC `0x0002` 写 `0x10`:
|
||||
|
||||
```text
|
||||
write SPI_ADDR = 0x00000002
|
||||
write SPI_WDATA = 0x00000010
|
||||
write SPI_CTRL = 0x00000101 // bit0=1 write, len=1
|
||||
wait done
|
||||
```
|
||||
|
||||
## 11. 复位默认值
|
||||
|
||||
| 项目 | 复位值 |
|
||||
| --- | ---: |
|
||||
| `direct_addr` | `0` |
|
||||
| `direct_wdata` | `0` |
|
||||
| `direct_len` | `1` |
|
||||
| `direct_write` | `1` |
|
||||
| `control_shadow` | `0` |
|
||||
| `ch_enable_shadow` | `0` |
|
||||
| `ch_index` | `0` |
|
||||
| `seq_id` | `SEQ_IDLE` |
|
||||
| `seq_step` | `0` |
|
||||
| `seq_active` | `0` |
|
||||
| `error_busy` | `0` |
|
||||
| `done_latched` | `0` |
|
||||
| `last_rdata` | `0` |
|
||||
| `last_addr` | `0` |
|
||||
| `asic_rst_n` | `1` |
|
||||
| `asic_trig` | `0` |
|
||||
| `asic_csn` | `1` |
|
||||
| `asic_sck` | `0` |
|
||||
| `asic_si` | `0` |
|
||||
|
||||
## 12. 集成注意事项
|
||||
|
||||
- `bram_clk` 和 `bram_rst` 当前未使用,BRAM 访问必须同步到 `clk`。
|
||||
- 只支持整字写,软件侧需要保证 `bram_we == 4'hF`。
|
||||
- `busy = 1` 时不要写命令寄存器,否则命令被丢弃并置位 `error_busy`。
|
||||
- `TRIGGER` 寄存器是通过 SPI 写 ASIC trigger register;`PIN_CTRL[1]` 是直接驱动 `asic_trig` 引脚,两者不是同一个功能。
|
||||
- `SPI_OPCODE_WRITE/READ` 需要与最终 CSI040 SPI 协议匹配。当前 testbench 使用 `8'h02/8'h03`。
|
||||
- 若系统时钟不是 100 MHz,需要重新计算 `SPI_CLK_DIV`,保证 CSI040 SPI 时序满足要求。
|
||||
- Direct SPI 多字节读写最大长度由 `MAX_BURST_BYTES` 控制,默认最多 4 byte。
|
||||
|
||||
## 13. 验证状态
|
||||
|
||||
当前 testbench 覆盖:
|
||||
|
||||
| 测试项 | 期望 |
|
||||
| --- | --- |
|
||||
| CONTROL 写 | SPI frame `0x02000210` |
|
||||
| CH_ENABLE 写 | SPI frame `0x0200075A` 和 `0x020008A5` |
|
||||
| CH3 CUR_A 写 | SPI frame `0x0200417F` |
|
||||
| DCS unlock | SPI frame `0x02000955/0x020009B3/0x0200090A` |
|
||||
| Direct read Part ID | SPI frame `0x03011D00`,读回 `0x28` |
|
||||
|
||||
已运行:
|
||||
|
||||
```text
|
||||
xvlog: pass
|
||||
xelab: pass
|
||||
xsim : $finish at 10940 ns
|
||||
```
|
||||
Reference in New Issue
Block a user