Forum Discussion

Altera_Forum's avatar
Altera_Forum
Icon for Honored Contributor rankHonored Contributor
13 years ago

design of a difficult VHDL Arithmetic and Logic Unit (ALU)

Hey guys, I was wondering if someone could give me a hand with designing a specific ALU.

Here are the main bits which I would like to implement:

- sequentlial unit with 2 registers (e.g. Acc and Data_Reg)

- immediate Read and Write Access to Acc

- 4 funtion bits (S01 - S03) to select an OpCode (see table below)

- ALU should flag for Acc = 0 (CPZ), for overflow (OVR) and for Acc = Data_Reg (AED)

S01...S02..S03..S04..

0......0......0......0......RES RESET Acc to 00000000 (Arith)

0......0......0......1......INC Acc = Acc + 1 (Arith)

0......0......1......0......ADD Acc = Acc + Data_Reg (Arith)

0......0......1......1......SUB Acc = Acc - Data_Reg (Arith)

0......1......0......0......MUL Acc = Acc x Data_Reg (Arith)

0......1......0......1......SHL Acc = Acc shifted left (up) by Data_Reg bits

0......1......1......0......SHR Acc = Acc shifted right (down) by Data_Reg bits

0......1......1......1......AND Acc <= Acc NAND Data_Reg (Logic)

1......0......0......0......XOR Acc <= Acc EXOR Data_Reg (Logic)

1......0......0......1......SET SET Acc to 11111111 (Arith)

1......0......1......0......LDA Load Acc from Data RAM (Cntrl)

1......0......1......1......LDD Load Data_Reg from Data RAM (Cntrl)

1......1......0......0......STA Store Acc to Data RAM (Cntrl)

1......1......0......1......STE Store External Data to Data RAM (Cntrl)

1......1......1......0......INZ Increment PC if ZFL = '1' (Cntrl)

1......1......1......1......JMP Jump to P(x)C if ZFL = '1' (Cntrl)

here is what I've done so far (I basically strugle with everything which is not implemented):


library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
 
entity simple_alu is
port(   Clk : in std_logic; --clock signal
        Acc, Data_Reg : in std_logic_vector (7 downto 0); --input operands
        Op : in std_logic_vector(3 downto 0); --Operation to be performed
        R : out std_logic_vector(7 downto 0)  --output of ALU
        );
end simple_alu;
 
architecture Behavioral of simple_alu is
 
--temporary signal declaration.
signal Reg1,Reg2,Reg3 : std_logic_vector(7 downto 0) := (others => '0');
 
begin
 
Reg1 <= Acc;
Reg2 <= Data_Reg;
R <= Reg3;
 
process(Clk)
begin
 
    if(rising_edge(Clk)) then --Do the calculation at the positive edge of clock cycle.
        case Op is
            when "0000" => Reg3 <= '00000000'              --0    RES    RESET Acc to 00000000 (Arith)
            when "0001" => Reg3 <=                             --1    INC    Acc = Acc + 1 (Arith)
            when "0010" => Reg3 <= Reg1 + Reg2;         --2    ADD    Acc = Acc + Data_Reg (Arith)
            when "0011" => Reg3 <= Reg1 - Reg2;            --3     SUB    Acc = Acc - Data_Reg (Arith)            
            when "0100" => Reg3 <=                              --4    MUL    Acc = Acc x Data_Reg (Arith)
            when "0101" => Reg3 <=                           --5    SHL    Acc = Acc shifted left (up) by Data_Reg bits
            when "0110" => Reg3 <=                           --6    SHR    Acc = Acc shifted right (down) by Data_Reg bits
            when "0111" => Reg3 <= Reg1 nand Reg2;        --7    Acc <= Acc NAND Data_Reg (Logic)                
                when "1000" => Reg3 <=     Reg1 xor Reg2;        --8    Acc <= Acc EXOR Data_Reg (Logic)
                when "1001" => Reg3 <=                                --9    SET Acc to 11111111 (Arith)
                when "1010" => Reg3 <=                                --A    Load Acc from Data RAM (Cntrl)
                when "1011" => Reg3 <=                                --B    Load Data_Reg from Data RAM (Cntrl)
                when "1100" => Reg3 <=                                --C    Store Acc to Data RAM (Cntrl)
                when "1101" => Reg3 <=                                --D    Store External Data to Data RAM (Cntrl)
                when "1110" => Reg3 <=                                --E    Increment PC if ZFL = '1' (Cntrl)
                when "1111" => Reg3 <=                                --F    Jump to P(x)C if ZFL = '1' (Cntrl)
            when others => Reg3 <= (others => '0');
                end case;       
    end if;
 
end process;   
 
 end Behavioral;    

all this code might be nonsense / not useful at all. I don't want anyone to solve this "task" but I would appreciate if you could let me know if I am on the right way?!

I would also appreciate if you could post code examples as I am quite new to VHDL and generally better in understanding when I look at actual code.

thanks in advance for any help you are able to provide.

Cheers!

6 Replies

  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    I think you're on the right approach.

    One thing, with numeric_std (good to see you're using it) std_logic_vectors are just collection of bits so it

    doesn't know how to 'add' them etc ....

    I'd declare reg1-3 as unsigned then ..

    op <= std_logic_vector(reg3);

    ..to assign the result as a std_logic_vector.

    Can you get hold of modelsim and play about with different combinations of operation? It'll help you see what's

    going on.

    Nial.
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    thanks for your quick response.

    - How can I'd declare reg1-3 as unsigned?

    - not sure if modelsim is available in uni - but I'll have a look tomorrow.
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    --- Quote Start ---

    - How can I'd declare reg1-3 as unsigned?

    --- Quote End ---

    signal Reg1,Reg2,Reg3 : unsigned(7 downto 0);
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    --- Quote Start ---

    How is that diagram coming along?

    --- Quote End ---

    like I said, Tricky****y, I've got it right in front of me; I'm not going to scan/upload it as I won't get more from you than another three words statement (no offence but it just hasn't been helpful at all).
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    I think one of the main problems with your code and comments is that you have several unimplemented cases that say set Acc to something or increment Acc. Acc cannot be set to anything because it's an input. Either you have the comments wrong and you actually mean something else, or you're trying to do something that you cannot.

    You also have 3 signals misleadingly called "RegN", when only Reg3 is actually a register. Reg1 and Reg2 are just wires connected to Acc and Data_reg inputs, and all Reg3 does it connect directly to the output. So first thing is you probably want to make Reg1 and Reg2 actual registers, and maybe only load the output in specific cases?