Multiplication in VHDL

Joined
Mar 20, 2009
Messages
1
Reaction score
0
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;
 
Joined
Mar 7, 2009
Messages
9
Reaction score
0
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)
 
Joined
Dec 9, 2008
Messages
88
Reaction score
0
There can be some pretty sophisticated algorithms behind that '*' symbol. Search the web for 'binary multiply' and choose your approach.
 
Joined
Dec 9, 2008
Messages
88
Reaction score
0
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.
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,764
Messages
2,569,566
Members
45,041
Latest member
RomeoFarnh

Latest Threads

Top