azonenberg / openfpga

Open FPGA tools
Other
257 stars 30 forks source link

ERROR: Cell "$abc$..." is of type "$_NOT_" which is not a valid GreenPak4 primitive #10

Closed whitequark closed 8 years ago

whitequark commented 8 years ago

To reproduce:

module ClkDiv #(parameter DIVISOR = 1) (clk, clkdiv);

  input  wire                     clk;
  output reg  [$clog2(DIVISOR):0] clkdiv = DIVISOR;

  always @(posedge clk)
    if(clkdiv == 0)
      clkdiv <= DIVISOR;
    else
      clkdiv <= clkdiv - 1;

endmodule

module Blinky(o_led1, o_led2, o_led3);

  (* LOC="P3" *) output wire o_led1;
  (* LOC="P4" *) output wire o_led2;
  (* LOC="P5" *) output wire o_led3;

  wire clk;
  GP_LFOSC #(
    .AUTO_PWRDN(0),
    .OUT_DIV(16)
  ) lfosc (
    .CLKOUT(clk)
  );

  wire clkdiv_state;
  ClkDiv #(
    .DIVISOR(108*3)
  ) clkdiv1 (
    .clk(clk),
    .clkdiv(clkdiv_state)
  );

  localparam RED = 0, REDYELLOW = 1, YELLOW = 2, GREEN = 3, GREENBLINK = 4;
  reg[2:0] state;
  always @(posedge clk)
    if(clkdiv_state == 0)
      case(state)
        RED:
          state <= REDYELLOW;
        REDYELLOW:
          state <= YELLOW;
        YELLOW:
          state <= GREEN;
        GREEN:
          state <= GREENBLINK;
        GREENBLINK:
          state <= RED;
      endcase

  wire clkdiv_blink;
  ClkDiv #(
    .DIVISOR(108/2)
  ) clkdiv2 (
    .clk(clk),
    .clkdiv(clkdiv_blink)
  );

  reg blink;
  always @(posedge clk)
    if(clkdiv_blink == 0)
      blink <= ~blink;

  wire[2:0] leds;
  always @(posedge clk)
    case(state)
      RED:
        leds = 3'b001;
      REDYELLOW:
        leds = 3'b011;
      YELLOW:
        leds = 3'b010;
      GREEN:
        leds = 3'b100;
      GREENBLINK:
        if(blink == 0)
          leds = 3'b000;
        else
          leds = 3'b100;
    endcase

  assign {o_led1, o_led2, o_led3} = leds;

endmodule

and apply the workaround from #7.

whitequark commented 8 years ago

Workaround: inline the module.

whitequark commented 8 years ago

Modules are not necessary to trigger this sort of bug, e.g.

module Blinky(o_led1, o_led2, o_led3, o_led4, o_led5, o_led6);

  (* LOC="P3" *) output wire o_led1;
  (* LOC="P4" *) output wire o_led2;
  (* LOC="P5" *) output wire o_led3;
  (* LOC="P6" *) output wire o_led4;
  (* LOC="P7" *) output wire o_led5;
  (* LOC="P8" *) output wire o_led6;

  GP_LFOSC #(
    .AUTO_PWRDN(0),
    .OUT_DIV(16)
  ) lfosc (
    .CLKOUT(clk)
  );

  reg[$clog2(108*3):0] clkdiv_state = 108*3;
  always @(posedge clk)
    if(clkdiv_state == 0)
      clkdiv_state <= 108*3;
    else
      clkdiv_state <= clkdiv_state - 1;

  localparam RED = 0, REDYELLOW = 1, YELLOW = 2, GREEN = 3, GREENBLINK = 4;
  reg[2:0] state1 = REDYELLOW, state2 = RED;
  always @(posedge clk)
    if(clkdiv_state == 0) begin
      case(state1)
        RED:
          state1 <= REDYELLOW;
        REDYELLOW:
          state1 <= GREEN;
        GREEN:
          state1 <= GREENBLINK;
        GREENBLINK:
          state1 <= YELLOW;
        YELLOW:
          state1 <= RED;
      endcase;
      state2 <= state1;
    end

  reg[$clog2(108/2):0] clkdiv_blink = 108/2;
  always @(posedge clk)
    if(clkdiv_blink == 0)
      clkdiv_blink <= 108/2;
    else
      clkdiv_blink <= clkdiv_blink - 1;

  reg blink;
  always @(posedge clk)
    if(clkdiv_blink == 0)
      blink <= ~blink;

  wire[2:0] leds1;
  always @(posedge clk)
    case(state1)
      RED:
        leds1 = ~3'b001;
      REDYELLOW:
        leds1 = ~3'b011;
      YELLOW:
        leds1 = ~3'b010;
      GREEN:
        leds1 = ~3'b100;
      GREENBLINK:
        if(blink == 0)
          leds1 = ~3'b000;
        else
          leds1 = ~3'b100;
    endcase

  wire[2:0] leds2;
  always @(posedge clk)
    case(state2)
      RED:
        leds2 = 3'b001;
      REDYELLOW:
        leds2 = 3'b011;
      YELLOW:
        leds2 = 3'b010;
      GREEN:
        leds2 = 3'b100;
      GREENBLINK:
        if(blink == 0)
          leds2 = 3'b000;
        else
          leds2 = 3'b100;
    endcase

  assign {o_led1, o_led2, o_led3} = leds1;
  assign {o_led4, o_led5, o_led6} = leds2;

endmodule
azonenberg commented 8 years ago

Closing as invalid. This is a Yosys issue, not a gp4par issue.

More precisely, the current Yosys "nlutmap" pass will map to generic RTL cells (which cannot be placed by gp4par since they don't correspond to an actual device resource) once it runs out of LUTs. The better option is to fail with an error in this case.

whitequark commented 8 years ago

Okay. Could you open a bug against yosys then? I am not familiar with nlutmap command and do not know how synth_greenpak4 uses it exactly, so you would write a better issue than me.

cliffordwolf commented 8 years ago

See https://github.com/cliffordwolf/yosys/commit/99edf249669158b8c8bef0c7c3b926a2bbb7a621

whitequark commented 8 years ago

@cliffordwolf Wonderful, thanks!