Turn 2 bit module (Multiplier) into more bits - verilog

I have the following code for a 2 bit multiplier:
module Multiplier (a0, a1, b0, b1, c[3:0]);
output [3:0]c;
input a0, a1, b0, b1;
wire a0b1, a1b0, ha0c, a1b1;
and (c[0], a0, b0);
and (a0b1, a0, b1);
and (a1b0, a1, b0);
HalfAdder ha0 (a1b0, a0b1, c[1], ha0c);
and (a1b1, a1, b1);
HalfAdder ha1 (ha0c, a1b1, c[2], c[3]);
endmodule
I want to be able to expand this to more than 2 bits though (32 bits). The structure of my code poses a challenge for this though. First off I would have to have 68 parameters for the module. Also I would have to manually create 64 wires (duplicates of wire a0b1, a1b0, ha0c, a1b1). Finally I would need to manually write out a bunch of logic gates and HalfAdder modules to connect all the logic. Because of this I am wondering if there is a way that I can refactor my code to be able to instantiate a binary multiplier of n (a passed parameter) size.

You need to parameterize and use a generate block. (And it is much better to use a synchronous circuit then an asynchronous circuit).
Here is an incomplete example, you can fill in the necessary logic :
module Multiplier (a, b, c, clk);
parameter WIDTH = 64;
output [2*WIDTH:0]c;
input [WIDTH-1:0]a;
input [WIDTH-1:0]b;
input clk;
genvar i;
generate for (i = 0; i < WIDTH; i <= i + 1)
begin : shifts
// shift a 1-bit for each i and 'logical and' it with b
reg [WIDTH + i :0]carry;
wire [WIDTH + i -1:0]shifted = {a,i{0}} & b[i];
// sum the result of shift and 'logical and'
always # (posedge clk)
begin
carry <= shifted + shifts[i-1].carry ;
end
end
assign c = shifts[WIDTH].carry;
endgenerate
endmodule

Related

Expression width 32 does not match width 1 of logic gate array port 1

I have two questions.
No output
Expression width 32 does not match width 1 of logic gate array port 1.
When I write and( OutAnd, a, b);, it shows an error.
Expression width 32 does not match width 1 of logic gate array port 1.
How can I fix it?
By the way. I forbid to use & operator, Procedure Assignment, and always block.
Here's my code:
ALU.v
module ALU(
input [5:0] Signal,
input [31:0] a, b,
output reg[31:0] Output
);
wire[31:0] OutAnd;
and( OutAnd, a, b); // AND <-- error
AluMux alumax0( .Signal(Signal), .in_And( OutAnd ) ); // AND
endmodule
AluMax.v
module AluMux(
input [5:0] Signal,
input [31:0] in_And, in_Or,
output reg[31:0] Output
);
parameter AND = 6'd36;
always # ( * )
begin
case ( Signal )
AND : Output = in_And;
default : Output = 32'd11;
endcase
end
endmodule
The output of the and gate defined to be 1 bit and you want to put 32 bits in it which may cause an error or a warning to solve this you have 2 way either instantiate 32 and gates with the following syntax
and u1 (OutAnd[0], a[0], b[0]);
and u1 (OutAnd[1], a[1], b[1]);
and u1 (OutAnd[2], a[2], b[2]);
.
.
.
and u1 (OutAnd[31], a[31], b[31]);
or use a generate statement here is a sample code
genvar i;
generate
for(i = 0;i < 32;i = i + 1) begin
and u1(OutAnd[i], a[i], b[i]);
end
endgenerate

Taylor Series in Verilog

I am doing my first student Project in Verilog. My project is to calculate log base 2 using "Taylor Series" in Fixed-Point arithmetic (s4.27). I have implemented the Horner's method as well in my code.
Overall it looks like this:
log=c0+(q*(c1+(q*(c2+(q*(c3+(q*(c4(q*(c5+(q*c6))))))))));
Finally log_base_2=log*con;
`timescale 10ns/10ns
module log (q ,clk,log_result);
input clk;
input [31:0] q; // q=x-a; x=user input, a=1.5 (Taylor series is calculated around point "a")
output [31:0] log_result;
localparam con= 32'h0B8AA3B0; //1.44269504088895
localparam c0 = 32'h033E647C; //0.40546510810816
localparam c1 = 32'h05555558; //0.66666666666666
localparam c2 = 32'hFE38E38E; //-0.222222222222
localparam c3 = 32'h00CA4588; //0.0987654321
localparam c4 = 32'hFF9ADD3C; //-0.04938271605
localparam c5 = 32'h0035F068; //0.02633744856
localparam c6 = 32'hFFE208AA; //-0.01463191587
wire [31:0] x0,x1,x2,x3,x4,x5,x6;
wire [31:0] y0,y1,y2,y3,y4,y5,y6;
multiplier #(27,32) m6(.i_multiplicand(q),.i_multiplier(c6),.o_result(x6));
adder #(27,32) a6 (.a(x6),.b(c5),.c(y6));
multiplier #(27,32) m5(.i_multiplicand(q),.i_multiplier(y6),.o_result(x5));
adder #(27,32) a5 (.a(x5),.b(c4),.c(y5));
multiplier #(27,32) m4(.i_multiplicand(q),.i_multiplier(y5),.o_result(x4));
adder #(27,32) a4 (.a(x4),.b(c3),.c(y4));
multiplier #(27,32) m3(.i_multiplicand(q),.i_multiplier(y4),.o_result(x3));
adder #(27,32) a3 (.a(x3),.b(c2),.c(y3));
multiplier #(27,32) m2(.i_multiplicand(q),.i_multiplier(y3),.o_result(x2));
adder #(27,32) a2 (.a(x2),.b(c1),.c(y2));
multiplier #(27,32) m1(.i_multiplicand(q),.i_multiplier(y2),.o_result(x1));
adder #(27,32) a1 (.a(x1),.b(c0),.c(y1));
multiplier #(27,32) (.i_multiplicand(con),.i_multiplier(y1),.o_result(x0));
assign log_result = x0;
endmodule
Test bench code:
`timescale 10ns/10ns
module tb_log ();
reg clk;
reg [ 31 : 0 ] q;
wire [ 31 : 0 ] log_result;
log log_i (
.q(q),
.clk(clk),
.log_result(log_result)
);
parameter CLKPERIODE = 100;
initial clk = 1'b1;
always #(CLKPERIODE/2) clk = !clk;
initial begin
$dumpfile("log_wave.vcd");
$dumpvars(1);
$monitor ("Q=%h,Log2=%h ", q, log_result);
#1
#(CLKPERIODE)
q = 32'hFC000000; // q=1-1.5=-0.5;
$finish();
end
endmodule
So I am expecting a result close to zero. But unfortunately I am getting 9B917CED. When I tried to include clock an error naming "Malformed Statement" occurred. I am using Icarus verilog for compiling.
Code for fixed-point multiplier(qmult) and adder(qadd)
I am sure there are bugs but currently my rookie eyes are unable to notice it.
What am I missing?
I suggest you do just one multiplication and one adder and check the result of that. Fixed point multiplications should be very well checked for overflowing, which I very strongly suspect is the case here!
It is a problem I have seen again and again: multipliers in all Verilog examples take two N bit numbers and produce a 2N result. Very few sources tackle e.g. a 20 stage FIR filter where you have twenty multipliers each using two 16 bit numbers. Following "example" code you end up with a 52 bit wide result.
To prevent overflow each argument of the multiplication should be <16 bits. (As you are using 32 bits results). Then every time you add you need another extra bit. Thus either your data gets wider further down the stream, or you have to start sufficiently small that it fits in the en result of 32 bits.
You can compensate if you have constant values and know what range of the result is. e.g. in a digital filter all coefficients add up to 1 and they are often positive, negative,positive, negative so the additions do not all increment all the time.
Welcome to the world of hardware integer arithmetics!

Verilog module for ALU but doesn't work properly

I am trying to write down ALU for verilog.
And there are several error I experiences.
First of all, here is my code:
module yAlu(z, ex, a, b, op);
input [31:0] a, b;
input [2:0] op;
output [31:0] z, ztemp;
output ex;
wire[31:0]a0,a1,a2,a3,a4, atemp;
assign slt = 0;
assign ex = 0;
assign a0 = a & b;
assign a1 = a | b;
assign a2 = a + b;
assign a3 = a - b;
assign a4 = a[31] ^ b[31];
yMux #(32) lo(zLo, a0, a1, op[0]);
yMux #(32) hi(zHi, a2, a3, op[0]);
yMux #(32) temp(atemp, zLo, zHi, op[1]);
assign z = (op[2] == 1) ? a4 : atemp;
assign slt = z;
endmodule
And yAlu.v uses following:
module yMux(z, a, b, c);
parameter SIZE = 2;
output [SIZE-1:0] z;
input [SIZE-1:0] a, b;
input c;
yMux1 mine[SIZE-1:0](z, a, b, c); // 2-­bit 2 -­to-­1 mux and it would be cumbersome to write 32 mux instantiation lines.
endmodule
Lastly above yMux uses following:
module yMux1(z, a, b, c);
output z;
input a, b, c;
wire notC, upper, lower;
// Gates and interconnections for MUX
// if c is 0, z=a.
// if c is 1, z=b
not my_not(notC, c);
and upperAnd(upper, a, notC);
and lowerAnd(lower, c, b);
or my_or(z, upper, lower);
endmodule
Here is is what it tests above yAlu:
module lab8;
reg [31:0] a, b;
reg [31:0] expect;
reg [2:0] op;
wire ex;
wire [31:0] z;
reg ok, flag;
yAlu mine(z, ex, a, b, op);
initial begin
repeat (10) begin
a = $random; b = $random;
if(op==0)
expect = a & b;
else if (op==1)
expect = a | b;
else if (op==2)
expect = a + b;
else if (op==3)
expect = a - b;
else if (op==4)
expect = (a < b) ? 1 : 0;
#1;
if(expect == z)
$display("PASS : expected=%d, a=%d, b=%d, z=%d, op=%d", expect,a,b,z,op);
#1;
$finish;
end
end
endmodule
My questions in order as follow:
Question 1.
Code above only works for 0 and 1. It doesn't work more than that.
For example, on the 2nd source code, there is
a = $random; b = $random;
it doesn't work for this. it only works when a=1 or 0 and b=1 or 0.
Question 2.
I am not sure "slt" function is working correctly. The instructor who teaches this never told me what slt does in lecture but have us design slt, by googling or something.
Question 3.
Whenever I compile, i get following Error. Why is this?
yAlu.v:38: warning: Port 1 (z) of yMux expects 32 bits, got 1.
yAlu.v:38: : Padding 31 high bits of the port.
yAlu.v:39: warning: Port 1 (z) of yMux expects 32 bits, got 1.
yAlu.v:39: : Padding 31 high bits of the port.
yAlu.v:40: warning: Port 2 (a) of yMux expects 32 bits, got 1.
yAlu.v:40: : Padding 31 high bits of the port.
yAlu.v:40: warning: Port 3 (b) of yMux expects 32 bits, got 1.
yAlu.v:40: : Padding 31 high bits of the port.
I can't fix this at all.
I don't even know I am doing it correctly. The manual that directs me to do what it says has no enough explanation as well as no sample output.
I couldn't finish in time anyway, so I guess it doesn't matter but I think I have to know solution for my problems.
Thank you very much if you can help me out.
As shown by the warnings, your port connection width are mismatched. Refer to single warning and other are the same to tackle.
yAlu.v:38: warning: Port 1 (z) of yMux expects 32 bits, got 1.
yAlu.v:38: : Padding 31 high bits of the port.
The module declares ports a,b,c and z, each of width defined by SIZE parameter.
module yMux(z, a, b, c);
parameter SIZE = 2;
output [SIZE-1:0] z;
input [SIZE-1:0] a, b;
Moreover, the SIZE is overridden while instantiating. Now, the value of SIZE is 32. Hence the width of each of a,b,c and z is 32-bits.
yMux #(32) lo(zLo, a0, a1, op[0]);
yMux #(32) hi(zHi, a2, a3, op[0]);
yMux #(32) temp(atemp, zLo, zHi, op[1]);
Here, the ports zLo,zHi is not declared and used directly in port connection.
Referring to IEEE 1800-2012, section 6.10- Implicit declarations:
If an identifier is used in a port expression declaration, then an
implicit net of default net type shall be assumed, with the vector
width of the port expression declaration.
This, if an undeclared identifier is used as a connection to an instance then an implicit net is inferred.
Thus, zLo,zHi are implicitly declared as single bit nets and the rest 32-bits are padded with zeros. Just declare them as follows and all warnings shall be removed:
wire [31:0] zLo,zHi;
To get an error in such a situation, use default_nettype none compiler directive.
For more information, refer Sutherland SV Gotchas paper, section 2.2 and SystemVerilog IEEE 1800-2012 for implicit declarations.

how to define N bus with width 32bit

I wanted to define large number of bus with bus width 32bit.
for example
input [31:0] a0, a1, a2, .... aN;
input [31:0] b0, b1, b2, .... bN;
output [31:0] c0, c1, c2, .... cN;
c0 = a0 + b0;
c1 = a1 + b1;
.
.
cN = aN + bN;
how can I realize this code with iteration?
Verilog Generates are designed for solving this issue. It would be easier if you can use unpacked arrays for ports.
Statements need to be contained in an initial or always, to imply the output is a flip-flop use always #(posedge clk) for a combinatorial circuit use always #*.
module example (
parameter N = 10
)(
input clk,
input [31:0] a [0:N],
input [31:0] b [0:N],
output reg [31:0] c [0:N]
);
genvar i;
generate
for(i=0; i<=N; i++) begin
always #(posedge clk) begin
c[i] <= a[i] + b[i];
end
end
endgenerate
endmodule
Generates are good when you need to parameterise module instance, the above can be rewritten with a plain for loop.
integer i;
always #(posedge clk) begin
for(i=0; i<=N; i++) begin
c[i] <= a[i] + b[i];
end
end
For synthesizable code the for loop must be able to be statically unrolled.

Using created ALU to make a bigger one

I have a 8-bit ALU unit in verilog that can do addition, invert, etc. This single unit is tested and performs correctly. When I combine 4 of these to make a bigger ALU every output is correct except when I choose the addition operation it comes out as
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx01010101, basically the first alu does the work right then the output from the second is xxxxxxxx as is the third and fourth. This is really frustrating!!
the 8 bit module( it would be nice to point if this model is behavioral or structural model i go for the former!)
module alu_8bit(
output reg [7:0] out,
output reg cout,g,e,
input [7:0] A,B,
input cin,
input [2:0] S
);
//used functions
parameter BUF_A = 3'b000;
parameter NOT_A = 3'b001;
parameter ADD = 3'b010;
parameter OR = 3'b011;
parameter AND = 3'b100;
parameter NOT_B = 3'b101;
parameter BUF_B = 3'b110;
parameter LOW = 3'b111;
always #(A or B or S) begin
//Comparator
g = A>B;
e = A==B;
//Other selective functions
case(S)
BUF_A: out = A;
NOT_A: out = ~A;
ADD: {cout,out} = A+B+cin;
OR: out = A | B;
AND: out = A & B;
NOT_B: out = ~B;
BUF_B: out = B;
LOW: out = {8{1'b0}};
endcase
end
endmodule
Here is the code of the bigger one:
module alu_32bit(
output [31:0] out,
output cout,g,e,
input [31:0] A,B,
input cin,
input [2:0] S
);
wire e1,e2,e3,e4;
wire g1,g2,g3,g4;
alu_8bit ALU1(out[7:0],cin2,g1,e1,A[7:0],B[7:0],cin,S);
alu_8bit ALU2(out[15:8],cin3,g2,e2,A[15:8],B[15:8],cin2,S);
alu_8bit ALU3(out[23:16],cin4,g3,e3,A[23:16],B[23:16],cin3,S);
alu_8bit ALU4(out[31:24],cout,g4,e4,A[31:24],B[31:24],cin4,S);
assign g = g4 | (e4 & g3) |(e4 & e3 & g2) | (e4& e3 & e2 & g1);
assign e = e4 & e3 & e2 & e1;
endmodule
Can any one give some help?! if you need more info just tell me.
Edited:
Waveform pic clearly input comes in correct but output not
The dataflow diagram shows that ALU1 output is just fine
Your sensitivity list for the main part of the ALU doesn't include cin.

Resources