-------------------------------------------------------------------------- -------------------------------------------------------------------------- -- File Name : fm8501.v -- Author(s) : Nand Kumar and Ranjan Prasad -- Affiliation : Laboratory for Digital Design Environments -- Department of Electrical & Computer Engineering -- University of Cincinnati -- Date Created : June 1991 -- Introduction : Behavioral description of FM8501, a 16-bit -- microprocessor. -- Source : Textual description obtained from ---- -- W. A. Hunt Jr., -- "FM8501: A Verified Microprocessor", -- Tech Rep 47, Institute for Computing Science, -- Univ of Texas at Austin, -- Feb 1986. -- -- -- Modified For Synthesis by Jay(anta) Roy, University of Cincinnati. -- Date Modified : Sept, 91. -- -- Disclaimer : This comes with absolutely no guarantees of any -- kind (just stating the obvious ...) -- -- Acknowledgement : The Distributed Synthesis Systems research at -- the Laboratory for Digital Design Environments, -- University of Cincinnati, is sponsored in part -- by the Defense Advanced Research Projects Agency -- under order number 7056 monitored by the Federal -- Bureau of Investigation under contract number -- J-FBI-89-094. -- -------------------------------------------------------------------------- -------------------------------------------------------------------------- package types is type Reg_file is array (0 to 7) of Bit_vector (15 downto 0); end types; use work.types.all; use work.functions.all; entity fm8501 is port (reset, dtack : in Bit; data_in : in Bit_vector (15 downto 0); data_out : out Bit_vector (15 downto 0); read, write : out Bit; addr_out : out Bit_vector (15 downto 0)); end fm8501; architecture Behavior of fm8501 is signal R : Reg_file := ( "0000000000000000", "0000000000000001", "0000000000011111", "0000000000000011", "0000000000000100", "0000000000000101", "0000000000000110", "0000000000000111"); alias PC : Bit_vector (15 downto 0) is R(0); signal c_flag, v_flag, n_flag, z_flag : Bit := '0'; signal zero : Bit_vector (15 downto 0) := "0000000000000000"; signal one : Bit_vector (15 downto 0) := "0000000000000001"; signal update_sig, continue_sig : Bit; begin decode : process variable mode_a : Bit_vector (1 downto 0); variable mode_b : Bit_vector (1 downto 0); variable reg_a : Bit_vector (2 downto 0); variable reg_b : Bit_vector (2 downto 0); variable op_code : Bit_vector (3 downto 0); variable move_bit : Bit; variable cc_bit : Bit; alias sig_mode_a : Bit_vector (1 downto 0) is data_in(4 downto 3); alias sig_mode_b : Bit_vector (1 downto 0) is data_in(9 downto 8); alias sig_reg_a : Bit_vector (2 downto 0) is data_in(2 downto 0); alias sig_reg_b : Bit_vector (2 downto 0) is data_in(7 downto 5); alias sig_op_code: Bit_vector (3 downto 0) is data_in(15 downto 12); alias sig_move_bit : Bit is data_in(11); alias sig_cc_bit : Bit is data_in(10); variable op_a, op_b : Bit_vector (15 downto 0); variable int_a, int_b : INTEGER; variable result : Bit_vector (15 downto 0); variable move_it : integer; variable sub_add_res : Bit_vector(16 downto 0); alias part_res :Bit_vector(15 downto 0) is sub_add_res(15 downto 0); alias carry_part : Bit is sub_add_res(16); alias rt_part : Bit_vector (14 downto 0) is result(15 downto 1); alias zero_bit : Bit is result(0); variable fifteen_zero : Bit_vector (14 downto 0):="000000000000000"; variable sixty_g : Bit_vector (15 downto 0) := "1000000000000000"; begin -- beginning of process if reset = '1' then PC <= zero; else read <= '1'; addr_out <= PC; wait on dtack until dtack = '1'; read <= '0'; wait for 1 ns; move_it := 0; mode_a := sig_mode_a; mode_b := sig_mode_b; reg_a := sig_reg_a; reg_b := sig_reg_b; op_code := sig_op_code; move_bit := sig_move_bit; cc_bit := sig_cc_bit; int_a := bits_to_int(reg_a); int_b := bits_to_int(reg_b); case mode_a is when "00" => op_a := R(int_a); when "01" => addr_out <= R(int_a); read <= '1'; wait on dtack until dtack = '1'; op_a := data_in; read <= '0'; when "10" => sub_add_res := R(int_a) - one; R(int_a) <= part_res; addr_out <= part_res; read <= '1'; wait on dtack until dtack = '1'; op_a := data_in; read <= '0'; when "11" => addr_out <= R(int_a); read <= '1'; sub_add_res := R(int_a) + one; R(int_a) <= part_res; wait on dtack until dtack = '1'; op_a := data_in; read <= '0'; end case; wait for 1 ns; case mode_b is when "00" => op_b := R(int_b); when "01" => addr_out <= R(int_b); read <= '1'; wait on dtack until dtack = '1'; op_b := data_in; read <= '0'; when "10" => sub_add_res := R(int_b) - one; R(int_b) <= part_res; addr_out <= part_res; read <= '1'; wait on dtack until dtack = '1'; op_b := data_in; read <= '0'; when "11" => addr_out <= R(int_b); read <= '1'; sub_add_res := R(int_b) + one; R(int_b) <= part_res; wait on dtack until dtack = '1'; op_b := data_in; read <= '0'; end case; wait for 1 ns; -- the execute part of the code case move_bit is when '0' => case op_code is when "0000" => result := op_a; when "0001" => sub_add_res := op_a + one; result := part_res; if cc_bit = '1' then v_flag <= carry_part; c_flag <= carry_part; end if; when "0010" => sub_add_res := op_b + op_a; if c_flag = '1' then sub_add_res := sub_add_res + one; end if; result := part_res; if cc_bit = '1' then v_flag <= carry_part; c_flag <= carry_part; end if; when "0011" => sub_add_res := op_a + op_b; result := part_res; if cc_bit = '1' then v_flag <= carry_part; c_flag <= carry_part; end if; when "0100" => sub_add_res := zero - op_a; result := part_res; if cc_bit = '1' then c_flag <= carry_part; n_flag <= carry_part; if result = zero then z_flag <= '1'; else z_flag <= '0'; end if; end if; when "0101" => sub_add_res := op_a - one; result := part_res; if cc_bit = '1' then c_flag <= carry_part; n_flag <= carry_part; if result = zero then z_flag <= '1'; else z_flag <= '0'; end if; end if; when "0110" => sub_add_res := op_b - op_a; if c_flag = '1' then sub_add_res := sub_add_res - one; end if; result := part_res; if cc_bit = '1' then c_flag <= carry_part; n_flag <= carry_part; if result = zero then z_flag <= '1'; else z_flag <= '0'; end if; end if; when "0111" => sub_add_res := op_b - op_a; result := part_res; if cc_bit = '1' then c_flag <= carry_part; n_flag <= carry_part; if result = zero then z_flag <= '1'; else z_flag <= '0'; end if; end if; when "1000" => result := op_a; result := rt_part + fifteen_zero; if c_flag = '1' then sub_add_res := sixty_g + result; result := part_res; end if; if zero_bit = '1' then c_flag <= '1'; else c_flag <= '0'; end if; when "1001" => result := op_a; result := rt_part + rt_part; when "1010" => result := op_a; result := rt_part + fifteen_zero; when "1011" => result := (op_a and (not op_b)) or ((not op_a) and op_b); when "1100" => result := op_a or op_b; when "1101" => result := op_a and op_b; when "1110" => result := not op_a; when "1111" => result := op_a; end case; move_it := 1; when '1' => case op_code is when "0000" => if c_flag = '0' then result := op_a; move_it := 1; end if; when "0001" => if c_flag = '1' then result := op_a; move_it := 1; end if; when "0010" => if v_flag = '0' then result := op_a; move_it := 1; end if; when "0011" => if v_flag = '1' then result := op_a; move_it := 1; end if; when "0100" => if z_flag = '0' then result := op_a; move_it := 1; end if; when "0101" => if z_flag = '1' then result := op_a; move_it := 1; end if; when "0110" => if n_flag = '0' then result := op_a; move_it := 1; end if; when "0111" => if n_flag = '1' then result := op_a; move_it := 1; end if; when "1111" => wait; when others => result := op_a; move_it := 1; end case; end case; wait for 1 ns; if move_it = 1 then case mode_b is when "00" => R(int_b) <= result; when others => data_out <= result; addr_out <= R(int_b); write <= '1'; wait on dtack until dtack = '1'; write <= '0'; end case; end if; wait for 1 ns; sub_add_res := PC + one; PC <= part_res; end if; -- update_sig <= '1', '0' after 1 ns; update_sig <= '1'; wait for 1 ns; update_sig <= '0'; wait on reset, continue_sig until reset = '1' or continue_sig = '1'; end process; update_pc : process begin -- continue_sig <= '1', '0' after 1 ns; continue_sig <= '1'; wait for 1 ns; continue_sig <= '0' after 1 ns; wait on update_sig until update_sig = '1'; end process; end Behavior;