以太网切包:
/*为什么要切包?
一个传输的以太网帧长度最小为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