title: Multiplication unit skips overflow bit during addition
body: <p>I made a simple multiplication unit (16-bit operands, 32-bit result) based on the &quot;shift-left, add&quot; principle, and it does not work properly in the adder part when the overflow bit needs to be considered.</p>
  <p>I have an idea what should be done (make a 17-bit sum vector and add an overflow bit to the product), but I don't know how to implement it. Below you can find the waveform file where I am showing the error location and the MPU.vhd file. The screenshot does not show the final result, but it is obvious that it will be wrong. How can I get it to work with large 16-bit numbers?</p>
  <p><a href="https://i.stack.imgur.com/L84p2.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/L84p2.png" alt="Place where the overflow bit is skipped" /></a></p>
  <p><strong>MPU.vhd</strong></p>
  <pre><code>library IEEE;
  use IEEE.std_logic_1164.all;
  use IEEE.numeric_std.all; 
  
  entity MPU_OP is
      port (C: in std_logic;    -- Clock
      RST : in std_logic;       -- Reset
      LAB : in std_logic;       -- Load A and B, P &lt;= 0
      SHIFT : in std_logic;     -- Shift B and P
      OUTHL : in std_logic;     -- Output most(0) or least(1) significant word P
      DA : in std_logic_vector(15 downto 0);   -- Data A
      DB : in std_logic_vector(15 downto 0);   -- Data B
      DP : out std_logic_vector(15 downto 0)); -- Word result P
  end entity;
  
  architecture BEH of MPU_OP is
  signal A, B : std_logic_vector(15 downto 0); -- A, B
  signal Pi, Ai, Si : integer;
  signal S : signed(15 downto 0); -- Sum 
  signal S2 : signed(16 downto 0);
  signal P : signed(31 downto 0); -- Product
  
  begin 
      RG_A : process(C, RST) -- Register for A
      begin
          if (RST = '1') then
              A &lt;= X&quot;0000&quot;;
          elsif rising_edge(C) then                                        `-- Reg_A`
              if LAB = '1' then
                  A &lt;= DA;
              end if;
          end if;
      end process;
      
      RG_B : process(C, RST) -- Register for B
      begin
          if (RST = '1') then
              B &lt;= X&quot;0000&quot;;
          elsif rising_edge(C) then
              if LAB = '1' then
                  B &lt;= DB;
              elsif (SHIFT = '1') then
                  B &lt;= std_logic_vector(shift_left(unsigned(B), 1));       `-- Reg_B`
              end if;
          end if;
      end process;    
      
      Adder : process (C)
      begin
          Pi &lt;= to_integer(unsigned(std_logic_vector(P(15 downto 0))));
          Ai &lt;= to_integer(unsigned(A));
  
          if B(15) = '1' then
              S &lt;= P(15 downto 0) + signed(A);                             -- Adder
              Si &lt;= Pi + Ai;
          else
              S &lt;= P(15 downto 0);    
              Si &lt;= Pi;
          S2 &lt;= to_signed(Si, S2'length); 
          end if;
      end process;
  
      
      RG_P : process (C, RST, P) -- Register for P   
      begin
          if RST = '1' then 
              P &lt;= X&quot;00000000&quot;;
          elsif rising_edge(C) then
              if LAB = '1' then
                  P &lt;= X&quot;00000000&quot;;
              elsif SHIFT = '1' then
                  if B /= &quot;1000000000000000&quot; then
                      P &lt;= P(30 downto 16) &amp; S &amp; '0'; -- Shift LEFT        `-- Reg_Product`
                  else
                      P &lt;= P(31 downto 16) &amp; S;
                  end if;
              end if;
          end if;
      end process;
      
      MUX_P : DP &lt;= std_logic_vector(P(15 downto 0)) when OUTHL = '1' else
          std_logic_vector(P(31 downto 16));
      
  end architecture;
          
  </code></pre>
  <p>Below is the minimal code to reproduce the above problem and the testbench for it.</p>
  <p><strong>MPU.vhd</strong></p>
  <pre><code>library IEEE;
  use IEEE.std_logic_1164.all;
  use IEEE.numeric_std.all; 
  
  entity MPU_TEST is
      port (C: in std_logic;
      LAB : in std_logic;
      SHIFT : in std_logic;
      DA : in std_logic_vector(15 downto 0);
      DB : in std_logic_vector(15 downto 0);
      DP : out std_logic_vector(31 downto 0));
  end entity;
  
  architecture BEH of MPU_TEST is
  signal A, B : std_logic_vector(15 downto 0);
  signal S : signed(15 downto 0);
  signal P : signed(31 downto 0); 
  
  begin 
      RG_A : process(C)
      begin
          if rising_edge(C) then
              if LAB = '1' then
                  A &lt;= DA;
              end if;
          end if;
      end process;
      
      RG_B : process(C) 
      begin 
          if rising_edge(C) then
              if LAB = '1' then
                  B &lt;= DB;
              elsif (SHIFT = '1') then
                  B &lt;= std_logic_vector(shift_left(unsigned(B), 1));
              end if;
          end if;
      end process;    
      
      Adder : process (C)
      begin
          if B(15) = '1' then
              S &lt;= P(15 downto 0) + signed(A);
          else
              S &lt;= P(15 downto 0);    
          end if;
      end process;
  
      
      RG_P : process (C, P) 
      begin 
          if rising_edge(C) then
              if LAB = '1' then
                  P &lt;= X&quot;00000000&quot;;
              elsif SHIFT = '1' then
                  if B /= &quot;1000000000000000&quot; then
                      P &lt;= P(30 downto 16) &amp; S &amp; '0';
                  else
                      P &lt;= P(31 downto 16) &amp; S;
                  end if;
              end if;
          end if;
      end process;
      
      DP &lt;= std_logic_vector(P);
  end architecture;
              
  </code></pre>
  <p><strong>MPU_TB.vhd</strong></p>
  <pre><code>library ieee;
  use ieee.NUMERIC_STD.all;
  use ieee.std_logic_1164.all;
  
  entity mpu_test_tb is
  end mpu_test_tb;
  
  architecture TB_ARCHITECTURE of mpu_test_tb is
      component mpu_test
      port(
          C : in STD_LOGIC;
          LAB : in STD_LOGIC;
          SHIFT : in STD_LOGIC;
          DA : in STD_LOGIC_VECTOR(15 downto 0);
          DB : in STD_LOGIC_VECTOR(15 downto 0);
          DP : out STD_LOGIC_VECTOR(31 downto 0) );
      end component;
  
  
      signal C : STD_LOGIC;
      signal LAB : STD_LOGIC;
      signal SHIFT : STD_LOGIC;
      signal DA : STD_LOGIC_VECTOR(15 downto 0);
      signal DB : STD_LOGIC_VECTOR(15 downto 0);
  
      signal DP : STD_LOGIC_VECTOR(31 downto 0);
  
  
  begin
  
  
      UUT : mpu_test
          port map (
              C =&gt; C,
              LAB =&gt; LAB,
              SHIFT =&gt; SHIFT,
              DA =&gt; DA,
              DB =&gt; DB,
              DP =&gt; DP
          );
  
      process
      begin 
          C &lt;= '0';
          wait for 5 ns;
          C &lt;= '1';
          wait for 5 ns;
      end process;
      
      LAB &lt;= '1', '0' after 10 ns;
      SHIFT &lt;= '0', '1' after 10 ns, '0' after 170 ns;
      DA &lt;= X&quot;1234&quot;;
      DB &lt;= X&quot;F234&quot;;
      
  end TB_ARCHITECTURE;
  </code></pre>
  <p>And a new signal with an incorrect multiplication result. The error occurs in adder.</p>
  <p><a href="https://i.stack.imgur.com/wNerc.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/wNerc.png" alt="enter image description here" /></a></p>