`timescale 1ns / 1ps
|
`timescale 1ns / 1ps
|
//////////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////////
|
// Company:
|
// Company:
|
// Engineer:
|
// Engineer:
|
//
|
//
|
// Create Date: 13:33:36 01/02/2014
|
// Create Date: 13:33:36 01/02/2014
|
// Design Name:
|
// Design Name:
|
// Module Name: qmults
|
// Module Name: qmults
|
// Project Name:
|
// Project Name:
|
// Target Devices:
|
// Target Devices:
|
// Tool versions:
|
// Tool versions:
|
// Description:
|
// Description:
|
//
|
//
|
// Dependencies:
|
// Dependencies:
|
//
|
//
|
// Revision:
|
// Revision:
|
// Revision 0.01 - File Created
|
// Revision 0.01 - File Created
|
// Additional Comments:
|
// Additional Comments:
|
//
|
//
|
//////////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////////
|
module qmults#(
|
module qmults#(
|
//Parameterized values
|
//Parameterized values
|
parameter Q = 15,
|
parameter Q = 15,
|
parameter N = 32
|
parameter N = 32
|
)
|
)
|
(
|
(
|
input [N-1:0] i_multiplicand,
|
input [N-1:0] i_multiplicand,
|
input [N-1:0] i_multiplier,
|
input [N-1:0] i_multiplier,
|
input i_start,
|
input i_start,
|
input i_clk,
|
input i_clk,
|
output [N-1:0] o_result_out,
|
output [N-1:0] o_result_out,
|
output o_complete,
|
output o_complete,
|
output o_overflow
|
output o_overflow
|
);
|
);
|
|
|
reg [2*N-2:0] reg_working_result; // a place to accumulate our result
|
reg [2*N-2:0] reg_working_result; // a place to accumulate our result
|
reg [2*N-2:0] reg_multiplier_temp; // a working copy of the multiplier
|
reg [2*N-2:0] reg_multiplier_temp; // a working copy of the multiplier
|
reg [N-1:0] reg_multiplicand_temp; // a working copy of the umultiplicand
|
reg [N-1:0] reg_multiplicand_temp; // a working copy of the umultiplicand
|
|
|
reg [N:0] reg_count; // This is obviously a lot bigger than it needs to be, as we only need
|
reg [N-1:0] reg_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
|
// 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
|
// logarithm (base 2), and I don't know how to do that in a
|
// way that will work for every possibility
|
// way that will work for every possibility
|
|
|
reg reg_done; // Computation completed flag
|
reg reg_done; // Computation completed flag
|
reg reg_sign; // The result's sign bit
|
reg reg_sign; // The result's sign bit
|
reg reg_overflow; // Overflow flag
|
reg reg_overflow; // Overflow flag
|
|
|
initial reg_done = 1'b1; // Initial state is to not be doing anything
|
initial reg_done = 1'b1; // Initial state is to not be doing anything
|
initial reg_overflow = 1'b0; // And there should be no woverflow present
|
initial reg_overflow = 1'b0; // And there should be no woverflow present
|
initial reg_sign = 1'b0; // And the sign should be positive
|
initial reg_sign = 1'b0; // And the sign should be positive
|
|
|
assign o_result_out[N-2:0] = reg_working_result[N-2+Q:Q]; // The multiplication results
|
assign o_result_out[N-2:0] = reg_working_result[N-2+Q:Q]; // The multiplication results
|
assign o_result_out[N-1] = reg_sign; // The sign of the result
|
assign o_result_out[N-1] = reg_sign; // The sign of the result
|
assign o_complete = reg_done; // "Done" flag
|
assign o_complete = reg_done; // "Done" flag
|
assign o_overflow = reg_overflow; // Overflow flag
|
assign o_overflow = reg_overflow; // Overflow flag
|
|
|
always @( posedge i_clk ) begin
|
always @( posedge i_clk ) begin
|
if( reg_done && i_start ) begin // This is our startup condition
|
if( reg_done && i_start ) begin // This is our startup condition
|
reg_done <= 1'b0; // We're not done
|
reg_done <= 1'b0; // We're not done
|
reg_count <= 0; // Reset the count
|
reg_count <= 0; // Reset the count
|
reg_working_result <= 0; // Clear out the result register
|
reg_working_result <= 0; // Clear out the result register
|
reg_multiplier_temp <= 0; // Clear out the multiplier register
|
reg_multiplier_temp <= 0; // Clear out the multiplier register
|
reg_multiplicand_temp <= 0; // Clear out the multiplicand register
|
reg_multiplicand_temp <= 0; // Clear out the multiplicand register
|
reg_overflow <= 1'b0; // Clear the overflow register
|
reg_overflow <= 1'b0; // Clear the overflow register
|
|
|
reg_multiplicand_temp <= i_multiplicand[N-2:0]; // Load the multiplicand in its working register and lose the sign bit
|
reg_multiplicand_temp <= i_multiplicand[N-2:0]; // Load the multiplicand in its working register and lose the sign bit
|
reg_multiplier_temp <= i_multiplier[N-2:0]; // Load the multiplier into its working register and lose the sign bit
|
reg_multiplier_temp <= i_multiplier[N-2:0]; // Load the multiplier into its working register and lose the sign bit
|
|
|
reg_sign <= i_multiplicand[N-1] ^ i_multiplier[N-1]; // Set the sign bit
|
reg_sign <= i_multiplicand[N-1] ^ i_multiplier[N-1]; // Set the sign bit
|
end
|
end
|
|
|
else if (!reg_done) begin
|
else if (!reg_done) begin
|
if (reg_multiplicand_temp[reg_count] == 1'b1) // if the appropriate multiplicand bit is 1
|
if (reg_multiplicand_temp[reg_count] == 1'b1) // if the appropriate multiplicand bit is 1
|
reg_working_result <= reg_working_result + reg_multiplier_temp; // then add the temp multiplier
|
reg_working_result <= reg_working_result + reg_multiplier_temp; // then add the temp multiplier
|
|
|
reg_multiplier_temp <= reg_multiplier_temp << 1; // Do a left-shift on the multiplier
|
reg_multiplier_temp <= reg_multiplier_temp << 1; // Do a left-shift on the multiplier
|
reg_count <= reg_count + 1; // Increment the count
|
reg_count <= reg_count + 1; // Increment the count
|
|
|
//stop condition
|
//stop condition
|
if(reg_count == N) begin
|
if(reg_count == N) begin
|
reg_done <= 1'b1; // If we're done, it's time to tell the calling process
|
reg_done <= 1'b1; // If we're done, it's time to tell the calling process
|
if (reg_working_result[2*N-2:N-1+Q] > 0) // Check for an overflow
|
if (reg_working_result[2*N-2:N-1+Q] > 0) // Check for an overflow
|
reg_overflow <= 1'b1;
|
reg_overflow <= 1'b1;
|
// else
|
// else
|
// reg_count <= reg_count + 1; // Increment the count
|
// reg_count <= reg_count + 1; // Increment the count
|
end
|
end
|
end
|
end
|
end
|
end
|
endmodule
|
endmodule
|
|
|