优化版 HTML:已添加侧边目录、章节锚点、响应式表格、打印样式和离线 CSS。
#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.vc64_pro.srcs/sources_1/rtl/csi040/csi040_spi_master.vc64_pro.srcs/sources_1/rtl/csi040/csi040_ctrl_tb.v
#2. 模块框图
+------------------------------+
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 拼接得到:
{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:
control_shadow <= bram_din[7:0]
SPI write addr 0x0002, data control_shadow, len 1
#8.2 CH_ENABLE
写 BRAM_ADDR_CH_ENABLE:
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 通道参数写
通道参数地址计算:
asic_addr = CSI_CH_BASE + CH_INDEX * CSI_CH_STRIDE + channel_offset
默认:
asic_addr = 0x0010 + CH_INDEX * 0x0010 + channel_offset
示例:
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:
1. 写 SPI_ADDR 设置 ASIC 地址
2. 写 SPI_WDATA 设置写数据
3. 写 SPI_CTRL 启动 direct transfer
4. 读操作完成后,从 SPI_RDATA 取数据
#9. SPI 时序规格
#9.1 SCK 频率
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:
byte0 opcode
byte1 address high byte
byte2 address low byte
byte3.. payload byte0..N
写 1 byte 示例:
opcode = 0x02
addr = 0x0002
data = 0x10
frame = 0x02_0002_10
#9.3 SPI bit 数
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 传输时间估算
不计状态机少量额外周期时:
transfer_time ≈ frame_bits * 2 * SPI_CLK_DIV * clk_period
100 MHz、SPI_CLK_DIV = 50、1 byte payload:
frame_bits = 32
transfer_time ≈ 32 * 2 * 50 * 10 ns = 32 us
#10. 软件推荐流程
#10.1 写普通命令
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:
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:
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 |
已运行:
xvlog: pass
xelab: pass
xsim : $finish at 10940 ns