1
\$\begingroup\$

I'm looking for some help understanding a synthesis error I run into frequently with Verilog code on an FPGA platform (Lattice ECP5U).

Here's a simplified setup that produces the error. riscv is a main module that instantiates a submodule called icache (some module ports omitted for simplicity).

module riscv();
  reg [31:0] ir; // instruction register
  icache icache(
    [...ports omitted...]
    .instruction           (ir)
  );
endmodule

module icache(
  [...ports omitted...]
  output wire [31:0]       instruction
);
  reg [31:0] ram [0:NUM_CACHE_LINES];
  always @(posedge clk) begin
    [...logic omitted...]
    instruction            <= ram[0];    // *** error here
  end
endmodule

The error I get, at the starred line above, is:

Assignment target 'instruction' must be of type reg, genvar, or logic.

I understand that instruction is marked as a wire in the port list, and the synthesis tool is telling me that it is expecting a flip flop. The problem is that I want the instruction fetched from icache to be registered in the top module, in the flip flops called ir, not registered twice as it would be if I were to mark instruction as output reg [31:0] instruction in icache's port list.

Basically, I don't understand why the synthesis tool can't "see" that instruction is just passing its value through to the ir flip flops in the parent module. Is this not legal Verilog?

And, anyway, given that the tool doesn't see things my way, what's the usual solution here? Should I just register instruction in the icache module and then have the ir variable in the top riscv module be marked as a wire type instead? Or should I register the value in both modules and just trust (+ verify) that the synthesis tool only generates one set of 32 flip flops for the instruction fetched from the icache?

\$\endgroup\$

1 Answer 1

2
\$\begingroup\$

Should I just register instruction in the icache module and then have the ir variable in the top riscv module be marked as a wire type instead?

Yes, that is the usual solution.

module riscv();
  wire [31:0] ir; // instruction register
  icache icache(
    [...ports omitted...]
    .instruction           (ir)
  );
endmodule

module icache(
  [...ports omitted...]
  output reg [31:0]       instruction
);
  reg [31:0] ram [0:NUM_CACHE_LINES];
  always @(posedge clk) begin
    [...logic omitted...]
    instruction            <= ram[0];
  end
endmodule

In icache, you make a procedural assignment (an assignment inside an always block) to instruction. That means you can not declare instruction as a wire in that module. It must be declared as a reg (or logic if you enable SystemVerilog features in your tools).

Keep in mind that the following code is synthesized into flip flops in the module where it resides:

  always @(posedge clk) begin
    instruction <= ram[0];
\$\endgroup\$
4
  • \$\begingroup\$ Secondly, declaring reg only does not mean that a flip flop will be created i.e. reg only does not mean memory element. \$\endgroup\$
    – Im Groot
    Feb 20 at 6:06
  • \$\begingroup\$ @ImGroot Yes, I realize that, but do you think there's a possibility that the synthesis tool would interpret a value that is reg'd in two places as an instruction to create two banks of flip flops for the value, and then require an extra clock cycle for a FF-to-FF transfer of the value? I'm new to Verilog, so maybe I'm misunderstanding how the tool would interpret that. \$\endgroup\$
    – jemalloc
    Feb 20 at 14:43
  • 2
    \$\begingroup\$ @jemalloc: No, the reg keyword does not work that way; simulation and synthesis depend on how you assign to the reg signal. \$\endgroup\$
    – toolic
    Feb 20 at 14:46
  • \$\begingroup\$ I think of it this way: every port of an instantiated block is a wire when viewed from the calling module. You are dropping a physical circuit in at that point. \$\endgroup\$
    – Troutdog
    Mar 2 at 15:22

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.