Pipeline stage got synthesised out?

F

Florian Schlembach

Guest
I am dealing with a synchronised design where I implement pipeline stages after each operation:

-------------code snippet start -------------
wire strobe_sq_round;
reg strobe_sq_round_reg;

round_sd #(.WIDTH_IN(31),.WIDTH_OUT(16)) round_q
(.clk(clock),
.reset(reset),
.in({sq_q_reg[35],sq_q_reg[29:0]}),
.strobe_in(strobe_sq_reg),
.out(sq_round_q),
.strobe_out(strobe_sq_round));

always @(posedge clock) begin
if(strobe_sq_round) begin
sq_round_q_reg <= sq_round_q;
end

strobe_sq_round_reg <= strobe_sq_round;
end

always @(posedge clock) begin
if(strobe_sq_round) begin
sq_round_i_reg <= sq_round_i;
sq_round_q_reg <= sq_round_q;
end

strobe_sq_round_reg <= strobe_sq_round;
end

sign_extend #(.bits_in(16), .bits_out(18)) sign_extend_cu_q (.in(sq_round_q_reg), .out(sq_se_q));

MULT18X18 cube_q
(.P(cu_q), .A(sq_se_q), .B(din_se_q_reg));
-------------code snippet end -------------

The pipeline stage strobe_sq_round_reg/sq_round_q_reg gets synthesised out so that the output of the round_q module is routed directly through the sign_extend_cu_q module and the cube_q multiplier. See the synthesis result (actually its RTL schematic, but post-synthesis is the same) here: http://qupload.com/images/087847bf27.png

As a consequence, I am getting a critical path because the rounding operation is performed within the same cycle of the mult-op.

How does it come that my pipeline stage gets optimised out and how do I prevent it? I am using XST as the synthesis tool. Register balancing is on, could that be the root cause? If yes, how can I get XST to retain my pipeline logic?

Thanks!
 
It's probably there somewhere. What's in the round_q block? If there is a DSP48 in there, there are lots of registers that your sq_round_q could be getting pulled into. For example, I've used a DSP48 with the a1,m, and p registers, followed by a register in fabric. The synthesizer (Synplify, in my case) might push m back into a2, p back into m, and the fabric register back into p. The same goes for blockRAMs.
 
Florian Schlembach wrote:
On Wednesday, 10 April 2013 23:00:41 UTC+2, Kevin Neilson wrote:
It's probably there somewhere. What's in the round_q block? If there is a DSP48 in there, there are lots of registers that your sq_round_q could be getting pulled into. For example, I've used a DSP48 with the a1,m, and p registers, followed by a register in fabric. The synthesizer (Synplify, in my case) might push m back into a2, p back into m, and the fabric register back into p. The same goes for blockRAMs.

Thanks, gabor (he answered on a thread, I deleted in the meantime before I opened this again) and Kevin.
@Kevin
unfortunately, they is now register surrounding this one. Neither one in the prior round block (also no DSP48) nor one in sign_extend.

By gabor
"Did you add the register after building the code without it? It looks
like a case of the tools using stale data. I've seen this a million
times with Xilinx ISE. The standard workaround is to "clean up" the
project using Project --> Cleanup Project Files...
When that doesn't work, I exit ISE, and delete the sub-folders it
generated under my project directory. That usually cleans out any
remaining history."

Already tried this without any effect.
Instead, I had a look into the synthesis report and discovered the following:
"WARNING:Xst:2677 - Node <sq_i_reg_0> of sequential type is unconnected in block <refmdl>. ..."

So the whole register is optimised away because it seems to be unconnected? I don't get that because in my point of view sq_i_reg is clearly connected:

sign_extend #(.bits_in(16), .bits_out(18)) sign_extend_cu_i (.in(sq_round_i_reg), .out(sq_se_i));

always @(posedge clock) begin
if(strobe_sq_round) begin
sq_round_q_reg <= sq_round_q;
end

strobe_sq_round_reg <= strobe_sq_round;
end

This seems to cause lots of trouble in my code. I already tried to cancel the if-clause but this doesnt seem to have an effect.

Whats wrong here?
The Warning refers to "sq_i_reg" while the closest thing in your posts
is "sq_round_i_reg"

Have you changed something in the posted code, or is the problem perhaps
elsewhere in the design?

--
Gabor
 
On Wednesday, 10 April 2013 23:00:41 UTC+2, Kevin Neilson wrote:
It's probably there somewhere. What's in the round_q block? If there is a DSP48 in there, there are lots of registers that your sq_round_q could be getting pulled into. For example, I've used a DSP48 with the a1,m, and p registers, followed by a register in fabric. The synthesizer (Synplify, in my case) might push m back into a2, p back into m, and the fabric register back into p. The same goes for blockRAMs.
Thanks, gabor (he answered on a thread, I deleted in the meantime before I opened this again) and Kevin.
@Kevin
unfortunately, they is now register surrounding this one. Neither one in the prior round block (also no DSP48) nor one in sign_extend.

By gabor
"Did you add the register after building the code without it? It looks
like a case of the tools using stale data. I've seen this a million
times with Xilinx ISE. The standard workaround is to "clean up" the
project using Project --> Cleanup Project Files...
When that doesn't work, I exit ISE, and delete the sub-folders it
generated under my project directory. That usually cleans out any
remaining history."

Already tried this without any effect.
Instead, I had a look into the synthesis report and discovered the following:
"WARNING:Xst:2677 - Node <sq_i_reg_0> of sequential type is unconnected in block <refmdl>. ..."

So the whole register is optimised away because it seems to be unconnected? I don't get that because in my point of view sq_i_reg is clearly connected:

sign_extend #(.bits_in(16), .bits_out(18)) sign_extend_cu_i (.in(sq_round_i_reg), .out(sq_se_i));

always @(posedge clock) begin
if(strobe_sq_round) begin
sq_round_q_reg <= sq_round_q;
end

strobe_sq_round_reg <= strobe_sq_round;
end

This seems to cause lots of trouble in my code. I already tried to cancel the if-clause but this doesnt seem to have an effect.

Whats wrong here?
 
Florian Schlembach wrote:
The Warning refers to "sq_i_reg" while the closest thing in your posts

is "sq_round_i_reg"


Yes, your right, I have confused it. Suddenly, the problem resolved itself. After cleaning the project dir, recompiling it multiple times, the register just appeared. Don't know what XST did before.

BTW: Is the following statement considered as bad coding practice because not all cases are covered? Or does this rather relate to combinational circuits? I am specifically thinking of the unintended latch-generation I always read about.

always @(posedge clock) begin
if(strobe_sq_round) begin
sq_round_i_reg <= sq_round_i;
end
end
No problem with that code. the "@(posedge clock)" ensures that
only edge-triggered flip-flops and no gated latches are inferred.
If the architecture supports clock enables, "strobe_sq_round"
could be used as the clock enable, otherwise the uncovered
cases would just require feedback from the Q output of the
inferred flop.

--
Gabor
 
The Warning refers to "sq_i_reg" while the closest thing in your posts

is "sq_round_i_reg"
Yes, your right, I have confused it. Suddenly, the problem resolved itself. After cleaning the project dir, recompiling it multiple times, the register just appeared. Don't know what XST did before.

BTW: Is the following statement considered as bad coding practice because not all cases are covered? Or does this rather relate to combinational circuits? I am specifically thinking of the unintended latch-generation I always read about.

always @(posedge clock) begin
if(strobe_sq_round) begin
sq_round_i_reg <= sq_round_i;
end
end
 

Welcome to EDABoard.com

Sponsor

Back
Top