赞
踩
物理层:网线+网卡(PHY芯片)
数据链路层:Mac层(数据有效传输)
如图所示:FPGA中的Mac层中的MII接口负责控制PHY芯片,PHY芯片通过网线与PC端进行以太网数据传输。
FPGA中Mac与PHY通信MII接口
MII接口4位传输,发送数据先发低位,再发高位。
发送ARP协议目的:知道IP地址后,得到MAC(主机硬件地址)
MAC层模块原理设计图:
使用MAC层发送ARP命令原理如图所示:
根据图上的ARP通信原理,设计时序图如下。
module mac_mii_send( input [47:0] mac_source , //Mac_source input [47:0] mac_goal , //other_Mac input rst_n , input mac_send_en , //pulse width > 40ns input [15:0] data_type , //agreement type input [10:0] data_length , //main data field length input [31:0] crc_result , //Frame check sequence // mii Interface input mii_tx_clk , //mii interface clk output reg mii_tx_en , //mii interface enable output reg [3:0] mii_txd , //mii interface data output mii_tx_error , //error signal high level effective // fifo Interface input [3:0] mac_send_data , //data read from fifo output fifo_rd_clk , //read fifo clock output data_req , //read request output reg send_done //pulse signal = 40ns ); reg [5:0] cnt ; wire en_tx_data ; reg [10:0] data_cnt ; reg en ; always @(posedge mii_tx_clk or negedge rst_n) if(!rst_n) en <= 1'b0; else if(mac_send_en) en <= 1'b1; else if(cnt == 'h35) //'d53 en <= 1'b0; always @(posedge mii_tx_clk or negedge rst_n) if(!rst_n) cnt <= 1'b0; else if(en) begin if(!en_tx_data) begin if(cnt <= 6'h36) //'d54 cnt <= cnt + 1'b1; else cnt <= 1'b0; end else cnt <= cnt ; end else cnt <= 1'b0; assign en_tx_data = (cnt == 'h2D)&&(data_cnt < data_length - 1'b1) ; //'d45 assign data_req = en_tx_data; //fifo request signal always @(posedge mii_tx_clk or negedge rst_n) if(!rst_n) data_cnt <= 1'b0; else if(en_tx_data) data_cnt <= data_cnt + 1'b1; else if(data_cnt == data_length - 1'b1) data_cnt <= 1'b0; // mian Sequencer always @(posedge mii_tx_clk or negedge rst_n) if(!rst_n) begin mii_txd <= 1'b0; send_done <= 1'b0; end else begin case(cnt) 6'h0: begin mii_txd <= 1'b0; send_done <= 1'b0; end 6'h1,6'h2,6'h3,6'h4,6'h5,6'h6,6'h7,6'h8,6'h9,6'ha,6'hb,6'hc,6'hd,6'he,6'hf: mii_txd <= 4'h5; //前导码 6'h10: mii_txd <= 4'hD; //帧开始符 6'h11: mii_txd <= mac_goal[43:40] ; //目的MAC地址 6'h12: mii_txd <= mac_goal[47:44] ; 6'h13: mii_txd <= mac_goal[35:32] ; 6'h14: mii_txd <= mac_goal[39:36] ; 6'h15: mii_txd <= mac_goal[27:24] ; 6'h16: mii_txd <= mac_goal[31:28] ; 6'h17: mii_txd <= mac_goal[19:16] ; 6'h18: mii_txd <= mac_goal[23:20] ; 6'h19: mii_txd <= mac_goal[11:8] ; 6'h1a: mii_txd <= mac_goal[15:12] ; 6'h1b: mii_txd <= mac_goal[3:0] ; 6'h1c: mii_txd <= mac_goal[7:4] ; 6'h1d: mii_txd <= mac_source [43:40] ; 6'h1e: mii_txd <= mac_source [47:44] ; //源MAC地址 6'h1f: mii_txd <= mac_source [35:32] ; 6'h20: mii_txd <= mac_source [39:36] ; 6'h21: mii_txd <= mac_source [27:24] ; 6'h22: mii_txd <= mac_source [31:28] ; 6'h23: mii_txd <= mac_source [19:16] ; 6'h24: mii_txd <= mac_source [23:20] ; 6'h25: mii_txd <= mac_source [11:8] ; 6'h26: mii_txd <= mac_source [15:12] ; 6'h27: mii_txd <= mac_source [3:0] ; 6'h28: mii_txd <= mac_source [7:4] ; 6'h29: mii_txd <= data_type[11:8] ; //长度/类型 6'h2a: mii_txd <= data_type[15:12] ; 6'h2b: mii_txd <= data_type[3:0] ; 6'h2c: mii_txd <= data_type[7:4] ; 6'h2d: //'d45 mii_txd <= mac_send_data ; 6'h2e: //'d46 mii_txd <= crc_result [27:24] ; 6'h2f: mii_txd <= crc_result [31:28] ; 6'h30: mii_txd <= crc_result [19:16] ; 6'h31: mii_txd <= crc_result [23:20] ; 6'h32: mii_txd <= crc_result [11:8] ; 6'h33: mii_txd <= crc_result [15:12] ; 6'h34: mii_txd <= crc_result [3:0] ; 6'h35: mii_txd <= crc_result [7:4] ; 6'h36: //'d54 begin send_done <= 1'b1; mii_txd <= 1'b0 ; end default: begin send_done <= 1'b0; mii_txd <= 1'b0 ; end endcase end always @(posedge mii_tx_clk or negedge rst_n) if(!rst_n) mii_tx_en <= 1'b0; else if(en && (cnt == 'h1)) //'d1 mii_tx_en <= 1'b1; else if(cnt == 'h36) //'d54 mii_tx_en <= 1'b0; else mii_tx_en <= mii_tx_en ; assign fifo_rd_clk = mii_tx_clk; endmodule
使用ARP工具生成Mac层传输的数据(不包含前导码和帧开始符),将数据复制到CRC生成工具,产生CRC校验值。
源主机通过广播形式发出 ARP 请求,以太网帧首部的硬件地址(目的MAC地址)填 FF:FF:FF:FF:FF:FF 表示广播。
使用case语句模拟FIFO写入数据。手动计算CRC码。
module mac_mii_send_test( input rst_n , input eth_tx_clk , output eth_tx_er , output eth_tx_en , output [3:0] eth_tx_data , output eth_rst_n ); parameter CRC = 32'h79D9D41B; //h42853ABE EA1C2E26 (PC IP 192.168.1.1 : h4DB06FEE) (PC IP 192.168.56.1 : hD892D6E1) wire mac_send_en ; wire [31:0] crc_result ; wire data_req ; wire send_done ; wire fifo_rd_clk ; reg [20:0] data_cnt ; reg [31:0] time_cnt ; reg [3:0] mac_send_data ; mac_mii_send mac_mii_send_inst( .mac_source (48'h17_31_81_ca_3c_7a), //Mac_source .mac_goal (48'hff_ff_ff_ff_ff_ff), //other_Mac radio .rst_n (rst_n), .mac_send_en (mac_send_en), //pulse width > 40ns .data_type (16'h08_06), //agreement type .data_length ('d112), //main data field length ARP字段与填充数据 data_length/2个字节 .crc_result (crc_result), //Frame check sequence // mii Interfac .mii_tx_clk (eth_tx_clk), //mii interface clk .mii_tx_en (eth_tx_en), //mii interface enable .mii_txd (eth_tx_data), //mii interface data .mii_tx_error (), //error signal high level effective // fifo Interface fifo 设置为 showahead 模式 .mac_send_data (mac_send_data), //data read from fifo .fifo_rd_clk (fifo_rd_clk), //read fifo clock .data_req (data_req), //read request .send_done (send_done) //pulse signal = 40ns ); assign eth_rst_n = 1; assign crc_result = {CRC[7:0],CRC[15:8],CRC[23:16],CRC[31:24]}; always @(posedge eth_tx_clk or negedge rst_n) if(!rst_n) data_cnt <= 1'b0; else if(data_req) data_cnt <= data_cnt + 1'b1; else data_cnt <= 1'b0; always @(posedge eth_tx_clk or negedge rst_n) if(!rst_n) time_cnt <= 'd0; else if(time_cnt == 'd80000) // time_cnt <= 1'b0; else time_cnt <= time_cnt + 1'b1; assign mac_send_en = (time_cnt == 'd50); //d2_499_999 always @(*) //ARP字段与填充数据 begin case(data_cnt) 0, 1, 3 : mac_send_data = 4'h0; 2 : mac_send_data = 4'h1; 4 : mac_send_data = 4'h8; 5 : mac_send_data = 4'h0; 6 : mac_send_data = 4'h0; 7 : mac_send_data = 4'h0; 8 : mac_send_data = 4'h6; //MAC地址长度 9 : mac_send_data = 4'h0; 10 : mac_send_data = 4'h4; //IP地址长度 11 : mac_send_data = 4'h0; 12 : mac_send_data = 4'h0; //操作码 请求包 13 : mac_send_data = 4'h0; 14 : mac_send_data = 4'h1; 15 : mac_send_data = 4'h0; 16 : mac_send_data = 4'h7; //源MAC地址 17 : mac_send_data = 4'h1; 18 : mac_send_data = 4'h1; 19 : mac_send_data = 4'h3; 20 : mac_send_data = 4'h1; 21 : mac_send_data = 4'h8; 22 : mac_send_data = 4'ha; 23 : mac_send_data = 4'hc; 24 : mac_send_data = 4'hc; 25 : mac_send_data = 4'h3; 26 : mac_send_data = 4'ha; 27 : mac_send_data = 4'h7; 28 : mac_send_data = 4'h0; //源IP地址 192.168.1.201 29 : mac_send_data = 4'hc; 30 : mac_send_data = 4'h8; 31 : mac_send_data = 4'ha; 32 : mac_send_data = 4'h1; 33 : mac_send_data = 4'h0; 34 : mac_send_data = 4'h9; 35 : mac_send_data = 4'hc; 36 : mac_send_data = 4'h0; //目标MAC地址 37 : mac_send_data = 4'h0; 38 : mac_send_data = 4'h0; 39 : mac_send_data = 4'h0; 40 : mac_send_data = 4'h0; 41 : mac_send_data = 4'h0; 42 : mac_send_data = 4'h0; 43 : mac_send_data = 4'h0; 44 : mac_send_data = 4'h0; 45 : mac_send_data = 4'h0; 46 : mac_send_data = 4'h0; 47 : mac_send_data = 4'h0; 48 : mac_send_data = 4'h0; //目标IP 192.168.1.4 49 : mac_send_data = 4'hc; 50 : mac_send_data = 4'h8; 51 : mac_send_data = 4'ha; 52 : mac_send_data = 4'h1; // 53 : mac_send_data = 4'h0; // 54 : mac_send_data = 4'h4; // 55 : mac_send_data = 4'h0; // 56 : mac_send_data = 4'h0; //填充 57 : mac_send_data = 4'h0; 58 : mac_send_data = 4'h0; 59 : mac_send_data = 4'h0; 60 : mac_send_data = 4'hf; 61 : mac_send_data = 4'hf; 62 : mac_send_data = 4'hf; 63 : mac_send_data = 4'hf; 64 : mac_send_data = 4'hf; 65 : mac_send_data = 4'hf; 66 : mac_send_data = 4'hf; 67 : mac_send_data = 4'hf; 68 : mac_send_data = 4'hf; 69 : mac_send_data = 4'hf; 70 : mac_send_data = 4'hf; 71 : mac_send_data = 4'hf; 72 : mac_send_data = 4'h0; 73 : mac_send_data = 4'h0; 74 : mac_send_data = 4'h3; 75 : mac_send_data = 4'h2; 76 : mac_send_data = 4'hd; 77 : mac_send_data = 4'hc; 78 : mac_send_data = 4'h6; 79 : mac_send_data = 4'h7; 80 : mac_send_data = 4'h3; 81 : mac_send_data = 4'h6; 82 : mac_send_data = 4'ha; 83 : mac_send_data = 4'h1; 84 : mac_send_data = 4'h8; 85 : mac_send_data = 4'h0; 86 : mac_send_data = 4'h6; 87 : mac_send_data = 4'h0; 88 : mac_send_data = 4'h0; 89 : mac_send_data = 4'h0; 90 : mac_send_data = 4'h1; 91 : mac_send_data = 4'h0; 92 : mac_send_data = 4'h3; 93 : mac_send_data = 4'h7; 94 : mac_send_data = 4'h4; 95 : mac_send_data = 4'h7; 96 : mac_send_data = 4'h5; 97 : mac_send_data = 4'h7; 98 : mac_send_data = 4'h6; 99 : mac_send_data = 4'h7; 100 : mac_send_data = 4'h7; 101 : mac_send_data = 4'h7; 102 : mac_send_data = 4'h1; 103 : mac_send_data = 4'h6; 104 : mac_send_data = 4'h2; 105 : mac_send_data = 4'h6; 106 : mac_send_data = 4'h3; 107 : mac_send_data = 4'h6; 108 : mac_send_data = 4'h4; 109 : mac_send_data = 4'h6; 110 : mac_send_data = 4'h5; 111 : mac_send_data = 4'h6; default : mac_send_data = 4'h0; endcase end endmodule
使用Wireshark软件查看ARP字段与应答。
将IP报头以2字节为单位相加(此时IP报头检验和为零),求和结果将数据高位溢出位加低16位,求和结果取反为IP报头检验和。
module ip_check( input [3:0] edition , //版本 input [3:0] head_length , //首部长度 input [7:0] service_type , //服务类型 input [15:0] ip_message_length , //ip报文长度 input [30:0] block_logo , //分段标识 + 偏移 input [7:0] life_cycle , //生存周期 input [7:0] agreement_type , //上层协议类型 // input [15:0] ip_checkout_0 , //计算时IP报头检验和为零 input [31:0] source_ip_address , //源IP地址 input [31:0] goal_ip_address , //目的IP地址 output [15:0] ip_checkout //IP报头检验和 ); wire [31:0] ip_check_sum ; wire [31:0] ip_check_sum_reg ; assign ip_check_sum_reg = ({edition,head_length,service_type} + ip_message_length + block_logo + {life_cycle,agreement_type} + source_ip_address[31:16] + source_ip_address[15:0] + goal_ip_address[31:16] + goal_ip_address[15:0]); assign ip_check_sum = ~(ip_check_sum_reg[31:16] + ip_check_sum_reg[15:0]); assign ip_checkout = ip_check_sum; endmodule
module mac_udp_send_test( input rst_n , input eth_tx_clk , output eth_tx_er , output eth_tx_en , output [3:0] eth_tx_data , output eth_rst_n ); parameter CRC = 32'hFE3A3426; //h42853ABE EA1C2E26 (PC IP 192.168.1.1 : h4DB06FEE) (PC IP 192.168.56.1 : hD892D6E1) parameter DATA_LENFTH = 11'd92; //46字节 wire mac_send_en ; wire [31:0] crc_result ; wire data_req ; wire send_done ; wire fifo_rd_clk ; reg [20:0] data_cnt ; reg [31:0] time_cnt ; reg [3:0] mac_send_data ; wire crc_en ; wire [31:0] crc ; wire [15:0] ip_checkout ; assign eth_rst_n = 1; assign crc_result = {CRC[7:0],CRC[15:8],CRC[23:16],CRC[31:24]}; // assign crc_result = CRC ; mac_udp_send mac_udp_send_inst( .mac_source (48'h17_31_81_CA_3C_7A), //Mac_source .mac_goal (48'h58_11_22_A0_E9_61), //目的MAC地址 .rst_n (rst_n), .mac_send_en (mac_send_en), //pulse width > 40ns .data_type (16'h08_00), // 长度/类型 UDP .data_length (DATA_LENFTH), // 数据与填充 data_length/2个字节 .crc_result (crc_result), //Frame check sequence // mii Interfac .mii_tx_clk (eth_tx_clk), //mii interface clk .mii_tx_en (eth_tx_en), //mii interface enable .mii_txd (eth_tx_data), //mii interface data .mii_tx_error (), //error signal high level effective // fifo Interface fifo 设置为 showahead 模式 .mac_send_data (mac_send_data), //data read from fifo input .fifo_rd_clk (fifo_rd_clk), //read fifo clock .data_req (data_req), //read request .crc_en (crc_en), .send_done (send_done) //pulse signal = 40ns ); ip_check ip_check_inst( .edition (4'h4) , //版本 .head_length (4'h5) , //首部长度 .service_type (0) , //服务类型 .ip_message_length (16'h002E) , //ip报文长度 .block_logo (0) , //分段标识等 .life_cycle (8'h40) , //生存周期 .agreement_type ('d17) , //上层协议类型 .source_ip_address ('hC0_A8_01_C9) , //源IP地址 .goal_ip_address ('hC0_A8_01_04) , //目的IP地址 .ip_checkout (ip_checkout) //IP报头检验和 ); always @(posedge eth_tx_clk or negedge rst_n) if(!rst_n) data_cnt <= 1'b0; else if(data_req) data_cnt <= data_cnt + 1'b1; else data_cnt <= 1'b0; always @(posedge eth_tx_clk or negedge rst_n) if(!rst_n) time_cnt <= 'd0; else if(time_cnt == 'd80000) // time_cnt <= 1'b0; else time_cnt <= time_cnt + 1'b1; assign mac_send_en = (time_cnt == 'd50); //d2_499_999 always @(*) //ARP字段与填充数据 begin case(data_cnt) 0 : mac_send_data = 4'h5; //IP首部长度 1 : mac_send_data = 4'h4; //IPV4 2 : mac_send_data = 4'h0; //服务类型 3 : mac_send_data = 4'h0; 4 : mac_send_data = 4'h0; //IP报文长度 5 : mac_send_data = 4'h0; 6 : mac_send_data = 4'he; 7 : mac_send_data = 4'h2; 8 : mac_send_data = 4'h0; //分段表示 设置0 9 : mac_send_data = 4'h0; 10 : mac_send_data = 4'h0; 11 : mac_send_data = 4'h0; 12 : mac_send_data = 4'h0; 13 : mac_send_data = 4'h0; 14 : mac_send_data = 4'h0; 15 : mac_send_data = 4'h0; 16 : mac_send_data = 4'h0; //周期 64 17 : mac_send_data = 4'h4; 18 : mac_send_data = 4'h1; //上层协议类型 19 : mac_send_data = 4'h1; // 算 20 : mac_send_data = ip_checkout[11:8]; //IP报头检验和 逻辑模块算出 忽略 ip_checkout[11:8] 21 : mac_send_data = ip_checkout[15:12]; //IP版本+....+目的IP地址 ip_checkout[15:12] 22 : mac_send_data = ip_checkout[3:0]; //测试校验和 图7.5-11 ip_checkout[3:0] 23 : mac_send_data = ip_checkout[7:4]; //ip_checkout[7:4] 24 : mac_send_data = 4'h0; //源IP地址 192.168.1.201 25 : mac_send_data = 4'hc; 26 : mac_send_data = 4'h8; 27 : mac_send_data = 4'ha; 28 : mac_send_data = 4'h1; 29 : mac_send_data = 4'h0; 30 : mac_send_data = 4'h9; 31 : mac_send_data = 4'hc; 32 : mac_send_data = 4'h0; //目的IP地址 4字节 192.168.1.4 33 : mac_send_data = 4'hc; 34 : mac_send_data = 4'h8; 35 : mac_send_data = 4'ha; 36 : mac_send_data = 4'h1; 37 : mac_send_data = 4'h0; 38 : mac_send_data = 4'h4; 39 : mac_send_data = 4'h0; //UDP协议层 40 : mac_send_data = 4'h9; //源端口号 2字节 6500 41 : mac_send_data = 4'h1; 42 : mac_send_data = 4'h4; 43 : mac_send_data = 4'h6; 44 : mac_send_data = 4'h5; //目的端口号 2字节 5500 45 : mac_send_data = 4'h1; 46 : mac_send_data = 4'hc; 47 : mac_send_data = 4'h7; 48 : mac_send_data = 4'h0; //UDP报文长度 26 2字节 49 : mac_send_data = 4'h0; 50 : mac_send_data = 4'ha; 51 : mac_send_data = 4'h1; 52 : mac_send_data = 4'h0; // UDP校验和 2字节 忽略全零 53 : mac_send_data = 4'h0; 54 : mac_send_data = 4'h0; 55 : mac_send_data = 4'h0; 56 : mac_send_data = 4'h8; //填充和数据 57 : mac_send_data = 4'h4; 58 : mac_send_data = 4'h5; 59 : mac_send_data = 4'h6; 60 : mac_send_data = 4'hc; 61 : mac_send_data = 4'h6; 62 : mac_send_data = 4'hc; 63 : mac_send_data = 4'h6; 64 : mac_send_data = 4'hf; 65 : mac_send_data = 4'h6; 66 : mac_send_data = 4'hc; 67 : mac_send_data = 4'h2; 68 : mac_send_data = 4'h7; 69 : mac_send_data = 4'h6; 70 : mac_send_data = 4'hf; 71 : mac_send_data = 4'h6; 72 : mac_send_data = 4'hf; 73 : mac_send_data = 4'h6; 74 : mac_send_data = 4'h4; 75 : mac_send_data = 4'h6; 76 : mac_send_data = 4'h0; 77 : mac_send_data = 4'h2; 78 : mac_send_data = 4'h4; 79 : mac_send_data = 4'h7; 80 : mac_send_data = 4'hf; 81 : mac_send_data = 4'h6; 82 : mac_send_data = 4'h0; 83 : mac_send_data = 4'h2; 84 : mac_send_data = 4'h6; 85 : mac_send_data = 4'h4; 86 : mac_send_data = 4'h0; 87 : mac_send_data = 4'h5; 88 : mac_send_data = 4'h7; 89 : mac_send_data = 4'h4; 90 : mac_send_data = 4'h1; 91 : mac_send_data = 4'h4; default : mac_send_data = 4'h0; endcase end endmodule
可以看到IP校验和无误,并且成功发送字母。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。