⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 divider_rtl_ser.vhd

📁 Intel微处理器8088的VHDL实现
💻 VHD
字号:
-- -----------------------------------------------------------------------------
--   CPU86 - VHDL CPU8088 IP core                                             --
--   Copyright (C) 2005-2008 HT-LAB                                           --
--                                                                            --
--   Contact/bugs : http://www.ht-lab.com/misc/feedback.html                  --
--   Web          : http://www.ht-lab.com                                     --
--                                                                            --
--   CPU86 is released as open-source under the Aladdin Free Public License.  --
--   Contact HT-Lab for commercial applications and/or support contracts.     --
--                                                                            --
--   Full details of the license can be found in the file "cpu86_license.txt" --
--   which is included in the distribution zip file.                          --
-- -----------------------------------------------------------------------------
--
-- -----------------------------------------------------------------------------
--  CPU86 Signed/Unsigned Restoring Divider 
--  VHDL Entity CPU.divider.rtl_ser
--
--  Created: by - Hans 24/06/2002
--
--  Version   Author          Date          Changes
--  0.1       HT-Lab          18/07/02      Tested on Modelsim SE 5.6
-- -----------------------------------------------------------------------------


LIBRARY ieee;
USE ieee.std_logic_1164.all;
USE ieee.std_logic_unsigned.all;
use ieee.std_logic_arith.all;

ENTITY divider IS
   GENERIC( 
      WIDTH_DIVID : integer := 32;      -- Width Dividend
      WIDTH_DIVIS : integer := 16;      -- Width Divisor
      WIDTH_SHORT : Integer := 8        -- Check Overflow against short Byte/Word
   );
   PORT( 
      clk       : IN     std_logic;                                  -- System Clock
      reset     : IN     std_logic;                                  -- Active high
      dividend  : IN     std_logic_vector (WIDTH_DIVID-1 DOWNTO 0);
      divisor   : IN     std_logic_vector (WIDTH_DIVIS-1 DOWNTO 0);
      quotient  : OUT    std_logic_vector (WIDTH_DIVIS-1 DOWNTO 0);
      remainder : OUT    std_logic_vector (WIDTH_DIVIS-1 DOWNTO 0);
      twocomp   : IN     std_logic;
      w         : IN     std_logic;                                  -- UNUSED!
      overflow  : OUT    std_logic;
      start     : IN     std_logic;
      done      : OUT    std_logic
   );
END divider ;


ARCHITECTURE rtl_ser OF divider IS

signal dividend_s     : std_logic_vector(WIDTH_DIVID downto 0);         -- Add extra guard bit
signal divisor_s      : std_logic_vector(WIDTH_DIVIS downto 0);         -- Add extra guard bit

signal divis_rect_s   : std_logic_vector(WIDTH_DIVIS-1 downto 0);       -- Divisor rectified for comparsion
               
signal signquot_s     : std_logic;
signal signremain_s   : std_logic;                         

signal accumulator_s  : std_logic_vector(WIDTH_DIVID downto 0); 
signal aluout_s       : std_logic_vector(WIDTH_DIVIS downto 0);         -- +1 bit
signal newaccu_s      : std_logic_vector(WIDTH_DIVID downto 0);         -- +1 bit

signal quot_s         : std_logic_vector (WIDTH_DIVIS-1 downto 0);
signal remain_s       : std_logic_vector (WIDTH_DIVIS-1 downto 0);

constant null_s       : std_logic_vector(31 downto 0) := X"00000000";   

signal count_s        : std_logic_vector (3 downto 0);                  -- Number of iterations

signal overflow_s     : std_logic; --_vector (WIDTH_DIVIS downto 0);
signal sremainder_s   : std_logic_vector (WIDTH_DIVIS-1 downto 0);
signal squotient_s    : std_logic_vector (WIDTH_DIVIS-1 downto 0);

signal signfailure_s  : std_logic;                                      -- incorrect result sign for signed division

signal zeroq_s        : std_logic;                                      -- Zero Quotient
signal zeror_s        : std_logic;                                      -- Zero Remainder
signal zerod_s        : std_logic;                                      -- Zero Divisor

signal pos_s          : std_logic;
signal neg_s          : std_logic;

type   states is (s0,s1,s2);                                            -- FSM 
signal state,nextstate: states;

function rectifyd (r  : in  std_logic_vector (WIDTH_DIVID downto 0);    -- Rectifier for dividend + 1 bit
                  twoc: in  std_logic)                                  -- Signed/Unsigned
  return std_logic_vector is 
  variable rec_v      : std_logic_vector (WIDTH_DIVID downto 0);                
begin
    if ((r(WIDTH_DIVID) and twoc)='1') then 
        rec_v := not(r); 
    else 
        rec_v := r;
    end if;
    return (rec_v + (r(WIDTH_DIVID) and twoc));        
end; 

function rectifys (r  : in  std_logic_vector (WIDTH_DIVIS-1 downto 0);  -- Rectifier for divisor
                  twoc: in  std_logic)                                  -- Signed/Unsigned
  return std_logic_vector is 
  variable rec_v      : std_logic_vector (WIDTH_DIVIS-1 downto 0);                
begin
    if ((r(WIDTH_DIVIS-1) and twoc)='1') then 
        rec_v := not(r); 
    else 
        rec_v := r;
    end if;
    return (rec_v + (r(WIDTH_DIVIS-1) and twoc));        
end; 


begin   

--  Sign Quotient
    signquot_s    <= (dividend(WIDTH_DIVID-1) xor divisor(WIDTH_DIVIS-1)) and twocomp;
        
--  Sign Remainder
    signremain_s  <= dividend(WIDTH_DIVID-1) and twocomp;


--  For unsigned dividend just add leading '0', for signed rectify sign extended dividend
    dividend_s    <= '0'&dividend when twocomp='0' else rectifyd(dividend(WIDTH_DIVID-1)&dividend, twocomp);                       

    divisor_s <= ('1'&divisor) when (divisor(WIDTH_DIVIS-1) and twocomp)='1' else not('0'&divisor) + '1';

--  Subtractor (Adder, WIDTH_DIVIS+1)
    aluout_s      <= accumulator_s(WIDTH_DIVID downto WIDTH_DIVID-WIDTH_DIVIS) + divisor_s;

--  Append Quotient section to aluout_s
    newaccu_s     <= aluout_s & accumulator_s(WIDTH_DIVID-WIDTH_DIVIS-1 downto 0);   

process (clk,reset)                         
    begin
        if (reset='1') then                     
            accumulator_s   <= (others => '0');
        elsif (rising_edge(clk)) then  
            if start='1' then                                           
                accumulator_s <= dividend_s(WIDTH_DIVID-1 downto 0) & '0';   -- Load Dividend in remainder +shl
            elsif pos_s='1' then                                             -- Positive, remain=shl(remain,1)
                accumulator_s <= newaccu_s(WIDTH_DIVID-1 downto 0) & '1';    -- Use sub result   
            elsif neg_s='1' then                                             -- Negative, shl(remainder,0)
                accumulator_s <= accumulator_s(WIDTH_DIVID-1 downto 0) & '0';-- Use original remainder
            end if;                               
        end if;   
end process;    

-- 2 Process Control FSM
process (clk,reset)       
    begin
        if (reset = '1') then     
            state   <= s0; 
            count_s <= (others => '0');             
        elsif (rising_edge(clk)) then    
            state <= nextstate;   
            if (state=s1) then
                count_s <= count_s - '1';
            elsif (state=s0) then
                count_s <=  CONV_STD_LOGIC_VECTOR(WIDTH_DIVIS-1, 4);     -- extra step CAN REDUCE BY 1 since DONE is latched!!
            end if;
        end if;   
end process;  

process(state,start,aluout_s,count_s)
    begin  
        case state is
          when s0 => 
                pos_s <= '0';
                neg_s <= '0';                                           
                if  start='1' then 
                    nextstate <= s1; 
                else 
                    nextstate <= s0;
                end if; 
          when s1 =>
                neg_s <= aluout_s(WIDTH_DIVIS);      
                pos_s <= not(aluout_s(WIDTH_DIVIS)); 
                if (count_s=null_s(3 downto 0)) then nextstate <= s2; -- Done 
                                                else nextstate <= s1; -- Next sub&shift
                end if;
          when s2=>
                pos_s <= '0';
                neg_s <= '0';                                           
                nextstate <= s0;  
          when others => 
                pos_s <= '0';
                neg_s <= '0';                                           
                nextstate <= s0;              
        end case;                   
end process;    

remain_s        <= accumulator_s(WIDTH_DIVID downto WIDTH_DIVID-WIDTH_DIVIS+1);

-- Overflow if remainder>divisor or divide by 0 or sign error. Change all to positive.
divis_rect_s    <= rectifys(divisor, twocomp);
overflow_s      <= '1' when ((remain_s>=divis_rect_s) or (zerod_s='1')) else '0';

-- bottom part of remainder is quotient
quot_s          <=  accumulator_s(WIDTH_DIVIS-1 downto 0);

-- Remainder Result
sremainder_s    <= ((not(remain_s)) + '1') when signremain_s='1' else remain_s;
remainder       <= sremainder_s;

-- Qotient Result
squotient_s     <= ((not(quot_s)) + '1')  when signquot_s='1'   else quot_s;    
quotient        <= squotient_s;

-- Detect zero vector
zeror_s         <= '1' when (twocomp='1' and sremainder_s=null_s(WIDTH_DIVIS-1 downto 0)) else '0';
zeroq_s         <= '1' when (twocomp='1' and squotient_s=null_s(WIDTH_DIVIS-1 downto 0)) else '0';
zerod_s         <= '1' when (divisor=null_s(WIDTH_DIVIS-1 downto 0)) else '0';

-- Detect Sign failure
signfailure_s   <= '1' when (signquot_s='1'   and squotient_s(WIDTH_DIVIS-1)='0'  and zeroq_s='0') or
                            (signremain_s='1' and sremainder_s(WIDTH_DIVIS-1)='0' and zeror_s='0') else '0';

done     <= '1' when state=s2 else '0';
-- state=s2 not required since overflow is latched when done=1
overflow <= '1' when (overflow_s='1' or signfailure_s='1') else '0';

end architecture rtl_ser;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -