From c7ef75b55c5ea7d98f76556e0371d589a19dde80 Mon Sep 17 00:00:00 2001 From: Anton Blanchard Date: Tue, 1 Feb 2022 20:52:58 +1100 Subject: [PATCH] Forgot multiply.vhdl --- asic/multiply.vhdl | 128 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 128 insertions(+) create mode 100644 asic/multiply.vhdl diff --git a/asic/multiply.vhdl b/asic/multiply.vhdl new file mode 100644 index 0000000..a604554 --- /dev/null +++ b/asic/multiply.vhdl @@ -0,0 +1,128 @@ +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +library work; +use work.common.all; + +-- XXX We should be able to make timing with a 2 cycle multiplier +entity multiply is + generic ( + PIPELINE_DEPTH : natural := 4 + ); + port ( + clk : in std_logic; + + m_in : in MultiplyInputType; + m_out : out MultiplyOutputType + ); +end entity multiply; + +architecture behaviour of multiply is + signal m: MultiplyInputType := MultiplyInputInit; + + type multiply_pipeline_stage is record + valid : std_ulogic; + is_32bit : std_ulogic; + not_res : std_ulogic; + end record; + constant MultiplyPipelineStageInit : multiply_pipeline_stage := (valid => '0', + is_32bit => '0', + not_res => '0'); + + type multiply_pipeline_type is array(0 to PIPELINE_DEPTH-1) of multiply_pipeline_stage; + constant MultiplyPipelineInit : multiply_pipeline_type := (others => MultiplyPipelineStageInit); + + type reg_type is record + multiply_pipeline : multiply_pipeline_type; + end record; + + signal r, rin : reg_type := (multiply_pipeline => MultiplyPipelineInit); + signal overflow : std_ulogic; + signal ovf_in : std_ulogic; + + signal mult_out : std_logic_vector(127 downto 0); + + component multiply_add_64x64 port( + clk : in std_logic; + a : in std_logic_vector(63 downto 0); + b : in std_logic_vector(63 downto 0); + c : in std_logic_vector(127 downto 0); + o : out std_logic_vector(127 downto 0) + ); + end component; +begin + multiply_0: process(clk) + begin + if rising_edge(clk) then + m <= m_in; + r <= rin; + overflow <= ovf_in; + end if; + end process; + + multiplier : multiply_add_64x64 + port map ( + clk => clk, + a => m.data1, + b => m.data2, + c => m.addend, + o => mult_out + ); + + multiply_1: process(all) + variable v : reg_type; + variable d : std_ulogic_vector(127 downto 0); + variable d2 : std_ulogic_vector(63 downto 0); + variable ov : std_ulogic; + begin + v := r; + v.multiply_pipeline(0).valid := m.valid; + v.multiply_pipeline(0).is_32bit := m.is_32bit; + v.multiply_pipeline(0).not_res := m.not_result; + + loop_0: for i in 1 to PIPELINE_DEPTH-1 loop + v.multiply_pipeline(i) := r.multiply_pipeline(i-1); + end loop; + + if v.multiply_pipeline(PIPELINE_DEPTH-1).not_res = '1' then + d := not mult_out; + else + d := mult_out; + 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; + ovf_in <= ov; + + m_out.result <= d; + m_out.overflow <= overflow; + m_out.valid <= v.multiply_pipeline(PIPELINE_DEPTH-1).valid; + + rin <= v; + end process; +end architecture behaviour; + + +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +entity short_multiply is + port ( + clk : in std_ulogic; + + a_in : in std_ulogic_vector(15 downto 0); + b_in : in std_ulogic_vector(15 downto 0); + m_out : out std_ulogic_vector(31 downto 0) + ); +end entity short_multiply; + +architecture behaviour of short_multiply is +begin + m_out <= std_ulogic_vector(signed(a_in) * signed(b_in)); +end architecture behaviour;