Multiplication in VHDL

Discussion in 'VHDL' started by b2386, Mar 20, 2009.

  1. b2386

    b2386

    Joined:
    Mar 20, 2009
    Messages:
    1
    Hi all,

    I am working on creating a simple computer in VHDL. Right now, I am trying to add a multiplication instruction but it is giving me problems. The code compiles fine. However, when I simulate the program, it shows the "MULTOUT" signal as being unknown (X) and it never takes on the correct value. Everything else if fine except for the multiplication part. The code is given below. Any advice would be much appreciated.


    LIBRARY IEEE;
    LIBRARY ALTERA_MF;
    LIBRARY LPM;

    USE ieee.std_logic_1164.ALL;
    USE ieee.std_logic_signed.ALL;
    USE ieee.numeric_std.ALL;
    USE ALTERA_MF.ALTERA_MF_COMPONENTS.ALL;
    USE LPM.LPM_COMPONENTS.ALL;


    ENTITY SCOMP IS
    PORT(
    CLOCK : IN STD_LOGIC;
    RESETN : IN STD_LOGIC;
    PC_OUT : OUT STD_LOGIC_VECTOR( 9 DOWNTO 0);
    AC_OUT : OUT STD_LOGIC_VECTOR(15 DOWNTO 0);
    MDR_OUT : OUT STD_LOGIC_VECTOR(15 DOWNTO 0);
    MAR_OUT : OUT STD_LOGIC_VECTOR( 9 DOWNTO 0);
    IO_WRITE : OUT STD_LOGIC;
    IO_CYCLE : OUT STD_LOGIC;
    IO_ADDR : OUT STD_LOGIC_VECTOR( 7 DOWNTO 0);
    IO_DATA : INOUT STD_LOGIC_VECTOR(15 DOWNTO 0)
    );
    END SCOMP;


    ARCHITECTURE a OF SCOMP IS
    TYPE STATE_TYPE IS (
    RESET_PC,
    FETCH,
    DECODE,
    EX_LOAD,
    EX_STORE,
    EX_STORE2,
    EX_ADD,
    EX_SUB,
    EX_JUMP,
    EX_JNEG,
    EX_JPOS,
    EX_JZERO,
    EX_AND,
    EX_OR,
    EX_XOR,
    EX_SHIFT,
    EX_ADDI,
    EX_ILOAD,
    EX_ISTORE,
    EX_CALL,
    EX_RETURN,
    EX_IN,
    EX_OUT,
    EX_OUT2,
    EX_MULT
    );

    TYPE STACK_TYPE IS ARRAY (0 TO 7) OF STD_LOGIC_VECTOR(9 DOWNTO 0);

    SIGNAL STATE : STATE_TYPE;
    SIGNAL PC_STACK : STACK_TYPE;
    SIGNAL IO_IN : STD_LOGIC_VECTOR(15 DOWNTO 0);
    SIGNAL AC : STD_LOGIC_VECTOR(15 DOWNTO 0);
    SIGNAL AC_SHIFTED : STD_LOGIC_VECTOR(15 DOWNTO 0);
    SIGNAL IR : STD_LOGIC_VECTOR(15 DOWNTO 0);
    SIGNAL MDR : STD_LOGIC_VECTOR(15 DOWNTO 0);
    SIGNAL PC : STD_LOGIC_VECTOR( 9 DOWNTO 0);
    SIGNAL MEM_ADDR : STD_LOGIC_VECTOR( 9 DOWNTO 0);
    SIGNAL MW : STD_LOGIC;
    SIGNAL IO_WRITE_INT : STD_LOGIC;
    SIGNAL MULTOUT : STD_LOGIC_VECTOR(31 DOWNTO 0);


    BEGIN

    PC_OUT <= PC;
    AC_OUT <= AC;
    MDR_OUT <= MDR;
    MAR_OUT <= IR(9 DOWNTO 0);
    IO_WRITE <= IO_WRITE_INT;
    IO_ADDR <= IR(7 DOWNTO 0);

    WITH STATE SELECT
    MEM_ADDR <= PC WHEN FETCH,
    IR(9 DOWNTO 0) WHEN OTHERS;

    WITH STATE SELECT
    IO_CYCLE <= '1' WHEN EX_IN,
    '1' WHEN EX_OUT2,
    '0' WHEN OTHERS;


    PROCESS (CLOCK, RESETN)
    BEGIN
    IF (RESETN = '0') THEN -- Active low, asynchronous reset
    STATE <= RESET_PC;
    ELSIF (RISING_EDGE(CLOCK)) THEN
    CASE STATE IS
    WHEN RESET_PC =>
    MW <= '0'; -- Clear memory write flag
    PC <= "0000000000"; -- Reset PC to the beginning of memory, address 0x000
    AC <= x"0000"; -- Clear AC register
    STATE <= FETCH;

    WHEN FETCH =>
    MW <= '0'; -- Clear memory write flag
    IO_WRITE_INT <= '0';
    IR <= MDR; -- Latch instruction into the IR
    PC <= PC + 1; -- Increment PC to next instruction address
    STATE <= DECODE;

    WHEN DECODE =>
    CASE IR(15 downto 10) IS
    WHEN "000000" => -- No Operation (NOP)
    STATE <= FETCH;
    WHEN "000001" => -- LOAD
    STATE <= EX_LOAD;
    WHEN "000010" => -- STORE
    STATE <= EX_STORE;
    WHEN "000011" => -- ADD
    STATE <= EX_ADD;
    WHEN "000100" => -- SUB
    STATE <= EX_SUB;
    WHEN "000101" => -- JUMP
    STATE <= EX_JUMP;
    WHEN "000110" => -- JNEG
    STATE <= EX_JNEG;
    WHEN "000111" => -- JPOS
    STATE <= EX_JPOS;
    WHEN "001000" => -- JZERO
    STATE <= EX_JZERO;
    WHEN "001001" => -- AND
    STATE <= EX_AND;
    WHEN "001010" => -- OR
    STATE <= EX_OR;
    WHEN "001011" => -- XOR
    STATE <= EX_XOR;
    WHEN "001100" => -- SHIFT
    STATE <= EX_SHIFT;
    WHEN "001101" => -- ADDI
    STATE <= EX_ADDI;
    WHEN "001110" => -- ILOAD
    STATE <= EX_ILOAD;
    WHEN "001111" => -- ISTORE
    STATE <= EX_ISTORE;
    WHEN "010000" => -- CALL
    STATE <= EX_CALL;
    WHEN "010001" => -- RETURN
    STATE <= EX_RETURN;
    WHEN "010010" => -- IN
    STATE <= EX_IN;
    WHEN "010011" => -- OUT
    IO_WRITE_INT <= '1';
    STATE <= EX_OUT;
    WHEN "010100" =>
    STATE <= EX_MULT; -- MULT

    WHEN OTHERS =>
    STATE <= FETCH; -- Invalid opcodes default to NOP
    END CASE;

    WHEN EX_LOAD =>
    AC <= MDR; -- Latch data from MDR (memory contents) to AC
    STATE <= FETCH;

    WHEN EX_STORE =>
    MW <= '1'; -- Raise MW to write AC to MEM
    STATE <= EX_STORE2;

    WHEN EX_STORE2 =>
    MW <= '0'; -- Drop MW to end write cycle
    STATE <= FETCH;

    WHEN EX_ADD =>
    AC <= AC + MDR;
    STATE <= FETCH;

    WHEN EX_SUB =>
    AC <= AC - MDR;
    STATE <= FETCH;

    WHEN EX_JUMP =>
    PC <= IR(9 DOWNTO 0);
    STATE <= FETCH;

    WHEN EX_JNEG =>
    IF (AC(15) = '1') THEN
    PC <= IR(9 DOWNTO 0);
    END IF;

    STATE <= FETCH;

    WHEN EX_JPOS =>
    IF ((AC(15) = '0') AND (AC /= x"0000")) THEN
    PC <= IR(9 DOWNTO 0);
    END IF;

    STATE <= FETCH;

    WHEN EX_JZERO =>
    IF (AC = x"0000") THEN
    PC <= IR(9 DOWNTO 0);
    END IF;

    STATE <= FETCH;

    WHEN EX_AND =>
    AC <= AC AND MDR;
    STATE <= FETCH;

    WHEN EX_OR =>
    AC <= AC OR MDR;
    STATE <= FETCH;

    WHEN EX_XOR =>
    AC <= AC XOR MDR;
    STATE <= FETCH;

    WHEN EX_SHIFT =>
    AC <= AC_SHIFTED;
    STATE <= FETCH;

    WHEN EX_ADDI =>
    AC <= AC + (IR(9) & IR(9) & IR(9) & IR(9) &
    IR(9) & IR(9) & IR(9 DOWNTO 0));
    STATE <= FETCH;


    WHEN EX_ILOAD =>
    IR(9 DOWNTO 0) <= MDR(9 DOWNTO 0);
    STATE <= EX_LOAD;

    WHEN EX_ISTORE =>
    IR(9 DOWNTO 0) <= MDR(9 DOWNTO 0);
    STATE <= EX_STORE;

    WHEN EX_CALL =>
    FOR i IN 0 TO 6 LOOP
    PC_STACK(i + 1) <= PC_STACK(i);
    END LOOP;

    PC_STACK(0) <= PC;
    PC <= IR(9 DOWNTO 0);
    STATE <= FETCH;

    WHEN EX_RETURN =>
    FOR i IN 0 TO 6 LOOP
    PC_STACK(i) <= PC_STACK(i + 1);
    END LOOP;

    PC <= PC_STACK(0);
    STATE <= FETCH;

    WHEN EX_IN =>
    AC <= IO_DATA;
    STATE <= FETCH;

    WHEN EX_OUT =>
    STATE <= EX_OUT2;

    WHEN EX_OUT2 =>
    STATE <= FETCH;

    WHEN EX_MULT =>
    MULTOUT <= AC*MDR;
    AC <= MULTOUT(23 DOWNTO 8 );
    STATE <= FETCH;

    WHEN OTHERS =>
    STATE <= FETCH; -- If an invalid state is reached, return to FETCH
    END CASE;
    END IF;
    END PROCESS;
    END a;
    b2386, Mar 20, 2009
    #1
    1. Advertising

  2. b2386

    Ukanbal

    Joined:
    Mar 7, 2009
    Messages:
    9
    i am not sure but i dont think you are allowed to do a '*' multiplication in your vhdl. i am not 100% on that but if i am right then you got 2 options.

    there are two type of multiplication and the most common one is add and shift.
    what it does is it uses a temp product signal as a storage inside the code and you have a loop.

    loop is going to be something like this

    for i 0 in 31 loop
    if multiplier(i) = '0' then
    shift1bitright multiplicant
    shift1bitright product
    elsif multiplier(i) = '1' then
    product <= product(i) + multiplicand(i)
    end loop


    its going to be something like that but you have to use a carry in as well to make sure the multiplication adds properly

    i hope it helps.

    (p.s if im wrong and you can do a '*' inside your code then dont mind me)
    Ukanbal, Mar 20, 2009
    #2
    1. Advertising

  3. b2386

    JohnDuq

    Joined:
    Dec 9, 2008
    Messages:
    88
    There can be some pretty sophisticated algorithms behind that '*' symbol. Search the web for 'binary multiply' and choose your approach.
    JohnDuq, Mar 20, 2009
    #3
  4. b2386

    JohnDuq

    Joined:
    Dec 9, 2008
    Messages:
    88
    On a bit more research I see there is a multiplier defined in VHDL

    VHDL Operators

    Highest precedence first,
    left to right within same precedence group,
    use parenthesis to control order.
    Unary operators take an operand on the right.
    "result same" means the result is the same as the right operand.
    Binary operators take an operand on the left and right.
    "result same" means the result is the same as the left operand.

    * multiplication, numeric * numeric, result numeric

    Look through the synthesize/translate reports line by line. You will probably find a clue there why the multiplication is not being supported.

    Try including 'USE std_logic_arith ALL' - that is typically where the multiplier function is defined.
    JohnDuq, Mar 20, 2009
    #4
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. wolfenstein_ddr

    multiplication in vhdl

    wolfenstein_ddr, Jan 10, 2008, in forum: VHDL
    Replies:
    0
    Views:
    924
    wolfenstein_ddr
    Jan 10, 2008
  2. William Hughes
    Replies:
    13
    Views:
    1,193
    Ben Bacarisse
    Mar 15, 2010
  3. a_bhatt
    Replies:
    0
    Views:
    1,227
    a_bhatt
    Mar 8, 2011
  4. apakhira
    Replies:
    3
    Views:
    4,211
    jeppe
    Oct 18, 2011
  5. chinna492
    Replies:
    0
    Views:
    763
    chinna492
    Oct 26, 2012
Loading...

Share This Page