# CCSDS122 Datamover 详细设计方案 > 版本: 2026-06-30 | 目标器件: Xilinx VU440 + Zynq UltraScale+ ZU4 --- ## 目录 1. [系统架构](#1-系统架构) 2. [DDR 地址空间分配](#2-ddr-地址空间分配) 3. [压缩输出地址空间分配](#3-压缩输出地址空间分配) 4. [模块划分与职责](#4-模块划分与职责) 5. [顶层状态机](#5-顶层状态机) 6. [Phase 1: 元数据读取](#6-phase-1-元数据读取) 7. [Phase 2: 辅助数据 DMA](#7-phase-2-辅助数据-dma) 8. [Phase 3: 图像压缩搬移](#8-phase-3-图像压缩搬移) 9. [MM2S 命令流水线](#9-mm2s-命令流水线) 10. [S2MM 命令策略](#10-s2mm-命令策略) 11. [地址计算模块](#11-地址计算模块) 12. [Bubble Removal 改动](#12-bubble-removal-改动) 13. [Stream 数据路径](#13-stream-数据路径) 14. [信号接口](#14-信号接口) 15. [参数配置](#15-参数配置) --- ## 1. 系统架构 ### 1.1 整体框图 ``` ┌─ PC ──────────────────────────────────────────────────────────────┐ │ upload_compress_download.py │ │ 串口上传原始图像 → 配置压缩参数 → 等待压缩完成 → 下载压缩结果 │ └──────────────────────────────┬──────────────────────────────────────┘ │ UART (COM7, 2M baud) ┌─ Zynq ZU4 (PS) ─────────────┼──────────────────────────────────────┐ │ ccsds_uart_axi │ │ │ ├─ uart_rx / uart_tx │ │ │ └─ axi_uart_upload ◄────────┘ │ │ ├─ m_axi (AXI4 Full) ──→ SmartConnect ──→ PS DDR4 │ │ └─ m_axil (AXI4 Lite) ──→ C2C ──→ VU440 axil_slave │ └────────────────────────────────┬────────────────────────────────────┘ │ C2C (SelectIO, 9对差分) ┌─ VU440 (PL) ──────────────────┼────────────────────────────────────┐ │ ccsds122_datamover │ │ │ ├─ ccsds122_stream_ctrl │ │ │ │ ├─ ccsds122_addr_calc │ │ │ │ └─ (FSM + MM2S/S2MM cmd) │ │ │ ├─ axi_datamover_0 (Xilinx IP) │ │ └─ ccsds122_compression_top │ │ ├─ ccsds122_bubble_removal_ctrl │ │ └─ top_bpe_encoder (CCSDS 122.0-B-2) │ └─────────────────────────────────────────────────────────────────────┘ ``` ### 1.2 数据流向 ``` 原始图像: Zynq DDR4 ──[MM2S Read]──→ Datamover ──[mm2s_stream]──→ stream_ctrl ↓ ↓ (C2C 回传) raw_s_axis ↓ bubble_removal ↓ top_bpe_encoder ↓ 压缩数据: pack_m_axis ↓ Zynq DDR4 ←──[S2MM Write]── Datamover ←──[s2mm_stream]── stream_ctrl ↑ (C2C 回传) 辅助数据 (不压缩): Zynq DDR4 ──[MM2S Read]──→ Datamover ──[mm2s_stream]──→ stream_ctrl │ (bypass MUX) Zynq DDR4 ←──[S2MM Write]── Datamover ←──[s2mm_stream]────┘ ``` ### 1.3 图像规格 | 参数 | 值 | |------|-----| | 像素位深 | 14-bit | | 每幅图尺寸 | 256 × 256 pixels | | 每 beat 像素数 | 4 | | 每幅图 beats | 16,384 | | 每幅图字节数 | 131,072 (128 KB) | | 每行取像素 | 256 pixels = 512 bytes | | 每幅图行数 | 256 rows | --- ## 2. DDR 地址空间分配 ### 2.1 总体布局 原始图像存储在 Zynq PS DDR4 的一个连续 128MB(或 64MB)块中,起始地址为 `flaw_image_addr`。 ``` ┌──────────────────────────────────────────────────────────────┐ │ flaw_image_addr (128MB Block) │ │ │ │ ┌──────────────────────────────────────────────────────┐ │ │ │ 区域 0: PAN 图像数据 (96MB / 48MB) │ │ │ ├──────────────────────────────────────────────────────┤ │ │ │ 区域 1: B1 图像数据 (6MB / 3MB) │ │ │ ├──────────────────────────────────────────────────────┤ │ │ │ 区域 2: B2 图像数据 (6MB / 3MB) │ │ │ ├──────────────────────────────────────────────────────┤ │ │ │ 区域 3: B3 图像数据 (6MB / 3MB) │ │ │ ├──────────────────────────────────────────────────────┤ │ │ │ 区域 4: B4 图像数据 (6MB / 3MB) │ │ │ ├──────────────────────────────────────────────────────┤ │ │ │ 辅助数据区 (各区域 aux 连续存放) │ │ │ │ PAN_aux + B1_aux + B2_aux + B3_aux + B4_aux │ │ │ ├──────────────────────────────────────────────────────┤ │ │ │ (padding to 128MB - 4KB) │ │ │ ├──────────────────────────────────────────────────────┤ │ │ │ 元数据: 5 × 32-bit row counts @ 最后 4KB │ │ │ └──────────────────────────────────────────────────────┘ │ └──────────────────────────────────────────────────────────────┘ ``` ### 2.2 模式 1: PAN + B1~B4 **128M Block:** | 区域 | 数据 | 分辨率 | 行跨距 | 原始大小 | 最大行数 | 图像偏移 | |------|------|--------|--------|---------|---------|---------| | PAN | 全色 | 6144×8192×2B | 12288 | 96 MB | 8192 | 0 | | B1 | 多光谱 | 1536×2048×2B | 3072 | 6 MB | 2048 | 96 MB | | B2 | 多光谱 | 1536×2048×2B | 3072 | 6 MB | 2048 | 102 MB | | B3 | 多光谱 | 1536×2048×2B | 3072 | 6 MB | 2048 | 108 MB | | B4 | 多光谱 | 1536×2048×2B | 3072 | 6 MB | 2048 | 114 MB | 图像数据总量: **120 MB**。辅助数据从 `flaw_image_addr + 120MB` 开始。 原始 DDR 区域示意图: ``` flaw_image_addr + 0 ──→ PAN (6144 px × 8192 rows × 2B) flaw_image_addr + 96MB ──→ B1 (1536 px × 2048 rows × 2B) flaw_image_addr + 102MB ──→ B2 (1536 px × 2048 rows × 2B) flaw_image_addr + 108MB ──→ B3 (1536 px × 2048 rows × 2B) flaw_image_addr + 114MB ──→ B4 (1536 px × 2048 rows × 2B) flaw_image_addr + 120MB ──→ aux 数据区 flaw_image_addr + 128MB - 4KB ──→ 元数据 ``` **64M Block:** | 区域 | 数据 | 行跨距 | 原始大小 | 最大行数 | 图像偏移 | |------|------|--------|---------|---------|---------| | PAN | 全色 | 12288 | 48 MB | 4096 | 0 | | B1 | 多光谱 | 3072 | 3 MB | 1024 | 48 MB | | B2 | 多光谱 | 3072 | 3 MB | 1024 | 51 MB | | B3 | 多光谱 | 3072 | 3 MB | 1024 | 54 MB | | B4 | 多光谱 | 3072 | 3 MB | 1024 | 57 MB | 图像数据总量: **60 MB**。 ### 2.3 模式 2: PAN only **128M Block:** | 区域 | 行跨距 | 原始大小 | 最大行数 | 图像偏移 | |------|--------|---------|---------|---------| | PAN | 12288 | 120 MB | 10240 | 0 | 图像数据总量: **120 MB**。 ``` flaw_image_addr + 0 ──→ PAN (6144 px × 10240 rows × 2B) flaw_image_addr + 120MB ──→ aux 数据区 flaw_image_addr + 128MB - 4KB ──→ 元数据 ``` **64M Block:** | 区域 | 行跨距 | 原始大小 | 最大行数 | 图像偏移 | |------|--------|---------|---------|---------| | PAN | 12288 | 60 MB | 5120 | 0 | 图像数据总量: **60 MB**。 ### 2.4 模式 3: B1~B4 **128M Block:** | 区域 | 行跨距 | 原始大小 | 最大行数 | 图像偏移 | |------|--------|---------|---------|---------| | B1 | 3072 | 30 MB | 10240 | 0 | | B2 | 3072 | 30 MB | 10240 | 30 MB | | B3 | 3072 | 30 MB | 10240 | 60 MB | | B4 | 3072 | 30 MB | 10240 | 90 MB | 图像数据总量: **120 MB**。 **64M Block:** | 区域 | 行跨距 | 原始大小 | 最大行数 | 图像偏移 | |------|--------|---------|---------|---------| | B1 | 3072 | 15 MB | 5120 | 0 | | B2 | 3072 | 15 MB | 5120 | 15 MB | | B3 | 3072 | 15 MB | 5120 | 30 MB | | B4 | 3072 | 15 MB | 5120 | 45 MB | 图像数据总量: **60 MB**。 ### 2.5 元数据格式 位于 `flaw_image_addr + BLOCK_SIZE - 4096`,前 20 字节: ``` Byte 0-3: PAN_row (big-endian 32-bit) Byte 4-7: B1_row (big-endian 32-bit) Byte 8-11: B2_row (big-endian 32-bit) Byte 12-15: B3_row (big-endian 32-bit) Byte 16-19: B4_row (big-endian 32-bit) ``` | 字段 | 含义 | 用途 | |------|------|------| | PAN_row | PAN 区域实际有效行数 | 决定 PAN 处理多少幅图、aux 大小 | | B1_row | B1 区域实际有效行数 | 决定 B1 处理多少幅图、aux 大小 | | B2_row | B2 区域实际有效行数 | 同上 | | B3_row | B3 区域实际有效行数 | 同上 | | B4_row | B4 区域实际有效行数 | 同上 | 按模式使用的字段: | 模式 | 使用字段 | |------|---------| | 1 | PAN_row, B1_row, B2_row, B3_row, B4_row | | 2 | PAN_row | | 3 | B1_row, B2_row, B3_row, B4_row | --- ## 3. 压缩输出地址空间分配 ### 3.1 总体布局 压缩数据通过 S2MM 写入 DDR,起始地址为 `COMPRESS_BASE_ADDR`(parameter)。每区域分配 `原始大小 + 1MB` 空间。 ### 3.2 模式 1, 128M ``` COMPRESS_BASE + 0 ──→ PAN aux (PAN_row × 140B) PAN 压缩数据 (最大 97MB - aux) COMPRESS_BASE + 97MB ──→ B1 aux (B1_row × 140B) B1 压缩数据 (最大 7MB - aux) COMPRESS_BASE + 104MB ──→ B2 aux (B2_row × 140B) B2 压缩数据 (最大 7MB - aux) COMPRESS_BASE + 111MB ──→ B3 aux (B3_row × 140B) B3 压缩数据 (最大 7MB - aux) COMPRESS_BASE + 118MB ──→ B4 aux (B4_row × 140B) B4 压缩数据 (最大 7MB - aux) ``` 参数表: ``` slot 0 (PAN) slot 1 (B1) slot 2 (B2) slot 3 (B3) slot 4 (B4) roff_q 0 96MB 102MB 108MB 114MB rstr_q 12288 3072 3072 3072 3072 rwid_q 6144 1536 1536 1536 1536 rmax_q 8192 2048 2048 2048 2048 rraw_q 96MB 6MB 6MB 6MB 6MB rall_q 97MB 7MB 7MB 7MB 7MB rpan_q 1 0 0 0 0 ``` | 累加器 | slot 0 | slot 1 | slot 2 | slot 3 | slot 4 | slot 5 | |--------|--------|--------|--------|--------|--------|--------| | img_cumul_q (图像累计) | 0 | 96MB | 102MB | 108MB | 114MB | 120MB | | comp_cumul_q (压缩累计) | 0 | 97MB | 104MB | 111MB | 118MB | 125MB | ### 3.3 模式 2, 128M ``` slot 0 (PAN) slot 1 slot 2 slot 3 slot 4 roff_q 0 0 0 0 0 rstr_q 12288 0 0 0 0 rwid_q 6144 0 0 0 0 rmax_q 10240 0 0 0 0 rraw_q 120MB 0 0 0 0 rall_q 121MB 0 0 0 0 rpan_q 1 0 0 0 0 rcnt_q = 1 img_cumul_q = [0, 120MB, 120MB, 120MB, 120MB, 120MB] comp_cumul_q = [0, 121MB, 121MB, 121MB, 121MB, 121MB] img_total_q = 120MB ``` ### 3.4 模式 3, 128M ``` slot 0 (B1) slot 1 (B2) slot 2 (B3) slot 3 (B4) slot 4 roff_q 0 30MB 60MB 90MB 0 rstr_q 3072 3072 3072 3072 0 rwid_q 1536 1536 1536 1536 0 rmax_q 10240 10240 10240 10240 0 rraw_q 30MB 30MB 30MB 30MB 0 rall_q 31MB 31MB 31MB 31MB 0 rpan_q 0 0 0 0 0 rcnt_q = 4 img_cumul_q = [0, 30MB, 60MB, 90MB, 120MB, 120MB] comp_cumul_q = [0, 31MB, 62MB, 93MB, 124MB, 124MB] img_total_q = 120MB ``` --- ## 4. 模块划分与职责 ``` ccsds122_datamover.sv ← 顶层集成 ├── axi_datamover_0 ← Xilinx AXI Datamover IP (DMA 引擎) ├── ccsds122_stream_ctrl.sv ← 主控制器 (FSM + 命令生成 + 流桥接) │ └── ccsds122_addr_calc.sv ← 地址与布局参数计算器 └── ccsds122_compression_top.sv ← 压缩子系统 ├── ccsds122_bubble_removal_ctrl.sv ← 气泡消除 + 流打包 └── top_bpe_encoder ← CCSDS 122.0-B-2 压缩核 ``` | 模块 | 职责 | |------|------| | `ccsds122_addr_calc` | 根据 mode + block_size 查表得到全部区域参数;计算 MM2S 行地址、aux 地址、总图像数 | | `ccsds122_stream_ctrl` | 三段式 FSM 控制全流程;MM2S/S2MM 命令生成与握手;stream MUX(正常/bypass);统计累加 | | `ccsds122_bubble_removal_ctrl` | 旋转+spill 气泡消除;每图 tlast 生成;raw path 字节计数 | | `ccsds122_datamover` | 顶层例化 + enable 锁存 + 统计信号透传 | --- ## 5. 顶层状态机 ### 5.1 状态定义 ``` typedef enum logic [3:0] { ST_IDLE = 4'd0, // 等待 enable 上升沿 ST_READ_META_CMD = 4'd1, // 发 MM2S 读 24B 元数据 ST_READ_META_WAIT = 4'd2, // 等 stream 数据 + STS ST_DMA_AUX_SEL = 4'd3, // 选下一个 aux 区域 ST_DMA_AUX_MM2S_CMD = 4'd4, // 发 MM2S aux 读 ST_DMA_AUX_S2MM_CMD = 4'd5, // 发 S2MM aux 写 ST_DMA_AUX_WAIT_STS = 4'd6, // 等双 STS ST_PROC_REGION_SEL = 4'd7, // 选下一个图像区域 ST_PROC_IMG_START = 4'd8, // 图像开始, 发 S2MM INDET ST_PROC_IMG_MM2S = 4'd9, // 256 cmd, 2-in-flight ST_PROC_IMG_WAIT_COMP = 4'd10, // 等压缩完成 ST_PROC_IMG_NEXT = 4'd11, // 下一幅 / 下一区域 ST_DONE = 4'd12 // 全部完成 } state_t; ``` ### 5.2 状态转移图 ``` IDLE ──enable_rise──→ META_CMD ──cmd握手──→ META_WAIT ──meta_done──→ AUX_SEL ↑ ↓ │ ┌── size>0 ──→ AUX_MM2S → AUX_S2MM → AUX_WAIT │ │ ↑ ↓ │ └─ size=0 (skip) ──┘ 双STS就绪 → AUX_SEL │ ↑ │ ┌─── region未完 ──────┘ │ │ │ AUX_SEL ──all done──→ PROC_SEL │ ↓ │ ┌── total=0 (skip) ──→ loop │ │ ↑ │ └─ total>0 ──→ IMG_START → IMG_MM2S │ ↑ ↓ │ ┌─ 还有图 ─┘ IMG_WAIT_COMP │ │ ↑ ↓ │ └───┘ IMG_NEXT (双标志) │ ↓ │ ┌─ 区域未完 → IMG_START │ └─ 区域完 → PROC_SEL │ ↓ └────────────────────────── enable=0 ──────────────────── DONE ← proc≥total ``` ### 5.3 三段式 FSM 结构 ``` Stage 1 (always_ff): state_q <= state_next ← 纯状态寄存器 Stage 2 (always_comb): state_next = f(state_q) ← 纯组合逻辑跳转 Stage 3 (always_ff): case(state_q) ... ← 输出赋值, 不驱动 state_next ``` Stage 2 所有转移条件使用握手信号或内部标志,Stage 3 不参与状态转移。 --- ## 6. Phase 1: 元数据读取 ### 6.1 流程 1. enable 上升沿 → 锁存 `flaw_image_addr`, `flaw_storage_mode`, `ac_mode` 2. `ST_READ_META_CMD`: 发一条 MM2S 读命令 - 地址: `flaw_image_addr + BLOCK_BYTES - 4096` - BTT: 24 字节 (8B 对齐, 3 个完整 beat) 3. `ST_READ_META_WAIT`: 等待 stream 数据 + MM2S STS ### 6.2 元数据接收 (192-bit shift buffer) ``` beat0 到达: meta_buf <= {128'd0, beat0} beat1 到达: meta_buf <= {meta_buf[127:0], beat1} = {64'd0, beat0, beat1} beat2 到达: meta_buf <= {meta_buf[127:0], beat2} = {beat0, beat1, beat2} ``` 提取: ``` meta_word0 = meta_buf[191:160] = beat0[63:32] = PAN_row meta_word1 = meta_buf[159:128] = beat0[31:0] = B1_row meta_word2 = meta_buf[127:96] = beat1[63:32] = B2_row meta_word3 = meta_buf[95:64] = beat1[31:0] = B3_row meta_word4 = meta_buf[63:32] = beat2[63:32] = B4_row meta_buf[31:0] = beat2[31:0] = 抛弃 (多读的4字节) ``` ### 6.3 按模式提取 ``` mode 1: row_pan = word0, row_b1 = word1, row_b2 = word2, row_b3 = word3, row_b4 = word4 mode 2: row_pan = word0, row_b1~b4 = 0 mode 3: row_pan = 0, row_b1 = word1, row_b2 = word2, row_b3 = word3, row_b4 = word4 ``` --- ## 7. Phase 2: 辅助数据 DMA ### 7.1 流程 逐区域遍历 (aux_region_q = 0 → region_count-1): 1. `ST_DMA_AUX_SEL`: 设置 `ac_region_idx`, 等待 addr_calc 输出稳定 2. 若 `aux_size == 0`: 跳过该区域 (`aux_region_q++`) 3. 若 `aux_size > 0`: - `ST_DMA_AUX_MM2S_CMD`: 发 MM2S 读 aux 数据 - `ST_DMA_AUX_S2MM_CMD`: 发 S2MM 写 aux 数据 (exact BTT) - `ST_DMA_AUX_WAIT_STS`: 分步等待两个 STS ### 7.2 地址计算 **aux 源地址 (MM2S 读):** ``` aux_mm2s_src = flaw_image_addr + img_total_q + cumulative_aux_offset ``` 其中: - `img_total_q` = 所有区域图像数据总大小 (mode 1: 120MB) - `cumulative_aux_offset` = 前面区域的 aux 数据累加 具体: | region_idx | cumulative_aux_offset | |-----------|----------------------| | 0 (PAN/B1) | 0 | | 1 (B1/B2) | calc_aux_size(s0) = s0_row × 140 | | 2 (B2/B3) | calc_aux_size(s0) + calc_aux_size(s1) | | 3 (B3/B4) | calc_aux_size(s0) + calc_aux_size(s1) + calc_aux_size(s2) | | 4 (B4) | ... + calc_aux_size(s3) | 其中 `sN` 通过 `slot_row(mode, N, ...)` 获得正确波段的 row_count。 **aux 目的地址 (S2MM 写):** ``` aux_s2mm_dst = COMPRESS_BASE_ADDR + comp_cumul_q[region_idx] ``` `comp_cumul_q` 是预计算的压缩区域累计偏移数组。 ### 7.3 Bypass 数据路径 ``` DMA_AUX 阶段: mm2s_stream_tready = s2mm_stream_tready ← 直通 s2mm_stream ← mm2s_stream ← MUX raw_s_axis 无效 (不进入压缩管线) pack_m_axis_tready = 0 ← 反压压缩输出 ``` ### 7.4 双 STS 分步跟踪 MM2S STS 和 S2MM STS 可能先后到达,使用独立标志: ``` aux_mm2s_sts_done: mm2s_sts_tvalid && mm2s_sts_tready → 锁存为 1 aux_s2mm_sts_done: s2mm_sts_tvalid && s2mm_sts_tready → 锁存为 1 两标志都为 1 → aux_region_q++, Stage2 跳回 AUX_SEL ``` --- ## 8. Phase 3: 图像压缩搬移 ### 8.1 流程 逐区域遍历 (proc_region_q = 0 → region_count-1): 1. `ST_PROC_REGION_SEL`: 设置 `ac_region_idx`, 等待 addr_calc - 若 `total_imgs == 0`: 跳过该区域 - 否则: 初始化 `img_idx=0`, `ac_img_init=1`, `s2mm_byte_off = aux_size` 2. 逐幅图处理: - `ST_PROC_IMG_START`: 发 S2MM INDET_BTT 命令 - `ST_PROC_IMG_MM2S`: 256 条 MM2S cmd, 2-in-flight 流水线 - `ST_PROC_IMG_WAIT_COMP`: 等 `flaw_compress_valid` - `ST_PROC_IMG_NEXT`: 累加压缩字节, 等 S2MM STS; 判断继续或下一区域 ### 8.2 单幅图 MM2S 搬移 每幅图 = 256 行, 每行 512 字节。MM2S 行地址: ``` cmd[N]: addr = flaw_image_addr + region_image_offset + img_col × 512 + (img_row_base + N) × row_stride ``` - `region_image_offset`: 当前区域在 DDR 中的起始偏移 (roff_q) - `img_col`: 当前图在行内的列索引 (0..23 PAN, 0..5 MS) - `img_row_base`: 当前图所在图像行的起始行号 (0, 256, 512, ...) - `row_stride`: PAN=12288 (6144×2), MS=3072 (1536×2) ### 8.3 图像遍历 每个区域内图像按行优先排列: ``` img_idx img_col (在行内) img_row_base 0 0 0 1 1 0 ... 23 (PAN) 23 0 24 0 256 25 1 256 ... ``` `img_col` 和 `img_row_base` 用寄存器递增, 无除法: ``` img_init → img_col=0, img_row_base=0 img_advance: if img_col < imgs_per_row-1: img_col++ else: img_col=0, img_row_base += 256 ``` ### 8.4 区域完成判断 ``` total_imgs = imgs_per_row × (row_count / 256) PAN (24): total = (row_count[31:8] << 4) + (row_count[31:8] << 3) // ×(16+8) MS (6): total = (row_count[31:8] << 2) + (row_count[31:8] << 1) // ×(4+2) ``` 当 `img_idx >= total_imgs` 时区域完成, `proc_region_q++`。 --- ## 9. MM2S 命令流水线 ### 9.1 2-in-flight 策略 ``` 阶段 1 — 初始连续发两条: Cycle 0: 发 cmd[0] (row=0), valid=1 Cycle 1: 握手完成, cmd_idx→1 Cycle 2: 发 cmd[1] (row=1), valid=1 Cycle 3: 握手完成, cmd_idx→2, pending=2 阶段 2 — 收一条 STS, 发一条 cmd (保持 pending=2): 收到 STS_N → 发 cmd[N+2], cmd_idx++ ... 阶段 3 — 最后收尾 (cmd_idx=256, 不发新cmd): 收到 STS_254 → pending: 2→1 收到 STS_255 → pending: 1→0 → 跳转 IMG_WAIT_COMP ``` ### 9.2 CMD 握手协议 ``` 发出: if (!mm2s_cmd_tvalid) → mm2s_cmd_tvalid <= 1, 写入 tdata 检测: if (mm2s_cmd_tvalid && mm2s_cmd_tready) → 握手完成, 状态推进 ``` ### 9.3 STS 处理时序 ``` mm2s_sts_tready: 仅在 cmd_idx ≥ 2 时拉高 - cmd_idx=0,1 时 tready=0 → 忽略提前到达的 STS - cmd_idx≥2 时 tready=1 → 接收 STS ``` --- ## 10. S2MM 命令策略 ### 10.1 三种场景 | 场景 | BTT 类型 | 数量 | |------|---------|------| | 辅助数据 | Exact BTT (= aux_size) | 每区域 1 条 | | 压缩图像 | INDET_BTT (eof=1, btt=MAX) | 每幅图 1 条 | ### 10.2 压缩 S2MM 命令 ``` s2mm_cmd: addr = COMPRESS_BASE_ADDR + region_comp_offset + s2mm_byte_off btt = MAX_BTT (23'h7F_FFFF) eof = 1 ``` `s2mm_byte_off` 每幅图累加 `flaw_compress_len`,跨区域时重置为 0。 ### 10.3 S2MM 完成检测 在 `ST_PROC_IMG_NEXT` 中用双标志: ``` img_flaw_done: flaw_compress_valid 到达 → 累加压缩字节 img_sts_done: s2mm_sts 握手完成 → 更新 img_idx 双标志就绪 → Stage2 跳转 (继续/下一区域) ``` 无论 `flaw_compress_valid` 和 `s2mm_sts` 谁先到, 都不会丢数据。 --- ## 11. 地址计算模块 ### 11.1 核心函数 | 函数 | 公式 | 说明 | |------|------|------| | `mb_offset(mb)` | `mb << 20` | MB → bytes | | `calc_aux_size(rc)` | `(rc<<7) + (rc<<3) + (rc<<2)` | rc × 140 = rc×(128+8+4) | | `slot_row(mode, s, ...)` | 查表 | mode 感知的 slot→row_count 映射 | ### 11.2 slot_row 映射表 ``` mode 1: s=0→pan, 1→b1, 2→b2, 3→b3, 4→b4 mode 2: s=0→pan, 其余→0 mode 3: s=0→b1, 1→b2, 2→b3, 3→b4, 4→0 ``` ### 11.3 移位乘法 所有乘数分解为 2 的幂之和, 使用移位加法: | 乘数 | 分解 | 实现 | |------|------|------| | ×140 | 128+8+4 | `(rc<<7)+(rc<<3)+(rc<<2)` | | ×24 (PAN total_imgs) | 16+8 | `(row256<<4)+(row256<<3)` | | ×6 (MS total_imgs) | 4+2 | `(row256<<2)+(row256<<1)` | | ×12288 (PAN stride) | 8192+4096 | `(row<<13)+(row<<12)` | | ×3072 (MS stride) | 2048+1024 | `(row<<11)+(row<<10)` | | ×512 (col offset) | 1<<9 | `{27'd0, img_col, 9'd0}` | | ×256 (row base) | 1<<8 | `img_row_base + 256` (加法) | ### 11.4 累积和 (阻塞赋值链) ``` cumul_img[0] = 0; for s=0..4: cumul_img[s+1] = cumul_img[s] + rraw_q[s]; // 阻塞 = for s=0..5: img_cumul_q[s] <= cumul_img[s]; // NBA <= ``` 阻塞赋值保证链式累加正确(`cumul_img[2] = cumul_img[1] + rraw[1]` 使用刚计算的 `cumul_img[1]`)。 --- ## 12. Bubble Removal 改动 ### 12.1 新增信号 ``` raw_image_done_q — 每幅图 raw data 收完标志 ``` ### 12.2 生命周期 ``` rst_n → raw_image_done_q = 0 enc_frame_start → raw_image_done_q = 0 (新图像开始) raw_byte_cnt + beat ≥ 131072 → raw_image_done_q = 1 (当前图像 raw data 收完) ``` ### 12.3 压缩路径替换 (3 处) ``` spill_is_last_next = comp_s_axis_tlast && raw_image_done_q (原 raw_all_done_q) accum_last_next = comp_s_axis_tlast && raw_image_done_q (原 raw_all_done_q) outbuf_last_next = accum_last_next && raw_image_done_q (原 raw_all_done_q) ``` 旋转+spill 算法完全不动。 --- ## 13. Stream 数据路径 ### 13.1 tready 控制 ``` mm2s_stream_tready: ST_READ_META_WAIT → 1'b1 (无条件接收 metadata) bypass_active → s2mm_stream_tready (bypass 直通) 否则 → raw_s_axis_tready (正常压缩路径) pack_m_axis_tready: bypass_active → 1'b0 (反压) 否则 → s2mm_stream_tready ``` ### 13.2 数据转发 ``` raw_s_axis (仅在 !bypass && state != META_WAIT): mm2s_stream → raw_s_axis → bubble_removal → encoder s2mm_stream: bypass_active: mm2s_stream → s2mm_stream (直通, aux 数据) !bypass: pack_m_axis → s2mm_stream (压缩数据) ``` --- ## 14. 信号接口 ### 14.1 顶层输入 (PS → datamover) | 信号 | 位宽 | 描述 | |------|------|------| | `enable` | 1 | 高有效, 上升沿触发全流程 | | `flaw_image_valid` | 1 | 单周期脉冲, 锁存 enable_latched | | `target_bpp` | 3 | CCSDS 目标 bpp (0/2/4/7) | | `flaw_image_addr` | 32 | 128MB 原始数据块首地址 | | `flaw_storage_mode` | 2 | 存储模式 (1/2/3) | ### 14.2 顶层输出 (datamover → PS) | 信号 | 位宽 | 描述 | |------|------|------| | `compressor_busy` | 1 | 高 = 处理中 | | `compress_pan_row` | 32 | PAN 有效行数 | | `compress_b1_row` | 32 | B1 有效行数 | | `compress_b2_row` | 32 | B2 有效行数 | | `compress_b3_row` | 32 | B3 有效行数 | | `compress_b4_row` | 32 | B4 有效行数 | | `s2mm_total_bytes` | 32 | S2MM 写入总字节 (aux + 压缩) | | `compress_pan_bytes` | 32 | PAN 压缩字节 | | `compress_b1_bytes` | 32 | B1 压缩字节 | | `compress_b2_bytes` | 32 | B2 压缩字节 | | `compress_b3_bytes` | 32 | B3 压缩字节 | | `compress_b4_bytes` | 32 | B4 压缩字节 | | `compress_done_valid` | 1 | 单周期脉冲, 全流程完成 | ### 14.3 内部 AXI 接口 | 接口 | 方向 | 描述 | |------|------|------| | `m_axi_mm2s_*` | 输出 | AXI4 Read (Datamover → DDR) | | `m_axi_s2mm_*` | 输出 | AXI4 Write (Datamover → DDR) | | `s_axis_mm2s_cmd` | 输出 | MM2S 命令 (72-bit) | | `m_axis_mm2s_sts` | 输入 | MM2S 状态 (8-bit) | | `s_axis_s2mm_cmd` | 输出 | S2MM 命令 (72-bit) | | `m_axis_s2mm_sts` | 输入 | S2MM 状态 (32-bit) | | `m_axis_mm2s` | 输入 | MM2S stream (64-bit) | | `s_axis_s2mm` | 输出 | S2MM stream (64-bit) | --- ## 15. 参数配置 ### 15.1 stream_ctrl 参数 | 参数 | 默认值 | 描述 | |------|--------|------| | `AXI_ADDR_W` | 32 | AXI 地址宽度 | | `CMD_WIDTH` | 72 | Datamover 命令宽度 | | `STATUS_WIDTH` | 8 | MM2S 状态宽度 | | `S2MM_STATUS_WIDTH` | 32 | S2MM 状态宽度 | | `MEMORY_BLOCK_MB` | 128 | DDR 块大小 (128 或 64) | | `COMPRESS_BASE_ADDR` | 32'h4000_0000 | 压缩输出基地址 | | `STORAGE_MODE1` | 2'd1 | 模式 1 编码 | | `STORAGE_MODE2` | 2'd2 | 模式 2 编码 | | `STORAGE_MODE3` | 2'd3 | 模式 3 编码 | | `ROWS_PER_IMAGE` | 256 | 每幅图行数 | | `BYTES_PER_ROW` | 512 | 每行字节数 | | `BYTES_PER_IMAGE` | 131072 | 每幅图字节数 | ### 15.2 addr_calc 参数 | 参数 | 默认值 | 描述 | |------|--------|------| | `AXI_ADDR_W` | 32 | 地址宽度 | | `MEMORY_BLOCK_MB` | 128 | 块大小 | | `COMPRESS_BASE` | 32'h4000_0000 | 压缩基地址 | ### 15.3 bubble_removal 参数 | 参数 | 值 | 描述 | |------|-----|------| | `RAW_IMAGE_BYTES` | 131072 | 每幅图字节数 (内部 localparam) | --- ## 附录 A: 关键时序路径 ``` CMD 握手: 2 拍 (发出 + 检测) STS 握手: 1 拍 (tready 已预先拉高) 图像间隔: ~5 拍 (IMG_NEXT 收尾 + IMG_START 发 S2MM) DMA_AUX 区域间隔: 2 拍 (等待 addr_calc) PROC 区域间隔: 2 拍 (等待 addr_calc) + 空区域跳过 0 拍 ``` ## 附录 B: 文件清单 ``` new/ccsds122_datamover.sv ← 顶层集成 new/ccsds122_stream_ctrl.sv ← 主控制器 (重写) new/ccsds122_addr_calc.sv ← 地址计算器 (新建) new/ccsds122_compression_top.sv ← 压缩子系统顶层 new/ccsds122_bubble_removal_ctrl.sv ← 气泡消除 (小改) new/ccsds122_axil_slave.sv ← AXI-Lite 寄存器 uart/ccsds_uart_axi.sv ← UART + AXI 封装 uart/axi_uart_upload.sv ← UART 协议引擎 scripts/upload_compress_download.py ← PC 控制脚本 ```