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