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 andbuffer[0]
receivesiResidual
. - When
oEnable
is HIGH, the buffer outputs the values of the last register tooResidual
(in this casebuffer[2]
) and the values are shifted accordingly. - When
oValid
is HIGH, it means thatoResidual
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:
- When
iValid
is LOW,buffer[0]
continues to receiveiResidual
and the values in the registers are shifted and I don't understand why. - When
oEnable
is HIGH, it is reflected only in the next clock cycle. However this is not the case foriValid
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
1 Answer 1
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.
-
\$\begingroup\$ Thanks for the answer. So it is possible that when
iValid
goes to HIGH andiResidual
changes at the same time, thatbuffer[0]
will receive the new value ofiResidual
, but whenoEnable
goes to HIGH that it will take a clock cycle forbuffer[2]
's value to change? \$\endgroup\$CuriousHooman– CuriousHooman2020年05月21日 12:25:48 +00:00Commented May 21, 2020 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– Elliot Alderson2020年05月21日 12:50:00 +00:00Commented May 21, 2020 at 12:50