以太网实战AD采集上传上位机——FPGA学习笔记27

news/2025/1/21 15:44:39/

一、设计目标

使用FPGA实现AD模块驱动采集模拟电压,通过以太网上传到电脑上位机。

二、框架设计

数据位宽转换模块(ad_10bit_to_16bit):为了方便数据传输,数据位宽转换模块实现了将十位的 AD 数据转换成十六位,并且为了异步 FIFO 传输将高八位和低八位交换然后传输给数据封装模块。
开始传输模块(start_transfer_ctrl):该模块接收上位机发送的命令来判断是否开启传输以及使用那个通道传输。
数据封装模块(img_data_pkt):该模块调用异步 FIFO 将十六位的 AD 数据转换为传输给以太网部分的八位 UDP 数据,并且控制一包数据的大小和以太网 UDP 开始发送信号。


(1)开始传输模块 start_transfer_ctrl

module start_transfer_ctrl(input                 clk                ,   //时钟信号input                 rst_n              ,   //复位信号,低电平有效input                 udp_rec_pkt_done   ,   //UDP单包数据接收完成信号 input                 udp_rec_en         ,   //UDP接收的数据使能信号input        [7 :0]   udp_rec_data       ,   //UDP接收的数据 input        [15:0]   udp_rec_byte_num   ,   //UDP接收到的字节数   output  reg  [1:0]    ctrl               ,                                output  reg           transfer_flag          //图像开始传输标志,1:开始传输 0:停止传输    
);    //parameter define
parameter  START_1 = 8'd1;  //通道一开始命令
parameter  STOP    = 8'd0;  //停止命令
parameter  START_2 = 8'd2;  //通道二开始命令//解析接收到的数据
always @(posedge clk or negedge rst_n) beginif (!rst_n) begintransfer_flag   <=  1'b0;endelse if (udp_rec_pkt_done && udp_rec_byte_num == 1'b1)beginif (udp_rec_data == START_1) begintransfer_flag   <=  1'b1;ctrl            <=  2'b01;endelse if (udp_rec_data == START_2) begintransfer_flag   <=  1'b1;ctrl            <=  2'b10;end else if (udp_rec_data == STOP) begintransfer_flag   <=  1'b0;ctrl            <=  2'b00;end else begintransfer_flag   <=  1'b0;ctrl            <=  2'b00;endend 
endendmodule

(2)开始传输模块  start_transfer_ctrl

module ad_10bit_to_16bit(input                 clk       ,input                 rst_n     ,input       [1:0]     sel       ,//控制命令input       [9:0]     ad_in1    ,//通道一数据input       [9:0]     ad_in2    ,//通道二数据output  reg [15:0]    ad_out     //输出数据
);//wire define 
wire [9:0]s_ad_in1;
wire [9:0]s_ad_in2;//十位扩展为十六位	
always @(posedge clk or negedge rst_n) beginif(!rst_n) beginad_out <= 16'd0;endelse if( sel == 2'b01) beginad_out<={6'd0,ad_in1};//这样补0为了适应上位机endelse if( sel == 2'b10) beginad_out<={6'd0,ad_in2};//endelse beginad_out <= 16'd0;end
endendmodule

(3)数据封装模块    img_data_pkt:

 

(4)UDP顶层修改

主要修改UDP顶层UDP协议接口,对ICMP以及ARP部分进行保留

module eth_top(input                   sys_rst_n           ,   //系统复位信号,低电平有效 input                   clk_200m            ,output                  gmii_rx_clk         ,output                  gmii_tx_clk         ,//PL以太网RGMII接口                     //inputinput                   eth_rxc             ,   //RGMII接收数据时钟input                   eth_rx_ctl          ,   //RGMII输入数据有效信号input       [3:0]       eth_rxd             ,   //RGMII输入数据//outputoutput                  eth_txc             ,   //RGMII发送数据时钟    output                  eth_tx_ctl          ,   //RGMII输出数据有效信号output      [3:0]       eth_txd             ,   //RGMII输出数据       //UDP接口input                   udp_tx_start_en     ,   //UDP发送开始使能信号 input       [7:0]       udp_tx_data         ,   //UDP待发送数据input       [15:0]      udp_tx_byte_num     ,   //UDP发送的有效字节数 单位:byte output                  udp_rec_pkt_done    ,   //UDP单包数据接收完成信号   output                  udp_tx_done         ,   //UDP发送完成信号 output                  udp_tx_req          ,   //UDP读数据请求信号output                  udp_rec_en          ,   //UDP接收的数据使能信号output      [7:0]       udp_rec_data        ,   //UDP接收的数据output      [15:0]      udp_rec_byte_num  	    //UDP接收的有效字节数 单位:byte);//parameter define
parameter  BOARD_MAC = 48'h00_11_22_33_44_55;       //开发板MAC地址     00-11-22-33-44-55
parameter  BOARD_IP  = {8'd192,8'd168,8'd1,8'd10};  //开发板IP地址      192.168.1.10
parameter  DES_MAC   = 48'hff_ff_ff_ff_ff_ff;       //目的MAC地址       ff_ff_ff_ff_ff_ff
parameter  DES_IP    = {8'd192,8'd168,8'd1,8'd102}; //目的IP地址        192.168.1.102     
parameter  IDELAY_VALUE = 15;                       //输入数据IO延时    (如果为n,表示延时n*78ps) //wire define
// wire                    clk_200m   		        ;   //用于IO延时的时钟 // wire                    gmii_rx_clk             ;   //GMII接收时钟
wire                    gmii_rx_dv              ;   //GMII接收数据有效信号
wire          [7:0]     gmii_rxd                ;   //GMII接收数据
// wire                    gmii_tx_clk             ;   //GMII发送时钟
wire                    gmii_tx_en              ;   //GMII发送数据使能信号
wire          [7:0]     gmii_txd                ;   //GMII发送数据     //ARP信号
wire                    arp_gmii_tx_en	        ;   //ARP GMII输出数据有效信号 
wire          [7:0]     arp_gmii_txd  	        ;   //ARP GMII输出数据
wire                    arp_rx_done   	        ;   //ARP接收完成信号
wire                    arp_rx_type   	        ;   //ARP接收类型 0:请求  1:应答
wire          [47:0]    src_mac       	        ;   //接收到目的MAC地址
wire          [31:0]    src_ip        	        ;   //接收到目的IP地址    
wire                    arp_tx_en     	        ;   //ARP发送使能信号
wire                    arp_tx_type   	        ;   //ARP发送类型 0:请求  1:应答
wire          [47:0]    des_mac       	        ;   //发送的目标MAC地址
wire          [31:0]    des_ip        	        ;   //发送的目标IP地址   
wire                    arp_tx_done   	        ;   //ARP发送完成信号//ICMP信号
wire                    icmp_gmii_tx_en	        ;   //ICMP GMII输出数据有效信号 
wire          [7:0]     icmp_gmii_txd  	        ;   //ICMP GMII输出数据
wire                    icmp_rec_pkt_done       ;   //ICMP单包数据接收完成信号
wire                    icmp_rec_en             ;   //ICMP接收的数据使能信号
wire          [ 7:0]    icmp_rec_data           ;   //ICMP接收的数据
wire          [15:0]    icmp_rec_byte_num       ;   //ICMP接收的有效字节数 单位:byte 
wire          [15:0]    icmp_tx_byte_num        ;   //ICMP发送的有效字节数 单位:byte 
wire                    icmp_tx_done   	        ;   //ICMP发送完成信号
wire                    icmp_tx_req             ;   //ICMP读数据请求信号
wire          [ 7:0]    icmp_tx_data            ;   //ICMP待发送数据
wire                    icmp_tx_start_en        ;   //ICMP发送开始使能信号//UDP信号
wire                    udp_gmii_tx_en	        ;   //UDP GMII输出数据有效信号 
wire          [7:0]     udp_gmii_txd  	        ;   //UDP GMII输出数据
// wire                    udp_rec_pkt_done  	        ;   //UDP单包数据接收完成信号
// wire                    udp_rec_en    	        ;   //UDP接收的数据使能信号
// wire          [ 7:0]    udp_rec_data  	        ;   //UDP接收的数据
// wire          [15:0]    udp_rec_byte_num  	        ;   //UDP接收的有效字节数 单位:byte 
// wire          [15:0]    udp_tx_byte_num   	    ;   //UDP发送的有效字节数 单位:byte 
// wire                    udp_tx_done   	        ;   //UDP发送完成信号
// wire                    udp_tx_req    	        ;   //UDP读数据请求信号
// wire          [ 7:0]    udp_tx_data   	        ;   //UDP待发送数据
// wire                    udp_tx_start_en   	    ;   //UDP发送开始使能信号wire          [7:0]	    rec_data			    ;   //FIFO写入数据
wire        		    rec_en			        ;   //FIFO写使能
wire        		    tx_req			        ;   //FIFO读使能
wire          [7:0]	    tx_data	    	        ;   //FIFO读出数据assign icmp_tx_start_en =   icmp_rec_pkt_done   ;   //ICMP 接收端结束标志,作为 ICMP发送端开始标志
assign icmp_tx_byte_num =   icmp_rec_byte_num   ;   //ICMP 接收端数据个数,作为 ICMP发送端发送数据 // assign udp_tx_start_en      =   udp_rec_pkt_done    ;   //UDP 接收端结束标志,作为 UDP发送开始使能信号
// assign udp_tx_byte_num      =   udp_rec_byte_num        ;   //UDP 接收端数据个数,作为 UDP发送端发送数据个数assign des_mac          =   src_mac             ;   //ARP 接收到的 源MAC,作为 ICMP\UDP 目的MAC,实际为电脑端MAC
assign des_ip           =   src_ip              ;   //ARP 接收到的 源IP ,作为 ICMP\UDP 目的IP ,实际为电脑端IP//数据位于异步FIFO之中,如需单独使用一侧功能,可以修改FIFO数据//需要注意写入有效数据数量要与此处相同,一定要注意 数据个数与FIFO读出数据对齐!!!!!!! // //MMCM/PLL 产生200Mhz时钟--> gmii2rgmii
// clk_wiz_0 u_clk_wiz_0
// (
//     .clk_out1           (clk_200m           ),      // output clk_out1
//     .reset              (~sys_rst_n         ),      // input reset
//     .locked             (locked             ),      // output locked
//     .clk_in1            (eth_rxc            )       // PHY侧提供eth_rxc时钟125Mhz
// );  //GMII接口转RGMII接口
gmii_to_rgmii 
#(.IDELAY_VALUE       (IDELAY_VALUE       )
)      
u_gmii_to_rgmii(        .idelay_clk         (clk_200m           ),      //IDELAY时钟//以太网GMII接口    .gmii_rx_clk        (gmii_rx_clk        ),      //GMII接收时钟.gmii_rx_dv         (gmii_rx_dv         ),      //GMII接收数据有效信号.gmii_rxd           (gmii_rxd           ),      //GMII接收数据.gmii_tx_clk        (gmii_tx_clk        ),      //GMII发送时钟.gmii_tx_en         (gmii_tx_en         ),      //GMII发送数据使能信号.gmii_txd           (gmii_txd           ),      //GMII发送数据   //以太网RGMII接口   .rgmii_rxc          (eth_rxc            ),      //RGMII接收时钟.rgmii_rx_ctl       (eth_rx_ctl         ),      //RGMII接收数据控制信号.rgmii_rxd          (eth_rxd            ),      //RGMII接收数据.rgmii_txc          (eth_txc            ),      //RGMII发送时钟    .rgmii_tx_ctl       (eth_tx_ctl         ),      //RGMII发送数据控制信号.rgmii_txd          (eth_txd            )       //RGMII发送数据   
);//ARP通信
arp                                             
#(.BOARD_MAC          (BOARD_MAC          ),      //参数例化.BOARD_IP           (BOARD_IP           ),.DES_MAC            (DES_MAC            ),.DES_IP             (DES_IP             )
)   
u_arp(  .rst_n              (sys_rst_n  	    ),      //复位信号,低电平有效//GMII接口  //input.gmii_rx_clk        (gmii_rx_clk	    ),      //GMII接收数据时钟.gmii_rx_dv         (gmii_rx_dv 	    ),      //GMII输入数据有效信号.gmii_rxd           (gmii_rxd   	    ),      //GMII输入数据.gmii_tx_clk        (gmii_tx_clk	    ),      //GMII发送数据时钟//output.gmii_tx_en         (arp_gmii_tx_en     ),      //GMII输出数据有效信号.gmii_txd           (arp_gmii_txd       ),      //GMII输出数据         //用户接口                           //output.arp_rx_done        (arp_rx_done	    ),      //ARP接收完成信号.arp_rx_type        (arp_rx_type	    ),      //ARP接收类型 0:请求  1:应答.src_mac            (src_mac    	    ),      //接收到目的MAC地址.src_ip             (src_ip     	    ),      //接收到目的IP地址 //input   .arp_tx_en          (arp_tx_en  	    ),      //ARP发送使能信号.arp_tx_type        (arp_tx_type	    ),      //ARP发送类型 0:请求  1:应答.des_mac            (des_mac    	    ),      //发送的目标MAC地址.des_ip             (des_ip     	    ),      //发送的目标IP地址//output.tx_done            (arp_tx_done	    )       //以太网发送完成信号    
);  //ICMP通信  
icmp                                             
#(.BOARD_MAC          (BOARD_MAC          ),      //参数例化.BOARD_IP           (BOARD_IP           ),.DES_MAC            (DES_MAC            ),.DES_IP             (DES_IP             )
)
u_icmp(.rst_n              (sys_rst_n   	    ),      //复位信号,低电平有效//GMII接口//input.gmii_rx_clk        (gmii_rx_clk 	    ),      //GMII接收数据时钟         .gmii_rx_dv         (gmii_rx_dv  	    ),      //GMII输入数据有效信号       .gmii_rxd           (gmii_rxd    	    ),      //GMII输入数据                 .gmii_tx_clk        (gmii_tx_clk 	    ),      //GMII发送数据时钟//output.gmii_tx_en         (icmp_gmii_tx_en	),      //GMII输出数据有效信号       .gmii_txd           (icmp_gmii_txd	    ),      //GMII输出数据//用户接口//output.rec_pkt_done       (icmp_rec_pkt_done  ),      //以太网单包数据接收完成信号  .rec_en             (icmp_rec_en        ), 	    //以太网接收的数据使能信号				  .rec_data           (icmp_rec_data      ),      //以太网接收的数据				 	    .rec_byte_num       (icmp_rec_byte_num  ),      //以太网接收的有效字节数 单位:byte   //input.tx_start_en        (icmp_tx_start_en   ),      //以太网开始发送信号      .tx_data            (icmp_tx_data       ),      //以太网待发送数据					     .tx_byte_num        (icmp_tx_byte_num   ),      //以太网发送的有效字节数 单位:byte.des_mac            (des_mac     	    ),      //发送的目标MAC地址.des_ip             (des_ip      	    ),      //发送的目标IP地址  //output.tx_done            (icmp_tx_done	    ),      //以太网发送完成信号      .tx_req             (icmp_tx_req        )       //读数据请求信号					     
); //UDP通信
udp                                             
#(.BOARD_MAC          (BOARD_MAC          ),      //参数例化.BOARD_IP           (BOARD_IP           ),.DES_MAC            (DES_MAC            ),.DES_IP             (DES_IP             )
)
u_udp(.rst_n              (sys_rst_n          ),      //复位信号,低电平有效//GMII接口//input.gmii_rx_clk        (gmii_rx_clk        ),      //GMII接收数据时钟 .gmii_rx_dv         (gmii_rx_dv         ),      //GMII输入数据有效信号.gmii_rxd           (gmii_rxd           ),      //GMII输入数据.gmii_tx_clk        (gmii_tx_clk        ),      //GMII发送数据时钟   //output .gmii_tx_en         (udp_gmii_tx_en     ),      //GMII输出数据有效信号.gmii_txd           (udp_gmii_txd       ),      //GMII输出数据 //用户接口//outpur.rec_pkt_done       (udp_rec_pkt_done   ),      //以太网单包数据接收完成信号 .rec_en             (udp_rec_en         ),      //以太网接收的数据使能信号.rec_data           (udp_rec_data       ),      //以太网接收的数据      .rec_byte_num       (udp_rec_byte_num   ),      //以太网接收的有效字节数 单位:byte      //input.tx_start_en        (udp_tx_start_en    ),      //以太网开始发送信号      .tx_data            (udp_tx_data        ),      //以太网待发送数据        .tx_byte_num        (udp_tx_byte_num    ),      //以太网发送的有效字节数 单位:byte      .des_mac            (des_mac            ),      //发送的目标MAC地址      .des_ip             (des_ip             ),      //发送的目标IP地址    //output .tx_done            (udp_tx_done        ),      //以太网发送完成信号 .tx_req             (udp_tx_req         )       //读数据请求信号   
); //异步FIFO,实际做同步FIFO使用
async_fifo_2048x8b u_async_fifo_2048x8b (//input.rst                (~sys_rst_n	        ),      //input wire rst.wr_clk             (gmii_rx_clk        ),  	//input wire wr_clk.rd_clk             (gmii_rx_clk        ),  	//input wire rd_clk.din                (rec_data	        ),      //input wire [7 : 0] din.wr_en              (rec_en		        ),    	//input wire wr_en.rd_en              (tx_req		        ),    	//input wire rd_en//output.dout               (tx_data	        ),      //output wire [7 : 0] dout.full               (                   ),      //output wire full.empty              (                   )    	//output wire empty
);// //预留调试ILA
// ila_0 ila_0_fifo (
// 	.clk                (gmii_rx_clk        ),      // input wire clk// 	.probe0             (rec_en             ),      // input wire [0:0]  probe0  
// 	.probe1             (rec_data           ),      // input wire [7:0]  probe1 
// 	.probe2             (tx_req             ),      // input wire [0:0]  probe2 
// 	.probe3             (tx_data            )       // input wire [7:0]  probe3
// );//以太网控制模块
eth_ctrl u_eth_ctrl(//input.clk            	(gmii_rx_clk	    ),      //时钟.rst_n          	(sys_rst_n		    ),      //系统复位信号,低电平有效 //ARP相关端口信号 //input.arp_rx_done    	(arp_rx_done   	    ),      //ARP接收完成信号.arp_rx_type    	(arp_rx_type   	    ),      //ARP接收类型 0:请求  1:应答.arp_tx_done    	(arp_tx_done   	    ),      //ARP发送完成信号.arp_gmii_tx_en 	(arp_gmii_tx_en	    ),      //ARP GMII输出数据有效信号 .arp_gmii_txd   	(arp_gmii_txd  	    ),      //ARP GMII输出数据//output.arp_tx_en      	(arp_tx_en     	    ),      //ARP发送使能信号.arp_tx_type    	(arp_tx_type   	    ),      //ARP发送类型 0:请求  1:应答//ICMP相关端口信号//input.icmp_tx_start_en	(icmp_tx_start_en   ),      //ICMP开始发送信号.icmp_tx_done		(icmp_tx_done	    ),      //ICMP发送完成信号.icmp_gmii_tx_en	(icmp_gmii_tx_en    ),      //ICMP GMII输出数据有效信号  .icmp_gmii_txd		(icmp_gmii_txd	    ),      //ICMP GMII输出数据 //ICMP fifo接口信号//input.icmp_rec_en       	(icmp_rec_en        ),      //ICMP接收的数据使能信号.icmp_rec_data     	(icmp_rec_data      ),      //ICMP接收的数据.icmp_tx_req       	(icmp_tx_req        ),      //ICMP读数据请求信号//output.icmp_tx_data      	(icmp_tx_data       ),      //ICMP待发送数据//UDP相关端口信号//input.udp_tx_start_en	(udp_tx_start_en   	),      //UDP开始发送信号.udp_tx_done    	(udp_tx_done   	    ),      //UDP发送完成信号    .udp_gmii_tx_en 	(udp_gmii_tx_en	    ),      //UDP GMII输出数据有效信号  .udp_gmii_txd   	(udp_gmii_txd  	    ),      //UDP GMII输出数据   //UDP fifo接口信号//input.udp_rec_data		(udp_rec_data       ),      //UDP接收的数据		--->      UDP要发送的数据.udp_rec_en			(udp_rec_en         ),      //UDP接收的数据使能信号     .udp_tx_req			(udp_tx_req         ),      //UDP读数据请求信号   //output .udp_tx_data		(                   ),      //UDP待发送数据		//fifo接口信号//output.rec_data			(rec_data	        ),      //待发送的数据	.rec_en	        	(rec_en	            ),      //读数据请求信号 .tx_req	        	(tx_req	            ),      //接收的数据使能信号//input.tx_data	    	(tx_data	        ),      //接收的数据//GMII发送引脚  //output.gmii_tx_en     	(gmii_tx_en    	    ),      //GMII输出数据有效信号 .gmii_txd       	(gmii_txd      	    )       //GMII输出数据 
);      endmodule

三、代码架构

四、下载测试

1、ping指令&ARP

2、UDP数据上报

正弦波

方波

三角波

多频音波

五、源码获取工程移植,请后台私信


http://www.ppmy.cn/news/1564992.html

相关文章

畅游Diffusion数字人(14):基于3D人体网格的语音驱动手势视频生成 ECCV 2024

畅游Diffusion数字人(0):专栏文章导航 前言:根据语音输入生成与说话内容、情感和节奏相匹配的自然、流畅且逼真的手势视频。该技术在虚拟形象、虚拟现实、动画制作等领域具有重要应用价值。然而这方面的研究非常少,这篇博客解读一篇ECCV 2024的最新论文。 目录 研究背景与挑…

一次完整的tcpdump -XX输出报文详解

报文&#xff1a; 03:32:51.745623 IP (tos 0x0, ttl 64, id 65006, offset 0, flags [DF], proto TCP (6), length 94) 10.229.43.200.6471 > 10.229.43.200.55674: Flags [P.], cksum 0x6daa (incorrect -> 0x2e06), seq 1:43, ack 42, win 3635, options [nop,nop…

分苹果,若a ^ b ^ c = 0意味着:a 和 (b ^ c) 的值相等,或者 b 和 (a ^ c) 的值相等,以及 c 和 (a ^ b) 的值相等。

若a ^ b ^ c faultSum&#xff0c;那么faultSum 0时&#xff0c;即可产生上面的平分方案。说明可以满足二进制平分 #include<bits/stdc.h> using namespace std; int main() { int n; cin>>n; vector<int> weight(n); for(int i0;i<n;i) {…

【网络编程】基础知识

目录 网络发展史 局域网和广域网 局域网&#xff08;LAN&#xff09; 广域网&#xff08;Wan&#xff09; 光猫 路由器 网线 设备通信的要素 IP地址 基本概念 地址划分 特殊地址&#xff08;后续编程使用&#xff09; IP地址转换 字节序 网络模型 网络的体系结…

使用EVE-NG-锐捷实现静态路由

一、项目拓扑 二、项目实现 1、路由器R1配置 进入特权模式 enable 进入全局模式 configure terminal更改名称为R1 hostname R1关闭域名解析。在域名解析开启的情况下&#xff0c;输错的命令会当做域名进行解析&#xff0c;卡住30秒左右&#xff0c;直至解析超时 …

项目实战--网页五子棋(游戏大厅)(3)

我们的游戏大厅界面主要需要包含两个功能&#xff0c;一是显示用户信息&#xff0c;二是匹配游戏按钮 1. 页面实现 hall.html <!DOCTYPE html> <html lang"ch"> <head><meta charset"UTF-8"><meta name"viewport"…

记录点android升级内容

Cleartext HTTP traffic to yun.tjwzkj.com not permitted 在android中不仅要由网络权限<uses-permission android:name"android.permission.INTERNET"/>&#xff0c;而且需要在Application中增加android:usesCleartextTraffic"true" 还可以创建xml…

doris:Kafka 导入数据

Doris 提供以下方式从 Kafka 导入数据&#xff1a; 使用 Routine Load 消费 Kafka 数据 Doris 通过 Routine Load 持续消费 Kafka Topic 中的数据。提交 Routine Load 作业后&#xff0c;Doris 会实时生成导入任务&#xff0c;消费 Kafka 集群中指定 Topic 的消息。Routine L…