UDP_data_process/status_to_udp.v

473 lines
17 KiB
Verilog
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

module status_to_udp (
input clk,
input reset,
input status_report_en,
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 [3:0] A_state; // 需要4位因为增加了WAIT_CMU_VALID等状态
localparam IDLE = 4'd0;
localparam WAIT_READ = 4'd1;
localparam RECV_TOE = 4'd2;
localparam WAIT_CMU_VALID = 4'd3; // 新增等待CMU valid
localparam RECV_CMU = 4'd4;
localparam WAIT_XYZ_VALID = 4'd5; // 新增等待XYZ valid
localparam RECV_XYZ = 4'd6;
localparam WAIT_DAQ_VALID = 4'd7; // 新增等待DAQ valid
localparam RECV_DAQ = 4'd8;
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_LENGTH = 3'd3;
localparam SEND_TOE_DATA_2 = 3'd4;
localparam SEND_CRC = 3'd5;
localparam SEND_INFO_HEAD_LENGTH = 3'd6;
localparam SEND_INFO_DATA = 3'd7;
// =========================== 寄存器定义 ===========================
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 send_finish;
reg [31:0] crc32_calc;
reg info_recv_flag;
reg [15:0] Info_data_bytes_num;
reg [15:0] Info_data_bytes_num_reg;
// 超时计数器
reg [7:0] wait_timeout_cnt;
// 轮询计数器
reg [1:0] poll_counter;
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;
// =========================== 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(fifo_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] dout
.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
.srst(reset), // input wire srst
.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
);
//32 to 32
fifo_generator_32to32 info_cache_fifo (
.clk(clk), // input wire clk
.srst(reset), // input wire srst
.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
);
// ILA实例化调试用
ila_00 ila_udp_data (
.clk(clk), // input wire clk
.probe0({
reset,
fifo_wr_en,
fifo_wr_data,
TOE_reg_dout,
TOE_reg_out_valid,
TOE_rec_fifo_rden,
TOE_rec_fifo_dout,
TOE_rec_fifo_empty,
info_cache_fifo_din,
info_cache_fifo_wren,
info_cache_fifo_rden,
info_cache_fifo_dout,
info_cache_fifo_empty,
TOE_ready_Data,
TOE_ready_Data_valid,
info_recv_flag,
send_busy,
A_state,
S_state,
crc32_calc,
TOE_payload,
Info_data_bytes_num,
Info_data_bytes_num_reg,
wait_timeout_cnt,
poll_counter
})
);
// =========================== 仲裁存储状态机 ===========================
always @(posedge clk) begin
if (reset) begin
A_state <= IDLE;
TOE_ready_Data <= 64'b0;
TOE_ready_Data_valid <= 1'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;
send_busy <= 1'b0;
CMU_Status_Info_ready <= 1'b0;
XYZ_Status_Info_ready <= 1'b0;
DAQ_Status_Info_ready <= 1'b0;
wait_timeout_cnt <= 8'b0;
poll_counter <= 2'b00;
end else begin
case (A_state)
IDLE: begin //0
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;
XYZ_Status_Info_ready <= 1'b0;
DAQ_Status_Info_ready <= 1'b0;
Info_data_bytes_num <= 16'b0;
wait_timeout_cnt <= 8'b0;
if (send_finish) begin
send_busy <= 1'b0;
end
// 优先级仲裁TOE > 状态信息板卡
if ((!TOE_rec_fifo_empty) && (!send_busy)) begin
A_state <= WAIT_READ;
TOE_rec_fifo_rden <= 1'b1;
end else if (status_report_en && (!send_busy)) begin
// 轮询不同的板卡按照CMU->XYZ->DAQ的顺序
case (poll_counter)
2'b00: begin // CMU
A_state <= WAIT_CMU_VALID;
CMU_Status_Info_ready <= 1'b1;
end
2'b01: begin // XYZ
A_state <= WAIT_XYZ_VALID;
XYZ_Status_Info_ready <= 1'b1;
end
2'b10: begin // DAQ
A_state <= WAIT_DAQ_VALID;
DAQ_Status_Info_ready <= 1'b1;
end
default: begin
A_state <= IDLE;
poll_counter <= 2'b00;
end
endcase
end else begin
A_state <= IDLE;
end
end
WAIT_READ: begin //1
A_state <= RECV_TOE;
TOE_rec_fifo_rden <= 1'b0;
end
RECV_TOE: begin //2
TOE_ready_Data[63] <= 1'b1; // 读标志位
TOE_ready_Data[56:52] <= 5'h02; // 新增
TOE_ready_Data[49:48] <= TOE_rec_fifo_dout[65:64]; // CID
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;
poll_counter <= 2'b00; // 重置轮询计数器
end
WAIT_CMU_VALID: begin //3
wait_timeout_cnt <= wait_timeout_cnt + 1;
if (CMU_Status_Info_valid) begin
wait_timeout_cnt <= 8'b0;
A_state <= RECV_CMU;
info_cache_fifo_wren <= 1'b1;
info_cache_fifo_din <= CMU_Status_Info_data;
Info_data_bytes_num <= Info_data_bytes_num + 4;
end else if (wait_timeout_cnt > 8'd10) begin // 超时10个周期
wait_timeout_cnt <= 8'b0;
CMU_Status_Info_ready <= 1'b0;
poll_counter <= poll_counter + 1; // 尝试下一个板卡
A_state <= IDLE;
end
end
RECV_CMU: begin //4
// 保持ready为高直到last信号到来
CMU_Status_Info_ready <= 1'b1;
if(CMU_Status_Info_valid) info_cache_fifo_wren <= 1'b1;
else info_cache_fifo_wren <= 1'b0;
info_cache_fifo_din <= CMU_Status_Info_data;
if (CMU_Status_Info_valid) begin /////valid可能为高低高低交替所以计数也要加判断逻辑以免多计数。
Info_data_bytes_num <= Info_data_bytes_num + 4;
end
if (CMU_Status_Info_last) begin
A_state <= IDLE;
CMU_Status_Info_ready <= 1'b0;
// info_cache_fifo_wren <= 1'b0;
send_busy <= 1'b1; // 拿到数立马进行发送状态
info_recv_flag <= 1'b1;
poll_counter <= 2'b00; // 重置轮询计数器
end
end
WAIT_XYZ_VALID: begin //5
wait_timeout_cnt <= wait_timeout_cnt + 1;
if (XYZ_Status_Info_valid) begin
wait_timeout_cnt <= 8'b0;
A_state <= RECV_XYZ;
info_cache_fifo_wren <= 1'b1;
info_cache_fifo_din <= XYZ_Status_Info_data;
Info_data_bytes_num <= Info_data_bytes_num + 4;
end else if (wait_timeout_cnt > 8'd10) begin // 超时10个周期
wait_timeout_cnt <= 8'b0;
XYZ_Status_Info_ready <= 1'b0;
poll_counter <= poll_counter + 1; // 尝试下一个板卡
A_state <= IDLE;
end
end
RECV_XYZ: begin //6
XYZ_Status_Info_ready <= 1'b1;
if(XYZ_Status_Info_valid) info_cache_fifo_wren <= 1'b1;
else info_cache_fifo_wren <= 1'b0;
info_cache_fifo_din <= XYZ_Status_Info_data;
if (XYZ_Status_Info_valid) begin /////valid可能为高低高低交替所以计数也要加判断逻辑以免多计数。
Info_data_bytes_num <= Info_data_bytes_num + 4;
end
if (XYZ_Status_Info_last) begin
A_state <= IDLE;
XYZ_Status_Info_ready <= 1'b0;
// info_cache_fifo_wren <= 1'b0;
send_busy <= 1'b1;
info_recv_flag <= 1'b1;
poll_counter <= 2'b00; // 重置轮询计数器
end
end
WAIT_DAQ_VALID: begin //7
wait_timeout_cnt <= wait_timeout_cnt + 1;
if (DAQ_Status_Info_valid) begin
wait_timeout_cnt <= 8'b0;
A_state <= RECV_DAQ;
info_cache_fifo_wren <= 1'b1;
info_cache_fifo_din <= DAQ_Status_Info_data;
Info_data_bytes_num <= Info_data_bytes_num + 4;
end else if (wait_timeout_cnt > 8'd10) begin // 超时10个周期
wait_timeout_cnt <= 8'b0;
DAQ_Status_Info_ready <= 1'b0;
poll_counter <= 2'b00; // 轮询回到CMU
A_state <= IDLE;
end
end
RECV_DAQ: begin //8
DAQ_Status_Info_ready <= 1'b1;
if(DAQ_Status_Info_valid) info_cache_fifo_wren <= 1'b1;
else info_cache_fifo_wren <= 1'b0;
info_cache_fifo_din <= DAQ_Status_Info_data;
if (DAQ_Status_Info_valid) begin /////valid可能为高低高低交替所以计数也要加判断逻辑以免多计数。
Info_data_bytes_num <= Info_data_bytes_num + 4;
end
if (DAQ_Status_Info_last) begin
A_state <= IDLE;
DAQ_Status_Info_ready <= 1'b0;
// info_cache_fifo_wren <= 1'b0;
send_busy <= 1'b1;
info_recv_flag <= 1'b1;
poll_counter <= 2'b00; // 重置轮询计数器
end
end
default: A_state <= IDLE;
endcase
end
end
// =========================== 发送状态机 ===========================
always @(posedge clk or posedge reset) begin
if(reset) begin
S_state <= SEND_IDLE;
fifo_wr_en <= 1'b0;
fifo_wr_data <= 32'b0;
crc32_calc <= 32'hFFFFFFFF;
info_cache_fifo_rden <= 1'b0;
TOE_payload <= 64'b0;
send_finish <= 1'b0;
Info_data_bytes_num_reg <= 1'b0;
end else begin
case(S_state)
SEND_IDLE: begin //0
fifo_wr_en <= 1'b0;
fifo_wr_data <= 32'b0;
crc32_calc <= 32'hFFFFFFFF;
send_finish <= 1'b0;
Info_data_bytes_num_reg <= 1'b0;
info_cache_fifo_rden <= 1'b0;
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'b1;
Info_data_bytes_num_reg <= Info_data_bytes_num;
end
end
SEND_TOE_HEAD_LENGTH: begin //1
fifo_wr_en <= 1'b1;
fifo_wr_data <= 32'h4547000c;
S_state <= SEND_TOE_DATA_1;
end
SEND_TOE_DATA_1: begin //2
fifo_wr_en <= 1'b1;
fifo_wr_data <= TOE_payload[63:32];
crc32_calc <= calc_crc32(TOE_payload[63:32], crc32_calc);
S_state <= SEND_TOE_DATA_LENGTH;
end
SEND_TOE_DATA_LENGTH: begin //3
fifo_wr_en <= 1'b1;
fifo_wr_data <= 32'd4; // 固定四字节长度
crc32_calc <= calc_crc32(32'd4, crc32_calc);
S_state <= SEND_TOE_DATA_2;
end
SEND_TOE_DATA_2: begin //4
fifo_wr_en <= 1'b1;
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 //5
fifo_wr_en <= 1'b1;
fifo_wr_data <= crc32_calc;
S_state <= SEND_IDLE;
send_finish <= 1'b1;
info_cache_fifo_rden <= 1'b0;
end
SEND_INFO_HEAD_LENGTH: begin //6
fifo_wr_en <= 1'b1;
fifo_wr_data[31:16] <= 16'h494e; // "IN"
fifo_wr_data[15:0] <= Info_data_bytes_num_reg;
crc32_calc <= 32'hFFFFFFFF; //be ready to caculate crc
S_state <= SEND_INFO_DATA;
end
SEND_INFO_DATA: begin //7
fifo_wr_en <= 1'b1;
fifo_wr_data <= info_cache_fifo_dout;
crc32_calc <= calc_crc32(info_cache_fifo_dout, crc32_calc);
if(info_cache_fifo_empty) begin
info_cache_fifo_rden <= 1'b0;
S_state <= SEND_CRC;
end else begin
info_cache_fifo_rden <= 1'b1;
end
end
default: S_state <= SEND_IDLE;
endcase
end
end
// =========================== CRC32计算函数 ===========================
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