summaryrefslogtreecommitdiff
path: root/testsuite/vests/vhdl-93/ashenden/compliant/ch_15_ctrl-b.vhd
diff options
context:
space:
mode:
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.vhd913
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;