git-svn-id: http://moon:8086/svn/vhdl/trunk@1424 cc03376c-175c-47c8-b038-4cd826a8556b
This commit is contained in:
2021-03-21 11:37:55 +00:00
parent 73cfd45401
commit bdb8fec295
83 changed files with 9477 additions and 0 deletions
Binary file not shown.
+9
View File
@@ -0,0 +1,9 @@
#!/bin/sh
std_opt="--workdir=work"
srcdir="./src"
ghdl --remove $std_opt
ghdl -i $std_opt $srcdir/*.vhdl
ghdl -m $std_opt dlx_test_behaviour
ghdl -r dlx_test_behaviour --vcd=dlx_test_behaviour.vcd --assert-level=note
+48
View File
@@ -0,0 +1,48 @@
This directory contains the source files for the DLX model suite.
The following copyright holds:
-- 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.
This suite is distributed as is, with no documentation or support. If
I get time, I may provide documentation at a later date.
Included in the directory is a file called module-directory, that
lists the source files with a brief description of each. You should
be able to compile them in the order listed.
To run a simulation that includes the memory entity, you will need to
have a file called dlx.out in the current working directory. This is
the memory image file loaded by the memory entity, containing DLX
instructions and data. The distribution directory contains two sample
DLX programs, simple.s and test_loop.s, along with assembled versions
in simple.out and test_loop.out. You can copy one of the .out files
to dlx.out to run the simulation.
I would be pleased to hear comments or bug reports (ie, bugs in the
model, not bugs in your VHDL tools!). You can mail them to me at the
above e-mail address.
Have fun!
Peter A.
2 November 1993.
+38
View File
@@ -0,0 +1,38 @@
---------------------------------------------------------------------------------------------------------------------------------------------------
Software Liability Information
The software package(s) (VHDL models, style guides, etc.) that you have are from
the RASSP server (http://rassp.scra.org). SCRA is maintaining this server for
DARPA as the RASSP Educator and Facilitator in order to provide current and
easily accessible information to the research community. While SCRA & DARPA
intend to keep the information accurate and timely, it cannot guarantee either.
Errors may be brought to our attention via email at info@rassp.scra.org and will
be corrected as soon as possible.
The use or purpose for which these Software Package(s) were developed may not be
appropriate for your intended use. The authors or distributors of this code are
not responsible for correctness or accuracy of the material in this package.
This code may not be distributed for commercial purposes unless provided for in
the software package itself.
WARRANTY
BY USING THESE SOFTWARE PACKAGES, USER EXPRESSLY AGREES THAT USE IS AT USER'S
SOLE RISK. IN NO EVENT SHALL THE UNITED STATES GOVERNMENT, SOUTH CAROLINA
RESEARCH AUTHORITY (SCRA), THE AUTHORS, OR THE COPYRIGHT HOLDERS BE LIABLE FOR
ANY INCIDENTAL, INDIRECT , SPECIAL, OR CONSEQUENTIAL DAMAGES WHATSOEVER ARISING
OUT OF OR RELATING TO THE USE OF THE INFORMATION/SOFTWARE PROVIDED IN THIS
PACKAGE. THE USER ASSUMES ALL RISKS, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL
OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PACKAGE
(INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR
LOSSES SUSTAINED BY USER OR THIRD PARTIES OR A FAILURE OF THE PACKAGE TO
OPERATE WITH ANY OTHER PACKAGES), EVEN IF THE UNITED STATES GOVERNMENT, SOUTH
CAROLINA RESEARCH AUTHORITY (SCRA), THE AUTHORS, THE COPYRIGHT HOLDERS, OR OTHER
PARTIES HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. THE PACKAGE IS
PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED. NO
WARRANTY OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE IS GIVEN OR
IMPLIED. THE ENTIRE RISK AS TO THE QUALITY, VALIDITY, AND PERFORMANCE OF THE
PACKAGE IS WITH THE USER. SHOULD THE PACKAGE PROVE DEFECTIVE, THE USER ASSUMES
ANY COST OF NECESSARY SERVICING, REPAIR OR CORRECTION.
---------------------------------------------------------------------------------------------------------------------------------------------------------
+38
View File
@@ -0,0 +1,38 @@
---------------------------------------------------------------------------------------------------------------------------------------------------
Software Liability Information
The software package(s) (VHDL models, style guides, etc.) that you have are from
the RASSP server (http://rassp.scra.org). SCRA is maintaining this server for
DARPA as the RASSP Educator and Facilitator in order to provide current and
easily accessible information to the research community. While SCRA & DARPA
intend to keep the information accurate and timely, it cannot guarantee either.
Errors may be brought to our attention via email at info@rassp.scra.org and will
be corrected as soon as possible.
The use or purpose for which these Software Package(s) were developed may not be
appropriate for your intended use. The authors or distributors of this code are
not responsible for correctness or accuracy of the material in this package.
This code may not be distributed for commercial purposes unless provided for in
the software package itself.
WARRANTY
BY USING THESE SOFTWARE PACKAGES, USER EXPRESSLY AGREES THAT USE IS AT USER'S
SOLE RISK. IN NO EVENT SHALL THE UNITED STATES GOVERNMENT, SOUTH CAROLINA
RESEARCH AUTHORITY (SCRA), THE AUTHORS, OR THE COPYRIGHT HOLDERS BE LIABLE FOR
ANY INCIDENTAL, INDIRECT , SPECIAL, OR CONSEQUENTIAL DAMAGES WHATSOEVER ARISING
OUT OF OR RELATING TO THE USE OF THE INFORMATION/SOFTWARE PROVIDED IN THIS
PACKAGE. THE USER ASSUMES ALL RISKS, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL
OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PACKAGE
(INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR
LOSSES SUSTAINED BY USER OR THIRD PARTIES OR A FAILURE OF THE PACKAGE TO
OPERATE WITH ANY OTHER PACKAGES), EVEN IF THE UNITED STATES GOVERNMENT, SOUTH
CAROLINA RESEARCH AUTHORITY (SCRA), THE AUTHORS, THE COPYRIGHT HOLDERS, OR OTHER
PARTIES HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. THE PACKAGE IS
PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED. NO
WARRANTY OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE IS GIVEN OR
IMPLIED. THE ENTIRE RISK AS TO THE QUALITY, VALIDITY, AND PERFORMANCE OF THE
PACKAGE IS WITH THE USER. SHOULD THE PACKAGE PROVE DEFECTIVE, THE USER ASSUMES
ANY COST OF NECESSARY SERVICING, REPAIR OR CORRECTION.
---------------------------------------------------------------------------------------------------------------------------------------------------------
+81
View File
@@ -0,0 +1,81 @@
--------------------------------------------------------------------------
--
-- 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-behaviour.vhdl,v $ $Revision: 2.1 $ $Date: 1993/11/02 18:52:07 $
--
--------------------------------------------------------------------------
--
-- Behavioural architecture of ALU.
--
architecture behaviour of alu is
begin
alu_op: process (s1, s2, latch_en, func)
use work.bv_arithmetic.all;
variable stored_s1, stored_s2 : dlx_word;
variable temp_result : dlx_word;
variable temp_overflow : boolean;
begin
if latch_en = '1' then
stored_s1 := s1;
stored_s2 := s2;
end if;
case func is
when alu_pass_s1 =>
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;
+45
View File
@@ -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;
+39
View File
@@ -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;
+982
View File
@@ -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;
+238
View File
@@ -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;
File diff suppressed because it is too large Load Diff
+36
View File
@@ -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;
+310
View File
@@ -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;
+61
View File
@@ -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;
+36
View File
@@ -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;
+48
View File
@@ -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;
+42
View File
@@ -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;
@@ -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;
+33
View File
@@ -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;
+858
View File
@@ -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;
+71
View File
@@ -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;
+63
View File
@@ -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
+614
View File
@@ -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;
+687
View File
@@ -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;
+286
View File
@@ -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;
+50
View File
@@ -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;
@@ -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;
+50
View File
@@ -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;
+258
View File
@@ -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;
+257
View File
@@ -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;
+104
View File
@@ -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;
+139
View File
@@ -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;
+33
View File
@@ -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;
+59
View File
@@ -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;
+74
View File
@@ -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;
@@ -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;
+103
View File
@@ -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;
+45
View File
@@ -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;
+44
View File
@@ -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;
+167
View File
@@ -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;
+61
View File
@@ -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;
+89
View File
@@ -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;
+35
View File
@@ -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;
+88
View File
@@ -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;
+46
View File
@@ -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;
+43
View File
@@ -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;
+41
View File
@@ -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;
+36
View File
@@ -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;
+226
View File
@@ -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;
+54
View File
@@ -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;
+330
View File
@@ -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;
+33
View File
@@ -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;
+158
View File
@@ -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.
+37
View File
@@ -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;
+41
View File
@@ -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;
+51
View File
@@ -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;
+42
View File
@@ -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;
@@ -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;
+44
View File
@@ -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;
+56
View File
@@ -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;
+42
View File
@@ -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;
+61
View File
@@ -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;
+42
View File
@@ -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;
+76
View File
@@ -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;
+46
View File
@@ -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;
+2
View File
@@ -0,0 +1,2 @@
00000000 20020000
00000004 44000000
+3
View File
@@ -0,0 +1,3 @@
.text 0
addi r2, r0, 0 ; r2 := 0
trap 0
+6
View File
@@ -0,0 +1,6 @@
00000000 20020000
00000004 ac020018
00000008 20420001
0000000c 6441000a
00000010 1420fff0
00000014 44000000
+10
View File
@@ -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
@@ -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"
@@ -0,0 +1,4 @@
set -tmpdir ./xst/projnav.tmp
elaborate
-ifn controller.prj
-ifmt mixed
@@ -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"
+14
View File
@@ -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
+1
View File
@@ -0,0 +1 @@
work
+3
View File
@@ -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"
+4
View File
@@ -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
+55
View File
@@ -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
+19
View File
@@ -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
@@ -0,0 +1 @@
work
+28
View File
@@ -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"
@@ -0,0 +1,4 @@
set -tmpdir ./xst/projnav.tmp
elaborate
-ifn dlx_test.prj
-ifmt mixed
@@ -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"
+1
View File
@@ -0,0 +1 @@
work