Xilinx AXI-LITE-ETH实现收发
`timescale 1ns / 1ps ////////////////////////////////////////////////////////////////////////////////// // Company: // Engineer: // // Create Date: 2021/08/10 09:52:27 // Design Name: // Module Name: Eth_TR // Project Name: // Target Devices: // Tool Versions: // Description: // // Dependencies: // // Revision: // Revision 0.01 - File Created // Additional Comments: // 1、打通AXI通信,实现配置PHY芯片 // 2、以太网数据收发 // 3、计算机ETH上位机抓包,实现无协议数据收�??? // 4、实现UART,打通计算机UART<-->ARTY UART <--> ARTY ETH <-->计算机ETH------------------未做 ////////////////////////////////////////////////////////////////////////////////// module Eth_TR( input CLK100MHZ, input ck_rst, input eth_col, input eth_crs, output eth_mdc, inout eth_mdio, output eth_ref_clk, output eth_rstn, input eth_rx_clk, input eth_rx_dv, input eth_rxerr, input [3:0]eth_rxd, input eth_tx_clk, output eth_tx_en, output [3:0]eth_txd ); clk_wiz_0 clk_wiz ( // Clock out ports .clk_out1(eth_ref_clk), // Status and control signals .resetn(ck_rst), .locked(), // Clock in ports .clk_in1(CLK100MHZ) ); wire phy_mdio_t,phy_mdio_o,phy_mdio_i; /* (*MARK_DEBUG = "TRUE"*)wire ip2intc_irpt; (*MARK_DEBUG = "TRUE"*)reg [12:0]s_axi_awaddr; (*MARK_DEBUG = "TRUE"*)reg s_axi_awvalid; (*MARK_DEBUG = "TRUE"*)wire s_axi_awready; (*MARK_DEBUG = "TRUE"*)reg [31:0]s_axi_wdata; (*MARK_DEBUG = "TRUE"*)reg [3:0]s_axi_wstrb; (*MARK_DEBUG = "TRUE"*)reg s_axi_wvalid; (*MARK_DEBUG = "TRUE"*)wire s_axi_wready; (*MARK_DEBUG = "TRUE"*)wire [1:0]s_axi_bresp; (*MARK_DEBUG = "TRUE"*)wire s_axi_bvalid; (*MARK_DEBUG = "TRUE"*)reg s_axi_bready; (*MARK_DEBUG = "TRUE"*)reg [12:0]s_axi_araddr; (*MARK_DEBUG = "TRUE"*)reg s_axi_arvalid ; (*MARK_DEBUG = "TRUE"*)wire s_axi_arready;//Read ready. This signal indicates that the master can accept the read data and response information. (*MARK_DEBUG = "TRUE"*)wire [31:0]s_axi_rdata; (*MARK_DEBUG = "TRUE"*)wire [1:0]s_axi_rresp; (*MARK_DEBUG = "TRUE"*)wire s_axi_rvalid; (*MARK_DEBUG = "TRUE"*)reg s_axi_rready; */ (*MARK_DEBUG = "TRUE"*)wire ip2intc_irpt; (*MARK_DEBUG = "TRUE"*)wire [12:0]s_axi_awaddr; (*MARK_DEBUG = "TRUE"*)wire s_axi_awvalid; (*MARK_DEBUG = "TRUE"*)wire s_axi_awready; (*MARK_DEBUG = "TRUE"*)wire [31:0]s_axi_wdata; (*MARK_DEBUG = "TRUE"*)wire [3:0]s_axi_wstrb; (*MARK_DEBUG = "TRUE"*)wire s_axi_wvalid; (*MARK_DEBUG = "TRUE"*)wire s_axi_wready; (*MARK_DEBUG = "TRUE"*)wire [1:0]s_axi_bresp; (*MARK_DEBUG = "TRUE"*)wire s_axi_bvalid; (*MARK_DEBUG = "TRUE"*)wire s_axi_bready; (*MARK_DEBUG = "TRUE"*)wire [12:0]s_axi_araddr; (*MARK_DEBUG = "TRUE"*)wire s_axi_arvalid ; (*MARK_DEBUG = "TRUE"*)wire s_axi_arready;//Read ready. This signal indicates that the master can accept the read data and response information. (*MARK_DEBUG = "TRUE"*)wire [31:0]s_axi_rdata; (*MARK_DEBUG = "TRUE"*)wire [1:0]s_axi_rresp; (*MARK_DEBUG = "TRUE"*)wire s_axi_rvalid; (*MARK_DEBUG = "TRUE"*)wire s_axi_rready; IOBUF #( .DRIVE(12), // Specify the output drive strength .IBUF_LOW_PWR("TRUE"), // Low Power - "TRUE", High Performance = "FALSE" .IOSTANDARD("DEFAULT"), // Specify the I/O standard .SLEW("SLOW") // Specify the output slew rate ) IOBUF_inst ( .O(phy_mdio_i), // Buffer output .IO(eth_mdio), // Buffer inout port (connect directly to top-level port) .I(phy_mdio_o), // Buffer input .T(phy_mdio_t) // 3-state enable input, high=input, low=output ); //打�?�AXI通信,实现配置PHY芯片 /************** //1、读PHY芯片ID mdio address 00001 �??0x07e4�??0x422 0000 0000 0000 0000 0000 0100 0010 0010 �??0x07f0�??0x9 0000 0000 0000 0000 0000 0000 0000 1001 之后�??0x7f0,若最低位�??0,�??0x07ec //2、配置PHY �?0x07e4�?0x20,向0x07e8�?0x3000,�?0x07f0�?0x9,之后读0x07f0到最后一位为0-----写PHY BMCR Done �?0x07e4�?0x421,�?0x07f0�?0x9,之后读0x07f0到最后一位为0,�?0x07ec //3、监测PHY状�?�寄存器 // ********以太网数据收�?--�? 1、向0x07f8�?32'h8000_0000 2、向0x17fc �?0x4('b1000),使能接收和接收中�? *************/ reg write,read; reg [12:0]write_addr,read_addr; reg [31:0]write_data; wire [31:0]read_data; wire read_done,write_done; (*MARK_DEBUG = "TRUE"*)reg read_DP_Done; (*MARK_DEBUG = "TRUE"*)reg write_DP_done; reg [11:0]read_dp_count; reg [11:0]write_dp_count; (*MARK_DEBUG = "TRUE"*)reg [31:0]Eth_State = 32'h0; parameter ETH_Idle = 32'h0000; parameter ETH_ReadPhyID_W07e4 = 32'h0001; parameter ETH_ReadPhyID_W07f0 = 32'h0002; parameter ETH_ReadPhyID_R07f0 = 32'h0004; parameter ETH_ReadPhyID_R07ec = 32'h0008;//read UID Done parameter ETH_CfgPhy_W07e4 = 32'h0010; parameter ETH_CfgPhy_W07e8 = 32'h0020; parameter ETH_CfgPhy_W07f0 = 32'h0040; parameter ETH_CfgPhy_R07f0 = 32'h0080;//Config PHY Done parameter ETH_RdPhyStat_W07e4 = 32'h0100;// parameter ETH_RdPhyStat_W07f0 = 32'h0200; parameter ETH_RdPhyStat_R07f0 = 32'h0400;// parameter ETH_RdPhyStat_R07ec = 32'h0800;//read PHY BMSR parameter ETH_EnGIE_W07f8 = 32'h1000;//enable global interrupt parameter ETH_EnRecInt_W17fc = 32'h2000;//enalbe Eth receive & int parameter ETH_WaitRecInt = 32'h4000; parameter ETH_RdDPRam_R17fc = 32'h8000;//status == 0 ? parameter ETH_RdDPRam = 32'h1_0000;//�?13'h1000~13'h1100,读结束回到ETH_EnRecInt_W17fc parameter ETH_WtDPRam_W0000 = 32'h2_0000;//写以太网数据 parameter ETH_WtDPRam_W07f4 = 32'h4_0000;//length parameter ETH_WtDPRam_W07f4_1 = 32'h8_0000; parameter ETH_WtDPRam_W07fc = 32'h10_0000;// parameter ETH_TransData = 32'h20_0000; parameter ETH_NOP = 32'h8000_0000; always @ (posedge CLK100MHZ or negedge ck_rst)begin if(~ck_rst)begin Eth_State <= ETH_Idle; end else begin case(Eth_State) ETH_Idle:begin Eth_State <= ETH_ReadPhyID_W07e4; end ETH_ReadPhyID_W07e4:begin if(write_done)begin Eth_State <= ETH_ReadPhyID_W07f0; end else begin Eth_State <= ETH_ReadPhyID_W07e4; end end ETH_ReadPhyID_W07f0:begin if(write_done) begin Eth_State <= ETH_ReadPhyID_R07f0; end else begin Eth_State <= ETH_ReadPhyID_W07f0; end end ETH_ReadPhyID_R07f0:begin if(read_done && (~read_data[0]))begin Eth_State <= ETH_ReadPhyID_R07ec; end else begin Eth_State <= ETH_ReadPhyID_R07f0; end end ETH_ReadPhyID_R07ec:begin if(read_done)begin Eth_State <= ETH_CfgPhy_W07e4; end else begin Eth_State <= ETH_ReadPhyID_R07ec; end end ETH_CfgPhy_W07e4:begin if(write_done)begin Eth_State <= ETH_CfgPhy_W07e8; end else begin Eth_State <= ETH_CfgPhy_W07e4; end end ETH_CfgPhy_W07e8:begin if(write_done) begin Eth_State <= ETH_CfgPhy_W07f0; end else begin Eth_State <= ETH_CfgPhy_W07e8; end end ETH_CfgPhy_W07f0:begin if(write_done) begin Eth_State <= ETH_CfgPhy_R07f0; end else begin Eth_State <= ETH_CfgPhy_W07f0; end end ETH_CfgPhy_R07f0:begin if(read_done && (~read_data[0]))begin Eth_State <= ETH_RdPhyStat_W07e4; end else begin Eth_State <= ETH_CfgPhy_R07f0; end end ETH_RdPhyStat_W07e4:begin if(write_done)begin Eth_State <= ETH_RdPhyStat_W07f0; end else begin Eth_State <= ETH_RdPhyStat_W07e4; end end ETH_RdPhyStat_W07f0:begin if(write_done)begin Eth_State <= ETH_RdPhyStat_R07f0; end else begin Eth_State <= ETH_RdPhyStat_W07f0; end end ETH_RdPhyStat_R07f0:begin if(read_done && (~read_data[0]))begin Eth_State <= ETH_RdPhyStat_R07ec; end else begin Eth_State <= ETH_RdPhyStat_R07f0; end end ETH_RdPhyStat_R07ec:begin if(read_done)begin //Eth_State <= ETH_NOP; if(read_data == 32'h786d)begin Eth_State <= ETH_EnGIE_W07f8; end else begin Eth_State <= ETH_RdPhyStat_W07f0; end end else begin Eth_State <= ETH_RdPhyStat_R07ec; end end ETH_EnGIE_W07f8:begin if(write_done) Eth_State <= ETH_EnRecInt_W17fc; else Eth_State <= ETH_EnGIE_W07f8; end ETH_EnRecInt_W17fc:begin//enalbe ETH Rec if(write_done) Eth_State <= ETH_WaitRecInt; else Eth_State <= ETH_EnRecInt_W17fc; end ETH_WaitRecInt:begin if(ip2intc_irpt)begin Eth_State <= ETH_RdDPRam_R17fc; end else begin Eth_State <= ETH_WaitRecInt; end end ETH_RdDPRam_R17fc:begin if(read_done && (read_data[0]))begin Eth_State <= ETH_RdDPRam; end else begin Eth_State <= ETH_RdDPRam_R17fc; end end ETH_RdDPRam:begin if(read_DP_Done)begin //Eth_State <= ETH_EnRecInt_W17fc;//读完数据清空中断标志 Eth_State <= ETH_WtDPRam_W0000; end else begin Eth_State <= ETH_RdDPRam; end end ETH_WtDPRam_W0000:begin if(write_DP_done)begin Eth_State <= ETH_WtDPRam_W07f4; end else begin Eth_State <= ETH_WtDPRam_W0000; end end ETH_WtDPRam_W07f4:begin if(write_addr == 13'h07f4) Eth_State <= ETH_WtDPRam_W07f4_1; end ETH_WtDPRam_W07f4_1:begin if(write_done)begin Eth_State <= ETH_WtDPRam_W07fc; end else begin Eth_State <= ETH_WtDPRam_W07f4_1; end end ETH_WtDPRam_W07fc:begin if(write_done)begin //Eth_State <= ETH_EnRecInt_W17fc;//读完数据清空中断标志 Eth_State <= ETH_TransData; end else begin Eth_State <= ETH_WtDPRam_W07fc; end end ETH_TransData:begin if(ip2intc_irpt)begin Eth_State <= ETH_EnRecInt_W17fc;//读完数据清空中断标志 end else begin Eth_State <= ETH_TransData; end end ETH_NOP:begin Eth_State <= ETH_NOP; end default:begin Eth_State <= ETH_Idle; end endcase end end reg [31:0] Data[15:0]; always @(posedge CLK100MHZ) begin Data[0] = 32'hf8_db_05_54;Data[1] = 32'h00_00_d1_29;Data[2] = 32'hce_fa_00_5e;Data[3] = 32'h00_45_00_08; Data[4] = 32'hb3_21_30_00;Data[5] = 32'h11_40_00_00;Data[6] = 32'ha8_c0_f0_d4;Data[7] = 32'ha8_c0_65_01; Data[8] = 32'h21_05_c8_01;Data[9] = 32'h1c_00_15_27;Data[10] = 32'hec_ef_0c_4a;Data[11] = 32'h36_c5_d6_3d; Data[12] = 32'h21_39_67_44;Data[13] = 32'hb3_6d_64_bc;Data[14] = 32'hb5_82_c8_97;Data[15] = 32'h00_00_41_50; end always @ (posedge CLK100MHZ or negedge ck_rst)begin if(~ck_rst)begin write <= 1'b0; read <= 1'b0; write_addr <= 13'h0; read_addr <= 13'h0; write_data <= 32'h0; end else begin case(Eth_State) ETH_Idle:begin write <= 1'b0; read <= 1'b0; write_addr <= 13'h0; read_addr <= 13'h0; write_data <= 32'h0; end ETH_ReadPhyID_W07e4:begin if(write_done) begin write <= 1'b0; end else begin write <= 1'b1; end write_addr <= 13'h07e4; write_data <= 32'h0422; end ETH_ReadPhyID_W07f0:begin if(write_done) begin write <= 1'b0; end else begin write <= 1'b1; end write_addr <= 13'h07f0; write_data <= 32'h9; end ETH_ReadPhyID_R07f0:begin if(read_done)begin read <= 1'b0; end else begin read <= 1'b1; end read_addr <= 13'h07f0; end ETH_ReadPhyID_R07ec:begin if(read_done) begin read <= 1'b0; end else begin read <= 1'b1; end read_addr <= 13'h07ec; end ETH_CfgPhy_W07e4:begin if(write_done) write <= 1'b0; else write <= 1'b1; write_addr <= 13'h07e4; write_data <= 32'h20; end ETH_CfgPhy_W07e8:begin if(write_done) write <= 1'b0; else write <= 1'b1; write_addr <= 13'h07e8; write_data <= 32'h3000; end ETH_CfgPhy_W07f0:begin if(write_done) write <= 1'b0; else write <= 1'b1; write_addr <= 13'h07f0; write_data <= 32'h9; end ETH_CfgPhy_R07f0:begin if(read_done) begin read <= 1'b0; end else begin read <= 1'b1; end read_addr <= 13'h07f0; end ETH_RdPhyStat_W07e4:begin if(write_done) write <= 1'b0; else write <= 1'b1; write_addr <= 13'h07e4; write_data <= 32'h421; end ETH_RdPhyStat_W07f0:begin if(write_done) write <= 1'b0; else write <= 1'b1; write_addr <= 13'h07f0; write_data <= 32'h9; end ETH_RdPhyStat_R07f0:begin if(read_done) begin read <= 1'b0; end else begin read <= 1'b1; end read_addr <= 13'h07f0; end ETH_RdPhyStat_R07ec:begin if(read_done) begin read <= 1'b0; end else begin read <= 1'b1; end read_addr <= 13'h07ec; end ETH_EnGIE_W07f8:begin write <= ~write_done; write_addr <= 13'h07f8; write_data <= 32'h8000_0000; end ETH_EnRecInt_W17fc:begin write <= ~write_done; write_addr <= 13'h17fc; write_data <= 32'h8; end ETH_RdDPRam_R17fc:begin read <= ~read_done; read_addr <= 13'h17fc; end ETH_RdDPRam:begin read <= ~read_done; read_addr <= 32'h1000 + read_dp_count; end ETH_WtDPRam_W0000:begin if(write_dp_count <= 13'h3c) begin write <= ~write_done; write_addr <= 13'h0 + write_dp_count; write_data <= Data[write_dp_count>>2]; end end ETH_WtDPRam_W07f4:begin write <= 1'b0; write_addr <= 13'h07f4; write_data <= 32'h3e;//length end ETH_WtDPRam_W07f4_1:begin if(write_done) write <= 1'b0; else write <= 1'b1; write_addr <= 13'h07f4; write_data <= 32'h3e;//length end ETH_WtDPRam_W07fc:begin write <= ~write_done; write_addr <= 13'h07fc; write_data <= 32'h9;//enable tx int end default:begin write <= 1'b0; read <= 1'b0; write_addr <= 13'h0; read_addr <= 13'h0; write_data <= 32'h0; end endcase end end //ETH发�?�处理分�? always @ (posedge CLK100MHZ or negedge ck_rst)begin if(~ck_rst)begin write_dp_count <= 12'h0; end else begin case(Eth_State) ETH_WtDPRam_W0000:begin if(write_done) write_dp_count <= write_dp_count + 4'd4; end default:begin write_dp_count <= 12'h0; end endcase end end always @ (posedge CLK100MHZ or negedge ck_rst)begin if(~ck_rst)begin write_DP_done <= 1'b0; end else begin if(write_done && (write_dp_count == 12'h3c)) write_DP_done <= 1'b1; else write_DP_done <= 1'b0; end end //ETH接收处理分支 always @ (posedge CLK100MHZ or negedge ck_rst)begin if(~ck_rst)begin read_dp_count <= 12'h0; end else begin case(Eth_State) ETH_RdDPRam:begin if(read_done) read_dp_count <= read_dp_count + 1'b1; end default:begin read_dp_count <= 12'h0; end endcase end end always @ (posedge CLK100MHZ or negedge ck_rst)begin if(~ck_rst)begin read_DP_Done <= 1'b0; end else begin if(read_done && (read_dp_count == 12'h100)) read_DP_Done <= 1'b1; else read_DP_Done <= 1'b0; end end axi_lite_tr axi_lite_tr1( .write(write), .read(read), .write_addr(write_addr), .read_addr(read_addr), .write_data(write_data), .read_data(read_data), .s_axi_aclk(CLK100MHZ) , //: IN STD_LOGIC; .s_axi_aresetn(ck_rst) , //: IN STD_LOGIC; .ip2intc_irpt(ip2intc_irpt) , //: OUT STD_LOGIC; .s_axi_awaddr(s_axi_awaddr) , //: IN STD_LOGIC_VECTOR(12 DOWNTO 0); .s_axi_awvalid(s_axi_awvalid) , //: IN STD_LOGIC; .s_axi_awready(s_axi_awready) , //: OUT STD_LOGIC; .s_axi_wdata(s_axi_wdata) , //: IN STD_LOGIC_VECTOR(31 DOWNTO 0); .s_axi_wstrb(s_axi_wstrb) , //: IN STD_LOGIC_VECTOR(3 DOWNTO 0); .s_axi_wvalid(s_axi_wvalid) , //: IN STD_LOGIC; .s_axi_wready(s_axi_wready) , //: OUT STD_LOGIC; .s_axi_bresp(s_axi_bresp) , //: OUT STD_LOGIC_VECTOR(1 DOWNTO 0); .s_axi_bvalid(s_axi_bvalid) , //: OUT STD_LOGIC; .s_axi_bready(s_axi_bready) , //: IN STD_LOGIC; .s_axi_araddr(s_axi_araddr) , //: IN STD_LOGIC_VECTOR(12 DOWNTO 0); .s_axi_arvalid(s_axi_arvalid) , //: IN STD_LOGIC; .s_axi_arready(s_axi_arready) , //: OUT STD_LOGIC; .s_axi_rdata(s_axi_rdata) , //: OUT STD_LOGIC_VECTOR(31 DOWNTO 0); .s_axi_rresp(s_axi_rresp) , //: OUT STD_LOGIC_VECTOR(1 DOWNTO 0); .s_axi_rvalid(s_axi_rvalid) , //: OUT STD_LOGIC; .s_axi_rready(s_axi_rready) , //: IN STD_LOGIC; .write_done(write_done), .read_done(read_done) ); axi_ethernetlite_0 axi_ethernetlite_1 ( .s_axi_aclk(CLK100MHZ), .s_axi_aresetn(ck_rst), .ip2intc_irpt(ip2intc_irpt), .s_axi_awaddr(s_axi_awaddr),// : IN STD_LOGIC_VECTOR(3 DOWNTO 0); .s_axi_awvalid(s_axi_awvalid),// : IN STD_LOGIC; .s_axi_awready(s_axi_awready),// : OUT STD_LOGIC; .s_axi_wdata(s_axi_wdata),// : IN STD_LOGIC_VECTOR(31 DOWNTO 0); .s_axi_wstrb(s_axi_wstrb),// : IN STD_LOGIC_VECTOR(3 DOWNTO 0); .s_axi_wvalid(s_axi_wvalid),// : IN STD_LOGIC; .s_axi_wready(s_axi_wready),// : OUT STD_LOGIC; .s_axi_bresp(s_axi_bresp),// : OUT STD_LOGIC_VECTOR(1 DOWNTO 0); .s_axi_bvalid(s_axi_bvalid),// : OUT STD_LOGIC; .s_axi_bready(s_axi_bready),// : IN STD_LOGIC; .s_axi_araddr(s_axi_araddr),// : IN STD_LOGIC_VECTOR(3 DOWNTO 0); .s_axi_arvalid(s_axi_arvalid),//: IN STD_LOGIC; .s_axi_arready(s_axi_arready),//: OUT STD_LOGIC; .s_axi_rdata(s_axi_rdata),// : OUT STD_LOGIC_VECTOR(31 DOWNTO 0); .s_axi_rresp(s_axi_rresp),// : OUT STD_LOGIC_VECTOR(1 DOWNTO 0); .s_axi_rvalid(s_axi_rvalid),// : OUT STD_LOGIC; .s_axi_rready(s_axi_rready),// : IN STD_LOGIC; .phy_tx_clk(eth_tx_clk), .phy_rx_clk(eth_rx_clk), .phy_crs(eth_crs), .phy_dv(eth_rx_dv), .phy_rx_data(eth_rxd), .phy_col(eth_col), .phy_rx_er(eth_rxerr), .phy_rst_n(eth_rstn), .phy_tx_en(eth_tx_en), .phy_tx_data(eth_txd), .phy_mdio_i(phy_mdio_i), .phy_mdio_o(phy_mdio_o), .phy_mdio_t(phy_mdio_t), .phy_mdc(eth_mdc) ); endmodule
1、PHY芯片为DP83848;
2、调用AXI-LITE读写模块:Xilinx AXI-LITE读写模块 - 昊天一怪 - 博客园 (cnblogs.com)
3、参考xilinx PG135手册