61.以太网数据回环实验(4)以太网数据收发器发送模块

2024-09-08 04:20

本文主要是介绍61.以太网数据回环实验(4)以太网数据收发器发送模块,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

(1)状态转移图:

(2)IP数据包格式:

(3)UDP数据包格式:

(4)以太网发送模块代码:

module udp_tx
(input   wire            gmii_txc    ,input   wire            reset_n     ,input   wire            tx_start_en ,       //以太网开始发送信号input   wire    [31:0]  tx_data     ,       //以太网待发送数据,来自fifo模块,因此更新需要同步tx_req信号input   wire    [15:0]  tx_byte_num ,       //以太网发送的有些数据字节个数input   wire    [31:0]  crc_data    ,       //CRC校验数据input   wire    [7:0]   crc_next    ,       //CRC下次校验完成数据output  reg     [7:0]   gmii_txd    ,       //32位转8位后的输出数据output  reg             gmii_tx_en  ,       //GMII传输有效信号output  reg             tx_done     ,       //以太网传输一帧数据完成的标志信号output  reg             tx_req      ,       //读取数据请求信号output  reg             crc_en      ,       //CRC开始校验使能output  reg             crc_clr             //CRC数据复位信号
);/*-----------参数定义------------*/
//开发板MAC地址(48位)
parameter BOARO_MAC     =   48'hff_ff_ff_ff_ff_ff   ;
//开发板IP地址(32位)
parameter BOARO_IP      =   {8'd0,8'd0,8'd0,8'd0}   ;
//目的MAC地址(48位)
parameter DES_MAC       =   48'hff_ff_ff_ff_ff_ff   ;
//目的IP地址(32位)
parameter DES_IP        =   {8'd0,8'd0,8'd0,8'd0}   ;
//状态机状态定义 独热吗编码
localparam ST_IDLE          =   7'b000_0001     ;           //空闲状态,等待开始发送信号
localparam ST_CHECK_SUM     =   7'b000_0010     ;           //IP首部校验和
localparam ST_PREAMBLE      =   7'b000_0100     ;           //发送前导码+帧起始界定符
localparam ST_ETH_HEAD      =   7'b000_1000     ;           //发送以太网帧头
localparam ST_IP_UDP_HEAD   =   7'b001_0000     ;           //发送IP首部+UDP首部
localparam ST_TX_DATA       =   7'b010_0000     ;           //发送数据
localparam ST_CRC           =   7'b100_0000     ;           //发送CRC校验值localparam ETH_TYPE         =   16'h0800        ;           //以太网协议类型  IP协议//寄存器定义
reg     [7:0]   preamble[7:0]       ;   //7个字节的前导码和一个字节的帧起始界定符
reg     [7:0]   eth_head[13:0]      ;   //14个字节的以太网帧头数据
reg     [31:0]  ip_udp_head[6:0]    ;   //IP首部(5个字节) + UDP首部(2个字节)reg             start_en_d0         ;   //以太网开始发送信号打一拍后信号
reg             start_en_d1         ;   //以太网开始发送信号打两拍后信号    
reg     [31:0]  check_sum           ;   //IP首部校验和
reg     [15:0]  data_len            ;   //有效数据字节长度
reg     [15:0]  ip_udp_data_len     ;   //ip首部加上udp首部加上有效数据字节的总长数
reg     [15:0]  udp_len             ;   //UDP长度reg     [6:0]   cur_state           ;       //当前状态
reg     [6:0]   next_state          ;       //下一个状态
reg             sw_en               ;       //状态跳转脉冲信号
reg     [4:0]   cnt                 ;       //数据计数器
reg     [1:0]   cnt_tx_bit_sel      ;       //最小时间单位计数器
reg     [15:0]  cnt_data            ;       //有效数据发送个数计数器
reg     [4:0]   cnt_add             ;       //以太网实际多发的字节个数计数器
reg             tx_done_t           ;       //传输完成信号(需要再延迟一拍处理)   
reg             posed_start_en_reg  ;       //上升沿开始有效脉冲信号wire            posed_start_en      ;       //开始信号上升沿设计
wire    [15:0]  real_tx_date_num    ;       //实际发送字节个数/*------------开始有效信号设计------------*/
always@(posedge gmii_txc or negedge reset_n)beginif(!reset_n)beginstart_en_d0  <= 1'd0;start_en_d1  <= 1'd0;endelse beginstart_en_d0 <= tx_start_en;start_en_d1 <= start_en_d0;end
endassign posed_start_en = ((start_en_d0) && (!start_en_d1));always@(posedge gmii_txc or negedge reset_n)if(!reset_n)posed_start_en_reg <= 1'd0;else posed_start_en_reg <= posed_start_en   ;/*------------以太网UDP最少数据字节设计------------*/
//以太网数据最少46字节,IP首部20个字节,UDP首部8个字节,因此数据至少46-20-8 = 18 字节
assign real_tx_date_num = (data_len >= 16'd18) ? data_len : 16'd18;/*------------data_len 、 ip_udp_data_len 、 udp_len寄存器设计------------*/
always@(posedge gmii_txc or negedge reset_n)beginif(!reset_n)begindata_len         <= 16'd0;ip_udp_data_len  <= 16'd0;udp_len          <= 16'd0;endelse beginif(posed_start_en && cur_state == ST_IDLE)begindata_len         <= tx_byte_num ;ip_udp_data_len  <= tx_byte_num + 16'd20 + 16'd8    ;udp_len          <= tx_byte_num + 16'd8             ;  endend
end        /*--------------三段式状态机编写主程序--------*/
//第一段:时序逻辑描述状态转移
always@(posedge gmii_txc or negedge reset_n)beginif(!reset_n)cur_state <=  ST_IDLE   ;else cur_state <= next_state ;
end//第二段:组合逻辑判断状态机转移条件
always@(*)beginnext_state = ST_IDLE  ;case(cur_state)ST_IDLE :if(sw_en)next_state = ST_CHECK_SUM;else next_state = ST_IDLE;ST_CHECK_SUM :if(sw_en)next_state = ST_PREAMBLE;else next_state = ST_CHECK_SUM;ST_PREAMBLE :if(sw_en)next_state = ST_ETH_HEAD;else next_state = ST_PREAMBLE;ST_ETH_HEAD  :if(sw_en)next_state = ST_IP_UDP_HEAD;else next_state = ST_ETH_HEAD;ST_IP_UDP_HEAD :if(sw_en)next_state = ST_TX_DATA;else next_state = ST_IP_UDP_HEAD;ST_TX_DATA :if(sw_en)next_state = ST_CRC;else next_state = ST_TX_DATA;ST_CRC :if(sw_en)next_state = ST_IDLE;else next_state = ST_CRC;default:next_state = ST_IDLE  ;endcase           
end//第三段:时序逻辑描述寄存器变量和状态输出 
always@(posedge gmii_txc or negedge reset_n)beginif(!reset_n)beginsw_en <= 1'd0;cnt <= 5'd0;check_sum <= 32'd0;ip_udp_head[1][31:16] <= 16'd0;   //把IP首部中的标识部分初始化为16'd0;cnt_tx_bit_sel <= 2'd0;crc_en <= 1'd0;gmii_tx_en <= 1'd0;gmii_txd <= 8'd0;tx_req <= 1'd0;tx_done_t <= 1'd0;cnt_data <= 16'd0;cnt_add <= 5'd0;//前导码和帧起始界定符初始化preamble[0] <= 8'h55;preamble[1] <= 8'h55;preamble[2] <= 8'h55;preamble[3] <= 8'h55;preamble[4] <= 8'h55;preamble[5] <= 8'h55;preamble[6] <= 8'h55;preamble[7] <= 8'hd5;//以太网帧头字节初始化//目的MAC地址eth_head[0]  <= DES_MAC[47:40];eth_head[1]  <= DES_MAC[39:32];eth_head[2]  <= DES_MAC[31:24];eth_head[3]  <= DES_MAC[23:16];eth_head[4]  <= DES_MAC[15:8];eth_head[5]  <= DES_MAC[7:0];//源MAC地址eth_head[6]  <= BOARO_MAC[47:40];eth_head[7]  <= BOARO_MAC[39:32];eth_head[8]  <= BOARO_MAC[31:24];eth_head[9]  <= BOARO_MAC[23:16];eth_head[10] <= BOARO_MAC[15:8];eth_head[11] <= BOARO_MAC[7:0];//协议类型eth_head[12] <= ETH_TYPE[15:8];eth_head[13] <= ETH_TYPE[7:0];  endelse beginsw_en <= 1'd0;tx_req <= 1'd0;crc_en <= 1'd0;gmii_tx_en <= 1'd0;tx_done_t <= 1'd0;case(next_state)ST_IDLE     :beginif(posed_start_en_reg)beginsw_en <= 1'd1;ip_udp_head[0] <= {8'h45,8'h00,ip_udp_data_len}; //版本:4 + 首部长度:20/4 = 5 + ip首部加上udp首部加上有效数据字节的总长数ip_udp_head[1][31:16] <= ip_udp_head[1][31:16] + 1'd1;//16位的标识,每发一个数据累加1ip_udp_head[1][15:0]  <= 16'b010_00000_0000_0000;   //前三位表示标记,010表示不分片ip_udp_head[2] <= {8'h40,8'h11,16'h0};      //生存时间:40 + 协议:11——UDP协议  01——TCP协议 + 首部校验和(先设置为0)ip_udp_head[3] <= BOARO_IP;                 //源IP地址ip_udp_head[4] <= DES_IP;                   //目的IP地址ip_udp_head[5] <= {16'd1234,16'd1234};      //源端口号(1234) + 目的端口号(1234)ip_udp_head[6] <= {udp_len,16'h0000} ;    //UDP长度 + UDP校验和endendST_CHECK_SUM  :begin            //IP首部校验和计算cnt <= cnt + 5'd1;if(cnt == 5'd0)check_sum <= ip_udp_head[0][31:16] + ip_udp_head[0][15:0]+ ip_udp_head[1][31:16] + ip_udp_head[1][15:0]+ ip_udp_head[2][31:16] + ip_udp_head[2][15:0]+ ip_udp_head[3][31:16] + ip_udp_head[3][15:0]+ ip_udp_head[4][31:16] + ip_udp_head[4][15:0];else if(cnt == 5'd1)    //可能出现进位,因此累加一次   check_sum <= check_sum[31:16] + check_sum[15:0];else if(cnt == 5'd2)     //可能再次出现进位,再累加一次check_sum <= check_sum[31:16] + check_sum[15:0];else if(cnt == 5'd3)beginsw_en <= 1'd1;cnt <= 5'd0;ip_udp_head[2][15:0] <= ~check_sum[15:0];    //ip_udp_head[2][15:0] 是原先设置成0的首部校验和部位end       endST_PREAMBLE   :begingmii_tx_en <= 1'd1;gmii_txd <= preamble[cnt];if(cnt == 5'd7)beginsw_en <= 1'd1;cnt <= 5'd0;    endelse cnt <= cnt + 5'd1;endST_ETH_HEAD :begingmii_tx_en <= 1'd1;crc_en <= 1'd1;gmii_txd <= eth_head[cnt];if(cnt == 5'd13)beginsw_en <= 1'd1;cnt <= 5'd0;    endelse cnt <= cnt + 5'd1;endST_IP_UDP_HEAD:begin            //发送IP首部 + UDP首部gmii_tx_en <= 1'd1;crc_en <= 1'd1;cnt_tx_bit_sel <= cnt_tx_bit_sel + 2'd1;if(cnt_tx_bit_sel == 2'd0)gmii_txd <= ip_udp_head[cnt][31:24];else if(cnt_tx_bit_sel == 2'd1)gmii_txd <= ip_udp_head[cnt][23:16];else if(cnt_tx_bit_sel == 2'd2)begingmii_txd <= ip_udp_head[cnt][15:8];if(cnt == 5'd6)//提前发送读取请求,等待有效数据发送至该模块tx_req <= 1'd1;endelse if(cnt_tx_bit_sel == 2'd3)begingmii_txd <= ip_udp_head[cnt][7:0];if(cnt == 5'd6)begincnt <= 5'd0;sw_en <= 1'd1;endelse cnt <= cnt + 5'd1;endendST_TX_DATA:begincrc_en <= 1'd1;gmii_tx_en <= 1'd1;cnt_tx_bit_sel <= cnt_tx_bit_sel + 2'd1;//cnt_data 、cnt_add设计if(cnt_data < data_len - 16'd1)cnt_data <= cnt_data + 16'd1;else if(cnt_data == data_len - 16'd1)begin//如果发送的有效数据少于18个字节,则在后面填补充位//补充的值为最后一次发送的有效数据gmii_txd <= 8'd0;/*在Verilog中,赋值语句是按照代码的顺序执行的,后面的赋值语句会覆盖前面的赋值因此gmii_txd <= 8'd0这条语句,虽然将gmii_txd赋值为8'd0,但根据cnt_tx_bit_sel的值,后面的赋值语句会根据条件逻辑来覆盖这个初始的赋值*/if(cnt_data + cnt_add < real_tx_date_num - 16'd1)cnt_add <= cnt_add + 5'd1;else beginsw_en <= 1'd1;cnt_data <= 16'd0;cnt_add <= 5'd0;cnt_tx_bit_sel <= 2'd0;endend//gmii_txd设计if(cnt_tx_bit_sel == 2'd0)gmii_txd   <= tx_data[31:24];else if(cnt_tx_bit_sel == 2'd1)gmii_txd   <= tx_data[23:16];else if(cnt_tx_bit_sel == 2'd2)begingmii_txd   <= tx_data[15:8];if(cnt_data != data_len - 16'd1)tx_req <= 1'd1;endelse if(cnt_tx_bit_sel == 2'd3)gmii_txd   <= tx_data[7:0];        endST_CRC  :begin      //发送CRC校验值gmii_tx_en <= 1'd1;cnt_tx_bit_sel <= cnt_tx_bit_sel + 2'd1;if(cnt_tx_bit_sel == 2'd0)gmii_txd <= {~crc_next[0],~crc_next[1],~crc_next[2],~crc_next[3],~crc_next[4],~crc_next[5],~crc_next[6],~crc_next[7]};else if(cnt_tx_bit_sel == 2'd1)gmii_txd <= {~crc_data[16],~crc_data[17],~crc_data[18],~crc_data[19],~crc_data[20],~crc_data[21],~crc_data[22],~crc_data[23]};                 else if(cnt_tx_bit_sel == 2'd2)gmii_txd <= {~crc_data[8],~crc_data[9],~crc_data[10],~crc_data[11],~crc_data[12],~crc_data[13],~crc_data[14],~crc_data[15]};else if(cnt_tx_bit_sel == 2'd3)begingmii_txd <= {~crc_data[0],~crc_data[1],~crc_data[2],~crc_data[3],~crc_data[4],~crc_data[5],~crc_data[6],~crc_data[7]};tx_done_t <= 1'd1;sw_en <= 1'd1;endenddefault:    ;endcaseend
end/*--------------发送完成信号以及crc值复位信号--------*/always@(posedge gmii_txc or negedge reset_n)beginif(!reset_n)begintx_done <= 1'd0;crc_clr <= 1'd0;endelse begintx_done <= tx_done_t;crc_clr <= tx_done_t;end
endendmodule

(5)以太网CRC校验模块代码:

module crc32_d8
(input                 gmii_txc      ,  //时钟信号input                 reset_n       ,  //复位信号,低电平有效input         [7:0]   data          ,  //输入待校验8位数据input                 crc_en        ,  //crc使能,开始校验标志input                 crc_clr       ,  //crc数据复位信号            output   reg  [31:0]  crc_data      ,  //CRC校验数据output        [31:0]  crc_next         //CRC下次校验完成数据
);//*****************************************************
//**                    main code
//*****************************************************//输入待校验8位数据,需要先将高低位互换
wire    [7:0]  data_t;assign data_t = {data[0],data[1],data[2],data[3],data[4],data[5],data[6],data[7]};//CRC32的生成多项式为:G(x)= x^32 + x^26 + x^23 + x^22 + x^16 + x^12 + x^11 + x^10 + x^8 + x^7 + x^5 + x^4 + x^2 + x^1 + 1assign crc_next[0] = crc_data[24] ^ crc_data[30] ^ data_t[0] ^ data_t[6];
assign crc_next[1] = crc_data[24] ^ crc_data[25] ^ crc_data[30] ^ crc_data[31] ^ data_t[0] ^ data_t[1] ^ data_t[6] ^ data_t[7];
assign crc_next[2] = crc_data[24] ^ crc_data[25] ^ crc_data[26] ^ crc_data[30] ^ crc_data[31] ^ data_t[0] ^ data_t[1] ^ data_t[2] ^ data_t[6] ^ data_t[7];
assign crc_next[3] = crc_data[25] ^ crc_data[26] ^ crc_data[27] ^ crc_data[31] ^ data_t[1] ^ data_t[2] ^ data_t[3] ^ data_t[7];
assign crc_next[4] = crc_data[24] ^ crc_data[26] ^ crc_data[27] ^ crc_data[28] ^ crc_data[30] ^ data_t[0] ^ data_t[2] ^ data_t[3] ^ data_t[4] ^ data_t[6];
assign crc_next[5] = crc_data[24] ^ crc_data[25] ^ crc_data[27] ^ crc_data[28] ^ crc_data[29] ^ crc_data[30] ^ crc_data[31] ^ data_t[0] ^ data_t[1] ^ data_t[3] ^ data_t[4] ^ data_t[5] ^ data_t[6] ^ data_t[7];
assign crc_next[6] = crc_data[25] ^ crc_data[26] ^ crc_data[28] ^ crc_data[29] ^ crc_data[30] ^ crc_data[31] ^ data_t[1] ^ data_t[2] ^ data_t[4] ^ data_t[5] ^ data_t[6] ^ data_t[7];
assign crc_next[7] = crc_data[24] ^ crc_data[26] ^ crc_data[27] ^ crc_data[29] ^ crc_data[31] ^ data_t[0] ^ data_t[2] ^ data_t[3] ^ data_t[5] ^ data_t[7];
assign crc_next[8] = crc_data[0] ^ crc_data[24] ^ crc_data[25] ^ crc_data[27] ^ crc_data[28] ^ data_t[0] ^ data_t[1] ^ data_t[3] ^ data_t[4];
assign crc_next[9] = crc_data[1] ^ crc_data[25] ^ crc_data[26] ^ crc_data[28] ^ crc_data[29] ^ data_t[1] ^ data_t[2] ^ data_t[4] ^ data_t[5];
assign crc_next[10] = crc_data[2] ^ crc_data[24] ^ crc_data[26] ^ crc_data[27] ^ crc_data[29] ^ data_t[0] ^ data_t[2] ^ data_t[3] ^ data_t[5];
assign crc_next[11] = crc_data[3] ^ crc_data[24] ^ crc_data[25] ^ crc_data[27] ^ crc_data[28] ^ data_t[0] ^ data_t[1] ^ data_t[3] ^ data_t[4];
assign crc_next[12] = crc_data[4] ^ crc_data[24] ^ crc_data[25] ^ crc_data[26] ^ crc_data[28] ^ crc_data[29] ^ crc_data[30] ^ data_t[0] ^ data_t[1] ^ data_t[2] ^ data_t[4] ^ data_t[5] ^ data_t[6];
assign crc_next[13] = crc_data[5] ^ crc_data[25] ^ crc_data[26] ^ crc_data[27] ^ crc_data[29] ^ crc_data[30] ^ crc_data[31] ^ data_t[1] ^ data_t[2] ^ data_t[3] ^ data_t[5] ^ data_t[6] ^ data_t[7];
assign crc_next[14] = crc_data[6] ^ crc_data[26] ^ crc_data[27] ^ crc_data[28] ^ crc_data[30] ^ crc_data[31] ^ data_t[2] ^ data_t[3] ^ data_t[4]^ data_t[6] ^ data_t[7];
assign crc_next[15] =  crc_data[7] ^ crc_data[27] ^ crc_data[28] ^ crc_data[29]^ crc_data[31] ^ data_t[3] ^ data_t[4] ^ data_t[5] ^ data_t[7];
assign crc_next[16] = crc_data[8] ^ crc_data[24] ^ crc_data[28] ^ crc_data[29] ^ data_t[0] ^ data_t[4] ^ data_t[5];
assign crc_next[17] = crc_data[9] ^ crc_data[25] ^ crc_data[29] ^ crc_data[30] ^ data_t[1] ^ data_t[5] ^ data_t[6];
assign crc_next[18] = crc_data[10] ^ crc_data[26] ^ crc_data[30] ^ crc_data[31] ^ data_t[2] ^ data_t[6] ^ data_t[7];
assign crc_next[19] = crc_data[11] ^ crc_data[27] ^ crc_data[31] ^ data_t[3] ^ data_t[7];
assign crc_next[20] = crc_data[12] ^ crc_data[28] ^ data_t[4];
assign crc_next[21] = crc_data[13] ^ crc_data[29] ^ data_t[5];
assign crc_next[22] = crc_data[14] ^ crc_data[24] ^ data_t[0];
assign crc_next[23] = crc_data[15] ^ crc_data[24] ^ crc_data[25] ^ crc_data[30] ^ data_t[0] ^ data_t[1] ^ data_t[6];
assign crc_next[24] = crc_data[16] ^ crc_data[25] ^ crc_data[26] ^ crc_data[31] ^ data_t[1] ^ data_t[2] ^ data_t[7];
assign crc_next[25] = crc_data[17] ^ crc_data[26] ^ crc_data[27] ^ data_t[2] ^ data_t[3];
assign crc_next[26] = crc_data[18] ^ crc_data[24] ^ crc_data[27] ^ crc_data[28] ^ crc_data[30] ^ data_t[0] ^ data_t[3] ^ data_t[4] ^ data_t[6];
assign crc_next[27] = crc_data[19] ^ crc_data[25] ^ crc_data[28] ^ crc_data[29] ^ crc_data[31] ^ data_t[1] ^ data_t[4] ^ data_t[5] ^ data_t[7];
assign crc_next[28] = crc_data[20] ^ crc_data[26] ^ crc_data[29] ^ crc_data[30] ^ data_t[2] ^ data_t[5] ^ data_t[6];
assign crc_next[29] = crc_data[21] ^ crc_data[27] ^ crc_data[30] ^ crc_data[31] ^ data_t[3] ^ data_t[6] ^ data_t[7];
assign crc_next[30] = crc_data[22] ^ crc_data[28] ^ crc_data[31] ^ data_t[4] ^ data_t[7];
assign crc_next[31] = crc_data[23] ^ crc_data[29] ^ data_t[5];always @(posedge gmii_txc or negedge reset_n) beginif(!reset_n)crc_data <= 32'hff_ff_ff_ff;else if(crc_clr)                             //CRC校验值复位crc_data <= 32'hff_ff_ff_ff;else if(crc_en)crc_data <= crc_next;
endendmodule

(6)仿真代码:

`timescale 1ns / 1psmodule tb_udp_tx;reg             gmii_txc        ;
reg             reset_n         ;
reg             tx_start_en     ;
reg     [31:0]  tx_data         ;
reg     [31:0]  data_mem[2:0]   ;
reg     [15:0]  data_cnt        ;wire    [31:0]  crc_next        ; 
wire    [31:0]  crc_data        ; 
wire    [7:0]   gmii_txd        ;  
wire            gmii_tx_en      ;
wire            tx_done         ;   
wire            tx_req          ;    
wire            crc_en          ;    
wire            crc_clr         ;   initial gmii_txc = 1'd1;
always#10 gmii_txc = ~gmii_txc;initial beginreset_n <= 1'd0;tx_start_en <= 1'd0;#200;reset_n <= 1'd1;#100;tx_start_en <= 1'd1;#40;tx_start_en <= 1'd0;#4000;$stop;
endalways@(posedge gmii_txc or negedge reset_n)if(!reset_n)begindata_mem[0] <= 32'h00_00_00_00;data_mem[1] <= 32'h00_00_00_00;data_mem[2] <= 32'h00_00_00_00;endelse begindata_mem[0] <= 32'h00_11_22_33;    data_mem[1] <= 32'h44_55_66_77;data_mem[2] <= 32'h88_99_aa_bb;endalways@(posedge gmii_txc or negedge reset_n)if(!reset_n)data_cnt <= 16'd0;else if(tx_req)data_cnt <= data_cnt + 16'd1;else data_cnt <= data_cnt ;always@(posedge gmii_txc or negedge reset_n)if(!reset_n)   tx_data <= 32'd0;else if(tx_req)tx_data <= data_mem[data_cnt];else tx_data <= tx_data;defparam udp_tx_inst.BOARO_MAC = 48'h12_34_56_78_9a_bc;
defparam udp_tx_inst.BOARO_IP  = 32'ha9_fe_01_17;
defparam udp_tx_inst.DES_MAC   = 48'hff_ff_ff_ff_ff_ff;
defparam udp_tx_inst.DES_IP    = 32'ha9_fe_00_45;udp_tx  udp_tx_inst
(.gmii_txc    (gmii_txc          ),.reset_n     (reset_n           ),.tx_start_en (tx_start_en       ),       //以太网开始发送信号.tx_data     (tx_data           ),       //以太网待发送数据,来自fifo模块,因此更新需要同步tx_req信号.tx_byte_num (16'd10            ),       //以太网发送的有些数据字节个数.crc_data    (crc_data          ),       //CRC校验数据.crc_next    (crc_next[31:24]   ),       //CRC下次校验完成数据.gmii_txd    (gmii_txd          ),       //32位转8位后的输出数据.gmii_tx_en  (gmii_tx_en        ),       //GMII传输有效信号.tx_done     (tx_done           ),       //以太网传输一帧数据完成的标志信号.tx_req      (tx_req            ),       //读取数据请求信号.crc_en      (crc_en            ),       //CRC开始校验使能.crc_clr     (crc_clr           )        //CRC数据复位信号
);crc32_d8 crc32_d8_inst
(.gmii_txc      (gmii_txc        ),  //时钟信号.reset_n       (reset_n         ),  //复位信号,低电平有效.data          (gmii_txd        ),  //输入待校验8位数据.crc_en        (crc_en          ),  //crc使能,开始校验标志.crc_clr       (crc_clr         ),  //crc数据复位信号            .crc_data      (crc_data        ),  //CRC校验数据.crc_next      (crc_next        )   //CRC下次校验完成数据
);endmodule

(7)仿真波形:

这篇关于61.以太网数据回环实验(4)以太网数据收发器发送模块的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1147104

相关文章

大模型研发全揭秘:客服工单数据标注的完整攻略

在人工智能(AI)领域,数据标注是模型训练过程中至关重要的一步。无论你是新手还是有经验的从业者,掌握数据标注的技术细节和常见问题的解决方案都能为你的AI项目增添不少价值。在电信运营商的客服系统中,工单数据是客户问题和解决方案的重要记录。通过对这些工单数据进行有效标注,不仅能够帮助提升客服自动化系统的智能化水平,还能优化客户服务流程,提高客户满意度。本文将详细介绍如何在电信运营商客服工单的背景下进行

基于MySQL Binlog的Elasticsearch数据同步实践

一、为什么要做 随着马蜂窝的逐渐发展,我们的业务数据越来越多,单纯使用 MySQL 已经不能满足我们的数据查询需求,例如对于商品、订单等数据的多维度检索。 使用 Elasticsearch 存储业务数据可以很好的解决我们业务中的搜索需求。而数据进行异构存储后,随之而来的就是数据同步的问题。 二、现有方法及问题 对于数据同步,我们目前的解决方案是建立数据中间表。把需要检索的业务数据,统一放到一张M

关于数据埋点,你需要了解这些基本知识

产品汪每天都在和数据打交道,你知道数据来自哪里吗? 移动app端内的用户行为数据大多来自埋点,了解一些埋点知识,能和数据分析师、技术侃大山,参与到前期的数据采集,更重要是让最终的埋点数据能为我所用,否则可怜巴巴等上几个月是常有的事。   埋点类型 根据埋点方式,可以区分为: 手动埋点半自动埋点全自动埋点 秉承“任何事物都有两面性”的道理:自动程度高的,能解决通用统计,便于统一化管理,但个性化定

python: 多模块(.py)中全局变量的导入

文章目录 global关键字可变类型和不可变类型数据的内存地址单模块(单个py文件)的全局变量示例总结 多模块(多个py文件)的全局变量from x import x导入全局变量示例 import x导入全局变量示例 总结 global关键字 global 的作用范围是模块(.py)级别: 当你在一个模块(文件)中使用 global 声明变量时,这个变量只在该模块的全局命名空

使用SecondaryNameNode恢复NameNode的数据

1)需求: NameNode进程挂了并且存储的数据也丢失了,如何恢复NameNode 此种方式恢复的数据可能存在小部分数据的丢失。 2)故障模拟 (1)kill -9 NameNode进程 [lytfly@hadoop102 current]$ kill -9 19886 (2)删除NameNode存储的数据(/opt/module/hadoop-3.1.4/data/tmp/dfs/na

异构存储(冷热数据分离)

异构存储主要解决不同的数据,存储在不同类型的硬盘中,达到最佳性能的问题。 异构存储Shell操作 (1)查看当前有哪些存储策略可以用 [lytfly@hadoop102 hadoop-3.1.4]$ hdfs storagepolicies -listPolicies (2)为指定路径(数据存储目录)设置指定的存储策略 hdfs storagepolicies -setStoragePo

Hadoop集群数据均衡之磁盘间数据均衡

生产环境,由于硬盘空间不足,往往需要增加一块硬盘。刚加载的硬盘没有数据时,可以执行磁盘数据均衡命令。(Hadoop3.x新特性) plan后面带的节点的名字必须是已经存在的,并且是需要均衡的节点。 如果节点不存在,会报如下错误: 如果节点只有一个硬盘的话,不会创建均衡计划: (1)生成均衡计划 hdfs diskbalancer -plan hadoop102 (2)执行均衡计划 hd

深入探索协同过滤:从原理到推荐模块案例

文章目录 前言一、协同过滤1. 基于用户的协同过滤(UserCF)2. 基于物品的协同过滤(ItemCF)3. 相似度计算方法 二、相似度计算方法1. 欧氏距离2. 皮尔逊相关系数3. 杰卡德相似系数4. 余弦相似度 三、推荐模块案例1.基于文章的协同过滤推荐功能2.基于用户的协同过滤推荐功能 前言     在信息过载的时代,推荐系统成为连接用户与内容的桥梁。本文聚焦于

【Prometheus】PromQL向量匹配实现不同标签的向量数据进行运算

✨✨ 欢迎大家来到景天科技苑✨✨ 🎈🎈 养成好习惯,先赞后看哦~🎈🎈 🏆 作者简介:景天科技苑 🏆《头衔》:大厂架构师,华为云开发者社区专家博主,阿里云开发者社区专家博主,CSDN全栈领域优质创作者,掘金优秀博主,51CTO博客专家等。 🏆《博客》:Python全栈,前后端开发,小程序开发,人工智能,js逆向,App逆向,网络系统安全,数据分析,Django,fastapi

烟火目标检测数据集 7800张 烟火检测 带标注 voc yolo

一个包含7800张带标注图像的数据集,专门用于烟火目标检测,是一个非常有价值的资源,尤其对于那些致力于公共安全、事件管理和烟花表演监控等领域的人士而言。下面是对此数据集的一个详细介绍: 数据集名称:烟火目标检测数据集 数据集规模: 图片数量:7800张类别:主要包含烟火类目标,可能还包括其他相关类别,如烟火发射装置、背景等。格式:图像文件通常为JPEG或PNG格式;标注文件可能为X