使用1位ALU制作16位ALU [英] Making a 16-bit ALU using 1-bit ALUs

查看:156
本文介绍了使用1位ALU制作16位ALU的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

你好,我试图从几个1位ALU中创建一个16位ALU
我创建了一个名为basic_alu1的程序包,其中包含1位ALU的一个组件,其代码为:

Hello I am trying to create a 16-bit ALU from several 1-bit ALUs I created a package named basic_alu1 which contains a component of the 1-bit ALU.The code for this is:

library ieee;
use ieee.std_logic_1164.all;
package basic_alu1 is
component alu1
    port (a, b: std_logic_vector(1 downto 0);
            m: in std_logic_vector(1 downto 0);
            result: out std_logic_vector(1 downto 0));
end component;
end package basic_alu1;


library ieee;
use ieee.std_logic_1164.all;
entity alu1 is
    port (a, b: std_logic_vector(1 downto 0);
    m: in std_logic_vector(1 downto 0);
    result: out std_logic_vector(1 downto 0));
end alu1; 
architecture arch1 of alu1 is 
begin
 process(a, b, m)
 begin
 case m is
 when "00" =>
    result <= a + b;
  when "01" =>
    result <= a + (not b) + 1;
  when "10" =>
    result <= a and b;
  when "11" =>
    result <= a or b;
end case
 end process
 end arch1

因此,在为了创建16位ALU,我正在使用for生成循环并实例化alu1的多个副本。我的问题是如何将计数器带入和带出计数器以及如何进行溢出检查。我的主要代码是:

So, in order to create the 16 bit ALU I am using a for generate loop and instantiate multiple copies of alu1. My question is how can I take the counter in and counter out and how can I have an overflow check. My main code is :

library ieee;
use ieee.std_logic_1164.all;
use work.basic_alu1.all;

entity alu16 is
  port (input_a : in std_logic_vector(15 downto 0);
        input_b : in std_logic_vector(15 downto 0);
        mode : in std_logic_vector(1 downto 0)
        result_x4 : out std_logic);
end alu16;

architecture structural of alu16 is
begin
G1 : for i in 0 to 15 generate
begin
    alu_16 : entity work.basic_alu1
    port map (
    a => input_a(i),
    b => input_b(i),
    m => mode,
    result => result_x4(i));
end generate;


推荐答案

下面是如何创建N的示例位加法器组件。首先,您需要创建一个完整的加法器,该加法器还要考虑进位。

Here is an example of how you can create a N-bit adder component. First of all you need to create a full adder which is a adder that also takes a carry in bit into account.

LIBRARY ieee;
USE ieee.std_logic_1164.ALL;

ENTITY fullAdder IS
    PORT (a     : IN STD_LOGIC;
          b     : IN STD_LOGIC;
          cin   : IN STD_LOGIC;
          y     : OUT STD_LOGIC;
          cout  : OUT STD_LOGIC);
END fullAdder;

ARCHITECTURE arch_fullAdder OF fullAdder IS
BEGIN
    y <= a XOR b XOR cin;
    cout <= (a AND b) OR 
            (b AND cin) OR 
            (a AND cin);
END arch_fullAdder;

使用此1位加法器时,可以通过生成多个来轻松生成N位波纹进位

When you have this 1-bit adder you can easily generate a N-bit ripple carry by generating multiple cells of the full adder we have above.

LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;

ENTITY ripple_adder IS 
    GENERIC (WIDTH : NATURAL := 32);
    PORT(a      : IN STD_LOGIC_VECTOR(WIDTH-1 DOWNTO 0);
         b      : IN STD_LOGIC_VECTOR(WIDTH-1 DOWNTO 0);
         cin    : IN STD_LOGIC := '0';
         y      : OUT STD_LOGIC_VECTOR(WIDTH-1 DOWNTO 0);
         cout   : OUT STD_LOGIC);
END ripple_adder;

ARCHITECTURE arch_ripple_adder OF ripple_adder IS

    SIGNAL carry    : STD_LOGIC_VECTOR(WIDTH DOWNTO 0);
    SIGNAL y_temp   : STD_LOGIC_VECTOR(WIDTH-1 DOWNTO 0);

    COMPONENT fullAdder IS
        PORT(a      : IN STD_LOGIC;
             b      : IN STD_LOGIC;
             cin    : IN STD_LOGIC;
             y      : OUT STD_LOGIC;
             cout   : OUT STD_LOGIC);
    END COMPONENT;
BEGIN  

    N_bit_adder_generate : FOR N IN 0 TO WIDTH-1 GENERATE
    N_bit_adder : fullAdder
        PORT MAP(a      => a(N),
                 b      => b (N),
                 cin    => carry(N),
                 y      => y_temp(N),
                 cout   => carry(N + 1));
    END GENERATE;

    carry(0) <= cin;
    cout <= carry(WIDTH);
    y <= y_temp;

END arch_ripple_adder;

拥有加法器后,您可以轻松地将加法器组件放入ALU中并指定不同的操作

When you have the adder you can easily put the adder component into an ALU and specify the different operations that the ALU should be able to perform.

LIBRARY  ieee;
USE  ieee.std_logic_1164.ALL;
USE ieee.numeric_std.ALL;

ENTITY ALU IS 
    GENERIC(WIDTH : NATURAL := 32);
    PORT(Clk    : IN STD_LOGIC := '0';
         Reset  : IN STD_LOGIC := '0';
         A      : IN STD_LOGIC_VECTOR(WIDTH-1 DOWNTO 0) := (OTHERS => '0');
         B      : IN STD_LOGIC_VECTOR(WIDTH-1 DOWNTO 0) := (OTHERS => '0');
         Op     : IN STD_LOGIC_VECTOR(3 DOWNTO 0) := (OTHERS => '0');
         Outs   : OUT STD_LOGIC_VECTOR(WIDTH-1 DOWNTO 0));
END ALU;

ARCHITECTURE arch_ALU OF ALU IS

    COMPONENT ripple_adder
    PORT(a      : IN STD_LOGIC_VECTOR(WIDTH-1 DOWNTO 0);
         b      : IN STD_LOGIC_VECTOR(WIDTH-1 DOWNTO 0);
         cin    : IN STD_LOGIC := '0';
         y      : OUT STD_LOGIC_VECTOR(WIDTH-1 DOWNTO 0);
         cout   : OUT STD_LOGIC);
END COMPONENT;

    SIGNAL RCA_output   : STD_LOGIC_VECTOR(WIDTH-1 DOWNTO 0) := (OTHERS => '0');
    SIGNAL B_neg        : STD_LOGIC_VECTOR(WIDTH-1 DOWNTO 0) := (OTHERS => '0');
    SIGNAL c_flag       : STD_LOGIC := '0';
    SIGNAL c_reg        : STD_LOGIC := '0';
    SIGNAL cin          : STD_LOGIC := '0';

BEGIN

RCA_comp : ripple_adder
   PORT MAP(a => A,
            b => B_neg,
            Cin => cin,
            y => RCA_output,
            Cout => c_flag);        

    WITH Op SELECT 
        B_neg <= NOT(B) WHEN "1000",
                     B  WHEN OTHERS;

    WITH Op SELECT
        cin <= '1'      WHEN "1000", -- SUB
                c_reg   WHEN "0111", -- ADDC
                '0'     WHEN OTHERS; -- ADD/ADDS    

    ALU_Process:
    PROCESS(Clk, Reset)
    BEGIN
        IF Reset = '0' THEN
            Outs <= (OTHERS => '0');
            c_reg <= '0';
        ELSIF rising_edge(Clk) THEN
            CASE Op IS
                WHEN "0001" => Outs <= A AND B;
                WHEN "0010" => Outs <= A OR  B;
                WHEN "0011" => Outs <= A NOR B;
                WHEN "0100" => Outs <= A XOR B;
                WHEN "0101" => Outs <= RCA_output; -- ADD 
                WHEN "0110" => Outs <= RCA_output; -- ADDS
                    c_reg <= c_flag;    
                WHEN "0111" => Outs <= RCA_output; -- ADDC
                WHEN "1000" => Outs <= RCA_output; -- SUB
                WHEN "1001" => Outs <= STD_LOGIC_VECTOR(UNSIGNED(A) SLL to_integer(UNSIGNED(B(4 DOWNTO 0))));
                WHEN "1010" => Outs <= STD_LOGIC_VECTOR(unsigned(A) SRL to_integer(UNSIGNED(B(4 DOWNTO 0))));
                WHEN "1011" => Outs <= STD_LOGIC_VECTOR(shift_right(SIGNED(A),to_integer(UNSIGNED(B(4 DOWNTO 0)))));
                WHEN OTHERS => Outs <= (OTHERS => '0');
            END CASE;
        END IF;
    END PROCESS;
END arch_ALU; 

但是该ALU并不那么复杂,没有那么多操作,但是可以轻松实现该功能添加。希望我给您的示例代码能对您有所帮助。

This ALU however is not that complex and don´t have that many operations but that functionality can easily be added. I hope the example code I have given you will help you.

这篇关于使用1位ALU制作16位ALU的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆