module smartnic_extern
    import sdnet_0_pkg::*;
(
    input   logic clk,
    input   logic rstn,

    input   USER_EXTERN_OUT_T    extern_from_sdnet,
    input   USER_EXTERN_VALID_T  extern_from_sdnet_valid,
    output  USER_EXTERN_IN_T     extern_to_sdnet,
    output  USER_EXTERN_VALID_T  extern_to_sdnet_valid
); 
    localparam N = 8;
    localparam LATENCY = 3; 
    USER_EXTERN_VALID_T valid_pipe [LATENCY]; 
    reg [N-1:0][63:0] event_timestamps = 0; 
    reg [N-1:0][39:0] event_cnts = 0;
    reg [39:0] event_cnt;

    reg [3:0]   encrypt; 
    reg [63:0]  timestamp;
    reg [63:0]  dmz_key; 
    reg [7:0]   event_id;

    reg [63:0]  timestamp_temp;
    reg [63:0]  dmz_key_temp;  
    reg [7:0]   event_id_temp; 
    reg [15:0]  time_diff;

    reg [127:0] extern_out;

    always_ff @(posedge clk) begin
      valid_pipe[LATENCY-1] <= extern_from_sdnet_valid; 
      for (int i=0; i<LATENCY-1; i++) begin 
            valid_pipe[i] <= valid_pipe[i+1];
      end
    end

    always_ff @(posedge clk) begin 
        if (extern_from_sdnet_valid) begin
            timestamp <= extern_from_sdnet[135:72];
            dmz_key <= extern_from_sdnet[71:8];
            event_id <= extern_from_sdnet[7:0];
            for (int i = 0; i < N; i++) begin
                if (i == extern_from_sdnet[143:136]) begin
                    event_cnts[i] <= 40'b0;
                end else begin
                    event_cnts[i] <= event_cnts[i];
                end
            end
        end else begin
            event_id <= 0;
        end

        if (valid_pipe[LATENCY-1] && event_id) begin
            timestamp_temp <= timestamp ^ dmz_key;
            event_cnt <= event_cnts[event_id];
            if (timestamp > event_timestamps[event_id]) begin
                time_diff <= timestamp - event_timestamps[event_id];  
            end else begin
                time_diff <= 16'b0;
            end 
            event_timestamps[event_id] <= timestamp;
        end
        event_id_temp <= event_id;
        
        if (valid_pipe[LATENCY-2] && event_id_temp) begin
            extern_out[127:64] <= timestamp_temp;
            extern_out[63:56]  <= event_id_temp;
            extern_out[55:16]  <= event_cnt + 1;
            extern_out[15:0]   <= time_diff;
            event_cnts[event_id_temp] <= event_cnt + 1;
        end 
    end  

    assign extern_to_sdnet       = extern_out; 
    assign extern_to_sdnet_valid = valid_pipe[0];

endmodule: smartnic_extern 
