FPGA gets its power from the flexibility. The design process can be time-consuming but you can design basically anything. In this project, I will give some examples of the multiplication and flexibility of FPGAs.

 

Multiplication consumes time and sometimes they specify the whole performance of the system. Impulse response or Fourier transform of the discrete signal is calculated by multiplying and adding the massive number of samples because of that the power of the digital signal processor(DSP) chips are compared with their multiplication and addition (MAC) numbers in a second. FPGAs, which provides custom solutions, are used in many applications which require huge MAC operations like military radar applications, adaptive noise cancellations, machine vision, HDTV and etc. The multiplication operation can be performed in many ways on FPGA. Based on the application, it can be implemented parallel or pipelined where the speed is important or it can be implemented to cost small footprint.

 

The DE0-Nano device 149 configurable pins therefor I will use 32*32 multiplier for the test. You can have more bits to multiply but you can't assign them to the pins. Hence, this is the demonstration of different methodologies, I don't use any other design than the multiplier.

 

Altera Megafunction

Let's start with the easiest way of multiplication using the libraries   Altera has something called Megafunctions and it is stated like:

 

As design complexities increase, use of vendor-specific intellectual property (IP) blocks has become a common design methodology. Altera provides parameterizable megafunctions that are optimized for Altera device architectures. Using megafunctions instead of coding your own logic saves valuable design time. Additionally, the Altera-provided functions may offer more efficient logic synthesis and device implementation. You can scale the megafunction’s size by setting parameters.

 

The Code:

module multiplier(m,q,result);  
  
  input [31:0]m;  
  input [31:0]q;  
  output [63:0]result;  
  
  assign result = m * q;  
  
endmodule 

 

The Result:

 

RTL Viewer:

 

It looks like the Altera EP4CE22F17C6  has built-in hardware multipliers and if use "a * b"  it is automatically done by the dedicated multiplier. The multiplication is done by using lpm_mult  megafunction. It only uses 79 logic elements. It looks like Altera megafunctions are working as expected. They save time and create an efficient logic synthesis. * b

 

The lpm_mult megafunction can be implemented using either logic resources or dedicated multiplier circuitry in Altera devices. Typically, the lpm_mult megafunction is translated to the dedicated multiplier circuitry when it is available because it provides better performance and resource utilization.

 

Array Multiplier

Another design method is array multiplier. Multiplier m and multiplicand q are multiplied by using array multiplier as shown in Figure Array Multiplier which is same as the paper and pencil multiplication. Summands are calculated by multiplying m with each bit of the q by BasePPI module at the top layer and PPI modules in other layers. In order to make the code more readable n-bit BasePPI and PPI modules are used and n-1 layer is generated with a loop. The size of the design is controlled by parameters n.

 

Array Multiplier

 

The Code:

 

module multiplier (m, q, result);


parameter n=32;
//assign inputs and outputs
input [n-1:0] m, q;
output  [2*n-1:0] result;




and(result[0],m[0],q[0]);


wire [n-1:0]link[n-1];


genvar i;
generate 
for(i=0;i<n-1;i=i+1)
begin:layers
if(i==0)
BasePPI(m,q[1:0],link[i],result[i+1]);
else
PPI(link[i-1], m, q[i+1] , link[i], result[i+1]);
end
assign result[2*n-1:n]=link[n-2];
endgenerate


endmodule


//****************************************************
//higher tier adder cell instantiating full adder


module PPI(PPI_bit, m, q, ,out,px);


//assign inputs and outputs
parameter n=4;
input [n-1:0] PPI_bit, m;
input q;
output [n-1:0]out;
output  px; 


genvar i;
generate


wire [n-1:0]link;

for(i=0;i<n;i=i+1)
begin:PPILayers
if(i==0)
half_adder( (q & m[i]),PPI_bit[i],px,link[i]);
else
full_adder( (q & m[i]),PPI_bit[i],link[i-1],out[i-1],link[i]);
end
assign out[n-1]=link[n-1];
endgenerate


endmodule




//*****************************************************
//base tier adder cell instantiating full adder


module BasePPI(m, q,out,px);


//assign inputs and outputs
parameter n=4;


input [n-1:0]m;
input [1:0]q;
output [n-1:0]out;
output px;  //product output


genvar i;


generate


wire [n-1:0]link; // for carry link 

for(i=0;i<n;i=i+1)
begin:basePPI
if(i==0)
half_adder( (q[1]& m[i]),(q[0] & m[i+1]),px,link[i]);
else if (i==n-1)
half_adder( (q[1]& m[i]),link[i-1],out[i-1],out[i]);
else
full_adder( (q[1]& m[i]),(q[0] & m[i+1]),link[i-1],out[i-1],link[i]);
end
endgenerate


endmodule




//**************************************************
//full adder
module full_adder( a, b, carry_in, sum, carry_out);


//assign inputs and outputs


input a, b, carry_in;
output reg sum, carry_out;


always
{carry_out,sum}=a+b+carry_in;




endmodule


//half adder
module half_adder( a, b, sum, carry_out);


//assign inputs and outputs


input a, b;
output reg sum, carry_out;


always
{carry_out,sum}=a+b;




endmodule

 

The result:

The output result shows that 251 logic element is used without using any embedded multipliers. It is a little larger than Altera megafunction. The RTL viewer is more complicated but acceptable.

 

RTL Viewer:

Sequential Multiplier

Assume the multiplicand (A) has N bits and the multiplier (B) has M bits. If we only want to invest in a single N-bit adder, we can build a sequential circuit that processes a single partial product at a time and then cycle the circuit M times.

This is how the sequential multiplier is described. The description depicts it will be space efficient but the implementation doesn't show it is correct. Maybe, my design is not efficient, I am still learning the language.

 

 

 

The Code:

module multiplier (m, q, result);


parameter n=32;


//assign inputs and outputs
input [n-1:0] m, q;
output [n+n-1:0] result;
reg [n-1:0] A,B;
reg [n-1:0]P;
reg carry;


  assign result = {P,B};
  
integer i;


always
begin
#1
for(i=0;i<n+1;i=i+1)
begin
if(i==0)
begin
A=m;
B=q;
P=0;
carry=0;
end
else
begin
          {carry, P} = P + (B[0]==1 ? A : 0) ;
{carry, P, B} = {carry,P,B}>>1;
end

end


end


endmodule

 

The Result:

This supposed to be a small footprint and slower but the result shows that it has the biggest footprint. It locates 2,046 logic elements which are much more than the other methods.

 

 

RTL Viewer:

The RTL viewer is much more complicated. It doesn't look like something understandable in a short time.

Test Code

When you design a circuit, you need to test it. But, the manual test can be time-consuming therefore it is good practice to write a test code for your design. You can test the design I have written up with the following test code. You can use Modelsim-Altera but if you don't want to install EDA tools you can use edaplayground.com. It has some limitations but easy to use. The following code doesn't test the all the input variables because of the limitations on edaplayground. You only need to change m and q variables in the for loops. The code below only checks for if the output is correct with the current inputs. There is no timing analysis.

 

module aritmetik_tst();

  // inputs and outputs for test circuit
  reg [31:0] m, q;
  wire [63:0] result;
  reg flag;
  integer i,j;

  // connection between testbench and design        
  multiplier i1 (  
    .m(m),
    .q(q),
    .result(result)
  );
initial
  begin
    m=0;
    q=0;
  end
  
  
always
begin                                                                     flag = 1;
  for (m = 1; m < 64; m = m + 1)
    begin
      for (q = 1; q < 64; q = q + 1)
       begin
        #1;
         if (result != m * q)
        begin
          flag = 0;
          $display("Test failed at %d x %d", q, m );
        end 
       end //end of for(m)
    end//end of for(q)
  
  if(flag==0)
    $display("Test Failed, End of Simulation");
  else
    $display("Test Successful, End of Simulation");
$finish;                                          
end     
  
endmodule

 

 

Result:

FPGA is so flexible you can almost design everything but it may be time-consuming. It looks like it is better to use Altera functions and trust the vendor. Quartus is so sophisticated software and I think vendor optimise their functions with cooperation between EDA tool and underlying hardware.