上传文件至 /

初步完成所有功能,但两个接收解析和接收转发未合并
This commit is contained in:
yangshenbo 2025-11-05 14:39:48 +08:00
commit 6287315eef
2 changed files with 690 additions and 0 deletions

357
UDP_data_process.v Normal file
View File

@ -0,0 +1,357 @@
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date: 2025/10/31 16:59:43
// Design Name:
// Module Name: UDP_data_process
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
`timescale 1ns / 1ps
module UDP_data_process (
input clk,
input reset,
input eth_linked,
output reg pulse_second,
// input data_fifo_rden,
// UDP接收FIFO接口
output reg udp_app_recv_fifo_rden,
input [7:0] udp_app_recv_fifo_rddata,
input [11:0] udp_app_recv_fifo_rdcnt,
input udp_app_recv_fifo_empty,
// UDP发送FIFO接口
input udp_app_send_fifo_rden,
output [7:0] udp_app_send_fifo_rddata,
output [11:0] udp_app_send_fifo_rdcnt,
output udp_app_send_fifo_empty,
// TOE寄存器接口
output reg TOE_reg_wren,
output reg TOE_reg_rden,
output reg [65:0] TOE_reg_din,
input TOE_reg_out_valid,
input [65:0] TOE_reg_dout,
// 通信板(CMU)状态信息接口
output CMU_Status_Info_ready,
input CMU_Status_Info_valid,
input CMU_Status_Info_last,
input [31:0] CMU_Status_Info_data,
// 调控板(XYZ)状态信息接口
output XYZ_Status_Info_ready,
input XYZ_Status_Info_valid,
input XYZ_Status_Info_last,
input [31:0] XYZ_Status_Info_data,
// 读出板(DAQ)状态信息接口
output DAQ_Status_Info_ready,
input DAQ_Status_Info_valid,
input DAQ_Status_Info_last,
input [31:0] DAQ_Status_Info_data
);
// wire udp_app_recv_fifo_rden_r;
wire udp_app_recv_fifo_ready;
wire udp_recv_data_tvalid;
wire [31:0]udp_recv_data;
// 协议头
parameter [15:0] HDR_DATA = 16'h4d44;
parameter [15:0] HDR_CTRL = 16'h4547;
parameter [15:0] HDR_TOE = 16'h494e;
// 4个状态空闲读Header读Length读Payload&Check
reg [1:0] parse_state;
localparam P_IDLE = 2'd0;
localparam P_DATA = 2'd1;
reg [2:0] deal_state;
reg deal_busy;
localparam D_IDLE = 3'd0;
localparam D_HEAD = 3'd1;
localparam D_TOE_1 = 3'd2;
localparam D_TOE_2 = 3'd3;
localparam D_EXE = 3'd4;
localparam D_CTRL =3'd5;
reg [3:0]TOE_SFP_ID;
reg TOE_RW_FLAG;
reg [31:0] TOE_ADDR;
reg [31:0] TOE_DATA;
reg [15:0] header_reg;
reg [15:0] length_reg;
reg [31:0] data_reg;
reg [31:0] crc32_calc;
reg [31:0] crc32_recv;
reg [15:0] payload_remain;
reg recv_udp_frame_last;
reg crc_match; // CRC校验匹配标记
wire crc_error;
wire [31:0]udp_recv_data_reorder;
reg cnt;
wire data_fifo_rst ;
reg data_fifo_wren;
reg [31:0] data_fifo_din;
reg data_fifo_rden;
wire [31:0] data_fifo_dout;
wire data_fifo_empty;
wire data_fifo_full;
reg state_report_en;
reg [27:0] second_timer = 'b0;
// ---------------------------
// 读取FIFO逻辑
// ---------------------------
always@(posedge clk)
if(reset)
udp_app_recv_fifo_rden <= 1'b0;
else if((~udp_app_recv_fifo_empty) && udp_app_recv_fifo_ready && (~deal_busy))
udp_app_recv_fifo_rden <= 1'b1;
else if(udp_app_recv_fifo_rdcnt == 12'b0)
udp_app_recv_fifo_rden <= 1'b0;
else
udp_app_recv_fifo_rden <= 1'b0;
//assign udp_app_recv_fifo_rden_r = udp_app_recv_fifo_rden && (~udp_app_recv_fifo_empty); // udp recv data does not delay, so the en needn't delay
axis_dwidth_converter_0 axis_dwidth_converter_udprx(
.aclk (clk), // input
.aresetn (~reset), // input
.s_axis_tvalid(udp_app_recv_fifo_rden), // input
.s_axis_tready(udp_app_recv_fifo_ready), // output
.s_axis_tdata (udp_app_recv_fifo_rddata), // input [7:0]
.m_axis_tvalid(udp_recv_data_tvalid), // output
.m_axis_tready(1'b1), // input
.m_axis_tdata (udp_recv_data) // output [63:0]
);
assign udp_recv_data_reorder = {udp_recv_data[7:0], udp_recv_data[15:8], udp_recv_data[23:16], udp_recv_data[31:24]};
assign crc_error = crc_match ^ recv_udp_frame_last;
always @(posedge clk or posedge reset) begin
if(reset)begin
cnt <=0;
parse_state <= 0;
crc32_recv<=0;
crc_match =1'b0;
payload_remain<=0;
recv_udp_frame_last <=0;
crc32_calc <= 32'hFFFFFFFF;
end
else begin
case (parse_state)
P_IDLE : begin
crc32_calc <= 32'hFFFFFFFF;
recv_udp_frame_last <=1'b0;
crc_match =1'b0;
if (udp_recv_data_tvalid) begin
payload_remain <= udp_recv_data_reorder[15:0];
data_fifo_din <=udp_recv_data_reorder;//存数据,跳到PDATA的时候就存成功了
data_fifo_wren <=1'b1;
parse_state <= P_DATA;
end
end
P_DATA : begin
data_fifo_wren <=1'b0;
if (udp_recv_data_tvalid) begin
if(payload_remain == 0) begin //判断余量为0的时候的tvalidcrc_rev数据就到了
parse_state <= P_IDLE;
crc32_recv <= udp_recv_data_reorder;
recv_udp_frame_last <=1'b1; //收到完整一帧
data_fifo_rden <= 1'b1;
if(crc32_calc == udp_recv_data_reorder)
crc_match =1'b1;
else
crc_match =1'b0;
end
else begin
data_reg <= udp_recv_data_reorder;
data_fifo_din <=udp_recv_data_reorder; //存数据,判断payload_remain == 0 payload就完整存进去了
data_fifo_wren <=1'b1;
crc32_calc <= calc_crc32(udp_recv_data_reorder,crc32_calc);
payload_remain <= payload_remain -4;
end
end
end
endcase
end
end
fifo_generator_0 data_cache_fifo (
.clk (clk), // 时钟
.srst (data_fifo_rst), // 同步复位
.din (data_fifo_din), // 写入数据
.wr_en (data_fifo_wren), // 写使能
.rd_en (data_fifo_rden), // 读使能
.dout (data_fifo_dout), // 读出数据
.full (data_fifo_full), // 满标志
.empty (data_fifo_empty) // 空标志
);
//处理状态机
always @(posedge clk or posedge reset) begin
if(reset)begin
data_fifo_rden <= 0;
deal_state <=0;
deal_busy <=0;
TOE_SFP_ID <=0;
TOE_RW_FLAG <=0;
TOE_ADDR <= 0;
TOE_DATA <= 0;
header_reg <=0;
TOE_reg_wren <= 0;
TOE_reg_rden <= 0;
TOE_reg_din <= 0;
state_report_en <= 0;
end
else begin
case(deal_state)
D_IDLE : begin
TOE_reg_wren <= 0;
TOE_reg_rden <= 0;
TOE_reg_din <= 0;
if(recv_udp_frame_last)begin //last拉高的同时 也把data_fifo_rden拉高了
deal_busy <= 1'b1;
data_fifo_rden <= 1; // 这个拉高其实没用如果这时候拉高下个时钟数据处来下下个时钟才能触发所以这个时钟数据就要出来
deal_state <= D_HEAD;
end
end
D_HEAD :begin //判断是头的类型执行对应操作
header_reg <= data_fifo_dout[31:16]; // Header高字节 data_fifo_dout出来的操作和被赋值的操作是同时进行的默认赋值前一个数
if( data_fifo_dout[31:16]== HDR_TOE )begin
deal_state<= D_TOE_1;
data_fifo_rden <= 1;
end
else if(data_fifo_dout[31:16] == HDR_CTRL)begin
deal_state <= D_CTRL;
data_fifo_rden <= 0; //如果现在拉低了
end
else
deal_state <= D_IDLE;
end
D_TOE_1 :begin
TOE_reg_wren <= 0;
TOE_reg_rden <= 0;
TOE_reg_din <= 0; //TOE控制清除
TOE_SFP_ID <= data_fifo_dout[23:20]; //TOE是64比特的数据此时获得的是高32bit
TOE_RW_FLAG <= data_fifo_dout[16] ;
TOE_ADDR <= data_fifo_dout[15:0] ; //虽然是32比特的寄存器但地址就是16位
deal_state <= D_TOE_2;
data_fifo_rden <= 1;
end
D_TOE_2 : begin
TOE_DATA <= data_fifo_dout;
deal_state <= D_EXE;
data_fifo_rden <= 0;
end
D_EXE : begin
if(header_reg == HDR_TOE)begin
//开始TOE命令处理
if(TOE_RW_FLAG) TOE_reg_rden <= 1'b1;
else TOE_reg_wren <= 1'b1;
TOE_reg_din <= {TOE_SFP_ID[1:0],TOE_ADDR,TOE_DATA};
//处理结束
if(data_fifo_empty) begin deal_state <=D_IDLE; deal_busy = 1'b0; end
else begin deal_state <= D_TOE_1; data_fifo_rden <= 1; end
end
end
D_CTRL : begin
if(data_fifo_dout ==32'h1000_0001)begin
state_report_en <= 1;
end
else if (data_fifo_dout ==32'h1000_0000)begin
state_report_en <= 0;
end
else begin
state_report_en <= 0;
end
deal_busy = 1'b0;
deal_state <= D_IDLE;
end
endcase
end
end
//CRC32计算函数生成多项式G(x) = x^32 + x^26 + x^23 + x^22 + x^16 + x^12 + x^11 + x^10 + x^8 + x^7 + x^5 + x^4 + x^2 + x + 1初始值0xffffffff
function [31:0] calc_crc32;
input [31:0] data;
input [31:0] crc;
reg [31:0] new_crc;
integer i;
localparam [31:0] POLY = 32'h04C11DB7;
begin
new_crc = crc ^ data;
for (i = 0; i < 32; i = i + 1) begin
if (new_crc[31]) begin
new_crc = (new_crc << 1) ^ POLY;
end else begin
new_crc = new_crc << 1;
end
end
calc_crc32 = new_crc;
end
endfunction
// 1 second timer
always@(posedge clk)
if(reset)
second_timer <= 'b0;
else if((second_timer < 28'd125 - 1) && state_report_en) //状态上报开启秒计数器才开始工作 实际为28'd125000000
second_timer <= second_timer + 1'b1;
else
second_timer <= 28'd0;
always@(posedge clk)
if(reset)
pulse_second <= 1'b0;
else if( (second_timer >28'd125 - 1 -16))begin
pulse_second <= 1'b1;
end
else
pulse_second <= 1'b0;
endmodule

333
status_to_udp.v Normal file
View File

@ -0,0 +1,333 @@
module status_to_udp (
input clk,
input reset,
input TOE_reg_out_valid,
input [65:0] TOE_reg_dout,
// 通信板(CMU)状态信息接口
output reg CMU_Status_Info_ready,
input CMU_Status_Info_valid,
input CMU_Status_Info_last,
input [31:0] CMU_Status_Info_data,
// 调控板(XYZ)状态信息接口
output reg XYZ_Status_Info_ready,
input XYZ_Status_Info_valid,
input XYZ_Status_Info_last,
input [31:0] XYZ_Status_Info_data,
// 读出板(DAQ)状态信息接口
output reg DAQ_Status_Info_ready,
input DAQ_Status_Info_valid,
input DAQ_Status_Info_last,
input [31:0] DAQ_Status_Info_data,
// UDP发送FIFO接口
input udp_app_send_fifo_rden,
output [7:0] udp_app_send_fifo_rddata,
output [11:0] udp_app_send_fifo_rdcnt,
output udp_app_send_fifo_empty
);
// =========================== 参数定义 ===========================
reg [2:0] A_state;
localparam IDLE = 3'd0;
localparam WAIT_READ =3'd1;
localparam RECV_TOE = 3'd2;
localparam RECV_CMU = 3'd3;
localparam RECV_XYZ = 3'd4;
localparam RECV_DAQ = 3'd5;
reg [2:0]S_state;
localparam SEND_IDLE = 3'd0;
localparam SEND_TOE_HEAD_LENGTH = 3'd1;
localparam SEND_TOE_DATA_1 = 3'd2;
localparam SEND_TOE_DATA_2 = 3'd3;
localparam SEND_CRC = 3'd4;
localparam SEND_INFO_HEAD_LENGTH = 3'd5;
localparam SEND_INFO_DATA = 3'd6;
// =========================== 寄存器定义 ===========================
reg [31:0] data_buffer;
reg [1:0] byte_counter;
reg buffer_valid;
// FIFO相关信号
reg fifo_wr_en;
reg [31:0] fifo_wr_data;
wire fifo_full;
wire TOE_rec_fifo_empty;
reg TOE_rec_fifo_rden;
wire [65:0]TOE_rec_fifo_dout;
reg [63:0]TOE_ready_Data;
reg TOE_ready_Data_valid;
reg [63:0]TOE_payload;
reg [31:0]CMU_Status_data;
reg send_busy;
reg [31:0]crc32_calc;
reg info_recv_flag;
reg [15:0]Info_data_bytes_num;
// =========================== FIFO实例化 ===========================
//512 depth 32to8
fifo_generator_32to8 fifo_32to8 (
.clk(clk), // input wire clk
.rst(reset), // input wire rst
.wr_en(fifo_wr_en), // input wire wr_en
.din(fifo_wr_data), // input wire [31 : 0] din
.full(), // output wire full
.rd_en(udp_app_send_fifo_rden), // input wire rd_en
.dout(udp_app_send_fifo_rddata), // output wire [7 : 0] doutCMU
.empty(udp_app_send_fifo_empty), // output wire empty
.rd_data_count(udp_app_send_fifo_rdcnt), // output wire [11 : 0] rd_data_count
.wr_rst_busy(), // output wire wr_rst_busy
.rd_rst_busy() // output wire rd_rst_busy
);
//256 depth 66 to 66
fifo_generator_66to66 TOE_rec_fifo (
.clk(clk), // input wire clk
.din(TOE_reg_dout), // input wire [65 : 0] din
.wr_en(TOE_reg_out_valid), // input wire wr_en
.rd_en(TOE_rec_fifo_rden), // input wire rd_en
.dout(TOE_rec_fifo_dout), // output wire [65 : 0] dout
.full(), // output wire full
.empty(TOE_rec_fifo_empty) // output wire empty
);
reg [31:0]info_cache_fifo_din;
reg info_cache_fifo_wren;
reg info_cache_fifo_rden;
wire [31:0]info_cache_fifo_dout;
wire info_cache_fifo_full;
wire info_cache_fifo_empty;
//32 to 32
fifo_generator_32to32 info_cache_fifo (
.clk(clk), // input wire clk
.din(info_cache_fifo_din), // input wire [31 : 0] din
.wr_en(info_cache_fifo_wren), // input wire wr_en
.rd_en(info_cache_fifo_rden), // input wire rd_en
.dout(info_cache_fifo_dout), // output wire [31 : 0] dout
.full(info_cache_fifo_full), // output wire full
.empty(info_cache_fifo_empty) // output wire empty
);
// =========================== 仲裁存储状态机 ===========================
always @(posedge clk or posedge reset) begin
if (reset)begin
A_state <= IDLE;
TOE_ready_Data <= 64'b0;
TOE_rec_fifo_rden <= 1'b0;
info_cache_fifo_din <= 32'b0;
info_cache_fifo_wren <= 1'b0;
info_recv_flag <= 1'b0;
Info_data_bytes_num <= 16'b0;
end
else
begin
case (A_state)
IDLE: begin
TOE_ready_Data <= 64'b0;
TOE_ready_Data_valid <=1'b0;
info_cache_fifo_wren <= 1'b0;
info_cache_fifo_din <= 32'b0;
info_recv_flag = 1'b0;
CMU_Status_Info_ready <=1'b0;
DAQ_Status_Info_ready <=1'b0;
XYZ_Status_Info_ready <=1'b0;
// 优先级仲裁TOE >CMU > XYZ > DAQ
if((!TOE_rec_fifo_empty) &&(!send_busy))begin
A_state <= WAIT_READ;
TOE_rec_fifo_rden <= 1'b1;
end
else if (CMU_Status_Info_valid &&(!send_busy))begin
A_state <= RECV_CMU;
end
else if (XYZ_Status_Info_valid &&(!send_busy))begin
A_state <= RECV_XYZ;
end
else if (DAQ_Status_Info_valid &&(!send_busy))begin
A_state <= RECV_DAQ;
end
else
A_state <= IDLE;
end
WAIT_READ : begin
A_state <= RECV_TOE;
TOE_rec_fifo_rden <= 1'b0;
end
RECV_TOE: begin
//执行TOE发送操作
TOE_ready_Data[53:52]<=TOE_rec_fifo_dout[65:64];
TOE_ready_Data[48]<= 1'b1;
TOE_ready_Data[47:32]<=TOE_rec_fifo_dout[47:32];
TOE_ready_Data[31:0] <= TOE_rec_fifo_dout[31:0];
TOE_ready_Data_valid <= 1'b1;
send_busy <= 1'b1; //拿到数立马进行发送状态
A_state <= IDLE;
end
RECV_CMU: begin
CMU_Status_Info_ready <=1'b1;
info_cache_fifo_wren <= 1'b1;
info_cache_fifo_din <= CMU_Status_Info_data;
Info_data_bytes_num <= Info_data_bytes_num + 3'd4;
if (CMU_Status_Info_last)begin
A_state <= IDLE;
send_busy <= 1'b1; //拿到数立马进行发送状态
info_recv_flag = 1'b1;
end
end
RECV_XYZ: begin
XYZ_Status_Info_ready <=1'b1;
info_cache_fifo_wren <= 1'b1;
info_cache_fifo_din <= XYZ_Status_Info_data;
Info_data_bytes_num <= Info_data_bytes_num + 3'd4;
if (XYZ_Status_Info_last)begin
A_state <= IDLE;
send_busy <= 1'b1; //拿到数立马进行发送状态
info_recv_flag = 1'b1;
end
end
RECV_DAQ: begin //5
DAQ_Status_Info_ready <=1'b1;
info_cache_fifo_wren <= 1'b1;
info_cache_fifo_din <= DAQ_Status_Info_data;
Info_data_bytes_num <= Info_data_bytes_num + 3'd4;
if (DAQ_Status_Info_last)begin
A_state <= IDLE;
send_busy <= 1'b1; //拿到数立马进行发送状态
info_recv_flag = 1'b1;
end
end
default: A_state <= IDLE;
endcase
end
end
//发送状态机
always @(posedge clk or posedge reset) begin
if(reset)begin
S_state <= SEND_IDLE;
send_busy <=1'b0;
fifo_wr_en<= 1'b0;
fifo_wr_data <= 32'b0;
crc32_calc <= 32'hFFFFFFFF;
info_cache_fifo_rden <= 1'b0;
TOE_payload <= 64'b0;
end
else begin
case(S_state)
SEND_IDLE : begin
fifo_wr_en <= 1'b0;
fifo_wr_data <= 32'b0;
crc32_calc <= 32'hFFFFFFFF;
if(TOE_ready_Data_valid) begin
TOE_payload <= TOE_ready_Data;
S_state <= SEND_TOE_HEAD_LENGTH;
end
else if(info_recv_flag) begin
S_state <= SEND_INFO_HEAD_LENGTH;
info_cache_fifo_rden <= 1;
end
end
SEND_TOE_HEAD_LENGTH :begin
fifo_wr_en <=1;
fifo_wr_data <= 32'h45470008;
S_state <= SEND_TOE_DATA_1;
end
SEND_TOE_DATA_1 : begin
fifo_wr_en <=1;
fifo_wr_data <= TOE_payload[63:32];
crc32_calc <= calc_crc32(TOE_payload[63:32],crc32_calc);
S_state <= SEND_TOE_DATA_2;
end
SEND_TOE_DATA_2 : begin
fifo_wr_en <=1;
fifo_wr_data <= TOE_payload[31:0];
crc32_calc <= calc_crc32(TOE_payload[31:0],crc32_calc);
S_state <= SEND_CRC;
end
SEND_CRC : begin //
fifo_wr_en <=1;
fifo_wr_data <= crc32_calc;
S_state <= SEND_IDLE;
send_busy <= 1'b0;
info_cache_fifo_rden <= 1'b0;
end
SEND_INFO_HEAD_LENGTH : begin //5
fifo_wr_en <=1;
fifo_wr_data[31:16] <= 32'h494e;
fifo_wr_data[15:0] <= Info_data_bytes_num;
Info_data_bytes_num <= 16'b0; //用完就清零
S_state <= SEND_INFO_DATA;
end
SEND_INFO_DATA : begin //6
fifo_wr_en <=1;
fifo_wr_data <= info_cache_fifo_dout;
crc32_calc <= calc_crc32(info_cache_fifo_dout,crc32_calc);
if(info_cache_fifo_empty)begin
S_state <= SEND_CRC;
end
end
endcase
end
end
// // =========================== FIFO写入控制 ===========================
//CRC32计算函数生成多项式G(x) = x^32 + x^26 + x^23 + x^22 + x^16 + x^12 + x^11 + x^10 + x^8 + x^7 + x^5 + x^4 + x^2 + x + 1初始值0xffffffff
function [31:0] calc_crc32;
input [31:0] data;
input [31:0] crc;
reg [31:0] new_crc;
integer i;
localparam [31:0] POLY = 32'h04C11DB7;
begin
new_crc = crc ^ data;
for (i = 0; i < 32; i = i + 1) begin
if (new_crc[31]) begin
new_crc = (new_crc << 1) ^ POLY;
end else begin
new_crc = new_crc << 1;
end
end
calc_crc32 = new_crc;
end
endfunction
endmodule