一、HDMI
1.1 、HDMI介紹
高清多媒體接口(High Definition Multimedia Interface)是一種全數(shù)字化視頻和聲音發(fā)送接口,可以發(fā)送未壓縮的音頻及視頻信號。HDMI可用于機頂盒、DVD播放機、個人計算機、電視、游戲主機、綜合擴大機、數(shù)字音響與電視機等設備。HDMI可以同時發(fā)送音頻和視頻信號,由于音頻和視頻信號采用同一條線材,大大簡化系統(tǒng)線路的安裝難度。
HDMI是被設計來取代較舊的模擬信號影音發(fā)送接口如SCART或RCA等端子的。它支持各類電視與計算機視頻格式,包括SDTV、HDTV視頻畫面,再加上多聲道數(shù)字音頻。HDMI與去掉音頻傳輸功能的UDI都繼承DVI的核心技術“傳輸最小化差分信號”TMDS,從本質上來說仍然是DVI的擴展。DVI、HDMI、UDI的視頻內(nèi)容都以即時、專線方式進行傳輸,這可以保證視頻流量大時不會發(fā)生堵塞的現(xiàn)象。每個像素數(shù)據(jù)量為24位。信號的時序與VGA極為類似。
1.1.1、HDMI接口
HDMI 1.0版本于2002年發(fā)布,最高數(shù)據(jù)傳輸速度為5Gbps;而2017年發(fā)布的HDMI 2.1標準的理論帶寬可達48Gbps。HDMI的規(guī)格書中規(guī)定了四種HDMI接口。HDMI向下兼容DVI,但是DVI(數(shù)字視頻接口)只能用于傳輸視頻,而不能同時傳輸音頻,這是兩者最大的區(qū)別。此外,DVI接口的尺寸明顯大于HDMI接口,
右側是最常見的A型HDMI接口,其引腳定義如下圖:
圖1.2.2HDMI接口引腳圖
DVI和HDMI接口協(xié)議在物理層使用TMDS標準傳輸音視頻數(shù)據(jù)。
1.1.2 、TMDS介紹
TMDS(Transition Minimized Differential Signaling,最小化傳輸差分信號)是美國Silicon Image公司開發(fā)的一項高速數(shù)據(jù)傳輸技術,在DVI和HDMI視頻接口中使用差分信號傳輸高速串行數(shù)據(jù)。TMDS差分傳輸技術使用兩個引腳(如圖21.1.2中的“數(shù)據(jù)2+”和“數(shù)據(jù)2-”)來傳輸一路信號,利用這兩個引腳間的電壓差的正負極性和大小來決定傳輸數(shù)據(jù)的數(shù)值(0或1)。
DVI或HDMI視頻傳輸所使用的TMDS連接通過四個串行通道實現(xiàn)。對于DVI來說,其中三個通道分別用于傳輸視頻中每個像素點的紅、綠、藍三個顏色分量(RGB4:4:4格式)。HDMI默認也是使用三個RGB通道,但是它同樣可以選擇傳輸像素點的亮度和色素信息(YCrCb44或YCrCb42格式)。第四個通道是時鐘通道,用于傳輸像素時鐘。獨立的TMDS時鐘通道為接收端提供接收的參考頻率,保證數(shù)據(jù)在接收端能夠正確恢復。
圖1.3.1 、TMDS連接示意圖
如果每個像素點的顏色深度為24位,即RGB每個顏色分量各占8位,那么每個通道上的顏色數(shù)據(jù)將通過一個8B/10B的編碼器(Encoder)來轉換成一個10位的像素字符。然后這個10位的字符通過并串轉換器(Serializer)轉換成串行數(shù)據(jù),最后由TMDS數(shù)據(jù)通道發(fā)送出去。這個10:1的并轉串過程所生成的串行數(shù)據(jù)速率是實際像素時鐘速率的10倍。
在傳輸視頻圖像的過程中,數(shù)據(jù)通道上傳輸?shù)氖蔷幋a后的有效像素字符。而在每一幀圖像的行與行之間,以及視頻中不同幀之間的時間間隔(消隱期)內(nèi),數(shù)據(jù)通道上傳輸?shù)膭t是控制字符。每個通道上有兩位控制信號的輸入接口,共對應四種不同的控制字符。這些控制字符提供了視頻的行同步(HZYNC)以及幀同步(VSYNC)信息,也可以用來指定所傳輸數(shù)據(jù)的邊界(用于同步)。
對于DVI傳輸,整個視頻的消隱期都用來傳輸控制字符。而HDMI傳輸?shù)南[期除了控制字符之外,還可以用于傳輸音頻或者其他附加數(shù)據(jù),比如字幕信息等。這就是DVI和HDMI協(xié)議之間最主要的差別。從圖1.3.1中也可以看出這一差別,即“Auxiliary Data”接口標有“HDMI Olny”,即它是HDMI所獨有的接口。
從前面的介紹中我們可以看出,TMDS連接從邏輯功能上可以劃分成兩個階段:編碼和并串轉換。在編碼階段,編碼器將視頻源中的像素數(shù)據(jù)、HDMI的音頻/附加數(shù)據(jù),以及行同步和場同步信號分別編碼成10位的字符流。然后在并串轉換階段將上述的字符流轉換成串行數(shù)據(jù)流,并將其從三個差分輸出通道發(fā)送出去。
DVI編碼器在視頻有效數(shù)據(jù)段輸出像素數(shù)據(jù),在消隱期輸出控制數(shù)據(jù),如圖1.3.2所示。其中VDE(Video Data Enable)為高電平時表示視頻數(shù)據(jù)有效,為低電平代表當前處于視頻消隱期。
圖1.3.2DVI編碼輸出示意圖
圖1.3.3給出了三個通道的DVI編碼器示意圖。對于像素數(shù)據(jù)的RGB三個顏色通道,編碼器的邏輯是完全相同的。VDE用于各個通道選擇輸出視頻像素數(shù)據(jù)還是控制數(shù)據(jù)。HSYNC和VSYNC信號在藍色通道進行編碼得到10位字符,然后在視頻消隱期傳輸。綠色和紅色通道的控制信號C0和C1同樣需要進行編碼,并在消隱期輸出。但是DVI規(guī)范中這兩個通道的控制信號是預留的(未用到),因此將其置為2‘b00。
圖1.3.3 DVI編碼示意圖
每個通道輸入的視頻像素數(shù)據(jù)都要使用DVI規(guī)范中的TMDS編碼算法進行編碼。每個8-bit的數(shù)據(jù)都將被轉換成460個特定10-bit字符中的一個。這個編碼機制大致上實現(xiàn)了傳輸過程中的直流平衡,即一段時間內(nèi)傳輸?shù)母唠娖剑〝?shù)字“1”)的個數(shù)大致等于低電平(數(shù)字“0”)的個數(shù)。同時,每個編碼后的10-bit字符中狀態(tài)跳轉(“由1到0”或者“由0到1”)的次數(shù)將被限制在五次以內(nèi)。
除了視頻數(shù)據(jù)之外,每個通道2-bit控制信號的狀態(tài)也要進行編碼,編碼后分別對應四個不同的10-bit控制字符,分別是10'b1101010100,10'b0010101011,10'b0101010100,和10'b1010101011。可以看出,每個控制字符都有七次以上的狀態(tài)跳轉。視頻字符和控制字符狀態(tài)跳轉次數(shù)的不同將會被用于發(fā)送和接收設備的同步。
HDMI協(xié)議與DVI協(xié)議在很多方面都是相同的,包括物理連接(TMDS)、有效視頻編碼算法以及控制字符的定義等。但是相比于DVI,HDMI在視頻的消隱期會傳輸更多的數(shù)據(jù),包括音頻數(shù)據(jù)和附加數(shù)據(jù)。4-bit音頻和附加數(shù)據(jù)將通過TERC4編碼機制轉換成10-bit TERC4字符,然后在綠色和紅色通道上傳輸。
HDMI在輸入附加數(shù)據(jù)的同時,還需要輸入ADE(Aux/Audio Data Enable)信號,其作用和VDE是類似的:當ADE為高電平時,表明輸入端的附加數(shù)據(jù)或者音頻數(shù)據(jù)有效。如果大家想了解更多有關HDMI的細節(jié),可以參考開發(fā)板資料(A盤)/8_FPGA參考資料/HDMI/《HDMI Specification 13a》。為了簡單起見,我們在這里把HDMI接口當作DVI接口進行驅動。
在編碼之后,3個通道的10-bit字符將進行并串轉換,這一過程是使用7系列FPGA中專用的硬件資源來實現(xiàn)的。7系列的FPGA提供了專用的并串轉換器——OSERDESE2。單一的OSERDESE2模塊可以實現(xiàn)8:1的并串轉換,通過位寬擴展可以實現(xiàn)10:1和14:1的轉換率。
1.2 HDMI設計思路
對于HDMI,和之前VGA項目差不多,可以通過修改VGA的驅動代碼,來實現(xiàn)HDMI的驅動,修改其中的分辨率和時鐘,即可完成。
對于HDMI來說,需要將信號轉為差分對,再將并轉為串。
1.3 代碼
modulehdmi_driver( inputwireclk, inputwirerst_n, outputwireVSYNC, outputwireHSYNC, outputwire[23:0]RGB, outputwireen_display ); parameterH_A=40; parameterH_B=220; parameterH_C=1280; parameterH_D=110; parameterH_E=1650; parameterV_A=5; parameterV_B=20; parameterV_C=720; parameterV_D=5; parameterV_E=750; reg[10:0]cnt_h; reg[9:0]cnt_v; wireen_h;//顯示列的C段有效標志信?? wireen_v;//顯示行的C段有效標志信?? wireaddr_en_h; wireaddr_en; always@(posedgeclk,negedgerst_n) begin if(rst_n==1'b0) cnt_h<=?11'd0; ????else?if(cnt_h?==?H_E?-?1) ??????cnt_h?<=?11'd0; ????else ??????cnt_h?<=?cnt_h?+?1'b1; ??end ?? ??always?@?(posedge?clk,?negedge?rst_n) ??begin ????if(rst_n?==?1'b0) ??????cnt_v?<=?10'd0; ????else?if(cnt_h?==?H_E?-?1) ??????begin ????????if(cnt_v?==?V_E?-?1) ??????????cnt_v?<=?10'd0; ????????else ??????????cnt_v?<=?cnt_v?+?1'b1; ??????end ????else ??????cnt_v?<=?cnt_v; ??end ?? ??assign?HSYNC?=?(cnt_h?=H_A+H_B&&cnt_h=V_A+V_B&&cnt_v=566&&cnt_h666)???1'b1?:?1'b0; //??assign?en_v?=?(cnt_v?>=277&&cnt_v377)???1'b1?:?1'b0; ?? //??assign?addr_en_h?=?(cnt_h?>=565&&cnt_h665)???1'b1?:?1'b0; //??assign?addr_en?=?(addr_en_h?&&?en_v)???1'b1?:?1'b0; ?? ??assign?en_display?=?(en_h?&&?en_v)???1'b1?:?1'b0; ?? ??assign?RGB?=?(en_display)???24'b11111111_11111111_11111111?:?24'd0; /* ??always?@?(posedge?clk,?negedge?rst_n) ??begin ????if(rst_n?==?1'b0) ??????addr?<=?14'd0; ????else?if(addr_en) ??????begin ????????if(addr?==?14'd9999) ??????????addr?<=?14'd0; ????????else ??????????addr?<=?addr?+?1'b1; ??????end ????else ??????addr?<=?addr; ??end ??*/ //??assign?RGB?=?(en_display)???q?:?8'd0; endmodule?
Top頂層模塊
moduletop( inputclk, inputrst_n, outputD0_P, outputD0_N, outputD1_P, outputD1_N, outputD2_P, outputD2_N, outputD3_P, outputD3_N ); wireVSYNC; wireHSYNC; wire[23:0]RGB; wireen_display; wireclk_1; wireclk_5; wirelocked; wireR_b; wireG_b; wireB_b; wireclk_b; wire[9:0]G,B,R; pllinstance_name ( //Clockoutports .clk_out1(clk_1),//outputclk_out1 .clk_out2(clk_5),//outputclk_out2 //Statusandcontrolsignals .reset(~rst_n),//inputreset .locked(locked),//outputlocked //Clockinports .clk_in1(clk));//inputclk_in1 vga_drivervga_driver_inst( .clk(clk_1), .rst_n(locked), .VSYNC(VSYNC), .HSYNC(HSYNC), .RGB(RGB), .en_display(en_display) ); dvi_encoderdvi_encoder_inst0( .clkin(clk_1),//pixelclockinput .rstin(~locked),//async.resetinput(activehigh) .din(RGB[23:16]),//datainputs:expectregistered .c0(1'b0),//c0input .c1(1'b0),//c1input .de(en_display),//deinput .dout(R)//dataoutputs ); serializer_10_to_1serializer_10_to_1_inst0( .reset(~locked),// .paralell_clk(clk_1),// .serial_clk_5x(clk_5),// .paralell_data(R),// .serial_data_out(R_b)// ); OBUFDSOBUFDS_inst0( .O(D2_P),//1-bitoutput:Diff_poutput(connectdirectlytotop-levelport) .OB(D2_N),//1-bitoutput:Diff_noutput(connectdirectlytotop-levelport) .I(R_b)//1-bitinput:Bufferinput ); dvi_encoderdvi_encoder_inst1( .clkin(clk_1),//pixelclockinput .rstin(~locked),//async.resetinput(activehigh) .din(RGB[15:8]),//datainputs:expectregistered .c0(1'b0),//c0input .c1(1'b0),//c1input .de(en_display),//deinput .dout(G)//dataoutputs ); serializer_10_to_1serializer_10_to_1_inst1( .reset(~locked),// .paralell_clk(clk_1),// .serial_clk_5x(clk_5),// .paralell_data(G),// .serial_data_out(G_b)// ); OBUFDSOBUFDS_inst1( .O(D1_P),//1-bitoutput:Diff_poutput(connectdirectlytotop-levelport) .OB(D1_N),//1-bitoutput:Diff_noutput(connectdirectlytotop-levelport) .I(G_b)//1-bitinput:Bufferinput ); dvi_encoderdvi_encoder_inst2( .clkin(clk_1),//pixelclockinput .rstin(~locked),//async.resetinput(activehigh) .din(RGB[7:0]),//datainputs:expectregistered .c0(HSYNC),//c0input .c1(VSYNC),//c1input .de(en_display),//deinput .dout(B)//dataoutputs ); serializer_10_to_1serializer_10_to_1_inst2( .reset(~locked), .paralell_clk(clk_1),// .serial_clk_5x(clk_5),// .paralell_data(B),// .serial_data_out(B_b)// ); OBUFDSOBUFDS_inst2( .O(D0_P),// .OB(D0_N),// .I(B_b)// ); serializer_10_to_1serializer_10_to_1_inst3( .reset(~locked), .paralell_clk(clk_1),// .serial_clk_5x(clk_5),// .paralell_data(10'b11111_00000), .serial_data_out(clk_b)// ); OBUFDSOBUFDS_inst3( .O(D3_P),//1-bitoutput:Diff_poutput(connectdirectlytotop-levelport) .OB(D3_N),//1-bitoutput:Diff_noutput(connectdirectlytotop-levelport) .I(clk_b)//1-bitinput:Bufferinput ); endmodule
對于其他模塊,都是進行調(diào)用,并沒有自己編寫,即不再簡述。
2.1 、UDP數(shù)據(jù)包介紹
2.2 、MAC協(xié)議
2.3 、IP協(xié)議
2.4 、UDP協(xié)議
2.5 、代碼
以下代碼即為UDP發(fā)送模塊。
moduleeth_tx( inputwireclk, inputwirerst_n, inputwirekey, outputreggmii_tx_en, outputwiregmii_tx_er, outputwiregmii_tx_clk, outputreg[7:0]gmii_tx_data ); //88-A4-C2-E5-D3-66{8'h8c,8'h82,8'hb9,8'h95,8'h10,8'hcc}; parameterPC_MAC={8'h88,8'ha4,8'hc2,8'he5,8'hd3,8'h66}; parameterBOARD_MAC={8'h88,8'ha4,8'hc2,8'he5,8'hd3,8'h67}; parameterPC_IP={8'd192,8'd168,8'd0,8'd2}; parameterBOARD_IP={8'd192,8'd168,8'd0,8'd3}; parameterPC_COM=16'd65533; parameterBOARD_COM=16'd65531; wireclk_125m; wirelocked; wireflag; wireneg_edge; regi_en; regi_init; wire[31:0]crc; wire[31:0]crc_new; reg[63:0]send_buf; reg[4:0]state; reg[9:0]send_cnt; wirekey_flag; wire[31:0]IP_HEAD1; wire[31:0]IP_HEAD2; wire[31:0]IP_HEAD3; wire[15:0]DATA_LEN; wire[15:0]UDP_LEN; wire[15:0]IP_HEAD_LEN; wire[15:0]IP_HEAD_SUM; wire[31:0]IP_HEAD_SUM1; assigngmii_tx_clk=clk_125m; assigngmii_tx_er=1'b0; assignDATA_LEN=16'd24; assignUDP_LEN=DATA_LEN+16'd8; assignIP_HEAD_LEN=UDP_LEN+16'd20; assignIP_HEAD1={8'h45,8'd0,IP_HEAD_LEN}; assignIP_HEAD2=32'd0; assignIP_HEAD3={8'hff,8'd17,IP_HEAD_SUM}; assignIP_HEAD_SUM1=IP_HEAD1[31:16]+IP_HEAD1[15:0]+IP_HEAD3[31:16]+PC_IP[31:16]+PC_IP[15:0]+BOARD_IP[31:16]+BOARD_IP[15:0]; assignIP_HEAD_SUM=~(IP_HEAD_SUM1[31:16]+IP_HEAD_SUM1[15:0]); my_pllmy_pll_inst( .areset(~rst_n), .inclk0(clk), .c0(clk_125m), .locked(locked) ); jitterjitter_inst( .clk(clk_125m), .rst_n(locked), .key(key), .flag(flag) ); neg_edgeneg_edge_inst( .clk(clk_125m), .rst_n(locked), .flag(flag), .neg_edge(neg_edge) ); CRC32_D8CRC32_D8_inst( .clk(clk_125m), .rst_n(locked), .i_en(i_en), .i_data(gmii_tx_data), .i_init(i_init), .crc(crc), .crc_new(crc_new) ); always@(posedgeclk_125m) begin if(locked==1'b0) begin gmii_tx_data<=?8'd0; ????????gmii_tx_en?<=?1'b0; ????????state?<=?5'd0; ????????i_en?<=?1'b0; ????????i_init?<=?1'b0; ????????send_buf?<=?64'd0; ????????send_cnt?<=?10'd0; ??????end ????else ??????case?(state) ????????5'd0?:??begin ??????????????????if?(neg_edge) ????????????????????state?<=?5'd1; ??????????????????else ????????????????????state?<=?5'd0; ????????????????end ????????5'd1?:??begin ??????????????????state?<=?5'd2; ??????????????????i_init?<=?1'b1; ??????????????????send_buf?<=?{{7{8'h55}},8'hd5}; ????????????????end? ????????5'd2?:??begin ??????????????????i_init?<=?1'b0; ??????????????????gmii_tx_en?<=?1'b1; ??????????????????if(send_cnt?10'd7) ????????????????????begin ??????????????????????send_cnt?<=?send_cnt?+?1'b1; ??????????????????????gmii_tx_data?<=?send_buf[63:56]; ??????????????????????send_buf?<=?{send_buf[55:0],send_buf[63:56]}; ????????????????????end ??????????????????else ????????????????????begin ??????????????????????send_cnt?<=?10'd0; ??????????????????????gmii_tx_data?<=?send_buf[63:56]; ??????????????????????send_buf?<=?{PC_MAC,16'd0}; ??????????????????????state?<=?5'd3; ????????????????????end ????????????????end ????????5'd3?:??begin ????????????????????i_en?<=?1'b1; ????????????????????if(send_cnt?10'd5) ??????????????????????begin ????????????????????????send_cnt?<=?send_cnt?+?1'b1; ????????????????????????gmii_tx_data?<=?send_buf[63:56]; ????????????????????????send_buf?<=?{send_buf[55:0],send_buf[63:56]}; ??????????????????????end ????????????????????else ??????????????????????begin ????????????????????????send_cnt?<=?10'd0; ????????????????????????gmii_tx_data?<=?send_buf[63:56]; ????????????????????????send_buf?<=?{BOARD_MAC,16'h0800}; ????????????????????????state?<=?5'd4; ??????????????????????end ????????????????end ????????5'd4??:?begin ??????????????????if(send_cnt?10'd7) ????????????????????begin ??????????????????????send_cnt?<=?send_cnt?+?1'b1; ??????????????????????gmii_tx_data?<=?send_buf[63:56]; ??????????????????????send_buf?<=?{send_buf[55:0],send_buf[63:56]}; ????????????????????end ??????????????????else ????????????????????begin ??????????????????????send_cnt?<=?10'd0; ??????????????????????gmii_tx_data?<=?send_buf[63:56]; ??????????????????????send_buf?<=?{IP_HEAD1,IP_HEAD2}; ??????????????????????state?<=?5'd5; ????????????????????end ????????????????end ????????5'd5??:?begin ??????????????????if(send_cnt?10'd7) ????????????????????begin ??????????????????????send_cnt?<=?send_cnt?+?1'b1; ??????????????????????gmii_tx_data?<=?send_buf[63:56]; ??????????????????????send_buf?<=?{send_buf[55:0],send_buf[63:56]}; ????????????????????end ??????????????????else ????????????????????begin ??????????????????????send_cnt?<=?10'd0; ??????????????????????gmii_tx_data?<=?send_buf[63:56]; ??????????????????????send_buf?<=?{IP_HEAD3,BOARD_IP}; ??????????????????????state?<=?5'd6; ????????????????????end ????????????????end ????????5'd6??:?begin ??????????????????if(send_cnt?10'd7) ????????????????????begin ??????????????????????send_cnt?<=?send_cnt?+?1'b1; ??????????????????????gmii_tx_data?<=?send_buf[63:56]; ??????????????????????send_buf?<=?{send_buf[55:0],send_buf[63:56]}; ????????????????????end ??????????????????else ????????????????????begin ??????????????????????send_cnt?<=?10'd0; ??????????????????????gmii_tx_data?<=?send_buf[63:56]; ??????????????????????send_buf?<=?{PC_IP,BOARD_COM,PC_COM}; ??????????????????????state?<=?5'd7; ????????????????????end ????????????????end ????????5'd7??:?begin ??????????????????if(send_cnt?10'd7) ????????????????????begin ??????????????????????send_cnt?<=?send_cnt?+?1'b1; ??????????????????????gmii_tx_data?<=?send_buf[63:56]; ??????????????????????send_buf?<=?{send_buf[55:0],send_buf[63:56]}; ????????????????????end ??????????????????else ????????????????????begin ??????????????????????send_cnt?<=?10'd0; ??????????????????????gmii_tx_data?<=?send_buf[63:56]; ??????????????????????send_buf?<=?{UDP_LEN,16'd0,32'd0}; ??????????????????????state?<=?5'd8; ????????????????????end ????????????????end ????????5'd8??:?begin ??????????????????if(send_cnt?10'd3) ????????????????????begin ??????????????????????send_cnt?<=?send_cnt?+?1'b1; ??????????????????????gmii_tx_data?<=?send_buf[63:56]; ??????????????????????send_buf?<=?{send_buf[55:0],send_buf[63:56]}; ????????????????????end ??????????????????else ????????????????????begin ??????????????????????send_cnt?<=?10'd0; ??????????????????????gmii_tx_data?<=?send_buf[63:56]; ??????????????????????send_buf?<=?"Hello!!!"; ??????????????????????state?<=?5'd9; ????????????????????end ????????????????end ????????5'd9??:?begin ??????????????????if(send_cnt?10'd7) ????????????????????begin ??????????????????????send_cnt?<=?send_cnt?+?1'b1; ??????????????????????gmii_tx_data?<=?send_buf[63:56]; ??????????????????????send_buf?<=?{send_buf[55:0],send_buf[63:56]}; ????????????????????end ??????????????????else ????????????????????begin ??????????????????????send_cnt?<=?10'd0; ??????????????????????gmii_tx_data?<=?send_buf[63:56]; ??????????????????????send_buf?<=?"World!!!"; ??????????????????????state?<=?5'd10; ????????????????????end ????????????????end ????????5'd10?:?begin ??????????????????if(send_cnt?10'd7) ????????????????????begin ??????????????????????send_cnt?<=?send_cnt?+?1'b1; ??????????????????????gmii_tx_data?<=?send_buf[63:56]; ??????????????????????send_buf?<=?{send_buf[55:0],send_buf[63:56]}; ????????????????????end ??????????????????else ????????????????????begin ??????????????????????send_cnt?<=?10'd0; ??????????????????????gmii_tx_data?<=?send_buf[63:56]; ??????????????????????send_buf?<=?"Lichuang"; ??????????????????????state?<=?5'd11; ????????????????????end ????????????????end ????????5'd11?:?begin ??????????????????if(send_cnt?10'd7) ????????????????????begin ??????????????????????send_cnt?<=?send_cnt?+?1'b1; ??????????????????????gmii_tx_data?<=?send_buf[63:56]; ??????????????????????send_buf?<=?{send_buf[55:0],send_buf[63:56]}; ????????????????????end ??????????????????else ????????????????????begin ??????????????????????send_cnt?<=?10'd0; ??????????????????????gmii_tx_data?<=?send_buf[63:56]; ??????????????????????send_buf?<=?64'd0; ??????????????????????state?<=?5'd12; ????????????????????end ????????????????end ????????5'd12?:?begin??? ??????????????????i_en?<=?1'b0; ??????????????????gmii_tx_data?<=?~{crc_new[24],crc_new[25],crc_new[26],crc_new[27],crc_new[28],crc_new[29],crc_new[30],crc_new[31]}; ??????????????????state?<=?5'd13; ????????????????end ????????5'd13?:?begin??? ??????????????????i_en?<=?1'b0; ??????????????????gmii_tx_data?<=?~{crc[16],crc[17],crc[18],crc[19],crc[20],crc[21],crc[22],crc[23]}; ??????????????????state?<=?5'd14; ????????????????end ????????5'd14?:?begin??? ??????????????????i_en?<=?1'b0; ??????????????????gmii_tx_data?<=?~{crc[8],crc[9],crc[10],crc[11],crc[12],crc[13],crc[14],crc[15]}; ??????????????????state?<=?5'd15; ????????????????end ????????5'd15?:?begin??? ??????????????????i_en?<=?1'b0; ??????????????????gmii_tx_data?<=?~{crc[0],crc[1],crc[2],crc[3],crc[4],crc[5],crc[6],crc[7]}; ??????????????????state?<=?5'd16; ????????????????end ????????5'd16?:?begin ??????????????????gmii_tx_en?<=?1'b0; ??????????????????state?<=?5'd0; ????????????????end ????????default:?; ??????endcase ??end endmodule
以下為發(fā)送模塊代碼:
moduleeth_rx( inputwirerx_clk, inputwirerst_n, inputwirerx_er, inputwirerx_en, inputwire[7:0]rx_data, outputregfifo_wr_en, outputregfifo_data_valid, outputregfifo_data_clr, outputreg[7:0]fifo_data, outputreg[15:0]data_cnt ); parameterPC_MAC={8'h88,8'ha4,8'hc2,8'he5,8'hd3,8'h66}; parameterBOARD_MAC={8'h88,8'ha4,8'hc2,8'he5,8'hd3,8'h67}; parameterPC_IP={8'd192,8'd168,8'd0,8'd2}; parameterBOARD_IP={8'd192,8'd168,8'd0,8'd3}; parameterPC_COM=16'd65533; parameterBOARD_COM=16'd65531; reg[4:0]state; regi_en; regi_init; wire[31:0]crc; reg[47:0]rx_buf; reg[9:0]rx_cnt; reg[31:0]IP_HEAD_SUM; reg[15:0]UDP_LEN; CRC32_D8CRC32_D8_inst( .clk(rx_clk), .rst_n(rst_n), .i_en(i_en), .i_data(rx_data), .i_init(i_init), .crc(crc), .crc_new() ); always@(posedgerx_clk) begin if(rst_n==1'b0) begin fifo_wr_en<=?1'b0; ????????????fifo_data?<=?8'd0; ????????????fifo_data_valid?<=?1'b0; ????????????fifo_data_clr?<=?1'b0; ????????????state?<=?5'd1; ????????????i_en?<=?1'b0; ????????????i_init?<=?1'b0; ????????????rx_buf?<=?48'd0; ????????????rx_cnt?<=?10'd0; ????????????IP_HEAD_SUM?<=?PC_IP[31:16]?+?PC_IP[15:0]?+?BOARD_IP[31:16]?+?BOARD_IP[15:0]; ????????????UDP_LEN?<=?16'd0; ????????data_cnt?<=?16'd0; ????????end ????else ????????case?(state) ????????????5'd0?:?begin ????????????????????fifo_wr_en?<=?1'b0; ????????????????????fifo_data?<=?8'd0; ????????????????????fifo_data_valid?<=?1'b0; ????????????????????fifo_data_clr?<=?1'b0; ????????????????????state?<=?5'd1; ????????????????????i_en?<=?1'b0; ????????????????????i_init?<=?1'b0; ????????????????????rx_buf?<=?48'd0; ????????????????????rx_cnt?<=?10'd0; ????????????????????IP_HEAD_SUM?<=?PC_IP[31:16]?+?PC_IP[15:0]?+?BOARD_IP[31:16]?+?BOARD_IP[15:0]; ????????????????????UDP_LEN?<=?16'd0; ???????????????????end? ????????????5'd1?:?begin ?????????????????????if?(rx_en?&&?rx_er?==?1'b0)? ?????????????????????????begin ?????????????????????????????i_init?<=?1'b1; ?????????????????????????????state?<=?5'd2; ?????????????????????????????rx_buf?<=?{rx_buf[39:0],rx_data}; ?????????????????????????end ?????????????????????else ?????????????????????????state?<=?5'd1; ???????????????????end ????????????5'd2?:?begin ????????????????????i_init?<=?1'b0; ????????????????????data_cnt?<=?16'd0; ????????????????????rx_buf?<=?{rx_buf[39:0],rx_data}; ????????????????????if?(rx_buf?==?{{5{8'h55}},8'hd5}) ??????????????????????begin? ????????????????????????state?<=?5'd3; ????????????????????????i_en?<=?1'd1; ??????????????????????end ????????????????????else ????????????????????????state?<=?5'd2; ???????????????????end ????????????5'd3?:?begin ????????????????????i_en?<=?1'b1; ????????????????????rx_buf?<=?{rx_buf[39:0],rx_data}; ????????????????????if(rx_cnt?10'd5) ????????????????????????rx_cnt?<=?rx_cnt?+?1; ????????????????????else ????????????????????????begin ????????????????????????????rx_cnt?<=?10'd0; ????????????????????????????if(rx_buf?==?BOARD_MAC) ????????????????????????????????state?<=?5'd4; ????????????????????????????else ????????????????????????????????state?<=?5'd20;? ????????????????????????end??? ????????????????????end ????????????5'd4??:?begin ?????????????????????i_en?<=?1'b1; ?????????????????????rx_buf?<=?{rx_buf[39:0],rx_data}; ?????????????????????if(rx_cnt?10'd5) ???????????????????????begin ?????????????????????????rx_cnt?<=?rx_cnt?+?1'b1; ???????????????????????end ?????????????????????else ???????????????????????begin ?????????????????????????rx_cnt?<=?10'd0; ?????????????????????????if(rx_buf?==?PC_MAC) ???????????????????????????state?<=?5'd5; ?????????????????????????else?? ???????????????????????????state?<=?5'd18; ???????????????????????end ????????????????????end ????????????5'd5??:?begin ??????????????????????i_en?<=?1'b1; ??????????????????????rx_buf?<=?{rx_buf[39:0],rx_data}; ??????????????????????if(rx_cnt?10'd5) ????????????????????????begin ??????????????????????????rx_cnt?<=?rx_cnt?+?1'b1; ????????????????????????end ??????????????????????else ????????????????????????begin ??????????????????????????rx_cnt?<=?10'd0; ??????????????????????????IP_HEAD_SUM?<=?IP_HEAD_SUM?+?rx_buf[31:16]?+?rx_buf[15:0]; ??????????????????????????if(rx_buf[47:24]?==?{16'h0800,8'h45}) ????????????????????????????state?<=?5'd6; ??????????????????????????else?? ????????????????????????????state?<=?5'd18; ????????????????????????end ????????????????????end ????????????5'd6??:?begin ??????????????????????i_en?<=?1'b1; ??????????????????????rx_buf?<=?{rx_buf[39:0],rx_data}; ??????????????????????if(rx_cnt?10'd3) ????????????????????????begin ??????????????????????????rx_cnt?<=?rx_cnt?+?1'b1; ????????????????????????end ??????????????????????else ????????????????????????begin ??????????????????????????rx_cnt?<=?10'd0; ??????????????????????????state?<=?5'd7; ??????????????????????????IP_HEAD_SUM?<=?IP_HEAD_SUM?+?rx_buf[31:16]?+?rx_buf[15:0]; ????????????????????????end ????????????????????end ????????????5'd7??:?begin ??????????????????????i_en?<=?1'b1; ??????????????????????rx_buf?<=?{rx_buf[39:0],rx_data}; ??????????????????????if(rx_cnt?10'd3) ????????????????????????begin ??????????????????????????rx_cnt?<=?rx_cnt?+?1'b1; ????????????????????????end ??????????????????????else ????????????????????????begin ??????????????????????????rx_cnt?<=?10'd0; ??????????????????????????IP_HEAD_SUM?<=?IP_HEAD_SUM?+?rx_buf[31:16]?+?rx_buf[15:0]; ??????????????????????????if(rx_buf[23:16]?==?8'd17) ????????????????????????????state?<=?5'd8; ??????????????????????????else?? ????????????????????????????state?<=?5'd18; ????????????????????????end ????????????????????end ????????????5'd8??:?begin ??????????????????????i_en?<=?1'b1; ??????????????????????rx_buf?<=?{rx_buf[39:0],rx_data}; ??????????????????????if(rx_cnt?10'd3) ????????????????????????begin ??????????????????????????rx_cnt?<=?rx_cnt?+?1'b1; ????????????????????????end ??????????????????????else ????????????????????????begin ??????????????????????????rx_cnt?<=?10'd0; ??????????????????????????if(rx_buf[31:0]?==?PC_IP) ????????????????????????????state?<=?5'd9; ??????????????????????????else?? ????????????????????????????state?<=?5'd18; ????????????????????????end ????????????????????end ????????????5'd9??:?begin ??????????????????????i_en?<=?1'b1; ??????????????????????rx_buf?<=?{rx_buf[39:0],rx_data}; ??????????????????????if(rx_cnt?10'd3) ????????????????????????begin ??????????????????????????rx_cnt?<=?rx_cnt?+?1'b1; ????????????????????????end ??????????????????????else ????????????????????????begin ??????????????????????????rx_cnt?<=?10'd0; ??????????????????????????IP_HEAD_SUM?<=?IP_HEAD_SUM?+?rx_buf[31:16]?+?rx_buf[15:0]; ??????????????????????????if(rx_buf[31:0]?==?BOARD_IP?&&?(IP_HEAD_SUM[31:16]?==?~IP_HEAD_SUM[15:0])) ????????????????????????????state?<=?5'd10; ??????????????????????????else?? ????????????????????????????state?<=?5'd18; ????????????????????????end ????????????????????end ????????????5'd10?:?begin ??????????????????????i_en?<=?1'b1; ??????????????????????rx_buf?<=?{rx_buf[39:0],rx_data}; ??????????????????????if(rx_cnt?10'd3) ????????????????????????begin ??????????????????????????rx_cnt?<=?rx_cnt?+?1'b1; ????????????????????????end ??????????????????????else ????????????????????????begin ??????????????????????????rx_cnt?<=?10'd0; ??????????????????????????if(rx_buf[31:0]?==?{PC_COM,BOARD_COM}) ????????????????????????????state?<=?5'd11; ??????????????????????????else?? ????????????????????????????state?<=?5'd18; ????????????????????????end ????????????????????end ????????????5'd11?:?begin ??????????????????????i_en?<=?1'b1; ??????????????????????rx_buf?<=?{rx_buf[39:0],rx_data}; ??????????????????????if(rx_cnt?10'd3) ????????????????????????begin ??????????????????????????rx_cnt?<=?rx_cnt?+?1'b1; ????????????????????????end ??????????????????????else ????????????????????????begin ??????????????????????????rx_cnt?<=?10'd0; ??????????????????????????state?<=?5'd12; ??????????????????????????UDP_LEN?<=?rx_buf[31:16]; ??????????????????data_cnt?<=?rx_buf[31:16]?-?16'd9; ????????????????????????end ????????????????????end ????????????5'd12?:?begin ??????????????????????if(rx_cnt?
其實現(xiàn)原理就是發(fā)送模塊的逆過程。
三 、 總結
以太網(wǎng)實現(xiàn)過程基于UDP,代碼思路根據(jù)每一層順序寫下來即可完成,其中需要注意的是MAC的地址需要提前準備好,因為沒有寫ARP協(xié)議,不可通過代碼來獲取MAC地址。端口號也需要提前準備好。在接收模塊中需要考慮CRC獲取數(shù)據(jù)的時機,不可提前也不可推遲。
審核編輯:劉清
-
FPGA
+關注
關注
1625文章
21624瀏覽量
601245 -
HDMI
+關注
關注
32文章
1643瀏覽量
151556 -
以太網(wǎng)
+關注
關注
40文章
5343瀏覽量
170804 -
VGA
+關注
關注
5文章
529瀏覽量
62768 -
RCA
+關注
關注
0文章
28瀏覽量
8767
原文標題:就業(yè)班學員學習筆記分享:FPGA之HDMI、以太網(wǎng)篇
文章出處:【微信號:HXSLH1010101010,微信公眾號:FPGA技術江湖】歡迎添加關注!文章轉載請注明出處。
發(fā)布評論請先 登錄
相關推薦
評論