Verilog: Instantiating arrays in modules - verilog

Let's say I have an adder module
module adder(
input [3:0] A,
input [3:0] B,
output [4:0] F
);
assign F = A + B;
endmodule;
and a toplevel module:
module toplevel(
input [3:0] X,
input [3:0] Y,
output [4:0] Z
);
adder adder_1(
.A(X),
.B(Y),
.F(Z)
);
endmodule;
Where I want to instantiate the adder. Would I be able to instantiate a module by assigning numbers to individual bits in its array?
For example can I write something like,
adder adder_1(
.A[0](X[0]),
.A[1](X[1},
and so on. Is there a way I can directly assign bit 0 of A from the adder module to a bit in the top level module?

You can use a temporary wire if your intention is to do some logic operations
on the toplevel port x bit by bit, the example below ands the 2nd bit only
of the port x with 0 and then connects it to the adder module
a quick example
wire [3 : 0] temp;
assign temp[0] = x[0];
assign temp[1] = x[1] & 1`b0;
assign temp[2] = x[2];
assign temp[3] = x[3];
adder adder_1(
.A(temp),
.B(Y),
.F(Z)
);

Yes, it is possible. in your case it would be like :
module toplevel(
input [3:0] X,
input [3:0] Y,
output [4:0] Z
);
adder adder_1(
.A({X[3],X[2],X[1],X[0]}),
.B(Y),
.F(Z)
);
endmodule;

Related

why output of 2nd function call to 4 bit adder is X(don't care)?

I am new to verilog, I was building a 32-bit adder using structural modelling. So I made a 1-bit full adder, then used that to construct a 4-bit adder, and that was used to create an 8- bit adder.
Everything works fine until the 4-bit adder but when I use the 4-bit adder as a function this error pops up.
module adder_1bit(Sum,CarryOut,A,B,CarryIn);
output Sum,CarryOut;
input A,B,CarryIn;
assign Sum = A^B^CarryIn;
assign CarryOut = (A&B) | (B&CarryIn) | (A&CarryIn);
endmodule
module adder_4bit(Sum,CarryOut,A,B,CarryIn);
output [3:0] Sum;
output CarryOut;
input [3:0] A,B;
input CarryIn;
wire w[2:0];
assign CarryIn = 1'b0;
adder_1bit add0(Sum[0],w[0],A[0],B[0],CarryIn);
adder_1bit add1(Sum[1],w[1],A[1],B[1],w[0]);
adder_1bit add2(Sum[2],w[2],A[2],B[2],w[1]);
adder_1bit add3(Sum[3],CarryOut,A[3],B[3],w[2]);
endmodule
module adder_8bit(Sum,CarryOut,A,B,CarryIn);
output [7:0] Sum;
output CarryOut;
input [7:0] A,B;
input CarryIn;
wire w;
assign CarryIn = 1'b0;
adder_4bit add4(Sum[3:0],w,A[3:0],B[3:0],CarryIn);
adder_4bit add5(Sum[7:4],CarryOut,A[7:4],B[7:4],w);
endmodule
When I run with the following testbench code I get MSB 4-bit get as don't care
module adder_test;
reg [7:0] A,B;
reg CarryIn;
wire [7:0] Sum;
wire CarryOut;
adder_8bit UUT (Sum,CarryOut,A,B,CarryIn);
initial
begin
A = 8'b00101011;
B = 8'b01010110;
CarryIn = 1'b0;
#10;
end
endmodule
Simulation Result
Your problem is in this statement: assign CarryIn = 1'b0;
The following happens:
module adder_4bit(Sum,CarryOut,A,B,CarryIn);
...
assign CarryIn = 1'b0;
In this case you have carryIn driven by two drivers:
the input port
the assign statement
Unless the value of the port is the same as your driver (1'b0) the resulting value of carryIn will always be 'x'. This interferes with all your results.
To fix the issue just move this statement to your test bench:
module adder_test;
...
wire CarryOut = 0;

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.

Connect 5-bit bus to 32-bit output bus

My design needs multiple multiplexers, all of them have two inputs and most are 32 bits wide. I started with designing the 32 bit, 2:1 multiplexer.
Now I need a 5 bit, 2:1 multiplexer and I want to reuse my 32 bit design. Connecting the inputs is easy (see code below), but I struggle to connect the output.
This is my code:
reg [4:0] a, b; // Inputs to the multiplexer.
reg select; // Select multiplexer output.
wire [4:0] result; // Output of the multiplexer.
multiplex32_2 mul({27'h0, a}, {27'h0, b}, select, result);
When I run the code through iverilog, I get a warning that says that the multiplexer expects a 32 bit output, but the connected bus is only 5 bit wide. The simulation shows the expected results, but I want to get rid of the warning.
Is there a way to tell iverilog to ignore the 27 unused bits of the multiplexer output or do I have to connect a 32 bit wide bus to the output of the multiplexer?
I don't know of a #pragma or something like that (similar to #pragma argsused from C) that can be used in Verilog.
Xilinx ISE, for example, has a feature called "message filtering", which allows the designer to silence specific warning messages. You find them once, select them, choose to ignore, and subsequent synthesis won't trigger those warnings.
Maybe you can design your multiplexer in a way you don't need to "waste" connections (not actually wasted though, as the synthesizer will prune unused connections from the netlist). A more elegant solution would be to use a parametrized module, and instantiate it with the required width. Something like this:
module mux #(parameter WIDTH=32) (
input wire [WIDTH-1:0] a,
input wire [WIDTH-1:0] b,
input wire sel,
output wire [WIDTH-1:0] o
);
assign o = (sel==1'b0)? a : b;
endmodule
This module has been tested with this simple test bench, which shows you how to instantiate a module with params:
module tb;
reg [31:0] a1,b1;
reg sel;
wire [31:0] o1;
reg [4:0] a2,b2;
wire [4:0] o2;
mux #(32) mux32 (a1,b1,sel,o1);
mux #(5) mux5 (a2,b2,sel,o2);
// Best way to instantiate them:
// mux #(.WIDTH(32)) mux32 (.a(a1),.b(b1),.sel(sel),o(o1));
// mux #(.WIDTH(5)) mux5 (.a(a2),.b(b2),.sel(sel),.o(o2));
initial begin
$dumpfile ("dump.vcd");
$dumpvars (1, tb);
a1 = 32'h01234567;
b1 = 32'h89ABCDEF;
a2 = 5'b11111;
b2 = 5'b00000;
repeat (4) begin
sel = 1'b0;
#10;
sel = 1'b1;
#10;
end
end
endmodule
You can test it yourself using this Eda Playground link:
http://www.edaplayground.com/x/Pkz
I think the problem relates to the output of the multiplexer which is still 5 bits wide. You can solve it by doing something like this:
reg [4:0] a, b; // Inputs to the multiplexer.
reg select; // Select multiplexer output.
wire [31:0] temp;
wire [4:0] result; // Output of the multiplexer.
multiplex32_2 mul({27'h0, a}, {27'h0, b}, select, temp);
assign result = temp[4:0];
This can be easily tested in http://www.edaplayground.com/ using the code below:
( I have re-used #mcleod_ideafix's code)
// Code your testbench here
// or browse Examples
module mux #(parameter WIDTH=32) (
input wire [WIDTH-1:0] a,
input wire [WIDTH-1:0] b,
input wire sel,
output wire [WIDTH-1:0] o
);
assign o = (sel==1'b0)? a : b;
endmodule
module tb;
reg [31:0] a,b;
wire [31:0] o;
wire [4:0] r;
reg sel;
initial begin
$dumpfile("dump.vcd"); $dumpvars;
a = 10; b = 20; sel = 1;
end
mux MM(a,b,sel,o);
assign r = o[4:0];
endmodule
Let me know if you are still getting a warning.

Testbench of floating point adder in verilog

I want to write floating point double precision adder. in the test-bench of that, I have some problems.
*adder is a module which gets two 64bits number and give sum of them.
this is my test bench:
module testadder;
reg [63:0] a;
reg [63:0] b;
wire [63:0] sum;
reg[10:0] expa,expb,expsum;
reg signa,signb,signsum,one;
reg[51:0] fa,fb,fsum;
real ta,tb,fa2,fb2,sumcheck,fsum2,resultmodulesum;
integer i;
reg [10:0]h23;
adder nameofinstance(sum,a,b);
initial begin
for(i=0;i<1000;i=i+1)
begin
h23=1023;
one=1'b1;
a = {$random(),$random()};
b = {$random(),$random()};
#10;
expa=a[62:52]-h23;
expb=b[62:52]-h23;
fa=a[51:0];
fb=b[51:0];
signa=a[63];
signb=b[63];
fa2 = ( $bitstoreal(fa)/(2**52) )+ one ;
ta=(-1)**(signa)*fa2*(2**expa);
fb2 = ( $bitstoreal(fb)/(2**52) ) + one;
tb=(-1)**(signb)*fb2*(2**expb);
sumcheck=ta+tb;
fsum=sum[51:0];
signsum=sum[63];
fsum2 = ( $bitstoreal(fsum)/(2**52) ) +one;
expsum=$bitstoreal(sum[62:52])-1023;
resultmodulesum=(-1)**(signsum)*fsum2*(2**expsum);
if(sumcheck!=resultmodulesum)
$display("wrong");
end
end
endmodule
module adder(sum,a, b);
input [63:0] a;
input [63:0] b;
reg [63:0] fa,fb;
always #(a or b) begin
fa={1'b1,a[51:0],12'b0};
fb={1'b1,b[51:0],12'b0};
end
endmodule
when i add ( $bitstoreal(fa)/(2**52) ) with one , fa2 get 1 ! but when i don't add it , fa2 get real value of (fa/2^52).
so I change my code to something like that to avoid adding with one, but another problem appears!
my change for making ta,tb and resultmodulesum:
(example for fa)
fa2 = ( $bitstoreal(fa)/(2**52) ) ;
ta=(-1)**(signa)*(fa2*(2**expa)+(2**expa));
2.then i understand that ta always get to (-1)**(signa)*(2**expa);
it means that fa2*(2**expa) is 0 ! but i don't know why and what can I do to make it correct.
I think that even if I didn't change my fa2 and fa2 (with one added in it) give correct output, my ta might has a problem.
3.I have another problem in my module that it is really strange!
little part of adder code module comes after test-bench code.
it is that when i debug my code, 63th bit of fb is 0! any idea?
This is not a full answer but more than can be expressed in the comments.
For the model of the floating point double I would have expected to see something along the lines of:
reg [63:0] a;
reg [63:0] b;
//Built in real for verification of code
real result;
real a_real;
real b_real;
initial begin
a = {$random(),$random()};
b = {$random(),$random()};
#1ps;
a_real = $bitstoreal(a);
b_real = $bitstoreal(b);
result = a_real + b_real;
$display("a %64b", a);
$display("b %64b", b);
$display("a_real %f", a_real);
$display("b_real %g", b_real);
$display("result %f", result);
#1ps;
$finish;
end
For splitting the randomised doubles up in to parts I would have expected to see some thing like:
wire a_sign; // 1 bit
wire [10:0] a_exponent;//11 bit
wire [51:0] a_fraction;//52 bit
assign a_sign = a[63] ;
assign a_exponent = a[62:52];
assign a_fraction = a[51:0] ;
wire b_sign; // 1 bit
wire [10:0] b_exponent;//11 bit
wire [51:0] b_fraction;//52 bit
assign b_sign = b[63] ;
assign b_exponent = b[62:52];
assign b_fraction = b[51:0] ;

How can i make my verilog shifter more general?

Here i have a shifter but as of rite now it only works for up to 3 bits. I've been looking and i can't find out how to make it work for up to 8 bits.
module shifter(a,b,out);
input [7:0] a, b;
output [7:0] out;
wire [7:0] out1, out2, out3;
mux_8b_2to1 first(a[7:0], {a[3:0],a[7:4]}, b[2], out1);
mux_8b_2to1 second(out1[7:0], {out1[5:0],out1[7:6]}, b[1], out2);
mux_8b_2to1 third(out2[7:0], {out2[6:0],out2[7]}, b[0], out);
endmodule
What you have is a Barrel Shifter. Two ways to make it more generic are make it a functional model (still synthesis-able) or structural model with a generate block. Both approaches follow IEEE Std 1364-2001 (aka Verilog-2001).
The functional generic approach for a barrel shifter only needs a down-shifter. The general function is out = {in,in} >> (WIDTH-shift) where leftover bits can be ignored. To protect for double-roll (i.e. shift > WIDTH ), use the mod operator on the shift (WIDTH-(shift%WIDTH)).
module barrel_shifter_functional #( parameter CTRL=3, parameter WIDTH=CTRL**2 )
( input wire [WIDTH-1:0] in,
input wire [ CTRL-1:0] shift,
output wire [WIDTH-1:0] out );
assign out = {2{in}} >> (WIDTH-(shift%WIDTH));
endmodule
The structural generic approach for a barrel shifter needs a generate block. The for loop in the generate block will unravel at compile time, not run time like a for loop like in an always block. To keep it generic also have have the 2-to-1 mux have a parametrized width. FYI, you can use the generate block with functional code too, for example comment out the mux_2to1 instantiation and uncomment the assign statement below it. Learn more about the generate block by reading IEEE Std 1800-2012 ยง 27. Generate constructs.
module barrel_shifter_structeral #( parameter CTRL=3, parameter WIDTH=CTRL**2 )
( input wire [WIDTH-1:0] in,
input wire [ CTRL-1:0] shift,
output wire [WIDTH-1:0] out );
wire [WIDTH-1:0] tmp [CTRL:0];
assign tmp[CTRL] = in;
assign out = tmp[0];
genvar i;
generate
for (i = 0; i < CTRL; i = i + 1) begin : mux
mux_2to1 #(.WIDTH(WIDTH)) g(
.in0(tmp[i+1]),
.in1({tmp[i+1][WIDTH-(2**i)-1:0],tmp[i+1][WIDTH-1:WIDTH-(2**i)]}),
.sel(shift[i]),
.out(tmp[i]) );
// assign tmp[i] = shift[i] ? {tmp[i+1][WIDTH-(2**i)-1:0],tmp[i+1][WIDTH-1:WIDTH-(2**i)]} : tmp[i+1];
end : mux
endgenerate
endmodule
module mux_2to1 #( parameter WIDTH=8 )
( input wire [WIDTH-1:0] in0, in1,
input wire sel,
output wire [WIDTH-1:0] out );
assign out = sel ? in1 : in0;
endmodule
Both examples are functionally equivalent and synthesize provided CTRL is less than or equal to the ceiling of log2(WIDTH). Synthesis will likely give different results. The generate method will exclusively use 2-to-1 muxes while the pure functional method will depend on the quality of the optimizer.
Working example # http://www.edaplayground.com/s/6/500
I've used the >> and << operators to generate a synthetizable design using ISEWebPack, as this:
module shifter(
input wire [7:0] a,
input wire [7:0] b,
input wire leftright, // 0=shift right, 1=shift left
output reg [7:0] out
);
always #* begin
if (leftright==0)
out = a>>b;
else
out = a<<b;
end
endmodule
This way, the symthesis tool will know that you want to implement a shifter and can use its own macros to best synthetize it:
Synthesizing Unit <shifter>.
Related source file is "shifter.v".
Found 8-bit shifter logical right for signal <out$shift0002> created at line 30.
Found 8-bit shifter logical left for signal <out$shift0003> created at line 32.

Resources