user3034001
user3034001

Reputation: 11

VHDL 4-bit binary divider

I am trying to make a binary divider to be part of a calculator using VHDL, I have written the code that I think should work but have been stuck for hours, can someone please help me.

    library IEEE;
    use IEEE.STD_LOGIC_1164.ALL;
    use IEEE.STD_LOGIC_ARITH.ALL;
    use IEEE.STD_LOGIC_UNSIGNED.ALL;


    entity Div is
    Port ( Ain   : in  STD_LOGIC_VECTOR (3 downto 0);
       Bin   : in  STD_LOGIC_VECTOR (3 downto 0);
       Q   : out  STD_LOGIC_VECTOR (3 downto 0);
       R   : out  STD_LOGIC_VECTOR (3 downto 0));
    end Div;

architecture Behavioral of Div is
Signal Atemp : Std_Logic_Vector (3 downto 0);
begin


Proc1: Process (Ain,Bin, Atemp)
variable cnt : STD_LOGIC_Vector(3 downto 0);
begin


if (Ain < Bin) then
        cnt := "0000";
        Atemp <= Ain;
elsif (Ain = Bin) then
        cnt := "0001";
elsif (Ain > Bin) then
        cnt := "0001";
        Atemp <= (Ain - Bin);
        while (Atemp >= Bin) loop
            if(Atemp >=Bin) then
                Atemp <= (Atemp - Bin);
                cnt := cnt + "0001";
            end if;
        end loop;
end if;
Q <= cnt;
R <= Atemp;
end process Proc1;
end Behavioral;

Upvotes: 1

Views: 21855

Answers (2)

VAP
VAP

Reputation: 551

To prevent mistakes, it is advisable to use explicitly the type unsigned or signed when implementing arithmetic circuits. The numeric_std package contains the following arithmetic operators for these types: +, -, *, /, abs, rem, mod.

Below is a suggested code (for unsigned division). Note that some lines in the arch can be eliminated, but were used to make the code more "didactic".

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity divider is
  generic (size: natural := 4);
  port ( 
    A: in std_logic_vector(size-1 downto 0);
    B: in std_logic_vector(size-1 downto 0);
    Q: out std_logic_vector(size-1 downto 0);
    R: out std_logic_vector(size-1 downto 0));
end entity;

architecture direct of divider is 
  signal Auns, Buns, Quns, Runs: unsigned(size-1 downto 0);
begin 

  --Convert inputs to unsigned:
  Auns <= unsigned(A);
  Buns <= unsigned(B);

  --Do the division:
  Quns <= Auns/Buns;
  Runs <= Auns rem Buns; --Or: Runs <= Auns - resize(Quns*Buns, size);

  --Covert results to std_logic_vector:
  Q <= std_logic_vector(Quns);
  R <= std_logic_vector(Runs);  

end architecture

Upvotes: 2

Morten Zilmer
Morten Zilmer

Reputation: 15924

In the iteration part of the divide process, when Ain > Bin, the assign Atemp <= (Ain - Bin) is always performed, even if the iteration should be completed. Process that assign to a signal also in the sensitivity list, is hard to get right.

The code may be updated with Atemp as a variable instead, some other simplifications with removal of unrequired code, and adding value for remainder when Ain = Bin, resulting in architecture as:

architecture Behavioral of Div is
begin

  Proc1 : process (Ain, Bin) is
    variable cnt   : std_logic_vector(3 downto 0);
    variable Atemp : std_logic_vector(3 downto 0);
  begin
    if (Ain < Bin) then
      cnt   := "0000";
      Atemp := Ain;
    elsif (Ain = Bin) then
      cnt := "0001";
      Atemp := (others => '0');  -- Added to give correct remainder
    elsif (Ain > Bin) then
      cnt   := "0001";
      Atemp := (Ain - Bin);
      while (Atemp >= Bin) loop
        -- Removed trivial true if statement, since condition identical to condition in while
        Atemp := (Atemp - Bin);
        cnt   := cnt + "0001";
      end loop;
    end if;
    Q <= cnt;
    R <= Atemp;
  end process Proc1;

end Behavioral;

The inner process statements may actually be reduced to:

cnt   := "0000";
Atemp := Ain;
while (Atemp >= Bin) loop
  Atemp := (Atemp - Bin);
  cnt   := cnt + "0001";
end loop;
Q <= cnt;
R <= Atemp;

Whether this will synthesize to the required frequency with the unrolled while is another question, that depends on the target frequency and technology.

An alternative solution, given the short Ain and Bin, is to implement the divider using a constant lookup table, with address as Ain & Bin and output of Q & R. This will evaluate in fixed time, and synthesis is very likely to reduce considerably if made as combinatorial logic.

Last comment is that you may also want to handle division by zero, when Bin is zero.

Upvotes: 3

Related Questions