------------------------------------------------------------------------------- -- Project Step 9 - Extra Credit -- Adding a shifter and doing integer multiplication -- -- NAME -- ------------------------------------------------------------------------------- -- the declaration for type shift_op which should be added to your support pkg -- it is included as a comment here ------------------------------------------------------------------------------- -- TYPE shift_operations IS (op_lsl,op_lsr,op_asl,op_asr,op_rol,op_ror, -- op_rolwc,op_rorwc); ------------------------------------------------------------------------------- -- Enter your entity and architecture for the datapath here. ------------------------------------------------------------------------------- -- *** -- *** -- *** -- *** -- *** ------------------------------------------------------------------------------- -- Test Bench Entity for the Register set ------------------------------------------------------------------------------- ENTITY ectb IS END ectb; LIBRARY IEEE; USE IEEE.STD_LOGIC_1164.ALL; -- *** remember to add your package USE WORK.alu_support2.all; ARCHITECTURE test OF ectb IS -- *** put your component declaration and configuration here -- *** -- *** -- *** -- *** -- *** -- controller signals and busses SIGNAL ABUS,BBUS : std_logic_vector (15 downto 0); SIGNAL Aregload,Bregload,Aregdrive,Bregdrive : std_logic; SIGNAL AregNo,BregNo : integer := 0; SIGNAL A_ALUload,B_ALUload,A_ALUdrive,B_ALUdrive : std_logic; SIGNAL A_ALUsel : std_logic; SIGNAL Cin,C,N,Z : std_logic; SIGNAL oper : operations; SIGNAL MCR : std_logic_vector (7 downto 0); SIGNAL Shift_op : shift_operations; SIGNAL Shift_dist : Integer; -- signals for checking of outputs SIGNAL exp_abus,exp_bbus : std_logic_vector (15 downto 0); SIGNAL abus_err,bbus_err : bit; SIGNAL cexp,zexp,nexp : std_logic := '0'; SIGNAL cerr,zerr,nerr : std_logic := '0'; SIGNAL tot_err : Integer := 0; TYPE LDItype IS (Idle,TBLoad,Load,Drive,Accum); CONSTANT HighZ : std_logic_vector (15 downto 0) := "ZZZZZZZZZZZZZZZZ"; type value_tbl_type is array (0 to 35) of std_logic_vector(15 downto 0); constant v_tbl : value_tbl_type := ( --v_tbl "0000000000000000", --X0000 0 "0101010101010101", --X5555 1 "0000000000000010", --X0002 2 "0000000000000011", --X0003 3 "0000000000000100", --X0004 4 "0000000000000101", --X0005 5 "0000000000000110", --X0006 6 "0000000000000111", --X0007 7 "0000000000001000", --X0008 8 "0000000000001001", --X0009 9 "0000000000001010", --X000A 10 "0000000000001011", --X000B 11 "0000000000001100", --X000C 12 "0000000000001101", --X000D 13 "0000000000001110", --X000E 14 "0000000000001111", --X000F 15 "0000000000000001", --X0001 16 "1010101010101010", --XAAAA 17 "1111111111111010", --XFFFA 18 "0000000000010010", --X0012 19 "0000000000011100", --X001C 20 "0000000000100111", --X0027 21 "0000000000011011", --X001B 22 "0000000111000000", --X01C0 23 "1000000000000000", --X8000 24 "1111100000000000", --XF100 25 "0000111110000000", --X0F10 26 "0000000000011111", --X001F 27 "0000000001111110", --X007E 28 "0000000111111000", --X01F8 29 "0000000000010100", --X0014 30 "0000000000101010", --X002A 31 "0000000001001000", --X0048 32 "0000000001101110", --X006E 33 "0000000010011100", --X009C 34 "0000000011010010");--X00D2 35 TYPE final_val_type IS ARRAY (0 to 15) OF INTEGER; CONSTANT fv_seq : final_val_type:=(0,1,2,5,9,15,18,16,9,19,20,21,22,14,13,0); CONSTANT ml_seq : final_val_type:=(0,0,2,6,4,30,6,31,8,32,10,33,12,34,14,35); TYPE cnz_val_type IS ARRAY (0 to 8) of std_logic_vector(2 downto 0); CONSTANT cnz_val : cnz_val_type := ("000","001","010","011", "100","101","110","111","---"); ---------------------------------------------------------------------------- BEGIN -- Testbench Architecture ---------------------------------------------------------------------------- -- ***Instantiate your datapath here -- *** -- *** -- *** -- *** -- *** ---------------------------------------------------------------------------- ---------------------------------------------------------------------------- applytest : PROCESS ---------------------------------------------------------------------------- ---------------------------------------------------------------------------- PROCEDURE bus_cycle (A_regldi : LDItype; A_reg_no : Integer; A_aluldi : LDItype; A_aluinsel : std_logic; A_BUS_VAL : std_logic_vector (15 downto 0); A_BUS_EXP : std_logic_vector (15 downto 0); B_regldi : LDItype; B_reg_no : Integer; B_aluldi : LDItype; B_BUS_VAL : std_logic_vector (15 downto 0); B_BUS_EXP : std_logic_vector (15 downto 0); Shf_op : Shift_operations; Shf_dist : Integer; MCR_ldi : LDItype; alu_op : operations; Cinval : std_logic; exp_cc : Integer; checkbus : BOOLEAN) IS BEGIN WAIT FOR 9 NS; -- 9 ns into cycle IF (ABUS /= HighZ) THEN Abus_err <= '1','0' after 1 ns; END IF; IF (BBUS /= HighZ) THEN Bbus_err <= '1','0' after 1 ns; END IF; WAIT FOR 1 NS; -- 10 ns into cycle AregNo <= A_reg_no; BregNo <= B_reg_no; Cin <= Cinval; exp_abus <= A_BUS_EXP; exp_bbus <= B_BUS_EXP; oper <= alu_op; A_Alusel <= A_aluinsel; shift_op <= shf_op; shift_dist <= shf_dist; CASE A_regldi IS WHEN TBLoad => Aregload <= '0'; ABUS <= A_BUS_VAL; WHEN Load => Aregload <= '0'; WHEN Drive => Aregdrive <= '0'; WHEN Idle | Accum => null; END CASE; CASE B_regldi IS WHEN TBLoad => Bregload <= '0'; BBUS <= B_BUS_VAL; WHEN Load => Bregload <= '0'; WHEN Drive => Bregdrive <= '0'; WHEN Idle | Accum => null; END CASE; CASE A_aluldi IS WHEN Load => A_ALUload <= '0'; WHEN Drive => A_ALUdrive <= '0'; WHEN TBLoad | Idle | Accum => null; END CASE; CASE B_aluldi IS WHEN Load => B_ALUload <= '0'; WHEN Drive => B_ALUdrive <= '0'; WHEN Accum => B_ALUload <= '0'; B_ALUdrive <= '0'; WHEN TBLoad | Idle => null; END CASE; WAIT FOR 10 NS; -- 20 ns into cycle IF checkbus THEN IF (ABUS /= A_BUS_EXP) THEN Abus_err <= '1','0' after 1 ns; END IF; IF (BBUS /= B_BUS_EXP) THEN Bbus_err <= '1','0' after 1 ns; END IF; END IF; WAIT FOR 49 NS; -- 69 ns into cycle IF checkbus THEN IF (ABUS /= A_BUS_EXP) THEN Abus_err <= '1','0' after 1 ns; END IF; IF (BBUS /= B_BUS_EXP) THEN Bbus_err <= '1','0' after 1 ns; END IF; END IF; WAIT FOR 1 NS; -- 70 ns into cycle IF (A_regldi = Load OR A_regldi = TBLoad) THEN Aregload <= '1'; END IF; IF (B_regldi = Load OR B_regldi = TBLoad) THEN Bregload <= '1'; END IF; IF (A_aluldi = Load) THEN A_ALUload <= '1'; END IF; IF (B_aluldi = Load OR B_aluldi = Accum) THEN B_ALUload <= '1'; END IF; IF (MCR_ldi = Load) THEN MCR <= ABUS(7 downto 0); END IF; WAIT FOR 10 NS; -- 80 ns into cycle IF (A_regldi = Drive) THEN Aregdrive <= '1'; END IF; IF (A_aluldi = Drive) THEN A_ALUdrive <= '1'; END IF; IF (A_regldi = TBLoad) THEN ABUS <= HighZ; END IF; IF (B_regldi = Drive) THEN Bregdrive <= '1'; END IF; IF (B_aluldi = Drive OR B_aluldi = Accum) THEN B_ALUdrive <= '1'; END IF; IF (B_regldi = TBLoad) THEN BBUS <= HighZ; END IF; exp_abus <= HighZ; exp_bbus <= HighZ; IF ((A_aluldi = Drive) or (B_aluldi = Drive)) THEN IF ((exp_cc /= 8) and (C /= cnz_val(exp_cc)(2))) THEN cerr <= '1', '0' after 1 ns; END IF; cexp <= cnz_val(exp_cc)(2); IF ((exp_cc /= 8) and (N /= cnz_val(exp_cc)(1))) THEN nerr <= '1', '0' after 1 ns; END IF; nexp <= cnz_val(exp_cc)(1); IF ((exp_cc /= 8) and (Z /= cnz_val(exp_cc)(0))) THEN zerr <= '1', '0' after 1 ns; END IF; zexp <= cnz_val(exp_cc)(0); END IF; WAIT FOR 11 NS; -- 91 ns into cycle IF (ABUS /= HighZ) THEN Abus_err <= '1','0' after 1 ns; END IF; IF (BBUS /= HighZ) THEN Bbus_err <= '1','0' after 1 ns; END IF; WAIT FOR 9 NS; -- end of 100 ns cycle END bus_cycle; ---------------------------------------------------------------------------- PROCEDURE oneregop (sregno : INTEGER; alu_oper:operations; alu_cin:std_logic; abusc1,bbusc1,abusc2,bbusc2:std_logic_vector(15 downto 0); exp_cc : Integer) IS BEGIN bus_cycle(Drive,sregno,load,'1',highZ,abusc1, Idle,0,idle,highz,bbusc1, op_lsl,0,idle,alu_oper,alu_cin,8,TRUE); bus_cycle(Idle,0,idle,'1',highZ,abusc2, Load,sregno,Drive,highz,bbusc2, op_lsl,0,idle,alu_oper,alu_cin,exp_cc,TRUE); END oneregop; ---------------------------------------------------------------------------- PROCEDURE tworegop (s1reg,s2reg:INTEGER; alu_oper:operations; alu_cin:std_logic; abusc1,bbusc1,abusc2,bbusc2:std_logic_vector(15 downto 0); exp_cc : Integer) IS BEGIN bus_cycle(Drive,s1reg,load,'1',highz,abusc1, Drive,s2reg,load,highz,bbusc1, op_lsl,0,idle,alu_oper,alu_cin,8,TRUE); bus_cycle(Idle,0,idle,'1',highz,abusc2, load,s2reg,drive,highz,bbusc2, op_lsl,0,idle,alu_oper,alu_cin,exp_cc,TRUE); END tworegop; ---------------------------------------------------------------------------- PROCEDURE shiftop (s1reg : Integer; s_op : shift_operations; s_dist : Integer; s_cin : std_logic; abusc1,bbusc1,abusc2,bbusc2:std_logic_vector(15 downto 0); exp_cc : Integer) IS BEGIN -- on first cycle move data to ALU and select shifter input and op_A bus_cycle(Drive,s1reg,Load,'0',HighZ,abusc1, Idle,0,Idle,HighZ,bbusc1, s_op,s_dist,idle,op_A,s_cin,exp_cc,TRUE); bus_cycle(Idle,0,idle,'0',HighZ,abusc2, Load,s1reg,Drive,HighZ,bbusc2, s_op,s_dist,idle,op_A,s_cin,exp_cc,TRUE); END shiftop; ---------------------------------------------------------------------------- ---------------------------------------------------------------------------- -- *** Put your multiply procedure here. ---------------------------------------------------------------------------- -- *** -- *** -- *** -- *** -- *** ---------------------------------------------------------------------------- ---------------------------------------------------------------------------- BEGIN -- Initialize all signals ABUS <= HighZ; BBUS <= HighZ; Aregload <= '1'; Bregload <= '1'; Aregdrive <= '1'; Bregdrive <= '1'; AregNo <= 0; BregNo <= 0; A_ALUload <= '1'; B_ALUload <= '1'; A_ALUsel <= '1'; Shift_op <= op_lsl; Shift_dist <= 0; A_ALUdrive <= '1'; B_ALUdrive <= '1'; Cin <= '0'; oper <= op_0; -- load initial values to registers using both Busses FOR I in 0 to 7 Loop bus_cycle(TBLoad,I,Idle,'1',v_tbl(I),v_tbl(I), TBLoad,15-I,Idle,v_tbl(15-I),v_tbl(15-I), op_lsl,0,idle,op_0,'0',8,TRUE); END LOOP; -- check contents were loaded correctly by dumping onto busses FOR I in 0 to 7 Loop bus_cycle(Drive,15-I,Idle,'1',HighZ,v_tbl(15-I), Drive,I,Idle,HighZ,v_tbl(I), op_lsl,0,idle,op_0,'0',8,TRUE); END LOOP; -- Start Operations -- R(0) xor R(1) -> R(1) tworegop(0,1,op_AxorB,'0',v_tbl(0),v_tbl(1),highz,v_tbl(1),0); -- R(1) or R(0) -> R(0) tworegop(1,0,op_AorB,'0',v_tbl(1),v_tbl(0),highz,v_tbl(1),0); -- not R(0) -> R(0) oneregop(0,op_notA,'0',v_tbl(1),highz,highz,v_tbl(17),2); -- R(1) and R(0) -> R(0) tworegop(1,0,op_AandB,'0',v_tbl(1),v_tbl(17),highz,v_tbl(0),1); -- R(2) + R(3) -> R(3) tworegop(2,3,op_AplusB,'0',v_tbl(2),v_tbl(3),highz,v_tbl(5),0); -- R(3) + R(4) -> R(4) tworegop(3,4,op_AplusB,'0',v_tbl(5),v_tbl(4),highz,v_tbl(9),0); -- R(4) + R(5) -> R(5) tworegop(4,5,op_AplusBwC,'1',v_tbl(9),v_tbl(5),highz,v_tbl(15),0); -- neg R(6) -> R(6) oneregop(6,op_negA,'0',v_tbl(6),highz,highz,v_tbl(18),2); -- R(6) + R(7) -> R(7) tworegop(6,7,op_AplusB,'0',v_tbl(18),v_tbl(7),highz,v_tbl(16),4); -- R(7) + R(8) -> R(8) tworegop(7,8,op_AplusB,'0',v_tbl(16),v_tbl(8),highz,v_tbl(9),0); -- R(8) + R(9) -> R(9) tworegop(8,9,op_AplusB,'0',v_tbl(9),v_tbl(9),highz,v_tbl(19),0); -- R(9) + R(10) -> R(10) tworegop(9,10,op_AplusB,'0',v_tbl(19),v_tbl(10),highz,v_tbl(20),0); -- R(10) + R(11) -> R(11) tworegop(10,11,op_AplusB,'0',v_tbl(20),v_tbl(11),highz,v_tbl(21),0); -- R(11) - R(12) -> R(12) tworegop(11,12,op_AminB,'0',v_tbl(21),v_tbl(12),highz,v_tbl(22),0); -- inc R(13) -> R(13) oneregop(13,op_incA,'0',v_tbl(13),highz,highz,v_tbl(14),0); -- dec (14) -> R(14) oneregop(14,op_decA,'0',v_tbl(14),highz,highz,v_tbl(13),0); -- "x_0000" -> R(15) oneregop(15,op_0,'0',v_tbl(15),highz,highz,v_tbl(0),1); -- final dump and check of registers using the Bbus FOR I in 0 to 7 Loop bus_cycle(Drive,I,Idle,'1',HighZ,v_tbl(fv_seq(I)), Drive,15-I,Idle,HighZ,v_tbl(fv_seq(15-I)), op_lsl,0,idle,op_0,'0',8,TRUE); END LOOP; -- check out shifter -- shift register 1 shiftop(13,op_lsl,0,'0',v_tbl(14),highz,highz,v_tbl(14),0); shiftop(13,op_lsl,1,'0',v_tbl(14),highz,highz,v_tbl(20),0); shiftop(13,op_lsl,4,'0',v_tbl(20),highz,highz,v_tbl(23),0); shiftop(13,op_lsl,9,'0',v_tbl(23),highz,highz,v_tbl(24),6); shiftop(13,op_asr,4,'0',v_tbl(24),highz,highz,v_tbl(25),2); shiftop(13,op_ror,4,'0',v_tbl(25),highz,highz,v_tbl(26),0); shiftop(13,op_rol,9,'0',v_tbl(26),highz,highz,v_tbl(27),4); shiftop(13,op_rolwc,2,'1',v_tbl(27),highz,highz,v_tbl(28),0); shiftop(13,op_asl,2,'1',v_tbl(28),highz,highz,v_tbl(29),0); shiftop(13,op_asr,11,'0',v_tbl(29),highz,highz,v_tbl(0),1); -- reload initial register values FOR I in 0 to 7 Loop bus_cycle(TBLoad,I,Idle,'1',v_tbl(I),v_tbl(I), TBLoad,15-I,Idle,v_tbl(15-I),v_tbl(15-I), op_lsl,0,idle,op_0,'0',8,TRUE); END LOOP; -- now multiply register pairs -- *** Put the code needed to call your multiply procedure -- to multiply the register pairs. -- *** -- *** -- *** -- *** -- *** -- final dump to check that multiply worked FOR I in 0 to 7 Loop bus_cycle(Drive,I,Idle,'1',HighZ,v_tbl(ml_seq(I)), Drive,15-I,Idle,HighZ,v_tbl(ml_seq(15-I)), op_lsl,0,idle,op_0,'0',8,TRUE); END LOOP; -- DONE - Ta DA!! WAIT; END PROCESS; PROCESS (abus_err,bbus_err,cerr,nerr,zerr) -- process to total errors VARIABLE temp_total : Integer; BEGIN temp_total := tot_err; IF (abus_err = '1' and abus_err'event) THEN temp_total := temp_total + 1; END IF; IF (bbus_err = '1' and bbus_err'event) THEN temp_total := temp_total + 1; END IF; IF (cerr = '1' and cerr'event) THEN temp_total := temp_total + 1; END IF; IF (nerr = '1' and nerr'event) THEN temp_total := temp_total + 1; END IF; IF (zerr = '1' and zerr'event) THEN temp_total := temp_total + 1; END IF; tot_err <= temp_total; END PROCESS; END test;