├── .gitignore ├── FPGA ├── bitstream_backup │ ├── 600p.sbit │ ├── 720p.sbit │ └── default.sbit └── constraint.fdc ├── LICENSE ├── RTL ├── eth_trans.v ├── fpga_top.v ├── mac │ ├── arp_cache.v │ ├── crc.v │ ├── dpram.v │ ├── icmp_reply.v │ ├── mac_test.v │ └── mac_top.v ├── main.filelist ├── new │ ├── camera_delay.v │ └── mac │ │ └── crc.v ├── reg_config_1.v ├── rtl │ ├── cmos_8_16bit.v │ ├── fram_buf.v │ ├── hdmi_ddr_ov5640_top.v │ ├── i2c_com.v │ ├── iic_dri.v │ ├── ms7200_ctl.v │ ├── ms7210_ctl.v │ ├── ms72xx_ctl.v │ ├── power_on_delay.v │ ├── rd_buf.v │ ├── rd_ctrl.v │ ├── reg_config.v │ ├── sync_vg.v │ ├── wr_buf.v │ ├── wr_cmd_trans.v │ ├── wr_ctrl.v │ └── wr_rd_ctrl_top.v ├── rx │ ├── arp_rx.v │ ├── ip_rx.v │ ├── mac_rx.v │ ├── mac_rx_top.v │ └── udp_rx.v ├── src │ └── util_gmii_to_rgmii.v └── tx │ ├── arp_tx.v │ ├── ip_tx.v │ ├── ip_tx_mode.v │ ├── mac_tx.v │ ├── mac_tx_mode.v │ ├── mac_tx_top.v │ └── udp_tx.v ├── dataset └── process.py ├── document ├── constraint.md └── 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 ├── readme.md └── software ├── model └── convert_tflite.py ├── obj_detect_multi_thread.py ├── obj_detect_single_thread.py └── udp_video.py /.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 -------------------------------------------------------------------------------- /FPGA/bitstream_backup/600p.sbit: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MongooseOrion/FPGA-Image-Recognition/7813e458d1600228886736094816db2f0a49ff39/FPGA/bitstream_backup/600p.sbit -------------------------------------------------------------------------------- /FPGA/bitstream_backup/720p.sbit: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MongooseOrion/FPGA-Image-Recognition/7813e458d1600228886736094816db2f0a49ff39/FPGA/bitstream_backup/720p.sbit -------------------------------------------------------------------------------- /FPGA/bitstream_backup/default.sbit: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MongooseOrion/FPGA-Image-Recognition/7813e458d1600228886736094816db2f0a49ff39/FPGA/bitstream_backup/default.sbit -------------------------------------------------------------------------------- /RTL/eth_trans.v: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MongooseOrion/FPGA-Image-Recognition/7813e458d1600228886736094816db2f0a49ff39/RTL/eth_trans.v -------------------------------------------------------------------------------- /RTL/fpga_top.v: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MongooseOrion/FPGA-Image-Recognition/7813e458d1600228886736094816db2f0a49ff39/RTL/fpga_top.v -------------------------------------------------------------------------------- /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/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/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/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/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/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/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/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/reg_config_1.v: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MongooseOrion/FPGA-Image-Recognition/7813e458d1600228886736094816db2f0a49ff39/RTL/reg_config_1.v -------------------------------------------------------------------------------- /RTL/rtl/cmos_8_16bit.v: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MongooseOrion/FPGA-Image-Recognition/7813e458d1600228886736094816db2f0a49ff39/RTL/rtl/cmos_8_16bit.v -------------------------------------------------------------------------------- /RTL/rtl/fram_buf.v: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MongooseOrion/FPGA-Image-Recognition/7813e458d1600228886736094816db2f0a49ff39/RTL/rtl/fram_buf.v -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /RTL/rtl/iic_dri.v: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MongooseOrion/FPGA-Image-Recognition/7813e458d1600228886736094816db2f0a49ff39/RTL/rtl/iic_dri.v -------------------------------------------------------------------------------- /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/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 | -------------------------------------------------------------------------------- /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/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 | -------------------------------------------------------------------------------- /RTL/rtl/reg_config.v: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MongooseOrion/FPGA-Image-Recognition/7813e458d1600228886736094816db2f0a49ff39/RTL/rtl/reg_config.v -------------------------------------------------------------------------------- /RTL/rtl/sync_vg.v: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MongooseOrion/FPGA-Image-Recognition/7813e458d1600228886736094816db2f0a49ff39/RTL/rtl/sync_vg.v -------------------------------------------------------------------------------- /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/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/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/rtl/wr_rd_ctrl_top.v: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MongooseOrion/FPGA-Image-Recognition/7813e458d1600228886736094816db2f0a49ff39/RTL/rtl/wr_rd_ctrl_top.v -------------------------------------------------------------------------------- /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/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/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/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/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/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/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 | -------------------------------------------------------------------------------- /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/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/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/tx/mac_tx_top.v: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MongooseOrion/FPGA-Image-Recognition/7813e458d1600228886736094816db2f0a49ff39/RTL/tx/mac_tx_top.v -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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() -------------------------------------------------------------------------------- /document/constraint.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MongooseOrion/FPGA-Image-Recognition/7813e458d1600228886736094816db2f0a49ff39/document/constraint.md -------------------------------------------------------------------------------- /document/pic/图片1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MongooseOrion/FPGA-Image-Recognition/7813e458d1600228886736094816db2f0a49ff39/document/pic/图片1.png -------------------------------------------------------------------------------- /document/pic/图片2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MongooseOrion/FPGA-Image-Recognition/7813e458d1600228886736094816db2f0a49ff39/document/pic/图片2.png -------------------------------------------------------------------------------- /document/pic/屏幕截图 2023-08-03 162036.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MongooseOrion/FPGA-Image-Recognition/7813e458d1600228886736094816db2f0a49ff39/document/pic/屏幕截图 2023-08-03 162036.png -------------------------------------------------------------------------------- /document/pic/屏幕截图 2023-08-09 164303.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MongooseOrion/FPGA-Image-Recognition/7813e458d1600228886736094816db2f0a49ff39/document/pic/屏幕截图 2023-08-09 164303.png -------------------------------------------------------------------------------- /document/pic/屏幕截图 2023-08-09 165537.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MongooseOrion/FPGA-Image-Recognition/7813e458d1600228886736094816db2f0a49ff39/document/pic/屏幕截图 2023-08-09 165537.png -------------------------------------------------------------------------------- /document/pic/屏幕截图 2023-08-09 165720.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MongooseOrion/FPGA-Image-Recognition/7813e458d1600228886736094816db2f0a49ff39/document/pic/屏幕截图 2023-08-09 165720.png -------------------------------------------------------------------------------- /document/pic/屏幕截图 2023-08-09 170151.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MongooseOrion/FPGA-Image-Recognition/7813e458d1600228886736094816db2f0a49ff39/document/pic/屏幕截图 2023-08-09 170151.png -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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() -------------------------------------------------------------------------------- /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 | --------------------------------------------------------------------------------