-1

I am new to verilog and working my way up on a small code for multiplying two fixed point complex numbers, and here is the top module and the testbench I have written for the same but the wave window shows all Z for my inputs, any help will be appreciated

        module complex(a,b,c,d,
        x,y,
        z);
        input  signed [15:0] a,b,c,d;
        
        output reg signed [31:0] x,y;
        output reg signed [63:0]z; //the size is doubled as it will be concatenated
        reg signed [31:0] ac,bd,ad,bc;
      
        
        initial begin
        
        ac=(a*c); 
        bd=(b*d);
        ad=(a*d);
        bc=(b*c);
        
        
        
        x=ac-bd; //real part of the complex number, real is stored in x reg
        y=ad+bc; // imaginary part of the complex number, imaginary is stored in y reg
        z={x,y}; // concatenation of real and imaginary, first 32 bits here are for real, of which 16 bits represent fraction, same concept for imaginary part
        
        end
        endmodule

   // TESTBENCH
   module complextb();
          reg signed [15:0] a,b,c,d;
          wire signed [31:0]x,y;
          wire signed [63:0] z; //the size is doubled as it will be concatenated
           complex DUT (.a(a),
     .b(b),
     .c(c),
     .d(d),
     .x(x),
     .y(y),
     .z(z));

     localparam SF= 2.0**-16.0;

     initial begin
     a=16'b01011000_01000000; 
     b=16'b00011001_01000000;
     c=16'b01011000_01000000;
     d=16'b00010100_01000000;

      #10

      $display("%f,%f", $itor(x*SF),$itor(y*SF));
      end
      endmodule

1 Answers1

0

From the logic you have written, it seems you want a combinational logic (as there is no clock involved). In order to have this work, you need combinational assignments, and in verilog it is better to write them outside of procedural blocks (like your initial begin).

Please also note that initial begin is not synthetizable unless particular use cases which depend on the vendor.

So I fixed you code like this:

module cplx_mul(a,b,c,d,
        x,y,
        z);
        input  signed [15:0] a,b,c,d;
        
        output signed [31:0] x,y;
        output signed [63:0]z; //the size is doubled as it will be concatenated
        wire signed [31:0] ac,bd,ad,bc;
      
        
        
        assign ac = (a*c); 
        assign bd=(b*d);
        assign ad=(a*d);
        assign bc=(b*c);
        
        
        
        assign x=ac-bd; //real part of the complex number, real is stored in x reg
        assign y=ad+bc; // imaginary part of the complex number, imaginary is stored in y reg
        assign z={x,y}; // concatenation of real and imaginary, first 32 bits here are for real, of which 16 bits represent fraction, same concept for imaginary part

endmodule;

And I got the following waveforms:

enter image description here

Note that this logic will have a very long critical path, so it could be better to pipeline the intermediate results, using registers and a clock.

module cplx_mul(clk,rst,a,b,c,d,
        x,y,
        z);
        
        input  clk,rst;
        input  signed [15:0] a,b,c,d;
        
        output signed [31:0] x,y;
        output signed [63:0]z; //the size is doubled as it will be concatenated
        reg signed [31:0] ac,bd,ad,bc;
        reg signed [63:0] x_r,y_r;
      
        always @( posedge clk) 
        begin
          // Synchronous reset
          if (rst) begin 
             ac <= 0; 
             bd <= 0;
             ad <= 0;
             bc <= 0;
             
             x_r <=0;
             y_r <=0;
          end else begin 
             ac <= (a*c); 
             bd <= (b*d);
             ad <= (a*d);
             bc <= (b*c);
             
             x_r <=ac-bd;
             y_r <=ad+bc;
          end
        end 
        
        assign x = x_r;
        assign y = y_r;
        assign z={x,y}; // concatenation of real and imaginary, first 32 bits here are for real, of which 16 bits represent fraction, same concept for imaginary part
        
        
endmodule

And the new testbench with the clock

module cplx_mul_tb();
          reg signed [15:0] a,b,c,d;
          wire signed [31:0]x,y;
          wire signed [63:0] z; //the size is doubled as it will be concatenated
          reg clk,rst;
          
      cplx_mul DUT (
      .clk(clk),
      .rst(rst),
      .a(a),
     .b(b),
     .c(c),
     .d(d),
     .x(x),
     .y(y),
     .z(z));
     
    
     localparam SF= 2.0**-16.0;
     
     initial clk = 0;
     always #10 clk=~clk;

     initial begin
     
     rst = 1;

       
     $dumpfile("dump.vcd"); $dumpvars;
     a=16'b01011000_01000000; 
     b=16'b00011001_01000000;
     c=16'b01011000_01000000;
     d=16'b00010100_01000000;

    
     // Start simulation - End of reset
     #30
     rst = 0;
     
      #10
       
            a=16'b0; 
     b=16'b0;
     c=16'b0;
     d=16'b0;

      $display("%f,%f", $itor(x*SF),$itor(y*SF));
      end
      endmodule

Which give the same results, but pipelined:

enter image description here

Fra93
  • 1,992
  • 1
  • 9
  • 18