--  logic taken from https://en.wikipedia.org/wiki/Division_algorithm
USE ieee.std_logic_1164.all;
USE ieee.numeric_std.all;

    OperandA    : in std_logic_vector(3 downto 0);
    OperandB    : in std_logic_vector(3 downto 0);
    Errorsig    : out STD_LOGIC := '0';
    Result_Low  : out std_logic_vector(3 downto 0);
    Result_High : out std_logic_vector(3 downto 0));
END Div;

signal Q,R : std_logic_vector (3 downto 0) := "0000";
signal i : integer := 3;
signal diff,borr : std_logic_vector (3 downto 0) := "0000";
signal er,err : std_logic := '0';

    OperandA    : in std_logic_vector(3 downto 0);
    OperandB    : in std_logic_vector(3 downto 0);
    Result_Low  : out std_logic_vector(3 downto 0);
    Result_High : out std_logic_vector(3 downto 0);
    Errorsig    : out std_Logic);
END component;

Sub1 : SUB
     PORT MAP(

    if OperandB = "0000" then i<=0; else                     
       for i in 3 to 0 loop     -- where n is number of bits in N
        R <= R(2 downto 0) & '0';          -- left-shift R by 1 bit
        R(0) <= OperandA(i);         -- set the least-significant bit of R equal to bit i of the numerator
         if R >= OperandB then
            -- Sub1(R,OperandB,diff,borr,err);
         R <= diff;
             Q(i) <= '1';
         end if;
        end loop; 
    end if;

  end process;

END behavioral;

--Someone please help me. Am a newbie and unable to figure it out on my own. Thanks

  • 2
    \$\begingroup\$ for i in 3 to 0 -> for i in 3 downto 0 \$\endgroup\$
    – Eugene Sh.
    Commented Jun 15, 2015 at 19:36
  • 2
    \$\begingroup\$ Indeed, 3 (up)to 0 is a null range. \$\endgroup\$
    – user16324
    Commented Jun 15, 2015 at 19:38
  • \$\begingroup\$ vcom Message # 1246: The specified range is a null range and therefore contains no values. This occurs when the direction is TO and LEFT > RIGHT, or when the direction is DOWNTO and LEFT < RIGHT. \$\endgroup\$
    – user8352
    Commented Jun 15, 2015 at 22:10

2 Answers 2


Besides the null range so ably pointed out by Brian and Eugene, your algorithm implementation won't work because it's depending on signal update values to occur in the same delta cycle. No signal is updated during the execution of a process, a new signal value assigned is available in subsequent simulation cycles, unlike variable assignment which takes effect immediately.

There are two ways to address this, introduce delay between each time a signal is assigned and when it is next used or use variables.

(There's actually a third way, evaluate before assign, but VHDL is specifically designed so you don't have to. Subsequent simulation cycles (Delta cycles) allow emulation of parallelism and are distinguished by not being preceded by the advancement of simulation time.)

This demonstrates how to use variables:

--  logic taken from https://en.wikipedia.org/wiki/division_algorithm
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity div is
        operanda:     in std_logic_vector(3 downto 0);
        operandb:     in std_logic_vector(3 downto 0);
        errorsig:     out std_logic := '0';
        result_low:   out std_logic_vector(3 downto 0);
        result_high:  out std_logic_vector(3 downto 0)
end div;

architecture foo of div is


        variable quotient:  unsigned (3 downto 0);
        variable remainder: unsigned (3 downto 0);
    -- if D == 0 then error(DivisionByZeroException) end
    -- Q := 0                 -- initialize quotient and remainder to zero
    -- R := 0
    -- for i = n-1...0 do     -- where n is number of bits in N
    --   R := R << 1          -- left-shift R by 1 bit
    --   R(0) := N(i)         -- set the least-significant bit of R equal to bit i of the numerator
    --   if R >= D then
    --     R := R - D
    --     Q(i) := 1
    --   end
    -- end

    -- We
        errorsig <= '0';      -- allows successive operations
        if operandb = "0000" then
        --     i<= 0;
            assert  operandb /= "0000"
                report "Division by Zero Exception"
                severity ERROR;
            errorsig <= '1';
            quotient := (others => '0'); -- "0000"
            remainder := (others => '0');
           for i in 3 downto 0 loop  
               remainder := remainder (2 downto 0) & '0';   -- r << 1
               remainder(0) := operanda(i);       -- operanda is numerator
               if remainder >= unsigned(operandb) then  -- operandb denominator
                    remainder := remainder - unsigned(operandb);
                    quotient(i) := '1';
               end if;
            end loop;
            result_high <= std_logic_vector(quotient); -- for error keeps
            result_low  <= std_logic_vector(remainder); -- last value (invalid)
        end if;
    end process;

end architecture foo;

library ieee;
use ieee.std_logic_1164.all;

entity div_tb is
end entity;

architecture foo of div_tb is
    signal operanda:    std_logic_vector (3 downto 0) := (others => '0');
    signal operandb:    std_logic_vector (3 downto 0) := (others => '1');
    signal errorsig:    std_logic;
    signal result_low:  std_logic_vector (3 downto 0);  -- remainder
    signal result_high: std_logic_vector (3 downto 0);  -- quotient
    entity work.div
        port map (
            operanda => operanda,
            operandb => operandb,
            errorsig => errorsig,
            result_low => result_low,
            result_high => result_high
        operanda <= "1000";  -- 8
        operandb <= "0010";  -- 2
        wait for 20 ns;
        operandb <= "0100";  -- 4
        wait for 20 ns;    
        operandb <= "1000";  -- 8
        wait for 20 ns;
        operanda <= "1111";  -- 15
        operandb <= "0011";  -- 3
        wait for 20 ns;
        operandb <= (others => '0');
        wait for 20 ns;
        operanda <= "1101";  -- 13
        operandb <= "0111";  -- 7
        wait for 20 ns;
    end process;
end architecture;

And when run even works:

div_tb.png (clickable)

Using a subroutine doing subtraction instead of an operator

We can look at the two involved functions in package numeric_std:

function "-" (L, R: UNSIGNED) return UNSIGNED is
  variable L01 : UNSIGNED(SIZE-1 downto 0);
  variable R01 : UNSIGNED(SIZE-1 downto 0);
  if ((L'LENGTH < 1) or (R'LENGTH < 1)) then return NAU;
  end if;
  L01 := TO_01(RESIZE(L, SIZE), 'X');
  if (L01(L01'LEFT)='X') then return L01;
  end if;
  R01 := TO_01(RESIZE(R, SIZE), 'X');
  if (R01(R01'LEFT)='X') then return R01;
  end if;
  return ADD_UNSIGNED(L01, not(R01), '1');
end "-";

  constant L_LEFT: INTEGER := L'LENGTH-1;
  alias XL: UNSIGNED(L_LEFT downto 0) is L;
  alias XR: UNSIGNED(L_LEFT downto 0) is R;
  variable RESULT: UNSIGNED(L_LEFT downto 0);
  variable CBIT: STD_LOGIC := C;
  for I in 0 to L_LEFT loop
    RESULT(I) := CBIT xor XL(I) xor XR(I);
    CBIT := (CBIT and XL(I)) or (CBIT and XR(I)) or (XL(I) and XR(I));
  end loop;
  return RESULT;

First we're going to call the function sub. We don't need resizing both operands are the same size. We do need copies of the parameters, and we can consolidate the bits we need:

architecture foo of div is
    function sub (L, R: unsigned) return unsigned is
        variable L01:       unsigned(L'LENGTH - 1 downto 0);
        variable R01:       unsigned(R'LENGTH - 1 downto 0);
        variable CBIT:      std_logic := '1';  -- carry in '1'
        variable RESULT:    unsigned(L01'RANGE);
        L01 :=     TO_01(L,'X');
        R01 := not TO_01(R,'X');

        for i in 0 to integer(L01'LENGTH) - 1 loop
            RESULT(i) := CBIT xor L01(i) xor R01(i);
            CBIT := (CBIT and L01(i)) or (CBIT and R01(i)) or (L01(i) and R01(i));        
        end loop;
        return RESULT;
    end function;

(And we did this as a block declarative item in the architecture declaration).

Then switch to the sub function:

                -- remainder := remainder - unsigned(operandb);
                remainder := sub(remainder, unsigned(operandb));

And all without using wait statements or adding operators:

div_tb_sub.png (clickable)

And this gives the same answer as using the "-" operator. (Note the radix of OperandA has been changed to decimal).

You could note there's a bit more optimization that can be done with a local function sub. We could get rid of the numeric_std package use clause and convert anything that's unsigned to std_logic_vector. You'd need a TO_01 function (or for loops to perform the same thing) for std_logic_vector.

You could simply the sub function a bit more too. (Hint: it implies removing functionality, implied by the and_table, or_table and xor_table in the package std_logic_1164 body. Do we really need TO_01? The purpose in package numeric_std is to represent binary numbers in type unsigned.) In other words you could write your own subtract function.

If you turn in something with a similar function you're going to be required to explain how it works.

  • \$\begingroup\$ And one more thing, I am not supposed to use subtract sign (- sign). Anyway I can subtract D from R logically without using the sign? \$\endgroup\$ Commented Jun 16, 2015 at 1:32
  • \$\begingroup\$ specifically the "-" operator, or any adding operator? Can you use a function? And is this going to be synthesized? \$\endgroup\$
    – user8352
    Commented Jun 16, 2015 at 6:08
  • \$\begingroup\$ Without using +,-,*,/. No wait cycles can be used. Yes I think we can use a function :-) And no just to be simulated :-) \$\endgroup\$ Commented Jun 16, 2015 at 6:23

You should replace this line:

for i in 3 to 0 ....

with this:

for i in 3 downto 0 ....

The syntax for i in A to B you are using in your code, iterating from i=A to i=B incrementing the value at each iteration. It means, that if A > B it will not work, since you can't go from A to B by incrementing. The syntax for going from A to B when A>B is to use for i in A downto B. This way the value of i will decrement at each iteration starting from A and reaching B.


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.