What is the difference between input and reg in Verilog? - verilog

I have a circuit whose truth value looks like this A =BC+^C[(B and C) or (not C)]
Here I give,
output A;
input B, C;
wire w1, w2;
and (w1, B, C);
not (w2, C);
or (A, w1, w2);
My question is why do we write input B, C; Can we write it as reg B, C;?
What exactly is the difference?.

You are not showing a complete example, but inputs and outputs are part of a hierarchical module declaration. reg is a data type associated with a signal. Typically one encapsulates your circuit in a module, and then you instantiate that module in a top-level module to provide stimulus and observe the outputs.
module circuit( output wire A;
input wire B, C;
wire w1, w2; // internal wires
and (w1, B, C);
not (w2, C);
or (A, w1, w2);
endmodule
module top;
reg B,C; // these are different signals that get connected to the circuit wires
wire A;
circuit c(A,B,C);
initial begin
B = 0; C = 0;
...
endmodule

comparing input and reg is similar to comparing a keyboard to a verilog code. input defines a direction of a port. reg defines a data type.
However, every port has a data type associated with it. Default data type for an input/output port is wire. So input B is the same as input wire B.
Now, the right question is: what would be a differnce between wire and reg.
wire is a data type for describing connection between module instances. Its main characteristic is that it should always be connected and cannot keep is state otherwise. reg can keep the state if not connected. There are multiple differences in usage which you can find in corresponding verilog tutorials.

Related

wire output can be used as an inside variable?

i am learning verilog and i am doing practice questions on https://hdlbits.01xz.net/wiki.
one of the questions is:
so my answer was:
module top_module(
input a,
input b,
input c,
input d,
output out,
output out_n );
wire and_ab;
wire and_cd;
wire or_out;
and(and_ab,a,b);
and(and_cd, c, d);
or(or_out, and_ab, and_cd);
assign out= or_out;
not(out_n,or_out);
endmodule
which is correct without any doubt, but their answer is:
module top_module (
input a,
input b,
input c,
input d,
output out,
output out_n );
wire w1, w2; // Declare two wires (named w1 and w2)
assign w1 = a&b; // First AND gate
assign w2 = c&d; // Second AND gate
assign out = w1|w2; // OR gate: Feeds both 'out' and the NOT gate
assign out_n = ~out; // NOT gate
endmodule
my question is how can it be possible they use 'output' wire as an 'input' to an assign in the same module? its not reg to hold it value, not that i know if you can do it with reg as an 'output' type.
Verilog and SV allow the reading of outputs from within a module.
It is different than VHDL which does not allow the same.

JK-flip flop using gate level description in Verilog give me a timming error

I still playing in the lowest Verilog level (gate level).
I found this post:
https://electronics.stackexchange.com/questions/390661/is-it-possible-to-create-a-working-jk-flip-flop-using-gate-level-description-in
in that I could understand that shoud work the idea, and I could solve to have a Master-Slave JK Flip-Flop for use it as a frequency divider. I use Icestorm toolchain, Yosys is not complaining, but Next-PNR is giving me this error:
ERROR: timing analysis failed due to presence of combinatorial loops, incomplete specification of timing ports, etc.
This is my code:
module syncRX(clk, signal, detect);
output wire [7:0] detect;
input clk, signal;
reg [6:0] det = 7'b1001010;
assign detect = {det, jk5_out};
jk_flip_flop_edge_triggered jk0(.Q(jk5_out), .Qn(Qn), .C(clk), .J(1), .K(1), .RESETn(0));
endmodule // top
module jk_flip_flop_edge_triggered(Q, Qn, C, J, K, RESETn);
output Q;
output Qn;
input C;
input J;
input K;
input RESETn;
wire Kn; // The complement of the K input.
wire D;
wire D1; // Data input to the D latch.
wire Cn; // Control input to the D latch.
wire Cnn; // Control input to the SR latch.
wire DQ; // Output from the D latch, inputs to the gated SR latch (S).
wire DQn; // Output from the D latch, inputs to the gated SR latch (R).
assign D1 = !RESETn ? 0 : D; // Upon reset force D1 = 0
not(Kn, K);
and(J1, J, Qn);
and(K1, Kn, Q);
or(D, J1, K1);
not(Cn, C);
not(Cnn, Cn);
d_latch dl(DQ, DQn, Cn, D1);
sr_latch_gated sr(Q, Qn, Cnn, DQ, DQn);
endmodule
module d_latch(Q, Qn, G, D);
output Q;
output Qn;
input G;
input D;
wire Dn;
wire D1;
wire Dn1;
not(Dn, D);
and(D1, G, D);
and(Dn1, G, Dn);
nor(Qn, D1, Q);
nor(Q, Dn1, Qn);
endmodule
module sr_latch_gated(Q, Qn, G, S, R);
output Q;
output Qn;
input G;
input S;
input R;
wire S1;
wire R1;
and(S1, G, S);
and(R1, G, R);
nor(Qn, S1, Q);
nor(Q, R1, Qn);
endmodule
Well, I can imagine the answer if I ask what happends, I would like to know why and how make it works! Thanks to all!
Loops:
pin syncRX.jk0.dl.D --> pins syncRX.jk0.dl.Q/Qn -->
pins syncRX.jk0.sr.S/R--> pins syncRX.jk0.sr.Q/Qn --> pin syncRX.jk0.dl.D
If you instantiate latch cell from standard library, issues related to timing path and timing check will be handled by that cell.
I would certainly think the loop will be reported by every well-known implementation tool. But since you said Yosys is not complaining, I'm also confused (I haven't used Yosys.)

inout with reg type in verilog

I have used inout with c, but for c to be on the LHS of procedural assignment, it needs to be a reg type variable. Can anyone help me out with this code?
module multiedgeclk(input clk ,[7:0] a,b,d, inout [7:0] c, output reg [7:0]f);
always #(posedge clk)
c <= a + b;
always #(negedge clk)
f = c & d;
endmodule
In verilog inout is the direction of the port. wire or reg is the type of the signal.
If you want to drive a bi-directional port, it should be declare as inout wire or inout and drive it with enable signal
Here is a example of bi-directional port.
module ABC( inout [7:0] c );
reg [7:0] c_out;
reg out_en;
assign c = out_en ? 8'hz : c_out;
/* something here
...
*/
endmodule
An inout port cannot be procedurally assigned. There is nothing to indicate how long to hold that value on the port. This is the problem for any wire. But wires have a strength mechanism for multiple continuous drivers, the highest strength wins. So you can use a continuous assignment to selectively drive a value or turn it off by driving a z value.
wire c;
reg c_reg;
assign c = c_reg;
Now you can procedurally assign c_reg to a value or 8'bz
See my article for more info about wires and reg types.

Verilog: Interface Module Input With a Reg

In the following code:
wire a;
reg b;
assign a = b;
ModuleName foo(a, other wire inputs, ... , wire outputs);
Assume that they are part of a top level module.
I wanted to run an always# block but make changes in the input of a module instantiated in this module.
always#(*) b = c^d; //Some Logic
The thing is, they are wires and cannot be on the LHS in an always# block. Can I make changes to band expect to see them in a i.e. the input of the Module foo.
Yes. Every time you change b, a will change too. That is what an assign statement does. Remember this is hardware. The statement
assign a = b;
means 'drive wire a with whatever value reg b has for all time'.

Confused with ripple carry adder output

I am working on a ripple carry adder using structural verilog, which is supposed to take in two random inputs and calculate accordingly.
The general rca I created calculated correctly, but for some reason I get weird outputs when I add a for loop and use the $random to generate.
Could someone kindly explain where I'm going wrong? Below is my code:
module full_adder(x,y,z,v,cout);
parameter delay = 1;
input x,y,z; //input a, b and c
output v,cout; //sum and carry out
xor #delay x1(w1,x,y);
xor #delay x2(v,w1,z);
and #delay a1(w2,z,y);
and #delay a2(w3,z,x);
and #delay a3(w4,x,y);
or #delay o1(cout, w2,w3,w4);
endmodule
module four_bit_adder(a,b,s,cout,cin);//four_bit_adder
input [15:0] a,b; //input a, b
input cin; //carry in
output [15:0] s; //output s
output cout; //carry out
wire [15:0] c;
full_adder fa1(a[0],b[0],cin,s[0],c0);
full_adder fa2(a[1],b[1],c0,s[1],c1);
.
.
.
full_adder fa16(a[15],b[15],c14,s[15],cout);
endmodule
module testAdder(a,b,s,cout,cin);
input [15:0] s;
input cout;
output [15:0] a,b;
output cin;
reg [15:0] a,b;
reg cin;
integer i;
integer seed1=4;
integer seed2=5;
initial begin
for(i=0; i<5000; i=i+1) begin
a = $random(seed1);
b = $random(seed2);
$monitor("a=%d, b=%d, cin=%d, s=%d, cout=%d",a,b,cin,s,cout);
$display("a=%d, b=%d, cin=%d, s=%d, cout=%d",a,b,cin,s,cout);
end
end
endmodule
Here are two lines from the output that I get:
a=38893, b=58591, cin=x, s= z, cout=z
a=55136, b=58098, cin=x, s= z, cout=z
This is a combinational circuit, so the output changes instantaneously as the input changes. But, here you are apply all the inputs at same timestamp which should not be done since the full_adder module provides 1-timestamp delay. This may not cause problems in this module, but may cause issues while modelling sequential logic. Add a minimum of #10 delay between inputs.
Also, $monitor executes on each change in the signal list, so no need to use it in for loop. Just initialize $monitor in initial condition.
cin is also not driven from the testbench. Default value of reg is 'x and that of wire is 'z. Here, cin is reg, so the default value is displayed, that is 'x
One more thing, you must instantiate the design in your testbench. And connect respective ports. The outputs from testbench act as inputs to your design and vice-versa. This is just like you instantiate full_adder module in four_bit_adder module in design.
Consider testadder as top level module and instantiate design in it. No need of declaring ports as input and output in this module. Declare the design input ports as reg or wire(example: reg [15:0] a when a is design input port) and output ports as wire (example: wire [15:0] sum when sum is design input port).
Referring to your question:
The general rca I created calculated correctly, but for some reason I get weird outputs when I add a for loop and use the $random to generate.
Instead of using $random, use $urandom_range() to generate random numbers in some range. Using SystemVerilog constraints constructs can also help. Refer this link.
Using $urandom_range shall eliminate use of seed1 and seed2, it shall generate random values with some random machine seed.
Following is the module testadder with some of the changes required:
module testAdder();
wire [15:0] s;
wire cout;
// output [15:0] a,b;
// output cin;
reg [15:0] a,b;
reg cin;
integer i;
integer seed1=4;
integer seed2=5;
// Instantiate design here
four_bit_adder fa(a,b,s,cout,cin);
initial begin
// Monitor here, only single time
$monitor("a=%d, b=%d, cin=%d, s=%d, cout=%d",a,b,cin,s,cout);
for(i=0; i<5000; i=i+1) begin
// Drive inputs with some delays.
#10;
// URANDOM_RANGE for input generation in a range
a = $urandom_range(0,15);
b = $urandom_range(0,15);
// a = $random(seed1);
// b = $random(seed2);
// Drive cin randomly.
cin = $random;
$display("a=%d, b=%d, cin=%d, s=%d, cout=%d",a,b,cin,s,cout);
end
end
endmodule
For more information, have a look at sample testbench at this link.

Resources