Multi-Base Calculator CSE378 Final Project By Matthew Lehn & Yanqing Zhu December 17, 2001 Professor Haskell
What About it? It’s a calculator created from the original W8Y Microprocessor in Lab 9 Supports unsigned operands and results Can accept operands in hexadecimal, decimal, or octal – Returns the result in the same base Adds, subtracts, multiplies, & divides
Lab 9 Modifications Our 7-segment display needs to show BASE and OPER, however, only the characters 0-F existed in seg7dec.vhd. We created a 1-bit register to store a “flag”. When the flag is TRUE, P and R replace the characters 6 and 7. We also need some place to store the user’s specified BASE. Since the data stack and return stack are inconvenient spots and would require additional operations to retrieve, we decided to make the flag/status register to 5-bits.
T(4:0) fload M StatusREG ● F clr clk ● ● clr clk Lab 9 Mods cont’d - Schematic M
Lab 9 Mods cont’d – Seg7Dec.vhd entity seg7dec is port (q: in STD_LOGIC_VECTOR(3 downto 0); flag: in STD_LOGIC_VECTOR(4 downto 0); AtoG: out STD_LOGIC_VECTOR(6 downto 0)); end seg7dec; architecture seg7dec_arch of seg7dec is begin process(q, flag) begin case q is when "0000" => AtoG <= " "; -- zero... when "0100" => AtoG <= " "; -- 4 when "0101" => AtoG <= " "; -- 5 or S when "0110" => if flag = "11111" then AtoG <= " "; -- P else AtoG <= " "; -- 6 end if; when "0111" => if flag = "11111" then AtoG <= " "; -- r else AtoG <= " "; -- 7 end if; when "1000" => AtoG <= " "; when others => AtoG <= " "; -- "dash" end case; end process; end seg7dec_arch;
Lab 9 Mods – cont’d Due to space constraints, we removed several opcodes from w8y_codes.vhd and w8y_control.vhd. nop, over, nip, plus1, minus1, andd, orr, xorr, twoslash, rfromdrop, j[n]btn1, j[n]btn2, j[n]btn4 Implemented the tof and ffetch commands tof -> Send T(4:0) to the 5-bit statusReg ffetch -> Fetch into T whatever is in the statusReg Added a drop_swap command (1 clk cycle) Drop T, T <= N2, N is unchanged
Lab 9 Mods – w8y_control.vhd when drop_swap => tsel <= "10"; tload <= '1'; dpop <= '1'; when tof => -- Pop T and push it onto the flag register tsel <= "11"; tload <= '1'; nsel <= "10"; nload <= '1'; dpop <= '1'; fload <= '1'; when ffetch => -- Copy F from status register to T and push data stack tsel <= "01"; tload <= '1'; nload <= '1'; dpush <= '1'; dssel <= "11"; when jz => pload <= not z; pinc <= z; tsel <= "11"; tload <= '1'; nsel <= "10"; nload <= '1'; dpop <= '1';
Lab 9 Mods – cont’d We expanded ALU4.vhd to include: Multiplication (mpp) Nmux in the DS_ALU component changed to allow 4 inputs. A signal y2 was added into the MUX. ALU can now accept T, N, AND N2 as inputs. Division (shldc) Addition w/ Carry (+C)
ALU4.VHD & W8Y_CONTROL.VHD Note: The rest of ALU4.VHD resembles the lecture notes for MPP and SHLDC. when "1111" =>-- N + T (will display a carry) yVector := AVector + BVector; -- 9 bits, 1 for the carry y2_tmp(0) := yVector(width); y2 <= yVector(width-1 downto 0); -- Store sum (minus carry) into N y <= y2_tmp; -- Store carry bit into T when plus_carry => -- Use when actually wanting to add two numbers as an -- operation and NOT for intermediate steps requiring -- addition. This function displays the carry, if it exists tload <= '1'; nsel <= "00"; nload <= '1'; alusel <= "1111"; when mpp => tload <= '1'; nsel <= "00"; nload <= '1'; alusel <= "1101"; when shldc => tload <= '1'; nsel <= "00"; nload <= '1'; alusel <= "1110";
Convert_in Function Basic Idea If entering “49” into the calculator: The input BCD number isn’t real 49 it’s only 2 digits 4 & 9 ! Represented as The real 49 = 4 *
Convert_in Function : CONVERT_IN ( BCD/BCO -- BIN ) DUP 4 FOR U2/ NEXT \ get higher 4 bits \ fetch the base UM* \ T*N return 16 bits DROP_SWAP \ drop + swap 4 FOR 2* NEXT \ shift out the lower 4 bits 4 FOR U2/ NEXT \ get the higher 4 bits + ; \ Hbits+ Lbits SN2NT A
Convert_out Function Basic Idea The convert_out function is just the reverse of the convert_in function, i.e. 4 & 9 4*A+9 = (31) 16 INPUT CONVERT_IN 4 & 9 (31) 16 /A = 4…9 OUTPUT CONVERT_OUT
Convert_out_8 Function Convert_out_8 Convert 8 bit number, used only for Subtraction & Division Operation Quotient/Difference Remainder Subtraction 0 ~ 99(Dec) 0 ~ 77(Oct) 0 ~ FF(Hex) Division 0 ~ 99(Dec) 0 ~ 49 (Dec: 99/50) 0 ~ 77(Oct) 0 ~ 37 (Oct: 77/40) 0 ~ FF(Hex) 0 ~ 7F (Hex: FF/80)
Convert_out_8 Function : CONVERT_OUT_8 ( Bin -- BCD/BCO ) 0 \ Push higher 8 bits of result into T \ Get base from statusReg UM/MOD \ Convert 4 FOR \ Shift & combine the answer 2* NEXT + \ HBit + LBit SWAP ;
Convert_out_16 Function Convert_out_16 Convert 16 bit number, used only for Addition & Multiplication Operation Product/Sum Addition 0 ~ 198(Dec) 0 ~ 176(Oct) 0 ~ 1FE(Hex) Multiplication 0 ~ 9801(Dec) 0 ~ 7601(Oct) 0 ~ FE01(Hex)
Convert_out_16 Function : CONVERT_OUT_16 ( BinL BinL -- BCDL/BCOL BCDH/BCOH ) 3 FOR MU/MOD \ Divide by base & return dbl quotient NEXT DROP \ Drop 00 in T 4 FOR \ T= bit of the answer 2* \ Shift it to higher bits NEXT + \ N= bit bit15-12= bit15-8 -ROT \ N= bit7-4, put it in T 4 FOR 2* \ Shift bit7-4 to the higher positions NEXT + \ N= bit3-0 + bit7-4= bit7-0 (in T) SWAP ; \ Swap bit15-8 w/ bit7-0
WHYP it Up! HEX : DELAY ( -- ) F5 FOR NEXT ; : = ( n1 n2 -- f ) - 0= ; : UM* ( u1 u2 -- ud ) 0 8 FOR mpp NEXT ROT_DROP ; : UM/MOD ( unumL unumH udenom -- urem uquot ) -ROT 8 FOR shldc NEXT ROT_DROP_SWAP ; : MU/MOD ( ud un -- urem udquot ) >R 0 \ udL udH 0 un UM/MOD \ udl remH quotH R> \ udL remH quotH un SWAP >R \ udL remH un UM/MOD \ remL quotL R> ; \ remL quotL quotH : CONVERT_IN ( fakebin -- realbin ) \ Convert BCD to real binary DUP 4 FOR \ Get the higher bits (shift right) U2/ NEXT \ Get the base from statusReg UM* \ Convert the higher bits DROP_SWAP \ Drop the 00 & load lower bits 4 FOR \ Get rid of the higher bits 2* NEXT 4 FOR \ Shift back the lower bits U2/ NEXT + ; \ HBit + LBit = real binary : CONVERT_OUT_16 ( bin -- fakebin ) \ Convert binary to designated base -- Used for addition & multiplication 3 FOR MU/MOD \ Divide by base- return dbl quot NEXT DROP \ Drop 00 in T
WHYP it Up – Cont’d 4 FOR \ T= bit of the answer 2* \ Shift it to higher bits NEXT + \ N= bit bit15-12= bit15-8 -ROT \ N= bit7-4, put it in T 4 FOR 2* \ Shift bit7-4 to the higher positions NEXT + \ N= bit3-0 + bit7-4= bit7-0 (in T) SWAP ; \ Swap bit15-8 w/ bit7-0 : CONVERT_OUT_8 \ Convert binary to designated base \ Used for subtraction & division 0 \ Push higher 8 bits of result into T \ Get base from statusReg UM/MOD \ Convert 4 FOR \ Shift & combine the answer as above 2* NEXT + \ HBit + LBit SWAP ; : GET2_N_CONVERT ( -- u1 u2 ) \ Fetch & convertt waitbtn3 DELAY CONVERT_IN \ to specified base waitbtn3 DELAY CONVERT_IN waitbtn3 ; : main ( -- ) BEGIN 5E \ Display BASE BA waitbtn3 DROP DROP \ Get rid of BA5E in T & N regs TRUE >F \ Set flag to TRUE so OPER is displayed \ Fetch the base (switches 4-8) DUP \ Copy base to N for later use E7 \ Display OPER 06 waitbtn3 DROP \ Drop 06 from T, put E7 in T FALSE \ Overwrite E7 in T with zeros >F \ Turn off P & R display mode \ Fetch operation (switches 1-2) TUCK + \ Place oper in N2 and add N & T LD! \ Light LEDs to signify base and oper SWAP \ Put base in T and oper in N >F \ Save base in statusReg; put oper in T DUP \ Duplicate oper into N C0 = \ Division IF
WHYP it Up – Cont’d DROP \ Remove oper GET2_N_CONVERT \ Get 2 operands & convert to base 0 SWAP \ Set high bits to 0 (8/8 div only) UM/MOD \ Divide N2 by T (N is 0) CONVERT_OUT_8 \ Convert quotient to base CONVERT_OUT_8 \ Convert remainder to base ELSE DUP 80 = \ Multiplication IF DROP \ Remove OPER GET2_N_CONVERT UM* \ Multiply T & N CONVERT_OUT_16 ELSE 40 = \ Subtraction IF GET2_N_CONVERT - \ Subtract T from N CONVERT_OUT_8 ELSE \ Addition GET2_N_CONVERT +C \ Add T & N; store carry in T CONVERT_OUT_16 THEN waitbtn3 \ Hold answer on display AGAIN ;
Compiled w8y_rom (1/3) type rom_array is array (0 to 223) of STD_LOGIC_VECTOR (7 downto 0); constant rom: rom_array := ( JMP, --0 X"83", --1 LIT, -- :DELAY X"f5", --3 tor, --4 drjne, --5 X"05", --6 RET, --7 minus, -- := zeroequal, --9 RET, --a LIT, -- :UM* X"00", --c LIT, --d X"08", --e tor, --f mpp, --10 drjne, --11 X"10", --12 ROT_DROP, --13 RET, --14 mrot, -- :UM/MOD LIT, --16 X"08", --17 tor, --18 shldc, --19 drjne, --1a X"19", --1b ROT_DROP_SWAP, --1c RET, --1d tor, -- :MU/MOD LIT, --1f X"00", --20 rfetch, --21 CALL, --22 X"15", --23 rfrom, --24 swap, --25 tor, --26 CALL, --27 X"15", --28 rfrom, --29 RET, --2a dup, -- :convert_in LIT, --2c X"04", --2d tor, --2e u2slash, --2f drjne, --30 X"2f", --31 ffetch, --32 CALL, --33 X"0b", --34 drop_swap, --35 LIT, --36 X"04", --37 tor, --38 twotimes, --39 drjne, --3a X"39", --3b LIT, --3c X"04", --3d tor, --3e u2slash, --3f drjne, --40 X"3f", --41 plus, --42 RET, --43 LIT, -- :conv_out_16 X"03", --45 tor, --46 ffetch, --47 CALL, --48 X"1e", --49 drjne, --4a X"47", --4b drop, --4c LIT, --4d X"04", --4e tor, --4f twotimes, --50 drjne, --51 X"50", --52 plus, --53
Compiled w8y_rom (2/3) mrot, --54 LIT, --55 X"04", --56 tor, --57 twotimes, --58 drjne, --59 X"58", --5a plus, --5b swap, --5c RET, --5d LIT, --5e X"00", -- :conv_out_8 ffetch, --60 CALL, --61 X"15", --62 LIT, --63 X"04", --64 tor, --65 twotimes, --66 drjne, --67 X"66", --68 plus, --69 swap, --6a RET, --6b JBTN3, -- :get2_n_conv X"6c", --6d JNBTN3, --6e X"6e", --6f swfetch, --70 CALL, --71 X"02", --72 CALL, --73 X"2b", --74 JBTN3, --75 X"75", --76 JNBTN3, --77 X"77", --78 swfetch, --79 CALL, --7a X"02", --7b CALL, --7c X"2b", --7d JBTN3, --7e X"7e", --7f JNBTN3, --80 X"80", --81 RET, --82 LIT, -- :MAIN X"5e", --84 LIT, --85 X"ba", --86 JBTN3, --87 X"87", --88 JNBTN3, --89 X"89", --8a drop, --8b drop, --8c ones, --8d tof, --8e swfetch, --8f dup, --90 LIT, --91 X"e7", --92 LIT, --93 X"06", --94 JBTN3, --95 X"95", --96 JNBTN3, --97 X"97", --98 drop, --99 zeros, --9a tof, --9b swfetch, --9c tuck, --9d plus, --9e ldstore, --9f swap, --a0 tof, --a1 dup, --a2 LIT, --a3 X"c0", -- DIVIDE CALL, --a5 X"08", --a6 JZ, --a7 X"b7", --a8 drop, --a9 CALL, --aa X"6c", --ab LIT, --ac X"00", --ad
Compiled w8y_rom (3/3) swap, --ae CALL, --af X"15", --b0 CALL, --b1 X"5e", --b2 CALL, --b3 X"5e", --b4 JMP, --b5 X"d9", --b6 dup, --b7 LIT, --b8 X"80", -- MULTIPLY CALL, --ba X"08", --bb JZ, --bc X"c7", --bd drop, --be CALL, --bf X"6c", --c0 CALL, --c1 X"0b", --c2 CALL, --c3 X"44", --c4 JMP, --c5 X"d9", --c6 LIT, --c7 X"40", -- SUBTRACT CALL, --c9 X"08", --ca JZ, --cb X"d4", --cc CALL, --cd X"6c", --ce minus, --cf CALL, --d0 X"5e", --d1 JMP, --d2 X"d9", --d3 CALL, -- ADD X"6c", --d5 plus_carry, --d6 CALL, --d7 X"44", --d8 JBTN3, --d9 X"d9", --da JNBTN3, --db X"db", --dc JMP, --dd X"83", --de X"00" --df );
Conclusion Unfortunately, since each simulation waveform is extraordinarily long and would take 10+ slides to cover, they will not be shown here. The result is not shown until 12,400 ns! Note that the calculator will only accept positive operands and only display positive results. For instance, it can’t perform (1 - F) or (-2 * 5).