From: Paul Mackerras Date: Thu, 21 May 2020 07:50:54 +0000 (+1000) Subject: multiply: Use DSP48 slices for multiplication on Xilinx FPGAs X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=0809bc898b0dacd1923d513331ac3008947bee31;p=microwatt.git multiply: Use DSP48 slices for multiplication on Xilinx FPGAs This adds a custom implementation of the multiplier which uses 16 DSP48E1 slices to do a 64x64 bit multiplication in 2 cycles. Signed-off-by: Paul Mackerras --- diff --git a/microwatt.core b/microwatt.core index 876f762..7d86cc2 100644 --- a/microwatt.core +++ b/microwatt.core @@ -26,7 +26,6 @@ filesets: - loadstore1.vhdl - mmu.vhdl - dcache.vhdl - - multiply.vhdl - divider.vhdl - rotator.vhdl - writeback.vhdl @@ -75,24 +74,28 @@ filesets: - fpga/nexys_a7.xdc : {file_type : xdc} - fpga/clk_gen_plle2.vhd : {file_type : vhdlSource-2008} - fpga/top-generic.vhdl : {file_type : vhdlSource-2008} + - xilinx-mult.vhdl : {file_type : vhdlSource-2008} nexys_video: files: - fpga/nexys-video.xdc : {file_type : xdc} - fpga/clk_gen_plle2.vhd : {file_type : vhdlSource-2008} - fpga/top-nexys-video.vhdl : {file_type : vhdlSource-2008} + - xilinx-mult.vhdl : {file_type : vhdlSource-2008} arty_a7: files: - fpga/arty_a7.xdc : {file_type : xdc} - fpga/clk_gen_plle2.vhd : {file_type : vhdlSource-2008} - fpga/top-arty.vhdl : {file_type : vhdlSource-2008} + - xilinx-mult.vhdl : {file_type : vhdlSource-2008} cmod_a7-35: files: - fpga/cmod_a7-35.xdc : {file_type : xdc} - fpga/clk_gen_mcmm.vhd : {file_type : vhdlSource-2008} - fpga/top-generic.vhdl : {file_type : vhdlSource-2008} + - xilinx-mult.vhdl : {file_type : vhdlSource-2008} litedram: depend : [":microwatt:litedram"] diff --git a/xilinx-mult.vhdl b/xilinx-mult.vhdl new file mode 100644 index 0000000..46366d6 --- /dev/null +++ b/xilinx-mult.vhdl @@ -0,0 +1,985 @@ +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +library work; +use work.common.all; + +library unisim; +use unisim.vcomponents.all; + +entity multiply is + port ( + clk : in std_logic; + + m_in : in Execute1ToMultiplyType; + m_out : out MultiplyToExecute1Type + ); +end entity multiply; + +architecture behaviour of multiply is + signal m00_p, m01_p, m02_p, m03_p : std_ulogic_vector(47 downto 0); + signal m00_pc : std_ulogic_vector(47 downto 0); + signal m10_p, m11_p, m12_p, m13_p : std_ulogic_vector(47 downto 0); + signal m11_pc, m12_pc, m13_pc : std_ulogic_vector(47 downto 0); + signal m20_p, m21_p, m22_p, m23_p : std_ulogic_vector(47 downto 0); + signal s0_pc, s1_pc : std_ulogic_vector(47 downto 0); + signal product_lo : std_ulogic_vector(31 downto 0); + signal product : std_ulogic_vector(127 downto 0); + signal addend : std_ulogic_vector(127 downto 0); + signal s0_carry, p0_carry : std_ulogic_vector(3 downto 0); + signal p0_mask : std_ulogic_vector(47 downto 0); + signal p0_pat, p0_patb : std_ulogic; + signal p1_pat, p1_patb : std_ulogic; + + signal req_32bit, r32_1 : std_ulogic; + signal req_neg, rneg_1 : std_ulogic; + signal valid_1 : std_ulogic; + +begin + addend <= (others => m_in.neg_result); + + m00: DSP48E1 + generic map ( + ACASCREG => 0, + ALUMODEREG => 0, + AREG => 0, + BCASCREG => 0, + BREG => 0, + CARRYINREG => 0, + CARRYINSELREG => 0, + INMODEREG => 0, + OPMODEREG => 0, + PREG => 0 + ) + port map ( + A => "0000000" & m_in.data1(22 downto 0), + ACIN => (others => '0'), + ALUMODE => "0000", + B => '0' & m_in.data2(16 downto 0), + BCIN => (others => '0'), + C => "00000000000000" & addend(33 downto 0), + CARRYCASCIN => '0', + CARRYIN => '0', + CARRYINSEL => "000", + CEA1 => '0', + CEA2 => '0', + CEAD => '0', + CEALUMODE => '0', + CEB1 => '0', + CEB2 => '0', + CEC => '1', + CECARRYIN => '0', + CECTRL => '0', + CED => '0', + CEINMODE => '0', + CEM => '1', + CEP => '0', + CLK => clk, + D => (others => '0'), + INMODE => "00000", + MULTSIGNIN => '0', + OPMODE => "0110101", + P => m00_p, + PCIN => (others => '0'), + PCOUT => m00_pc, + RSTA => '0', + RSTALLCARRYIN => '0', + RSTALUMODE => '0', + RSTB => '0', + RSTC => '0', + RSTCTRL => '0', + RSTD => '0', + RSTINMODE => '0', + RSTM => '0', + RSTP => '0' + ); + + m01: DSP48E1 + generic map ( + ACASCREG => 0, + ALUMODEREG => 0, + AREG => 0, + BCASCREG => 0, + BREG => 0, + CARRYINREG => 0, + CARRYINSELREG => 0, + INMODEREG => 0, + OPMODEREG => 0, + PREG => 0 + ) + port map ( + A => "0000000" & m_in.data1(22 downto 0), + ACIN => (others => '0'), + ALUMODE => "0000", + B => '0' & m_in.data2(33 downto 17), + BCIN => (others => '0'), + C => (others => '0'), + CARRYCASCIN => '0', + CARRYIN => '0', + CARRYINSEL => "000", + CEA1 => '0', + CEA2 => '0', + CEAD => '0', + CEALUMODE => '0', + CEB1 => '0', + CEB2 => '0', + CEC => '1', + CECARRYIN => '0', + CECTRL => '0', + CED => '0', + CEINMODE => '0', + CEM => '1', + CEP => '0', + CLK => clk, + D => (others => '0'), + INMODE => "00000", + MULTSIGNIN => '0', + OPMODE => "1010101", + P => m01_p, + PCIN => m00_pc, + RSTA => '0', + RSTALLCARRYIN => '0', + RSTALUMODE => '0', + RSTB => '0', + RSTC => '0', + RSTCTRL => '0', + RSTD => '0', + RSTINMODE => '0', + RSTM => '0', + RSTP => '0' + ); + + m02: DSP48E1 + generic map ( + ACASCREG => 0, + ALUMODEREG => 0, + AREG => 0, + BCASCREG => 0, + BREG => 0, + CARRYINREG => 0, + CARRYINSELREG => 0, + INMODEREG => 0, + OPMODEREG => 0, + PREG => 0 + ) + port map ( + A => "0000000" & m_in.data1(22 downto 0), + ACIN => (others => '0'), + ALUMODE => "0000", + B => '0' & m_in.data2(50 downto 34), + BCIN => (others => '0'), + C => x"0000000" & "000" & addend(50 downto 34), + CARRYCASCIN => '0', + CARRYIN => '0', + CARRYINSEL => "000", + CEA1 => '0', + CEA2 => '0', + CEAD => '0', + CEALUMODE => '0', + CEB1 => '0', + CEB2 => '0', + CEC => '1', + CECARRYIN => '0', + CECTRL => '0', + CED => '0', + CEINMODE => '0', + CEM => '1', + CEP => '0', + CLK => clk, + D => (others => '0'), + INMODE => "00000", + MULTSIGNIN => '0', + OPMODE => "0110101", + P => m02_p, + PCIN => (others => '0'), + RSTA => '0', + RSTALLCARRYIN => '0', + RSTALUMODE => '0', + RSTB => '0', + RSTC => '0', + RSTCTRL => '0', + RSTD => '0', + RSTINMODE => '0', + RSTM => '0', + RSTP => '0' + ); + + m03: DSP48E1 + generic map ( + ACASCREG => 0, + ALUMODEREG => 0, + AREG => 0, + BCASCREG => 0, + BREG => 0, + CARRYINREG => 0, + CARRYINSELREG => 0, + INMODEREG => 0, + OPMODEREG => 0, + PREG => 0 + ) + port map ( + A => "0000000" & m_in.data1(22 downto 0), + ACIN => (others => '0'), + ALUMODE => "0000", + B => "00000" & m_in.data2(63 downto 51), + BCIN => (others => '0'), + C => x"000000" & '0' & addend(73 downto 51), + CARRYCASCIN => '0', + CARRYIN => '0', + CARRYINSEL => "000", + CEA1 => '0', + CEA2 => '0', + CEAD => '0', + CEALUMODE => '0', + CEB1 => '0', + CEB2 => '0', + CEC => '1', + CECARRYIN => '0', + CECTRL => '0', + CED => '0', + CEINMODE => '0', + CEM => '1', + CEP => '0', + CLK => clk, + D => (others => '0'), + INMODE => "00000", + MULTSIGNIN => '0', + OPMODE => "0110101", + P => m03_p, + PCIN => (others => '0'), + RSTA => '0', + RSTALLCARRYIN => '0', + RSTALUMODE => '0', + RSTB => '0', + RSTC => '0', + RSTCTRL => '0', + RSTD => '0', + RSTINMODE => '0', + RSTM => '0', + RSTP => '0' + ); + + m10: DSP48E1 + generic map ( + ACASCREG => 0, + ALUMODEREG => 0, + AREG => 0, + BCASCREG => 0, + BREG => 0, + CARRYINREG => 0, + CARRYINSELREG => 0, + CREG => 0, + INMODEREG => 0, + OPMODEREG => 0, + PREG => 0 + ) + port map ( + A => "0000000000000" & m_in.data1(39 downto 23), + ACIN => (others => '0'), + ALUMODE => "0000", + B => '0' & m_in.data2(16 downto 0), + BCIN => (others => '0'), + C => x"000" & "00" & m01_p(39 downto 6), + CARRYCASCIN => '0', + CARRYIN => '0', + CARRYINSEL => "000", + CEA1 => '0', + CEA2 => '0', + CEAD => '0', + CEALUMODE => '0', + CEB1 => '0', + CEB2 => '0', + CEC => '0', + CECARRYIN => '0', + CECTRL => '0', + CED => '0', + CEINMODE => '0', + CEM => '1', + CEP => '0', + CLK => clk, + D => (others => '0'), + INMODE => "00000", + MULTSIGNIN => '0', + OPMODE => "0110101", + P => m10_p, + PCIN => (others => '0'), + RSTA => '0', + RSTALLCARRYIN => '0', + RSTALUMODE => '0', + RSTB => '0', + RSTC => '0', + RSTCTRL => '0', + RSTD => '0', + RSTINMODE => '0', + RSTM => '0', + RSTP => '0' + ); + + m11: DSP48E1 + generic map ( + ACASCREG => 0, + ALUMODEREG => 0, + AREG => 0, + BCASCREG => 0, + BREG => 0, + CARRYINREG => 0, + CARRYINSELREG => 0, + CREG => 0, + INMODEREG => 0, + OPMODEREG => 0, + PREG => 0 + ) + port map ( + A => "0000000000000" & m_in.data1(39 downto 23), + ACIN => (others => '0'), + ALUMODE => "0000", + B => '0' & m_in.data2(33 downto 17), + BCIN => (others => '0'), + C => x"000" & "00" & m02_p(39 downto 6), + CARRYCASCIN => '0', + CARRYIN => '0', + CARRYINSEL => "000", + CEA1 => '0', + CEA2 => '0', + CEAD => '0', + CEALUMODE => '0', + CEB1 => '0', + CEB2 => '0', + CEC => '0', + CECARRYIN => '0', + CECTRL => '0', + CED => '0', + CEINMODE => '0', + CEM => '1', + CEP => '0', + CLK => clk, + D => (others => '0'), + INMODE => "00000", + MULTSIGNIN => '0', + OPMODE => "0110101", + P => m11_p, + PCIN => (others => '0'), + PCOUT => m11_pc, + RSTA => '0', + RSTALLCARRYIN => '0', + RSTALUMODE => '0', + RSTB => '0', + RSTC => '0', + RSTCTRL => '0', + RSTD => '0', + RSTINMODE => '0', + RSTM => '0', + RSTP => '0' + ); + + m12: DSP48E1 + generic map ( + ACASCREG => 0, + ALUMODEREG => 0, + AREG => 0, + BCASCREG => 0, + BREG => 0, + CARRYINREG => 0, + CARRYINSELREG => 0, + CREG => 0, + INMODEREG => 0, + OPMODEREG => 0, + PREG => 0 + ) + port map ( + A => "0000000000000" & m_in.data1(39 downto 23), + ACIN => (others => '0'), + ALUMODE => "0000", + B => '0' & m_in.data2(50 downto 34), + BCIN => (others => '0'), + C => x"0000" & '0' & m03_p(36 downto 6), + CARRYCASCIN => '0', + CARRYIN => '0', + CARRYINSEL => "000", + CEA1 => '0', + CEA2 => '0', + CEAD => '0', + CEALUMODE => '0', + CEB1 => '0', + CEB2 => '0', + CEC => '0', + CECARRYIN => '0', + CECTRL => '0', + CED => '0', + CEINMODE => '0', + CEM => '1', + CEP => '0', + CLK => clk, + D => (others => '0'), + INMODE => "00000", + MULTSIGNIN => '0', + OPMODE => "0110101", + P => m12_p, + PCIN => (others => '0'), + PCOUT => m12_pc, + RSTA => '0', + RSTALLCARRYIN => '0', + RSTALUMODE => '0', + RSTB => '0', + RSTC => '0', + RSTCTRL => '0', + RSTD => '0', + RSTINMODE => '0', + RSTM => '0', + RSTP => '0' + ); + + m13: DSP48E1 + generic map ( + ACASCREG => 0, + ALUMODEREG => 0, + AREG => 0, + BCASCREG => 0, + BREG => 0, + CARRYINREG => 0, + CARRYINSELREG => 0, + INMODEREG => 0, + OPMODEREG => 0, + PREG => 0 + ) + port map ( + A => "0000000000000" & m_in.data1(39 downto 23), + ACIN => (others => '0'), + ALUMODE => "0000", + B => "00000" & m_in.data2(63 downto 51), + BCIN => (others => '0'), + C => x"0000000" & "000" & addend(90 downto 74), + CARRYCASCIN => '0', + CARRYIN => '0', + CARRYINSEL => "000", + CEA1 => '0', + CEA2 => '0', + CEAD => '0', + CEALUMODE => '0', + CEB1 => '0', + CEB2 => '0', + CEC => '1', + CECARRYIN => '0', + CECTRL => '0', + CED => '0', + CEINMODE => '0', + CEM => '1', + CEP => '0', + CLK => clk, + D => (others => '0'), + INMODE => "00000", + MULTSIGNIN => '0', + OPMODE => "0110101", + P => m13_p, + PCIN => (others => '0'), + PCOUT => m13_pc, + RSTA => '0', + RSTALLCARRYIN => '0', + RSTALUMODE => '0', + RSTB => '0', + RSTC => '0', + RSTCTRL => '0', + RSTD => '0', + RSTINMODE => '0', + RSTM => '0', + RSTP => '0' + ); + + m20: DSP48E1 + generic map ( + ACASCREG => 0, + ALUMODEREG => 0, + AREG => 0, + BCASCREG => 0, + BREG => 0, + CARRYINREG => 0, + CARRYINSELREG => 0, + INMODEREG => 0, + OPMODEREG => 0, + PREG => 0 + ) + port map ( + A => "000000" & m_in.data1(63 downto 40), + ACIN => (others => '0'), + ALUMODE => "0000", + B => '0' & m_in.data2(16 downto 0), + BCIN => (others => '0'), + C => (others => '0'), + CARRYCASCIN => '0', + CARRYIN => '0', + CARRYINSEL => "000", + CEA1 => '0', + CEA2 => '0', + CEAD => '0', + CEALUMODE => '0', + CEB1 => '0', + CEB2 => '0', + CEC => '1', + CECARRYIN => '0', + CECTRL => '0', + CED => '0', + CEINMODE => '0', + CEM => '1', + CEP => '0', + CLK => clk, + D => (others => '0'), + INMODE => "00000", + MULTSIGNIN => '0', + OPMODE => "0010101", + P => m20_p, + PCIN => m11_pc, + RSTA => '0', + RSTALLCARRYIN => '0', + RSTALUMODE => '0', + RSTB => '0', + RSTC => '0', + RSTCTRL => '0', + RSTD => '0', + RSTINMODE => '0', + RSTM => '0', + RSTP => '0' + ); + + m21: DSP48E1 + generic map ( + ACASCREG => 0, + ALUMODEREG => 0, + AREG => 0, + BCASCREG => 0, + BREG => 0, + CARRYINREG => 0, + CARRYINSELREG => 0, + INMODEREG => 0, + OPMODEREG => 0, + PREG => 0 + ) + port map ( + A => "000000" & m_in.data1(63 downto 40), + ACIN => (others => '0'), + ALUMODE => "0000", + B => '0' & m_in.data2(33 downto 17), + BCIN => (others => '0'), + C => (others => '0'), + CARRYCASCIN => '0', + CARRYIN => '0', + CARRYINSEL => "000", + CEA1 => '0', + CEA2 => '0', + CEAD => '0', + CEALUMODE => '0', + CEB1 => '0', + CEB2 => '0', + CEC => '1', + CECARRYIN => '0', + CECTRL => '0', + CED => '0', + CEINMODE => '0', + CEM => '1', + CEP => '0', + CLK => clk, + D => (others => '0'), + INMODE => "00000", + MULTSIGNIN => '0', + OPMODE => "0010101", + P => m21_p, + PCIN => m12_pc, + RSTA => '0', + RSTALLCARRYIN => '0', + RSTALUMODE => '0', + RSTB => '0', + RSTC => '0', + RSTCTRL => '0', + RSTD => '0', + RSTINMODE => '0', + RSTM => '0', + RSTP => '0' + ); + + m22: DSP48E1 + generic map ( + ACASCREG => 0, + ALUMODEREG => 0, + AREG => 0, + BCASCREG => 0, + BREG => 0, + CARRYINREG => 0, + CARRYINSELREG => 0, + INMODEREG => 0, + OPMODEREG => 0, + PREG => 0 + ) + port map ( + A => "000000" & m_in.data1(63 downto 40), + ACIN => (others => '0'), + ALUMODE => "0000", + B => '0' & m_in.data2(50 downto 34), + BCIN => (others => '0'), + C => (others => '0'), + CARRYCASCIN => '0', + CARRYIN => '0', + CARRYINSEL => "000", + CEA1 => '0', + CEA2 => '0', + CEAD => '0', + CEALUMODE => '0', + CEB1 => '0', + CEB2 => '0', + CEC => '1', + CECARRYIN => '0', + CECTRL => '0', + CED => '0', + CEINMODE => '0', + CEM => '1', + CEP => '0', + CLK => clk, + D => (others => '0'), + INMODE => "00000", + MULTSIGNIN => '0', + OPMODE => "0010101", + P => m22_p, + PCIN => m13_pc, + RSTA => '0', + RSTALLCARRYIN => '0', + RSTALUMODE => '0', + RSTB => '0', + RSTC => '0', + RSTCTRL => '0', + RSTD => '0', + RSTINMODE => '0', + RSTM => '0', + RSTP => '0' + ); + + m23: DSP48E1 + generic map ( + ACASCREG => 0, + ALUMODEREG => 0, + AREG => 0, + BCASCREG => 0, + BREG => 0, + CARRYINREG => 0, + CARRYINSELREG => 0, + INMODEREG => 0, + OPMODEREG => 0, + PREG => 0 + ) + port map ( + A => "000000" & m_in.data1(63 downto 40), + ACIN => (others => '0'), + ALUMODE => "0000", + B => "00000" & m_in.data2(63 downto 51), + BCIN => (others => '0'), + C => x"00" & "000" & addend(127 downto 91), + CARRYCASCIN => '0', + CARRYIN => '0', + CARRYINSEL => "000", + CEA1 => '0', + CEA2 => '0', + CEAD => '0', + CEALUMODE => '0', + CEB1 => '0', + CEB2 => '0', + CEC => '1', + CECARRYIN => '0', + CECTRL => '0', + CED => '0', + CEINMODE => '0', + CEM => '1', + CEP => '0', + CLK => clk, + D => (others => '0'), + INMODE => "00000", + MULTSIGNIN => '0', + OPMODE => "0110101", + P => m23_p, + PCIN => (others => '0'), + RSTA => '0', + RSTALLCARRYIN => '0', + RSTALUMODE => '0', + RSTB => '0', + RSTC => '0', + RSTCTRL => '0', + RSTD => '0', + RSTINMODE => '0', + RSTM => '0', + RSTP => '0' + ); + + s0: DSP48E1 + generic map ( + ACASCREG => 1, + ALUMODEREG => 0, + AREG => 1, + BCASCREG => 1, + BREG => 1, + CARRYINREG => 0, + CARRYINSELREG => 0, + CREG => 1, + INMODEREG => 0, + MREG => 0, + OPMODEREG => 0, + PREG => 0, + USE_MULT => "none" + ) + port map ( + A => m22_p(5 downto 0) & x"0000" & m10_p(34 downto 27), + ACIN => (others => '0'), + ALUMODE => "0000", + B => m10_p(26 downto 9), + BCIN => (others => '0'), + C => m20_p(39 downto 0) & m02_p(5 downto 0) & "00", + CARRYCASCIN => '0', + CARRYIN => '0', + CARRYINSEL => "000", + CARRYOUT => s0_carry, + CEA1 => '0', + CEA2 => '1', + CEAD => '0', + CEALUMODE => '0', + CEB1 => '0', + CEB2 => '1', + CEC => '1', + CECARRYIN => '0', + CECTRL => '0', + CED => '0', + CEINMODE => '0', + CEM => '0', + CEP => '0', + CLK => clk, + D => (others => '0'), + INMODE => "00000", + MULTSIGNIN => '0', + OPMODE => "0001111", + PCIN => (others => '0'), + PCOUT => s0_pc, + RSTA => '0', + RSTALLCARRYIN => '0', + RSTALUMODE => '0', + RSTB => '0', + RSTC => '0', + RSTCTRL => '0', + RSTD => '0', + RSTINMODE => '0', + RSTM => '0', + RSTP => '0' + ); + + s1: DSP48E1 + generic map ( + ACASCREG => 1, + ALUMODEREG => 0, + AREG => 1, + BCASCREG => 1, + BREG => 1, + CARRYINREG => 0, + CARRYINSELREG => 0, + CREG => 1, + INMODEREG => 0, + MREG => 0, + OPMODEREG => 0, + PREG => 0, + USE_MULT => "none" + ) + port map ( + A => x"000" & m22_p(41 downto 24), + ACIN => (others => '0'), + ALUMODE => "0000", + B => m22_p(23 downto 6), + BCIN => (others => '0'), + C => m23_p(36 downto 0) & x"00" & "0" & m20_p(41 downto 40), + CARRYCASCIN => '0', + CARRYIN => s0_carry(3), + CARRYINSEL => "000", + CEA1 => '0', + CEA2 => '1', + CEAD => '0', + CEALUMODE => '0', + CEB1 => '0', + CEB2 => '1', + CEC => '1', + CECARRYIN => '0', + CECTRL => '0', + CED => '0', + CEINMODE => '0', + CEM => '0', + CEP => '0', + CLK => clk, + D => (others => '0'), + INMODE => "00000", + MULTSIGNIN => '0', + OPMODE => "0001111", + PCIN => (others => '0'), + PCOUT => s1_pc, + RSTA => '0', + RSTALLCARRYIN => '0', + RSTALUMODE => '0', + RSTB => '0', + RSTC => '0', + RSTCTRL => '0', + RSTD => '0', + RSTINMODE => '0', + RSTM => '0', + RSTP => '0' + ); + + -- mask is 0 for 32-bit ops, 0x0000ffffffff for 64-bit + p0_mask(47 downto 31) <= (others => '0'); + p0_mask(30 downto 0) <= (others => not r32_1); + + p0: DSP48E1 + generic map ( + ACASCREG => 1, + ALUMODEREG => 1, + AREG => 1, + BCASCREG => 1, + BREG => 1, + CARRYINREG => 0, + CARRYINSELREG => 0, + CREG => 1, + INMODEREG => 0, + MREG => 0, + OPMODEREG => 0, + PREG => 0, + SEL_MASK => "C", + USE_MULT => "none", + USE_PATTERN_DETECT => "PATDET" + ) + port map ( + A => m21_p(22 downto 0) & m03_p(5 downto 0) & '0', + ACIN => (others => '0'), + ALUMODE => "00" & rneg_1 & '0', + B => (others => '0'), + BCIN => (others => '0'), + C => p0_mask, + CARRYCASCIN => '0', + CARRYIN => '0', + CARRYINSEL => "000", + CARRYOUT => p0_carry, + CEA1 => '0', + CEA2 => '1', + CEAD => '0', + CEALUMODE => '1', + CEB1 => '0', + CEB2 => '1', + CEC => '1', + CECARRYIN => '0', + CECTRL => '0', + CED => '0', + CEINMODE => '0', + CEM => '0', + CEP => '0', + CLK => clk, + D => (others => '0'), + INMODE => "00000", + MULTSIGNIN => '0', + OPMODE => "0010011", + P => product(79 downto 32), + PATTERNDETECT => p0_pat, + PATTERNBDETECT => p0_patb, + PCIN => s0_pc, + RSTA => '0', + RSTALLCARRYIN => '0', + RSTALUMODE => '0', + RSTB => '0', + RSTC => '0', + RSTCTRL => '0', + RSTD => '0', + RSTINMODE => '0', + RSTM => '0', + RSTP => '0' + ); + + p1: DSP48E1 + generic map ( + ACASCREG => 1, + ALUMODEREG => 1, + AREG => 1, + BCASCREG => 1, + BREG => 1, + CARRYINREG => 0, + CARRYINSELREG => 0, + CREG => 0, + INMODEREG => 0, + MASK => x"000000000000", + MREG => 0, + OPMODEREG => 0, + PREG => 0, + USE_MULT => "none", + USE_PATTERN_DETECT => "PATDET" + ) + port map ( + A => x"0000000" & '0' & m21_p(41), + ACIN => (others => '0'), + ALUMODE => "00" & rneg_1 & '0', + B => m21_p(40 downto 23), + BCIN => (others => '0'), + C => (others => '0'), + CARRYCASCIN => '0', + CARRYIN => p0_carry(3), + CARRYINSEL => "000", + CEA1 => '0', + CEA2 => '1', + CEAD => '0', + CEALUMODE => '1', + CEB1 => '0', + CEB2 => '1', + CEC => '0', + CECARRYIN => '0', + CECTRL => '0', + CED => '0', + CEINMODE => '0', + CEM => '0', + CEP => '0', + CLK => clk, + D => (others => '0'), + INMODE => "00000", + MULTSIGNIN => '0', + OPMODE => "0010011", + P => product(127 downto 80), + PATTERNDETECT => p1_pat, + PATTERNBDETECT => p1_patb, + PCIN => s1_pc, + RSTA => '0', + RSTALLCARRYIN => '0', + RSTALUMODE => '0', + RSTB => '0', + RSTC => '0', + RSTCTRL => '0', + RSTD => '0', + RSTINMODE => '0', + RSTM => '0', + RSTP => '0' + ); + + product(31 downto 0) <= product_lo xor (31 downto 0 => req_neg); + + mult_out: process(all) + variable ov : std_ulogic; + begin + -- set overflow if the high bits are neither all zeroes nor all ones + if req_32bit = '0' then + ov := not ((p1_pat and p0_pat) or (p1_patb and p0_patb)); + else + ov := not ((p1_pat and p0_pat and not product(31)) or + (p1_patb and p0_patb and product(31))); + end if; + + m_out.result <= product; + m_out.overflow <= ov; + end process; + + process(clk) + begin + if rising_edge(clk) then + product_lo <= m10_p(8 downto 0) & m01_p(5 downto 0) & m00_p(16 downto 0); + m_out.valid <= valid_1; + valid_1 <= m_in.valid; + req_32bit <= r32_1; + r32_1 <= m_in.is_32bit; + req_neg <= rneg_1; + rneg_1 <= m_in.neg_result; + end if; + end process; + +end architecture behaviour;