Reg Cannot Be Driven by Primitives or Continuous Assignment
Table of Contents
Simple guide to Verilog Wire and Reg types
The aim of this article is to help clear any confusion for beginners when using verilog wire and reg data types between modules. We'll start with the basic rules for both.
The simple wire rules are:
-
A wire from an outer module can be connected to the input or output of an inner module.
The simple reg rules are:
-
A reg can be used as input to an inner module.
-
In an inner module, a reg can be used as an output, but not as an input.
-
A reg in an outer module cannot be connected to the output reg of an inner module. This rule can seem confusing.
This illustration will help show what connections are possible:
Testing simple wires between modules
The verilog for two simple modules to demonstrate connecting wires are:
`include "innermodule.v" module top; wire w_inputForInnerModule; wire w_outputFromInnerModule; InnerModule innermodule ( .i_inner_input(w_inputForInnerModule) , .o_inner_output(w_outputFromInnerModule) ) ; endmodule
module InnerModule ( input i_inner_input, output o_inner_output ) ; assign o_inner_output = i_inner_input; endmodule
The InnerModule simply connects its input to the output and the top level module has two internal wires that connect to InnerModule's input and output ports but that is all. The wire values are indeterminate, and the design is of little practical use. But it does demonstrate how wires can be connected between modules.
However, we need more than wires. We need reg variables for our logic and processing so that we can eventually pass this information to wires.
More rules for a wire and reg data types
More rules for wire data types:
-
Only wires can be assigned to using the
assign
statement. They are continuously connected. -
Wires can't store information. They have no state.
-
Wires cannot be assigned a value in an
always
block.
More rules for reg data types:
-
A reg can store information.
-
Only a reg can be assigned a value in an
always
block. -
A reg cannot be continually assigned to using the
assign
statement. -
A reg can continually pass to a wire using
assign
. -
Reg can be used to create both combination and sequential logic.
That's a lot to take in. Let's work through them:
Reg In / Wire Out
Let's try the case where we have a reg in the outer module that is initialised to 1 and is connected to the input of the inner module.
`include "innermodule.v" module top; reg r_inputForInnerModule = 1'b1 ; wire w_outputFromInnerModule; InnerModule innermodule ( .i_inner_input(r_inputForInnerModule) , .o_inner_output(w_outputFromInnerModule) ) ; endmodule
module InnerModule ( input i_inner_input, output o_inner_output ) ; assign o_inner_output = i_inner_input; endmodule
And I guess I should supply a small testbench to prove that the output from the inner module was collected from the reg in the outer module:
`timescale 1ns / 1ns `include "top.v" module top_tb; top top_test ( ) ; initial begin $dumpfile ( "top_tb.lxt" ) ; $dumpvars ( 0 ,top_tb) ; end initial begin # 20 $finish ; end endmodule
See FPGA Verilog simulation using GTKWave if you need help setting up testbenches for use in GTKWave simulations.
You can see above that the reg that contained the value of 1'b1 has set the wire w_outputFromInnerModule
to HIGH. Nice.
A module's output reg cannot connect to a reg in the outer module
It is quite possible to pass back an output reg from a module. But it has to connect to a wire. So let's begin with some code attempting to do the wrong thing with the inner module. We can't just use:
//bad InnerModule module InnerModule ( input i_inner_input, output reg o_inner_output = 1'b0 ) ; assign o_inner_output = i_inner_input; endmodule
This will give us an error of: reg o_inner_output; cannot be driven by primitives or continuous assignment.
We cannot use the assign
statement to wire two regs together. But we can change the value of the output reg whenever i_inner_input
changes using the always
block:
module InnerModule ( input i_inner_input, output reg o_inner_output = 1'b0 ) ; always @ (i_inner_input) begin o_inner_output <= i_inner_input; end endmodule
Let's come up with an outer module that tries to connect a reg to the output reg of the inner module. Can we do it?:
//bad top module `include "innermodule.v" module top; reg r_inputForInnerModule = 1'b1 ; reg r_outputFromInnerModule = 1'b0 ; InnerModule innermodule ( .i_inner_input(r_inputForInnerModule) , .o_inner_output(r_outputFromInnerModule) ) ; endmodule
We get an error from iverilog stating: reg r_outputFromInnerModule; cannot be driven by primitives or continuous assignment.
Same deal.
So going back to the original rule we wanted to test: no we can't connect the reg to the output reg of an inner module. We must connect to a wire in the outer module. Therefore, the correct way is to go with this instead:
`include "innermodule.v" module top; reg r_inputForInnerModule = 1'b1 ; wire w_outputFromInnerModule; InnerModule innermodule ( .i_inner_input(r_inputForInnerModule) , .o_inner_output(w_outputFromInnerModule) ) ; endmodule
And this will be fine. Again, let's test it using the testbench from before:
It actually ends up being the same simulation result. Interesting right?
You can see the reg was initialised to 1 which made the output equal to 1. This output set w_outputFromInnerModule
to HIGH. Fantastic stuff.
If you ever find yourself unsure, always refer to the illustration at the start for a reminder of who can go where.
I would love to hear if this helps you out. Feel free to use the contact link at the top to say hi.
Additional references
Source: https://blog.waynejohnson.net/doku.php/verilog_wire_and_reg
0 Response to "Reg Cannot Be Driven by Primitives or Continuous Assignment"
Post a Comment