| Latency(CLK) | 1 | 
    
    module compress(iVld, iStall, iNew, iData, oVld, oStall, oData, reset, clk);
            parameter       W       = 32;
            parameter       NOP     = 2'h0;
            parameter       PLUS1   = 2'h1;
            parameter       PLUS2   = 2'h2;
            parameter       CHANGE  = 2'h3;
            input           iVld;
            output          iStall;
            input           iNew;
            input   [W-1:0] iData;
            output          oVld;
            input           oStall;
            output  [W-1:0] oData;
            input           reset;
            input           clk;
    
            reg     [W-1:0] lData;          // Latched Data
            wire    [W-1:0] lData0;         // Latched Data + 0
            wire    [W-1:0] lData1;         // Latched Data + 1
            wire    [W-1:0] lData2;         // Latched Data + 2
            wire            eq0;
            wire            eq1;
            wire            eq2;
            wire            iOpVld;
            wire            iOpStall;
            reg     [1:0]   iOpData;        // Operation Code
            wire            iItVld;
            wire            iItStall;
            reg     [W-1:0] iItData;        // Initial Data
            wire            oOpVld;
            wire            oOpStall;
            wire    [1:0]   oOpData;        // Operation Code
            wire            oItVld;
            wire            oItStall;
            wire    [W-1:0] oItData;        // Initial Data
            reg     [W-1:0] oData;
    
            wire            iAlloc  = iVld & !iStall;
            wire            oAlloc  = oVld & !oStall;
            wire            oNew    = (oOpData == CHANGE);
    
            reg     [W-1:0] acc;
            // Past Data for Comparison
            always @(posedge clk)
                    if (iAlloc)
                            lData   <= #1 iData;
            assign iStall   = iOpStall | iItStall;
    
            assign lData0   = lData;
            assign lData1   = lData + 'd1;
            assign lData2   = lData + 'd2;
    
            assign eq0      = (iData == lData0);
            assign eq1      = (iData == lData1);
            assign eq2      = (iData == lData2);
    
            assign iOpVld   = iVld & !iItStall;
            assign iItVld   = iVld & !iOpStall;
    
            // Operation Code
            always @(iNew or eq0 or eq1 or eq2)
                    casex ({iNew, eq2, eq1, eq0})
                            4'b1xxx,
                            4'b0000: iOpData = CHANGE;
                            4'b0001: iOpData = NOP;
                            4'b001x: iOpData = PLUS1;
                            4'b01xx: iOpData = PLUS2;
                    endcase
    
            assign iItData  = iData;
    
            // Operation FIFO (Depth 2^4, Data Width W bit)
            fifo #(2, 4) opFifo (
                    .iVld   (iOpVld),
                    .iStall (iOpStall),
                    .iData  (iOpData),
                    .oVld   (oOpVld),
                    .oStall (oOpStall),
                    .oData  (oOpData),
                    .reset  (reset),
                    .clk    (clk)
                    );
    
            // Initial FIFO (Depth 2^1, Data Width W bit)
            fifo #(W, 1) itFifo (
                    .iVld   (iItVld),
                    .iStall (iItStall),
                    .iData  (iItData),
                    .oVld   (oItVld),
                    .oStall (oItStall),
                    .oData  (oItData),
                    .reset  (reset),
                    .clk    (clk)
                    );
    
            // Accumulator
            always @(posedge clk)
                    if (oAlloc)
                            acc     <= #1 oData;
    
            // Operation
            always @(oOpData or oItData or acc)
                    casex (oOpData)
                            NOP:    oData   = acc;
                            PLUS1:  oData   = acc + 'd1;
                            PLUS2:  oData   = acc + 'd2;
                            CHANGE: oData   = oItData;
                    endcase
    
            assign oOpStall = oStall | !oItVld;
            assign oItStall = oStall | !oOpVld & !oNew;
    
            assign oVld     = oOpVld & (!oItStall | !oNew);
    
    endmodule
    
             |