加入星計劃,您可以享受以下權(quán)益:

  • 創(chuàng)作內(nèi)容快速變現(xiàn)
  • 行業(yè)影響力擴散
  • 作品版權(quán)保護
  • 300W+ 專業(yè)用戶
  • 1.5W+ 優(yōu)質(zhì)創(chuàng)作者
  • 5000+ 長期合作伙伴
立即加入
  • 正文
    • 一、HDMI
    • 二、以太網(wǎng)
    • 三 、 總結(jié)
  • 推薦器件
  • 相關(guān)推薦
  • 電子產(chǎn)業(yè)圖譜
申請入駐 產(chǎn)業(yè)圖譜

就業(yè)班學員學習筆記分享:FPGA之HDMI、以太網(wǎng)篇

01/15 11:50
1654
加入交流群
掃碼加入
獲取工程師必備禮包
參與熱點資訊討論

一、HDMI

1.1 、HDMI介紹

高清多媒體接口(High Definition Multimedia Interface)是一種全數(shù)字化視頻和聲音發(fā)送接口,可以發(fā)送未壓縮的音頻及視頻信號。HDMI可用于機頂盒、DVD播放機、個人計算機、電視、游戲主機、綜合擴大機、數(shù)字音響與電視機等設(shè)備。HDMI可以同時發(fā)送音頻和視頻信號,由于音頻和視頻信號采用同一條線材,大大簡化系統(tǒng)線路的安裝難度。

HDMI是被設(shè)計來取代較舊的模擬信號影音發(fā)送接口如SCART或RCA等端子的。它支持各類電視與計算機視頻格式,包括SDTV、HDTV視頻畫面,再加上多聲道數(shù)字音頻。HDMI與去掉音頻傳輸功能的UDI都繼承DVI的核心技術(shù)“傳輸最小化差分信號”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接口,如圖:

右側(cè)是最常見的A型HDMI接口,其引腳定義如下圖:

圖1.2.2 HDMI接口引腳圖

DVI和HDMI接口協(xié)議在物理層使用TMDS標準傳輸音視頻數(shù)據(jù)。

1.1.2 、TMDS介紹

TMDS(Transition Minimized Differential Signaling,最小化傳輸差分信號)是美國Silicon Image公司開發(fā)的一項高速數(shù)據(jù)傳輸技術(shù),在DVI和HDMI視頻接口中使用差分信號傳輸高速串行數(shù)據(jù)。TMDS差分傳輸技術(shù)使用兩個引腳(如圖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通道,但是它同樣可以選擇傳輸像素點的亮度和色素信息(YCrCb4:4:4或YCrCb4:2:2格式)。第四個通道是時鐘通道,用于傳輸像素時鐘。獨立的TMDS時鐘通道為接收端提供接收的參考頻率,保證數(shù)據(jù)在接收端能夠正確恢復。

圖1.3.1 、TMDS連接示意圖

如果每個像素點的顏色深度為24位,即RGB每個顏色分量各占8位,那么每個通道上的顏色數(shù)據(jù)將通過一個8B/10B的編碼器(Encoder)來轉(zhuǎn)換成一個10位的像素字符。然后這個10位的字符通過并串轉(zhuǎn)換器(Serializer)轉(zhuǎn)換成串行數(shù)據(jù),最后由TMDS數(shù)據(jù)通道發(fā)送出去。這個10:1的并轉(zhuǎn)串過程所生成的串行數(shù)據(jù)速率是實際像素時鐘速率的10倍。

在傳輸視頻圖像的過程中,數(shù)據(jù)通道上傳輸?shù)氖蔷幋a后的有效像素字符。而在每一幀圖像的行與行之間,以及視頻中不同幀之間的時間間隔(消隱期)內(nèi),數(shù)據(jù)通道上傳輸?shù)膭t是控制字符。每個通道上有兩位控制信號的輸入接口,共對應(yīng)四種不同的控制字符。這些控制字符提供了視頻的行同步(HZYNC)以及幀同步(VSYNC)信息,也可以用來指定所傳輸數(shù)據(jù)的邊界(用于同步)。

對于DVI傳輸,整個視頻的消隱期都用來傳輸控制字符。而HDMI傳輸?shù)南[期除了控制字符之外,還可以用于傳輸音頻或者其他附加數(shù)據(jù),比如字幕信息等。這就是DVI和HDMI協(xié)議之間最主要的差別。從圖1.3.1中也可以看出這一差別,即“Auxiliary Data”接口標有“HDMI Olny”,即它是HDMI所獨有的接口。

從前面的介紹中我們可以看出,TMDS連接從邏輯功能上可以劃分成兩個階段:編碼和并串轉(zhuǎn)換。在編碼階段,編碼器將視頻源中的像素數(shù)據(jù)、HDMI的音頻/附加數(shù)據(jù),以及行同步和場同步信號分別編碼成10位的字符流。然后在并串轉(zhuǎn)換階段將上述的字符流轉(zhuǎn)換成串行數(shù)據(jù)流,并將其從三個差分輸出通道發(fā)送出去。

DVI編碼器在視頻有效數(shù)據(jù)段輸出像素數(shù)據(jù),在消隱期輸出控制數(shù)據(jù),如圖1.3.2所示。其中VDE(Video Data Enable)為高電平時表示視頻數(shù)據(jù)有效,為低電平代表當前處于視頻消隱期。

圖1.3.2 DVI編碼輸出示意圖

圖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ù)都將被轉(zhuǎn)換成460個特定10-bit字符中的一個。這個編碼機制大致上實現(xiàn)了傳輸過程中的直流平衡,即一段時間內(nèi)傳輸?shù)母唠娖剑〝?shù)字“1”)的個數(shù)大致等于低電平(數(shù)字“0”)的個數(shù)。同時,每個編碼后的10-bit字符中狀態(tài)跳轉(zhuǎn)(“由1到0”或者“由0到1”)的次數(shù)將被限制在五次以內(nèi)。

除了視頻數(shù)據(jù)之外,每個通道2-bit控制信號的狀態(tài)也要進行編碼,編碼后分別對應(yīng)四個不同的10-bit控制字符,分別是10'b1101010100,10'b0010101011,10'b0101010100,和10'b1010101011。可以看出,每個控制字符都有七次以上的狀態(tài)跳轉(zhuǎn)。視頻字符和控制字符狀態(tài)跳轉(zhuǎn)次數(shù)的不同將會被用于發(fā)送和接收設(shè)備的同步。

HDMI協(xié)議與DVI協(xié)議在很多方面都是相同的,包括物理連接(TMDS)、有效視頻編碼算法以及控制字符的定義等。但是相比于DVI,HDMI在視頻的消隱期會傳輸更多的數(shù)據(jù),包括音頻數(shù)據(jù)和附加數(shù)據(jù)。4-bit音頻和附加數(shù)據(jù)將通過TERC4編碼機制轉(zhuǎn)換成10-bit TERC4字符,然后在綠色和紅色通道上傳輸。

HDMI在輸入附加數(shù)據(jù)的同時,還需要輸入ADE(Aux/Audio Data Enable)信號,其作用和VDE是類似的:當ADE為高電平時,表明輸入端的附加數(shù)據(jù)或者音頻數(shù)據(jù)有效。如果大家想了解更多有關(guān)HDMI的細節(jié),可以參考開發(fā)板資料(A盤)/8_FPGA參考資料/HDMI/《HDMI Specification 13a》。為了簡單起見,我們在這里把HDMI接口當作DVI接口進行驅(qū)動。

在編碼之后,3個通道的10-bit字符將進行并串轉(zhuǎn)換,這一過程是使用7系列FPGA中專用的硬件資源來實現(xiàn)的。7系列的FPGA提供了專用的并串轉(zhuǎn)換器——OSERDESE2。單一的OSERDESE2模塊可以實現(xiàn)8:1的并串轉(zhuǎn)換,通過位寬擴展可以實現(xiàn)10:1和14:1的轉(zhuǎn)換率。

1.2 HDMI設(shè)計思路

對于HDMI,和之前VGA項目差不多,可以通過修改VGA的驅(qū)動代碼,來實現(xiàn)HDMI的驅(qū)動,修改其中的分辨率和時鐘,即可完成。

對于HDMI來說,需要將信號轉(zhuǎn)為差分對,再將并轉(zhuǎn)為串。

1.3 代碼

module?hdmi_driver(

??input???wire??????????????clk,
??input???wire??????????????rst_n,
??output??wire??????????????VSYNC,
??output??wire??????????????HSYNC,
??output??wire????[23:0]????RGB,
??output??wire??????????????en_display
);

??parameter?H_A?=??40;
??parameter?H_B?=?220;
??parameter?H_C?=?1280;
??parameter?H_D?=?110;
??parameter?H_E?=?1650;
??
??parameter?V_A?=???5;
??parameter?V_B?=??20;
??parameter?V_C?=?720;
??parameter?V_D?=???5;
??parameter?V_E?=?750;
??
??reg?????[10:0]??????cnt_h;
??reg?????[9:0]???????cnt_v;
??wire????????????????en_h;?????//顯示列的C段有效標志信??
??wire????????????????en_v;?????//顯示行的C段有效標志信??

??wire????????????????addr_en_h;
??wire????????????????addr_en;
??
??
??always?@?(posedge?clk,?negedge?rst_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)???1'b0?:?1'b1;
??assign?VSYNC?=?(cnt_v?<?V_A)???1'b0?:?1'b1;
?
??assign?en_h?=?(cnt_h?>=?H_A?+?H_B?&&?cnt_h?<?H_A?+?H_B?+?H_C)???1'b1?:?1'b0;
??assign?en_v?=?(cnt_v?>=?V_A?+?V_B?&&?cnt_v?<?V_A?+?V_B?+?V_C)???1'b1?:?1'b0;
??
//??assign?en_h?=?(cnt_h?>=?566?&&?cnt_h?<?666)???1'b1?:?1'b0;
//??assign?en_v?=?(cnt_v?>=?277?&&?cnt_v?<?377)???1'b1?:?1'b0;
??
//??assign?addr_en_h?=?(cnt_h?>=?565?&&?cnt_h?<?665)???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頂層模塊

module?top(

input???????????????????????clk,
input???????????????????????rst_n,

output??????????????????????D0_P,
output??????????????????????D0_N,
output??????????????????????D1_P,
output??????????????????????D1_N,
output??????????????????????D2_P,
output??????????????????????D2_N,
output??????????????????????D3_P,
output??????????????????????D3_N
????);
????wire????????????VSYNC;
????wire????????????HSYNC;
????wire????[23:0]??RGB;
????wire????????????en_display;
????wire????????????clk_1;
????wire????????????clk_5;
????wire????????????locked;
????wire????????????R_b;
????wire????????????G_b;
????wire????????????B_b;
????wire????????????clk_b;
????wire?????[9:0]???????G,B,R;
????
??pll?instance_name
???(
????//?Clock?out?ports
????.clk_out1(clk_1),?????//?output?clk_out1
????.clk_out2(clk_5),?????//?output?clk_out2
????//?Status?and?control?signals
????.reset(~rst_n),?//?input?reset
????.locked(locked),???????//?output?locked
???//?Clock?in?ports
????.clk_in1(clk));??????//?input?clk_in1???
????
????

vga_driver?vga_driver_inst(

??.clk??????????????(clk_1),
??.rst_n????????????(locked),
??
??.VSYNC????????????(VSYNC),
??.HSYNC????????????(HSYNC),
??.RGB??????????????(RGB),
??.en_display???????(en_display)
);

dvi_encoder?dvi_encoder_inst0(
??.clkin????????????(clk_1),????//?pixel?clock?input
??.rstin????????????(~locked),????//?async.?reset?input?(active?high)
??.din??????????????(RGB[23:16]),??????//?data?inputs:?expect?registered
??.c0???????????????(1'b0),???????//?c0?input
??.c1???????????????(1'b0),???????//?c1?input
??.de???????????????(en_display),???????//?de?input
??.dout?????????????(R)??????//?data?outputs
);?

serializer_10_to_1?serializer_10_to_1_inst0(
????.reset??????????????(~locked),??????????????//?
????.paralell_clk???????(clk_1),???????//?
????.serial_clk_5x??????(clk_5),??????//?
????.paralell_data??????(R),??????//?
????.serial_data_out????(R_b)?????//?
????);
???OBUFDS?OBUFDS_inst0?(
??????.O(D2_P),???//?1-bit?output:?Diff_p?output?(connect?directly?to?top-level?port)
??????.OB(D2_N),?//?1-bit?output:?Diff_n?output?(connect?directly?to?top-level?port)
??????.I(R_b)????//?1-bit?input:?Buffer?input
???);

dvi_encoder?dvi_encoder_inst1(
??.clkin????????????(clk_1),????//?pixel?clock?input
??.rstin????????????(~locked),????//?async.?reset?input?(active?high)
??.din??????????????(RGB[15:8]),??????//?data?inputs:?expect?registered
??.c0???????????????(1'b0),???????//?c0?input
??.c1???????????????(1'b0),???????//?c1?input
??.de???????????????(en_display),???????//?de?input
??.dout?????????????(G)??????//?data?outputs
);?

serializer_10_to_1?serializer_10_to_1_inst1(
????.reset??????????????(~locked),??????????????//?
????.paralell_clk???????(clk_1),???????//?
????.serial_clk_5x??????(clk_5),??????//?
????.paralell_data??????(G),??????//?

????.serial_data_out????(G_b)?????//?
????);
???OBUFDS?OBUFDS_inst1?(
??????.O(D1_P),???//?1-bit?output:?Diff_p?output?(connect?directly?to?top-level?port)
??????.OB(D1_N),?//?1-bit?output:?Diff_n?output?(connect?directly?to?top-level?port)
??????.I(G_b)????//?1-bit?input:?Buffer?input
???);
???
???
???dvi_encoder?dvi_encoder_inst2(
??.clkin????????????(clk_1),????//?pixel?clock?input
??.rstin????????????(~locked),????//?async.?reset?input?(active?high)
??.din??????????????(RGB[7:0]),??????//?data?inputs:?expect?registered
??.c0???????????????(HSYNC),???????//?c0?input
??.c1???????????????(VSYNC),???????//?c1?input
??.de???????????????(en_display),???????//?de?input
??.dout?????????????(B)??????//?data?outputs
);?

serializer_10_to_1?serializer_10_to_1_inst2(
????.reset??????????????(~locked),????????
????.paralell_clk???????(clk_1),???????//?
????.serial_clk_5x??????(clk_5),??????//
????.paralell_data??????(B),??????//?

????.serial_data_out????(B_b)?????//?
????);
???OBUFDS?OBUFDS_inst2?(
??????.O(D0_P),???//
??????.OB(D0_N),?//?
??????.I(B_b)????//?
???);
serializer_10_to_1?serializer_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)?????//?
????);
OBUFDS?OBUFDS_inst3?(
??????.O(D3_P),???//?1-bit?output:?Diff_p?output?(connect?directly?to?top-level?port)
??????.OB(D3_N),?//?1-bit?output:?Diff_n?output?(connect?directly?to?top-level?port)
??????.I(clk_b)????//?1-bit?input:?Buffer?input
???);
endmodule

對于其他模塊,都是進行調(diào)用,并沒有自己編寫,即不再簡述。

二、以太網(wǎng)

2.1 、UDP數(shù)據(jù)包介紹

2.2 、MAC協(xié)議

2.3 、IP協(xié)議

2.4 、UDP協(xié)議

2.5 、代碼

以下代碼即為UDP發(fā)送模塊。

module?eth_tx?(
????
????input????wire???????????????????clk,
????input????wire???????????????????rst_n,
????input????wire???????????????????key,

????output???reg????????????????????gmii_tx_en,
????output???wire???????????????????gmii_tx_er,
????output???wire???????????????????gmii_tx_clk,
????output???reg???????[7:0]????????gmii_tx_data

);
??//88-A4-C2-E5-D3-66????{8'h8c,8'h82,8'hb9,8'h95,8'h10,8'hcc};
??parameter???PC_MAC????=?{8'h88,8'ha4,8'hc2,8'he5,8'hd3,8'h66};
??parameter???BOARD_MAC?=?{8'h88,8'ha4,8'hc2,8'he5,8'hd3,8'h67};
??parameter???PC_IP?????=?{8'd192,8'd168,8'd0,8'd2};
??parameter???BOARD_IP??=?{8'd192,8'd168,8'd0,8'd3};
??parameter???PC_COM????=?16'd65533;
??parameter???BOARD_COM?=?16'd65531;

??

??wire????????????????clk_125m;
??wire????????????????locked;
??wire????????????????flag;
??wire????????????????neg_edge;
??reg?????????????????i_en;
??reg?????????????????i_init;
??wire??????[31:0]????crc;
??wire??????[31:0]????crc_new;
??reg???????[63:0]????send_buf;
??reg???????[?4:0]????state;
??reg???????[?9:0]????send_cnt;
??wire????????????????key_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;

??assign?gmii_tx_clk?=?clk_125m;
??assign?gmii_tx_er??=?1'b0;
??assign?DATA_LEN????=?16'd24;
??assign?UDP_LEN?????=?DATA_LEN?+?16'd8;
??assign?IP_HEAD_LEN?=?UDP_LEN?+?16'd20;
??assign?IP_HEAD1????=?{8'h45,8'd0,IP_HEAD_LEN};
??assign?IP_HEAD2????=?32'd0;
??assign?IP_HEAD3????=?{8'hff,8'd17,IP_HEAD_SUM};
??assign?IP_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];
??assign?IP_HEAD_SUM?=?~(IP_HEAD_SUM1[31:16]?+?IP_HEAD_SUM1[15:0]);

??my_pll??my_pll_inst?(
??.areset?(?~rst_n?),
??.inclk0?(?clk?),
??.c0?(?clk_125m?),
??.locked?(?locked?)
??);

??jitter?jitter_inst(
??
??.clk????????(clk_125m),
??.rst_n????????(locked),
??.key????????(key),
??
??.flag???????(flag)
??);

??neg_edge?neg_edge_inst(
??
??.clk????????(clk_125m),
??.rst_n????????(locked),
??.flag???????(flag),
??
??.neg_edge?????(neg_edge)??
??);

??CRC32_D8?CRC32_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?@(posedge?clk_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ā)送模塊代碼:

module?eth_rx(

????input??wire?????????????????rx_clk,
????input??wire?????????????????rst_n,
????input??wire?????????????????rx_er,
????input??wire?????????????????rx_en,
????input??wire?????[7:0]???????rx_data,

????output?reg??????????????????fifo_wr_en,
????output?reg??????????????????fifo_data_valid,
????output?reg??????????????????fifo_data_clr,
????output?reg??????[7:0]???????fifo_data,
????output?reg??????[15:0]??????data_cnt

);

??parameter???PC_MAC????=?{8'h88,8'ha4,8'hc2,8'he5,8'hd3,8'h66};
??parameter???BOARD_MAC?=?{8'h88,8'ha4,8'hc2,8'he5,8'hd3,8'h67};
??parameter???PC_IP?????=?{8'd192,8'd168,8'd0,8'd2};
??parameter???BOARD_IP??=?{8'd192,8'd168,8'd0,8'd3};
??parameter???PC_COM????=?16'd65533;
??parameter???BOARD_COM?=?16'd65531;

??reg???????[4:0]???????state;
??reg???????????????????i_en;
??reg???????????????????i_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_D8?CRC32_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?@(posedge?rx_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?<?UDP_LEN?-?16'd9)
????????????????????????begin
??????????????????????????rx_cnt?<=?rx_cnt?+?1'b1;
??????????????????????????fifo_wr_en?<=?1'b1;
??????????????????????????fifo_data?<=?rx_data;
????????????????????????end
??????????????????????else
????????????????????????begin
??????????????????????????fifo_wr_en?<=?1'b0;
??????????????????????????fifo_data?<=?rx_data;
??????????????????????????state?<=?5'd13;
????????????????????????end
????????????????????end
????????????5'd13?:?begin
??????????????????????state?<=?5'd14;
????????????????????end
????????????5'd14?:?begin
??????????????????????state?<=?5'd15;
????????????????????end
????????????5'd15?:?begin
??????????????????????state?<=?5'd16;
??????????????????????i_en?<=?1'd0;
????????????????????end
???????????
????????????5'd17?:?begin
??????????????????????if(crc?==?32'hc704dd7b)
????????????????????????begin
??????????????????????????fifo_data_valid?<=?1'b1;
??????????????????????????state?<=?5'd0;
????????????????????????end
??????????????????????else
????????????????????????begin
??????????????????????????fifo_data_clr?<=?1'b1;
??????????????????????????state?<=?5'd0;
????????????????????????end
????????????????????end
????????????5'd18?:?begin
??????????????????????if(rx_en?==?1'b0)
????????????????????????state?<=?5'd0;
??????????????????????else
????????????????????????state?<=?5'd18;
????????????????????end
??????????????default:?;
????????endcase
??end

endmodule?

其實現(xiàn)原理就是發(fā)送模塊的逆過程。

三 、 總結(jié)

以太網(wǎng)實現(xiàn)過程基于UDP,代碼思路根據(jù)每一層順序?qū)懴聛砑纯赏瓿?,其中需要注意的是MAC的地址需要提前準備好,因為沒有寫ARP協(xié)議,不可通過代碼來獲取MAC地址。端口號也需要提前準備好。在接收模塊中需要考慮CRC獲取數(shù)據(jù)的時機,不可提前也不可推遲。

未待完續(xù),持續(xù)更新,大家請多多關(guān)注。有需要的也可以報名參加叁芯智能科技FPGA工程師就業(yè)班,主打Xilinx,課程內(nèi)容豐富,系統(tǒng)性學習FPGA,高薪就業(yè),線上線下同步,近期新班04月15號開班,可以實地考察,免費試聽,常年開班,歡迎報名參加!

FPGA就業(yè)班,2023.04.15開班,系統(tǒng)性學習FPGA,高薪就業(yè),線上線下同步!

推薦器件

更多器件
器件型號 數(shù)量 器件廠商 器件描述 數(shù)據(jù)手冊 ECAD模型 風險等級 參考價格 更多信息
10M08SCE144I7G 1 Altera Corporation Field Programmable Gate Array, 8000-Cell, CMOS, PQFP144, 22 X 22 MM, 0.50 MM PITCH, ROHS COMPLIANT, PLASTIC, EQFP-144

ECAD模型

下載ECAD模型
$19.84 查看
XC7A35T-2FGG484I 1 AMD Xilinx Field Programmable Gate Array, 2600 CLBs, 1286MHz, 33280-Cell, CMOS, PBGA484, FBGA-484

ECAD模型

下載ECAD模型
$70.07 查看
EP4CE6F17C8N 1 Altera Corporation Field Programmable Gate Array, 392 CLBs, 472.5MHz, 6272-Cell, PBGA256, 17 X 17 MM, 1 MM PITCH, LEAD FREE, FBGA-256

ECAD模型

下載ECAD模型
$127.84 查看

相關(guān)推薦

電子產(chǎn)業(yè)圖譜

任何技術(shù)的學習就好比一個江湖,對于每一位俠客都需要不斷的歷練,從初入江湖的小白到歸隱山林的隱世高人,需要不斷的自我感悟自己修煉,讓我們一起仗劍闖FPGA乃至更大的江湖。