行场同步信号生成、消隐区处理与时序参数化设计
视频时序控制器是视频系统的心脏,生成精确的HSYNC/VSYNC/DE信号。VGA 640x480@60Hz:H_TOTAL=800(640+16+96+48),V_TOTAL=525(480+10+2+33),像素时钟25.175MHz。1080p需要148.5MHz像素时钟。同步信号极性因分辨率而异。
| 分辨率 | 像素时钟 | H_TOTAL | V_TOTAL |
|---|---|---|---|
| 640x480@60 | 25.175MHz | 800 | 525 |
| 800x600@60 | 40.000MHz | 1056 | 628 |
| 1280x720@60 | 74.250MHz | 1650 | 750 |
| 1920x1080@60 | 148.500MHz | 2200 | 1125 |
// 第05课:视频时序生成器
module video_timing_gen #(
parameter IMG_W=640, IMG_H=480,
parameter H_FP=16, H_SYNC=96, H_BP=48,
parameter V_FP=10, V_SYNC=2, V_BP=33,
parameter H_TOTAL=IMG_W+H_FP+H_SYNC+H_BP,
parameter V_TOTAL=IMG_H+V_FP+V_SYNC+V_BP
)(
input wire clk, rst_n,
output reg hsync, vsync, de, sof,
output reg [11:0] hcnt, vcnt
);
always @(posedge clk or negedge rst_n) begin
if (!rst_n) hcnt<=0; else if (hcnt==H_TOTAL-1) hcnt<=0; else hcnt<=hcnt+1;
end
always @(posedge clk or negedge rst_n) begin
if (!rst_n) vcnt<=0;
else if (hcnt==H_TOTAL-1) begin if (vcnt==V_TOTAL-1) vcnt<=0; else vcnt<=vcnt+1; end
end
always @(posedge clk or negedge rst_n) begin
if (!rst_n) hsync<=1;
else hsync <= (hcnt>=IMG_W+H_FP && hcnt<IMG_W+H_FP+H_SYNC) ? 1'b0 : 1'b1;
end
always @(posedge clk or negedge rst_n) begin
if (!rst_n) vsync<=1;
else vsync <= (vcnt>=IMG_H+V_FP && vcnt<IMG_H+V_FP+V_SYNC) ? 1'b0 : 1'b1;
end
always @(posedge clk or negedge rst_n) begin
if (!rst_n) de<=0; else de<=(hcnt<IMG_W)&&(vcnt<IMG_H);
end
always @(posedge clk or negedge rst_n) begin
if (!rst_n) sof<=0; else sof<=(hcnt==0)&&(vcnt==0);
end
endmodule
✅Verilator验证通过 — 本课Verilog代码已通过 Verilator --lint-only 检查。
本节深入探讨视频时序生成在FPGA实现中的关键设计决策和优化策略。
视频处理模块的时序设计需要考虑以下因素:
FPGA资源有限,视频处理模块需要精心优化:
| 策略 | 适用场景 | 节省资源 |
|---|---|---|
| 时分复用乘法器 | 像素时钟远低于系统时钟 | DSP 4~8x |
| 移位替代乘法 | 系数为2的幂次 | DSP 1个/次 |
| CSD编码 | 固定系数乘法 | DSP全部 |
| 查表替代计算 | 非线性函数(sin,exp) | 逻辑大量 |
| 对称性利用 | FIR系数对称 | 乘法器减半 |
视频处理中定点运算的精度直接影响图像质量。分析方法:
8bit视频处理的经验法则:中间结果至少保留12bit,最终输出截断到8bit。
好的视频处理模块应该是参数化的:
视频模块的完整验证包括:
标准视频模块接口信号:
input wire clk, rst_n, // 时钟复位 input wire valid_in, // 输入有效 input wire [DATA_W-1:0] data_in, // 输入数据 input wire sof_in, eol_in, // 帧起始/行结束 output reg valid_out, // 输出有效 output reg [DATA_W-1:0] data_out, // 输出数据 output reg sof_out, eol_out // 帧起始/行结束
这种接口设计使模块可以自由级联,形成处理流水线。
视频处理是持续运行的,功耗优化很重要:
隔行扫描将每帧分为奇场和偶场:
场同步信号在半行处切换,这是隔行时序的标志。
DVI和HDMI本质上传输的是TMDS编码的视频时序:
| 分辨率@帧率 | H_TOTAL | V_TOTAL | 像素时钟 |
|---|---|---|---|
| 640x480@60 | 800 | 525 | 25.175 MHz |
| 1280x720@60 | 1650 | 750 | 74.250 MHz |
| 1920x1080@60 | 2200 | 1125 | 148.500 MHz |
| 3840x2160@60 | 4400 | 2250 | 594.000 MHz |
FPGA需要PLL生成精确的像素时钟。以Xilinx MMCM为例:
// 100MHz输入 -> 148.5MHz像素时钟
MMCM_BASE #(
.CLKIN_PERIOD (10.0),
.CLKFBOUT_MULT_F(14.85),
.CLKOUT0_DIVIDE_F(10.0)
) mmcm_inst (
.CLKIN(clk_100m),
.CLKOUT0(clk_148m5),
...
);
| 术语 | 英文 | 说明 |
|---|---|---|
| 像素 | Pixel | 图像最小单元 |
| 帧 | Frame | 一帧完整图像 |
| 场 | Field | 隔行扫描的半帧 |
| 消隐 | Blanking | 非有效视频区域 |
| 流水线 | Pipeline | 多级并行处理架构 |
| 定点数 | Fixed-point | 有限精度数值表示 |
| 饱和截断 | Saturation | 超出范围钳位到边界 |
| 行缓冲 | Line Buffer | 缓存一行像素的存储器 |
| 帧缓冲 | Frame Buffer | 缓存一帧图像的存储器 |
| 时序 | Timing | 视频同步信号参数 |
| 错误现象 | 可能原因 | 解决方法 |
|---|---|---|
| 输出全零 | 复位未释放或valid未传播 | 检查rst_n和valid链 |
| 色彩偏移 | 系数位宽不足或溢出 | 增加中间结果位宽 |
| 行间错位 | 行缓冲地址不对齐 | 检查写地址和读地址 |
| 画面闪烁 | 时序违例或跨时钟域 | 添加同步器或约束 |
| 边缘伪影 | 边界处理不正确 | 添加边界检测和钳位 |
| 资源 | 估计使用量 | 说明 |
|---|---|---|
| LUT | 100~500 | 加法器、比较器、选择器 |
| FF | 50~200 | 流水线寄存器、状态机 |
| DSP | 0~9 | 乘法器(色彩转换9个) |
| BRAM(18K) | 0~6 | 行缓冲(2~4行)、帧缓冲、LUT |
| 延迟 | 2~5 cycles | 流水线级数 |
# 语法检查
verilator --lint-only verilog/lesson_05.v
# 带波形仿真(需要testbench)
verilator --trace --cc verilog/lesson_05.v --exe tb.cpp
make -C obj_dir -f Vlesson_05.mk
./obj_dir/Vlesson_05