问题
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
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;
回答1:
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;
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;
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;
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.
来源:https://stackoverflow.com/questions/37274666/making-a-16-bit-alu-using-1-bit-alus