data1: std_ulogic_vector(63 downto 0);
data2: std_ulogic_vector(63 downto 0);
addend: std_ulogic_vector(127 downto 0);
- is_32bit: std_ulogic;
- not_result: std_ulogic;
+ is_signed: std_ulogic;
+ subtract: std_ulogic; -- 0 => addend + data1 * data2, 1 => addend - data1 * data2
end record;
- constant MultiplyInputInit : MultiplyInputType := (valid => '0',
- is_32bit => '0', not_result => '0',
- others => (others => '0'));
+ constant MultiplyInputInit : MultiplyInputType := (data1 => 64x"0", data2 => 64x"0",
+ addend => 128x"0", others => '0');
type MultiplyOutputType is record
valid: std_ulogic;
overflow_32 <= calc_ov(a_inv(31), b_in(31), carry_32, sum_with_carry(31));
overflow_64 <= calc_ov(a_inv(63), b_in(63), carry_64, sum_with_carry(63));
- -- signals to multiply and divide units
+ -- signals to multiplier
+ addend := (others => '0');
+ if e_in.reg_valid3 = '1' then
+ -- integer multiply-add, major op 4 (if it is a multiply)
+ addend(63 downto 0) := c_in;
+ if e_in.is_signed = '1' then
+ addend(127 downto 64) := (others => c_in(63));
+ end if;
+ end if;
+ x_to_multiply.data1 <= std_ulogic_vector(a_in);
+ x_to_multiply.data2 <= std_ulogic_vector(b_in);
+ x_to_multiply.is_signed <= e_in.is_signed;
+ x_to_multiply.subtract <= '0';
+ x_to_multiply.addend <= addend;
+
+ -- Interface to divide unit
sign1 := '0';
sign2 := '0';
if e_in.is_signed = '1' then
abs2 := - signed(b_in);
end if;
- -- Interface to multiply and divide units
x_to_divider.is_signed <= e_in.is_signed;
x_to_divider.is_32bit <= e_in.is_32bit;
x_to_divider.is_extended <= '0';
x_to_divider.is_modulus <= '1';
end if;
x_to_divider.flush <= flush_in;
-
- addend := (others => '0');
- if e_in.reg_valid3 = '1' then
- -- integer multiply-add, major op 4 (if it is a multiply)
- addend(63 downto 0) := c_in;
- if e_in.is_signed = '1' then
- addend(127 downto 64) := (others => c_in(63));
- end if;
- end if;
- if (sign1 xor sign2) = '1' then
- addend := not addend;
- end if;
-
- x_to_multiply.data1 <= std_ulogic_vector(abs1);
- x_to_multiply.data2 <= std_ulogic_vector(abs2);
- x_to_multiply.is_32bit <= e_in.is_32bit;
- x_to_multiply.not_result <= sign1 xor sign2;
- x_to_multiply.addend <= addend;
x_to_divider.neg_result <= sign1 xor (sign2 and not x_to_divider.is_modulus);
if e_in.is_32bit = '0' then
-- 64-bit forms
end if;
-- signals to 32-bit multiplier
- x_to_mult_32s.data1 <= 31x"0" & (a_in(31) and e_in.is_signed) & a_in(31 downto 0);
- x_to_mult_32s.data2 <= 31x"0" & (b_in(31) and e_in.is_signed) & b_in(31 downto 0);
+ x_to_mult_32s.data1 <= 32x"0" & a_in(31 downto 0);
+ x_to_mult_32s.data2 <= 32x"0" & b_in(31 downto 0);
+ x_to_mult_32s.is_signed <= e_in.is_signed;
-- The following are unused, but set here to avoid X states
- x_to_mult_32s.is_32bit <= '1';
- x_to_mult_32s.not_result <= '0';
+ x_to_mult_32s.subtract <= '0';
x_to_mult_32s.addend <= (others => '0');
shortmul_result <= std_ulogic_vector(resize(signed(mshort_p), 64));
set_b_mant := '0';
set_c := '0';
set_s := '0';
- f_to_multiply.is_32bit <= '0';
+ f_to_multiply.is_signed <= '0';
f_to_multiply.valid <= '0';
msel_1 <= MUL1_A;
msel_2 <= MUL2_C;
maddend(UNIT_BIT - 1 downto 0) := r.s;
when others =>
end case;
- if msel_inv = '1' then
- f_to_multiply.addend <= not maddend;
- else
- f_to_multiply.addend <= maddend;
- end if;
- f_to_multiply.not_result <= msel_inv;
+ f_to_multiply.addend <= maddend;
+ f_to_multiply.subtract <= msel_inv;
if set_y = '1' then
v.y := f_to_multiply.data2;
end if;
variable ov : std_ulogic;
begin
v.valid := m_in.valid;
- v.data := signed(m_in.data1(32 downto 0)) * signed(m_in.data2(32 downto 0));
+ v.data := signed((m_in.is_signed and m_in.data1(31)) & m_in.data1(31 downto 0)) *
+ signed((m_in.is_signed and m_in.data2(31)) & m_in.data2(31 downto 0));
d := std_ulogic_vector(r.data(63 downto 0));
entity multiply is
generic (
- PIPELINE_DEPTH : natural := 4
+ PIPELINE_DEPTH : natural := 3
);
port (
clk : in std_logic;
type multiply_pipeline_stage is record
valid : std_ulogic;
data : unsigned(127 downto 0);
- is_32bit : std_ulogic;
- not_res : std_ulogic;
end record;
constant MultiplyPipelineStageInit : multiply_pipeline_stage := (valid => '0',
- is_32bit => '0', not_res => '0',
data => (others => '0'));
type multiply_pipeline_type is array(0 to PIPELINE_DEPTH-1) of multiply_pipeline_stage;
multiply_1: process(all)
variable v : reg_type;
+ variable a, b : std_ulogic_vector(64 downto 0);
+ variable prod : std_ulogic_vector(129 downto 0);
variable d : std_ulogic_vector(127 downto 0);
variable d2 : std_ulogic_vector(63 downto 0);
variable ov : std_ulogic;
begin
v := r;
+ a := (m.is_signed and m.data1(63)) & m.data1;
+ b := (m.is_signed and m.data2(63)) & m.data2;
+ prod := std_ulogic_vector(signed(a) * signed(b));
v.multiply_pipeline(0).valid := m.valid;
- v.multiply_pipeline(0).data := (unsigned(m.data1) * unsigned(m.data2)) + unsigned(m.addend);
- v.multiply_pipeline(0).is_32bit := m.is_32bit;
- v.multiply_pipeline(0).not_res := m.not_result;
+ if m.subtract = '1' then
+ v.multiply_pipeline(0).data := unsigned(m.addend) - unsigned(prod(127 downto 0));
+ else
+ v.multiply_pipeline(0).data := unsigned(m.addend) + unsigned(prod(127 downto 0));
+ end if;
loop_0: for i in 1 to PIPELINE_DEPTH-1 loop
v.multiply_pipeline(i) := r.multiply_pipeline(i-1);
end loop;
d := std_ulogic_vector(v.multiply_pipeline(PIPELINE_DEPTH-1).data);
- if v.multiply_pipeline(PIPELINE_DEPTH-1).not_res = '1' then
- d := not d;
- end if;
-
- ov := '0';
- if v.multiply_pipeline(PIPELINE_DEPTH-1).is_32bit = '1' then
- ov := (or d(63 downto 31)) and not (and d(63 downto 31));
- else
- ov := (or d(127 downto 63)) and not (and d(127 downto 63));
- end if;
+ ov := (or d(127 downto 63)) and not (and d(127 downto 63));
ovf_in <= ov;
m_out.result <= d;
signal product_lo : std_ulogic_vector(22 downto 0);
begin
- -- sign extend
- data1 <= std_ulogic_vector(resize(signed(m_in.data1(32 downto 0)), 53));
- data2 <= std_ulogic_vector(resize(signed(m_in.data2(32 downto 0)), 35));
+ -- sign extend if signed
+ data1(31 downto 0) <= m_in.data1(31 downto 0);
+ data1(52 downto 32) <= (others => m_in.is_signed and m_in.data1(31));
+ data2(31 downto 0) <= m_in.data2(31 downto 0);
+ data2(34 downto 32) <= (others => m_in.is_signed and m_in.data2(31));
clocken <= m_in.valid and not stall;
end entity multiply;
architecture behaviour of multiply is
+ signal d1sign : std_ulogic_vector(13 downto 0);
+ signal d2sign : std_ulogic_vector(4 downto 0);
signal m00_p, m01_p, m02_p, m03_p : std_ulogic_vector(47 downto 0);
signal m00_pc, m02_pc : std_ulogic_vector(47 downto 0);
signal m10_p, m11_p, m12_p, m13_p : std_ulogic_vector(47 downto 0);
signal overflow : std_ulogic;
begin
- addend <= m_in.addend;
+ addend <= m_in.addend when m_in.subtract = '0' else not m_in.addend;
+ d1sign <= (others => m_in.data1(63) and m_in.is_signed);
+ d2sign <= (others => m_in.data2(63) and m_in.is_signed);
m00: DSP48E1
generic map (
A => 6x"0" & m_in.data1(23 downto 0),
ACIN => (others => '0'),
ALUMODE => "0000",
- B => "00000" & m_in.data2(63 downto 51),
+ B => d2sign & m_in.data2(63 downto 51),
BCIN => (others => '0'),
C => (others => '0'),
CARRYCASCIN => '0',
A => 6x"0" & m_in.data1(47 downto 24),
ACIN => (others => '0'),
ALUMODE => "0000",
- B => "00000" & m_in.data2(63 downto 51),
+ B => d2sign & m_in.data2(63 downto 51),
BCIN => (others => '0'),
C => (others => '0'),
CARRYCASCIN => '0',
PREG => 1
)
port map (
- A => 14x"0" & m_in.data1(63 downto 48),
+ A => d1sign & m_in.data1(63 downto 48),
ACIN => (others => '0'),
ALUMODE => "0000",
B => '0' & m_in.data2(16 downto 0),
PREG => 0
)
port map (
- A => 14x"0" & m_in.data1(63 downto 48),
+ A => d1sign & m_in.data1(63 downto 48),
ACIN => (others => '0'),
ALUMODE => "0000",
B => '0' & m_in.data2(33 downto 17),
PREG => 1
)
port map (
- A => 14x"0" & m_in.data1(63 downto 48),
+ A => d1sign & m_in.data1(63 downto 48),
ACIN => (others => '0'),
ALUMODE => "0000",
B => '0' & m_in.data2(50 downto 34),
PREG => 0
)
port map (
- A => 14x"0" & m_in.data1(63 downto 48),
+ A => d1sign & m_in.data1(63 downto 48),
ACIN => (others => '0'),
ALUMODE => "0000",
- B => "00000" & m_in.data2(63 downto 51),
+ B => d2sign & m_in.data2(63 downto 51),
BCIN => (others => '0'),
C => (others => '0'),
CARRYCASCIN => '0',
end if;
m_out.valid <= valid_1;
valid_1 <= m_in.valid;
- rnot_1 <= m_in.not_result;
+ rnot_1 <= m_in.subtract;
overflow <= not ((p1_pat and p0_pat) or (p1_patb and p0_patb));
end if;
end process;