0
votes

I designed a 16-by-16 multiplier in verilog. It compiles with no errors but results are not correct. Can anybody help me by the code reformation?

The code is:

module q_1_2 (input [15:0]x,y, output [31:0]z);

  parameter size=256, width=16;
  wire [size-1:0]pi,ci,po,co;

  genvar  i,j;
  generate

    for (j=0;j<16;j=j+1) assign pi[width*0+j]=0;
    for (i=0;i<16;i=i+1) assign ci[width*i+0]=0;
    q_1_1 eb0_0 (x[0],y[0],pi[o],ci[0],po[0],co[0]);

    for (j=1;j<16;j=j+1) begin
     assign ci[width*0+j] = co[width*0+(j-1)];
     q_1_1 eb0_j (x[0],y[j],pi[width*0+j],ci[width*0+j],po[width*0+j],co[width*0+j]);
    end

    for (i=1;i<16;i=i+1) begin
     assign pi[width*i+0] = po[width*(i-1)+0];
     q_1_1 ebi_0 (x[i],y[0],pi[width*i+0],ci[width*i+0],po[width*i+0],co[width*i+0]);
    end

    for (i=1;i<16;i=i+1) begin
      for (j=1;j<15;j=j+1) begin
        assign ci[width*i+j] = co[width*i+(j-1)];
        assign pi[width*i+j] = po[width*(i-1)+j];
        q_1_1 ebi_j (x[i],y[j],pi[width*i+j],ci[width*i+j],po[width*i+j],co[width*i+j]);
      end

      assign ci[width*i+15] = co[width*i+14];
      assign pi[width*i+15] = co[width*(i-1)+15];
      q_1_1 ebi_15 (x[i],y[15],pi[width*i+15],ci[width*i+15],po[width*i+15],co[width*i+15]);
    end

    for (i=0;i<16;i=i+1) assign z[i] = po[width*i+0];
    for (j=1;j<16;j=j+1) assign z[j+15] = po[width*15+j];
    assign z[31] = co[width*15+15];

  endgenerate
endmodule

where the q_1_1 module is:

module q_1_1 (input xi,yi,pi,ci, output po,co);
  wire i,j,k,l,m,n;
  and #5 (i,xi,yi);
  and #5 (j,pi,i);
  and #5 (k,ci,i);
  and #5 (l,pi,ci);
  or #5 (m,j,k);
  or #5 (co,l,m);
  xor #5 (n,pi,i);
  xor #5 (po,ci,i);
endmodule

and the tb is:

module testq_1_2();

reg [15:0] xx,yy;
wire[31:0] zz;

q_1_2 eb(xx,yy,zz);

initial begin
    #0       xx=0;     yy=0;
    #1000    xx=9;     yy=11;
    #1000    xx=16;    yy=8;
    #1000    xx=14;    yy=14;
    #1000    xx=7;     yy=12;
    #1000    xx=24;    yy=3;
    #1000    xx=83;    yy=201;
    #1000    xx=24831; yy=19047;
    #1000    xx=0;     yy=0;
    #1000;
   end
endmodule

so what's wrong?

tnx!

1

1 Answers

0
votes

Even though it compiles, the connections are incorrect. For example, ci[width*i] where i>0 will have two drivers, one is the assign statement assign ci[width*i+0]=0; and the other is assign ci[width*0+j] = co[width*0+(j-1)];. Similar problem for pi[width*i]. There is also pi[o] which I believe should be pi[0]. The q_1_1 module has unused gates and nets. The code doesn't have any comments or labels which makes it hard to follow.

Try splitting the carry. One group as the carry out for each partial sum. The other as a local net withing the generate for-loop. In general creating local nets with in a generate for-loop can help with readability and are probable. Instead of debugging a 16-by-16 multiplier, shrink it down to a 4-by-4 or 2-by-2. It will be easier to debug. You are already have the parameter, just need to use it in a few more places.

Below code is a sample how the connections should work for a multiplier. I removed the logic portions since this question appears to be homework.

wire [WIDTH*WIDTH-1:0] pp,mask;
wire [WIDTH-1:0] rco; // ripple carry out

assign rco[0] = 1'b0;
assign pp[WIDTH-1:0] = mask[WIDTH-1:0];

genvar i,j;
generate
    for (i=0; i<WIDTH; i=i+1) begin : mask_mux
        assign mask[WIDTH*i +: WIDTH] = // mux logic ...
    end

    for (i=1; i<WIDTH; i=i+1) begin : ripple_adder
        // These wire are local to this scope
        wire [WIDTH-1:0] part_sel;
        wire [WIDTH:0] carry;
        assign carry[0] = 1'b0;
        assign part_sel[WIDTH-1] = rco[i-1]; 
        assign part_sel[WIDTH-2:0] = pp[WIDTH*(i-1)+1 +: WIDTH-1];
        for (j=0; j<WIDTH; j=j+1) begin : bit_adder
            // adder logic ...
        end
        assign rco[i] = carry[WIDTH];
    end
    for (i=0; i<WIDTH;i=i+1) begin : output_lsb
        assign z[i] = pp[WIDTH*i];
    end
endgenerate
assign z[WIDTH*2-1:WIDTH] = {rco[WIDTH-1],pp[WIDTH*WIDTH-1 -: WIDTH-1]};