0
\$\begingroup\$

I am facing an issue with the post-synthesis implementation of a special Serial-In-Serial-Out kind of buffer. It receives inputs and stores them in registers and can later output the stored inputs.

  • When iReset is HIGH, the contents of the buffer are cleared.
  • When iValid is HIGH, the values of the registers in the buffer are shifted and buffer[0] receives iResidual.
  • When oEnable is HIGH, the buffer outputs the values of the last register to oResidual (in this case buffer[2]) and the values are shifted accordingly.
  • When oValid is HIGH, it means that oResidual is a valid output.

Here is the full code:

module ResidualBuffer (
    input iClock,
    input iValid,
    input iReset,
    input oEnable,
    input signed [15:0] iResidual,

    output signed [15:0] oResidual,
    output oValid,
    output signed [15:0] bufferReg0,
    output signed [15:0] bufferReg1,
    output signed [15:0] bufferReg2
    );

parameter blkSize = 3;

reg signed [15:0] buffer [0 : blkSize - 1];

integer i;

reg signed [15:0] oResidualReg;
assign oResidual = oResidualReg;

reg signed [blkSize : 0] oValidReg = -2; // for blkSize = 3, oValidReg = 4'b1110
assign oValid = oValidReg[0];

assign bufferReg0 = buffer[0];
assign bufferReg1 = buffer[1];
assign bufferReg2 = buffer[2];

always @(posedge iClock or posedge iReset) begin
    if (iReset) begin
        for (i = 0; i < blkSize; i = i + 1) begin
            buffer[i] <= 0;
        end
        oResidualReg <= 0;
        oValidReg <= -2;
    end else if (iValid) begin
        for (i = 1; i < blkSize; i = i + 1) begin
            buffer[i] <= buffer[i - 1];
        end
        buffer[0] <= iResidual;
        oResidualReg <= oResidualReg;
        oValidReg <= oValidReg;
    end else if (oEnable) begin
        oValidReg <= oValidReg>>1;
        oResidualReg <= buffer[blkSize - 1];
        for (i = 1; i < blkSize; i = i + 1) begin
            buffer[i] <= buffer[i - 1];
        end
    end
end
endmodule

The behavioural simulation is working as expected: Behavioural-simulation

The post-synthesis simulation is different and confusing: Post-synthesis-simulation

The problems I am facing are:

  1. When iValid is LOW, buffer[0] continues to receive iResidual and the values in the registers are shifted and I don't understand why.
  2. When oEnable is HIGH, it is reflected only in the next clock cycle. However this is not the case for iValid as explained in (1) and I don't understand why.

~Edit: For those who want to look at the testbench I used

`timescale 1ns / 100ps

module ResidualBufferTB;

    reg iClock;
    reg iValid;
    reg iReset;
    reg oEnable;
    reg signed [15:0] iResidual;
    wire signed [15:0] oResidual;
    wire oValid;
    wire signed [15:0] bufferReg0;
    wire signed [15:0] bufferReg1;
    wire signed [15:0] bufferReg2;

    ResidualBuffer #(.blkSize(3)) DUT (
                        .iClock(iClock),
                        .iValid(iValid),
                        .iReset(iReset),
                        .oEnable(oEnable),
                        .iResidual(iResidual),
                        .oResidual(oResidual),
                        .oValid(oValid),
                        .bufferReg0(bufferReg0),
                        .bufferReg1(bufferReg1),
                        .bufferReg2(bufferReg2)
                       );
    always begin
        #0 iClock = 0;

        #125 iClock = 1;

        #125 iClock = 0;
    end

    initial begin
        iReset = 1; iValid = 0; oEnable = 0;

        #125 iReset = 0;

        #250 iValid = 1; iResidual = 20;

        #250 iResidual = -123;

        #250 iResidual = 31;

        #250 iValid = 0; iResidual = 0;

        #250

        #250 oEnable = 1;

        #1250

        $stop;
    end

endmodule
\$\endgroup\$
0
\$\begingroup\$

You didn't provide the testbench so I can't be certain but it looks like you are changing the values of the inputs at the same time the clock rises. That will often cause differences between behavioral and post-synthesis simulations.

You may be seeing the results of setup time violations in the logic. The behavioral simulation has no delays but the post-synthesis simulation does, so their behavior will be different. Try moving the changes in the inputs to be coincident with the falling edge of the clock rather than the rising edge.

| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ Thanks for the answer. So it is possible that when iValid goes to HIGH and iResidual changes at the same time, that buffer[0] will receive the new value of iResidual, but when oEnable goes to HIGH that it will take a clock cycle for buffer[2]'s value to change? \$\endgroup\$ – CuriousHooman May 21 at 12:25
  • \$\begingroup\$ Your design is synchronous...we only care about the values of the inputs when a rising clock edge occurs. So, all of the inputs should be stable (unchanging) for at least a short time before the clock edge and a short time after the clock edge. \$\endgroup\$ – Elliot Alderson May 21 at 12:50

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.