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:

cdiag

//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

Popular posts from this blog

c++ - Creating new partition disk winapi -

Android Prevent Bluetooth Pairing Dialog -

VBA function to include CDATA -