Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Yosys will sometimes emit a flip-flop that never toggles instead of a constant 0 #4872

Open
leocassarani opened this issue Jan 28, 2025 · 0 comments
Labels
pending-verification This issue is pending verification and/or reproduction

Comments

@leocassarani
Copy link

leocassarani commented Jan 28, 2025

Version

Yosys 0.49+3 (git sha1 3d35f36, x86_64-apple-darwin23.5-clang++ 18.1.8 -fPIC -O3)

On which OS did this happen?

macOS

Reproduction Steps

I was seeing some very strange behaviour as a result of Yosys being able to optimise away large parts of my design. Eventually I was able to produce a minimal reproduction case, which uncovered a nextpnr bug.

When running synth_ecp5 on the following Verilog module, Yosys will output a useless flip-flop with CE set to 1 and CEMUX set to INV. Similarly, synth_ice40 produces a flip-flop with E set to 0 and D set to 1.

This is because Yosys correctly recognises that b will never be 0, and therefore c <= 1'b1 will never be triggered.

module top (
  input clk,
  output reg c = 1'b0
);

  reg a = 1'b0;
  always @(posedge clk)
    a <= !a;

  wire [2:0] b = 3'd3 + { 2'b0, a };

  always @(posedge clk)
    if (b == 3'd0) c <= 1'b1;

endmodule

However, if b is changed to any other 3-bit value between 1 and 6 inclusive, Yosys correctly optimises away the flip-flop and outputs a constant 0.

Calling synth_ecp5/ice40 with the -dff flag produces the desired result, but it's not clear to me why that should be necessary in this simple case.

Note that this behaviour is also present for bit widths larger than 3. For example, this variation also produces a flip-flop that will never trigger (while values lower than 5'd13 correctly output a constant 0):

module top (
  input clk,
  output reg c = 1'b0
);

  reg [1:0] a = 2'd0;
  always @(posedge clk)
    a <= a + 1;

  wire [4:0] b = 5'd13 + { 3'b0, a };

  always @(posedge clk)
    if (b == 5'd0) c <= 1'b1;

endmodule

Expected Behavior

module \top

  wire output 2 \c

  wire input 1 \clk

  connect \c 1'0
end

Actual Behavior

synth_ecp5

module \top

  attribute \unused_bits "0 1 2"
  wire width 3 \b

  wire output 2 \c

  wire input 1 \clk

  attribute \module_not_derived 1
  cell \TRELLIS_FF \c_TRELLIS_FF_Q
    parameter \CEMUX "INV"
    parameter \CLKMUX "CLK"
    parameter \GSR "DISABLED"
    parameter \LSRMUX "LSR"
    parameter \REGSET "RESET"
    connect \CE 1'1
    connect \CLK \clk
    connect \DI 1'1
    connect \LSR 1'0
    connect \Q \c
  end

  connect \b [0] \b [1]
end

synth_ice40

module \top

  wire width 3 \b

  wire output 2 \c

  wire input 1 \clk

  attribute \module_not_derived 1
  cell \SB_DFFE \c_SB_DFFE_Q
    connect \C \clk
    connect \D 1'1
    connect \E 1'0
    connect \Q \c
  end

  connect \b 3'x
end
@leocassarani leocassarani added the pending-verification This issue is pending verification and/or reproduction label Jan 28, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
pending-verification This issue is pending verification and/or reproduction
Projects
None yet
Development

No branches or pull requests

1 participant