OpenCores
URL https://opencores.org/ocsvn/mkjpeg/mkjpeg/trunk

Subversion Repositories mkjpeg

[/] [mkjpeg/] [trunk/] [design/] [quantizer/] [s_divider.vhd] - Rev 48

Go to most recent revision | Compare with Previous | Blame | View Log

--------------------------------------------------------------------------------
--                                                                            --
--                          V H D L    F I L E                                --
--                          COPYRIGHT (C) 2006-2009                           --
--                                                                            --
--------------------------------------------------------------------------------
--                                                                            --
-- Title       : DIVIDER                                                      --
-- Design      : Signed Pipelined Divider core                                --
-- Author      : Michal Krepa                                                 --
--                                                                            --
--------------------------------------------------------------------------------
--                                                                            --
-- File        : S_DIVIDER.VHD                                                --
-- Created     : Sat Aug 26 2006                                              --
-- Modified    : Thu Mar 12 2009                                              --
--                                                                            --
--------------------------------------------------------------------------------
--                                                                            --
--  Description : Signed Pipelined Divider                                    --
--                                                                            --
-- dividend allowable range of -2**SIZE_C to 2**SIZE_C-1 [SIGNED number]      --
-- divisor allowable range of 1 to (2**SIZE_C)/2-1 [UNSIGNED number]          --
-- pipeline latency is 2*SIZE_C+2 (time from latching input to result ready)  --
-- when pipeline is full new result is generated every clock cycle            --
-- Non-Restoring division algorithm                                           --
-- Use SIZE_C constant in divider entity to adjust bit width                  --
--------------------------------------------------------------------------------
 
--------------------------------------------------------------------------------
-- MAIN DIVIDER top level
--------------------------------------------------------------------------------
library IEEE;
  use IEEE.STD_LOGIC_1164.All;
  use IEEE.NUMERIC_STD.all;
 
entity s_divider is
  generic 
  ( 
       SIZE_C          : INTEGER := 32
  ) ;            -- SIZE_C: Number of bits
  port 
  (
       rst   : in  STD_LOGIC;
       clk   : in  STD_LOGIC;
       a     : in  STD_LOGIC_VECTOR(SIZE_C-1 downto 0) ;     
       d     : in  STD_LOGIC_VECTOR(SIZE_C-1 downto 0) ;     
 
       q     : out STD_LOGIC_VECTOR(SIZE_C-1 downto 0) ;     
       r     : out STD_LOGIC_VECTOR(SIZE_C-1 downto 0) ;
       round : out STD_LOGIC
  ) ;   
end s_divider ;
 
architecture str of s_divider is
 
  type S_ARRAY  is array(0 to SIZE_C+3) of unsigned(SIZE_C-1 downto 0);
  type S2_ARRAY is array(0 to SIZE_C+1) of unsigned(2*SIZE_C-1 downto 0);
 
  signal d_s          : S_ARRAY;
  signal q_s          : S_ARRAY;
  signal r_s          : S2_ARRAY;
  signal diff         : S_ARRAY;
  signal qu_s         : STD_LOGIC_VECTOR(SIZE_C-1 downto 0);
  signal ru_s         : unsigned(SIZE_C-1 downto 0);
  signal qu_s2        : STD_LOGIC_VECTOR(SIZE_C-1 downto 0);
  signal ru_s2        : unsigned(SIZE_C-1 downto 0);
  signal d_reg        : STD_LOGIC_VECTOR(SIZE_C-1 downto 0);
  signal pipeline_reg : STD_LOGIC_VECTOR(SIZE_C+3-1 downto 0);
  signal r_reg        : STD_LOGIC_VECTOR(SIZE_C-1 downto 0);
 
begin
 
 pipeline : process(clk,rst)
 begin
   if rst = '1' then
     for k in 0 to SIZE_C loop
       r_s(k) <= (others => '0');
       q_s(k) <= (others => '0');
       d_s(k) <= (others => '0');
     end loop;
     pipeline_reg <= (others => '0');
   elsif clk = '1' and clk'event then
 
     -- negative number
     if a(SIZE_C-1) = '1' then
       -- negate negative number to create positive
       r_s(0)       <= unsigned(resize(unsigned(not(SIGNED(a)) + TO_SIGNED(1,SIZE_C)),2*SIZE_C));
       -- left shift
       pipeline_reg <= pipeline_reg(pipeline_reg'high-1 downto 0) & '1';
     else
       r_s(0)       <= resize(unsigned(a),2*SIZE_C);
       -- left shift
       pipeline_reg <= pipeline_reg(pipeline_reg'high-1 downto 0) & '0';
     end if;
     d_s(0) <= unsigned(d);
     q_s(0) <= (others => '0');
 
     -- pipeline
     for k in 0 to SIZE_C loop
       -- test remainder if positive/negative
       if r_s(k)(2*SIZE_C-1) = '0' then
         -- shift r_tmp one bit left and subtract d_tmp from upper part of r_tmp 
         r_s(k+1)(2*SIZE_C-1 downto SIZE_C) <= r_s(k)(2*SIZE_C-2 downto SIZE_C-1) - d_s(k);
       else
         r_s(k+1)(2*SIZE_C-1 downto SIZE_C) <= r_s(k)(2*SIZE_C-2 downto SIZE_C-1) + d_s(k);
       end if;
       -- shift r_tmp one bit left (lower part)
       r_s(k+1)(SIZE_C-1 downto 0) <= r_s(k)(SIZE_C-2 downto 0) & '0';
 
       if diff(k)(SIZE_C-1) = '0' then
         q_s(k+1) <= q_s(k)(SIZE_C-2 downto 0) & '1';
       else
         q_s(k+1) <= q_s(k)(SIZE_C-2 downto 0) & '0';
       end if;
 
       d_s(k+1) <= d_s(k);
     end loop;
   end if;
 end process;  
 
 G_DIFF: for x in 0 to SIZE_C generate
   diff(x) <= r_s(x)(2*SIZE_C-2 downto SIZE_C-1) - d_s(x) when r_s(x)(2*SIZE_C-1) = '0'
              else r_s(x)(2*SIZE_C-2 downto SIZE_C-1) + d_s(x);
 end generate G_DIFF;
 
 qu_s <= STD_LOGIC_VECTOR( q_s(SIZE_C) );
 ru_s <= r_s(SIZE_C)(2*SIZE_C-1 downto SIZE_C);
 
 process(clk,rst)
 begin
   if rst = '1' then
     q     <= (others => '0'); 
     r_reg <= (others => '0');   
     round <= '0'; 
   elsif clk = '1' and clk'event then
 
 
     if ru_s(SIZE_C-1) = '0' then
       ru_s2 <= (ru_s);
     else
       ru_s2 <= (unsigned(ru_s) + d_s(SIZE_C));
     end if;
     qu_s2 <= qu_s;
 
     -- negative number
     if pipeline_reg(SIZE_C+1) = '1' then
       -- negate positive number to create negative
       q <= STD_LOGIC_VECTOR(not(SIGNED(qu_s2)) + TO_SIGNED(1,SIZE_C));
       r_reg <= STD_LOGIC_VECTOR(not(SIGNED(ru_s2)) + TO_SIGNED(1,SIZE_C));
     else
       q <= STD_LOGIC_VECTOR(qu_s2);
       r_reg <= STD_LOGIC_VECTOR(ru_s2);
     end if; 
 
     -- if 2*remainder >= divisor then add 1 to round to nearest integer
     if (ru_s2(SIZE_C-2 downto 0) & '0') >= d_s(SIZE_C+1) then
       round <= '1';
     else
       round <= '0';
     end if;
   end if;
 end process; 
 
 -- remainder
 r <= r_reg;
 
end str;
 
 
 

Go to most recent revision | Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.