From bdb8fec295753a2aca306db05409d8eaa7c81fc0 Mon Sep 17 00:00:00 2001 From: Jens Ahrensfeld Date: Sun, 21 Mar 2021 11:37:55 +0000 Subject: [PATCH] - added git-svn-id: http://moon:8086/svn/vhdl/trunk@1424 cc03376c-175c-47c8-b038-4cd826a8556b --- projects/dlx/dlx.tar.gz | Bin 0 -> 38256 bytes projects/dlx/make.sh | 9 + projects/dlx/src/README | 48 + projects/dlx/src/__DISCLAIMER.TXT | 38 + projects/dlx/src/__README.TXT | 38 + projects/dlx/src/alu-behaviour.vhdl | 81 ++ projects/dlx/src/alu.vhdl | 45 + projects/dlx/src/alu_types.vhdl | 39 + projects/dlx/src/bv_arithmetic-body.vhdl | 982 +++++++++++++++ projects/dlx/src/bv_arithmetic.vhdl | 238 ++++ projects/dlx/src/bv_test-bench.vhdl | 1121 +++++++++++++++++ projects/dlx/src/bv_test.vhdl | 36 + projects/dlx/src/cache-behaviour.vhdl | 310 +++++ projects/dlx/src/cache.vhdl | 61 + projects/dlx/src/cache_types.vhdl | 36 + projects/dlx/src/clock_gen-behaviour.vhdl | 48 + projects/dlx/src/clock_gen.vhdl | 42 + projects/dlx/src/clock_gen_test-bench.vhdl | 50 + projects/dlx/src/clock_gen_test.vhdl | 33 + projects/dlx/src/controller-behaviour.vhdl | 858 +++++++++++++ projects/dlx/src/controller.vhdl | 71 ++ projects/dlx/src/distribution-manifest | 63 + projects/dlx/src/dlx-behaviour.vhdl | 614 +++++++++ projects/dlx/src/dlx-instrumented.vhdl | 687 ++++++++++ projects/dlx/src/dlx-rtl.vhdl | 286 +++++ projects/dlx/src/dlx.vhdl | 50 + .../dlx/src/dlx_bus_monitor-behaviour.vhdl | 171 +++ projects/dlx/src/dlx_bus_monitor.vhdl | 50 + projects/dlx/src/dlx_instr-body.vhdl | 258 ++++ projects/dlx/src/dlx_instr.vhdl | 257 ++++ projects/dlx/src/dlx_test-bench.vhdl | 104 ++ projects/dlx/src/dlx_test-bench_cache.vhdl | 139 ++ projects/dlx/src/dlx_test.vhdl | 33 + projects/dlx/src/dlx_test_behaviour.vhdl | 59 + projects/dlx/src/dlx_test_cache.vhdl | 74 ++ projects/dlx/src/dlx_test_instrumented.vhdl | 60 + projects/dlx/src/dlx_test_rtl.vhdl | 103 ++ projects/dlx/src/dlx_types-body.vhdl | 45 + projects/dlx/src/dlx_types.vhdl | 44 + projects/dlx/src/images-body.vhdl | 167 +++ projects/dlx/src/images.vhdl | 61 + projects/dlx/src/images_test-bench.vhdl | 89 ++ projects/dlx/src/images_test.vhdl | 35 + projects/dlx/src/ir-behaviour.vhdl | 88 ++ projects/dlx/src/ir.vhdl | 46 + projects/dlx/src/latch-behaviour.vhdl | 43 + projects/dlx/src/latch.vhdl | 41 + projects/dlx/src/mem_types.vhdl | 36 + projects/dlx/src/memory-behaviour.vhdl | 226 ++++ projects/dlx/src/memory.vhdl | 54 + projects/dlx/src/memory_test-bench.vhdl | 330 +++++ projects/dlx/src/memory_test.vhdl | 33 + projects/dlx/src/module-directory | 158 +++ projects/dlx/src/mux2-behaviour.vhdl | 37 + projects/dlx/src/mux2.vhdl | 41 + projects/dlx/src/reg_1_out-behaviour.vhdl | 51 + projects/dlx/src/reg_1_out.vhdl | 42 + projects/dlx/src/reg_2_1_out-behaviour.vhdl | 58 + projects/dlx/src/reg_2_1_out.vhdl | 44 + projects/dlx/src/reg_2_out-behaviour.vhdl | 56 + projects/dlx/src/reg_2_out.vhdl | 42 + projects/dlx/src/reg_3_out-behaviour.vhdl | 61 + projects/dlx/src/reg_3_out.vhdl | 42 + projects/dlx/src/reg_file-behaviour.vhdl | 76 ++ projects/dlx/src/reg_file.vhdl | 46 + projects/dlx/src/simple.out | 2 + projects/dlx/src/simple.s | 3 + projects/dlx/src/test_loop.out | 6 + projects/dlx/src/test_loop.s | 10 + projects/dlx/syn/ise/project/controller.prj | 5 + projects/dlx/syn/ise/project/controller.xst | 4 + .../dlx/syn/ise/project/controller_vhdl.prj | 5 + projects/dlx/syn/ise/project/dlx.fdo | 14 + projects/dlx/syn/ise/project/dlx.lso | 1 + projects/dlx/syn/ise/project/dlx.prj | 3 + projects/dlx/syn/ise/project/dlx.udo | 4 + projects/dlx/syn/ise/project/dlx.xst | 55 + projects/dlx/syn/ise/project/dlx_test.fdo | 19 + projects/dlx/syn/ise/project/dlx_test.lso | 1 + projects/dlx/syn/ise/project/dlx_test.prj | 28 + projects/dlx/syn/ise/project/dlx_test.xst | 4 + .../dlx/syn/ise/project/dlx_test_vhdl.prj | 28 + projects/dlx/syn/ise/project/prjname.lso | 1 + 83 files changed, 9477 insertions(+) create mode 100644 projects/dlx/dlx.tar.gz create mode 100644 projects/dlx/make.sh create mode 100644 projects/dlx/src/README create mode 100644 projects/dlx/src/__DISCLAIMER.TXT create mode 100644 projects/dlx/src/__README.TXT create mode 100644 projects/dlx/src/alu-behaviour.vhdl create mode 100644 projects/dlx/src/alu.vhdl create mode 100644 projects/dlx/src/alu_types.vhdl create mode 100644 projects/dlx/src/bv_arithmetic-body.vhdl create mode 100644 projects/dlx/src/bv_arithmetic.vhdl create mode 100644 projects/dlx/src/bv_test-bench.vhdl create mode 100644 projects/dlx/src/bv_test.vhdl create mode 100644 projects/dlx/src/cache-behaviour.vhdl create mode 100644 projects/dlx/src/cache.vhdl create mode 100644 projects/dlx/src/cache_types.vhdl create mode 100644 projects/dlx/src/clock_gen-behaviour.vhdl create mode 100644 projects/dlx/src/clock_gen.vhdl create mode 100644 projects/dlx/src/clock_gen_test-bench.vhdl create mode 100644 projects/dlx/src/clock_gen_test.vhdl create mode 100644 projects/dlx/src/controller-behaviour.vhdl create mode 100644 projects/dlx/src/controller.vhdl create mode 100644 projects/dlx/src/distribution-manifest create mode 100644 projects/dlx/src/dlx-behaviour.vhdl create mode 100644 projects/dlx/src/dlx-instrumented.vhdl create mode 100644 projects/dlx/src/dlx-rtl.vhdl create mode 100644 projects/dlx/src/dlx.vhdl create mode 100644 projects/dlx/src/dlx_bus_monitor-behaviour.vhdl create mode 100644 projects/dlx/src/dlx_bus_monitor.vhdl create mode 100644 projects/dlx/src/dlx_instr-body.vhdl create mode 100644 projects/dlx/src/dlx_instr.vhdl create mode 100644 projects/dlx/src/dlx_test-bench.vhdl create mode 100644 projects/dlx/src/dlx_test-bench_cache.vhdl create mode 100644 projects/dlx/src/dlx_test.vhdl create mode 100644 projects/dlx/src/dlx_test_behaviour.vhdl create mode 100644 projects/dlx/src/dlx_test_cache.vhdl create mode 100644 projects/dlx/src/dlx_test_instrumented.vhdl create mode 100644 projects/dlx/src/dlx_test_rtl.vhdl create mode 100644 projects/dlx/src/dlx_types-body.vhdl create mode 100644 projects/dlx/src/dlx_types.vhdl create mode 100644 projects/dlx/src/images-body.vhdl create mode 100644 projects/dlx/src/images.vhdl create mode 100644 projects/dlx/src/images_test-bench.vhdl create mode 100644 projects/dlx/src/images_test.vhdl create mode 100644 projects/dlx/src/ir-behaviour.vhdl create mode 100644 projects/dlx/src/ir.vhdl create mode 100644 projects/dlx/src/latch-behaviour.vhdl create mode 100644 projects/dlx/src/latch.vhdl create mode 100644 projects/dlx/src/mem_types.vhdl create mode 100644 projects/dlx/src/memory-behaviour.vhdl create mode 100644 projects/dlx/src/memory.vhdl create mode 100644 projects/dlx/src/memory_test-bench.vhdl create mode 100644 projects/dlx/src/memory_test.vhdl create mode 100644 projects/dlx/src/module-directory create mode 100644 projects/dlx/src/mux2-behaviour.vhdl create mode 100644 projects/dlx/src/mux2.vhdl create mode 100644 projects/dlx/src/reg_1_out-behaviour.vhdl create mode 100644 projects/dlx/src/reg_1_out.vhdl create mode 100644 projects/dlx/src/reg_2_1_out-behaviour.vhdl create mode 100644 projects/dlx/src/reg_2_1_out.vhdl create mode 100644 projects/dlx/src/reg_2_out-behaviour.vhdl create mode 100644 projects/dlx/src/reg_2_out.vhdl create mode 100644 projects/dlx/src/reg_3_out-behaviour.vhdl create mode 100644 projects/dlx/src/reg_3_out.vhdl create mode 100644 projects/dlx/src/reg_file-behaviour.vhdl create mode 100644 projects/dlx/src/reg_file.vhdl create mode 100644 projects/dlx/src/simple.out create mode 100644 projects/dlx/src/simple.s create mode 100644 projects/dlx/src/test_loop.out create mode 100644 projects/dlx/src/test_loop.s create mode 100644 projects/dlx/syn/ise/project/controller.prj create mode 100644 projects/dlx/syn/ise/project/controller.xst create mode 100644 projects/dlx/syn/ise/project/controller_vhdl.prj create mode 100644 projects/dlx/syn/ise/project/dlx.fdo create mode 100644 projects/dlx/syn/ise/project/dlx.lso create mode 100644 projects/dlx/syn/ise/project/dlx.prj create mode 100644 projects/dlx/syn/ise/project/dlx.udo create mode 100644 projects/dlx/syn/ise/project/dlx.xst create mode 100644 projects/dlx/syn/ise/project/dlx_test.fdo create mode 100644 projects/dlx/syn/ise/project/dlx_test.lso create mode 100644 projects/dlx/syn/ise/project/dlx_test.prj create mode 100644 projects/dlx/syn/ise/project/dlx_test.xst create mode 100644 projects/dlx/syn/ise/project/dlx_test_vhdl.prj create mode 100644 projects/dlx/syn/ise/project/prjname.lso diff --git a/projects/dlx/dlx.tar.gz b/projects/dlx/dlx.tar.gz new file mode 100644 index 0000000000000000000000000000000000000000..6444e44966501595533c4f18d50d6adf893b1e31 GIT binary patch literal 38256 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 + temp_result := stored_s1; + when alu_pass_s2 => + temp_result := stored_s2; + when alu_and => + temp_result := stored_s1 and stored_s2; + when alu_or => + temp_result := stored_s1 or stored_s2; + when alu_xor => + temp_result := stored_s1 xor stored_s2; + when alu_sll => + temp_result := bv_sll(stored_s1, bv_to_natural(stored_s2(27 to 31))); + when alu_srl => + temp_result := bv_srl(stored_s1, bv_to_natural(stored_s2(27 to 31))); + when alu_sra => + temp_result := bv_sra(stored_s1, bv_to_natural(stored_s2(27 to 31))); + when alu_add => + bv_add(stored_s1, stored_s2, temp_result, temp_overflow); + when alu_addu => + bv_addu(stored_s1, stored_s2, temp_result, temp_overflow); + when alu_sub => + bv_sub(stored_s1, stored_s2, temp_result, temp_overflow); + when alu_subu => + bv_subu(stored_s1, stored_s2, temp_result, temp_overflow); + end case; + result <= temp_result after Tpd; + zero <= bit'val(boolean'pos(temp_result = dlx_word'(X"0000_0000"))) after Tpd; + negative <= temp_result(0) after Tpd; + overflow <= bit'val(boolean'pos(temp_overflow)) after Tpd; + end process alu_op; + +end behaviour; diff --git a/projects/dlx/src/alu.vhdl b/projects/dlx/src/alu.vhdl new file mode 100644 index 0000000..24bc4f1 --- /dev/null +++ b/projects/dlx/src/alu.vhdl @@ -0,0 +1,45 @@ +-------------------------------------------------------------------------- +-- +-- Copyright (C) 1993, Peter J. Ashenden +-- Mail: Dept. Computer Science +-- University of Adelaide, SA 5005, Australia +-- e-mail: petera@cs.adelaide.edu.au +-- +-- This program 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 1, or (at your option) +-- any later version. +-- +-- This program 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 this program; if not, write to the Free Software +-- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +-- +-------------------------------------------------------------------------- +-- +-- $RCSfile: alu.vhdl,v $ $Revision: 2.1 $ $Date: 1993/11/02 18:50:25 $ +-- +-------------------------------------------------------------------------- +-- +-- Entity declaration for ALU. +-- + + +use work.dlx_types.all, + work.alu_types.all; + +entity alu is + generic (Tpd : Time; + tag : string := ""; + origin_x, origin_y : real := 0.0); + port (s1 : in dlx_word; + s2 : in dlx_word; + result : out dlx_word; + latch_en : in bit; + func : in alu_func; + zero, negative, overflow : out bit); +end alu; diff --git a/projects/dlx/src/alu_types.vhdl b/projects/dlx/src/alu_types.vhdl new file mode 100644 index 0000000..b31ff2d --- /dev/null +++ b/projects/dlx/src/alu_types.vhdl @@ -0,0 +1,39 @@ +-------------------------------------------------------------------------- +-- +-- Copyright (C) 1993, Peter J. Ashenden +-- Mail: Dept. Computer Science +-- University of Adelaide, SA 5005, Australia +-- e-mail: petera@cs.adelaide.edu.au +-- +-- This program 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 1, or (at your option) +-- any later version. +-- +-- This program 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 this program; if not, write to the Free Software +-- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +-- +-------------------------------------------------------------------------- +-- +-- $RCSfile: alu_types.vhdl,v $ $Revision: 2.1 $ $Date: 1993/11/02 18:48:41 $ +-- +-------------------------------------------------------------------------- +-- +-- Package defining types for ALU. +-- + + +package alu_types is + + type alu_func is (alu_add, alu_addu, alu_sub, alu_subu, + alu_and, alu_or, alu_xor, + alu_sll, alu_srl, alu_sra, + alu_pass_s1, alu_pass_s2); + +end alu_types; diff --git a/projects/dlx/src/bv_arithmetic-body.vhdl b/projects/dlx/src/bv_arithmetic-body.vhdl new file mode 100644 index 0000000..81524da --- /dev/null +++ b/projects/dlx/src/bv_arithmetic-body.vhdl @@ -0,0 +1,982 @@ +-------------------------------------------------------------------------- +-- +-- Copyright (C) 1993, Peter J. Ashenden +-- Mail: Dept. Computer Science +-- University of Adelaide, SA 5005, Australia +-- e-mail: petera@cs.adelaide.edu.au +-- +-- This program 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 1, or (at your option) +-- any later version. +-- +-- This program 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 this program; if not, write to the Free Software +-- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +-- +-------------------------------------------------------------------------- +-- +-- $RCSfile: bv_arithmetic-body.vhdl,v $ $Revision: 2.1 $ $Date: 1993/11/02 22:50:39 $ +-- +-------------------------------------------------------------------------- +-- +-- Bit vector arithmetic package body. +-- +-- Does arithmetic and logical operations on bit vectors, treating them +-- as either unsigned or signed (2's complement) integers. Leftmost bit +-- is most significant or sign bit, rightmost bit is least significant +-- bit. Dyadic operations need the two arguments to be of the same +-- length, however their index ranges and directions may differ. Results +-- must be of the same length as the operands. +-- +-------------------------------------------------------------------------- + +package body bv_arithmetic is + + ---------------------------------------------------------------- + -- Type conversions + ---------------------------------------------------------------- + + ---------------------------------------------------------------- + -- bv_to_natural + -- + -- Convert bit vector encoded unsigned integer to natural. + ---------------------------------------------------------------- + + function bv_to_natural(bv : in bit_vector) return natural is + + variable result : natural := 0; + + begin + for index in bv'range loop + result := result * 2 + bit'pos(bv(index)); + end loop; + return result; + end bv_to_natural; + + + ---------------------------------------------------------------- + -- natural_to_bv + -- + -- Convert natural to bit vector encoded unsigned integer. + -- (length is used as the size of the result.) + ---------------------------------------------------------------- + + function natural_to_bv(nat : in natural; + length : in natural) return bit_vector is + + variable temp : natural := nat; + variable result : bit_vector(0 to length-1); + + begin + for index in result'reverse_range loop + result(index) := bit'val(temp rem 2); + temp := temp / 2; + end loop; + return result; + end natural_to_bv; + + + ---------------------------------------------------------------- + -- bv_to_integer + -- + -- Convert bit vector encoded signed integer to integer + ---------------------------------------------------------------- + + function bv_to_integer(bv : in bit_vector) return integer is + + variable temp : bit_vector(bv'range); + variable result : integer := 0; + + begin + if bv(bv'left) = '1' then -- negative number + temp := not bv; + else + temp := bv; + end if; + for index in bv'range loop -- sign bit of temp = '0' + result := result * 2 + bit'pos(temp(index)); + end loop; + if bv(bv'left) = '1' then + result := (-result) - 1; + end if; + return result; + end bv_to_integer; + + + ---------------------------------------------------------------- + -- integer_to_bv + -- + -- Convert integer to bit vector encoded signed integer. + -- (length is used as the size of the result.) + ---------------------------------------------------------------- + + function integer_to_bv(int : in integer; + length : in natural) return bit_vector is + + variable temp : integer; + variable result : bit_vector(0 to length-1); + + begin + if int < 0 then + temp := -(int+1); + else + temp := int; + end if; + for index in result'reverse_range loop + result(index) := bit'val(temp rem 2); + temp := temp / 2; + end loop; + if int < 0 then + result := not result; + result(result'left) := '1'; + end if; + return result; + end integer_to_bv; + + + ---------------------------------------------------------------- + -- Arithmetic operations + ---------------------------------------------------------------- + + ---------------------------------------------------------------- + -- bv_add + -- + -- Signed addition with overflow detection + ---------------------------------------------------------------- + + procedure bv_add (bv1, bv2 : in bit_vector; + bv_result : out bit_vector; + overflow : out boolean) is + + alias op1 : bit_vector(1 to bv1'length) is bv1; + alias op2 : bit_vector(1 to bv2'length) is bv2; + variable result : bit_vector(1 to bv_result'length); + variable carry_in : bit; + variable carry_out : bit := '0'; + + begin + assert bv1'length = bv2'length and bv1'length = bv_result'length + report "bv_add: operands of different lengths" + severity failure; + for index in result'reverse_range loop + carry_in := carry_out; -- of previous bit + result(index) := op1(index) xor op2(index) xor carry_in; + carry_out := (op1(index) and op2(index)) + or (carry_in and (op1(index) xor op2(index))); + end loop; + bv_result := result; + overflow := carry_out /= carry_in; + end bv_add; + + + ---------------------------------------------------------------- + -- "+" + -- + -- Signed addition without overflow detection + ---------------------------------------------------------------- + + function "+" (bv1, bv2 : in bit_vector) return bit_vector is + + alias op1 : bit_vector(1 to bv1'length) is bv1; + alias op2 : bit_vector(1 to bv2'length) is bv2; + variable result : bit_vector(1 to bv1'length); + variable carry_in : bit; + variable carry_out : bit := '0'; + + begin + assert bv1'length = bv2'length + -- use concatenation to work around Synthesia MINT code gen bug + report '"' & '+' & '"' & ": operands of different lengths" + severity failure; + for index in result'reverse_range loop + carry_in := carry_out; -- of previous bit + result(index) := op1(index) xor op2(index) xor carry_in; + carry_out := (op1(index) and op2(index)) + or (carry_in and (op1(index) xor op2(index))); + end loop; + return result; + end "+"; + + + ---------------------------------------------------------------- + -- bv_sub + -- + -- Signed subtraction with overflow detection + ---------------------------------------------------------------- + + procedure bv_sub (bv1, bv2 : in bit_vector; + bv_result : out bit_vector; + overflow : out boolean) is + + -- subtraction implemented by adding ((not bv2) + 1), ie -bv2 + + alias op1 : bit_vector(1 to bv1'length) is bv1; + alias op2 : bit_vector(1 to bv2'length) is bv2; + variable result : bit_vector(1 to bv_result'length); + variable carry_in : bit; + variable carry_out : bit := '1'; + + begin + assert bv1'length = bv2'length and bv1'length = bv_result'length + report "bv_sub: operands of different lengths" + severity failure; + for index in result'reverse_range loop + carry_in := carry_out; -- of previous bit + result(index) := op1(index) xor (not op2(index)) xor carry_in; + carry_out := (op1(index) and (not op2(index))) + or (carry_in and (op1(index) xor (not op2(index)))); + end loop; + bv_result := result; + overflow := carry_out /= carry_in; + end bv_sub; + + + ---------------------------------------------------------------- + -- "-" + -- + -- Signed subtraction without overflow detection + ---------------------------------------------------------------- + + function "-" (bv1, bv2 : in bit_vector) return bit_vector is + + -- subtraction implemented by adding ((not bv2) + 1), ie -bv2 + + alias op1 : bit_vector(1 to bv1'length) is bv1; + alias op2 : bit_vector(1 to bv2'length) is bv2; + variable result : bit_vector(1 to bv1'length); + variable carry_in : bit; + variable carry_out : bit := '1'; + + begin + assert bv1'length = bv2'length + -- use concatenation to work around Synthesia MINT code gen bug + report '"' & '-' & '"' & ": operands of different lengths" + severity failure; + for index in result'reverse_range loop + carry_in := carry_out; -- of previous bit + result(index) := op1(index) xor (not op2(index)) xor carry_in; + carry_out := (op1(index) and (not op2(index))) + or (carry_in and (op1(index) xor (not op2(index)))); + end loop; + return result; + end "-"; + + + ---------------------------------------------------------------- + -- bv_addu + -- + -- Unsigned addition with overflow detection + ---------------------------------------------------------------- + + procedure bv_addu (bv1, bv2 : in bit_vector; + bv_result : out bit_vector; + overflow : out boolean) is + + alias op1 : bit_vector(1 to bv1'length) is bv1; + alias op2 : bit_vector(1 to bv2'length) is bv2; + variable result : bit_vector(1 to bv_result'length); + variable carry : bit := '0'; + + begin + assert bv1'length = bv2'length and bv1'length = bv_result'length + report "bv_addu: operands of different lengths" + severity failure; + for index in result'reverse_range loop + result(index) := op1(index) xor op2(index) xor carry; + carry := (op1(index) and op2(index)) + or (carry and (op1(index) xor op2(index))); + end loop; + bv_result := result; + overflow := carry = '1'; + end bv_addu; + + + ---------------------------------------------------------------- + -- bv_addu + -- + -- Unsigned addition without overflow detection + ---------------------------------------------------------------- + + procedure bv_addu (bv1, bv2 : in bit_vector; + bv_result : out bit_vector) is + + alias op1 : bit_vector(1 to bv1'length) is bv1; + alias op2 : bit_vector(1 to bv2'length) is bv2; + variable result : bit_vector(1 to bv_result'length); + variable carry : bit := '0'; + + begin + assert bv1'length = bv2'length and bv1'length = bv_result'length + report "bv_addu: operands of different lengths" + severity failure; + for index in result'reverse_range loop + result(index) := op1(index) xor op2(index) xor carry; + carry := (op1(index) and op2(index)) + or (carry and (op1(index) xor op2(index))); + end loop; + bv_result := result; + end bv_addu; + + + ---------------------------------------------------------------- + -- bv_subu + -- + -- Unsigned subtraction with overflow detection + ---------------------------------------------------------------- + + procedure bv_subu (bv1, bv2 : in bit_vector; + bv_result : out bit_vector; + overflow : out boolean) is + + alias op1 : bit_vector(1 to bv1'length) is bv1; + alias op2 : bit_vector(1 to bv2'length) is bv2; + variable result : bit_vector(1 to bv_result'length); + variable borrow : bit := '0'; + + begin + assert bv1'length = bv2'length and bv1'length = bv_result'length + report "bv_subu: operands of different lengths" + severity failure; + for index in result'reverse_range loop + result(index) := op1(index) xor op2(index) xor borrow; + borrow := (not op1(index) and op2(index)) + or (borrow and not (op1(index) xor op2(index))); + end loop; + bv_result := result; + overflow := borrow = '1'; + end bv_subu; + + + ---------------------------------------------------------------- + -- bv_subu + -- + -- Unsigned subtraction without overflow detection + ---------------------------------------------------------------- + + procedure bv_subu (bv1, bv2 : in bit_vector; + bv_result : out bit_vector) is + + alias op1 : bit_vector(1 to bv1'length) is bv1; + alias op2 : bit_vector(1 to bv2'length) is bv2; + variable result : bit_vector(1 to bv_result'length); + variable borrow : bit := '0'; + + begin + assert bv1'length = bv2'length and bv1'length = bv_result'length + report "bv_subu: operands of different lengths" + severity failure; + for index in result'reverse_range loop + result(index) := op1(index) xor op2(index) xor borrow; + borrow := (not op1(index) and op2(index)) + or (borrow and not (op1(index) xor op2(index))); + end loop; + bv_result := result; + end bv_subu; + + + ---------------------------------------------------------------- + -- bv_neg + -- + -- Signed negation with overflow detection + ---------------------------------------------------------------- + + procedure bv_neg (bv : in bit_vector; + bv_result : out bit_vector; + overflow : out boolean) is + + CONSTANT zero : bit_vector(bv'range) := (others => '0'); + + begin + bv_sub( zero, bv, bv_result, overflow ); + end bv_neg; + + + ---------------------------------------------------------------- + -- "-" + -- + -- Signed negation without overflow detection + ---------------------------------------------------------------- + + function "-" (bv : in bit_vector) return bit_vector is + + CONSTANT zero : bit_vector(bv'range) := (others => '0'); + + begin + return zero - bv; + end "-"; + + + ---------------------------------------------------------------- + -- bv_mult + -- + -- Signed multiplication with overflow detection + ---------------------------------------------------------------- + + procedure bv_mult (bv1, bv2 : in bit_vector; + bv_result : out bit_vector; + overflow : out boolean) is + + variable negative_result : boolean; + variable op1 : bit_vector(bv1'range) := bv1; + variable op2 : bit_vector(bv2'range) := bv2; + variable multu_result : bit_vector(bv1'range); + variable multu_overflow : boolean; + -- constant abs_min_int : bit_vector(bv1'range) + -- := (bv1'left => '1', others => '0'); + -- causes Synthesia MINT code generator to prang. Work around: + variable abs_min_int : bit_vector(bv1'range) := (others => '0'); + + begin + assert bv1'length = bv2'length and bv1'length = bv_result'length + report "bv_mult: operands of different lengths" + severity failure; + abs_min_int(bv1'left) := '1'; -- Synthesia work around + negative_result := (op1(op1'left) = '1') xor (op2(op2'left) = '1'); + if (op1(op1'left) = '1') then + op1 := - bv1; + end if; + if (op2(op2'left) = '1') then + op2 := - bv2; + end if; + bv_multu(op1, op2, multu_result, multu_overflow); + if (negative_result) then + overflow := multu_overflow or (multu_result > abs_min_int); + bv_result := - multu_result; + else + overflow := multu_overflow or (multu_result(multu_result'left) = '1'); + bv_result := multu_result; + end if; + end bv_mult; + + + ---------------------------------------------------------------- + -- "*" + -- + -- Signed multiplication without overflow detection + ---------------------------------------------------------------- + + function "*" (bv1, bv2 : in bit_vector) return bit_vector is + + variable negative_result : boolean; + variable op1 : bit_vector(bv1'range) := bv1; + variable op2 : bit_vector(bv2'range) := bv2; + variable result : bit_vector(bv1'range); + + begin + assert bv1'length = bv2'length + -- use concatenation to work around Synthesia MINT code gen bug + report '"' & '*' & '"' & ": operands of different lengths" + severity failure; + negative_result := (op1(op1'left) = '1') xor (op2(op2'left) = '1'); + if (op1(op1'left) = '1') then + op1 := - bv1; + end if; + if (op2(op2'left) = '1') then + op2 := - bv2; + end if; + bv_multu(op1, op2, result); + if (negative_result) then + result := - result; + end if; + return result; + end "*"; + + + ---------------------------------------------------------------- + -- bv_multu + -- + -- Unsigned multiplication with overflow detection + ---------------------------------------------------------------- + + procedure bv_multu (bv1, bv2 : in bit_vector; + bv_result : out bit_vector; + overflow : out boolean) is + + -- Based on shift&add multiplier in Appendix A of Hennessy & Patterson + + constant bv_length : natural := bv1'length; + constant accum_length : natural := bv_length * 2; + constant zero : bit_vector(accum_length-1 downto bv_length) + := (others => '0'); + variable accum : bit_vector(accum_length-1 downto 0); + variable addu_overflow : boolean; + variable carry : bit; + + begin + assert bv1'length = bv2'length and bv1'length = bv_result'length + report "bv_multu: operands of different lengths" + severity failure; + accum(bv_length-1 downto 0) := bv1; + accum(accum_length-1 downto bv_length) := zero; + for count in 1 to bv_length loop + if (accum(0) = '1') then + bv_addu( accum(accum_length-1 downto bv_length), bv2, + accum(accum_length-1 downto bv_length), addu_overflow); + carry := bit'val(boolean'pos(addu_overflow)); + else + carry := '0'; + end if; + accum := carry & accum(accum_length-1 downto 1); + end loop; + bv_result := accum(bv_length-1 downto 0); + overflow := accum(accum_length-1 downto bv_length) /= zero; + end bv_multu; + + + ---------------------------------------------------------------- + -- bv_multu + -- + -- Unsigned multiplication without overflow detection + ---------------------------------------------------------------- + + procedure bv_multu (bv1, bv2 : in bit_vector; + bv_result : out bit_vector) is + + -- Use bv_multu with overflow detection, but ignore overflow flag + + variable tmp_overflow : boolean; + + begin + -- following procedure asserts bv1'length = bv2'length + bv_multu(bv1, bv2, bv_result, tmp_overflow); + end bv_multu; + + + ---------------------------------------------------------------- + -- bv_div + -- + -- Signed division with divide by zero and overflow detection + ---------------------------------------------------------------- + + procedure bv_div (bv1, bv2 : in bit_vector; + bv_result : out bit_vector; + div_by_zero : out boolean; + overflow : out boolean) is + + -- Need overflow, in case divide b"10...0" (min_int) by -1 + -- Don't use bv_to_int, in case size bigger than host machine! + + variable negative_result : boolean; + variable op1 : bit_vector(bv1'range) := bv1; + variable op2 : bit_vector(bv2'range) := bv2; + variable divu_result : bit_vector(bv1'range); + + begin + assert bv1'length = bv2'length + report "bv_div: operands of different lengths" + severity failure; + negative_result := (op1(op1'left) = '1') xor (op2(op2'left) = '1'); + if (op1(op1'left) = '1') then + op1 := - bv1; + end if; + if (op2(op2'left) = '1') then + op2 := - bv2; + end if; + bv_divu(op1, op2, divu_result, div_by_zero); + if (negative_result) then + overflow := false; + bv_result := - divu_result; + else + overflow := divu_result(divu_result'left) = '1'; + bv_result := divu_result; + end if; + end bv_div; + + + ---------------------------------------------------------------- + -- "/" + -- + -- Signed division without divide by zero and overflow detection + ---------------------------------------------------------------- + + function "/" (bv1, bv2 : in bit_vector) return bit_vector is + + variable negative_result : boolean; + variable op1 : bit_vector(bv1'range) := bv1; + variable op2 : bit_vector(bv2'range) := bv2; + variable result : bit_vector(bv1'range); + + begin + assert bv1'length = bv2'length + -- use concatenation to work around Synthesia MINT code gen bug + report '"' & '/' & '"' & ": operands of different lengths" + severity failure; + negative_result := (op1(op1'left) = '1') xor (op2(op2'left) = '1'); + if (op1(op1'left) = '1') then + op1 := - bv1; + end if; + if (op2(op2'left) = '1') then + op2 := - bv2; + end if; + bv_divu(op1, op2, result); + if (negative_result) then + result := - result; + end if; + return result; + end "/"; + + + ---------------------------------------------------------------- + -- bv_divu + -- + -- Unsigned division with divide by zero detection + ---------------------------------------------------------------- + + procedure bv_divu (bv1, bv2 : in bit_vector; + bv_result : out bit_vector; + div_by_zero : out boolean) is + + -- based on algorithm in Sun Sparc architecture manual + + constant len : natural := bv1'length; + variable zero, one, + big_value : bit_vector(len-1 downto 0) + := (others => '0'); + variable dividend : bit_vector(bv1'length-1 downto 0) := bv1; + variable divisor : bit_vector(bv2'length-1 downto 0) := bv2; + variable quotient : bit_vector(len-1 downto 0); -- unsigned + variable remainder : bit_vector(len-1 downto 0); -- signed + variable shifted_divisor, + shifted_1 : bit_vector(len-1 downto 0); + variable log_quotient : natural; + variable ignore_overflow : boolean; + + begin + assert bv1'length = bv2'length + report "bv_divu: operands of different lengths" + severity failure; + one(0) := '1'; + big_value(len-2) := '1'; + -- + -- check for zero divisor + -- + if (divisor = zero) then + div_by_zero := true; + return; + end if; + -- + -- estimate log of quotient + -- + log_quotient := 0; + shifted_divisor := divisor; + loop + exit when (log_quotient >= len) + or (shifted_divisor > big_value) + or (shifted_divisor >= dividend); + log_quotient := log_quotient + 1; + shifted_divisor := bv_sll(shifted_divisor, 1); + end loop; + -- + -- perform division + -- + remainder := dividend; + quotient := zero; + shifted_divisor := bv_sll(divisor, log_quotient); + shifted_1 := bv_sll(one, log_quotient); + for iter in log_quotient downto 0 loop + if bv_ge(remainder, zero) then + bv_sub(remainder, shifted_divisor, remainder, ignore_overflow); + bv_addu(quotient, shifted_1, quotient, ignore_overflow); + else + bv_add(remainder, shifted_divisor, remainder, ignore_overflow); + bv_subu(quotient, shifted_1, quotient, ignore_overflow); + end if; + shifted_divisor := '0' & shifted_divisor(len-1 downto 1); + shifted_1 := '0' & shifted_1(len-1 downto 1); + end loop; + if (bv_lt(remainder, zero)) then + bv_add(remainder, divisor, remainder, ignore_overflow); + bv_subu(quotient, one, quotient, ignore_overflow); + end if; + bv_result := quotient; + end bv_divu; + + + ---------------------------------------------------------------- + -- bv_divu + -- + -- Unsigned division without divide by zero detection + ---------------------------------------------------------------- + + procedure bv_divu (bv1, bv2 : in bit_vector; + bv_result : out bit_vector) is + + -- Use bv_divu with divide by zero detection, + -- but ignore div_by_zero flag + + variable tmp_div_by_zero : boolean; + + begin + -- following procedure asserts bv1'length = bv2'length + bv_divu(bv1, bv2, bv_result, tmp_div_by_zero); + end bv_divu; + + + ---------------------------------------------------------------- + -- Logical operators + -- (Provided for VHDL-87, built in for VHDL-93) + ---------------------------------------------------------------- + + ---------------------------------------------------------------- + -- bv_sll + -- + -- Shift left logical (fill with '0' bits) + ---------------------------------------------------------------- + + function bv_sll (bv : in bit_vector; + shift_count : in natural) return bit_vector is + + constant bv_length : natural := bv'length; + constant actual_shift_count : natural := shift_count mod bv_length; + alias bv_norm : bit_vector(1 to bv_length) is bv; + variable result : bit_vector(1 to bv_length) := (others => '0'); + + begin + result(1 to bv_length - actual_shift_count) + := bv_norm(actual_shift_count + 1 to bv_length); + return result; + end bv_sll; + + + ---------------------------------------------------------------- + -- bv_srl + -- + -- Shift right logical (fill with '0' bits) + ---------------------------------------------------------------- + + function bv_srl (bv : in bit_vector; + shift_count : in natural) return bit_vector is + + constant bv_length : natural := bv'length; + constant actual_shift_count : natural := shift_count mod bv_length; + alias bv_norm : bit_vector(1 to bv_length) is bv; + variable result : bit_vector(1 to bv_length) := (others => '0'); + + begin + result(actual_shift_count + 1 to bv_length) + := bv_norm(1 to bv_length - actual_shift_count); + return result; + end bv_srl; + + + ---------------------------------------------------------------- + -- bv_sra + -- + -- Shift right arithmetic (fill with copy of sign bit) + ---------------------------------------------------------------- + + + function bv_sra (bv : in bit_vector; + shift_count : in natural) return bit_vector is + + constant bv_length : natural := bv'length; + constant actual_shift_count : natural := shift_count mod bv_length; + alias bv_norm : bit_vector(1 to bv_length) is bv; + variable result : bit_vector(1 to bv_length) := (others => bv(bv'left)); + + begin + result(actual_shift_count + 1 to bv_length) + := bv_norm(1 to bv_length - actual_shift_count); + return result; + end bv_sra; + + + ---------------------------------------------------------------- + -- bv_rol + -- + -- Rotate left + ---------------------------------------------------------------- + + function bv_rol (bv : in bit_vector; + rotate_count : in natural) return bit_vector is + + constant bv_length : natural := bv'length; + constant actual_rotate_count : natural := rotate_count mod bv_length; + alias bv_norm : bit_vector(1 to bv_length) is bv; + variable result : bit_vector(1 to bv_length); + + begin + result(1 to bv_length - actual_rotate_count) + := bv_norm(actual_rotate_count + 1 to bv_length); + result(bv_length - actual_rotate_count + 1 to bv_length) + := bv_norm(1 to actual_rotate_count); + return result; + end bv_rol; + + + ---------------------------------------------------------------- + -- bv_ror + -- + -- Rotate right + ---------------------------------------------------------------- + + function bv_ror (bv : in bit_vector; + rotate_count : in natural) return bit_vector is + + constant bv_length : natural := bv'length; + constant actual_rotate_count : natural := rotate_count mod bv_length; + alias bv_norm : bit_vector(1 to bv_length) is bv; + variable result : bit_vector(1 to bv_length); + + begin + result(actual_rotate_count + 1 to bv_length) + := bv_norm(1 to bv_length - actual_rotate_count); + result(1 to actual_rotate_count) + := bv_norm(bv_length - actual_rotate_count + 1 to bv_length); + return result; + end bv_ror; + + + ---------------------------------------------------------------- + -- Arithmetic comparison operators. + -- Perform comparisons on bit vector encoded signed integers. + -- (For unsigned integers, built in lexical comparison does + -- the required operation.) + ---------------------------------------------------------------- + + ---------------------------------------------------------------- + -- bv_lt + -- + -- Signed less than comparison + ---------------------------------------------------------------- + + function bv_lt (bv1, bv2 : in bit_vector) return boolean is + + variable tmp1 : bit_vector(bv1'range) := bv1; + variable tmp2 : bit_vector(bv2'range) := bv2; + + begin + assert bv1'length = bv2'length + report "bv_lt: operands of different lengths" + severity failure; + tmp1(tmp1'left) := not tmp1(tmp1'left); + tmp2(tmp2'left) := not tmp2(tmp2'left); + return tmp1 < tmp2; + end bv_lt; + + + ---------------------------------------------------------------- + -- bv_le + -- + -- Signed less than or equal comparison + ---------------------------------------------------------------- + + function bv_le (bv1, bv2 : in bit_vector) return boolean is + + variable tmp1 : bit_vector(bv1'range) := bv1; + variable tmp2 : bit_vector(bv2'range) := bv2; + + begin + assert bv1'length = bv2'length + report "bv_le: operands of different lengths" + severity failure; + tmp1(tmp1'left) := not tmp1(tmp1'left); + tmp2(tmp2'left) := not tmp2(tmp2'left); + return tmp1 <= tmp2; + end bv_le; + + + ---------------------------------------------------------------- + -- bv_gt + -- + -- Signed greater than comparison + ---------------------------------------------------------------- + + function bv_gt (bv1, bv2 : in bit_vector) return boolean is + + variable tmp1 : bit_vector(bv1'range) := bv1; + variable tmp2 : bit_vector(bv2'range) := bv2; + + begin + assert bv1'length = bv2'length + report "bv_gt: operands of different lengths" + severity failure; + tmp1(tmp1'left) := not tmp1(tmp1'left); + tmp2(tmp2'left) := not tmp2(tmp2'left); + return tmp1 > tmp2; + end bv_gt; + + + ---------------------------------------------------------------- + -- bv_ge + -- + -- Signed greater than or equal comparison + ---------------------------------------------------------------- + + function bv_ge (bv1, bv2 : in bit_vector) return boolean is + + variable tmp1 : bit_vector(bv1'range) := bv1; + variable tmp2 : bit_vector(bv2'range) := bv2; + + begin + assert bv1'length = bv2'length + report "bv_ged: operands of different lengths" + severity failure; + tmp1(tmp1'left) := not tmp1(tmp1'left); + tmp2(tmp2'left) := not tmp2(tmp2'left); + return tmp1 >= tmp2; + end bv_ge; + + + ---------------------------------------------------------------- + -- Extension operators - convert a bit vector to a longer one + ---------------------------------------------------------------- + + ---------------------------------------------------------------- + -- bv_sext + -- + -- Sign extension - replicate the sign bit of the operand into + -- the most significant bits of the result. Length parameter + -- determines size of result. If length < bv'length, result is + -- rightmost length bits of bv. + ---------------------------------------------------------------- + + function bv_sext (bv : in bit_vector; + length : in natural) return bit_vector is + + alias bv_norm : bit_vector(1 to bv'length) is bv; + variable result : bit_vector(1 to length) := (others => bv(bv'left)); + variable src_length : natural := bv'length; + + begin + if src_length > length then + src_length := length; + end if; + result(length - src_length + 1 to length) + := bv_norm(bv'length - src_length + 1 to bv'length); + return result; + end bv_sext; + + + ---------------------------------------------------------------- + -- bv_zext + -- + -- Zero extension - replicate zero bits into the most significant + -- bits of the result. Length parameter determines size of result. + -- If length < bv'length, result is rightmost length bits of bv. + ---------------------------------------------------------------- + + function bv_zext (bv : in bit_vector; + length : in natural) return bit_vector is + + alias bv_norm : bit_vector(1 to bv'length) is bv; + variable result : bit_vector(1 to length) := (others => '0'); + variable src_length : natural := bv'length; + + begin + if src_length > length then + src_length := length; + end if; + result(length - src_length + 1 to length) + := bv_norm(bv'length - src_length + 1 to bv'length); + return result; + end bv_zext; + + +end bv_arithmetic; diff --git a/projects/dlx/src/bv_arithmetic.vhdl b/projects/dlx/src/bv_arithmetic.vhdl new file mode 100644 index 0000000..e304e73 --- /dev/null +++ b/projects/dlx/src/bv_arithmetic.vhdl @@ -0,0 +1,238 @@ +-------------------------------------------------------------------------- +-- +-- Copyright (C) 1993, Peter J. Ashenden +-- Mail: Dept. Computer Science +-- University of Adelaide, SA 5005, Australia +-- e-mail: petera@cs.adelaide.edu.au +-- +-- This program 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 1, or (at your option) +-- any later version. +-- +-- This program 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 this program; if not, write to the Free Software +-- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +-- +-------------------------------------------------------------------------- +-- +-- $RCSfile: bv_arithmetic.vhdl,v $ $Revision: 2.1 $ $Date: 1993/10/31 20:10:41 $ +-- +-------------------------------------------------------------------------- +-- +-- Bit vector arithmetic package specification. +-- +-- Does arithmetic and logical operations on bit vectors, treating them +-- as either unsigned or signed (2's complement) integers. Leftmost bit +-- is most significant or sign bit, rightmost bit is least significant +-- bit. Dyadic operations need the two arguments to be of the same +-- length, however their index ranges and directions may differ. Results +-- must be of the same length as the operands. +-- +-------------------------------------------------------------------------- + +use std.textio.line; + +package bv_arithmetic is + + ---------------------------------------------------------------- + -- Type conversions + ---------------------------------------------------------------- + + -- Convert bit vector encoded unsigned integer to natural. + + function bv_to_natural (bv : in bit_vector) return natural; + + -- Convert natural to bit vector encoded unsigned integer. + -- (length is used as the size of the result.) + + function natural_to_bv (nat : in natural; + length : in natural) return bit_vector; + + -- Convert bit vector encoded signed integer to integer + + function bv_to_integer (bv : in bit_vector) return integer; + + -- Convert integer to bit vector encoded signed integer. + -- (length is used as the size of the result.) + + function integer_to_bv (int : in integer; + length : in natural) return bit_vector; + + ---------------------------------------------------------------- + -- Arithmetic operations + ---------------------------------------------------------------- + + -- Signed addition with overflow detection + + procedure bv_add (bv1, bv2 : in bit_vector; + bv_result : out bit_vector; + overflow : out boolean); + + -- Signed addition without overflow detection + + function "+" (bv1, bv2 : in bit_vector) return bit_vector; + + -- Signed subtraction with overflow detection + + procedure bv_sub (bv1, bv2 : in bit_vector; + bv_result : out bit_vector; + overflow : out boolean); + + -- Signed subtraction without overflow detection + + function "-" (bv1, bv2 : in bit_vector) return bit_vector; + + -- Unsigned addition with overflow detection + + procedure bv_addu (bv1, bv2 : in bit_vector; + bv_result : out bit_vector; + overflow : out boolean); + + -- Unsigned addition without overflow detection + + procedure bv_addu (bv1, bv2 : in bit_vector; + bv_result : out bit_vector); + + -- Unsigned subtraction with overflow detection + + procedure bv_subu (bv1, bv2 : in bit_vector; + bv_result : out bit_vector; + overflow : out boolean); + + -- Unsigned subtraction without overflow detection + + procedure bv_subu (bv1, bv2 : in bit_vector; + bv_result : out bit_vector); + + -- Signed negation with overflow detection + + procedure bv_neg (bv : in bit_vector; + bv_result : out bit_vector; + overflow : out boolean); + + -- Signed negation without overflow detection + + function "-" (bv : in bit_vector) return bit_vector; + + -- Signed multiplication with overflow detection + + procedure bv_mult (bv1, bv2 : in bit_vector; + bv_result : out bit_vector; + overflow : out boolean); + + -- Signed multiplication without overflow detection + + function "*" (bv1, bv2 : in bit_vector) return bit_vector; + + -- Unsigned multiplication with overflow detection + + procedure bv_multu (bv1, bv2 : in bit_vector; + bv_result : out bit_vector; + overflow : out boolean); + + -- Unsigned multiplication without overflow detection + + procedure bv_multu (bv1, bv2 : in bit_vector; + bv_result : out bit_vector); + + -- Signed division with divide by zero and overflow detection + + procedure bv_div (bv1, bv2 : in bit_vector; + bv_result : out bit_vector; + div_by_zero : out boolean; + overflow : out boolean); + + -- Signed division without divide by zero and overflow detection + + function "/" (bv1, bv2 : in bit_vector) return bit_vector; + + -- Unsigned division with divide by zero detection + + procedure bv_divu (bv1, bv2 : in bit_vector; + bv_result : out bit_vector; + div_by_zero : out boolean); + + -- Unsigned division without divide by zero detection + + procedure bv_divu (bv1, bv2 : in bit_vector; + bv_result : out bit_vector); + + ---------------------------------------------------------------- + -- Logical operators + -- (Provided for VHDL-87, built in for VHDL-93) + ---------------------------------------------------------------- + + -- Shift left logical (fill with '0' bits) + + function bv_sll (bv : in bit_vector; + shift_count : in natural) return bit_vector; + + -- Shift right logical (fill with '0' bits) + + function bv_srl (bv : in bit_vector; + shift_count : in natural) return bit_vector; + + -- Shift right arithmetic (fill with copy of sign bit) + + function bv_sra (bv : in bit_vector; + shift_count : in natural) return bit_vector; + + -- Rotate left + + function bv_rol (bv : in bit_vector; + rotate_count : in natural) return bit_vector; + + -- Rotate right + + function bv_ror (bv : in bit_vector; + rotate_count : in natural) return bit_vector; + + ---------------------------------------------------------------- + -- Arithmetic comparison operators. + -- Perform comparisons on bit vector encoded signed integers. + -- (For unsigned integers, built in lexical comparison does + -- the required operation.) + ---------------------------------------------------------------- + + -- Signed less than comparison + + function bv_lt (bv1, bv2 : in bit_vector) return boolean; + + -- Signed less than or equal comparison + + function bv_le (bv1, bv2 : in bit_vector) return boolean; + + -- Signed greater than comparison + + function bv_gt (bv1, bv2 : in bit_vector) return boolean; + + -- Signed greater than or equal comparison + + function bv_ge (bv1, bv2 : in bit_vector) return boolean; + + ---------------------------------------------------------------- + -- Extension operators - convert a bit vector to a longer one + ---------------------------------------------------------------- + + -- Sign extension - replicate the sign bit of the operand into + -- the most significant bits of the result. Length parameter + -- determines size of result. If length < bv'length, result is + -- rightmost length bits of bv. + + function bv_sext (bv : in bit_vector; + length : in natural) return bit_vector; + + -- Zero extension - replicate zero bits into the most significant + -- bits of the result. Length parameter determines size of result. + -- If length < bv'length, result is rightmost length bits of bv. + + function bv_zext (bv : in bit_vector; + length : in natural) return bit_vector; + +end bv_arithmetic; diff --git a/projects/dlx/src/bv_test-bench.vhdl b/projects/dlx/src/bv_test-bench.vhdl new file mode 100644 index 0000000..2b29d33 --- /dev/null +++ b/projects/dlx/src/bv_test-bench.vhdl @@ -0,0 +1,1121 @@ +-------------------------------------------------------------------------- +-- +-- Copyright (C) 1993, Peter J. Ashenden +-- Mail: Dept. Computer Science +-- University of Adelaide, SA 5005, Australia +-- e-mail: petera@cs.adelaide.edu.au +-- +-- This program 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 1, or (at your option) +-- any later version. +-- +-- This program 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 this program; if not, write to the Free Software +-- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +-- +-------------------------------------------------------------------------- +-- +-- $RCSfile: bv_test-bench.vhdl,v $ $Revision: 2.1 $ $Date: 1993/10/31 20:13:16 $ +-- +-------------------------------------------------------------------------- +-- +-- Architecture for test bench for bit vector arithmetic package. +-- + + +use std.textio.all, work.bv_arithmetic.all; + +architecture bench of bv_test is + +begin + + process + + variable L : line; + variable byte : bit_vector(0 to 7); + variable word : bit_vector(1 to 32); + variable half_byte : bit_vector(1 to 4); + variable overflow, div_by_zero, result : boolean; + + begin + WAIT for 1 ns; + + ---------------------------------------------------------------- + ---------------------------------------------------------------- + -- test bit_vector to numeric conversions + ---------------------------------------------------------------- + ---------------------------------------------------------------- + + write(L, string'("Testing bv_to_natural:")); + writeline(output, L); + + write(L, string'(" bv_to_natural(X""02"") = ")); + write(L, bv_to_natural(X"02")); + writeline(output, L); + assert bv_to_natural(X"02") = 2; + + write(L, string'(" bv_to_natural(X""FE"") = ")); + write(L, bv_to_natural(X"FE")); + writeline(output, L); + assert bv_to_natural(X"FE") = 254; + + ---------------------------------------------------------------- + + write(L, string'("Testing natural_to_bv:")); + writeline(output, L); + + write(L, string'(" natural_to_bv(2) = ")); + write(L, natural_to_bv(2, 8)); + writeline(output, L); + assert natural_to_bv(2, 8) = X"02"; + + write(L, string'(" natural_to_bv(254) = ")); + write(L, natural_to_bv(254, 8)); + writeline(output, L); + assert natural_to_bv(254, 8) = X"FE"; + + ---------------------------------------------------------------- + + write(L, string'("Testing bv_to_integer:")); + writeline(output, L); + + write(L, string'(" bv_to_integer(X""02"") = ")); + write(L, bv_to_integer(X"02")); + writeline(output, L); + assert bv_to_integer(X"02") = 2; + + write(L, string'(" bv_to_integer(X""FE"") = ")); + write(L, bv_to_integer(X"FE")); + writeline(output, L); + assert bv_to_integer(X"FE") = -2; + + ---------------------------------------------------------------- + + write(L, string'("Testing integer_to_bv:")); + writeline(output, L); + + write(L, string'(" integer_to_bv(2) = ")); + write(L, integer_to_bv(2, 8)); + writeline(output, L); + assert integer_to_bv(2, 8) = X"02"; + + write(L, string'(" integer_to_bv(-2) = ")); + write(L, integer_to_bv(-2, 8)); + writeline(output, L); + assert integer_to_bv(-2, 8) = X"FE"; + + + ---------------------------------------------------------------- + ---------------------------------------------------------------- + -- Arithmetic operations + ---------------------------------------------------------------- + ---------------------------------------------------------------- + + ---------------------------------------------------------------- + -- bv_add: Signed addition with overflow detection + ---------------------------------------------------------------- + + writeline(output, L); + write(L, string'("Testing bv_add with overflow:")); + writeline(output, L); + + write(L, string'(" 2+2 = ")); + bv_add(X"02", X"02", byte, overflow); + write(L, byte); + write(L, string'(", overflow = ")); write(L, overflow); + writeline(output, L); + assert byte = X"04" and not overflow; + + write(L, string'(" 2+(-3) = ")); + bv_add(X"02", X"FD", byte, overflow); + write(L, byte); + write(L, string'(", overflow = ")); write(L, overflow); + writeline(output, L); + assert byte = X"FF" and not overflow; + + write(L, string'(" 64+64 = ")); + bv_add(X"40", X"40", byte, overflow); + write(L, byte); + write(L, string'(", overflow = ")); write(L, overflow); + writeline(output, L); + assert byte = X"80" and overflow; + + write(L, string'(" -64+(-64) = ")); + bv_add(X"C0", X"C0", byte, overflow); + write(L, byte); + write(L, string'(", overflow = ")); write(L, overflow); + writeline(output, L); + assert byte = X"80" and not overflow; + + ---------------------------------------------------------------- + -- "+": Signed addition without overflow detection + ---------------------------------------------------------------- + + writeline(output, L); + write(L, string'("Testing ""+"" without overflow:")); + writeline(output, L); + + write(L, string'(" 2+2 = ")); + byte := X"02" + X"02"; + write(L, byte); + writeline(output, L); + assert byte = X"04"; + + write(L, string'(" 2+(-3) = ")); + byte := X"02" + X"FD"; + write(L, byte); + writeline(output, L); + assert byte = X"FF"; + + write(L, string'(" 64+64 = ")); + byte := X"40" + X"40"; + write(L, byte); + writeline(output, L); + assert byte = X"80"; + + write(L, string'(" -64+(-64) = ")); + byte := X"C0" + X"C0"; + write(L, byte); + writeline(output, L); + assert byte = X"80"; + + ---------------------------------------------------------------- + -- bv_sub: Signed subtraction with overflow detection + ---------------------------------------------------------------- + + writeline(output, L); + write(L, string'("Testing bv_sub with overflow:")); + writeline(output, L); + + write(L, string'(" 2-2 = ")); + bv_sub(X"02", X"02", byte, overflow); + write(L, byte); + write(L, string'(", overflow = ")); write(L, overflow); + writeline(output, L); + assert byte = X"00" and not overflow; + + write(L, string'(" 2-(-3) = ")); + bv_sub(X"02", X"FD", byte, overflow); + write(L, byte); + write(L, string'(", overflow = ")); write(L, overflow); + writeline(output, L); + assert byte = X"05" and not overflow; + + write(L, string'(" 64-(-64) = ")); + bv_sub(X"40", X"C0", byte, overflow); + write(L, byte); + write(L, string'(", overflow = ")); write(L, overflow); + writeline(output, L); + assert byte = X"80" and overflow; + + write(L, string'(" -64-64 = ")); + bv_sub(X"C0", X"40", byte, overflow); + write(L, byte); + write(L, string'(", overflow = ")); write(L, overflow); + writeline(output, L); + assert byte = X"80" and not overflow; + + ---------------------------------------------------------------- + -- "-": Signed subtraction without overflow detection + ---------------------------------------------------------------- + + writeline(output, L); + write(L, string'("Testing ""-"" without overflow:")); + writeline(output, L); + + write(L, string'(" 2-2 = ")); + byte := X"02" - X"02"; + write(L, byte); + writeline(output, L); + assert byte = X"00"; + + write(L, string'(" 2-(-3) = ")); + byte := X"02" - X"FD"; + write(L, byte); + writeline(output, L); + assert byte = X"05"; + + write(L, string'(" 64-(-64) = ")); + byte := X"40" - X"C0"; + write(L, byte); + writeline(output, L); + assert byte = X"80"; + + write(L, string'(" -64-64 = ")); + byte := X"C0" - X"40"; + write(L, byte); + writeline(output, L); + assert byte = X"80"; + + ---------------------------------------------------------------- + -- bv_addu: Unsigned addition with overflow detection + ---------------------------------------------------------------- + + writeline(output, L); + write(L, string'("Testing bv_addu with overflow:")); + writeline(output, L); + + write(L, string'(" 2+2 = ")); + bv_addu(X"02", X"02", byte, overflow); + write(L, byte); + write(L, string'(", overflow = ")); write(L, overflow); + writeline(output, L); + assert byte = X"04" and not overflow; + + write(L, string'(" 64+64 = ")); + bv_addu(X"40", X"40", byte, overflow); + write(L, byte); + write(L, string'(", overflow = ")); write(L, overflow); + writeline(output, L); + assert byte = X"80" and not overflow; + + write(L, string'(" 128+128 = ")); + bv_addu(X"80", X"80", byte, overflow); + write(L, byte); + write(L, string'(", overflow = ")); write(L, overflow); + writeline(output, L); + assert byte = X"00" and overflow; + + ---------------------------------------------------------------- + -- bv_addu: Unsigned addition without overflow detection + ---------------------------------------------------------------- + + writeline(output, L); + write(L, string'("Testing bv_addu without overflow:")); + writeline(output, L); + + write(L, string'(" 2+2 = ")); + bv_addu(X"02", X"02", byte); + write(L, byte); + writeline(output, L); + assert byte = X"04"; + + write(L, string'(" 64+64 = ")); + bv_addu(X"40", X"40", byte); + write(L, byte); + writeline(output, L); + assert byte = X"80"; + + write(L, string'(" 128+128 = ")); + bv_addu(X"80", X"80", byte); + write(L, byte); + writeline(output, L); + assert byte = X"00"; + + ---------------------------------------------------------------- + -- bv_subu: Unsigned subtraction with overflow detection + ---------------------------------------------------------------- + + writeline(output, L); + write(L, string'("Testing bv_subu with overflow:")); + writeline(output, L); + + write(L, string'(" 3-2 = ")); + bv_subu(X"03", X"02", byte, overflow); + write(L, byte); + write(L, string'(", overflow = ")); write(L, overflow); + writeline(output, L); + assert byte = X"01" and not overflow; + + write(L, string'(" 64-64 = ")); + bv_subu(X"40", X"40", byte, overflow); + write(L, byte); + write(L, string'(", overflow = ")); write(L, overflow); + writeline(output, L); + assert byte = X"00" and not overflow; + + write(L, string'(" 64-128 = ")); + bv_subu(X"40", X"80", byte, overflow); + write(L, byte); + write(L, string'(", overflow = ")); write(L, overflow); + writeline(output, L); + assert byte = X"C0" and overflow; + + ---------------------------------------------------------------- + -- bv_subu: Unsigned subtraction without overflow detection + ---------------------------------------------------------------- + + writeline(output, L); + write(L, string'("Testing bv_subu without overflow:")); + writeline(output, L); + + write(L, string'(" 3-2 = ")); + bv_subu(X"03", X"02", byte); + write(L, byte); + writeline(output, L); + assert byte = X"01"; + + write(L, string'(" 64-64 = ")); + bv_subu(X"40", X"40", byte); + write(L, byte); + writeline(output, L); + assert byte = X"00"; + + write(L, string'(" 64-128 = ")); + bv_subu(X"40", X"80", byte); + write(L, byte); + writeline(output, L); + assert byte = X"C0"; + + ---------------------------------------------------------------- + -- bv_neg: Signed negation with overflow detection + ---------------------------------------------------------------- + + writeline(output, L); + write(L, string'("Testing bv_neg with overflow:")); + writeline(output, L); + + write(L, string'(" -(3) = ")); + bv_neg(X"03", byte, overflow); + write(L, byte); + write(L, string'(", overflow = ")); write(L, overflow); + writeline(output, L); + assert byte = X"FD" and not overflow; + + write(L, string'(" -(-3) = ")); + bv_neg(X"FD", byte, overflow); + write(L, byte); + write(L, string'(", overflow = ")); write(L, overflow); + writeline(output, L); + assert byte = X"03" and not overflow; + + write(L, string'(" -(127) = ")); + bv_neg(X"7F", byte, overflow); + write(L, byte); + write(L, string'(", overflow = ")); write(L, overflow); + writeline(output, L); + assert byte = X"81" and not overflow; + + write(L, string'(" -(-128) = ")); + bv_neg(X"80", byte, overflow); + write(L, byte); + write(L, string'(", overflow = ")); write(L, overflow); + writeline(output, L); + assert byte = X"80" and overflow; + + ---------------------------------------------------------------- + -- "-": Signed negation without overflow detection + ---------------------------------------------------------------- + + writeline(output, L); + write(L, string'("Testing ""-"" without overflow:")); + writeline(output, L); + + write(L, string'(" -(3) = ")); + byte := - X"03"; + write(L, byte); + writeline(output, L); + assert byte = X"FD"; + + write(L, string'(" -(-3) = ")); + byte := - X"FD"; + write(L, byte); + writeline(output, L); + assert byte = X"03"; + + write(L, string'(" -(127) = ")); + byte := - X"7F"; + write(L, byte); + writeline(output, L); + assert byte = X"81"; + + write(L, string'(" -(-128) = ")); + byte := - X"80"; + write(L, byte); + writeline(output, L); + assert byte = X"80"; + + ---------------------------------------------------------------- + -- bv_mult: Signed multiplication with overflow detection + ---------------------------------------------------------------- + + writeline(output, L); + write(L, string'("Testing bv_mult with overflow:")); + writeline(output, L); + + write(L, string'(" 5*(-3) = ")); + bv_mult(X"05", X"FD", byte, overflow); + write(L, byte); + write(L, string'(", overflow = ")); write(L, overflow); + writeline(output, L); + assert byte = X"F1" and not overflow; + + write(L, string'(" (-5)*(-3) = ")); + bv_mult(X"FB", X"FD", byte, overflow); + write(L, byte); + write(L, string'(", overflow = ")); write(L, overflow); + writeline(output, L); + assert byte = X"0F" and not overflow; + + write(L, string'(" 16*8 = ")); + bv_mult(X"10", X"08", byte, overflow); + write(L, byte); + write(L, string'(", overflow = ")); write(L, overflow); + writeline(output, L); + assert byte = X"80" and overflow; + + write(L, string'(" 16*16 = ")); + bv_mult(X"10", X"10", byte, overflow); + write(L, byte); + write(L, string'(", overflow = ")); write(L, overflow); + writeline(output, L); + assert byte = X"00" and overflow; + + write(L, string'(" 16*(-8) = ")); + bv_mult(X"10", X"F8", byte, overflow); + write(L, byte); + write(L, string'(", overflow = ")); write(L, overflow); + writeline(output, L); + assert byte = X"80" and not overflow; + + write(L, string'(" 16*(-16) = ")); + bv_mult(X"10", X"F0", byte, overflow); + write(L, byte); + write(L, string'(", overflow = ")); write(L, overflow); + writeline(output, L); + assert byte = X"00" and overflow; + + ---------------------------------------------------------------- + -- "*": Signed multiplication without overflow detection + ---------------------------------------------------------------- + + writeline(output, L); + write(L, string'("Testing ""*"" without overflow:")); + writeline(output, L); + + write(L, string'(" 5*(-3) = ")); + byte := X"05" * X"FD"; + write(L, byte); + writeline(output, L); + assert byte = X"F1"; + + write(L, string'(" (-5)*(-3) = ")); + byte := X"FB" * X"FD"; + write(L, byte); + writeline(output, L); + assert byte = X"0F"; + + write(L, string'(" 16*8 = ")); + byte := X"10" * X"08"; + write(L, byte); + writeline(output, L); + assert byte = X"80"; + + write(L, string'(" 16*16 = ")); + byte := X"10" * X"10"; + write(L, byte); + writeline(output, L); + assert byte = X"00"; + + write(L, string'(" 16*(-8) = ")); + byte := X"10" * X"F8"; + write(L, byte); + writeline(output, L); + assert byte = X"80"; + + write(L, string'(" 16*(-16) = ")); + byte := X"10" * X"F0"; + write(L, byte); + writeline(output, L); + assert byte = X"00"; + + ---------------------------------------------------------------- + -- bv_multu: Unsigned multiplication with overflow detection + ---------------------------------------------------------------- + + writeline(output, L); + write(L, string'("Testing bv_multu with overflow:")); + writeline(output, L); + + write(L, string'(" 5*7 = ")); + bv_multu(X"05", X"07", byte, overflow); + write(L, byte); + write(L, string'(", overflow = ")); write(L, overflow); + writeline(output, L); + assert byte = X"23" and not overflow; + + write(L, string'(" 16*8 = ")); + bv_multu(X"10", X"08", byte, overflow); + write(L, byte); + write(L, string'(", overflow = ")); write(L, overflow); + writeline(output, L); + assert byte = X"80" and not overflow; + + write(L, string'(" 16*16 = ")); + bv_multu(X"10", X"10", byte, overflow); + write(L, byte); + write(L, string'(", overflow = ")); write(L, overflow); + writeline(output, L); + assert byte = X"00" and overflow; + + ---------------------------------------------------------------- + -- bv_multu: Unsigned multiplication without overflow detection + ---------------------------------------------------------------- + + writeline(output, L); + write(L, string'("Testing bv_multu without overflow:")); + writeline(output, L); + + write(L, string'(" 5*7 = ")); + bv_multu(X"05", X"07", byte); + write(L, byte); + writeline(output, L); + assert byte = X"23"; + + write(L, string'(" 16*8 = ")); + bv_multu(X"10", X"08", byte); + write(L, byte); + writeline(output, L); + assert byte = X"80"; + + write(L, string'(" 16*16 = ")); + bv_multu(X"10", X"10", byte); + write(L, byte); + writeline(output, L); + assert byte = X"00"; + + ---------------------------------------------------------------- + -- bv_div: Signed division with divide by zero and overflow detection + ---------------------------------------------------------------- + + writeline(output, L); + write(L, string'("Testing bv_div with flags:")); + writeline(output, L); + + write(L, string'(" 7/2 = ")); + bv_div(X"07", X"02", byte, div_by_zero, overflow); + write(L, byte); + write(L, string'(", div_by_zero = ")); write(L, div_by_zero); + write(L, string'(", overflow = ")); write(L, overflow); + writeline(output, L); + assert byte = X"03" and not div_by_zero and not overflow; + + write(L, string'(" -7/2 = ")); + bv_div(X"F9", X"02", byte, div_by_zero, overflow); + write(L, byte); + write(L, string'(", div_by_zero = ")); write(L, div_by_zero); + write(L, string'(", overflow = ")); write(L, overflow); + writeline(output, L); + assert byte = X"FD" and not div_by_zero and not overflow; + + write(L, string'(" 7/-2 = ")); + bv_div(X"07", X"FE", byte, div_by_zero, overflow); + write(L, byte); + write(L, string'(", div_by_zero = ")); write(L, div_by_zero); + write(L, string'(", overflow = ")); write(L, overflow); + writeline(output, L); + assert byte = X"FD" and not div_by_zero and not overflow; + + write(L, string'(" -7/-2 = ")); + bv_div(X"F9", X"FE", byte, div_by_zero, overflow); + write(L, byte); + write(L, string'(", div_by_zero = ")); write(L, div_by_zero); + write(L, string'(", overflow = ")); write(L, overflow); + writeline(output, L); + assert byte = X"03" and not div_by_zero and not overflow; + + write(L, string'(" -128/1 = ")); + bv_div(X"80", X"01", byte, div_by_zero, overflow); + write(L, byte); + write(L, string'(", div_by_zero = ")); write(L, div_by_zero); + write(L, string'(", overflow = ")); write(L, overflow); + writeline(output, L); + assert byte = X"80" and not div_by_zero and not overflow; + + write(L, string'(" -128/-1 = ")); + bv_div(X"80", X"FF", byte, div_by_zero, overflow); + write(L, byte); + write(L, string'(", div_by_zero = ")); write(L, div_by_zero); + write(L, string'(", overflow = ")); write(L, overflow); + writeline(output, L); + assert byte = X"80" and not div_by_zero and overflow; + + write(L, string'(" -16/0 = ")); + bv_div(X"F0", X"00", byte, div_by_zero, overflow); + write(L, byte); + write(L, string'(", div_by_zero = ")); write(L, div_by_zero); + write(L, string'(", overflow = ")); write(L, overflow); + writeline(output, L); + assert byte = X"00" and div_by_zero and not overflow; + + ---------------------------------------------------------------- + -- "/": Signed division without divide by zero and overflow detection + ---------------------------------------------------------------- + + writeline(output, L); + write(L, string'("Testing ""/"" without flags:")); + writeline(output, L); + + write(L, string'(" 7/2 = ")); + byte := X"07" / X"02"; + write(L, byte); + writeline(output, L); + assert byte = X"03"; + + write(L, string'(" -7/2 = ")); + byte := X"F9" / X"02"; + write(L, byte); + writeline(output, L); + assert byte = X"FD"; + + write(L, string'(" 7/-2 = ")); + byte := X"07" / X"FE"; + write(L, byte); + writeline(output, L); + assert byte = X"FD"; + + write(L, string'(" -7/-2 = ")); + byte := X"F9" / X"FE"; + write(L, byte); + writeline(output, L); + assert byte = X"03"; + + write(L, string'(" -128/1 = ")); + byte := X"80" / X"01"; + write(L, byte); + writeline(output, L); + assert byte = X"80"; + + write(L, string'(" -128/-1 = ")); + byte := X"80" / X"FF"; + write(L, byte); + writeline(output, L); + assert byte = X"80"; + + write(L, string'(" -16/0 = ")); + byte := X"F0" / X"00"; + write(L, byte); + writeline(output, L); + assert byte = X"00"; + + ---------------------------------------------------------------- + -- bv_divu: Unsigned division with divide by zero detection + ---------------------------------------------------------------- + + writeline(output, L); + write(L, string'("Testing bv_divu with flag:")); + writeline(output, L); + + write(L, string'(" 7/2 = ")); + bv_divu(X"07", X"02", byte, div_by_zero); + write(L, byte); + write(L, string'(", div_by_zero = ")); write(L, div_by_zero); + writeline(output, L); + assert byte = X"03" and not div_by_zero; + + write(L, string'(" 14/7 = ")); + bv_divu(X"0E", X"07", byte, div_by_zero); + write(L, byte); + write(L, string'(", div_by_zero = ")); write(L, div_by_zero); + writeline(output, L); + assert byte = X"02" and not div_by_zero; + + write(L, string'(" 16/1 = ")); + bv_divu(X"10", X"01", byte, div_by_zero); + write(L, byte); + write(L, string'(", div_by_zero = ")); write(L, div_by_zero); + writeline(output, L); + assert byte = X"10" and not div_by_zero; + + write(L, string'(" 16/0 = ")); + bv_divu(X"10", X"00", byte, div_by_zero); + write(L, byte); + write(L, string'(", div_by_zero = ")); write(L, div_by_zero); + writeline(output, L); + assert byte = X"10" and div_by_zero; + + write(L, string'(" 16/16 = ")); + bv_divu(X"10", X"10", byte, div_by_zero); + write(L, byte); + write(L, string'(", div_by_zero = ")); write(L, div_by_zero); + writeline(output, L); + assert byte = X"01" and not div_by_zero; + + write(L, string'(" 1/16 = ")); + bv_divu(X"01", X"10", byte, div_by_zero); + write(L, byte); + write(L, string'(", div_by_zero = ")); write(L, div_by_zero); + writeline(output, L); + assert byte = X"00" and not div_by_zero; + + write(L, string'(" 255/1 = ")); + bv_divu(X"FF", X"01", byte, div_by_zero); + write(L, byte); + write(L, string'(", div_by_zero = ")); write(L, div_by_zero); + writeline(output, L); + assert byte = X"FF" and not div_by_zero; + + ---------------------------------------------------------------- + -- bv_divu: Unsigned division without divide by zero detection + ---------------------------------------------------------------- + + writeline(output, L); + write(L, string'("Testing bv_divu without flag:")); + writeline(output, L); + + write(L, string'(" 7/2 = ")); + bv_divu(X"07", X"02", byte); + write(L, byte); + writeline(output, L); + assert byte = X"03"; + + write(L, string'(" 14/7 = ")); + bv_divu(X"0E", X"07", byte); + write(L, byte); + writeline(output, L); + assert byte = X"02"; + + write(L, string'(" 16/1 = ")); + bv_divu(X"10", X"01", byte); + write(L, byte); + writeline(output, L); + assert byte = X"10"; + + write(L, string'(" 16/0 = ")); + bv_divu(X"10", X"00", byte); + write(L, byte); + writeline(output, L); + assert byte = X"10"; + + write(L, string'(" 16/16 = ")); + bv_divu(X"10", X"10", byte); + write(L, byte); + writeline(output, L); + assert byte = X"01"; + + write(L, string'(" 1/16 = ")); + bv_divu(X"01", X"10", byte); + write(L, byte); + writeline(output, L); + assert byte = X"00"; + + write(L, string'(" 255/1 = ")); + bv_divu(X"FF", X"01", byte); + write(L, byte); + writeline(output, L); + assert byte = X"FF"; + + + ---------------------------------------------------------------- + ---------------------------------------------------------------- + -- Logical operators + -- (Provided for VHDL-87, built in for VHDL-93) + ---------------------------------------------------------------- + ---------------------------------------------------------------- + + ---------------------------------------------------------------- + -- bv_sll: Shift left logical (fill with '0' bits) + ---------------------------------------------------------------- + + writeline(output, L); + write(L, string'("Testing bv_sll:")); + writeline(output, L); + + write(L, string'(" 10100101 sll 4 = ")); + byte := bv_sll(B"10100101", 4); + write(L, byte); + writeline(output, L); + assert byte = B"01010000"; + + ---------------------------------------------------------------- + -- bv_srl: Shift right logical (fill with '0' bits) + ---------------------------------------------------------------- + + writeline(output, L); + write(L, string'("Testing bv_srl:")); + writeline(output, L); + + write(L, string'(" 10100101 srl 4 = ")); + byte := bv_srl(B"10100101", 4); + write(L, byte); + writeline(output, L); + assert byte = B"00001010"; + + ---------------------------------------------------------------- + -- bv_sra: Shift right arithmetic (fill with copy of sign bit) + ---------------------------------------------------------------- + + writeline(output, L); + write(L, string'("Testing bv_sra:")); + writeline(output, L); + + write(L, string'(" 01011010 sra 4 = ")); + byte := bv_sra(B"01011010", 4); + write(L, byte); + writeline(output, L); + assert byte = B"00000101"; + + write(L, string'(" 10100101 sra 4 = ")); + byte := bv_sra(B"10100101", 4); + write(L, byte); + writeline(output, L); + assert byte = B"11111010"; + + ---------------------------------------------------------------- + -- bv_rol: Rotate left + ---------------------------------------------------------------- + + writeline(output, L); + write(L, string'("Testing bv_rol:")); + writeline(output, L); + + write(L, string'(" 10100101 rol 3 = ")); + byte := bv_rol(B"10100101", 3); + write(L, byte); + writeline(output, L); + assert byte = B"00101101"; + + ---------------------------------------------------------------- + -- bv_rol: Rotate right + ---------------------------------------------------------------- + + writeline(output, L); + write(L, string'("Testing bv_ror:")); + writeline(output, L); + + write(L, string'(" 10100101 ror 3 = ")); + byte := bv_ror(B"10100101", 3); + write(L, byte); + writeline(output, L); + assert byte = B"10110100"; + + + ---------------------------------------------------------------- + ---------------------------------------------------------------- + -- Arithmetic comparison operators. + ---------------------------------------------------------------- + ---------------------------------------------------------------- + + ---------------------------------------------------------------- + -- bv_lt: Signed less than comparison + ---------------------------------------------------------------- + + writeline(output, L); + write(L, string'("Testing bv_lt:")); + writeline(output, L); + + write(L, string'(" 2 < 2 = ")); + result := bv_lt(X"02", X"02"); + write(L, result); + writeline(output, L); + assert NOT result; + + write(L, string'(" 2 < 3 = ")); + result := bv_lt(X"02", X"03"); + write(L, result); + writeline(output, L); + assert result; + + write(L, string'(" -2 < 2 = ")); + result := bv_lt(X"FE", X"02"); + write(L, result); + writeline(output, L); + assert result; + + write(L, string'(" 2 < -3 = ")); + result := bv_lt(X"02", X"FD"); + write(L, result); + writeline(output, L); + assert NOT result; + + ---------------------------------------------------------------- + -- bv_le: Signed less than or equal comparison + ---------------------------------------------------------------- + + writeline(output, L); + write(L, string'("Testing bv_le:")); + writeline(output, L); + + write(L, string'(" 2 <= 2 = ")); + result := bv_le(X"02", X"02"); + write(L, result); + writeline(output, L); + assert result; + + write(L, string'(" 2 <= 3 = ")); + result := bv_le(X"02", X"03"); + write(L, result); + writeline(output, L); + assert result; + + write(L, string'(" -2 <= 2 = ")); + result := bv_le(X"FE", X"02"); + write(L, result); + writeline(output, L); + assert result; + + write(L, string'(" 2 <= -3 = ")); + result := bv_le(X"02", X"FD"); + write(L, result); + writeline(output, L); + assert NOT result; + + ---------------------------------------------------------------- + -- bv_gt: Signed greater than comparison + ---------------------------------------------------------------- + + writeline(output, L); + write(L, string'("Testing bv_gt:")); + writeline(output, L); + + write(L, string'(" 2 > 2 = ")); + result := bv_gt(X"02", X"02"); + write(L, result); + writeline(output, L); + assert NOT result; + + write(L, string'(" 3 > 2 = ")); + result := bv_gt(X"03", X"02"); + write(L, result); + writeline(output, L); + assert result; + + write(L, string'(" 2 > -2 = ")); + result := bv_gt(X"02", X"FE"); + write(L, result); + writeline(output, L); + assert result; + + write(L, string'(" -3 > 2 = ")); + result := bv_gt(X"FD", X"02"); + write(L, result); + writeline(output, L); + assert NOT result; + + ---------------------------------------------------------------- + -- bv_ge: Signed greater than or equal comparison + ---------------------------------------------------------------- + + writeline(output, L); + write(L, string'("Testing bv_ge:")); + writeline(output, L); + + write(L, string'(" 2 >= 2 = ")); + result := bv_ge(X"02", X"02"); + write(L, result); + writeline(output, L); + assert result; + + write(L, string'(" 3 >= 2 = ")); + result := bv_ge(X"03", X"02"); + write(L, result); + writeline(output, L); + assert result; + + write(L, string'(" 2 >= -2 = ")); + result := bv_ge(X"02", X"FE"); + write(L, result); + writeline(output, L); + assert result; + + write(L, string'(" -3 >= 2 = ")); + result := bv_ge(X"FD", X"02"); + write(L, result); + writeline(output, L); + assert NOT result; + + ---------------------------------------------------------------- + ---------------------------------------------------------------- + -- Extension operators - convert a bit vector to a longer one + ---------------------------------------------------------------- + ---------------------------------------------------------------- + + ---------------------------------------------------------------- + -- bv_sext: Sign extension + ---------------------------------------------------------------- + + writeline(output, L); + write(L, string'("Testing bv_sext:")); + writeline(output, L); + + write(L, string'(" sext(X""02"", 32) = ")); + word := bv_sext(X"02", 32); + write(L, word); + writeline(output, L); + assert word = X"00000002"; + + write(L, string'(" sext(X""FE"", 32) = ")); + word := bv_sext(X"FE", 32); + write(L, word); + writeline(output, L); + assert word = X"FFFFFFFE"; + + write(L, string'(" sext(X""02"", 8) = ")); + byte := bv_sext(X"02", 8); + write(L, byte); + writeline(output, L); + assert byte = X"02"; + + write(L, string'(" sext(X""FE"", 8) = ")); + byte := bv_sext(X"FE", 8); + write(L, byte); + writeline(output, L); + assert byte = X"FE"; + + write(L, string'(" sext(X""02"", 4) = ")); + half_byte := bv_sext(X"02", 4); + write(L, half_byte); + writeline(output, L); + assert half_byte = X"2"; + + write(L, string'(" sext(X""FE"", 4) = ")); + half_byte := bv_sext(X"FE", 4); + write(L, half_byte); + writeline(output, L); + assert half_byte = X"E"; + + ---------------------------------------------------------------- + -- bv_zext" Zero extension + ---------------------------------------------------------------- + + writeline(output, L); + write(L, string'("Testing bv_zext:")); + writeline(output, L); + + write(L, string'(" zext(X""02"", 32) = ")); + word := bv_zext(X"02", 32); + write(L, word); + writeline(output, L); + assert word = X"00000002"; + + write(L, string'(" zext(X""FE"", 32) = ")); + word := bv_zext(X"FE", 32); + write(L, word); + writeline(output, L); + assert word = X"000000FE"; + + write(L, string'(" zext(X""02"", 8) = ")); + byte := bv_zext(X"02", 8); + write(L, byte); + writeline(output, L); + assert byte = X"02"; + + write(L, string'(" zext(X""FE"", 8) = ")); + byte := bv_zext(X"FE", 8); + write(L, byte); + writeline(output, L); + assert byte = X"FE"; + + write(L, string'(" zext(X""02"", 4) = ")); + half_byte := bv_zext(X"02", 4); + write(L, half_byte); + writeline(output, L); + assert half_byte = X"2"; + + write(L, string'(" zext(X""FE"", 4) = ")); + half_byte := bv_zext(X"FE", 4); + write(L, half_byte); + writeline(output, L); + assert half_byte = X"E"; + + + wait; + end process; + +end bench; diff --git a/projects/dlx/src/bv_test.vhdl b/projects/dlx/src/bv_test.vhdl new file mode 100644 index 0000000..f7d231c --- /dev/null +++ b/projects/dlx/src/bv_test.vhdl @@ -0,0 +1,36 @@ +-------------------------------------------------------------------------- +-- +-- Copyright (C) 1993, Peter J. Ashenden +-- Mail: Dept. Computer Science +-- University of Adelaide, SA 5005, Australia +-- e-mail: petera@cs.adelaide.edu.au +-- +-- This program 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 1, or (at your option) +-- any later version. +-- +-- This program 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 this program; if not, write to the Free Software +-- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +-- +-------------------------------------------------------------------------- +-- +-- $RCSfile: bv_test.vhdl,v $ $Revision: 2.1 $ $Date: 1993/10/31 20:12:11 $ +-- +-------------------------------------------------------------------------- +-- +-- Entity declaration for test bench for bit vector arithmetic package. +-- + + +entity bv_test is + +begin + +end bv_test; diff --git a/projects/dlx/src/cache-behaviour.vhdl b/projects/dlx/src/cache-behaviour.vhdl new file mode 100644 index 0000000..4f9dfb7 --- /dev/null +++ b/projects/dlx/src/cache-behaviour.vhdl @@ -0,0 +1,310 @@ +-------------------------------------------------------------------------- +-- +-- Copyright (C) 1993, Peter J. Ashenden +-- Mail: Dept. Computer Science +-- University of Adelaide, SA 5005, Australia +-- e-mail: petera@cs.adelaide.edu.au +-- +-- This program 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 1, or (at your option) +-- any later version. +-- +-- This program 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 this program; if not, write to the Free Software +-- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +-- +-------------------------------------------------------------------------- +-- +-- $RCSfile: cache-behaviour.vhdl,v $ $Revision: 2.1 $ $Date: 1993/11/02 22:13:32 $ +-- +-------------------------------------------------------------------------- +-- +-- Behavioural architecture for cache. +-- + + +use work.bv_arithmetic.bv_to_natural, + work.bv_arithmetic.natural_to_bv; + + +architecture behaviour of cache is + +begin -- behaviour + + cache_behaviour : process + + constant words_per_line : positive := line_size / 4; + constant number_of_sets : positive := cache_size / line_size / associativity; + + subtype word_offset_range is natural range 0 to words_per_line-1; + subtype entry_index_range is natural range 0 to associativity-1; + subtype set_index_range is natural range 0 to number_of_sets-1; + + type line is array (word_offset_range) of dlx_word; + + type entry is record + tag : natural; + valid : boolean; + dirty : boolean; + data : line; + end record; + + type store_array is array (set_index_range, entry_index_range) of entry; + + variable store : store_array; + variable cpu_address : natural; + variable word_offset : word_offset_range; + variable set_index : set_index_range; + variable cpu_tag : natural; + variable entry_index : entry_index_range; + variable hit : boolean; + variable next_replacement_entry_index : entry_index_range := 0; + + + procedure do_read_hit is + begin + cpu_d <= store(set_index, entry_index).data(word_offset); + cpu_ready <= '1' after Tpd_clk_out; + wait until phi2 = '0'; + cpu_d <= null after Tpd_clk_out; + cpu_ready <= '0' after Tpd_clk_out; + end do_read_hit; + + + procedure do_write_through is + begin + wait until phi1 = '1'; + if reset = '1' then + return; + end if; + mem_a <= cpu_a after Tpd_clk_out; + mem_width <= cpu_width after Tpd_clk_out; + mem_d <= cpu_d after Tpd_clk_out; + mem_write <= '1' after Tpd_clk_out; + mem_burst <= '0' after Tpd_clk_out; + mem_enable <= '1' after Tpd_clk_out; + wait until mem_ready = '1' or reset = '1'; + cpu_ready <= mem_ready after Tpd_clk_out; + wait until phi2 = '0'; + mem_d <= null after Tpd_clk_out; + mem_write <= '0' after Tpd_clk_out; + mem_enable <= '0' after Tpd_clk_out; + cpu_ready <= '0' after Tpd_clk_out; + end do_write_through; + + + procedure do_write_hit is + begin + case cpu_width is + when width_word => + store(set_index, entry_index).data(word_offset) := cpu_d; + when width_halfword => + if cpu_a(1) = '0' then -- ms half word + store(set_index, entry_index).data(word_offset)(0 to 15) := cpu_d(0 to 15); + else -- ls half word + store(set_index, entry_index).data(word_offset)(16 to 23) := cpu_d(16 to 23); + end if; + when width_byte => + if cpu_a(1) = '0' then -- ms half word + if cpu_a(0) = '0' then -- byte 0 + store(set_index, entry_index).data(word_offset)(0 to 7) := cpu_d(0 to 7); + else -- byte 1 + store(set_index, entry_index).data(word_offset)(8 to 15) := cpu_d(8 to 15); + end if; + else -- ls half word + if cpu_a(0) = '0' then -- byte 2 + store(set_index, entry_index).data(word_offset)(16 to 23) := cpu_d(16 to 23); + else -- byte 3 + store(set_index, entry_index).data(word_offset)(24 to 31) := cpu_d(24 to 31); + end if; + end if; + end case; + if write_strategy = copy_back then + store(set_index, entry_index).dirty := true; + end if; + -- + -- if write_through cache, also update main memory + if write_strategy = write_through then + do_write_through; + else -- copy_back cache + cpu_ready <= '1' after Tpd_clk_out; + wait until phi2 = '0'; + cpu_ready <= '0' after Tpd_clk_out; + end if; + end do_write_hit; + + + procedure copy_back_line is + variable next_address : natural; + variable old_word_offset : natural; + begin + next_address := (store(set_index, entry_index).tag * number_of_sets + + set_index) * line_size; + wait until phi1 = '1'; + if reset = '1' then + return; + end if; + mem_width <= width_word after Tpd_clk_out; + mem_write <= '1' after Tpd_clk_out; + mem_enable <= '1' after Tpd_clk_out; + mem_burst <= '1' after Tpd_clk_out; + old_word_offset := 0; + burst_loop : loop + if old_word_offset = words_per_line-1 then + mem_burst <= '0' after Tpd_clk_out; + end if; + mem_a <= natural_to_bv(next_address, mem_a'length) after Tpd_clk_out; + mem_d <= store(set_index, entry_index).data(old_word_offset) after Tpd_clk_out; + wait_loop : loop + wait until phi2 = '0'; + exit burst_loop when reset = '1' + or (mem_ready = '1' and old_word_offset = words_per_line-1); + exit wait_loop when mem_ready = '1'; + end loop wait_loop; + old_word_offset := old_word_offset + 1; + next_address := next_address + 4; + end loop burst_loop; + store(set_index, entry_index).dirty := false; + mem_d <= null after Tpd_clk_out; + mem_write <= '0' after Tpd_clk_out; + mem_enable <= '0' after Tpd_clk_out; + end copy_back_line; + + + procedure fetch_line is + variable next_address : natural; + variable new_word_offset : natural; + begin + next_address := (cpu_address / line_size) * line_size; + wait until phi1 = '1'; + if reset = '1' then + return; + end if; + mem_width <= width_word after Tpd_clk_out; + mem_write <= '0' after Tpd_clk_out; + mem_enable <= '1' after Tpd_clk_out; + mem_burst <= '1' after Tpd_clk_out; + new_word_offset := 0; + burst_loop : loop + if new_word_offset = words_per_line-1 then + mem_burst <= '0' after Tpd_clk_out; + end if; + mem_a <= natural_to_bv(next_address, mem_a'length) after Tpd_clk_out; + wait_loop : loop + wait until phi2 = '0'; + store(set_index, entry_index).data(new_word_offset) := mem_d; + exit burst_loop when reset = '1' + or (mem_ready = '1' and new_word_offset = words_per_line-1); + exit wait_loop when mem_ready = '1'; + end loop wait_loop; + new_word_offset := new_word_offset + 1; + next_address := next_address + 4; + end loop burst_loop; + store(set_index, entry_index).valid := true; + store(set_index, entry_index).tag := cpu_tag; + store(set_index, entry_index).dirty := false; + mem_enable <= '0' after Tpd_clk_out; + end fetch_line; + + + procedure replace_line is + begin + -- first chose an entry using "random" number generator + entry_index := next_replacement_entry_index; + next_replacement_entry_index + := (next_replacement_entry_index + 1) mod associativity; + if store(set_index, entry_index).dirty then + copy_back_line; + end if; + fetch_line; + end replace_line; + + + procedure do_read_miss is + begin + replace_line; + if reset = '1' then + return; + end if; + do_read_hit; + end do_read_miss; + + + procedure do_write_miss is + begin + -- if write_through cache, just update main memory + if write_strategy = write_through then + do_write_through; + else -- copy_back cache + replace_line; + if reset = '1' then + return; + end if; + do_write_hit; + end if; + end do_write_miss; + + + begin -- process cache_behaviour + -- reset: initialize outputs and the cache store valid bits + cpu_ready <= '0'; + cpu_d <= null; + mem_enable <= '0'; + mem_width <= width_word; + mem_write <= '0'; + mem_burst <= '0'; + mem_a <= X"00000000"; + mem_d <= null; + for init_set_index in set_index_range loop + for init_entry_index in entry_index_range loop + store(init_set_index, init_entry_index).valid := false; + store(init_set_index, init_entry_index).dirty := false; + end loop; -- init_entry_index + end loop; -- init_set_index + -- + loop + -- wait for a cpu request + wait until phi2 = '1' and cpu_enable = '1'; + -- decode address + cpu_address := bv_to_natural(cpu_a); + word_offset := (cpu_address mod line_size) / 4; + set_index := (cpu_address / line_size) mod number_of_sets; + cpu_tag := cpu_address / line_size / number_of_sets; + -- check for hit + hit := false; + for lookup_entry_index in entry_index_range loop + if store(set_index, lookup_entry_index).valid + and store(set_index, lookup_entry_index).tag = cpu_tag then + hit := true; + entry_index := lookup_entry_index; + exit; + end if; + end loop; -- lookup_entry + -- + if hit then + if cpu_write = '1' then + do_write_hit; + else + do_read_hit; + end if; + else + if cpu_write = '1' then + do_write_miss; + else + do_read_miss; + end if; + end if; + exit when reset = '1'; + end loop; + -- loop exited on reset: wait until it goes inactive + -- then start again + wait until phi2 = '0' and reset = '0'; + end process cache_behaviour; + +end behaviour; diff --git a/projects/dlx/src/cache.vhdl b/projects/dlx/src/cache.vhdl new file mode 100644 index 0000000..9b9d862 --- /dev/null +++ b/projects/dlx/src/cache.vhdl @@ -0,0 +1,61 @@ +-------------------------------------------------------------------------- +-- +-- Copyright (C) 1993, Peter J. Ashenden +-- Mail: Dept. Computer Science +-- University of Adelaide, SA 5005, Australia +-- e-mail: petera@cs.adelaide.edu.au +-- +-- This program 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 1, or (at your option) +-- any later version. +-- +-- This program 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 this program; if not, write to the Free Software +-- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +-- +-------------------------------------------------------------------------- +-- +-- $RCSfile: cache.vhdl,v $ $Revision: 2.1 $ $Date: 1993/11/02 21:42:34 $ +-- +-------------------------------------------------------------------------- +-- +-- Entity declaration for cache. +-- + + +use work.dlx_types.all, + work.mem_types.all, + work.cache_types.all; + +entity cache is + generic (cache_size : positive; -- in bytes, power of 2 + line_size : positive; -- in bytes, power of 2 + associativity : positive; -- 1 = direct mapped + write_strategy : strategy_type; -- write_through or copy_back + Tpd_clk_out : Time; -- clock to output propagation delay + tag : string := ""; + origin_x, origin_y : real := 0.0); + port (phi1, phi2 : in bit; -- 2-phase non-overlapping clocks + reset : in bit; -- synchronous reset input + -- connections to CPU + cpu_enable : in bit; -- starts memory cycle + cpu_width : in mem_width; -- byte/halfword/word indicator + cpu_write : in bit; -- selects read or write cycle + cpu_ready : out bit; -- status from memory system + cpu_a : in dlx_address; -- address bus output + cpu_d : inout dlx_word_bus bus; -- bidirectional data bus + -- connections to memory + mem_enable : out bit; -- starts memory cycle + mem_width : out mem_width; -- byte/halfword/word indicator + mem_write : out bit; -- selects read or write cycle + mem_burst : out bit; -- tell memory to burst txfer + mem_ready : in bit; -- status from memory system + mem_a : out dlx_address; -- address bus output + mem_d : inout dlx_word_bus bus); -- bidirectional data bus +end cache; diff --git a/projects/dlx/src/cache_types.vhdl b/projects/dlx/src/cache_types.vhdl new file mode 100644 index 0000000..aff9a27 --- /dev/null +++ b/projects/dlx/src/cache_types.vhdl @@ -0,0 +1,36 @@ +-------------------------------------------------------------------------- +-- +-- Copyright (C) 1993, Peter J. Ashenden +-- Mail: Dept. Computer Science +-- University of Adelaide, SA 5005, Australia +-- e-mail: petera@cs.adelaide.edu.au +-- +-- This program 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 1, or (at your option) +-- any later version. +-- +-- This program 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 this program; if not, write to the Free Software +-- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +-- +-------------------------------------------------------------------------- +-- +-- $RCSfile: cache_types.vhdl,v $ $Revision: 2.1 $ $Date: 1993/11/02 21:40:49 $ +-- +-------------------------------------------------------------------------- +-- +-- Package spec defining types for cache. +-- + + +package cache_types is + + type strategy_type is (write_through, copy_back); + +end cache_types; diff --git a/projects/dlx/src/clock_gen-behaviour.vhdl b/projects/dlx/src/clock_gen-behaviour.vhdl new file mode 100644 index 0000000..4ac8042 --- /dev/null +++ b/projects/dlx/src/clock_gen-behaviour.vhdl @@ -0,0 +1,48 @@ +-------------------------------------------------------------------------- +-- +-- Copyright (C) 1993, Peter J. Ashenden +-- Mail: Dept. Computer Science +-- University of Adelaide, SA 5005, Australia +-- e-mail: petera@cs.adelaide.edu.au +-- +-- This program 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 1, or (at your option) +-- any later version. +-- +-- This program 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 this program; if not, write to the Free Software +-- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +-- +-------------------------------------------------------------------------- +-- +-- $RCSfile: clock_gen-behaviour.vhdl,v $ $Revision: 2.1 $ $Date: 1993/10/31 20:29:05 $ +-- +-------------------------------------------------------------------------- +-- +-- Behavioural architecture body for clock generator +-- + + +architecture behaviour of clock_gen is + + constant clock_period : Time := 2*(Tpw+Tps); + +begin + + reset_driver: + reset <= '1', '0' after 2*clock_period + Tpw+Tps; + + clock_driver : process + begin + phi1 <= '1', '0' after Tpw; + phi2 <= '1' after Tpw+Tps, '0' after Tpw+Tps+Tpw; + wait for clock_period; + end process clock_driver; + +end behaviour; diff --git a/projects/dlx/src/clock_gen.vhdl b/projects/dlx/src/clock_gen.vhdl new file mode 100644 index 0000000..3c5a48e --- /dev/null +++ b/projects/dlx/src/clock_gen.vhdl @@ -0,0 +1,42 @@ +-------------------------------------------------------------------------- +-- +-- Copyright (C) 1993, Peter J. Ashenden +-- Mail: Dept. Computer Science +-- University of Adelaide, SA 5005, Australia +-- e-mail: petera@cs.adelaide.edu.au +-- +-- This program 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 1, or (at your option) +-- any later version. +-- +-- This program 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 this program; if not, write to the Free Software +-- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +-- +-------------------------------------------------------------------------- +-- +-- $RCSfile: clock_gen.vhdl,v $ $Revision: 2.1 $ $Date: 1993/10/31 20:20:50 $ +-- +-------------------------------------------------------------------------- +-- +-- Entity declaration for clock generator +-- + + +entity clock_gen is + + generic (Tpw : Time; -- clock pulse width + Tps : Time; -- clock pulse separation + tag : string := ""; + origin_x, origin_y : real := 0.0); + + port (phi1, phi2 : out bit; -- two-phase non-overlapping clocks + reset : out bit); -- synchronous reset + +end clock_gen; diff --git a/projects/dlx/src/clock_gen_test-bench.vhdl b/projects/dlx/src/clock_gen_test-bench.vhdl new file mode 100644 index 0000000..a3d4395 --- /dev/null +++ b/projects/dlx/src/clock_gen_test-bench.vhdl @@ -0,0 +1,50 @@ +-------------------------------------------------------------------------- +-- +-- Copyright (C) 1993, Peter J. Ashenden +-- Mail: Dept. Computer Science +-- University of Adelaide, SA 5005, Australia +-- e-mail: petera@cs.adelaide.edu.au +-- +-- This program 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 1, or (at your option) +-- any later version. +-- +-- This program 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 this program; if not, write to the Free Software +-- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +-- +-------------------------------------------------------------------------- +-- +-- $RCSfile: clock_gen_test-bench.vhdl,v $ $Revision: 2.1 $ $Date: 1993/10/31 20:29:43 $ +-- +-------------------------------------------------------------------------- +-- +-- Architecture for test bench for clock generator +-- + + +architecture bench of clock_gen_test is + + component clock_gen + port (phi1, phi2 : out bit; + reset : out bit); + end component; + + for cg : clock_gen + use entity work.clock_gen(behaviour) + generic map (Tpw => 8 ns, Tps => 2 ns); + + signal p1, p2, reset : bit; + +begin + + cg : clock_gen + port map (p1, p2, reset); + +end bench; diff --git a/projects/dlx/src/clock_gen_test.vhdl b/projects/dlx/src/clock_gen_test.vhdl new file mode 100644 index 0000000..d4c9422 --- /dev/null +++ b/projects/dlx/src/clock_gen_test.vhdl @@ -0,0 +1,33 @@ +-------------------------------------------------------------------------- +-- +-- Copyright (C) 1993, Peter J. Ashenden +-- Mail: Dept. Computer Science +-- University of Adelaide, SA 5005, Australia +-- e-mail: petera@cs.adelaide.edu.au +-- +-- This program 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 1, or (at your option) +-- any later version. +-- +-- This program 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 this program; if not, write to the Free Software +-- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +-- +-------------------------------------------------------------------------- +-- +-- $RCSfile: clock_gen_test.vhdl,v $ $Revision: 2.1 $ $Date: 1993/10/31 20:29:32 $ +-- +-------------------------------------------------------------------------- +-- +-- Entity declaration for test bench for clock generator +-- + + +entity clock_gen_test is +end clock_gen_test; diff --git a/projects/dlx/src/controller-behaviour.vhdl b/projects/dlx/src/controller-behaviour.vhdl new file mode 100644 index 0000000..251c3be --- /dev/null +++ b/projects/dlx/src/controller-behaviour.vhdl @@ -0,0 +1,858 @@ +-------------------------------------------------------------------------- +-- +-- Copyright (C) 1993, Peter J. Ashenden +-- Mail: Dept. Computer Science +-- University of Adelaide, SA 5005, Australia +-- e-mail: petera@cs.adelaide.edu.au +-- +-- This program 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 1, or (at your option) +-- any later version. +-- +-- This program 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 this program; if not, write to the Free Software +-- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +-- +-------------------------------------------------------------------------- +-- +-- $RCSfile: controller-behaviour.vhdl,v $ $Revision: 2.1 $ $Date: 1993/11/02 21:36:38 $ +-- +-------------------------------------------------------------------------- +-- +-- Behavioural architecture of DLX control section. +-- + + +use work.bv_arithmetic.all, std.textio.all; + +architecture behaviour of controller is + +begin -- behaviour + + sequencer : process + + alias IR_opcode : dlx_opcode is current_instruction(0 to 5); + alias IR_sp_func : dlx_sp_func is current_instruction(26 to 31); + alias IR_fp_func : dlx_fp_func is current_instruction(27 to 31); + alias IR_rs1 : dlx_reg_addr is current_instruction(6 to 10); + alias IR_rs2 : dlx_reg_addr is current_instruction(11 to 15); + alias IR_Itype_rd : dlx_reg_addr is current_instruction(11 to 15); + alias IR_Rtype_rd : dlx_reg_addr is current_instruction(16 to 20); + alias IR_immed16 : dlx_immed16 is current_instruction(16 to 31); + alias IR_immed26 : dlx_immed26 is current_instruction(6 to 31); + + variable IR_opcode_num : dlx_opcode_num; + variable IR_sp_func_num : dlx_sp_func_num; + variable IR_fp_func_num : dlx_fp_func_num; + + variable result_of_set_is_1, branch_taken : boolean; + + variable L : line; + + 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 <= width_word after Tpd_clk_ctrl; + ifetch <= '1' after Tpd_clk_ctrl; + mem_enable <= '1' after Tpd_clk_ctrl; + -- wait until phi2, then enable IR input + wait until phi2 = '1'; + ir_latch_en <= '1' after Tpd_clk_ctrl; + -- wait until memory is ready at end of phi2 + loop + wait until phi2 = '0'; + if reset = '1' then + return; + end if; + exit when 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 bus_instruction_fetch; + + procedure bus_data_read(read_width : in 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; + mem_enable <= '1' after Tpd_clk_ctrl; + -- wait until phi2, then enable MDR input + wait until phi2 = '1'; + 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 phi2 = '0'; + if reset = '1' then + return; + end if; + exit when 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 bus_data_read; + + procedure bus_data_write(write_width : in 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 phi2 = '0'; + if reset = '1' then + return; + end if; + exit when 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 bus_data_write; + + procedure do_set_result is + begin + wait until phi1 = '1'; + 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_latch_en <= '1' after Tpd_clk_ctrl; + alu_function <= alu_pass_s2 after Tpd_clk_ctrl; + -- + wait until phi1 = '0'; + alu_latch_en <= '0' after Tpd_clk_ctrl; + const2 <= null after Tpd_clk_const; + -- + wait until phi2 = '1'; + c_latch_en <= '1' after Tpd_clk_ctrl; + -- + wait until phi2 = '0'; + c_latch_en <= '0' after Tpd_clk_ctrl; + end do_set_result; + + procedure do_EX_set_unsigned(immed : boolean) is + begin + wait until phi1 = '1'; + a_out_en <= '1' after Tpd_clk_ctrl; + if immed then + ir_immed_sel2 <= immed_size_16 after Tpd_clk_ctrl; + ir_immed_unsigned2 <= '1' after Tpd_clk_ctrl; + ir_immed_en2 <= '1' after Tpd_clk_ctrl; + else + b_out_en <= '1' after Tpd_clk_ctrl; + end if; + alu_latch_en <= '1' after Tpd_clk_ctrl; + alu_function <= alu_subu after Tpd_clk_ctrl; + -- + wait until phi1 = '0'; + alu_latch_en <= '0' after Tpd_clk_ctrl; + a_out_en <= '0' after Tpd_clk_ctrl; + if immed then + ir_immed_en2 <= '0' after Tpd_clk_ctrl; + else + b_out_en <= '0' after Tpd_clk_ctrl; + end if; + -- + wait until phi2 = '0'; + if immed then + case IR_opcode is + when op_sequi => + result_of_set_is_1 := alu_zero = '1'; + when op_sneui => + result_of_set_is_1 := alu_zero /= '1'; + when op_sltui => + result_of_set_is_1 := alu_overflow = '1'; + when op_sgtui => + result_of_set_is_1 := alu_overflow /= '1' and alu_zero /= '1'; + when op_sleui => + result_of_set_is_1 := alu_overflow = '1' or alu_zero = '1'; + when op_sgeui => + result_of_set_is_1 := alu_overflow /= '1'; + when others => + null; + end case; + else + case IR_sp_func is + when sp_func_sequ => + result_of_set_is_1 := alu_zero = '1'; + when sp_func_sneu => + result_of_set_is_1 := alu_zero /= '1'; + when sp_func_sltu => + result_of_set_is_1 := alu_overflow = '1'; + when sp_func_sgtu => + result_of_set_is_1 := alu_overflow /= '1' and alu_zero /= '1'; + when sp_func_sleu => + result_of_set_is_1 := alu_overflow = '1' or alu_zero = '1'; + when sp_func_sgeu => + result_of_set_is_1 := alu_overflow /= '1'; + when others => + null; + end case; + end if; + -- + do_set_result; + end do_EX_set_unsigned; + + procedure do_EX_set_signed(immed : boolean) is + begin + wait until phi1 = '1'; + a_out_en <= '1' after Tpd_clk_ctrl; + if immed then + ir_immed_sel2 <= immed_size_16 after Tpd_clk_ctrl; + ir_immed_unsigned2 <= '0' after Tpd_clk_ctrl; + ir_immed_en2 <= '1' after Tpd_clk_ctrl; + else + b_out_en <= '1' after Tpd_clk_ctrl; + end if; + alu_latch_en <= '1' after Tpd_clk_ctrl; + alu_function <= alu_sub after Tpd_clk_ctrl; + -- + wait until phi1 = '0'; + alu_latch_en <= '0' after Tpd_clk_ctrl; + a_out_en <= '0' after Tpd_clk_ctrl; + if immed then + ir_immed_en2 <= '0' after Tpd_clk_ctrl; + else + b_out_en <= '0' after Tpd_clk_ctrl; + end if; + -- + wait until phi2 = '0'; + if immed then + case IR_opcode is + when op_seqi => + result_of_set_is_1 := alu_zero = '1'; + when op_snei => + result_of_set_is_1 := alu_zero /= '1'; + when op_slti => + result_of_set_is_1 := alu_negative = '1'; + when op_sgti => + result_of_set_is_1 := alu_negative /= '1' and alu_zero /= '1'; + when op_slei => + result_of_set_is_1 := alu_negative = '1' or alu_zero = '1'; + when op_sgei => + result_of_set_is_1 := alu_negative /= '1'; + when others => + null; + end case; + else + case IR_sp_func is + when sp_func_seq => + result_of_set_is_1 := alu_zero = '1'; + when sp_func_sne => + result_of_set_is_1 := alu_zero /= '1'; + when sp_func_slt => + result_of_set_is_1 := alu_negative = '1'; + when sp_func_sgt => + result_of_set_is_1 := alu_negative /= '1' and alu_zero /= '1'; + when sp_func_sle => + result_of_set_is_1 := alu_negative = '1' or alu_zero = '1'; + when sp_func_sge => + result_of_set_is_1 := alu_negative /= '1'; + when others => + null; + end case; + end if; + -- + do_set_result; + end do_EX_set_signed; + + procedure do_EX_arith_logic is + begin + wait until phi1 = '1'; + a_out_en <= '1' after Tpd_clk_ctrl; + b_out_en <= '1' after Tpd_clk_ctrl; + alu_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 phi1 = '0'; + alu_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 phi2 = '1'; + c_latch_en <= '1' after Tpd_clk_ctrl; + -- + wait until phi2 = '0'; + c_latch_en <= '0' after Tpd_clk_ctrl; + end do_EX_arith_logic; + + procedure do_EX_arith_logic_immed is + begin + wait until phi1 = '1'; + a_out_en <= '1' after Tpd_clk_ctrl; + ir_immed_sel2 <= immed_size_16 after Tpd_clk_ctrl; + if IR_opcode = op_addi or IR_opcode = op_subi then + ir_immed_unsigned2 <= '0' after Tpd_clk_ctrl; + else + ir_immed_unsigned2 <= '1' after Tpd_clk_ctrl; + end if; + ir_immed_en2 <= '1' after Tpd_clk_ctrl; + alu_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 phi1 = '0'; + alu_latch_en <= '0' after Tpd_clk_ctrl; + a_out_en <= '0' after Tpd_clk_ctrl; + ir_immed_en2 <= '0' after Tpd_clk_ctrl; + -- + wait until phi2 = '1'; + c_latch_en <= '1' after Tpd_clk_ctrl; + -- + wait until phi2 = '0'; + c_latch_en <= '0' after Tpd_clk_ctrl; + end do_EX_arith_logic_immed; + + procedure do_EX_link is + begin + wait until phi1 = '1'; + pc_out_en1 <= '1' after Tpd_clk_ctrl; + alu_latch_en <= '1' after Tpd_clk_ctrl; + alu_function <= alu_pass_s1 after Tpd_clk_ctrl; + -- + wait until phi1 = '0'; + alu_latch_en <= '0' after Tpd_clk_ctrl; + pc_out_en1 <= '0' after Tpd_clk_ctrl; + -- + wait until phi2 = '1'; + c_latch_en <= '1' after Tpd_clk_ctrl; + -- + wait until phi2 = '0'; + c_latch_en <= '0' after Tpd_clk_ctrl; + end do_EX_link; + + procedure do_EX_lhi is + begin + wait until phi1 = '1'; + ir_immed_sel1 <= immed_size_16 after Tpd_clk_ctrl; + ir_immed_unsigned1 <= '1' after Tpd_clk_ctrl; + ir_immed_en1 <= '1' after Tpd_clk_ctrl; + const2 <= X"0000_0010" after Tpd_clk_const; -- shift by 16 bits + alu_latch_en <= '1' after Tpd_clk_ctrl; + alu_function <= alu_sll after Tpd_clk_ctrl; + -- + wait until phi1 = '0'; + alu_latch_en <= '0' after Tpd_clk_ctrl; + ir_immed_en1 <= '0' after Tpd_clk_ctrl; + const2 <= null after Tpd_clk_const; + -- + wait until phi2 = '1'; + c_latch_en <= '1' after Tpd_clk_ctrl; + -- + wait until phi2 = '0'; + c_latch_en <= '0' after Tpd_clk_ctrl; + end do_EX_lhi; + + procedure do_EX_branch is + begin + wait until phi1 = '1'; + a_out_en <= '1' after Tpd_clk_ctrl; + const2 <= X"0000_0000" after Tpd_clk_const; + alu_latch_en <= '1' after Tpd_clk_ctrl; + alu_function <= alu_sub after Tpd_clk_ctrl; + -- + wait until phi1 = '0'; + alu_latch_en <= '0' after Tpd_clk_ctrl; + a_out_en <= '0' after Tpd_clk_ctrl; + const2 <= null after Tpd_clk_const; + -- + wait until phi2 = '0'; + if IR_opcode = op_beqz then + branch_taken := alu_zero = '1'; + else + branch_taken := alu_zero /= '1'; + end if; + end do_EX_branch; + + procedure do_EX_load_store is + begin + wait until phi1 = '1'; + a_out_en <= '1' after Tpd_clk_ctrl; + ir_immed_sel2 <= immed_size_16 after Tpd_clk_ctrl; + ir_immed_unsigned2 <= '0' after Tpd_clk_ctrl; + ir_immed_en2 <= '1' after Tpd_clk_ctrl; + alu_function <= alu_add after Tpd_clk_ctrl; + alu_latch_en <= '1' after Tpd_clk_ctrl; + -- + wait until phi1 = '0'; + alu_latch_en <= '0' after Tpd_clk_ctrl; + a_out_en <= '0' after Tpd_clk_ctrl; + ir_immed_en2 <= '0' after Tpd_clk_ctrl; + -- + wait until phi2 = '1'; + mar_latch_en <= '1' after Tpd_clk_ctrl; + -- + wait until phi2 = '0'; + mar_latch_en <= '0' after Tpd_clk_ctrl; + end do_EX_load_store; + + procedure do_MEM_jump is + begin + wait until phi1 = '1'; + pc_out_en1 <= '1' after Tpd_clk_ctrl; + ir_immed_sel2 <= immed_size_26 after Tpd_clk_ctrl; + ir_immed_unsigned2 <= '0' after Tpd_clk_ctrl; + ir_immed_en2 <= '1' after Tpd_clk_ctrl; + alu_latch_en <= '1' after Tpd_clk_ctrl; + alu_function <= alu_add after Tpd_clk_ctrl; + -- + wait until phi1 = '0'; + alu_latch_en <= '0' after Tpd_clk_ctrl; + pc_out_en1 <= '0' after Tpd_clk_ctrl; + ir_immed_en2 <= '0' after Tpd_clk_ctrl; + -- + wait until phi2 = '1'; + pc_latch_en <= '1' after Tpd_clk_ctrl; + -- + wait until phi2 = '0'; + pc_latch_en <= '0' after Tpd_clk_ctrl; + end do_MEM_jump; + + procedure do_MEM_jump_reg is + begin + wait until phi1 = '1'; + a_out_en <= '1' after Tpd_clk_ctrl; + alu_latch_en <= '1' after Tpd_clk_ctrl; + alu_function <= alu_pass_s1 after Tpd_clk_ctrl; + -- + wait until phi1 = '0'; + alu_latch_en <= '0' after Tpd_clk_ctrl; + a_out_en <= '0' after Tpd_clk_ctrl; + -- + wait until phi2 = '1'; + pc_latch_en <= '1' after Tpd_clk_ctrl; + -- + wait until phi2 = '0'; + pc_latch_en <= '0' after Tpd_clk_ctrl; + end do_MEM_jump_reg; + + procedure do_MEM_branch is + begin + wait until phi1 = '1'; + pc_out_en1 <= '1' after Tpd_clk_ctrl; + ir_immed_sel2 <= immed_size_16 after Tpd_clk_ctrl; + ir_immed_unsigned2 <= '0' after Tpd_clk_ctrl; + ir_immed_en2 <= '1' after Tpd_clk_ctrl; + alu_latch_en <= '1' after Tpd_clk_ctrl; + alu_function <= alu_add after Tpd_clk_ctrl; + -- + wait until phi1 = '0'; + alu_latch_en <= '0' after Tpd_clk_ctrl; + pc_out_en1 <= '0' after Tpd_clk_ctrl; + ir_immed_en2 <= '0' after Tpd_clk_ctrl; + -- + wait until phi2 = '1'; + pc_latch_en <= '1' after Tpd_clk_ctrl; + -- + wait until phi2 = '0'; + pc_latch_en <= '0' after Tpd_clk_ctrl; + end do_MEM_branch; + + procedure do_MEM_load is + begin + wait until phi1 = '1'; + bus_data_read(width_word); + if reset = '1' then + return; + end if; + -- + wait until phi1 = '1'; + mdr_out_en1 <= '1' after Tpd_clk_ctrl; + alu_function <= alu_pass_s1 after Tpd_clk_ctrl; + alu_latch_en <= '1' after Tpd_clk_ctrl; + -- + wait until phi1 = '0'; + mdr_out_en1 <= '0' after Tpd_clk_ctrl; + alu_latch_en <= '0' after Tpd_clk_ctrl; + -- + wait until phi2 = '1'; + c_latch_en <= '1' after Tpd_clk_ctrl; + -- + wait until phi2 = '0'; + c_latch_en <= '0' after Tpd_clk_ctrl; + end do_MEM_load; + + procedure do_MEM_store is + begin + wait until phi1 = '1'; + b_out_en <= '1' after Tpd_clk_ctrl; + alu_function <= alu_pass_s2 after Tpd_clk_ctrl; + alu_latch_en <= '1' after Tpd_clk_ctrl; + -- + wait until phi1 = '0'; + b_out_en <= '0' after Tpd_clk_ctrl; + alu_latch_en <= '0' after Tpd_clk_ctrl; + -- + wait until phi2 = '1'; + mdr_mux_sel <= '0' after Tpd_clk_ctrl; + mdr_latch_en <= '1' after Tpd_clk_ctrl; + -- + wait until phi2 = '0'; + mdr_latch_en <= '0' after Tpd_clk_ctrl; + -- + wait until phi1 = '1'; + bus_data_write(width_word); + end do_MEM_store; + + procedure do_WB(Rd : dlx_reg_addr) is + begin + wait until phi1 = '1'; + reg_dest_addr <= Rd after Tpd_clk_ctrl; + reg_write <= '1' after Tpd_clk_ctrl; + -- + wait until phi2 = '0'; + reg_write <= '0' after Tpd_clk_ctrl; + end do_WB; + + + begin -- sequencer + -- + ---------------------------------------------------------------- + -- initialize all control signals + ---------------------------------------------------------------- + if debug then + write(L, string'("controller: initializing")); + writeline(output, L); + end if; + -- + halt <= '0' after Tpd_clk_ctrl; + width <= 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_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_immed_sel1 <= immed_size_16 after Tpd_clk_ctrl; + ir_immed_sel2 <= immed_size_16 after Tpd_clk_ctrl; + ir_immed_unsigned1 <= '0' after Tpd_clk_ctrl; + ir_immed_unsigned2 <= '0' after Tpd_clk_ctrl; + ir_immed_en1 <= '0' after Tpd_clk_ctrl; + ir_immed_en2 <= '0' after Tpd_clk_ctrl; + const1 <= null after Tpd_clk_const; + const2 <= null after Tpd_clk_const; + -- + wait until phi2 = '0' and reset = '0'; + -- + ---------------------------------------------------------------- + -- control loop + ---------------------------------------------------------------- + loop + -- + ---------------------------------------------------------------- + -- fetch next instruction (IF) + ---------------------------------------------------------------- + wait until phi1 = '1'; + if debug then + write(L, string'("controller: instruction fetch")); + writeline(output, L); + end if; + -- + bus_instruction_fetch; + -- + ---------------------------------------------------------------- + -- instruction decode, source register read, and PC increment (ID) + ---------------------------------------------------------------- + wait until phi1 = '1'; + if debug then + write(L, string'("controller: decode, reg-read and PC incr")); + writeline(output, L); + end if; + -- + IR_opcode_num := bv_to_natural(IR_opcode); + IR_sp_func_num := bv_to_natural(IR_sp_func); + IR_fp_func_num := bv_to_natural(IR_fp_func); + -- + 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_latch_en <= '1' after Tpd_clk_ctrl; + alu_function <= alu_addu after Tpd_clk_ctrl; + -- + wait until phi1 = '0'; + a_latch_en <= '0' after Tpd_clk_ctrl; + b_latch_en <= '0' after Tpd_clk_ctrl; + alu_latch_en <= '0' after Tpd_clk_ctrl; + pc_out_en1 <= '0' after Tpd_clk_ctrl; + const2 <= null after Tpd_clk_const; + -- + wait until phi2 = '1'; + pc_latch_en <= '1' after Tpd_clk_ctrl; + -- + wait until phi2 = '0'; + pc_latch_en <= '0' after Tpd_clk_ctrl; + -- + ---------------------------------------------------------------- + -- execute instruction, (EX, MEM, WB) + ---------------------------------------------------------------- + if debug then + write(L, string'("controller: execute")); + writeline(output, L); + end if; + -- + case IR_opcode is + when op_special => + case IR_sp_func is + when sp_func_nop => + null; + 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_add | sp_func_addu | + sp_func_sub | sp_func_subu | + sp_func_and | sp_func_or | sp_func_xor | + sp_func_sll | sp_func_srl | sp_func_sra => + do_EX_arith_logic; + 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 => + assert false + report "MOVI2S instruction not implemented" severity warning; + when sp_func_movs2i => + assert false + report "MOVS2I instruction not implemented" severity warning; + when sp_func_movf => + assert false + report "MOVF instruction not implemented" severity warning; + when sp_func_movd => + assert false + report "MOVD instruction not implemented" severity warning; + when sp_func_movfp2i => + assert false + report "MOVFP2I instruction not implemented" severity warning; + when sp_func_movi2fp => + assert false + report "MOVI2FP instruction not implemented" severity warning; + when others => + assert false + report "undefined special instruction function" severity error; + end case; + when op_fparith => + case IR_fp_func is + when 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_mult | fp_func_multu | fp_func_div | fp_func_divu | + 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 => + assert false + report "floating point instructions not implemented" severity warning; + when others => + assert false + report "undefined floating point instruction function" severity error; + end case; + when op_j => + do_MEM_jump; + when op_jr => + do_MEM_jump_reg; + when op_jal => + do_EX_link; + do_MEM_jump; + do_WB(natural_to_bv(link_reg, 5)); + when op_jalr => + do_EX_link; + do_MEM_jump_reg; + do_WB(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_bfpt => + assert false + report "BFPT instruction not implemented" severity warning; + when op_bfpf => + assert false + report "BFPF instruction not implemented" severity warning; + when op_addi | op_subi | + op_addui | op_subui | + op_andi | op_ori | op_xori | + op_slli | op_srli | op_srai => + do_EX_arith_logic_immed; + do_WB(IR_Itype_rd); + when op_lhi => + do_EX_lhi; + do_WB(IR_Itype_rd); + when op_rfe => + assert false + report "RFE instruction not implemented" severity warning; + when op_trap => + assert false + report "TRAP instruction encountered, execution halted" + severity note; + wait until phi1 = '1'; + halt <= '1' after Tpd_clk_ctrl; + wait until reset = '1'; + exit; + 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_lb => + assert false + report "LB instruction not implemented" severity warning; + when op_lh => + assert false + report "LH instruction not implemented" severity warning; + when op_lw => + do_EX_load_store; + do_MEM_load; + exit when reset = '1'; + do_WB(IR_Itype_rd); + when op_sw => + do_EX_load_store; + do_MEM_store; + exit when reset = '1'; + when op_lbu => + assert false + report "LBU instruction not implemented" severity warning; + when op_lhu => + assert false + report "LHU instruction not implemented" severity warning; + when op_sb => + assert false + report "SB instruction not implemented" severity warning; + when op_sh => + assert false + report "SH instruction not implemented" severity warning; + when op_lf => + assert false + report "LF instruction not implemented" severity warning; + when op_ld => + assert false + report "LD instruction not implemented" severity warning; + when op_sf => + assert false + report "SF instruction not implemented" severity warning; + when op_sd => + assert false + report "SD instruction not implemented" severity warning; + 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 others => + assert false + report "undefined instruction" severity error; + end case; + -- + end loop; + -- + ---------------------------------------------------------------- + -- loop exited on reset + ---------------------------------------------------------------- + assert reset = '1' + report "Internal error: reset code reached with reset = '0'" + severity failure; + -- + -- start again + -- + end process sequencer; + + +end behaviour; diff --git a/projects/dlx/src/controller.vhdl b/projects/dlx/src/controller.vhdl new file mode 100644 index 0000000..fac18f6 --- /dev/null +++ b/projects/dlx/src/controller.vhdl @@ -0,0 +1,71 @@ +-------------------------------------------------------------------------- +-- +-- Copyright (C) 1993, Peter J. Ashenden +-- Mail: Dept. Computer Science +-- University of Adelaide, SA 5005, Australia +-- e-mail: petera@cs.adelaide.edu.au +-- +-- This program 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 1, or (at your option) +-- any later version. +-- +-- This program 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 this program; if not, write to the Free Software +-- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +-- +-------------------------------------------------------------------------- +-- +-- $RCSfile: controller.vhdl,v $ $Revision: 2.1 $ $Date: 1993/11/02 19:19:52 $ +-- +-------------------------------------------------------------------------- +-- +-- Entity declaration for DLX control section. +-- + + +use work.dlx_types.all, + work.dlx_instr.all, + work.alu_types.all, + work.mem_types.all; + +entity controller is + generic (Tpd_clk_ctrl, Tpd_clk_const : Time; + debug : boolean := false; + tag : string := ""; + origin_x, origin_y : real := 0.0); + port (phi1, phi2 : in bit; + reset : in bit; + halt : out bit; + width : out mem_width; + write_enable : out bit; + mem_enable : out bit; + ifetch : out bit; + ready : in bit; + alu_latch_en : out bit; + alu_function : out alu_func; + alu_zero, alu_negative, alu_overflow : in bit; + reg_s1_addr, reg_s2_addr, reg_dest_addr : out dlx_reg_addr; + reg_write : out bit; + c_latch_en : out bit; + a_latch_en, a_out_en : out bit; + b_latch_en, b_out_en : out bit; + temp_latch_en, temp_out_en1, temp_out_en2 : out bit; + iar_latch_en, iar_out_en1, iar_out_en2 : out bit; + pc_latch_en, pc_out_en1, pc_out_en2 : out bit; + mar_latch_en, mar_out_en1, mar_out_en2 : out bit; + mem_addr_mux_sel : out bit; + mdr_latch_en, mdr_out_en1, mdr_out_en2, mdr_out_en3 : out bit; + mdr_mux_sel : out bit; + ir_latch_en : out bit; + ir_immed_sel1, ir_immed_sel2 : out immed_size; + ir_immed_unsigned1, ir_immed_unsigned2 : out bit; + ir_immed_en1, ir_immed_en2 : out bit; + current_instruction : in dlx_word; + const1, const2 : out dlx_word_bus bus); +end controller; diff --git a/projects/dlx/src/distribution-manifest b/projects/dlx/src/distribution-manifest new file mode 100644 index 0000000..a24c9dc --- /dev/null +++ b/projects/dlx/src/distribution-manifest @@ -0,0 +1,63 @@ +distribution-manifest +README +module-directory +simple.s +test_loop.s +images.vhdl +images-body.vhdl +images_test.vhdl +images_test-bench.vhdl +bv_arithmetic.vhdl +bv_arithmetic-body.vhdl +bv_test.vhdl +bv_test-bench.vhdl +clock_gen.vhdl +clock_gen-behaviour.vhdl +clock_gen_test.vhdl +clock_gen_test-bench.vhdl +dlx_types.vhdl +dlx_types-body.vhdl +mem_types.vhdl +memory.vhdl +memory-behaviour.vhdl +memory_test.vhdl +memory_test-bench.vhdl +dlx_instr.vhdl +dlx_instr-body.vhdl +dlx_bus_monitor.vhdl +dlx_bus_monitor-behaviour.vhdl +dlx_test.vhdl +dlx_test-bench.vhdl +dlx.vhdl +dlx-behaviour.vhdl +dlx_test_behaviour.vhdl +dlx-instrumented.vhdl +dlx_test_instrumented.vhdl +alu_types.vhdl +alu.vhdl +alu-behaviour.vhdl +ir.vhdl +ir-behaviour.vhdl +latch.vhdl +latch-behaviour.vhdl +mux2.vhdl +mux2-behaviour.vhdl +reg_1_out.vhdl +reg_1_out-behaviour.vhdl +reg_2_1_out.vhdl +reg_2_1_out-behaviour.vhdl +reg_2_out.vhdl +reg_2_out-behaviour.vhdl +reg_3_out.vhdl +reg_3_out-behaviour.vhdl +reg_file.vhdl +reg_file-behaviour.vhdl +controller.vhdl +controller-behaviour.vhdl +dlx-rtl.vhdl +dlx_test_rtl.vhdl +cache_types.vhdl +cache.vhdl +cache-behaviour.vhdl +dlx_test-bench_cache.vhdl +dlx_test_cache.vhdl diff --git a/projects/dlx/src/dlx-behaviour.vhdl b/projects/dlx/src/dlx-behaviour.vhdl new file mode 100644 index 0000000..4e8507a --- /dev/null +++ b/projects/dlx/src/dlx-behaviour.vhdl @@ -0,0 +1,614 @@ +-------------------------------------------------------------------------- +-- +-- Copyright (C) 1993, Peter J. Ashenden +-- Mail: Dept. Computer Science +-- University of Adelaide, SA 5005, Australia +-- e-mail: petera@cs.adelaide.edu.au +-- +-- This program 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 1, or (at your option) +-- any later version. +-- +-- This program 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 this program; if not, write to the Free Software +-- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +-- +-------------------------------------------------------------------------- +-- +-- $RCSfile: dlx-behaviour.vhdl,v $ $Revision: 2.1 $ $Date: 1993/11/02 17:59:40 $ +-- +-------------------------------------------------------------------------- +-- +-- Behavioural architecture for DLX processor +-- + + +use work.dlx_instr.all, + work.bv_arithmetic.all, + std.textio.all; + + +architecture behaviour of dlx is + +begin -- behaviour + + interpreter: process + + type reg_array is array (reg_index) of dlx_word; + + variable reg : reg_array; + variable fp_reg : reg_array; + + variable PC : dlx_word; + variable user_mode : boolean; + variable overflow, div_by_zero : boolean; + + constant PC_incr : dlx_word := X"0000_0004"; + + variable IR : dlx_word; + alias IR_opcode : dlx_opcode is IR(0 to 5); + alias IR_sp_func : dlx_sp_func is IR(26 to 31); + alias IR_fp_func : dlx_fp_func is IR(27 to 31); + alias IR_rs1 : dlx_reg_addr is IR(6 to 10); + alias IR_rs2 : dlx_reg_addr is IR(11 to 15); + alias IR_Itype_rd : dlx_reg_addr is IR(11 to 15); + alias IR_Rtype_rd : dlx_reg_addr is IR(16 to 20); + alias IR_immed16 : dlx_immed16 is IR(16 to 31); + alias IR_immed26 : dlx_immed26 is IR(6 to 31); + + variable IR_opcode_num : dlx_opcode_num; + variable IR_sp_func_num : dlx_sp_func_num; + variable IR_fp_func_num : dlx_fp_func_num; + variable rs1, rs2, Itype_rd, Rtype_rd : reg_index; + variable mem_addr : dlx_address; + variable mem_data : dlx_word; + + subtype ls_2_addr_bits is bit_vector(1 downto 0); + + variable L : line; + + + procedure write (address : in dlx_address; + data_width : in mem_width; + data : in dlx_word; + signal phi1, phi2 : in bit; -- 2-phase non-overlapping clks + signal reset : in bit; -- synchronous reset input + signal a : out dlx_address; -- address bus output + signal d : inout dlx_word_bus; -- bidirectional data bus + signal width : out mem_width; -- byte/halfword/word + signal write_enable : out bit; -- selects read/write cycle + signal mem_enable : out bit; -- starts memory cycle + signal ifetch : out bit; -- indicates instruction fetch + signal ready : in bit; -- status from memory system + Tpd_clk_out : in time -- clock to output delay + ) is + + begin + wait until phi1 = '1'; + if reset = '1' then + return; + end if; + a <= address after Tpd_clk_out; + width <= data_width after Tpd_clk_out; + d <= data after Tpd_clk_out; + write_enable <= '1' after Tpd_clk_out; + mem_enable <= '1' after Tpd_clk_out; + ifetch <= '0' after Tpd_clk_out; + loop + wait until phi2 = '0'; + exit when ready = '1' or reset = '1'; + end loop; + d <= null after Tpd_clk_out; + write_enable <= '0' after Tpd_clk_out; + mem_enable <= '0' after Tpd_clk_out; + end write; + + + procedure bus_read (address : in dlx_address; + data_width : in mem_width; + instr_fetch : in boolean; + data : out dlx_word; + signal phi1, phi2 : in bit; -- 2-phase non-overlapping clks + signal reset : in bit; -- synchronous reset input + signal a : out dlx_address; -- address bus output + signal d : inout dlx_word_bus; -- bidirectional data bus + signal width : out mem_width; -- byte/halfword/word + signal write_enable : out bit; -- selects read/write cycle + signal mem_enable : out bit; -- starts memory cycle + signal ifetch : out bit; -- indicates instruction eftch + signal ready : in bit; -- status from memory system + Tpd_clk_out : in time -- clock to output delay + ) is + + begin + wait until phi1 = '1'; + if reset = '1' then + return; + end if; + a <= address after Tpd_clk_out; + width <= data_width after Tpd_clk_out; + mem_enable <= '1' after Tpd_clk_out; + ifetch <= bit'val(boolean'pos(instr_fetch)) after Tpd_clk_out; + loop + wait until phi2 = '0'; + exit when ready = '1' or reset = '1'; + end loop; + data := d; + mem_enable <= '0' after Tpd_clk_out; + end bus_read; + + + begin -- interpreter + -- + -- reset the processor + -- + d <= null; + halt <= '0'; + write_enable <= '0'; + mem_enable <= '0'; + reg(0) := X"0000_0000"; + PC := X"0000_0000"; + user_mode := false; + -- + -- fetch-decode-execute loop + -- + loop + -- + -- fetch next instruction + -- + if debug then + write(L, tag); + write(L, string'(": fetching instruction...")); + writeline(output, L); + end if; + -- + bus_read(PC, width_word, true, IR, + phi1, phi2, reset, a, d, width, write_enable, mem_enable, ifetch, ready, + Tpd_clk_out); + exit when reset = '1'; + -- + -- increment the PC to point to the following instruction + -- + if debug then + write(L, tag); + write(L, string'(": incrementing PC...")); + writeline(output, L); + end if; + -- + bv_add(PC, PC_incr, PC, overflow); + -- + -- decode the instruction + -- + if debug then + write(L, tag); + write(L, string'(": decoding instruction...")); + writeline(output, L); + end if; + -- + IR_opcode_num := bv_to_natural(IR_opcode); + IR_sp_func_num := bv_to_natural(IR_sp_func); + IR_fp_func_num := bv_to_natural(IR_fp_func); + rs1 := bv_to_natural(IR_rs1); + rs2 := bv_to_natural(IR_rs2); + Itype_rd := bv_to_natural(IR_Itype_rd); + Rtype_rd := bv_to_natural(IR_Rtype_rd); + -- + -- exectute + -- + if debug then + write(L, tag); + write(L, string'(": executing instruction...")); + writeline(output, L); + end if; + -- + case IR_opcode is + when op_special => + case IR_sp_func is + WHEN sp_func_nop => + null; + when sp_func_sll => + reg(Rtype_rd) := bv_sll(reg(rs1), bv_to_natural(reg(rs2)(27 to 31))); + when sp_func_srl => + reg(Rtype_rd) := bv_srl(reg(rs1), bv_to_natural(reg(rs2)(27 to 31))); + when sp_func_sra => + reg(Rtype_rd) := bv_sra(reg(rs1), bv_to_natural(reg(rs2)(27 to 31))); + when sp_func_sequ => + if reg(rs1) = reg(rs2) then + reg(Rtype_rd) := X"0000_0001"; + else + reg(Rtype_rd) := X"0000_0000"; + end if; + when sp_func_sneu => + if reg(rs1) /= reg(rs2) then + reg(Rtype_rd) := X"0000_0001"; + else + reg(Rtype_rd) := X"0000_0000"; + end if; + when sp_func_sltu => + if reg(rs1) < reg(rs2) then + reg(Rtype_rd) := X"0000_0001"; + else + reg(Rtype_rd) := X"0000_0000"; + end if; + when sp_func_sgtu => + if reg(rs1) > reg(rs2) then + reg(Rtype_rd) := X"0000_0001"; + else + reg(Rtype_rd) := X"0000_0000"; + end if; + when sp_func_sleu => + if reg(rs1) <= reg(rs2) then + reg(Rtype_rd) := X"0000_0001"; + else + reg(Rtype_rd) := X"0000_0000"; + end if; + when sp_func_sgeu => + if reg(rs1) >= reg(rs2) then + reg(Rtype_rd) := X"0000_0001"; + else + reg(Rtype_rd) := X"0000_0000"; + end if; + when sp_func_add => + bv_add(reg(rs1), reg(rs2), reg(Rtype_rd), overflow); + when sp_func_addu => + bv_addu(reg(rs1), reg(rs2), reg(Rtype_rd), overflow); + when sp_func_sub => + bv_sub(reg(rs1), reg(rs2), reg(Rtype_rd), overflow); + when sp_func_subu => + bv_subu(reg(rs1), reg(rs2), reg(Rtype_rd), overflow); + when sp_func_and => + reg(Rtype_rd) := reg(rs1) and reg(rs2); + when sp_func_or => + reg(Rtype_rd) := reg(rs1) or reg(rs2); + when sp_func_xor => + reg(Rtype_rd) := reg(rs1) xor reg(rs2); + when sp_func_seq => + if reg(rs1) = reg(rs2) then + reg(Rtype_rd) := X"0000_0001"; + else + reg(Rtype_rd) := X"0000_0000"; + end if; + when sp_func_sne => + if reg(rs1) /= reg(rs2) then + reg(Rtype_rd) := X"0000_0001"; + else + reg(Rtype_rd) := X"0000_0000"; + end if; + when sp_func_slt => + if bv_lt(reg(rs1), reg(rs2)) then + reg(Rtype_rd) := X"0000_0001"; + else + reg(Rtype_rd) := X"0000_0000"; + end if; + when sp_func_sgt => + if bv_gt(reg(rs1), reg(rs2)) then + reg(Rtype_rd) := X"0000_0001"; + else + reg(Rtype_rd) := X"0000_0000"; + end if; + when sp_func_sle => + if bv_le(reg(rs1), reg(rs2)) then + reg(Rtype_rd) := X"0000_0001"; + else + reg(Rtype_rd) := X"0000_0000"; + end if; + when sp_func_sge => + if bv_ge(reg(rs1), reg(rs2)) then + reg(Rtype_rd) := X"0000_0001"; + else + reg(Rtype_rd) := X"0000_0000"; + end if; + when sp_func_movi2s => + assert false + report "MOVI2S instruction not implemented" severity warning; + when sp_func_movs2i => + assert false + report "MOVS2I instruction not implemented" severity warning; + when sp_func_movf => + assert false + report "MOVF instruction not implemented" severity warning; + when sp_func_movd => + assert false + report "MOVD instruction not implemented" severity warning; + when sp_func_movfp2i => + reg(Rtype_rd) := fp_reg(rs1); + when sp_func_movi2fp => + fp_reg(Rtype_rd) := reg(rs1); + when others => + assert false + report "undefined special instruction function" severity error; + end case; + when op_fparith => + case IR_fp_func is + when fp_func_mult => + bv_mult(fp_reg(rs1), fp_reg(rs2), fp_reg(Rtype_rd), overflow); + when fp_func_multu => + bv_multu(fp_reg(rs1), fp_reg(rs2), fp_reg(Rtype_rd), overflow); + when fp_func_div => + bv_div(fp_reg(rs1), fp_reg(rs2), fp_reg(Rtype_rd), div_by_zero, overflow); + when fp_func_divu => + bv_divu(fp_reg(rs1), fp_reg(rs2), fp_reg(Rtype_rd), div_by_zero); + when 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 => + assert false + report "floating point instructions not implemented" severity warning; + when others => + assert false + report "undefined floating point instruction function" severity error; + end case; + when op_j => + bv_add(PC, bv_sext(IR_immed26, 32), PC, overflow); + when op_jal => + reg(link_reg) := PC; + bv_add(PC, bv_sext(IR_immed26, 32), PC, overflow); + when op_beqz => + if reg(rs1) = X"0000_0000" then + bv_add(PC, bv_sext(IR_immed16, 32), PC, overflow); + end if; + when op_bnez => + if reg(rs1) /= X"0000_0000" then + bv_add(PC, bv_sext(IR_immed16, 32), PC, overflow); + end if; + when op_bfpt => + assert false + report "BFPT instruction not implemented" severity warning; + when op_bfpf => + assert false + report "BFPF instruction not implemented" severity warning; + when op_addi => + bv_add(reg(rs1), bv_sext(IR_immed16, 32), reg(Itype_rd), overflow); + when op_addui => + bv_addu(reg(rs1), bv_zext(IR_immed16, 32), reg(Itype_rd), overflow); + when op_subi => + bv_sub(reg(rs1), bv_sext(IR_immed16, 32), reg(Itype_rd), overflow); + when op_subui => + bv_subu(reg(rs1), bv_zext(IR_immed16, 32), reg(Itype_rd), overflow); + when op_slli => + reg(Itype_rd) := bv_sll(reg(rs1), bv_to_natural(IR_immed16(11 to 15))); + when op_srli => + reg(Itype_rd) := bv_srl(reg(rs1), bv_to_natural(IR_immed16(11 to 15))); + when op_srai => + reg(Itype_rd) := bv_sra(reg(rs1), bv_to_natural(IR_immed16(11 to 15))); + when op_andi => + reg(Itype_rd) := reg(rs1) and bv_zext(IR_immed16, 32); + when op_ori => + reg(Itype_rd) := reg(rs1) or bv_zext(IR_immed16, 32); + when op_xori => + reg(Itype_rd) := reg(rs1) xor bv_zext(IR_immed16, 32); + when op_lhi => + reg(Itype_rd) := IR_immed16 & X"0000"; + when op_rfe => + assert false + report "RFE instruction not implemented" severity warning; + when op_trap => + assert false + report "TRAP instruction encountered, execution halted" + severity note; + halt <= '1' after Tpd_clk_out; + wait until reset = '1'; + exit; + when op_jr => + PC := reg(rs1); + when op_jalr => + reg(link_reg) := PC; + PC := reg(rs1); + when op_seqi => + if reg(rs1) = bv_sext(IR_immed16, 32) then + reg(Itype_rd) := X"0000_0001"; + else + reg(Itype_rd) := X"0000_0000"; + end if; + when op_snei => + if reg(rs1) /= bv_sext(IR_immed16, 32) then + reg(Itype_rd) := X"0000_0001"; + else + reg(Itype_rd) := X"0000_0000"; + end if; + when op_slti => + if bv_lt(reg(rs1), bv_sext(IR_immed16, 32)) then + reg(Itype_rd) := X"0000_0001"; + else + reg(Itype_rd) := X"0000_0000"; + end if; + when op_sgti => + if bv_gt(reg(rs1), bv_sext(IR_immed16, 32)) then + reg(Itype_rd) := X"0000_0001"; + else + reg(Itype_rd) := X"0000_0000"; + end if; + when op_slei => + if bv_le(reg(rs1), bv_sext(IR_immed16, 32)) then + reg(Itype_rd) := X"0000_0001"; + else + reg(Itype_rd) := X"0000_0000"; + end if; + when op_sgei => + if bv_ge(reg(rs1), bv_sext(IR_immed16, 32)) then + reg(Itype_rd) := X"0000_0001"; + else + reg(Itype_rd) := X"0000_0000"; + end if; + when op_lb => + bv_add(reg(rs1), bv_sext(IR_immed16, 32), mem_addr, overflow); + bus_read(mem_addr, width_byte, false, mem_data, + phi1, phi2, reset, a, d, width, write_enable, mem_enable, ifetch, ready, + Tpd_clk_out); + exit when reset = '1'; + case ls_2_addr_bits'(mem_addr(1 downto 0)) is + when B"00" => + reg(Itype_rd) := bv_sext(mem_data(0 to 7), 32); + when B"01" => + reg(Itype_rd) := bv_sext(mem_data(8 to 15), 32); + when B"10" => + reg(Itype_rd) := bv_sext(mem_data(16 to 23), 32); + when B"11" => + reg(Itype_rd) := bv_sext(mem_data(24 to 31), 32); + end case; + when op_lh => + bv_add(reg(rs1), bv_sext(IR_immed16, 32), mem_addr, overflow); + bus_read(mem_addr, width_halfword, false, mem_data, + phi1, phi2, reset, a, d, width, write_enable, mem_enable, ifetch, ready, + Tpd_clk_out); + exit when reset = '1'; + if mem_addr(1) = '0' then + reg(Itype_rd) := bv_sext(mem_data(0 to 15), 32); + else + reg(Itype_rd) := bv_sext(mem_data(16 to 31), 32); + end if; + when op_lw => + bv_add(reg(rs1), bv_sext(IR_immed16, 32), mem_addr, overflow); + bus_read(mem_addr, width_word, false, mem_data, + phi1, phi2, reset, a, d, width, write_enable, mem_enable, ifetch, ready, + Tpd_clk_out); + exit when reset = '1'; + reg(Itype_rd) := mem_data; + when op_lbu => + bv_add(reg(rs1), bv_sext(IR_immed16, 32), mem_addr, overflow); + bus_read(mem_addr, width_byte, false, mem_data, + phi1, phi2, reset, a, d, width, write_enable, mem_enable, ifetch, ready, + Tpd_clk_out); + exit when reset = '1'; + case ls_2_addr_bits'(mem_addr(1 downto 0)) is + when B"00" => + reg(Itype_rd) := bv_zext(mem_data(0 to 7), 32); + when B"01" => + reg(Itype_rd) := bv_zext(mem_data(8 to 15), 32); + when B"10" => + reg(Itype_rd) := bv_zext(mem_data(16 to 23), 32); + when B"11" => + reg(Itype_rd) := bv_zext(mem_data(24 to 31), 32); + end case; + when op_lhu => + bv_add(reg(rs1), bv_sext(IR_immed16, 32), mem_addr, overflow); + bus_read(mem_addr, width_halfword, false, mem_data, + phi1, phi2, reset, a, d, width, write_enable, mem_enable, ifetch, ready, + Tpd_clk_out); + exit when reset = '1'; + if mem_addr(1) = '0' then + reg(Itype_rd) := bv_zext(mem_data(0 to 15), 32); + else + reg(Itype_rd) := bv_zext(mem_data(16 to 31), 32); + end if; + when op_lf => + assert false + report "LF instruction not implemented" severity warning; + when op_ld => + assert false + report "LD instruction not implemented" severity warning; + when op_sb => + bv_add(reg(rs1), bv_sext(IR_immed16, 32), mem_addr, overflow); + mem_data := X"0000_0000"; + case ls_2_addr_bits'(mem_addr(1 downto 0)) is + when B"00" => + mem_data(0 to 7) := reg(Itype_rd)(0 to 7); + when B"01" => + mem_data(8 to 15) := reg(Itype_rd)(0 to 7); + when B"10" => + mem_data(16 to 23) := reg(Itype_rd)(0 to 7); + when B"11" => + mem_data(24 to 31) := reg(Itype_rd)(0 to 7); + end case; + write(mem_addr, width_halfword, mem_data, + phi1, phi2, reset, a, d, width, write_enable, mem_enable, ifetch, ready, + Tpd_clk_out); + exit when reset = '1'; + when op_sh => + bv_add(reg(rs1), bv_sext(IR_immed16, 32), mem_addr, overflow); + mem_data := X"0000_0000"; + if mem_addr(1) = '0' then + mem_data(0 to 15) := reg(Itype_rd)(0 to 15); + else + mem_data(16 to 31) := reg(Itype_rd)(0 to 15); + end if; + write(mem_addr, width_halfword, mem_data, + phi1, phi2, reset, a, d, width, write_enable, mem_enable, ifetch, ready, + Tpd_clk_out); + exit when reset = '1'; + when op_sw => + bv_add(reg(rs1), bv_sext(IR_immed16, 32), mem_addr, overflow); + mem_data := reg(Itype_rd); + write(mem_addr, width_word, mem_data, + phi1, phi2, reset, a, d, width, write_enable, mem_enable, ifetch, ready, + Tpd_clk_out); + exit when reset = '1'; + when op_sf => + assert false + report "SF instruction not implemented" severity warning; + when op_sd => + assert false + report "SD instruction not implemented" severity warning; + when op_sequi => + if reg(rs1) = bv_zext(IR_immed16, 32) then + reg(Itype_rd) := X"0000_0001"; + else + reg(Itype_rd) := X"0000_0000"; + end if; + when op_sneui => + if reg(rs1) /= bv_zext(IR_immed16, 32) then + reg(Itype_rd) := X"0000_0001"; + else + reg(Itype_rd) := X"0000_0000"; + end if; + when op_sltui => + if reg(rs1) < bv_zext(IR_immed16, 32) then + reg(Itype_rd) := X"0000_0001"; + else + reg(Itype_rd) := X"0000_0000"; + end if; + when op_sgtui => + if reg(rs1) > bv_zext(IR_immed16, 32) then + reg(Itype_rd) := X"0000_0001"; + else + reg(Itype_rd) := X"0000_0000"; + end if; + when op_sleui => + if reg(rs1) <= bv_zext(IR_immed16, 32) then + reg(Itype_rd) := X"0000_0001"; + else + reg(Itype_rd) := X"0000_0000"; + end if; + when op_sgeui => + if reg(rs1) >= bv_zext(IR_immed16, 32) then + reg(Itype_rd) := X"0000_0001"; + else + reg(Itype_rd) := X"0000_0000"; + end if; + when others => + assert false + report "undefined instruction" severity error; + end case; + -- + -- fix up R0 in case it was overwritten + -- + reg(0) := X"0000_0000"; + -- + if debug then + write(L, tag); + write(L, string'(": end of execution")); + writeline(output, L); + end if; + -- + end loop; + -- + -- loop is only exited when reset active: wait until it goes inactive + -- + assert reset = '1' + report "reset code reached with reset = '0'" severity error; + wait until phi2 = '0' and reset = '0'; + -- + -- process interpreter now starts again from beginning + -- + end process interpreter; + +end behaviour; diff --git a/projects/dlx/src/dlx-instrumented.vhdl b/projects/dlx/src/dlx-instrumented.vhdl new file mode 100644 index 0000000..0faacd7 --- /dev/null +++ b/projects/dlx/src/dlx-instrumented.vhdl @@ -0,0 +1,687 @@ +-------------------------------------------------------------------------- +-- +-- Copyright (C) 1993, Peter J. Ashenden +-- Mail: Dept. Computer Science +-- University of Adelaide, SA 5005, Australia +-- e-mail: petera@cs.adelaide.edu.au +-- +-- This program 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 1, or (at your option) +-- any later version. +-- +-- This program 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 this program; if not, write to the Free Software +-- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +-- +-------------------------------------------------------------------------- +-- +-- $RCSfile: dlx-instrumented.vhdl,v $ $Revision: 2.1 $ $Date: 1993/11/02 18:36:01 $ +-- +-------------------------------------------------------------------------- +-- +-- Instrumented behavioural architecture for DLX, that generates +-- a files of instruction execution frequencies for a program. +-- + + +use work.dlx_instr.all, + work.bv_arithmetic.all, + std.textio.all; + + +architecture instrumented of dlx is + +begin -- instrumented + + interpreter: process + + type reg_array is array (reg_index) of dlx_word; + + variable reg : reg_array; + variable fp_reg : reg_array; + + variable PC : dlx_word; + variable user_mode : boolean; + variable overflow, div_by_zero : boolean; + + constant PC_incr : dlx_word := X"0000_0004"; + + variable IR : dlx_word; + alias IR_opcode : dlx_opcode is IR(0 to 5); + alias IR_sp_func : dlx_sp_func is IR(26 to 31); + alias IR_fp_func : dlx_fp_func is IR(27 to 31); + alias IR_rs1 : dlx_reg_addr is IR(6 to 10); + alias IR_rs2 : dlx_reg_addr is IR(11 to 15); + alias IR_Itype_rd : dlx_reg_addr is IR(11 to 15); + alias IR_Rtype_rd : dlx_reg_addr is IR(16 to 20); + alias IR_immed16 : dlx_immed16 is IR(16 to 31); + alias IR_immed26 : dlx_immed26 is IR(6 to 31); + + variable IR_opcode_num : dlx_opcode_num; + variable IR_sp_func_num : dlx_sp_func_num; + variable IR_fp_func_num : dlx_fp_func_num; + variable rs1, rs2, Itype_rd, Rtype_rd : reg_index; + variable mem_addr : dlx_address; + variable mem_data : dlx_word; + + subtype ls_2_addr_bits is bit_vector(1 downto 0); + + file data : text is out "dlx_instruction_counts"; + + variable L : line; + + + --------------------------------------------------------------------------- + -- instrumentation: array of counters, one per instruction + --------------------------------------------------------------------------- + + type opcode_count_array is array (dlx_opcode_num) of natural; + type sp_func_count_array is array (dlx_sp_func_num) of natural; + type fp_func_count_array is array (dlx_fp_func_num) of natural; + + variable op_count : opcode_count_array := (others => 0); + variable sp_func_count : sp_func_count_array := (others => 0); + variable fp_func_count : fp_func_count_array := (others => 0); + + variable instr_count : natural := 0; + + --------------------------------------------------------------------------- + -- instrumentation: procedure to dump counter values + --------------------------------------------------------------------------- + + procedure instrumentation_dump is + variable L : line; + begin + for op in dlx_opcode_num loop + write(L, opcode_names(op)); + write(L, ' '); + write(L, op_count(op)); + writeline(data, L); + end loop; + for sp_func in dlx_sp_func_num loop + write(L, sp_func_names(sp_func)); + write(L, ' '); + write(L, sp_func_count(sp_func)); + writeline(data, L); + end loop; + for fp_func in dlx_fp_func_num loop + write(L, fp_func_names(fp_func)); + write(L, ' '); + write(L, fp_func_count(fp_func)); + writeline(data, L); + end loop; + end instrumentation_dump; + + --------------------------------------------------------------------------- + + + procedure write (address : in dlx_address; + data_width : in mem_width; + data : in dlx_word; + signal phi1, phi2 : in bit; -- 2-phase non-overlapping clks + signal reset : in bit; -- synchronous reset input + signal a : out dlx_address; -- address bus output + signal d : inout dlx_word_bus; -- bidirectional data bus + signal width : out mem_width; -- byte/halfword/word + signal write_enable : out bit; -- selects read/write cycle + signal mem_enable : out bit; -- starts memory cycle + signal ifetch : out bit; -- indicates instruction fetch + signal ready : in bit; -- status from memory system + Tpd_clk_out : in time -- clock to output delay + ) is + + begin + wait until phi1 = '1'; + if reset = '1' then + return; + end if; + a <= address after Tpd_clk_out; + width <= data_width after Tpd_clk_out; + d <= data after Tpd_clk_out; + write_enable <= '1' after Tpd_clk_out; + mem_enable <= '1' after Tpd_clk_out; + ifetch <= '0' after Tpd_clk_out; + loop + wait until phi2 = '0'; + exit when ready = '1' or reset = '1'; + end loop; + d <= null after Tpd_clk_out; + write_enable <= '0' after Tpd_clk_out; + mem_enable <= '0' after Tpd_clk_out; + end write; + + + procedure bus_read (address : in dlx_address; + data_width : in mem_width; + instr_fetch : in boolean; + data : out dlx_word; + signal phi1, phi2 : in bit; -- 2-phase non-overlapping clks + signal reset : in bit; -- synchronous reset input + signal a : out dlx_address; -- address bus output + signal d : inout dlx_word_bus; -- bidirectional data bus + signal width : out mem_width; -- byte/halfword/word + signal write_enable : out bit; -- selects read/write cycle + signal mem_enable : out bit; -- starts memory cycle + signal ifetch : out bit; -- indicates instruction eftch + signal ready : in bit; -- status from memory system + Tpd_clk_out : in time -- clock to output delay + ) is + + begin + wait until phi1 = '1'; + if reset = '1' then + return; + end if; + a <= address after Tpd_clk_out; + width <= data_width after Tpd_clk_out; + mem_enable <= '1' after Tpd_clk_out; + ifetch <= bit'val(boolean'pos(instr_fetch)) after Tpd_clk_out; + loop + wait until phi2 = '0'; + exit when ready = '1' or reset = '1'; + end loop; + data := d; + mem_enable <= '0' after Tpd_clk_out; + end bus_read; + + + begin -- interpreter + -- + -- reset the processor + -- + d <= null; + halt <= '0'; + write_enable <= '0'; + mem_enable <= '0'; + reg(0) := X"0000_0000"; + PC := X"0000_0000"; + user_mode := false; + -- + -- fetch-decode-execute loop + -- + loop + -- + -- fetch next instruction + -- + if debug then + write(L, tag); + write(L, string'(": fetching instruction...")); + writeline(output, L); + end if; + -- + bus_read(PC, width_word, true, IR, + phi1, phi2, reset, a, d, width, write_enable, mem_enable, ifetch, ready, + Tpd_clk_out); + exit when reset = '1'; + -- + -- increment the PC to point to the following instruction + -- + if debug then + write(L, tag); + write(L, string'(": incrementing PC...")); + writeline(output, L); + end if; + -- + bv_add(PC, PC_incr, PC, overflow); + -- + -- decode the instruction + -- + if debug then + write(L, tag); + write(L, string'(": decoding instruction...")); + writeline(output, L); + end if; + -- + IR_opcode_num := bv_to_natural(IR_opcode); + IR_sp_func_num := bv_to_natural(IR_sp_func); + IR_fp_func_num := bv_to_natural(IR_fp_func); + rs1 := bv_to_natural(IR_rs1); + rs2 := bv_to_natural(IR_rs2); + Itype_rd := bv_to_natural(IR_Itype_rd); + Rtype_rd := bv_to_natural(IR_Rtype_rd); + -- + ------------------------------------------------------------------------- + -- instrumentation: increment counter for decoded instruction + ------------------------------------------------------------------------- + -- + op_count(IR_opcode_num) := op_count(IR_opcode_num) + 1; + if IR_opcode = op_special then + sp_func_count(IR_sp_func_num) := sp_func_count(IR_sp_func_num) + 1; + elsif IR_opcode = op_fparith then + fp_func_count(IR_fp_func_num) := fp_func_count(IR_fp_func_num) + 1; + end if; + instr_count := instr_count + 1; + -- + ------------------------------------------------------------------------- + -- + -- exectute + -- + if debug then + write(L, tag); + write(L, string'(": executing instruction...")); + writeline(output, L); + end if; + -- + case IR_opcode is + when op_special => + case IR_sp_func is + WHEN sp_func_nop => + null; + when sp_func_sll => + reg(Rtype_rd) := bv_sll(reg(rs1), bv_to_natural(reg(rs2)(27 to 31))); + when sp_func_srl => + reg(Rtype_rd) := bv_srl(reg(rs1), bv_to_natural(reg(rs2)(27 to 31))); + when sp_func_sra => + reg(Rtype_rd) := bv_sra(reg(rs1), bv_to_natural(reg(rs2)(27 to 31))); + when sp_func_sequ => + if reg(rs1) = reg(rs2) then + reg(Rtype_rd) := X"0000_0001"; + else + reg(Rtype_rd) := X"0000_0000"; + end if; + when sp_func_sneu => + if reg(rs1) /= reg(rs2) then + reg(Rtype_rd) := X"0000_0001"; + else + reg(Rtype_rd) := X"0000_0000"; + end if; + when sp_func_sltu => + if reg(rs1) < reg(rs2) then + reg(Rtype_rd) := X"0000_0001"; + else + reg(Rtype_rd) := X"0000_0000"; + end if; + when sp_func_sgtu => + if reg(rs1) > reg(rs2) then + reg(Rtype_rd) := X"0000_0001"; + else + reg(Rtype_rd) := X"0000_0000"; + end if; + when sp_func_sleu => + if reg(rs1) <= reg(rs2) then + reg(Rtype_rd) := X"0000_0001"; + else + reg(Rtype_rd) := X"0000_0000"; + end if; + when sp_func_sgeu => + if reg(rs1) >= reg(rs2) then + reg(Rtype_rd) := X"0000_0001"; + else + reg(Rtype_rd) := X"0000_0000"; + end if; + when sp_func_add => + bv_add(reg(rs1), reg(rs2), reg(Rtype_rd), overflow); + when sp_func_addu => + bv_addu(reg(rs1), reg(rs2), reg(Rtype_rd), overflow); + when sp_func_sub => + bv_sub(reg(rs1), reg(rs2), reg(Rtype_rd), overflow); + when sp_func_subu => + bv_subu(reg(rs1), reg(rs2), reg(Rtype_rd), overflow); + when sp_func_and => + reg(Rtype_rd) := reg(rs1) and reg(rs2); + when sp_func_or => + reg(Rtype_rd) := reg(rs1) or reg(rs2); + when sp_func_xor => + reg(Rtype_rd) := reg(rs1) xor reg(rs2); + when sp_func_seq => + if reg(rs1) = reg(rs2) then + reg(Rtype_rd) := X"0000_0001"; + else + reg(Rtype_rd) := X"0000_0000"; + end if; + when sp_func_sne => + if reg(rs1) /= reg(rs2) then + reg(Rtype_rd) := X"0000_0001"; + else + reg(Rtype_rd) := X"0000_0000"; + end if; + when sp_func_slt => + if bv_lt(reg(rs1), reg(rs2)) then + reg(Rtype_rd) := X"0000_0001"; + else + reg(Rtype_rd) := X"0000_0000"; + end if; + when sp_func_sgt => + if bv_gt(reg(rs1), reg(rs2)) then + reg(Rtype_rd) := X"0000_0001"; + else + reg(Rtype_rd) := X"0000_0000"; + end if; + when sp_func_sle => + if bv_le(reg(rs1), reg(rs2)) then + reg(Rtype_rd) := X"0000_0001"; + else + reg(Rtype_rd) := X"0000_0000"; + end if; + when sp_func_sge => + if bv_ge(reg(rs1), reg(rs2)) then + reg(Rtype_rd) := X"0000_0001"; + else + reg(Rtype_rd) := X"0000_0000"; + end if; + when sp_func_movi2s => + assert false + report "MOVI2S instruction not implemented" severity warning; + when sp_func_movs2i => + assert false + report "MOVS2I instruction not implemented" severity warning; + when sp_func_movf => + assert false + report "MOVF instruction not implemented" severity warning; + when sp_func_movd => + assert false + report "MOVD instruction not implemented" severity warning; + when sp_func_movfp2i => + reg(Rtype_rd) := fp_reg(rs1); + when sp_func_movi2fp => + fp_reg(Rtype_rd) := reg(rs1); + when others => + assert false + report "undefined special instruction function" severity error; + end case; + when op_fparith => + case IR_fp_func is + when fp_func_mult => + bv_mult(fp_reg(rs1), fp_reg(rs2), fp_reg(Rtype_rd), overflow); + when fp_func_multu => + bv_multu(fp_reg(rs1), fp_reg(rs2), fp_reg(Rtype_rd), overflow); + when fp_func_div => + bv_div(fp_reg(rs1), fp_reg(rs2), fp_reg(Rtype_rd), div_by_zero, overflow); + when fp_func_divu => + bv_divu(fp_reg(rs1), fp_reg(rs2), fp_reg(Rtype_rd), div_by_zero); + when 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 => + assert false + report "floating point instructions not implemented" severity warning; + when others => + assert false + report "undefined floating point instruction function" severity error; + end case; + when op_j => + bv_add(PC, bv_sext(IR_immed26, 32), PC, overflow); + when op_jal => + reg(link_reg) := PC; + bv_add(PC, bv_sext(IR_immed26, 32), PC, overflow); + when op_beqz => + if reg(rs1) = X"0000_0000" then + bv_add(PC, bv_sext(IR_immed16, 32), PC, overflow); + end if; + when op_bnez => + if reg(rs1) /= X"0000_0000" then + bv_add(PC, bv_sext(IR_immed16, 32), PC, overflow); + end if; + when op_bfpt => + assert false + report "BFPT instruction not implemented" severity warning; + when op_bfpf => + assert false + report "BFPF instruction not implemented" severity warning; + when op_addi => + bv_add(reg(rs1), bv_sext(IR_immed16, 32), reg(Itype_rd), overflow); + when op_addui => + bv_addu(reg(rs1), bv_zext(IR_immed16, 32), reg(Itype_rd), overflow); + when op_subi => + bv_sub(reg(rs1), bv_sext(IR_immed16, 32), reg(Itype_rd), overflow); + when op_subui => + bv_subu(reg(rs1), bv_zext(IR_immed16, 32), reg(Itype_rd), overflow); + when op_slli => + reg(Itype_rd) := bv_sll(reg(rs1), bv_to_natural(IR_immed16(11 to 15))); + when op_srli => + reg(Itype_rd) := bv_srl(reg(rs1), bv_to_natural(IR_immed16(11 to 15))); + when op_srai => + reg(Itype_rd) := bv_sra(reg(rs1), bv_to_natural(IR_immed16(11 to 15))); + when op_andi => + reg(Itype_rd) := reg(rs1) and bv_zext(IR_immed16, 32); + when op_ori => + reg(Itype_rd) := reg(rs1) or bv_zext(IR_immed16, 32); + when op_xori => + reg(Itype_rd) := reg(rs1) xor bv_zext(IR_immed16, 32); + when op_lhi => + reg(Itype_rd) := IR_immed16 & X"0000"; + when op_rfe => + assert false + report "RFE instruction not implemented" severity warning; + when op_trap => + assert false + report "TRAP instruction encountered, execution halted" + severity note; + halt <= '1' after Tpd_clk_out; + --------------------------------------------------------------------- + -- instrumentation: dump counters + --------------------------------------------------------------------- + instrumentation_dump; + --------------------------------------------------------------------- + wait until reset = '1'; + exit; + when op_jr => + PC := reg(rs1); + when op_jalr => + reg(link_reg) := PC; + PC := reg(rs1); + when op_seqi => + if reg(rs1) = bv_sext(IR_immed16, 32) then + reg(Itype_rd) := X"0000_0001"; + else + reg(Itype_rd) := X"0000_0000"; + end if; + when op_snei => + if reg(rs1) /= bv_sext(IR_immed16, 32) then + reg(Itype_rd) := X"0000_0001"; + else + reg(Itype_rd) := X"0000_0000"; + end if; + when op_slti => + if bv_lt(reg(rs1), bv_sext(IR_immed16, 32)) then + reg(Itype_rd) := X"0000_0001"; + else + reg(Itype_rd) := X"0000_0000"; + end if; + when op_sgti => + if bv_gt(reg(rs1), bv_sext(IR_immed16, 32)) then + reg(Itype_rd) := X"0000_0001"; + else + reg(Itype_rd) := X"0000_0000"; + end if; + when op_slei => + if bv_le(reg(rs1), bv_sext(IR_immed16, 32)) then + reg(Itype_rd) := X"0000_0001"; + else + reg(Itype_rd) := X"0000_0000"; + end if; + when op_sgei => + if bv_ge(reg(rs1), bv_sext(IR_immed16, 32)) then + reg(Itype_rd) := X"0000_0001"; + else + reg(Itype_rd) := X"0000_0000"; + end if; + when op_lb => + bv_add(reg(rs1), bv_sext(IR_immed16, 32), mem_addr, overflow); + bus_read(mem_addr, width_byte, false, mem_data, + phi1, phi2, reset, a, d, width, write_enable, mem_enable, ifetch, ready, + Tpd_clk_out); + exit when reset = '1'; + case ls_2_addr_bits'(mem_addr(1 downto 0)) is + when B"00" => + reg(Itype_rd) := bv_sext(mem_data(0 to 7), 32); + when B"01" => + reg(Itype_rd) := bv_sext(mem_data(8 to 15), 32); + when B"10" => + reg(Itype_rd) := bv_sext(mem_data(16 to 23), 32); + when B"11" => + reg(Itype_rd) := bv_sext(mem_data(24 to 31), 32); + end case; + when op_lh => + bv_add(reg(rs1), bv_sext(IR_immed16, 32), mem_addr, overflow); + bus_read(mem_addr, width_halfword, false, mem_data, + phi1, phi2, reset, a, d, width, write_enable, mem_enable, ifetch, ready, + Tpd_clk_out); + exit when reset = '1'; + if mem_addr(1) = '0' then + reg(Itype_rd) := bv_sext(mem_data(0 to 15), 32); + else + reg(Itype_rd) := bv_sext(mem_data(16 to 31), 32); + end if; + when op_lw => + bv_add(reg(rs1), bv_sext(IR_immed16, 32), mem_addr, overflow); + bus_read(mem_addr, width_word, false, mem_data, + phi1, phi2, reset, a, d, width, write_enable, mem_enable, ifetch, ready, + Tpd_clk_out); + exit when reset = '1'; + reg(Itype_rd) := mem_data; + when op_lbu => + bv_add(reg(rs1), bv_sext(IR_immed16, 32), mem_addr, overflow); + bus_read(mem_addr, width_byte, false, mem_data, + phi1, phi2, reset, a, d, width, write_enable, mem_enable, ifetch, ready, + Tpd_clk_out); + exit when reset = '1'; + case ls_2_addr_bits'(mem_addr(1 downto 0)) is + when B"00" => + reg(Itype_rd) := bv_zext(mem_data(0 to 7), 32); + when B"01" => + reg(Itype_rd) := bv_zext(mem_data(8 to 15), 32); + when B"10" => + reg(Itype_rd) := bv_zext(mem_data(16 to 23), 32); + when B"11" => + reg(Itype_rd) := bv_zext(mem_data(24 to 31), 32); + end case; + when op_lhu => + bv_add(reg(rs1), bv_sext(IR_immed16, 32), mem_addr, overflow); + bus_read(mem_addr, width_halfword, false, mem_data, + phi1, phi2, reset, a, d, width, write_enable, mem_enable, ifetch, ready, + Tpd_clk_out); + exit when reset = '1'; + if mem_addr(1) = '0' then + reg(Itype_rd) := bv_zext(mem_data(0 to 15), 32); + else + reg(Itype_rd) := bv_zext(mem_data(16 to 31), 32); + end if; + when op_lf => + assert false + report "LF instruction not implemented" severity warning; + when op_ld => + assert false + report "LD instruction not implemented" severity warning; + when op_sb => + bv_add(reg(rs1), bv_sext(IR_immed16, 32), mem_addr, overflow); + mem_data := X"0000_0000"; + case ls_2_addr_bits'(mem_addr(1 downto 0)) is + when B"00" => + mem_data(0 to 7) := reg(Itype_rd)(0 to 7); + when B"01" => + mem_data(8 to 15) := reg(Itype_rd)(0 to 7); + when B"10" => + mem_data(16 to 23) := reg(Itype_rd)(0 to 7); + when B"11" => + mem_data(24 to 31) := reg(Itype_rd)(0 to 7); + end case; + write(mem_addr, width_halfword, mem_data, + phi1, phi2, reset, a, d, width, write_enable, mem_enable, ifetch, ready, + Tpd_clk_out); + exit when reset = '1'; + when op_sh => + bv_add(reg(rs1), bv_sext(IR_immed16, 32), mem_addr, overflow); + mem_data := X"0000_0000"; + if mem_addr(1) = '0' then + mem_data(0 to 15) := reg(Itype_rd)(0 to 15); + else + mem_data(16 to 31) := reg(Itype_rd)(0 to 15); + end if; + write(mem_addr, width_halfword, mem_data, + phi1, phi2, reset, a, d, width, write_enable, mem_enable, ifetch, ready, + Tpd_clk_out); + exit when reset = '1'; + when op_sw => + bv_add(reg(rs1), bv_sext(IR_immed16, 32), mem_addr, overflow); + mem_data := reg(Itype_rd); + write(mem_addr, width_word, mem_data, + phi1, phi2, reset, a, d, width, write_enable, mem_enable, ifetch, ready, + Tpd_clk_out); + exit when reset = '1'; + when op_sf => + assert false + report "SF instruction not implemented" severity warning; + when op_sd => + assert false + report "SD instruction not implemented" severity warning; + when op_sequi => + if reg(rs1) = bv_zext(IR_immed16, 32) then + reg(Itype_rd) := X"0000_0001"; + else + reg(Itype_rd) := X"0000_0000"; + end if; + when op_sneui => + if reg(rs1) /= bv_zext(IR_immed16, 32) then + reg(Itype_rd) := X"0000_0001"; + else + reg(Itype_rd) := X"0000_0000"; + end if; + when op_sltui => + if reg(rs1) < bv_zext(IR_immed16, 32) then + reg(Itype_rd) := X"0000_0001"; + else + reg(Itype_rd) := X"0000_0000"; + end if; + when op_sgtui => + if reg(rs1) > bv_zext(IR_immed16, 32) then + reg(Itype_rd) := X"0000_0001"; + else + reg(Itype_rd) := X"0000_0000"; + end if; + when op_sleui => + if reg(rs1) <= bv_zext(IR_immed16, 32) then + reg(Itype_rd) := X"0000_0001"; + else + reg(Itype_rd) := X"0000_0000"; + end if; + when op_sgeui => + if reg(rs1) >= bv_zext(IR_immed16, 32) then + reg(Itype_rd) := X"0000_0001"; + else + reg(Itype_rd) := X"0000_0000"; + end if; + when others => + assert false + report "undefined instruction" severity error; + end case; + -- + -- fix up R0 in case it was overwritten + -- + reg(0) := X"0000_0000"; + -- + if debug then + write(L, tag); + write(L, string'(": end of execution")); + writeline(output, L); + end if; + if instr_count mod 100 = 0 then + write(L, tag); + write(L, string'(": executed ")); + write(L, instr_count); + write(L, string'(" instructions")); + writeline(output, L); + end if; + -- + end loop; + -- + -- loop is only exited when reset active: wait until it goes inactive + -- + assert reset = '1' + report "reset code reached with reset = '0'" severity error; + wait until phi2 = '0' and reset = '0'; + -- + -- process interpreter now starts again from beginning + -- + end process interpreter; + +end instrumented; diff --git a/projects/dlx/src/dlx-rtl.vhdl b/projects/dlx/src/dlx-rtl.vhdl new file mode 100644 index 0000000..21ce048 --- /dev/null +++ b/projects/dlx/src/dlx-rtl.vhdl @@ -0,0 +1,286 @@ +-------------------------------------------------------------------------- +-- +-- Copyright (C) 1993, Peter J. Ashenden +-- Mail: Dept. Computer Science +-- University of Adelaide, SA 5005, Australia +-- e-mail: petera@cs.adelaide.edu.au +-- +-- This program 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 1, or (at your option) +-- any later version. +-- +-- This program 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 this program; if not, write to the Free Software +-- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +-- +-------------------------------------------------------------------------- +-- +-- $RCSfile: dlx-rtl.vhdl,v $ $Revision: 2.1 $ $Date: 1993/11/02 19:54:44 $ +-- +-------------------------------------------------------------------------- +-- +-- Register transfer level architecture of DLX processor. +-- + + +use std.textio.all, + work.images.image_hex, + work.bv_arithmetic.all, + work.dlx_instr.all, + work.alu_types.all; + + +architecture rtl of dlx is + + component alu + port (s1 : in dlx_word; + s2 : in dlx_word; + result : out dlx_word; + latch_en : in bit; + func : in alu_func; + zero, negative, overflow : out bit); + end component; + + component reg_file + port (a1 : in dlx_reg_addr; -- port1 address + q1 : out dlx_word; -- port1 read data + a2 : in dlx_reg_addr; -- port2 address + q2 : out dlx_word; -- port2 read data + a3 : in dlx_reg_addr; -- port3 address + d3 : in dlx_word; -- port3 write data + write_en : in bit); -- port3 write enable + end component; + + component latch + port (d : in dlx_word; + q : out dlx_word; + latch_en : in bit); + end component; + + component reg_1_out + port (d : in dlx_word; + q : out dlx_word_bus bus; + latch_en : in bit; + out_en : in bit); + end component; + + component reg_2_out + port (d : in dlx_word; + q1, q2 : out dlx_word_bus bus; + latch_en : in bit; + out_en1, out_en2 : in bit); + end component; + + component reg_3_out + port (d : in dlx_word; + q1, q2, q3 : out dlx_word_bus bus; + latch_en : in bit; + out_en1, out_en2, out_en3 : in bit); + end component; + + component reg_2_1_out + port (d : in dlx_word; + q1, q2 : out dlx_word_bus bus; + q3 : out dlx_word; + latch_en : in bit; + out_en1, out_en2 : in bit); + end component; + + component mux2 + port (i0, i1 : in dlx_word; + y : out dlx_word; + sel : in bit); + end component; + + component ir + port (d : in dlx_word; -- instruction input from memory + immed_q1, immed_q2 : out dlx_word_bus bus; + ir_out : out dlx_word; -- instruction output to control + latch_en : in bit; + immed_sel1, immed_sel2 : in immed_size; -- select 16-bit or 26-bit immed + immed_unsigned1, immed_unsigned2 : in bit; -- extend immed unsigned/signed + immed_en1, immed_en2 : in bit); -- enable immed const outputs + end component; + + component controller + port (phi1, phi2 : in bit; + reset : in bit; + halt : out bit; + width : out mem_width; + write_enable : out bit; + mem_enable : out bit; + ifetch : out bit; + ready : in bit; + alu_latch_en : out bit; + alu_function : out alu_func; + alu_zero, alu_negative, alu_overflow : in bit; + reg_s1_addr, reg_s2_addr, reg_dest_addr : out dlx_reg_addr; + reg_write : out bit; + c_latch_en : out bit; + a_latch_en, a_out_en : out bit; + b_latch_en, b_out_en : out bit; + temp_latch_en, temp_out_en1, temp_out_en2 : out bit; + iar_latch_en, iar_out_en1, iar_out_en2 : out bit; + pc_latch_en, pc_out_en1, pc_out_en2 : out bit; + mar_latch_en, mar_out_en1, mar_out_en2 : out bit; + mem_addr_mux_sel : out bit; + mdr_latch_en, mdr_out_en1, mdr_out_en2, mdr_out_en3 : out bit; + mdr_mux_sel : out bit; + ir_latch_en : out bit; + ir_immed_sel1, ir_immed_sel2 : out immed_size; + ir_immed_unsigned1, ir_immed_unsigned2 : out bit; + ir_immed_en1, ir_immed_en2 : out bit; + current_instruction : in dlx_word; + const1, const2 : out dlx_word_bus bus); + end component; + + signal s1_bus, s2_bus : dlx_word_bus; + signal dest_bus : dlx_word; + signal alu_latch_en : bit; + signal alu_function : alu_func; + signal alu_zero, alu_negative, alu_overflow : bit; + signal reg_s1_addr, reg_s2_addr, reg_dest_addr : dlx_reg_addr; + signal reg_file_out1, reg_file_out2, reg_file_in : dlx_word; + signal reg_write : bit; + signal a_out_en, a_latch_en : bit; + signal b_out_en, b_latch_en : bit; + signal c_latch_en : bit; + signal temp_out_en1, temp_out_en2, temp_latch_en : bit; + signal iar_out_en1, iar_out_en2, iar_latch_en : bit; + signal pc_out_en1, pc_out_en2, pc_latch_en : bit; + signal pc_to_mem : dlx_word; + signal mar_out_en1, mar_out_en2, mar_latch_en : bit; + signal mar_to_mem : dlx_word; + signal mem_addr_mux_sel : bit; + signal mdr_out_en1, mdr_out_en2, mdr_out_en3, mdr_latch_en : bit; + signal mdr_in : dlx_word; + signal mdr_mux_sel : bit; + signal current_instruction : dlx_word; + signal ir_latch_en : bit; + signal ir_immed_sel1, ir_immed_sel2 : immed_size; + signal ir_immed_unsigned1, ir_immed_unsigned2 : bit; + signal ir_immed_en1, ir_immed_en2 : bit; + +begin + + the_alu : alu + port map (s1 => s1_bus, s2 => s2_bus, result => dest_bus, + latch_en => alu_latch_en, func => alu_function, + zero => alu_zero, negative => alu_negative, overflow => alu_overflow); + + the_reg_file : reg_file + port map (a1 => reg_s1_addr, q1 => reg_file_out1, + a2 => reg_s2_addr, q2 => reg_file_out2, + a3 => reg_dest_addr, d3 => reg_file_in, + write_en => reg_write); + + c_reg : latch + port map (d => dest_bus, q => reg_file_in, latch_en => c_latch_en); + + a_reg : reg_1_out + port map (d => reg_file_out1, q => s1_bus, + latch_en => a_latch_en, out_en => a_out_en); + + b_reg : reg_1_out + port map (d => reg_file_out2, q => s2_bus, + latch_en => b_latch_en, out_en => b_out_en); + + temp_reg : reg_2_out + port map (d => dest_bus, q1 => s1_bus, q2 => s2_bus, + latch_en => temp_latch_en, + out_en1 => temp_out_en1, out_en2 => temp_out_en2); + + iar_reg : reg_2_out + port map (d => dest_bus, q1 => s1_bus, q2 => s2_bus, + latch_en => iar_latch_en, + out_en1 => iar_out_en1, out_en2 => iar_out_en2); + + pc_reg : reg_2_1_out + port map (d => dest_bus, q1 => s1_bus, q2 => s2_bus, q3 => pc_to_mem, + latch_en => pc_latch_en, + out_en1 => pc_out_en1, out_en2 => pc_out_en2); + + mar_reg : reg_2_1_out + port map (d => dest_bus, q1 => s1_bus, q2 => s2_bus, q3 => mar_to_mem, + latch_en => mar_latch_en, + out_en1 => mar_out_en1, out_en2 => mar_out_en2); + + mem_addr_mux : mux2 + port map (i0 => pc_to_mem, i1 => mar_to_mem, y => a, + sel => mem_addr_mux_sel); + + mdr_reg : reg_3_out + port map (d => mdr_in, q1 => s1_bus, q2 => s2_bus, q3 => d, + latch_en => mdr_latch_en, + out_en1 => mdr_out_en1, out_en2 => mdr_out_en2, + out_en3 => mdr_out_en3); + + mdr_mux : mux2 + port map (i0 => dest_bus, i1 => d, y => mdr_in, + sel => mdr_mux_sel); + + instr_reg : ir + port map (d => d, immed_q1 => s1_bus, immed_q2 => s2_bus, + ir_out => current_instruction, + latch_en => ir_latch_en, + immed_sel1 => ir_immed_sel1, immed_sel2 => ir_immed_sel2, + immed_unsigned1 => ir_immed_unsigned1, + immed_unsigned2 => ir_immed_unsigned2, + immed_en1 => ir_immed_en1, immed_en2 => ir_immed_en2); + + the_controller : controller + port map (phi1, phi2, reset, halt, + width, write_enable, mem_enable, ifetch, ready, + alu_latch_en, alu_function, alu_zero, alu_negative, alu_overflow, + reg_s1_addr, reg_s2_addr, reg_dest_addr, reg_write, + c_latch_en, a_latch_en, a_out_en, b_latch_en, b_out_en, + temp_latch_en, temp_out_en1, temp_out_en2, + iar_latch_en, iar_out_en1, iar_out_en2, + pc_latch_en, pc_out_en1, pc_out_en2, + mar_latch_en, mar_out_en1, mar_out_en2, mem_addr_mux_sel, + mdr_latch_en, mdr_out_en1, mdr_out_en2, + mdr_out_en3, mdr_mux_sel, + ir_latch_en, ir_immed_sel1, ir_immed_sel2, + ir_immed_unsigned1, ir_immed_unsigned2, ir_immed_en1, ir_immed_en2, + current_instruction, s1_bus, s2_bus); + + debug_s1 : if debug generate + s1_monitor : process (s1_bus) + variable L : line; + begin + write(L, tag); + write(L, string'(" s1_monitor: ")); + write(L, image_hex(s1_bus)); + writeline(output, L); + end process s1_monitor; + end generate; + + debug_s2 : if debug generate + s2_monitor : process (s2_bus) + variable L : line; + begin + write(L, tag); + write(L, string'(" s2_monitor: ")); + write(L, image_hex(s2_bus)); + writeline(output, L); + end process s2_monitor; + end generate; + + debug_dest : if debug generate + dest_monitor : process (dest_bus) + variable L : line; + begin + write(L, tag); + write(L, string'(" dest_monitor: ")); + write(L, image_hex(dest_bus)); + writeline(output, L); + end process dest_monitor; + end generate; + +end rtl; diff --git a/projects/dlx/src/dlx.vhdl b/projects/dlx/src/dlx.vhdl new file mode 100644 index 0000000..b384d92 --- /dev/null +++ b/projects/dlx/src/dlx.vhdl @@ -0,0 +1,50 @@ +-------------------------------------------------------------------------- +-- +-- Copyright (C) 1993, Peter J. Ashenden +-- Mail: Dept. Computer Science +-- University of Adelaide, SA 5005, Australia +-- e-mail: petera@cs.adelaide.edu.au +-- +-- This program 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 1, or (at your option) +-- any later version. +-- +-- This program 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 this program; if not, write to the Free Software +-- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +-- +-------------------------------------------------------------------------- +-- +-- $RCSfile: dlx.vhdl,v $ $Revision: 2.1 $ $Date: 1993/10/31 22:37:14 $ +-- +-------------------------------------------------------------------------- +-- +-- Entity specification for DLX processor +-- + + +use work.dlx_types.all, + work.mem_types.all; + +entity dlx is + generic (Tpd_clk_out : Time; -- clock to output propagation delay + debug : boolean := false; -- controls debug trace writes + tag : string := ""; + origin_x, origin_y : real := 0.0); + port (phi1, phi2 : in bit; -- 2-phase non-overlapping clocks + reset : in bit; -- synchronous reset input + a : out dlx_address; -- address bus output + d : inout dlx_word_bus bus; -- bidirectional data bus + halt : out bit; -- halt indicator + width : out mem_width; -- byte/haldword/word indicator + write_enable : out bit; -- selects read or write cycle + mem_enable : out bit; -- starts memory cycle + ifetch : out bit; -- indicates instruction fetch + ready : in bit); -- status from memory system +end dlx; diff --git a/projects/dlx/src/dlx_bus_monitor-behaviour.vhdl b/projects/dlx/src/dlx_bus_monitor-behaviour.vhdl new file mode 100644 index 0000000..1873e73 --- /dev/null +++ b/projects/dlx/src/dlx_bus_monitor-behaviour.vhdl @@ -0,0 +1,171 @@ +-------------------------------------------------------------------------- +-- +-- Copyright (C) 1993, Peter J. Ashenden +-- Mail: Dept. Computer Science +-- University of Adelaide, SA 5005, Australia +-- e-mail: petera@cs.adelaide.edu.au +-- +-- This program 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 1, or (at your option) +-- any later version. +-- +-- This program 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 this program; if not, write to the Free Software +-- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +-- +-------------------------------------------------------------------------- +-- +-- $RCSfile: dlx_bus_monitor-behaviour.vhdl,v $ $Revision: 2.1 $ $Date: 1993/10/31 22:36:40 $ +-- +-------------------------------------------------------------------------- +-- +-- Behavioural architecture of DLX bus monitor +-- + + +use std.textio.all, + work.dlx_instr.all, + work.images.image_hex; + + +architecture behaviour of dlx_bus_monitor is + +begin + + monitor : if enable generate + + enabled_monitor : process + + variable write_command, instr_fetch : boolean; + variable L : line; + + begin + monitor_loop : loop + -- + -- wait for a command, valid on leading edge of phi2 + -- + wait until phi2 = '1' and mem_enable = '1'; + -- + -- capture the command information + -- + write_command := write_enable = '1'; + instr_fetch := ifetch = '1'; + write(L, tag); + write(L, string'(": ")); + if write_command then + write(L, string'("D-write to ")); + elsif instr_fetch then + write(L, string'("I-fetch from ")); + else + write(L, string'("D-read from ")); + end if; + write(L, image_hex(a)); + if verbose then + case width is + when width_word => + write(L, string'(", word")); + when width_halfword => + write(L, string'(", halfword")); + when width_byte => + write(L, string'(", byte")); + end case; + if burst = '1' then + write(L, string'(", burst ")); + else + write(L, string'(", single ")); + end if; + writeline(output, L); + else + if not instr_fetch then + write(L, string'(", data")); + else + writeline(output, L); + end if; + end if; + -- + burst_loop : loop + if write_command then + if verbose then + write(L, tag); + write(L, string'(": Write data ")); + write(L, image_hex(d)); + writeline(output, L); + else + write(L, ' '); + write(L, image_hex(d)); + end if; + end if; + -- wait for the response from memory + loop + wait until phi2 = '0'; + if reset = '1' then + exit monitor_loop; + end if; + exit when ready = '1'; + end loop; + if write_command then + if verbose then + write(L, tag); + write(L, string'(": Ready")); + writeline(output, L); + end if; + elsif instr_fetch then + if verbose then + write(L, tag); + write(L, string'(": Ready, instruction ")); + write(L, image_hex(d)); + write(L, string'(" [ ")); + write_instr(L, d); + write(L, string'(" ]")); + writeline(output, L); + else -- brief instruction fetch + write(L, tag); + write(L, string'(": ")); + write(L, image_hex(d)); + write(L, string'(" [ ")); + write_instr(L, d); + write(L, string'(" ]")); + writeline(output, L); + end if; + else -- data fetch + if verbose then + write(L, tag); + write(L, string'(": Ready, data ")); + write(L, image_hex(d)); + writeline(output, L); + else -- brief data fetch + write(L, ' '); + write(L, image_hex(d)); + end if; + end if; + exit burst_loop when burst = '0'; + end loop burst_loop; + -- + if not verbose and not instr_fetch then + writeline(output, L); + end if; + end loop monitor_loop; + -- + -- get here when reset is asserted + -- + assert reset = '1' + report "reset code reached with reset = '0'" severity error; + write(L, string'("DLX_bus_monitor: Reset")); + writeline(output, L); + wait until phi2 = '0' and reset = '0'; + write(L, string'("DLX_bus_monitor: End Reset")); + writeline(output, L); + -- + -- process monitor now starts again from beginning + -- + end process enabled_monitor; + + end generate; + +end behaviour; diff --git a/projects/dlx/src/dlx_bus_monitor.vhdl b/projects/dlx/src/dlx_bus_monitor.vhdl new file mode 100644 index 0000000..ccac761 --- /dev/null +++ b/projects/dlx/src/dlx_bus_monitor.vhdl @@ -0,0 +1,50 @@ +-------------------------------------------------------------------------- +-- +-- Copyright (C) 1993, Peter J. Ashenden +-- Mail: Dept. Computer Science +-- University of Adelaide, SA 5005, Australia +-- e-mail: petera@cs.adelaide.edu.au +-- +-- This program 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 1, or (at your option) +-- any later version. +-- +-- This program 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 this program; if not, write to the Free Software +-- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +-- +-------------------------------------------------------------------------- +-- +-- $RCSfile: dlx_bus_monitor.vhdl,v $ $Revision: 2.1 $ $Date: 1993/10/31 22:35:51 $ +-- +-------------------------------------------------------------------------- +-- +-- Entity declaration of DLX bus monitor +-- + + +use work.dlx_types.all, + work.mem_types.all; + +entity dlx_bus_monitor is + generic (enable : boolean := true; -- enable monitoring + verbose : boolean := true; -- verbose vs brief info + tag : string := ""); + port (phi1, phi2 : in bit; -- 2-phase non-overlapping clocks + reset : in bit; -- synchronous reset + a : in dlx_address; -- address bus + d : in dlx_word; -- data bus + halt : in bit; -- halt indicator + width : in mem_width; -- byte/haldword/word indicator + write_enable : in bit; -- selects read or write cycle + burst : in bit := '0'; -- indicates more to come in burst + mem_enable : in bit; -- starts memory cycle + ifetch : in bit; -- indicates instruction fetch + ready : in bit); -- status from memory system +end dlx_bus_monitor; diff --git a/projects/dlx/src/dlx_instr-body.vhdl b/projects/dlx/src/dlx_instr-body.vhdl new file mode 100644 index 0000000..69b3095 --- /dev/null +++ b/projects/dlx/src/dlx_instr-body.vhdl @@ -0,0 +1,258 @@ +-------------------------------------------------------------------------- +-- +-- Copyright (C) 1993, Peter J. Ashenden +-- Mail: Dept. Computer Science +-- University of Adelaide, SA 5005, Australia +-- e-mail: petera@cs.adelaide.edu.au +-- +-- This program 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 1, or (at your option) +-- any later version. +-- +-- This program 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 this program; if not, write to the Free Software +-- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +-- +-------------------------------------------------------------------------- +-- +-- $RCSfile: dlx_instr-body.vhdl,v $ $Revision: 2.1 $ $Date: 1993/10/31 22:35:21 $ +-- +-------------------------------------------------------------------------- +-- +-- Package body for DLX instructions +-- + + +use std.textio.all, + work.bv_arithmetic.bv_to_natural, + work.bv_arithmetic.bv_to_integer; + + +package body dlx_instr is + + constant opcode_names : opcode_name_array := + ( "SPECIAL ", "FPARITH ", "J ", "JAL ", + "BEQZ ", "BNEZ ", "BFPT ", "BFPF ", + "ADDI ", "ADDUI ", "SUBI ", "SUBUI ", + "ANDI ", "ORI ", "XORI ", "LHI ", + "RFE ", "TRAP ", "JR ", "JALR ", + "SLLI ", "UNDEF_15", "SRLI ", "SRAI ", + "SEQI ", "SNEI ", "SLTI ", "SGTI ", + "SLEI ", "SGEI ", "UNDEF_1E", "UNDEF_1F", + "LB ", "LH ", "UNDEF_22", "LW ", + "LBU ", "LHU ", "LF ", "LD ", + "SB ", "SH ", "UNDEF_2A", "SW ", + "UNDEF_2C", "UNDEF_2D", "SF ", "SD ", + "SEQUI ", "SNEUI ", "SLTUI ", "SGTUI ", + "SLEUI ", "SGEUI ", "UNDEF_36", "UNDEF_37", + "UNDEF_38", "UNDEF_39", "UNDEF_3A", "UNDEF_3B", + "UNDEF_3C", "UNDEF_3D", "UNDEF_3E", "UNDEF_3F" ); + + constant sp_func_names : sp_func_name_array := + ( "NOP ", "UNDEF_01", "UNDEF_02", "UNDEF_03", + "SLL ", "UNDEF_05", "SRL ", "SRA ", + "UNDEF_08", "UNDEF_09", "UNDEF_0A", "UNDEF_0B", + "UNDEF_0C", "UNDEF_0D", "UNDEF_0E", "UNDEF_0F", + "SEQU ", "SNEU ", "SLTU ", "SGTU ", + "SLEU ", "SGEU ", "UNDEF_16", "UNDEF_17", + "UNDEF_18", "UNDEF_19", "UNDEF_1A", "UNDEF_1B", + "UNDEF_1C", "UNDEF_1D", "UNDEF_1E", "UNDEF_1F", + "ADD ", "ADDU ", "SUB ", "SUBU ", + "AND ", "OR ", "XOR ", "UNDEF_27", + "SEQ ", "SNE ", "SLT ", "SGT ", + "SLE ", "SGE ", "UNDEF_2E", "UNDEF_2F", + "MOVI2S ", "MOVS2I ", "MOVF ", "MOVD ", + "MOVFP2I ", "MOVI2FP ", "UNDEF_36", "UNDEF_37", + "UNDEF_38", "UNDEF_39", "UNDEF_3A", "UNDEF_3B", + "UNDEF_3C", "UNDEF_3D", "UNDEF_3E", "UNDEF_3F" ); + + constant fp_func_names : fp_func_name_array := + ( "ADDF ", "SUBF ", "MULTF ", "DIVF ", + "ADDD ", "SUBD ", "MULTD ", "DIVD ", + "CVTF2D ", "CVTF2I ", "CVTD2F ", "CVTD2I ", + "CVTI2F ", "CVTI2D ", "MULT ", "DIV ", + "EQF ", "NEF ", "LTF ", "GTF ", + "LEF ", "GEF ", "MULTU ", "DIVU ", + "EQD ", "NED ", "LTD ", "GTD ", + "LED ", "GED ", "UNDEF_1E", "UNDEF_1F" ); + + + procedure write_reg (L : inout line; reg : reg_index) is + + begin + write(L, 'R'); + write(L, reg); + end write_reg; + + + procedure write_freg (L : inout line; freg : reg_index) is + + begin + write(L, 'F'); + write(L, freg); + end write_freg; + + + procedure write_special_reg (L : inout line; reg : reg_index) is + + begin + case reg is + when 0 => + write(L, string'("IAR")); + WHEN 1 => + write(L, string'("FSR")); + when others => + write(L, string'("SR")); + write(L, reg); + end case; + end write_special_reg; + + + procedure write_instr (L : inout line; instr : in dlx_word) is + + alias instr_opcode : dlx_opcode is instr(0 to 5); + alias instr_sp_func : dlx_sp_func is instr(26 to 31); + alias instr_fp_func : dlx_fp_func is instr(27 to 31); + alias instr_rs1 : dlx_reg_addr is instr(6 to 10); + alias instr_rs2 : dlx_reg_addr is instr(11 to 15); + alias instr_Itype_rd : dlx_reg_addr is instr(11 to 15); + alias instr_Rtype_rd : dlx_reg_addr is instr(16 to 20); + alias instr_immed16 : dlx_immed16 is instr(16 to 31); + alias instr_immed26 : dlx_immed26 is instr(6 to 31); + + variable instr_opcode_num : dlx_opcode_num; + variable instr_sp_func_num : dlx_sp_func_num; + variable instr_fp_func_num : dlx_fp_func_num; + variable rs1 : reg_index; + variable rs2 : reg_index; + variable Itype_rd : reg_index; + variable Rtype_rd : reg_index; + + begin + instr_opcode_num := bv_to_natural(instr_opcode); + instr_sp_func_num := bv_to_natural(instr_sp_func); + instr_fp_func_num := bv_to_natural(instr_fp_func); + rs1 := bv_to_natural(instr_rs1); + rs2 := bv_to_natural(instr_rs2); + Itype_rd := bv_to_natural(instr_Itype_rd); + Rtype_rd := bv_to_natural(instr_Rtype_rd); + -- + if (instr_opcode /= op_special) and (instr_opcode /= op_fparith) then + write(L, opcode_names(instr_opcode_num)); + write(L, ' '); + end if; + case instr_opcode is + when op_special => + write(L, sp_func_names(instr_sp_func_num)); + write(L, ' '); + case instr_sp_func is + when sp_func_nop => + null; + when sp_func_sll | sp_func_srl | sp_func_sra | + sp_func_sequ | sp_func_sneu | sp_func_sltu | + sp_func_sgtu | sp_func_sleu | sp_func_sgeu | + sp_func_add | sp_func_addu | sp_func_sub | sp_func_subu | + sp_func_and | sp_func_or | sp_func_xor | + sp_func_seq | sp_func_sne | sp_func_slt | + sp_func_sgt | sp_func_sle | sp_func_sge => + write_reg(L, Rtype_rd); write(L, string'(", ")); + write_reg(L, rs1); write(L, string'(", ")); + write_reg(L, rs2); + when sp_func_movi2s => + write_special_reg(L, Rtype_rd); write(L, string'(", ")); + write_reg(L, rs1); + when sp_func_movs2i => + write_reg(L, Rtype_rd); write(L, string'(", ")); + write_special_reg(L, rs1); + when sp_func_movf | sp_func_movd => + write_freg(L, Rtype_rd); write(L, string'(", ")); + write_freg(L, rs1); + when sp_func_movfp2i => + write_reg(L, Rtype_rd); write(L, string'(", ")); + write_freg(L, rs1); + when sp_func_movi2fp => + write_freg(L, Rtype_rd); write(L, string'(", ")); + write_reg(L, rs1); + when others => + null; + end case; + when op_fparith => + write(L, fp_func_names(instr_fp_func_num)); + write(L, ' '); + case instr_fp_func is + when 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_mult | fp_func_div | fp_func_multu | fp_func_divu => + write_freg(L, Rtype_rd); write(L, string'(", ")); + write_freg(L, rs1); write(L, string'(", ")); + write_freg(L, rs2); + when fp_func_cvtf2d | fp_func_cvtd2f => + write_freg(L, Rtype_rd); write(L, string'(", ")); + write_freg(L, rs1); + when fp_func_cvtf2i | fp_func_cvtd2i => + write_reg(L, Rtype_rd); write(L, string'(", ")); + write_freg(L, rs1); + when fp_func_cvti2f | fp_func_cvti2d => + write_freg(L, Rtype_rd); write(L, string'(", ")); + write_reg(L, rs1); + when 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 => + write_freg(L, rs1); write(L, string'(", ")); + write_freg(L, rs2); + when others => + null; + end case; + when op_j | op_jal => + write(L, bv_to_integer(instr_immed26)); + when op_beqz | op_bnez => + write_reg(L, rs1); write(L, string'(", ")); + write(L, bv_to_integer(instr_immed16)); + when op_bfpt | op_bfpf => + write(L, bv_to_integer(instr_immed16)); + when op_slli | op_srli | op_srai => + write_reg(L, Itype_rd); write(L, string'(", ")); + write_reg(L, rs1); write(L, string'(", ")); + write(L, bv_to_natural(instr_immed16(11 to 15))); + when op_addi | op_subi | + op_seqi | op_snei | op_slti | op_sgti | op_slei | op_sgei => + write_reg(L, Itype_rd); write(L, string'(", ")); + write_reg(L, rs1); write(L, string'(", ")); + write(L, bv_to_integer(instr_immed16)); + when op_addui | op_subui | op_andi | op_ori | op_xori | + op_sequi | op_sneui | op_sltui | op_sgtui | op_sleui | op_sgeui => + write_reg(L, Itype_rd); write(L, string'(", ")); + write_reg(L, rs1); write(L, string'(", ")); + write(L, bv_to_natural(instr_immed16)); + when op_lhi => + write_reg(L, Itype_rd); write(L, string'(", ")); + write(L, bv_to_natural(instr_immed16)); + when op_rfe => + null; + when op_trap => + write(L, bv_to_natural(instr_immed26)); + when op_jr | op_jalr => + write_reg(L, rs1); + when op_lb | op_lh | op_lw | + op_lbu | op_lhu | op_lf | op_ld => + write_reg(L, Itype_rd); write(L, string'(", ")); + write(L, bv_to_integer(instr_immed16)); write(L, '('); + write_reg(L, rs1); write(L, ')'); + when op_sb | op_sh | op_sw | op_sf | op_sd => + write(L, bv_to_integer(instr_immed16)); + write(L, '('); write_reg(L, rs1); write(L, string'("), ")); + write_reg(L, Itype_rd); + when others => + null; + end case; + end write_instr; + + +end dlx_instr; diff --git a/projects/dlx/src/dlx_instr.vhdl b/projects/dlx/src/dlx_instr.vhdl new file mode 100644 index 0000000..499f11b --- /dev/null +++ b/projects/dlx/src/dlx_instr.vhdl @@ -0,0 +1,257 @@ +-------------------------------------------------------------------------- +-- +-- Copyright (C) 1993, Peter J. Ashenden +-- Mail: Dept. Computer Science +-- University of Adelaide, SA 5005, Australia +-- e-mail: petera@cs.adelaide.edu.au +-- +-- This program 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 1, or (at your option) +-- any later version. +-- +-- This program 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 this program; if not, write to the Free Software +-- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +-- +-------------------------------------------------------------------------- +-- +-- $RCSfile: dlx_instr.vhdl,v $ $Revision: 2.1 $ $Date: 1993/10/31 22:34:41 $ +-- +-------------------------------------------------------------------------- +-- +-- Package specification for DLX instructions +-- + + +use std.textio.line, + work.dlx_types.all; + +package dlx_instr is + +-- A dlx instruction is 32 bits wide. There are three instruction formats: +-- +-- I-type: +-- 0 5 6 10 11 15 16 31 +-- +----------------------------------------------------------------+ +-- | opcode | rs1 | rd | immed16 | +-- +----------------------------------------------------------------+ +-- +-- R-type: +-- 0 5 6 10 11 15 16 20 21 25 26 31 +-- +----------------------------------------------------------------+ +-- | opcode | rs1 | rs2 | rd | | func | +-- +----------------------------------------------------------------+ +-- +-- J-type: +-- 0 5 6 31 +-- +----------------------------------------------------------------+ +-- | opcode | immed26 | +-- +----------------------------------------------------------------+ +-- + + subtype dlx_opcode is bit_vector(0 to 5); + subtype dlx_sp_func is bit_vector(0 to 5); + subtype dlx_fp_func is bit_vector(0 to 4); + subtype dlx_reg_addr is bit_vector(0 to 4); + subtype dlx_immed16 is bit_vector(0 to 15); + subtype dlx_immed26 is bit_vector(0 to 25); + + + constant op_special : dlx_opcode := B"000000"; + constant op_fparith : dlx_opcode := B"000001"; + constant op_j : dlx_opcode := B"000010"; + constant op_jal : dlx_opcode := B"000011"; + constant op_beqz : dlx_opcode := B"000100"; + constant op_bnez : dlx_opcode := B"000101"; + constant op_bfpt : dlx_opcode := B"000110"; + constant op_bfpf : dlx_opcode := B"000111"; + constant op_addi : dlx_opcode := B"001000"; + constant op_addui : dlx_opcode := B"001001"; + constant op_subi : dlx_opcode := B"001010"; + constant op_subui : dlx_opcode := B"001011"; + constant op_andi : dlx_opcode := B"001100"; + constant op_ori : dlx_opcode := B"001101"; + constant op_xori : dlx_opcode := B"001110"; + constant op_lhi : dlx_opcode := B"001111"; + + constant op_rfe : dlx_opcode := B"010000"; + constant op_trap : dlx_opcode := B"010001"; + constant op_jr : dlx_opcode := B"010010"; + constant op_jalr : dlx_opcode := B"010011"; + constant op_slli : dlx_opcode := B"010100"; + constant op_undef_15 : dlx_opcode := B"010101"; + constant op_srli : dlx_opcode := B"010110"; + constant op_srai : dlx_opcode := B"010111"; + constant op_seqi : dlx_opcode := B"011000"; + constant op_snei : dlx_opcode := B"011001"; + constant op_slti : dlx_opcode := B"011010"; + constant op_sgti : dlx_opcode := B"011011"; + constant op_slei : dlx_opcode := B"011100"; + constant op_sgei : dlx_opcode := B"011101"; + constant op_undef_1E : dlx_opcode := B"011110"; + constant op_undef_1F : dlx_opcode := B"011111"; + + constant op_lb : dlx_opcode := B"100000"; + constant op_lh : dlx_opcode := B"100001"; + constant op_undef_22 : dlx_opcode := B"100010"; + constant op_lw : dlx_opcode := B"100011"; + constant op_lbu : dlx_opcode := B"100100"; + constant op_lhu : dlx_opcode := B"100101"; + constant op_lf : dlx_opcode := B"100110"; + constant op_ld : dlx_opcode := B"100111"; + constant op_sb : dlx_opcode := B"101000"; + constant op_sh : dlx_opcode := B"101001"; + constant op_undef_2A : dlx_opcode := B"101010"; + constant op_sw : dlx_opcode := B"101011"; + constant op_undef_2C : dlx_opcode := B"101100"; + constant op_undef_2D : dlx_opcode := B"101101"; + constant op_sf : dlx_opcode := B"101110"; + constant op_sd : dlx_opcode := B"101111"; + + constant op_sequi : dlx_opcode := B"110000"; + constant op_sneui : dlx_opcode := B"110001"; + constant op_sltui : dlx_opcode := B"110010"; + constant op_sgtui : dlx_opcode := B"110011"; + constant op_sleui : dlx_opcode := B"110100"; + constant op_sgeui : dlx_opcode := B"110101"; + constant op_undef_36 : dlx_opcode := B"110110"; + constant op_undef_37 : dlx_opcode := B"110111"; + constant op_undef_38 : dlx_opcode := B"111000"; + constant op_undef_39 : dlx_opcode := B"111001"; + constant op_undef_3A : dlx_opcode := B"111010"; + constant op_undef_3B : dlx_opcode := B"111011"; + constant op_undef_3C : dlx_opcode := B"111100"; + constant op_undef_3D : dlx_opcode := B"111101"; + constant op_undef_3E : dlx_opcode := B"111110"; + constant op_undef_3F : dlx_opcode := B"111111"; + + constant sp_func_nop : dlx_sp_func := B"000000"; + constant sp_func_undef_01 : dlx_sp_func := B"000001"; + constant sp_func_undef_02 : dlx_sp_func := B"000010"; + constant sp_func_undef_03 : dlx_sp_func := B"000011"; + constant sp_func_sll : dlx_sp_func := B"000100"; + constant sp_func_undef_05 : dlx_sp_func := B"000101"; + constant sp_func_srl : dlx_sp_func := B"000110"; + constant sp_func_sra : dlx_sp_func := B"000111"; + constant sp_func_undef_08 : dlx_sp_func := B"001000"; + constant sp_func_undef_09 : dlx_sp_func := B"001001"; + constant sp_func_undef_0A : dlx_sp_func := B"001010"; + constant sp_func_undef_0B : dlx_sp_func := B"001011"; + constant sp_func_undef_0C : dlx_sp_func := B"001100"; + constant sp_func_undef_0D : dlx_sp_func := B"001101"; + constant sp_func_undef_0E : dlx_sp_func := B"001110"; + constant sp_func_undef_0F : dlx_sp_func := B"001111"; + + constant sp_func_sequ : dlx_sp_func := B"010000"; + constant sp_func_sneu : dlx_sp_func := B"010001"; + constant sp_func_sltu : dlx_sp_func := B"010010"; + constant sp_func_sgtu : dlx_sp_func := B"010011"; + constant sp_func_sleu : dlx_sp_func := B"010100"; + constant sp_func_sgeu : dlx_sp_func := B"010101"; + constant sp_func_undef_16 : dlx_sp_func := B"010110"; + constant sp_func_undef_17 : dlx_sp_func := B"010111"; + constant sp_func_undef_18 : dlx_sp_func := B"011000"; + constant sp_func_undef_19 : dlx_sp_func := B"011001"; + constant sp_func_undef_1A : dlx_sp_func := B"011010"; + constant sp_func_undef_1B : dlx_sp_func := B"011011"; + constant sp_func_undef_1C : dlx_sp_func := B"011100"; + constant sp_func_undef_1D : dlx_sp_func := B"011101"; + constant sp_func_undef_1E : dlx_sp_func := B"011110"; + constant sp_func_undef_1F : dlx_sp_func := B"011111"; + + constant sp_func_add : dlx_sp_func := B"100000"; + constant sp_func_addu : dlx_sp_func := B"100001"; + constant sp_func_sub : dlx_sp_func := B"100010"; + constant sp_func_subu : dlx_sp_func := B"100011"; + constant sp_func_and : dlx_sp_func := B"100100"; + constant sp_func_or : dlx_sp_func := B"100101"; + constant sp_func_xor : dlx_sp_func := B"100110"; + constant sp_func_undef_27 : dlx_sp_func := B"100111"; + constant sp_func_seq : dlx_sp_func := B"101000"; + constant sp_func_sne : dlx_sp_func := B"101001"; + constant sp_func_slt : dlx_sp_func := B"101010"; + constant sp_func_sgt : dlx_sp_func := B"101011"; + constant sp_func_sle : dlx_sp_func := B"101100"; + constant sp_func_sge : dlx_sp_func := B"101101"; + constant sp_func_undef_2E : dlx_sp_func := B"101110"; + constant sp_func_undef_2F : dlx_sp_func := B"101111"; + + constant sp_func_movi2s : dlx_sp_func := B"110000"; + constant sp_func_movs2i : dlx_sp_func := B"110001"; + constant sp_func_movf : dlx_sp_func := B"110010"; + constant sp_func_movd : dlx_sp_func := B"110011"; + constant sp_func_movfp2i : dlx_sp_func := B"110100"; + constant sp_func_movi2fp : dlx_sp_func := B"110101"; + constant sp_func_undef_36 : dlx_sp_func := B"110110"; + constant sp_func_undef_37 : dlx_sp_func := B"110111"; + constant sp_func_undef_38 : dlx_sp_func := B"111000"; + constant sp_func_undef_39 : dlx_sp_func := B"111001"; + constant sp_func_undef_3A : dlx_sp_func := B"111010"; + constant sp_func_undef_3B : dlx_sp_func := B"111011"; + constant sp_func_undef_3C : dlx_sp_func := B"111100"; + constant sp_func_undef_3D : dlx_sp_func := B"111101"; + constant sp_func_undef_3E : dlx_sp_func := B"111110"; + constant sp_func_undef_3F : dlx_sp_func := B"111111"; + + constant fp_func_addf : dlx_fp_func := B"00000"; + constant fp_func_subf : dlx_fp_func := B"00001"; + constant fp_func_multf : dlx_fp_func := B"00010"; + constant fp_func_divf : dlx_fp_func := B"00011"; + constant fp_func_addd : dlx_fp_func := B"00100"; + constant fp_func_subd : dlx_fp_func := B"00101"; + constant fp_func_multd : dlx_fp_func := B"00110"; + constant fp_func_divd : dlx_fp_func := B"00111"; + constant fp_func_cvtf2d : dlx_fp_func := B"01000"; + constant fp_func_cvtf2i : dlx_fp_func := B"01001"; + constant fp_func_cvtd2f : dlx_fp_func := B"01010"; + constant fp_func_cvtd2i : dlx_fp_func := B"01011"; + constant fp_func_cvti2f : dlx_fp_func := B"01100"; + constant fp_func_cvti2d : dlx_fp_func := B"01101"; + constant fp_func_mult : dlx_fp_func := B"01110"; + constant fp_func_div : dlx_fp_func := B"01111"; + + constant fp_func_eqf : dlx_fp_func := B"10000"; + constant fp_func_nef : dlx_fp_func := B"10001"; + constant fp_func_ltf : dlx_fp_func := B"10010"; + constant fp_func_gtf : dlx_fp_func := B"10011"; + constant fp_func_lef : dlx_fp_func := B"10100"; + constant fp_func_gef : dlx_fp_func := B"10101"; + constant fp_func_multu : dlx_fp_func := B"10110"; + constant fp_func_divu : dlx_fp_func := B"10111"; + constant fp_func_eqd : dlx_fp_func := B"11000"; + constant fp_func_ned : dlx_fp_func := B"11001"; + constant fp_func_ltd : dlx_fp_func := B"11010"; + constant fp_func_gtd : dlx_fp_func := B"11011"; + constant fp_func_led : dlx_fp_func := B"11100"; + constant fp_func_ged : dlx_fp_func := B"11101"; + constant fp_func_undef_1E : dlx_fp_func := B"11110"; + constant fp_func_undef_1F : dlx_fp_func := B"11111"; + + subtype dlx_opcode_num is natural range 0 to 63; + subtype dlx_sp_func_num is natural range 0 to 63; + subtype dlx_fp_func_num is natural range 0 to 31; + + subtype instr_name is string(1 to 8); + type opcode_name_array is array (dlx_opcode_num) of instr_name; + type sp_func_name_array is array (dlx_sp_func_num) of instr_name; + type fp_func_name_array is array (dlx_fp_func_num) of instr_name; + + constant opcode_names : opcode_name_array; + constant sp_func_names : sp_func_name_array; + constant fp_func_names : fp_func_name_array; + + type immed_size is (immed_size_16, immed_size_26); + + subtype reg_index is natural range 0 to 31; + + constant link_reg : reg_index := 31; + + procedure write_instr (L : inout line; instr : in dlx_word); + +end dlx_instr; diff --git a/projects/dlx/src/dlx_test-bench.vhdl b/projects/dlx/src/dlx_test-bench.vhdl new file mode 100644 index 0000000..98fa114 --- /dev/null +++ b/projects/dlx/src/dlx_test-bench.vhdl @@ -0,0 +1,104 @@ +-------------------------------------------------------------------------- +-- +-- Copyright (C) 1993, Peter J. Ashenden +-- Mail: Dept. Computer Science +-- University of Adelaide, SA 5005, Australia +-- e-mail: petera@cs.adelaide.edu.au +-- +-- This program 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 1, or (at your option) +-- any later version. +-- +-- This program 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 this program; if not, write to the Free Software +-- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +-- +-------------------------------------------------------------------------- +-- +-- $RCSfile: dlx_test-bench.vhdl,v $ $Revision: 2.1 $ $Date: 1993/10/31 22:40:43 $ +-- +-------------------------------------------------------------------------- +-- +-- Architecture for test bench for DLX, +-- consisting of clock generator, memory and bus_monitor +-- + + +use std.textio.all, + work.dlx_types.all, work.mem_types.all; + +architecture bench of dlx_test is + + component clock_gen + port (phi1, phi2 : out bit; + reset : out bit); + end component; + + component memory + port (phi1, phi2 : in bit; + a : in dlx_address; + d : inout dlx_word_bus bus; + width : in mem_width; + write_enable : in bit; + burst : in bit := '0'; + mem_enable : in bit; + ready : out bit); + end component; + + component dlx + port (phi1, phi2 : in bit; -- 2-phase non-overlapping clocks + reset : in bit; -- synchronous reset input + a : out dlx_address; -- address bus output + d : inout dlx_word_bus bus; -- bidirectional data bus + halt : out bit; -- halt indicator + width : out mem_width; -- byte/haldword/word indicator + write_enable : out bit; -- selects read or write cycle + mem_enable : out bit; -- starts memory cycle + ifetch : out bit; -- indicates instruction fetch + ready : in bit); -- status from memory system + end component; + + component dlx_bus_monitor + port (phi1, phi2 : in bit; -- 2-phase non-overlapping clocks + reset : in bit; -- synchronous reset + a : in dlx_address; -- address bus + d : in dlx_word; -- data bus + halt : in bit; -- halt indicator + width : in mem_width; -- byte/haldword/word indicator + write_enable : in bit; -- selects read or write cycle + burst : in bit := '0'; -- indicates more to come in burst + mem_enable : in bit; -- starts memory cycle + ifetch : in bit; -- indicates instruction fetch + ready : in bit); -- status from memory system + end component; + + signal phi1, phi2, reset : bit; + signal a : dlx_address; + signal d : dlx_word_bus bus; + signal halt : bit; + signal width : mem_width; + signal write_enable, mem_enable, ifetch, ready : bit; + +begin + + cg : clock_gen + port map (phi1, phi2, reset); + + mem : memory + port map (phi1, phi2, a, d, width, write_enable, open, mem_enable, ready); + + proc : dlx + port map (phi1, phi2, reset, a, d, + halt, width, write_enable, mem_enable, ifetch, ready); + + bus_monitor : dlx_bus_monitor + port map (phi1, phi2, reset, a, d, + halt, width, write_enable, open, mem_enable, ifetch, ready); + +end bench; diff --git a/projects/dlx/src/dlx_test-bench_cache.vhdl b/projects/dlx/src/dlx_test-bench_cache.vhdl new file mode 100644 index 0000000..f1ead7b --- /dev/null +++ b/projects/dlx/src/dlx_test-bench_cache.vhdl @@ -0,0 +1,139 @@ +-------------------------------------------------------------------------- +-- +-- Copyright (C) 1993, Peter J. Ashenden +-- Mail: Dept. Computer Science +-- University of Adelaide, SA 5005, Australia +-- e-mail: petera@cs.adelaide.edu.au +-- +-- This program 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 1, or (at your option) +-- any later version. +-- +-- This program 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 this program; if not, write to the Free Software +-- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +-- +-------------------------------------------------------------------------- +-- +-- $RCSfile: dlx_test-bench_cache.vhdl,v $ $Revision: 2.1 $ $Date: 1993/11/02 22:14:11 $ +-- +-------------------------------------------------------------------------- +-- +-- Architecture for test bench for DLX and cache, including clock generator, +-- memory and bus monitors for both CPU/cache and cache/memory buses. +-- + + +use std.textio.all, + work.dlx_types.all, + work.mem_types.all; + + +architecture bench_cache of dlx_test is + + component clock_gen + port (phi1, phi2 : out bit; + reset : out bit); + end component; + + component memory + port (phi1, phi2 : in bit; + a : in dlx_address; + d : inout dlx_word_bus bus; + width : in mem_width; + write_enable : in bit; + burst : in bit := '0'; + mem_enable : in bit; + ready : out bit); + end component; + + component dlx + port (phi1, phi2 : in bit; -- 2-phase non-overlapping clocks + reset : in bit; -- synchronous reset input + a : out dlx_address; -- address bus output + d : inout dlx_word_bus bus; -- bidirectional data bus + halt : out bit; -- halt indicator + width : out mem_width; -- byte/haldword/word indicator + write_enable : out bit; -- selects read or write cycle + mem_enable : out bit; -- starts memory cycle + ifetch : out bit; -- indicates instruction fetch + ready : in bit); -- status from memory system + end component; + + component cache + port (phi1, phi2 : in bit; -- 2-phase non-overlapping clocks + reset : in bit; -- synchronous reset input + -- connections to CPU + cpu_enable : in bit; -- starts memory cycle + cpu_width : in mem_width; -- byte/halfword/word indicator + cpu_write : in bit; -- selects read or write cycle + cpu_ready : out bit; -- status from memory system + cpu_a : in dlx_address; -- address bus output + cpu_d : inout dlx_word_bus bus; -- bidirectional data bus + -- connections to memory + mem_enable : out bit; -- starts memory cycle + mem_width : out mem_width; -- byte/halfword/word indicator + mem_write : out bit; -- selects read or write cycle + mem_burst : out bit; -- tell memory to burst txfer + mem_ready : in bit; -- status from memory system + mem_a : out dlx_address; -- address bus output + mem_d : inout dlx_word_bus bus); -- bidirectional data bus + end component; + + component dlx_bus_monitor + port (phi1, phi2 : in bit; -- 2-phase non-overlapping clocks + reset : in bit; -- synchronous reset + a : in dlx_address; -- address bus + d : in dlx_word; -- data bus + halt : in bit; -- halt indicator + width : in mem_width; -- byte/haldword/word indicator + write_enable : in bit; -- selects read or write cycle + burst : in bit := '0'; -- indicates more to come in burst + mem_enable : in bit; -- starts memory cycle + ifetch : in bit; -- indicates instruction fetch + ready : in bit); -- status from memory system + end component; + + signal phi1, phi2, reset : bit; + signal cpu_a, mem_a : dlx_address; + signal cpu_d, mem_d : dlx_word_bus bus; + signal halt : bit; + signal cpu_width, mem_width : mem_width; + signal cpu_enable, mem_enable, + cpu_write, mem_write, + cpu_ready, mem_ready, + mem_burst, ifetch : bit; + +begin + + cg : clock_gen + port map (phi1, phi2, reset); + + mem : memory + port map (phi1, phi2, mem_a, mem_d, + mem_width, mem_write, mem_burst, mem_enable, mem_ready); + + proc : dlx + port map (phi1, phi2, reset, cpu_a, cpu_d, + halt, cpu_width, cpu_write, cpu_enable, ifetch, cpu_ready); + + the_cache : cache + port map (phi1, phi2, reset, + cpu_enable, cpu_width, cpu_write, cpu_ready, cpu_a, cpu_d, + mem_enable, mem_width, mem_write, mem_burst, mem_ready, mem_a, mem_d); + + cpu_cache_monitor : dlx_bus_monitor + port map (phi1, phi2, reset, cpu_a, cpu_d, + halt, cpu_width, cpu_write, open, cpu_enable, ifetch, cpu_ready); + + cache_mem_monitor : dlx_bus_monitor + port map (phi1, phi2, reset, mem_a, mem_d, + halt, mem_width, mem_write, mem_burst, mem_enable, ifetch, mem_ready); + +end bench_cache; diff --git a/projects/dlx/src/dlx_test.vhdl b/projects/dlx/src/dlx_test.vhdl new file mode 100644 index 0000000..02cb3d9 --- /dev/null +++ b/projects/dlx/src/dlx_test.vhdl @@ -0,0 +1,33 @@ +-------------------------------------------------------------------------- +-- +-- Copyright (C) 1993, Peter J. Ashenden +-- Mail: Dept. Computer Science +-- University of Adelaide, SA 5005, Australia +-- e-mail: petera@cs.adelaide.edu.au +-- +-- This program 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 1, or (at your option) +-- any later version. +-- +-- This program 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 this program; if not, write to the Free Software +-- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +-- +-------------------------------------------------------------------------- +-- +-- $RCSfile: dlx_test.vhdl,v $ $Revision: 2.1 $ $Date: 1993/10/31 22:39:49 $ +-- +-------------------------------------------------------------------------- +-- +-- Entity declaration for test bench for DLX +-- + + +entity dlx_test is +end dlx_test; diff --git a/projects/dlx/src/dlx_test_behaviour.vhdl b/projects/dlx/src/dlx_test_behaviour.vhdl new file mode 100644 index 0000000..b8f8f83 --- /dev/null +++ b/projects/dlx/src/dlx_test_behaviour.vhdl @@ -0,0 +1,59 @@ +-------------------------------------------------------------------------- +-- +-- Copyright (C) 1993, Peter J. Ashenden +-- Mail: Dept. Computer Science +-- University of Adelaide, SA 5005, Australia +-- e-mail: petera@cs.adelaide.edu.au +-- +-- This program 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 1, or (at your option) +-- any later version. +-- +-- This program 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 this program; if not, write to the Free Software +-- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +-- +-------------------------------------------------------------------------- +-- +-- $RCSfile: dlx_test_behaviour.vhdl,v $ $Revision: 2.2 $ $Date: 1993/11/02 17:59:08 $ +-- +-------------------------------------------------------------------------- +-- +-- Configuration of test bench for DLX, using architecture behaviour +-- + + +configuration dlx_test_behaviour of dlx_test is + + for bench + + for cg : clock_gen + use entity work.clock_gen(behaviour) + generic map (Tpw => 8 ns, Tps => 2 ns); + end for; + + for mem : memory + use entity work.memory(behaviour) + generic map (mem_size => 65536, + Tac1 => 95 ns, Tacb => 35 ns, Tpd_clk_out => 2 ns); + end for; + + for bus_monitor : dlx_bus_monitor + use entity work.dlx_bus_monitor(behaviour) + generic map (enable => true, verbose => false, tag => "bus monitor"); + end for; + + for proc : dlx + use entity work.dlx(behaviour) + generic map (Tpd_clk_out => 2 ns, debug => true, tag => "proc"); + end for; + + end for; + +end dlx_test_behaviour; diff --git a/projects/dlx/src/dlx_test_cache.vhdl b/projects/dlx/src/dlx_test_cache.vhdl new file mode 100644 index 0000000..1568a97 --- /dev/null +++ b/projects/dlx/src/dlx_test_cache.vhdl @@ -0,0 +1,74 @@ +-------------------------------------------------------------------------- +-- +-- Copyright (C) 1993, Peter J. Ashenden +-- Mail: Dept. Computer Science +-- University of Adelaide, SA 5005, Australia +-- e-mail: petera@cs.adelaide.edu.au +-- +-- This program 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 1, or (at your option) +-- any later version. +-- +-- This program 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 this program; if not, write to the Free Software +-- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +-- +-------------------------------------------------------------------------- +-- +-- $RCSfile: dlx_test_cache.vhdl,v $ $Revision: 2.1 $ $Date: 1993/11/02 22:16:15 $ +-- +-------------------------------------------------------------------------- +-- +-- Configuration of test bench for DLX and cache, +-- using behavioural architectures. +-- + + +configuration dlx_test_cache of dlx_test is + + for bench_cache + + use work.cache_types.all; + + for cg : clock_gen + use entity work.clock_gen(behaviour) + generic map (Tpw => 8 ns, Tps => 2 ns); + end for; + + for mem : memory + use entity work.memory(behaviour) + generic map (mem_size => 65536, + Tac1 => 95 ns, Tacb => 35 ns, Tpd_clk_out => 2 ns); + end for; + + for the_cache : cache + use entity work.cache(behaviour) + generic map (cache_size => 4096, line_size => 16, + associativity => 2, write_strategy => write_through, + Tpd_clk_out => 2 ns); + end for; + + for cpu_cache_monitor : dlx_bus_monitor + use entity work.dlx_bus_monitor(behaviour) + generic map (enable => true, verbose => false, tag => "cpu cache monitor"); + end for; + + for cache_mem_monitor : dlx_bus_monitor + use entity work.dlx_bus_monitor(behaviour) + generic map (enable => true, verbose => false, tag => "cache mem monitor"); + end for; + + for proc : dlx + use entity work.dlx(behaviour) + generic map (Tpd_clk_out => 2 ns, debug => false, tag => "proc"); + end for; + + end for; + +end dlx_test_cache; diff --git a/projects/dlx/src/dlx_test_instrumented.vhdl b/projects/dlx/src/dlx_test_instrumented.vhdl new file mode 100644 index 0000000..46ff96a --- /dev/null +++ b/projects/dlx/src/dlx_test_instrumented.vhdl @@ -0,0 +1,60 @@ +-------------------------------------------------------------------------- +-- +-- Copyright (C) 1993, Peter J. Ashenden +-- Mail: Dept. Computer Science +-- University of Adelaide, SA 5005, Australia +-- e-mail: petera@cs.adelaide.edu.au +-- +-- This program 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 1, or (at your option) +-- any later version. +-- +-- This program 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 this program; if not, write to the Free Software +-- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +-- +-------------------------------------------------------------------------- +-- +-- $RCSfile: dlx_test_instrumented.vhdl,v $ $Revision: 2.1 $ $Date: 1993/11/02 18:37:44 $ +-- +-------------------------------------------------------------------------- +-- +-- Configuration of test bench for DLX, using instrumented +-- architecture of CPU and empty architecture of bus monitor. +-- + + +configuration dlx_test_instrumented of dlx_test is + + for bench + + for cg : clock_gen + use entity work.clock_gen(behaviour) + generic map (Tpw => 8 ns, Tps => 2 ns); + end for; + + for mem : memory + use entity work.memory(behaviour) + generic map (mem_size => 65536, + Tac1 => 95 ns, Tacb => 35 ns, Tpd_clk_out => 2 ns); + end for; + + for bus_monitor : dlx_bus_monitor + use entity work.dlx_bus_monitor(behaviour) + generic map (enable => false); + end for; + + for proc : dlx + use entity work.dlx(instrumented) + generic map (Tpd_clk_out => 2 ns, debug => false, tag => "proc"); + end for; + + end for; + +end dlx_test_instrumented; diff --git a/projects/dlx/src/dlx_test_rtl.vhdl b/projects/dlx/src/dlx_test_rtl.vhdl new file mode 100644 index 0000000..9271536 --- /dev/null +++ b/projects/dlx/src/dlx_test_rtl.vhdl @@ -0,0 +1,103 @@ +-------------------------------------------------------------------------- +-- +-- Copyright (C) 1993, Peter J. Ashenden +-- Mail: Dept. Computer Science +-- University of Adelaide, SA 5005, Australia +-- e-mail: petera@cs.adelaide.edu.au +-- +-- This program 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 1, or (at your option) +-- any later version. +-- +-- This program 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 this program; if not, write to the Free Software +-- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +-- +-------------------------------------------------------------------------- +-- +-- $RCSfile: dlx_test_rtl.vhdl,v $ $Revision: 2.1 $ $Date: 1993/11/02 20:20:00 $ +-- +-------------------------------------------------------------------------- +-- +-- Configuration of DLX test bench using register transfer level +-- architecture of DLX processor. +-- + + +configuration dlx_test_rtl of dlx_test is + + for bench + + for cg : clock_gen + use entity work.clock_gen(behaviour) + generic map (Tpw => 8 ns, Tps => 2 ns); + end for; + + for mem : memory + use entity work.memory(behaviour) + generic map (mem_size => 65536, + Tac1 => 95 ns, Tacb => 35 ns, Tpd_clk_out => 2 ns); + end for; + + for bus_monitor : dlx_bus_monitor + use entity work.dlx_bus_monitor(behaviour) + generic map (enable => true, verbose => true, tag => "bus monitor"); + end for; + + for proc : dlx + use entity work.dlx(rtl) + generic map (Tpd_clk_out => 2 ns, debug => true, tag => "proc"); + for rtl + for all : alu + use entity work.alu(behaviour) + generic map (Tpd => 4 ns); + end for; + for all : reg_file + use entity work.reg_file(behaviour) + generic map (Tac => 4 ns); + end for; + for all : latch + use entity work.latch(behaviour) + generic map (Tpd => 2 ns); + end for; + for all : reg_1_out + use entity work.reg_1_out(behaviour) + generic map (Tpd => 2 ns); + end for; + for all : reg_2_out + use entity work.reg_2_out(behaviour) + generic map (Tpd => 2 ns); + end for; + for all : reg_2_1_out + use entity work.reg_2_1_out(behaviour) + generic map (Tpd => 2 ns); + end for; + for all : reg_3_out + use entity work.reg_3_out(behaviour) + generic map (Tpd => 2 ns); + end for; + for all : mux2 + use entity work.mux2(behaviour) + generic map (Tpd => 1 ns); + end for; + for all : ir + use entity work.ir(behaviour) + generic map (Tpd => 2 ns); + end for; + for the_controller : controller + use entity work.controller(behaviour) + generic map (Tpd_clk_ctrl => 2 ns, Tpd_clk_const => 4 ns, + debug => true); + end for; + end for; -- rtl of dlx + end for; -- proc : dlx + + end for; -- bench of dlx_test + +end dlx_test_rtl; diff --git a/projects/dlx/src/dlx_types-body.vhdl b/projects/dlx/src/dlx_types-body.vhdl new file mode 100644 index 0000000..1dc4c51 --- /dev/null +++ b/projects/dlx/src/dlx_types-body.vhdl @@ -0,0 +1,45 @@ +-------------------------------------------------------------------------- +-- +-- Copyright (C) 1993, Peter J. Ashenden +-- Mail: Dept. Computer Science +-- University of Adelaide, SA 5005, Australia +-- e-mail: petera@cs.adelaide.edu.au +-- +-- This program 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 1, or (at your option) +-- any later version. +-- +-- This program 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 this program; if not, write to the Free Software +-- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +-- +-------------------------------------------------------------------------- +-- +-- $RCSfile: dlx_types-body.vhdl,v $ $Revision: 2.1 $ $Date: 1993/10/31 20:37:38 $ +-- +-------------------------------------------------------------------------- +-- +-- Package body for types used in dlx model +-- + + +package body dlx_types is + + function resolve_dlx_word (values : in dlx_word_array) return dlx_word is + + variable result : dlx_word := X"0000_0000"; + + begin + for i in values'range loop + result := result or values(i); + end loop; + return result; + end resolve_dlx_word; + +end dlx_types; diff --git a/projects/dlx/src/dlx_types.vhdl b/projects/dlx/src/dlx_types.vhdl new file mode 100644 index 0000000..feec534 --- /dev/null +++ b/projects/dlx/src/dlx_types.vhdl @@ -0,0 +1,44 @@ +-------------------------------------------------------------------------- +-- +-- Copyright (C) 1993, Peter J. Ashenden +-- Mail: Dept. Computer Science +-- University of Adelaide, SA 5005, Australia +-- e-mail: petera@cs.adelaide.edu.au +-- +-- This program 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 1, or (at your option) +-- any later version. +-- +-- This program 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 this program; if not, write to the Free Software +-- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +-- +-------------------------------------------------------------------------- +-- +-- $RCSfile: dlx_types.vhdl,v $ $Revision: 2.1 $ $Date: 1993/10/31 20:35:20 $ +-- +-------------------------------------------------------------------------- +-- +-- Package specification for types used in dlx model +-- + + +package dlx_types is + + subtype dlx_word is bit_vector(0 to 31); -- bit 0 is msb + subtype dlx_halfword is bit_vector(0 to 15); -- bit 0 is msb + subtype dlx_byte is bit_vector(0 to 7); -- bit 0 is msb + + type dlx_word_array is array (positive range <>) of dlx_word; + function resolve_dlx_word (values : in dlx_word_array) return dlx_word; + subtype dlx_word_bus is resolve_dlx_word dlx_word; + + subtype dlx_address is bit_vector(31 downto 0); -- bit 0 is lsb + +end dlx_types; diff --git a/projects/dlx/src/images-body.vhdl b/projects/dlx/src/images-body.vhdl new file mode 100644 index 0000000..61edbce --- /dev/null +++ b/projects/dlx/src/images-body.vhdl @@ -0,0 +1,167 @@ +-------------------------------------------------------------------------- +-- +-- Copyright (C) 1993, Peter J. Ashenden +-- Mail: Dept. Computer Science +-- University of Adelaide, SA 5005, Australia +-- e-mail: petera@cs.adelaide.edu.au +-- +-- This program 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 1, or (at your option) +-- any later version. +-- +-- This program 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 this program; if not, write to the Free Software +-- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +-- +-------------------------------------------------------------------------- +-- +-- $RCSfile: images-body.vhdl,v $ $Revision: 1.1 $ $Date: 1993/10/25 20:46:18 $ +-- +-------------------------------------------------------------------------- +-- +-- Images package body. +-- +-- Functions that return the string image of values. +-- Each image is a correctly formed literal according to the +-- rules of VHDL-93. +-- +-------------------------------------------------------------------------- + +package body images is + + + -- Image of bit vector as binary bit string literal + -- (in the format B"...") + -- Length of result is bv'length + 3 + + function image (bv : in bit_vector) return string is + + alias bv_norm : bit_vector(1 to bv'length) is bv; + variable result : string(1 to bv'length + 3); + + begin + result(1) := 'B'; + result(2) := '"'; + for index in bv_norm'range loop + if bv_norm(index) = '0' then + result(index + 2) := '0'; + else + result(index + 2) := '1'; + end if; + end loop; + result(bv'length + 3) := '"'; + return result; + end image; + + ---------------------------------------------------------------- + + -- Image of bit vector as octal bit string literal + -- (in the format O"...") + -- Length of result is (bv'length+2)/3 + 3 + + function image_octal (bv : in bit_vector) return string is + + constant nr_digits : natural := (bv'length + 2) / 3; + variable result : string(1 to nr_digits + 3); + variable bits : bit_vector(0 to 3*nr_digits - 1) := (others => '0'); + variable three_bits : bit_vector(0 to 2); + variable digit : character; + + begin + result(1) := 'O'; + result(2) := '"'; + bits(bits'right - bv'length + 1 to bits'right) := bv; + for index in 0 to nr_digits - 1 loop + three_bits := bits(3*index to 3*index + 2); + case three_bits is + when b"000" => + digit := '0'; + when b"001" => + digit := '1'; + when b"010" => + digit := '2'; + when b"011" => + digit := '3'; + when b"100" => + digit := '4'; + when b"101" => + digit := '5'; + when b"110" => + digit := '6'; + when b"111" => + digit := '7'; + end case; + result(index + 3) := digit; + end loop; + result(nr_digits + 3) := '"'; + return result; + end image_octal; + + ---------------------------------------------------------------- + + -- Image of bit vector as hex bit string literal + -- (in the format X"...") + -- Length of result is (bv'length+3)/4 + 3 + + function image_hex (bv : in bit_vector) return string is + + constant nr_digits : natural := (bv'length + 3) / 4; + variable result : string(1 to nr_digits + 3); + variable bits : bit_vector(0 to 4*nr_digits - 1) := (others => '0'); + variable four_bits : bit_vector(0 to 3); + variable digit : character; + + begin + result(1) := 'X'; + result(2) := '"'; + bits(bits'right - bv'length + 1 to bits'right) := bv; + for index in 0 to nr_digits - 1 loop + four_bits := bits(4*index to 4*index + 3); + case four_bits is + when b"0000" => + digit := '0'; + when b"0001" => + digit := '1'; + when b"0010" => + digit := '2'; + when b"0011" => + digit := '3'; + when b"0100" => + digit := '4'; + when b"0101" => + digit := '5'; + when b"0110" => + digit := '6'; + when b"0111" => + digit := '7'; + when b"1000" => + digit := '8'; + when b"1001" => + digit := '9'; + when b"1010" => + digit := 'A'; + when b"1011" => + digit := 'B'; + when b"1100" => + digit := 'C'; + when b"1101" => + digit := 'D'; + when b"1110" => + digit := 'E'; + when b"1111" => + digit := 'F'; + end case; + result(index + 3) := digit; + end loop; + result(nr_digits + 3) := '"'; + return result; + end image_hex; + + +end images; diff --git a/projects/dlx/src/images.vhdl b/projects/dlx/src/images.vhdl new file mode 100644 index 0000000..72ac30a --- /dev/null +++ b/projects/dlx/src/images.vhdl @@ -0,0 +1,61 @@ +-------------------------------------------------------------------------- +-- +-- Copyright (C) 1993, Peter J. Ashenden +-- Mail: Dept. Computer Science +-- University of Adelaide, SA 5005, Australia +-- e-mail: petera@cs.adelaide.edu.au +-- +-- This program 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 1, or (at your option) +-- any later version. +-- +-- This program 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 this program; if not, write to the Free Software +-- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +-- +-------------------------------------------------------------------------- +-- +-- $RCSfile: images.vhdl,v $ $Revision: 1.1 $ $Date: 1993/10/25 20:45:45 $ +-- +-------------------------------------------------------------------------- +-- +-- Images package specification. +-- +-- Functions that return the string image of values. +-- Each image is a correctly formed literal according to the +-- rules of VHDL-93. +-- +-------------------------------------------------------------------------- + +package images is + + + -- Image of bit vector as binary bit string literal + -- (in the format B"...") + -- Length of result is bv'length + 3 + + function image (bv : in bit_vector) return string; + + + -- Image of bit vector as octal bit string literal + -- (in the format O"...") + -- Length of result is (bv'length+2)/3 + 3 + + function image_octal (bv : in bit_vector) return string; + + + -- Image of bit vector as hex bit string literal + -- (in the format X"...") + -- Length of result is (bv'length+3)/4 + 3 + + function image_hex (bv : in bit_vector) return string; + + +end images; + diff --git a/projects/dlx/src/images_test-bench.vhdl b/projects/dlx/src/images_test-bench.vhdl new file mode 100644 index 0000000..619ce70 --- /dev/null +++ b/projects/dlx/src/images_test-bench.vhdl @@ -0,0 +1,89 @@ +-------------------------------------------------------------------------- +-- +-- Copyright (C) 1993, Peter J. Ashenden +-- Mail: Dept. Computer Science +-- University of Adelaide, SA 5005, Australia +-- e-mail: petera@cs.adelaide.edu.au +-- +-- This program 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 1, or (at your option) +-- any later version. +-- +-- This program 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 this program; if not, write to the Free Software +-- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +-- +-------------------------------------------------------------------------- +-- +-- $RCSfile: images_test-bench.vhdl,v $ $Revision: 1.1 $ $Date: 1993/10/25 20:47:40 $ +-- +-------------------------------------------------------------------------- +-- +-- Architecture declaration for test bench for images package +-- + +use std.textio.all; + +use work.images.all; + +architecture bench of images_test is + +begin + + process + + variable L : line; + + begin + ---------------------------------------------------------------- + -- Test binary image of a bit vector + ---------------------------------------------------------------- + write(L, image(b"01")); + writeline(output, L); + write(L, image(b"01011010")); + writeline(output, L); + + ---------------------------------------------------------------- + -- Test octal image of a bit vector + ---------------------------------------------------------------- + write(L, image_octal(o"05")); + writeline(output, L); + write(L, image_octal(o"370")); + writeline(output, L); + write(L, image_octal(b"1")); + writeline(output, L); + write(L, image_octal(b"11000")); + writeline(output, L); + + ---------------------------------------------------------------- + -- Test hex image of a bit vector + ---------------------------------------------------------------- + write(L, image_hex(x"0C")); + writeline(output, L); + write(L, image_hex(x"F1")); + writeline(output, L); + write(L, image_hex("1")); + writeline(output, L); + write(L, image_hex(b"1001000")); + writeline(output, L); + + ---------------------------------------------------------------- + -- Add further tests here ... + ---------------------------------------------------------------- + + + ---------------------------------------------------------------- + -- end of tests + ---------------------------------------------------------------- + wait; + end process; + +end bench; + + diff --git a/projects/dlx/src/images_test.vhdl b/projects/dlx/src/images_test.vhdl new file mode 100644 index 0000000..5eb4389 --- /dev/null +++ b/projects/dlx/src/images_test.vhdl @@ -0,0 +1,35 @@ +-------------------------------------------------------------------------- +-- +-- Copyright (C) 1993, Peter J. Ashenden +-- Mail: Dept. Computer Science +-- University of Adelaide, SA 5005, Australia +-- e-mail: petera@cs.adelaide.edu.au +-- +-- This program 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 1, or (at your option) +-- any later version. +-- +-- This program 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 this program; if not, write to the Free Software +-- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +-- +-------------------------------------------------------------------------- +-- +-- $RCSfile: images_test.vhdl,v $ $Revision: 1.1 $ $Date: 1993/10/25 20:47:12 $ +-- +-------------------------------------------------------------------------- +-- +-- Entity declaration for test bench for images package +-- + +entity images_test is + +end images_test; + + diff --git a/projects/dlx/src/ir-behaviour.vhdl b/projects/dlx/src/ir-behaviour.vhdl new file mode 100644 index 0000000..ff432f2 --- /dev/null +++ b/projects/dlx/src/ir-behaviour.vhdl @@ -0,0 +1,88 @@ +-------------------------------------------------------------------------- +-- +-- Copyright (C) 1993, Peter J. Ashenden +-- Mail: Dept. Computer Science +-- University of Adelaide, SA 5005, Australia +-- e-mail: petera@cs.adelaide.edu.au +-- +-- This program 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 1, or (at your option) +-- any later version. +-- +-- This program 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 this program; if not, write to the Free Software +-- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +-- +-------------------------------------------------------------------------- +-- +-- $RCSfile: ir-behaviour.vhdl,v $ $Revision: 2.1 $ $Date: 1993/11/02 18:56:39 $ +-- +-------------------------------------------------------------------------- +-- +-- Behavioural architecture of instruction register. +-- + + +use work.dlx_instr.all; + +architecture behaviour of ir is + +begin + + reg: process (d, latch_en, immed_sel1, immed_sel2, + immed_unsigned1, immed_unsigned2, immed_en1, immed_en2) + + variable latched_instr : dlx_word; + + use work.bv_arithmetic.bv_zext, work.bv_arithmetic.bv_sext; + + begin + if latch_en = '1' then + latched_instr := d; + ir_out <= latched_instr after Tpd; + end if; + -- + if immed_en1 = '1' then + if immed_sel1 = immed_size_16 then + if immed_unsigned1 = '1' then + immed_q1 <= bv_zext(latched_instr(16 to 31), 32) after Tpd; + else + immed_q1 <= bv_sext(latched_instr(16 to 31), 32) after Tpd; + end if; + else -- immed_sel1 = immed_size_26 + if immed_unsigned1 = '1' then + immed_q1 <= bv_zext(latched_instr(6 to 31), 32) after Tpd; + else + immed_q1 <= bv_sext(latched_instr(6 to 31), 32) after Tpd; + end if; + end if; + else + immed_q1 <= null after Tpd; + end if; + -- + if immed_en2 = '1' then + if immed_sel2 = immed_size_16 then + if immed_unsigned2 = '1' then + immed_q2 <= bv_zext(latched_instr(16 to 31), 32) after Tpd; + else + immed_q2 <= bv_sext(latched_instr(16 to 31), 32) after Tpd; + end if; + else -- immed_sel2 = immed_size_26 + if immed_unsigned2 = '1' then + immed_q2 <= bv_zext(latched_instr(6 to 31), 32) after Tpd; + else + immed_q2 <= bv_sext(latched_instr(6 to 31), 32) after Tpd; + end if; + end if; + else + immed_q2 <= null after Tpd; + end if; + end process reg; + +end behaviour; diff --git a/projects/dlx/src/ir.vhdl b/projects/dlx/src/ir.vhdl new file mode 100644 index 0000000..d7640b0 --- /dev/null +++ b/projects/dlx/src/ir.vhdl @@ -0,0 +1,46 @@ +-------------------------------------------------------------------------- +-- +-- Copyright (C) 1993, Peter J. Ashenden +-- Mail: Dept. Computer Science +-- University of Adelaide, SA 5005, Australia +-- e-mail: petera@cs.adelaide.edu.au +-- +-- This program 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 1, or (at your option) +-- any later version. +-- +-- This program 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 this program; if not, write to the Free Software +-- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +-- +-------------------------------------------------------------------------- +-- +-- $RCSfile: ir.vhdl,v $ $Revision: 2.1 $ $Date: 1993/11/02 18:55:16 $ +-- +-------------------------------------------------------------------------- +-- +-- Entity declaration for instruction register. +-- + + +use work.dlx_types.all, + work.dlx_instr.immed_size; + +entity ir is + generic (Tpd : Time; + tag : string := ""; + origin_x, origin_y : real := 0.0); + port (d : in dlx_word; + immed_q1, immed_q2 : out dlx_word_bus bus; + ir_out : out dlx_word; + latch_en : in bit; + immed_sel1, immed_sel2 : in immed_size; + immed_unsigned1, immed_unsigned2 : in bit; + immed_en1, immed_en2 : in bit); +end ir; diff --git a/projects/dlx/src/latch-behaviour.vhdl b/projects/dlx/src/latch-behaviour.vhdl new file mode 100644 index 0000000..54fbb8d --- /dev/null +++ b/projects/dlx/src/latch-behaviour.vhdl @@ -0,0 +1,43 @@ +-------------------------------------------------------------------------- +-- +-- Copyright (C) 1993, Peter J. Ashenden +-- Mail: Dept. Computer Science +-- University of Adelaide, SA 5005, Australia +-- e-mail: petera@cs.adelaide.edu.au +-- +-- This program 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 1, or (at your option) +-- any later version. +-- +-- This program 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 this program; if not, write to the Free Software +-- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +-- +-------------------------------------------------------------------------- +-- +-- $RCSfile: latch-behaviour.vhdl,v $ $Revision: 2.1 $ $Date: 1993/11/02 18:59:13 $ +-- +-------------------------------------------------------------------------- +-- +-- Behavioural architecture of transparent latch. +-- + + +architecture behaviour of latch is + +begin + + process (d, latch_en) + begin + if latch_en = '1' then + q <= d after Tpd; + end if; + end process; + +end behaviour; diff --git a/projects/dlx/src/latch.vhdl b/projects/dlx/src/latch.vhdl new file mode 100644 index 0000000..7f8653f --- /dev/null +++ b/projects/dlx/src/latch.vhdl @@ -0,0 +1,41 @@ +-------------------------------------------------------------------------- +-- +-- Copyright (C) 1993, Peter J. Ashenden +-- Mail: Dept. Computer Science +-- University of Adelaide, SA 5005, Australia +-- e-mail: petera@cs.adelaide.edu.au +-- +-- This program 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 1, or (at your option) +-- any later version. +-- +-- This program 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 this program; if not, write to the Free Software +-- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +-- +-------------------------------------------------------------------------- +-- +-- $RCSfile: latch.vhdl,v $ $Revision: 2.1 $ $Date: 1993/11/02 18:58:13 $ +-- +-------------------------------------------------------------------------- +-- +-- Entity declaration for transparent latch. +-- + + +use work.dlx_types.all; + +entity latch is + generic (Tpd : Time; + tag : string := ""; + origin_x, origin_y : real := 0.0); + port (d : in dlx_word; + q : out dlx_word; + latch_en : in bit); +end latch; diff --git a/projects/dlx/src/mem_types.vhdl b/projects/dlx/src/mem_types.vhdl new file mode 100644 index 0000000..9dc2e97 --- /dev/null +++ b/projects/dlx/src/mem_types.vhdl @@ -0,0 +1,36 @@ +-------------------------------------------------------------------------- +-- +-- Copyright (C) 1993, Peter J. Ashenden +-- Mail: Dept. Computer Science +-- University of Adelaide, SA 5005, Australia +-- e-mail: petera@cs.adelaide.edu.au +-- +-- This program 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 1, or (at your option) +-- any later version. +-- +-- This program 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 this program; if not, write to the Free Software +-- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +-- +-------------------------------------------------------------------------- +-- +-- $RCSfile: mem_types.vhdl,v $ $Revision: 2.1 $ $Date: 1993/10/31 20:39:06 $ +-- +-------------------------------------------------------------------------- +-- +-- Types package for memory model +-- + + +package mem_types is + + type mem_width is (width_byte, width_halfword, width_word); + +end mem_types; diff --git a/projects/dlx/src/memory-behaviour.vhdl b/projects/dlx/src/memory-behaviour.vhdl new file mode 100644 index 0000000..1cee156 --- /dev/null +++ b/projects/dlx/src/memory-behaviour.vhdl @@ -0,0 +1,226 @@ +-------------------------------------------------------------------------- +-- +-- Copyright (C) 1993, Peter J. Ashenden +-- Mail: Dept. Computer Science +-- University of Adelaide, SA 5005, Australia +-- e-mail: petera@cs.adelaide.edu.au +-- +-- This program 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 1, or (at your option) +-- any later version. +-- +-- This program 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 this program; if not, write to the Free Software +-- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +-- +-------------------------------------------------------------------------- +-- +-- $RCSfile: memory-behaviour.vhdl,v $ $Revision: 2.1 $ $Date: 1993/10/31 21:09:45 $ +-- +-------------------------------------------------------------------------- +-- +-- Behavioural architecture for memory model +-- + + +use work.bv_arithmetic.bv_to_natural, + work.bv_arithmetic.natural_to_bv, + work.images.image_hex, + std.textio.all; + + +architecture behaviour of memory is + +begin + + mem : process + + constant low_address : natural := 0; + constant high_address : natural := mem_size - 1; + + subtype byte is bit_vector(0 to 7); + subtype ls_2_bits is bit_vector(1 downto 0); + + type memory_array is + array (natural range low_address to high_address) of byte; + + variable mem : memory_array; + variable aligned_a : dlx_address; + variable address : natural; + + variable L : line; + + + procedure load(mem : out memory_array) is + + file binary_file : text is in "dlx.out"; + variable L : line; + variable addr : natural; + variable word : dlx_word; + + procedure read_hex_natural(L : inout line; addr : out natural) is + variable result : natural := 0; + variable ch : character; + begin + for i in 1 to 8 loop + read(L, ch); + if ('0' <= ch and ch <= '9') then + result := result*16 + character'pos(ch) - character'pos('0'); + else + result := result*16 + character'pos(ch) - character'pos('a') + 10; + end if; + end loop; + addr := result; + end read_hex_natural; + + procedure read_hex_word(L : inout line; word : out dlx_word) is + variable result : dlx_word; + variable digit, r : natural := 0; + variable ch : character; + begin + read(L, ch); -- the space between addr and data + for i in 10 to 17 loop + read(L, ch); + if ('0' <= ch and ch <= '9') then + digit := character'pos(ch) - character'pos('0'); + else + digit := character'pos(ch) - character'pos('a') + 10; + end if; + result(r to r+3) := natural_to_bv(digit, 4); + r := r + 4; + end loop; + word := result; + end read_hex_word; + + begin + while not endfile(binary_file) loop + readline(binary_file, L); + read_hex_natural(L, addr); + read_hex_word(L, word); + -- + write(L, addr); + write(L, ' '); + write(L, image_hex(word)); + writeline(output, L); + -- + mem(addr) := word(0 to 7); + mem(addr+1) := word(8 to 15); + mem(addr+2) := word(16 to 23); + mem(addr+3) := word(24 to 31); + end loop; + end load; + + + procedure do_write is + begin + -- + -- align address to accessed unit + -- + aligned_a := a; + case width is + when width_word => + aligned_a(1 downto 0) := b"00"; + when width_halfword => + aligned_a(0) := '0'; + when width_byte => + null; + end case; + address := bv_to_natural(aligned_a); + case width is + when width_word => + mem(address) := d(0 to 7); + mem(address+1) := d(8 to 15); + mem(address+2) := d(16 to 23); + mem(address+3) := d(24 to 31); + when width_halfword => + if a(1) = '0' then -- ms half word + mem(address) := d(0 to 7); + mem(address+1) := d(8 to 15); + else -- ls half word + mem(address) := d(16 to 23); + mem(address+1) := d(24 to 31); + end if; + when width_byte => + case ls_2_bits'(a(1 downto 0)) is + when b"00" => + mem(address) := d(0 to 7); + when b"01" => + mem(address) := d(8 to 15); + when b"10" => + mem(address) := d(16 to 23); + when b"11" => + mem(address) := d(24 to 31); + end case; + end case; + end do_write; + + procedure do_read is + begin + aligned_a := a; + aligned_a(1 downto 0) := b"00"; + address := bv_to_natural(aligned_a); + d <= mem(address) & mem(address+1) & mem(address+2) & mem(address+3); + end do_read; + + + begin + load(mem); + -- initialize outputs + -- + d <= null; + ready <= '0'; + -- + -- process memory cycles + -- + loop + -- + -- wait for a command, valid on leading edge of phi2 + -- + wait until phi2 = '1' and mem_enable = '1'; + -- + -- decode address and perform command if selected + -- + address := bv_to_natural(a); + if address >= low_address and address <= high_address then + if write_enable = '1' then -- write cycle + do_write; + wait for Tac1; -- write access time, 1st cycle + else -- read cycle + wait for Tac1; -- read access time, 1st cycle + do_read; + end if; + -- ready synchronous with phi2 + wait until phi2 = '1'; + ready <= '1' after Tpd_clk_out; + wait until phi2 = '0'; + ready <= '0' after Tpd_clk_out; + -- do subsequent cycles in burst + while burst = '1' loop + wait until phi2 = '1'; + if write_enable = '1' then -- write cycle + do_write; + wait for Tacb; -- write access time, burst cycle + else -- read cycle + wait for Tacb; -- read access time, burst cycle + do_read; + end if; + -- ready synchronous with phi2 + wait until phi2 = '1'; + ready <= '1' after Tpd_clk_out; + wait until phi2 = '0'; + ready <= '0' after Tpd_clk_out; + end loop; + if write_enable = '0' then -- was read + d <= null after Tpd_clk_out; + end if; + end if; + end loop; + end process; + +end behaviour; diff --git a/projects/dlx/src/memory.vhdl b/projects/dlx/src/memory.vhdl new file mode 100644 index 0000000..7051901 --- /dev/null +++ b/projects/dlx/src/memory.vhdl @@ -0,0 +1,54 @@ +-------------------------------------------------------------------------- +-- +-- Copyright (C) 1993, Peter J. Ashenden +-- Mail: Dept. Computer Science +-- University of Adelaide, SA 5005, Australia +-- e-mail: petera@cs.adelaide.edu.au +-- +-- This program 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 1, or (at your option) +-- any later version. +-- +-- This program 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 this program; if not, write to the Free Software +-- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +-- +-------------------------------------------------------------------------- +-- +-- $RCSfile: memory.vhdl,v $ $Revision: 2.1 $ $Date: 1993/10/31 21:09:12 $ +-- +-------------------------------------------------------------------------- +-- +-- Entity declaration for memory model +-- + + +use work.dlx_types.all, work.mem_types.all; + +entity memory is + + generic (mem_size : positive; -- size in bytes (multiple of 4) + Tac1 : Time; -- access time 1st cycle (read or write) + Tacb : Time; -- access time burst (read or write) + Tpd_clk_out : Time; -- clock to output delay + tag : string := ""; + origin_x, origin_y : real := 0.0); + + port (phi1, phi2 : in bit; -- 2-phase non-overlapping clocks + a : in dlx_address; -- byte address: a(0) is lsb + d : inout dlx_word_bus bus; -- bidirectional data bus: d(0) is msb + width : in mem_width; -- byte/haldword/word indicator + write_enable : in bit; -- selects read or write cycle + burst : in bit := '0'; -- indicates more to come in burst + -- can be left open + -- for non-burst client + mem_enable : in bit; -- starts memory cycle + ready : out bit); -- status from memory system + +end memory; diff --git a/projects/dlx/src/memory_test-bench.vhdl b/projects/dlx/src/memory_test-bench.vhdl new file mode 100644 index 0000000..a54e35b --- /dev/null +++ b/projects/dlx/src/memory_test-bench.vhdl @@ -0,0 +1,330 @@ +-------------------------------------------------------------------------- +-- +-- Copyright (C) 1993, Peter J. Ashenden +-- Mail: Dept. Computer Science +-- University of Adelaide, SA 5005, Australia +-- e-mail: petera@cs.adelaide.edu.au +-- +-- This program 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 1, or (at your option) +-- any later version. +-- +-- This program 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 this program; if not, write to the Free Software +-- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +-- +-------------------------------------------------------------------------- +-- +-- $RCSfile: memory_test-bench.vhdl,v $ $Revision: 2.1 $ $Date: 1993/10/31 21:10:12 $ +-- +-------------------------------------------------------------------------- +-- +-- Architecture for test bench for behavioural architecture of memory +-- + + +use std.textio.all, + work.dlx_types.all, + work.mem_types.all, + work.bv_arithmetic.bv_addu, + work.images.image_hex; + +architecture bench of memory_test is + + component clock_gen + port (phi1, phi2 : out bit; + reset : out bit); + end component; + + component memory + port (phi1, phi2 : in bit; + a : in dlx_address; + d : inout dlx_word_bus bus; + width : in mem_width; + write_enable : in bit; + burst : in bit; + mem_enable : in bit; + ready : out bit); + end component; + + for cg : clock_gen + use entity work.clock_gen(behaviour) + generic map (Tpw => 8 ns, Tps => 2 ns); + + for mem : memory + use entity work.memory(behaviour) + generic map (mem_size => 65536, + Tac1 => 95 ns, Tacb => 15 ns, Tpd_clk_out => 2 ns); + + signal phi1, phi2, reset : bit; + signal a : dlx_address; + signal d : dlx_word_bus bus; + signal width : mem_width; + signal write_enable, mem_enable, burst, ifetch, ready : bit; + + +begin + + cg : clock_gen + port map (phi1, phi2, reset); + + mem : memory + port map (phi1, phi2, a, d, width, write_enable, burst, mem_enable, ready); + + test: process + + variable data_word : dlx_word; + variable L : line; + VARIABLE blk : dlx_word_array(1 to 4); + + procedure write (address : in dlx_address; + data_width : in mem_width; + data : in dlx_word; + Tpd_clk_out : in time -- clock to output delay + ) is + + begin -- write + wait until phi1 = '1'; + if reset = '1' then + return; + end if; + a <= address after Tpd_clk_out; + width <= data_width after Tpd_clk_out; + d <= data after Tpd_clk_out; + write_enable <= '1' after Tpd_clk_out; + burst <= '0' after Tpd_Clk_Out; + mem_enable <= '1' after Tpd_clk_out; + ifetch <= '0' after Tpd_clk_out; + loop + wait until phi2 = '0'; + exit when ready = '1' or reset = '1'; + end loop; + d <= null after Tpd_clk_out; + write_enable <= '0' after Tpd_clk_out; + mem_enable <= '0' after Tpd_clk_out; + end write; + + + procedure read (address : in dlx_address; + data_width : in mem_width; + instr_fetch : in boolean; + data : out dlx_word; + Tpd_clk_out : in time -- clock to output delay + ) is + + begin -- read + wait until phi1 = '1'; + if reset = '1' then + return; + end if; + a <= address after Tpd_clk_out; + width <= data_width after Tpd_clk_out; + write_enable <= '0' after Tpd_clk_out; + burst <= '0' after Tpd_Clk_Out; + mem_enable <= '1' after Tpd_clk_out; + ifetch <= bit'val(boolean'pos(instr_fetch)) after Tpd_clk_out; + loop + wait until phi2 = '0'; + exit when ready = '1' or reset = '1'; + end loop; + data := d; + mem_enable <= '0' after Tpd_clk_out; + end read; + + + procedure write_burst (address : in dlx_address; + data : in dlx_word_array; + Tpd_clk_out : in time -- clock to output delay + ) is + VARIABLE next_address : dlx_address := address; + VARIABLE ignore_overflow : boolean; + VARIABLE index : natural; + begin -- write_burst + wait until phi1 = '1'; + if reset = '1' then + return; + end if; + width <= width_word after Tpd_clk_out; + write_enable <= '1' after Tpd_clk_out; + mem_enable <= '1' after Tpd_clk_out; + ifetch <= '0' after Tpd_clk_out; + burst <= '1' after Tpd_Clk_Out; + index := data'left; + burst_loop : LOOP + IF (index = data'right) THEN + burst <= '0' after Tpd_Clk_Out; + END IF; + a <= next_address after Tpd_clk_out; + d <= data(index) after Tpd_clk_out; + wait_loop : LOOP + WAIT UNTIL phi2 = '0'; + EXIT burst_loop WHEN reset = '1' OR (ready = '1' AND index = data'right); + EXIT wait_loop WHEN ready = '1'; + END LOOP wait_loop; + index := index + 1; + bv_addu(next_address, X"00000004", next_address, ignore_overflow); + END LOOP burst_loop; + d <= null after Tpd_clk_out; + write_enable <= '0' after Tpd_clk_out; + mem_enable <= '0' after Tpd_clk_out; + end write_burst; + + + procedure read_burst (address : in dlx_address; + data : out dlx_word_array; + Tpd_clk_out : in time -- clock to output delay + ) is + VARIABLE next_address : dlx_address := address; + VARIABLE ignore_overflow : boolean; + VARIABLE index : natural; + begin -- read_burst + wait until phi1 = '1'; + if reset = '1' then + return; + end if; + width <= width_word after Tpd_clk_out; + write_enable <= '0' after Tpd_clk_out; + mem_enable <= '1' after Tpd_clk_out; + ifetch <= '0' after Tpd_clk_out; + burst <= '1' after Tpd_Clk_Out; + index := data'left; + burst_loop : LOOP + IF (index = data'right) THEN + burst <= '0' after Tpd_Clk_Out; + END IF; + a <= next_address after Tpd_clk_out; + wait_loop : LOOP + WAIT UNTIL phi2 = '0'; + data(index) := d; + EXIT burst_loop WHEN reset = '1' OR (ready = '1' AND index = data'right); + EXIT wait_loop WHEN ready = '1'; + END LOOP wait_loop; + index := index + 1; + bv_addu(next_address, X"00000004", next_address, ignore_overflow); + END LOOP burst_loop; + mem_enable <= '0' after Tpd_clk_out; + end read_burst; + + + begin + wait until reset = '0'; + write(L, string'("Write word X""00000004"" to 4:")); + writeline(output, L); + write(X"0000_0004", width_word, X"00000004", 2 ns); + -- + write(L, string'("Read word from X""00000004"":")); + writeline(output, L); + data_word := X"0000_0000"; + read(X"0000_0004", width_word, false, data_word, 2 ns); + write(L, string'(" result:")); + write(L, image_hex(data_word)); + writeline(output, L); + -- + write(L, string'("Write halfword X""2222"" to 0:")); + writeline(output, L); + write(X"0000_0000", width_halfword, X"2222_0000", 2 ns); + -- + write(L, string'("Write halfword X""3333"" to 2:")); + writeline(output, L); + write(X"0000_0002", width_halfword, X"0000_3333", 2 ns); + -- + write(L, string'("Read word from X""00000000"":")); + writeline(output, L); + data_word := X"0000_0000"; + read(X"0000_0000", width_word, false, data_word, 2 ns); + write(L, string'(" result:")); + write(L, image_hex(data_word)); + writeline(output, L); + -- + write(L, string'("Read halfword from X""00000003"":")); + writeline(output, L); + data_word := X"0000_0000"; + read(X"0000_0003", width_halfword, false, data_word, 2 ns); + write(L, string'(" result:")); + write(L, image_hex(data_word)); + writeline(output, L); + -- + write(L, string'("Write bytes X""44"" to 4, X""55"" to 5, X""66"" to 6, X""77"" to 7:")); + writeline(output, L); + write(X"0000_0004", width_byte, X"44_00_00_00", 2 ns); + write(X"0000_0005", width_byte, X"00_55_00_00", 2 ns); + write(X"0000_0006", width_byte, X"00_00_66_00", 2 ns); + write(X"0000_0007", width_byte, X"00_00_00_77", 2 ns); + -- + write(L, string'("Read word from X""00000004"":")); + writeline(output, L); + data_word := X"0000_0000"; + read(X"0000_0004", width_word, false, data_word, 2 ns); + write(L, string'(" result:")); + write(L, image_hex(data_word)); + writeline(output, L); + -- + write(L, string'("Read byte from X""00000004"":")); + writeline(output, L); + data_word := X"0000_0000"; + read(X"0000_0004", width_byte, false, data_word, 2 ns); + write(L, string'(" result:")); + write(L, image_hex(data_word)); + writeline(output, L); + -- + write(L, string'("Read byte from X""00000005"":")); + writeline(output, L); + data_word := X"0000_0000"; + read(X"0000_0005", width_byte, false, data_word, 2 ns); + write(L, string'(" result:")); + write(L, image_hex(data_word)); + writeline(output, L); + -- + write(L, string'("Read byte from X""00000006"":")); + writeline(output, L); + data_word := X"0000_0000"; + read(X"0000_0006", width_byte, false, data_word, 2 ns); + write(L, string'(" result:")); + write(L, image_hex(data_word)); + writeline(output, L); + -- + write(L, string'("Read byte from X""00000007"":")); + writeline(output, L); + data_word := X"0000_0000"; + read(X"0000_0007", width_byte, false, data_word, 2 ns); + write(L, string'(" result:")); + write(L, image_hex(data_word)); + writeline(output, L); + -- + write(L, string'("Write burst to 8..11:")); + writeline(output, L); + blk := (X"88888888", X"99999999", X"AAAAAAAA", X"BBBBBBBB"); + write_burst(X"0000_0008", blk, 2 ns); + -- + write(L, string'("Read burst from 8..11:")); + writeline(output, L); + blk := (OTHERS => X"0000_0000"); + read_burst(X"0000_0008", blk, 2 ns); + write(L, string'(" result: (")); + FOR i IN blk'range LOOP + write(L, image_hex(blk(i))); + IF (i /= blk'right) THEN + write(L, string'(", ")); + END IF; + END LOOP; -- i + write(L, ')'); + writeline(output, L); + -- + -- This should hang + write(L, string'("Read word from X""00100000"":")); + writeline(output, L); + data_word := X"0000_0000"; + read(X"0010_0000", width_word, false, data_word, 2 ns); + write(L, string'(" result:")); + write(L, data_word); + writeline(output, L); + -- + end process test; + +end bench; diff --git a/projects/dlx/src/memory_test.vhdl b/projects/dlx/src/memory_test.vhdl new file mode 100644 index 0000000..976caef --- /dev/null +++ b/projects/dlx/src/memory_test.vhdl @@ -0,0 +1,33 @@ +-------------------------------------------------------------------------- +-- +-- Copyright (C) 1993, Peter J. Ashenden +-- Mail: Dept. Computer Science +-- University of Adelaide, SA 5005, Australia +-- e-mail: petera@cs.adelaide.edu.au +-- +-- This program 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 1, or (at your option) +-- any later version. +-- +-- This program 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 this program; if not, write to the Free Software +-- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +-- +-------------------------------------------------------------------------- +-- +-- $RCSfile: memory_test.vhdl,v $ $Revision: 2.1 $ $Date: 1993/10/31 21:10:02 $ +-- +-------------------------------------------------------------------------- +-- +-- Entity declaration for test bench for memory +-- + + +entity memory_test is +end memory_test; diff --git a/projects/dlx/src/module-directory b/projects/dlx/src/module-directory new file mode 100644 index 0000000..4d5523d --- /dev/null +++ b/projects/dlx/src/module-directory @@ -0,0 +1,158 @@ +images.vhdl + Package specification for images. +images-body.vhdl + Package body for images. +images_test.vhdl + Entity declaration for test bench for images package. +images_test-bench.vhdl + Architecture body for test bench for images package. + +bv_arithmetic.vhdl + Package specification for bit vector conversions and arithmetic +bv_arithmetic-body.vhdl + Package body for bit vector conversions and arithmetic +bv_test.vhdl + Entity declaration for test bench for bit vector arithmetic package +bv_test-bench.vhdl + Architecture for test bench for bit vector arithmetic package + +---------------------------------------------------------------- + +clock_gen.vhdl + Entity declaration for clock generator +clock_gen-behaviour.vhdl + Behavioural architecture body for clock generator +clock_gen_test.vhdl + Entity declaration for test bench for clock generator +clock_gen_test-bench.vhdl + Architecture for test bench for clock generator + +dlx_types.vhdl + Package specification for types used in dlx model +dlx_types-body.vhdl + Package body for types used in dlx model + +mem_types.vhdl + Types package for memory model + +memory.vhdl + Entity declaration for memory model +memory-behaviour.vhdl + Behavioural architecture for memory model +memory_test.vhdl + Entity declaration for test bench for memory +memory_test-bench.vhdl + Architecture for test bench for behavioural architecture of memory + +dlx_instr.vhdl + Package specification for DLX instructions +dlx_instr-body.vhdl + Package body for DLX instructions + +dlx_bus_monitor.vhdl + Entity declaration of DLX bus monitor +dlx_bus_monitor-behaviour.vhdl + Behavioural architecture of DLX bus monitor + +dlx_test.vhdl + Entity declaration for test bench for DLX +dlx_test-bench.vhdl + Architecture for test bench for DLX, + consisting of clock generator, memory and bus_monitor + +dlx.vhdl + Entity specification for DLX processor + +dlx-behaviour.vhdl + Behavioural architecture for DLX processor +dlx_test_behaviour.vhdl + Configuration of test bench for DLX, using architecture behaviour + +dlx-instrumented.vhdl + Instrumented behavioural architecture for DLX, that generates + a files of instruction execution frequencies for a program. +dlx_test_instrumented.vhdl + Configuration of test bench for DLX, using instrumented + architecture of CPU and empty architecture of bus monitor. + +---------------------------------------------------------------- + +alu_types.vhdl + Package defining types for ALU. +alu.vhdl + Entity declaration for ALU. +alu-behaviour.vhdl + Behavioural architecture of ALU. + +ir.vhdl + Entity declaration for instruction register. +ir-behaviour.vhdl + Behavioural architecture of instruction register. + +latch.vhdl + Entity declaration for transparent latch. +latch-behaviour.vhdl + Behavioural architecture of transparent latch. + +mux2.vhdl + Entity declaration for two-input multiplexor. +mux2-behaviour.vhdl + Behavioural architecture of two-input multiplexor. + +reg_1_out.vhdl + Entity declaration for register with one tri-state output. +reg_1_out-behaviour.vhdl + Behavioural architecture of register with one tri-state output. + +reg_2_1_out.vhdl + Entity declaration for register with two tri-state outputs and + one ordinary output. +reg_2_1_out-behaviour.vhdl + Behavioural architecture of register with two tri-state + outputs and one ordinary output. + +reg_2_out.vhdl + Entity declaration for register with two tri-state outputs. +reg_2_out-behaviour.vhdl + Behavioural architecture of register with two tri-state outputs. + +reg_3_out.vhdl + Entity declaration for register with three tri-state outputs. +reg_3_out-behaviour.vhdl + Behavioural architecture of register with three tri-state outputs. + +reg_file.vhdl + Entity declaration for register file. +reg_file-behaviour.vhdl + Behavioural architecture of register file. + +controller.vhdl + Entity declaration for DLX control section. +controller-behaviour.vhdl + Behavioural architecture of DLX control section. + +dlx-rtl.vhdl + Register transfer level architecture of DLX processor. + +dlx_test_rtl.vhdl + Configuration of DLX test bench using register transfer level + architecture of DLX processor. + +---------------------------------------------------------------- + +cache_types.vhdl + Package spec defining types for cache. +cache.vhdl + Entity declaration for cache. +cache-behaviour.vhdl + Behavioural architecture for cache. + +dlx_test-bench_cache.vhdl + Architecture for test bench for DLX and cache, + including clock generator, memory and bus monitors for + both CPU/cache and cache/memory buses. + +dlx_test_cache.vhdl + Configuration of test bench for DLX and cache, + using behavioural architectures. + diff --git a/projects/dlx/src/mux2-behaviour.vhdl b/projects/dlx/src/mux2-behaviour.vhdl new file mode 100644 index 0000000..20c73ad --- /dev/null +++ b/projects/dlx/src/mux2-behaviour.vhdl @@ -0,0 +1,37 @@ +-------------------------------------------------------------------------- +-- +-- Copyright (C) 1993, Peter J. Ashenden +-- Mail: Dept. Computer Science +-- University of Adelaide, SA 5005, Australia +-- e-mail: petera@cs.adelaide.edu.au +-- +-- This program 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 1, or (at your option) +-- any later version. +-- +-- This program 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 this program; if not, write to the Free Software +-- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +-- +-------------------------------------------------------------------------- +-- +-- $RCSfile: mux2-behaviour.vhdl,v $ $Revision: 2.1 $ $Date: 1993/11/02 19:02:04 $ +-- +-------------------------------------------------------------------------- +-- +-- Behavioural architecture of two-input multiplexor. +-- + + +architecture behaviour of mux2 is +begin + with sel select + y <= i0 after Tpd when '0', + i1 after Tpd when '1'; +end behaviour; diff --git a/projects/dlx/src/mux2.vhdl b/projects/dlx/src/mux2.vhdl new file mode 100644 index 0000000..69d122b --- /dev/null +++ b/projects/dlx/src/mux2.vhdl @@ -0,0 +1,41 @@ +-------------------------------------------------------------------------- +-- +-- Copyright (C) 1993, Peter J. Ashenden +-- Mail: Dept. Computer Science +-- University of Adelaide, SA 5005, Australia +-- e-mail: petera@cs.adelaide.edu.au +-- +-- This program 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 1, or (at your option) +-- any later version. +-- +-- This program 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 this program; if not, write to the Free Software +-- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +-- +-------------------------------------------------------------------------- +-- +-- $RCSfile: mux2.vhdl,v $ $Revision: 2.1 $ $Date: 1993/11/02 19:01:03 $ +-- +-------------------------------------------------------------------------- +-- +-- Entity declaration for two-input multiplexor. +-- + + +use work.dlx_types.all; + +entity mux2 is + generic (Tpd : Time; + tag : string := ""; + origin_x, origin_y : real := 0.0); + port (i0, i1 : in dlx_word; + y : out dlx_word; + sel : in bit); +end mux2; diff --git a/projects/dlx/src/reg_1_out-behaviour.vhdl b/projects/dlx/src/reg_1_out-behaviour.vhdl new file mode 100644 index 0000000..6a84717 --- /dev/null +++ b/projects/dlx/src/reg_1_out-behaviour.vhdl @@ -0,0 +1,51 @@ +-------------------------------------------------------------------------- +-- +-- Copyright (C) 1993, Peter J. Ashenden +-- Mail: Dept. Computer Science +-- University of Adelaide, SA 5005, Australia +-- e-mail: petera@cs.adelaide.edu.au +-- +-- This program 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 1, or (at your option) +-- any later version. +-- +-- This program 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 this program; if not, write to the Free Software +-- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +-- +-------------------------------------------------------------------------- +-- +-- $RCSfile: reg_1_out-behaviour.vhdl,v $ $Revision: 2.1 $ $Date: 1993/11/02 19:04:21 $ +-- +-------------------------------------------------------------------------- +-- +-- Behavioural architecture of register with one tri-state output. +-- + + +architecture behaviour of reg_1_out is + +begin + + reg: process (d, latch_en, out_en) + + variable latched_value : dlx_word; + + begin + if latch_en = '1' then + latched_value := d; + end if; + if out_en = '1' then + q <= latched_value after Tpd; + else + q <= null after Tpd; + end if; + end process reg; + +end behaviour; diff --git a/projects/dlx/src/reg_1_out.vhdl b/projects/dlx/src/reg_1_out.vhdl new file mode 100644 index 0000000..a43d75d --- /dev/null +++ b/projects/dlx/src/reg_1_out.vhdl @@ -0,0 +1,42 @@ +-------------------------------------------------------------------------- +-- +-- Copyright (C) 1993, Peter J. Ashenden +-- Mail: Dept. Computer Science +-- University of Adelaide, SA 5005, Australia +-- e-mail: petera@cs.adelaide.edu.au +-- +-- This program 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 1, or (at your option) +-- any later version. +-- +-- This program 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 this program; if not, write to the Free Software +-- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +-- +-------------------------------------------------------------------------- +-- +-- $RCSfile: reg_1_out.vhdl,v $ $Revision: 2.1 $ $Date: 1993/11/02 19:04:11 $ +-- +-------------------------------------------------------------------------- +-- +-- Entity declaration for register with one tri-state output. +-- + + +use work.dlx_types.all; + +entity reg_1_out is + generic (Tpd : Time; + tag : string := ""; + origin_x, origin_y : real := 0.0); + port (d : in dlx_word; + q : out dlx_word_bus bus; + latch_en : in bit; + out_en : in bit); +end reg_1_out; diff --git a/projects/dlx/src/reg_2_1_out-behaviour.vhdl b/projects/dlx/src/reg_2_1_out-behaviour.vhdl new file mode 100644 index 0000000..6339ce9 --- /dev/null +++ b/projects/dlx/src/reg_2_1_out-behaviour.vhdl @@ -0,0 +1,58 @@ +-------------------------------------------------------------------------- +-- +-- Copyright (C) 1993, Peter J. Ashenden +-- Mail: Dept. Computer Science +-- University of Adelaide, SA 5005, Australia +-- e-mail: petera@cs.adelaide.edu.au +-- +-- This program 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 1, or (at your option) +-- any later version. +-- +-- This program 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 this program; if not, write to the Free Software +-- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +-- +-------------------------------------------------------------------------- +-- +-- $RCSfile: reg_2_1_out-behaviour.vhdl,v $ $Revision: 2.1 $ $Date: 1993/11/02 19:06:59 $ +-- +-------------------------------------------------------------------------- +-- +-- Behavioural architecture of register with two tri-state +-- outputs and one ordinary output. +-- + + +architecture behaviour of reg_2_1_out is + +begin + + reg: process (d, latch_en, out_en1, out_en2) + + variable latched_value : dlx_word; + + begin + if latch_en = '1' then + latched_value := d; + end if; + if out_en1 = '1' then + q1 <= latched_value after Tpd; + else + q1 <= null after Tpd; + end if; + if out_en2 = '1' then + q2 <= latched_value after Tpd; + else + q2 <= null after Tpd; + end if; + q3 <= latched_value after Tpd; + end process reg; + +end behaviour; diff --git a/projects/dlx/src/reg_2_1_out.vhdl b/projects/dlx/src/reg_2_1_out.vhdl new file mode 100644 index 0000000..c0767c5 --- /dev/null +++ b/projects/dlx/src/reg_2_1_out.vhdl @@ -0,0 +1,44 @@ +-------------------------------------------------------------------------- +-- +-- Copyright (C) 1993, Peter J. Ashenden +-- Mail: Dept. Computer Science +-- University of Adelaide, SA 5005, Australia +-- e-mail: petera@cs.adelaide.edu.au +-- +-- This program 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 1, or (at your option) +-- any later version. +-- +-- This program 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 this program; if not, write to the Free Software +-- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +-- +-------------------------------------------------------------------------- +-- +-- $RCSfile: reg_2_1_out.vhdl,v $ $Revision: 2.1 $ $Date: 1993/11/02 19:06:47 $ +-- +-------------------------------------------------------------------------- +-- +-- Entity declaration for register with two tri-state outputs and +-- one ordinary output. +-- + + +use work.dlx_types.all; + +entity reg_2_1_out is + generic (Tpd : Time; + tag : string := ""; + origin_x, origin_y : real := 0.0); + port (d : in dlx_word; + q1, q2 : out dlx_word_bus bus; + q3 : out dlx_word; + latch_en : in bit; + out_en1, out_en2 : in bit); +end reg_2_1_out; diff --git a/projects/dlx/src/reg_2_out-behaviour.vhdl b/projects/dlx/src/reg_2_out-behaviour.vhdl new file mode 100644 index 0000000..585bfe6 --- /dev/null +++ b/projects/dlx/src/reg_2_out-behaviour.vhdl @@ -0,0 +1,56 @@ +-------------------------------------------------------------------------- +-- +-- Copyright (C) 1993, Peter J. Ashenden +-- Mail: Dept. Computer Science +-- University of Adelaide, SA 5005, Australia +-- e-mail: petera@cs.adelaide.edu.au +-- +-- This program 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 1, or (at your option) +-- any later version. +-- +-- This program 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 this program; if not, write to the Free Software +-- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +-- +-------------------------------------------------------------------------- +-- +-- $RCSfile: reg_2_out-behaviour.vhdl,v $ $Revision: 2.1 $ $Date: 1993/11/02 19:09:21 $ +-- +-------------------------------------------------------------------------- +-- +-- Behavioural architecture of register with two tri-state outputs. +-- + + +architecture behaviour of reg_2_out is + +begin + + reg: process (d, latch_en, out_en1, out_en2) + + variable latched_value : dlx_word; + + begin + if latch_en = '1' then + latched_value := d; + end if; + if out_en1 = '1' then + q1 <= latched_value after Tpd; + else + q1 <= null after Tpd; + end if; + if out_en2 = '1' then + q2 <= latched_value after Tpd; + else + q2 <= null after Tpd; + end if; + end process reg; + +end behaviour; diff --git a/projects/dlx/src/reg_2_out.vhdl b/projects/dlx/src/reg_2_out.vhdl new file mode 100644 index 0000000..43f5cfc --- /dev/null +++ b/projects/dlx/src/reg_2_out.vhdl @@ -0,0 +1,42 @@ +-------------------------------------------------------------------------- +-- +-- Copyright (C) 1993, Peter J. Ashenden +-- Mail: Dept. Computer Science +-- University of Adelaide, SA 5005, Australia +-- e-mail: petera@cs.adelaide.edu.au +-- +-- This program 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 1, or (at your option) +-- any later version. +-- +-- This program 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 this program; if not, write to the Free Software +-- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +-- +-------------------------------------------------------------------------- +-- +-- $RCSfile: reg_2_out.vhdl,v $ $Revision: 2.1 $ $Date: 1993/11/02 19:09:13 $ +-- +-------------------------------------------------------------------------- +-- +-- Entity declaration for register with two tri-state outputs. +-- + + +use work.dlx_types.all; + +entity reg_2_out is + generic (Tpd : Time; + tag : string := ""; + origin_x, origin_y : real := 0.0); + port (d : in dlx_word; + q1, q2 : out dlx_word_bus bus; + latch_en : in bit; + out_en1, out_en2 : in bit); +end reg_2_out; diff --git a/projects/dlx/src/reg_3_out-behaviour.vhdl b/projects/dlx/src/reg_3_out-behaviour.vhdl new file mode 100644 index 0000000..7f5208d --- /dev/null +++ b/projects/dlx/src/reg_3_out-behaviour.vhdl @@ -0,0 +1,61 @@ +-------------------------------------------------------------------------- +-- +-- Copyright (C) 1993, Peter J. Ashenden +-- Mail: Dept. Computer Science +-- University of Adelaide, SA 5005, Australia +-- e-mail: petera@cs.adelaide.edu.au +-- +-- This program 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 1, or (at your option) +-- any later version. +-- +-- This program 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 this program; if not, write to the Free Software +-- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +-- +-------------------------------------------------------------------------- +-- +-- $RCSfile: reg_3_out-behaviour.vhdl,v $ $Revision: 2.1 $ $Date: 1993/11/02 19:14:21 $ +-- +-------------------------------------------------------------------------- +-- +-- Behavioural architecture of register with three tri-state outputs. +-- + + +architecture behaviour of reg_3_out is + +begin + + reg: process (d, latch_en, out_en1, out_en2, out_en3) + + variable latched_value : dlx_word; + + begin + if latch_en = '1' then + latched_value := d; + end if; + if out_en1 = '1' then + q1 <= latched_value after Tpd; + else + q1 <= null after Tpd; + end if; + if out_en2 = '1' then + q2 <= latched_value after Tpd; + else + q2 <= null after Tpd; + end if; + if out_en3 = '1' then + q3 <= latched_value after Tpd; + else + q3 <= null after Tpd; + end if; + end process reg; + +end behaviour; diff --git a/projects/dlx/src/reg_3_out.vhdl b/projects/dlx/src/reg_3_out.vhdl new file mode 100644 index 0000000..84a4d5e --- /dev/null +++ b/projects/dlx/src/reg_3_out.vhdl @@ -0,0 +1,42 @@ +-------------------------------------------------------------------------- +-- +-- Copyright (C) 1993, Peter J. Ashenden +-- Mail: Dept. Computer Science +-- University of Adelaide, SA 5005, Australia +-- e-mail: petera@cs.adelaide.edu.au +-- +-- This program 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 1, or (at your option) +-- any later version. +-- +-- This program 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 this program; if not, write to the Free Software +-- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +-- +-------------------------------------------------------------------------- +-- +-- $RCSfile: reg_3_out.vhdl,v $ $Revision: 2.1 $ $Date: 1993/11/02 19:14:00 $ +-- +-------------------------------------------------------------------------- +-- +-- Entity declaration for register with three tri-state outputs. +-- + + +use work.dlx_types.all; + +entity reg_3_out is + generic (Tpd : Time; + tag : string := ""; + origin_x, origin_y : real := 0.0); + port (d : in dlx_word; + q1, q2, q3 : out dlx_word_bus bus; + latch_en : in bit; + out_en1, out_en2, out_en3 : in bit); +end reg_3_out; diff --git a/projects/dlx/src/reg_file-behaviour.vhdl b/projects/dlx/src/reg_file-behaviour.vhdl new file mode 100644 index 0000000..ec39c67 --- /dev/null +++ b/projects/dlx/src/reg_file-behaviour.vhdl @@ -0,0 +1,76 @@ +-------------------------------------------------------------------------- +-- +-- Copyright (C) 1993, Peter J. Ashenden +-- Mail: Dept. Computer Science +-- University of Adelaide, SA 5005, Australia +-- e-mail: petera@cs.adelaide.edu.au +-- +-- This program 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 1, or (at your option) +-- any later version. +-- +-- This program 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 this program; if not, write to the Free Software +-- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +-- +-------------------------------------------------------------------------- +-- +-- $RCSfile: reg_file-behaviour.vhdl,v $ $Revision: 2.1 $ $Date: 1993/11/02 19:16:52 $ +-- +-------------------------------------------------------------------------- +-- +-- Behavioural architecture of register file. +-- + + +architecture behaviour of reg_file is + +begin + + reg: process (a1, a2, a3, d3, write_en) + + use work.bv_arithmetic.bv_to_natural; + + constant all_zeros : dlx_word := X"0000_0000"; + + type register_array is array (reg_index range 1 to 31) of dlx_word; + + variable register_file : register_array; + variable reg_index1, reg_index2, reg_index3 : reg_index; + + begin + -- do write first if enabled + -- + if write_en = '1' then + reg_index3 := bv_to_natural(a3); + if reg_index3 /= 0 then + register_file(reg_index3) := d3; + end if; + end if; + -- + -- read port 1 + -- + reg_index1 := bv_to_natural(a1); + if reg_index1 /= 0 then + q1 <= register_file(reg_index1) after Tac; + else + q1 <= all_zeros after Tac; + end if; + -- + -- read port 2 + -- + reg_index2 := bv_to_natural(a2); + if reg_index2 /= 0 then + q2 <= register_file(reg_index2) after Tac; + else + q2 <= all_zeros after Tac; + end if; + end process reg; + +end behaviour; diff --git a/projects/dlx/src/reg_file.vhdl b/projects/dlx/src/reg_file.vhdl new file mode 100644 index 0000000..0bab518 --- /dev/null +++ b/projects/dlx/src/reg_file.vhdl @@ -0,0 +1,46 @@ +-------------------------------------------------------------------------- +-- +-- Copyright (C) 1993, Peter J. Ashenden +-- Mail: Dept. Computer Science +-- University of Adelaide, SA 5005, Australia +-- e-mail: petera@cs.adelaide.edu.au +-- +-- This program 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 1, or (at your option) +-- any later version. +-- +-- This program 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 this program; if not, write to the Free Software +-- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +-- +-------------------------------------------------------------------------- +-- +-- $RCSfile: reg_file.vhdl,v $ $Revision: 2.1 $ $Date: 1993/11/02 19:16:43 $ +-- +-------------------------------------------------------------------------- +-- +-- Entity declaration for register file. +-- + + +use work.dlx_types.all, + work.dlx_instr.all; + +entity reg_file is + generic (Tac : Time; + tag : string := ""; + origin_x, origin_y : real := 0.0); + port (a1 : in dlx_reg_addr; + q1 : out dlx_word; + a2 : in dlx_reg_addr; + q2 : out dlx_word; + a3 : in dlx_reg_addr; + d3 : in dlx_word; + write_en : in bit); +end reg_file; diff --git a/projects/dlx/src/simple.out b/projects/dlx/src/simple.out new file mode 100644 index 0000000..60b5c17 --- /dev/null +++ b/projects/dlx/src/simple.out @@ -0,0 +1,2 @@ +00000000 20020000 +00000004 44000000 diff --git a/projects/dlx/src/simple.s b/projects/dlx/src/simple.s new file mode 100644 index 0000000..ff51d33 --- /dev/null +++ b/projects/dlx/src/simple.s @@ -0,0 +1,3 @@ + .text 0 + addi r2, r0, 0 ; r2 := 0 + trap 0 diff --git a/projects/dlx/src/test_loop.out b/projects/dlx/src/test_loop.out new file mode 100644 index 0000000..ed3bf6b --- /dev/null +++ b/projects/dlx/src/test_loop.out @@ -0,0 +1,6 @@ +00000000 20020000 +00000004 ac020018 +00000008 20420001 +0000000c 6441000a +00000010 1420fff0 +00000014 44000000 diff --git a/projects/dlx/src/test_loop.s b/projects/dlx/src/test_loop.s new file mode 100644 index 0000000..e3c56e7 --- /dev/null +++ b/projects/dlx/src/test_loop.s @@ -0,0 +1,10 @@ + .text 0 + addi r2, r0, 0 ; r2 := 0 +loop: + sw counter(r0), r2 ; counter := r2 + addi r2, r2, 1 ; increment r2 + snei r1, r2, 10 ; if r2 = 10 then + bnez r1, loop ; next loop + trap 0 +counter: + .word 0 diff --git a/projects/dlx/syn/ise/project/controller.prj b/projects/dlx/syn/ise/project/controller.prj new file mode 100644 index 0000000..85def89 --- /dev/null +++ b/projects/dlx/syn/ise/project/controller.prj @@ -0,0 +1,5 @@ +vhdl work "E:/work/lib/HDL/Cores/CPUs/DLX/dlx_types.vhdl" +vhdl work "E:/work/lib/HDL/Cores/CPUs/DLX/dlx_instr.vhdl" +vhdl work "E:/work/lib/HDL/Cores/CPUs/DLX/alu_types.vhdl" +vhdl work "E:/work/lib/HDL/Cores/CPUs/DLX/controller.vhdl" +vhdl work "E:/work/lib/HDL/Cores/CPUs/DLX/controller-behavior.vhdl" diff --git a/projects/dlx/syn/ise/project/controller.xst b/projects/dlx/syn/ise/project/controller.xst new file mode 100644 index 0000000..c2b33b1 --- /dev/null +++ b/projects/dlx/syn/ise/project/controller.xst @@ -0,0 +1,4 @@ +set -tmpdir ./xst/projnav.tmp +elaborate +-ifn controller.prj +-ifmt mixed diff --git a/projects/dlx/syn/ise/project/controller_vhdl.prj b/projects/dlx/syn/ise/project/controller_vhdl.prj new file mode 100644 index 0000000..22b1376 --- /dev/null +++ b/projects/dlx/syn/ise/project/controller_vhdl.prj @@ -0,0 +1,5 @@ +work "E:\work\lib\HDL\Cores\CPUs\DLX\dlx_types.vhdl" +work "E:\work\lib\HDL\Cores\CPUs\DLX\dlx_instr.vhdl" +work "E:\work\lib\HDL\Cores\CPUs\DLX\alu_types.vhdl" +work "E:\work\lib\HDL\Cores\CPUs\DLX\controller.vhdl" +work "E:\work\lib\HDL\Cores\CPUs\DLX\controller-behavior.vhdl" diff --git a/projects/dlx/syn/ise/project/dlx.fdo b/projects/dlx/syn/ise/project/dlx.fdo new file mode 100644 index 0000000..17ee927 --- /dev/null +++ b/projects/dlx/syn/ise/project/dlx.fdo @@ -0,0 +1,14 @@ +## NOTE: Do not edit this file. +## Autogenerated by ProjNav (creatfdo.tcl) on Sat Jul 08 02:17:03 Westeuropäische Sommerzeit 2006 +## +vlib work +vcom -explicit -93 "E:/work/lib/HDL/Cores/CPUs/DLX/dlx_types.vhdl" +vcom -explicit -93 "E:/work/lib/HDL/Cores/CPUs/DLX/dlx_instr.vhdl" +vcom -explicit -93 "E:/work/lib/HDL/Cores/CPUs/DLX/dlx-behavior.vhdl" +vsim -t 1ps -lib work dlx +do {dlx.udo} +view wave +add wave * +view structure +view signals +run 1000ns diff --git a/projects/dlx/syn/ise/project/dlx.lso b/projects/dlx/syn/ise/project/dlx.lso new file mode 100644 index 0000000..22de730 --- /dev/null +++ b/projects/dlx/syn/ise/project/dlx.lso @@ -0,0 +1 @@ +work diff --git a/projects/dlx/syn/ise/project/dlx.prj b/projects/dlx/syn/ise/project/dlx.prj new file mode 100644 index 0000000..28cf02e --- /dev/null +++ b/projects/dlx/syn/ise/project/dlx.prj @@ -0,0 +1,3 @@ +vhdl work "E:/work/lib/HDL/Cores/CPUs/DLX/dlx_types.vhdl" +vhdl work "E:/work/lib/HDL/Cores/CPUs/DLX/dlx_instr.vhdl" +vhdl work "E:/work/lib/HDL/Cores/CPUs/DLX/dlx-behavior.vhdl" diff --git a/projects/dlx/syn/ise/project/dlx.udo b/projects/dlx/syn/ise/project/dlx.udo new file mode 100644 index 0000000..2adcb27 --- /dev/null +++ b/projects/dlx/syn/ise/project/dlx.udo @@ -0,0 +1,4 @@ +-- ProjNav VHDL simulation template: dlx.udo +-- You may edit this file after the line that starts with +-- '-- START' to customize your simulation +-- START user-defined simulation commands diff --git a/projects/dlx/syn/ise/project/dlx.xst b/projects/dlx/syn/ise/project/dlx.xst new file mode 100644 index 0000000..d2d0217 --- /dev/null +++ b/projects/dlx/syn/ise/project/dlx.xst @@ -0,0 +1,55 @@ +set -tmpdir ./xst/projnav.tmp +set -xsthdpdir ./xst +run +-ifn dlx.prj +-ifmt mixed +-ofn dlx +-ofmt NGC +-p xc4vsx35-10-ff668 +-top dlx +-opt_mode Speed +-opt_level 1 +-iuc NO +-lso dlx.lso +-keep_hierarchy NO +-rtlview Yes +-glob_opt AllClockNets +-read_cores YES +-write_timing_constraints NO +-cross_clock_analysis NO +-hierarchy_separator / +-bus_delimiter <> +-case maintain +-slice_utilization_ratio 100 +-dsp_utilization_ratio 100 +-verilog2001 YES +-fsm_extract YES -fsm_encoding Auto +-safe_implementation No +-fsm_style lut +-ram_extract Yes +-ram_style Auto +-rom_extract Yes +-mux_style Auto +-decoder_extract YES +-priority_extract YES +-shreg_extract YES +-shift_extract YES +-xor_collapse YES +-rom_style Auto +-mux_extract YES +-resource_sharing YES +-use_dsp48 auto +-iobuf YES +-max_fanout 500 +-bufg 32 +-bufr 24 +-register_duplication YES +-register_balancing No +-slice_packing YES +-optimize_primitives NO +-use_clock_enable Auto +-use_sync_set Auto +-use_sync_reset Auto +-iob auto +-equivalent_register_removal YES +-slice_utilization_ratio_maxmargin 5 diff --git a/projects/dlx/syn/ise/project/dlx_test.fdo b/projects/dlx/syn/ise/project/dlx_test.fdo new file mode 100644 index 0000000..a14aa1f --- /dev/null +++ b/projects/dlx/syn/ise/project/dlx_test.fdo @@ -0,0 +1,19 @@ +## NOTE: Do not edit this file. +## Autogenerated by ProjNav (creatfdo.tcl) on Sat Jul 08 02:23:56 Westeuropäische Sommerzeit 2006 +## +vlib work +vcom -explicit -93 "E:/work/lib/HDL/Cores/CPUs/DLX/dlx_types.vhdl" +vcom -explicit -93 "E:/work/lib/HDL/Cores/CPUs/DLX/dlx_instr.vhdl" +vcom -explicit -93 "E:/work/lib/HDL/Cores/CPUs/DLX/memory.vhdl" +vcom -explicit -93 "E:/work/lib/HDL/Cores/CPUs/DLX/dlx-behavior.vhdl" +vcom -explicit -93 "E:/work/lib/HDL/Cores/CPUs/DLX/clock_gen.vhdl" +vcom -explicit -93 "E:/work/lib/HDL/Cores/CPUs/DLX/memory-preloaded.vhdl" +vcom -explicit -93 "E:/work/lib/HDL/Cores/CPUs/DLX/clock_gen-behavior.vhdl" +vcom -explicit -93 "E:/work/lib/HDL/Cores/CPUs/DLX/dlx_test-verifier.vhdl" +vsim -t 1ps -lib work dlx_test +do {dlx_test.udo} +view wave +add wave * +view structure +view signals +run 1000ns diff --git a/projects/dlx/syn/ise/project/dlx_test.lso b/projects/dlx/syn/ise/project/dlx_test.lso new file mode 100644 index 0000000..22de730 --- /dev/null +++ b/projects/dlx/syn/ise/project/dlx_test.lso @@ -0,0 +1 @@ +work diff --git a/projects/dlx/syn/ise/project/dlx_test.prj b/projects/dlx/syn/ise/project/dlx_test.prj new file mode 100644 index 0000000..f56c4ac --- /dev/null +++ b/projects/dlx/syn/ise/project/dlx_test.prj @@ -0,0 +1,28 @@ +vhdl work "E:/work/lib/HDL/Cores/CPUs/DLX/dlx_types.vhdl" +vhdl work "E:/work/lib/HDL/Cores/CPUs/DLX/dlx_instr.vhdl" +vhdl work "E:/work/lib/HDL/Cores/CPUs/DLX/alu_types.vhdl" +vhdl work "E:/work/lib/HDL/Cores/CPUs/DLX/reg_multiple_plus_one_out_reset.vhdl" +vhdl work "E:/work/lib/HDL/Cores/CPUs/DLX/reg_multiple_plus_one_out.vhdl" +vhdl work "E:/work/lib/HDL/Cores/CPUs/DLX/reg_multiple_out.vhdl" +vhdl work "E:/work/lib/HDL/Cores/CPUs/DLX/reg_file.vhdl" +vhdl work "E:/work/lib/HDL/Cores/CPUs/DLX/reg.vhdl" +vhdl work "E:/work/lib/HDL/Cores/CPUs/DLX/mux2.vhdl" +vhdl work "E:/work/lib/HDL/Cores/CPUs/DLX/ir_extender.vhdl" +vhdl work "E:/work/lib/HDL/Cores/CPUs/DLX/controller.vhdl" +vhdl work "E:/work/lib/HDL/Cores/CPUs/DLX/alu.vhdl" +vhdl work "E:/work/lib/HDL/Cores/CPUs/DLX/reg_multiple_plus_one_out_reset-behavior.vhdl" +vhdl work "E:/work/lib/HDL/Cores/CPUs/DLX/reg_multiple_plus_one_out-behavior.vhdl" +vhdl work "E:/work/lib/HDL/Cores/CPUs/DLX/reg_multiple_out-behavior.vhdl" +vhdl work "E:/work/lib/HDL/Cores/CPUs/DLX/reg_file-behavior.vhdl" +vhdl work "E:/work/lib/HDL/Cores/CPUs/DLX/reg-behavior.vhdl" +vhdl work "E:/work/lib/HDL/Cores/CPUs/DLX/mux2-behavior.vhdl" +vhdl work "E:/work/lib/HDL/Cores/CPUs/DLX/ir_extender-behavior.vhdl" +vhdl work "E:/work/lib/HDL/Cores/CPUs/DLX/controller-behavior.vhdl" +vhdl work "E:/work/lib/HDL/Cores/CPUs/DLX/alu-behavior.vhdl" +vhdl work "E:/work/lib/HDL/Cores/CPUs/DLX/memory.vhdl" +vhdl work "E:/work/lib/HDL/Cores/CPUs/DLX/dlx.vhdl" +vhdl work "E:/work/lib/HDL/Cores/CPUs/DLX/clock_gen.vhdl" +vhdl work "E:/work/lib/HDL/Cores/CPUs/DLX/memory-file_loaded.vhdl" +vhdl work "E:/work/lib/HDL/Cores/CPUs/DLX/dlx-rtl.vhdl" +vhdl work "E:/work/lib/HDL/Cores/CPUs/DLX/clock_gen-behavior.vhdl" +vhdl work "E:/work/lib/HDL/Cores/CPUs/DLX/dlx_test-verifier.vhdl" diff --git a/projects/dlx/syn/ise/project/dlx_test.xst b/projects/dlx/syn/ise/project/dlx_test.xst new file mode 100644 index 0000000..af56ea5 --- /dev/null +++ b/projects/dlx/syn/ise/project/dlx_test.xst @@ -0,0 +1,4 @@ +set -tmpdir ./xst/projnav.tmp +elaborate +-ifn dlx_test.prj +-ifmt mixed diff --git a/projects/dlx/syn/ise/project/dlx_test_vhdl.prj b/projects/dlx/syn/ise/project/dlx_test_vhdl.prj new file mode 100644 index 0000000..4005546 --- /dev/null +++ b/projects/dlx/syn/ise/project/dlx_test_vhdl.prj @@ -0,0 +1,28 @@ +work "E:\work\lib\HDL\Cores\CPUs\DLX\dlx_types.vhdl" +work "E:\work\lib\HDL\Cores\CPUs\DLX\dlx_instr.vhdl" +work "E:\work\lib\HDL\Cores\CPUs\DLX\alu_types.vhdl" +work "E:\work\lib\HDL\Cores\CPUs\DLX\reg_multiple_plus_one_out_reset.vhdl" +work "E:\work\lib\HDL\Cores\CPUs\DLX\reg_multiple_plus_one_out.vhdl" +work "E:\work\lib\HDL\Cores\CPUs\DLX\reg_multiple_out.vhdl" +work "E:\work\lib\HDL\Cores\CPUs\DLX\reg_file.vhdl" +work "E:\work\lib\HDL\Cores\CPUs\DLX\reg.vhdl" +work "E:\work\lib\HDL\Cores\CPUs\DLX\mux2.vhdl" +work "E:\work\lib\HDL\Cores\CPUs\DLX\ir_extender.vhdl" +work "E:\work\lib\HDL\Cores\CPUs\DLX\controller.vhdl" +work "E:\work\lib\HDL\Cores\CPUs\DLX\alu.vhdl" +work "E:\work\lib\HDL\Cores\CPUs\DLX\reg_multiple_plus_one_out_reset-behavior.vhdl" +work "E:\work\lib\HDL\Cores\CPUs\DLX\reg_multiple_plus_one_out-behavior.vhdl" +work "E:\work\lib\HDL\Cores\CPUs\DLX\reg_multiple_out-behavior.vhdl" +work "E:\work\lib\HDL\Cores\CPUs\DLX\reg_file-behavior.vhdl" +work "E:\work\lib\HDL\Cores\CPUs\DLX\reg-behavior.vhdl" +work "E:\work\lib\HDL\Cores\CPUs\DLX\mux2-behavior.vhdl" +work "E:\work\lib\HDL\Cores\CPUs\DLX\ir_extender-behavior.vhdl" +work "E:\work\lib\HDL\Cores\CPUs\DLX\controller-behavior.vhdl" +work "E:\work\lib\HDL\Cores\CPUs\DLX\alu-behavior.vhdl" +work "E:\work\lib\HDL\Cores\CPUs\DLX\memory.vhdl" +work "E:\work\lib\HDL\Cores\CPUs\DLX\dlx.vhdl" +work "E:\work\lib\HDL\Cores\CPUs\DLX\clock_gen.vhdl" +work "E:\work\lib\HDL\Cores\CPUs\DLX\memory-file_loaded.vhdl" +work "E:\work\lib\HDL\Cores\CPUs\DLX\dlx-rtl.vhdl" +work "E:\work\lib\HDL\Cores\CPUs\DLX\clock_gen-behavior.vhdl" +work "E:\work\lib\HDL\Cores\CPUs\DLX\dlx_test-verifier.vhdl" diff --git a/projects/dlx/syn/ise/project/prjname.lso b/projects/dlx/syn/ise/project/prjname.lso new file mode 100644 index 0000000..22de730 --- /dev/null +++ b/projects/dlx/syn/ise/project/prjname.lso @@ -0,0 +1 @@ +work