简体   繁体   English

VHDL 4位二​​进制除法器

[英]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. 我正在尝试使用VHDL使二进制除法器成为计算器的一部分,我编写了一些代码,虽然我认为它应该可以工作,但是已经停滞了几个小时,请有人帮我。

    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;

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. 在除法过程的迭代部分中,当Ain > Bin时,即使应完成迭代,也始终执行赋值Atemp <= (Ain - Bin) 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: 可以使用Atemp作为变量来更新代码,或者通过删除不需要的代码来进行其他一些简化,并在Ain = Bin时增加余数的值,从而导致体系结构为:

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. 是否将其与展开的while合成为所需的频率是另一个问题,这取决于目标频率和技术。

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 . 给定简短的AinBin的另一种解决方案是使用常数查找表来实现除法器,地址为Ain & Bin并输出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. 最后的评论是,当Bin为零时,您可能还想处理零除。

To prevent mistakes, it is advisable to use explicitly the type unsigned or signed when implementing arithmetic circuits. 为防止错误,建议在实现算术电路时明确使用unsigned或signed类型。 The numeric_std package contains the following arithmetic operators for these types: +, -, *, /, abs, rem, mod. numeric_std软件包包含以下针对这些类型的算术运算符:+,-,*,/,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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM