260 likes | 408 Views
Function Unit. Lecture 8.3 A VHDL Forth Core for FPGAs: Sect. 4. FC16 Forth Core. Instructions for the FC16 Function Unit. case fcode is when "010000" => -- a + b y <= a + b; when "010001" => -- b - a y <= b - a; when "010010" => -- 1+
E N D
Function Unit Lecture 8.3 A VHDL Forth Core for FPGAs: Sect. 4
FC16 Forth Core
case fcode is when "010000" => -- a + b y <= a + b; when "010001" => -- b - a y <= b - a; when "010010" => -- 1+ y <= a + 1; when "010011" => -- 1- y <= a - 1; when "010100" => -- invert y <= not a; when "010101" => -- a and b y <= a and b; when "010110" => -- a or b y <= a or b; when "010111" => -- a xor b y <= a xor b;
when "011000" => -- 2* y <= a(width-2 downto 0) & '0'; when "011001" => -- U2/ y <= '0' & a(width-1 downto 1); when "011010" => -- 2/ y <= a(width-1) & a(width-1 downto 1); when "011011" => -- RSHIFT y <= SHR(b,a); when "011100" => -- LSHIFT y <= SHL(b,a);
when "100000" => -- TRUE y <= true; when "100001" => -- FALSE y <= false; when "100010" => if (Z = '0') then -- 0= NOT y <= true; else y <= false; end if; when "100011" => if (a(width-1) = '1') then -- 0< y <= true; else y <= false; end if;
when "100100" => if (b > a) then -- U> y <= true; else y <= false; end if; when "100101" => if (b < a) then -- U< y <= true; else y <= false; end if; when "100110" => if (a = b) then -- = y <= true; else y <= false; end if;
when "100111" => if (b >= a) then -- U>= y <= true; else y <= false; end if; when "101000" => if (b <= a) then -- U<= y <= true; else y <= false; end if; when "101001" => if (a /= b) then -- <> y <= true; else y <= false; end if;
when "101010" => if (bvs > avs) then -- > y <= true; else y <= false; end if; when "101011" => if (bvs < avs) then -- < y <= true; else y <= false; end if; when "101100" => if (bvs >= avs) then -- >= y <= true; else y <= false; end if;
when "101101" => if (bvs <= avs) then -- <= y <= true; else y <= false; end if; when others => y <= false; y1 <= false; end case;
Code Name Function 001D mpp multiply partial product (used for multiplication) 001E shldc shift left and decrement conditionally (used for division) Multiply and Divide Instructions
opcodes.vhd -- Function Unit instructions constant plus: opcode := X"0010"; -- + constant minus: opcode := X"0011"; -- - constant plus1: opcode := X"0012"; -- 1+ constant minus1: opcode := X"0013"; -- 1- constant invert: opcode := X"0014"; -- INVERT constant andd: opcode := X"0015"; -- AND constant orr: opcode := X"0016"; -- OR constant xorr: opcode := X"0017"; -- XOR constant twotimes: opcode := X"0018"; -- 2* constant u2slash: opcode := X"0019"; -- U2/ constant twoslash: opcode := X"001A"; -- 2/ constant rshift: opcode := X"001B"; -- RSHIFT constant lshift: opcode := X"001C"; -- LSHIFT constant mpp: opcode := X"001D"; -- mpp constant shldc: opcode := X"001E"; -- shldc
mpp Multiply partial product when mpp => tload <= '1'; nload <= '1'; nsel <= "10"; fcode <= icode(5 downto 0);
variable AVector: STD_LOGIC_VECTOR (width downto 0); variable BVector: STD_LOGIC_VECTOR (width downto 0); variable CVector: STD_LOGIC_VECTOR (width downto 0); variable yVector: STD_LOGIC_VECTOR (width downto 0); variable y1_tmp: STD_LOGIC_VECTOR (width-1 downto 0); begin In Funit16 AVector := '0' & a; BVector := '0' & b; CVector := '0' & c; y1_tmp := false; yVector := '0' & false;
mpp (multiply partial product) if N(0) = 1 then adsh else sh end if; when "011101" => -- mpp if b(0) = '1' then yVector := AVector + CVector; else yVector := AVector; end if; y <= yVector(width downto 1); y1 <= yVector(0) & b(width-1 downto 1); T N N2
16 x 16 = 32 Multiplication : UM* ( u1 u2 - upL upH ) 0 mpp mpp mpp mpp mpp mpp mpp mpp mpp mpp mpp mpp mpp mpp mpp mpp ROT_DROP ;
shldc Shift left and decrement conditionally when shldc=> tload <= '1'; nload <= '1'; nsel <= "10"; fcode <= icode(5 downto 0);
Division N2 N T : UM/MOD ( unumL unumH udenom -- urem uquot ) N2 N T -ROT \ udenom unumL unumH SHLDC SHLDC SHLDC SHLDC \ denom quot rem ROT_DROP_SWAP ; All other signed and unsigned division operations can be derived as WHYP words from UM/MOD
when "011110" => -- shldc yVector := a & b(width-1); y1_tmp := b(width-2 downto 0) & '0'; if yVector > CVector then yVector := yVector - CVector; y1_tmp(0) := '1'; end if; y <= yVector(width-1 downto 0); y1 <= y1_tmp; for I in 0 to 3 loop sll T & N; if T[8:4] > N2 then T := T - (0 & N2); N(0) := ‘1’; end if; end loop; T N sll 100001110 1101 N2
32 / 16 = 16:16 Division : UM/MOD ( unL unH ud -- ur uq ) -ROT shldc shldc shldc shldc shldc shldc shldc shldc shldc shldc shldc shldc shldc shldc shldc shldc ROT_DROP_SWAP ;
WHYP Test Files mul.whp -- multiplies two 16-bit numbers div.whp -- divides a 32-bit number by a 16-bit number fact16.whp -- computes the factorial of a number leap.whp -- checks if a year is a leap year
: UM* ( u1 u2 - upL upH ) 0 mpp mpp mpp mpp mpp mpp mpp mpp mpp mpp mpp mpp mpp mpp mpp mpp ROT_DROP ; : MAIN ( -- ) BEGIN waitB4 S@ \ get u1HI DUP DIG! 8 LSHIFT waitB4 S@ \ get u1LO OR DUP DIG! waitB4 S@ \ get u2HI DUP DIG! 8 LSHIFT waitB4 S@ \ get u2LO OR DUP DIG! waitB4 UM* \ multiply DIG! \ display upH waitB4 DIG! \ display upL AGAIN ; Mul.whp
: UM/MOD ( unL unH ud -- ur uq ) -ROT shldc shldc shldc shldc shldc shldc shldc shldc shldc shldc shldc shldc shldc shldc shldc shldc ROT_DROP_SWAP ; : MAIN ( -- ) BEGIN waitB4 S@ \ get unHHI DUP DIG! 8 LSHIFT waitB4 S@ \ get unHLO OR DUP DIG! waitB4 S@ \ get unLHI DUP DIG! 8 LSHIFT waitB4 S@ \ get unLLO OR DUP DIG! SWAP \ numerator waitB4 S@ \ get udHI DUP DIG! 8 LSHIFT waitB4 S@ \ get udLO OR \ denominator DUP DIG! waitB4 UM/MOD \ divide DIG! \ display uq waitB4 DIG! \ display ur AGAIN ; Div.whp
\ Example of BEGIN...WHILE...REPEAT : UM* ( u1 u2 - upL upH ) 0 mpp mpp mpp mpp mpp mpp mpp mpp mpp mpp mpp mpp mpp mpp mpp mpp ROT_DROP ; : * ( n1 n2 -- n3 ) UM* DROP ; : factorial ( n -- n! ) 1 2 ROT \ x i n BEGIN \ x i n OVER OVER <= \ x i n f WHILE \ x i n -ROT TUCK \ n i x i * SWAP \ n x' i 1+ ROT \ x' i' n REPEAT \ x i n DROP DROP ; \ x : main ( -- ) BEGIN waitB4 S@ DUP DIG! waitB4 factorial DIG! AGAIN ; Fact16.whp
Leap.whp \ leap year : UM/MOD ( unumL unumH udenom - urem uquot ) -ROT 16 FOR shldc NEXT ROT_DROP_SWAP ; : U/MOD ( n1 n2 -- urem uquot ) >R 0 R> UM/MOD ; : MOD ( n1 n2 -- urem ) U/MOD DROP ;
Leap.whp (cont.) : ?leap ( year -- flag ) DUP 400 MOD 0= IF DROP TRUE ELSE DUP 100 MOD 0= IF DROP FALSE ELSE 4 MOD 0= IF TRUE ELSE FALSE THEN THEN THEN ; : main ( -- ) BEGIN waitB4 S@ DUP DIG! 8 LSHIFT waitB4 S@ OR DUP DIG! waitB4 ?leap DIG! AGAIN ; Note: A year is a leap year if it is divisible by 4, but not by 100, or if it is divisible by 400.