------------------------------------------------------------ -- mult.vhd -- -- This file includes models for the Xilinx based multiply unit. -- -- The "interface" module is responsible for communication -- with the SPARC board. -- -- The "datapath" module contains the registers shifters and adder -- required for multiplication. -- -- The "vmu" module groups the interface and the datapath as well -- as providing simple logic for driving the seven segment display -- and generating the signals; EnableOperand1, EnableOperand2 and -- UpdateResult. -- -- For operation the circuit must be connected to: -- 1. a SPARC board via the dedicated cable -- 2. a controller unit -- 3. a clock source 1Hz to 50kHz -- 4. a normally high nRESET input -- ------------------------------------------------------------ ------------------------------------------------------------ -- Entity and architecture for interface -- -- You should not need to modify this module -- ------------------------------------------------------------ library ieee; use ieee.std_logic_1164.all; entity interface is port (clock, nReset, H2, C3, C2, EnableOperand1, EnableOperand2, UpdateResult: in std_logic; Bus8 : inout std_logic_vector(7 downto 0); Bus32 : inout std_logic_vector(31 downto 0); H3, H1, Start : inout std_logic -- not INOUT but readable OUT ); end entity interface; architecture behaviour of interface is signal Operand1, Operand2, Result : std_logic_vector(31 downto 0); signal Address : std_logic_vector(7 downto 0); signal loadData, loadAddr : std_logic; signal H3old, H2sync, H1old, C2old, C2sync, C2syncold, UpdateResultOld : std_logic; begin Bus32 <= Operand1 when EnableOperand1='1' else (others => 'Z'); Bus32 <= Operand2 when EnableOperand2='1' else (others => 'Z'); Bus8 <= Result(07 downto 00) when ( H1='0' and Address(1 downto 0)="00" ) else (others => 'Z'); Bus8 <= Result(15 downto 08) when ( H1='0' and Address(1 downto 0)="01" ) else (others => 'Z'); Bus8 <= Result(23 downto 16) when ( H1='0' and Address(1 downto 0)="10" ) else (others => 'Z'); Bus8 <= Result(31 downto 24) when ( H1='0' and Address(1 downto 0)="11" ) else (others => 'Z'); glue: process(clock, nReset) is begin if (nReset = '0' ) then H2sync <= '0'; H1old <= '0'; C2sync <= '0'; C2syncold <= '0'; UpdateResultold <= '0'; H3old <= '0'; elsif rising_edge(clock) then H2sync <= H2; H1old <= H1; C2sync <= C2; C2syncold <= C2sync; UpdateResultold <= UpdateResult; H3old <= H3; end if; end process glue; H1 <= not ( H2sync or H1old ); loadData <= H1 and not C3; loadAddr <= H1 and C3; Start <= C2sync and not C2syncold; -- These might give better synchronization behaviour H3 <= (C2sync and not C2syncold) or (H3old and not (UpdateResultold and not UpdateResult)); registers: process(clock, nReset) is begin if (nReset = '0' ) then Operand1 <= (others => '0'); Operand2 <= (others => '0'); Address <= (others => '0'); Result <= (others => '0'); elsif rising_edge(clock) then if loadAddr='1' then Address <= Bus8; end if; if loadData='1' then if Address(7 downto 2)="000000" then if Address(1 downto 0)="11" then Operand1(31 downto 24) <= Bus8; end if; if Address(1 downto 0)="10" then Operand1(23 downto 16) <= Bus8; end if; if Address(1 downto 0)="01" then Operand1(15 downto 08) <= Bus8; end if; if Address(1 downto 0)="00" then Operand1(07 downto 00) <= Bus8; end if; elsif Address(7 downto 2)="000001" then if Address(1 downto 0)="11" then Operand2(31 downto 24) <= Bus8; end if; if Address(1 downto 0)="10" then Operand2(23 downto 16) <= Bus8; end if; if Address(1 downto 0)="01" then Operand2(15 downto 08) <= Bus8; end if; if Address(1 downto 0)="00" then Operand2(07 downto 00) <= Bus8; end if; end if; end if; if UpdateResult='1' then Result <= Bus32; end if; end if; end process registers; end architecture behaviour; ------------------------------------------------------------ -- Entity and architecture for datapath -- -- This version supports multiplication of two 8-BIT -- UNSIGNED numbers to produce a 16 bit result -- It can be used with a controller in MODE 0 or MODE 3. -- ------------------------------------------------------------ library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; entity datapath is port (clock, nReset : in std_logic; UpdateA, UpdateB, UpdateP, Shift, ZeroP, Subtract, EnableP: in std_logic; SystemDataBus32 : inout std_logic_vector(31 downto 0); LsbB, EmptyB, FullB : out std_logic ); end entity datapath; architecture behaviour of datapath is signal A, P : unsigned(15 downto 0); signal B : unsigned(7 downto 0); begin SystemDataBus32(15 downto 0) <= std_logic_vector(P) when EnableP='1' else (others => 'Z'); SystemDataBus32(31 downto 16) <= (others => '0') when EnableP='1' else (others => 'Z'); LsbB <= B(0); EmptyB <= not (B(0) or B(1) or B(2) or B(3) or B(4) or B(5) or B(6) or B(7)); FullB <= B(0) and B(1) and B(2) and B(3) and B(4) and B(5) and B(6) and B(7); registers: process(clock, nReset) is begin if (nReset = '0' ) then A <= (others => '0'); B <= (others => '0'); P <= (others => '0'); elsif rising_edge(clock) then if UpdateA='1' then if Shift='1' then A <= A sll 1; else A(15 downto 8) <= "00000000"; A(7 downto 0) <= unsigned( SystemDataBus32(7 downto 0)); end if; end if; if UpdateB='1' then if Shift='1' then B <= B srl 1; else B <= unsigned( SystemDataBus32(7 downto 0)); end if; end if; if UpdateP='1' then if ZeroP='1' then P <= (others => '0'); else P <= P + A; end if; end if; end if; end process registers; end architecture behaviour; ------------------------------------------------------------ -- Entity and architecture for complete multiplier ------------------------------------------------------------ library ieee; use ieee.std_logic_1164.all; entity vmu is port (clock12MHz : in std_logic; clock : in std_logic; nReset, H2, C3, C2 : in std_logic; portB : inout std_logic_vector(7 downto 0); H3, H1 : inout std_logic; -- not INOUT but readable OUT Start, LsbB, EmptyB, FullB : inout std_logic; -- not INOUT but readable OUT UpdateA, UpdateB, UpdateP, Shift, ZeroP, Subtract, EnableP : in std_logic; segA, segB, segC, segD, segE, segF, segG, ucRESET, ramDISABLE: out std_logic); end entity vmu; architecture structure of vmu is component interface is port (clock, nReset, H2, C3, C2, EnableOperand1, EnableOperand2, UpdateResult: in std_logic; Bus8 : inout std_logic_vector(7 downto 0); Bus32 : inout std_logic_vector(31 downto 0); H3, H1, Start : inout std_logic ); end component interface; component datapath is port (clock, nReset : in std_logic; UpdateA, UpdateB, UpdateP, Shift, ZeroP, Subtract, EnableP: in std_logic; SystemDataBus32 : inout std_logic_vector(31 downto 0); LsbB, EmptyB, FullB : out std_logic ); end component datapath; signal EnableOperand1, EnableOperand2, UpdateResult : std_logic; signal SystemDataBus : std_logic_vector(31 downto 0); signal delay_stage : std_logic; begin ramDISABLE <= '1'; -- Disable the RAM on the Xilinx board ucRESET <= '1'; -- Reset and hence disable the microcontroller --Display the number "1" on the 7 segment display --This simple fixed status message informs us that the --"mult.bit" image has been downloaded. --The central segment (segG) should flash or appear dimmed --to inform us that the system is receiving a clock. --A more advanced system will provide more status information --to the user via this 7 segment display. segA <= '0'; segF <= '0'; segB <= '1'; segG <= clock; segE <= '0'; segC <= '1'; segD <= '0'; interface_inst : interface port map (clock, nReset, H2, C3, C2, EnableOperand1, EnableOperand2, UpdateResult, PortB, SystemDataBus, H3, H1, Start ); datapath_inst : datapath port map (clock, nReset, UpdateA, UpdateB, UpdateP, Shift, ZeroP, Subtract, EnableP, SystemDataBus, LsbB, EmptyB, FullB ); EnableOperand1 <= UpdateA and not Shift; EnableOperand2 <= UpdateB and not Shift; UpdateResult <= EnableP; end architecture structure;