-------------------------------------------------- -- Model : 8051 Behavioral Model, -- VHDL Entity mc8051.al_unit.interface -- -- Author : Michael Mayer (mrmayer@computer.org), -- Dr. Hardy J. Pottinger, -- Department of Electrical Engineering -- University of Missouri - Rolla -- -- Created at : 09/19/98 20:02:07 -- LIBRARY ieee ; USE ieee.std_logic_1164.all; USE ieee.numeric_std.all; LIBRARY mc8051 ; USE mc8051.cpu_pack.all; USE mc8051.synth_pack.all; ENTITY al_unit IS PORT( ac : IN std_logic ; alu_cmd : IN std_logic_vector( 3 DOWNTO 0 ) ; bit_loc : IN std_logic_vector( 2 DOWNTO 0 ) ; cpu_rst : IN std_logic ; cy : IN std_logic ; data_alu : IN std_logic_vector( 2 DOWNTO 0 ) ; int_clk : IN std_logic ; ov : IN std_logic ; set_ac_ov : IN std_logic ; set_cy : IN std_logic ; tmp1 : IN std_logic_vector( 7 DOWNTO 0 ) ; tmp1_done : IN std_logic ; tmp2 : IN std_logic_vector( 7 DOWNTO 0 ) ; use_acc_0 : IN std_logic ; use_cy : IN std_logic ; ac_out : OUT std_logic ; alu_result : OUT std_logic_vector( 7 DOWNTO 0 ) ; cmp_true : OUT std_logic ; cy_out : OUT std_logic ; ov_out : OUT std_logic ); -- Declarations END al_unit ; -- -- VHDL Architecture mc8051.al_unit.spec -- -- Created: -- by - mrmayer.UNKNOWN (eceultra20.ece.umr.edu) -- at - 23:25:29 09/02/98 -- -- Generated by Mentor Graphics' Renoir(TM) 3.0 (Build 110) -- -- the organization is such: -- tmp1 and tmp2 contain two data paramaters to be used, -- tmp1 may be complemented and will then be converted to unsigned (arith1) -- tmp2 may likely be the acc and will be converted to unsigned (arith2) -- ctrl lines will cause these two arith's to be added, (or hence subtracted -- if 2's complement was takes on tmp1) or logically combined. -- Bit functions may also be performed. Flags changed. -- A comparison will be made between the answer and arith2. -- The answer will be output to dest. -- This all happens before done goes high (one clock cycle after rdy -- goes high - triggered by tmp1_reg). -- input ports: alu_cmd(3 DOWNTO 0); data_alu(2 DOWNTO 0); -- set_cy -- set_ac_ov -- use_cy -- use_old_flags -- bit_loc (2 DOWNTO 0); -- cpl_tmp1 -- output ports -- test_result -- result (7 DOWNTO 0); -- ac_out, ov_out, cy_out, wr_out architecture spec of al_unit is SIGNAL rdy, rdy_clk, done, done_clk : std_logic; SIGNAL cy_tmp, ac_tmp, ov_tmp : std_logic; SIGNAL cy_tmp1 : std_logic; -- SIGNAL cy_old, ac_old, ov_old : std_logic; SIGNAL bit_instr : std_logic; -- '1' if its a bit instr SIGNAL bit1, bit2, bit_ans : std_logic; SIGNAL tmp1_eq_tmp2, bit_to_insert : std_logic; SIGNAL tmp1_with_bit : std_logic_vector(7 DOWNTO 0); -- the parts of answer, separate to get info for ac, cy, ov SIGNAL add_en, sub_en : std_logic; SIGNAL arith1_ls, arith2_ls, add_ls : unsigned(4 DOWNTO 0); SIGNAL arith1_ms, arith2_ms, add_ms : unsigned(3 DOWNTO 0); SIGNAL add_msb : std_logic; SIGNAL arith_ans : unsigned(7 DOWNTO 0); SIGNAL tmp1_7_XOR_tmp2_7 : std_logic; -- signals for the pre-processing to occur on the temp registers SIGNAL tmp1_post, tmp2_post : std_logic_vector(7 DOWNTO 0); SIGNAL tmp1_2, tmp1_3 : unsigned(7 DOWNTO 0); begin ------------------- BEGIN HANDSHAKING and CONTROL PROCESSING -- The following are flip - flops -- rdy is set on a clock edge after it receives tmp1_done -- rdy_clk <= tmp1_done AND int_clk; -- -- rdy <= '0' WHEN done = '1' OR cpu_rst = '1' ELSE -- '1' WHEN rising_edge(rdy_clk) ELSE -- rdy; -- -- -- alu_done is set one clock cycle after rdy (delayed just to be safe) -- done_clk <= rdy AND int_clk; -- done <= '0' WHEN cpu_rst = '1' ELSE -- '1' WHEN rising_edge(done_clk) ELSE -- done; -- -- alu_done <= done; -------------- DETERMINE THE ANSWER HERE -- assign the answer to the output port result alu_result <= tmp1_post WHEN alu_cmd = pass_tmp1 ELSE tmp2_post WHEN alu_cmd = pass_tmp2 ELSE tmp2_post WHEN alu_cmd = rotate ELSE tmp1_with_bit WHEN bit_instr = '1' ELSE std_logic_vector(arith_ans); ------------- BEGIN PRE OPERAND PROCESSING -- first decide to complement the temp1 register tmp1_2 <= unsigned(NOT tmp1) WHEN std_match(data_alu,t1_cpl_val) ELSE unsigned(tmp1); -- second perform any necessay inc / dec tmp1_3 <= tmp1_2 + 1 WHEN std_match(data_alu,t1_inc_val) ELSE tmp1_2 - 1 WHEN std_match(data_alu,t1_dec_val) ELSE tmp1_2; -- third, decide if need to use cpl, inc/dec, swap, or just plain tmp1 tmp1_post <= tmp1(7 DOWNTO 4) & tmp2(3 DOWNTO 0) WHEN std_match(alu_cmd,xchd1) ELSE std_logic_vector(tmp1_3) WHEN std_match(alu_cmd,std_alu_data) ELSE tmp1; ------------- BEGIN BIT STUFF bit_instr <= '1' WHEN std_match(alu_cmd,"11--") ELSE '0'; -- use a selector to get the corret bit for bit1 bit1 <= cy WHEN use_cy = '1' ELSE tmp1(0) WHEN bit_loc = "000" ELSE tmp1(1) WHEN bit_loc = "001" ELSE tmp1(2) WHEN bit_loc = "010" ELSE tmp1(3) WHEN bit_loc = "011" ELSE tmp1(4) WHEN bit_loc = "100" ELSE tmp1(5) WHEN bit_loc = "101" ELSE tmp1(6) WHEN bit_loc = "110" ELSE tmp1(7) WHEN bit_loc = "111" ELSE 'X'; -- bit2 is input to the bit operator, and equal bit1 or /bit1 -- cpl bit1 if cpl_bit_logic bit2 <= NOT bit1 WHEN std_match(alu_cmd,cpl_bit_logic) ELSE bit1; -- perform bit operations bit_ans <= bit2 AND cy WHEN std_match(data_alu,anl_instr) ELSE -- anl instr bit2 OR cy WHEN std_match(data_alu,orl_instr) ELSE -- orl instr bit2; bit_to_insert <= '0' WHEN alu_cmd = clr_bit ELSE '1' WHEN alu_cmd = set_bit ELSE bit_ans; -- figure out where the bit gets inserted tmp1_with_bit(0) <= bit_to_insert WHEN bit_loc = "000" ELSE tmp1(0); tmp1_with_bit(1) <= bit_to_insert WHEN bit_loc = "001" ELSE tmp1(1); tmp1_with_bit(2) <= bit_to_insert WHEN bit_loc = "010" ELSE tmp1(2); tmp1_with_bit(3) <= bit_to_insert WHEN bit_loc = "011" ELSE tmp1(3); tmp1_with_bit(4) <= bit_to_insert WHEN bit_loc = "100" ELSE tmp1(4); tmp1_with_bit(5) <= bit_to_insert WHEN bit_loc = "101" ELSE tmp1(5); tmp1_with_bit(6) <= bit_to_insert WHEN bit_loc = "110" ELSE tmp1(6); tmp1_with_bit(7) <= bit_to_insert WHEN bit_loc = "111" ELSE tmp1(7); tmp1_eq_tmp2 <= '1' WHEN std_match(tmp1_post,tmp2_post) ELSE '0'; cmp_true <= bit_ans WHEN bit_instr = '1' ELSE -- for JB, JNB, JC, JBC, etc. tmp1_eq_tmp2 WHEN std_match(alu_cmd,compare_1_2) ELSE -- for JZ NOT tmp1_eq_tmp2; -- for JNZ, DJNZ, CJNE ------------- END BIT STUFF ------------- BEGIN ARITHMATIC & LOGIC arith1_ls <= unsigned('0' & tmp1(3 DOWNTO 0)); arith2_ls <= unsigned('0' & tmp2(3 DOWNTO 0)); arith1_ms <= unsigned('0' & tmp1(6 DOWNTO 4)); arith2_ms <= unsigned('0' & tmp2(6 DOWNTO 4)); -- FULL ADDER WITH AC, OV, AND CY INFO -- add first 4 bits and store ac add_ls <= arith2_ls + arith1_ls; -- need to complement the ac if it is a subtraction ac_tmp <= NOT add_ls(4) WHEN std_match(data_alu,t1_cpl_val) ELSE add_ls(4); -- add next 3 bits (to get ov info) add_ms <= (arith2_ms + arith1_ms) + ("000" & add_ls(4)); -- find the msb tmp1_7_XOR_tmp2_7 <= tmp1(7) XOR tmp2(7); add_msb <= tmp1_7_XOR_tmp2_7 XOR add_ms(3); -- find the carry bit cy_tmp1 <= (tmp1_7_XOR_tmp2_7 AND add_ms(3)) OR (tmp1(3) AND tmp2(3)); cy_tmp <= NOT cy_tmp1 WHEN std_match(data_alu,t1_cpl_val) ELSE cy_tmp1; -- ov represents (carry from bit 6 to 7) XOR (cy); ov_tmp <= cy_tmp XOR add_ms(3); ---- mmayer is ov correct? I think so. -- mimic the arithmatic and logic units arith_ans <= add_msb & add_ms(2 DOWNTO 0) & add_ls(3 DOWNTO 0) WHEN std_match(alu_cmd ,add_instr) ELSE unsigned(tmp1_post) AND unsigned(tmp2_post) WHEN std_match(data_alu,anl_instr) ELSE unsigned(tmp1_post) OR unsigned(tmp2_post) WHEN std_match(data_alu,orl_instr) ELSE unsigned(tmp1_post) XOR unsigned(tmp2_post) WHEN std_match(data_alu,xrl_instr) ELSE NOT unsigned(tmp2_post) WHEN std_match(data_alu,cpl_instr) ELSE unsigned(tmp2_post); -- need to do mul and div and da ------------- END ARITHMATIC & LOGIC -- write bits to psw cy_out <= bit_ans WHEN (bit_instr AND set_cy) = '1' ELSE cy_tmp WHEN set_cy = '1' ELSE cy; ac_out <= ac_tmp WHEN set_ac_ov = '1' ELSE ac; ov_out <= ov_tmp WHEN set_ac_ov = '1' ELSE ov; -- WHAT IS THIS NEXT LINE FOR? -- mrmayer -- wr_out <= done; end architecture spec;