////////////////////////////////////////////////////////////////////////////////// // qmults.sv // SystemVerilog version of qmults.v from Basel Halak // // This module acts as a sign-magnitde multiplier for fixed-point numbers // (note that the coding is not two's complement so the inputs and outputs are not declared as "signed") // // Parameters: // N is the total number of bits (note that the result has the same number of bits as each of the operands) // Q is the number of bits after the binary point // ////////////////////////////////////////////////////////////////////////////////// module qmults#( //Parameterized values parameter Q = 0, parameter N = 32 ) ( input [N-1:0] multiplicand, input [N-1:0] multiplier, input start, input Clock, input nReset, output logic [N-1:0] result, output logic complete, output logic overflow ); timeunit 1ns; timeprecision 1ps; logic [2*N-2:0] working_result; // a place to accumulate our result logic [2*N-2:0] multiplier_temp; // a working copy of the multiplier logic [N-1:0] multiplicand_temp; // a working copy of the umultiplicand logic [N-1:0] count; // This is obviously a lot bigger than it needs to be, as we only need // count to N, but computing that number of bits requires a // logarithm (base 2), and I don't know how to do that in a // way that will work for every possibility logic sign; // The result's sign bit assign result[N-2:0] = working_result[N-2+Q:Q]; // The multiplication results assign result[N-1] = sign; // The sign of the result always @( posedge Clock or negedge nReset) if (!nReset) begin complete <= '1; // Initial state is to not be doing anything overflow <= '0; // And there should be no woverflow present sign <= '0; // And the sign should be positive count <= '0; // Reset the count multiplier_temp <= '0; // Reset the multiplier register multiplicand_temp <= '0; // Reset the multiplicand register working_result <= '0; // end else if( complete && start ) begin // This is our startup condition complete <= '0; // We're not done count <= '0; // Reset the count working_result <= '0; // Clear out the result register multiplier_temp <= '0; // Clear out the multiplier register multiplicand_temp <= '0; // Clear out the multiplicand register overflow <= '0; // Clear the overflow register multiplicand_temp <= multiplicand[N-2:0]; // Load the multiplicand in its working register and lose the sign bit multiplier_temp <= multiplier[N-2:0]; // Load the multiplier into its working register and lose the sign bit sign <= multiplicand[N-1] ^ multiplier[N-1]; // Set the sign bit end else if (!complete) begin if (multiplicand_temp[count] == 1) // if the appropriate multiplicand bit is 1 working_result <= working_result + multiplier_temp; // then add the temp multiplier multiplier_temp <= multiplier_temp << 1; // Do a left-shift on the multiplier count <= count + 1; // Increment the count //stop condition if(count == N) begin complete <= '1; // If we're done, it's time to tell the calling process if (working_result[2*N-2:N-1+Q] > 0) // Check for an overflow overflow <= '1; end end endmodule