一、在数据FIFO前加数据个数包文
此处是输入一个完整包文后才输出
如何在FIFO的前面加上表示其个数的包文,使用计数器计数,将其值存储到信息FIFO中。在发送的时候,先发送数据个数的包文,之后再发送数据FIFO,那么怎么选择发送的是数据还是计数的数据。
此时就需要有一个状态信号,标识是发送数据还是发送计数的数据。
//计数器
always @(posedge clk or negedge rst_n)begin
if(rst_n==0)begin
cnt <= 0;
end
else if(add_cnt)begin
if(end_cnt)begin
cnt <= 0;
end
else begin
cnt <= cnt + 1'b1;
end
end
end
assign add_cnt = din_vld ;
assign end_cnt = add_cnt && din_eop;
//数据FIFO的写数据和写使能
assign wr_en = din_vld;
assign wdata = {din_sop,din_eop,din};
//信息FIFO的写数据和写使能
assign msg_wr_en = end_cnt ;
assign msg_wdata = cnt + 1 ;
//需要一个信号来选择到底是发送状态还是非发送状态
//flag == 1,表示发送的是数据
//flag == 0,表示发送的是长度
assign flag_start = flag == 0 && msg_empty == 0; //发送的是长度
always @(posedge clk or negedge rst_n)begin
if(rst_n==0)begin
flag <= 0;
end
else if(flag_start)begin
flag <= 1;
end
else if(flag == 1 && dout_eop_tmp)begin
flag <= 0;
end
end
assign dout_eop_tmp = rd_en && q[8];
//数据FIFO的读使能
assign rd_en = flag && msg_empty == 0 ;
//数据FIFO的读使能
assign msg_rd_en = dout_eop_tmp ;//输出一个完整的包文后清空总线上的数据,总线上出现下一个长度数据等待被读
//dout
always @(posedge clk or negedge rst_n)begin
if(rst_n==0)begin
dout <= 0;
end
else if(flag_start)begin
dout <= msg_q[7:0];
end
else begin
dout <= q[7:0];
end
end
//dout_sop
always @(posedge clk or negedge rst_n)begin
if(rst_n==0)begin
dout_sop <= 0;
end
else begin
dout_sop <= flag_start; //注意,此刻的SOP信号是第一个输出,即在数据长度位需要打上SOP
end
end
//dout_eop
always @(posedge clk or negedge rst_n)begin
if(rst_n==0)begin
dout_eop <= 0;
end
else begin
dout_eop <= rd_en && q[8];
end
end
//dout_vld
always @(posedge clk or negedge rst_n)begin
if(rst_n==0)begin
dout_vld <= 0;
end
else begin
dout_vld <= rd_en || flag_start;
end
end
二、加上数据长度和校验和
发送顺序 : 数据长度,校验和,数据。
首先,数据长度和【一】中的实现方法一样,在此不再重复。而校验和需要设计,校验和的校验规则如下:
- 数据依次相加,将得到的值记为a;
- 若两数相加产生进位,则将a的进位加到a的低16位得到和b;
- 将b重复上述步骤,直到算出最后的结果
- 对结果取取反便是最终的校验和
//需要注意的问题
//1. SOP时的值要清0,即赋值给它最初的和
//2. 第17位和第15位有没有相加
//3.写入信息FIFO的有没有相加
always @ (*)begin
if(din_vld)begin
if(din_sop)begin
sum_tmp_a = din;
end
else begin
sum_tmp_a = sum + din;
end
end
else begin
sum_tmp_a = sum;
end
end
assign sum_tmp_b = sum_tmp_a[16] + sum_tmp_a[15:0];
always @(posedge clk or negedge rst_n)begin
if(rst_n==0)begin
sum <= 0;
end
else begin
sum <= sum_tmp_b;
end
end
//写数据与写使能与【一】相同,此处不相同
//信息FIFO的写使能和写数据
assign msg_wr_en = end_cnt ;
assign msg_wdata = {cnt , ~sum_tmp_c};
指示信号也与【一】中差不多
//flag == 1,表示发送数据,flag==0 表示发送的是长度和校验和
always @(posedge clk or negedge rst_n)begin
if(rst_n==0)begin
flag <= 0;
end
else if(end_cnt1)begin
flag <= 1;
end
else if(flag==1 && dout_eop_tmp)begin
flag <= 0;
end
end
assign dout_eop_tmp = rd_en && q[16];
always @(posedge clk or negedge rst_n)begin
if(rst_n==0)begin
cnt1 <= 0;
end
else if(add_cnt1)begin
if(end_cnt1)begin
cnt1 <= 0;
end
else
cnt1 <= cnt1 + 1'b1;
end
end
assign add_cnt1 = msg_empty == 0 && empty == 0 && flag == 0;
assign end_cnt1 = add_cnt1 && cnt1 == 2 - 1;
//数据FIFO读使能
assign rd_en = flag && empty == 0;
//信息FIFO读使能
assign msg_rd_en = dout_eop_tmp;
输出数据和指示信号等
//dout
always @(posedge clk or negedge rst_n)begin
if(rst_n==0)begin
dout <= 0;
end
else if(add_cnt1)begin
dout <= msg_q[31 - 16*cnt1 -:16];
end
else begin
dout <= q[15:0];
end
end
//dout_sop
//注意,该SOP信号应该出现在第一个发送的数上,即数据长度
always @(posedge clk or negedge rst_n)begin
if(rst_n==0)begin
dout_vld <= 0;
end
else begin
dout_vld <= add_cnt1 && cnt1 == 1-1;
end
end
//其他信号设计与上面基本一致