接第三阶段,上次说道要将cnn这个模块接入到高云自带的视频实例里面,于是就开始学习和了解这个实例里面的每个模块的功能,后来发现,除了要看一下高云自己的ip文档外,还要看很多视频处理相关的协议文档,比如下面的这些,仅作参考?
*附件:DP-1.1a.pdf*附件:DVI-1.0.pdf*附件:Hdmi-1.4-Latest Publications.pdf*附件:High-Definition Multimedia Interface.pdf
等等吧
当然还有这些:

因为我是按照顺序去看这个实例的每个文件的,所以今天就看到了这个lvds相关的文件,其实就是在看hdmi的时候,要了解这个lvds文件,所以就逐渐清楚怎么完成这个拼图了?
后面还有详细看这几个文件,如图所示:

为什么呢?因为现在逐渐清晰了?
这个LVDS模块是负责视频信号输出的吗?
是的,几乎可以肯定,这个模块是负责将并行视频数据转换为高速串行LVDS信号并输出的。
wire VCC;
wire GND;
OVIDEO \ovideo_gen[0].ovideo_inst (
.Q(q[0]),
.D6(din[6]),
.D5(din[5]),
.D4(din[4]),
.D3(din[3]),
.D2(din[2]),
.D1(din[1]),
.D0(din[0]),
.PCLK(pclk),
.FCLK(fclk),
.RESET(reset)
);
-
模块名 ddio_lvds :
- ddio 通常是 Double Data Rate Input/Output 的缩写,意为双倍数据速率IO。这是实现高速串行输出的基础。
- lvds 是 Low-Voltage Differential Signaling(低压差分信号)的缩写,是一种非常常见的高速、低功耗、抗干扰能力强的物理层接口,广泛用于视频传输(如连接液晶屏、摄像头)。
-
核心元件 OVIDEO:
- 这个名字很可能代表 Output Video 或者 Output Video Serializer。
- 这是一个专用的硬件原语(Primitive),很可能是FPGA厂商(如Gowin, Xilinx, Altera等)提供的,用于实现高速串行化。你无法看到它的内部代码,因为它直接映射到FPGA芯片内部的专用硬件电路上。
-
信号功能分析:
- din [6:0] (Input): 这是7位的并行数据输入**。在视频应用中,这通常代表一个像素的一个颜色分量(如R/G/B中的一个),或者是某种编码后的视频数据。**
- pclk (Input): 并行时钟 (Parallel Clock)。这是 din 数据输入所同步的时钟,也叫像素时钟。例如,一个60Hz的1080p视频,其pclk大约是148.5MHz。
- fclk (Input): 快速时钟 (Fast Clock) 或 串行时钟 (Serial Clock)。这是一个比pclk快很多的时钟,用于驱动串行化过程。在典型的7:1串行化(将7位并行数据转为1位串行数据)中,fclk 的频率是 pclk 的7倍。
- reset (Input): 复位信号。
- q [0:0] (Output): 串行数据输出。经过OVIDEO原语处理后,7位的并行数据din被转换成了1位的高速串行数据流,从这里输出。这个q引脚最终会连接到FPGA的物理IO引脚上,形成LVDS差分对的一端。
结论:这个模块是一个7:1的视频数据串行器,它接收低速的并行视频数据,并将其转换为高速的LVDS串行信号进行输出。它通常是视频输出接口(如连接屏幕)的物理层驱动模块。
这里接上一个CNN模块在逻辑上行得通吗?
绝对行得通!这是一个非常合理且常见的应用场景。
将CNN模块和这个LVDS输出模块连接起来,就构成了一个典型的“AI视频处理与显示系统”。
1. 逻辑可行性分析
整个系统的数据流会是这样的:
[视频源] -> [FPGA输入接口] -> [CNN模块] -> [LVDS输出模块] -> [显示设备]
这个逻辑流程非常通顺,完全可行。FPGA的并行计算能力非常适合实时处理视频流,而CNN是处理图像/视频的利器。
下面是伪代码:
wire video_in_pclk;
wire video_in_vsync;
wire video_in_href;
wire [23:0] video_in_rgb;
wire cnn_out_pclk;
wire cnn_out_vsync;
wire cnn_out_href;
wire [23:0] cnn_out_rgb;
wire lvds_fclk;
wire lvds_reset;
wire [6:0] lvds_din_r;
wire [6:0] lvds_din_g;
wire [6:0] lvds_din_b;
wire lvds_q_r;
wire lvds_q_g;
wire lvds_q_b;
pll_module u_pll (
.clk_in(sys_clk),
.clk_cnn(cnn_pclk),
.clk_lvds_p(lvds_pclk),
.clk_lvds_f(lvds_fclk)
);
cnn_accelerator u_cnn (
.clk(cnn_pclk),
.reset(reset),
.din_vsync(video_in_vsync),
.din_href(video_in_href),
.din_rgb(video_in_rgb),
.dout_vsync(cnn_out_vsync),
.dout_href(cnn_out_href),
.dout_rgb(cnn_out_rgb)
);
assign lvds_din_r = cnn_out_rgb[23:17];
assign lvds_din_g = cnn_out_rgb[15:9];
assign lvds_din_b = cnn_out_rgb[7:1];
ddio_lvds lvds_red_inst (
.din(lvds_din_r),
.fclk(lvds_fclk),
.pclk(lvds_pclk),
.reset(reset),
.q(lvds_q_r)
);
ddio_lvds lvds_green_inst (
.din(lvds_din_g),
.fclk(lvds_fclk),
.pclk(lvds_pclk),
.reset(reset),
.q(lvds_q_g)
);
ddio_lvds lvds_blue_inst (
.din(lvds_din_b),
.fclk(lvds_fclk),
.pclk(lvds_pclk),
.reset(reset),
.q(lvds_q_b)
);
那么上面说的 MIPI CSI-2接收模块可以用这个实现吗?
module MIPI_CSI2_SOFT (
I_RSTN,
I_BYTE_CLK,
I_REF_DT,
I_READY,
I_DATA0,
O_SP_EN,
O_LP_EN,
O_LP_AV_EN,
O_ECC_OK,
O_ECC,
O_WC,
O_VC,
O_DT,
O_PAYLOAD,
O_PAYLOAD_DV
)
;
input I_RSTN;
input I_BYTE_CLK;
input [5:0] I_REF_DT;
input I_READY;
input [7:0] I_DATA0;
output O_SP_EN;
output O_LP_EN;
output O_LP_AV_EN;
output O_ECC_OK;
output [7:0] O_ECC;
output [15:0] O_WC;
output [1:0] O_VC;
output [5:0] O_DT;
output [7:0] O_PAYLOAD;
output [0:0] O_PAYLOAD_DV;
wire VCC;
wire GND;
\~DSI_CSI2_RX.MIPI_CSI2_SOFT u_dsi_csi2 (
.I_BYTE_CLK(I_BYTE_CLK),
.I_READY(I_READY),
.I_RSTN(I_RSTN),
.I_DATA0(I_DATA0[7:0]),
.I_REF_DT(I_REF_DT[5:0]),
.O_LP_AV_EN(O_LP_AV_EN),
.O_SP_EN(O_SP_EN),
.O_LP_EN(O_LP_EN),
.O_ECC_OK(O_ECC_OK),
.O_PAYLOAD_DV(O_PAYLOAD_DV[0]),
.O_PAYLOAD(O_PAYLOAD[7:0]),
.O_ECC(O_ECC[7:0]),
.O_WC(O_WC[15:0]),
.O_VC(O_VC[1:0]),
.O_DT(O_DT[5:0])
);
VCC VCC_cZ (
.V(VCC)
);
GND GND_cZ (
.G(GND)
);
GSR GSR (
.GSRI(VCC)
);
endmodule
这个模块 MIPI_CSI2_SOFT 是一个MIPI CSI-2协议解码器(Protocol Decoder)。
它的核心功能是接收来自物理层(PHY)的、已经解串(Deserialized)后的字节流,并根据CSI-2协议规范,解析出数据包的各个组成部分。
我们来看它的输入和输出信号,就能清晰地理解其功能:
输入信号分析:
- I_BYTE_CLK: 字节时钟 (Byte Clock)。这是从物理层恢复出的时钟,每个时钟周期对应一个字节的数据。它的频率通常是 MIPI D-PHY 通道速率的1/8。
- I_DATA0: 8位并行数据 (Parallel Data)。这是从高速串行差分信号解串后得到的8位数据流。这是最核心的数据输入。
- I_RSTN: 复位信号。
- I_READY: PHY就绪信号。当物理层完成初始化并准备好输出稳定数据时,这个信号会拉高。
- I_REF_DT: 参考数据类型 (Reference Data Type)。这个信号可能用于配置模块,告诉它要特别关注或过滤哪种类型的数据包。
输出信号分析:
这些输出完美地对应了MIPI CSI-2协议中定义的数据包结构。
它在整个MIPI CSI-2接收链路中的位置
一个完整的MIPI CSI-2接收器通常包含两个主要部分:物理层(PHY)和协议层(Controller)。
[摄像头] -> [MIPI D-PHY (物理层)] -> [MIPI CSI-2 Controller (协议层)] -> [后续处理逻辑]
所以,要实现一个完整的MIPI CSI-2接收模块,你需要:
例化一个D-PHY硬核IP,并将其输出连接到你这个 MIPI_CSI2_SOFT 模块的输入上。
如何与CNN模块连接?
现在我们拥有了完整的输入链路,可以将其与CNN模块连接起来了。
[摄像头] -> [D-PHY] -> [MIPI_CSI2_SOFT] -> [像素重组/格式转换] -> [CNN模块]
wire byte_clk;
wire [7:0] data0;
wire phy_ready;
wire [5:0] packet_dt;
wire [7:0] payload_data;
wire payload_dv;
wire cnn_pclk;
wire cnn_vsync;
wire cnn_href;
wire [7:0] cnn_din;
MIPI_DPHY_RX_IP u_dphy (
.clk_hs(camera_clk_p, camera_clk_n),
.data_hs(camera_data_p, camera_data_n),
.byte_clk(byte_clk),
.data_out(data0),
.phy_ready(phy_ready)
);
MIPI_CSI2_SOFT u_csi2_decoder (
.I_RSTN(rstn),
.I_BYTE_CLK(byte_clk),
.I_READY(phy_ready),
.I_DATA0(data0),
.O_DT(packet_dt),
.O_PAYLOAD(payload_data),
.O_PAYLOAD_DV(payload_dv),
);
Pixel_Reconstructor u_pixel_reconstructor (
.clk(byte_clk),
.rstn(rstn),
.packet_dt(packet_dt),
.payload_data(payload_data),
.payload_dv(payload_dv),
.pclk(cnn_pclk),
.vsync(cnn_vsync),
.href(cnn_href),
.pixel_data(cnn_din)
);
cnn_accelerator u_cnn (
.clk(cnn_pclk),
.reset(~rstn),
.din_vsync(cnn_vsync),
.din_href(cnn_href),
.din_pixel(cnn_din),
);
所以:需要编写的 Pixel_Reconstructor 模块的功能:
总之,在后续的实践中,将继续加深对mipi相关模块的理解,并尝试完成这个模块直接的拼接。最后附上一个文件,如果有需要,可以自行取悦:
*附件:02-2_SC2210_DDR3_LVDS_1024600.xlsx