diff options
Diffstat (limited to 'testsuite/vests/vhdl-93/ashenden/compliant/ch_15_ctrl-b.vhd')
-rw-r--r-- | testsuite/vests/vhdl-93/ashenden/compliant/ch_15_ctrl-b.vhd | 913 |
1 files changed, 913 insertions, 0 deletions
diff --git a/testsuite/vests/vhdl-93/ashenden/compliant/ch_15_ctrl-b.vhd b/testsuite/vests/vhdl-93/ashenden/compliant/ch_15_ctrl-b.vhd new file mode 100644 index 0000000..7f773c2 --- /dev/null +++ b/testsuite/vests/vhdl-93/ashenden/compliant/ch_15_ctrl-b.vhd @@ -0,0 +1,913 @@ + +-- Copyright (C) 1996 Morgan Kaufmann Publishers, Inc + +-- This file is part of VESTs (Vhdl tESTs). + +-- VESTs is free software; you can redistribute it and/or modify it +-- under the terms of the GNU General Public License as published by the +-- Free Software Foundation; either version 2 of the License, or (at +-- your option) any later version. + +-- VESTs is distributed in the hope that it will be useful, but WITHOUT +-- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +-- FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +-- for more details. + +-- You should have received a copy of the GNU General Public License +-- along with VESTs; if not, write to the Free Software Foundation, +-- Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +-- --------------------------------------------------------------------- +-- +-- $Id: ch_15_ctrl-b.vhd,v 1.3 2001-10-26 16:29:35 paw Exp $ +-- $Revision: 1.3 $ +-- +-- --------------------------------------------------------------------- + +library bv_utilities; +use bv_utilities.bv_arithmetic.all; + +library work; +use work.dlx_instr.all; + +architecture behavior of controller is + +begin -- behavior + + sequencer : process is + + variable current_instruction_bv : dlx_bv_word; + + alias IR_opcode : dlx_opcode is current_instruction_bv(0 to 5); + alias IR_sp_func : dlx_sp_func is current_instruction_bv(26 to 31); + alias IR_fp_func : dlx_fp_func is current_instruction_bv(27 to 31); + + alias IR_rs1 : reg_file_addr is current_instruction(6 to 10); + alias IR_rs2 : reg_file_addr is current_instruction(11 to 15); + alias IR_Itype_rd : reg_file_addr is current_instruction(11 to 15); + alias IR_Rtype_rd : reg_file_addr is current_instruction(16 to 20); + + variable result_of_set_is_1, branch_taken : boolean; + + variable disassembled_instr : string(1 to 40); + variable disassembled_instr_len : positive; + + variable instr_count : natural := 0; + + procedure bus_instruction_fetch is + begin + -- use PC as address + mem_addr_mux_sel <= '0' after Tpd_clk_ctrl; + -- set up memory control signals + width <= dlx_mem_width_word after Tpd_clk_ctrl; + ifetch <= '1' after Tpd_clk_ctrl; + write_enable <= '0' after Tpd_clk_ctrl; + mem_enable <= '1' after Tpd_clk_ctrl; + -- wait until phi2, then enable IR input + wait until rising_edge(phi2); + ir_latch_en <= '1' after Tpd_clk_ctrl; + -- wait until memory is ready at end of phi2 + loop + wait until falling_edge(phi2); + if To_bit(reset) = '1' then + return; + end if; + exit when To_bit(ready) = '1'; + end loop; + -- disable IR input and memory control signals + ir_latch_en <= '0' after Tpd_clk_ctrl; + mem_enable <= '0' after Tpd_clk_ctrl; + end procedure bus_instruction_fetch; + + procedure bus_data_read ( read_width : in dlx_mem_width ) is + begin + -- use MAR as address + mem_addr_mux_sel <= '1' after Tpd_clk_ctrl; + -- set up memory control signals + width <= read_width after Tpd_clk_ctrl; + ifetch <= '0' after Tpd_clk_ctrl; + write_enable <= '0' after Tpd_clk_ctrl; + mem_enable <= '1' after Tpd_clk_ctrl; + -- wait until phi2, then enable MDR input + wait until rising_edge(phi2); + mdr_mux_sel <= '1' after Tpd_clk_ctrl; + mdr_latch_en <= '1' after Tpd_clk_ctrl; + -- wait until memory is ready at end of phi2 + loop + wait until falling_edge(phi2); + if To_bit(reset) = '1' then + return; + end if; + exit when To_bit(ready) = '1'; + end loop; + -- disable MDR input and memory control signals + mdr_latch_en <= '0' after Tpd_clk_ctrl; + mem_enable <= '0' after Tpd_clk_ctrl; + end procedure bus_data_read; + + procedure bus_data_write ( write_width : in dlx_mem_width ) is + begin + -- use MAR as address + mem_addr_mux_sel <= '1' after Tpd_clk_ctrl; + -- enable MDR output + mdr_out_en3 <= '1' after Tpd_clk_ctrl; + -- set up memory control signals + width <= write_width after Tpd_clk_ctrl; + ifetch <= '0' after Tpd_clk_ctrl; + write_enable <= '1' after Tpd_clk_ctrl; + mem_enable <= '1' after Tpd_clk_ctrl; + -- wait until memory is ready at end of phi2 + loop + wait until falling_edge(phi2); + if To_bit(reset) = '1' then + return; + end if; + exit when To_bit(ready) = '1'; + end loop; + -- disable MDR output and memory control signals + write_enable <= '0' after Tpd_clk_ctrl; + mem_enable <= '0' after Tpd_clk_ctrl; + mdr_out_en3 <= '0' after Tpd_clk_ctrl; + end procedure bus_data_write; + + procedure do_set_result is + begin + wait until rising_edge(phi1); + if result_of_set_is_1 then + const2 <= X"0000_0001" after Tpd_clk_const; + else + const2 <= X"0000_0000" after Tpd_clk_const; + end if; + alu_in_latch_en <= '1' after Tpd_clk_ctrl; + alu_function <= alu_pass_s2 after Tpd_clk_ctrl; + + wait until falling_edge(phi1); + alu_in_latch_en <= '0' after Tpd_clk_ctrl; + const2 <= disabled_dlx_word after Tpd_clk_const; + + wait until rising_edge(phi2); + c_latch_en <= '1' after Tpd_clk_ctrl; + + wait until falling_edge(phi2); + c_latch_en <= '0' after Tpd_clk_ctrl; + end procedure do_set_result; + + procedure do_EX_set_unsigned ( immed : boolean ) is + begin + wait until rising_edge(phi1); + a_out_en <= '1' after Tpd_clk_ctrl; + if immed then + ir_immed2_size_26 <= '0' after Tpd_clk_ctrl; + ir_immed2_unsigned <= '1' after Tpd_clk_ctrl; + ir_immed2_en <= '1' after Tpd_clk_ctrl; + else + b_out_en <= '1' after Tpd_clk_ctrl; + end if; + alu_in_latch_en <= '1' after Tpd_clk_ctrl; + alu_function <= alu_subu after Tpd_clk_ctrl; + + wait until falling_edge(phi1); + alu_in_latch_en <= '0' after Tpd_clk_ctrl; + a_out_en <= '0' after Tpd_clk_ctrl; + if immed then + ir_immed2_en <= '0' after Tpd_clk_ctrl; + else + b_out_en <= '0' after Tpd_clk_ctrl; + end if; + + wait until falling_edge(phi2); + if immed then + case IR_opcode is + when op_sequi => + result_of_set_is_1 := To_bit(alu_zero) = '1'; + when op_sneui => + result_of_set_is_1 := To_bit(alu_zero) /= '1'; + when op_sltui => + result_of_set_is_1 := To_bit(alu_overflow) = '1'; + when op_sgtui => + result_of_set_is_1 := To_bit(alu_overflow) /= '1' and To_bit(alu_zero) /= '1'; + when op_sleui => + result_of_set_is_1 := To_bit(alu_overflow) = '1' or To_bit(alu_zero) = '1'; + when op_sgeui => + result_of_set_is_1 := To_bit(alu_overflow) /= '1'; + when others => + null; + end case; + else + case IR_sp_func is + when sp_func_sequ => + result_of_set_is_1 := To_bit(alu_zero) = '1'; + when sp_func_sneu => + result_of_set_is_1 := To_bit(alu_zero) /= '1'; + when sp_func_sltu => + result_of_set_is_1 := To_bit(alu_overflow) = '1'; + when sp_func_sgtu => + result_of_set_is_1 := To_bit(alu_overflow) /= '1' and To_bit(alu_zero) /= '1'; + when sp_func_sleu => + result_of_set_is_1 := To_bit(alu_overflow) = '1' or To_bit(alu_zero) = '1'; + when sp_func_sgeu => + result_of_set_is_1 := To_bit(alu_overflow) /= '1'; + when others => + null; + end case; + end if; + + do_set_result; + end procedure do_EX_set_unsigned; + + procedure do_EX_set_signed ( immed : boolean ) is + begin + wait until rising_edge(phi1); + a_out_en <= '1' after Tpd_clk_ctrl; + if immed then + ir_immed2_size_26 <= '0' after Tpd_clk_ctrl; + ir_immed2_unsigned <= '0' after Tpd_clk_ctrl; + ir_immed2_en <= '1' after Tpd_clk_ctrl; + else + b_out_en <= '1' after Tpd_clk_ctrl; + end if; + alu_in_latch_en <= '1' after Tpd_clk_ctrl; + alu_function <= alu_sub after Tpd_clk_ctrl; + + wait until falling_edge(phi1); + alu_in_latch_en <= '0' after Tpd_clk_ctrl; + a_out_en <= '0' after Tpd_clk_ctrl; + if immed then + ir_immed2_en <= '0' after Tpd_clk_ctrl; + else + b_out_en <= '0' after Tpd_clk_ctrl; + end if; + + wait until falling_edge(phi2); + if immed then + case IR_opcode is + when op_seqi => + result_of_set_is_1 := To_bit(alu_zero) = '1'; + when op_snei => + result_of_set_is_1 := To_bit(alu_zero) /= '1'; + when op_slti => + result_of_set_is_1 := To_bit(alu_negative) = '1'; + when op_sgti => + result_of_set_is_1 := To_bit(alu_negative) /= '1' and To_bit(alu_zero) /= '1'; + when op_slei => + result_of_set_is_1 := To_bit(alu_negative) = '1' or To_bit(alu_zero) = '1'; + when op_sgei => + result_of_set_is_1 := To_bit(alu_negative) /= '1'; + when others => + null; + end case; + else + case IR_sp_func is + when sp_func_seq => + result_of_set_is_1 := To_bit(alu_zero) = '1'; + when sp_func_sne => + result_of_set_is_1 := To_bit(alu_zero) /= '1'; + when sp_func_slt => + result_of_set_is_1 := To_bit(alu_negative) = '1'; + when sp_func_sgt => + result_of_set_is_1 := To_bit(alu_negative) /= '1' and To_bit(alu_zero) /= '1'; + when sp_func_sle => + result_of_set_is_1 := To_bit(alu_negative) = '1' or To_bit(alu_zero) = '1'; + when sp_func_sge => + result_of_set_is_1 := To_bit(alu_negative) /= '1'; + when others => + null; + end case; + end if; + + do_set_result; + end procedure do_EX_set_signed; + + procedure do_EX_arith_logic is + begin + wait until rising_edge(phi1); + a_out_en <= '1' after Tpd_clk_ctrl; + b_out_en <= '1' after Tpd_clk_ctrl; + alu_in_latch_en <= '1' after Tpd_clk_ctrl; + case IR_sp_func is + when sp_func_add => + alu_function <= alu_add after Tpd_clk_ctrl; + when sp_func_addu => + alu_function <= alu_addu after Tpd_clk_ctrl; + when sp_func_sub => + alu_function <= alu_sub after Tpd_clk_ctrl; + when sp_func_subu => + alu_function <= alu_subu after Tpd_clk_ctrl; + when sp_func_and => + alu_function <= alu_and after Tpd_clk_ctrl; + when sp_func_or => + alu_function <= alu_or after Tpd_clk_ctrl; + when sp_func_xor => + alu_function <= alu_xor after Tpd_clk_ctrl; + when sp_func_sll => + alu_function <= alu_sll after Tpd_clk_ctrl; + when sp_func_srl => + alu_function <= alu_srl after Tpd_clk_ctrl; + when sp_func_sra => + alu_function <= alu_sra after Tpd_clk_ctrl; + when others => + null; + end case; -- IR_sp_func + + wait until falling_edge(phi1); + alu_in_latch_en <= '0' after Tpd_clk_ctrl; + a_out_en <= '0' after Tpd_clk_ctrl; + b_out_en <= '0' after Tpd_clk_ctrl; + + wait until rising_edge(phi2); + c_latch_en <= '1' after Tpd_clk_ctrl; + + wait until falling_edge(phi2); + c_latch_en <= '0' after Tpd_clk_ctrl; + end procedure do_EX_arith_logic; + + procedure do_EX_arith_logic_immed is + begin + wait until rising_edge(phi1); + a_out_en <= '1' after Tpd_clk_ctrl; + ir_immed2_size_26 <= '0' after Tpd_clk_ctrl; + if IR_opcode = op_addi or IR_opcode = op_subi then + ir_immed2_unsigned <= '0' after Tpd_clk_ctrl; + else + ir_immed2_unsigned <= '1' after Tpd_clk_ctrl; + end if; + ir_immed2_en <= '1' after Tpd_clk_ctrl; + alu_in_latch_en <= '1' after Tpd_clk_ctrl; + case IR_opcode is + when op_addi => + alu_function <= alu_add after Tpd_clk_ctrl; + when op_subi => + alu_function <= alu_sub after Tpd_clk_ctrl; + when op_addui => + alu_function <= alu_addu after Tpd_clk_ctrl; + when op_subui => + alu_function <= alu_subu after Tpd_clk_ctrl; + when op_andi => + alu_function <= alu_and after Tpd_clk_ctrl; + when op_ori => + alu_function <= alu_or after Tpd_clk_ctrl; + when op_xori => + alu_function <= alu_xor after Tpd_clk_ctrl; + when op_slli => + alu_function <= alu_sll after Tpd_clk_ctrl; + when op_srli => + alu_function <= alu_srl after Tpd_clk_ctrl; + when op_srai => + alu_function <= alu_sra after Tpd_clk_ctrl; + when others => + null; + end case; -- IR_opcode + + wait until falling_edge(phi1); + alu_in_latch_en <= '0' after Tpd_clk_ctrl; + a_out_en <= '0' after Tpd_clk_ctrl; + ir_immed2_en <= '0' after Tpd_clk_ctrl; + + wait until rising_edge(phi2); + c_latch_en <= '1' after Tpd_clk_ctrl; + + wait until falling_edge(phi2); + c_latch_en <= '0' after Tpd_clk_ctrl; + end procedure do_EX_arith_logic_immed; + + procedure do_EX_link is + begin + wait until rising_edge(phi1); + pc_out_en1 <= '1' after Tpd_clk_ctrl; + alu_in_latch_en <= '1' after Tpd_clk_ctrl; + alu_function <= alu_pass_s1 after Tpd_clk_ctrl; + + wait until falling_edge(phi1); + alu_in_latch_en <= '0' after Tpd_clk_ctrl; + pc_out_en1 <= '0' after Tpd_clk_ctrl; + + wait until rising_edge(phi2); + c_latch_en <= '1' after Tpd_clk_ctrl; + + wait until falling_edge(phi2); + c_latch_en <= '0' after Tpd_clk_ctrl; + end procedure do_EX_link; + + procedure do_EX_lhi is + begin + wait until rising_edge(phi1); + ir_immed1_size_26 <= '0' after Tpd_clk_ctrl; + ir_immed1_unsigned <= '1' after Tpd_clk_ctrl; + ir_immed1_en <= '1' after Tpd_clk_ctrl; + const2 <= X"0000_0010" after Tpd_clk_const; -- shift by 16 bits + alu_in_latch_en <= '1' after Tpd_clk_ctrl; + alu_function <= alu_sll after Tpd_clk_ctrl; + + wait until falling_edge(phi1); + alu_in_latch_en <= '0' after Tpd_clk_ctrl; + ir_immed1_en <= '0' after Tpd_clk_ctrl; + const2 <= disabled_dlx_word after Tpd_clk_const; + + wait until rising_edge(phi2); + c_latch_en <= '1' after Tpd_clk_ctrl; + + wait until falling_edge(phi2); + c_latch_en <= '0' after Tpd_clk_ctrl; + end procedure do_EX_lhi; + + procedure do_EX_branch is + begin + wait until rising_edge(phi1); + a_out_en <= '1' after Tpd_clk_ctrl; + alu_in_latch_en <= '1' after Tpd_clk_ctrl; + alu_function <= alu_pass_s1 after Tpd_clk_ctrl; + + wait until falling_edge(phi1); + alu_in_latch_en <= '0' after Tpd_clk_ctrl; + a_out_en <= '0' after Tpd_clk_ctrl; + + wait until falling_edge(phi2); + if IR_opcode = op_beqz then + branch_taken := To_bit(alu_zero) = '1'; + else + branch_taken := To_bit(alu_zero) /= '1'; + end if; + end procedure do_EX_branch; + + procedure do_EX_load_store is + begin + wait until rising_edge(phi1); + a_out_en <= '1' after Tpd_clk_ctrl; + ir_immed2_size_26 <= '0' after Tpd_clk_ctrl; + ir_immed2_unsigned <= '0' after Tpd_clk_ctrl; + ir_immed2_en <= '1' after Tpd_clk_ctrl; + alu_function <= alu_add after Tpd_clk_ctrl; + alu_in_latch_en <= '1' after Tpd_clk_ctrl; + + wait until falling_edge(phi1); + alu_in_latch_en <= '0' after Tpd_clk_ctrl; + a_out_en <= '0' after Tpd_clk_ctrl; + ir_immed2_en <= '0' after Tpd_clk_ctrl; + + wait until rising_edge(phi2); + mar_latch_en <= '1' after Tpd_clk_ctrl; + + wait until falling_edge(phi2); + mar_latch_en <= '0' after Tpd_clk_ctrl; + end procedure do_EX_load_store; + + procedure do_MEM_jump is + begin + wait until rising_edge(phi1); + pc_out_en1 <= '1' after Tpd_clk_ctrl; + ir_immed2_size_26 <= '1' after Tpd_clk_ctrl; + ir_immed2_unsigned <= '0' after Tpd_clk_ctrl; + ir_immed2_en <= '1' after Tpd_clk_ctrl; + alu_in_latch_en <= '1' after Tpd_clk_ctrl; + alu_function <= alu_add after Tpd_clk_ctrl; + + wait until falling_edge(phi1); + alu_in_latch_en <= '0' after Tpd_clk_ctrl; + pc_out_en1 <= '0' after Tpd_clk_ctrl; + ir_immed2_en <= '0' after Tpd_clk_ctrl; + + wait until rising_edge(phi2); + pc_latch_en <= '1' after Tpd_clk_ctrl; + + wait until falling_edge(phi2); + pc_latch_en <= '0' after Tpd_clk_ctrl; + end procedure do_MEM_jump; + + procedure do_MEM_jump_reg is + begin + wait until rising_edge(phi1); + a_out_en <= '1' after Tpd_clk_ctrl; + alu_in_latch_en <= '1' after Tpd_clk_ctrl; + alu_function <= alu_pass_s1 after Tpd_clk_ctrl; + + wait until falling_edge(phi1); + alu_in_latch_en <= '0' after Tpd_clk_ctrl; + a_out_en <= '0' after Tpd_clk_ctrl; + + wait until rising_edge(phi2); + pc_latch_en <= '1' after Tpd_clk_ctrl; + + wait until falling_edge(phi2); + pc_latch_en <= '0' after Tpd_clk_ctrl; + end procedure do_MEM_jump_reg; + + procedure do_MEM_branch is + begin + wait until rising_edge(phi1); + pc_out_en1 <= '1' after Tpd_clk_ctrl; + ir_immed2_size_26 <= '0' after Tpd_clk_ctrl; + ir_immed2_unsigned <= '0' after Tpd_clk_ctrl; + ir_immed2_en <= '1' after Tpd_clk_ctrl; + alu_in_latch_en <= '1' after Tpd_clk_ctrl; + alu_function <= alu_add after Tpd_clk_ctrl; + + wait until falling_edge(phi1); + alu_in_latch_en <= '0' after Tpd_clk_ctrl; + pc_out_en1 <= '0' after Tpd_clk_ctrl; + ir_immed2_en <= '0' after Tpd_clk_ctrl; + + wait until rising_edge(phi2); + pc_latch_en <= '1' after Tpd_clk_ctrl; + + wait until falling_edge(phi2); + pc_latch_en <= '0' after Tpd_clk_ctrl; + end procedure do_MEM_branch; + + procedure do_MEM_load is + subtype ls_2_addr_bits is bit_vector(1 downto 0); + begin + wait until rising_edge(phi1); + if IR_opcode = op_lb or IR_opcode = op_lbu then + bus_data_read(dlx_mem_width_byte); + elsif IR_opcode = op_lh or IR_opcode = op_lhu then + bus_data_read(dlx_mem_width_halfword); + else + bus_data_read(dlx_mem_width_word); + end if; + if To_bit(reset) = '1' then + return; + end if; + + if ( (IR_opcode = op_lb or IR_opcode = op_lbu) and To_bitvector(mem_addr) /= "00" ) + or ( (IR_opcode = op_lh or IR_opcode = op_lhu) and To_bit(mem_addr(1)) /= '0' ) then + -- first step of extension: left-justify byte or halfword -> mdr + wait until rising_edge(phi1); + mdr_out_en1 <= '1' after Tpd_clk_ctrl; + if IR_opcode = op_lb or IR_opcode = op_lbu then + case ls_2_addr_bits'(To_bitvector(mem_addr)) is + when "00" => + null; + when "01" => + const2 <= X"0000_0008" after Tpd_clk_const; + when "10" => + const2 <= X"0000_0010" after Tpd_clk_const; + when "11" => + const2 <= X"0000_0018" after Tpd_clk_const; + end case; + else + const2 <= X"0000_0010" after Tpd_clk_const; + end if; + alu_function <= alu_sll after Tpd_clk_ctrl; + alu_in_latch_en <= '1' after Tpd_clk_ctrl; + + wait until falling_edge(phi1); + mdr_out_en1 <= '0' after Tpd_clk_ctrl; + const2 <= disabled_dlx_word after Tpd_clk_const; + alu_in_latch_en <= '0' after Tpd_clk_ctrl; + + wait until rising_edge(phi2); + mdr_mux_sel <= '0' after Tpd_clk_ctrl; + mdr_latch_en <= '1' after Tpd_clk_ctrl; + + wait until falling_edge(phi2); + mdr_latch_en <= '0' after Tpd_clk_ctrl; + end if; + + wait until rising_edge(phi1); + mdr_out_en1 <= '1' after Tpd_clk_ctrl; + if IR_opcode = op_lb or IR_opcode = op_lbu then + const2 <= X"0000_0018" after Tpd_clk_const; + elsif IR_opcode = op_lh or IR_opcode = op_lhu then + const2 <= X"0000_0010" after Tpd_clk_const; + else + const2 <= X"0000_0000" after Tpd_clk_const; + end if; + if IR_opcode = op_lbu or IR_opcode = op_lhu then + alu_function <= alu_srl after Tpd_clk_ctrl; + else + alu_function <= alu_sra after Tpd_clk_ctrl; + end if; + alu_in_latch_en <= '1' after Tpd_clk_ctrl; + + wait until falling_edge(phi1); + mdr_out_en1 <= '0' after Tpd_clk_ctrl; + const2 <= disabled_dlx_word after Tpd_clk_const; + alu_in_latch_en <= '0' after Tpd_clk_ctrl; + + wait until rising_edge(phi2); + c_latch_en <= '1' after Tpd_clk_ctrl; + + wait until falling_edge(phi2); + c_latch_en <= '0' after Tpd_clk_ctrl; + end procedure do_MEM_load; + + procedure do_MEM_store is + subtype ls_2_addr_bits is bit_vector(1 downto 0); + begin + wait until rising_edge(phi1); + b_out_en <= '1' after Tpd_clk_ctrl; + alu_function <= alu_pass_s2 after Tpd_clk_ctrl; + alu_in_latch_en <= '1' after Tpd_clk_ctrl; + + wait until falling_edge(phi1); + b_out_en <= '0' after Tpd_clk_ctrl; + alu_in_latch_en <= '0' after Tpd_clk_ctrl; + + wait until rising_edge(phi2); + mdr_mux_sel <= '0' after Tpd_clk_ctrl; + mdr_latch_en <= '1' after Tpd_clk_ctrl; + + wait until falling_edge(phi2); + mdr_latch_en <= '0' after Tpd_clk_ctrl; + + if ( IR_opcode = op_sb and To_bitvector(mem_addr) /= "11" ) + or ( IR_opcode = op_sh and To_bit(mem_addr(1)) /= '1' ) then + -- align byte or halfword -> mdr + wait until rising_edge(phi1); + mdr_out_en1 <= '1' after Tpd_clk_ctrl; + if IR_opcode = op_sb then + case ls_2_addr_bits'(To_bitvector(mem_addr)) is + when "00" => + const2 <= X"0000_0018" after Tpd_clk_const; + when "01" => + const2 <= X"0000_0010" after Tpd_clk_const; + when "10" => + const2 <= X"0000_0008" after Tpd_clk_const; + when "11" => + null; + end case; + else + const2 <= X"0000_0010" after Tpd_clk_const; + end if; + alu_function <= alu_sll after Tpd_clk_ctrl; + alu_in_latch_en <= '1' after Tpd_clk_ctrl; + + wait until falling_edge(phi1); + mdr_out_en1 <= '0' after Tpd_clk_ctrl; + const2 <= disabled_dlx_word after Tpd_clk_const; + alu_in_latch_en <= '0' after Tpd_clk_ctrl; + + wait until rising_edge(phi2); + mdr_mux_sel <= '0' after Tpd_clk_ctrl; + mdr_latch_en <= '1' after Tpd_clk_ctrl; + + wait until falling_edge(phi2); + mdr_latch_en <= '0' after Tpd_clk_ctrl; + end if; + + wait until rising_edge(phi1); + if IR_opcode = op_sb then + bus_data_write(dlx_mem_width_byte); + elsif IR_opcode = op_sh then + bus_data_write(dlx_mem_width_halfword); + else + bus_data_write(dlx_mem_width_word); + end if; + end procedure do_MEM_store; + + procedure do_WB ( Rd : reg_file_addr ) is + begin + wait until rising_edge(phi1); + reg_dest_addr <= Rd after Tpd_clk_ctrl; + reg_write <= '1' after Tpd_clk_ctrl; + + wait until falling_edge(phi2); + reg_write <= '0' after Tpd_clk_ctrl; + end procedure do_WB; + + procedure execute_op_special is + begin + case IR_sp_func is + when sp_func_nop => + null; + when sp_func_add | sp_func_addu | sp_func_sub | sp_func_subu + | sp_func_sll | sp_func_srl | sp_func_sra + | sp_func_and | sp_func_or | sp_func_xor => + do_EX_arith_logic; + do_WB(IR_Rtype_rd); + when sp_func_sequ | sp_func_sneu | sp_func_sltu + | sp_func_sgtu | sp_func_sleu | sp_func_sgeu => + do_EX_set_unsigned(immed => false); + do_WB(IR_Rtype_rd); + when sp_func_seq | sp_func_sne | sp_func_slt + | sp_func_sgt | sp_func_sle | sp_func_sge => + do_EX_set_signed(immed => false); + do_WB(IR_Rtype_rd); + when sp_func_movi2s | sp_func_movs2i + | sp_func_movf | sp_func_movd + | sp_func_movfp2i | sp_func_movi2fp => + report sp_func_names(bv_to_natural(IR_sp_func)) + & " instruction not implemented" severity warning; + when others => + report "undefined special instruction function" severity error; + end case; + end procedure execute_op_special; + + procedure execute_op_fparith is + begin + case IR_fp_func is + when fp_func_mult | fp_func_multu | fp_func_div | fp_func_divu + | fp_func_addf | fp_func_subf | fp_func_multf | fp_func_divf + | fp_func_addd | fp_func_subd | fp_func_multd | fp_func_divd + | fp_func_cvtf2d | fp_func_cvtf2i | fp_func_cvtd2f + | fp_func_cvtd2i | fp_func_cvti2f | fp_func_cvti2d + | fp_func_eqf | fp_func_nef | fp_func_ltf | fp_func_gtf + | fp_func_lef | fp_func_gef | fp_func_eqd | fp_func_ned + | fp_func_ltd | fp_func_gtd | fp_func_led | fp_func_ged => + report fp_func_names(bv_to_natural(IR_fp_func)) + & " instruction not implemented" severity warning; + when others => + report "undefined floating point instruction function" severity error; + end case; + end procedure execute_op_fparith; + + begin -- sequencer + + ---------------------------------------------------------------- + -- initialize all control signals + ---------------------------------------------------------------- + if debug > none then + report "initializing"; + end if; + + halt <= '0' after Tpd_clk_ctrl; + width <= dlx_mem_width_word after Tpd_clk_ctrl; + write_enable <= '0' after Tpd_clk_ctrl; + mem_enable <= '0' after Tpd_clk_ctrl; + ifetch <= '0' after Tpd_clk_ctrl; + alu_in_latch_en <= '0' after Tpd_clk_ctrl; + alu_function <= alu_add after Tpd_clk_ctrl; + reg_s1_addr <= B"00000" after Tpd_clk_ctrl; + reg_s2_addr <= B"00000" after Tpd_clk_ctrl; + reg_dest_addr <= B"00000" after Tpd_clk_ctrl; + reg_write <= '0' after Tpd_clk_ctrl; + c_latch_en <= '0' after Tpd_clk_ctrl; + a_latch_en <= '0' after Tpd_clk_ctrl; + a_out_en <= '0' after Tpd_clk_ctrl; + b_latch_en <= '0' after Tpd_clk_ctrl; + b_out_en <= '0' after Tpd_clk_ctrl; + temp_latch_en <= '0' after Tpd_clk_ctrl; + temp_out_en1 <= '0' after Tpd_clk_ctrl; + temp_out_en2 <= '0' after Tpd_clk_ctrl; + iar_latch_en <= '0' after Tpd_clk_ctrl; + iar_out_en1 <= '0' after Tpd_clk_ctrl; + iar_out_en2 <= '0' after Tpd_clk_ctrl; + pc_latch_en <= '0' after Tpd_clk_ctrl; + pc_out_en1 <= '0' after Tpd_clk_ctrl; + pc_out_en2 <= '0' after Tpd_clk_ctrl; + mar_latch_en <= '0' after Tpd_clk_ctrl; + mar_out_en1 <= '0' after Tpd_clk_ctrl; + mar_out_en2 <= '0' after Tpd_clk_ctrl; + mem_addr_mux_sel <= '0' after Tpd_clk_ctrl; + mdr_latch_en <= '0' after Tpd_clk_ctrl; + mdr_out_en1 <= '0' after Tpd_clk_ctrl; + mdr_out_en2 <= '0' after Tpd_clk_ctrl; + mdr_out_en3 <= '0' after Tpd_clk_ctrl; + mdr_mux_sel <= '0' after Tpd_clk_ctrl; + ir_latch_en <= '0' after Tpd_clk_ctrl; + ir_immed1_size_26 <= '0' after Tpd_clk_ctrl; + ir_immed2_size_26 <= '0' after Tpd_clk_ctrl; + ir_immed2_unsigned <= '0' after Tpd_clk_ctrl; + ir_immed2_unsigned <= '0' after Tpd_clk_ctrl; + ir_immed1_en <= '0' after Tpd_clk_ctrl; + ir_immed2_en <= '0' after Tpd_clk_ctrl; + const1 <= disabled_dlx_word after Tpd_clk_const; + const2 <= disabled_dlx_word after Tpd_clk_const; + + instr_count := 0; + + wait on phi2 until falling_edge(phi2) and To_bit(reset) = '0'; + + ---------------------------------------------------------------- + -- control loop + ---------------------------------------------------------------- + loop + exit when To_bit(reset) = '1'; + + ---------------------------------------------------------------- + -- fetch next instruction (IF) + ---------------------------------------------------------------- + wait until rising_edge(phi1); + + instr_count := instr_count + 1; + if debug = msg_every_100_instructions and instr_count mod 100 = 0 then + report "instruction count = " & natural'image(instr_count); + end if; + + if debug >= msg_each_instruction then + report "fetching instruction"; + end if; + + bus_instruction_fetch; + exit when To_bit(reset) = '1'; + current_instruction_bv := To_bitvector(current_instruction); + + if debug >= trace_each_instruction then + disassemble(current_instruction_bv, disassembled_instr, disassembled_instr_len); + report disassembled_instr(1 to disassembled_instr_len); + end if; + + ---------------------------------------------------------------- + -- instruction decode, source register read and PC increment (ID) + ---------------------------------------------------------------- + wait until rising_edge(phi1); + + if debug = trace_each_step then + report "decode, source register read and PC increment"; + end if; + + reg_s1_addr <= IR_rs1 after Tpd_clk_ctrl; + reg_s2_addr <= IR_rs2 after Tpd_clk_ctrl; + a_latch_en <= '1' after Tpd_clk_ctrl; + b_latch_en <= '1' after Tpd_clk_ctrl; + + pc_out_en1 <= '1' after Tpd_clk_ctrl; + const2 <= X"0000_0004" after Tpd_clk_const; + alu_in_latch_en <= '1' after Tpd_clk_ctrl; + alu_function <= alu_addu after Tpd_clk_ctrl; + + wait until falling_edge(phi1); + a_latch_en <= '0' after Tpd_clk_ctrl; + b_latch_en <= '0' after Tpd_clk_ctrl; + alu_in_latch_en <= '0' after Tpd_clk_ctrl; + pc_out_en1 <= '0' after Tpd_clk_ctrl; + const2 <= disabled_dlx_word after Tpd_clk_const; + + wait until rising_edge(phi2); + pc_latch_en <= '1' after Tpd_clk_ctrl; + + wait until falling_edge(phi2); + pc_latch_en <= '0' after Tpd_clk_ctrl; + + ---------------------------------------------------------------- + -- execute instruction, (EX, MEM, WB) + ---------------------------------------------------------------- + if debug = trace_each_step then + report "execute"; + end if; + + case IR_opcode is + when op_special => + execute_op_special; + when op_fparith => + execute_op_fparith; + when op_j => + do_MEM_jump; + when op_jal => + do_EX_link; + do_MEM_jump; + do_WB(To_X01(natural_to_bv(link_reg, 5))); + when op_jr => + do_MEM_jump_reg; + when op_jalr => + do_EX_link; + do_MEM_jump_reg; + do_WB(To_X01(natural_to_bv(link_reg, 5))); + when op_beqz | op_bnez => + do_EX_branch; + if branch_taken then + do_MEM_branch; + end if; + when op_addi | op_subi | op_addui | op_subui + | op_slli | op_srli | op_srai + | op_andi | op_ori | op_xori => + do_EX_arith_logic_immed; + do_WB(IR_Itype_rd); + when op_lhi => + do_EX_lhi; + do_WB(IR_Itype_rd); + when op_sequi | op_sneui | op_sltui + | op_sgtui | op_sleui | op_sgeui => + do_EX_set_unsigned(immed => true); + do_WB(IR_Itype_rd); + when op_seqi | op_snei | op_slti + | op_sgti | op_slei | op_sgei => + do_EX_set_signed(immed => true); + do_WB(IR_Itype_rd); + when op_trap => + report "TRAP instruction encountered, execution halted" + severity note; + wait until rising_edge(phi1); + halt <= '1' after Tpd_clk_ctrl; + wait until reset = '1'; + exit; + when op_lb | op_lh | op_lw | op_lbu | op_lhu => + do_EX_load_store; + do_MEM_load; + exit when reset = '1'; + do_WB(IR_Itype_rd); + when op_sb | op_sh | op_sw => + do_EX_load_store; + do_MEM_store; + exit when reset = '1'; + when op_rfe | op_bfpt | op_bfpf | op_lf | op_ld | op_sf | op_sd => + report opcode_names(bv_to_natural(IR_opcode)) + & " instruction not implemented" severity warning; + when others => + report "undefined instruction" severity error; + end case; + + -- overflow and divide-by-zero exception handing + -- (not implemented) + + if debug = trace_each_step then + report "end of execution"; + end if; + + end loop; + -- loop is only exited when reset active: + -- process interpreter starts again from beginning + end process sequencer; + + +end architecture behavior; |