1. 程式人生 > 其它 >乙太網幀的最小長度_關於乙太網切包

乙太網幀的最小長度_關於乙太網切包

技術標籤:乙太網幀的最小長度

乙太網切包

/* 為什麼要切包
一個傳輸的乙太網幀長度最小為64個位元組,最長為1518個位元組:[ 6位元組目的Mac地址 + 6位元組源Mac地址 + 2位元組的type型別 + 46-1500個位元組的資料 + 4位元組的FCS ] 如果傳輸的乙太網幀太長,傳輸過程中,若發生一個錯誤,就要重傳幀,其他終端將一直等待,效率很低。因此把幀的長度控制在46~1500位元組之間。*/
/* 本工程的要求是要求報文範圍是1~9600位元組,報文與報文之間的間隔至少要在46位元組以上,設計乙太網切包模組。
如果輸入的報文長度小於46位元組,那麼就要在後面進行補0操作,輸出46位元組的報文;
如果輸入的報文長度大於46且小於1500位元組,不進行操作,直接輸出報文;
如果輸入的報文長度大於1500位元組,那麼就要對報文進行切包操作,切包之後的資料若小於46則進行補0,輸出報文;*/
module eth_packet(
    input clk,
    input rst_n,
    input [7:0] din,
    input din_vld,
    input din_sop, // 報文頭
    input din_eop, // 報文尾
    output reg[7:0] dout,
    output reg dout_vld,
    output reg dout_sop,
    output reg dout_eop    

);

wire add_cnt_wr,end_cnt_wr;
wire add_cnt_zero,end_cnt_zero;
wire fir_cnt_wr;
wire data_fifo_q_eoc; 
wire data_fifo_rdreq;
wire [7:0]data_fifo_q;
wire [10:0]len_fifo_q;
wire len_fifo_empty;
wire [11:0]data_fifo_data;
wire data_fifo_wrreq;
wire data_fifo_empty;
wire [10:0]len_fifo_data;
wire len_fifo_rdreq;
wire len_fifo_wrreq;
wire start_cnt_zero;
wire data_fifo_full;
wire len_fifo_full;

reg [10:0]cnt_wr;
reg [5:0]cnt_zero;
reg flag_zero;
reg flag;

always @(posedge clk or negedge rst_n)begin 
    if(~rst_n)
        cnt_wr <= 0;
    else if (add_cnt_wr) 
         if (end_cnt_wr)
         cnt_wr <= 0;
        else cnt_wr <= cnt_wr + 1'b1;
end

assign add_cnt_wr =din_vld;
assign end_cnt_wr =add_cnt_wr && ((cnt_wr==1500-1) || din_eop);

assign fir_cnt_wr = add_cnt_wr && cnt_wr==0;  //輸出報文的第一個位元組;
assign data_fifo_q_eoc = data_fifo_rdreq && data_fifo_q[0]; // 輸出報文的最後一個位元組,即處理完一個完整的報文;

always @(posedge clk or negedge rst_n)begin 
    if(~rst_n)
        cnt_zero <= 0;
    else if (add_cnt_zero) 
         if (end_cnt_zero)
         cnt_zero <= 0;
        else cnt_zero <= cnt_zero + 1'b1;
end

assign add_cnt_zero =flag_zero;
assign end_cnt_zero =add_cnt_zero && (46-len_fifo_q-1);

always @(posedge clk or negedge rst_n)begin 
    if(~rst_n)
         flag <= 0;
    else if (flag==0 && flag_zero ==0 && len_fifo_empty ==0) 
         flag <= 1;
    else if(data_fifo_q_eoc)
         flag <= 0;
end

always @(posedge clk or negedge rst_n)begin 
    if(~rst_n)
         flag_zero <= 0;
    else if (start_cnt_zero) 
         flag_zero <= 1;
    else if(end_cnt_zero)
         flag_zero <= 0;
end

assign start_cnt_zero = data_fifo_q_eoc && len_fifo_q <11'd46 ;

always @(posedge clk or negedge rst_n)begin 
    if(~rst_n)
         dout <= 0;
    else if (data_fifo_rdreq) 
         dout <=data_fifo_data[11:4];
    else 
         dout <= 0;
end

always @(posedge clk or negedge rst_n)begin 
    if(~rst_n)
         dout_vld <= 0;
    else if (data_fifo_rdreq) 
         dout_vld <= 1;
    else 
         dout_vld <= 0;
end

always @(posedge clk or negedge rst_n)begin 
    if(~rst_n)
         dout_sop <= 0;
    else if (fir_cnt_wr) 
         dout_sop <= 1;
    else 
         dout_sop <= 0;
end

always @(posedge clk or negedge rst_n)begin 
    if(~rst_n)
         dout_eop <= 0;
    else if ( (data_fifo_q_eoc && start_cnt_zero ==1'b0) || end_cnt_zero ) 
         dout_eop <= 1;
    else 
         dout_eop <= 0;
end

// 同步資料fifo
fifo_generator_0 data_fifo_12b (
  .clk(clk),      // input wire clk
  .srst(rst_n),    // input wire srst
  .din(data_fifo_data),      // input wire [11 : 0] din
  .wr_en(data_fifo_wrreq),  // input wire wr_en
  .rd_en(data_fifo_rdreq),  // input wire rd_en
  .dout(data_fifo_q),    // output wire [11 : 0] dout
  .full(data_fifo_full),    // output wire full
  .empty(data_fifo_empty)  // output wire empty
);
assign data_fifo_wrreq = din_vld && ~data_fifo_full;
assign data_fifo_data = {din,din_sop,din_eop,fir_cnt_wr,end_cnt_wr};
assign data_fifo_rdreq = flag && data_fifo_empty==1'b0;

// 同步資訊fifo 
fifo_generator_1 len_fifo_11b (
  .clk(clk),      // input wire clk
  .srst(rst_n),    // input wire srst
  .din(len_fifo_data),      // input wire [10 : 0] din
  .wr_en(len_fifo_wrreq),  // input wire wr_en
  .rd_en(len_fifo_rdreq),  // input wire rd_en
  .dout(dout),    // output wire [10 : 0] dout
  .full(len_fifo_full),    // output wire full
  .empty(len_fifo_empty)  // output wire empty
);
assign len_fifo_data = cnt_wr + 1;
assign len_fifo_rdreq = (data_fifo_q_eoc && start_cnt_zero ==1'b0) || end_cnt_zero ; // 處理傳輸完一個完整的報文且不需要補0 || 補0結束; 
assign len_fifo_wrreq = end_cnt_wr && ~len_fifo_full;

endmodule