一、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,從本質(zhì)上來說仍然是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
+關注
關注
1650文章
22217瀏覽量
627896 -
HDMI
+關注
關注
34文章
1856瀏覽量
158127 -
以太網(wǎng)
+關注
關注
41文章
5872瀏覽量
178929 -
VGA
+關注
關注
5文章
572瀏覽量
65587 -
RCA
+關注
關注
0文章
44瀏覽量
9179
原文標題:就業(yè)班學員學習筆記分享:FPGA之HDMI、以太網(wǎng)篇
文章出處:【微信號:HXSLH1010101010,微信公眾號:FPGA技術江湖】歡迎添加關注!文章轉載請注明出處。
發(fā)布評論請先 登錄
基于Xilinx FPGA的千兆以太網(wǎng)控制器的開發(fā)
簡談基于FPGA的千兆以太網(wǎng)
基于FPGA的以太網(wǎng)ARP通信測試(二)
#電子技術 #FPGA 千兆網(wǎng)以太網(wǎng)工程(項目開發(fā)能力)
基于FPGA的萬兆以太網(wǎng)接口的設計與實現(xiàn)
就業(yè)班學員學習筆記分享:FPGA之HDMI、以太網(wǎng)篇
基于FPGA的萬兆以太網(wǎng)接口設計
一種基于FPGA的以太網(wǎng)高速傳輸平臺
在工業(yè)以太網(wǎng)領域采用FPGA的好處
詳解FPGA的10G以太網(wǎng)接口調(diào)試
FPGA如何為以太網(wǎng)和千兆以太網(wǎng)解決低功耗問題
STM32以太網(wǎng)培訓資料之以太網(wǎng)外設
基于FPGA的以太網(wǎng)中繼器設計

FPGA之HDMI與以太網(wǎng)篇分享
評論