---------------------------------------------------------------------
|
---------------------------------------------------------------------
|
-- Sequential multiplier
|
-- Sequential multiplier
|
--
|
--
|
-- Part of the LXP32 CPU
|
-- Part of the LXP32 CPU
|
--
|
--
|
-- Copyright (c) 2016 by Alex I. Kuznetsov
|
-- Copyright (c) 2016 by Alex I. Kuznetsov
|
--
|
--
|
-- The smallest possible multiplier. Implemented using
|
-- The smallest possible multiplier. Implemented using
|
-- an accumulator. One multiplication takes 34 cycles.
|
-- an accumulator. One multiplication takes 34 cycles.
|
---------------------------------------------------------------------
|
---------------------------------------------------------------------
|
|
|
library ieee;
|
library ieee;
|
use ieee.std_logic_1164.all;
|
use ieee.std_logic_1164.all;
|
use ieee.numeric_std.all;
|
use ieee.numeric_std.all;
|
|
|
entity lxp32_mul_seq is
|
entity lxp32_mul_seq is
|
port(
|
port(
|
clk_i: in std_logic;
|
clk_i: in std_logic;
|
rst_i: in std_logic;
|
rst_i: in std_logic;
|
ce_i: in std_logic;
|
ce_i: in std_logic;
|
op1_i: in std_logic_vector(31 downto 0);
|
op1_i: in std_logic_vector(31 downto 0);
|
op2_i: in std_logic_vector(31 downto 0);
|
op2_i: in std_logic_vector(31 downto 0);
|
ce_o: out std_logic;
|
ce_o: out std_logic;
|
result_o: out std_logic_vector(31 downto 0)
|
result_o: out std_logic_vector(31 downto 0)
|
);
|
);
|
end entity;
|
end entity;
|
|
|
architecture rtl of lxp32_mul_seq is
|
architecture rtl of lxp32_mul_seq is
|
|
|
signal reg1: unsigned(op1_i'range);
|
signal reg1: unsigned(op1_i'range);
|
signal reg2: unsigned(op2_i'range);
|
signal reg2: unsigned(op2_i'range);
|
signal pp: unsigned(31 downto 0);
|
signal pp: unsigned(31 downto 0);
|
signal acc_sum: unsigned(31 downto 0);
|
signal acc_sum: unsigned(31 downto 0);
|
signal cnt: integer range 0 to 32:=0;
|
signal cnt: integer range 0 to 32:=0;
|
signal ceo: std_logic:='0';
|
signal ceo: std_logic:='0';
|
|
|
begin
|
begin
|
|
|
pp<=reg1 when reg2(0)='1' else (others=>'0');
|
pp<=reg1 when reg2(0)='1' else (others=>'0');
|
|
|
process (clk_i) is
|
process (clk_i) is
|
begin
|
begin
|
if rising_edge(clk_i) then
|
if rising_edge(clk_i) then
|
if rst_i='1' then
|
if rst_i='1' then
|
ceo<='0';
|
ceo<='0';
|
cnt<=0;
|
cnt<=0;
|
reg1<=(others=>'-');
|
reg1<=(others=>'-');
|
reg2<=(others=>'-');
|
reg2<=(others=>'-');
|
acc_sum<=(others=>'-');
|
acc_sum<=(others=>'-');
|
else
|
else
|
if cnt=1 then
|
if cnt=1 then
|
ceo<='1';
|
ceo<='1';
|
else
|
else
|
ceo<='0';
|
ceo<='0';
|
end if;
|
end if;
|
|
|
if ce_i='1' then
|
if ce_i='1' then
|
cnt<=32;
|
cnt<=32;
|
reg1<=unsigned(op1_i);
|
reg1<=unsigned(op1_i);
|
reg2<=unsigned(op2_i);
|
reg2<=unsigned(op2_i);
|
acc_sum<=(others=>'0');
|
acc_sum<=(others=>'0');
|
else
|
else
|
acc_sum<=acc_sum+pp;
|
acc_sum<=acc_sum+pp;
|
reg1<=reg1(reg1'high-1 downto 0)&"0";
|
reg1<=reg1(reg1'high-1 downto 0)&"0";
|
reg2<="0"®2(reg2'high downto 1);
|
reg2<="0"®2(reg2'high downto 1);
|
if cnt>0 then
|
if cnt>0 then
|
cnt<=cnt-1;
|
cnt<=cnt-1;
|
end if;
|
end if;
|
end if;
|
end if;
|
end if;
|
end if;
|
end if;
|
end if;
|
end process;
|
end process;
|
|
|
result_o<=std_logic_vector(acc_sum);
|
result_o<=std_logic_vector(acc_sum);
|
ce_o<=ceo;
|
ce_o<=ceo;
|
|
|
end architecture;
|
end architecture;
|
|
|