Professional Documents
Culture Documents
use IEEE.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity path is
port (
clk: in STD_LOGIC;
reset: in STD_LOGIC;
data: in STD_LOGIC_VECTOR (7 downto 0);
pathOut: out STD_LOGIC_VECTOR (7 downto 0);
addr: out STD_LOGIC_VECTOR (15 downto 0);
ALUFlag: out STD_LOGIC_VECTOR (8 downto 0)
);
end path;
architecture path_arch of path is
--multiplier
COMPONENT mult
PORT(
clk : IN std_logic;
start : IN
std_logic;
pass : IN std_logic;
finish: IN
std_logic;
port (
inA: in STD_LOGIC_VECTOR (9 downto 0);
inB: in STD_LOGIC_VECTOR (9 downto 0);
fn: in STD_LOGIC_VECTOR (3 downto 0);
aluout: out STD_LOGIC_VECTOR (9 downto 0);
flags: out STD_LOGIC_VECTOR (3 downto 0)
);
END COMPONENT;
COMPONENT shifter
port (
shtIn: in STD_LOGIC_VECTOR (9 downto 0);
sfn: in STD_LOGIC_VECTOR (3 downto 0);
shtOut: out STD_LOGIC_VECTOR (9 downto 0);
shtFlag: out STD_LOGIC;
shEn: in std_logic
);
END COMPONENT;
-- register signals
SIGNAL r0,r1,r2,r3: std_logic_vector(3 downto 0);
SIGNAL rgEn: std_logic;
-- multiplier interconnects
SIGNAL pass_logic: std_logic;
SIGNAL mul1,mul2,rin: std_logic_vector(3 downto 0);
SIGNAL multout: std_logic_vector(9 DOWNTO 0);
--mux and tristate signals
SIGNAL d1out, d2out: STD_LOGIC_VECTOR (9 downto 0);
SIGNAL outEn: STD_LOGIC;
--alu connection signals
SIGNAL aluout, aluI1, aluI2 : STD_LOGIC_VECTOR (9 downto 0);
--alu state signals
regEn <= '1' when (start = '1' AND ((op ="000") OR (op = "001") OR (op = "010" A
ND shOp(3) = '0') OR (op = "100" AND func(2) = '1'))) else '0';
--alu inputs
aluI1 <= multout when (op = "001" AND func(2) = '0') else shtOut;
aluI2 <= imm when ((op = "000") AND (func(4) = '1')) else
d1out when (op = "001" AND func(2) = '0') else d2out;
--limiter outputs
pathOut <= lmOut when outEn = '1' else "ZZZZZZZZ";
--disp variable
disp <= '1' WHEN ((op = "011") OR (op = "010" AND shOp(3) = '1') OR (op = "100"
AND func(4) = '1')) ELSE '0';
--calculate address
addr <= (mah & mal) WHEN (disp = '1' AND start = '1') ELSE
--sp
pc;
--finish signal for states
finish <= '1' when (state = "101" AND NOT (op = "001")) else
'0' when (op = "111" AND func = "11111") else
'0' when (state = "101" AND op = "001" AND NOT(mstate = "10")) else
'1' when (mstate = "10") else '0';
-- Set variables for next state
nextstate <=
-- 0->1
"001" WHEN state = "000" ELSE
-- 1->2
"010" WHEN (state = "001" AND NOT (op = "111")) ELSE
-- 1->5
"101" WHEN (state = "001" AND op = "111") ELSE
-- 2->3
"011" WHEN (state = "010" AND (disp = '1')) ELSE
-- 2->5
END IF;
-- State 1->2 transition
IF (nextstate = "010" AND state = "001") THEN
ir2 <= data;
END IF;
-- State 1->5 transition
IF (nextstate = "101" AND state = "001") THEN
start <= '1';
END IF;
-- State 2->5 transition
IF (nextstate = "101" AND state = "010") THEN
start <= '1';
END IF;
-- State 2->3 transition
IF (nextstate = "011" AND state = "010") THEN
mah <= data;
END IF;
-- State 3->4 transition
IF (nextstate = "100" AND state = "011") THEN
mal <= data;
END IF;
-- State 4->5 transition
IF (nextstate = "101" AND state = "100") THEN
start <= '1';
END IF;
-- State 5->1 transition
IF (nextstate = "001" AND state = "101") THEN
ir1 <= data;
start <= '0';
--
END IF;
END IF;
END PROCESS;
-- mux for accumlators
regSel: PROCESS (clk, reset)
BEGIN
IF (reset ='1') THEN
a0 <= "0000000000";
a1 <= "0000000000";
a2 <= "0000000000";
a3 <= "0000000000";
ELSIF (clk='1' AND clk'event) THEN
IF (regEn = '1' AND NOT (op = "001")) THEN
CASE aca(1 DOWNTO 0) IS
WHEN "00" => a0 <= aluout;
WHEN "01" => a1 <= aluout;
WHEN "10" => a2 <= aluout;
WHEN OTHERS => a3 <= aluout;
END CASE;
END IF;
IF (regEn = '1' AND (op = "001" OR (op = "100" AND func(2) = '1'))) THEN
CASE aca(1 DOWNTO 0) IS
WHEN "00" => a0 <= multout;
WHEN "01" => a1 <= multout;
WHEN "10" => a2 <= multout;
WHEN OTHERS => a3 <= multout;
END CASE;
END IF;
END IF;
END PROCESS regSel;
--limiter
funct:PROCESS(lmIn, lmfn)
BEGIN
CASE lmfn IS
WHEN "1000" => --limit to eight (LIMA)
IF lmIn(8 DOWNTO 7) = "00" THEN
zz <= "0000" & lmIn(9) & lmIn(6 DOWNTO 0);
ELSE
zz <= "00" & lmIn(8 DOWNTO 7) & lmIn(9) & "1111111";
END IF;
WHEN "1001" => --limit to four (LIMF)
IF lmIn(8 DOWNTO 3) = "000000" THEN
zz <= "00000000" & lmIn(9) & lmIn(2 DOWNTO 0);
ELSE
zz <= lmIn(6 DOWNTO 3) & "0000" & lmIn(9) & "111";
END IF;
WHEN "1010" => zz <= "00" & lmIn(1 DOWNTO 0) & lmIn(9 DOWNTO 2);
te to eight (TNKA)
--trunca
WHEN "1011" => zz <= lmIn(3 DOWNTO 0) & lmIn(9) & lmIn(6 DOWNTO 4) & "0000";
--truncate to four (RNDF)
WHEN "1100" => zz <= "00" & lmIn(8 DOWNTO 7) & lmIn(9) & lmIn(6 DOWNTO 0);
--round to eight (RNDA)
WHEN "1101" => zz <= lmIn(6 DOWNTO 3) & lmIn(9) & "0000" & lmIn(2 DOWNTO 0);
--round to four (TNKF)
WHEN OTHERS => zz <= "00" & lmIn(9 DOWNTO 0);
END CASE;
lmFlag <= zz(11 DOWNTO 8);
lmOut <= zz(7 DOWNTO 0);
END PROCESS funct;
--calculate flags for mult
PROCESS (multout)
BEGIN
--pass lmIn
WHEN "0011" => z <= '0' & (inA or inB); --inA or inB
WHEN "0100" => z <= '0' & (inA xor inB);
WHEN "0101" => z <= ('0' & inA) - inB; --cmp inA and inB
WHEN "0110" => z <= ('0' & not inA);
--invert inA
--increment inA
--decrement inA
--pass zero
--negate inA
--pass zero
END CASE;
--flags: |overflow | zero | negative | carry|
flags(0) <= z(10);
flags(1) <= z(9);
IF z(9 DOWNTO 0) = "0000000000" THEN
flags(2) <= '1';
ELSE
flags(2) <= '0';
END IF;
CASE fn(3 DOWNTO 0) IS
WHEN "0000" => flags(3) <= (inA(9)and inB(9) and (not z(9))) or ((not inA(9)) an
d (not inB(9)) and z(9));
WHEN "0001" => flags(3) <= (inA(9)and inB(9) and (not z(9))) or ((not inA(9)) an
d (not inB(9)) and z(9));
WHEN "0101" => flags(3) <= (inA(9)and inB(9) and (not z(9))) or ((not inA(9)) an
d (not inB(9)) and z(9));
WHEN OTHERS => flags(3) <= '0';
END CASE;
CASE fn(3 DOWNTO 0) IS
WHEN "0101" => aluout <= inA(9 downto 0);
WHEN "0001" => z <= shtIn(0) & '0' & shtIn(9 DOWNTO 1); --arithmetic shift right
input
WHEN "0010" => z <= shtIn(0) & shtIn(9) & shtIn(9 DOWNTO 1);
right input
WHEN "0011" => z <= shtIn(9 DOWNTO 0) & shtIn(9);
--logical shift
WHEN "0100" => z <= shtIn(0) & shtIn(0) & shtIn(9 DOWNTO 1);
--rotate right i
nput
WHEN "0101" =>
IF shtIn(3 DOWNTO 0) = "0000" THEN
z <= '0' & shtIn(9) & shtIn(8 DOWNTO 4) & "0000";
--round input
ELSE
z <= '1' & shtIn(9) & shtIn(8 DOWNTO 4) & "0000";
END IF;
WHEN "0110" => IF shtIn(8 DOWNTO 5) = "0000" THEN
z <= '0' & shtIn(9) & "0000" & shtIn(4 DOWNTO 0);
--truncate input
ELSE
z <= '1' & shtIn(9) & "0000" & shtIn(4 DOWNTO 0);
END IF;
WHEN OTHERS => z <= '0' & shtIn(9 DOWNTO 0);
--pass shtIn
END CASE;
ELSE
z <= '0' & shtIn(9 DOWNTO 0);
END IF;
shtFlag <= z(10);
shtOut <= z(9 DOWNTO 0);
END PROCESS funct;
end shifter_arch;
-------------------------------------------------------------------------------------------------- mult.vhd
-- A 4-bit, fixed-point, integer multiplier module
LIBRARY ieee;
USE ieee.std_logic_1164.all;
-- Standard logic
clk : IN std_logic;
start : IN
std_logic;
pass : IN std_logic;
finish: IN
std_logic;