( ESNUG 321 Item 9 ) ---------------------------------------------- [6/8/99]
Subject: ( ESNUG 318 #10 319 #12 ) Want To Remove Tied-off/Dead Flip-flops
> I've noticed the problem John Patty described for several years now, and
> it's only a subset of the real problem, which is Design Compiler never
> removes storage elements. I've tried connecting set, reset, clock, or
> data to force FFs or latches to constant values, and DC always kept them
> in the design.
>
> - William Liao
> MMC Networks
From: "Paul.Zimmer" <paul.zimmer@cerent.com>
John,
This is not so. In fact, this has been one of my gripes about dc over the
years. The one guaranteed way to get a sequential element optimized out
is to not use the output. Here is some code that seems to instantiate two
4-bit counters and 2 flops, using both sync and async resets. After compile
(indeed, after the verilog read), the result is no gates whatsoever!
Here's the code:
module no_flops ( clk, datain, sync_ctr_eq_16, async_ctr_eq_16, reset );
input clk;
input datain;
output sync_ctr_eq_16;
output async_ctr_eq_16;
input reset;
reg [3:0] sync_counter; // Note: not big enough!
always @(posedge clk)
begin
if (reset)
sync_counter <= 0;
else
sync_counter <= sync_counter + 1;
end
assign sync_ctr_eq_16 = (sync_counter == 16);
reg [3:0] async_counter; // Note: not big enough!
always @(posedge clk or posedge reset)
begin
if (reset)
async_counter <= 0;
else
async_counter <= async_counter + 1;
end
assign async_ctr_eq_16 = (async_counter == 16);
reg sync_dummy; // Note: doesn't go anywhere!
always @(posedge clk)
begin
if (reset)
sync_dummy <= 0;
else
sync_dummy <= datain;
end
reg async_dummy; // Note: doesn't go anywhere!
always @(posedge clk or posedge reset)
begin
if (reset)
async_dummy <= 0;
else
async_dummy <= datain;
end
endmodule
The counter comes from a real-life example where a designer inadvertently
upped the value he was checking for without remember to increase the
counter size. Easy to do. Synopsys SILENTLY removed all the flops!
Even the dummy flops are from real-life. Anybody ever mis-type a signal
name on a flop and get an unconnected output and no flop?
I think Synopsys should issue a very specific warning whenever it removes
a sequential element. This is almost never what the designer intended.
True, you can tell the flops didn't get created because the "Inferred
memory devices in process:" block doesn't appear during the verilog read,
but I'm synthesizing a million gates here. I can't go look at this
report on every module every time I rebuild the chip. If there were a
specific warning, I could grep for it.
- Paul Zimmer
Cerent Corporation
---- ---- ---- ---- ---- ---- ----
From: Thorsten Lutscher <thlu@force.de>
John,
I am not sure if this is the answer, but we encountered the same problem
while trying to make the insertion of a FF dependent on a parameter.
Solution was to add a wire between the output of the FF and the output
of the module (in Verilog):
output ff_q;
wire ff_q;
reg loc_ff_q;
// first the flip flop
always @(posedge clk or negedge reset)
if(~reset)
loc_ff_q <= 0;
else begin
loc_ff_q <= whatever;
end
// then the wire (INSERT_THE_FF is the parameter)
always @(loc_ff_q)
ff_q = INSERT_THE_FF ? loc_ff_q : 0;
If the parameter is 0, Synopsys will not instantiate a Flip-Flop.
- Thorsten Lutscher
FORCE Computers GmbH Germany
---- ---- ---- ---- ---- ---- ----
From: William Liao <wliao@mmcnet.com>
Hi John,
To figure this all out, I created some test cases myself.
What I did is to create three HDL flip-flops: DFF (D with no Reset), DFFR
(D with Reset), and DFFS (D with Set). Then I instantiated them 6 times:
1) DFF with clk
2) DFFR with Reset and clk
3) DFFS with Set and clk
4) DFF with data
5) DFFR with Reset
6) DFFS with Set
Then I instantiated them again, exactly the same input connections,
but the output pins do not drive anything.
module dff (clk, d, q);
input clk;
input d;
output q;
reg q;
always @(posedge clk) q <= d;
endmodule
module dffs (clk, d, q, s);
input clk;
input d;
input s;
output q;
reg q;
// synopsys async_set_reset_local dffs_block "s"
always @(posedge clk or posedge s)
begin : dffs_block
if (s)
q <= 1'b1;
else
q <= d;
end
endmodule
module dffr (clk, d, q, r);
input clk;
input d;
input r;
output q;
reg q;
// synopsys async_set_reset_local dffr_block "r"
always @(posedge clk or posedge r)
begin : dffr_block
if (r)
q <= 1'b0;
else
q <= d;
end
endmodule
module test (clk, s, d, q, t);
input clk;
input s;
input d;
output [5:0] q;
output t;
reg t;
dff no_clk(.clk(1'b1), .d(d), .q(q[0]));
dffs no_clk_ws(.clk(1'b1), .d(d), .s(1'b1), .q(q[1]));
dffr no_clk_wr(.clk(1'b1), .d(d), .r(1'b1), .q(q[2]));
dff no_d(.clk(clk), .d(1'b0), .q(q[3]));
dffs no_s(.clk(clk), .d(d), .s(1'b1), .q(q[4]));
dffr no_r(.clk(clk), .d(d), .r(1'b1), .q(q[5]));
dff nf_no_clk(.clk(1'b1), .d(d));
dffs nf_no_clk_ws(.clk(1'b1), .d(d), .s(1'b1));
dffr nf_no_clk_wr(.clk(1'b1), .d(d), .r(1'b1));
dff nf_no_d(.clk(clk), .d(1'b0));
dffs nf_no_s(.clk(clk), .d(d), .s(1'b1));
dffr nf_no_r(.clk(clk), .d(d), .r(1'b1));
endmodule
The result can be summarized like this: If a cell is not sequential (no
clk), DC will try to remove it. If a cell does not drive anything, DC
will try to remove it. But if a cell is sequential (has clk), or it
drives something, DC is stuck with it, no matter how input pins are
connected.
If you have time, try the example, then have fun with other combinations.
- William Liao
MMC Networks
|
|