2
\$\begingroup\$

There is a register in my design that I am using for debug purposes with zero fan-out. Since it isn't driving any logic, the synthesizer optimizes it away. However, as far as my knowledge goes, using the noprune attribute will direct the synthesizer to keep the register.

Unfortunately, even with this synthesis attribute the register is removed from the design in Quartus II. It was suggested to me that since the module has minimal other logic, that it may cause an issue. This doesn't seem quite right to me, though.

I've tried other similar attributes, like preserve - but this didn't work either.

Is this a quirk of Quartus? Would I be better off to try synthesizing the design in something like Synopsys Synplify and then porting that design to Quartus for fitting?

Any ideas what the problem could be?

Thanks in advance!

Here is the code for the module:

VERSION 1

module connector_test(button, txd)

input button;
output reg txd;
reg [2999:0] data /* synthesis noprune */;

always @(button) begin
if(button==1'b0) begin
    txd <= 1'b0;
    data <= {3000 {1'b1}};
end
else begin
    txd <= 1'b1;
    data <= 3000'b0;
end

end

endmodule

...and the synthesis summary:

+------------------------------------------------------------------------------------+
; Analysis & Synthesis Summary                                                       ;
+------------------------------------+-----------------------------------------------+
; Analysis & Synthesis Status        ; Successful - Tue Sep 18 18:20:36 2012         ;
; Quartus II 32-bit Version          ; 12.0 Build 232 07/05/2012 SP 1 SJ Web Edition ;
; Revision Name                      ; connector_test                                ;
; Top-level Entity Name              ; connector_test                                ;
; Family                             ; Cyclone III                                   ;
; Total logic elements               ; 0                                             ;
;     Total combinational functions  ; 0                                             ;
;     Dedicated logic registers      ; 0                                             ;
; Total registers                    ; 0                                             ;
; Total pins                         ; 2                                             ;
; Total virtual pins                 ; 0                                             ;
; Total memory bits                  ; 0                                             ;
; Embedded Multiplier 9-bit elements ; 0                                             ;
; Total PLLs                         ; 0                                             ;
+------------------------------------+-----------------------------------------------+

VERSION 2:

module trigger_test(trigger, reset, clk);

input clk;
input reset;
output reg trigger;
reg [2999:0] data = 3000'b0 /* synthesis noprune */;
reg [15:0] counter = 16'h32; //Trigger will be set every 1000ns (1us).

always @(posedge clk) begin

if(~reset) begin
    trigger <= 1'b0;
    data <= 3000'b0;
    counter <= 16'h32;
end 
else begin
    if(!counter) begin
        trigger <= 1'b1;    //Trigger and data will stay at these values for 20ns because they're synced with the clk.
        data <= {3000 {1'b1}};
        counter <= 16'h32;
    end
    else begin
        trigger <= 1'b0;
        data <= 3000'b0;
        counter <= counter - 1;
    end
end

end
endmodule

VERSION 3:

module toplevel(clk, reset, trigger, out);

input clk;
input reset;
output reg trigger;
output wire out;

reg d = 1'b1;
reg q;

shift shifter( .clk(clk),
       .si(q),
       .so(out));

toggle tff_inst ( .d(d),
          .clk(clk),
          .rst(reset),
          .q(q));

endmodule

TOGGLE:

module toggle(d, clk, rst, q);

input clk;
input d;
input rst;
output reg q;

always @(posedge clk or negedge rst) begin
if(~rst)
    q <= 1'b0;
else if (d) 
    q <= !q;
end

endmodule

The third version also does not synthesize any registers - and I believe this is because I'm receiving a warning that the signal out (the output of the shift register) is stuck at GND. This may be because I'm not initializing the toggling register that gives input to the shift register - but I'm not sure how to initialize this outside of simulation purposes. Any suggestions?

\$\endgroup\$
  • \$\begingroup\$ Interesting, the Xilinx equivalent of noprune 'S' (for save) synthesizes correctly and uses 3000 LUTS as indicated in the report. What's the solution to get this working in Quartus? \$\endgroup\$ – kbarber Sep 19 '12 at 7:04
  • \$\begingroup\$ Version, please. \$\endgroup\$ – Brian Carlton Sep 19 '12 at 23:13
  • \$\begingroup\$ The latest version of Xilinx, 14.2. \$\endgroup\$ – kbarber Sep 19 '12 at 23:52
4
\$\begingroup\$

Despite the "reg" declaration in the source code, you have not in fact created any registers. The behavior of your 3000-bit "data" bus is simply that its value is a function of the current value of the "button" input; it doesn't depend on the past history of that or any other signal, so there's no actual memory behavior specified, and therefore no synthesizable flip-flops.

The only logic here is a simple inverter, the output of which is replicated 3000 times. Since nothing is connected to the "data" bus (and it isn't even specified as an output port of the module), there's no need to implement logic to support the fanout, and in fact, there's no need to implement the inverter at all. What is it you're actually trying to debug? By what mechanism were you hoping to observe the data bus?

I'm guessing that Xilinx took an ultra-conservative approach and actually implemented 3000 inverters. I have no idea why it would do that. The answer may have something to do with the actual debug mechanisms that each manufacturer builds into its chips.

If you're trying to measure things like power consumption for various levels of FPGA utilization, the usual technique for this is to create a long shift register. The register is clocked by common clock signal (usually a global clock) and the input of the first bit and the output of the last bit are brought out to pins (the latter is so that the synthesis software doesn't "prune" away the entire chain).

You control the amount of resouce utilization by varying the length of the shift register, and you control the amount of switching activity by the pattern that you shift into it. A pattern of all zeros or all ones eventually has the minimum activity, while a pattern of alternating ones and zeros eventually ramps up to the maximum level of activity.

module shift (clk, si, so);
  parameter SHIFT_LENGTH = 3000;
  input     clk, si;
  output    so;
  reg    [SHIFT_LENGTH-1:0] data;
  always @(posedge clk) begin
    data <= {data[SHIFT_LENGTH-2:0], si};
  end
  assign so = data[SHIFT_LENGTH-1];
endmodule
\$\endgroup\$
  • \$\begingroup\$ Great explanation! In fact, after looking at the RTL from Xilinx - that is exactly what happened - it synthesized 3000 inverters. Interesting, but not what I'm looking for. I think 'debug' was maybe the wrong term to use - but I am using it in a sense for prototyping purposes. I want to measure the power consumed by the FPGA for different amounts of resource usage and switching activity. I thought making a large 'register' to represent a distinct amount of resource usage would be straight-forward. I found the idea from a journal article and wanted to try it out. \$\endgroup\$ – kbarber Sep 19 '12 at 15:59
  • \$\begingroup\$ I also know it's possible to keep registers that "don't go anywhere" for debug purposes like SignalTap - so I thought it should be do-able. What would you suggest in order to have the synthesizer actually implement a register? Declare a DFF module and instantiate this 3000 times? Is there a better way? Thanks again! \$\endgroup\$ – kbarber Sep 19 '12 at 16:00
  • \$\begingroup\$ The usual technique for what you're trying to do is to create a long shift register. It needs both a data and a clock input, and if you tie the output to a pin, it won't get "pruned". \$\endgroup\$ – Dave Tweed Sep 19 '12 at 16:21
  • \$\begingroup\$ Ahh, that makes sense! Good solution. Thanks again for all of the advice. \$\endgroup\$ – kbarber Sep 19 '12 at 21:11
  • \$\begingroup\$ This may seem like an elementary question - but what is the best way to shift the alternating pattern into the register from a toplevel module? \$\endgroup\$ – kbarber Sep 19 '12 at 21: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.