= 系统组成及功能说明

== 整体介绍

根据设计，本组绘制了如下系统框图，并将在之后根据框图进行各部分的详细讲解：

#figure(
  image("../images/SystemDiagram_Colord.svg",width: 18cm),
  caption: "总体系统框图"
)<系统框图>

可能乍一看这个系统框图会显得比较庞大、难以分辨每一部分，但其实每个部分的功能相当清晰和明确。在接下来的整体说明当中，我将整体介绍使用到的外设和作用。

=== 框图一览

根据如上 @系统框图 ,可以较好地看到我们的系统主要依托FPGA芯片和几个基本的片外外设——其中，外设在框图中的位置为 _FPGA板卡内资源_ 的大框 之外的四个小框，即为：

#figure(
  table(
    columns: (auto,auto,auto,auto,auto),
    [*片外外设名称*],[外部按键输入],[摄像头OV5640],[DRAM芯片],[RTL8201F 百兆网芯片],
    [*片内模块对应*],[模式切换],[CMOS摄像头模块],[DDR存储模块],[UDP顶层模块],
    [*外设实现功能*],[使用 *单按键* 对于模式进行切换],[配置外部摄像头/转存摄像头捕获数据],[使用DRAM生成视频缓存],[配置以太网向上位机发送],
    [*代码中模块名称*],[module_shift],[cmos_8_16bit#linebreak()和i2c_config],[DDR3_Memory\_#linebreak()Interface_Top_inst],[udp_top],
  ),
  caption: "片外外设和对应接口模块一览"
)<外设一览表>

==== 主要外设

根据@外设一览表 所示， 面对各个外设、FPGA板卡主要完成的任务大略如下：

+ *外部按键输入*:通过常用的按键滤波、消抖操作，实现使用单键切换状态、及时进入下一状态的操作。
+ *摄像头OV5640*： 本次我们使用CMOS芯片 _OV5640_ 作为采集视频信号的摄像头芯片，其拥有SCCB接口和DVP接口提供配置和数据传输。
+ *DRAM芯片*： 本次使用的底板中，拥有一块DDR3的DRAM，结合高云提供的 _Video_Frame_Buffer_ 软核，构建一个含有3帧的视频缓存。使用近似于VGA标准的同步信号进行数据的传输，用于接收并行视频输入数据，然后缓存至存储器，并同时输出并行视频数据，从而实现帧缓存的功能。@gowin_2023_gowin
+ *RTL8201F*： 使用底板提供的 _RTL8201F_ 百兆以太网芯片，用于实现物理层的接口转换和信号调理。它支持10/100M自适应以太网速率，并具备自动协商功能，能够根据连接的设备自动选择最佳的速率。该芯片通过提供标准的MII（介质独立接口）和RMII（简化的介质独立接口）接口，与主控芯片（如单片机）进行通信。@_2023_phyrtl8201fcsdn\

==== 外设实物图

综合本次外设和实际应用情况，我们在这里给出实物图、并标注了如上四个外设所在的位置如 ：@主要功能外设标注

#figure(
  image("../images/BOARD_LOOKING_DOWN_Writed.png",width: 18cm,),
  caption: "主要功能外设标注"
)<主要功能外设标注>

=== 内部模块

由于熟练使用外设即可完成大部分基础功能，内部模块的撰写主要作用为： *增强* 和 *融合*。

在连接部分当中，一般情况下，多为外部外设/软核的输出的位宽不一致、因此会采取FIFO等方式、重新设计数据位宽度、让生成与等待异步的数据能够被较好地放入另一个时钟当中。因此、这一部分由于出现在两个外设支持模块相互连接的地方、故被不再被单独列出。

而在增强部分中，我们主要只考虑 *视频处理模块*：在这一部分中，我们会进行需要进行的工作，完成如 @VIP模块功能 所示的全部功能，
#figure(
  table(columns:(auto,auto,auto,auto),
  [*功能名称*],[灰度处理],[二值化],[边缘检测]),
  caption: "视频处理模块功能"
)<VIP模块功能>

==== 视频上位机模块

为实现功能，我们构建了如@上位机 所示的上位机模块：

#figure(
  image("../images/上位机.png",height: 8cm),
  caption: "MOS法师上位机软件"
)<上位机>

在这个上位机中，能够通过较为简单地调节左侧的各项设置进行接收模式的修改，
同时在软件的下方，也具有较为简洁明了的帧率指示、分辨率指示。

上位机使用的接收UDP数据格式为：

+ *帧头*：如果该次发送为首次发送，则会十六进制发送`0xf05aa50f`四个字节,进行表示：这个UDP报文为需要被上位机解析的报文。而上位机也会继续解析余下这一帧的全部报文。
+ *分辨率信息*：如果该次发送为首次发送，则会接着帧头按照16进制转换发送分辨率信息$640 times 480$,表示本帧的分辨率。
+ *帧内容*：以太网会按照行内容发送帧内容，每行的长度为 $640$ 个标准 RGB5-6-5的数据。

因此，如果是首行，则会发送长度为：1288的数据，如果是后续的`479`行，则会发送数据长度为1280的数据、因为少了一个分辨率的信息。可以使用`Wireshark` 软件进行以太帧的捕获，UDP报文情况详见@以太网抓帧：

#figure(
  image("../images/UDP_Wiresharked.png",width: 15cm),
  caption: "以太网抓帧UDP报文表"
)<以太网抓帧>

== 各模块介绍

=== UDP模块


udp_top模块是一个多功能的数字系统，涵盖了时钟管理、数据缓冲和以太网通信功能。

首先我们来看它的物理接口：在以太网芯片当中，用以连接以太网MAC层和PHY芯片的常用接口有：MII、RMII、SMII、GMII、RGMII。@_19

在本次UDP的实验当中、我们使用的芯片 _RTL8201F_ 使用的是以太网当中的RMII接口， @RMII物理接口示意 为 RMII 接口连接示意图。

#figure(
  image("../images/RMII_PHY.png",width:6.9cm),
  caption: "RMII物理接口示意"
)<RMII物理接口示意>

可以从 @RMII物理接口示意 当中看出，RMII 只需 7 根通信，在功能上却能够与MII是相同的。因此，我们构建如下的硬件框图结构@UDP模块框图 让RMII能够发送UDP报文：

#figure(
  image("../images/STATE.png"),
  caption: "UDP模块框图"
)<UDP模块框图>

可以看到，RMII模块的主要工作有两个：

+ *控制UDP通信：* 其中，通信的UDP部分使用RMII转GMII的模块进行完成——原因在于GMII拥有8条并行数据线，而RMII只有两条。使用GMII数据线转RMII可以有效地减少发送需要的时钟周期，在PLL时钟较低的同时就能够达到较高的发送速率。
+ *管理RMII状态*： 向其他上游逻辑模块，如控制FIFO的状态机@UDP模块状态转移图 进行状态汇报，管理状态。

#figure(
  image("../images/UDP_STATE.png",width: 9cm),
  caption: "UDP模块状态转移图"
)<UDP模块状态转移图>

在状态转移中可以看到，在发送时，主要在`数据发送`状态会从FIFO当中获取来自IP核缓存的以太网信息。

- 而在 *头一帧* 当中，则会在几个状态之中，发送此帧需要的各种帧头信息。
- 在其他帧当中，则会在等待时钟对齐之后，直接将数据发送到UDP模块当中。

_注意：_ 进入到Idle状态的条件为：当从RMII模块传回的信息表示RMII不忙碌时。

=== CMOS图像收集模块

在CMOS模块当中，我们使用OV5640作为CMOS，其上有两种总线接口，作用如下：

- *SCCB接口* ：时序上和 $I^2 C$接口一致，作用为配置 _OV5640_ 芯片的相关功能即向摄像头寄存器写入对应指令。由于需要配置较多寄存器，对于OV5640摄像头具体配置信息，这里不再列举，具体的有，比如：修改输出图像的格式、画幅等。
- *DVP接口* ： DVP（Digital Video Port）是非差分信号的并口传输，在本次实验当中、数据位为有8bit，是。在配置寄存器之后，按照较为标准的VGA时序等进行发送、并使用同步信号等判断是否已经接收完成一帧。@_2020_cmos

#figure(
  image("../images/cmos_i2c.svg",width: 12cm),
  caption: "CMOS配置和数据传输框图"
)<CMOS配置和数据传输框图>

由于这里DVP使用的位宽为硬件限制的8位，而如果使用高云的硬核作为视频缓存Buffer，则至少需要使用16bit的数据位宽。因此需要使用 *数据位转换* 模块让数据能够进入缓存。


=== 图像存储/数据流转移模块

#figure(
  image("../images/Memory_IP.svg",width: 7cm),
  caption: "存储模块系统框图"
)<存储模块系统框图>

输入行缓存控制电路接收并行视频输入数据，然后缓存到输入 FIFO 行
缓存中。当 FIFO 中数据存储到预先设定的阈值时，就向仲裁控制器发出写
请求。当仲裁控制器响应请求，给与存储器控制权，则开始发送写数据，地
址和命令。@gowin_2023_gowin

=== 图像处理模块

#figure(
  image("../images/vip.svg",height: 8cm),
  caption:"图像数据处理模块"
)<图像数据处理模块>

==== 二值化部分

*图像二值化* 是将像素点的灰度值设为最大（白色）或最小（黑色），以显示明显的黑白效果。以8bit灰度图像为例，二值化通过选取阈值将亮度高于阈值的像素点设为白色（255），低于阈值的设为黑色（0），突出图像的特征。@_2020_fpgaov5640

二值化的实现方法有两种：手动指定阈值和自适应阈值（如OTSU算法）。手动方法计算量小，速度快但适用性有限；自适应方法适用性强，能清晰显示图像轮廓，但计算更复杂。 *本作品采用手动阈值方法* ，适用于特定物体与背景灰度差异显著的情况。

在本次作品当中，我们使用OV5640摄像头采集RGB565数据，转化为Ycbcr格式后进行二值化。

其模块连接如@VIP内部连接图 所示：

#figure(
  image("../images/IN_VIP.png",width: 12cm),
  caption: "VIP内部连接图"
)<VIP内部连接图>

在对于二值化图像的发送中，并没有刻意对图像进行压缩，这也降低了误码对于发送的影响。虽然同时也较为浪费带宽。

==== 边缘检测部分

在边缘检测部分，主要依托于二值化打下的二值化图像的基础进行处理，根据连接图 @VIP内部连接图 可以看出，在二值化后，图像会先进入一个中值滤波，随后进入SOBEL边缘检测算法模块，进行边缘检测的计算。

SOBEL算法的实现可见@SOBEL ，中值滤波的实现可见 。这里放入附录当中。


=== 模式切换模块

在模式切换模块当中，我们主要使用按键信号作为状态信号切换的标志，其实现也较为简单，只要通过对于下降沿的检测、简单滤波，判断是否释放即可实现。

在状态切换之后，直接输出选择需要输出的信号即可。

#figure(
  image("../images/module_shift.svg",width: 12cm),
  caption: "模式切换模块框图"
)<模式切换模块框图>

