32 Bit ALU in VHDL Carry Out -
i'm supposed write simple 32 bit alu in vhdl. working fine, except 2 things. alu supposed have carry out , overflow flag , cant't figure out how implement that.
first general question. circuit diagram shows subtraction alu inverts subtrahend , adds "1" create negative equivalent of input value in 2s-complement. mean should work unsigned values input? or should stick std_logic_vector?
since carry out bit bit not "fit" result word, tried 0 extend summands, create temporary 33 bit sum signal , divide result carry out , actual sum. unfortunately when simulating "uu...u" output sum.( did described here: https://en.wikibooks.org/wiki/vhdl_for_fpga_design/4-bit_alu)
and overflow flag: since description of alu behavioral don't have access carries, means can't determine if overflow occured xoring last 2 carries(assuming values in 2s-complement, i'm not quite sure in point first question shows...). there way identify overflow? turning "an overflow occurs when..." rules 1 finds on internet if statements?
this code far. version giving me "uuu...u" output when adding/ subtracting.
library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; entity alu port ( clk : in std_logic; : in std_logic_vector (31 downto 0); b : in std_logic_vector(31 downto 0); y : out std_logic_vector(31 downto 0); op : in std_logic_vector(2 downto 0); nul : out boolean; cout : out std_logic); end alu; architecture behavioral of alu signal smd0, smd1, sum : std_logic_vector (31 downto 0); signal temp : std_logic_vector (32 downto 0); signal cry : std_logic; signal snul : boolean; begin smd0 <= a; smd1 <= b; y <= sum; cout <= cry; nul <= snul; process(clk) begin if (rising_edge(clk)) if ( sum = "00000000000000000000000000000000") -------zero flag snul <= true; else snul <= false; end if; case op when "000" => sum <= smd0 , smd1; when "001" => sum <= smd0 xor smd1; when "010" => temp <= std_logic_vector((unsigned("0" & smd0) + unsigned(smd1))); sum <= temp(31 downto 0); cry <= temp(32); when "100" => sum <= smd0 , not smd1; when "101" => sum <= smd0 xor not smd1; when "110" => sum <= std_logic_vector((unsigned(smd0) - unsigned(smd1))); when "111" => if (a < b) sum <= "00000000000000000000000000000001"; else sum <= "00000000000000000000000000000000"; end if; when others => null; end case; end if; end process; end behavioral;
any comments on code appreciated since i'm new vhdl(we talked half lecture...) , figured out googling , playing around.
that's given circuit diagram:
//edit:
another thing. 0 flag not work after "000". idea why it's output except first case?
in answer first question: yes, use unsigned library ieee.std_numeric. it's ideal sort of operation.
secondly, overflow can detected comparing output input. instance, in two's compliment, if perform +ve plus +ve , overflow, result have msb set result -ve.
to summarise addition , subtraction
addition | (+ve) - (+ve) | (+ve) - (-ve) | (-ve) - (+ve) | (-ve) + (-ve)| ----------------------------------------------------------------------------- result (+ve) | - | - | - | overflow | ----------------------------------------------------------------------------- result (-ve) | overflow | - | - | - | ----------------------------------------------------------------------------- subtraction | (+ve) - (+ve) | (+ve) - (-ve) | (-ve) - (+ve) | (-ve) - (-ve)| ----------------------------------------------------------------------------- result (+ve) | - | - | overflow | - | ----------------------------------------------------------------------------- result (-ve) | - | overflow | - | - | -----------------------------------------------------------------------------
similar rules can worked out multiplication , division, more involved.
edit
below suggested way go (you realise vhdl (mostly) case insensitive hope? seem using shift key). you're question i've no idea flag want overflow flag, haven't put 1 in.
library ieee; use ieee.std_logic_164.all; use ieee.numeric_std.all; entity alu port ( signal clk : in std_logic; signal : in std_logic_vector(31 downto 0); signal b : in std_logic_vector(31 downto 0); signal y : in std_logic_vector(31 downto 0); signal op : in std_logic_vector(3 downto 0); signal nul : out boolean; signal cout : out std_logic ) end entity; architecture behavioral of alu type op_type (op_and, op_a_and_nb, op_a_xor_nb, op_compare, op_xor, op_add, op_sub, op_nop); signal enum_op : op_type; signal a_minus_b : std_logic_vector(32 downto 0); signal a_plus_b : std_logic_vector(32 downto 0); signal reg : std_logic_vector(32 downto 0); begin a_minus_b <= std_logic_vector(signed(a(a'high) & a) - signed(b(b'high) & b)); a_plus_b <= std_logic_vector(signed(a(a'high) & a) + signed(b(b'high) & b)); process(op) begin case op when "000" => enum_op <= op_and; when "001" => enum_op <= op_xor; when "010" => enum_op <= op_add; when "100" => enum_op <= op_a_and_nb; when "101" => enum_op <= op_a_xor_nb; when "110" => enum_op <= op_sub; when "111" => enum_op <= op_compare; when others => enum_op <= op_nop; end case; end process; process(clk) begin if rising_edge(clk) case enum_op when op_add => reg <= a_plus_b; when op_sub => reg <= a_minus_b; when op_and => reg <= '0' & (a , b); when op_xor => reg <= '0' & (a xor b); when op_a_and_nb => reg <= '0' & (a , not b); when op_a_xor_nb => reg <= '0' & (a xor not b); when op_compare => reg(32) <= '0'; reg(31 downto 1) <= (others => '0'); reg(0) <= a_minus_b(32); when op_nop => reg(32) <= '0'; end if; end process; y <= reg(31 downto 0); count <= reg(32); nul <= unsigned(reg) = '0'; end architecture;
Comments
Post a Comment