├── RTL
├── eth_trans.v
├── fpga_top.v
├── reg_config_1.v
├── rtl
│ ├── fram_buf.v
│ ├── iic_dri.v
│ ├── sync_vg.v
│ ├── reg_config.v
│ ├── cmos_8_16bit.v
│ ├── wr_rd_ctrl_top.v
│ ├── power_on_delay.v
│ ├── i2c_com.v
│ ├── rd_ctrl.v
│ ├── wr_ctrl.v
│ ├── rd_buf.v
│ ├── ms72xx_ctl.v
│ ├── wr_buf.v
│ └── wr_cmd_trans.v
├── tx
│ ├── mac_tx_top.v
│ ├── mac_tx_mode.v
│ ├── ip_tx_mode.v
│ ├── mac_tx.v
│ ├── udp_tx.v
│ ├── arp_tx.v
│ └── ip_tx.v
├── main.filelist
├── mac
│ ├── dpram.v
│ ├── arp_cache.v
│ ├── crc.v
│ ├── mac_top.v
│ └── mac_test.v
├── new
│ ├── camera_delay.v
│ └── mac
│ │ └── crc.v
├── rx
│ ├── mac_rx_top.v
│ ├── arp_rx.v
│ ├── ip_rx.v
│ └── udp_rx.v
└── src
│ └── util_gmii_to_rgmii.v
├── document
├── pic
│ ├── 图片1.png
│ ├── 图片2.png
│ ├── 屏幕截图 2023-08-03 162036.png
│ ├── 屏幕截图 2023-08-09 164303.png
│ ├── 屏幕截图 2023-08-09 165537.png
│ ├── 屏幕截图 2023-08-09 165720.png
│ └── 屏幕截图 2023-08-09 170151.png
└── constraint.md
├── FPGA
└── bitstream_backup
│ ├── 600p.sbit
│ ├── 720p.sbit
│ └── default.sbit
├── software
├── model
│ └── convert_tflite.py
├── udp_video.py
├── obj_detect_multi_thread.py
└── obj_detect_single_thread.py
├── .gitignore
├── readme.md
└── dataset
└── process.py
/RTL/eth_trans.v:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MongooseOrion/FPGA-Image-Recognition/HEAD/RTL/eth_trans.v
--------------------------------------------------------------------------------
/RTL/fpga_top.v:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MongooseOrion/FPGA-Image-Recognition/HEAD/RTL/fpga_top.v
--------------------------------------------------------------------------------
/RTL/reg_config_1.v:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MongooseOrion/FPGA-Image-Recognition/HEAD/RTL/reg_config_1.v
--------------------------------------------------------------------------------
/RTL/rtl/fram_buf.v:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MongooseOrion/FPGA-Image-Recognition/HEAD/RTL/rtl/fram_buf.v
--------------------------------------------------------------------------------
/RTL/rtl/iic_dri.v:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MongooseOrion/FPGA-Image-Recognition/HEAD/RTL/rtl/iic_dri.v
--------------------------------------------------------------------------------
/RTL/rtl/sync_vg.v:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MongooseOrion/FPGA-Image-Recognition/HEAD/RTL/rtl/sync_vg.v
--------------------------------------------------------------------------------
/RTL/rtl/reg_config.v:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MongooseOrion/FPGA-Image-Recognition/HEAD/RTL/rtl/reg_config.v
--------------------------------------------------------------------------------
/RTL/tx/mac_tx_top.v:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MongooseOrion/FPGA-Image-Recognition/HEAD/RTL/tx/mac_tx_top.v
--------------------------------------------------------------------------------
/document/pic/图片1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MongooseOrion/FPGA-Image-Recognition/HEAD/document/pic/图片1.png
--------------------------------------------------------------------------------
/document/pic/图片2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MongooseOrion/FPGA-Image-Recognition/HEAD/document/pic/图片2.png
--------------------------------------------------------------------------------
/RTL/rtl/cmos_8_16bit.v:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MongooseOrion/FPGA-Image-Recognition/HEAD/RTL/rtl/cmos_8_16bit.v
--------------------------------------------------------------------------------
/document/constraint.md:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MongooseOrion/FPGA-Image-Recognition/HEAD/document/constraint.md
--------------------------------------------------------------------------------
/RTL/rtl/wr_rd_ctrl_top.v:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MongooseOrion/FPGA-Image-Recognition/HEAD/RTL/rtl/wr_rd_ctrl_top.v
--------------------------------------------------------------------------------
/FPGA/bitstream_backup/600p.sbit:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MongooseOrion/FPGA-Image-Recognition/HEAD/FPGA/bitstream_backup/600p.sbit
--------------------------------------------------------------------------------
/FPGA/bitstream_backup/720p.sbit:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MongooseOrion/FPGA-Image-Recognition/HEAD/FPGA/bitstream_backup/720p.sbit
--------------------------------------------------------------------------------
/FPGA/bitstream_backup/default.sbit:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MongooseOrion/FPGA-Image-Recognition/HEAD/FPGA/bitstream_backup/default.sbit
--------------------------------------------------------------------------------
/document/pic/屏幕截图 2023-08-03 162036.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MongooseOrion/FPGA-Image-Recognition/HEAD/document/pic/屏幕截图 2023-08-03 162036.png
--------------------------------------------------------------------------------
/document/pic/屏幕截图 2023-08-09 164303.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MongooseOrion/FPGA-Image-Recognition/HEAD/document/pic/屏幕截图 2023-08-09 164303.png
--------------------------------------------------------------------------------
/document/pic/屏幕截图 2023-08-09 165537.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MongooseOrion/FPGA-Image-Recognition/HEAD/document/pic/屏幕截图 2023-08-09 165537.png
--------------------------------------------------------------------------------
/document/pic/屏幕截图 2023-08-09 165720.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MongooseOrion/FPGA-Image-Recognition/HEAD/document/pic/屏幕截图 2023-08-09 165720.png
--------------------------------------------------------------------------------
/document/pic/屏幕截图 2023-08-09 170151.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MongooseOrion/FPGA-Image-Recognition/HEAD/document/pic/屏幕截图 2023-08-09 170151.png
--------------------------------------------------------------------------------
/software/model/convert_tflite.py:
--------------------------------------------------------------------------------
1 | import tensorflow as tf
2 |
3 | # 加载模型
4 | model = tf.keras.models.load_model('C:\\Users\\smn90\\repo\\FPGA-Image-Recognition\\software\\model\\tiny_yolo_weights.h5')
5 |
6 | # 转换为 TFLite 模型
7 | converter = tf.lite.TFLiteConverter.from_keras_model(model)
8 | tflite_model = converter.convert()
9 |
10 | # 保存为 TFLite 文件
11 | with open('tiny_yolo_model.tflite', 'wb') as f:
12 | f.write(tflite_model)
13 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | ## 用于 vivado 应用程序的 .gitignore 文件
2 | ## 根据一般的工程规范,HDL 项目文件夹应当按如下命名规则:
3 | ##
4 | ## doc 用于放置设计说明、系统框图、设计思路等文件
5 | ## ip 用于放置 ip 核文件
6 | ## prj/par 用于工程创建的路径
7 | ## rtl/src 用于存放源文件
8 | ## sim/tb 用于存放仿真文件
9 | ## vivado 用于存放所有由 vivado 程序创建的文件(如果有,上述第 2,3,4,5 将自动由程序存入)
10 | ##
11 | ## 根目录不需要的文件
12 | *.jou
13 | *.log
14 | *.zip
15 | *.xml
16 | *.h5
17 | *.weights
18 |
19 | ## 隐藏文件夹
20 | **/.Xil
21 | **/.jobs
22 | /project.old
23 |
24 | /dataset/*
25 | /software/keil
26 | !/dataset/process.py
27 | !/dataset/categary.txt
28 | !/dataset/train_main.txt
29 | !/dataset/train_raw.txt
30 | /RTL/filelist.py
31 |
32 | /document/ip_settings.md
--------------------------------------------------------------------------------
/RTL/main.filelist:
--------------------------------------------------------------------------------
1 | // 主系统请按照如下的文件名对应加入 FPGA 开发工具链中
2 | //
3 |
4 | eth_trans.v
5 | fpga_top.v
6 | reg_config_1.v
7 | arp_cache.v
8 | crc.v
9 | dpram.v
10 | icmp_reply.v
11 | mac_test.v
12 | mac_top.v
13 | camera_delay.v
14 | crc.v
15 | cmos_8_16bit.v
16 | fram_buf.v
17 | i2c_com.v
18 | iic_dri.v
19 | ms7200_ctl.v
20 | ms7210_ctl.v
21 | ms72xx_ctl.v
22 | power_on_delay.v
23 | rd_buf.v
24 | rd_ctrl.v
25 | reg_config.v
26 | sync_vg.v
27 | wr_buf.v
28 | wr_cmd_trans.v
29 | wr_ctrl.v
30 | wr_rd_ctrl_top.v
31 | arp_rx.v
32 | ip_rx.v
33 | mac_rx.v
34 | mac_rx_top.v
35 | udp_rx.v
36 | util_gmii_to_rgmii.v
37 | arp_tx.v
38 | ip_tx.v
39 | ip_tx_mode.v
40 | mac_tx.v
41 | mac_tx_mode.v
42 | mac_tx_top.v
43 | udp_tx.v
44 |
--------------------------------------------------------------------------------
/RTL/mac/dpram.v:
--------------------------------------------------------------------------------
1 | module dpram
2 | #(
3 | parameter WIDTH = 8,
4 | parameter DEPTH = 10
5 | )
6 | ( input clock,
7 | input [WIDTH-1:0] data,
8 | input [DEPTH-1:0] wraddress,
9 | input [DEPTH-1:0] rdaddress,
10 | input wren,
11 | output [WIDTH-1:0] q
12 | );
13 |
14 | reg [WIDTH-1:0] ram[2**DEPTH-1:0]; //declare ram
15 | reg [DEPTH-1:0] raddr_reg ;
16 |
17 | always @ (posedge clock)
18 | begin
19 | if (wren) //write
20 | ram[wraddress] <= data;
21 | raddr_reg <= rdaddress ;
22 | end
23 |
24 | assign q = ram[raddr_reg] ;
25 |
26 | endmodule
27 |
--------------------------------------------------------------------------------
/RTL/new/camera_delay.v:
--------------------------------------------------------------------------------
1 | module camera_delay
2 | (
3 | input cmos_pclk, //cmos pxiel clock
4 | input cmos_href, //cmos hsync refrence
5 | input cmos_vsync, //cmos vsync
6 | input [7:0] cmos_data, //cmos data
7 |
8 | output cmos_href_delay, //cmos hsync refrence
9 | output cmos_vsync_delay, //cmos vsync
10 | output [7:0] cmos_data_delay //cmos data
11 | ) ;
12 |
13 | reg [2:0] cmos_href_buf ;
14 | reg [2:0] cmos_vsync_buf ;
15 | reg [7:0] cmos_data_d0 ;
16 | reg [7:0] cmos_data_d1 ;
17 | reg [7:0] cmos_data_d2 ;
18 |
19 |
20 | always @(posedge cmos_pclk)
21 | begin
22 | cmos_href_buf <= {cmos_href_buf[1:0], cmos_href} ;
23 | end
24 |
25 | always @(posedge cmos_pclk)
26 | begin
27 | cmos_vsync_buf <= {cmos_vsync_buf[1:0], cmos_vsync} ;
28 | end
29 |
30 | always @(posedge cmos_pclk)
31 | begin
32 | cmos_data_d0 <= cmos_data ;
33 | cmos_data_d1 <= cmos_data_d0 ;
34 | cmos_data_d2 <= cmos_data_d1 ;
35 | end
36 |
37 | assign cmos_href_delay = cmos_href_buf[2] ;
38 | assign cmos_vsync_delay = cmos_vsync_buf[2] ;
39 | assign cmos_data_delay = cmos_data_d2 ;
40 |
41 |
42 |
43 | endmodule
44 |
--------------------------------------------------------------------------------
/RTL/mac/arp_cache.v:
--------------------------------------------------------------------------------
1 | module arp_cache
2 | (
3 | input clk ,
4 | input rst_n ,
5 |
6 | input arp_found,
7 | input [31:0] arp_rec_source_ip_addr,
8 | input [47:0] arp_rec_source_mac_addr,
9 |
10 | input [31:0] destination_ip_addr,
11 | output reg [47:0] destination_mac_addr,
12 |
13 | output reg mac_not_exist
14 | ) ;
15 |
16 | reg [79:0] arp_cache ;
17 |
18 | //init arp cache
19 | always @(posedge clk or negedge rst_n)
20 | begin
21 | if (~rst_n)
22 | arp_cache <= 80'h00_00_00_00_ff_ff_ff_ff_ff_ff ;
23 | else if (arp_found)
24 | arp_cache <= {arp_rec_source_ip_addr, arp_rec_source_mac_addr} ;
25 | else
26 | arp_cache <= arp_cache ;
27 | end
28 |
29 | always @(posedge clk or negedge rst_n)
30 | begin
31 | if (~rst_n)
32 | destination_mac_addr <= 48'hff_ff_ff_ff_ff_ff ;
33 | else if (destination_ip_addr == arp_cache[79:48])
34 | destination_mac_addr <= arp_cache[47:0] ;
35 | else
36 | destination_mac_addr <= 48'hff_ff_ff_ff_ff_ff ;
37 | end
38 |
39 | always @(posedge clk or negedge rst_n)
40 | begin
41 | if (~rst_n)
42 | mac_not_exist <= 1'b0 ;
43 | else if (destination_ip_addr != arp_cache[79:48])
44 | mac_not_exist <= 1'b1 ;
45 | else if (destination_ip_addr == arp_cache[79:48] && arp_cache[47:0] == 48'hff_ff_ff_ff_ff_ff)
46 | mac_not_exist <= 1'b1 ;
47 | else
48 | mac_not_exist <= 1'b0 ;
49 | end
50 |
51 | endmodule
52 |
--------------------------------------------------------------------------------
/RTL/rtl/power_on_delay.v:
--------------------------------------------------------------------------------
1 | `timescale 1ns / 1ps
2 | //////////////////////////////////////////////////////////////////////////////////
3 | // Company:Meyesemi
4 | // Engineer: Will
5 | //
6 | // Create Date: 2023-03-17
7 | // Design Name:
8 | // Module Name:
9 | // Project Name:
10 | // Target Devices: Pango
11 | // Tool Versions:
12 | // Description:
13 | //
14 | // Dependencies:
15 | //
16 | // Revision:
17 | // Revision 1.0 - File Created
18 | // Additional Comments:
19 | //
20 | //////////////////////////////////////////////////////////////////////////////////
21 | //camera power on timing requirement
22 | module power_on_delay(
23 | input clk_50M ,
24 | input reset_n ,
25 | output camera1_rstn ,
26 | output camera2_rstn ,
27 | output camera_pwnd ,
28 | output initial_en
29 | );
30 | reg [18:0]cnt1;
31 | reg [15:0]cnt2;
32 | reg [19:0]cnt3;
33 | reg initial_en;
34 | reg camera_rstn_reg;
35 | reg camera_pwnd_reg;
36 |
37 | assign camera1_rstn=camera_rstn_reg;
38 | assign camera2_rstn=camera_rstn_reg;
39 | assign camera_pwnd=camera_pwnd_reg;
40 |
41 | //5ms, delay from sensor power up stable to Pwdn pull down
42 | always@(posedge clk_50M)begin
43 | if(reset_n==1'b0) begin
44 | cnt1<=0;
45 | camera_pwnd_reg<=1'b1;// 1'b1
46 | end
47 | else if(cnt1<19'h40000) begin
48 | cnt1<=cnt1+1'b1;
49 | camera_pwnd_reg<=1'b1;
50 | end
51 | else
52 | camera_pwnd_reg<=1'b0;
53 | end
54 |
55 | //1.3ms, delay from pwdn low to resetb pull up
56 | always@(posedge clk_50M)begin
57 | if(camera_pwnd_reg==1) begin
58 | cnt2<=0;
59 | camera_rstn_reg<=1'b0;
60 | end
61 | else if(cnt2<16'hffff) begin
62 | cnt2<=cnt2+1'b1;
63 | camera_rstn_reg<=1'b0;
64 | end
65 | else
66 | camera_rstn_reg<=1'b1;
67 | end
68 |
69 | //21ms, delay from resetb pul high to SCCB initialization
70 | always@(posedge clk_50M)begin
71 | if(camera_rstn_reg==0) begin
72 | cnt3<=0;
73 | initial_en<=1'b0;
74 | end
75 | else if(cnt3<20'hfffff) begin
76 | cnt3<=cnt3+1'b1;
77 | initial_en<=1'b0;
78 | end
79 | else
80 | initial_en<=1'b1;
81 | end
82 |
83 | endmodule
84 |
--------------------------------------------------------------------------------
/readme.md:
--------------------------------------------------------------------------------
1 | # 基于 FPGA 的图像内目标识别系统
2 |
3 | 该项目是一个利用 FPGA 采集图像,然后将图像传输到电脑执行目标检测任务的系统。该系统基于 Yolov3 模型验证,利用 Keras-TensorFlow 运行。数据处理任务需要在电脑端运行。该系统利用 UDP 网络协议传输图像数据至电脑端,并通过 OpenCV 和其他 Python 库实现图像数据解码。
4 |
5 | 系统的一般工作方式如下:首先,系统通过摄像头捕获实时图像,并将图像数据处理为 RGB565 和(或)YUV422 通用图像编码格式。接下来,经过逻辑模块的处理,通过 DDR 和 FIFO 等跨时钟缓存存储硬件,将图像数据传输给 HDMI 处理模块和 UDP 发送编码模块。然后,系统可将摄像头采集的图像通过 HDMI 显示在兼容的显示屏上,其中图像参数为 $1280 \times 720,\\ 60FPS$。同时,另一路图像数据通过 UDP 发送模块编码后传输给电脑,并通过电脑执行目标检测任务。
6 |
7 | ## 运行环境
8 |
9 | * Pango Design Suite Lite 2022.2
10 | * PGL50H-6FBG484 芯片部件编号
11 | * 开发平台:MES50HP
12 |
13 | ## 存储库结构
14 |
15 | ```
16 | |-- dataset // 数据集处理相关文件
17 | |-- document // 开发文档
18 | |-- constraint.md // 硬件约束参考
19 | |-- FPGA // FPGA 工程文件,例如约束文件和比特流文件
20 | |-- RTL // RTL 代码
21 | |-- software // 相关程序代码
22 | ```
23 |
24 | ## 硬件侧
25 | ### 系统框图
26 |
27 | 该项目的主要硬件模块包括:摄像头模块(OV5640)、高速存取模块(DDR3)、显示模块(HDMI)和以太网 UDP 收发模块。
28 |
29 |

30 |
31 | 该系统包含两个 OV5640 摄像头。其中一个摄像头的配置为 YUV422 格式,流处理格式为 JPEG 2,分辨率为 $1280\times 720$,以 JPEG 2 模式进行配置能够生成具有固定数据长度的帧信息;另一个摄像头的配置为 RGB565 格式,流处理格式为视频流,分辨率为 $1280\times 720$。
32 |
33 | YUV422 格式的视频信号在传输过程中,数据通过 UDP 模块拆分为元数据,以便通过网络接口传输到连接的 PC 端。PC 端接收到数据后,可以进行进一步的处理和分析。
34 |
35 | 另一路视频信号配置为 RGB565 格式,将 8 位的数据拼接为 16 位的 RGB565 数据,然后通过 DDR 缓存。最后,通过 HDMI 接口将存储在 DDR 缓存中的视频数据发送到连接的显示屏上进行实时显示。
36 |
37 | ## 软件侧
38 | ### 深度学习模型介绍
39 |
40 | 该项目采用的目标检测模型为 Yolov3。有关模型的更多细节,可访问作者存储库[在 Tensorflow2 上使用 yolov3 进行目标检测](https://github.com/MongooseOrion/tf2-keras-yolo3)了解,在本仓库中不再重新添加相关模型文件。
41 |
42 | **请注意,该仓库仅包括采集图像数据和以太网传输的 verilog 代码。若要执行目标识别,则你必须拉取上述的仓库或者使用其他的模型,本仓库 `software` 文件夹内的 python 程序仅可适配 Yolov3 模型**。
43 |
44 | ### 电脑端 UDP 接收程序设计
45 |
46 | 若要正常执行目标检测,你首先需要在 Windows 设置中将目标设备的 IP 地址设置为 `192.168.0.3`。
47 |
48 | JPEG 的起始标识符应该是 `\xff\xd8`。使用 `find()` 方法可查找起始标识符在 `received_data` 中的位置。如果找到了起始标识符,则继续检查结束标识符。
49 |
50 | JPEG 的结束标识符应该是 `\xff\xd9`。使用 `find()` 方法可在 `received_data` 中查找结束标识符的位置。如果找到了结束标识符,则截取图像数据,将其存储在 `image_data` 中,然后调用 cv2 模块拼合图像。
51 |
52 | ## 训练数据集
53 |
54 | *你可以自行使用其他的开源框架训练和执行目标检测任务。*
55 |
56 | 该项目的目标数据集内包括有 1000 个训练视频及其对应的按帧记录的 JSON 标注文件。
57 |
58 | 
59 |
60 | 处理过程如下述所示:
61 | 1. 为了能够使用 yolov3 模型训练,必须按照图片和对应 txt 文件的方式对数据集进行处理,于是调用 `opencv` 将所有视频切成单帧;
62 | 2. 将标注文件(格式为 json)的 bbox 和目标种类信息按照:`path/to/img xmin,ymin,xmax,ymax,category_name0 xmin,ymin,xmax,ymax,category_name1 ...` 的格式以追加模式写入标注文件 `train.txt` 中;
63 | 3. 将 `category_name` 保存在 `classes.txt` 中;
64 | 4. 交叉比对,删去不含 bbox 信息的帧,也即没有被 json 文件记录的帧,经过比对,大约有 300 个视频或 20 万帧没有 bbox 信息;
65 | 5. 由于原始 json 标注文件对于目标种类的索引都是从 0 开始,这也就是第二步中没有直接按索引号标识 `category_name` 的原因,在此步骤中将 `train.txt` 中每行的 `category_name` 按照 `classes.txt` 中的顺序替换为索引号;
66 | 6. 打乱排序,准备训练。
67 |
68 | 有关处理数据集的源代码,请[点此](https://github.com/MongooseOrion/FPGA-Image-Recognition/blob/master/dataset/process.py)查看。
69 |
70 | ## 识别效果
71 |
72 | 为保证截图效果,设置了中断,因此程序状态显示为 “未响应”。
73 |
74 | 
75 |
--------------------------------------------------------------------------------
/RTL/tx/mac_tx_mode.v:
--------------------------------------------------------------------------------
1 | //////////////////////////////////////////////////////////////////////////////////////
2 | //Module Name : mac_tx_mode
3 | //Description : This module is arbitration for MAC layer signal, which from IP and ARP
4 | //
5 | //////////////////////////////////////////////////////////////////////////////////////
6 | `timescale 1 ns/1 ns
7 | module mac_tx_mode
8 | (
9 | input clk ,
10 | input rst_n,
11 |
12 | input arp_tx_ready ,
13 | input [7:0] arp_tx_data,
14 | input arp_tx_end,
15 |
16 | input ip_tx_ready,
17 | input [7:0] ip_tx_data,
18 | input ip_tx_end,
19 |
20 | output reg mac_tx_ready,
21 | output reg [7:0] mac_tx_data,
22 | output reg mac_tx_end
23 | );
24 |
25 |
26 |
27 | reg [15:0] timeout ;
28 |
29 | parameter IDLE = 3'b001 ;
30 | parameter ARP = 3'b010 ;
31 | parameter IP = 3'b100 ;
32 |
33 |
34 | reg [2:0] state ;
35 | reg [2:0] next_state ;
36 |
37 | always @(posedge clk or negedge rst_n)
38 | begin
39 | if (~rst_n)
40 | state <= IDLE ;
41 | else
42 | state <= next_state ;
43 | end
44 |
45 | always @(*)
46 | begin
47 | case(state)
48 | IDLE :
49 | begin
50 | if (arp_tx_ready)
51 | next_state <= ARP ;
52 | else if (ip_tx_ready)
53 | next_state <= IP ;
54 | else
55 | next_state <= IDLE ;
56 | end
57 |
58 | ARP :
59 | begin
60 | if (arp_tx_end)
61 | next_state <= IDLE ;
62 | else if (timeout == 16'hffff)
63 | next_state <= IDLE ;
64 | else
65 | next_state <= ARP ;
66 | end
67 | IP :
68 | begin
69 | if (ip_tx_end)
70 | next_state <= IDLE ;
71 | else if (timeout == 16'hffff)
72 | next_state <= IDLE ;
73 | else
74 | next_state <= IP ;
75 | end
76 | default :
77 | next_state <= IDLE ;
78 | endcase
79 | end
80 |
81 |
82 | always @(posedge clk or negedge rst_n)
83 | begin
84 | if (~rst_n)
85 | timeout <= 16'd0 ;
86 | else if (state == ARP || state == IP)
87 | timeout <= timeout + 1'b1 ;
88 | else
89 | timeout <= 16'd0 ;
90 | end
91 |
92 |
93 |
94 | always @(posedge clk or negedge rst_n)
95 | begin
96 | if (~rst_n)
97 | begin
98 | mac_tx_ready <= 1'b0 ;
99 | mac_tx_data <= 8'h00 ;
100 | mac_tx_end <= 1'b0 ;
101 | end
102 | else if (state == ARP)
103 | begin
104 | mac_tx_ready <= arp_tx_ready ;
105 | mac_tx_data <= arp_tx_data ;
106 | mac_tx_end <= arp_tx_end ;
107 | end
108 | else if (state == IP)
109 | begin
110 | mac_tx_ready <= ip_tx_ready ;
111 | mac_tx_data <= ip_tx_data ;
112 | mac_tx_end <= ip_tx_end ;
113 | end
114 | else
115 | begin
116 | mac_tx_ready <= 1'b0 ;
117 | mac_tx_data <= 8'h00 ;
118 | mac_tx_end <= 1'b0 ;
119 | end
120 | end
121 |
122 | endmodule
123 |
124 |
125 |
--------------------------------------------------------------------------------
/RTL/mac/crc.v:
--------------------------------------------------------------------------------
1 | `timescale 1ns / 1ps
2 | /****************************************/
3 | // CRC32数据校验模块 //
4 | /****************************************/
5 | module crc (Clk, Reset, Data_in, Enable, Crc,CrcNext);
6 |
7 |
8 | parameter Tp = 1;
9 |
10 | input Clk;
11 | input Reset;
12 | input [7:0] Data_in;
13 | input Enable;
14 |
15 | output [31:0] Crc;
16 | reg [31:0] Crc;
17 |
18 | output [31:0] CrcNext;
19 |
20 | wire [7:0] Data;
21 |
22 | assign Data={Data_in[0],Data_in[1],Data_in[2],Data_in[3],Data_in[4],Data_in[5],Data_in[6],Data_in[7]};
23 |
24 |
25 | assign CrcNext[0] = Crc[24] ^ Crc[30] ^ Data[0] ^ Data[6];
26 | assign CrcNext[1] = Crc[24] ^ Crc[25] ^ Crc[30] ^ Crc[31] ^ Data[0] ^ Data[1] ^ Data[6] ^ Data[7];
27 | assign CrcNext[2] = Crc[24] ^ Crc[25] ^ Crc[26] ^ Crc[30] ^ Crc[31] ^ Data[0] ^ Data[1] ^ Data[2] ^ Data[6] ^ Data[7];
28 | assign CrcNext[3] = Crc[25] ^ Crc[26] ^ Crc[27] ^ Crc[31] ^ Data[1] ^ Data[2] ^ Data[3] ^ Data[7];
29 | assign CrcNext[4] = Crc[24] ^ Crc[26] ^ Crc[27] ^ Crc[28] ^ Crc[30] ^ Data[0] ^ Data[2] ^ Data[3] ^ Data[4] ^ Data[6];
30 | assign CrcNext[5] = Crc[24] ^ Crc[25] ^ Crc[27] ^ Crc[28] ^ Crc[29] ^ Crc[30] ^ Crc[31] ^ Data[0] ^ Data[1] ^ Data[3] ^ Data[4] ^ Data[5] ^ Data[6] ^ Data[7];
31 | assign CrcNext[6] = Crc[25] ^ Crc[26] ^ Crc[28] ^ Crc[29] ^ Crc[30] ^ Crc[31] ^ Data[1] ^ Data[2] ^ Data[4] ^ Data[5] ^ Data[6] ^ Data[7];
32 | assign CrcNext[7] = Crc[24] ^ Crc[26] ^ Crc[27] ^ Crc[29] ^ Crc[31] ^ Data[0] ^ Data[2] ^ Data[3] ^ Data[5] ^ Data[7];
33 | assign CrcNext[8] = Crc[0] ^ Crc[24] ^ Crc[25] ^ Crc[27] ^ Crc[28] ^ Data[0] ^ Data[1] ^ Data[3] ^ Data[4];
34 | assign CrcNext[9] = Crc[1] ^ Crc[25] ^ Crc[26] ^ Crc[28] ^ Crc[29] ^ Data[1] ^ Data[2] ^ Data[4] ^ Data[5];
35 | assign CrcNext[10] = Crc[2] ^ Crc[24] ^ Crc[26] ^ Crc[27] ^ Crc[29] ^ Data[0] ^ Data[2] ^ Data[3] ^ Data[5];
36 | assign CrcNext[11] = Crc[3] ^ Crc[24] ^ Crc[25] ^ Crc[27] ^ Crc[28] ^ Data[0] ^ Data[1] ^ Data[3] ^ Data[4];
37 | assign CrcNext[12] = Crc[4] ^ Crc[24] ^ Crc[25] ^ Crc[26] ^ Crc[28] ^ Crc[29] ^ Crc[30] ^ Data[0] ^ Data[1] ^ Data[2] ^ Data[4] ^ Data[5] ^ Data[6];
38 | assign CrcNext[13] = Crc[5] ^ Crc[25] ^ Crc[26] ^ Crc[27] ^ Crc[29] ^ Crc[30] ^ Crc[31] ^ Data[1] ^ Data[2] ^ Data[3] ^ Data[5] ^ Data[6] ^ Data[7];
39 | assign CrcNext[14] = Crc[6] ^ Crc[26] ^ Crc[27] ^ Crc[28] ^ Crc[30] ^ Crc[31] ^ Data[2] ^ Data[3] ^ Data[4] ^ Data[6] ^ Data[7];
40 | assign CrcNext[15] = Crc[7] ^ Crc[27] ^ Crc[28] ^ Crc[29] ^ Crc[31] ^ Data[3] ^ Data[4] ^ Data[5] ^ Data[7];
41 | assign CrcNext[16] = Crc[8] ^ Crc[24] ^ Crc[28] ^ Crc[29] ^ Data[0] ^ Data[4] ^ Data[5];
42 | assign CrcNext[17] = Crc[9] ^ Crc[25] ^ Crc[29] ^ Crc[30] ^ Data[1] ^ Data[5] ^ Data[6];
43 | assign CrcNext[18] = Crc[10] ^ Crc[26] ^ Crc[30] ^ Crc[31] ^ Data[2] ^ Data[6] ^ Data[7];
44 | assign CrcNext[19] = Crc[11] ^ Crc[27] ^ Crc[31] ^ Data[3] ^ Data[7];
45 | assign CrcNext[20] = Crc[12] ^ Crc[28] ^ Data[4];
46 | assign CrcNext[21] = Crc[13] ^ Crc[29] ^ Data[5];
47 | assign CrcNext[22] = Crc[14] ^ Crc[24] ^ Data[0];
48 | assign CrcNext[23] = Crc[15] ^ Crc[24] ^ Crc[25] ^ Crc[30] ^ Data[0] ^ Data[1] ^ Data[6];
49 | assign CrcNext[24] = Crc[16] ^ Crc[25] ^ Crc[26] ^ Crc[31] ^ Data[1] ^ Data[2] ^ Data[7];
50 | assign CrcNext[25] = Crc[17] ^ Crc[26] ^ Crc[27] ^ Data[2] ^ Data[3];
51 | assign CrcNext[26] = Crc[18] ^ Crc[24] ^ Crc[27] ^ Crc[28] ^ Crc[30] ^ Data[0] ^ Data[3] ^ Data[4] ^ Data[6];
52 | assign CrcNext[27] = Crc[19] ^ Crc[25] ^ Crc[28] ^ Crc[29] ^ Crc[31] ^ Data[1] ^ Data[4] ^ Data[5] ^ Data[7];
53 | assign CrcNext[28] = Crc[20] ^ Crc[26] ^ Crc[29] ^ Crc[30] ^ Data[2] ^ Data[5] ^ Data[6];
54 | assign CrcNext[29] = Crc[21] ^ Crc[27] ^ Crc[30] ^ Crc[31] ^ Data[3] ^ Data[6] ^ Data[7];
55 | assign CrcNext[30] = Crc[22] ^ Crc[28] ^ Crc[31] ^ Data[4] ^ Data[7];
56 | assign CrcNext[31] = Crc[23] ^ Crc[29] ^ Data[5];
57 |
58 | always @ (posedge Clk, posedge Reset)
59 | begin
60 | if (Reset)
61 | begin
62 | Crc <={32{1'b1}};
63 | end
64 | else if (Enable)
65 | Crc <=CrcNext;
66 | end
67 | endmodule
68 |
--------------------------------------------------------------------------------
/RTL/new/mac/crc.v:
--------------------------------------------------------------------------------
1 | `timescale 1ns / 1ps
2 | /****************************************/
3 | // CRC32数据校验模块 //
4 | /****************************************/
5 | module crc (Clk, Reset, Data_in, Enable, Crc,CrcNext);
6 |
7 |
8 | parameter Tp = 1;
9 |
10 | input Clk;
11 | input Reset;
12 | input [7:0] Data_in;
13 | input Enable;
14 |
15 | output [31:0] Crc;
16 | reg [31:0] Crc;
17 |
18 | output [31:0] CrcNext;
19 |
20 | wire [7:0] Data;
21 |
22 | assign Data={Data_in[0],Data_in[1],Data_in[2],Data_in[3],Data_in[4],Data_in[5],Data_in[6],Data_in[7]};
23 |
24 |
25 | assign CrcNext[0] = Crc[24] ^ Crc[30] ^ Data[0] ^ Data[6];
26 | assign CrcNext[1] = Crc[24] ^ Crc[25] ^ Crc[30] ^ Crc[31] ^ Data[0] ^ Data[1] ^ Data[6] ^ Data[7];
27 | assign CrcNext[2] = Crc[24] ^ Crc[25] ^ Crc[26] ^ Crc[30] ^ Crc[31] ^ Data[0] ^ Data[1] ^ Data[2] ^ Data[6] ^ Data[7];
28 | assign CrcNext[3] = Crc[25] ^ Crc[26] ^ Crc[27] ^ Crc[31] ^ Data[1] ^ Data[2] ^ Data[3] ^ Data[7];
29 | assign CrcNext[4] = Crc[24] ^ Crc[26] ^ Crc[27] ^ Crc[28] ^ Crc[30] ^ Data[0] ^ Data[2] ^ Data[3] ^ Data[4] ^ Data[6];
30 | assign CrcNext[5] = Crc[24] ^ Crc[25] ^ Crc[27] ^ Crc[28] ^ Crc[29] ^ Crc[30] ^ Crc[31] ^ Data[0] ^ Data[1] ^ Data[3] ^ Data[4] ^ Data[5] ^ Data[6] ^ Data[7];
31 | assign CrcNext[6] = Crc[25] ^ Crc[26] ^ Crc[28] ^ Crc[29] ^ Crc[30] ^ Crc[31] ^ Data[1] ^ Data[2] ^ Data[4] ^ Data[5] ^ Data[6] ^ Data[7];
32 | assign CrcNext[7] = Crc[24] ^ Crc[26] ^ Crc[27] ^ Crc[29] ^ Crc[31] ^ Data[0] ^ Data[2] ^ Data[3] ^ Data[5] ^ Data[7];
33 | assign CrcNext[8] = Crc[0] ^ Crc[24] ^ Crc[25] ^ Crc[27] ^ Crc[28] ^ Data[0] ^ Data[1] ^ Data[3] ^ Data[4];
34 | assign CrcNext[9] = Crc[1] ^ Crc[25] ^ Crc[26] ^ Crc[28] ^ Crc[29] ^ Data[1] ^ Data[2] ^ Data[4] ^ Data[5];
35 | assign CrcNext[10] = Crc[2] ^ Crc[24] ^ Crc[26] ^ Crc[27] ^ Crc[29] ^ Data[0] ^ Data[2] ^ Data[3] ^ Data[5];
36 | assign CrcNext[11] = Crc[3] ^ Crc[24] ^ Crc[25] ^ Crc[27] ^ Crc[28] ^ Data[0] ^ Data[1] ^ Data[3] ^ Data[4];
37 | assign CrcNext[12] = Crc[4] ^ Crc[24] ^ Crc[25] ^ Crc[26] ^ Crc[28] ^ Crc[29] ^ Crc[30] ^ Data[0] ^ Data[1] ^ Data[2] ^ Data[4] ^ Data[5] ^ Data[6];
38 | assign CrcNext[13] = Crc[5] ^ Crc[25] ^ Crc[26] ^ Crc[27] ^ Crc[29] ^ Crc[30] ^ Crc[31] ^ Data[1] ^ Data[2] ^ Data[3] ^ Data[5] ^ Data[6] ^ Data[7];
39 | assign CrcNext[14] = Crc[6] ^ Crc[26] ^ Crc[27] ^ Crc[28] ^ Crc[30] ^ Crc[31] ^ Data[2] ^ Data[3] ^ Data[4] ^ Data[6] ^ Data[7];
40 | assign CrcNext[15] = Crc[7] ^ Crc[27] ^ Crc[28] ^ Crc[29] ^ Crc[31] ^ Data[3] ^ Data[4] ^ Data[5] ^ Data[7];
41 | assign CrcNext[16] = Crc[8] ^ Crc[24] ^ Crc[28] ^ Crc[29] ^ Data[0] ^ Data[4] ^ Data[5];
42 | assign CrcNext[17] = Crc[9] ^ Crc[25] ^ Crc[29] ^ Crc[30] ^ Data[1] ^ Data[5] ^ Data[6];
43 | assign CrcNext[18] = Crc[10] ^ Crc[26] ^ Crc[30] ^ Crc[31] ^ Data[2] ^ Data[6] ^ Data[7];
44 | assign CrcNext[19] = Crc[11] ^ Crc[27] ^ Crc[31] ^ Data[3] ^ Data[7];
45 | assign CrcNext[20] = Crc[12] ^ Crc[28] ^ Data[4];
46 | assign CrcNext[21] = Crc[13] ^ Crc[29] ^ Data[5];
47 | assign CrcNext[22] = Crc[14] ^ Crc[24] ^ Data[0];
48 | assign CrcNext[23] = Crc[15] ^ Crc[24] ^ Crc[25] ^ Crc[30] ^ Data[0] ^ Data[1] ^ Data[6];
49 | assign CrcNext[24] = Crc[16] ^ Crc[25] ^ Crc[26] ^ Crc[31] ^ Data[1] ^ Data[2] ^ Data[7];
50 | assign CrcNext[25] = Crc[17] ^ Crc[26] ^ Crc[27] ^ Data[2] ^ Data[3];
51 | assign CrcNext[26] = Crc[18] ^ Crc[24] ^ Crc[27] ^ Crc[28] ^ Crc[30] ^ Data[0] ^ Data[3] ^ Data[4] ^ Data[6];
52 | assign CrcNext[27] = Crc[19] ^ Crc[25] ^ Crc[28] ^ Crc[29] ^ Crc[31] ^ Data[1] ^ Data[4] ^ Data[5] ^ Data[7];
53 | assign CrcNext[28] = Crc[20] ^ Crc[26] ^ Crc[29] ^ Crc[30] ^ Data[2] ^ Data[5] ^ Data[6];
54 | assign CrcNext[29] = Crc[21] ^ Crc[27] ^ Crc[30] ^ Crc[31] ^ Data[3] ^ Data[6] ^ Data[7];
55 | assign CrcNext[30] = Crc[22] ^ Crc[28] ^ Crc[31] ^ Data[4] ^ Data[7];
56 | assign CrcNext[31] = Crc[23] ^ Crc[29] ^ Data[5];
57 |
58 | always @ (posedge Clk, posedge Reset)
59 | begin
60 | if (Reset)
61 | begin
62 | Crc <={32{1'b1}};
63 | end
64 | else if (Enable)
65 | Crc <=CrcNext;
66 | end
67 | endmodule
68 |
--------------------------------------------------------------------------------
/RTL/tx/ip_tx_mode.v:
--------------------------------------------------------------------------------
1 | //////////////////////////////////////////////////////////////////////////////////////
2 | //Module Name : ip_tx_mode
3 | //Description : This module is arbitration for ip layer signal, which from udp and icmp
4 | //
5 | //////////////////////////////////////////////////////////////////////////////////////
6 | `timescale 1 ns/1 ns
7 | module ip_tx_mode
8 | (
9 | input clk ,
10 | input rst_n,
11 | input mac_tx_end,
12 |
13 | input udp_tx_ready ,
14 | input [7:0] udp_tx_data,
15 | input [15:0] udp_send_data_length,
16 |
17 |
18 | input icmp_tx_ready,
19 | input [7:0] icmp_tx_data,
20 | input [15:0] icmp_send_data_length,
21 |
22 |
23 | output reg ip_tx_ready,
24 | output reg [7:0] ip_tx_data,
25 | output reg [7:0] ip_send_type,
26 | output reg [15:0] ip_send_data_length
27 |
28 |
29 | );
30 |
31 | localparam ip_udp_type = 8'h11 ;
32 | localparam ip_icmp_type = 8'h01 ;
33 |
34 | reg [15:0] timeout ;
35 |
36 | parameter IDLE = 3'b001 ;
37 | parameter UDP = 3'b010 ;
38 | parameter ICMP = 3'b100 ;
39 |
40 |
41 | reg [2:0] state ;
42 | reg [2:0] next_state ;
43 |
44 | always @(posedge clk or negedge rst_n)
45 | begin
46 | if (~rst_n)
47 | state <= IDLE ;
48 | else
49 | state <= next_state ;
50 | end
51 |
52 | always @(*)
53 | begin
54 | case(state)
55 | IDLE :
56 | begin
57 | if (udp_tx_ready)
58 | next_state <= UDP ;
59 | else if (icmp_tx_ready)
60 | next_state <= ICMP ;
61 | else
62 | next_state <= IDLE ;
63 | end
64 |
65 | UDP :
66 | begin
67 | if (mac_tx_end)
68 | next_state <= IDLE ;
69 | else if (timeout == 16'hffff)
70 | next_state <= IDLE ;
71 | else
72 | next_state <= UDP ;
73 | end
74 | ICMP :
75 | begin
76 | if (mac_tx_end)
77 | next_state <= IDLE ;
78 | else if (timeout == 16'hffff)
79 | next_state <= IDLE ;
80 | else
81 | next_state <= ICMP ;
82 | end
83 | default :
84 | next_state <= IDLE ;
85 | endcase
86 | end
87 |
88 |
89 | always @(posedge clk or negedge rst_n)
90 | begin
91 | if (~rst_n)
92 | timeout <= 16'd0 ;
93 | else if (state == UDP || state == ICMP)
94 | timeout <= timeout + 1'b1 ;
95 | else
96 | timeout <= 16'd0 ;
97 | end
98 |
99 | always @(posedge clk or negedge rst_n)
100 | begin
101 | if (~rst_n)
102 | ip_send_data_length <= 16'd0 ;
103 | else if (state == ICMP)
104 | ip_send_data_length <= icmp_send_data_length ;
105 | else
106 | ip_send_data_length <= udp_send_data_length + 28 ;
107 | end
108 |
109 |
110 | always @(posedge clk or negedge rst_n)
111 | begin
112 | if (~rst_n)
113 | begin
114 | ip_tx_ready <= 1'b0 ;
115 | ip_tx_data <= 8'h00 ;
116 | ip_send_type <= ip_udp_type ;
117 | end
118 | else if (state == UDP)
119 | begin
120 | ip_tx_ready <= udp_tx_ready ;
121 | ip_tx_data <= udp_tx_data ;
122 | ip_send_type <= ip_udp_type ;
123 |
124 | end
125 | else if (state == ICMP)
126 | begin
127 | ip_tx_ready <= icmp_tx_ready ;
128 | ip_tx_data <= icmp_tx_data ;
129 | ip_send_type <= ip_icmp_type ;
130 |
131 | end
132 | else
133 | begin
134 | ip_tx_ready <= 1'b0 ;
135 | ip_tx_data <= 8'h00 ;
136 | ip_send_type <= ip_udp_type ;
137 | end
138 | end
139 |
140 |
141 |
142 | endmodule
143 |
144 |
145 |
--------------------------------------------------------------------------------
/RTL/rtl/i2c_com.v:
--------------------------------------------------------------------------------
1 | //////////////////////////////////////////////////////////////////////////////////
2 | // Company:Meyesemi
3 | // Engineer: Will
4 | //
5 | // Create Date: 2023-03-17
6 | // Design Name:
7 | // Module Name:
8 | // Project Name:
9 | // Target Devices: Pango
10 | // Tool Versions:
11 | // Description:
12 | //
13 | // Dependencies:
14 | //
15 | // Revision:
16 | // Revision 1.0 - File Created
17 | // Additional Comments:
18 | //
19 | //////////////////////////////////////////////////////////////////////////////////
20 | //sclk,sdin数据传输时序代码(i2c写控制代码)
21 | module i2c_com(clock_i2c , //i2c控制接口传输所需时钟,0-400khz,此处为20khz
22 | camera_rstn ,
23 | ack , //应答信号
24 | i2c_data , //sdin接口传输的32位数据
25 | start , //开始传输标志
26 | tr_end , //传输结束标志
27 | i2c_sclk , //FPGA与camera iic时钟接口
28 | i2c_sdat //FPGA与camera iic数据接口
29 | );
30 | input [31:0]i2c_data;
31 | input camera_rstn;
32 | input clock_i2c;
33 | output ack;
34 | input start;
35 | output tr_end;
36 | output i2c_sclk;
37 | inout i2c_sdat;
38 | reg [5:0] cyc_count;
39 | reg reg_sdat;
40 | reg sclk;
41 | reg ack1,ack2,ack3;
42 | reg tr_end;
43 |
44 |
45 | wire i2c_sclk;
46 | wire i2c_sdat;
47 | wire ack;
48 |
49 | assign ack=ack1|ack2|ack3;
50 | assign i2c_sclk=sclk|(((cyc_count>=4)&(cyc_count<=39))?~clock_i2c:0);
51 | assign i2c_sdat=reg_sdat?1'bz:0;
52 |
53 | always@(posedge clock_i2c)
54 | begin
55 | if(!camera_rstn)
56 | cyc_count<=6'b111111;
57 | else
58 | begin
59 | if(start==0)
60 | cyc_count<=0;
61 | else if(cyc_count<6'b111111)
62 | cyc_count<=cyc_count+1;
63 | end
64 | end
65 |
66 |
67 | always@(posedge clock_i2c)
68 | begin
69 | if(!camera_rstn)
70 | begin
71 | tr_end<=0;
72 | ack1<=1;
73 | ack2<=1;
74 | ack3<=1;
75 | sclk<=1;
76 | reg_sdat<=1;
77 | end
78 | else
79 | case(cyc_count)
80 | 0:begin ack1<=1;ack2<=1;ack3<=1;tr_end<=0;sclk<=1;reg_sdat<=1;end
81 | 1:reg_sdat<=0; //开始传输
82 | 2:sclk<=0;
83 | 3:reg_sdat<=i2c_data[31];
84 | 4:reg_sdat<=i2c_data[30];
85 | 5:reg_sdat<=i2c_data[29];
86 | 6:reg_sdat<=i2c_data[28];
87 | 7:reg_sdat<=i2c_data[27];
88 | 8:reg_sdat<=i2c_data[26];
89 | 9:reg_sdat<=i2c_data[25];
90 | 10:reg_sdat<=i2c_data[24];
91 | 11:reg_sdat<=1; //应答信号
92 | 12:begin reg_sdat<=i2c_data[23];ack1<=i2c_sdat;end
93 | 13:reg_sdat<=i2c_data[22];
94 | 14:reg_sdat<=i2c_data[21];
95 | 15:reg_sdat<=i2c_data[20];
96 | 16:reg_sdat<=i2c_data[19];
97 | 17:reg_sdat<=i2c_data[18];
98 | 18:reg_sdat<=i2c_data[17];
99 | 19:reg_sdat<=i2c_data[16];
100 | 20:reg_sdat<=1; //应答信号
101 | 21:begin reg_sdat<=i2c_data[15];ack1<=i2c_sdat;end
102 | 22:reg_sdat<=i2c_data[14];
103 | 23:reg_sdat<=i2c_data[13];
104 | 24:reg_sdat<=i2c_data[12];
105 | 25:reg_sdat<=i2c_data[11];
106 | 26:reg_sdat<=i2c_data[10];
107 | 27:reg_sdat<=i2c_data[9];
108 | 28:reg_sdat<=i2c_data[8];
109 | 29:reg_sdat<=1; //应答信号
110 | 30:begin reg_sdat<=i2c_data[7];ack2<=i2c_sdat;end
111 | 31:reg_sdat<=i2c_data[6];
112 | 32:reg_sdat<=i2c_data[5];
113 | 33:reg_sdat<=i2c_data[4];
114 | 34:reg_sdat<=i2c_data[3];
115 | 35:reg_sdat<=i2c_data[2];
116 | 36:reg_sdat<=i2c_data[1];
117 | 37:reg_sdat<=i2c_data[0];
118 | 38:reg_sdat<=1; //应答信号
119 | 39:begin ack3<=i2c_sdat;sclk<=0;reg_sdat<=0;end
120 | 40:sclk<=1;
121 | 41:begin reg_sdat<=1;tr_end<=1;end
122 | endcase
123 |
124 | end
125 | endmodule
126 |
127 |
--------------------------------------------------------------------------------
/software/udp_video.py:
--------------------------------------------------------------------------------
1 | ''' ======================================================================
2 | * Copyright (c) 2023, MongooseOrion.
3 | * All rights reserved.
4 | *
5 | * The following code snippet may contain portions that are derived from
6 | * OPEN-SOURCE communities, and these portions will be licensed with:
7 | *
8 | *
9 | *
10 | * If there is no OPEN-SOURCE licenses are listed, it indicates none of
11 | * content in this Code document is sourced from OPEN-SOURCE communities.
12 | *
13 | * In this case, the document is protected by copyright, and any use of
14 | * all or part of its content by individuals, organizations, or companies
15 | * without authorization is prohibited, unless the project repository
16 | * associated with this document has added relevant OPEN-SOURCE licenses
17 | * by github.com/MongooseOrion.
18 | *
19 | * Please make sure using the content of this document in accordance with
20 | * the respective OPEN-SOURCE licenses.
21 | *
22 | * THIS CODE IS PROVIDED BY https://github.com/MongooseOrion.
23 | * FILE ENCODER TYPE: UTF-8
24 | * ========================================================================
25 | '''
26 | # 将 UDP 传输的图像数据拼合为图像
27 |
28 | import threading
29 | import socket
30 | import numpy as np
31 | import cv2
32 | import time
33 |
34 | # 共享数据
35 | received_data = bytearray()
36 |
37 | # 创建一个锁
38 | lock = threading.Lock()
39 |
40 | # 创建一个事件,用于通知线程退出
41 | exit_event = threading.Event()
42 |
43 | # 第一个函数,用于不停的接收数据
44 | def udp_receive_data():
45 | global received_data
46 | UDP_IP = "192.168.0.3" # 监听所有可用的网络接口
47 | UDP_PORT = 8080
48 | BUFFER_SIZE = 10240
49 | # 创建UDP套接字
50 | udp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
51 | udp_socket.bind((UDP_IP, UDP_PORT))
52 | while not exit_event.is_set():
53 | # 接收数据 在使用共享数据之前先获取锁
54 | data, addr = udp_socket.recvfrom(BUFFER_SIZE)
55 | with lock:
56 | received_data += data
57 | # 在使用完共享数据后释放锁
58 |
59 | # 第二个函数,用于显示图像
60 | def cv_imshow():
61 | global received_data
62 | start_marker = b"\xff\xd8"
63 | end_marker = b"\xff\xd9"
64 | i = 0
65 | start_time = 0
66 | end_time = 0
67 | fps = 0
68 | # 帧率显示数字大小等参数设置
69 | font = cv2.FONT_HERSHEY_SIMPLEX
70 | font_scale = 0.5
71 | font_thickness = 1
72 | font_color = (255, 255, 255) # 白色
73 | while not exit_event.is_set():
74 | #检查起始标识符
75 | # with lock:
76 | start_pos = received_data.find(start_marker)
77 | if start_pos != -1:
78 | while True:
79 | time.sleep(0.005) #当检查到起始符后,要过一段时间结束符才会到来,暂停一小会防止程序卡死
80 | # 检查结束标识符
81 | with lock:
82 | end_pos = received_data.find(end_marker, start_pos + len(start_marker))
83 | if end_pos != -1:
84 | with lock:
85 | image_data = received_data[start_pos:end_pos + len(end_marker)]
86 | received_data = received_data[end_pos + len(end_marker):] #清除已经显示信息
87 | try:
88 | image = np.frombuffer(image_data, dtype=np.uint8)
89 | image = cv2.imdecode(image, cv2.IMREAD_COLOR)
90 | height, width, channels = image.shape
91 | resolution_str = f"Resolution: {width} x {height}"
92 | #帧率计算,15帧计算一次,并在图片数据上添加帧率数据
93 | if(i==1):
94 | start_time = time.time()
95 | elif (i==16):
96 | i=0
97 | end_time = time.time()
98 | fps = 15/(end_time - start_time)
99 | cv2.putText(image, f'FPS: {fps:.2f}', (10, 30), font, font_scale, font_color, font_thickness)
100 | cv2.imshow(resolution_str, image)
101 | i=i+1
102 | key = cv2.waitKey(1)
103 | if key == ord('q'): # 按下 'q' 键退出
104 | exit_event.set()
105 | except Exception as e:
106 | print(f"Failed to decode image: {e}")
107 |
108 | break #跳出循环
109 |
110 | # 创建两个线程,分别运行两个不同的函数
111 | thread1 = threading.Thread(target=udp_receive_data)
112 | thread2 = threading.Thread(target=cv_imshow)
113 |
114 | # 启动线程
115 | thread1.start()
116 | thread2.start()
117 |
118 |
119 |
120 | # 等待两个线程执行完毕
121 | thread1.join()
122 | thread2.join()
123 |
124 | print("Main thread exiting.")
125 |
--------------------------------------------------------------------------------
/RTL/rtl/rd_ctrl.v:
--------------------------------------------------------------------------------
1 | `timescale 1ns / 1ps
2 | //////////////////////////////////////////////////////////////////////////////////
3 | // Company: Meyesemi
4 | // Engineer: Nill
5 | //
6 | // Create Date: 07/01/23 17:29:29
7 | // Design Name:
8 | // Module Name: rd_ctrl
9 | // Project Name:
10 | // Target Devices:
11 | // Tool Versions:
12 | // Description:
13 | //
14 | // Dependencies:
15 | //
16 | // Revision:
17 | // Revision 0.01 - File Created
18 | // Additional Comments:
19 | //
20 | //////////////////////////////////////////////////////////////////////////////////
21 | `define UD #1
22 |
23 | module rd_ctrl #(
24 | parameter CTRL_ADDR_WIDTH = 28,
25 | parameter MEM_DQ_WIDTH = 16
26 | )(
27 | input clk ,
28 | input rst_n ,
29 |
30 | input [CTRL_ADDR_WIDTH-1:0] read_addr ,
31 | input [3:0] read_id ,
32 | input [3:0] read_len ,
33 | input read_en ,
34 | output reg read_done_p =0,
35 |
36 | input read_ready ,
37 | output [MEM_DQ_WIDTH*8-1:0] read_rdata ,
38 | output read_rdata_en ,
39 |
40 | output reg [CTRL_ADDR_WIDTH-1:0] axi_araddr =0,
41 | output reg [3:0] axi_arid =0,
42 | output reg [3:0] axi_arlen =0,
43 | output [2:0] axi_arsize ,
44 | output [1:0] axi_arburst ,
45 | output reg axi_arvalid =0,
46 | input axi_arready , //only support 2'b01: INCR
47 |
48 | output axi_rready ,
49 | input [MEM_DQ_WIDTH*8-1:0] axi_rdata ,
50 | input axi_rvalid ,
51 | input axi_rlast ,
52 | input [3:0] axi_rid ,
53 | input [1:0] axi_rresp
54 | );
55 |
56 | localparam E_IDLE = 3'd0;
57 | localparam E_RD = 3'd1;
58 | localparam E_END = 3'd2;
59 | localparam DQ_NUM = MEM_DQ_WIDTH/8;
60 |
61 | assign axi_arburst = 2'b01;
62 | assign axi_arsize = 3'b110;
63 |
64 | reg [2:0] test_rd_state;
65 | reg [3:0] rd_delay_cnt;
66 |
67 | always @(posedge clk or negedge rst_n)
68 | begin
69 | if (!rst_n)
70 | test_rd_state <= E_IDLE;
71 | else begin
72 | case (test_rd_state)
73 | E_IDLE: begin
74 | if (read_en)
75 | test_rd_state <= E_RD;
76 | end
77 | E_RD: begin
78 | if (axi_arvalid&axi_arready)//(rd_delay_cnt == 4'd7)//
79 | test_rd_state <= E_END;
80 | end
81 | E_END: begin
82 | if (rd_delay_cnt == 4'd15)
83 | test_rd_state <= E_IDLE;
84 | end
85 | default: test_rd_state <= E_IDLE;
86 | endcase
87 | end
88 | end
89 |
90 |
91 | always @(posedge clk or negedge rst_n)
92 | begin
93 | if (!rst_n)
94 | rd_delay_cnt <= 4'b0;
95 | else if((test_rd_state == E_END))
96 | rd_delay_cnt <= rd_delay_cnt + 1'b1;
97 | else
98 | rd_delay_cnt <= 4'b0;
99 | end
100 |
101 | always @(posedge clk or negedge rst_n)
102 | begin
103 | if (!rst_n) begin
104 | axi_araddr <= {CTRL_ADDR_WIDTH{1'b0}};
105 | axi_arid <= 4'b0;
106 | axi_arlen <= 4'b0;
107 | end
108 | else if((test_rd_state == E_IDLE) & read_en)
109 | begin
110 | axi_arid <= read_id;
111 | axi_araddr <= read_addr;
112 | axi_arlen <= read_len;
113 | end
114 | end
115 |
116 | always @(posedge clk or negedge rst_n)
117 | begin
118 | if (!rst_n) begin
119 | axi_arvalid <= 1'b0;
120 | read_done_p <= 1'b0;
121 | end
122 | else begin
123 | case (test_rd_state)
124 | E_IDLE: begin
125 | read_done_p <= 1'b0 ;
126 | axi_arvalid <= 1'b0;
127 | end
128 | E_RD: begin
129 | axi_arvalid <= 1'b1;
130 |
131 | if (axi_arvalid&axi_arready)
132 | axi_arvalid <= 1'b0;
133 | end
134 | E_END: begin
135 | axi_arvalid <= 1'b0;
136 | if(rd_delay_cnt == 4'd15)
137 | read_done_p <= 1'b1;
138 | end
139 | default: begin
140 | axi_arvalid <= 1'b0;
141 | read_done_p <= 1'b0;
142 | end
143 | endcase
144 | end
145 | end
146 |
147 | assign axi_ready = read_ready;
148 | assign read_rdata = axi_rdata;
149 | assign read_rdata_en = axi_rvalid;
150 | assign axi_rready = 1'b1;
151 |
152 | endmodule
153 |
154 |
--------------------------------------------------------------------------------
/software/obj_detect_multi_thread.py:
--------------------------------------------------------------------------------
1 | ''' ======================================================================
2 | * Copyright (c) 2023, MongooseOrion.
3 | * All rights reserved.
4 | *
5 | * The following code snippet may contain portions that are derived from
6 | * OPEN-SOURCE communities, and these portions will be licensed with:
7 | *
8 | *
9 | *
10 | * If there is no OPEN-SOURCE licenses are listed, it indicates none of
11 | * content in this Code document is sourced from OPEN-SOURCE communities.
12 | *
13 | * In this case, the document is protected by copyright, and any use of
14 | * all or part of its content by individuals, organizations, or companies
15 | * without authorization is prohibited, unless the project repository
16 | * associated with this document has added relevant OPEN-SOURCE licenses
17 | * by github.com/MongooseOrion.
18 | *
19 | * Please make sure using the content of this document in accordance with
20 | * the respective OPEN-SOURCE licenses.
21 | *
22 | * THIS CODE IS PROVIDED BY https://github.com/MongooseOrion.
23 | * FILE ENCODER TYPE: UTF-8
24 | * ========================================================================
25 | '''
26 | # 使用 yolo 对 UDP 传输的图像数据进行目标检测,多线程
27 | import threading
28 | import socket
29 | import numpy as np
30 | import cv2
31 | from datetime import datetime
32 | import json
33 | import tensorflow as tf
34 | import keyboard
35 | from yolo import YOLO
36 | from PIL import Image
37 | import os
38 | import sys
39 | import time
40 | import settings
41 |
42 |
43 | # 共享数据
44 | received_data = bytearray()
45 |
46 | # 创建一个锁
47 | lock = threading.Lock()
48 |
49 | lock2 = threading.Lock()
50 |
51 | # 创建一个事件,用于通知线程退出
52 | exit_event = threading.Event()
53 |
54 | new_frame_event = threading.Event()
55 |
56 |
57 | # 第一个函数,用于不停的接收数据
58 | def udp_receive_data():
59 | global received_data
60 | UDP_IP = "192.168.0.3" # 监听所有可用的网络接口
61 | UDP_PORT = 8080
62 | BUFFER_SIZE = 10240
63 | # 创建UDP套接字
64 | udp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
65 | udp_socket.bind((UDP_IP, UDP_PORT))
66 | while not exit_event.is_set():
67 | # 接收数据 在使用共享数据之前先获取锁
68 | data, addr = udp_socket.recvfrom(BUFFER_SIZE)
69 | with lock:
70 | received_data += data
71 | # 在使用完共享数据后释放锁
72 |
73 | #第二个函数,用来保存图像数据
74 | def image_data_saved():
75 | global received_data
76 | global image
77 | start_marker = b"\xff\xd8"
78 | end_marker = b"\xff\xd9"
79 |
80 | while not exit_event.is_set():
81 | #检查起始标识符
82 | start_pos = received_data.find(start_marker)
83 | if start_pos != -1:
84 | while True:
85 | time.sleep(0.001) #当检查到起始符后,要过一段时间结束符才会到来,暂停一小会防止程序卡死
86 | # 检查结束标识符
87 | #with lock:
88 | end_pos = received_data.find(end_marker, start_pos + len(start_marker))
89 | if end_pos != -1:
90 | with lock:
91 | image_data = received_data[start_pos:end_pos + len(end_marker)]
92 | received_data = received_data[end_pos + len(end_marker):] #清除已经显示信息
93 | try:
94 | image1 = np.frombuffer(image_data, dtype=np.uint8)
95 | with lock2:
96 | image = cv2.imdecode(image1, cv2.IMREAD_COLOR)
97 | new_frame_event.set()
98 |
99 | except Exception as e:
100 | print(f"Failed to decode image: {e}")
101 |
102 | break #跳出循环
103 |
104 |
105 | # 第三个函数,用于处理图像
106 | def cv_imshow():
107 | global image
108 | global capture_target_frame_count
109 | i = 0
110 | start_time = 0
111 | end_time = 0
112 | fps = 0
113 | # 帧率显示数字大小等参数设置
114 | font = cv2.FONT_HERSHEY_SIMPLEX
115 | font_scale = 0.5
116 | font_thickness = 1
117 | font_color = (255, 255, 255) # 白色
118 |
119 | print("处理部分启动")
120 | image2=0
121 |
122 | capture_target_frame_count = 0
123 |
124 | # 加载YOLOv3模型
125 | model_path = settings.DEFAULT_MODEL_PATH # 根据实际路径修改
126 | yolo = YOLO(model_path=model_path)
127 |
128 |
129 | while not exit_event.is_set():
130 | new_frame_event.wait() #等待新的一帧数据,防止重复识别,该模型识别的时间一般小于<0.02s,而接收到的图像为30帧(约0.03s)
131 | with lock2:
132 | image2 = image.copy()
133 | new_frame_event.clear() # 重置事件,等待下一帧数据
134 | image3 = image2.copy()
135 | # 进行模型推断
136 | time1=time.time()
137 | outputs = yolo.detect_image(Image.fromarray(image2))
138 | print(str(time.time()-time1))
139 | # 将检测结果转换为OpenCV图像格式
140 | result_image = np.array(outputs)
141 | if(i==1):
142 | start_time = time.time()
143 | elif (i==16):
144 | i=0
145 | end_time = time.time()
146 | fps = 15/(end_time - start_time) #取15帧的平均帧率
147 | cv2.putText(result_image, f'FPS: {fps:.2f}', (10, 30), font, font_scale, font_color, font_thickness)
148 | i=i+1
149 | # 显示结果
150 | cv2.imshow('yolo_v3', result_image)
151 | key = cv2.waitKey(1)
152 |
153 | if key == ord('q'): # 按下 'q' 键退出
154 | exit_event.set()
155 |
156 |
157 |
158 | # 创建三个线程,分别运行两个不同的函数
159 | thread1 = threading.Thread(target=udp_receive_data)
160 | thread2 = threading.Thread(target=cv_imshow)
161 | thread3 = threading.Thread(target=image_data_saved)
162 |
163 | # 启动线程
164 |
165 | thread1.start()
166 | thread3.start()
167 | print("延迟8s等待模型加载模型")
168 | time.sleep(8)
169 |
170 | thread2.start()
171 |
172 |
173 | # 等待两个线程执行完毕
174 | thread1.join()
175 | thread2.join()
176 | thread3.join()
177 |
178 | print("Main thread exiting.")
179 |
--------------------------------------------------------------------------------
/software/obj_detect_single_thread.py:
--------------------------------------------------------------------------------
1 | ''' ======================================================================
2 | * Copyright (c) 2023, MongooseOrion.
3 | * All rights reserved.
4 | *
5 | * The following code snippet may contain portions that are derived from
6 | * OPEN-SOURCE communities, and these portions will be licensed with:
7 | *
8 | *
9 | *
10 | * If there is no OPEN-SOURCE licenses are listed, it indicates none of
11 | * content in this Code document is sourced from OPEN-SOURCE communities.
12 | *
13 | * In this case, the document is protected by copyright, and any use of
14 | * all or part of its content by individuals, organizations, or companies
15 | * without authorization is prohibited, unless the project repository
16 | * associated with this document has added relevant OPEN-SOURCE licenses
17 | * by github.com/MongooseOrion.
18 | *
19 | * Please make sure using the content of this document in accordance with
20 | * the respective OPEN-SOURCE licenses.
21 | *
22 | * THIS CODE IS PROVIDED BY https://github.com/MongooseOrion.
23 | * FILE ENCODER TYPE: UTF-8
24 | * ========================================================================
25 | '''
26 | # 使用 yolo 对 UDP 传输的图像数据进行目标检测,单线程
27 | import socket
28 | import numpy as np
29 | import cv2
30 | import sys
31 | import argparse
32 | from yolo import YOLO
33 | from PIL import Image
34 | import os
35 | import sys
36 | import time
37 |
38 | import settings
39 |
40 | UDP_IP = "192.168.0.3" # 监听所有可用的网络接口
41 | UDP_PORT = 8080
42 | BUFFER_SIZE = 2764800
43 |
44 | # 创建UDP套接字
45 | udp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
46 | udp_socket.bind((UDP_IP, UDP_PORT))
47 |
48 | # 用于保存已接收的图像数据
49 | received_data = bytearray()
50 |
51 | # 期望的图像尺寸
52 | expected_image_size = 1280 * 720 * 3
53 |
54 | # 加载YOLOv3模型
55 | model_path = settings.DEFAULT_MODEL_PATH # 在此处根据实际路径修改
56 | yolo = YOLO(model_path=model_path)
57 |
58 | # 创建视频编写器
59 | if os.path.exists('model_data/video.avi'):
60 | os.remove('model_data/video.avi')
61 | output_path = 'model_data/video.avi'
62 | fourcc = cv2.VideoWriter_fourcc(*'XVID')
63 | output_video = cv2.VideoWriter(output_path, fourcc, 20.0, (1280, 720))
64 |
65 | # 帧数显示
66 | start_time = time.time()
67 | frame_count = 0
68 |
69 | while True:
70 | # 接收数据
71 | data, addr = udp_socket.recvfrom(BUFFER_SIZE)
72 |
73 | # 添加接收到的数据到已接收的数据缓冲区
74 | received_data += data
75 |
76 | # 检查起始标识符
77 | start_marker = b"\xff\xd8\xff\xe0"
78 | start_pos = received_data.find(start_marker)
79 |
80 | if start_pos != -1:
81 | # 检查结束标识符
82 | end_marker = b"\xff\xd9"
83 | end_pos = received_data.find(end_marker, start_pos + len(start_marker))
84 |
85 | if end_pos != -1:
86 |
87 | data_length = end_pos - start_pos
88 | if data_length < 345600:
89 | # 继续接收数据,直到达到指定长度
90 | while data_length < 345600:
91 | additional_data, _ = udp_socket.recvfrom(BUFFER_SIZE)
92 | received_data += additional_data
93 | data_length = len(received_data) - start_pos
94 |
95 | # 检查是否出现新的结束符
96 | new_end_pos = received_data.find(end_marker, end_pos + len(end_marker))
97 | if new_end_pos != -1:
98 | # 更新结束符位置
99 | end_pos = new_end_pos
100 | data_length = end_pos - start_pos
101 |
102 | # 截取图像数据
103 | image_data = received_data[start_pos:end_pos + len(end_marker)]
104 |
105 | try:
106 | # 解码图像数据
107 | image = np.frombuffer(image_data, dtype=np.uint8)
108 | image = cv2.imdecode(image, cv2.IMREAD_UNCHANGED)
109 |
110 | # 填充破损的图像数据为全零数据
111 | if len(image.shape) == 3 and image.shape[2] != 3:
112 | filled_data = np.zeros((image.shape[0], image.shape[1], 3), dtype=np.uint8)
113 | filled_data[:image.shape[0], :image.shape[1], :image.shape[2]] = image
114 | image = filled_data
115 |
116 | # 执行目标检测
117 | detected_image = yolo.detect_image(Image.fromarray(image))
118 |
119 | # 将检测结果转换为OpenCV图像格式
120 | result_image = np.array(detected_image)
121 | #result_final = cv2.cvtColor(np.array(result_image), cv2.COLOR_BGR2RGB)
122 |
123 | # 裁剪画面
124 | result_height = result_image.shape[0]
125 | result_width = result_image.shape[1]
126 |
127 | crop_height = int(result_height * 0.99) # 要裁剪的高度(例如保留顶部25%的画面)
128 | crop_left = int(result_width * 0.01)
129 | crop_right = int(result_width * 0.99)
130 | result_image = result_image[:crop_height, crop_left:crop_right, :]
131 |
132 | # 将结果写入视频流
133 | output_video.write(result_image)
134 |
135 | # 在每一帧处理之后增加帧数计数
136 | frame_count += 1
137 | # 计算经过的时间
138 | elapsed_time = time.time() - start_time
139 | # 计算实时 FPS 值
140 | fps = (frame_count / elapsed_time)*3
141 | # 在图像的左上角绘制 FPS 值
142 | cv2.putText(result_image, f"FPS: {fps:.2f}", (10, 30), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 255), 1)
143 |
144 | # 显示图像
145 | cv2.imshow("Frame", result_image)
146 |
147 | # 清除已显示的图像数据
148 | received_data = received_data[end_pos + len(end_marker):]
149 |
150 | except Exception as e:
151 | print(f"Failed to decode image: {e}")
152 |
153 | else:
154 | # 未找到结束标识符,继续接收数据
155 | continue
156 |
157 | # 按下 'q' 键退出循环
158 | if cv2.waitKey(1) & 0xFF == ord('q'):
159 | break
160 |
161 | # 清理资源
162 | udp_socket.close()
163 | cv2.destroyAllWindows()
--------------------------------------------------------------------------------
/RTL/rtl/wr_ctrl.v:
--------------------------------------------------------------------------------
1 | `timescale 1ns / 1ps
2 | //////////////////////////////////////////////////////////////////////////////////
3 | // Company: Meyesemi
4 | // Engineer: Nill
5 | //
6 | // Create Date: 07/01/23 17:29:04
7 | // Design Name:
8 | // Module Name: wr_ctrl
9 | // Project Name:
10 | // Target Devices:
11 | // Tool Versions:
12 | // Description:
13 | //
14 | // Dependencies:
15 | //
16 | // Revision:
17 | // Revision 0.01 - File Created
18 | // Additional Comments:
19 | //
20 | //////////////////////////////////////////////////////////////////////////////////
21 | `define UD #1
22 |
23 | module wr_ctrl #(
24 | parameter CTRL_ADDR_WIDTH = 28,
25 | parameter MEM_DQ_WIDTH = 16
26 | )(
27 | input clk ,
28 | input rst_n ,
29 |
30 | input wr_en ,
31 | input [CTRL_ADDR_WIDTH-1:0] wr_addr ,
32 | input [3:0] wr_id ,
33 | input [3:0] wr_len ,
34 | output wr_cmd_done ,
35 | output wr_ready ,
36 | input wr_data_en ,
37 | input [MEM_DQ_WIDTH*8-1:0] wr_data ,
38 | output wr_bac ,
39 |
40 | output reg [CTRL_ADDR_WIDTH-1:0] axi_awaddr =0,
41 | output reg [3:0] axi_awid =0,
42 | output reg [3:0] axi_awlen =0,
43 | output [2:0] axi_awsize ,
44 | output [1:0] axi_awburst , //only support 2'b01: INCR
45 | input axi_awready ,
46 | output reg axi_awvalid =0,
47 |
48 | output [MEM_DQ_WIDTH*8-1:0] axi_wdata ,
49 | output [MEM_DQ_WIDTH -1 :0] axi_wstrb ,
50 | input axi_wlast ,
51 | output axi_wvalid ,
52 | input axi_wready ,
53 | input [3 : 0] axi_bid , // Master Interface Write Response.
54 | input [1 : 0] axi_bresp , // Write response. This signal indicates the status of the write transaction.
55 | input axi_bvalid , // Write response valid. This signal indicates that the channel is signaling a valid write response.
56 | output reg axi_bready =1, // Response ready. This signal indicates that the master can accept a write response.
57 | output reg [2:0] test_wr_state =0
58 | );
59 |
60 | localparam DQ_NUM = MEM_DQ_WIDTH/8;
61 |
62 | localparam E_IDLE = 3'd0;
63 | localparam E_WR = 3'd1;
64 | localparam E_END = 3'd2;
65 |
66 | assign axi_awburst = 2'b01;
67 | assign axi_awsize = 3'b110;
68 |
69 | assign axi_wstrb = {MEM_DQ_WIDTH{1'b1}};
70 |
71 | //===========================================================================
72 | // write ADDR channels
73 | //===========================================================================
74 | reg [3:0] cmd_cnt;
75 | always @(posedge clk)
76 | begin
77 | if (!rst_n) begin
78 | axi_awaddr <= 'b0;
79 | axi_awid <= 4'b0;
80 | axi_awlen <= 4'b0;
81 | axi_awvalid <= 1'b0;
82 | end
83 | else if(wr_en)
84 | begin
85 | axi_awid <= wr_id;
86 | axi_awaddr <= wr_addr;
87 | axi_awlen <= wr_len;
88 | axi_awvalid <= 1'b1;
89 | end
90 | else if(axi_awvalid & axi_awready)
91 | begin
92 | axi_awvalid <= 1'b0;
93 | axi_awid <= axi_awid;
94 | axi_awaddr <= axi_awaddr;
95 | axi_awlen <= axi_awlen;
96 | end
97 | else
98 | begin
99 | axi_awvalid <= axi_awvalid;
100 | axi_awid <= axi_awid;
101 | axi_awaddr <= axi_awaddr;
102 | axi_awlen <= axi_awlen;
103 | end
104 | end
105 |
106 | //----------------------------
107 | //Write Response (B) Channel
108 | //----------------------------
109 | always @(posedge clk)
110 | begin
111 | if (rst_n == 0)
112 | axi_bready <= 1'b0;
113 | else
114 | axi_bready <= 1'b1;
115 | end
116 |
117 | wire [3:0] trans_len/* synthesis PAP_MARK_DEBUG="true" */;
118 | wire burst_finish;
119 |
120 | assign trans_len = wr_len;
121 |
122 | always @(posedge clk)
123 | begin
124 | if (!rst_n)
125 | cmd_cnt <= 4'd0;
126 | else
127 | begin
128 | if(axi_awvalid & axi_awready)
129 | cmd_cnt <= cmd_cnt + 4'd1;
130 | else if(axi_wlast && axi_wvalid && axi_wready)
131 | cmd_cnt <= cmd_cnt - 4'd1;
132 | else
133 | cmd_cnt <= cmd_cnt;
134 | end
135 | end
136 |
137 | reg write_en;
138 | reg [3:0] axi_data_cnt;
139 | always @(posedge clk)
140 | begin
141 | if (!rst_n)
142 | write_en <= 1'b0;
143 | else if(axi_awvalid & axi_awready & cmd_cnt == 4'd0)
144 | write_en <= 1'b1;
145 |
146 | else if(axi_wvalid && axi_data_cnt == trans_len && axi_wready)
147 | write_en <= 1'b0;
148 | end
149 |
150 | assign wr_ready = axi_wready;
151 |
152 | always @(posedge clk)
153 | begin
154 | if (!rst_n)
155 | axi_data_cnt <= 4'd0;
156 | else if(cmd_cnt > 4'd1 && ~write_en)
157 | axi_data_cnt <= 4'd0;
158 | else
159 | begin
160 | if(axi_wready & axi_wvalid)
161 | begin
162 | if(axi_data_cnt == trans_len)
163 | axi_data_cnt <= 4'd0;
164 | else
165 | axi_data_cnt <= axi_data_cnt + 1'b1;
166 | end
167 | else
168 | axi_data_cnt <= axi_data_cnt;
169 | end
170 | end
171 |
172 | reg axi_wready_1d;
173 | assign burst_finish = ~axi_wready_1d && axi_wready;
174 |
175 | always @(posedge clk)
176 | begin
177 | axi_wready_1d <= axi_wready;
178 | end
179 |
180 | assign wr_cmd_done = axi_wlast;
181 | assign axi_wdata = wr_data ;
182 | assign axi_wvalid = axi_wready;
183 | assign wr_bac = axi_wvalid && (~axi_wready && axi_wready_1d);
184 |
185 | endmodule
186 |
--------------------------------------------------------------------------------
/RTL/rx/mac_rx_top.v:
--------------------------------------------------------------------------------
1 | //////////////////////////////////////////////////////////////////////////////////////
2 | //Module Name : mac_rx_top
3 | //Description : MAC RX Top
4 | //
5 | //////////////////////////////////////////////////////////////////////////////////////
6 | `timescale 1 ns/1 ns
7 | module mac_rx_top
8 | (
9 | input clk,
10 | input rst_n,
11 |
12 | input rx_dv,
13 | input [7:0] mac_rx_datain,
14 |
15 | input [31:0] local_ip_addr,
16 | input [47:0] local_mac_addr,
17 |
18 | input arp_reply_ack,
19 | output arp_reply_req,
20 | output [31:0] arp_rec_source_ip_addr,
21 | output [47:0] arp_rec_source_mac_addr,
22 | // output [31:0] ip_rec_source_ip_addr,
23 |
24 |
25 | output [7:0] udp_rec_ram_rdata ,
26 | input [10:0] udp_rec_ram_read_addr,
27 | output [15:0] udp_rec_data_length,
28 | output udp_rec_data_valid,
29 |
30 | output [7:0] mac_rx_dataout,
31 | output [15:0] upper_layer_data_length ,
32 | output [15:0] ip_total_data_length,
33 | output icmp_rx_req,
34 | output icmp_rev_error,
35 |
36 | output arp_found
37 | ) ;
38 |
39 | wire ip_rx_req ;
40 | wire udp_rx_req ;
41 | wire ip_rx_end ;
42 |
43 | wire arp_rx_req ;
44 | wire arp_rx_end ;
45 |
46 | wire [7:0] net_protocol ;
47 |
48 | wire [31:0] ip_rec_destination_addr ;
49 | wire [31:0] ip_rec_source_ip_addr ;
50 | wire ip_addr_check_error ;
51 | wire ip_checksum_error ;
52 | wire mac_rec_error ;
53 |
54 | wire [47:0] mac_rx_destination_mac_addr ;
55 | wire [47:0] mac_rx_source_mac_addr ;
56 |
57 | wire crcen ;
58 | wire crcre ;
59 | wire [7:0] crc_din ;
60 | wire [31:0] crc_result ;
61 |
62 |
63 |
64 | assign icmp_rev_error = (mac_rec_error | ip_checksum_error | ip_addr_check_error) ;
65 |
66 |
67 | crc c0
68 | (
69 | .Clk (clk),
70 | .Reset (crcre),
71 | .Data_in (crc_din),
72 | .Enable (crcen),
73 | .Crc (crc_result),
74 | .CrcNext ()
75 | ) ;
76 |
77 | mac_rx mac0
78 | (
79 | .clk (clk) ,
80 | .rst_n (rst_n) ,
81 |
82 | .rx_dv (rx_dv ),
83 | .mac_rx_datain (mac_rx_datain ),
84 |
85 | .crc_result (crc_result ) ,
86 | .crcen (crcen ),
87 | .crcre (crcre ),
88 | .crc_din (crc_din ),
89 |
90 | .checksum_err (ip_checksum_error ),
91 |
92 | .ip_rx_end (ip_rx_end ),
93 | .arp_rx_end (arp_rx_end),
94 |
95 | .ip_rx_req (ip_rx_req ),
96 | .arp_rx_req (arp_rx_req),
97 |
98 | .mac_rx_dataout (mac_rx_dataout ),
99 | .mac_rec_error (mac_rec_error),
100 |
101 | .mac_rx_destination_mac_addr (mac_rx_destination_mac_addr ),
102 | .mac_rx_source_mac_addr (mac_rx_source_mac_addr)
103 | );
104 |
105 |
106 | ip_rx ip0
107 | (
108 | .clk (clk),
109 | .rst_n (rst_n) ,
110 |
111 | .ip_rx_data (mac_rx_dataout) ,
112 | .ip_rx_req (ip_rx_req) ,
113 | .ip_rx_end (ip_rx_end) ,
114 | .icmp_rx_req (icmp_rx_req ),
115 |
116 | .local_ip_addr (local_ip_addr ),
117 | .local_mac_addr (local_mac_addr),
118 |
119 | .ip_addr_check_error (ip_addr_check_error),
120 | .mac_rx_destination_mac_addr (mac_rx_destination_mac_addr),
121 |
122 | .upper_layer_data_length (upper_layer_data_length ),
123 | .ip_total_data_length (ip_total_data_length ),
124 |
125 | .net_protocol (net_protocol),
126 | .ip_rec_source_addr (ip_rec_source_ip_addr),
127 | .ip_rec_destination_addr (ip_rec_destination_addr),
128 | .udp_rx_req (udp_rx_req),
129 | .ip_checksum_error (ip_checksum_error)
130 |
131 | ) ;
132 |
133 |
134 | udp_rx udp0
135 | (
136 | .clk (clk) ,
137 | .rst_n (rst_n) ,
138 |
139 | .udp_rx_data (mac_rx_dataout),
140 | .udp_rx_req (udp_rx_req),
141 |
142 | .mac_rec_error (mac_rec_error),
143 |
144 | .ip_addr_check_error (ip_addr_check_error),
145 |
146 | .net_protocol (net_protocol),
147 | .ip_rec_source_addr (ip_rec_source_ip_addr),
148 | .ip_rec_destination_addr (ip_rec_destination_addr),
149 | .ip_checksum_error (ip_checksum_error),
150 |
151 | .upper_layer_data_length (upper_layer_data_length ),
152 |
153 | .udp_rec_ram_rdata (udp_rec_ram_rdata),
154 | .udp_rec_ram_read_addr (udp_rec_ram_read_addr),
155 | .udp_rec_data_length (udp_rec_data_length ),
156 |
157 | .udp_rec_data_valid (udp_rec_data_valid)
158 | );
159 |
160 |
161 | arp_rx arp0
162 | (
163 | .clk (clk) ,
164 | .rst_n (rst_n),
165 |
166 | .local_ip_addr (local_ip_addr ),
167 | .local_mac_addr (local_mac_addr),
168 |
169 | .arp_rx_data (mac_rx_dataout ),
170 | .arp_rx_req (arp_rx_req ),
171 |
172 | .arp_reply_ack (arp_reply_ack ),
173 | .arp_rx_end (arp_rx_end ),
174 | .arp_reply_req (arp_reply_req ),
175 |
176 | .arp_rec_source_ip_addr (arp_rec_source_ip_addr ),
177 | .arp_rec_source_mac_addr (arp_rec_source_mac_addr ),
178 | .arp_found (arp_found )
179 |
180 | ) ;
181 |
182 |
183 | endmodule
184 |
--------------------------------------------------------------------------------
/RTL/tx/mac_tx.v:
--------------------------------------------------------------------------------
1 | //////////////////////////////////////////////////////////////////////////////////////
2 | //Module Name : mac_tx
3 | //Description : This module is MAC layer module, which receive data from ARP or IP module,
4 | // In this module, CRC checksum is generated
5 | //
6 | //////////////////////////////////////////////////////////////////////////////////////
7 | `timescale 1 ns/1 ns
8 | module mac_tx
9 | (
10 | input clk,
11 | input rst_n,
12 |
13 | input [31:0] crc_result ,
14 | output reg crcen,
15 | output reg crcre,
16 | output reg [7:0] crc_din,
17 |
18 | input [7:0] mac_frame_data, //data from ip or arp
19 | input mac_tx_ready, //ready from ip or arp
20 | input mac_tx_end, //end from ip or arp
21 |
22 | output reg [7:0] mac_tx_data,
23 | output reg mac_send_end,
24 | output reg mac_data_valid,
25 | output reg mac_data_req //request data from arp or ip
26 |
27 | ) ;
28 |
29 |
30 | reg [3:0] mac_tx_cnt ;
31 | reg [31:0] crc ;
32 |
33 | reg [7:0] mac_frame_data_dly ;
34 | reg mac_tx_end_dly ;
35 | reg [7:0] mac_tx_data_tmp ;
36 | reg mac_data_valid_tmp ;
37 | reg [15:0] timeout ;
38 |
39 |
40 | //MAC send FSM
41 | parameter SEND_IDLE = 6'b000_001 ;
42 | parameter SEND_START = 6'b000_010 ;
43 | parameter SEND_PREAMBLE = 6'b000_100 ;
44 | parameter SEND_DATA = 6'b001_000 ;
45 | parameter SEND_CRC = 6'b010_000 ;
46 | parameter SEND_END = 6'b100_000 ;
47 |
48 | reg [5:0] send_state ;
49 | reg [5:0] send_next_state ;
50 |
51 | always @(posedge clk or negedge rst_n)
52 | begin
53 | if (~rst_n)
54 | send_state <= SEND_START ;
55 | else
56 | send_state <= send_next_state ;
57 | end
58 |
59 | always @(*)
60 | begin
61 | case(send_state)
62 |
63 | SEND_START :
64 | begin
65 | if (mac_tx_ready)
66 | send_next_state <= SEND_PREAMBLE ;
67 | else
68 | send_next_state <= SEND_START ;
69 | end
70 | SEND_PREAMBLE :
71 | begin
72 | if (mac_tx_cnt == 7)
73 | send_next_state <= SEND_DATA ;
74 | else
75 | send_next_state <= SEND_PREAMBLE ;
76 | end
77 | SEND_DATA :
78 | begin
79 | if (mac_tx_end_dly)
80 | send_next_state <= SEND_CRC ;
81 | else if (timeout == 16'hffff)
82 | send_next_state <= SEND_END ;
83 | else
84 | send_next_state <= SEND_DATA ;
85 | end
86 | SEND_CRC :
87 | begin
88 | if (mac_tx_cnt == 4)
89 | send_next_state <= SEND_END ;
90 | else
91 | send_next_state <= SEND_CRC ;
92 | end
93 | SEND_END :
94 | send_next_state <= SEND_START ;
95 | default :
96 | send_next_state <= SEND_START ;
97 | endcase
98 | end
99 |
100 |
101 |
102 | always @(posedge clk or negedge rst_n)
103 | begin
104 | if (~rst_n)
105 | mac_send_end <= 1'b0 ;
106 | else if (send_state == SEND_END)
107 | mac_send_end <= 1'b1 ;
108 | else
109 | mac_send_end <= 1'b0 ;
110 | end
111 |
112 | always @(posedge clk or negedge rst_n)
113 | begin
114 | if (~rst_n)
115 | begin
116 | crcre <= 1'b1 ;
117 | crcen <= 1'b0 ;
118 | crc_din <= 8'd0 ;
119 | end
120 | else if (send_state == SEND_DATA || (send_state == SEND_PREAMBLE && mac_tx_cnt == 7))
121 | begin
122 | crcre <= 1'b0 ;
123 | crcen <= 1'b1 ;
124 | crc_din <= mac_frame_data ;
125 | end
126 | else
127 | begin
128 | crcre <= 1'b1 ;
129 | crcen <= 1'b0 ;
130 | crc_din <= 8'd0 ;
131 | end
132 | end
133 |
134 |
135 | always @(posedge clk or negedge rst_n)
136 | begin
137 | if (~rst_n)
138 | mac_data_valid_tmp <= 1'b0 ;
139 | else if (send_state == SEND_PREAMBLE || send_state == SEND_DATA || (send_state == SEND_CRC && mac_tx_cnt < 4))
140 | mac_data_valid_tmp <= 1'b1 ;
141 | else
142 | mac_data_valid_tmp <= 1'b0 ;
143 | end
144 |
145 | always @(posedge clk or negedge rst_n)
146 | begin
147 | if (~rst_n)
148 | mac_data_valid <= 1'b0 ;
149 | else
150 | mac_data_valid <= mac_data_valid_tmp ;
151 | end
152 | //request data from arp or ip
153 | always @(posedge clk or negedge rst_n)
154 | begin
155 | if (~rst_n)
156 | mac_data_req <= 1'b0 ;
157 | else if (send_state == SEND_PREAMBLE && mac_tx_cnt == 3)
158 | mac_data_req <= 1'b1 ;
159 | else
160 | mac_data_req <= 1'b0 ;
161 | end
162 | //timeout counter
163 | always @(posedge clk or negedge rst_n)
164 | begin
165 | if (~rst_n)
166 | timeout <= 16'd0 ;
167 | else if (send_state == SEND_DATA)
168 | timeout <= timeout + 1'b1 ;
169 | else
170 | timeout <= 16'd0 ;
171 | end
172 |
173 |
174 | always @(posedge clk or negedge rst_n)
175 | begin
176 | if (~rst_n)
177 | crc <= 32'hffffffff ;
178 | else if (crcen)
179 | crc <= crc_result ;
180 | end
181 |
182 | always @(posedge clk or negedge rst_n)
183 | begin
184 | if (~rst_n)
185 | begin
186 | mac_frame_data_dly <= 8'd0 ;
187 | mac_tx_end_dly <= 1'b0 ;
188 | end
189 | else
190 | begin
191 | mac_frame_data_dly <= mac_frame_data ;
192 | mac_tx_end_dly <= mac_tx_end ;
193 | end
194 | end
195 |
196 | always @(posedge clk or negedge rst_n)
197 | begin
198 | if (~rst_n)
199 | mac_tx_cnt <= 4'd0 ;
200 | else if (send_state == SEND_PREAMBLE || send_state == SEND_CRC)
201 | mac_tx_cnt <= mac_tx_cnt + 1'b1 ;
202 | else
203 | mac_tx_cnt <= 4'd0 ;
204 | end
205 | //mac send data frame
206 | always @(posedge clk or negedge rst_n)
207 | begin
208 | if (~rst_n)
209 | mac_tx_data_tmp <= 8'h00 ;
210 | else if (send_state == SEND_PREAMBLE)
211 | begin
212 | if (mac_tx_cnt < 7)
213 | mac_tx_data_tmp <= 8'h55 ;
214 | else
215 | mac_tx_data_tmp <= 8'hd5 ;
216 | end
217 | else if (send_state == SEND_DATA)
218 | mac_tx_data_tmp <= mac_frame_data_dly ;
219 | end
220 |
221 | always @(posedge clk or negedge rst_n)
222 | begin
223 | if (~rst_n)
224 | mac_tx_data <= 8'h00 ;
225 | else if (send_state == SEND_CRC)
226 | begin
227 | case(mac_tx_cnt)
228 | 4'd0 : mac_tx_data <= mac_tx_data_tmp ;
229 | 4'd1 : mac_tx_data <= {~crc[24], ~crc[25], ~crc[26], ~crc[27], ~crc[28], ~crc[29], ~crc[30], ~crc[31]} ;
230 | 4'd2 : mac_tx_data <= {~crc[16], ~crc[17], ~crc[18], ~crc[19], ~crc[20], ~crc[21], ~crc[22], ~crc[23]} ;
231 | 4'd3 : mac_tx_data <= {~crc[8], ~crc[9], ~crc[10], ~crc[11], ~crc[12], ~crc[13], ~crc[14], ~crc[15]} ;
232 | 4'd4 : mac_tx_data <= {~crc[0], ~crc[1], ~crc[2], ~crc[3], ~crc[4], ~crc[5], ~crc[6], ~crc[7]} ;
233 | default : mac_tx_data <= 8'h00 ;
234 | endcase
235 | end
236 | else
237 | mac_tx_data <= mac_tx_data_tmp ;
238 | end
239 |
240 | endmodule
241 |
--------------------------------------------------------------------------------
/RTL/rx/arp_rx.v:
--------------------------------------------------------------------------------
1 | //////////////////////////////////////////////////////////////////////////////////////
2 | //Module Name : arp_rx
3 | //Description : This module is used to receive ARP data and send ARP reply request
4 | //
5 | //////////////////////////////////////////////////////////////////////////////////////
6 | `timescale 1 ns/1 ns
7 | module arp_rx
8 | (
9 | input clk,
10 | input rst_n,
11 |
12 | input [31:0] local_ip_addr,
13 | input [47:0] local_mac_addr,
14 | input [7:0] arp_rx_data, //arp received data
15 | input arp_rx_req, //arp rx request from mac
16 | output reg arp_rx_end, //arp rx end
17 |
18 | input arp_reply_ack, //arp reply ack from arp reply module
19 | output reg arp_reply_req, //arp reply request to arp reply module
20 |
21 | output reg [31:0] arp_rec_source_ip_addr, //arp received source ip address
22 | output reg [47:0] arp_rec_source_mac_addr, //arp received mac address
23 | output reg arp_found //found destination mac address
24 | ) ;
25 |
26 | localparam ARP_REQUEST_CODE = 16'h0001 ;
27 | localparam ARP_REPLY_CODE = 16'h0002 ;
28 |
29 | reg [31:0] arp_rec_destination_ip_addr ;
30 | reg [47:0] arp_rec_destination_mac_addr ;
31 | reg [15:0] arp_rec_op ;
32 | reg [7:0] arp_rx_cnt ;
33 |
34 | parameter IDLE = 4'b0001 ;
35 | parameter ARP_REC_DATA = 4'b0010 ;
36 | parameter ARP_WAIT = 4'b0100 ;
37 | parameter ARP_END = 4'b1000 ;
38 |
39 | reg [3:0] state ;
40 | reg [3:0] next_state ;
41 |
42 | always @(posedge clk or negedge rst_n)
43 | begin
44 | if (~rst_n)
45 | state <= IDLE ;
46 | else
47 | state <= next_state ;
48 | end
49 |
50 | always @(*)
51 | begin
52 | case(state)
53 | IDLE :
54 | begin
55 | if (arp_rx_req)
56 | next_state <= ARP_REC_DATA ;
57 | else
58 | next_state <= IDLE ;
59 | end
60 | ARP_REC_DATA :
61 | begin
62 | if (arp_rx_cnt == 45)
63 | next_state <= ARP_WAIT ;
64 | else
65 | next_state <= ARP_REC_DATA ;
66 | end
67 | ARP_WAIT :
68 | begin
69 | if (arp_rx_cnt == 99)
70 | next_state <= ARP_END ;
71 | else
72 | next_state <= ARP_WAIT ;
73 | end
74 |
75 | ARP_END :
76 | next_state <= IDLE ;
77 |
78 | default :
79 | next_state <= IDLE ;
80 | endcase
81 | end
82 |
83 |
84 | always @(posedge clk or negedge rst_n)
85 | begin
86 | if (~rst_n)
87 | arp_rx_end <= 1'b0 ;
88 | else if (state == ARP_REC_DATA || arp_rx_cnt == 44)
89 | arp_rx_end <= 1'b1 ;
90 | else
91 | arp_rx_end <= 1'b0 ;
92 | end
93 |
94 | //received arp request
95 | always @(posedge clk or negedge rst_n)
96 | begin
97 | if (~rst_n)
98 | arp_reply_req <= 1'b0 ;
99 | else if (arp_rx_req)
100 | arp_reply_req <= 1'b0 ;
101 | else if (arp_reply_ack)
102 | arp_reply_req <= 1'b0 ;
103 | else if (state == ARP_END)
104 | begin
105 | if (arp_rec_op == ARP_REQUEST_CODE && arp_rec_destination_ip_addr == local_ip_addr)
106 | arp_reply_req <= 1'b1 ;
107 | end
108 | end
109 | //received arp reply
110 | always @(posedge clk or negedge rst_n)
111 | begin
112 | if (~rst_n)
113 | arp_found <= 1'b0 ;
114 | else if (state == ARP_END)
115 | begin
116 | if (arp_rec_op == ARP_REPLY_CODE && arp_rec_destination_ip_addr == local_ip_addr && arp_rec_destination_mac_addr == local_mac_addr)
117 | arp_found <= 1'b1 ;
118 | end
119 | else
120 | arp_found <= 1'b0 ;
121 | end
122 |
123 | always @(posedge clk or negedge rst_n)
124 | begin
125 | if (~rst_n)
126 | arp_rx_cnt <= 8'd0 ;
127 | else if (state == ARP_REC_DATA || state == ARP_WAIT)
128 | arp_rx_cnt <= arp_rx_cnt + 1'b1 ;
129 | else
130 | arp_rx_cnt <= 8'd0 ;
131 | end
132 |
133 | always @(posedge clk or negedge rst_n)
134 | begin
135 | if (~rst_n)
136 | arp_rec_op <= 16'd0 ;
137 | else if (state == ARP_REC_DATA && arp_rx_cnt == 8'd6)
138 | arp_rec_op[15:8] <= arp_rx_data ;
139 | else if (state == ARP_REC_DATA && arp_rx_cnt == 8'd7)
140 | arp_rec_op[7:0] <= arp_rx_data ;
141 | end
142 |
143 | always @(posedge clk or negedge rst_n)
144 | begin
145 | if (~rst_n)
146 | arp_rec_source_mac_addr <= 48'd0 ;
147 | else if (state == ARP_REC_DATA && arp_rx_cnt == 8'd8)
148 | arp_rec_source_mac_addr[47:40] <= arp_rx_data ;
149 | else if (state == ARP_REC_DATA && arp_rx_cnt == 8'd9)
150 | arp_rec_source_mac_addr[39:32] <= arp_rx_data ;
151 | else if (state == ARP_REC_DATA && arp_rx_cnt == 8'd10)
152 | arp_rec_source_mac_addr[31:24] <= arp_rx_data ;
153 | else if (state == ARP_REC_DATA && arp_rx_cnt == 8'd11)
154 | arp_rec_source_mac_addr[23:16] <= arp_rx_data ;
155 | else if (state == ARP_REC_DATA && arp_rx_cnt == 8'd12)
156 | arp_rec_source_mac_addr[15:8] <= arp_rx_data ;
157 | else if (state == ARP_REC_DATA && arp_rx_cnt == 8'd13)
158 | arp_rec_source_mac_addr[7:0] <= arp_rx_data ;
159 | end
160 |
161 | always @(posedge clk or negedge rst_n)
162 | begin
163 | if (~rst_n)
164 | arp_rec_source_ip_addr <= 32'd0 ;
165 | else if (state == ARP_REC_DATA && arp_rx_cnt == 8'd14)
166 | arp_rec_source_ip_addr[31:24] <= arp_rx_data ;
167 | else if (state == ARP_REC_DATA && arp_rx_cnt == 8'd15)
168 | arp_rec_source_ip_addr[23:16] <= arp_rx_data ;
169 | else if (state == ARP_REC_DATA && arp_rx_cnt == 8'd16)
170 | arp_rec_source_ip_addr[15:8] <= arp_rx_data ;
171 | else if (state == ARP_REC_DATA && arp_rx_cnt == 8'd17)
172 | arp_rec_source_ip_addr[7:0] <= arp_rx_data ;
173 | end
174 |
175 | always @(posedge clk or negedge rst_n)
176 | begin
177 | if (~rst_n)
178 | arp_rec_destination_mac_addr <= 48'd0 ;
179 | else if (state == ARP_REC_DATA && arp_rx_cnt == 8'd18)
180 | arp_rec_destination_mac_addr[47:40] <= arp_rx_data ;
181 | else if (state == ARP_REC_DATA && arp_rx_cnt == 8'd19)
182 | arp_rec_destination_mac_addr[39:32] <= arp_rx_data ;
183 | else if (state == ARP_REC_DATA && arp_rx_cnt == 8'd20)
184 | arp_rec_destination_mac_addr[31:24] <= arp_rx_data ;
185 | else if (state == ARP_REC_DATA && arp_rx_cnt == 8'd21)
186 | arp_rec_destination_mac_addr[23:16] <= arp_rx_data ;
187 | else if (state == ARP_REC_DATA && arp_rx_cnt == 8'd22)
188 | arp_rec_destination_mac_addr[15:8] <= arp_rx_data ;
189 | else if (state == ARP_REC_DATA && arp_rx_cnt == 8'd23)
190 | arp_rec_destination_mac_addr[7:0] <= arp_rx_data ;
191 | end
192 |
193 | always @(posedge clk or negedge rst_n)
194 | begin
195 | if (~rst_n)
196 | arp_rec_destination_ip_addr <= 32'd0 ;
197 | else if (state == ARP_REC_DATA && arp_rx_cnt == 8'd24)
198 | arp_rec_destination_ip_addr[31:24] <= arp_rx_data ;
199 | else if (state == ARP_REC_DATA && arp_rx_cnt == 8'd25)
200 | arp_rec_destination_ip_addr[23:16] <= arp_rx_data ;
201 | else if (state == ARP_REC_DATA && arp_rx_cnt == 8'd26)
202 | arp_rec_destination_ip_addr[15:8] <= arp_rx_data ;
203 | else if (state == ARP_REC_DATA && arp_rx_cnt == 8'd27)
204 | arp_rec_destination_ip_addr[7:0] <= arp_rx_data ;
205 | end
206 |
207 |
208 | endmodule
209 |
--------------------------------------------------------------------------------
/RTL/tx/udp_tx.v:
--------------------------------------------------------------------------------
1 | //////////////////////////////////////////////////////////////////////////////////////
2 | //Module Name : udp_tx
3 | //Description : This module is used to send UDP data and generate UDP checksum
4 | //
5 | //////////////////////////////////////////////////////////////////////////////////////
6 | `timescale 1 ns/1 ns
7 | module udp_tx
8 | (
9 | input clk,
10 | input rst_n,
11 |
12 | input [31:0] source_ip_addr,
13 | input [31:0] destination_ip_addr,
14 |
15 | input [15:0] udp_send_source_port,
16 | input [15:0] udp_send_destination_port,
17 | input [15:0] udp_send_data_length,
18 |
19 |
20 | input [7:0] fifo_data, //FIFO中的数据
21 | output reg fifo_rd_en, //FIFO读使能
22 | input [7:0] ram_wr_data,
23 | input ram_wr_en,
24 | output reg udp_ram_data_req,
25 |
26 | input udp_tx_req,
27 | input udp_data_req,
28 | output reg udp_tx_ready,
29 | output reg [7:0] udp_tx_data,
30 | output udp_tx_end
31 |
32 | ) ;
33 |
34 | reg [3:0] header_checksum_cnt ;
35 | reg checksum_finish ;
36 | reg [10:0] ram_write_addr ;
37 | reg [10:0] ram_read_addr ;
38 | reg [7:0] ram_rdata_d0 ;
39 | reg [7:0] ram_rdata_d1 ;
40 | reg [7:0] ram_wr_data_d0 ;
41 | reg [7:0] ram_wr_data_d1 ;
42 |
43 | wire [7:0] ram_rdata ;
44 | reg [5:0] ram_data_length ;
45 |
46 | reg [15:0] udp_send_cnt ;
47 | reg [15:0] udp_data_length ; //valid data length
48 | reg [15:0] udp_total_data_length ;//data length when transfer
49 |
50 | reg [15:0] timeout ;
51 |
52 |
53 |
54 |
55 | parameter IDLE = 7'b000_0001 ;
56 | parameter HEADER_CHECKSUM = 7'b000_0010 ;
57 | parameter GEN_CHECKSUM = 7'b000_0100 ;
58 | parameter GEN_ODD_CHECKSUM = 7'b000_1000 ;
59 | parameter GEN_CHECKSUM_END = 7'b001_0000 ;
60 | parameter SEND_WAIT = 7'b010_0000 ;
61 | parameter UDP_SEND = 7'b100_0000 ;
62 |
63 |
64 | reg [6:0] state ;
65 | reg [6:0] next_state ;
66 |
67 |
68 | always @(posedge clk or negedge rst_n)
69 | begin
70 | if (~rst_n)
71 | state <= IDLE ;
72 | else
73 | state <= next_state ;
74 | end
75 |
76 | always @(*)
77 | begin
78 | case(state)
79 | IDLE :
80 | begin
81 | if (udp_tx_req)
82 | next_state <= SEND_WAIT ;
83 | else
84 | next_state <= IDLE ;
85 | end
86 |
87 | SEND_WAIT :
88 | begin
89 | if (udp_data_req)
90 | next_state <= UDP_SEND ;
91 | else if (timeout == 16'hffff)
92 | next_state <= IDLE ;
93 | else
94 | next_state <= SEND_WAIT ;
95 | end
96 |
97 | UDP_SEND :
98 | begin
99 | if (udp_send_cnt == udp_total_data_length)
100 | next_state <= IDLE ;
101 | else
102 | next_state <= UDP_SEND ;
103 | end
104 | default :
105 | next_state <= IDLE ;
106 | endcase
107 | end
108 |
109 |
110 | always @(posedge clk or negedge rst_n)
111 | begin
112 | if (~rst_n)
113 | udp_tx_ready <= 1'b0 ;
114 | else if (state == SEND_WAIT)
115 | udp_tx_ready <= 1'b1 ;
116 | else
117 | udp_tx_ready <= 1'b0 ;
118 | end
119 |
120 |
121 | //timeout counter
122 | always @(posedge clk or negedge rst_n)
123 | begin
124 | if (~rst_n)
125 | ram_write_addr <= 11'd0 ;
126 | else if (ram_wr_en)
127 | ram_write_addr <= ram_write_addr + 1'b1 ;
128 | else
129 | ram_write_addr <= 11'd0 ;
130 | end
131 |
132 |
133 | //timeout counter
134 | always @(posedge clk or negedge rst_n)
135 | begin
136 | if (~rst_n)
137 | timeout <= 16'd0 ;
138 | else if (state == SEND_WAIT)
139 | timeout <= timeout + 1'b1 ;
140 | else
141 | timeout <= 16'd0 ;
142 | end
143 |
144 |
145 |
146 | always @(posedge clk or negedge rst_n)
147 | begin
148 | if(rst_n == 1'b0)
149 | begin
150 | ram_wr_data_d0 <= 8'd0 ;
151 | ram_wr_data_d1 <= 8'd0 ;
152 | end
153 | else
154 | begin
155 | ram_wr_data_d0 <= ram_wr_data ;
156 | ram_wr_data_d1 <= ram_wr_data_d0 ;
157 | end
158 | end
159 | //ram signal
160 |
161 | always @(posedge clk or negedge rst_n)
162 | begin
163 | if(rst_n == 1'b0)
164 | begin
165 | ram_rdata_d0 <= 8'd0 ;
166 | ram_rdata_d1 <= 8'd0 ;
167 | end
168 | else
169 | begin
170 | ram_rdata_d0 <= fifo_data ;
171 | ram_rdata_d1 <= ram_rdata_d0 ;
172 | end
173 | end
174 |
175 |
176 | always @(posedge clk or negedge rst_n)
177 | begin
178 | if(rst_n == 1'b0)
179 | fifo_rd_en <= 1'b0 ;
180 | else if (state == UDP_SEND && udp_send_cnt > 3 && udp_send_cnt < udp_total_data_length - 3)
181 | fifo_rd_en <= 1'b1 ;
182 | else
183 | fifo_rd_en <= 1'b0 ;
184 | end
185 |
186 | //checksum counter
187 | always @(posedge clk or negedge rst_n)
188 | begin
189 | if (~rst_n)
190 | udp_send_cnt <= 16'd0 ;
191 | else if (state == UDP_SEND)
192 | udp_send_cnt <= udp_send_cnt + 1'b1 ;
193 | else
194 | udp_send_cnt <= 16'd0 ;
195 | end
196 |
197 |
198 | //generate udp and ip data length
199 | always @(posedge clk or negedge rst_n)
200 | begin
201 | if(rst_n == 1'b0)
202 | begin
203 | udp_total_data_length <= 16'd0 ;
204 | udp_data_length <= 16'd0 ;
205 | end
206 | else
207 | begin
208 | udp_data_length <= udp_send_data_length + 8;
209 | if (udp_send_data_length < 18)
210 | udp_total_data_length <= 26 ;
211 | else
212 | udp_total_data_length <= udp_send_data_length + 8 ;
213 | end
214 | end
215 |
216 |
217 | //*****************************************************************************************//
218 | //send udp data
219 | //*****************************************************************************************//
220 | always @(posedge clk or negedge rst_n)
221 | begin
222 | if (~rst_n)
223 | udp_tx_data <= 8'h00 ;
224 | else if (state == UDP_SEND)
225 | begin
226 | case(udp_send_cnt)
227 | 16'd0 : udp_tx_data <= udp_send_source_port[15:8] ;
228 | 16'd1 : udp_tx_data <= udp_send_source_port[7:0] ;
229 | 16'd2 : udp_tx_data <= udp_send_destination_port[15:8] ;
230 | 16'd3 : udp_tx_data <= udp_send_destination_port[7:0] ;
231 | 16'd4 : udp_tx_data <= udp_data_length[15:8] ;
232 | 16'd5 : udp_tx_data <= udp_data_length[7:0] ;
233 | 16'd6 : udp_tx_data <= 8'h00 ;//checksum[15:8] ;
234 | 16'd7 : udp_tx_data <= 8'h00 ;//checksum[7:0] ;
235 | default :
236 | begin
237 | if (udp_data_length < 26)
238 | begin
239 | if (udp_send_cnt <= udp_data_length - 1)
240 | udp_tx_data <= ram_rdata_d0 ;
241 | else
242 | udp_tx_data <= 8'h00 ;
243 | end
244 | else
245 | udp_tx_data <= ram_rdata_d0 ;
246 | end
247 | endcase
248 | end
249 | else
250 | udp_tx_data <= 8'h00 ;
251 | end
252 |
253 | endmodule
254 |
--------------------------------------------------------------------------------
/RTL/mac/mac_top.v:
--------------------------------------------------------------------------------
1 | //////////////////////////////////////////////////////////////////////////////////////
2 | //Module Name : mac_top
3 | //Description :
4 | //
5 | //////////////////////////////////////////////////////////////////////////////////////
6 | `timescale 1 ns/1 ns
7 | module mac_top
8 | (
9 | input gmii_tx_clk ,
10 | input gmii_rx_clk ,
11 | input rst_n ,
12 | input [15:0] identify_code,
13 | input [47:0] source_mac_addr , //source mac address
14 | input [7:0] TTL,
15 | input [31:0] source_ip_addr,
16 | input [31:0] destination_ip_addr,
17 | input [15:0] udp_send_source_port,
18 | input [15:0] udp_send_destination_port,
19 | // output [31:0] ip_rec_source_ip_addr,
20 |
21 | input [7:0] fifo_data, //FIFO中的数据
22 | output fifo_rd_en, //FIFO读使能
23 |
24 | input [7:0] ram_wr_data,
25 | input ram_wr_en,
26 | output udp_ram_data_req,
27 | input [15:0] udp_send_data_length,
28 |
29 | input udp_tx_req,
30 | input arp_request_req,
31 | output mac_data_valid,
32 | output mac_send_end,
33 | output [7:0] mac_tx_data,
34 |
35 | input rx_dv,
36 | input [7:0] mac_rx_datain,
37 | output [7:0] udp_rec_ram_rdata ,
38 | input [10:0] udp_rec_ram_read_addr,
39 | output [15:0] udp_rec_data_length,
40 | output udp_rec_data_valid,
41 |
42 | output arp_found,
43 | output mac_not_exist
44 |
45 | ) ;
46 |
47 |
48 | wire arp_reply_ack ;
49 | wire arp_reply_req ;
50 | wire [31:0] arp_rec_source_ip_addr ;
51 | wire [47:0] arp_rec_source_mac_addr ;
52 | wire [47:0] destination_mac_addr ;
53 |
54 | wire [7:0] mac_rx_dataout ;
55 | wire [15:0] upper_layer_data_length ;
56 | wire icmp_rx_req ;
57 | wire icmp_rev_error ;
58 | wire upper_data_req ;
59 | wire icmp_tx_ready ;
60 | wire [7:0] icmp_tx_data ;
61 | wire icmp_tx_end ;
62 | wire icmp_tx_req ;
63 | wire [15:0] icmp_send_data_length ;
64 |
65 | mac_tx_top mac_tx0
66 | (
67 | .clk (gmii_tx_clk) ,
68 | .rst_n (rst_n) ,
69 |
70 | .destination_mac_addr (destination_mac_addr) , //destination mac address
71 | .source_mac_addr (source_mac_addr) , //source mac address
72 |
73 | .TTL (TTL),
74 | .source_ip_addr (source_ip_addr),
75 | .destination_ip_addr (destination_ip_addr),
76 |
77 | .udp_send_source_port (udp_send_source_port),
78 | .udp_send_destination_port (udp_send_destination_port),
79 |
80 | .arp_reply_ack (arp_reply_ack ),
81 | .arp_reply_req (arp_reply_req ),
82 | .arp_rec_source_ip_addr (arp_rec_source_ip_addr ),
83 | .arp_rec_source_mac_addr (arp_rec_source_mac_addr ),
84 | .arp_request_req (arp_request_req ),
85 |
86 | .fifo_data (fifo_data),
87 | .fifo_rd_en (fifo_rd_en),
88 | .ram_wr_data (ram_wr_data) ,
89 | .ram_wr_en (ram_wr_en),
90 | .udp_tx_req (udp_tx_req),
91 | .udp_send_data_length (udp_send_data_length ),
92 | .udp_ram_data_req (udp_ram_data_req ),
93 |
94 | .upper_data_req (upper_data_req ),
95 | .icmp_tx_ready (icmp_tx_ready ),
96 | .icmp_tx_data (icmp_tx_data ),
97 | .icmp_tx_end (icmp_tx_end ),
98 | .icmp_tx_req (icmp_tx_req ),
99 | .icmp_send_data_length (icmp_send_data_length),
100 | .identify_code (identify_code ),
101 | .mac_data_valid (mac_data_valid),
102 | .mac_send_end (mac_send_end),
103 | .mac_tx_data (mac_tx_data)
104 | ) ;
105 |
106 |
107 |
108 |
109 |
110 |
111 | mac_rx_top mac_rx0
112 | (
113 | .clk (gmii_rx_clk) ,
114 | .rst_n (rst_n) ,
115 |
116 | .rx_dv (rx_dv ),
117 | .mac_rx_datain (mac_rx_datain ),
118 |
119 | .local_ip_addr (source_ip_addr ),
120 | .local_mac_addr (source_mac_addr),
121 |
122 | .arp_reply_ack (arp_reply_ack ),
123 | .arp_reply_req (arp_reply_req ),
124 | .arp_rec_source_ip_addr (arp_rec_source_ip_addr ),
125 | .arp_rec_source_mac_addr (arp_rec_source_mac_addr ),
126 | // .ip_rec_source_ip_addr (ip_rec_source_ip_addr ),
127 |
128 | .udp_rec_ram_rdata (udp_rec_ram_rdata),
129 | .udp_rec_ram_read_addr (udp_rec_ram_read_addr),
130 | .udp_rec_data_length (udp_rec_data_length ),
131 | .udp_rec_data_valid (udp_rec_data_valid),
132 |
133 | .mac_rx_dataout (mac_rx_dataout ),
134 | .upper_layer_data_length (upper_layer_data_length ),
135 | .ip_total_data_length (icmp_send_data_length),
136 | .icmp_rx_req (icmp_rx_req ),
137 | .icmp_rev_error (icmp_rev_error ),
138 |
139 | .arp_found (arp_found )
140 | ) ;
141 |
142 |
143 | icmp_reply icmp0
144 | (
145 | .clk (gmii_rx_clk) ,
146 | .rst_n (rst_n) ,
147 |
148 | .icmp_rx_data (mac_rx_dataout ),
149 | .icmp_rx_req (icmp_rx_req ),
150 | .icmp_rev_error (icmp_rev_error ),
151 |
152 | .upper_layer_data_length (upper_layer_data_length ),
153 |
154 | .icmp_data_req (upper_data_req ),
155 | .icmp_tx_ready (icmp_tx_ready ),
156 | .icmp_tx_data (icmp_tx_data ),
157 | .icmp_tx_end (icmp_tx_end ),
158 | .icmp_tx_req (icmp_tx_req )
159 |
160 |
161 | );
162 |
163 |
164 | arp_cache cache0
165 | (
166 | .clk (gmii_tx_clk),
167 | .rst_n (rst_n),
168 | .arp_found (arp_found ),
169 | .arp_rec_source_ip_addr (arp_rec_source_ip_addr ),
170 | .arp_rec_source_mac_addr (arp_rec_source_mac_addr ),
171 | .destination_ip_addr (destination_ip_addr),
172 | .destination_mac_addr (destination_mac_addr) ,
173 | .mac_not_exist (mac_not_exist )
174 | );
175 | endmodule
176 |
--------------------------------------------------------------------------------
/RTL/rtl/rd_buf.v:
--------------------------------------------------------------------------------
1 | `timescale 1ns / 1ps
2 | //////////////////////////////////////////////////////////////////////////////////
3 | // Company: Meyesemi
4 | // Engineer: Nill
5 | //
6 | // Create Date: 15/03/23 15:02:21
7 | // Design Name:
8 | // Module Name: rd_buf
9 | // Project Name:
10 | // Target Devices:
11 | // Tool Versions:
12 | // Description:
13 | //
14 | // Dependencies:
15 | //
16 | // Revision:
17 | // Revision 0.01 - File Created
18 | // Additional Comments:
19 | //
20 | //////////////////////////////////////////////////////////////////////////////////
21 | `define UD #1
22 | module rd_buf #(
23 | parameter ADDR_WIDTH = 6'd27,
24 | parameter ADDR_OFFSET = 32'h0000_0000,
25 | parameter H_NUM = 12'd1920,
26 | parameter V_NUM = 12'd1080,
27 | parameter DQ_WIDTH = 12'd32,
28 | parameter LEN_WIDTH = 12'd16,
29 | parameter PIX_WIDTH = 12'd24,
30 | parameter LINE_ADDR_WIDTH = 16'd19,
31 | parameter FRAME_CNT_WIDTH = 16'd8
32 | ) (
33 | input ddr_clk,
34 | input ddr_rstn,
35 |
36 | input vout_clk,
37 | input rd_fsync,
38 | input rd_en,
39 | output vout_de,
40 | output [PIX_WIDTH- 1'b1 : 0] vout_data,
41 |
42 | input init_done,
43 |
44 | output ddr_rreq,
45 | output [ADDR_WIDTH- 1'b1 : 0] ddr_raddr,
46 | output [LEN_WIDTH- 1'b1 : 0] ddr_rd_len,
47 | input ddr_rrdy,
48 | input ddr_rdone,
49 |
50 | input [8*DQ_WIDTH- 1'b1 : 0] ddr_rdata,
51 | input ddr_rdata_en
52 | );
53 | localparam SIM = 1'b0;
54 | localparam RAM_WIDTH = 16'd32;
55 | localparam DDR_DATA_WIDTH = DQ_WIDTH * 8;
56 | localparam WR_LINE_NUM = H_NUM * PIX_WIDTH/RAM_WIDTH;
57 | localparam RD_LINE_NUM = WR_LINE_NUM * RAM_WIDTH/DDR_DATA_WIDTH;
58 | localparam DDR_ADDR_OFFSET= RD_LINE_NUM*DDR_DATA_WIDTH/DQ_WIDTH;
59 |
60 | //===========================================================================
61 | reg rd_fsync_1d;
62 | reg rd_en_1d,rd_en_2d;
63 | wire rd_rst;
64 | reg ddr_rstn_1d,ddr_rstn_2d;
65 | always @(posedge vout_clk)
66 | begin
67 | rd_fsync_1d <= rd_fsync;
68 | rd_en_1d <= rd_en;
69 | rd_en_2d <= rd_en_1d;
70 | ddr_rstn_1d <= ddr_rstn;
71 | ddr_rstn_2d <= ddr_rstn_1d;
72 | end
73 | assign rd_rst = ~rd_fsync_1d &rd_fsync;
74 |
75 | //===========================================================================
76 | reg wr_fsync_1d,wr_fsync_2d,wr_fsync_3d;
77 | wire wr_rst;
78 |
79 | reg wr_en_1d,wr_en_2d,wr_en_3d;
80 | reg wr_trig;
81 | reg [11:0] wr_line;
82 | always @(posedge ddr_clk)
83 | begin
84 | wr_fsync_1d <= rd_fsync;
85 | wr_fsync_2d <= wr_fsync_1d;
86 | wr_fsync_3d <= wr_fsync_2d;
87 |
88 | wr_en_1d <= rd_en;
89 | wr_en_2d <= wr_en_1d;
90 | wr_en_3d <= wr_en_2d;
91 |
92 | wr_trig <= wr_rst || (~wr_en_3d && wr_en_2d && wr_line != V_NUM);
93 | end
94 | always @(posedge ddr_clk)
95 | begin
96 | if(wr_rst || (~ddr_rstn))
97 | wr_line <= 12'd1;
98 | else if(wr_trig)
99 | wr_line <= wr_line + 12'd1;
100 | end
101 |
102 | assign wr_rst = ~wr_fsync_3d && wr_fsync_2d;
103 |
104 | //==========================================================================
105 | reg [FRAME_CNT_WIDTH - 1'b1 :0] wr_frame_cnt=0;
106 | always @(posedge ddr_clk)
107 | begin
108 | if(wr_rst)
109 | wr_frame_cnt <= wr_frame_cnt + 1'b1;
110 | else
111 | wr_frame_cnt <= wr_frame_cnt;
112 | end
113 |
114 | reg [LINE_ADDR_WIDTH - 1'b1 :0] wr_cnt;
115 | always @(posedge ddr_clk)
116 | begin
117 | if(wr_rst)
118 | wr_cnt <= 9'd0;
119 | else if(ddr_rdone)
120 | wr_cnt <= wr_cnt + DDR_ADDR_OFFSET;
121 | else
122 | wr_cnt <= wr_cnt;
123 | end
124 |
125 | assign ddr_rreq = wr_trig;
126 | assign ddr_raddr = {wr_frame_cnt[0],wr_cnt} + ADDR_OFFSET;
127 | assign ddr_rd_len = RD_LINE_NUM;
128 |
129 | reg [ 8:0] wr_addr;
130 | reg [11:0] rd_addr;
131 | wire [RAM_WIDTH-1:0] rd_data;
132 |
133 | //===========================================================================
134 | always @(posedge ddr_clk)
135 | begin
136 | if(wr_rst)
137 | wr_addr <= (SIM == 1'b1) ? 9'd180 : 9'd0;
138 | else if(ddr_rdata_en)
139 | wr_addr <= wr_addr + 9'd1;
140 | else
141 | wr_addr <= wr_addr;
142 | end
143 |
144 | rd_fram_buf rd_fram_buf (
145 | .wr_data ( ddr_rdata ),// input [255:0]
146 | .wr_addr ( wr_addr ),// input [8:0]
147 | .wr_en ( ddr_rdata_en ),// input
148 | .wr_clk ( ddr_clk ),// input
149 | .wr_rst ( ~ddr_rstn ),// input
150 | .rd_addr ( rd_addr ),// input [11:0]
151 | .rd_data ( rd_data ),// output [31:0]
152 | .rd_clk ( vout_clk ),// input
153 | .rd_rst ( ~ddr_rstn_2d ) // input
154 | );
155 |
156 | reg [1:0] rd_cnt;
157 | wire read_en;
158 | always @(posedge vout_clk)
159 | begin
160 | if(rd_en)
161 | rd_cnt <= rd_cnt + 1'b1;
162 | else
163 | rd_cnt <= 2'd0;
164 | end
165 |
166 | always @(posedge vout_clk)
167 | begin
168 | if(rd_rst)
169 | rd_addr <= 'd0;
170 | else if(read_en)
171 | rd_addr <= rd_addr + 1'b1;
172 | else
173 | rd_addr <= rd_addr;
174 | end
175 |
176 | reg [PIX_WIDTH- 1'b1 : 0] read_data;
177 | reg [RAM_WIDTH-1:0] rd_data_1d;
178 | always @(posedge vout_clk)
179 | begin
180 | rd_data_1d <= rd_data;
181 | end
182 |
183 | generate
184 | if(PIX_WIDTH == 6'd24)
185 | begin
186 | assign read_en = rd_en && (rd_cnt != 2'd3);
187 |
188 | always @(posedge vout_clk)
189 | begin
190 | if(rd_en_1d)
191 | begin
192 | if(rd_cnt[1:0] == 2'd1)
193 | read_data <= rd_data[PIX_WIDTH-1:0];
194 | else if(rd_cnt[1:0] == 2'd2)
195 | read_data <= {rd_data[15:0],rd_data_1d[31:PIX_WIDTH]};
196 | else if(rd_cnt[1:0] == 2'd3)
197 | read_data <= {rd_data[7:0],rd_data_1d[31:16]};
198 | else
199 | read_data <= rd_data_1d[31:8];
200 | end
201 | else
202 | read_data <= 'd0;
203 | end
204 | end
205 | else if(PIX_WIDTH == 6'd16)
206 | begin
207 | assign read_en = rd_en && (rd_cnt[0] != 1'b1);
208 |
209 | always @(posedge vout_clk)
210 | begin
211 | if(rd_en_1d)
212 | begin
213 | if(rd_cnt[0])
214 | read_data <= rd_data[15:0];
215 | else
216 | read_data <= rd_data_1d[31:16];
217 | end
218 | else
219 | read_data <= 'd0;
220 | end
221 | end
222 | else
223 | begin
224 | assign read_en = rd_en;
225 |
226 | always @(posedge vout_clk)
227 | begin
228 | read_data <= rd_data;
229 | end
230 | end
231 | endgenerate
232 |
233 | assign vout_de = rd_en_2d;
234 | assign vout_data = read_data;
235 |
236 | endmodule
237 |
--------------------------------------------------------------------------------
/RTL/mac/mac_test.v:
--------------------------------------------------------------------------------
1 | //////////////////////////////////////////////////////////////////////////////////////
2 | //Module Name : mac_top
3 | //Description :
4 | //
5 | //////////////////////////////////////////////////////////////////////////////////////
6 | `timescale 1 ns/1 ns
7 | module mac_test
8 | (
9 | input rst_n ,
10 | input cmos_vsync,
11 | input cmos_href,
12 | input reg_conf_done,
13 | // input vsync_posedge,
14 | // input [15:0] identify_code,
15 | input [15:0] udp_send_data_length,
16 | input [7:0] fifo_data, //FIFO中的数据
17 | input [10:0] fifo_data_count, //FIFO中的数据数量
18 | output reg fifo_rd_en, //FIFO读使��?
19 |
20 | input gmii_tx_clk ,
21 | input gmii_rx_clk ,
22 | input gmii_rx_dv,
23 | input [7:0] gmii_rxd,
24 | output reg gmii_tx_en,
25 | output reg [7:0] gmii_txd
26 |
27 | );
28 |
29 |
30 |
31 | reg gmii_rx_dv_d0 ;
32 | reg [7:0] gmii_rxd_d0 ;
33 | wire gmii_tx_en_tmp ;
34 | wire [7:0] gmii_txd_tmp ;
35 |
36 | reg [9:0] vsync_posedge_buf ;
37 | reg [15:0] identify_code_d0 ;
38 |
39 | wire udp_tx_req ;
40 | wire arp_request_req ;
41 | wire mac_send_end ;
42 | reg write_end ;
43 |
44 | wire [7:0] udp_rec_ram_rdata ;
45 | reg [10:0] udp_rec_ram_read_addr ;
46 | wire [15:0] udp_rec_data_length ;
47 | wire udp_rec_data_valid ;
48 |
49 | reg [10:0] fifo_rdusedw ;
50 | reg [31:0] wait_cnt ;
51 |
52 |
53 |
54 |
55 |
56 | wire button_negedge ;
57 |
58 | wire mac_not_exist ;
59 | wire arp_found ;
60 | wire fifo_rd_en_tmp ;
61 |
62 | parameter IDLE = 10'b0000000001 ;
63 | parameter ARP_REQ = 10'b0000000010 ;
64 | parameter ARP_SEND = 10'b0000000100 ;
65 | parameter ARP_WAIT = 10'b0000001000 ;
66 | parameter GEN_REQ = 10'b0000010000 ;
67 | parameter CHECK_FIFO = 10'b0000100000 ;
68 | parameter SEND = 10'b0001000000 ;
69 | parameter WAIT = 10'b0010000000 ;
70 | parameter CHECK_ARP = 10'b0100000000 ;
71 | parameter WAIT_SYNC = 10'b1000000000 ;
72 |
73 |
74 | (* MARK_DEBUG="true" *)reg [9:0] state ;
75 |
76 | always @(posedge gmii_tx_clk or negedge rst_n)
77 | begin
78 | if (~rst_n)
79 | state <= IDLE ;
80 | else
81 | begin
82 | case(state)
83 | IDLE : begin
84 | if (wait_cnt == 32'd1250000 ) //wait for 10ms
85 | state <= ARP_REQ ;
86 | else
87 | state <= IDLE ;
88 | end
89 |
90 | ARP_REQ : state <= ARP_SEND ;
91 | ARP_SEND : begin
92 | if (mac_send_end)
93 | state <= ARP_WAIT ;
94 | else
95 | state <= ARP_SEND ;
96 | end
97 | ARP_WAIT : begin
98 | if (arp_found)
99 | state <= WAIT_SYNC ;
100 | else if (wait_cnt == 32'd125_000_000)
101 | state <= ARP_REQ ;
102 | else
103 | state <= ARP_WAIT ;
104 | end
105 | WAIT_SYNC : begin
106 | if (vsync_posedge_buf[9])
107 | state <= CHECK_FIFO ;
108 | else
109 | state <= WAIT_SYNC ;
110 | end
111 | CHECK_FIFO : begin
112 | if (fifo_rdusedw > 11'd1000)
113 | state <= GEN_REQ ;
114 | else if (wait_cnt== 32'd125_000_000)
115 | state <= WAIT_SYNC ;
116 | else
117 | state <= CHECK_FIFO ;
118 | end
119 |
120 | GEN_REQ : begin
121 | state <= SEND ;
122 | end
123 |
124 | SEND : begin
125 | if (mac_send_end)
126 | state <= CHECK_ARP ;
127 | else
128 | state <= SEND ;
129 | end
130 |
131 | WAIT : begin
132 | if (wait_cnt == 32'd2048)
133 | state <= CHECK_ARP ;
134 | else
135 | state <= WAIT ;
136 | end
137 | CHECK_ARP : begin
138 | if (mac_not_exist)
139 | state <= ARP_REQ ;
140 | else
141 | state <= CHECK_FIFO ;
142 | end
143 | default : state <= IDLE ;
144 | endcase
145 | end
146 | end
147 |
148 | always@(posedge gmii_rx_clk or negedge rst_n)
149 | begin
150 | if(rst_n == 1'b0)
151 | begin
152 | gmii_rx_dv_d0 <= 1'b0 ;
153 | gmii_rxd_d0 <= 8'd0 ;
154 | end
155 | else
156 | begin
157 | gmii_rx_dv_d0 <= gmii_rx_dv ;
158 | gmii_rxd_d0 <= gmii_rxd ;
159 | end
160 | end
161 |
162 | always@(posedge gmii_tx_clk or negedge rst_n)
163 | begin
164 | if(rst_n == 1'b0)
165 | begin
166 | gmii_tx_en <= 1'b0 ;
167 | gmii_txd <= 8'd0 ;
168 | end
169 | else
170 | begin
171 | gmii_tx_en <= gmii_tx_en_tmp ;
172 | gmii_txd <= gmii_txd_tmp ;
173 | end
174 | end
175 |
176 | mac_top mac_top0
177 | (
178 | .gmii_tx_clk (gmii_tx_clk) ,
179 | .gmii_rx_clk (gmii_rx_clk) ,
180 | .rst_n (rst_n) ,
181 |
182 | .source_mac_addr (48'h00_0a_35_01_fe_c0) , //source mac address
183 | .identify_code (identify_code_d0 ),
184 | .TTL (8'h80),
185 | .source_ip_addr (32'hc0a80002),
186 | .destination_ip_addr (32'hc0a80003),
187 | .udp_send_source_port (16'h1f90),
188 | .udp_send_destination_port (16'h1f90),
189 |
190 | .fifo_data (fifo_data),
191 | .fifo_rd_en (fifo_rd_en_tmp),
192 | .ram_wr_data () ,
193 | .ram_wr_en (),
194 | .udp_ram_data_req (),
195 | .udp_send_data_length (udp_send_data_length),
196 |
197 | .udp_tx_req (udp_tx_req),
198 | .arp_request_req (arp_request_req ),
199 |
200 | .mac_send_end (mac_send_end),
201 | .mac_data_valid (gmii_tx_en_tmp),
202 | .mac_tx_data (gmii_txd_tmp),
203 | .rx_dv (gmii_rx_dv_d0 ),
204 | .mac_rx_datain (gmii_rxd_d0 ),
205 |
206 | .udp_rec_ram_rdata (udp_rec_ram_rdata),
207 | .udp_rec_ram_read_addr (udp_rec_ram_read_addr),
208 | .udp_rec_data_length (udp_rec_data_length ),
209 |
210 | .udp_rec_data_valid (udp_rec_data_valid),
211 | .arp_found (arp_found ),
212 | .mac_not_exist (mac_not_exist )
213 | ) ;
214 |
215 | assign udp_tx_req = (state == GEN_REQ) ;
216 | assign arp_request_req = (state == ARP_REQ) ;
217 |
218 | always @(posedge gmii_tx_clk or negedge rst_n)
219 | begin
220 | if (!rst_n)
221 | fifo_rdusedw <= 11'd0 ;
222 | else
223 | fifo_rdusedw <= fifo_data_count ;
224 | end
225 |
226 | reg cmos_vsync_d0 ;
227 | reg cmos_vsync_d1 ;
228 | reg cmos_vsync_d2 ;
229 | wire vsync_posedge ;
230 | reg cmos_href_d0 ;
231 | reg cmos_href_d1 ;
232 | reg cmos_href_d2 ;
233 | reg [15:0] identify_code ;
234 |
235 | always @(posedge gmii_tx_clk or negedge rst_n)
236 | begin
237 | if (!rst_n)
238 | begin
239 | cmos_vsync_d0 <= 1'b0 ;
240 | cmos_vsync_d1 <= 1'b0 ;
241 | cmos_vsync_d2 <= 1'b0 ;
242 | end
243 | else
244 | begin
245 | cmos_vsync_d0 <= cmos_vsync ;
246 | cmos_vsync_d1 <= cmos_vsync_d0 ;
247 | cmos_vsync_d2 <= cmos_vsync_d1 ;
248 | end
249 | end
250 |
251 | assign vsync_posedge = ~cmos_vsync_d2 & cmos_vsync_d1 ;
252 |
253 | always @(posedge gmii_tx_clk or negedge rst_n)
254 | begin
255 | if (!rst_n)
256 | begin
257 | cmos_href_d0 <= 1'b0 ;
258 | cmos_href_d1 <= 1'b0 ;
259 | cmos_href_d2 <= 1'b0 ;
260 | end
261 | else
262 | begin
263 | cmos_href_d0 <= cmos_href ;
264 | cmos_href_d1 <= cmos_href_d0 ;
265 | cmos_href_d2 <= cmos_href_d1 ;
266 | end
267 | end
268 |
269 | always @(posedge gmii_tx_clk or negedge rst_n)
270 | begin
271 | if (!rst_n)
272 | identify_code <= 16'd0 ;
273 | else if (vsync_posedge)
274 | identify_code <= 16'd0 ;
275 | else if (cmos_href_d1 == 1'b1 && cmos_href_d2 == 1'b0)
276 | identify_code <= identify_code + 1'b1 ;
277 | end
278 |
279 |
280 | always@(posedge gmii_tx_clk or negedge rst_n)
281 | begin
282 | if(rst_n == 1'b0)
283 | wait_cnt <= 0 ;
284 | else if (state == IDLE ||state == CHECK_FIFO || state == WAIT || state == ARP_WAIT)
285 | wait_cnt <= wait_cnt + 1'b1 ;
286 | else
287 | wait_cnt <= 0 ;
288 | end
289 |
290 | always@(posedge gmii_tx_clk or negedge rst_n)
291 | begin
292 | if(rst_n == 1'b0)
293 | vsync_posedge_buf <= 10'd0 ;
294 | else
295 | vsync_posedge_buf <= {vsync_posedge_buf[8:0], vsync_posedge} ;
296 | end
297 |
298 | always@(posedge gmii_tx_clk or negedge rst_n)
299 | begin
300 | if(rst_n == 1'b0)
301 | identify_code_d0 <= 10'd0 ;
302 | else if (state == CHECK_FIFO)
303 | identify_code_d0 <= identify_code ;
304 | end
305 |
306 | always@(posedge gmii_tx_clk or negedge rst_n)
307 | begin
308 | if(rst_n == 1'b0)
309 | fifo_rd_en <= 1'b0 ;
310 | else
311 | fifo_rd_en <= fifo_rd_en_tmp ;
312 | end
313 |
314 | endmodule
315 |
--------------------------------------------------------------------------------
/RTL/rtl/ms72xx_ctl.v:
--------------------------------------------------------------------------------
1 | `timescale 1ns / 1ps
2 | //////////////////////////////////////////////////////////////////////////////////
3 | // Company:Meyesemi
4 | // Engineer: Will
5 | //
6 | // Create Date: 2023-01-29 20:31
7 | // Design Name:
8 | // Module Name:
9 | // Project Name:
10 | // Target Devices: Pango
11 | // Tool Versions:
12 | // Description:
13 | //
14 | // Dependencies:
15 | //
16 | // Revision:
17 | // Revision 1.0 - File Created
18 | // Additional Comments:
19 | //
20 | //////////////////////////////////////////////////////////////////////////////////
21 |
22 | `define UD #1
23 | module ms72xx_ctl(
24 | input clk,
25 | input rst_n,
26 | output init_over_tx,
27 | output init_over_rx,
28 | output iic_tx_scl,
29 | inout iic_tx_sda,
30 | output iic_scl,
31 | inout iic_sda
32 | );
33 | reg rstn_temp1,rstn_temp2;
34 | reg rstn;
35 | always @(posedge clk or negedge rst_n)
36 | begin
37 | if(!rst_n)
38 | rstn_temp1 <= 1'b0;
39 | else
40 | rstn_temp1 <= rst_n;
41 | end
42 |
43 | always @(posedge clk)
44 | begin
45 | rstn_temp2 <= rstn_temp1;
46 | rstn <= rstn_temp2;
47 | end
48 |
49 | wire init_over_rx;
50 | wire [7:0] device_id_rx;
51 | wire iic_trig_rx ;
52 | wire w_r_rx ;
53 | wire [15:0] addr_rx ;
54 | wire [ 7:0] data_in_rx ;
55 | wire busy_rx ;
56 | wire [ 7:0] data_out_rx ;
57 | wire byte_over_rx;
58 |
59 | wire [7:0] device_id_tx;
60 | wire iic_trig_tx ;
61 | wire w_r_tx ;
62 | wire [15:0] addr_tx /*synthesis PAP_MARK_DEBUG="true"*/;
63 | wire [ 7:0] data_in_tx ;
64 | wire busy_tx ;
65 | wire [ 7:0] data_out_tx ;
66 | wire byte_over_tx;
67 |
68 |
69 | ms7200_ctl ms7200_ctl(
70 | .clk ( clk ),//input
71 | .rstn ( rstn ),//input
72 |
73 | .init_over ( init_over_rx ),//output reg
74 | .device_id ( device_id_rx ),//output [7:0]
75 | .iic_trig ( iic_trig_rx ),//output reg
76 | .w_r ( w_r_rx ),//output reg
77 | .addr ( addr_rx ),//output reg [15:0]
78 | .data_in ( data_in_rx ),//output reg [ 7:0]
79 | .busy ( busy_rx ),//input
80 | .data_out ( data_out_rx ),//input [ 7:0]
81 | .byte_over ( byte_over_rx ) //input
82 | );
83 |
84 | ms7210_ctl ms7210_ctl(
85 | .clk ( clk ),//input
86 | .rstn ( rstn ),//input rstn),//
87 | .init_over ( init_over_tx ),//output reg
88 | .device_id ( device_id_tx ),//output [7:0]
89 | .iic_trig ( iic_trig_tx ),//output reg
90 | .w_r ( w_r_tx ),//output reg
91 | .addr ( addr_tx ),//output reg [15:0]
92 | .data_in ( data_in_tx ),//output reg [ 7:0]
93 | .busy ( busy_tx ),//input
94 | .data_out ( data_out_tx ),//input [ 7:0]
95 | .byte_over ( byte_over_tx ) //input
96 | );
97 |
98 |
99 |
100 | wire sda_in/*synthesis PAP_MARK_DEBUG="true"*/;
101 | wire sda_out/*synthesis PAP_MARK_DEBUG="true"*/;
102 | wire sda_out_en/*synthesis PAP_MARK_DEBUG="true"*/;
103 | iic_dri #(
104 | .CLK_FRE ( 27'd10_000_000 ),//parameter CLK_FRE = 27'd50_000_000,//system clock frequency
105 | .IIC_FREQ ( 20'd400_000 ),//parameter IIC_FREQ = 20'd400_000, //I2c clock frequency
106 | .T_WR ( 10'd1 ),//parameter T_WR = 10'd5, //I2c transmit delay ms
107 | .ADDR_BYTE ( 2'd2 ),//parameter ADDR_BYTE = 2'd1, //I2C addr byte number
108 | .LEN_WIDTH ( 8'd3 ),//parameter LEN_WIDTH = 8'd3, //I2C transmit byte width
109 | .DATA_BYTE ( 2'd1 ) //parameter DATA_BYTE = 2'd1 //I2C data byte number
110 | )iic_dri_rx(
111 | .clk ( clk ),//input clk,
112 | .rstn ( rstn ),//input rstn,
113 | .device_id ( device_id_rx ),//input device_id,
114 | .pluse ( iic_trig_rx ),//input pluse, //I2C transmit trigger
115 | .w_r ( w_r_rx ),//input w_r, //I2C transmit direction 1:send 0:receive
116 | .byte_len ( 4'd1 ),//input [LEN_WIDTH:0] byte_len, //I2C transmit data byte length of once trigger
117 |
118 | .addr ( addr_rx ),//input [7:0] addr, //I2C transmit addr
119 | .data_in ( data_in_rx ),//input [7:0] data_in, //I2C send data
120 |
121 | .busy ( busy_rx ),//output reg busy=0, //I2C bus status
122 |
123 | .byte_over ( byte_over_rx ),//output reg byte_over=0, //I2C byte transmit over flag
124 | .data_out ( data_out_rx ),//output reg[7:0] data_out, //I2C receive data
125 |
126 | .scl ( iic_scl ),//output scl,
127 | .sda_in ( sda_in ),//input sda_in,
128 | .sda_out ( sda_out ),//output reg sda_out=1'b1,
129 | .sda_out_en ( sda_out_en ) //output sda_out_en
130 | );
131 |
132 | assign iic_sda = sda_out_en ? sda_out : 1'bz;
133 | assign sda_in = iic_sda;
134 |
135 | wire sda_tx_in/*synthesis PAP_MARK_DEBUG="true"*/;
136 | wire sda_tx_out/*synthesis PAP_MARK_DEBUG="true"*/;
137 | wire sda_tx_out_en/*synthesis PAP_MARK_DEBUG="true"*/;
138 | iic_dri #(
139 | .CLK_FRE ( 27'd10_000_000 ),//parameter CLK_FRE = 27'd50_000_000,//system clock frequency
140 | .IIC_FREQ ( 20'd400_000 ),//parameter IIC_FREQ = 20'd400_000, //I2c clock frequency
141 | .T_WR ( 10'd1 ),//parameter T_WR = 10'd5, //I2c transmit delay ms
142 | .ADDR_BYTE ( 2'd2 ),//parameter ADDR_BYTE = 2'd1, //I2C addr byte number
143 | .LEN_WIDTH ( 8'd3 ),//parameter LEN_WIDTH = 8'd3, //I2C transmit byte width
144 | .DATA_BYTE ( 2'd1 ) //parameter DATA_BYTE = 2'd1 //I2C data byte number
145 | )iic_dri_tx(
146 | .clk ( clk ),//input clk,
147 | .rstn ( rstn ),//input rstn,
148 | .device_id ( device_id_tx ),//input device_id,
149 | .pluse ( iic_trig_tx ),//input pluse, //I2C transmit trigger
150 | .w_r ( w_r_tx ),//input w_r, //I2C transmit direction 1:send 0:receive
151 | .byte_len ( 4'd1 ),//input [LEN_WIDTH:0] byte_len, //I2C transmit data byte length of once trigger
152 |
153 | .addr ( addr_tx ),//input [7:0] addr, //I2C transmit addr
154 | .data_in ( data_in_tx ),//input [7:0] data_in, //I2C send data
155 |
156 | .busy ( busy_tx ),//output reg busy=0, //I2C bus status
157 |
158 | .byte_over ( byte_over_tx ),//output reg byte_over=0, //I2C byte transmit over flag
159 | .data_out ( data_out_tx ),//output reg[7:0] data_out, //I2C receive data
160 |
161 | .scl ( iic_tx_scl ),//output scl,
162 | .sda_in ( sda_tx_in ),//input sda_in,
163 | .sda_out ( sda_tx_out ),//output reg sda_out=1'b1,
164 | .sda_out_en ( sda_tx_out_en ) //output sda_out_en
165 | );
166 |
167 | assign iic_tx_sda = sda_tx_out_en ? sda_tx_out : 1'bz;
168 | assign sda_tx_in = iic_tx_sda;
169 | // GTP_IOBUF #(
170 | // .IOSTANDARD ( "DEFAULT" ),
171 | // .SLEW_RATE ( "SLOW" ),
172 | // .DRIVE_STRENGTH ( "8" ),
173 | // .TERM_DDR ( "ON" )
174 | // ) GTP_IOBUF (
175 | // .IO ( iic_sda ),// INOUT
176 | // .O ( sda_in ), // OUTPUT
177 | // .I ( sda_out ), // INPUT
178 | // .T ( sda_out_en ) // INPUT
179 | // );
180 |
181 | endmodule
182 |
--------------------------------------------------------------------------------
/RTL/tx/arp_tx.v:
--------------------------------------------------------------------------------
1 | //////////////////////////////////////////////////////////////////////////////////////
2 | //Module Name : arp_tx
3 | //Description : This module is used to send arp data when request arp or reply arp
4 | //
5 | //////////////////////////////////////////////////////////////////////////////////////
6 | `timescale 1 ns/1 ns
7 | module arp_tx
8 | (
9 | input clk ,
10 | input rst_n ,
11 |
12 | input [47:0] destination_mac_addr , //destination mac address
13 | input [47:0] source_mac_addr , //source mac address
14 | input [31:0] source_ip_addr , //source ip address
15 | input [31:0] destination_ip_addr , //destination ip address
16 |
17 | input mac_data_req, //mac layer request data
18 | input arp_request_req, //arp request
19 | output reg arp_reply_ack, //arp reply ack to arp rx module
20 | input arp_reply_req, //arp reply request from arp rx module
21 | input [31:0] arp_rec_source_ip_addr,
22 | input [47:0] arp_rec_source_mac_addr ,
23 |
24 | output reg arp_tx_ready,
25 | output reg [7:0] arp_tx_data,
26 | output reg arp_tx_end
27 | ) ;
28 |
29 | localparam mac_type = 16'h0806 ;
30 | localparam hardware_type = 16'h0001 ;
31 | localparam protocol_type = 16'h0800 ;
32 | localparam mac_length = 8'h06 ;
33 | localparam ip_length = 8'h04 ;
34 |
35 | localparam ARP_REQUEST_CODE = 16'h0001 ;
36 | localparam ARP_REPLY_CODE = 16'h0002 ;
37 |
38 |
39 | reg [15:0] op ;
40 |
41 | reg [31:0] arp_destination_ip_addr ;
42 | reg [47:0] arp_destination_mac_addr ;
43 | reg [15:0] arp_send_cnt ;
44 | reg [15:0] timeout ;
45 |
46 | parameter IDLE = 5'b00001 ;
47 | parameter ARP_REQUEST_WAIT = 5'b00010 ;
48 | parameter ARP_REQUEST = 5'b00100 ;
49 | parameter ARP_REPLY_WAIT = 5'b01000 ;
50 | parameter ARP_REPLY = 5'b10000 ;
51 |
52 |
53 | reg [4:0] state ;
54 | reg [4:0] next_state ;
55 |
56 | always @(posedge clk or negedge rst_n)
57 | begin
58 | if (~rst_n)
59 | state <= IDLE ;
60 | else
61 | state <= next_state ;
62 | end
63 |
64 | always @(*)
65 | begin
66 | case(state)
67 | IDLE :
68 | begin
69 | if (arp_request_req)
70 | next_state <= ARP_REQUEST_WAIT ;
71 | else if (arp_reply_req)
72 | next_state <= ARP_REPLY_WAIT ;
73 | else
74 | next_state <= IDLE ;
75 | end
76 | ARP_REQUEST_WAIT :
77 | begin
78 | if (mac_data_req)
79 | next_state <= ARP_REQUEST ;
80 | else if (timeout == 16'hffff)
81 | next_state <= IDLE ;
82 | else
83 | next_state <= ARP_REQUEST_WAIT ;
84 | end
85 | ARP_REQUEST :
86 | begin
87 | if (arp_tx_end)
88 | next_state <= IDLE ;
89 | else
90 | next_state <= ARP_REQUEST ;
91 | end
92 | ARP_REPLY_WAIT :
93 | begin
94 | if (mac_data_req)
95 | next_state <= ARP_REPLY ;
96 | else if (timeout == 16'hffff)
97 | next_state <= IDLE ;
98 | else
99 | next_state <= ARP_REPLY_WAIT ;
100 | end
101 | ARP_REPLY :
102 | begin
103 | if (arp_tx_end)
104 | next_state <= IDLE ;
105 | else
106 | next_state <= ARP_REPLY ;
107 | end
108 | default :
109 | next_state <= IDLE ;
110 | endcase
111 | end
112 |
113 |
114 |
115 | always @(posedge clk or negedge rst_n)
116 | begin
117 | if (~rst_n)
118 | op <= 16'd0 ;
119 | else if (state == ARP_REPLY)
120 | op <= ARP_REPLY_CODE ;
121 | else
122 | op <= ARP_REQUEST_CODE ;
123 | end
124 |
125 | always @(posedge clk or negedge rst_n)
126 | begin
127 | if (~rst_n)
128 | arp_tx_ready <= 1'b0 ;
129 | else if (state == ARP_REQUEST_WAIT || state == ARP_REPLY_WAIT)
130 | arp_tx_ready <= 1'b1 ;
131 | else
132 | arp_tx_ready <= 1'b0 ;
133 | end
134 |
135 | always @(posedge clk or negedge rst_n)
136 | begin
137 | if (~rst_n)
138 | arp_tx_end <= 1'b0 ;
139 | else if ((state == ARP_REQUEST && arp_send_cnt == 13 + 46 ) || (state == ARP_REPLY && arp_send_cnt == 13 + 46 ))
140 | arp_tx_end <= 1'b1 ;
141 | else
142 | arp_tx_end <= 1'b0 ;
143 | end
144 |
145 |
146 | //timeout counter
147 | always @(posedge clk or negedge rst_n)
148 | begin
149 | if (~rst_n)
150 | timeout <= 16'd0 ;
151 | else if (state == ARP_REQUEST_WAIT || state == ARP_REPLY_WAIT)
152 | timeout <= timeout + 1'b1 ;
153 | else
154 | timeout <= 16'd0 ;
155 | end
156 |
157 |
158 | always @(posedge clk or negedge rst_n)
159 | begin
160 | if (~rst_n)
161 | arp_destination_ip_addr <= 32'd0 ;
162 | else if (state == ARP_REQUEST_WAIT)
163 | arp_destination_ip_addr <= destination_ip_addr ;
164 | else if (state == ARP_REPLY_WAIT)
165 | arp_destination_ip_addr <= arp_rec_source_ip_addr ;
166 | end
167 |
168 | always @(posedge clk or negedge rst_n)
169 | begin
170 | if (~rst_n)
171 | arp_destination_mac_addr <= 48'd0 ;
172 | else if (state == ARP_REQUEST_WAIT)
173 | arp_destination_mac_addr <= destination_mac_addr ;
174 | else if (state == ARP_REPLY_WAIT)
175 | arp_destination_mac_addr <= arp_rec_source_mac_addr ;
176 | end
177 |
178 |
179 | always @(posedge clk or negedge rst_n)
180 | begin
181 | if (~rst_n)
182 | arp_reply_ack <= 1'b0 ;
183 | else if (state == ARP_REPLY_WAIT)
184 | arp_reply_ack <= 1'b1 ;
185 | else
186 | arp_reply_ack <= 1'b0 ;
187 | end
188 |
189 | always @(posedge clk or negedge rst_n)
190 | begin
191 | if (~rst_n)
192 | arp_send_cnt <= 16'd0 ;
193 | else if (state == ARP_REQUEST || state == ARP_REPLY)
194 | arp_send_cnt <= arp_send_cnt + 1'b1 ;
195 | else
196 | arp_send_cnt <= 16'd0 ;
197 | end
198 |
199 |
200 | always @(posedge clk or negedge rst_n)
201 | begin
202 | if (~rst_n)
203 | arp_tx_data <= 8'd0 ;
204 | else if(state == ARP_REQUEST || state == ARP_REPLY)
205 | begin
206 | case(arp_send_cnt)
207 | 16'd0 : arp_tx_data <= arp_destination_mac_addr[47:40] ;
208 | 16'd1 : arp_tx_data <= arp_destination_mac_addr[39:32] ;
209 | 16'd2 : arp_tx_data <= arp_destination_mac_addr[31:24] ;
210 | 16'd3 : arp_tx_data <= arp_destination_mac_addr[23:16] ;
211 | 16'd4 : arp_tx_data <= arp_destination_mac_addr[15:8] ;
212 | 16'd5 : arp_tx_data <= arp_destination_mac_addr[7:0] ;
213 | 16'd6 : arp_tx_data <= source_mac_addr[47:40] ;
214 | 16'd7 : arp_tx_data <= source_mac_addr[39:32] ;
215 | 16'd8 : arp_tx_data <= source_mac_addr[31:24] ;
216 | 16'd9 : arp_tx_data <= source_mac_addr[23:16] ;
217 | 16'd10 : arp_tx_data <= source_mac_addr[15:8] ;
218 | 16'd11 : arp_tx_data <= source_mac_addr[7:0] ;
219 | 16'd12 : arp_tx_data <= mac_type[15:8] ; //frame type
220 | 16'd13 : arp_tx_data <= mac_type[7:0] ;
221 | 16'd14 : arp_tx_data <= hardware_type[15:8] ; //hardware type
222 | 16'd15 : arp_tx_data <= hardware_type[7:0] ;
223 | 16'd16 : arp_tx_data <= protocol_type[15:8] ; //protocol type using IP 0800
224 | 16'd17 : arp_tx_data <= protocol_type[7:0] ;
225 | 16'd18 : arp_tx_data <= mac_length ; //MAC address length
226 | 16'd19 : arp_tx_data <= ip_length ; //IP address length
227 | 16'd20 : arp_tx_data <= op[15:8] ;
228 | 16'd21 : arp_tx_data <= op[7:0] ;
229 | 16'd22 : arp_tx_data <= source_mac_addr[47:40] ;
230 | 16'd23 : arp_tx_data <= source_mac_addr[39:32] ;
231 | 16'd24 : arp_tx_data <= source_mac_addr[31:24] ;
232 | 16'd25 : arp_tx_data <= source_mac_addr[23:16] ;
233 | 16'd26 : arp_tx_data <= source_mac_addr[15:8] ;
234 | 16'd27 : arp_tx_data <= source_mac_addr[7:0] ;
235 | 16'd28 : arp_tx_data <= source_ip_addr[31:24] ;
236 | 16'd29 : arp_tx_data <= source_ip_addr[23:16] ;
237 | 16'd30 : arp_tx_data <= source_ip_addr[15:8] ;
238 | 16'd31 : arp_tx_data <= source_ip_addr[7:0] ;
239 | 16'd32 : arp_tx_data <= arp_destination_mac_addr[47:40] ;
240 | 16'd33 : arp_tx_data <= arp_destination_mac_addr[39:32] ;
241 | 16'd34 : arp_tx_data <= arp_destination_mac_addr[31:24] ;
242 | 16'd35 : arp_tx_data <= arp_destination_mac_addr[23:16] ;
243 | 16'd36 : arp_tx_data <= arp_destination_mac_addr[15:8] ;
244 | 16'd37 : arp_tx_data <= arp_destination_mac_addr[7:0] ;
245 | 16'd38 : arp_tx_data <= arp_destination_ip_addr[31:24] ;
246 | 16'd39 : arp_tx_data <= arp_destination_ip_addr[23:16] ;
247 | 16'd40 : arp_tx_data <= arp_destination_ip_addr[15:8] ;
248 | 16'd41 : arp_tx_data <= arp_destination_ip_addr[7:0] ;
249 | default : arp_tx_data <= 8'd0 ;
250 | endcase
251 | end
252 | else
253 | arp_tx_data <= 8'd0 ;
254 | end
255 |
256 |
257 |
258 | endmodule
259 |
--------------------------------------------------------------------------------
/RTL/rtl/wr_buf.v:
--------------------------------------------------------------------------------
1 | `timescale 1ns / 1ps
2 | //////////////////////////////////////////////////////////////////////////////////
3 | // Company: Meyesemi
4 | // Engineer: Nill
5 | //
6 | // Create Date: 07/03/23 19:13:35
7 | // Design Name:
8 | // Module Name: wr_buf
9 | // Project Name:
10 | // Target Devices:
11 | // Tool Versions:
12 | // Description:
13 | //
14 | // Dependencies:
15 | //
16 | // Revision:
17 | // Revision 0.01 - File Created
18 | // Additional Comments:
19 | //
20 | //////////////////////////////////////////////////////////////////////////////////
21 | `define UD #1
22 | module wr_buf #(
23 | parameter ADDR_WIDTH = 6'd27,
24 | parameter ADDR_OFFSET = 32'h0000_0000,
25 | parameter H_NUM = 12'd1920,
26 | parameter V_NUM = 12'd1080,
27 | parameter DQ_WIDTH = 12'd32,
28 | parameter LEN_WIDTH = 12'd16,
29 | parameter PIX_WIDTH = 12'd24,
30 | parameter LINE_ADDR_WIDTH = 16'd19,
31 | parameter FRAME_CNT_WIDTH = 16'd8
32 | ) (
33 | input ddr_clk,
34 | input ddr_rstn,
35 |
36 | input wr_clk,
37 | input wr_fsync,
38 | input wr_en,
39 | input [PIX_WIDTH- 1'b1 : 0] wr_data,
40 |
41 | input rd_bac,
42 | output ddr_wreq,
43 | output [ADDR_WIDTH- 1'b1 : 0] ddr_waddr,
44 | output [LEN_WIDTH- 1'b1 : 0] ddr_wr_len,
45 | input ddr_wrdy,
46 | input ddr_wdone,
47 | output [8*DQ_WIDTH- 1'b1 : 0] ddr_wdata,
48 | input ddr_wdata_req,
49 |
50 | output [FRAME_CNT_WIDTH-1 :0] frame_wcnt,
51 | output frame_wirq
52 | );
53 | localparam RAM_WIDTH = 16'd32;
54 | localparam DDR_DATA_WIDTH = DQ_WIDTH * 8;
55 | localparam WR_LINE_NUM = H_NUM*PIX_WIDTH/RAM_WIDTH;
56 | localparam RD_LINE_NUM = WR_LINE_NUM*RAM_WIDTH/DDR_DATA_WIDTH;
57 | localparam DDR_ADDR_OFFSET= RD_LINE_NUM*DDR_DATA_WIDTH/DQ_WIDTH;
58 |
59 | //===========================================================================
60 | reg wr_fsync_1d;
61 | reg wr_en_1d;
62 | wire wr_rst;
63 | reg wr_enable=0;
64 |
65 | reg ddr_rstn_1d,ddr_rstn_2d;
66 |
67 | always @(posedge wr_clk)
68 | begin
69 | wr_fsync_1d <= wr_fsync;
70 | wr_en_1d <= wr_en;
71 | ddr_rstn_1d <= ddr_rstn;
72 | ddr_rstn_2d <= ddr_rstn_1d;
73 |
74 | if(~wr_fsync_1d & wr_fsync && ddr_rstn_2d)
75 | wr_enable <= 1'b1;
76 | else
77 | wr_enable <= wr_enable;
78 | end
79 |
80 | assign wr_rst = (~wr_fsync_1d & wr_fsync) | (~ddr_rstn_2d);
81 |
82 | //===========================================================================
83 | reg rd_fsync_1d,rd_fsync_2d,rd_fsync_3d;
84 | wire rd_rst;
85 | always @(posedge ddr_clk)
86 | begin
87 | rd_fsync_1d <= wr_fsync;
88 | rd_fsync_2d <= rd_fsync_1d;
89 | rd_fsync_3d <= rd_fsync_2d;
90 | end
91 |
92 | assign rd_rst = (~rd_fsync_3d && rd_fsync_2d) | (~ddr_rstn);
93 |
94 | //===========================================================================
95 | // wr_addr control
96 | reg [11:0] x_cnt;
97 | reg [11:0] y_cnt;
98 | reg [31 : 0] write_data;
99 | reg [PIX_WIDTH- 1'b1 : 0] wr_data_1d;
100 | reg write_en;
101 | reg [11:0] wr_addr=0;
102 |
103 | generate
104 | if(PIX_WIDTH == 6'd24)
105 | begin
106 | always @(posedge wr_clk)
107 | begin
108 | wr_data_1d <= wr_data;
109 |
110 | write_en <= (x_cnt[1:0] != 0);
111 |
112 | if(x_cnt[1:0] == 2'd1)
113 | write_data <= {wr_data[7:0],wr_data_1d};
114 | else if(x_cnt[1:0] == 2'd2)
115 | write_data <= {wr_data[15:0],wr_data_1d[PIX_WIDTH-1'b1:8]};
116 | else if(x_cnt[1:0] == 2'd3)
117 | write_data <= {wr_data,wr_data_1d[PIX_WIDTH-1'b1:16]};
118 | else
119 | write_data <= write_data;
120 | end
121 | end
122 | else if(PIX_WIDTH == 6'd16)
123 | begin
124 | always @(posedge wr_clk)
125 | begin
126 | wr_data_1d <= wr_data;
127 |
128 | write_en <= x_cnt[0];
129 | if(x_cnt[0])
130 | write_data <= {wr_data,wr_data_1d};
131 | else
132 | write_data <= write_data;
133 | end
134 | end
135 | else
136 | begin
137 | always @(posedge wr_clk)
138 | begin
139 | write_data <= wr_data;
140 | write_en <= wr_en;
141 | end
142 | end
143 | endgenerate
144 |
145 | always @(posedge wr_clk)
146 | begin
147 | if(wr_rst)
148 | wr_addr <= 12'd0;
149 | else
150 | begin
151 | if(write_en & wr_enable)
152 | wr_addr <= wr_addr + 12'd1;
153 | else
154 | wr_addr <= wr_addr;
155 | end
156 | end
157 |
158 | always @(posedge wr_clk)
159 | begin
160 | if(wr_rst)
161 | x_cnt <= 12'd0;
162 | else if(wr_en & wr_enable)
163 | x_cnt <= x_cnt + 1'b1;
164 | else
165 | x_cnt <= 12'd0;
166 | end
167 |
168 | always @(posedge wr_clk)
169 | begin
170 | if(wr_rst)
171 | y_cnt <= 12'd0;
172 | else if(~wr_en_1d & wr_en & wr_enable)
173 | y_cnt <= y_cnt + 1'b1;
174 | else
175 | y_cnt <= y_cnt;
176 | end
177 |
178 | reg rd_pulse;
179 | always @(posedge wr_clk)
180 | begin
181 | if(x_cnt > H_NUM - 5'd20 & wr_enable)
182 | rd_pulse <= 1'b1;
183 | else
184 | rd_pulse <= 1'b0;
185 | end
186 |
187 | reg [8:0] rd_addr=0;
188 | wire [255:0] rd_wdata;
189 | reg [255:0] rd_wdata_1d=0;
190 | wr_fram_buf wr_fram_buf (
191 | .wr_data ( write_data ),// input [31:0]
192 | .wr_addr ( wr_addr ),// input [11:0]
193 | .wr_en ( write_en ),// input
194 | .wr_clk ( wr_clk ),// input
195 | .wr_rst ( ~ddr_rstn_2d ),// input
196 |
197 | .rd_addr ( rd_addr ),// input [8:0]
198 | .rd_data ( rd_wdata ),// output [255:0]
199 | .rd_clk ( ddr_clk ),// input
200 | .rd_rst ( ~ddr_rstn ) // input
201 | );
202 |
203 | reg rd_pulse_1d,rd_pulse_2d,rd_pulse_3d;
204 | always @(posedge ddr_clk)
205 | begin
206 | rd_pulse_1d <= rd_pulse;
207 | rd_pulse_2d <= rd_pulse_1d;
208 | rd_pulse_3d <= rd_pulse_2d;
209 | end
210 |
211 | wire rd_trig;
212 | assign rd_trig = ~rd_pulse_3d && rd_pulse_2d;
213 |
214 | reg ddr_wr_req=0;
215 | reg ddr_wr_req_1d;
216 | assign ddr_wreq =ddr_wr_req;
217 |
218 | always @(posedge ddr_clk)
219 | begin
220 | ddr_wr_req_1d <= ddr_wr_req;
221 |
222 | if(rd_trig)
223 | ddr_wr_req <= 1'b1;
224 | else if(ddr_wdata_req)
225 | ddr_wr_req <= 1'b0;
226 | else
227 | ddr_wr_req <= ddr_wr_req;
228 | end
229 |
230 | reg rd_en_1d;
231 | reg ddr_wdata_req_1d;
232 | always @(posedge ddr_clk)
233 | begin
234 | ddr_wdata_req_1d <= ddr_wdata_req;
235 | rd_en_1d <= ~ddr_wr_req_1d & ddr_wr_req;
236 | end
237 |
238 | always @(posedge ddr_clk)
239 | begin
240 | if(ddr_wdata_req_1d | rd_en_1d)
241 | rd_wdata_1d <= rd_wdata;
242 | else
243 | rd_wdata_1d <= rd_wdata_1d;
244 | end
245 |
246 | reg line_flag=0;
247 | always@(posedge ddr_clk)
248 | begin
249 | if(rd_rst)
250 | line_flag <= 1'b0;
251 | else if(rd_trig)
252 | line_flag <= 1'b1;
253 | else
254 | line_flag <= line_flag;
255 | end
256 |
257 | always @(posedge ddr_clk)
258 | begin
259 | if(rd_rst)
260 | rd_addr <= 1'b0;
261 | else if(~ddr_wr_req_1d & ddr_wr_req)
262 | rd_addr <= rd_addr + 1'b1;
263 | else if(ddr_wdata_req)
264 | rd_addr <= rd_addr + 1'b1;
265 | else if(rd_trig & line_flag)
266 | rd_addr <= rd_addr - 1'b1;
267 | else
268 | rd_addr <= rd_addr;
269 | end
270 |
271 | reg [FRAME_CNT_WIDTH - 1'b1 :0] rd_frame_cnt=1;
272 | always @(posedge ddr_clk)
273 | begin
274 | if(~ddr_rstn)
275 | rd_frame_cnt <= 'd0;
276 | else if(~rd_fsync_3d && rd_fsync_2d)
277 | rd_frame_cnt <= rd_frame_cnt + 1'b1;
278 | else
279 | rd_frame_cnt <= rd_frame_cnt;
280 | end
281 |
282 | reg [LINE_ADDR_WIDTH - 1'b1 :0] rd_cnt;
283 | always @(posedge ddr_clk)
284 | begin
285 | if(rd_rst)
286 | rd_cnt <= 9'd0;
287 | else if(ddr_wdone)
288 | rd_cnt <= rd_cnt + DDR_ADDR_OFFSET;
289 | else
290 | rd_cnt <= rd_cnt;
291 | end
292 |
293 | reg wirq_en=0;
294 | always @(posedge ddr_clk)
295 | begin
296 | if (~rd_fsync_2d && rd_fsync_3d)
297 | wirq_en <= 1'b1;
298 | else
299 | wirq_en <= wirq_en;
300 | end
301 |
302 | assign ddr_wdata = (~ddr_wdata_req_1d & ddr_wdata_req) ? rd_wdata_1d : rd_wdata;
303 | assign ddr_waddr = {rd_frame_cnt[0],rd_cnt} + ADDR_OFFSET;
304 | assign ddr_wr_len = RD_LINE_NUM;
305 | assign frame_wcnt = rd_frame_cnt;
306 | assign frame_wirq = wirq_en && rd_fsync_3d;
307 |
308 | endmodule
309 |
--------------------------------------------------------------------------------
/RTL/rx/ip_rx.v:
--------------------------------------------------------------------------------
1 | //////////////////////////////////////////////////////////////////////////////////////
2 | //Module Name : ip_rx
3 | //Description : This module is used to receive IP data and verify IP header checksum
4 | //
5 | //////////////////////////////////////////////////////////////////////////////////////
6 | `timescale 1 ns/1 ns
7 | module ip_rx
8 | (
9 | input clk,
10 | input rst_n,
11 |
12 | input [31:0] local_ip_addr,
13 | input [47:0] local_mac_addr,
14 |
15 | input [7:0] ip_rx_data,
16 | input ip_rx_req,
17 | input [47:0] mac_rx_destination_mac_addr,
18 |
19 | output reg udp_rx_req, //udp rx request
20 | output reg icmp_rx_req, //icmp rx request
21 | output reg ip_addr_check_error, //ip address is not equal to local address
22 |
23 | output reg [15:0] upper_layer_data_length, //udp or icmp data length = ip data length - ip header length
24 | output reg [15:0] ip_total_data_length, //send data length
25 |
26 | output reg [7:0] net_protocol, //network layer protocol: 8'h11 udp 8'h01 icmp
27 | output reg [31:0] ip_rec_source_addr, //received source ip address
28 | output reg [31:0] ip_rec_destination_addr, //received destination ip address
29 |
30 | output reg ip_rx_end,
31 | output reg ip_checksum_error
32 |
33 | ) ;
34 |
35 | reg [15:0] ip_rx_cnt ;
36 | reg [15:0] ip_rec_data_length ;
37 |
38 | reg [7:0] ip_rx_data_d0 ;
39 | reg [7:0] ip_rx_data_d1 ;
40 |
41 | reg [15:0] ip_rec_checksum ;
42 |
43 | reg [3:0] header_length_buf ;
44 | wire [5:0] header_length ;
45 |
46 | parameter IDLE = 5'b00001 ;
47 | parameter REC_HEADER0 = 5'b00010 ;
48 | parameter REC_HEADER1 = 5'b00100 ;
49 | parameter REC_DATA = 5'b01000 ;
50 | parameter REC_END = 5'b10000 ;
51 |
52 | reg [4:0] state ;
53 | reg [4:0] next_state ;
54 |
55 | always @(posedge clk or negedge rst_n)
56 | begin
57 | if (~rst_n)
58 | state <= IDLE ;
59 | else
60 | state <= next_state ;
61 | end
62 |
63 | always @(*)
64 | begin
65 | case(state)
66 | IDLE :
67 | begin
68 | if (ip_rx_req == 1'b1)
69 | next_state <= REC_HEADER0 ;
70 | else
71 | next_state <= IDLE ;
72 | end
73 | REC_HEADER0 :
74 | begin
75 | if (ip_rx_cnt == 16'd3)
76 | next_state <= REC_HEADER1 ;
77 | else
78 | next_state <= REC_HEADER0 ;
79 | end
80 | REC_HEADER1 :
81 | begin
82 | if (ip_rx_cnt == header_length - 1)
83 | next_state <= REC_DATA ;
84 | else
85 | next_state <= REC_HEADER1 ;
86 | end
87 | REC_DATA :
88 | begin
89 | if (ip_checksum_error || ip_rx_end)
90 | next_state <= REC_END ;
91 | else if (ip_rx_cnt == 16'hffff)
92 | next_state <= REC_END ;
93 | else
94 | next_state <= REC_DATA ;
95 | end
96 | REC_END :
97 | next_state <= IDLE ;
98 | default :
99 | next_state <= IDLE ;
100 | endcase
101 | end
102 |
103 | assign header_length = 4*header_length_buf ;
104 |
105 | always @(posedge clk or negedge rst_n)
106 | begin
107 | if (~rst_n)
108 | ip_rx_end <= 1'b0 ;
109 | else if (state == REC_DATA && ip_rx_cnt == ip_total_data_length - 2)
110 | ip_rx_end <= 1'b1 ;
111 | else
112 | ip_rx_end <= 1'b0 ;
113 | end
114 | //mac addr and ip addr is not equal to local addr, assert error
115 | always @(posedge clk or negedge rst_n)
116 | begin
117 | if (~rst_n)
118 | ip_addr_check_error <= 1'b0 ;
119 | else if (state == REC_DATA)
120 | begin
121 | if (mac_rx_destination_mac_addr == local_mac_addr && ip_rec_destination_addr == local_ip_addr)
122 | ip_addr_check_error <= 1'b0 ;
123 | else
124 | ip_addr_check_error <= 1'b1 ;
125 | end
126 | else
127 | ip_addr_check_error <= 1'b0 ;
128 | end
129 | //generate udp rx request signal
130 | always @(posedge clk or negedge rst_n)
131 | begin
132 | if (~rst_n)
133 | udp_rx_req <= 1'b0 ;
134 | else if (state == REC_HEADER1 && net_protocol == 8'h11 && ip_rx_cnt == header_length - 2)
135 | udp_rx_req <= 1'b1 ;
136 | else
137 | udp_rx_req <= 1'b0 ;
138 | end
139 | //generate icmp rx request signal
140 | always @(posedge clk or negedge rst_n)
141 | begin
142 | if (~rst_n)
143 | icmp_rx_req <= 1'b0 ;
144 | else if (state == REC_HEADER1 && net_protocol == 8'h01 && ip_rx_cnt == header_length - 2)
145 | icmp_rx_req <= 1'b1 ;
146 | else
147 | icmp_rx_req <= 1'b0 ;
148 | end
149 |
150 |
151 | //icmp or udp data length
152 | always @(posedge clk or negedge rst_n)
153 | begin
154 | if (~rst_n)
155 | begin
156 | upper_layer_data_length <= 16'd0 ;
157 | end
158 | else
159 | begin
160 | upper_layer_data_length <= ip_rec_data_length - header_length ;
161 | end
162 | end
163 |
164 | always @(posedge clk or negedge rst_n)
165 | begin
166 | if (~rst_n)
167 | begin
168 | ip_rx_data_d0 <= 8'd0 ;
169 | ip_rx_data_d1 <= 8'd0 ;
170 | end
171 | else
172 | begin
173 | ip_rx_data_d0 <= ip_rx_data ;
174 | ip_rx_data_d1 <= ip_rx_data_d0 ;
175 | end
176 | end
177 |
178 | always @(posedge clk or negedge rst_n)
179 | begin
180 | if (~rst_n)
181 | ip_rx_cnt <= 16'd0 ;
182 | else if (state == REC_HEADER0 || state == REC_HEADER1 || state == REC_DATA)
183 | ip_rx_cnt <= ip_rx_cnt + 1'b1 ;
184 | else
185 | ip_rx_cnt <= 16'd0 ;
186 | end
187 | //total length
188 | always @(posedge clk or negedge rst_n)
189 | begin
190 | if (~rst_n)
191 | ip_total_data_length <= 16'd0 ;
192 | else if (state == REC_HEADER1)
193 | begin
194 | if (ip_rec_data_length < 16'd46)
195 | ip_total_data_length <= 16'd46 ;
196 | else
197 | ip_total_data_length <= ip_rec_data_length ;
198 | end
199 | end
200 |
201 |
202 | //ip header length
203 | always @(posedge clk or negedge rst_n)
204 | begin
205 | if (~rst_n)
206 | header_length_buf <= 4'd0 ;
207 | else if (state == REC_HEADER0 && ip_rx_cnt == 16'd0)
208 | header_length_buf <= ip_rx_data[3:0] ;
209 | end
210 | //ip data total length
211 | always @(posedge clk or negedge rst_n)
212 | begin
213 | if (~rst_n)
214 | ip_rec_data_length <= 16'd0 ;
215 | else if (state == REC_HEADER0 && ip_rx_cnt == 16'd2)
216 | ip_rec_data_length[15:8] <= ip_rx_data ;
217 | else if (state == REC_HEADER0 && ip_rx_cnt == 16'd3)
218 | ip_rec_data_length[7:0] <= ip_rx_data ;
219 | end
220 | //network layer protocol
221 | always @(posedge clk or negedge rst_n)
222 | begin
223 | if (~rst_n)
224 | net_protocol <= 8'd0 ;
225 | else if (state == REC_HEADER1 && ip_rx_cnt == 16'd9)
226 | net_protocol <= ip_rx_data ;
227 | end
228 |
229 | //ip source address
230 | always @(posedge clk or negedge rst_n)
231 | begin
232 | if (~rst_n)
233 | ip_rec_source_addr <= 32'd0 ;
234 | else if (state == REC_HEADER1 && ip_rx_cnt == 16'd12)
235 | ip_rec_source_addr[31:24] <= ip_rx_data ;
236 | else if (state == REC_HEADER1 && ip_rx_cnt == 16'd13)
237 | ip_rec_source_addr[23:16] <= ip_rx_data ;
238 | else if (state == REC_HEADER1 && ip_rx_cnt == 16'd14)
239 | ip_rec_source_addr[15:8] <= ip_rx_data ;
240 | else if (state == REC_HEADER1 && ip_rx_cnt == 16'd15)
241 | ip_rec_source_addr[7:0] <= ip_rx_data ;
242 | end
243 | //ip source address
244 | always @(posedge clk or negedge rst_n)
245 | begin
246 | if (~rst_n)
247 | ip_rec_destination_addr <= 32'd0 ;
248 | else if (state == REC_HEADER1 && ip_rx_cnt == 16'd16)
249 | ip_rec_destination_addr[31:24] <= ip_rx_data ;
250 | else if (state == REC_HEADER1 && ip_rx_cnt == 16'd17)
251 | ip_rec_destination_addr[23:16] <= ip_rx_data ;
252 | else if (state == REC_HEADER1 && ip_rx_cnt == 16'd18)
253 | ip_rec_destination_addr[15:8] <= ip_rx_data ;
254 | else if (state == REC_HEADER1 && ip_rx_cnt == 16'd19)
255 | ip_rec_destination_addr[7:0] <= ip_rx_data ;
256 | end
257 |
258 |
259 | //****************************************************************//
260 | //verify checksum
261 | //****************************************************************//
262 | reg [31:0] checksum_tmp ;
263 | reg [31:0] checksum_buf ;
264 | reg [31:0] check_out ;
265 | reg [31:0] checkout_buf ;
266 | wire [15:0] checksum ;
267 | reg [2:0] checksum_cnt ;
268 |
269 | //checksum function
270 | function [31:0] checksum_adder
271 | (
272 | input [31:0] dataina,
273 | input [31:0] datainb
274 | );
275 |
276 | begin
277 | checksum_adder = dataina + datainb;
278 | end
279 | endfunction
280 |
281 | function [31:0] checksum_out
282 | (
283 | input [31:0] dataina
284 | );
285 |
286 | begin
287 | checksum_out = dataina[15:0]+dataina[31:16];
288 | end
289 |
290 | endfunction
291 |
292 | always @(posedge clk or negedge rst_n)
293 | begin
294 | if (~rst_n)
295 | checksum_tmp <= 32'd0;
296 | else if (state == REC_HEADER0 || state == REC_HEADER1)
297 | begin
298 | if (ip_rx_cnt[0] == 1'b1)
299 | checksum_tmp <= checksum_adder({ip_rx_data_d0, ip_rx_data},checksum_buf);
300 | end
301 | else if (state == IDLE)
302 | checksum_tmp <= 32'd0;
303 | end
304 |
305 | always @(posedge clk or negedge rst_n)
306 | begin
307 | if (~rst_n)
308 | check_out <= 32'd0;
309 | else if (state == REC_DATA)
310 | check_out <= checksum_out(checksum_tmp) ;
311 | end
312 |
313 | always @(posedge clk or negedge rst_n)
314 | begin
315 | if(rst_n == 1'b0)
316 | checksum_cnt <= 3'd0 ;
317 | else if (state == REC_DATA)
318 | begin
319 | if (checksum_cnt == 3'd7)
320 | checksum_cnt <= checksum_cnt ;
321 | else
322 | checksum_cnt <= checksum_cnt + 1'b1 ;
323 | end
324 | else
325 | checksum_cnt <= 3'd0 ;
326 | end
327 |
328 | always @(posedge clk or negedge rst_n)
329 | begin
330 | if (~rst_n)
331 | checksum_buf <= 32'd0 ;
332 | else
333 | checksum_buf <= checksum_tmp ;
334 | end
335 |
336 | always @(posedge clk or negedge rst_n)
337 | begin
338 | if (~rst_n)
339 | checkout_buf <= 32'd0 ;
340 | else
341 | checkout_buf <= check_out ;
342 | end
343 |
344 | assign checksum = ~checkout_buf[15:0] ;
345 |
346 | always @(posedge clk or negedge rst_n)
347 | begin
348 | if (~rst_n)
349 | ip_checksum_error <= 1'b0 ;
350 | else if (state == REC_DATA && checksum_cnt == 3'd2)
351 | begin
352 | if (checksum == 16'd0)
353 | ip_checksum_error <= 1'b0 ;
354 | else
355 | ip_checksum_error <= 1'b1 ;
356 | end
357 | else
358 | ip_checksum_error <= 1'b0 ;
359 | end
360 |
361 | endmodule
362 |
--------------------------------------------------------------------------------
/RTL/rtl/wr_cmd_trans.v:
--------------------------------------------------------------------------------
1 | `timescale 1ns / 1ps
2 | //////////////////////////////////////////////////////////////////////////////////
3 | // Company: Meyesemi
4 | // Engineer: Nill
5 | //
6 | // Create Date: 29/01/23 14:24:22
7 | // Design Name:
8 | // Module Name: wr_cmd_trans
9 | // Project Name:
10 | // Target Devices:
11 | // Tool Versions:
12 | // Description:
13 | //
14 | // Dependencies:
15 | //
16 | // Revision:
17 | // Revision 0.01 - File Created
18 | // Additional Comments:
19 | //
20 | //////////////////////////////////////////////////////////////////////////////////
21 | `define UD #1
22 | module wr_cmd_trans #(
23 | parameter CTRL_ADDR_WIDTH = 28,
24 | parameter MEM_DQ_WIDTH = 16
25 | ) (
26 | input clk,
27 | input rstn,
28 |
29 | input wr_cmd_en,
30 | input [CTRL_ADDR_WIDTH-1:0] wr_cmd_addr,
31 | input [31: 0] wr_cmd_len,
32 | output reg wr_cmd_ready,
33 | output reg wr_cmd_done,
34 | input wr_bac,
35 | input [MEM_DQ_WIDTH*8-1:0] wr_ctrl_data,
36 | output wr_data_re,
37 |
38 | output reg wr_en=0,
39 | output reg [CTRL_ADDR_WIDTH-1:0] wr_addr=0,
40 | output reg [ 3: 0] wr_id=0,
41 | output reg [ 3: 0] wr_len=0,
42 | output reg wr_data_en=0,
43 | output [MEM_DQ_WIDTH*8-1:0] wr_data,
44 | input wr_ready,
45 | input wr_done,
46 |
47 | input rd_cmd_en,
48 | input [CTRL_ADDR_WIDTH-1:0] rd_cmd_addr,
49 | input [31: 0] rd_cmd_len,
50 | output reg rd_cmd_ready=1,
51 | output reg rd_cmd_done=0,
52 | input read_en,
53 |
54 | output reg rd_en =0,
55 | output reg [CTRL_ADDR_WIDTH-1:0] rd_addr =0,
56 | output reg [3:0] rd_id =0,
57 | output reg [3:0] rd_len =0,
58 | input rd_done_p
59 | );
60 |
61 | reg wr_done_1d;
62 | reg wr_cmd_en_1d;
63 | reg [15:0] wr_cnt;
64 | reg write_enable;
65 | reg [31:0] wr_trans_len;
66 | wire wr_cmd_trig;
67 | always @(posedge clk)
68 | begin
69 | wr_done_1d <= wr_done;
70 | wr_cmd_en_1d <= wr_cmd_en;
71 |
72 | if(wr_cmd_trig)
73 | wr_trans_len <= wr_cmd_len;
74 | else
75 | wr_trans_len <= wr_trans_len;
76 | end
77 | assign wr_cmd_trig = ~wr_cmd_en_1d & wr_cmd_en;
78 |
79 | always @(posedge clk)
80 | begin
81 | if(~rstn)
82 | wr_en <= 1'd0;
83 | else if(wr_cmd_trig)
84 | wr_en <= 1'd1;
85 | else if(wr_cnt < wr_trans_len && (~wr_done_1d && wr_done))
86 | wr_en <= 1'd1;
87 | else
88 | wr_en <= 1'd0;
89 | end
90 |
91 | always @(posedge clk)
92 | begin
93 | if(~rstn)
94 | write_enable <= 1'd0;
95 | else if(wr_cmd_trig)
96 | write_enable <= 1'd1;
97 | else if(wr_cnt >= wr_trans_len - 16 && (~wr_done_1d && wr_done))
98 | write_enable <= 1'd0;
99 | else
100 | write_enable <= write_enable;
101 | end
102 |
103 | always @(posedge clk)
104 | begin
105 | if(~rstn)
106 | wr_cnt <= 16'd0;
107 | else if(wr_cmd_trig)
108 | wr_cnt <= 16'd16;
109 | else if(write_enable && (~wr_done_1d && wr_done))
110 | begin
111 | if(wr_cnt >= wr_trans_len - 16)
112 | wr_cnt <= wr_cmd_len;
113 | else
114 | wr_cnt <= wr_cnt + 16'd16;
115 | end
116 | else
117 | wr_cnt <= wr_cnt;
118 | end
119 |
120 | always @(posedge clk)
121 | begin
122 | if(~rstn)
123 | wr_cmd_done <= 1'd0;
124 | else
125 | begin
126 | if(wr_cnt == wr_trans_len && (~wr_done_1d && wr_done))
127 | wr_cmd_done <= 1'd1;
128 | else
129 | wr_cmd_done <= 1'd0;
130 | end
131 | end
132 |
133 | always @(posedge clk)
134 | begin
135 | if(~rstn)
136 | wr_cmd_ready <= 1'd1;
137 | else
138 | begin
139 | if(wr_cmd_trig)
140 | wr_cmd_ready <= 1'd0;
141 | else if(wr_cmd_done)
142 | wr_cmd_ready <= 1'd1;
143 | else
144 | wr_cmd_ready <= wr_cmd_ready;
145 | end
146 | end
147 |
148 | always @(posedge clk)
149 | begin
150 | if(~rstn)
151 | begin
152 | wr_addr <= {CTRL_ADDR_WIDTH{1'b0}};
153 | wr_id <= 'd0;
154 | wr_len <= 4'd15;
155 | end
156 | else if(wr_cmd_trig)
157 | begin
158 | wr_addr <= wr_cmd_addr;
159 | wr_id <= 'd0;
160 | wr_len <= 4'd15;
161 | end
162 | else
163 | begin
164 | if(~wr_done_1d && wr_done)
165 | begin
166 | if(wr_cnt >= wr_trans_len - 16)
167 | wr_len <= wr_trans_len - wr_cnt - 1'b1;
168 | else
169 | wr_len <= 4'd15;
170 |
171 | wr_addr <= wr_addr + {wr_len,3'd0} + 4'b1000;//12'd1024;
172 | end
173 | else
174 | begin
175 | // wr_id <= wr_id;
176 | wr_addr <= wr_addr;
177 | end
178 | end
179 | end
180 |
181 | reg [3:0] burst_cnt ;
182 | reg wr_data_re_reg;
183 | always @(posedge clk)
184 | begin
185 | if(~rstn)
186 | wr_data_re_reg <= 1'b0;
187 | else if(wr_ready)
188 | begin
189 | if(burst_cnt == wr_len && wr_data_re_reg)
190 | wr_data_re_reg <= 1'b0;
191 | else
192 | wr_data_re_reg <= 1'b1;
193 | end
194 | else
195 | wr_data_re_reg <= 1'b0;
196 | end
197 | assign wr_data_re = wr_ready;// & wr_data_re_reg;
198 |
199 | always @(posedge clk)
200 | begin
201 | if(wr_data_re)
202 | wr_data_en <= 1'b1;
203 | else
204 | wr_data_en <= 1'b0;
205 | end
206 |
207 | always @(posedge clk)
208 | begin
209 | if(~rstn)
210 | burst_cnt <= 1'b0;
211 | else if(wr_data_re && wr_ready)
212 | begin
213 | if(burst_cnt == wr_len)
214 | burst_cnt <= 1'b0;
215 | else
216 | burst_cnt <= burst_cnt + 1'b1;
217 | end
218 | else if(wr_bac)
219 | burst_cnt <= burst_cnt - 1'b1;
220 | else
221 | burst_cnt <= burst_cnt;
222 | end
223 |
224 | assign wr_data = wr_ctrl_data;
225 |
226 | //============================================================================
227 | // read chanel
228 | //============================================================================
229 | reg read_enable;
230 | reg [15:0] rd_cnt;
231 | reg rd_done_1d;
232 | reg rd_cmd_en_1d;
233 | reg [31:0] rd_trans_len;
234 | wire rd_cmd_trig;
235 | assign rd_cmd_trig = ~rd_cmd_en_1d & rd_cmd_en;
236 | always @(posedge clk)
237 | begin
238 | rd_done_1d <= rd_done_p;
239 | rd_cmd_en_1d <= rd_cmd_en;
240 | if(rd_cmd_trig)
241 | rd_trans_len <= rd_cmd_len;
242 | else
243 | rd_trans_len <= rd_trans_len;
244 |
245 |
246 | if(~rstn)
247 | read_enable <= 1'b0;
248 | else if(rd_cmd_trig)
249 | read_enable <= 1'b1;
250 | else if(rd_cnt >= rd_trans_len - 16 && (~rd_done_1d && rd_done_p))
251 | read_enable <= 1'b0;
252 | else
253 | read_enable <= read_enable;
254 | end
255 |
256 | reg read_enable_1d;
257 |
258 | always @(posedge clk)
259 | begin
260 | read_enable_1d <= read_enable;
261 |
262 | if(~rstn)
263 | rd_en <= 1'd0;
264 | else if(~read_enable_1d && read_enable)
265 | rd_en <= 1'd1;
266 | else if(rd_cnt < rd_trans_len && (~rd_done_1d && rd_done_p))
267 | rd_en <= 1'd1;
268 | else
269 | rd_en <= 1'd0;
270 | end
271 |
272 | reg [15:0] rd_data_cnt;
273 | always @(posedge clk)
274 | begin
275 | if(~rstn)
276 | rd_data_cnt <= 1'd0;
277 | else if(rd_cmd_trig)
278 | rd_data_cnt <= 1'd0;
279 | else if(read_en)
280 | begin
281 | if(rd_data_cnt == rd_trans_len - 1'b1)
282 | rd_data_cnt <= 1'd0;
283 | else
284 | rd_data_cnt <= rd_data_cnt + 1'd1;
285 | end
286 | else
287 | rd_data_cnt <= rd_data_cnt;
288 | end
289 |
290 | always @(posedge clk)
291 | begin
292 | if(~rstn)
293 | rd_cmd_done <= 1'd0;
294 | else
295 | begin
296 | if(rd_data_cnt == rd_trans_len - 1'b1)
297 | rd_cmd_done <= 1'd1;
298 | else
299 | rd_cmd_done <= 1'd0;
300 | end
301 | end
302 |
303 | always @(posedge clk)
304 | begin
305 | if(~rstn)
306 | rd_cmd_ready <= 1'd1;
307 | else
308 | begin
309 | if(rd_cmd_trig)
310 | rd_cmd_ready <= 1'd0;
311 | else if(rd_cnt == rd_trans_len && (~rd_done_1d && rd_done_p))
312 | rd_cmd_ready <= 1'd1;
313 | else
314 | rd_cmd_ready <= rd_cmd_ready;
315 | end
316 | end
317 |
318 | always @(posedge clk)
319 | begin
320 | if(~rstn)
321 | rd_cnt <= 16'd0;
322 | else if(~read_enable_1d && read_enable)
323 | rd_cnt <= 16'd16;
324 | else if(read_enable && (~rd_done_1d && rd_done_p))
325 | begin
326 | if(rd_cnt >= rd_cmd_len - 16)
327 | rd_cnt <= rd_cmd_len;
328 | else
329 | rd_cnt <= rd_cnt + 16'd16;
330 | end
331 | else
332 | rd_cnt <= rd_cnt;
333 | end
334 |
335 | always @(posedge clk)
336 | begin
337 | if(~rstn)
338 | begin
339 | rd_addr <= {CTRL_ADDR_WIDTH{1'b0}};
340 | rd_id <= 'd0;
341 | rd_len <= 4'd15;
342 | end
343 | else if(~read_enable_1d && read_enable)
344 | begin
345 | rd_addr <= rd_cmd_addr;
346 | rd_id <= 'd0;
347 | rd_len <= 4'd15;
348 | end
349 | else
350 | begin
351 | if(~rd_done_1d && rd_done_p)
352 | begin
353 | if(rd_cnt >= rd_cmd_len - 16)
354 | rd_len <= rd_cmd_len - rd_cnt - 1'b1;
355 | else
356 | rd_len <= 4'd15;
357 |
358 | rd_addr <= rd_addr + {rd_len,3'd0} + 4'b1000;//12'd1024;
359 | end
360 | else
361 | begin
362 | rd_addr <= rd_addr;
363 | end
364 | end
365 | end
366 |
367 | endmodule
368 |
--------------------------------------------------------------------------------
/RTL/src/util_gmii_to_rgmii.v:
--------------------------------------------------------------------------------
1 |
2 |
3 | module util_gmii_to_rgmii (
4 | reset,
5 | rgmii_td,
6 | rgmii_tx_ctl,
7 | rgmii_txc,
8 | rgmii_rd,
9 | rgmii_rx_ctl,
10 | gmii_rx_clk,
11 | rgmii_rxc,
12 | gmii_txd,
13 | gmii_tx_en,
14 | gmii_tx_er,
15 | gmii_tx_clk,
16 | gmii_crs,
17 | gmii_col,
18 | gmii_rxd,
19 | gmii_rx_dv,
20 | gmii_rx_er,
21 | speed_selection,
22 | duplex_mode,
23 | led,
24 | pll_phase_shft_lock,
25 | clk,
26 | sys_clk
27 | );
28 | input sys_clk;
29 | output pll_phase_shft_lock;
30 | output clk;
31 | output reg led;
32 | input rgmii_rxc;//add
33 | input reset;
34 | output [ 3:0] rgmii_td;
35 | output rgmii_tx_ctl;
36 | output rgmii_txc;
37 | input [ 3:0] rgmii_rd;
38 | input rgmii_rx_ctl;
39 | output gmii_rx_clk;
40 | input [ 7:0] gmii_txd;
41 | input gmii_tx_en;
42 | input gmii_tx_er;
43 | output gmii_tx_clk;
44 | output gmii_crs;
45 | output gmii_col;
46 | output [ 7:0] gmii_rxd;
47 | output gmii_rx_dv;
48 | output gmii_rx_er;
49 | input [ 1:0] speed_selection; // 1x gigabit, 01 100Mbps, 00 10mbps
50 | input duplex_mode; // 1 full, 0 half
51 |
52 | wire gigabit;
53 | wire gmii_tx_clk_s;
54 | wire gmii_rx_dv_s;
55 |
56 | wire [ 7:0] gmii_rxd_s;
57 | wire rgmii_rx_ctl_delay;
58 | wire rgmii_rx_ctl_s;
59 | // registers
60 | reg tx_reset_d1;
61 | reg tx_reset_sync;
62 | reg rx_reset_d1;
63 | reg [ 7:0] gmii_txd_r;
64 | reg gmii_tx_en_r;
65 | reg gmii_tx_er_r;
66 | reg [ 7:0] gmii_txd_r_d1;
67 | reg gmii_tx_en_r_d1;
68 | reg gmii_tx_er_r_d1;
69 |
70 | reg rgmii_tx_ctl_r;
71 | reg [ 3:0] gmii_txd_low;
72 | reg gmii_col;
73 | reg gmii_crs;
74 |
75 | reg [ 7:0] gmii_rxd;
76 | reg gmii_rx_dv;
77 | reg gmii_rx_er;
78 | wire padt1 ;
79 | wire padt2 ;
80 | wire padt3 ;
81 | wire padt4 ;
82 | wire padt5 ;
83 | wire padt6 ;
84 | wire stx_txc ;
85 | wire stx_ctr ;
86 | wire [3:0] stxd_rgm ;
87 | assign gigabit = speed_selection [1];
88 | assign gmii_tx_clk = gmii_tx_clk_s;
89 | assign gmii_tx_clk_s = gmii_rx_clk;
90 |
91 | //test led
92 | reg[28:0] cnt_timer;
93 | always @(posedge gmii_tx_clk_s)
94 | begin
95 | cnt_timer<=cnt_timer+1'b1;
96 | if( cnt_timer==29'h3ffffff)
97 | begin
98 | led=~led;
99 | cnt_timer<=29'h0;
100 | end
101 | end
102 |
103 | wire gmii_rx_clk;
104 | wire rx_clki_shft_bufg;
105 |
106 |
107 | wire clk;
108 | pll_sft U_pll_phase_shift(
109 | .clkout0 (rx_clki_shft ), //125MHz
110 | .clkout1 (clk ), //200MHz
111 | .clkin1 (rgmii_rxc ),
112 | .clkfb (gmii_rx_clk ),
113 | .pll_rst (1'b0 ),
114 | .pll_lock (pll_phase_shft_lock)
115 | );
116 |
117 | GTP_CLKBUFG GTP_CLKBUFG_RXSHFT(
118 | .CLKIN (rx_clki_shft),
119 | .CLKOUT (gmii_rx_clk )
120 | );
121 |
122 | /*GTP_CLKBUFG GTP_CLKBUFG_RXSHFT(
123 | .CLKIN (~rgmii_rxc),
124 | .CLKOUT (gmii_rx_clk )
125 | );*/
126 | //assign gmii_rx_clk=rgmii_rxc;
127 | always @(posedge gmii_rx_clk)
128 | begin
129 | gmii_rxd = gmii_rxd_s;
130 | gmii_rx_dv = gmii_rx_dv_s;
131 | gmii_rx_er = gmii_rx_dv_s ^ rgmii_rx_ctl_s;
132 | end
133 |
134 | always @(posedge gmii_tx_clk_s) begin
135 | tx_reset_d1 <= reset;
136 | tx_reset_sync <= tx_reset_d1;
137 | end
138 |
139 | always @(posedge gmii_tx_clk_s)
140 | begin
141 | rgmii_tx_ctl_r = gmii_tx_en_r ^ gmii_tx_er_r;
142 | gmii_txd_low = gigabit ? gmii_txd_r[7:4] : gmii_txd_r[3:0];
143 | gmii_col = duplex_mode ? 1'b0 : (gmii_tx_en_r| gmii_tx_er_r) & ( gmii_rx_dv | gmii_rx_er) ;
144 | gmii_crs = duplex_mode ? 1'b0 : (gmii_tx_en_r| gmii_tx_er_r| gmii_rx_dv | gmii_rx_er);
145 | end
146 |
147 | always @(posedge gmii_tx_clk_s) begin
148 | if (tx_reset_sync == 1'b1) begin
149 | gmii_txd_r <= 8'h0;
150 | gmii_tx_en_r <= 1'b0;
151 | gmii_tx_er_r <= 1'b0;
152 | end
153 | else
154 | begin
155 | gmii_txd_r <= gmii_txd;
156 | gmii_tx_en_r <= gmii_tx_en;
157 | gmii_tx_er_r <= gmii_tx_er;
158 | gmii_txd_r_d1 <= gmii_txd_r;
159 | gmii_tx_en_r_d1 <= gmii_tx_en_r;
160 | gmii_tx_er_r_d1 <= gmii_tx_er_r;
161 | end
162 | end
163 |
164 |
165 |
166 |
167 | GTP_OSERDES #(
168 | .OSERDES_MODE("ODDR"), //"ODDR","OMDDR","OGSER4","OMSER4","OGSER7","OGSER8",OMSER8"
169 | .WL_EXTEND ("FALSE"), //"TRUE"; "FALSE"
170 | .GRS_EN ("TRUE"), //"TRUE"; "FALSE"
171 | .LRS_EN ("TRUE"), //"TRUE"; "FALSE"
172 | .TSDDR_INIT (1'b0) //1'b0;1'b1
173 | ) gtp_ogddr6(
174 | .DO (stx_txc),
175 | .TQ (padt6),
176 | .DI ({7'd0,1'b1}),
177 | .TI (4'd0),
178 | .RCLK (gmii_tx_clk_s),
179 | .SERCLK(gmii_tx_clk_s),
180 | .OCLK (1'd0),
181 | .RST (tx_reset_sync)
182 | );
183 | GTP_OUTBUFT gtp_outbuft6
184 | (
185 |
186 | .I(stx_txc),
187 | .T(padt6) ,
188 | .O(rgmii_txc)
189 | );
190 |
191 |
192 | GTP_OSERDES #(
193 | .OSERDES_MODE("ODDR"), //"ODDR","OMDDR","OGSER4","OMSER4","OGSER7","OGSER8",OMSER8"
194 | .WL_EXTEND ("FALSE"), //"TRUE"; "FALSE"
195 | .GRS_EN ("TRUE"), //"TRUE"; "FALSE"
196 | .LRS_EN ("TRUE"), //"TRUE"; "FALSE"
197 | .TSDDR_INIT (1'b0) //1'b0;1'b1
198 | ) gtp_ogddr2(
199 | .DO (stxd_rgm[3]),
200 | .TQ (padt2),
201 | .DI ({6'd0,gmii_txd_low[3],gmii_txd_r_d1[3]}),
202 | .TI (4'd0),
203 | .RCLK (gmii_tx_clk_s),
204 | .SERCLK(gmii_tx_clk_s),
205 | .OCLK (1'd0),
206 | .RST (tx_reset_sync)
207 | );
208 |
209 | GTP_OUTBUFT gtp_outbuft2
210 | (
211 |
212 | .I(stxd_rgm[3]),
213 | .T(padt2) ,
214 | .O(rgmii_td[3])
215 | );
216 | //---------------------------------------
217 |
218 | GTP_OSERDES #(
219 | .OSERDES_MODE("ODDR"), //"ODDR","OMDDR","OGSER4","OMSER4","OGSER7","OGSER8",OMSER8"
220 | .WL_EXTEND ("FALSE"), //"TRUE"; "FALSE"
221 | .GRS_EN ("TRUE"), //"TRUE"; "FALSE"
222 | .LRS_EN ("TRUE"), //"TRUE"; "FALSE"
223 | .TSDDR_INIT (1'b0) //1'b0;1'b1
224 | ) gtp_ogddr3(
225 | .DO (stxd_rgm[2]),
226 | .TQ (padt3),
227 | .DI ({6'd0,gmii_txd_low[2],gmii_txd_r_d1[2]}),
228 | .TI (4'd0),
229 | .RCLK (gmii_tx_clk_s),
230 | .SERCLK(gmii_tx_clk_s),
231 | .OCLK (1'd0),
232 | .RST (tx_reset_sync)
233 | );
234 |
235 | GTP_OUTBUFT gtp_outbuft3
236 | (
237 | .I(stxd_rgm[2]),
238 | .T(padt3) ,
239 | .O(rgmii_td[2])
240 | );
241 | //--------------------------------------
242 |
243 | GTP_OSERDES #(
244 | .OSERDES_MODE("ODDR"), //"ODDR","OMDDR","OGSER4","OMSER4","OGSER7","OGSER8",OMSER8"
245 | .WL_EXTEND ("FALSE"), //"TRUE"; "FALSE"
246 | .GRS_EN ("TRUE"), //"TRUE"; "FALSE"
247 | .LRS_EN ("TRUE"), //"TRUE"; "FALSE"
248 | .TSDDR_INIT (1'b0) //1'b0;1'b1
249 | ) gtp_ogddr4(
250 | .DO (stxd_rgm[1]),
251 | .TQ (padt4),
252 | .DI ({6'd0,gmii_txd_low[1],gmii_txd_r_d1[1]}),
253 | .TI (4'd0),
254 | .RCLK (gmii_tx_clk_s),
255 | .SERCLK(gmii_tx_clk_s),
256 | .OCLK (1'd0),
257 | .RST (tx_reset_sync)
258 | );
259 |
260 | GTP_OUTBUFT gtp_outbuft4
261 | (
262 | .I(stxd_rgm[1]),
263 | .T(padt4) ,
264 | .O(rgmii_td[1])
265 | );
266 | //--------------------------------------
267 |
268 | GTP_OSERDES #(
269 | .OSERDES_MODE("ODDR"), //"ODDR","OMDDR","OGSER4","OMSER4","OGSER7","OGSER8",OMSER8"
270 | .WL_EXTEND ("FALSE"), //"TRUE"; "FALSE"
271 | .GRS_EN ("TRUE"), //"TRUE"; "FALSE"
272 | .LRS_EN ("TRUE"), //"TRUE"; "FALSE"
273 | .TSDDR_INIT (1'b0) //1'b0;1'b1
274 | ) gtp_ogddr5(
275 | .DO (stxd_rgm[0]),
276 | .TQ (padt5),
277 | .DI ({6'd0,gmii_txd_low[0],gmii_txd_r_d1[0]}),
278 | .TI (4'd0),
279 | .RCLK (gmii_tx_clk_s),
280 | .SERCLK(gmii_tx_clk_s),
281 | .OCLK (1'd0),
282 | .RST (tx_reset_sync)
283 | );
284 |
285 |
286 | GTP_OUTBUFT gtp_outbuft5
287 | (
288 |
289 | .I(stxd_rgm[0]),
290 | .T(padt5) ,
291 | .O(rgmii_td[0])
292 | );
293 |
294 | GTP_OSERDES #(
295 | .OSERDES_MODE("ODDR"), //"ODDR","OMDDR","OGSER4","OMSER4","OGSER7","OGSER8",OMSER8"
296 | .WL_EXTEND ("FALSE"), //"TRUE"; "FALSE"
297 | .GRS_EN ("TRUE"), //"TRUE"; "FALSE"
298 | .LRS_EN ("TRUE"), //"TRUE"; "FALSE"
299 | .TSDDR_INIT (1'b0) //1'b0;1'b1
300 | ) gtp_ogddr1(
301 | .DO (stx_ctr),
302 | .TQ (padt1),
303 | .DI ({6'd0,rgmii_tx_ctl_r,gmii_tx_en_r_d1}),
304 | .TI (4'd0),
305 | .RCLK (gmii_tx_clk_s),
306 | .SERCLK(gmii_tx_clk_s),
307 | .OCLK (1'd0),
308 | .RST (tx_reset_sync)
309 | );
310 | GTP_OUTBUFT gtp_outbuft1
311 | (
312 |
313 | .I(stx_ctr),
314 | .T(padt1) ,
315 | .O(rgmii_tx_ctl)
316 | );
317 |
318 |
319 | wire [5:0] nc1;
320 | GTP_ISERDES #(
321 | .ISERDES_MODE("IDDR"), //"IDDR","IMDDR","IGDES4","IMDES4","IGDES7","IGDES8","IMDES8"
322 | .GRS_EN ("TRUE"), //"TRUE"; "FALSE"
323 | .LRS_EN ("TRUE") //"TRUE"; "FALSE"
324 | ) igddr1(
325 | .DI (rgmii_rd[0]),
326 | .ICLK (1'd0 ),
327 | .DESCLK(gmii_rx_clk ),
328 | .RCLK (gmii_rx_clk ),
329 | .WADDR (3'd0),
330 | .RADDR (3'd0),
331 | .RST (1'b0),
332 | .DO ({gmii_rxd_s[4],gmii_rxd_s[0],nc1})
333 | );
334 |
335 | wire [5:0] nc2;
336 | GTP_ISERDES #(
337 | .ISERDES_MODE("IDDR"), //"IDDR","IMDDR","IGDES4","IMDES4","IGDES7","IGDES8","IMDES8"
338 | .GRS_EN ("TRUE"), //"TRUE"; "FALSE"
339 | .LRS_EN ("TRUE") //"TRUE"; "FALSE"
340 | ) igddr2(
341 | .DI (rgmii_rd[1]),
342 | .ICLK (1'd0 ),
343 | .DESCLK(gmii_rx_clk ),
344 | .RCLK (gmii_rx_clk ),
345 | .WADDR (3'd0),
346 | .RADDR (3'd0),
347 | .RST (1'b0),
348 | .DO ({gmii_rxd_s[5],gmii_rxd_s[1],nc2})
349 | );
350 |
351 | wire [5:0] nc3;
352 | GTP_ISERDES #(
353 | .ISERDES_MODE("IDDR"), //"IDDR","IMDDR","IGDES4","IMDES4","IGDES7","IGDES8","IMDES8"
354 | .GRS_EN ("TRUE"), //"TRUE"; "FALSE"
355 | .LRS_EN ("TRUE") //"TRUE"; "FALSE"
356 | ) igddr3(
357 | .DI (rgmii_rd[2]),
358 | .ICLK (1'd0 ),
359 | .DESCLK(gmii_rx_clk ),
360 | .RCLK (gmii_rx_clk ),
361 | .WADDR (3'd0),
362 | .RADDR (3'd0),
363 | .RST (1'b0),
364 | .DO ({gmii_rxd_s[6],gmii_rxd_s[2],nc3})
365 | );
366 |
367 | wire [5:0] nc4;
368 | GTP_ISERDES #(
369 | .ISERDES_MODE("IDDR"), //"IDDR","IMDDR","IGDES4","IMDES4","IGDES7","IGDES8","IMDES8"
370 | .GRS_EN ("TRUE"), //"TRUE"; "FALSE"
371 | .LRS_EN ("TRUE") //"TRUE"; "FALSE"
372 | ) igddr4(
373 | .DI (rgmii_rd[3]),
374 | .ICLK (1'd0 ),
375 | .DESCLK(gmii_rx_clk ),
376 | .RCLK (gmii_rx_clk ),
377 | .WADDR (3'd0),
378 | .RADDR (3'd0),
379 | .RST (1'b0),
380 | .DO ({gmii_rxd_s[7],gmii_rxd_s[3],nc4})
381 | );
382 |
383 | wire [5:0] nc5;
384 | GTP_ISERDES #(
385 | .ISERDES_MODE("IDDR"), //"IDDR","IMDDR","IGDES4","IMDES4","IGDES7","IGDES8","IMDES8"
386 | .GRS_EN ("TRUE"), //"TRUE"; "FALSE"
387 | .LRS_EN ("TRUE") //"TRUE"; "FALSE"
388 | ) igddr5(
389 | .DI (rgmii_rx_ctl),
390 | .ICLK (1'd0 ),
391 | .DESCLK(gmii_rx_clk ),
392 | .RCLK (gmii_rx_clk ),
393 | .WADDR (3'd0),
394 | .RADDR (3'd0),
395 | .RST (1'b0),
396 | .DO ({rgmii_rx_ctl_s,gmii_rx_dv_s,nc5})
397 | );
398 |
399 |
400 | endmodule
401 |
--------------------------------------------------------------------------------
/RTL/rx/udp_rx.v:
--------------------------------------------------------------------------------
1 | //////////////////////////////////////////////////////////////////////////////////////
2 | //Module Name : udp_rx
3 | //Description : This module is used to receive UDP data and verify UDP checksum
4 | //
5 | //////////////////////////////////////////////////////////////////////////////////////
6 | `timescale 1 ns/1 ns
7 | module udp_rx
8 | (
9 | input clk,
10 | input rst_n,
11 |
12 | input [7:0] udp_rx_data,
13 | input udp_rx_req,
14 |
15 | input mac_rec_error,
16 | input [7:0] net_protocol,
17 | input [31:0] ip_rec_source_addr,
18 | input [31:0] ip_rec_destination_addr,
19 | input ip_checksum_error,
20 | input ip_addr_check_error,
21 |
22 | input [15:0] upper_layer_data_length,
23 | output [7:0] udp_rec_ram_rdata , //udp ram read data
24 | input [10:0] udp_rec_ram_read_addr, //udp ram read address
25 | output reg [15:0] udp_rec_data_length, //udp data length
26 | output reg udp_rec_data_valid //udp data valid
27 | );
28 |
29 | reg [15:0] udp_rx_cnt ;
30 | reg verify_end ;
31 | reg udp_checksum_error ;
32 |
33 | reg [10:0] ram_write_addr ;
34 | reg ram_wr_en ;
35 | reg [15:0] udp_data_length ;
36 | reg ip_addr_check_error_d0 ;
37 | reg [7:0] udp_rx_data_d0 ; //udp data resigster
38 |
39 | parameter IDLE = 8'b0000_0001 ;
40 | parameter REC_HEAD = 8'b0000_0010 ;
41 | parameter REC_DATA = 8'b0000_0100 ;
42 | parameter REC_ODD_DATA = 8'b0000_1000 ;
43 | parameter VERIFY_CHECKSUM = 8'b0001_0000 ;
44 | parameter REC_ERROR = 8'b0010_0000 ;
45 | parameter REC_END_WAIT = 8'b0100_0000 ;
46 | parameter REC_END = 8'b1000_0000 ;
47 |
48 | reg [7:0] state ;
49 | reg [7:0] next_state ;
50 |
51 | always @(posedge clk or negedge rst_n)
52 | begin
53 | if (~rst_n)
54 | state <= IDLE ;
55 | else
56 | state <= next_state ;
57 | end
58 |
59 | always @(*)
60 | begin
61 | case(state)
62 | IDLE :
63 | begin
64 | if (udp_rx_req == 1'b1)
65 | next_state <= REC_HEAD ;
66 | else
67 | next_state <= IDLE ;
68 | end
69 | REC_HEAD :
70 | begin
71 | if (ip_checksum_error)
72 | next_state <= REC_ERROR ;
73 | else if (udp_rx_cnt == 16'd7)
74 | begin
75 | if (udp_data_length == 16'd9)
76 | next_state <= REC_ODD_DATA ;
77 | else
78 | next_state <= REC_DATA ;
79 | end
80 | else if (ip_addr_check_error_d0)
81 | next_state <= REC_ERROR ;
82 | else
83 | next_state <= REC_HEAD ;
84 | end
85 | REC_DATA :
86 | begin
87 | if (ip_checksum_error)
88 | next_state <= REC_ERROR ;
89 | else if (udp_data_length[0] == 1'b1 && udp_rx_cnt == udp_data_length - 2)
90 | next_state <= REC_ODD_DATA ;
91 | else if (udp_data_length[0] == 1'b0 && udp_rx_cnt == udp_data_length - 1)
92 | next_state <= VERIFY_CHECKSUM ;
93 | else
94 | next_state <= REC_DATA ;
95 | end
96 | REC_ODD_DATA :
97 | begin
98 | if (ip_checksum_error)
99 | next_state <= REC_ERROR ;
100 | else if (udp_rx_cnt == udp_data_length - 1)
101 | next_state <= VERIFY_CHECKSUM ;
102 | else
103 | next_state <= REC_ODD_DATA ;
104 | end
105 | VERIFY_CHECKSUM :
106 | begin
107 | if (udp_checksum_error)
108 | next_state <= REC_ERROR ;
109 | else if (verify_end)
110 | next_state <= REC_END_WAIT ;
111 | else if (udp_rx_cnt == 16'hffff)
112 | next_state <= IDLE ;
113 | else
114 | next_state <= VERIFY_CHECKSUM ;
115 | end
116 | REC_ERROR :
117 | next_state <= IDLE ;
118 | REC_END_WAIT :
119 | begin
120 | if (udp_rx_cnt == 16'd63)
121 | next_state <= REC_END ;
122 | else
123 | next_state <= REC_END_WAIT ;
124 | end
125 | REC_END :
126 | next_state <= IDLE ;
127 | default :
128 | next_state <= IDLE ;
129 | endcase
130 | end
131 |
132 |
133 |
134 |
135 | always @(posedge clk or negedge rst_n)
136 | begin
137 | if (~rst_n)
138 | ram_wr_en <= 1'b0 ;
139 | else if ((state == REC_DATA || state == REC_ODD_DATA) && udp_rx_cnt < udp_data_length)
140 | ram_wr_en <= 1'b1 ;
141 | else
142 | ram_wr_en <= 1'b0 ;
143 | end
144 |
145 | always @(posedge clk or negedge rst_n)
146 | begin
147 | if (~rst_n)
148 | ram_write_addr <= 11'd0 ;
149 | else if (state == REC_DATA || state == REC_ODD_DATA)
150 | ram_write_addr <= udp_rx_cnt - 8 ;
151 | else
152 | ram_write_addr <= 11'd0 ;
153 | end
154 | //ip address check
155 | always @(posedge clk or negedge rst_n)
156 | begin
157 | if (~rst_n)
158 | ip_addr_check_error_d0 <= 1'b0 ;
159 | else
160 | ip_addr_check_error_d0 <= ip_addr_check_error ;
161 | end
162 | //udp data length
163 | always @(posedge clk or negedge rst_n)
164 | begin
165 | if (~rst_n)
166 | udp_data_length <= 16'd0 ;
167 | else if (state == IDLE)
168 | udp_data_length <= upper_layer_data_length ;
169 | end
170 |
171 | always @(posedge clk or negedge rst_n)
172 | begin
173 | if (~rst_n)
174 | udp_rec_data_length <= 16'd0 ;
175 | else if (state == REC_END)
176 | udp_rec_data_length <= udp_data_length ;
177 | end
178 |
179 | always @(posedge clk or negedge rst_n)
180 | begin
181 | if (~rst_n)
182 | udp_rx_cnt <= 16'd0 ;
183 | else if (state == REC_HEAD || state == REC_DATA || state == REC_END_WAIT)
184 | udp_rx_cnt <= udp_rx_cnt + 1'b1 ;
185 | else
186 | udp_rx_cnt <= 16'd0 ;
187 | end
188 |
189 | always @(posedge clk or negedge rst_n)
190 | begin
191 | if (~rst_n)
192 | udp_rx_data_d0 <= 8'd0 ;
193 | else
194 | udp_rx_data_d0 <= udp_rx_data ;
195 | end
196 |
197 | dpram
198 | #(
199 | .WIDTH(8),
200 | .DEPTH(11)
201 | )
202 | udp_receive_ram
203 | (
204 | .clock (clk ),
205 | .data (udp_rx_data_d0 ),
206 | .rdaddress (udp_rec_ram_read_addr ),
207 | .wraddress (ram_write_addr ),
208 | .wren (ram_wr_en ),
209 | .q (udp_rec_ram_rdata )
210 | );
211 |
212 |
213 | //****************************************************************//
214 | //verify checksum
215 | //****************************************************************//
216 | reg [16:0] checksum_tmp0 ;
217 | reg [16:0] checksum_tmp1 ;
218 | reg [16:0] checksum_tmp2 ;
219 | reg [17:0] checksum_tmp3 ;
220 | reg [18:0] checksum_tmp4 ;
221 | reg [31:0] checksum_tmp5 ;
222 | reg [31:0] checksum_buf ;
223 | reg [31:0] check_out ;
224 | reg [31:0] checkout_buf ;
225 | wire [15:0] checksum ;
226 | reg [2:0] checksum_cnt ;
227 |
228 | //checksum function
229 | function [31:0] checksum_adder
230 | (
231 | input [31:0] dataina,
232 | input [31:0] datainb
233 | );
234 |
235 | begin
236 | checksum_adder = dataina + datainb;
237 | end
238 | endfunction
239 |
240 | function [31:0] checksum_out
241 | (
242 | input [31:0] dataina
243 | );
244 |
245 | begin
246 | checksum_out = dataina[15:0]+dataina[31:16];
247 | end
248 |
249 | endfunction
250 |
251 | always @(posedge clk or negedge rst_n)
252 | begin
253 | if(rst_n == 1'b0)
254 | begin
255 | checksum_tmp0 <= 17'd0 ;
256 | checksum_tmp1 <= 17'd0 ;
257 | checksum_tmp2 <= 17'd0 ;
258 | checksum_tmp3 <= 18'd0 ;
259 | checksum_tmp4 <= 19'd0 ;
260 | end
261 | else if (state == REC_HEAD)
262 | begin
263 | checksum_tmp0 <= checksum_adder(ip_rec_source_addr[31:16],ip_rec_source_addr[15:0]); //source ip address
264 | checksum_tmp1 <= checksum_adder(ip_rec_destination_addr[31:16],ip_rec_destination_addr[15:0]); //destination ip address
265 | checksum_tmp2 <= checksum_adder({8'd0,net_protocol},udp_data_length); //protocol type
266 | checksum_tmp3 <= checksum_adder(checksum_tmp0,checksum_tmp1); //protocol type
267 | checksum_tmp4 <= checksum_adder(checksum_tmp2,checksum_tmp3);
268 | end
269 | else if (state == IDLE)
270 | begin
271 | checksum_tmp0 <= 17'd0 ;
272 | checksum_tmp1 <= 17'd0 ;
273 | checksum_tmp2 <= 17'd0 ;
274 | checksum_tmp3 <= 18'd0 ;
275 | checksum_tmp4 <= 19'd0 ;
276 | end
277 | end
278 |
279 | always @(posedge clk or negedge rst_n)
280 | begin
281 | if(rst_n == 1'b0)
282 | checksum_tmp5 <= 32'd0;
283 | else if (state == REC_HEAD || state == REC_DATA)
284 | begin
285 | if (udp_rx_cnt[0] == 1'b1)
286 | checksum_tmp5 <= checksum_adder({udp_rx_data_d0,udp_rx_data},checksum_buf);
287 | end
288 | else if (state == REC_ODD_DATA)
289 | checksum_tmp5 <= checksum_adder({udp_rx_data,8'h00},checksum_tmp5); //if udp data length is odd, fill with one byte 8'h00
290 | else if (state == IDLE)
291 | checksum_tmp5 <= 32'd0 ;
292 | end
293 |
294 | always @(posedge clk or negedge rst_n)
295 | begin
296 | if(rst_n == 1'b0)
297 | checksum_cnt <= 3'd0 ;
298 | else if (state == VERIFY_CHECKSUM)
299 | checksum_cnt <= checksum_cnt + 1'b1 ;
300 | else
301 | checksum_cnt <= 3'd0 ;
302 | end
303 |
304 | always @(posedge clk or negedge rst_n)
305 | begin
306 | if(rst_n == 1'b0)
307 | check_out <= 32'd0;
308 | else if (state == VERIFY_CHECKSUM)
309 | begin
310 | if(checksum_cnt == 3'd0)
311 | check_out <= checksum_adder(checksum_tmp4, checksum_tmp5);
312 | else if (checksum_cnt == 3'd1)
313 | check_out <= checksum_out(check_out) ;
314 | else if (checksum_cnt == 3'd2)
315 | check_out <= checksum_out(check_out) ;
316 | end
317 | end
318 |
319 | always @(posedge clk or negedge rst_n)
320 | begin
321 | if (~rst_n)
322 | checksum_buf <= 32'd0 ;
323 | else if (state == REC_HEAD || state == REC_DATA)
324 | checksum_buf <= checksum_tmp5 ;
325 | else
326 | checksum_buf <= 32'd0 ;
327 | end
328 |
329 | always @(posedge clk or negedge rst_n)
330 | begin
331 | if (~rst_n)
332 | checkout_buf <= 32'd0 ;
333 | else if (state == VERIFY_CHECKSUM)
334 | checkout_buf <= check_out ;
335 | else
336 | checkout_buf <= 32'd0 ;
337 | end
338 |
339 | assign checksum = ~checkout_buf[15:0] ;
340 | //**************************************************//
341 | //generate udp rx end
342 | always @(posedge clk or negedge rst_n)
343 | begin
344 | if (~rst_n)
345 | begin
346 | udp_checksum_error <= 1'b0 ;
347 | verify_end <= 1'b0 ;
348 | end
349 | else if (state == VERIFY_CHECKSUM && checksum_cnt == 3'd4)
350 | begin
351 | if (checksum == 16'd0)
352 | begin
353 | udp_checksum_error <= 1'b0 ;
354 | verify_end <= 1'b1 ;
355 | end
356 | else
357 | begin
358 | udp_checksum_error <= 1'b1 ;
359 | verify_end <= 1'b0 ;
360 | end
361 | end
362 | else
363 | begin
364 | udp_checksum_error <= 1'b0 ;
365 | verify_end <= 1'b0 ;
366 | end
367 | end
368 |
369 | always @(posedge clk or negedge rst_n)
370 | begin
371 | if (~rst_n)
372 | udp_rec_data_valid <= 1'b0 ;
373 | else if (state == REC_END_WAIT)
374 | udp_rec_data_valid <= 1'b0 ;
375 | else if (state == REC_END)
376 | begin
377 | if (mac_rec_error)
378 | udp_rec_data_valid <= 1'b0 ;
379 | else
380 | udp_rec_data_valid <= 1'b1 ;
381 | end
382 | end
383 |
384 |
385 | endmodule
386 |
--------------------------------------------------------------------------------
/RTL/tx/ip_tx.v:
--------------------------------------------------------------------------------
1 | //////////////////////////////////////////////////////////////////////////////////////
2 | //Module Name : ip_tx
3 | //Description : This module is used to send ip layer data, generate ip header checksum,
4 | // receive data from udp or icmp, then send to mac layer
5 | //
6 | //
7 | //////////////////////////////////////////////////////////////////////////////////////
8 | `timescale 1 ns/1 ns
9 | module ip_tx
10 | (
11 | input clk ,
12 | input rst_n ,
13 | input [15:0] identify_code,
14 | input [47:0] destination_mac_addr , //destination mac address
15 | input [47:0] source_mac_addr , //source mac address
16 | input [7:0] TTL,
17 | input [7:0] ip_send_type,
18 | input [31:0] source_ip_addr,
19 | input [31:0] destination_ip_addr,
20 | input [7:0] upper_layer_data, //data from udp or icmp
21 | output reg upper_data_req, //request data from udp or icmp
22 |
23 | input mac_data_req,
24 | input upper_tx_ready,
25 | input ip_tx_req,
26 | input [15:0] ip_send_data_length ,
27 |
28 | output ip_tx_busy,
29 | output reg ip_tx_ready,
30 | output reg [7:0] ip_tx_data,
31 | output reg ip_tx_end
32 | ) ;
33 |
34 | localparam mac_type = 16'h0800 ;
35 | localparam ip_version = 4'h4 ; //ipv4
36 | localparam header_len = 4'h5 ; //header length
37 |
38 | reg checksum_finish ;
39 |
40 | reg [15:0] ip_send_data_length_d0 ;
41 | reg [15:0] ip_send_cnt ;
42 | reg [15:0] timeout ;
43 | reg [3:0] wait_cnt ;
44 |
45 | parameter IDLE = 6'b000_001 ;
46 | parameter WAIT_DATA_LENGTH = 6'b000_010 ;
47 | parameter GEN_CHECKSUM = 6'b000_100 ;
48 | parameter SEND_WAIT = 6'b001_000 ;
49 | parameter WAIT_MAC = 6'b010_000 ;
50 | parameter IP_SEND = 6'b100_000 ;
51 |
52 | reg [5:0] state ;
53 | reg [5:0] next_state ;
54 |
55 | always @(posedge clk or negedge rst_n)
56 | begin
57 | if (~rst_n)
58 | state <= IDLE ;
59 | else
60 | state <= next_state ;
61 | end
62 |
63 | always @(*)
64 | begin
65 | case(state)
66 | IDLE :
67 | begin
68 | if (ip_tx_req)
69 | next_state <= WAIT_DATA_LENGTH ;
70 | else
71 | next_state <= IDLE ;
72 | end
73 |
74 | WAIT_DATA_LENGTH :
75 | begin
76 | if (wait_cnt == 4'd7)
77 | next_state <= GEN_CHECKSUM ;
78 | else
79 | next_state <= WAIT_DATA_LENGTH ;
80 | end
81 | GEN_CHECKSUM :
82 | begin
83 | if (checksum_finish)
84 | next_state <= SEND_WAIT ;
85 | else
86 | next_state <= GEN_CHECKSUM ;
87 | end
88 |
89 | SEND_WAIT :
90 | begin
91 | if (upper_tx_ready)
92 | next_state <= WAIT_MAC ;
93 | else if (timeout == 16'hffff)
94 | next_state <= IDLE ;
95 | else
96 | next_state <= SEND_WAIT ;
97 | end
98 | WAIT_MAC :
99 | begin
100 | if (mac_data_req)
101 | next_state <= IP_SEND ;
102 | else if (timeout == 16'hffff)
103 | next_state <= IDLE ;
104 | else
105 | next_state <= WAIT_MAC ;
106 | end
107 | IP_SEND :
108 | begin
109 | if (ip_send_cnt == 14 + ip_send_data_length_d0)
110 | next_state <= IDLE ;
111 | else
112 | next_state <= IP_SEND ;
113 | end
114 | default :
115 | next_state <= IDLE ;
116 | endcase
117 | end
118 |
119 |
120 |
121 | always @(posedge clk or negedge rst_n)
122 | begin
123 | if (~rst_n)
124 | ip_tx_ready <= 1'b0 ;
125 | else if (state == WAIT_MAC)
126 | ip_tx_ready <= upper_tx_ready ;
127 | else
128 | ip_tx_ready <= 1'b0 ;
129 | end
130 |
131 | always @(posedge clk or negedge rst_n)
132 | begin
133 | if (~rst_n)
134 | ip_tx_end <= 1'b0 ;
135 | else if ((state == IP_SEND) && (ip_send_cnt == 13 + ip_send_data_length_d0))
136 | ip_tx_end <= 1'b1 ;
137 | else
138 | ip_tx_end <= 1'b0 ;
139 | end
140 |
141 | //request data from icmp or udp
142 | always @(posedge clk or negedge rst_n)
143 | begin
144 | if (~rst_n)
145 | upper_data_req <= 1'b0 ;
146 | else if (state == IP_SEND && ip_send_cnt == 16'd30)
147 | upper_data_req <= 1'b1 ;
148 | else
149 | upper_data_req <= 1'b0 ;
150 | end
151 |
152 | //timeout counter
153 | always @(posedge clk or negedge rst_n)
154 | begin
155 | if (~rst_n)
156 | timeout <= 16'd0 ;
157 | else if (upper_tx_ready)
158 | timeout <= 16'd0 ;
159 | else if (state == SEND_WAIT || state == WAIT_MAC)
160 | timeout <= timeout + 1'b1 ;
161 | else
162 | timeout <= 16'd0 ;
163 | end
164 |
165 | always @(posedge clk or negedge rst_n)
166 | begin
167 | if (~rst_n)
168 | wait_cnt <= 4'd0 ;
169 | else if (state == WAIT_DATA_LENGTH)
170 | wait_cnt <= wait_cnt + 1'b1 ;
171 | else
172 | wait_cnt <= 4'd0 ;
173 | end
174 |
175 | //always @(posedge clk or negedge rst_n)
176 | //begin
177 | // if (~rst_n)
178 | // identify_code <= 16'd0 ;
179 | // else if (ip_tx_end)
180 | // identify_code <= identify_code + 1'b1 ;
181 | //end
182 |
183 | always @(posedge clk or negedge rst_n)
184 | begin
185 | if (~rst_n)
186 | ip_send_data_length_d0 <= 16'd0 ;
187 | else
188 | begin
189 | if (ip_send_data_length < 46)
190 | ip_send_data_length_d0 <= 16'd46 ;
191 | else
192 | ip_send_data_length_d0 <= ip_send_data_length ;
193 | end
194 | end
195 |
196 | always @(posedge clk or negedge rst_n)
197 | begin
198 | if (~rst_n)
199 | ip_send_cnt <= 16'd0 ;
200 | else if (state == GEN_CHECKSUM || state == IP_SEND)
201 | ip_send_cnt <= ip_send_cnt + 1'b1 ;
202 | else
203 | ip_send_cnt <= 16'd0 ;
204 | end
205 | //checksum generation
206 |
207 | reg [16:0] checksum_tmp0 ;
208 | reg [16:0] checksum_tmp1 ;
209 | reg [16:0] checksum_tmp2 ;
210 | reg [16:0] checksum_tmp3 ;
211 | reg [16:0] checksum_tmp4 ;
212 | reg [17:0] checksum_tmp5 ;
213 | reg [17:0] checksum_tmp6 ;
214 | reg [18:0] checksum_tmp7 ;
215 | reg [19:0] checksum_tmp8 ;
216 | reg [19:0] check_out ;
217 | reg [19:0] checkout_buf ;
218 | reg [15:0] checksum ;
219 |
220 |
221 | //checksum function
222 | function [31:0] checksum_adder
223 | (
224 | input [31:0] dataina,
225 | input [31:0] datainb
226 | );
227 |
228 | begin
229 | checksum_adder = dataina + datainb;
230 | end
231 | endfunction
232 |
233 | function [31:0] checksum_out
234 | (
235 | input [31:0] dataina
236 | );
237 |
238 | begin
239 | checksum_out = dataina[15:0]+dataina[31:16];
240 | end
241 |
242 | endfunction
243 |
244 |
245 | always @(posedge clk or negedge rst_n)
246 | begin
247 | if (~rst_n)
248 | begin
249 | checksum_tmp0 <= 17'd0 ;
250 | checksum_tmp1 <= 17'd0 ;
251 | checksum_tmp2 <= 17'd0 ;
252 | checksum_tmp3 <= 17'd0 ;
253 | checksum_tmp4 <= 17'd0 ;
254 | checksum_tmp5 <= 18'd0 ;
255 | checksum_tmp6 <= 18'd0 ;
256 | checksum_tmp7 <= 19'd0 ;
257 | checksum_tmp8 <= 20'd0 ;
258 | check_out <= 20'd0 ;
259 | checkout_buf <= 20'd0 ;
260 | end
261 | else if (state == GEN_CHECKSUM)
262 | begin
263 | checksum_tmp0 <= checksum_adder(16'h4500,ip_send_data_length);
264 | checksum_tmp1 <= checksum_adder(identify_code, 16'h4000) ;
265 | checksum_tmp2 <= checksum_adder({TTL,ip_send_type}, 16'h0000) ;
266 | checksum_tmp3 <= checksum_adder(source_ip_addr[31:16], source_ip_addr[15:0]) ;
267 | checksum_tmp4 <= checksum_adder(destination_ip_addr[31:16], destination_ip_addr[15:0]) ;
268 | checksum_tmp5 <= checksum_adder(checksum_tmp0, checksum_tmp1) ;
269 | checksum_tmp6 <= checksum_adder(checksum_tmp2, checksum_tmp3) ;
270 | checksum_tmp7 <= checksum_adder(checksum_tmp5, checksum_tmp6) ;
271 | checksum_tmp8 <= checksum_adder(checksum_tmp4, checksum_tmp7) ;
272 | check_out <= checksum_out(checksum_tmp8) ;
273 | checkout_buf <= checksum_out(check_out) ;
274 | end
275 | else if (state == IDLE)
276 | begin
277 | checksum_tmp0 <= 17'd0 ;
278 | checksum_tmp1 <= 17'd0 ;
279 | checksum_tmp2 <= 17'd0 ;
280 | checksum_tmp3 <= 17'd0 ;
281 | checksum_tmp4 <= 17'd0 ;
282 | checksum_tmp5 <= 18'd0 ;
283 | checksum_tmp6 <= 18'd0 ;
284 | checksum_tmp7 <= 19'd0 ;
285 | checksum_tmp8 <= 20'd0 ;
286 | check_out <= 20'd0 ;
287 | checkout_buf <= 20'd0 ;
288 | end
289 | end
290 |
291 |
292 |
293 |
294 |
295 | always @(posedge clk or negedge rst_n)
296 | begin
297 | if (~rst_n)
298 | checksum <= 32'd0 ;
299 | else if (state == GEN_CHECKSUM)
300 | checksum <= ~checkout_buf[15:0] ;
301 | end
302 | //assign checksum = ~checkout_buf[15:0] ;
303 | //*******************************************************//
304 |
305 | always @(posedge clk or negedge rst_n)
306 | begin
307 | if (~rst_n)
308 | checksum_finish <= 1'b0 ;
309 | else if (state == GEN_CHECKSUM && ip_send_cnt == 16'd13)
310 | checksum_finish <= 1'b1 ;
311 | else
312 | checksum_finish <= 1'b0 ;
313 | end
314 |
315 | always @(posedge clk or negedge rst_n)
316 | begin
317 | if (~rst_n)
318 | ip_tx_data <= 8'h00 ;
319 | else if (state == IP_SEND)
320 | begin
321 | case(ip_send_cnt)
322 | 16'd0 : ip_tx_data <= destination_mac_addr[47:40] ;
323 | 16'd1 : ip_tx_data <= destination_mac_addr[39:32] ;
324 | 16'd2 : ip_tx_data <= destination_mac_addr[31:24] ;
325 | 16'd3 : ip_tx_data <= destination_mac_addr[23:16] ;
326 | 16'd4 : ip_tx_data <= destination_mac_addr[15:8] ;
327 | 16'd5 : ip_tx_data <= destination_mac_addr[7:0] ;
328 | 16'd6 : ip_tx_data <= source_mac_addr[47:40] ;
329 | 16'd7 : ip_tx_data <= source_mac_addr[39:32] ;
330 | 16'd8 : ip_tx_data <= source_mac_addr[31:24] ;
331 | 16'd9 : ip_tx_data <= source_mac_addr[23:16] ;
332 | 16'd10 : ip_tx_data <= source_mac_addr[15:8] ;
333 | 16'd11 : ip_tx_data <= source_mac_addr[7:0] ;
334 | 16'd12 : ip_tx_data <= mac_type[15:8] ;
335 | 16'd13 : ip_tx_data <= mac_type[7:0] ;
336 | 16'd14 : ip_tx_data <= {ip_version, header_len} ;
337 | 16'd15 : ip_tx_data <= 8'h00 ;
338 | 16'd16 : ip_tx_data <= ip_send_data_length[15:8] ;
339 | 16'd17 : ip_tx_data <= ip_send_data_length[7:0] ;
340 | 16'd18 : ip_tx_data <= identify_code[15:8] ;
341 | 16'd19 : ip_tx_data <= identify_code[7:0] ;
342 | 16'd20 : ip_tx_data <= 8'h40 ;
343 | 16'd21 : ip_tx_data <= 8'h00 ;
344 | 16'd22 : ip_tx_data <= TTL ;
345 | 16'd23 : ip_tx_data <= ip_send_type ;
346 | 16'd24 : ip_tx_data <= checksum[15:8] ;
347 | 16'd25 : ip_tx_data <= checksum[7:0] ;
348 | 16'd26 : ip_tx_data <= source_ip_addr[31:24] ;
349 | 16'd27 : ip_tx_data <= source_ip_addr[23:16] ;
350 | 16'd28 : ip_tx_data <= source_ip_addr[15:8] ;
351 | 16'd29 : ip_tx_data <= source_ip_addr[7:0] ;
352 | 16'd30 : ip_tx_data <= destination_ip_addr[31:24] ;
353 | 16'd31 : ip_tx_data <= destination_ip_addr[23:16] ;
354 | 16'd32 : ip_tx_data <= destination_ip_addr[15:8] ;
355 | 16'd33 : ip_tx_data <= destination_ip_addr[7:0] ;
356 | default : ip_tx_data <= upper_layer_data ;
357 | endcase
358 | end
359 | else
360 | ip_tx_data <= 8'h00 ;
361 | end
362 |
363 |
364 |
365 | endmodule
366 |
--------------------------------------------------------------------------------
/dataset/process.py:
--------------------------------------------------------------------------------
1 | import cv2
2 | import os
3 | import sys
4 | import json
5 | import shutil
6 | import numpy as np
7 | import random
8 |
9 | # 把视频所有帧分离为图片
10 | def save_img():
11 | video_path = 'C:\\Users\\smn90\\repo\\FPGA-Image-Recognition\\dataset\\video\\'
12 | videos = os.listdir(video_path)
13 |
14 | for video_name in videos:
15 | file_name = video_name.split('.')[0]
16 | folder_name = os.path.join(video_path, file_name)
17 | os.makedirs(folder_name, exist_ok=True)
18 |
19 | # 读入视频文件
20 | vc = cv2.VideoCapture(video_path + video_name)
21 | c = 0
22 | print(file_name)
23 | rval = vc.isOpened()
24 | print(rval)
25 |
26 | # 循环读取视频帧
27 | while rval:
28 | rval, frame = vc.read()
29 | pic_path = folder_name + '\\'
30 | if rval:
31 | c_fill = str(c).zfill(6)
32 | # 存储为图像,保存名为视频名_帧数.jpg
33 | cv2.imwrite(pic_path + file_name + '_' + c_fill + '.jpg', frame)
34 | cv2.waitKey(1)
35 | else:
36 | break
37 | c = c + 1
38 |
39 | vc.release()
40 | print('save_success')
41 | print(folder_name)
42 | '''
43 | # 中断
44 | ans = input('input anything: ')
45 | if ans=='1':
46 | sys.exit()
47 | '''
48 |
49 | # 重命名每帧图片名称
50 | def rename():
51 | img_path = 'C:\\Users\\smn90\\repo\\FPGA-Image-Recognition\\dataset\\video\\ILSVRC2015_train_00005003'
52 | new_path = 'C:\\Users\\smn90\\repo\\FPGA-Image-Recognition\\dataset\\video\\ILSVRC2015_train_00005003_new'
53 | if not os.path.exists(new_path):
54 | os.makedirs(new_path)
55 | imgname = os.listdir(img_path)
56 | n = len(imgname)
57 | images = os.listdir(new_path)
58 | imgname.sort(key=lambda x: int(x[:-4]))
59 | count = len(images)
60 | i = count
61 |
62 | for img in imgname:
63 | if img.endswith('.jpg'):
64 | oldname = os.path.join(os.path.abspath(img_path), img)
65 | nname = str(i)
66 | nname = nname.zfill(6)
67 | newname = os.path.join(os.path.abspath(new_path), nname + '.jpg')
68 |
69 | try:
70 | os.rename(oldname, newname)
71 | print("rename %s to %s ..." % (oldname, newname))
72 | i = i + 1
73 | except:
74 | continue
75 |
76 | print("total %d to rename & converted %d files" % (n, i))
77 |
78 | # 格式化 Json 文件
79 | def fm_js():
80 | json_path = 'C:\\Users\\smn90\\repo\\FPGA-Image-Recognition\\dataset\\train\\'
81 | json_file = os.listdir(json_path)
82 | video_path = 'C:\\Users\\smn90\\repo\\FPGA-Image-Recognition\\dataset\\video\\'
83 | videos = os.listdir(video_path)
84 |
85 | for json_name in json_file:
86 | json_file_path = os.path.join(json_path, json_name)
87 |
88 | with open(json_file_path, 'r') as f:
89 | data = json.load(f)
90 |
91 | img_folder_name = data['video_id']
92 | # 检查 json 文件中的 video_id 是否存在有视频
93 | #if img_folder_name in videos:
94 |
95 | #list_object=[]
96 | dic_object={}
97 | for item in data['subject/objects']:
98 | #list_object.append(item['category'])
99 | dic_object[str(item['tid'])] = item['category']
100 |
101 | with open('train.txt','a') as train:
102 | num = 0
103 | for item in data['trajectories']:
104 | for r in range(len(item)):
105 | bbox_obj = item[r] # 按顺序取出每帧的 bbox
106 |
107 | tid = bbox_obj['tid']
108 | xmin = bbox_obj['bbox']['xmin']
109 | ymin = bbox_obj['bbox']['ymin']
110 | xmax = bbox_obj['bbox']['xmax']
111 | ymax = bbox_obj['bbox']['ymax']
112 | #obj=list_object[tid]
113 | obj = dic_object.get(str(tid))
114 |
115 | # 把图片的绝对路径打印
116 | num_temp = str(num).zfill(6)
117 | img_path = video_path + img_folder_name + '\\' + img_folder_name + '_' + num_temp + '.jpg'
118 | if r == 0:
119 | train.write(img_path +' '+str(xmin)+','+str(ymin)+','+str(xmax)+','+str(ymax)+ ',' + str(obj)+' ')
120 | else:
121 | train.write(str(xmin)+','+str(ymin)+','+str(xmax)+','+str(ymax) + ',' + str(obj)+' ')
122 |
123 | if r==len(item)-1:
124 | train.write('\n')
125 |
126 | num = num + 1
127 |
128 | # 中断
129 | '''
130 | ans = input('input anything: ')
131 | if ans=='1':
132 | sys.exit()
133 | '''
134 |
135 | # 将图片文件搬运到另一个文件夹
136 | def move():
137 | folder_path = 'C:\\Users\\smn90\\repo\\FPGA-Image-Recognition\\dataset\\video\\'
138 | folder_list = os.listdir(folder_path)
139 |
140 | for folder in folder_list:
141 | try:
142 | img_path = os.path.join(folder_path,folder)
143 | for img in os.listdir(img_path):
144 | src_path = os.path.join(img_path,img)
145 | dst_path = os.path.join(folder_path,img)
146 | shutil.move(src_path,dst_path)
147 | except:
148 | continue
149 |
150 | #中断
151 | '''
152 | ans = input('input anything: ')
153 | if ans=='1':
154 | sys.exit()
155 | '''
156 |
157 |
158 | # 交叉比对图片是否都有对应的标注文件,有的放一个文件夹,没有的放另一个文件夹
159 | def verify():
160 | img_path = 'C:\\Users\\smn90\\repo\\FPGA-Image-Recognition\\dataset\\video_temp\\'
161 | txt_path = 'C:\\Users\\smn90\\repo\\FPGA-Image-Recognition\\dataset\\train_extract.txt'
162 | new_path = 'C:\\Users\\smn90\\repo\\FPGA-Image-Recognition\\dataset\\video\\'
163 |
164 | with open(txt_path,'r') as f:
165 | for line in f:
166 | # 获取文件路径
167 | file_path = line.split()[0]
168 | #print(file_path)
169 | # 检查文件是否存在
170 | if os.path.isfile(file_path):
171 | #shutil.move(file_path,new_path)
172 | pass
173 | else:
174 | print(file_path)
175 | '''
176 | with open('train_failed.txt','a') as fail:
177 | fail.write(line)
178 | '''
179 | '''
180 | ans = input('input anything: ')
181 | if ans=='1':
182 | sys.exit()
183 | '''
184 |
185 | # 修改 txt 内容
186 | def modify():
187 | txt_path = 'C:\\Users\\smn90\\repo\\FPGA-Image-Recognition\\dataset\\train.txt'
188 |
189 | with open(txt_path, 'r') as f:
190 | lines = f.readlines()
191 | new_lines = []
192 | for line in lines:
193 | new_line = line[:58] + line[84:]
194 | new_lines.append(new_line)
195 |
196 | with open('train_new.txt', 'w') as f:
197 | f.writelines(new_lines)
198 |
199 |
200 | # 统计 txt 的所有目标类别,并替换名称为索引号
201 | def categary():
202 | file_path = 'C:\\Users\\smn90\\repo\\FPGA-Image-Recognition\\dataset\\train_new_1.txt'
203 | task_path = 'C:\\Users\\smn90\\repo\\FPGA-Image-Recognition\\dataset\\train_new_2.txt'
204 |
205 | obj_list = []
206 | with open(file_path, 'r') as f:
207 | for line in f:
208 | line_list = line.split()
209 | # 以逗号作为标识符检测有几个 bbox
210 | for item in line_list:
211 | if len(item.split(',')) > 1:
212 | obj = item.split(',')[-1]
213 | if obj not in obj_list:
214 | obj_list.append(obj)
215 |
216 | with open('categary.txt','w') as f:
217 | for obj in obj_list:
218 | f.write(obj + '\n')
219 |
220 | with open(task_path, 'r+') as f:
221 | lines = f.readlines()
222 | f.seek(0) # 将文件指针移回文件开头
223 |
224 | for line in lines:
225 | line = line.strip()
226 | items = line.split()
227 | new_items = []
228 | new_path_list = []
229 |
230 | for item in items:
231 | if len(item.split(',')) > 1:
232 | category = item.split(',')[-1]
233 | index = obj_list.index(category)
234 | new_items.append(item.replace(str(category), str(index)))
235 | else:
236 | new_path_list.append(item)
237 |
238 | new_line = ' '.join(new_path_list) + ' ' + ' '.join(new_items) + '\n'
239 | f.write(new_line)
240 |
241 | f.truncate() # 截断文件,删除多余内容
242 |
243 |
244 | # 令 txt 的标识与图片一一对应,去除没有 bbox 的帧信息
245 | def txt_veri():
246 | file_path = 'C:\\Users\\smn90\\repo\\FPGA-Image-Recognition\\dataset\\train_new_2.txt'
247 | pic_path = 'C:\\Users\\smn90\\repo\\FPGA-Image-Recognition\\dataset\\video\\'
248 |
249 | with open(file_path, 'r') as f, open('temp.txt', 'w') as temp:
250 | for line in f:
251 | line_list = line.split()
252 | path = line_list[0]
253 | if os.path.isfile(path):
254 | temp.write(line)
255 | else:
256 | pass
257 |
258 | # 将多种分辨率的照片全部缩放为 416x416,并在保持原始比例的情况下进行填充
259 | def resize_and_pad():
260 | file_path = 'C:\\Users\\smn90\\repo\\FPGA-Image-Recognition\\dataset\\train_new_2.txt'
261 | resize_path = 'C:\\Users\\smn90\\repo\\FPGA-Image-Recognition\\dataset\\video_resize\\'
262 | target_size = (416, 416)
263 |
264 | with open(file_path, 'r') as f:
265 | for line in f:
266 | line_list = line.split()
267 | image = cv2.imread(line_list[0])
268 |
269 | # 获取原始图像的尺寸
270 | height, width = image.shape[:2]
271 | # 计算缩放比例
272 | scale = min(target_size[0] / width, target_size[1] / height)
273 | new_width = int(width * scale)
274 | new_height = int(height * scale)
275 | # 缩放图像
276 | resized_image = cv2.resize(image, (new_width, new_height))
277 | # 创建目标大小的画布
278 | canvas = np.ones((target_size[1], target_size[0], 3), dtype=np.uint8) * 255
279 | # 计算填充位置
280 | x_offset = (target_size[0] - new_width) // 2
281 | y_offset = (target_size[1] - new_height) // 2
282 | # 将缩放后的图像复制到画布上
283 | canvas[y_offset:y_offset + new_height, x_offset:x_offset + new_width, :] = resized_image
284 |
285 | # 保存
286 | # 获取原始图像的文件名
287 | image_name = os.path.basename(line_list[0])
288 | # 构建保存路径
289 | output_path = os.path.join(resize_path, image_name)
290 | # 保存缩放和填充后的图像
291 | cv2.imwrite(output_path, canvas)
292 |
293 |
294 | # 仅抽取一部分图片用于训练,直接操作目标 txt 文件
295 | def simple():
296 | file_path = 'C:\\Users\\smn90\\repo\\FPGA-Image-Recognition\\dataset\\train_raw.txt'
297 | new_path = 'C:\\Users\\smn90\\repo\\FPGA-Image-Recognition\\dataset\\train_extract.txt'
298 |
299 | video_frames = {}
300 | line_list = []
301 | data_list = []
302 | pre_video_id = None
303 | flag = 0
304 | with open(file_path,'r') as f, open(new_path,'w') as new:
305 | for line in f:
306 | line_list = line.split()
307 | image_path = line_list[0]
308 | video_id = image_path.split('\\')[-1].split('_')[-2]
309 | frame_number = image_path.split('_')[-1].split('.')[0]
310 |
311 | if video_id not in video_frames:
312 | video_frames[video_id] = []
313 | video_frames[video_id].append(frame_number)
314 |
315 | if video_id == pre_video_id:
316 | flag = flag + 1
317 | data_list.append(line)
318 | else:
319 | if pre_video_id == None:
320 | pass
321 | else:
322 | tag = int(flag * 0.2)
323 | random_numbers = random.sample(range(flag), tag)
324 |
325 | for item in random_numbers:
326 | new.write(data_list[item])
327 |
328 | flag = 0
329 | data_list = [line]
330 |
331 | pre_video_id = video_id
332 |
333 |
334 |
335 | # 将 train.txt 的数据按行打乱
336 | def index():
337 | file_path = 'C:\\Users\\smn90\\repo\\deep_learn\\object_recog\\train_file\\VOC2007\\2007_train.txt'
338 | new_path = 'C:\\Users\\smn90\\repo\\deep_learn\\object_recog\\train_file\\VOC2007\\2007_train_random.txt'
339 | with open(file_path, 'r') as f:
340 | lines = f.readlines()
341 |
342 | # 打乱数据顺序
343 | random.shuffle(lines)
344 |
345 | # 将打乱后的数据写回文件
346 | with open(new_path, 'w') as f:
347 | f.writelines(lines)
348 |
349 |
350 |
351 |
352 | #save_img()
353 | #rename()
354 | #fm_js()
355 | #move()
356 | #verify()
357 | #modify()
358 | #categary()
359 | #txt_veri()
360 | #resize_and_pad()
361 | #simple()
362 | index()
--------------------------------------------------------------------------------