【问题标题】:4 bit adder in vhdlvhdl 中的 4 位加法器
【发布时间】:2013-09-13 19:49:15
【问题描述】:

我对 vhdl 语言很陌生,所以请多多包涵。我刚刚为 1 位加法器编写了 vhdl 代码,但在编写 4 位加法器时遇到了麻烦。这就是我到目前为止所得到的,如果有人能指出我要查找的正确方向,那就太棒了!

VHDL代码:

LIBRARY IEEE; 
USE IEEE.STD_LOGIC_1164.ALL; 

ENTITY Adder4 IS
  GENERIC(CONSTANT N: INTEGER := 4);
  PORT(
    a, b: IN STD_LOGIC_VECTOR(N-1 DOWNTO 0);  -- Input SW[7..4]: a[3..0] inputs,
                                              -- SW[3..0]: b[3..0]
    sum: OUT STD_LOGIC_VECTOR(N-1 DOWNTO 0); -- Output LEDR[3..0]
    cOut: OUT STD_LOGIC -- Output LEDR[4]
  );
END Adder4;

ARCHITECTURE imp OF Adder4 IS
  COMPONENT Adder1 
  PORT(
    a, b, cIn : in STD_LOGIC;
    sum, cOut : out STD_LOGIC);
  END COMPONENT;
  SIGNAL carry_sig: std_logic_vector(N DOWNTO 0);
BEGIN
  -- What to write here?
END imp;

【问题讨论】:

    标签: vhdl intel-fpga


    【解决方案1】:

    尊重 sharth 关于您是否打算在 Adder4 中实例化 N 个 Adder1 的好答案:

    ARCHITECTURE imp OF Adder4 IS
    COMPONENT Adder1 
    PORT(
    a, b, cIn : in STD_LOGIC;
    sum, cOut : out STD_LOGIC);
    END COMPONENT;
    SIGNAL carry_sig: std_logic_vector(N-1 DOWNTO 0);
    signal carry_in:  std_logic_vector(N-1 DOWNTO 0);
    BEGIN
    -- What to write here?
    
        carry_in <= ((carry_sig(N-2 downto 0)) &'0');
    Adders:
    for i in 0 to N-1 generate
        begin
        ADD1:
            Adder1 port map (
                a => a(i), 
                b => b(i),
                cIn => carry_in(i),
                sum => sum(i),
                cOut => carry_sig(i)            
            );
        end generate;
    
    Carry_Out:
        cOut <= carry_sig(N-1);
    
    END imp;
    
    ARCHITECTURE gen OF Adder4 IS
        COMPONENT Adder1 
        PORT(
            a, b, cIn : in STD_LOGIC;
            sum, cOut : out STD_LOGIC);
            END COMPONENT;
    
    SIGNAL carry_sig: std_logic_vector(N-1 DOWNTO 0);
    
    BEGIN
    -- What to write here?
    
    Adders:
        for i in 0 to N-1 generate
        ADD0:    
            if i = 0 generate
            Add1:
                Adder1 port map (
                    a => a(i), 
                    b => b(i),
                    cIn => '0',
                    sum => sum(i),
                    cOut => carry_sig(i)            
                );
            end generate;
        ADDN:
            if i /= 0 generate
                Add1:
                Adder1 port map (
                    a => a(i), 
                    b => b(i),
                    cIn => carry_sig(i-1),
                    sum => sum(i),
                    cOut => carry_sig(i)  
                );          
            end generate;
    
        end generate;
    
    Carry_Out:
        cOut <= carry_sig(N-1);
    
    END architecture;
    

    我自己更喜欢第一个架构 (imp),它需要第二个 std_logic_vector 用于进位输入,但大大简化了任何生成构造。两者之间的层次结构有所不同,第一个更容易阅读。


    第一个架构 (imp) 还展示了如何手动实例化 Adder1 四次,消除了 generate 构造并将所有 (i) 范围表达式替换为它们各自的 Adder1 实例范围表达式 ((0),(1),(2) ,(3),分别)。

    手动实例化的 adder1 看起来像:

    -- Note in this case you'd likely declare all the std_logic_vector with 
    -- ranges (3 downto 0)
    
    
        SIGNAL carry_sig: std_logic_vector(3 DOWNTO 0);
        signal carry_in:  std_logic_vector(3 downto 0);
    BEGIN
    -- What to write here?
    
        carry_in <= ((carry_sig(2 downto 0)) &'0'); 
    
        ADD0:
            Adder1 port map (
                a => a(0), 
                b => b(0),
                cIn => carry_in(0),
                sum => sum(0),
                cOut => carry_sig(0)            
            );
    
     ...
    
        ADD3:
            Adder1 port map (
                a => a(3), 
                b => b(3),
                cIn => carry_in(3),
                sum => sum(3),
                cOut => carry_sig(3)            
            );
    
    cOut <= carry_sig(3); -- or connect directly to cOut in ADD3 above
    

    使用 carry_sig 的附加进位向量向上调整,最低有效进位进位为 '0',使其易于编写。如果进位信号和进位信号分别命名,那么实现进位前瞻方法也更容易阅读。


    一个测试台也可以容纳一个宽度为N的Adder4:

    library ieee;
    use ieee.std_logic_1164.all;
    use ieee.numeric_std.all;
    
    entity adder4_tb is
           constant N:  natural := 4; 
    end entity;
    
    architecture tb of adder4_tb is
       signal a,b,sum:  std_logic_vector (N-1 downto 0);
       signal carryout:    std_logic;
    
    begin
    
    DUT: entity work.Adder4
        generic map (N => N)  -- associates formal N with actual N (a constant)
        port map (
            a => a,
            b => b,
            sum => sum,
            cOut => carryout
        );
    
    STIMULUS:
        process 
        variable i,j:   integer;
        begin
            for i in 0 to N*N-1 loop
                for j in 0 to N*N-1 loop
                    a <= std_logic_vector(to_unsigned(i,N)); 
                    b <= std_logic_vector(to_unsigned(j,N));
                    wait for 10 ns;     -- so we can view waveform display
                end loop;
            end loop;
            wait;   -- end the simulation
        end process;   
    end architecture;
    

    所有这些都没有考虑进位树延迟时间,它可能会受到实施或使用快速进位电路(例如进位前瞻)的影响。

    这给了我们一个看起来像这样的模拟:

    或者为了更仔细的查看:

    当使用基于生成语句的架构时,如果您更改了 N 的声明,您将拥有一个加法器,它将以 N 指定的可变宽度进行合成和模拟,直到纹波进位不再适用于输入数据速率(10 ns 目前在测试台上)。

    注意泛型 N 形式与测试台中声明的实际 N 的泛型映射关联意味着在这种情况下,测试台中声明的 N 也设置了 Adder4 中的宽度 N。

    【讨论】:

      【解决方案2】:

      嗯,我们应该问的第一个问题是原理图应该是什么样子。也许是这样的:

      【讨论】:

      • 是的,这正是它看起来的样子,哈哈。我知道我将不得不使用的东西是 PORT MAPS。不过不知道该怎么说,因为没有像 1 位加法器那样的与或异或门。
      • @shawn 因为您有使用泛型 N 声明的端口 std_logic_vector 大小,您需要使用一个或多个生成语句来实例化 Adder1 实例,而 Adder4 仅暗示 4。如果您可以消除泛型 N将向量大小固定为 3 到 0,您可以简单地实例化 Adder1 四次,连接来自端口和 carry_sig 的适当输入和输出,如 sharth 的图表所示。请参阅VHDL: Creating a Hierarchical Design 了解使用 Altera 的示例。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多