User Tools

Site Tools


verilog_wire_and_reg

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

verilog_wire_and_reg [2021/03/04 10:41] (current)
sausage created
Line 1: Line 1:
 +====== Simple guide to Verilog Wire and Reg types ======
  
 +{{ :​verilog:​wire-reg-cover.png?​direct&​300|}}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:
 +
 +{{ :​verilog:​verilog-reg-wires.png?​direct |}}
 +
 +===== Testing simple wires between modules =====
 +
 +The verilog for two simple modules to demonstrate connecting wires are:
 +
 +<code verilog >
 +`include "​innermodule.v"​
 +
 +module top;
 +
 +    wire w_inputForInnerModule;​
 +    wire w_outputFromInnerModule;​
 +
 +
 +    InnerModule innermodule
 +    (
 +        .i_inner_input(w_inputForInnerModule),​
 +        .o_inner_output(w_outputFromInnerModule)
 +    );
 +
 +endmodule
 +</​code>​
 +
 +
 +<code verilog >
 +module InnerModule
 + (
 + input i_inner_input,​
 + output o_inner_output
 + );
 +
 +    assign o_inner_output = i_inner_input;​
 +
 +endmodule
 +</​code>​
 +
 +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.
 +
 +<code verilog >
 +`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
 +</​code>​
 +
 +<code verilog >
 +module InnerModule
 + (
 + input i_inner_input,​
 + output o_inner_output
 + );
 +
 +    assign o_inner_output = i_inner_input;​
 +
 +endmodule
 +</​code>​
 +
 +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:
 +
 +<code verilog >
 +`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
 +</​code>​
 +
 +See [[gtkwave_simulation_for_ice|FPGA Verilog simulation using GTKWave]] if you need help setting up testbenches for use in GTKWave simulations.
 +
 +{{ :​verilog:​inner-output-to-wire.png?​direct |}}
 +
 +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:
 +
 +<code verilog >
 +//bad InnerModule
 +module InnerModule
 +    (
 +        input i_inner_input,​
 +        output reg o_inner_output = 1'b0
 +    );
 +
 +    assign o_inner_output = i_inner_input;​
 +
 +endmodule
 +</​code> ​
 +
 +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:
 +
 +<code verilog >
 +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
 +</​code>​
 +  ​
 +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?:
 +
 +<code verilog >
 +//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
 +</​code>​
 +
 +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:
 +
 +<code verilog >
 +`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
 +</​code>​
 +
 +And this will be fine. Again, let's test it using the testbench from before:
 +
 +{{ :​verilog:​inner-output-to-wire.png?​direct |}}
 +
 +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 ====
 +https://​www.youtube.com/​watch?​v=zWEgSHZ5ex4
verilog_wire_and_reg.txt ยท Last modified: 2021/03/04 10:41 by sausage