/* Copyright (C) 2008 Martin Furter This file is part of wbavr. wbavr is free software/hardware; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. wbavr is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with wbavr; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. ==============================================================================*/ /* wbavr_multiply: 8bit * 8bit -> 16bit plus carry supporting signed and float. */ module wbavr_multiply( a_i, // input byte 'a' a_signed_i, // 1 if 'a' is signed b_i, // input byte 'b' b_signed_i, // 1 if 'b' is signed float_i, // 1 if float multiplication product_lo_o, // output low byte product_hi_o, // output high byte carry_o // output carry bit ); input [7:0] a_i; input a_signed_i; input [7:0] b_i; input b_signed_i; input float_i; output [7:0] product_lo_o; output [7:0] product_hi_o; output carry_o; wire [15:0] unsigned_result; wire [7:0] a_sub1; wire [7:0] b_sub1; wire [7:0] a_sub2; wire [7:0] b_sub2; wire [7:0] sub; wire [15:0] int_result; wire [16:0] result; // unsigned multiplication assign unsigned_result = a_i * b_i; // values to subtract if needed assign a_sub1 = a_signed_i ? { 1'b0, a_i[6:0] } : { a_i[7:0] }; assign b_sub1 = b_signed_i ? { 1'b0, b_i[6:0] } : { b_i[7:0] }; // values to subtract or zero assign a_sub2 = &{ b_signed_i, b_i[7] } ? a_sub1 : 8'b0000_0000; assign b_sub2 = &{ a_signed_i, a_i[7] } ? b_sub1 : 8'b0000_0000; // sum of the values to subtract assign sub = a_sub2 + b_sub2; // integer result, signed or unsigned assign int_result = { unsigned_result[15:8] - sub, unsigned_result[7:0] }; // result, integer or float assign result = float_i ? { int_result, 1'b0 } : { 0'b0, int_result }; // outputs assign product_lo_o = result[7:0]; assign product_hi_o = result[15:8]; // carry is always the MSB of the integer result assign carry_o = int_result[15]; endmodule