From 7e1b772d5614cae30543f003aecb4ffae8d705c5 Mon Sep 17 00:00:00 2001 From: Marcel Date: Sun, 6 Sep 2020 18:16:38 +0200 Subject: [PATCH] add 68k10 and 68k30 to common --- common/CPU/68K10/license/cern_ohl_v_1_2.odt | Bin 0 -> 25148 bytes common/CPU/68K10/license/cern_ohl_v_1_2.pdf | Bin 0 -> 98023 bytes common/CPU/68K10/license/cern_ohl_v_1_2.txt | 897 ++++++ .../68K10/license/cern_ohl_v_1_2_howto.odt | Bin 0 -> 36026 bytes .../68K10/license/cern_ohl_v_1_2_howto.pdf | Bin 0 -> 56377 bytes common/CPU/68K10/wf68K10.sdc | 40 + .../CPU/68K10/wf68k10_address_registers.vhd | 512 ++++ common/CPU/68K10/wf68k10_alu.vhd | 1071 +++++++ common/CPU/68K10/wf68k10_bus_interface.vhd | 767 +++++ common/CPU/68K10/wf68k10_control.vhd | 2044 +++++++++++++ common/CPU/68K10/wf68k10_data_registers.vhd | 137 + .../CPU/68K10/wf68k10_exception_handler.vhd | 818 ++++++ common/CPU/68K10/wf68k10_opcode_decoder.vhd | 1228 ++++++++ common/CPU/68K10/wf68k10_pkg.vhd | 413 +++ common/CPU/68K10/wf68k10_top.vhd | 1257 ++++++++ common/CPU/68K30L/license/cern_ohl_v_1_2.odt | Bin 0 -> 25148 bytes common/CPU/68K30L/license/cern_ohl_v_1_2.pdf | Bin 0 -> 98023 bytes common/CPU/68K30L/license/cern_ohl_v_1_2.txt | 897 ++++++ .../68K30L/license/cern_ohl_v_1_2_howto.odt | Bin 0 -> 36026 bytes .../68K30L/license/cern_ohl_v_1_2_howto.pdf | Bin 0 -> 56377 bytes common/CPU/68K30L/wf68K30L.sdc | 40 + .../CPU/68K30L/wf68k30L_address_registers.vhd | 680 +++++ common/CPU/68K30L/wf68k30L_alu.vhd | 1264 ++++++++ common/CPU/68K30L/wf68k30L_bus_interface.vhd | 879 ++++++ common/CPU/68K30L/wf68k30L_control.vhd | 2553 +++++++++++++++++ common/CPU/68K30L/wf68k30L_data_registers.vhd | 137 + .../CPU/68K30L/wf68k30L_exception_handler.vhd | 934 ++++++ common/CPU/68K30L/wf68k30L_opcode_decoder.vhd | 1345 +++++++++ common/CPU/68K30L/wf68k30L_pkg.vhd | 457 +++ common/CPU/68K30L/wf68k30L_top.vhd | 1212 ++++++++ 30 files changed, 19582 insertions(+) create mode 100644 common/CPU/68K10/license/cern_ohl_v_1_2.odt create mode 100644 common/CPU/68K10/license/cern_ohl_v_1_2.pdf create mode 100644 common/CPU/68K10/license/cern_ohl_v_1_2.txt create mode 100644 common/CPU/68K10/license/cern_ohl_v_1_2_howto.odt create mode 100644 common/CPU/68K10/license/cern_ohl_v_1_2_howto.pdf create mode 100644 common/CPU/68K10/wf68K10.sdc create mode 100644 common/CPU/68K10/wf68k10_address_registers.vhd create mode 100644 common/CPU/68K10/wf68k10_alu.vhd create mode 100644 common/CPU/68K10/wf68k10_bus_interface.vhd create mode 100644 common/CPU/68K10/wf68k10_control.vhd create mode 100644 common/CPU/68K10/wf68k10_data_registers.vhd create mode 100644 common/CPU/68K10/wf68k10_exception_handler.vhd create mode 100644 common/CPU/68K10/wf68k10_opcode_decoder.vhd create mode 100644 common/CPU/68K10/wf68k10_pkg.vhd create mode 100644 common/CPU/68K10/wf68k10_top.vhd create mode 100644 common/CPU/68K30L/license/cern_ohl_v_1_2.odt create mode 100644 common/CPU/68K30L/license/cern_ohl_v_1_2.pdf create mode 100644 common/CPU/68K30L/license/cern_ohl_v_1_2.txt create mode 100644 common/CPU/68K30L/license/cern_ohl_v_1_2_howto.odt create mode 100644 common/CPU/68K30L/license/cern_ohl_v_1_2_howto.pdf create mode 100644 common/CPU/68K30L/wf68K30L.sdc create mode 100644 common/CPU/68K30L/wf68k30L_address_registers.vhd create mode 100644 common/CPU/68K30L/wf68k30L_alu.vhd create mode 100644 common/CPU/68K30L/wf68k30L_bus_interface.vhd create mode 100644 common/CPU/68K30L/wf68k30L_control.vhd create mode 100644 common/CPU/68K30L/wf68k30L_data_registers.vhd create mode 100644 common/CPU/68K30L/wf68k30L_exception_handler.vhd create mode 100644 common/CPU/68K30L/wf68k30L_opcode_decoder.vhd create mode 100644 common/CPU/68K30L/wf68k30L_pkg.vhd create mode 100644 common/CPU/68K30L/wf68k30L_top.vhd diff --git a/common/CPU/68K10/license/cern_ohl_v_1_2.odt b/common/CPU/68K10/license/cern_ohl_v_1_2.odt new file mode 100644 index 0000000000000000000000000000000000000000..0e4038a4f57e3a45b037e14cb1b89b92c1795150 GIT binary patch literal 25148 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 + + + +CERN Open Hardware Licence - cern_ohl_v_1_2.txt - Open Hardware Repository + + + + + + + + + + + + + + + + + + + +
+
+ + + + +
+ + +
+ +

cern_ohl_v_1_2.txt

+ +
+

Licence text in text format. - + Javier Serrano, 2013-09-06 10:05

+

Download (8.9 kB)

+ +
+  +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1
CERN Open Hardware Licence v1.2 
+
2
+
3
Preamble
+
4
+
5
Through this CERN Open Hardware Licence ("CERN OHL") version 1.2, CERN
+
6
wishes to provide a tool to foster collaboration and sharing among
+
7
hardware designers.  The CERN OHL is copyright CERN. Anyone is welcome
+
8
to use the CERN OHL, in unmodified form only, for the distribution of
+
9
their own Open Hardware designs. Any other right is reserved. Release
+
10
of hardware designs under the CERN OHL does not constitute an
+
11
endorsement of the licensor or its designs nor does it imply any
+
12
involvement by CERN in the development of such designs.
+
13
+
14
1. Definitions
+
15
+
16
In this Licence, the following terms have the following meanings:
+
17
 
+
18
“Licence” means this CERN OHL.
+
19
+
20
“Documentation” means schematic diagrams, designs, circuit or circuit
+
21
board layouts, mechanical drawings, flow charts and descriptive text,
+
22
and other explanatory material that is explicitly stated as being made
+
23
available under the conditions of this Licence. The Documentation may
+
24
be in any medium, including but not limited to computer files and
+
25
representations on paper, film, or any other media.
+
26
+
27
“Documentation Location” means a location where the Licensor has
+
28
placed Documentation, and which he believes will be publicly
+
29
accessible for at least three years from the first communication to
+
30
the public or distribution of Documentation.
+
31
+
32
“Product” means either an entire, or any part of a, device built using
+
33
the Documentation or the modified Documentation.
+
34
+
35
“Licensee” means any natural or legal person exercising rights under
+
36
this Licence.
+
37
+
38
“Licensor” means any natural or legal person that creates or modifies
+
39
Documentation and subsequently communicates to the public and/ or
+
40
distributes the resulting Documentation under the terms and conditions
+
41
of this Licence.
+
42
+
43
A Licensee may at the same time be a Licensor, and vice versa. 
+
44
+
45
Use of the masculine gender includes the feminine and neuter genders
+
46
and is employed solely to facilitate reading.
+
47
+
48
2. Applicability
+
49
+
50
2.1. This Licence governs the use, copying, modification,
+
51
communication to the public and distribution of the Documentation, and
+
52
the manufacture and distribution of Products. By exercising any right
+
53
granted under this Licence, the Licensee irrevocably accepts these
+
54
terms and conditions.
+
55
+
56
2.2. This Licence is granted by the Licensor directly to the Licensee,
+
57
and shall apply worldwide and without limitation in time. The Licensee
+
58
may assign his licence rights or grant sub-licences.
+
59
+
60
2.3. This Licence does not extend to software, firmware, or code
+
61
loaded into programmable devices which may be used in conjunction with
+
62
the Documentation, the modified Documentation or with Products, unless
+
63
such software, firmware, or code is explicitly expressed to be subject
+
64
to this Licence. The use of such software, firmware, or code is
+
65
otherwise subject to the applicable licence terms and conditions.
+
66
+
67
3. Copying, modification, communication to the public and distribution
+
68
of the Documentation
+
69
+
70
3.1. The Licensee shall keep intact all copyright and trademarks
+
71
notices, all notices referring to Documentation Location, and all
+
72
notices that refer to this Licence and to the disclaimer of warranties
+
73
that are included in the Documentation. He shall include a copy
+
74
thereof in every copy of the Documentation or, as the case may be,
+
75
modified Documentation, that he communicates to the public or
+
76
distributes.
+
77
+
78
3.2. The Licensee may copy, communicate to the public and distribute
+
79
verbatim copies of the Documentation, in any medium, subject to the
+
80
requirements specified in section 3.1.
+
81
+
82
3.3. The Licensee may modify the Documentation or any portion thereof
+
83
provided that upon modification of the Documentation, the Licensee
+
84
shall make the modified Documentation available from a Documentation
+
85
Location such that it can be easily located by an original Licensor
+
86
once the Licensee communicates to the public or distributes the
+
87
modified Documentation under section 3.4, and, where required by
+
88
section 4.1, by a recipient of a Product. However, the Licensor shall
+
89
not assert his rights under the foregoing proviso unless or until a
+
90
Product is distributed.
+
91
+
92
3.4. The Licensee may communicate to the public and distribute the
+
93
modified Documentation (thereby in addition to being a Licensee also
+
94
becoming a Licensor), always provided that he shall:
+
95
+
96
a) comply with section 3.1;
+
97
+
98
b) cause the modified Documentation to carry prominent notices stating
+
99
that the Licensee has modified the Documentation, with the date and
+
100
description of the modifications;
+
101
+
102
c) cause the modified Documentation to carry a new Documentation
+
103
Location notice if the original Documentation provided for one;
+
104
+
105
d) make available the modified Documentation at the same level of
+
106
abstraction as that of the Documentation, in the preferred format for
+
107
making modifications to it (e.g. the native format of the CAD tool as
+
108
applicable), and in the event that format is proprietary, in a format
+
109
viewable with a tool licensed under an OSI-approved license if the
+
110
proprietary tool can create it; and
+
111
+
112
e) license the modified Documentation under the terms and conditions
+
113
of this Licence or, where applicable, a later version of this Licence
+
114
as may be issued by CERN.
+
115
+
116
3.5. The Licence includes a non-exclusive licence to those patents or
+
117
registered designs that are held by, under the control of, or
+
118
sub-licensable by the Licensor, to the extent necessary to make use of
+
119
the rights granted under this Licence. The scope of this section 3.5
+
120
shall be strictly limited to the parts of the Documentation or
+
121
modified Documentation created by the Licensor.
+
122
+
123
4. Manufacture and distribution of Products
+
124
+
125
4.1. The Licensee may manufacture or distribute Products always
+
126
provided that, where such manufacture or distribution requires a
+
127
licence under this Licence the Licensee provides to each recipient of
+
128
such Products an easy means of accessing a copy of the Documentation
+
129
or modified Documentation, as applicable, as set out in section 3.
+
130
+
131
4.2. The Licensee is invited to inform any Licensor who has indicated
+
132
his wish to receive this information about the type, quantity and
+
133
dates of production of Products the Licensee has (had) manufactured
+
134
+
135
5. Warranty and liability
+
136
+
137
5.1. DISCLAIMER – The Documentation and any modified Documentation are
+
138
provided "as is" and any express or implied warranties, including, but
+
139
not limited to, implied warranties of merchantability, of satisfactory
+
140
quality, non-infringement of third party rights, and fitness for a
+
141
particular purpose or use are disclaimed in respect of the
+
142
Documentation, the modified Documentation or any Product. The Licensor
+
143
makes no representation that the Documentation, modified
+
144
Documentation, or any Product, does or will not infringe any patent,
+
145
copyright, trade secret or other proprietary right. The entire risk as
+
146
to the use, quality, and performance of a Product shall be with the
+
147
Licensee and not the Licensor. This disclaimer of warranty is an
+
148
essential part of this Licence and a condition for the grant of any
+
149
rights granted under this Licence. The Licensee warrants that it does
+
150
not act in a consumer capacity.
+
151
+
152
5.2. LIMITATION OF LIABILITY – The Licensor shall have no liability
+
153
for direct, indirect, special, incidental, consequential, exemplary,
+
154
punitive or other damages of any character including, without
+
155
limitation, procurement of substitute goods or services, loss of use,
+
156
data or profits, or business interruption, however caused and on any
+
157
theory of contract, warranty, tort (including negligence), product
+
158
liability or otherwise, arising in any way in relation to the
+
159
Documentation, modified Documentation and/or the use, manufacture or
+
160
distribution of a Product, even if advised of the possibility of such
+
161
damages, and the Licensee shall hold the Licensor(s) free and harmless
+
162
from any liability, costs, damages, fees and expenses, including
+
163
claims by third parties, in relation to such use.
+
164
+
165
6. General
+
166
+
167
6.1. Except for the rights explicitly granted hereunder, this Licence
+
168
does not imply or represent any transfer or assignment of intellectual
+
169
property rights to the Licensee.
+
170
+
171
6.2. The Licensee shall not use or make reference to any of the names
+
172
(including acronyms and abbreviations), images, or logos under which
+
173
the Licensor is known, save in so far as required to comply with
+
174
section 3. Any such permitted use or reference shall be factual and
+
175
shall in no event suggest any kind of endorsement by the Licensor or
+
176
its personnel of the modified Documentation or any Product, or any
+
177
kind of implication by the Licensor or its personnel in the
+
178
preparation of the modified Documentation or Product.
+
179
+
180
6.3. CERN may publish updated versions of this Licence which retain
+
181
the same general provisions as this version, but differ in detail so
+
182
far this is required and reasonable. New versions will be published
+
183
with a unique version number.
+
184
+
185
6.4. This Licence shall terminate with immediate effect, upon written
+
186
notice and without involvement of a court if the Licensee fails to
+
187
comply with any of its terms and conditions, or if the Licensee
+
188
initiates legal action against Licensor in relation to this
+
189
Licence. Section 5 shall continue to apply.
+
+
+ + + + + + +
+
+
+ + + + +
+
+ + + + + + diff --git a/common/CPU/68K10/license/cern_ohl_v_1_2_howto.odt b/common/CPU/68K10/license/cern_ohl_v_1_2_howto.odt new file mode 100644 index 0000000000000000000000000000000000000000..0a1ea6bad3b9d6f28367df588c1923badd1fc7b2 GIT binary patch literal 36026 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 N!d1YM>sLF72LR{7@1g(z literal 0 HcmV?d00001 diff --git a/common/CPU/68K10/license/cern_ohl_v_1_2_howto.pdf b/common/CPU/68K10/license/cern_ohl_v_1_2_howto.pdf new file mode 100644 index 0000000000000000000000000000000000000000..feec8175c8dc265f19cb55d226c576455afeed22 GIT binary patch literal 56377 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 HlEd&Ha;r%$ literal 0 HcmV?d00001 diff --git a/common/CPU/68K10/wf68K10.sdc b/common/CPU/68K10/wf68K10.sdc new file mode 100644 index 00000000..024872bf --- /dev/null +++ b/common/CPU/68K10/wf68K10.sdc @@ -0,0 +1,40 @@ +# +# Copyright 2014 Wolfgang Foerster Inventronik GmbH. +# +# This documentation describes Open Hardware and is licensed +# under the CERN OHL v. 1.2. You may redistribute and modify +# this documentation under the terms of the CERN OHL v.1.2. +# (http://ohwr.org/cernohl). This documentation is distributed +# WITHOUT ANY EXPRESS OR IMPLIED WARRANTY, INCLUDING OF +# MERCHANTABILITY, SATISFACTORY QUALITY AND FITNESS FOR A +# PARTICULAR PURPOSE. Please see the CERN OHL v.1.2 for +# applicable conditions + +# Revision History + +# Revision 2K14B 20140922 WF +# Initial Release. + + +#************************************************************** +# Time Information +#************************************************************** + +# set_time_format -unit ns -decimal_places 3 + + + +#************************************************************** +# Create Clock +#************************************************************** + +# create_clock -name CLK -period 100.000 -waveform {0.000 50.000} [get_ports {CLK}] +create_clock -period 20.000 -name CLK [get_ports {CLK}] + +#derive_pll_clocks +#derive_pll_clocks -use_net_name +derive_clock_uncertainty + +#set_clock_groups -exclusive -group {CLK_PLL1} +#set_clock_groups -exclusive -group {CLK_PLL2} +#set_clock_groups -exclusive -group {CODEC_SCLK} diff --git a/common/CPU/68K10/wf68k10_address_registers.vhd b/common/CPU/68K10/wf68k10_address_registers.vhd new file mode 100644 index 00000000..c3d6578f --- /dev/null +++ b/common/CPU/68K10/wf68k10_address_registers.vhd @@ -0,0 +1,512 @@ +------------------------------------------------------------------------ +---- ---- +---- WF68K10 IP Core: Address register logic. ---- +---- ---- +---- Description: ---- +---- This module provides the address registers, stack pointers, ---- +---- the address arithmetics, the program counter logic and the SFC ---- +---- and DFC registers. The address registers are accessible by two ---- +---- read and two write ports simultaneously. For more information ---- +---- refer to the MC68030 User' Manual. ---- +---- ---- +---- Author(s): ---- +---- - Wolfgang Foerster, wf@experiment-s.de; wf@inventronik.de ---- +---- ---- +------------------------------------------------------------------------ +---- ---- +---- Copyright 2014-2019 Wolfgang Foerster Inventronik GmbH. ---- +---- ---- +---- This documentation describes Open Hardware and is licensed ---- +---- under the CERN OHL v. 1.2. You may redistribute and modify ---- +---- this documentation under the terms of the CERN OHL v.1.2. ---- +---- (http://ohwr.org/cernohl). This documentation is distributed ---- +---- WITHOUT ANY EXPRESS OR IMPLIED WARRANTY, INCLUDING OF ---- +---- MERCHANTABILITY, SATISFACTORY QUALITY AND FITNESS FOR A ---- +---- PARTICULAR PURPOSE. Please see the CERN OHL v.1.2 for ---- +---- applicable conditions ---- +---- ---- +------------------------------------------------------------------------ +-- +-- Revision History +-- +-- Revision 2K14B 20141201 WF +-- Initial Release. +-- Revision 2K16A 20160620 WF +-- Minor optimizations. +-- Revision 2K18A 20180620 WF +-- Changed ADR_ATN logic to be valid one clock cycle earlier. +-- Fixed PC restoring during exception processing. +-- Fixed the writing ISP_REG during EXG instruction with two address registers. +-- Fixed writing the stack pointer registers (SBIT_WB is used instead of SBIT). +-- The address registers are always written long. +-- Bugfix: exception handler do not increment and decrement the USP any more. +-- MOVEM-Fix: the effective address in memory to register is stored (STORE_AEFF) not to be overwritten in case the addressing register is also loaded. +-- Revision 2K19A 2019## WF +-- Removed ADR_ATN. We do not need this any more. +-- Fixed the condition if UNMARK and AR_MARK_USED are asserted simultaneously (see process P_IN_USE). +-- + +use work.WF68K10_PKG.all; + +library ieee; +use ieee.std_logic_1164.all; +use ieee.std_logic_unsigned.all; + +entity WF68K10_ADDRESS_REGISTERS is + port ( + CLK : in std_logic; + RESET : in bit; + + -- Address and data: + AR_IN_1 : in std_logic_vector(31 downto 0); + AR_IN_2 : in std_logic_vector(31 downto 0); + AR_OUT_1 : out std_logic_vector(31 downto 0); + AR_OUT_2 : out std_logic_vector(31 downto 0); + INDEX_IN : in std_logic_vector(31 downto 0); + PC : out std_logic_vector(31 downto 0); -- Program counter (or sPC) always word aligned. + PC_EW_OFFSET : in std_logic_vector(3 downto 0); -- Offset to the first address extension word. + STORE_ADR_FORMAT : in bit; + STORE_ABS_HI : in bit; + STORE_ABS_LO : in bit; + STORE_D16 : in bit; + STORE_DISPL : in bit; + STORE_AEFF : in bit; + OP_SIZE : in OP_SIZETYPE; + + ADR_OFFSET : in std_logic_vector(31 downto 0); + ADR_MARK_USED : in bit; + USE_APAIR : in boolean; + ADR_IN_USE : out bit; + + ADR_MODE : in std_logic_vector(2 downto 0); + AMODE_SEL : in std_logic_vector(2 downto 0); + ADR_EFF : out std_logic_vector(31 downto 0); -- This is the effective address. + ADR_EFF_WB : out std_logic_vector(31 downto 0); -- This is the effective address. + + DFC : out std_logic_vector(2 downto 0); + DFC_WR : in bit; + SFC : out std_logic_vector(2 downto 0); + SFC_WR : in bit; + + ISP_DEC : in bit; + ISP_WR : in bit; + USP_RD : in bit; + USP_WR : in bit; + + -- Registers controls: + AR_MARK_USED : in bit; + AR_IN_USE : out bit; + AR_SEL_RD_1 : in std_logic_vector(2 downto 0); + AR_SEL_RD_2 : in std_logic_vector(2 downto 0); + AR_SEL_WR_1 : in std_logic_vector(2 downto 0); + AR_SEL_WR_2 : in std_logic_vector(2 downto 0); + AR_DEC : in bit; -- Address register decrement. + AR_INC : in bit; -- Address register increment. + AR_WR_1 : in bit; -- Address register write. + AR_WR_2 : in bit; -- Address register write. + UNMARK : in bit; + + EXT_WORD : in std_logic_vector(15 downto 0); + + SBIT : in std_logic; + + SP_ADD_DISPL : in bit; + RESTORE_ISP_PC : in bit; + + -- Other controls: + DISPLACEMENT : in std_logic_vector(31 downto 0); + PC_ADD_DISPL : in bit; + PC_INC : in bit; -- Program counter increment. + PC_LOAD : in bit; -- Program counter write. + PC_RESTORE : in bit; + PC_OFFSET : in std_logic_vector(7 downto 0) + ); +end entity WF68K10_ADDRESS_REGISTERS; + +architecture BEHAVIOR of WF68K10_ADDRESS_REGISTERS is +type AR_TYPE is array(0 to 6) of std_logic_vector(31 downto 0); +signal ADR_EFF_I : std_logic_vector(31 downto 0); +signal AR : AR_TYPE; -- Address registers A0 to A6. +signal AR_OUT_1_I : std_logic_vector(31 downto 0); +signal AR_OUT_2_I : std_logic_vector(31 downto 0); +signal ADR_WB : std_logic_vector(32 downto 0); +signal AR_PNTR_1 : integer range 0 to 7; +signal AR_PNTR_2 : integer range 0 to 7; +signal AR_PNTR_WB_1 : integer range 0 to 7; +signal AR_PNTR_WB_2 : integer range 0 to 7; +signal AR_USED_1 : std_logic_vector(3 downto 0); +signal AR_USED_2 : std_logic_vector(3 downto 0); +signal DFC_REG : std_logic_vector(2 downto 0); -- Special function code registers. +signal ISP_REG : std_logic_vector(31 downto 0); -- Interrupt stack pointer (refers to A7'' in the supervisor mode). +signal SBIT_WB : std_logic; +signal PC_I : std_logic_vector(31 downto 0); -- Active program counter. +signal SCALE : std_logic_vector(1 downto 0); -- Scale information for the index. +signal SFC_REG : std_logic_vector(2 downto 0); -- Special function code registers. +signal USP_REG : std_logic_vector(31 downto 0); -- User stack pointer (refers to A7 in the user mode.). +begin + INBUFFER: process + begin + wait until CLK = '1' and CLK' event; + if AR_MARK_USED = '1' then + AR_PNTR_WB_1 <= conv_integer(AR_SEL_WR_1); + AR_PNTR_WB_2 <= conv_integer(AR_SEL_WR_2); + end if; + end process INBUFFER; + + AR_PNTR_1 <= conv_integer(AR_SEL_RD_1); + AR_PNTR_2 <= conv_integer(AR_SEL_RD_2); + + P_IN_USE: process + variable DELAY : boolean; + begin + wait until CLK = '1' and CLK' event; + if RESET = '1' or (UNMARK = '1' and AR_MARK_USED = '0') then + AR_USED_1(3) <= '0'; + AR_USED_2(3) <= '0'; + elsif AR_MARK_USED = '1' then + AR_USED_1 <= '1' & AR_SEL_WR_1; + if USE_APAIR = true then + AR_USED_2 <= '1' & AR_SEL_WR_2; + end if; + SBIT_WB <= SBIT; + end if; + -- + if RESET = '1' or (UNMARK = '1' and AR_MARK_USED = '0') then + ADR_WB(32) <= '0'; + DELAY := false; + elsif ADR_MARK_USED = '1' then + DELAY := true; -- One clock cycle address calculation delay. + elsif DELAY = true then + ADR_WB <= '1' & ADR_EFF_I; + DELAY := false; + end if; + end process P_IN_USE; + + AR_IN_USE <= '1' when AR_USED_1(3) = '1' and AR_USED_1(2 downto 0) = AR_SEL_RD_1 else + '1' when AR_USED_1(3) = '1' and AR_USED_1(2 downto 0) = AR_SEL_RD_2 else + '1' when AR_USED_2(3) = '1' and AR_USED_2(2 downto 0) = AR_SEL_RD_1 else + '1' when AR_USED_2(3) = '1' and AR_USED_2(2 downto 0) = AR_SEL_RD_2 else '0'; + + AR_OUT_1 <= AR_OUT_1_I; + AR_OUT_2 <= AR_OUT_2_I; + + ADR_IN_USE <= '1' when ADR_WB(32) = '1' and ADR_WB(31 downto 2) = ADR_EFF_I(31 downto 2) else -- Actual long word address. + '1' when ADR_WB(32) = '1' and ADR_WB(31 downto 2) - '1' = ADR_EFF_I(31 downto 2) else -- Lock a misaligned access. + '1' when ADR_WB(32) = '1' and ADR_WB(31 downto 2) + '1' = ADR_EFF_I(31 downto 2) else '0'; -- Lock a misaligned access. + + ADR_FORMAT: process + begin + wait until CLK = '1' and CLK' event; + if STORE_ADR_FORMAT = '1' then + SCALE <= EXT_WORD(10 downto 9); + end if; + end process ADR_FORMAT; + + ADDRESS_MODES: process(ADR_MODE, AMODE_SEL, AR, AR_PNTR_1, CLK, + ISP_REG, PC_EW_OFFSET, PC_I, RESTORE_ISP_PC, SBIT, USP_REG) + -- The effective address calculation takes place in this process depending on the + -- selected addressing mode. + -- The PC address (PC_I) used for the address calculation points to the first + -- extension word used. + variable ABS_ADDRESS : std_logic_vector(31 downto 0); + variable ADR_EFF_VAR : std_logic_vector(31 downto 0); + variable ADR_EFF_TMP : std_logic_vector(31 downto 0); + variable ADR_MUX : std_logic_vector(31 downto 0); + variable BASE_DISPL : std_logic_vector(31 downto 0); + variable INDEX : std_logic_vector(31 downto 0) := x"00000000"; + variable INDEX_SCALED : std_logic_vector(31 downto 0); + variable PCVAR : std_logic_vector(31 downto 0); + begin + PCVAR := PC_I + PC_EW_OFFSET; -- This is the address of the extension word. + + if CLK = '1' and CLK' event then + -- This logic selects the INDEX from one of the data registers or from one of + -- the address registers. Furthermore the index needs to be sign extended from + -- 8 bit to 32 bit or from 16 bit to 32 bit dependent on the address mode. + -- In case of a long word operation, no extension is required. The index is + -- multiplied by 1, 2, 4 or 8. + if STORE_ADR_FORMAT = '1' and EXT_WORD(15) = '0' and EXT_WORD(11) = '1' then + INDEX := INDEX_IN; -- Long data register. + elsif STORE_ADR_FORMAT = '1' and EXT_WORD(15) = '0' then + for i in 31 downto 16 loop + INDEX(i) := INDEX_IN(15); + end loop; + INDEX(15 downto 0) := INDEX_IN(15 downto 0); -- Sign extended data register; + elsif STORE_ADR_FORMAT = '1' and EXT_WORD(11) = '1' then -- Long address register. + if EXT_WORD(14 downto 12) = "111" and SBIT = '1' then + INDEX := ISP_REG; + elsif EXT_WORD(14 downto 12) = "111" and SBIT = '0' then + INDEX := USP_REG; + else + INDEX := AR(conv_integer(EXT_WORD(14 downto 12))); + end if; + elsif STORE_ADR_FORMAT = '1' then -- Sign extended address register; + if EXT_WORD(14 downto 12) = "111" and SBIT = '1' then + for i in 31 downto 16 loop + INDEX(i) := ISP_REG(15); + end loop; + INDEX(15 downto 0) := ISP_REG(15 downto 0); + elsif EXT_WORD(14 downto 12) = "111" and SBIT = '0' then + for i in 31 downto 16 loop + INDEX(i) := USP_REG(15); + end loop; + INDEX(15 downto 0) := USP_REG(15 downto 0); + else + for i in 31 downto 16 loop + INDEX(i) := AR(conv_integer(EXT_WORD(14 downto 12)))(15); + end loop; + INDEX(15 downto 0) := AR(conv_integer(EXT_WORD(14 downto 12)))(15 downto 0); + end if; + end if; + -- + case SCALE is + when "00" => INDEX_SCALED := INDEX; -- Multiple by 1. + when "01" => INDEX_SCALED := INDEX(30 downto 0) & '0'; -- Multiple by 2. + when "10" => INDEX_SCALED := INDEX(29 downto 0) & "00"; -- Multiple by 4. + when others => INDEX_SCALED := INDEX(28 downto 0) & "000"; -- Multiple by 8. + end case; + -- + -- The displacement needs to be sign extended from 8 bit to 32, from 16 bit to 32 bit or + -- not extended dependent on the address mode. + if RESET = '1' then + BASE_DISPL := (others => '0'); -- Null base displacement. + elsif STORE_ADR_FORMAT = '1' then + for i in 31 downto 8 loop + BASE_DISPL(i) := EXT_WORD(7); + end loop; + BASE_DISPL(7 downto 0) := EXT_WORD(7 downto 0); + elsif STORE_D16 = '1' then + for i in 31 downto 16 loop + BASE_DISPL(i) := EXT_WORD(15); + end loop; + BASE_DISPL(15 downto 0) := EXT_WORD; + elsif STORE_DISPL = '1' then + BASE_DISPL := DISPLACEMENT; + end if; + -- + if STORE_ABS_LO = '1' then + if AMODE_SEL = "000" then + for i in 31 downto 16 loop + ABS_ADDRESS(i) := EXT_WORD(15); + end loop; + end if; + ABS_ADDRESS(15 downto 0) := EXT_WORD; + elsif STORE_ABS_HI = '1' then + ABS_ADDRESS(31 downto 16) := EXT_WORD; + end if; + end if; + + case AR_PNTR_1 is + when 7 => + if SBIT = '1' then + ADR_MUX := ISP_REG; + else + ADR_MUX := USP_REG; + end if; + when others => ADR_MUX := AR(AR_PNTR_1); + end case; + + case ADR_MODE is + -- when "000" | "001" => Direct address modes: no effective address required. + when "010" | "011" | "100" => + ADR_EFF_VAR := ADR_MUX; -- (An), (An)+, -(An). + when "101" => -- Address register indirect with offset. Assembler syntax: (d16,An). + ADR_EFF_VAR := ADR_MUX + BASE_DISPL; -- (d16,An). + when "110" => + ADR_EFF_VAR := ADR_MUX + BASE_DISPL + INDEX_SCALED; -- (d8, An, Xn, SIZE*SCALE). + when "111" => + case AMODE_SEL is + when "000" | "001" => + ADR_EFF_VAR := ABS_ADDRESS; + when "010" => -- (d16, PC). + ADR_EFF_VAR := PCVAR + BASE_DISPL; + when "011" => + -- Assembler syntax: (d8,PC,Xn.SIZE*SCALE). + ADR_EFF_VAR := PCVAR + BASE_DISPL + INDEX_SCALED; -- (d8, PC, Xn, SIZE*SCALE). + when others => + ADR_EFF_VAR := (others => '-'); -- Don't care, while not used. + end case; + when others => + ADR_EFF_VAR := (others => '-'); -- Result not required. + end case; + -- + if CLK = '1' and CLK' event then + if RESTORE_ISP_PC = '1' then + ADR_EFF_I <= ADR_OFFSET; -- During exception processing. + elsif STORE_AEFF = '1' then -- Used for MOVEM. + ADR_EFF_I <= ADR_EFF_TMP + ADR_OFFSET; -- Keep the effective address. See also CONTROL section. + else -- Normal operation: + ADR_EFF_I <= ADR_EFF_VAR + ADR_OFFSET; + ADR_EFF_TMP := ADR_EFF_VAR; + end if; + end if; + end process ADDRESS_MODES; + + ADR_EFF <= ADR_EFF_I; + ADR_EFF_WB <= ADR_WB(31 downto 0); + + -- Data outputs: + AR_OUT_1_I <= USP_REG when USP_RD = '1' else + AR(AR_PNTR_1) when AR_PNTR_1 < 7 else + ISP_REG when SBIT = '1' else USP_REG; + + AR_OUT_2_I <= AR(AR_PNTR_2) when AR_PNTR_2 < 7 else + ISP_REG when SBIT = '1' else USP_REG; + + PC <= PC_I; + + PROGRAM_COUNTER: process + -- Note: PC_LOAD and PC_ADD_DISPL must be highest + -- prioritized. The reason is that in case of jumps + -- or branches the Ipipe is flushed in connection + -- with PC_INC. In such cases PC_LOAD or PC_ADD_DISPL + -- are asserted simultaneously with PC_INC. + begin + wait until CLK = '1' and CLK' event; + if RESET = '1' then + PC_I <= (others => '0'); + elsif PC_LOAD = '1' then + PC_I <= AR_IN_1; + elsif PC_ADD_DISPL = '1' then + PC_I <= PC_I + DISPLACEMENT; + elsif PC_RESTORE = '1' then + PC_I <= AR_IN_1; -- Keep prioritization! + elsif PC_INC = '1' then + PC_I <= PC_I + PC_OFFSET; + end if; + end process PROGRAM_COUNTER; + + STACK_POINTERS: process + -- The registers are modeled in a way + -- that write and simultaneously increment + -- decrement and others are possible for + -- different registers. + begin + wait until CLK = '1' and CLK' event; + ---------------------------------------- ISP section ---------------------------------------- + if RESET = '1' then + ISP_REG <= (others => '0'); + elsif AR_WR_1 = '1' and AR_PNTR_WB_1 = 7 and SBIT_WB = '1' then + ISP_REG <= AR_IN_1; -- Always written long. + end if; + + if AR_INC = '1' and AR_PNTR_1 = 7 and SBIT = '1' then + case OP_SIZE is + when BYTE => ISP_REG <= ISP_REG + "10"; -- Increment by two! + when WORD => ISP_REG <= ISP_REG + "10"; -- Increment by two. + when others => ISP_REG <= ISP_REG + "100"; -- Increment by four, (LONG). + end case; + end if; + + if ISP_DEC = '1' or (AR_DEC = '1' and AR_PNTR_1 = 7 and SBIT = '1') then + case OP_SIZE is + when BYTE => ISP_REG <= ISP_REG - "10"; -- Decrement by two! + when WORD => ISP_REG <= ISP_REG - "10"; -- Decrement by two. + when others => ISP_REG <= ISP_REG - "100"; -- Decrement by four, (LONG). + end case; + end if; + + if ISP_WR = '1' then + ISP_REG <= AR_IN_1; + elsif SP_ADD_DISPL = '1' and AR_INC = '1' and SBIT = '1' then + ISP_REG <= ISP_REG + DISPLACEMENT + "100"; -- Used for RTD. + elsif SP_ADD_DISPL = '1' and SBIT = '1' then + ISP_REG <= ISP_REG + DISPLACEMENT; + end if; + + ---------------------------------------- USP section ---------------------------------------- + if RESET = '1' then + USP_REG <= (others => '0'); + elsif AR_WR_1 = '1' and AR_PNTR_WB_1 = 7 and SBIT_WB = '0' then + USP_REG <= AR_IN_1; -- Always written long. + end if; + + if AR_INC = '1' and AR_PNTR_1 = 7 and SBIT = '0' then + case OP_SIZE is + when BYTE => USP_REG <= USP_REG + "10"; -- Increment by two! + when WORD => USP_REG <= USP_REG + "10"; -- Increment by two. + when others => USP_REG <= USP_REG + "100"; -- Increment by four, (LONG). + end case; + end if; + + if AR_DEC = '1' and AR_PNTR_1 = 7 and SBIT = '0' then + case OP_SIZE is + when BYTE => USP_REG <= USP_REG - "10"; -- Decrement by two! + when WORD => USP_REG <= USP_REG - "10"; -- Decrement by two. + when others => USP_REG <= USP_REG - "100"; -- Decrement by four, (LONG). + end case; + end if; + + if USP_WR = '1' then + USP_REG <= AR_IN_1; + elsif SP_ADD_DISPL = '1' and AR_INC = '1' and SBIT = '0' then + USP_REG <= USP_REG + DISPLACEMENT + "100"; -- Used for RTD. + elsif SP_ADD_DISPL = '1' and SBIT = '0' then + USP_REG <= USP_REG + DISPLACEMENT; + end if; + + ---------------------------------- ISP / USP section ---------------------------------------- + if AR_WR_2 = '1' and AR_PNTR_WB_2 = 7 and SBIT_WB = '1' then + ISP_REG <= AR_IN_2; -- Used for EXG and UNLK. + elsif AR_WR_2 = '1' and AR_PNTR_WB_2 = 7 then + USP_REG <= AR_IN_2; -- Used for EXG and UNLK. + end if; + end process STACK_POINTERS; + + ADDRESS_REGISTERS: process + -- The registers are modeled in a way + -- that write and simultaneously increment + -- decrement and others are possible for + -- different registers. + begin + -- + wait until CLK = '1' and CLK' event; + + if RESET = '1' then + AR <= (others => (Others => '0')); + end if; + + if AR_WR_1 = '1' and AR_PNTR_WB_1 < 7 then + AR(AR_PNTR_WB_1) <= AR_IN_1; -- Always written long. + end if; + + if AR_INC = '1' and AR_PNTR_1 < 7 then + case OP_SIZE is + when BYTE => AR(AR_PNTR_1) <= AR(AR_PNTR_1) + '1'; + when WORD => AR(AR_PNTR_1) <= AR(AR_PNTR_1) + "10"; + when others => AR(AR_PNTR_1) <= AR(AR_PNTR_1) + "100"; + end case; + end if; + + if AR_DEC = '1' and AR_PNTR_1 < 7 then + case OP_SIZE is + when BYTE => AR(AR_PNTR_1) <= AR(AR_PNTR_1) - '1'; + when WORD => AR(AR_PNTR_1) <= AR(AR_PNTR_1) - "10"; + when others => AR(AR_PNTR_1) <= AR(AR_PNTR_1) - "100"; + end case; + end if; + + if AR_WR_2 = '1' and AR_PNTR_WB_2 < 7 then + AR(AR_PNTR_WB_2) <= AR_IN_2; -- Used for EXG and UNLK. + end if; + end process ADDRESS_REGISTERS; + + FCODES: process + -- These flip flops provide the alternate function + -- code registers. + variable SFC_REG : std_logic_vector(2 downto 0); + variable DFC_REG : std_logic_vector(2 downto 0); + begin + wait until CLK = '1' and CLK' event; + if DFC_WR = '1' then + DFC_REG := AR_IN_1(2 downto 0); + end if; + -- + if SFC_WR = '1' then + SFC_REG := AR_IN_1(2 downto 0); + end if; + -- + DFC <= DFC_REG; + SFC <= SFC_REG; + end process FCODES; +end BEHAVIOR; diff --git a/common/CPU/68K10/wf68k10_alu.vhd b/common/CPU/68K10/wf68k10_alu.vhd new file mode 100644 index 00000000..5c7cdb78 --- /dev/null +++ b/common/CPU/68K10/wf68k10_alu.vhd @@ -0,0 +1,1071 @@ +------------------------------------------------------------------------ +---- ---- +---- WF68K10 IP Core: Address register logic. ---- +---- ---- +---- Description: ---- +---- This arithmetical logical unit handles all integer operations. ---- +---- The shift operations are computed by a standard shifter within ---- +---- up to 32 clock cycles depending on the shift width. The multi- ---- +---- plication is modeled as a hardware multiplier which calculates ---- +---- the result in one clock cycle. The division requires 32 clock ---- +---- cycles for 32 bit wide operands. The date which is required ---- +---- for the respective operation is stored in registers. The ALU ---- +---- works together with the writeback of the operands as third ---- +---- stage in the pipelined architecture. The handshaking is provi- ---- +---- ded by ALU_REQ, ALU_ACK and ALU_BUSY. For more information ---- +---- refer to the MC68010 User' Manual. ---- +---- ---- +---- Author(s): ---- +---- - Wolfgang Foerster, wf@experiment-s.de; wf@inventronik.de ---- +---- ---- +------------------------------------------------------------------------ +---- ---- +---- Copyright 2014-2019 Wolfgang Foerster Inventronik GmbH. ---- +---- ---- +---- This documentation describes Open Hardware and is licensed ---- +---- under the CERN OHL v. 1.2. You may redistribute and modify ---- +---- this documentation under the terms of the CERN OHL v.1.2. ---- +---- (http://ohwr.org/cernohl). This documentation is distributed ---- +---- WITHOUT ANY EXPRESS OR IMPLIED WARRANTY, INCLUDING OF ---- +---- MERCHANTABILITY, SATISFACTORY QUALITY AND FITNESS FOR A ---- +---- PARTICULAR PURPOSE. Please see the CERN OHL v.1.2 for ---- +---- applicable conditions ---- +---- ---- +------------------------------------------------------------------------ +-- +-- Revision History +-- +-- Revision 2K14B 20141201 WF +-- Initial Release. +-- Revision 2K18A 20180620 WF +-- Bug fix: MOVEM sign extension. +-- Fix for restoring correct values during the DIVS and DIVU in word format. +-- Fixed the SUBQ calculation. +-- Rearranged the Offset for the JSR instruction. +-- EXT instruction uses now RESULT(63 downto 0). +-- Shifter signals now ready if shift width is zero. +-- Fixed wrong condition codes for AND_B, ANDI, EOR, EORI, OR_B, ORI and NOT_B. +-- Fixed writeback issues in the status register logic. +-- Fixed the condition code calculation for NEG and NEGX. +-- Revision 2K19A 20190419 WF +-- Fixed a bug in MULU.W (input operands are now 16 bit wide). +-- + +library work; +use work.WF68K10_PKG.all; + +library ieee; +use ieee.std_logic_1164.all; +use ieee.std_logic_unsigned.all; +use ieee.numeric_std.all; + +entity WF68K10_ALU is + port ( + CLK : in std_logic; + RESET : in bit; + + LOAD_OP1 : in bit; + LOAD_OP2 : in bit; + LOAD_OP3 : in bit; + + OP1_IN : in Std_Logic_Vector(31 downto 0); + OP2_IN : in Std_Logic_Vector(31 downto 0); + OP3_IN : in Std_Logic_Vector(31 downto 0); + + BITPOS_IN : in Std_Logic_Vector(4 downto 0); + + RESULT : out Std_Logic_Vector(63 downto 0); + + ADR_MODE_IN : in Std_Logic_Vector(2 downto 0); + OP_SIZE_IN : in OP_SIZETYPE; + OP_IN : in OP_68K; + OP_WB : in OP_68K; + BIW_0_IN : in Std_Logic_Vector(11 downto 0); + BIW_1_IN : in Std_Logic_Vector(15 downto 0); + + -- The Flags: + SR_WR : in bit; + SR_INIT : in bit; + CC_UPDT : in bit; + + STATUS_REG_OUT : out std_logic_vector(15 downto 0); + ALU_COND : out boolean; + + -- Status and Control: + ALU_INIT : in bit; -- Strobe. + ALU_BSY : out bit; + ALU_REQ : buffer bit; + ALU_ACK : in bit; + IRQ_PEND : in std_logic_vector(2 downto 0); + TRAP_CHK : out bit; -- Trap due to the CHK instruction. + TRAP_DIVZERO : out bit -- Trap due to divide by zero. + ); +end entity WF68K10_ALU; + +architecture BEHAVIOUR of WF68K10_ALU is +type DIV_STATES is (IDLE, INIT, CALC); +type SHIFT_STATES is (IDLE, RUN); +signal ALU_COND_I : boolean; +signal ADR_MODE : Std_Logic_Vector(2 downto 0); +signal BITPOS : integer range 0 to 31; +signal BIW_0 : Std_Logic_Vector(11 downto 0); +signal BIW_1 : Std_Logic_Vector(15 downto 0); +signal CB_BCD : std_logic; +signal CHK_CMP_COND : boolean; +signal DIV_RDY : bit; +signal DIV_STATE : DIV_STATES := IDLE; +signal MSB : integer range 0 to 31; +signal OP : OP_68K := UNIMPLEMENTED; +signal OP1 : Std_Logic_Vector(31 downto 0); +signal OP2 : Std_Logic_Vector(31 downto 0); +signal OP3 : Std_Logic_Vector(31 downto 0); +signal OP1_SIGNEXT : Std_Logic_Vector(31 downto 0); +signal OP2_SIGNEXT : Std_Logic_Vector(31 downto 0); +signal OP_SIZE : OP_SIZETYPE := LONG; +signal QUOTIENT : unsigned(31 downto 0); +signal REMAINDER : unsigned(31 downto 0); +signal RESULT_BCDOP : Std_Logic_Vector(7 downto 0); +signal RESULT_BITOP : Std_Logic_Vector(31 downto 0); +signal RESULT_INTOP : Std_Logic_Vector(31 downto 0); +signal RESULT_LOGOP : Std_Logic_Vector(31 downto 0); +signal RESULT_MUL : Std_Logic_Vector(63 downto 0); +signal RESULT_SHIFTOP : Std_Logic_Vector(31 downto 0); +signal RESULT_OTHERS : Std_Logic_Vector(31 downto 0); +signal SHIFT_STATE : SHIFT_STATES; +signal SHIFT_WIDTH : Std_Logic_Vector(5 downto 0); +signal SHIFT_WIDTH_IN : Std_Logic_Vector(5 downto 0); +signal SHFT_LOAD : bit; +signal SHFT_RDY : bit; +signal SHFT_EN : bit; +signal STATUS_REG : Std_Logic_Vector(15 downto 0); +signal VFLAG_DIV : std_logic; +signal XFLAG_SHFT : std_logic; +signal XNZVC : Std_Logic_Vector(4 downto 0); +begin + PARAMETER_BUFFER: process + begin + wait until CLK = '1' and CLK' event; + if ALU_INIT = '1' then + ADR_MODE <= ADR_MODE_IN; + OP_SIZE <= OP_SIZE_IN; + OP <= OP_IN; + BIW_0 <= BIW_0_IN; + BIW_1 <= BIW_1_IN; + BITPOS <= To_Integer(unsigned(BITPOS_IN)); + SHIFT_WIDTH <= SHIFT_WIDTH_IN; + end if; + end process PARAMETER_BUFFER; + + OPERANDS: process + -- During instruction execution, the buffers are written + -- before or during ALU_INIT and copied to the operands + -- during ALU_INIT. + variable OP1_BUFFER : Std_Logic_Vector(31 downto 0); + variable OP2_BUFFER : Std_Logic_Vector(31 downto 0); + variable OP3_BUFFER : Std_Logic_Vector(31 downto 0); + begin + wait until CLK = '1' and CLK' event; + + if LOAD_OP1 = '1' then + OP1_BUFFER := OP1_IN; + end if; + + if LOAD_OP2 = '1' then + OP2_BUFFER := OP2_IN; + end if; + + if LOAD_OP3 = '1' then + OP3_BUFFER := OP3_IN; + end if; + + if ALU_INIT = '1' then + OP1 <= OP1_BUFFER; + OP2 <= OP2_BUFFER; + OP3 <= OP3_BUFFER; + end if; + end process OPERANDS; + + P_BUSY: process + begin + wait until CLK = '1' and CLK' event; + if ALU_INIT = '1' then + ALU_BSY <= '1'; + elsif ALU_ACK = '1' or RESET = '1' then + ALU_BSY <= '0'; + end if; + -- This signal requests the control state machine to proceed when the ALU is ready. + if ALU_ACK = '1' then + ALU_REQ <= '0'; + elsif (OP = ASL or OP = ASR or OP = LSL or OP = LSR or OP = ROTL or OP = ROTR or OP = ROXL or OP = ROXR) and SHFT_RDY = '1' then + ALU_REQ <= '1'; + elsif (OP = DIVS or OP = DIVU) and DIV_RDY = '1' then + ALU_REQ <= '1'; + elsif OP_IN = DIVS or OP_IN = DIVU then + null; + elsif OP_IN = ASL or OP_IN = ASR or OP_IN = LSL or OP_IN = LSR then + null; + elsif OP_IN = ROTL or OP_IN = ROTR or OP_IN = ROXL or OP_IN = ROXR then + null; + elsif ALU_INIT = '1' then + ALU_REQ <= '1'; + end if; + end process P_BUSY; + + with OP_SIZE select + MSB <= 31 when LONG, + 15 when WORD, + 7 when BYTE; + + SIGNEXT: process(OP, OP1, OP2, OP3, OP_SIZE) + -- This module provides the required sign extensions. + begin + case OP_SIZE is + when LONG => + OP1_SIGNEXT <= OP1; + OP2_SIGNEXT <= OP2; + when WORD => + for i in 31 downto 16 loop + OP1_SIGNEXT(i) <= OP1(15); + OP2_SIGNEXT(i) <= OP2(15); + end loop; + OP1_SIGNEXT(15 downto 0) <= OP1(15 downto 0); + OP2_SIGNEXT(15 downto 0) <= OP2(15 downto 0); + when BYTE => + for i in 31 downto 8 loop + OP1_SIGNEXT(i) <= OP1(7); + OP2_SIGNEXT(i) <= OP2(7); + end loop; + OP1_SIGNEXT(7 downto 0) <= OP1(7 downto 0); + OP2_SIGNEXT(7 downto 0) <= OP2(7 downto 0); + end case; + end process SIGNEXT; + + P_BCDOP: process(OP, STATUS_REG, OP1, OP2) + -- The BCD operations are all byte wide and unsigned. + variable X_IN_I : unsigned(0 downto 0); + variable TEMP0 : unsigned(4 downto 0); + variable TEMP1 : unsigned(4 downto 0); + variable Z_0 : unsigned(3 downto 0); + variable C_0 : unsigned(0 downto 0); + variable Z_1 : unsigned(3 downto 0); + variable C_1 : std_logic; + variable S_0 : unsigned(3 downto 0); + variable S_1 : unsigned(3 downto 0); + begin + X_IN_I(0) := STATUS_REG(4); -- Inverted extended Flag. + + case OP is + when ABCD => + TEMP0 := unsigned('0' & OP2(3 downto 0)) + unsigned('0' & OP1(3 downto 0)) + ("0000" & X_IN_I); + when NBCD => + TEMP0 := unsigned(OP1(4 downto 0)) - unsigned('0' & OP2(3 downto 0)) - ("0000" & X_IN_I); + when others => -- Valid for SBCD. + TEMP0 := unsigned('0' & OP2(3 downto 0)) - unsigned('0' & OP1(3 downto 0)) - ("0000" & X_IN_I); + end case; + + if Std_Logic_Vector(TEMP0) > "01001" then + Z_0 := "0110"; + C_0 := "1"; + else + Z_0 := "0000"; + C_0 := "0"; + end if; + + case OP is + when ABCD => + TEMP1 := unsigned('0' & OP2(7 downto 4)) + unsigned('0' & OP1(7 downto 4)) + ("0000" & C_0); + when NBCD => + TEMP1 := unsigned(OP1(4 downto 0)) - unsigned('0' & OP2(7 downto 4)) - ("0000" & X_IN_I); + when others => -- Valid for SBCD. + TEMP1 := unsigned('0' & OP2(7 downto 4)) - unsigned('0' & OP1(7 downto 4)) - ("0000" & C_0); + end case; + + if Std_Logic_Vector(TEMP1) > "01001" then + Z_1 := "0110"; + C_1 := '1'; + else + Z_1 := "0000"; + C_1 := '0'; + end if; + + case OP is + when ABCD => + S_1 := TEMP1(3 downto 0) + Z_1; + S_0 := TEMP0(3 downto 0) + Z_0; + when others => -- Valid for SBCD, NBCD. + S_1 := TEMP1(3 downto 0) - Z_1; + S_0 := TEMP0(3 downto 0) - Z_0; + end case; + -- + CB_BCD <= C_1; + RESULT_BCDOP(7 downto 4) <= Std_Logic_Vector(S_1); + RESULT_BCDOP(3 downto 0) <= Std_Logic_Vector(S_0); + end process P_BCDOP; + + P_BITOP: process(BITPOS, OP, OP2) + -- Bit manipulation operations. + begin + RESULT_BITOP <= OP2; -- The default is the unmanipulated data. + -- + case OP is + when BCHG => + RESULT_BITOP(BITPOS) <= not OP2(BITPOS); + when BCLR => + RESULT_BITOP(BITPOS) <= '0'; + when BSET => + RESULT_BITOP(BITPOS) <= '1'; + when others => + RESULT_BITOP <= OP2; -- Dummy, no result required for BTST. + end case; + end process P_BITOP; + + DIVISION: process + variable BITCNT : integer range 0 to 64; + variable DIVIDEND : unsigned(63 downto 0); + variable DIVISOR : unsigned(31 downto 0); + variable QUOTIENT_REST : unsigned(31 downto 0); + variable QUOTIENT_VAR : unsigned(31 downto 0); + variable REMAINDER_REST : unsigned(31 downto 0); + variable REMAINDER_VAR : unsigned(31 downto 0); + -- Be aware, that the destination and source operands + -- may be reloaded during the division operation. For + -- this, we use the restore values in case of an overflow. + begin + wait until CLK = '1' and CLK' event; + DIV_RDY <= '0'; + case DIV_STATE is + when IDLE => + if ALU_INIT = '1' and (OP_IN = DIVS or OP_IN = DIVU) then + DIV_STATE <= INIT; + end if; + when INIT => + if OP = DIVS and OP_SIZE = LONG and BIW_1(10) = '1' and OP3(31) = '1' then -- 64 bit signed negative dividend. + DIVIDEND := unsigned(not (OP3 & OP2) + '1'); + elsif (OP = DIVS or OP = DIVU) and OP_SIZE = LONG and BIW_1(10) = '1' then -- 64 bit positive or unsigned dividend. + DIVIDEND := unsigned(OP3 & OP2); + elsif OP = DIVS and OP2(31) = '1' then -- 32 bit signed negative dividend. + DIVIDEND := x"00000000" & unsigned(not(OP2) + '1'); + else -- 32 bit positive or unsigned dividend. + DIVIDEND := x"00000000" & unsigned(OP2); + end if; + + if OP = DIVS and OP_SIZE = LONG and OP1(31) = '1' then -- 32 bit signed negative divisor. + DIVISOR := unsigned(not OP1 + '1'); + elsif OP_SIZE = LONG then -- 32 bit positive or unsigned divisor. + DIVISOR := unsigned(OP1); + elsif OP = DIVS and OP_SIZE = WORD and OP1(15) = '1' then -- 16 bit signed negative divisor. + DIVISOR := x"0000" & unsigned(not OP1(15 downto 0) + '1'); + else -- 16 bit posive or unsigned divisor. + DIVISOR := x"0000" & unsigned(OP1(15 downto 0)); + end if; + + VFLAG_DIV <= '0'; + QUOTIENT <= (others => '0'); + QUOTIENT_VAR := (others => '0'); + QUOTIENT_REST := unsigned(OP2); + + REMAINDER <= (others => '0'); + REMAINDER_VAR := (others => '0'); + + case OP_SIZE is + when LONG => REMAINDER_REST := unsigned(OP3); + when others => REMAINDER_REST := unsigned(x"0000" & OP2(31 downto 16)); + end case; + + if OP_SIZE = LONG and BIW_1(10) = '1' then + BITCNT := 64; + else + BITCNT := 32; + end if; + + if DIVISOR = x"00000000" then -- Division by zero. + QUOTIENT <= (others => '1'); + REMAINDER <= (others => '1'); + DIV_STATE <= IDLE; + DIV_RDY <= '1'; + elsif x"00000000" & DIVISOR > DIVIDEND then -- Divisor > dividend. + REMAINDER <= DIVIDEND(31 downto 0); + DIV_STATE <= IDLE; + DIV_RDY <= '1'; + elsif x"00000000" & DIVISOR = DIVIDEND then -- Result is 1. + QUOTIENT <= x"00000001"; + DIV_STATE <= IDLE; + DIV_RDY <= '1'; + else + DIV_STATE <= CALC; + end if; + when CALC => + BITCNT := BITCNT - 1; + -- + if REMAINDER_VAR & DIVIDEND(BITCNT) < DIVISOR then + REMAINDER_VAR := REMAINDER_VAR(30 downto 0) & DIVIDEND(BITCNT); + elsif OP_SIZE = LONG and BITCNT > 31 then -- Division overflow in 64 bit mode. + VFLAG_DIV <= '1'; + DIV_STATE <= IDLE; + DIV_RDY <= '1'; + QUOTIENT <= QUOTIENT_REST; + REMAINDER <= REMAINDER_REST; + elsif OP_SIZE = WORD and BITCNT > 15 then -- Division overflow in 64 bit mode. + VFLAG_DIV <= '1'; + DIV_STATE <= IDLE; + DIV_RDY <= '1'; + QUOTIENT <= QUOTIENT_REST; + REMAINDER <= REMAINDER_REST; + else + REMAINDER_VAR := (REMAINDER_VAR(30 downto 0) & DIVIDEND(BITCNT)) - DIVISOR; + QUOTIENT_VAR(BITCNT) := '1'; + end if; + -- + if BITCNT = 0 then + -- Adjust signs: + if OP = DIVS and OP_SIZE = LONG and BIW_1(10) = '1' and (OP3(31) xor OP1(31)) = '1' then + QUOTIENT <= not QUOTIENT_VAR + 1; -- Negative, change sign. + elsif OP = DIVS and OP_SIZE = LONG and BIW_1(10) = '0' and (OP2(31) xor OP1(31)) = '1' then + QUOTIENT <= not QUOTIENT_VAR + 1; -- Negative, change sign. + elsif OP = DIVS and OP_SIZE = WORD and (OP2(31) xor OP1(15)) = '1' then + QUOTIENT <= not QUOTIENT_VAR + 1; -- Negative, change sign. + else + QUOTIENT <= QUOTIENT_VAR; + end if; + -- + REMAINDER <= REMAINDER_VAR; + DIV_RDY <= '1'; + DIV_STATE <= IDLE; + end if; + end case; + end process DIVISION; + + P_INTOP: process(OP, OP1, OP1_SIGNEXT, OP2, OP2_SIGNEXT, ADR_MODE, STATUS_REG, RESULT_INTOP) + -- The integer arithmetics ADD, SUB, NEG and CMP in their different variations are modelled here. + variable X_IN_I : Std_Logic_Vector(0 downto 0); + variable RESULT : unsigned(31 downto 0); + begin + X_IN_I(0) := STATUS_REG(4); -- Extended Flag. + case OP is + when ADDA => -- No sign extension for the destination. + RESULT := unsigned(OP2) + unsigned(OP1_SIGNEXT); + when ADDQ => + case ADR_MODE is + when "001" => RESULT := unsigned(OP2) + unsigned(OP1); -- No sign extension for address destination. + when others => RESULT := unsigned(OP2_SIGNEXT) + unsigned(OP1); + end case; + when SUBQ => + case ADR_MODE is + when "001" => RESULT := unsigned(OP2) - unsigned(OP1); -- No sign extension for address destination. + when others => RESULT := unsigned(OP2_SIGNEXT) - unsigned(OP1); + end case; + when ADD | ADDI => + RESULT := unsigned(OP2_SIGNEXT) + unsigned(OP1_SIGNEXT); + when ADDX => + RESULT := unsigned(OP2_SIGNEXT) + unsigned(OP1_SIGNEXT) + unsigned(X_IN_I); + when CMPA | DBcc | SUBA => -- No sign extension for the destination. + RESULT := unsigned(OP2) - unsigned(OP1_SIGNEXT); + when CMP | CMPI | CMPM | SUB | SUBI => + RESULT := unsigned(OP2_SIGNEXT) - unsigned(OP1_SIGNEXT); + when SUBX => + RESULT := unsigned(OP2_SIGNEXT) - unsigned(OP1_SIGNEXT) - unsigned(X_IN_I); + when NEG => + RESULT := unsigned(OP1_SIGNEXT) - unsigned(OP2_SIGNEXT); + when NEGX => + RESULT := unsigned(OP1_SIGNEXT) - unsigned(OP2_SIGNEXT) - unsigned(X_IN_I); + when CLR => + RESULT := (others => '0'); + when others => + RESULT := (others => '0'); -- Don't care. + end case; + RESULT_INTOP <= Std_Logic_Vector(RESULT); + end process P_INTOP; + + P_LOGOP: process(OP, OP1, OP2) + -- This process provides the logic operations: + -- AND, OR, XOR and NOT. + -- The logic operations require no signed / unsigned + -- modelling. + begin + case OP is + when AND_B | ANDI | ANDI_TO_CCR | ANDI_TO_SR => + RESULT_LOGOP <= OP1 and OP2; + when OR_B | ORI | ORI_TO_CCR | ORI_TO_SR => + RESULT_LOGOP <= OP1 or OP2; + when EOR | EORI | EORI_TO_CCR | EORI_TO_SR => + RESULT_LOGOP <= OP1 xor OP2; + when others => -- NOT_B. + RESULT_LOGOP <= not OP2; + end case; + end process P_LOGOP; + + RESULT_MUL <= Std_Logic_Vector(signed(OP1_SIGNEXT) * signed(OP2_SIGNEXT)) when OP = MULS else + Std_Logic_Vector(unsigned(OP1) * unsigned(OP2)) when OP_SIZE = LONG else + Std_Logic_Vector(unsigned(x"0000" & OP1(15 downto 0)) * unsigned(x"0000" & OP2(15 downto 0))); + + P_OTHERS: process(ALU_COND_I, BIW_0, OP, OP1, OP2, OP1_SIGNEXT, OP2_SIGNEXT, OP_SIZE) + -- This process provides the calculation for special operations. + variable RESULT : unsigned(31 downto 0); + begin + RESULT := (others => '0'); + case OP is + when EXT => + case BIW_0(8 downto 6) is + when "011" => + for i in 31 downto 16 loop + RESULT(i) := OP2(15); + end loop; + RESULT(15 downto 0) := unsigned(OP2(15 downto 0)); + when others => -- Word. + for i in 15 downto 8 loop + RESULT(i) := OP2(7); + end loop; + RESULT(31 downto 16) := unsigned(OP2(31 downto 16)); + RESULT(7 downto 0) := unsigned(OP2(7 downto 0)); + end case; + when JSR => + RESULT := unsigned(OP1) + "10"; -- Add offset of two to the Pointer of the last extension word. + when MOVEQ => + for i in 31 downto 8 loop + RESULT(i) := OP1(7); + end loop; + RESULT(7 downto 0) := unsigned(OP1(7 downto 0)); + when Scc => + if ALU_COND_I = true then + RESULT := (others => '1'); + else + RESULT := (others => '0'); + end if; + when SWAP => + RESULT := unsigned(OP2(15 downto 0)) & unsigned(OP2(31 downto 16)); + when TAS => + RESULT := x"000000" & '1' & unsigned(OP2(6 downto 0)); -- Set the MSB. + when LINK | TST => + RESULT := unsigned(OP2); + when MOVEA | MOVEM | MOVES => + RESULT := unsigned(OP1_SIGNEXT); + when others => -- MOVE_FROM_CCR, MOVE_TO_CCR, MOVE_FROM_SR, MOVE_TO_SR, MOVE, MOVEC, MOVEP, STOP. + RESULT := unsigned(OP1); + end case; + RESULT_OTHERS <= Std_Logic_Vector(RESULT); + end process P_OTHERS; + + SHFT_LOAD <= '1' when ALU_INIT = '1' and (OP_IN = ASL or OP_IN = ASR) else + '1' when ALU_INIT = '1' and (OP_IN = LSL or OP_IN = LSR) else + '1' when ALU_INIT = '1' and (OP_IN = ROTL or OP_IN = ROTR) else + '1' when ALU_INIT = '1' and (OP_IN = ROXL or OP_IN = ROXR) else '0'; + + SHIFT_WIDTH_IN <= "000001" when BIW_0_IN(7 downto 6) = "11" else -- Memory shifts. + "001000" when BIW_0_IN(5) = '0' and BIW_0_IN(11 downto 9) = "000" else -- Direct. + "000" & BIW_0_IN(11 downto 9) when BIW_0_IN(5) = '0' else -- Direct. + OP1_IN(5 downto 0); + + P_SHFT_CTRL: process + -- The variable shift or rotate length requires a control + -- to achieve the correct OPERAND manipulation. + variable BIT_CNT : std_logic_vector(5 downto 0); + begin + wait until CLK = '1' and CLK' event; + + SHFT_RDY <= '0'; + + if SHIFT_STATE = IDLE then + if SHFT_LOAD = '1' and SHIFT_WIDTH_IN = "000000" then + SHFT_RDY <= '1'; + elsif SHFT_LOAD = '1' then + SHIFT_STATE <= RUN; + BIT_CNT := SHIFT_WIDTH_IN; + SHFT_EN <= '1'; + else + SHIFT_STATE <= IDLE; + BIT_CNT := (others => '0'); + SHFT_EN <= '0'; + end if; + elsif SHIFT_STATE = RUN then + if BIT_CNT = "000001" then + SHIFT_STATE <= IDLE; + SHFT_EN <= '0'; + SHFT_RDY <= '1'; + else + SHIFT_STATE <= RUN; + BIT_CNT := BIT_CNT - '1'; + SHFT_EN <= '1'; + end if; + end if; + end process P_SHFT_CTRL; + + SHIFTER: process + begin + wait until CLK = '1' and CLK' event; + if SHFT_LOAD = '1' then -- Load data in the shifter unit. + RESULT_SHIFTOP <= OP2_IN; -- Load data for the shift or rotate operations. + elsif SHFT_EN = '1' then -- Shift and rotate operations: + case OP is + when ASL => + if OP_SIZE = LONG then + RESULT_SHIFTOP <= RESULT_SHIFTOP(30 downto 0) & '0'; + elsif OP_SIZE = WORD then + RESULT_SHIFTOP <= x"0000" & RESULT_SHIFTOP(14 downto 0) & '0'; + else -- OP_SIZE = BYTE. + RESULT_SHIFTOP <= x"000000" & RESULT_SHIFTOP(6 downto 0) & '0'; + end if; + when ASR => + if OP_SIZE = LONG then + RESULT_SHIFTOP <= RESULT_SHIFTOP(31) & RESULT_SHIFTOP(31 downto 1); + elsif OP_SIZE = WORD then + RESULT_SHIFTOP <= x"0000" & RESULT_SHIFTOP(15) & RESULT_SHIFTOP(15 downto 1); + else -- OP_SIZE = BYTE. + RESULT_SHIFTOP <= x"000000" & RESULT_SHIFTOP(7) & RESULT_SHIFTOP(7 downto 1); + end if; + when LSL => + if OP_SIZE = LONG then + RESULT_SHIFTOP <= RESULT_SHIFTOP(30 downto 0) & '0'; + elsif OP_SIZE = WORD then + RESULT_SHIFTOP <= x"0000" & RESULT_SHIFTOP(14 downto 0) & '0'; + else -- OP_SIZE = BYTE. + RESULT_SHIFTOP <= x"000000" & RESULT_SHIFTOP(6 downto 0) & '0'; + end if; + when LSR => + if OP_SIZE = LONG then + RESULT_SHIFTOP <= '0' & RESULT_SHIFTOP(31 downto 1); + elsif OP_SIZE = WORD then + RESULT_SHIFTOP <= x"0000" & '0' & RESULT_SHIFTOP(15 downto 1); + else -- OP_SIZE = BYTE. + RESULT_SHIFTOP <= x"000000" & '0' & RESULT_SHIFTOP(7 downto 1); + end if; + when ROTL => + if OP_SIZE = LONG then + RESULT_SHIFTOP <= RESULT_SHIFTOP(30 downto 0) & RESULT_SHIFTOP(31); + elsif OP_SIZE = WORD then + RESULT_SHIFTOP <= x"0000" & RESULT_SHIFTOP(14 downto 0) & RESULT_SHIFTOP(15); + else -- OP_SIZE = BYTE. + RESULT_SHIFTOP <= x"000000" & RESULT_SHIFTOP(6 downto 0) & RESULT_SHIFTOP(7); + end if; + -- X not affected; + when ROTR => + if OP_SIZE = LONG then + RESULT_SHIFTOP <= RESULT_SHIFTOP(0) & RESULT_SHIFTOP(31 downto 1); + elsif OP_SIZE = WORD then + RESULT_SHIFTOP <= x"0000" & RESULT_SHIFTOP(0) & RESULT_SHIFTOP(15 downto 1); + else -- OP_SIZE = BYTE. + RESULT_SHIFTOP <= x"000000" & RESULT_SHIFTOP(0) & RESULT_SHIFTOP(7 downto 1); + end if; + -- X not affected; + when ROXL => + if OP_SIZE = LONG then + RESULT_SHIFTOP <= RESULT_SHIFTOP(30 downto 0) & XFLAG_SHFT; + elsif OP_SIZE = WORD then + RESULT_SHIFTOP <= x"0000" & RESULT_SHIFTOP(14 downto 0) & XFLAG_SHFT; + else -- OP_SIZE = BYTE. + RESULT_SHIFTOP <= x"000000" & RESULT_SHIFTOP(6 downto 0) & XFLAG_SHFT; + end if; + when ROXR => + if OP_SIZE = LONG then + RESULT_SHIFTOP <= XFLAG_SHFT & RESULT_SHIFTOP(31 downto 1); + elsif OP_SIZE = WORD then + RESULT_SHIFTOP <= x"0000" & XFLAG_SHFT & RESULT_SHIFTOP(15 downto 1); + else -- OP_SIZE = BYTE. + RESULT_SHIFTOP <= x"000000" & XFLAG_SHFT & RESULT_SHIFTOP(7 downto 1); + end if; + when others => null; -- Unaffected, forbidden. + end case; + end if; + end process SHIFTER; + + P_OUT: process + begin + wait until CLK = '1' and CLK' event; + case OP is + when ABCD | NBCD | SBCD => + RESULT <= x"00000000000000" & RESULT_BCDOP; -- Byte only. + when BCHG | BCLR | BSET | BTST => + RESULT <= x"00000000" & RESULT_BITOP; + when ADD | ADDA | ADDI | ADDQ | ADDX | CLR | CMP | CMPA | CMPI => + RESULT <= x"00000000" & RESULT_INTOP; + when CMPM | DBcc | NEG | NEGX | SUB | SUBA | SUBI | SUBQ | SUBX => + RESULT <= x"00000000" & RESULT_INTOP; + when AND_B | ANDI | EOR | EORI | NOT_B | OR_B | ORI => + RESULT <= x"00000000" & RESULT_LOGOP; + when ANDI_TO_SR | EORI_TO_SR | ORI_TO_SR => -- Used for branch prediction. + RESULT <= x"00000000" & RESULT_LOGOP; + when ASL | ASR | LSL | LSR | ROTL | ROTR | ROXL | ROXR => + RESULT <= x"00000000" & RESULT_SHIFTOP; + when DIVS | DIVU => + case OP_SIZE is + when LONG => RESULT <= Std_Logic_Vector(REMAINDER) & Std_Logic_Vector(QUOTIENT); + when others => RESULT <= x"00000000" & Std_Logic_Vector(REMAINDER(15 downto 0)) & Std_Logic_Vector(QUOTIENT(15 downto 0)); + end case; + when MULS | MULU => + RESULT <= RESULT_MUL; + when others => + RESULT <= OP2 & RESULT_OTHERS; -- OP2 is used for EXG. + end case; + end process P_OUT; + + -- Out of bounds condition: + CHK_CMP_COND <= true when OP = CHK and OP2_SIGNEXT(MSB) = '1' else -- Negative destination. + true when OP = CHK and signed(OP2_SIGNEXT) > signed(OP1_SIGNEXT) else false; + + -- All traps must be modeled as strobes. + TRAP_CHK <= '1' when ALU_ACK = '1' and OP = CHK and CHK_CMP_COND = true else '0'; + TRAP_DIVZERO <= '1' when ALU_INIT = '1' and (OP_IN = DIVS or OP_IN = DIVU) and OP1_IN = x"00000000" else '0'; + + COND_CODES: process(BIW_1, BITPOS, CB_BCD, CHK_CMP_COND, CLK, OP1, OP1_SIGNEXT, OP2, OP2_SIGNEXT, + MSB, OP, OP_SIZE, QUOTIENT, RESULT_BCDOP, RESULT_INTOP, RESULT_LOGOP, RESULT_MUL, RESULT_SHIFTOP, + RESULT_OTHERS, SHIFT_WIDTH, STATUS_REG, VFLAG_DIV, XFLAG_SHFT) + -- In this process all the condition codes X (eXtended), N (Negative) + -- Z (Zero), V (oVerflow) and C (Carry / borrow) are calculated for + -- all integer operations. Except for the MULS, MULU, DIVS, DIVU the + -- new conditions are valid one clock cycle after the operation starts. + -- For the multiplication and the division, the codes are valid after + -- BUSY is released. + variable TMP : std_logic; + variable Z, RM, SM, DM : std_logic; + variable CFLAG_SHFT : std_logic; + variable VFLAG_SHFT : std_logic; + variable NFLAG_DIV : std_logic; + variable NFLAG_MUL : std_logic; + variable VFLAG_MUL : std_logic; + variable RM_SM_DM : bit_vector(2 downto 0); + begin + -- Shifter C, X and V flags: + if CLK = '1' and CLK' event then + if SHFT_LOAD = '1' or SHIFT_WIDTH = "000000" then + XFLAG_SHFT <= STATUS_REG(4); + elsif SHFT_EN = '1' then + case OP is + when ROTL | ROTR => + XFLAG_SHFT <= STATUS_REG(4); -- Unaffected. + when ASL | LSL | ROXL => + case OP_SIZE is + when LONG => + XFLAG_SHFT <= RESULT_SHIFTOP(31); + when WORD => + XFLAG_SHFT <= RESULT_SHIFTOP(15); + when BYTE => + XFLAG_SHFT <= RESULT_SHIFTOP(7); + end case; + when others => -- ASR, LSR, ROXR. + XFLAG_SHFT <= RESULT_SHIFTOP(0); + end case; + end if; + -- + if (OP = ROXL or OP = ROXR) and SHIFT_WIDTH = "000000" then + CFLAG_SHFT := STATUS_REG(4); + elsif SHIFT_WIDTH = "000000" then + CFLAG_SHFT := '0'; + elsif SHFT_EN = '1' then + case OP is + when ASL | LSL | ROTL | ROXL => + case OP_SIZE is + when LONG => + CFLAG_SHFT := RESULT_SHIFTOP(31); + when WORD => + CFLAG_SHFT := RESULT_SHIFTOP(15); + when BYTE => + CFLAG_SHFT := RESULT_SHIFTOP(7); + end case; + when others => -- ASR, LSR, ROTR, ROXR + CFLAG_SHFT := RESULT_SHIFTOP(0); + end case; + end if; + -- + -- This logic provides a detection of any toggling of the most significant + -- bit of the shifter unit during the ASL shift process. For all other shift + -- operations, the V flag is always zero. + if SHFT_LOAD = '1' or SHIFT_WIDTH = "000000" then + VFLAG_SHFT := '0'; + elsif SHFT_EN = '1' then + case OP is + when ASL => -- ASR MSB is always unchanged. + if OP_SIZE = LONG then + VFLAG_SHFT := (RESULT_SHIFTOP(31) xor RESULT_SHIFTOP(30)) or VFLAG_SHFT; + elsif OP_SIZE = WORD then + VFLAG_SHFT := (RESULT_SHIFTOP(15) xor RESULT_SHIFTOP(14)) or VFLAG_SHFT; + else -- OP_SIZE = BYTE. + VFLAG_SHFT := (RESULT_SHIFTOP(7) xor RESULT_SHIFTOP(6)) or VFLAG_SHFT; + end if; + when others => + VFLAG_SHFT := '0'; + end case; + end if; + end if; + + -- DIVISION: + if OP_SIZE = LONG and QUOTIENT(31) = '1' then + NFLAG_DIV := '1'; + elsif OP_SIZE = WORD and QUOTIENT(15) = '1' then + NFLAG_DIV := '1'; + else + NFLAG_DIV := '0'; + end if; + + -- Integer operations: + case OP is + when ADD | ADDI | ADDQ | ADDX | CMP | CMPA | CMPI | CMPM | NEG | NEGX | SUB | SUBI | SUBQ | SUBX => + RM := RESULT_INTOP(MSB); + SM := OP1_SIGNEXT(MSB); + DM := OP2_SIGNEXT(MSB); + when others => + RM := '-'; SM := '-'; DM := '-'; + end case; + + RM_SM_DM := To_Bit(RM) & To_Bit(SM) & To_Bit(DM); + + -- Multiplication: + if OP_SIZE = LONG and BIW_1(10) = '1' and RESULT_MUL(63) = '1' then -- 64 bit result. + NFLAG_MUL := '1'; + elsif RESULT_MUL(31) = '1' then -- 32 bit result. + NFLAG_MUL := '1'; + else + NFLAG_MUL := '0'; + end if; + + if OP_SIZE = LONG and BIW_1(10) = '0' and OP = MULS and RESULT_MUL(31) = '0' and RESULT_MUL(63 downto 32) /= x"00000000" then + VFLAG_MUL := '1'; + elsif OP_SIZE = LONG and BIW_1(10) = '0' and OP = MULS and RESULT_MUL(31) = '1' and RESULT_MUL(63 downto 32) /= x"FFFFFFFF" then + VFLAG_MUL := '1'; + elsif OP_SIZE = LONG and BIW_1(10) = '0' and OP = MULU and RESULT_MUL(63 downto 32) /= x"00000000" then + VFLAG_MUL := '1'; + else + VFLAG_MUL := '0'; + end if; + + -- The Z Flag: + TMP := '0'; + case OP is + when ADD | ADDI | ADDQ | ADDX | CMP | CMPA | CMPI | CMPM | NEG | NEGX | SUB | SUBI | SUBQ | SUBX => + for i in RESULT_INTOP' range loop + if i <= MSB then + TMP:= TMP or RESULT_INTOP(i); -- Detect '1'. + end if; + end loop; + Z := not TMP; -- Invert for Z fLAG . + when AND_B | ANDI | EOR | EORI | OR_B | ORI | NOT_B => + for i in RESULT_LOGOP' range loop + if i <= MSB then + TMP:= TMP or RESULT_LOGOP(i); -- Detect '1'. + end if; + end loop; + Z := not TMP; -- Invert for Z fLAG . + when ASL | ASR | LSL | LSR | ROTL | ROTR | ROXL | ROXR => + for i in RESULT_SHIFTOP' range loop + if i <= MSB then + TMP:= TMP or RESULT_SHIFTOP(i); -- Detect '1'. + end if; + end loop; + Z := not TMP; -- Invert for Z fLAG . + when BCHG | BCLR | BSET | BTST => + Z := not OP2(BITPOS); + when DIVS | DIVU => + if QUOTIENT = x"00000000" then + Z := '1'; + else + Z := '0'; + end if; + when EXT | MOVE | SWAP | TST => + for i in RESULT_OTHERS' range loop + if i <= MSB then + TMP:= TMP or RESULT_OTHERS(i); -- Detect '1'. + end if; + end loop; + Z := not TMP; -- Invert for Z fLAG . + when MULS | MULU => + if OP_SIZE = LONG and BIW_1(10) = '1' and RESULT_MUL = x"0000000000000000" then -- 64 bit result. + Z := '1'; + elsif RESULT_MUL(31 downto 0) = x"00000000" then -- 32 bit result. + Z := '1'; + else + Z := '0'; + end if; + when TAS => + for i in OP2_SIGNEXT' range loop + if i <= MSB then + TMP := TMP or OP2_SIGNEXT(i); -- Detect '1'. + end if; + end loop; + Z := not TMP; -- Invert for Z fLAG . + when others => + Z := '0'; + end case; + + case OP is + when ABCD | NBCD | SBCD => + if RESULT_BCDOP = x"00" then -- N and V are undefined, don't care. + XNZVC <= CB_BCD & '-' & STATUS_REG(2) & '-' & CB_BCD; + else + XNZVC <= CB_BCD & '-' & '0' & '-' & CB_BCD; + end if; + when ADD | ADDI | ADDQ | ADDX => + if (SM = '1' and DM = '1') or (RM = '0' and SM = '1') or (RM = '0' and DM = '1') then + XNZVC(4) <= '1'; + XNZVC(0) <= '1'; + else + XNZVC(4) <= '0'; + XNZVC(0) <= '0'; + end if; + -- + if Z = '1' then + if OP = ADDX then + XNZVC(3 downto 2) <= '0' & STATUS_REG(2); + else + XNZVC(3 downto 2) <= "01"; + end if; + else + XNZVC(3 downto 2) <= RM & '0'; + end if; + -- + case RM_SM_DM is + when "011" => XNZVC(1) <= '1'; + when "100" => XNZVC(1) <= '1'; + when others => XNZVC(1) <= '0'; + end case; + when AND_B | ANDI | EOR | EORI | OR_B | ORI | NOT_B => + XNZVC <= STATUS_REG(4) & RESULT_LOGOP(MSB) & Z & "00"; + when ANDI_TO_CCR | EORI_TO_CCR | ORI_TO_CCR => + XNZVC <= RESULT_LOGOP(4 downto 0); + when ASL | ASR | LSL | LSR | ROTL | ROTR | ROXL | ROXR => + XNZVC <= XFLAG_SHFT & RESULT_SHIFTOP(MSB) & Z & VFLAG_SHFT & CFLAG_SHFT; + when BCHG | BCLR | BSET | BTST => + XNZVC <= STATUS_REG(4 downto 3) & Z & STATUS_REG(1 downto 0); + when CLR => + XNZVC <= STATUS_REG(4) & "0100"; + when SUB | SUBI | SUBQ | SUBX => + if (SM = '1' and DM = '0') or (RM = '1' and SM = '1') or (RM = '1' and DM = '0') then + XNZVC(4) <= '1'; + XNZVC(0) <= '1'; + else + XNZVC(4) <= '0'; + XNZVC(0) <= '0'; + end if; + -- + if Z = '1' then + if OP = SUBX then + XNZVC(3 downto 2) <= '0' & STATUS_REG(2); + else + XNZVC(3 downto 2) <= "01"; + end if; + else + XNZVC(3 downto 2) <= RM & '0'; + end if; + -- + case RM_SM_DM is + when "001" => XNZVC(1) <= '1'; + when "110" => XNZVC(1) <= '1'; + when others => XNZVC(1) <= '0'; + end case; + when CMP | CMPA | CMPI | CMPM => + XNZVC(4) <= STATUS_REG(4); + -- + if Z = '1' then + XNZVC(3 downto 2) <= "01"; + else + XNZVC(3 downto 2) <= RM & '0'; + end if; + -- + case RM_SM_DM is + when "001" => XNZVC(1) <= '1'; + when "110" => XNZVC(1) <= '1'; + when others => XNZVC(1) <= '0'; + end case; + -- + if (SM = '1' and DM = '0') or (RM = '1' and SM = '1') or (RM = '1' and DM = '0') then + XNZVC(0) <= '1'; + else + XNZVC(0) <= '0'; + end if; + when CHK => + if OP2_SIGNEXT(MSB) = '1' then + XNZVC <= STATUS_REG(4) & '1' & "000"; + elsif CHK_CMP_COND = true then + XNZVC <= STATUS_REG(4) & '0' & "000"; + else + XNZVC <= STATUS_REG(4 downto 3) & "000"; + end if; + when DIVS | DIVU => + XNZVC <= STATUS_REG(4) & NFLAG_DIV & Z & VFLAG_DIV & '0'; + when EXT | MOVE | TST => + XNZVC <= STATUS_REG(4) & RESULT_OTHERS(MSB) & Z & "00"; + when MOVEQ => + if OP1_SIGNEXT(7 downto 0) = x"00" then + XNZVC <= STATUS_REG(4) & "0100"; + else + XNZVC <= STATUS_REG(4) & OP1_SIGNEXT(7) & "000"; + end if; + when MULS | MULU => + XNZVC <= STATUS_REG(4) & NFLAG_MUL & Z & VFLAG_MUL & '0'; + when NEG | NEGX => + XNZVC(4) <= DM or RM; + -- + if Z = '1' then + if OP = NEGX then + XNZVC(3 downto 2) <= '0' & STATUS_REG(2); + else + XNZVC(3 downto 2) <= "01"; + end if; + else + XNZVC(3 downto 2) <= RM & '0'; + end if; + -- + XNZVC(1) <= DM and RM; + XNZVC(0) <= DM or RM; + when RTR => + XNZVC <= OP2(4 downto 0); + when SWAP => + XNZVC <= STATUS_REG(4) & RESULT_OTHERS(MSB) & Z & "00"; + when others => -- TAS, Byte only. + XNZVC <= STATUS_REG(4) & OP2_SIGNEXT(MSB) & Z & "00"; + end case; + end process COND_CODES; + + ALU_COND <= ALU_COND_I; -- This signal may not be registerd to meet a correct timing. + -- Status register conditions: (STATUS_REG(4) = X, STATUS_REG(3) = N, STATUS_REG(2) = Z, STATUS_REG(1) = V, STATUS_REG(0) = C.) + ALU_COND_I <= true when OP = TRAPV and STATUS_REG(1) = '1' else + false when OP = TRAPV else + true when BIW_0(11 downto 8) = x"0" else -- True. + true when BIW_0(11 downto 8) = x"2" and (STATUS_REG(2) nor STATUS_REG(0)) = '1' else -- High. + true when BIW_0(11 downto 8) = x"3" and (STATUS_REG(2) or STATUS_REG(0)) = '1' else -- Low or same. + true when BIW_0(11 downto 8) = x"4" and STATUS_REG(0) = '0' else -- Carry clear. + true when BIW_0(11 downto 8) = x"5" and STATUS_REG(0) = '1' else -- Carry set. + true when BIW_0(11 downto 8) = x"6" and STATUS_REG(2) = '0' else -- Not Equal. + true when BIW_0(11 downto 8) = x"7" and STATUS_REG(2) = '1' else -- Equal. + true when BIW_0(11 downto 8) = x"8" and STATUS_REG(1) = '0' else -- Overflow clear. + true when BIW_0(11 downto 8) = x"9" and STATUS_REG(1) = '1' else -- Overflow set. + true when BIW_0(11 downto 8) = x"A" and STATUS_REG(3) = '0' else -- Plus. + true when BIW_0(11 downto 8) = x"B" and STATUS_REG(3) = '1' else -- Minus. + true when BIW_0(11 downto 8) = x"C" and (STATUS_REG(3) xnor STATUS_REG(1)) = '1' else -- Greater or Equal. + true when BIW_0(11 downto 8) = x"D" and (STATUS_REG(3) xor STATUS_REG(1)) = '1' else -- Less than. + true when BIW_0(11 downto 8) = x"E" and STATUS_REG(3 downto 1) = "101" else -- Greater than. + true when BIW_0(11 downto 8) = x"E" and STATUS_REG(3 downto 1) = "000" else -- Greater than. + true when BIW_0(11 downto 8) = x"F" and STATUS_REG(2) = '1' else -- Less or equal. + true when BIW_0(11 downto 8) = x"F" and (STATUS_REG(3) xor STATUS_REG(1)) = '1' else false; -- Less or equal. + + P_STATUS_REG: process + -- This process is the status register with it's related logic. + -- The status register is written 16 bit wide for MOVE_TO_CCR (the ALU result is 16 bit wide). + -- The status register is written entirely for ANDI_TO_SR, EORI_TO_SR, ORI_TO_SR. + -- The status register lower byte is written for ANDI_TO_CCR, EORI_TO_CCR, ORI_TO_CCR. + variable SREG_MEM : std_logic_vector(15 downto 0) := x"0000"; + begin + wait until CLK = '1' and CLK' event; + -- + if CC_UPDT = '1' then + SREG_MEM(4 downto 0) := XNZVC; + end if; + -- + if SR_INIT = '1' then + SREG_MEM(15 downto 13) := "001"; -- Trace cleared, S = '1'. + SREG_MEM(10 downto 8) := IRQ_PEND; -- Update IRQ level. + end if; + -- + if SR_WR = '1' and OP_IN = RTE then -- Written by the exception handler, no ALU required. + SREG_MEM := OP1_IN(15 downto 0); + elsif SR_WR = '1' and (OP_WB = MOVE_TO_CCR or OP_WB = MOVE_TO_SR or OP_WB = STOP) then + SREG_MEM := RESULT_OTHERS(15 downto 0); + elsif SR_WR = '1' and (OP_WB = ANDI_TO_CCR or OP_WB = EORI_TO_CCR or OP_WB = ORI_TO_CCR) then + SREG_MEM(7 downto 5) := RESULT_LOGOP(7 downto 5); -- Bits 4 downto 0 are written via CC_UPDT. + elsif SR_WR = '1' then -- ANDI_TO_SR, EORI_TO_SR, ORI_TO_SR. + SREG_MEM := RESULT_LOGOP(15 downto 0); + end if; + -- + STATUS_REG <= SREG_MEM; -- Fully populated status register. + -- STATUS_REG <= SREG_MEM(15 downto 12) & '0' & SREG_MEM(10 downto 8) & "000" & SREG_MEM(4 downto 0); -- Partially populated. + end process P_STATUS_REG; + -- + STATUS_REG_OUT <= STATUS_REG; +end BEHAVIOUR; diff --git a/common/CPU/68K10/wf68k10_bus_interface.vhd b/common/CPU/68K10/wf68k10_bus_interface.vhd new file mode 100644 index 00000000..fb134a5c --- /dev/null +++ b/common/CPU/68K10/wf68k10_bus_interface.vhd @@ -0,0 +1,767 @@ +------------------------------------------------------------------------ +---- ---- +---- WF68K10 IP Core: this is the bus interface. ---- +---- ---- +---- Description: ---- +---- This module is a 68010 compatible bus controller featuring ---- +---- all of the 68010 bus interface functionality. ---- +---- ---- +---- Bus cycle operation: ---- +---- A bus cycle is invoked by either asserting RD_REQ, WR_REQ or ---- +---- OPCODE_REQ. Data is provided after the respective bus cycle ---- +---- has finished. The RD_REQ, WR_REQ or OPCODE_REQ signals should ---- +---- stay asserted until the respective _RDY signal from the bus ---- +---- controller indicates, that the data is available. These _RDY ---- +---- signals are strobes. If more than one read or write request ---- +---- are asserted the same time, RD_REQ is prioritized over WR_REQ ---- +---- and OPCODE_REQ has lowest priority. For more information of ---- +---- the signal functionality of the bus controller entity see also ---- +---- the comments below. ---- +---- ---- +---- Remarks: ---- +---- ---- +---- Bus arbitration topics: ---- +---- Additionally to the single wire and the three wire bus arbi- ---- +---- tration as described in the 68030 hardware manual, the bus ---- +---- controller also features the two wire arbitration as des- ---- +---- cribed in the documentation of the 68020 processor. ---- +---- ---- +---- Author(s): ---- +---- - Wolfgang Foerster, wf@experiment-s.de; wf@inventronik.de ---- +---- ---- +------------------------------------------------------------------------ +---- ---- +---- Copyright © 2014-2019 Wolfgang Foerster Inventronik GmbH. ---- +---- ---- +---- This documentation describes Open Hardware and is licensed ---- +---- under the CERN OHL v. 1.2. You may redistribute and modify ---- +---- this documentation under the terms of the CERN OHL v.1.2. ---- +---- (http://ohwr.org/cernohl). This documentation is distributed ---- +---- WITHOUT ANY EXPRESS OR IMPLIED WARRANTY, INCLUDING OF ---- +---- MERCHANTABILITY, SATISFACTORY QUALITY AND FITNESS FOR A ---- +---- PARTICULAR PURPOSE. Please see the CERN OHL v.1.2 for ---- +---- applicable conditions ---- +---- ---- +------------------------------------------------------------------------ +-- +-- Revision History +-- +-- Revision 2K14B 20141201 WF +-- Initial Release. +-- Revision 2K18A 20180620 WF +-- Fixed a bug in the DATA_PORT_OUT multiplexer. Thanks to Gary Bingham for the support. +-- Fixed a bug in the DATA_INMUX multiplexer. Thanks to Gary Bingham for the support. +-- Revision 2K18A 20180620 WF +-- RESET is now 124 instead of 512 clock cycles. +-- Adjusted the SSW to 68K10. +-- Removed RERUN_RMC. +-- Suppress bus faults during RESET instruction. +-- Optimized ASn and DSn timing for synchronous RAM. +-- DATA_PORT_EN timing optimization. +-- BUS_EN is now active except during arbitration. +-- Rearanged the DATA_RDY vs. BUS_FLT logic. +-- Opted out START_READ and CHK_RD. +-- UDSn and LDSn are now always enabled for opcode cycles (bugfix). +-- Fixed the faulty bus arbitration logic. +-- Rearranged address error handling. +-- Revision 2K20A 20200620 WF +-- ASn and DSn are not asserted in S0 any more. +-- Some modifications to optimize the RETRY logic. +-- + +library work; +use work.WF68K10_PKG.all; + +library ieee; +use ieee.std_logic_1164.all; +use ieee.std_logic_unsigned.all; +use ieee.numeric_std.all; + +entity WF68K10_BUS_INTERFACE is + port ( + -- System control: + CLK : in std_logic; -- System clock. + + -- Adress bus: + ADR_IN_P : in std_logic_vector(31 downto 0); -- Logical address line inputs. + ADR_OUT_P : out std_logic_vector(31 downto 0); -- Address line outputs. + + -- Function code relevant stuff: + FC_IN : in std_logic_vector(2 downto 0); -- Function codes. + FC_OUT : out std_logic_vector(2 downto 0); -- Physical function codes (top level entity). + + -- Data bus: + DATA_PORT_IN : in std_logic_vector(15 downto 0); -- Data bus input lines (top level entity). + DATA_PORT_OUT : out std_logic_vector(15 downto 0); -- Data bus output lines (top level entity). + DATA_FROM_CORE : in std_logic_vector(31 downto 0); -- Internal bus input lines. + DATA_TO_CORE : out std_logic_vector(31 downto 0); -- Internal data bus output lines. + OPCODE_TO_CORE : out std_logic_vector(15 downto 0); -- Internal instruction bus output lines. + + -- Tri state controls: + DATA_PORT_EN : out std_logic; -- For the data bus. + BUS_EN : out std_logic; -- For all other bus control signals. + + + -- Operation size: + OP_SIZE : in OP_SIZETYPE; -- Used for bus access control. + + -- Control signals: + RD_REQ : in bit; -- Read data. + WR_REQ : in bit; -- Write data. + DATA_RDY : out bit; -- Indicates 'new data available' (this is a strobe). + DATA_VALID : out std_logic; -- The data buffer contains valid data when '1'. + OPCODE_REQ : in bit; -- Read opcode. + OPCODE_RDY : out bit; -- Indicates 'new opcode available' (this is a strobe). + OPCODE_VALID : out std_logic; -- The opcode buffer contains valid data when '1'. + RMC : in bit; -- Indicates a read modify write operation. + BUSY_EXH : in bit; + INBUFFER : out std_logic_vector(31 downto 0); -- Used by the exception handler for stack frame type B. + OUTBUFFER : out std_logic_vector(31 downto 0); -- Used by the exception handler for stack frame types A and B. + SSW : out std_logic_vector(15 downto 0); + + -- Asynchronous bus control signals: + DTACKn : in std_logic; -- Asynchronous bus cycle termination (top level entity). + ASn : out std_logic; -- Adress select (top level entity). + UDSn : out std_logic; -- Data select (top level entity). + LDSn : out std_logic; -- Data select (top level entity). + RWn : out std_logic; -- Hi is read, low = write (top level entity). + RMCn : out std_logic; -- Read modify write indicator (top level entity). + DBENn : out std_logic; -- Data buffer enable (top level entity). + + -- Synchronous peripheral control: + E : out std_logic; + VMAn : out std_logic; + VMA_EN : out std_logic; + VPAn : in std_logic; + + -- Bus arbitration: + BRn : in std_logic; -- Bus request (top level entity). + BGACKn : in std_logic; -- Bus grant acknowledge (top level entity). + BGn : out std_logic; -- Bus grant (top level entity). + + -- Exception signals: + RESET_IN : in std_logic; -- System's reset input (top level entity). + RESET_STRB : in bit; -- From Core: force external reset. + RESET_OUT : out std_logic; -- System's reset output open drain enable. + RESET_CPU : out bit; -- Internal reset used for CPU initialization. + AVECn : in std_logic; -- Auto interrupt vector input (top level entity). + HALTn : in std_logic; -- Halt (top level entity). + BERRn : in std_logic; -- Bus error (top level entity). + AERR : out bit; -- Core internal address error. + + BUS_BSY : out bit -- Bus is busy when '1'. + ); +end entity WF68K10_BUS_INTERFACE; + +architecture BEHAVIOR of WF68K10_BUS_INTERFACE is +type BUS_CTRL_STATES is (IDLE, START_CYCLE, DATA_C1C4); +type ARB_STATES is(IDLE, GRANT, WAIT_RELEASE_3WIRE); +type TIME_SLICES is (IDLE, S0, S1, S2, S3, S4, S5); +signal ADR_OFFSET : std_logic_vector(5 downto 0); +signal ADR_OUT_I : std_logic_vector(31 downto 0); +signal AERR_I : bit; +signal ARB_STATE : ARB_STATES := IDLE; +signal AVEC_In : std_logic; +signal BGACK_In : std_logic; +signal BR_In : std_logic; +signal BUS_CTRL_STATE : BUS_CTRL_STATES; +signal BUS_CYC_RDY : bit; +signal BUS_FLT : std_logic; +signal DATA_INMUX : std_logic_vector(31 downto 0); +signal DATA_RDY_I : bit; +signal DBUFFER : std_logic_vector(31 downto 0); +signal DSn : std_logic; +signal DTACK_In : std_logic; +signal HALT_In : std_logic; +signal HALTED : bit; +signal NEXT_ARB_STATE : ARB_STATES; +signal NEXT_BUS_CTRL_STATE : BUS_CTRL_STATES; +signal OBUFFER : std_logic_vector(15 downto 0); +signal OPCODE_ACCESS : bit; +signal OPCODE_RDY_I : bit; +signal READ_ACCESS : bit; +signal RESET_CPU_I : bit; +signal RESET_OUT_I : std_logic; +signal RETRY : bit; +signal RW_In : std_logic; +signal SIZE_D : std_logic_vector(1 downto 0); +signal SIZE_I : std_logic_vector(1 downto 0); +signal SIZE_N : std_logic_vector(2 downto 0) := "000"; +signal SLICE_CNT_N : std_logic_vector(2 downto 0); +signal SLICE_CNT_P : std_logic_vector(2 downto 0); +signal SYNCn : bit; +signal T_SLICE : TIME_SLICES; +signal VMA_In : std_logic; +signal WAITSTATES : bit; +signal WP_BUFFER : std_logic_vector(31 downto 0); +signal WRITE_ACCESS : bit; +begin + P_SYNC: process(CLK) + -- These flip flops synchronize external signals on the negative clock edge. This + -- meets the requirement of sampling these signals in the end of S2 for asynchronous + -- bus access. Be aware, that we have to buffer the RETRY signal to prevent the bus + -- controller of spurious or timing critical BERRn and/or HALTn signals. The logic + -- for BUS_FLT and RETRY is coded in a way that we have a bus error or a retry + -- condition but not both at the same time. + -- Note: there is no need to synchronize the already synchronous bus control signals + variable BERR_VARn : std_logic; + variable HALT_VARn : std_logic; + begin + if CLK = '0' and CLK' event then + DTACK_In <= DTACKn; + BR_In <= BRn; + BGACK_In <= BGACKn; + AVEC_In <= AVECn; + HALT_VARn := HALTn; + BERR_VARn := BERRn; + end if; + -- + if CLK = '1' and CLK' event then + if BUS_CTRL_STATE = START_CYCLE then + AERR <= AERR_I; -- AERR_I is valid in this state. + else + AERR <= '0'; + end if; + -- + HALT_In <= HALTn or HALT_VARn; + -- + if BUS_CTRL_STATE = DATA_C1C4 then + if (BERRn nand BERR_VARn) = '1' and (HALTn or HALT_VARn) = '0' and SIZE_N /= "000" then + RETRY <= '1'; + elsif T_SLICE = IDLE and (BERRn = '1' and HALTn = '1' and BERR_VARn = '1' and HALT_VARn = '1') then + RETRY <= '0'; + elsif RETRY = '0' then + BUS_FLT <= (BERRn nor BERR_VARn) and HALT_VARn and HALTn; + end if; + else + BUS_FLT <= '0'; + RETRY <= '0'; + end if; + end if; + end process P_SYNC; + + ACCESSTYPE: process + -- This logic stores the execution unit control + -- signals during the current bus access. This is + -- important for the bus control signals to be + -- stable during the complete bus access. + begin + wait until CLK = '1' and CLK' event; + if BUS_CTRL_STATE = START_CYCLE then + if READ_ACCESS = '1' or WRITE_ACCESS = '1' or OPCODE_ACCESS = '1' then + null; -- Do not start either new cycle. + elsif RD_REQ = '1' then + READ_ACCESS <= '1'; + elsif WR_REQ = '1' then + WRITE_ACCESS <= '1'; + elsif OPCODE_REQ = '1' then + OPCODE_ACCESS <= '1'; + end if; + elsif AERR_I = '1' or (BUS_CTRL_STATE = DATA_C1C4 and NEXT_BUS_CTRL_STATE = IDLE) then + READ_ACCESS <= '0'; + WRITE_ACCESS <= '0'; + OPCODE_ACCESS <= '0'; + end if; + end process ACCESSTYPE; + + P_DF: process + -- This is the logic which provides the fault flags for data cycles and + -- input and output buffer information. + variable SIZEVAR : std_logic_vector(1 downto 0) := "00"; + begin + wait until CLK = '1' and CLK' event; + if BUSY_EXH = '0' then -- Do not alter during exception processing. + case OP_SIZE is + when LONG => SIZEVAR := "10"; + when WORD => SIZEVAR := "01"; + when BYTE => SIZEVAR := "00"; + end case; + -- + if BUS_CTRL_STATE = START_CYCLE and NEXT_BUS_CTRL_STATE = DATA_C1C4 then + SSW <= To_StdLogicVector (RMC & '0' & OPCODE_REQ & RD_REQ & RMC) & SIZEVAR & RW_In & "00000" & FC_IN; + end if; + + OUTBUFFER <= WP_BUFFER; -- Used for exception stack frame type A and B. + INBUFFER <= DATA_INMUX; -- Used for exception stack frame type B. + end if; + end process P_DF; + + WRITEBACK_INFO: process + -- This registers stor writeback relevant information. + begin + wait until CLK = '1' and CLK' event; + if BUS_CTRL_STATE = IDLE and NEXT_BUS_CTRL_STATE = START_CYCLE then -- Freeze during a bus cycle. + WP_BUFFER <= DATA_FROM_CORE; + end if; + end process WRITEBACK_INFO; + + BUS_BSY <= '1' when BUS_CTRL_STATE /= IDLE else '0'; + + PARTITIONING: process + -- This logic gives information about the remaining bus cycles The initial + -- size is sampled right before the bus acces. This requires the RD_REQ + -- and WR_REQ signals to work on the positive clock edge. + variable RESTORE_VAR : std_logic_vector(2 downto 0) := "000"; + begin + wait until CLK = '1' and CLK' event; + + if BUS_CTRL_STATE = DATA_C1C4 and T_SLICE = S1 then -- On positive clock edge. + RESTORE_VAR := SIZE_N; -- We need this initial value for early RETRY. + end if; + -- + if RESET_CPU_I = '1' then + SIZE_N <= "000"; + elsif BUS_CTRL_STATE /= DATA_C1C4 and NEXT_BUS_CTRL_STATE = DATA_C1C4 then + if RD_REQ = '1' or WR_REQ = '1' then + case OP_SIZE is + when LONG => SIZE_N <= "100"; + when WORD => SIZE_N <= "010"; + when BYTE => SIZE_N <= "001"; + end case; + else -- OPCODE_ACCESS. + SIZE_N <= "010"; -- WORD. + end if; + end if; + + -- Decrementing the size information: + -- In this logic all permutations are considered. This allows a dynamically changing bus size. + if RETRY = '1' then + SIZE_N <= RESTORE_VAR; + elsif BUS_CTRL_STATE = DATA_C1C4 and T_SLICE = S3 and WAITSTATES = '0' then -- On positive clock edge. + if ADR_OUT_I(1 downto 0) = "11" then + SIZE_N <= SIZE_N - '1'; + elsif ADR_OUT_I(1 downto 0) = "01" then + SIZE_N <= SIZE_N - '1'; + elsif SIZE_N = "001" then + SIZE_N <= SIZE_N - '1'; + else + SIZE_N <= SIZE_N - "10"; + end if; + end if; + -- + if (BUS_FLT = '1' and HALT_In = '1') then -- Abort bus cycle. + SIZE_N <= "000"; + end if; + end process PARTITIONING; + + SIZE_I <= SIZE_N(1 downto 0) when T_SLICE = S0 or T_SLICE = S1 else SIZE_D; + + P_DELAY: process + -- This delay is responsible for a correct SIZE_I information. Use this, if the + -- process PARTITIONING works on the positive clock edge. The SIZE_I information + -- is delayed by half a clock cycle to be valid just in time of sampling the INMUX. + begin + wait until CLK = '1' and CLK' event; + SIZE_D <= SIZE_N(1 downto 0); + end process P_DELAY; + + BUS_STATE_REG: process + -- This is the bus controller's state register. + begin + wait until CLK = '1' and CLK' event; + BUS_CTRL_STATE <= NEXT_BUS_CTRL_STATE; + end process BUS_STATE_REG; + + BUS_CTRL_DEC: process(ADR_IN_P, ADR_OUT_I, AERR_I, ARB_STATE, BGACK_In, BR_In, BUS_CTRL_STATE, BUS_CYC_RDY, + BUS_FLT, HALT_In, OPCODE_REQ, RD_REQ, RESET_CPU_I, RMC, SIZE_N, WR_REQ) + -- This is the bus controller's state machine decoder. A SIZE_N count of "000" means that all bytes + -- to be transfered. After a bus transfer a value of x"0" indicates that no further bytes are required + -- for a bus transfer. + begin + case BUS_CTRL_STATE is + when IDLE => + if RESET_CPU_I = '1' then + NEXT_BUS_CTRL_STATE <= IDLE; -- Reset condition (bus cycle terminated). + elsif HALT_In = '0' then + NEXT_BUS_CTRL_STATE <= IDLE; -- This is the 'HALT' condition. + elsif (BR_In = '0' and RMC = '0') or ARB_STATE /= IDLE or BGACK_In = '0' then + NEXT_BUS_CTRL_STATE <= IDLE; -- Arbitration, wait! + elsif RD_REQ = '1' then + NEXT_BUS_CTRL_STATE <= START_CYCLE; -- Read cycle. + elsif WR_REQ = '1' then + NEXT_BUS_CTRL_STATE <= START_CYCLE; -- Write cycle. + elsif OPCODE_REQ = '1' then + NEXT_BUS_CTRL_STATE <= START_CYCLE; -- Opcode cycle. + else + NEXT_BUS_CTRL_STATE <= IDLE; + end if; + when START_CYCLE => + if (RD_REQ = '1' or WR_REQ = '1') and AERR_I = '1' then + NEXT_BUS_CTRL_STATE <= IDLE; + elsif RD_REQ = '1' then + NEXT_BUS_CTRL_STATE <= DATA_C1C4; + elsif WR_REQ = '1' then + NEXT_BUS_CTRL_STATE <= DATA_C1C4; + elsif OPCODE_REQ = '1' and ADR_IN_P(0) = '1' then + NEXT_BUS_CTRL_STATE <= IDLE; -- Abort due to address error. + elsif OPCODE_REQ = '1' then + NEXT_BUS_CTRL_STATE <= DATA_C1C4; + else + NEXT_BUS_CTRL_STATE <= IDLE; + end if; + when DATA_C1C4 => + if BUS_CYC_RDY = '1' and SIZE_N = "000" then + NEXT_BUS_CTRL_STATE <= IDLE; + else + NEXT_BUS_CTRL_STATE <= DATA_C1C4; + end if; + end case; + end process BUS_CTRL_DEC; + + P_ADR_OFFS: process + -- This process provides a temporary address offset. + variable OFFSET_VAR : std_logic_vector(2 downto 0) := "000"; + begin + wait until CLK = '1' and CLK' event; + if RESET_CPU_I = '1' then + OFFSET_VAR := "000"; + elsif T_SLICE = S3 then + case ADR_OUT_I(1 downto 0) is + when "01" | "11" => OFFSET_VAR := "001"; + when others => OFFSET_VAR := "010"; + end case; + end if; + -- + if RESET_CPU_I = '1' then + ADR_OFFSET <= (others => '0'); + elsif RETRY = '1' then + null; -- Do not update if there is a retry cycle. + elsif BUS_CTRL_STATE /= IDLE and NEXT_BUS_CTRL_STATE = IDLE then + ADR_OFFSET <= (others => '0'); + elsif BUS_CYC_RDY = '1' then + ADR_OFFSET <= ADR_OFFSET + OFFSET_VAR; + end if; + end process P_ADR_OFFS; + + ADR_OUT_I <= ADR_IN_P + ADR_OFFSET; + ADR_OUT_P <= ADR_OUT_I; + + FC_OUT <= FC_IN; + + -- Address and bus errors: + AERR_I <= '1' when BUS_CTRL_STATE = START_CYCLE and OPCODE_REQ = '1' and RD_REQ = '0' and WR_REQ = '0' and ADR_IN_P(0) = '1' else + '1' when BUS_CTRL_STATE = START_CYCLE and OP_SIZE = LONG and ADR_IN_P(0) = '1' else + '1' when BUS_CTRL_STATE = START_CYCLE and OP_SIZE = WORD and ADR_IN_P(0) = '1' else '0'; + + + DATA_PORT_OUT <= WP_BUFFER(31 downto 16) when SIZE_I = "00" else + WP_BUFFER(15 downto 0) when SIZE_I = "10" else + WP_BUFFER(7 downto 0) & WP_BUFFER(7 downto 0); + + IN_MUX: process + -- This is the input multiplexer which can handle up to four bytes. + begin + wait until CLK = '0' and CLK' event; + -- + if T_SLICE = S4 then + case SIZE_I is + when "00" => + DATA_INMUX(31 downto 16) <= DATA_PORT_IN; + when "10" => -- Word. + DATA_INMUX(15 downto 0) <= DATA_PORT_IN; + when others => -- Byte. + case ADR_OUT_I(0) is + when '0' => DATA_INMUX(7 downto 0) <= DATA_PORT_IN(15 downto 8); + when others => DATA_INMUX(7 downto 0) <= DATA_PORT_IN(7 downto 0); + end case; + end case; + end if; + end process IN_MUX; + + VALIDATION: process + -- These flip flops detect a fault during the read operation over one or + -- several bytes or during the write operation. + begin + wait until CLK = '1' and CLK' event; + -- + if RESET_CPU_I = '1' then + OPCODE_VALID <= '1'; + elsif OPCODE_ACCESS = '1' and BUS_CTRL_STATE = DATA_C1C4 and BUS_FLT = '1' then + OPCODE_VALID <= '0'; + elsif OPCODE_RDY_I = '1' then + OPCODE_VALID <= '1'; -- Reset after use, TRAP_BERR is asserted during DATA_RDY. + end if; + -- + if RESET_CPU_I = '1' then + DATA_VALID <= '1'; + elsif BUS_CTRL_STATE = DATA_C1C4 and BUS_FLT = '1' then + DATA_VALID <= '0'; + elsif DATA_RDY_I = '1' then + DATA_VALID <= '1'; -- Reset after use, TRAP_BERR is asserted during DATA_RDY. + end if; + end process VALIDATION; + + PREFETCH_BUFFERS: process + -- These are the data and the operation code input registers. After a last read to the registered + -- input multiplexer, the respective data is copied from the input multiplexer to these buffers. + -- The opcode buffer is always written with 32 bit data. The data buffers may contain invalid bytes + -- in case of word or byte data size. + variable DBUFFER_MEM : std_logic_vector(31 downto 8) := x"000000"; + variable RDY_VAR : bit := '0'; + begin + wait until CLK = '1' and CLK' event; + -- + OPCODE_RDY_I <= '0'; -- This is a strobe. + DATA_RDY_I <= '0'; -- This is a strobe. + -- + -- The following variable is responsible, that the _RDY signals are + -- always strobes. + if DATA_RDY_I = '1' or OPCODE_RDY_I = '1' then + RDY_VAR := '0'; + elsif BUS_CTRL_STATE = START_CYCLE then + RDY_VAR := '1'; + end if; + -- Opcode cycle: + if AERR_I = '1' then + OPCODE_RDY_I <= '1'; + elsif OPCODE_ACCESS = '1' and BUS_CTRL_STATE = DATA_C1C4 and BUS_CYC_RDY = '1' and SIZE_N = "000" then + -- Instruction prefetches are always long and on word boundaries. + -- The word is available after the first word read. + OBUFFER <= DATA_INMUX(15 downto 0); + OPCODE_RDY_I <= RDY_VAR; + end if; + -- Data cycle: + if AERR_I = '1' then + DATA_RDY_I <= '1'; + elsif WRITE_ACCESS = '1' and BUS_CTRL_STATE = DATA_C1C4 and BUS_CYC_RDY = '1' and SIZE_N = "000" then + DATA_RDY_I <= RDY_VAR; + elsif READ_ACCESS = '1' and BUS_CTRL_STATE = DATA_C1C4 and BUS_CYC_RDY = '1' then + case OP_SIZE is + when LONG => + if SIZE_N = "000" then + DBUFFER <= DATA_INMUX; + DATA_RDY_I <= RDY_VAR; + end if; + when WORD => + if SIZE_N = "000" then + DBUFFER <= x"0000" & DATA_INMUX(15 downto 0); + DATA_RDY_I <= RDY_VAR; + end if; + when BYTE => -- Byte always aligned. + DATA_RDY_I <= RDY_VAR; + DBUFFER <= x"000000" & DATA_INMUX(7 downto 0); + end case; + end if; + end process PREFETCH_BUFFERS; + + DATA_RDY <= DATA_RDY_I; + OPCODE_RDY <= OPCODE_RDY_I; + + DATA_TO_CORE <= DBUFFER; + OPCODE_TO_CORE <= OBUFFER; + + WAITSTATES <= '0' when T_SLICE /= S3 else + '1' when RESET_OUT_I = '1' else -- No bus fault during RESET instruction. + '0' when SYNCn = '0' else -- For synchronous bus cycles. + '0' when DTACK_In = '0' else -- For asynchronous bus cycles. + '0' when ADR_IN_P(19 downto 16) = x"F" and AVEC_In = '0' else -- Interrupt acknowledge space cycle. + '0' when BUS_FLT = '1' else -- In case of a bus error; + '0' when RESET_CPU_I = '1' else '1'; -- A CPU reset terminates the current bus cycle. + + SLICES: process(CLK) + -- This process provides the central timing for the read, write and read modify write cycle as also + -- for the bus arbitration procedure. Be aware, that the bus controller state machine changes it's + -- state on the positive clock edge. The BUS_CYC_RDY signal is asserted during S3 or S5. So the + -- slice counter working on the positive clock edge may change it's state. + begin + if CLK = '1' and CLK' event then + if BUS_CTRL_STATE = IDLE then + SLICE_CNT_P <= "111"; -- Init. + elsif RETRY = '1' then + SLICE_CNT_P <= "111"; -- Stay in IDLE, go to IDLE. + elsif BUS_CTRL_STATE /= IDLE and NEXT_BUS_CTRL_STATE = IDLE then + SLICE_CNT_P <= "111"; -- Init. + elsif SLICE_CNT_P = "010" then + if RETRY = '1' then + SLICE_CNT_P <= "111"; -- Go IDLE. + elsif BUS_CTRL_STATE = DATA_C1C4 and NEXT_BUS_CTRL_STATE = IDLE then + SLICE_CNT_P <= "111"; -- Ready. + else + SLICE_CNT_P <= "000"; -- Go on. + end if; + elsif WAITSTATES = '0' then + SLICE_CNT_P <= SLICE_CNT_P + '1'; -- Cycle active. + end if; + end if; + -- + if CLK = '0' and CLK' event then + SLICE_CNT_N <= SLICE_CNT_P; -- Follow the P counter. + end if; + end process SLICES; + + T_SLICE <= S0 when SLICE_CNT_P = "000" and SLICE_CNT_N = "111" else + S1 when SLICE_CNT_P = "000" and SLICE_CNT_N = "000" else + S2 when SLICE_CNT_P = "001" and SLICE_CNT_N = "000" else + S3 when SLICE_CNT_P = "001" and SLICE_CNT_N = "001" else + S4 when SLICE_CNT_P = "010" and SLICE_CNT_N = "001" else + S5 when SLICE_CNT_P = "010" and SLICE_CNT_N = "010" else + S0 when SLICE_CNT_P = "000" and SLICE_CNT_N = "010" else IDLE; -- Rollover from state S5 to S0. + + -- Bus control signals: + RWn <= RW_In; + RW_In <= '0' when WRITE_ACCESS = '1' and BUS_CTRL_STATE = DATA_C1C4 else '1'; + RMCn <= '0' when RMC = '1' else '1'; + ASn <= '0' when T_SLICE = S1 or T_SLICE = S2 or T_SLICE = S3 or T_SLICE = S4 else '1'; + + UDSn <= '1' when OPCODE_ACCESS = '0' and OP_SIZE = BYTE and ADR_OUT_I(0) = '1' else DSn; + LDSn <= '1' when OPCODE_ACCESS = '0' and OP_SIZE = BYTE and ADR_OUT_I(0) = '0' else DSn; + DSn <= '0' when (T_SLICE = S3 or T_SLICE = S4 or T_SLICE = S5) and WRITE_ACCESS = '1' else -- Write. + '0' when T_SLICE = S1 or T_SLICE = S2 or T_SLICE = S3 or T_SLICE = S4 else '1'; -- Read. + + DBENn <= '0' when (T_SLICE = S1 or T_SLICE = S2 or T_SLICE = S3 or T_SLICE = S4 or T_SLICE = S5) and WRITE_ACCESS = '1' else -- Write. + '0' when T_SLICE = S2 or T_SLICE = S3 or T_SLICE = S4 else '1'; -- Read. + + -- Bus tri state controls: + BUS_EN <= '1' when ARB_STATE = IDLE and RESET_CPU_I = '0' else '0'; + DATA_PORT_EN <= '1' when WRITE_ACCESS = '1' and ARB_STATE = IDLE and RESET_CPU_I = '0' else '0'; + + -- Progress controls: + BUS_CYC_RDY <= '0' when RETRY = '1' else + '1' when T_SLICE = S5 else '0'; -- Asynchronous cycles. + + -- Bus arbitration: + ARB_REG: process + -- This is the arbiters state register. + begin + wait until CLK = '1' and CLK' event; + -- + if RESET_CPU_I = '1' then + ARB_STATE <= IDLE; + else + ARB_STATE <= NEXT_ARB_STATE; + end if; + end process ARB_REG; + + ARB_DEC: process(ARB_STATE, BGACK_In, BR_In, BUS_CTRL_STATE, RETRY, RMC) + -- This is the bus arbitration state machine's decoder. It can handle single-, two- + -- or three wire arbitration. The two wire arbitration is done in the GRANT state + -- by negating BRn. + begin + case ARB_STATE is + when IDLE => + if RMC = '1' and RETRY = '0' then + NEXT_ARB_STATE <= IDLE; -- Arbitration in RETRY operation is possible. + elsif BGACK_In = '0' and BUS_CTRL_STATE = IDLE then -- This is the single wire arbitration. + NEXT_ARB_STATE <= WAIT_RELEASE_3WIRE; + elsif BR_In = '0' and BUS_CTRL_STATE = IDLE then -- Wait until the bus is free. + NEXT_ARB_STATE <= GRANT; + else + NEXT_ARB_STATE <= IDLE; + end if; + when GRANT => + if BGACK_In = '0' then + NEXT_ARB_STATE <= WAIT_RELEASE_3WIRE; + elsif BR_In = '1' then + NEXT_ARB_STATE <= IDLE; -- Resume normal operation. + else + NEXT_ARB_STATE <= GRANT; + end if; + when WAIT_RELEASE_3WIRE => + if BGACK_In = '1' and BR_In = '0' then + NEXT_ARB_STATE <= GRANT; -- Re-enter new arbitration. + elsif BGACK_In = '1' then + NEXT_ARB_STATE <= IDLE; + else + NEXT_ARB_STATE <= WAIT_RELEASE_3WIRE; + end if; + end case; + end process ARB_DEC; + + BGn <= '0' when ARB_STATE = GRANT else '1'; + + -- RESET logic: + RESET_FILTER: process + -- This process filters the incoming reset pin. + -- If RESET_IN and HALT_In are asserted together for longer + -- than 10 clock cycles over the execution of a CPU reset + -- command, the CPU reset is released. + variable STARTUP : boolean := false; + variable TMP : std_logic_vector(3 downto 0) := x"0"; + begin + wait until CLK = '1' and CLK' event; + -- + if RESET_IN = '1' and HALT_In = '0' and RESET_OUT_I = '0' and TMP < x"F" then + TMP := TMP + '1'; + elsif RESET_IN = '0' or HALT_In = '1' or RESET_OUT_I = '1' then + TMP := x"0"; + end if; + if TMP > x"A" then + RESET_CPU_I <= '1'; -- Release internal reset. + STARTUP := true; + elsif STARTUP = false then + RESET_CPU_I <= '1'; + else + RESET_CPU_I <= '0'; + end if; + end process RESET_FILTER; + + RESET_TIMER: process + -- This logic is responsible for the assertion of the + -- reset output for 124 clock cycles, during the reset + -- command. The LOCK variable avoids re-initialisation + -- of the counter in the case that the RESET_EN is no + -- strobe. + variable TMP : std_logic_vector(6 downto 0) := "0000000"; + begin + wait until CLK = '1' and CLK' event; + -- + if RESET_STRB = '1' or TMP > "0000000" then + RESET_OUT_I <= '1'; + else + RESET_OUT_I <= '0'; + end if; + -- + if RESET_STRB = '1' then + TMP := "1111011"; -- 124 initial value. + elsif TMP > "0000000" then + TMP := TMP - '1'; + end if; + end process RESET_TIMER; + + RESET_CPU <= RESET_CPU_I; + RESET_OUT <= RESET_OUT_I; + + VMA_EN <= '0' when ARB_STATE /= IDLE or RESET_CPU_I = '1' else '1'; + VMAn <= VMA_In; + + -- Synchronous bus timing: + E_TIMER: process + -- The E clock is a free running clock with a period of 10 times + -- the CLK period. The pulse ratio is 4 CLK high and 6 CLK low. + -- Use a synchronous reset due to FPGA constraints. + variable TMP : std_logic_vector(3 downto 0); + begin + wait until CLK = '1' and CLK' event; + if RESET_CPU_I = '1' then + TMP := x"0"; + VMA_In <= '1'; + SYNCn <= '1'; + E <= '1'; + elsif TMP < x"9" then + TMP := TMP + '1'; + else + TMP := x"0"; + end if; + + -- E logic: + if TMP = x"0" then + E <= '1'; + elsif TMP = x"4" then + E <= '0'; + end if; + + -- VMA logic: + if VPAn = '0' and TMP >= x"4" then -- Switch, when E is low. + VMA_In <= '0'; + elsif VPAn = '1' then + VMA_In <= '1'; + end if; + + -- SYNCn logic (wait states controlling): + if VPAn = '0' and VMA_In = '0' and TMP = x"2" then -- Adjust E to S6.. + SYNCn <= '0'; + elsif VPAn = '1' then + SYNCn <= '1'; + end if; + end process E_TIMER; +end BEHAVIOR; diff --git a/common/CPU/68K10/wf68k10_control.vhd b/common/CPU/68K10/wf68k10_control.vhd new file mode 100644 index 00000000..2d26b4c3 --- /dev/null +++ b/common/CPU/68K10/wf68k10_control.vhd @@ -0,0 +1,2044 @@ +------------------------------------------------------------------------ +---- ---- +---- WF68K10 IP Core: this is the main controller to handle all ---- +---- integer instructions. ---- +---- ---- +---- Description: ---- +---- This controller handles all integer instructions and provides ---- +---- all required system control signals. The instructions are ---- +---- requested from the instruction prefetch unit in the opcode ---- +---- decoder unit. The data is mostly written to the ALU and after- ---- +---- wards from the ALU to the writeback logic. This pipelined ---- +---- structure requires a correct management of data in use. Any ---- +---- address or data registers or memory addresses which are in use ---- +---- are marked by a flag not to be used befor written back. Any ---- +---- time data or address reegisters or the effective address are ---- +---- in the writeback pipe, the respective use flag is evaluated. ---- +---- Instructions like MOVE read unused source and the destination ---- +---- is written, when the ALU and writeback controller 'free'. ---- +---- Instructions like ADD, SUB etc. read unused source and desti- ---- +---- nations and write back the destination, when the operands are ---- +---- not used any more and the ALU and writeback controller are not ---- +---- in use by another operation. ---- +---- The main controller is the second pipeline stage of the CPU. ---- +---- The pipelining structure also requires some special treatment ---- +---- for the system control instructions as described as follows: ---- +------------------------------------------------------------------------ +---- System Control Instructions: ---- +---- There are several instructions which require the instruction ---- +---- pipe to be flushed as described in the following. For further ---- +---- information refer to the 68Kxx data sheets. ---- +---- ---- +---- 1. TRAP generating: ---- +---- The following instructions result in a pipe flush when the ---- +---- exception handler takes control over the system: ---- +---- BKPT, CHK, ILLEGAL, TRAP, TRAPV ---- +---- There are some other indirect conditions flushing the pipe ---- +---- such as the STOP which is invoked by an external interrupt.---- +---- ---- +---- 2. Privilege violations: ---- +---- Some instructions may result in a privilege violation ---- +---- when executed in user space. The result will be a ---- +---- privilege violation trap and the ipipe is flushed when ---- +---- the exception handler takes over. The instructions are: ---- +---- ANDI_TO_SR, EORI_TO_SR, ORI_TO_SR, MOVEC, MOVES, MOVE_USP, ---- +---- MOVE_FROM_SR (68K10), MOVE_TO_SR, RESET, RTE and STOP. ---- +---- ---- +---- 3. Branches and Jumps: ---- +---- In case of branches and jumps and the respective return ---- +---- operations it is required to flush the instruction pipe. ---- +---- If PC value changes due to any branch or jump, it is neces- ---- +---- sary to flush the instruction pipe to invalidate already ---- +---- loaded 'old' instructions. This affects: ---- +---- BRA, BSR, Bcc, DBcc, JMP, JSR and the returns: ---- +---- RTD, RTR, RTS, RTE and also STOP. ---- +---- ---- +------------------------------------------------------------------------ +---- Data hazards: ---- +---- To avoid malfunction by using old data several things have ---- +---- to be taken into account: ---- +---- 1. Operations manipulating the system registers must wait ---- +---- in the end of the operation until the ALU has updated ---- +---- the condition codes. These operations are ANDI_TO_SR, ---- +---- EORI_TO_SR, ORI_TO_SR, MOVE_TO_SR and MOVEC. ---- +---- 2. Operations using the staus register must not start until ---- +---- the ALU has updated the condition codes. These operations ---- +---- are MOVE_FROM_CCR, MOVE_FROM_SR and MOVEC. ---- +---- 3. Operations using the stack pointer must not start until ---- +---- the stack pointer is updated by the previous operation. ---- +---- Operations using the stack pointer are RTD, RTR, RTS, ---- +---- MOVEC, MOVE_USP and UNLK. ---- +---- 4. Operations manipulating the stack pointer without using ---- +---- the ALU must not start until the stack is written by the ---- +---- previous operation. Stack pointer manipulating operations ---- +---- are BSR, JSR, LINK and PEA. ---- +------------------------------------------------------------------------ +---- ---- +---- Remarks: ---- +---- ---- +---- Author(s): ---- +---- - Wolfgang Foerster, wf@experiment-s.de; wf@inventronik.de ---- +---- ---- +------------------------------------------------------------------------ +---- ---- +---- Copyright © 2014-2019 Wolfgang Foerster Inventronik GmbH. ---- +---- ---- +---- This documentation describes Open Hardware and is licensed ---- +---- under the CERN OHL v. 1.2. You may redistribute and modify ---- +---- this documentation under the terms of the CERN OHL v.1.2. ---- +---- (http://ohwr.org/cernohl). This documentation is distributed ---- +---- WITHOUT ANY EXPRESS OR IMPLIED WARRANTY, INCLUDING OF ---- +---- MERCHANTABILITY, SATISFACTORY QUALITY AND FITNESS FOR A ---- +---- PARTICULAR PURPOSE. Please see the CERN OHL v.1.2 for ---- +---- applicable conditions ---- +---- ---- +------------------------------------------------------------------------ +-- +-- Revision History +-- +-- Revision 2K14B 20141201 WF +-- Initial Release. +-- Revision 2K16A 20160620 WF +-- Fixed a bug in the MOVEM operation. +-- Break the DBcc_LOOP when the exception handler is busy. +-- Revision 2K18A (unreleased) WF +-- Fixed a bug in MOVE An,-(Ay). Thanks to Gary Bingham for the support. +-- Removed RERUN_RMC. +-- Fixed wrong PEA behaviour. +-- Fixed the displacement for LINK. +-- Fixed AR_MARK_USED in LINK. +-- Fixed the operation size for MOVEQ. +-- ADDQ, SUBQ Fix: address registers are always written long. +-- ADDI, ANDI, EORI, ORI, SUBI: address is not marked used if destination is Dn. +-- ADDI, ANDI, EORI, ORI, SUBI: data register is marked used if destination is Dn. +-- EXG: rearranged logic to meet the new top level multiplexers. +-- LINK, UNLK: wait in START_OP until the ALU is ready (avoids possible data hazards). +-- LINK, UNLK: fixed the write back operation size. +-- MOVEM: Fixed predecrement mode for consecutive MOVEM -(An). +-- MOVEP: MOVEP_PNTR is now correct for consecutive MOVEP. +-- MOVEP: avoid structural hazard in SWITCH_STATE by waiting for ALU. +-- EOR: fixed a bug in the writeback mechanism. +-- BSR, JSR: EXEC_WB state machine waits now for ALU_INIT. Avoid structural / data hazard. +-- The instruction pipe is not flushed for ANDI_TO_CCR, EORI_TO_CCR, ORI_TO_CCR. +-- The instruction pipe is not flushed for MOVE_FROM_CCR, MOVE_TO_CCR, MOVE_FROM_SR, MOVE_USP, MOVEC. +-- Modifications in the FETCH state machine to avoid several data hazards for MOVEM, MOVE_FROM_CCR, MOVE_FROM_SR. +-- Modifications in the FETCH state machine to avoid several data hazards for ANDI_TO_CCR, ANDI_TO_SR, EORI_TO_CCR, EORI_TO_SR, ORI_TO_CCR, ORI_TO_SR. +-- Bugfix: the condition codes were not updated if there was a pending interrupt. +-- We have to stop a pending operation in case of a pending interrupt. This is done by rejecting OW_RDY. +-- Write the undecremented Register for MOVE Ax, -(Ax). +-- LINK A7 and PEA(A7) stacks the undecremented A7. +-- UNMARK is now asserted in the end of the write cycle. This avoids data hazards. +-- Fixed a MOVEC writeback issue (use BIW_WB... instead of BIW_...). +-- Fixed a USP writeback issue (use BIW_WB... instead of BIW_...). +-- Introduced a switch NO_PIPELINE. +-- MOVEM-Fix: the effective address in memory to register is stored (STORE_AEFF) not to be overwritten in case the addressing register is also loaded. +-- DBcc: fixed a data hazard for DBcc_COND evaluation by waiting on the ALU result. +-- Fixed DR_WR_1 locking against AR_WR_2. +-- IPIPE is flushed, when there is a memory space change in the end of xx_TO_SR operations. +-- To handle correct addressing, ADR_OFFSET is now cleared right in the end of the respective operation. +-- Fixed a bug in EOR writing back in register direct mode. +-- ADDQ and SUBQ: fixed (An)+ mode. An increments now. +-- Fixed DIVS, DIVU in memory address modes (wrong control flow). +-- ADDQ and SUBQ: fixed condition code control UPDT_CC. +-- Fixed a data hazard bug using addressing modes with index register. +-- Rewritten DBcc loop for split loops (see LOOP_SPLIT). +-- BTST: fixed (d16,Ax) addressing mode. +-- Fixed several pipelinig issues (hazards). +-- Revision 2K19A 20190419 WF +-- Introdeced a new state CALC_AEFF which results in no need of ADR_ATN and a twice highre fmax. +-- Revision 2K19B 20191224 WF +-- NOP explicitely synchronizes the instruction pipe now. +-- Control: BUSY is now asserted when an opword is loaded and we have to wait in START_OP (avoids other controllers to reload the opword, see OW_REQ). +-- Removed a data hazard condition (A7) for JSR, PEA, LINK and UNLK in the beginning of the operation. +-- + +use work.WF68K10_PKG.all; + +library ieee; +use ieee.std_logic_1164.all; +use ieee.std_logic_unsigned.all; +use ieee.numeric_std.all; + +entity WF68K10_CONTROL is + generic(NO_PIPELINE : boolean); -- If true the controller work in scalar mode. + port ( + CLK : in std_logic; -- System clock. + RESET_CPU : in bit; -- CPU reset. + + BUSY : out bit; -- Main controller finished an execution. + BUSY_EXH : in bit; + EXH_REQ : in bit; + INT_TRIG : out bit; + + OW_REQ : out bit; -- Operation words request. + OW_VALID : in std_logic; -- Operation words is valid. + EW_REQ : out bit; -- Extension word request. + EW_ACK : in bit; -- Extension word available. + OPD_ACK : in bit; -- Opcode has new data. + + ADR_MARK_USED : out bit; + ADR_IN_USE : in bit; + ADR_OFFSET : out std_logic_vector(5 downto 0); + + DATA_RD : out bit; + DATA_WR : out bit; + DATA_RDY : in bit; + DATA_VALID : in std_logic; + RMC : out bit; + + LOAD_OP1 : out bit; + LOAD_OP2 : out bit; + LOAD_OP3 : out bit; + STORE_ADR_FORMAT : out bit; + STORE_D16 : out bit; + STORE_DISPL : out bit; + STORE_ABS_HI : out bit; + STORE_ABS_LO : out bit; + STORE_AEFF : out bit; + STORE_IDATA_B2 : out bit; + STORE_IDATA_B1 : out bit; + + -- System control signals: + OP : in OP_68K; + OP_SIZE : out OP_SIZETYPE; + BIW_0 : in std_logic_vector(13 downto 0); + BIW_1 : in std_logic_vector(15 downto 0); + EXT_WORD : in std_logic_vector(15 downto 0); + + ADR_MODE : out std_logic_vector(2 downto 0); + AMODE_SEL : out std_logic_vector(2 downto 0); + + OP_WB : out OP_68K; + OP_SIZE_WB : out OP_SIZETYPE; + BIW_0_WB_73 : out std_logic_vector(7 downto 3); -- Used for EXG. + + AR_MARK_USED : out bit; + USE_APAIR : out boolean; + AR_IN_USE : in bit; + AR_SEL_RD_1 : out std_logic_vector(2 downto 0); + AR_SEL_RD_2 : out std_logic_vector(2 downto 0); + AR_SEL_WR_1 : out std_logic_vector(2 downto 0); + AR_SEL_WR_2 : out std_logic_vector(2 downto 0); + AR_INC : out bit; + AR_DEC : out bit; + AR_WR_1 : out bit; + AR_WR_2 : out bit; + + DR_MARK_USED : out bit; + USE_DPAIR : out boolean; + DR_IN_USE : in bit; + DR_SEL_WR_1 : out std_logic_vector(2 downto 0); + DR_SEL_WR_2 : out std_logic_vector(2 downto 0); + DR_SEL_RD_1 : out std_logic_vector(2 downto 0); + DR_SEL_RD_2 : out std_logic_vector(2 downto 0); + DR_WR_1 : out bit; + DR_WR_2 : out bit; + + UNMARK : out bit; + + DISPLACEMENT : out std_logic_vector(31 downto 0); + PC_ADD_DISPL : out bit; + PC_LOAD : out bit; + PC_INC_EXH : in bit; + + SP_ADD_DISPL : out bit; + + DFC_WR : out bit; + DFC_RD : out bit; + SFC_WR : out bit; + SFC_RD : out bit; + + VBR_WR : out bit; + VBR_RD : out bit; + + USP_RD : out bit; + USP_WR : out bit; + + IPIPE_FLUSH : out bit; -- Abandon the instruction pipeline. + + ALU_INIT : out bit; + ALU_BSY : in bit; + ALU_REQ : in bit; + ALU_ACK : out bit; + + BKPT_CYCLE : out bit; + BKPT_INSERT : out bit; + + LOOP_BSY : in bit; + LOOP_SPLIT : out boolean; + LOOP_EXIT : out bit; + + SR_WR : out bit; + MOVEM_ADn : out bit; + MOVEP_PNTR : out integer range 0 to 3; + CC_UPDT : out bit; + TRACE_EN : in std_logic; + ALU_COND : in boolean; + DBcc_COND : in boolean; + BRANCH_ATN : in bit; + RESET_STRB : out bit; + BERR : out bit; + EX_TRACE : out bit; + TRAP_ILLEGAL : out bit; -- Used for BKPT. + TRAP_V : out bit + ); +end entity WF68K10_CONTROL; + +architecture BEHAVIOUR of WF68K10_CONTROL is +type FETCH_STATES is (START_OP, CALC_AEFF, FETCH_DISPL, FETCH_EXWORD_1, FETCH_ABS_HI, FETCH_ABS_LO, + FETCH_IDATA_B2, FETCH_IDATA_B1, FETCH_OPERAND, INIT_EXEC_WB, SLEEP, SWITCH_STATE); +type EXEC_WB_STATES is (IDLE, EXECUTE, WRITEBACK, WRITE_DEST); +signal FETCH_STATE : FETCH_STATES; +signal NEXT_FETCH_STATE : FETCH_STATES; +signal EXEC_WB_STATE : EXEC_WB_STATES; +signal NEXT_EXEC_WB_STATE : EXEC_WB_STATES; +signal ADR_MODE_I : std_logic_vector(2 downto 0); +signal ALU_INIT_I : bit; +signal ALU_TRIG : bit; +signal AR_DEC_I : bit; +signal AR_WR_I : bit; +signal AR_WR_II : bit; +signal BIW_0_WB : std_logic_vector(11 downto 0); +signal BIW_1_WB : std_logic_vector(15 downto 0); +signal DATA_RD_I : bit; +signal DATA_WR_I : bit; +signal EW_RDY : bit; +signal INIT_ENTRY : bit; +signal IPIPE_FLUSH_I : bit; +signal LOOP_EXIT_I : bit; +signal MOVEM_ADn_I : bit; +signal MOVEM_ADn_WB : bit; +signal MOVEM_COND : boolean; +signal MOVEM_FIRST_RD : boolean; +signal MOVEM_INH_WR : boolean; +signal MOVEM_LAST_WR : boolean; +signal MOVEM_PNTR : std_logic_vector(3 downto 0); +signal MOVEP_PNTR_I : integer range 0 to 3; +signal OP_SIZE_I : OP_SIZETYPE; +signal OP_WB_I : OP_68K := UNIMPLEMENTED; +signal OW_RDY : bit; +signal PC_LOAD_I : bit; +signal PHASE2 : boolean; +signal RD_RDY : bit; +signal READ_CYCLE : bit; +signal UPDT_CC : bit; +signal WR_RDY : bit; +signal WRITE_CYCLE : bit; +-- Debugging: +signal OP_TEST : bit; +begin + BUSY <= '1' when OPD_ACK = '1' else -- Early indication. + '1' when OW_RDY = '1' and OP /= ILLEGAL and OP /= RTE and OP /= TRAP and OP /= UNIMPLEMENTED else -- In progress MAIN is now busy. + '1' when LOOP_BSY = '1' else -- Finish the DBcc loop. + '1' when ALU_BSY = '1' else -- Busy, wait. + '1' when FETCH_STATE /= START_OP else '0'; -- Main controller is busy. + + -- The interrupt must not be activated when the controller is in its START_OP + -- state and fetches new OPWORDS. so we define the trigger for the interrupt + -- in the end of the FETCH phase. The SLEEP state is important for STOP. + INT_TRIG <= '1' when FETCH_STATE = INIT_EXEC_WB or FETCH_STATE = SLEEP else '0'; + + OW_REQ <= '0' when BUSY_EXH = '1' else + '0' when EXH_REQ = '1' and LOOP_BSY = '0' else -- Non interrupt exception requests, loop has priority. + '0' when OPD_ACK = '1' or OW_RDY = '1' else + '1' when NO_PIPELINE = true and FETCH_STATE = START_OP and ALU_BSY = '0' else + '1' when NO_PIPELINE = false and FETCH_STATE = START_OP else '0'; + + DATA_AVAILABLE: process + -- These flip flops store the information whether the data required in the different + -- states is available or not. This is necessary in case of delayed cycles for + -- example if the required address register is not ready to be read. + begin + wait until CLK = '1' and CLK' event; + if RESET_CPU = '1' then + OW_RDY <= '0'; + elsif FETCH_STATE = START_OP and NEXT_FETCH_STATE /= START_OP then + OW_RDY <= '0'; -- Reset. + elsif FETCH_STATE = START_OP and (OP = ILLEGAL or OP = RTE or OP = TRAP or OP = UNIMPLEMENTED) and BUSY_EXH = '1' then + OW_RDY <= '0'; -- Done. + elsif OPD_ACK = '1' then + OW_RDY <= '1'; -- Set. + end if; + + if FETCH_STATE = START_OP then + EW_RDY <= '0'; + elsif FETCH_STATE = FETCH_DISPL and NEXT_FETCH_STATE /= FETCH_DISPL then + EW_RDY <= '0'; + elsif FETCH_STATE = FETCH_EXWORD_1 and NEXT_FETCH_STATE /= FETCH_EXWORD_1 then + EW_RDY <= '0'; + elsif FETCH_STATE = FETCH_IDATA_B1 and NEXT_FETCH_STATE /= FETCH_IDATA_B1 then + EW_RDY <= '0'; + elsif (FETCH_STATE = FETCH_DISPL or FETCH_STATE = FETCH_EXWORD_1 or FETCH_STATE = FETCH_IDATA_B1) and EW_ACK = '1' then + EW_RDY <= '1'; + end if; + end process DATA_AVAILABLE; + + EW_REQ <= '0' when EW_ACK = '1' or EW_RDY = '1' else + '1' when FETCH_STATE = FETCH_DISPL or FETCH_STATE = FETCH_EXWORD_1 else + '1' when FETCH_STATE = FETCH_ABS_HI or FETCH_STATE = FETCH_ABS_LO else + '1' when FETCH_STATE = FETCH_IDATA_B2 or FETCH_STATE = FETCH_IDATA_B1 else + '1' when FETCH_STATE /= FETCH_DISPL and NEXT_FETCH_STATE = FETCH_DISPL else + '1' when FETCH_STATE /= FETCH_EXWORD_1 and NEXT_FETCH_STATE = FETCH_EXWORD_1 else + '1' when FETCH_STATE /= FETCH_ABS_HI and NEXT_FETCH_STATE = FETCH_ABS_HI else + '1' when FETCH_STATE /= FETCH_ABS_LO and NEXT_FETCH_STATE = FETCH_ABS_LO else + '1' when FETCH_STATE /= FETCH_IDATA_B2 and NEXT_FETCH_STATE = FETCH_IDATA_B2 else + '1' when FETCH_STATE /= FETCH_IDATA_B1 and NEXT_FETCH_STATE = FETCH_IDATA_B1 else '0'; + + CYCLECONTROL: process + -- This process contros the read and write signals, if + -- asserted simultaneously. In this way, a read cycle is + -- not interrupted by a write cycle and vice versa. + begin + wait until CLK = '1' and CLK' event; + if DATA_RDY = '1' then + WRITE_CYCLE <= '0'; + READ_CYCLE <= '0'; + elsif DATA_WR_I = '1' then + WRITE_CYCLE <= '1'; + READ_CYCLE <= '0'; + elsif DATA_RD_I = '1' then + READ_CYCLE <= '1'; + WRITE_CYCLE <= '0'; + end if; + end process CYCLECONTROL; + + RD_RDY <= DATA_RDY when READ_CYCLE = '1' else '0'; + WR_RDY <= DATA_RDY when WRITE_CYCLE = '1' else '0'; + + INIT_ENTRY <= '1' when FETCH_STATE /= INIT_EXEC_WB and NEXT_FETCH_STATE = INIT_EXEC_WB else '0'; + + DATA_RD <= DATA_RD_I; + DATA_RD_I <= '0' when DATA_WR_I = '1' and READ_CYCLE = '0' and WRITE_CYCLE = '0' else -- Write is prioritized. + '0' when WRITE_CYCLE = '1' else -- Do not read during a write cycle. + '0' when ADR_IN_USE = '1' else -- Avoid data hazards. + '0' when DATA_RDY = '1' else + '1' when FETCH_STATE = FETCH_OPERAND else '0'; + + DATA_WR <= DATA_WR_I; + DATA_WR_I <= '0' when READ_CYCLE = '1' else -- Do not write during a read cycle. + '0' when DATA_RDY = '1' else + '1' when EXEC_WB_STATE = WRITE_DEST else '0'; + + RMC <= '1' when OP = TAS and FETCH_STATE /= START_OP else '0'; + + ALU_ACK <= '1' when EXEC_WB_STATE = EXECUTE and NEXT_EXEC_WB_STATE = IDLE else + '1' when EXEC_WB_STATE = WRITEBACK else + '1' when EXEC_WB_STATE = WRITE_DEST and WR_RDY = '1' else '0'; + + -- Store the extension word right in the end due to used data and/or address registers. + STORE_ADR_FORMAT <= '1' when FETCH_STATE = FETCH_EXWORD_1 and NEXT_FETCH_STATE /= FETCH_EXWORD_1 else '0'; + + STORE_D16 <= '1' when FETCH_STATE = FETCH_DISPL and EW_ACK = '1' else '0'; + + STORE_DISPL <= '1' when OP = MOVEP and FETCH_STATE = START_OP and NEXT_FETCH_STATE /= START_OP and BIW_0(7 downto 6) < "10" else -- Memory to register. + '1' when OP = MOVEP and FETCH_STATE = SWITCH_STATE else '0'; -- Register to memory. + + STORE_ABS_HI <= '1' when FETCH_STATE = FETCH_ABS_HI and EW_ACK = '1' else '0'; + STORE_ABS_LO <= '1' when FETCH_STATE = FETCH_ABS_LO and EW_ACK = '1' else '0'; + + STORE_IDATA_B2 <= '1' when FETCH_STATE = FETCH_IDATA_B2 and EW_ACK = '1' else '0'; + STORE_IDATA_B1 <= '1' when FETCH_STATE = FETCH_IDATA_B1 and EW_ACK = '1' else '0'; + + LOAD_OP1 <= '1' when OP = CMPM and FETCH_STATE = FETCH_OPERAND and RD_RDY = '1' and DATA_VALID = '1' and PHASE2 = true else + '1' when OP = MOVE and BIW_0(8 downto 6) = "100" and BIW_0(5 downto 3) = "001" and BIW_0(11 downto 9) = BIW_0(2 downto 0) and INIT_ENTRY = '1' else -- Load early to write the undecremented Register for Ax, -(Ax). + '1' when OP = MOVES and FETCH_STATE = START_OP and NEXT_FETCH_STATE /= START_OP and ADR_MODE_I = "100" and BIW_1(15) = '1' and BIW_1(11) = '1' and BIW_1(14 downto 12) = BIW_0(2 downto 0) else -- Load the adressing register before decrementing. + '1' when OP = PEA and FETCH_STATE = SWITCH_STATE and PHASE2 = true else -- Load early not to stack the decremented value. + '0' when OP = CMPM or OP = PEA else + '0' when OP = MOVE and BIW_0(8 downto 6) = "100" and BIW_0(5 downto 3) = "001" and BIW_0(11 downto 9) = BIW_0(2 downto 0) else + '0' when OP = MOVES and ADR_MODE_I = "100" and BIW_1(15) = '1' and BIW_1(11) = '1' and BIW_1(14 downto 12) = BIW_0(2 downto 0) else -- Do not load the decremented addressing register. + '1' when ALU_INIT_I = '1' else '0'; + + LOAD_OP2 <= '1' when (OP = ABCD or OP = SBCD) and FETCH_STATE = FETCH_OPERAND and RD_RDY = '1' and DATA_VALID = '1' and PHASE2 = false else + '1' when (OP = ADDX or OP = SUBX) and FETCH_STATE = FETCH_OPERAND and RD_RDY = '1' and DATA_VALID = '1' and PHASE2 = false else + '1' when (OP = ABCD or OP = SBCD) and FETCH_STATE = INIT_EXEC_WB and BIW_0(3) = '0' else -- Register direct. + '1' when (OP = ADDX or OP = SUBX) and FETCH_STATE = INIT_EXEC_WB and BIW_0(3) = '0' else -- Register direct. + '1' when OP = CMPM and FETCH_STATE = FETCH_OPERAND and RD_RDY = '1' and DATA_VALID = '1' and PHASE2 = false else + '0' when OP = ABCD or OP = SBCD or OP = ADDX or OP = SUBX or OP = CMPM else + '1' when OP = LINK and BIW_0(2 downto 0) = "111" and FETCH_STATE = START_OP and NEXT_FETCH_STATE /= START_OP else -- Load early not to stack the decremented address register. + '0' when OP = LINK and BIW_0(2 downto 0) = "111" else + '1' when INIT_ENTRY = '1' else '0'; + + LOAD_OP3 <= '1' when (OP = DIVS or OP = DIVU) and OP_SIZE_I = LONG and BIW_1(10) = '1' and INIT_ENTRY = '1' else '0'; -- 64 bit operand. + + SR_WR <= '1' when (OP_WB_I = ANDI_TO_SR or OP_WB_I = EORI_TO_SR or OP_WB_I = ORI_TO_SR) and EXEC_WB_STATE = WRITEBACK else + '1' when (OP_WB_I = MOVE_TO_CCR or OP_WB_I = MOVE_TO_SR) and EXEC_WB_STATE = WRITEBACK else + '1' when OP_WB_I = STOP and EXEC_WB_STATE = WRITEBACK else '0'; + + -- Addressing mode: + ADR_MODE <= ADR_MODE_I; + ADR_MODE_I <= "010" when OP = BSR or OP = LINK or OP = UNLK else -- (An), (Dn). + "010" when OP = RTD or OP = RTR or OP = RTS else -- (An). + "011" when OP = CMPM else -- (An)+ + "100" when OP = ABCD or OP = SBCD else -- -(An). + "100" when OP = ADDX or OP = SUBX else -- -(An). + "101" when OP = MOVEP else -- (d16, An). + -- The following two conditions change the address mode right in the end of the fetch phase. + "010" when (OP = JSR or OP = PEA) and FETCH_STATE = INIT_EXEC_WB and ALU_BSY = '0' else -- (A7). + BIW_0(8 downto 6) when OP = MOVE and FETCH_STATE = INIT_EXEC_WB and ALU_BSY = '0' else + BIW_0(8 downto 6) when OP = MOVE and PHASE2 = true else + BIW_0(5 downto 3); + + -- This is the selector for the address mode "111". + AMODE_SEL <= BIW_0(11 downto 9) when OP = MOVE and (NEXT_FETCH_STATE = INIT_EXEC_WB or FETCH_STATE = INIT_EXEC_WB) else + BIW_0(11 downto 9) when OP = MOVE and PHASE2 = true else BIW_0(2 downto 0); + + -- Used for the addressing modes and as source selector. + -- In case of the addressing modes, the selector mus be valid one clock cycle before the bus cycle + -- starts due to the pipeline stage for ADR_REG in the address register section. + AR_SEL_RD_1 <= BIW_0(11 downto 9) when (OP = ABCD or OP = SBCD) and FETCH_STATE = START_OP else + BIW_0(11 downto 9) when (OP = ABCD or OP = SBCD) and FETCH_STATE = CALC_AEFF and PHASE2 = false else + BIW_0(11 downto 9) when (OP = ABCD or OP = SBCD) and FETCH_STATE = FETCH_OPERAND and PHASE2 = false and RD_RDY = '0' else -- Destination first. + BIW_0(11 downto 9) when (OP = ABCD or OP = SBCD) and FETCH_STATE = INIT_EXEC_WB else + BIW_0(11 downto 9) when (OP = ADDX or OP = SUBX) and FETCH_STATE = START_OP else + BIW_0(11 downto 9) when (OP = ADDX or OP = SUBX) and FETCH_STATE = CALC_AEFF and PHASE2 = false else + BIW_0(11 downto 9) when (OP = ADDX or OP = SUBX) and FETCH_STATE = FETCH_OPERAND and PHASE2 = false and RD_RDY = '0' else -- Destination first. + BIW_0(11 downto 9) when (OP = ADDX or OP = SUBX) and FETCH_STATE = INIT_EXEC_WB else + BIW_0(11 downto 9) when OP = CMPM and FETCH_STATE = FETCH_OPERAND and PHASE2 = false else -- Fetch destination. + BIW_0(11 downto 9) when OP = MOVE and FETCH_STATE = START_OP and BIW_0(5 downto 3) < "010" and BIW_0(8 downto 6) /= "000" else -- Source is Dn, An. + BIW_0(11 downto 9) when OP = MOVE and FETCH_STATE = CALC_AEFF and PHASE2 = true else + BIW_0(11 downto 9) when OP = MOVE and FETCH_STATE = FETCH_OPERAND and RD_RDY = '1' and BIW_0(8 downto 6) = "100" and BIW_0(5 downto 3) /= "011" else -- All except (An)+,-(An). + BIW_0(11 downto 9) when OP = MOVE and FETCH_STATE = FETCH_IDATA_B1 and BIW_0(8 downto 6) /= "000" else + BIW_0(11 downto 9) when OP = MOVE and FETCH_STATE = FETCH_ABS_LO and BIW_0(8 downto 6) /= "000" and PHASE2 = false else + BIW_0(11 downto 9) when OP = MOVE and FETCH_STATE = SWITCH_STATE and BIW_0(8 downto 6) /= "000" else + BIW_0(11 downto 9) when OP = MOVE and FETCH_STATE = INIT_EXEC_WB and BIW_0(8 downto 6) /= "000" else + BIW_1(14 downto 12) when OP = MOVEC and BIW_0(0) = '1' else -- MOVEC: general register to control register. + "111" when OP = BSR or OP = MOVEC else -- Stack pointers. + "111" when (OP = JSR or OP = LINK) and FETCH_STATE = START_OP else -- Select the SP to decrement. + "111" when OP = PEA and FETCH_STATE = SWITCH_STATE and PHASE2 = true else -- Select the SP to decrement. + "111" when (OP = JSR or OP = LINK or OP = PEA) and FETCH_STATE = INIT_EXEC_WB else -- Writeback address is the SP. + "111" when OP = RTD or OP = RTR or OP = RTS else -- Stack pointer. + "111" when OP = UNLK and (FETCH_STATE = START_OP or FETCH_STATE = CALC_AEFF or FETCH_STATE = FETCH_OPERAND) else -- Check in START_OP to avoid dataz hazards! + BIW_0(2 downto 0) when OP = ABCD or OP = ADD or OP = ADDA or OP = ADDI or OP = ADDQ or OP = ADDX or OP = AND_B or OP = ANDI else + BIW_0(2 downto 0) when OP = ASL or OP = ASR or OP = BCHG or OP = BCLR or OP = BSET or OP = BTST else + BIW_0(2 downto 0) when OP = CHK or OP = CLR or OP = CMP or OP = CMPA or OP = CMPI or OP = CMPM else + BIW_0(2 downto 0) when OP = DIVS or OP = DIVU or OP = EOR or OP = EORI or OP = EXG or OP = JMP or OP = JSR or OP = LEA or OP = LINK or OP = LSL or OP = LSR else + BIW_0(2 downto 0) when OP = MOVE or OP = MOVEA or OP = MOVE_FROM_CCR or OP = MOVE_FROM_SR or OP = MOVE_TO_CCR or OP = MOVE_TO_SR else + BIW_0(2 downto 0) when OP = MOVE_USP or OP = MOVEM or OP = MOVEP or OP = MOVES or OP = MULS or OP = MULU else + BIW_0(2 downto 0) when OP = NBCD or OP = NEG or OP = NEGX or OP = NOT_B or OP = OR_B or OP = ORI or OP = PEA else + BIW_0(2 downto 0) when OP = ROTL or OP = ROTR or OP = ROXL or OP = ROXR or OP = SBCD or OP = Scc or OP = SUB or OP = SUBA else + BIW_0(2 downto 0) when OP = SUBI or OP = SUBQ or OP = SUBX or OP = TAS or OP = TST or OP = UNLK else "000"; + + -- Always the destination. + AR_SEL_WR_1 <= BIW_0(2 downto 0) when OP = ADDQ or OP = SUBQ else + BIW_0(2 downto 0) when OP = EXG and BIW_0(7 downto 3) = "10001" else -- Data and Address register. + BIW_1(14 downto 12) when OP = MOVEC or OP = MOVES else + "111" when OP = UNLK and FETCH_STATE = START_OP else + BIW_0(2 downto 0) when OP = LINK else + MOVEM_PNTR(2 downto 0) when OP = MOVEM else + BIW_0(2 downto 0) when OP = MOVE_USP else + BIW_0(11 downto 9); -- ADDA, EXG, LEA, MOVE, MOVEA, SUBA. + + AR_WR_1 <= AR_WR_I; + AR_WR_I <= '1' when OP = LINK and FETCH_STATE = INIT_EXEC_WB and ALU_BSY = '0' else -- Write SP to An. + '1' when OP = UNLK and FETCH_STATE = SWITCH_STATE and NEXT_FETCH_STATE /= SWITCH_STATE else -- Write An to SP. + '0' when EXEC_WB_STATE /= WRITEBACK else + '1' when OP_WB_I = ADDA or OP_WB_I = SUBA else + '1' when (OP_WB_I = ADDQ or OP_WB_I = SUBQ) and BIW_0_WB(5 downto 3) = "001" else + '1' when OP_WB_I = EXG and BIW_0_WB(7 downto 3) = "01001" else -- Two address registers. + '1' when OP_WB_I = EXG and BIW_0_WB(7 downto 3) = "10001" else -- Data and Address register. + '1' when OP_WB_I = LEA else + '1' when OP_WB_I = MOVE_USP and BIW_0_WB(3) = '1' else + '1' when OP_WB_I = MOVEA else + '1' when OP_WB_I = MOVEC and BIW_1_WB(15) = '1' and BIW_0_WB(0) = '0' else + '1' when OP_WB_I = MOVES and BIW_1_WB(15) = '1' else + '1' when OP_WB_I = MOVEM and MOVEM_ADn_WB = '1' else '0'; + + AR_SEL_RD_2 <= MOVEM_PNTR(2 downto 0) when OP = MOVEM else -- This is the non addressing output. + BIW_1(14 downto 12) when OP = MOVES else + BIW_0(2 downto 0) when OP = ADDQ or OP = MOVE or OP = SUBQ or OP = TST else + BIW_0(2 downto 0) when OP = EXG and BIW_0(7 downto 3) = "10001" else -- Data and address register. + BIW_0(11 downto 9) when OP = ADDA or OP = CMPA or OP = EXG or OP = SUBA else "000"; + + AR_SEL_WR_2 <= BIW_0(2 downto 0); -- Used for EXG, UNLK. + + AR_WR_2 <= AR_WR_II; + AR_WR_II <= '1' when OP_WB_I = UNLK and EXEC_WB_STATE = WRITEBACK else -- Write (SP) to An. + '1' when OP_WB_I = EXG and EXEC_WB_STATE = WRITEBACK and BIW_0_WB(7 downto 3) = "01001" else '0'; -- Two address registers. + + AR_INC <= '1' when (OP = ADD or OP = CMP or OP = SUB) and ADR_MODE_I = "011" and ALU_INIT_I = '1' else + '1' when (OP = ADDA or OP = CMPA or OP = SUBA) and ADR_MODE_I = "011" and FETCH_STATE = FETCH_OPERAND and DATA_RDY = '1' else + '1' when (OP = ADDI or OP = CMPI or OP = SUBI) and ADR_MODE_I = "011" and ALU_INIT_I = '1' else + '1' when (OP = ADDQ or OP = SUBQ) and ADR_MODE_I = "011" and ALU_INIT_I = '1' else + '1' when (OP = AND_B or OP = EOR or OP = OR_B) and ADR_MODE_I = "011" and ALU_INIT_I = '1' else + '1' when (OP = ANDI or OP = EORI or OP = ORI) and ADR_MODE_I = "011" and ALU_INIT_I = '1' else + '1' when (OP = ASL or OP = ASR or OP = LSL or OP = LSR) and BIW_0(7 downto 3) = "11011" and ALU_INIT_I = '1' else + '1' when (OP = ROTL or OP = ROTR or OP = ROXL or OP = ROXR) and BIW_0(7 downto 3) = "11011" and ALU_INIT_I = '1' else + '1' when (OP = BCHG or OP = BCLR or OP = BSET or OP = BTST) and ADR_MODE_I = "011" and ALU_INIT_I = '1' else + '1' when OP = TAS and ADR_MODE_I = "011" and FETCH_STATE = INIT_EXEC_WB and NEXT_FETCH_STATE /= INIT_EXEC_WB else + '1' when (OP = CHK or OP = CLR or OP = TST or OP = Scc) and ADR_MODE_I = "011" and ALU_INIT_I = '1' else + '1' when (OP = NBCD or OP = NEG or OP = NEGX or OP = NOT_B) and ADR_MODE_I = "011" and ALU_INIT_I = '1' else + '1' when OP = CMPM and FETCH_STATE = FETCH_OPERAND and RD_RDY = '1' and DATA_VALID = '1' else + '1' when (OP = MULS or OP = MULU or OP = DIVS or OP = DIVU) and ADR_MODE_I = "011" and ALU_INIT_I = '1' else + '1' when (OP = MOVE_FROM_CCR or OP = MOVE_FROM_SR) and ADR_MODE_I = "011" and FETCH_STATE = INIT_EXEC_WB and NEXT_FETCH_STATE /= INIT_EXEC_WB else + '1' when (OP = MOVE_TO_CCR or OP = MOVE_TO_SR) and ADR_MODE_I = "011" and FETCH_STATE = INIT_EXEC_WB and NEXT_FETCH_STATE /= INIT_EXEC_WB else + '1' when OP = MOVE and ADR_MODE_I = "011" and FETCH_STATE = FETCH_OPERAND and NEXT_FETCH_STATE /= FETCH_OPERAND else + '1' when OP = MOVE and BIW_0(8 downto 6) = "011" and FETCH_STATE = INIT_EXEC_WB and NEXT_FETCH_STATE /= INIT_EXEC_WB else + '1' when OP = MOVEA and ADR_MODE_I = "011" and FETCH_STATE = INIT_EXEC_WB and NEXT_FETCH_STATE /= INIT_EXEC_WB else + '1' when OP = MOVEM and ADR_MODE_I = "011" and ALU_INIT_I = '1' else + '1' when OP = MOVES and ADR_MODE_I = "011" and ALU_INIT_I = '1' else + '1' when (OP = UNLK or OP = RTD or OP = RTR or OP = RTS) and FETCH_STATE = FETCH_OPERAND and RD_RDY = '1' and DATA_VALID = '1' else '0'; + + with OP select + AR_DEC_I <= '1' when ABCD | ADD | ADDA | ADDI | ADDQ | ADDX | AND_B | ANDI | ASL | ASR | BCHG | BCLR | BSET | BTST | CHK | CMP | CMPA | CMPI | + DIVS | DIVU | EOR | EORI | LSL | LSR | MOVE | MOVEA | MOVE_TO_CCR | MOVE_TO_SR | MOVES | MULS | MULU | NBCD | NEG | NEGX | + NOT_B | OR_B | ORI | ROTL | ROTR | ROXL | ROXR | SBCD | SUB | SUBA | SUBI | SUBQ | SUBX | TAS | TST, '0' when others; + + AR_DEC <= AR_DEC_I when ADR_MODE_I = "100" and FETCH_STATE /= CALC_AEFF and NEXT_FETCH_STATE = CALC_AEFF else + '1' when (OP = BSR or OP = JSR or OP = LINK) and FETCH_STATE = START_OP and NEXT_FETCH_STATE /= START_OP else + '1' when (OP = CLR or OP = Scc) and ADR_MODE_I = "100" and INIT_ENTRY = '1' else + '1' when OP = MOVE and BIW_0(8 downto 6) = "100" and BIW_0(5 downto 3) /= "011" and INIT_ENTRY = '1' else -- Not (An)+,-(An). + '1' when OP = MOVE and BIW_0(8 downto 6) = "100" and FETCH_STATE = SWITCH_STATE else -- Needed for source (An)+ mode. + '1' when OP = MOVEM and ADR_MODE_I = "100" and INIT_ENTRY = '1' else -- Decrement before the first bus access. + '1' when OP = MOVEM and ADR_MODE_I = "100" and ALU_INIT_I = '1' and MOVEM_LAST_WR = false else -- After the last bus access the address register is not decremented. + '1' when (OP = MOVE_FROM_CCR or OP = MOVE_FROM_SR) and ADR_MODE_I = "100" and INIT_ENTRY = '1' else + '1' when OP = MOVES and ADR_MODE_I = "100" and BIW_1(11) = '1' and INIT_ENTRY = '1' else + -- PEA: decrement late in SWITCH_STATE not to decremented address register for PEA (xx,A7,yy) address modi. + '1' when OP = PEA and FETCH_STATE = SWITCH_STATE and PHASE2 = true else '0'; + + DR_SEL_RD_1 <= EXT_WORD(14 downto 12) when FETCH_STATE = FETCH_EXWORD_1 else -- Index register + BIW_0(11 downto 9) when (OP = ADD or OP = SUB) and BIW_0(8) = '1' else + BIW_0(11 downto 9) when (OP = AND_B or OP = EOR or OP = OR_B) and BIW_0(8) = '1' else + BIW_0(11 downto 9) when OP = BCHG or OP = BCLR or OP = BSET or OP = BTST else + BIW_0(11 downto 9) when OP = ASL or OP = ASR or OP = LSL or OP = LSR else + BIW_0(11 downto 9) when OP = ROTL or OP = ROTR or OP = ROXL or OP = ROXR else + BIW_1(2 downto 0) when (OP = DIVS or OP = DIVU) and FETCH_STATE /= INIT_EXEC_WB and BIW_0(8 downto 6) = "001" else -- LONG 64. + MOVEM_PNTR(2 downto 0) when OP = MOVEM else + BIW_0(11 downto 9) when OP = MOVEP else + BIW_1(14 downto 12) when OP = MOVEC or OP = MOVES else + BIW_0(2 downto 0) when OP = ADD or OP = AND_B or OP = OR_B or OP = SUB else + BIW_0(2 downto 0) when OP = ABCD or OP = ADDA or OP = ADDX or OP = CHK or OP = CMP or OP = CMPA else + BIW_0(11 downto 9) when OP = EXG and BIW_0(7 downto 3) = "10001" else -- Data and address register. + BIW_0(2 downto 0) when OP = DIVS or OP = DIVU or OP = EXG else + BIW_0(2 downto 0) when OP = MOVE or OP = MOVEA or OP = MOVE_TO_CCR or OP = MOVE_TO_SR or OP = MULS or OP = MULU else + BIW_0(2 downto 0) when OP = SBCD or OP = SUBA or OP = SUBX else "000"; + + DR_SEL_WR_1 <= BIW_1(14 downto 12) when OP = MOVEC or OP = MOVES else + BIW_0(11 downto 9) when OP = ABCD or OP = SBCD else + BIW_0(11 downto 9) when OP = ADDX or OP = SUBX else + BIW_0(11 downto 9) when OP = ADD or OP = SUB else + BIW_0(11 downto 9) when OP = AND_B or OP = OR_B else + BIW_0(11 downto 9) when (OP = DIVS or OP = DIVU) and OP_SIZE_I = WORD else + BIW_1(14 downto 12) when OP = DIVS or OP = DIVU else + BIW_0(11 downto 9) when (OP = MULS or OP = MULU) and OP_SIZE_I = WORD else + BIW_1(14 downto 12) when OP = MULS or OP = MULU else -- Low order result and operand. + BIW_0(11 downto 9) when OP = EXG else + BIW_0(11 downto 9) when OP = MOVE or OP = MOVEP or OP = MOVEQ else + MOVEM_PNTR(2 downto 0) when OP = MOVEM else + BIW_0(2 downto 0); + + DR_WR_1 <= '1' when OP_WB_I = EXG and EXEC_WB_STATE = WRITEBACK and BIW_0_WB(7 downto 3) = "10001" else -- Address- and data register. + '0' when AR_WR_I = '1' else -- This is the locking AR against DR. + '0' when AR_WR_II = '1' else -- This is the locking AR against DR. + '0' when OP_WB_I = ANDI_TO_SR or OP_WB_I = EORI_TO_SR or OP_WB_I = ORI_TO_SR else + '0' when OP_WB_I = MOVE_TO_CCR or OP_WB_I = MOVE_TO_SR else + '0' when OP_WB_I = MOVE_USP else -- USP is written. + '0' when OP_WB_I = MOVEC and BIW_0_WB(0) = '1' else -- To control register. + '0' when OP_WB_I = STOP else -- SR is written but not DR. + '1' when EXEC_WB_STATE = WRITEBACK else '0'; + + DR_SEL_RD_2 <= BIW_0(11 downto 9) when OP = ABCD or OP = SBCD or OP = ADDX or OP = SUBX else + BIW_0(2 downto 0) when (OP = ADD or OP = AND_B or OP = OR_B or OP = SUB) and BIW_0(8) = '1' else + BIW_0(11 downto 9) when OP = ADD or OP = CMP or OP = SUB or OP = AND_B or OP = OR_B else + BIW_0(11 downto 9) when OP = CHK or OP = EXG else + BIW_0(11 downto 9) when (OP = DIVS or OP = DIVU) and BIW_0(7) = '1' else -- WORD size. + BIW_1(14 downto 12) when (OP = DIVS or OP = DIVU) else -- Quotient low portion. + BIW_0(11 downto 9) when (OP = MULS or OP = MULU) and BIW_0(7) = '1' else -- WORD size. + BIW_1(14 downto 12) when (OP = MULS or OP = MULU) else + BIW_0(2 downto 0) when OP = BCHG or OP = BCLR or OP = BSET or OP = BTST else + BIW_0(2 downto 0) when OP = ADDI or OP = ADDQ or OP = ANDI or OP = BCHG or OP = BCLR or OP = BSET or OP = BTST or OP = CMPI else + BIW_0(2 downto 0) when OP = DBcc or OP = EOR or OP = EORI or OP = EXT or OP = NBCD or OP = NEG or OP = NEGX else + BIW_0(2 downto 0) when OP = NOT_B or OP = ORI or OP = SUBI or OP = SUBQ or OP = SWAP or OP = TAS or OP = TST else + BIW_0(2 downto 0) when OP = ASL or OP = ASR or OP = LSL or OP = LSR else + BIW_0(2 downto 0) when OP = ROTL or OP = ROTR or OP = ROXL or OP = ROXR else "000"; + + DR_SEL_WR_2 <= BIW_0(2 downto 0) when OP = EXG else BIW_1(2 downto 0); -- Default is for DIVS and DIVU, MULS, MULU. + + -- Normally source register. Writte in a few exceptions. + DR_WR_2 <= '1' when OP_WB_I = EXG and EXEC_WB_STATE = WRITEBACK and BIW_0_WB(7 downto 3) = "01000" else -- Two data registers. + '1' when OP_WB_I = DIVS and EXEC_WB_STATE = WRITEBACK and BIW_0_WB(8 downto 6) = "001" and BIW_1_WB(14 downto 12) /= BIW_1_WB(2 downto 0) else + '1' when OP_WB_I = DIVU and EXEC_WB_STATE = WRITEBACK and BIW_0_WB(8 downto 6) = "001" and BIW_1_WB(14 downto 12) /= BIW_1_WB(2 downto 0) else + '1' when OP_WB_I = MULS and EXEC_WB_STATE = WRITEBACK and BIW_0_WB(8 downto 6) = "000" and BIW_1_WB(10) = '1' and BIW_1_WB(14 downto 12) /= BIW_1_WB(2 downto 0) else + '1' when OP_WB_I = MULU and EXEC_WB_STATE = WRITEBACK and BIW_0_WB(8 downto 6) = "000" and BIW_1_WB(10) = '1' and BIW_1_WB(14 downto 12) /= BIW_1_WB(2 downto 0) else '0'; + + WB_BUFFER: process + -- This process stores the data for the + -- WRITEBACK or the WRITE_DEST procedure. + -- The MOVEM condition is foreseen to bring + -- the ADn_WB and the PNTR_WB right in time + -- befor the address or data registers are + -- marked used. + begin + wait until CLK = '1' and CLK' event; + if OP = LINK and FETCH_STATE = START_OP and NEXT_FETCH_STATE = SWITCH_STATE then + OP_SIZE_WB <= OP_SIZE_I; -- Bring this information early because the registers are written early. + elsif ALU_INIT_I = '1' then + if OP = DIVS or OP = DIVU or OP = MULS or OP = MULU then + OP_SIZE_WB <= LONG; + elsif OP = MOVEM and BIW_0(10) = '1' then -- Memory to register. + OP_SIZE_WB <= LONG; -- Registers are always written long. + else + OP_SIZE_WB <= OP_SIZE_I; -- Store right in the end before data processing starts. + end if; + + MOVEM_ADn_WB <= MOVEM_ADn_I; + OP_WB_I <= OP; + BIW_0_WB <= BIW_0(11 downto 0); + BIW_1_WB <= BIW_1; + end if; + end process WB_BUFFER; + + OP_WB <= OP_WB_I; + BIW_0_WB_73 <= BIW_0_WB(7 downto 3); + + OP_SIZE <= OP_SIZE_I; + OP_SIZE_I <= LONG when (OP = ADDA or OP = CMPA or OP = SUBA) and BIW_0(8 downto 7) = "11" else + LONG when (OP = BCHG or OP = BCLR or OP = BTST or OP = BSET) and BIW_0(5 downto 3) = "000" else + LONG when OP = EXT and BIW_0(8 downto 6) = "011" else + LONG when OP = BSR or OP = EXG or OP = JSR or OP = LEA or OP = LINK or OP = PEA or OP = SWAP or OP = UNLK else + LONG when OP = CHK and BIW_0(8 downto 7) = "10" else + LONG when (OP = MOVE or OP = MOVEA) and BIW_0(13 downto 12) = "10" else + LONG when OP = MOVEC or OP = MOVEQ or OP = MOVE_USP or OP = RTD or OP = RTS else + LONG when OP = MOVEM and BIW_0(6) = '1' else + LONG when OP = MOVEP and FETCH_STATE = INIT_EXEC_WB and BIW_0(7 downto 6) < "10" else -- Writeback to registers is long (see top level multiplexer). + LONG when (OP = DIVS or OP = DIVU or OP = MULS or OP = MULU) and BIW_0(7) = '0' else + LONG when OP = RTR and PHASE2 = true else -- Read PC. + WORD when (OP = ADDA or OP = CMPA or OP = SUBA) and BIW_0(8 downto 7) = "01" else + WORD when (OP = ASL or OP = ASR) and BIW_0(7 downto 6) = "11" else -- Memory shifts. + WORD when OP = ANDI_TO_SR or OP = EORI_TO_SR or OP = ORI_TO_SR else + WORD when OP = BKPT and FETCH_STATE = FETCH_OPERAND and DATA_RD_I = '1' else + WORD when OP = CHK and BIW_0(8 downto 7) = "11" else + WORD when OP = DBcc or OP = EXT else + WORD when (OP = LSL or OP = LSR) and BIW_0(7 downto 6) = "11" else -- Memory shifts. + WORD when (OP = MOVE or OP = MOVEA) and BIW_0(13 downto 12) = "11" else + WORD when OP = MOVE_FROM_CCR or OP = MOVE_TO_CCR else + WORD when OP = MOVE_FROM_SR or OP = MOVE_TO_SR else + WORD when OP = MOVEM or OP = RTR else + WORD when OP = DIVS or OP = DIVU or OP = MULS or OP = MULU else + WORD when (OP = ROTL or OP = ROTR) and BIW_0(7 downto 6) = "11" else -- Memory shifts. + WORD when (OP = ROXL or OP = ROXR) and BIW_0(7 downto 6) = "11" else -- Memory shifts. + BYTE when OP = ABCD or OP = NBCD or OP = SBCD else + BYTE when OP = ANDI_TO_CCR or OP = EORI_TO_CCR or OP = ORI_TO_CCR else + BYTE when OP = BCHG or OP = BCLR or OP = BTST or OP = BSET else + BYTE when OP = MOVE or OP = MOVEP else + BYTE when OP = Scc or OP = TAS else + -- The following are default settings for all other OP_SIZE relevant operations. + BYTE when BIW_0(7 downto 6) = "00" else + WORD when BIW_0(7 downto 6) = "01" else LONG; + + BKPT_CYCLE <= '1' when OP = BKPT and FETCH_STATE = FETCH_OPERAND and DATA_RD_I = '1' else '0'; + BKPT_INSERT <= '1' when OP = BKPT and FETCH_STATE = FETCH_OPERAND and RD_RDY = '1' and DATA_VALID = '1' else '0'; + + -- All traps must be modeled as strobes. + TRAP_ILLEGAL <= '1' when OP = BKPT and FETCH_STATE = FETCH_OPERAND and RD_RDY = '1' and DATA_VALID = '0' else '0'; + + TRAP_V <= '1' when OP = TRAPV and ALU_COND = true and FETCH_STATE = SLEEP and NEXT_FETCH_STATE = START_OP else '0'; + + BERR <= '0' when FETCH_STATE = START_OP and EXEC_WB_STATE = IDLE else -- Disable when controller is not active. + '0' when OP = BKPT else -- No bus error during breakpoint cycle. + '1' when DATA_RDY = '1' and DATA_VALID = '0' else + '1' when OPD_ACK = '1' and OW_VALID = '0' else + '1' when EW_ACK = '1' and OW_VALID = '0' else '0'; + + SFC_RD <= '1' when OP = MOVEC and BIW_0(0) = '0' and BIW_1(11 downto 0) = x"000" else '0'; + SFC_WR <= '1' when OP_WB_I = MOVEC and BIW_0_WB(0) = '1' and BIW_1_WB(11 downto 0) = x"000" and EXEC_WB_STATE = WRITEBACK else '0'; + + DFC_RD <= '1' when OP = MOVEC and BIW_0(0) = '0' and BIW_1(11 downto 0) = x"001" else '0'; + DFC_WR <= '1' when OP_WB_I = MOVEC and BIW_0_WB(0) = '1' and BIW_1_WB(11 downto 0) = x"001" and EXEC_WB_STATE = WRITEBACK else '0'; + + VBR_RD <= '1' when OP = MOVEC and BIW_0(0) = '0' and BIW_1(11 downto 0) = x"801" else '0'; + VBR_WR <= '1' when OP_WB_I = MOVEC and BIW_0_WB(0) = '1' and BIW_1_WB(11 downto 0) = x"801" and EXEC_WB_STATE = WRITEBACK else '0'; + + USP_RD <= '1' when OP = MOVE_USP and BIW_0(3) = '1' else + '1' when OP = MOVEC and BIW_0(0) = '0' and BIW_1(11 downto 0) = x"800" else '0'; + USP_WR <= '1' when OP_WB_I = MOVE_USP and EXEC_WB_STATE = WRITEBACK and BIW_0_WB(3) = '0' else + '1' when OP_WB_I = MOVEC and BIW_0_WB(0) = '1' and BIW_1_WB(11 downto 0) = x"800" and EXEC_WB_STATE = WRITEBACK else '0'; + + P_DISPLACEMENT: process + variable DISPL_VAR : std_logic_vector(31 downto 0); + -- The displacement is is always word sized and sign + -- extended for the K00/K10. + begin + wait until CLK = '1' and CLK' event; + case OP is + when Bcc | BRA | BSR => + case BIW_0(7 downto 0) is + when x"00" => + for i in 16 to 31 loop + DISPL_VAR(i) := BIW_1(15); + end loop; + DISPL_VAR(15 downto 0) := BIW_1; + when others => + for i in 8 to 31 loop + DISPL_VAR(i) := BIW_0(7); + end loop; + DISPL_VAR(7 downto 0) := BIW_0(7 downto 0); + end case; + when DBcc | MOVEP | RTD => + for i in 16 to 31 loop + DISPL_VAR(i) := BIW_1(15); + end loop; + DISPL_VAR(15 downto 0) := BIW_1; + when others => -- Used for LINK. + for i in 16 to 31 loop + DISPL_VAR(i) := BIW_1(15); + end loop; + DISPL_VAR(15 downto 0) := BIW_1; + end case; + -- + case OP is + when LINK | MOVEP => DISPLACEMENT <= DISPL_VAR; + when others => DISPLACEMENT <= DISPL_VAR + "10"; + end case; + end process P_DISPLACEMENT; + + PC_ADD_DISPL <= '1' when OP = Bcc and FETCH_STATE /= START_OP and NEXT_FETCH_STATE = START_OP and ALU_COND = true else + '1' when (OP = BRA or OP = BSR) and FETCH_STATE /= START_OP and NEXT_FETCH_STATE = START_OP else + '1' when OP = DBcc and FETCH_STATE /= START_OP and NEXT_FETCH_STATE = START_OP and ALU_COND = false and DBcc_COND = false else '0'; + + PC_LOAD <= PC_LOAD_I; + PC_LOAD_I <= '1' when (OP = JMP or OP = JSR) and FETCH_STATE /= START_OP and NEXT_FETCH_STATE = START_OP else + '1' when (OP = RTD or OP = RTR or OP = RTS) and FETCH_STATE /= START_OP and NEXT_FETCH_STATE = START_OP else '0'; + + -- The pipe is flushed for the system control instructions. Be aware, that the operations resulting in an exception + -- like the CHK or TRAP operations flush the pipe via the exception handler. + -- Context switch may occur from: + -- changing the PC value (branches etc.) + -- changing the RAM space (status register MSBs). + -- changing Function codes or the active stack pointer. + IPIPE_FLUSH <= IPIPE_FLUSH_I; + IPIPE_FLUSH_I <= '1' when (OP = BRA or OP = BSR) and FETCH_STATE /= START_OP and NEXT_FETCH_STATE = START_OP else + '1' when OP = Bcc and FETCH_STATE /= START_OP and NEXT_FETCH_STATE = START_OP and ALU_COND = true else + '1' when OP = DBcc and LOOP_BSY = '0' and FETCH_STATE /= START_OP and NEXT_FETCH_STATE = START_OP and ALU_COND = false and DBcc_COND = false else + '1' when OP = DBcc and LOOP_EXIT_I = '1' and (ALU_COND = true or DBcc_COND = true) else -- Flush the pipe after a finished loop. + '1' when (OP = ANDI_TO_SR or OP = EORI_TO_SR or OP = MOVE_TO_SR or OP = ORI_TO_SR) and FETCH_STATE = SLEEP and NEXT_FETCH_STATE = START_OP else + '1' when (OP = JMP or OP = JSR) and FETCH_STATE /= START_OP and NEXT_FETCH_STATE = START_OP else + '1' when OP = MOVEC and BIW_0(0) = '1' and FETCH_STATE /= START_OP and NEXT_FETCH_STATE = START_OP else -- Writing control registers. + '1' when (OP = RTD or OP = RTR or OP = RTS) and FETCH_STATE /= START_OP and NEXT_FETCH_STATE = START_OP else '0'; + + SP_ADD_DISPL <= '1' when OP = LINK and FETCH_STATE = INIT_EXEC_WB and ALU_BSY = '0' else + '1' when OP = RTD and FETCH_STATE = FETCH_OPERAND and RD_RDY = '1' and DATA_VALID = '1' else '0'; + + ALU_TRIG <= '0' when ALU_BSY = '1' or FETCH_STATE /= INIT_EXEC_WB else + '0' when OP = CMPM and PHASE2 = false else + '0' when OP = MOVE and PHASE2 = true else -- No ALU required after second portion of address calculation. + '0' when OP = MOVEM and MOVEM_COND = false else + '0' when OP = MOVEM and BIW_0(10) = '1' and MOVEM_FIRST_RD = false else -- Do not load before the first read access. + '0' when OP = RTR and PHASE2 = true else '1'; -- RTR: not when PC is loaded. + + -- This is the signal loading the operands into the ALU registers: + ALU_INIT <= ALU_INIT_I; + with OP select + ALU_INIT_I <= ALU_TRIG when ABCD | ADD | ADDA | ADDI | ADDQ | ADDX | AND_B | ANDI | ANDI_TO_CCR | ANDI_TO_SR | ASL | ASR | Bcc | BCHG | + BCLR | BSET | BSR | BTST | CHK | CLR | CMP | CMPA | CMPI | CMPM | DBcc | DIVS | DIVU | EOR | EORI | + EORI_TO_CCR | EORI_TO_SR | EXG | EXT | JSR | LEA | LINK | LSL | LSR | MOVE | MOVEA | MOVE_FROM_CCR | + MOVE_TO_CCR | MOVE_FROM_SR | MOVE_TO_SR | MOVE_USP | MOVEC | MOVEM | MOVEQ | MOVEP | MOVES | MULS | + MULU | NBCD | NEG | NEGX | NOT_B | OR_B | ORI | ORI_TO_CCR | ORI_TO_SR | PEA | ROTL | ROTR | ROXL | + ROXR | RTR | SBCD | Scc | SUB | SUBA | SUBI | SUBQ | SUBX | SWAP | STOP | TAS | TRAPV | TST | UNLK, '0' when others; + + UPDT_CC <= '0' when (OP_WB_I = ADDQ or OP_WB_I = SUBQ) and BIW_0_WB(5 downto 3) = "001" else ALU_REQ; -- No update for ADDQ and SUBQ when destination is an address register. + + with OP_WB_I select + CC_UPDT <= UPDT_CC when ABCD | ADD | ADDI | ADDQ | ADDX | AND_B | ANDI | ANDI_TO_CCR | ASL | ASR | BCHG | BCLR | + BSET | BTST | CHK | CLR | CMP | CMPA | CMPI | CMPM | DIVS | DIVU | + EOR | EORI | EORI_TO_CCR | EXT | LSL | LSR | MOVE | MOVEQ | MULS | MULU | NBCD | + NEG | NEGX | NOT_B | OR_B | ORI | ORI_TO_CCR | ROTL | ROTR | ROXL | ROXR | RTR | SBCD | + SUB | SUBI | SUBQ | SUBX | SWAP | TAS | TST, '0' when others; + + ADR_MARK_USED <= '1' when OP = MOVE and FETCH_STATE = INIT_EXEC_WB and PHASE2 = true else -- Destination address calculation done. + '0' when FETCH_STATE /= INIT_EXEC_WB or ALU_BSY = '1' else -- Deactivate except in the end of INIT_EXEC_WB. + '1' when OP = BSR or OP = JSR or OP = LINK or OP = PEA else + '1' when (OP = ADDI or OP = ANDI or OP = EOR or OP = EORI or OP = ORI or OP = SUBI) and BIW_0(5 downto 3) /= "000" else + '1' when (OP = ABCD or OP = SBCD or OP = ADDX or OP = SUBX) and BIW_0(3) = '1' else + '1' when (OP = ADD or OP = AND_B or OP = OR_B or OP = SUB) and BIW_0(8) = '1' else -- Destination is memory. + '1' when (OP = ADDQ or OP = BCHG or OP = BCLR or OP = BSET or OP = CLR or OP = MOVE_FROM_CCR or OP = MOVE_FROM_SR) and BIW_0(5 downto 3) > "001" else + '1' when (OP = NBCD or OP = NEG or OP = NEGX or OP = NOT_B or OP = Scc or OP = SUBQ or OP = TAS) and BIW_0(5 downto 3) > "001" else + '1' when (OP = ASL or OP = ASR or OP = LSL or OP = LSR) and BIW_0(7 downto 6) = "11" else -- Memory shifts. + '1' when (OP = ROTL or OP = ROTR or OP = ROXL or OP = ROXR) and BIW_0(7 downto 6) = "11" else -- Memory shifts. + '1' when OP = MOVE and PHASE2 = false and BIW_0(8 downto 6) /= "000" and BIW_0(8 downto 6) < "101" else -- We do not need destination address calculation access. + '1' when OP = MOVEM and BIW_0(10) = '0' and MOVEM_COND = true else -- Register to memory. + '1' when OP = MOVEP and BIW_0(7 downto 6) > "01" else -- Register to Memory. + '1' when OP = MOVES and BIW_1(11) = '1' else '0'; -- Register to memory. + + AR_MARK_USED <= '1' when OP = UNLK and FETCH_STATE /= SWITCH_STATE and NEXT_FETCH_STATE = SWITCH_STATE else -- This is for An to SP. + '1' when OP = LINK and FETCH_STATE = SWITCH_STATE and NEXT_FETCH_STATE /= SWITCH_STATE else -- This is for SP to An. + '0' when FETCH_STATE /= INIT_EXEC_WB or NEXT_FETCH_STATE = INIT_EXEC_WB else -- Deactivate except in the end of INIT_EXEC_WB. + '1' when OP = ADDA or OP = SUBA else + '1' when (OP = ADDQ or OP = SUBQ) and BIW_0(5 downto 3) = "001" else + '1' when OP = EXG and BIW_0(7 downto 3) /= "01000" else + '1' when OP = LEA else + '1' when OP = MOVE_USP else + '1' when OP = MOVEM and BIW_0(10) = '1' and MOVEM_ADn_I = '1' and MOVEM_COND = true else -- Memory to register. + '1' when OP = MOVEA else + '1' when OP = MOVEC and BIW_0(0) = '0' and BIW_1(15) = '1' else -- Destination is Ax. + '1' when OP = MOVES and BIW_1(15) = '1' and BIW_1(11) = '0' else + '1' when OP = UNLK else '0'; + + DR_MARK_USED <= '0' when FETCH_STATE /= INIT_EXEC_WB or NEXT_FETCH_STATE = INIT_EXEC_WB else -- Deactivate except in the end of INIT_EXEC_WB. + '1' when (OP = ABCD or OP = SBCD) and BIW_0(3) = '0' else + '1' when (OP = ADDX or OP = SUBX) and BIW_0(3) = '0' else + '1' when (OP = ADDQ or OP = SUBQ) and BIW_0(5 downto 3) = "000" else + '1' when (OP = ADD or OP = SUB) and BIW_0(8) = '0' else -- Destination is a register. + '1' when (OP = ADDI or OP = ANDI or OP = EOR or OP = EORI or OP = ORI or OP = SUBI) and BIW_0(5 downto 3) = "000" else + '1' when (OP = AND_B or OP = OR_B) and BIW_0(8) = '0' else -- Destination is a register. + '1' when (OP = ASL or OP = ASR) and BIW_0(7 downto 6) /= "11" else + '1' when (OP = LSL or OP = LSR) and BIW_0(7 downto 6) /= "11" else + '1' when (OP = ROTL or OP = ROTR) and BIW_0(7 downto 6) /= "11" else + '1' when (OP = ROXL or OP = ROXR) and BIW_0(7 downto 6) /= "11" else + '1' when (OP = BCHG or OP = BCLR or OP = BSET) and BIW_0(5 downto 3) = "000" else + '1' when (OP = CLR or OP = TAS or OP = Scc) and BIW_0(5 downto 3) = "000" else + '1' when OP = DBcc or OP = DIVS or OP = DIVU or OP = MULS or OP = MULU else + '1' when OP = EXG and BIW_0(7 downto 3) /= "01001" else + '1' when OP = EXT or OP = SWAP else + '1' when OP = MOVE and BIW_0(8 downto 6) = "000" else + '1' when (OP = MOVE_FROM_CCR or OP = MOVE_FROM_SR) and BIW_0(5 downto 3) = "000" else + '1' when OP = MOVEM and BIW_0(10) = '1' and MOVEM_ADn_I = '0' and MOVEM_COND = true else -- Memory to register. + '1' when OP = MOVEP and BIW_0(7 downto 6) < "10" else -- Memory to register. + '1' when OP = MOVEC and BIW_0(0) = '0' and BIW_1(15) = '0' else -- Destination is Dx. + '1' when OP = MOVEQ else + '1' when OP = MOVES and BIW_1(15) = '0' and BIW_1(11) = '0' else + '1' when (OP = NBCD or OP = NEG or OP = NEGX or OP = NOT_B) and BIW_0(5 downto 3) = "000" else '0'; + + UNMARK <= '1' when EXEC_WB_STATE /= IDLE and NEXT_EXEC_WB_STATE = IDLE else '0'; -- Release a pending write cycle when done. + + -- These signals indicates, that two registers are prepared to be written. In this case, the values + -- in both of these registers are invalidated before the writeback. + USE_APAIR <= true when OP = EXG and BIW_0(7 downto 3) = "01001" else false; + USE_DPAIR <= true when OP = EXG and BIW_0(7 downto 3) = "01000" else + true when (OP = DIVS or OP = DIVU) and OP_SIZE_I = LONG and BIW_1(14 downto 12) /= BIW_1(2 downto 0) else + true when (OP = MULS or OP = MULU) and OP_SIZE_I = LONG and BIW_1(10) = '1' and BIW_1(14 downto 12) /= BIW_1(2 downto 0) else false; + + LOOP_EXIT <= LOOP_EXIT_I; + LOOP_EXIT_I <= '1' when OP /= DBcc and LOOP_BSY = '1' and FETCH_STATE /= START_OP and NEXT_FETCH_STATE = START_OP and EXH_REQ = '1' else -- Exception! break the loop. + '1' when OP = DBcc and LOOP_BSY = '1' and FETCH_STATE = SLEEP and NEXT_FETCH_STATE = START_OP and (ALU_COND = true or DBcc_COND = true) else '0'; -- 68010 loop mechanism. + + LOOP_CTRL: process + -- This flip flop indicates, if a DBcc loop operation has finished if the exception handler indicates an interrupt. + -- If so, no action is required. If the loop is split (when not finished) the exception handler may not increment + -- the PC to hold the value of the loop operation. + -- Split the loop between the loop op and DBcc to handle the PC value at interrupts correctly. + begin + wait until CLK = '1' and CLK' event; + if FETCH_STATE = START_OP and NEXT_FETCH_STATE /= START_OP then + LOOP_SPLIT <= false; + elsif PC_INC_EXH = '1' then + LOOP_SPLIT <= false; + elsif OP /= DBcc and EXH_REQ = '1' and LOOP_BSY = '1' and FETCH_STATE = SLEEP and NEXT_FETCH_STATE = START_OP then + LOOP_SPLIT <= true; + end if; + end process LOOP_CTRL; + + RESET_STRB <= '1' when OP = RESET and INIT_ENTRY = '1' else '0'; + + EX_TRACE <= '0' when OP = ILLEGAL or OP = UNIMPLEMENTED else + '1' when TRACE_EN = '1' and OPD_ACK = '1' and FETCH_STATE = START_OP and OP = TRAP else + '1' when TRACE_EN = '1' and FETCH_STATE /= START_OP and NEXT_FETCH_STATE = START_OP else '0'; + + ADDRESS_OFFSET: process + variable ADR_OFFS_VAR: std_logic_vector(5 downto 0) := "000000"; + begin + wait until CLK = '1' and CLK' event; + if FETCH_STATE = START_OP then + ADR_OFFS_VAR := "000000"; + else + case OP is + when MOVEM => + if ADR_MODE_I = "011" or ADR_MODE_I = "100" then -- (An)+, -(An). + null; -- Offset comes from addressing register in register to memory mode. + elsif BIW_0(10) = '1' and MOVEM_FIRST_RD = false then + null; -- Do not increment before the first bus access. + elsif MOVEM_COND = true and FETCH_STATE = INIT_EXEC_WB and ALU_BSY = '0' and OP_SIZE_I = LONG then + ADR_OFFS_VAR := ADR_OFFS_VAR + "100"; -- Register to memory. + elsif MOVEM_COND = true and FETCH_STATE = INIT_EXEC_WB and ALU_BSY = '0' then + ADR_OFFS_VAR := ADR_OFFS_VAR + "10"; -- Register to memory. + end if; + when MOVEP => + if FETCH_STATE = INIT_EXEC_WB and ALU_BSY = '0' then + ADR_OFFS_VAR := ADR_OFFS_VAR + "10"; + end if; + when others => null; + end case; + end if; + ADR_OFFSET <= ADR_OFFS_VAR; + end process ADDRESS_OFFSET; + + MOVEM_CONTROL: process(ADR_MODE_I, CLK, BIW_0, BIW_1, OP, RESET_CPU, FETCH_STATE, NEXT_FETCH_STATE, ALU_BSY, MOVEM_PNTR) + variable INDEX : integer range 0 to 15 := 0; + variable MOVEM_PVAR : std_logic_vector(3 downto 0) := x"0"; + variable BITS : std_logic_vector(4 downto 0); + begin + if CLK = '1' and CLK' event then + if FETCH_STATE = START_OP then + MOVEM_PVAR := x"0"; + elsif FETCH_STATE = INIT_EXEC_WB and MOVEM_COND = false and MOVEM_PVAR < x"F" and ALU_BSY = '0' then + MOVEM_PVAR := MOVEM_PVAR + '1'; -- No data to write. + elsif BIW_0(10) = '1' and MOVEM_FIRST_RD = true and FETCH_STATE = INIT_EXEC_WB and MOVEM_PVAR < x"F" and ALU_BSY = '0' then + MOVEM_PVAR := MOVEM_PVAR + '1'; -- Data has not been read. + elsif BIW_0(10) = '0' and FETCH_STATE = INIT_EXEC_WB and MOVEM_PVAR < x"F" and ALU_BSY = '0' then + MOVEM_PVAR := MOVEM_PVAR + '1'; -- Data has been written. + end if; + + if OP = MOVEM and ALU_INIT_I = '1' and ADR_MODE_I = "011" and MOVEM_ADn_I = '1' and MOVEM_PNTR(2 downto 0) = BIW_0(2 downto 0) then + MOVEM_INH_WR <= true; -- Do not write the addressing register. + elsif ALU_INIT_I = '1' then + MOVEM_INH_WR <= false; + end if; + + if FETCH_STATE = START_OP then + MOVEM_FIRST_RD <= false; + elsif OP = MOVEM and FETCH_STATE = FETCH_OPERAND and RD_RDY = '1' then + MOVEM_FIRST_RD <= true; + end if; + + if RESET_CPU = '1' or (FETCH_STATE /= START_OP and NEXT_FETCH_STATE = START_OP) then + BITS := "00000"; + MOVEM_LAST_WR <= false; + elsif OP = MOVEM and FETCH_STATE = START_OP and NEXT_FETCH_STATE /= START_OP and ADR_MODE_I = "100" then -- -(An). + for i in 0 to 15 loop + BITS := BITS + BIW_1(i); -- Count number of '1's. + end loop; + MOVEM_LAST_WR <= false; + elsif OP = MOVEM and ALU_INIT_I = '1' and BITS > "00001" then + BITS := BITS - '1'; + elsif OP = MOVEM and BITS = "00001" then + MOVEM_LAST_WR <= true; + end if; + + -- During the MOVEM instruction in memory to register operation and addressing modes "010", "101","110" the effective address might be + -- affected, if the addressing register is active in the register list mask. To deal with it, the effective address is stored until the + -- MOVEM has read all registers from memory addressed by the initial addressing register (old value). + -- This logic is modeled synchronously (one clock latency) due to the one clock delay of the address calculation. + if OP /= MOVEM or BIW_0(10) /= '1' or (ADR_MODE_I /= "010" and ADR_MODE_I /= "101" and ADR_MODE_I /= "110") then + STORE_AEFF <= '0'; + elsif FETCH_STATE /= START_OP and NEXT_FETCH_STATE = START_OP then + STORE_AEFF <= '0'; -- Operation completed. + elsif FETCH_STATE = SWITCH_STATE or FETCH_STATE = CALC_AEFF or FETCH_STATE = FETCH_OPERAND or FETCH_STATE = INIT_EXEC_WB then + STORE_AEFF <= '1'; + end if; + end if; + + -- This signal determines whether to handle address or data registers. + if ADR_MODE_I = "100" then -- -(An). + MOVEM_ADn_I <= not To_Bit(MOVEM_PVAR(3)); + MOVEM_ADn <= not To_Bit(MOVEM_PVAR(3)); + else + MOVEM_ADn_I <= To_Bit(MOVEM_PVAR(3)); + MOVEM_ADn <= To_Bit(MOVEM_PVAR(3)); + end if; + + INDEX := To_Integer(unsigned(MOVEM_PVAR)); + + -- The following signal determines if a register is affected or not, depending + -- on the status of the register list bit. + if OP = MOVEM and BIW_1(INDEX) = '1' then + MOVEM_COND <= true; + else + MOVEM_COND <= false; + end if; + + -- This signal determines whether to handle address or data registers. + if ADR_MODE_I = "100" then -- -(An). + MOVEM_PNTR <= not MOVEM_PVAR; -- Count down. + else + MOVEM_PNTR <= MOVEM_PVAR; + end if; + end process MOVEM_CONTROL; + + MOVEP_CONTROL: process(CLK, MOVEP_PNTR_I) + -- This logic handles the bytes to be written or read during the MOVEP + -- operation. In LONG mode 4 bytes are affected and in WORD mode two bytes. + begin + if CLK = '1' and CLK' event then + if RESET_CPU = '1' or (FETCH_STATE /= START_OP and NEXT_FETCH_STATE = START_OP) then + MOVEP_PNTR_I <= 0; + elsif FETCH_STATE = START_OP and (BIW_0(8 downto 6) = "101" or BIW_0(8 downto 6) = "111") then + MOVEP_PNTR_I <= 3; -- LONG. + elsif FETCH_STATE = START_OP then + MOVEP_PNTR_I <= 1; -- WORD. + elsif FETCH_STATE = INIT_EXEC_WB and ALU_BSY = '0' and MOVEP_PNTR_I /= 0 then + MOVEP_PNTR_I <= MOVEP_PNTR_I - 1; -- Register to memory + end if; + end if; + MOVEP_PNTR <= MOVEP_PNTR_I; + end process MOVEP_CONTROL; + + PHASE2_CONTROL: process + -- This is used for some operations which require + -- two control sequences. + begin + wait until CLK = '1' and CLK' event; + if NEXT_FETCH_STATE = START_OP then + PHASE2 <= false; + elsif (OP = ABCD or OP = SBCD) and FETCH_STATE = FETCH_OPERAND and RD_RDY = '1' then + PHASE2 <= true; -- One clock cycle delay for destination address calculation. + elsif (OP = ADDX or OP = SUBX) and FETCH_STATE = FETCH_OPERAND and RD_RDY = '1' then + PHASE2 <= true; -- One clock cycle delay for destination address calculation. + elsif OP = CMPM and FETCH_STATE = INIT_EXEC_WB and ALU_BSY = '0' then + PHASE2 <= true; -- Used as a control flow switch. + elsif OP = JSR and FETCH_STATE = SLEEP then + PHASE2 <= true; -- One clock cycle delay for address calculation. + elsif OP = PEA and FETCH_STATE = SWITCH_STATE then + PHASE2 <= true; -- One clock cycle delay for address calculation. + elsif OP = RTR and FETCH_STATE = INIT_EXEC_WB and NEXT_FETCH_STATE = CALC_AEFF then + PHASE2 <= true; -- Used as a control flow switch. + elsif OP = MOVE and FETCH_STATE = INIT_EXEC_WB and ALU_BSY = '0' and BIW_0(8 downto 6) > "100" then + PHASE2 <= true; -- Indicate destination address calculation is in progress. + end if; + end process PHASE2_CONTROL; + + STATE_REGs: process + begin + wait until CLK = '1' and CLK' event; + if RESET_CPU = '1' then + FETCH_STATE <= START_OP; + EXEC_WB_STATE <= IDLE; + elsif EW_ACK = '1' and OW_VALID = '0' then + FETCH_STATE <= START_OP; -- Bus error. + EXEC_WB_STATE <= IDLE; + elsif OPD_ACK = '1' and OW_VALID = '0' then + FETCH_STATE <= START_OP; -- Bus error. + EXEC_WB_STATE <= IDLE; + elsif DATA_RD_I = '1' and RD_RDY = '1' and DATA_VALID = '0' then + FETCH_STATE <= START_OP; -- Bus error. + EXEC_WB_STATE <= IDLE; + elsif DATA_WR_I = '1' and RD_RDY = '1' and DATA_VALID = '0' then + FETCH_STATE <= START_OP; -- Bus error. + EXEC_WB_STATE <= IDLE; + else + FETCH_STATE <= NEXT_FETCH_STATE; + EXEC_WB_STATE <= NEXT_EXEC_WB_STATE; + end if; + end process STATE_REGs; + + -- Debugging: + -- Use this signal to detect instructions in use in the writeback path (OP_WB_I) or in the fetch path (OP). + -- for these instructions you can halt the pipeline in the START_OP state to detect any problems. + -- with OP select + -- with OP_WB_I select + -- OP_TEST <= '1' when ADDA | ADDQ | EXG | LEA | LINK | MOVEA | MOVE_USP | MOVEC | MOVEM | MOVES | SUBA | SUBQ | UNLK | -- Address register manipulations. + -- ASL | ASR | LSL | LSR | ROTL | ROTR | ROXL | ROXR | DIVS | DIVU | -- Long ALU operations. (68K10, 68K30L have no barrel shifter). + -- ADD | AND_B | CLR | EOR | SUB | OR_B | CMP | CMPA | CMPM | NOT_B | NBCD | NEG | NEGX | SWAP | TAS | TST | + -- ANDI_TO_CCR | ANDI_TO_SR | EORI_TO_CCR | EORI_TO_SR | ORI_TO_CCR | ORI_TO_SR | MOVE_FROM_CCR | + -- MOVE_TO_CCR | MOVE_FROM_SR | MOVE_TO_SR | MOVE | MOVEQ | MOVEP | PEA | + -- ABCD | ADDX | SBCD | SUBX | BCHG | BCLR | BSET | BTST | EXT | + -- Bcc | BSR | CHK | DBcc | JSR | TRAPV | RTR | Scc | STOP | + -- ADDI | ANDI | SUBI | CMPI | EORI | ORI | MULS | MULU, '0' when others; + + FETCH_DEC: process(ADR_MODE_I, ALU_BSY, ALU_COND, AR_IN_USE, BIW_0, BIW_1, BRANCH_ATN, DR_IN_USE, EW_ACK, + EW_RDY, EXEC_WB_STATE, EXH_REQ, EXT_WORD, FETCH_STATE, MOVEM_COND, MOVEM_PNTR, MOVEP_PNTR_I, + NEXT_EXEC_WB_STATE, OP, OP_SIZE_I, OP_WB_I, OPD_ACK, OW_RDY, PHASE2, RD_RDY, TRACE_EN, WR_RDY) + -- ADH: avoid data hazard. + -- ASH: avoid structural hazard. + -- ACH: avoid control hazard. + begin + case FETCH_STATE is + when START_OP => + if OPD_ACK = '0' and OW_RDY = '0' then + NEXT_FETCH_STATE <= START_OP; + -- Debugging: + --elsif OP_TEST = '1' and ALU_BSY = '1' then + -- NEXT_FETCH_STATE <= START_OP; + else + case OP is + when ILLEGAL | RTE | TRAP | UNIMPLEMENTED => + NEXT_FETCH_STATE <= START_OP; + when DBcc | EXT | MOVEQ | SWAP => + if DR_IN_USE = '1' then + NEXT_FETCH_STATE <= START_OP; -- Wait, ADH. + else + NEXT_FETCH_STATE <= INIT_EXEC_WB; -- Proceed. + end if; + when ABCD | SBCD | ADDX | SUBX => + if BIW_0(3) = '0' and DR_IN_USE = '0' then -- ADH. + NEXT_FETCH_STATE <= INIT_EXEC_WB; -- Register to register. + elsif BIW_0(3) = '1' and AR_IN_USE = '0' then -- Check for destination addressing register. ADH. + NEXT_FETCH_STATE <= CALC_AEFF; -- Memory to memory. + else + NEXT_FETCH_STATE <= START_OP; -- Wait, ADH. + end if; + when ADD | ADDI | ADDQ | AND_B | ANDI | CMP | CMPI | EOR | EORI | + NBCD | NEG | NEGX | NOT_B | OR_B | ORI | SUB | SUBI | SUBQ | TST | TAS => + -- These instructions have to take the destination into aspect + -- because the destination is an ALU operand and may cause data hazards. + case BIW_0(5 downto 3) is + when "000" => -- Dn. + if DR_IN_USE = '0' then + NEXT_FETCH_STATE <= INIT_EXEC_WB; + else + NEXT_FETCH_STATE <= START_OP; + end if; + when "001" => -- An. + if (OP = ADD or OP = SUB or OP = AND_B or OP = EOR or OP = OR_B or OP = CMP) and (AR_IN_USE = '1' or DR_IN_USE = '1')then -- ADH. + NEXT_FETCH_STATE <= START_OP; + elsif AR_IN_USE = '0' then + NEXT_FETCH_STATE <= INIT_EXEC_WB; + else + NEXT_FETCH_STATE <= START_OP; + end if; + when "010" | "011" => -- (An), (An)+. + if AR_IN_USE = '1' then -- ADH. + NEXT_FETCH_STATE <= START_OP; -- Wait, ADH. + else + NEXT_FETCH_STATE <= FETCH_OPERAND; + end if; + when "100" => -- -(An). + if AR_IN_USE = '1' then -- ADH. + NEXT_FETCH_STATE <= START_OP; -- Wait, ADH. + else + NEXT_FETCH_STATE <= CALC_AEFF; + end if; + when "101" => + NEXT_FETCH_STATE <= FETCH_DISPL; + when "110" => + NEXT_FETCH_STATE <= FETCH_EXWORD_1; + when others => -- "111" + if BIW_0(2 downto 0) = "000" then + NEXT_FETCH_STATE <= FETCH_ABS_LO; + elsif BIW_0(2 downto 0) = "001" then + NEXT_FETCH_STATE <= FETCH_ABS_HI; + elsif BIW_0(2 downto 0) = "100" and OP_SIZE_I = LONG then + NEXT_FETCH_STATE <= FETCH_IDATA_B2; + elsif BIW_0(2 downto 0) = "100" then -- Word or byte. + NEXT_FETCH_STATE <= FETCH_IDATA_B1; + elsif BIW_0(2 downto 0) = "010" then + NEXT_FETCH_STATE <= FETCH_DISPL; + else + NEXT_FETCH_STATE <= FETCH_EXWORD_1; + end if; + end case; + when ADDA | BCHG | BCLR | BSET | BTST | CHK | CMPA | + DIVS | DIVU | MULS | MULU | MOVEA | MOVE_TO_CCR | MOVE_TO_SR | SUBA => + case BIW_0(5 downto 3) is + when "000" => -- Source is Dn. + if (OP = ADDA or OP = SUBA or OP = CMPA or OP = MOVEA) and (AR_IN_USE = '1' or DR_IN_USE = '1') then -- ADH. + NEXT_FETCH_STATE <= START_OP; + elsif DR_IN_USE = '0' then + NEXT_FETCH_STATE <= INIT_EXEC_WB; + else + NEXT_FETCH_STATE <= START_OP; + end if; + when "001" => -- Valid for ADDA, CMPA, MOVEA, SUBA; source is An. + if AR_IN_USE = '0' then + NEXT_FETCH_STATE <= INIT_EXEC_WB; -- ADH. + else + NEXT_FETCH_STATE <= START_OP; + end if; + when "010" | "011" => -- (An), (An)+. + if AR_IN_USE = '1' then -- ADH. + NEXT_FETCH_STATE <= START_OP; -- Wait, ADH! + else + NEXT_FETCH_STATE <= FETCH_OPERAND; + end if; + when "100" => -- -(An). + if AR_IN_USE = '1' then -- ADH. + NEXT_FETCH_STATE <= START_OP; -- Wait, ADH! + else + NEXT_FETCH_STATE <= CALC_AEFF; + end if; + when "101" => + NEXT_FETCH_STATE <= FETCH_DISPL; + when "110" => + NEXT_FETCH_STATE <= FETCH_EXWORD_1; + when others => -- "111" + if BIW_0(2 downto 0) = "000" then + NEXT_FETCH_STATE <= FETCH_ABS_LO; + elsif BIW_0(2 downto 0) = "001" then + NEXT_FETCH_STATE <= FETCH_ABS_HI; + elsif BIW_0(2 downto 0) = "100" and OP_SIZE_I = LONG then + NEXT_FETCH_STATE <= FETCH_IDATA_B2; + elsif BIW_0(2 downto 0) = "100" then -- Word or Byte. + NEXT_FETCH_STATE <= FETCH_IDATA_B1; + elsif BIW_0(2 downto 0) = "010" then + NEXT_FETCH_STATE <= FETCH_DISPL; + else + NEXT_FETCH_STATE <= FETCH_EXWORD_1; + end if; + end case; + when EXG => + if BIW_0(7 downto 3) = "10001" and (DR_IN_USE = '1' or AR_IN_USE = '1') then + NEXT_FETCH_STATE <= START_OP; -- Wait, ADH. + elsif BIW_0(7 downto 3) = "01000" and DR_IN_USE = '1' then + NEXT_FETCH_STATE <= START_OP; -- Wait, ADH. + elsif BIW_0(7 downto 3) = "01001" and AR_IN_USE = '1' then + NEXT_FETCH_STATE <= START_OP; -- Wait, ADH. + else + NEXT_FETCH_STATE <= INIT_EXEC_WB; + end if; + when NOP => -- Synchronize the instruction pipeline. + if ALU_BSY = '0' and EXEC_WB_STATE = IDLE then + NEXT_FETCH_STATE <= INIT_EXEC_WB; + else + NEXT_FETCH_STATE <= START_OP; + end if; + when MOVE_FROM_CCR | MOVE_FROM_SR => + if ALU_BSY = '0' then + case BIW_0(5 downto 3) is + when "000" => -- Destination is Dn. + if DR_IN_USE = '0' then + NEXT_FETCH_STATE <= INIT_EXEC_WB; + else + NEXT_FETCH_STATE <= START_OP; + end if; + when "010" | "011" | "100" => -- (An), (An)+, -(An). + if AR_IN_USE = '0' then + NEXT_FETCH_STATE <= INIT_EXEC_WB; + else + NEXT_FETCH_STATE <= START_OP; -- Wait, ADH. + end if; + when "101" => + NEXT_FETCH_STATE <= FETCH_DISPL; + when "110" => + NEXT_FETCH_STATE <= FETCH_EXWORD_1; + when others => -- "111" + if BIW_0(2 downto 0) = "000" then + NEXT_FETCH_STATE <= FETCH_ABS_LO; + else + NEXT_FETCH_STATE <= FETCH_ABS_HI; + end if; + end case; + else + NEXT_FETCH_STATE <= START_OP; + end if; + when ASL | ASR | LSL | LSR | ROTL | ROTR | ROXL | ROXR => + if BIW_0(7 downto 6) /= "11" then -- Register shifts. + if DR_IN_USE = '0' then + NEXT_FETCH_STATE <= INIT_EXEC_WB; -- ADH. + else + NEXT_FETCH_STATE <= START_OP; + end if; + else -- Memory shifts. + case BIW_0(5 downto 3) is + when "010" | "011" => -- (An), (An)+. + if AR_IN_USE = '0' then -- ADH. + NEXT_FETCH_STATE <= FETCH_OPERAND; + else + NEXT_FETCH_STATE <= START_OP; + end if; + when "100" => -- -(An). + if AR_IN_USE = '0' then -- ADH. + NEXT_FETCH_STATE <= CALC_AEFF; + else + NEXT_FETCH_STATE <= START_OP; + end if; + when "101" => + NEXT_FETCH_STATE <= FETCH_DISPL; + when "110" => + NEXT_FETCH_STATE <= FETCH_EXWORD_1; + when others => -- "111". + if BIW_0(2 downto 0) = "000" then + NEXT_FETCH_STATE <= FETCH_ABS_LO; + else + NEXT_FETCH_STATE <= FETCH_ABS_HI; + end if; + end case; + end if; + when BKPT => + -- Wait until the bus controller is free to avoid a structural + -- hazard due to the top level function code multiplexer which + -- switches the CPU_SPACE selector. + if ALU_BSY = '0' then + NEXT_FETCH_STATE <= FETCH_OPERAND; + else + NEXT_FETCH_STATE <= START_OP; + end if; + when CMPM | RTD | RTR | RTS => + if AR_IN_USE = '0' then -- ADH. + NEXT_FETCH_STATE <= FETCH_OPERAND; + else + NEXT_FETCH_STATE <= START_OP; + end if; + when CLR | JMP | JSR | LEA | PEA | Scc => -- No read access required. + case BIW_0(5 downto 3) is + when "000" => -- CLR, Scc. + if DR_IN_USE = '0' then + NEXT_FETCH_STATE <= INIT_EXEC_WB; + else + NEXT_FETCH_STATE <= START_OP; + end if; + when "001" | "010" | "011" | "100" => + if AR_IN_USE = '1' then + NEXT_FETCH_STATE <= START_OP; -- Wait, ADH. + elsif OP = LEA or OP = PEA then + NEXT_FETCH_STATE <= SWITCH_STATE; + else + NEXT_FETCH_STATE <= INIT_EXEC_WB; + end if; + when "101" => + NEXT_FETCH_STATE <= FETCH_DISPL; + when "110" => + NEXT_FETCH_STATE <= FETCH_EXWORD_1; + when others => -- "111" + if BIW_0(2 downto 0) = "000" then + NEXT_FETCH_STATE <= FETCH_ABS_LO; + elsif BIW_0(2 downto 0) = "001" then + NEXT_FETCH_STATE <= FETCH_ABS_HI; + elsif BIW_0(2 downto 0) = "010" then + NEXT_FETCH_STATE <= FETCH_DISPL; + else + NEXT_FETCH_STATE <= FETCH_EXWORD_1; + end if; + end case; + -- + -- The following condition is a special case for the + -- stack manipulating operations JSR and PEA. If A7 + -- is in use, we have to wait in all addressing modes. + if (OP = JSR or OP = PEA) and AR_IN_USE = '1' then + NEXT_FETCH_STATE <= START_OP; -- Wait, ADH. + end if; + when LINK | UNLK => + -- We have to wait for the ALU because the registers are written without pipelining + -- through the ALU and the stack is decremented early. For PEA we have to wait in + -- all addressing modes, if A7 is in use. + if OP = LINK and (ALU_BSY = '1' or AR_IN_USE = '1') then + NEXT_FETCH_STATE <= START_OP; -- Wait, ADH, ASH (two address registers are affected). + elsif OP = UNLK and ALU_BSY = '1' then + NEXT_FETCH_STATE <= START_OP; -- Wait, ADH, ASH (two address registers are affected). + else + NEXT_FETCH_STATE <= SWITCH_STATE; -- Stack pointer is decremented in this state. + end if; + when MOVE => + case BIW_0(5 downto 3) is -- Source operand. + when "000" => -- Dn. + -- Destination is -(An) and will be decremented here, wait. + if BIW_0(8 downto 6) = "100" and (AR_IN_USE = '1' or DR_IN_USE = '1') then + NEXT_FETCH_STATE <= START_OP; + elsif DR_IN_USE = '1' then + NEXT_FETCH_STATE <= START_OP; + else + NEXT_FETCH_STATE <= INIT_EXEC_WB; + end if; + when "001" => -- An. + if AR_IN_USE = '1' then + NEXT_FETCH_STATE <= START_OP; + else + NEXT_FETCH_STATE <= INIT_EXEC_WB; + end if; + when "010" | "011" => -- (An), (An)+. + if AR_IN_USE = '0' then + NEXT_FETCH_STATE <= FETCH_OPERAND; + else + NEXT_FETCH_STATE <= START_OP; + end if; + when "100" => -- -(An). + if AR_IN_USE = '0' then + NEXT_FETCH_STATE <= CALC_AEFF; + else + NEXT_FETCH_STATE <= START_OP; + end if; + when "101" => + NEXT_FETCH_STATE <= FETCH_DISPL; + when "110" => + NEXT_FETCH_STATE <= FETCH_EXWORD_1; + when others => + if BIW_0(2 downto 0) = "000" then + NEXT_FETCH_STATE <= FETCH_ABS_LO; + elsif BIW_0(2 downto 0) = "001" then + NEXT_FETCH_STATE <= FETCH_ABS_HI; + elsif BIW_0(2 downto 0) = "100" and BIW_0(13 downto 12) = "10" then -- Long. + NEXT_FETCH_STATE <= FETCH_IDATA_B2; + elsif BIW_0(2 downto 0) = "100" then -- Word or Byte. + NEXT_FETCH_STATE <= FETCH_IDATA_B1; + elsif BIW_0(2 downto 0) = "010" then + NEXT_FETCH_STATE <= FETCH_DISPL; + else + NEXT_FETCH_STATE <= FETCH_EXWORD_1; + end if; + end case; + when MOVEM => + case BIW_0(5 downto 3) is + when "010" | "011" | "100" => -- (An), (An)+, -(An). + if AR_IN_USE = '1' then -- ADH. + NEXT_FETCH_STATE <= START_OP; + else + NEXT_FETCH_STATE <= INIT_EXEC_WB; + end if; + when "101" => + NEXT_FETCH_STATE <= FETCH_DISPL; + when "110" => + NEXT_FETCH_STATE <= FETCH_EXWORD_1; + when others => + if BIW_0(2 downto 0) = "000" then + NEXT_FETCH_STATE <= FETCH_ABS_LO; + elsif BIW_0(2 downto 0) = "001" then + NEXT_FETCH_STATE <= FETCH_ABS_HI; + elsif BIW_0(2 downto 0) = "010" then + NEXT_FETCH_STATE <= FETCH_DISPL; + else + NEXT_FETCH_STATE <= FETCH_EXWORD_1; + end if; + end case; + when MOVEP => + if AR_IN_USE = '0' and BIW_0(7 downto 6) < "10" then + NEXT_FETCH_STATE <= SWITCH_STATE; -- Memory to register. + elsif AR_IN_USE = '0' and DR_IN_USE = '0' then -- ADH. + NEXT_FETCH_STATE <= SWITCH_STATE; -- Register to memory. + else + NEXT_FETCH_STATE <= START_OP; + end if; + when BSR | MOVE_USP => + -- MOVE_USP: wait until A7 has been updated to load the correct data to the ALU. + -- BSR: wait until A7 has been updated before decrementing. + + if AR_IN_USE = '0' then -- ADH. + NEXT_FETCH_STATE <= INIT_EXEC_WB; + else + NEXT_FETCH_STATE <= START_OP; + end if; + when MOVEC => + if BIW_0(0) = '1' and BIW_1(15) = '1' and AR_IN_USE = '1' then -- Address register is source. + NEXT_FETCH_STATE <= START_OP; -- Wait, ADH. + elsif BIW_0(0) = '1' and BIW_1(15) = '0' and DR_IN_USE = '1' then -- Data register is source. + NEXT_FETCH_STATE <= START_OP; -- Wait, ADH. + else + NEXT_FETCH_STATE <= INIT_EXEC_WB; -- AR, DR are destination. + end if; + when MOVES => + case BIW_0(5 downto 3) is + when "010" | "011" => -- (An), (An)+. + if BIW_1(11) = '0' and AR_IN_USE = '0' then -- ADH. + NEXT_FETCH_STATE <= FETCH_OPERAND; -- Memory to register. + elsif BIW_1(11) = '1' and AR_IN_USE = '0' then -- ADH. + NEXT_FETCH_STATE <= INIT_EXEC_WB; -- Register to memory. + else + NEXT_FETCH_STATE <= START_OP; -- Wait, ADH. + end if; + when "100" => -- -(An). + if BIW_1(11) = '0' and AR_IN_USE = '0' then -- ADH. + NEXT_FETCH_STATE <= CALC_AEFF; -- Memory to register. + elsif BIW_1(11) = '1' and AR_IN_USE = '0' then -- ADH. + NEXT_FETCH_STATE <= INIT_EXEC_WB; -- Register to memory. + else + NEXT_FETCH_STATE <= START_OP; -- Wait, ADH. + end if; + when "101" => + NEXT_FETCH_STATE <= FETCH_DISPL; + when "110" => + NEXT_FETCH_STATE <= FETCH_EXWORD_1; + when others => -- "111" + if BIW_0(2 downto 0) = "000" then + NEXT_FETCH_STATE <= FETCH_ABS_LO; + else + NEXT_FETCH_STATE <= FETCH_ABS_HI; + end if; + end case; + -- Register to memory: + if BIW_1(11) = '1' and BIW_1(15) = '1' and AR_IN_USE = '1' then -- ADH. + NEXT_FETCH_STATE <= START_OP; + elsif BIW_1(11) = '1' and BIW_1(15) = '0' and DR_IN_USE = '1' then -- ADH. + NEXT_FETCH_STATE <= START_OP; + end if; + when ANDI_TO_CCR | ANDI_TO_SR | EORI_TO_CCR | EORI_TO_SR | ORI_TO_CCR | ORI_TO_SR | RESET => + -- Wait until the status register / condition codes have been updated. Otherwise we + -- possibly have a data hazard using the wrong condition codes for the operation. + -- Be aware: for the ANDI_TO_SR, EORI_TO_SR, MOVE_TO_SR and ORI_TOI_SR operations + -- the pipe flush results in automatically aligned condition codes. Nevertheless + -- we need this logic for the respective operations, if the pipe is not flushed, + -- in the case of non changing RAM space. + -- For the RESET: we should not reset in running writeback cycles. + if ALU_BSY = '1' then + NEXT_FETCH_STATE <= START_OP; + else + NEXT_FETCH_STATE <= INIT_EXEC_WB; + end if; + when others => -- Bcc, BRA, STOP, TRAPV. + NEXT_FETCH_STATE <= INIT_EXEC_WB; + end case; + end if; + when FETCH_DISPL => + case OP is + when ADD | CMP | SUB | AND_B | EOR | OR_B => + if (EW_ACK = '1' or EW_RDY = '1') and AR_IN_USE = '0' then -- ADH. + NEXT_FETCH_STATE <= CALC_AEFF; + else + NEXT_FETCH_STATE <= FETCH_DISPL; + end if; + when ADDA | BCHG | BCLR | BSET | BTST | CHK | CMPA | DIVS | DIVU | MULS | MULU | MOVE | MOVEA | MOVE_TO_CCR | MOVE_TO_SR | SUBA => + if (EW_ACK = '1' or EW_RDY = '1') and OP = MOVE and PHASE2 = true and AR_IN_USE = '0' then -- ADH. + NEXT_FETCH_STATE <= INIT_EXEC_WB; + elsif (EW_ACK = '1' or EW_RDY = '1') and AR_IN_USE = '0' then -- ADH. + NEXT_FETCH_STATE <= CALC_AEFF; + else + NEXT_FETCH_STATE <= FETCH_DISPL; + end if; + when ADDI | ADDQ | ANDI | CMPI | EORI | NBCD | NEG | NEGX | NOT_B | ORI | SUBI | SUBQ | TST | TAS | ASL | ASR | LSL | LSR | ROTL | ROTR | ROXL | ROXR => + if (EW_ACK = '1' or EW_RDY = '1') and AR_IN_USE = '0' then -- ADH. + NEXT_FETCH_STATE <= CALC_AEFF; + else + NEXT_FETCH_STATE <= FETCH_DISPL; + end if; + when MOVES => + if (EW_ACK = '1' or EW_RDY = '1') and AR_IN_USE = '0' and BIW_1(11) = '0' then + NEXT_FETCH_STATE <= CALC_AEFF; + elsif (EW_ACK = '1' or EW_RDY = '1') and AR_IN_USE = '0' then + NEXT_FETCH_STATE <= INIT_EXEC_WB; + else + NEXT_FETCH_STATE <= FETCH_DISPL; + end if; + when LEA | PEA => + if (EW_ACK = '1' or EW_RDY = '1') and AR_IN_USE = '0' then -- ADH. + NEXT_FETCH_STATE <= SWITCH_STATE; + else + NEXT_FETCH_STATE <= FETCH_DISPL; + end if; + when others => -- CLR, JMP, JSR, MOVE_FROM_CCR, MOVE_FROM_SR, MOVEM, Scc. + if (EW_ACK = '1' or EW_RDY = '1') and AR_IN_USE = '0' then -- ADH. + NEXT_FETCH_STATE <= INIT_EXEC_WB; + else + NEXT_FETCH_STATE <= FETCH_DISPL; + end if; + end case; + when FETCH_EXWORD_1 => + -- Be aware that the An registers which will be addressed by EXWORD_1 and are used for several addressing modes + -- are valid right after this state (because every address register manipulation requires no more than two clock cycles). + if EW_ACK = '1' or EW_RDY = '1' then -- Null displacement. + case OP is + when ADD | CMP | SUB | AND_B | EOR | OR_B => + if (BIW_1(15) = '0' and AR_IN_USE = '0' and DR_IN_USE = '0') or (BIW_1(15) = '1' and AR_IN_USE = '0') then -- ADH. + NEXT_FETCH_STATE <= CALC_AEFF; + else + NEXT_FETCH_STATE <= FETCH_EXWORD_1; + end if; + when ADDA | BCHG | BCLR | BSET | BTST | CHK | CMPA | DIVS | DIVU | MULS | MULU | MOVE | MOVEA | MOVE_TO_CCR | MOVE_TO_SR | SUBA => + if OP = MOVE and PHASE2 = true and BIW_1(15) = '0' and AR_IN_USE = '0' and DR_IN_USE = '0' then -- ADH. + NEXT_FETCH_STATE <= INIT_EXEC_WB; + elsif OP = MOVE and PHASE2 = true and BIW_1(15) = '1' and AR_IN_USE = '0' then -- ADH. + NEXT_FETCH_STATE <= INIT_EXEC_WB; + elsif (BIW_1(15) = '0' and AR_IN_USE = '0' and DR_IN_USE = '0') or (BIW_1(15) = '1' and AR_IN_USE = '0') then -- ADH. + NEXT_FETCH_STATE <= CALC_AEFF; + else + NEXT_FETCH_STATE <= FETCH_EXWORD_1; + end if; + when MOVES => + if (BIW_1(15) = '0' and AR_IN_USE = '0' and DR_IN_USE = '0') or (BIW_1(15) = '1' and AR_IN_USE = '0') then -- ADH. + if BIW_1(11) = '0' then + NEXT_FETCH_STATE <= CALC_AEFF; + else + NEXT_FETCH_STATE <= INIT_EXEC_WB; + end if; + else + NEXT_FETCH_STATE <= FETCH_EXWORD_1; + end if; + when ADDI | ADDQ | ANDI | CMPI | EORI | NBCD | NEG | NEGX | NOT_B | ORI | SUBI | SUBQ | TST | TAS | ASL | ASR | LSL | LSR | ROTL | ROTR | ROXL | ROXR => + if (BIW_1(15) = '0' and AR_IN_USE = '0' and DR_IN_USE = '0') or (BIW_1(15) = '1' and AR_IN_USE = '0') then -- ADH. + NEXT_FETCH_STATE <= CALC_AEFF; + else + NEXT_FETCH_STATE <= FETCH_EXWORD_1; + end if; + when LEA | PEA => + if (BIW_1(15) = '0' and AR_IN_USE = '0' and DR_IN_USE = '0') or (BIW_1(15) = '1' and AR_IN_USE = '0') then -- ADH. + NEXT_FETCH_STATE <= SWITCH_STATE; + else + NEXT_FETCH_STATE <= FETCH_EXWORD_1; + end if; + when others => -- CLR, JMP, JSR, MOVE_FROM_CCR, MOVE_FROM_SR, MOVEM, Scc. + if (BIW_1(15) = '0' and AR_IN_USE = '0' and DR_IN_USE = '0') or (BIW_1(15) = '1' and AR_IN_USE = '0') then -- ADH. + NEXT_FETCH_STATE <= INIT_EXEC_WB; + else + NEXT_FETCH_STATE <= FETCH_EXWORD_1; + end if; + end case; + else + NEXT_FETCH_STATE <= FETCH_EXWORD_1; + end if; + when FETCH_ABS_HI => + if EW_ACK = '1' then + NEXT_FETCH_STATE <= FETCH_ABS_LO; + else + NEXT_FETCH_STATE <= FETCH_ABS_HI; + end if; + when FETCH_ABS_LO => + if EW_ACK = '1' then + case OP is + when CLR | JMP | JSR | MOVE_FROM_CCR | MOVE_FROM_SR | MOVEM | Scc => + NEXT_FETCH_STATE <= INIT_EXEC_WB; + when LEA | PEA => + NEXT_FETCH_STATE <= SWITCH_STATE; + when MOVE => + if PHASE2 = false then + NEXT_FETCH_STATE <= CALC_AEFF; + else + NEXT_FETCH_STATE <= INIT_EXEC_WB; + end if; + when MOVES => + if BIW_1(11) = '0' then + NEXT_FETCH_STATE <= CALC_AEFF; + else + NEXT_FETCH_STATE <= INIT_EXEC_WB; + end if; + when others => + NEXT_FETCH_STATE <= CALC_AEFF; + end case; + else + NEXT_FETCH_STATE <= FETCH_ABS_LO; + end if; + when FETCH_IDATA_B2 => + if EW_ACK = '1' then + NEXT_FETCH_STATE <= FETCH_IDATA_B1; + else + NEXT_FETCH_STATE <= FETCH_IDATA_B2; + end if; + when FETCH_IDATA_B1 => + if EW_ACK = '1' or EW_RDY = '1' then + case OP is -- ADH. + when ADD | SUB | AND_B | OR_B | BTST | DIVS | DIVU | MULS | MULU | CHK | MOVE => + NEXT_FETCH_STATE <= SWITCH_STATE; + when ADDA | CMPA | SUBA | MOVEA => + NEXT_FETCH_STATE <= SWITCH_STATE; + when others => + if DR_IN_USE = '1' then -- ADH. + NEXT_FETCH_STATE <= FETCH_IDATA_B1; + else + NEXT_FETCH_STATE <= INIT_EXEC_WB; + end if; + end case; + else + NEXT_FETCH_STATE <= FETCH_IDATA_B1; + end if; + when CALC_AEFF => + NEXT_FETCH_STATE <= FETCH_OPERAND; -- One CLK calculation delay. + when FETCH_OPERAND => + if RD_RDY = '1' then + case OP is + when ABCD | ADDX | SBCD | SUBX => + if PHASE2 = false then + NEXT_FETCH_STATE <= CALC_AEFF; + else + NEXT_FETCH_STATE <= INIT_EXEC_WB; + end if; + when ADD | CMP | CHK | SUB | AND_B | EOR | OR_B | BCHG | BCLR | BSET | BTST | DIVS | DIVU | MULS | MULU => + if DR_IN_USE = '1' then + NEXT_FETCH_STATE <= SWITCH_STATE; + else + NEXT_FETCH_STATE <= INIT_EXEC_WB; + end if; + when ADDA | CMPA | SUBA => + if BIW_0(11 downto 9) = BIW_0(2 downto 0) and ADR_MODE_I = "011" then + NEXT_FETCH_STATE <= SWITCH_STATE; -- Postincrement (Ax)+, AX; wait before loading the ALU. + else + NEXT_FETCH_STATE <= INIT_EXEC_WB; + end if; + when MOVE => + if BIW_0(8 downto 6) = "100" and ADR_MODE_I = "011" then -- (An)+,-(An). + NEXT_FETCH_STATE <= SWITCH_STATE; + else + NEXT_FETCH_STATE <= INIT_EXEC_WB; + end if; + when others => + NEXT_FETCH_STATE <= INIT_EXEC_WB; + end case; + else + NEXT_FETCH_STATE <= FETCH_OPERAND; + end if; + when SWITCH_STATE => -- This state is used individually by several operations. + case OP is + when ADDA | CMPA | SUBA | MOVEA => -- Address register operations. + if AR_IN_USE = '0' then + NEXT_FETCH_STATE <= INIT_EXEC_WB; + else + NEXT_FETCH_STATE <= SWITCH_STATE; + end if; + when LEA | LINK | MOVE => + -- LEA: calculate effective address (1 clock cycle) load it in INIT_EXEC_WB. + -- LINK: used to load the decremented stack pointer. + -- MOVE: Used for (An)+,-(An). address mode. + NEXT_FETCH_STATE <= INIT_EXEC_WB; + when UNLK => -- SP is updated here. + NEXT_FETCH_STATE <= CALC_AEFF; + when MOVEM => -- MOVEM requires 1 CLK cycle for address calculation. + if MOVEM_COND = false then + NEXT_FETCH_STATE <= INIT_EXEC_WB; -- Cancel bus access. + else + NEXT_FETCH_STATE <= CALC_AEFF; + end if; + when MOVEP => -- Register select and displacement update. + if DR_IN_USE = '0' and BIW_0(7 downto 6) < "10" then + NEXT_FETCH_STATE <= CALC_AEFF; + elsif DR_IN_USE = '0' and ALU_BSY = '0' then -- ASH. + NEXT_FETCH_STATE <= INIT_EXEC_WB; -- Register to memory. + else + NEXT_FETCH_STATE <= SWITCH_STATE; + end if; + when PEA => + -- PEA requires two clock cycles here for effective adress calculation because it + -- is loaded early. The first clock cycle the address becomes valid and after the + -- second the address is loaded to the ALU for writing on the stack. + if PHASE2 = false then + NEXT_FETCH_STATE <= SWITCH_STATE; + else + NEXT_FETCH_STATE <= INIT_EXEC_WB; + end if; + when others => -- Data register operations. + if DR_IN_USE = '0' then + NEXT_FETCH_STATE <= INIT_EXEC_WB; + else + NEXT_FETCH_STATE <= SWITCH_STATE; + end if; + end case; + when INIT_EXEC_WB => + case OP is + when ANDI_TO_SR | EORI_TO_SR | MOVE_TO_SR | ORI_TO_SR => + if ALU_BSY = '0' and BRANCH_ATN = '1' then + NEXT_FETCH_STATE <= SLEEP; -- Wait for new processor context. + elsif ALU_BSY = '0' then + NEXT_FETCH_STATE <= START_OP; -- Proceed normally. + else + NEXT_FETCH_STATE <= INIT_EXEC_WB; + end if; + when Bcc | CHK | DBcc | JMP | TRAPV => + if ALU_BSY = '0' then + NEXT_FETCH_STATE <= SLEEP; + else + NEXT_FETCH_STATE <= INIT_EXEC_WB; + end if; + when JSR | MOVEC | TAS => + -- TAS provides a RMC operation so have to sleep a little bit ;-) + if ALU_BSY = '0' then + NEXT_FETCH_STATE <= SLEEP; + else + NEXT_FETCH_STATE <= INIT_EXEC_WB; + end if; + when BRA | BSR | RTD | RTS => + if ALU_BSY = '0' then + NEXT_FETCH_STATE <= START_OP; + else + NEXT_FETCH_STATE <= INIT_EXEC_WB; + end if; + when CMPM => + if ALU_BSY = '0' and PHASE2 = false then + NEXT_FETCH_STATE <= FETCH_OPERAND; -- Second compare required? + elsif ALU_BSY = '0' then -- ASH. + NEXT_FETCH_STATE <= START_OP; + else + NEXT_FETCH_STATE <= INIT_EXEC_WB; + end if; + when MOVE_USP => + if ALU_BSY = '0' and BIW_0(3) = '0' then -- An to USP. + NEXT_FETCH_STATE <= SLEEP; + elsif ALU_BSY = '0' then + NEXT_FETCH_STATE <= START_OP; -- USP to An. + else + NEXT_FETCH_STATE <= INIT_EXEC_WB; + end if; + when MOVE => + if ALU_BSY = '0' and PHASE2 = false then -- Load the Operand into the ALU here. + case BIW_0(8 downto 6) is -- Destination operand. + when "101" => + NEXT_FETCH_STATE <= FETCH_DISPL; + when "110" => + NEXT_FETCH_STATE <= FETCH_EXWORD_1; + when "111" => + if BIW_0(11 downto 9) = "000" then + NEXT_FETCH_STATE <= FETCH_ABS_LO; + else + NEXT_FETCH_STATE <= FETCH_ABS_HI; + end if; + when others => -- No destination address calculation required. + NEXT_FETCH_STATE <= START_OP; + end case; + elsif PHASE2 = true then -- ALU is not required at this point. + NEXT_FETCH_STATE <= START_OP; + else + NEXT_FETCH_STATE <= INIT_EXEC_WB; + end if; + when MOVEM => + if ALU_BSY = '0' and BIW_0(10) = '0' and ADR_MODE_I = "100" and MOVEM_PNTR = x"0" then -- -(An), register to memory. + NEXT_FETCH_STATE <= SLEEP; -- Data completely transfered to the ALU. + elsif ALU_BSY = '0' and BIW_0(10) = '0' and ADR_MODE_I /= "100" and MOVEM_PNTR = x"F" then -- Register to memory + NEXT_FETCH_STATE <= SLEEP; -- Data completely transfered to the ALU. + elsif ALU_BSY = '0' and BIW_0(10) = '1' and MOVEM_PNTR = x"F" then -- Memory to register. + NEXT_FETCH_STATE <= SLEEP; -- Data completely transfered to the ALU. + elsif ALU_BSY = '0' and BIW_0(10) = '1' then -- Memory to register. + NEXT_FETCH_STATE <= SWITCH_STATE; + else + NEXT_FETCH_STATE <= INIT_EXEC_WB; -- Register to memory. + end if; + when MOVEP => + if ALU_BSY = '0' and MOVEP_PNTR_I = 0 then + NEXT_FETCH_STATE <= START_OP; -- Ready. + elsif ALU_BSY = '0' and BIW_0(7 downto 6) < "10" then + NEXT_FETCH_STATE <= CALC_AEFF; -- Memory to register. + else + NEXT_FETCH_STATE <= INIT_EXEC_WB; -- Register to memory. + end if; + when NOP => + if ALU_BSY = '1' then -- ASH. + NEXT_FETCH_STATE <= INIT_EXEC_WB; -- Wait for all pending bus cycles to be completed. + else + NEXT_FETCH_STATE <= START_OP; + end if; + when RTR => + if ALU_BSY = '0' and PHASE2 = false then + NEXT_FETCH_STATE <= CALC_AEFF; + elsif ALU_BSY = '0' and PHASE2 = true then + NEXT_FETCH_STATE <= START_OP; + else + NEXT_FETCH_STATE <= INIT_EXEC_WB; + end if; + when STOP => + if ALU_BSY = '0' then -- ASH. + NEXT_FETCH_STATE <= SLEEP; + else + NEXT_FETCH_STATE <= INIT_EXEC_WB; + end if; + when UNLK => + if ALU_BSY = '0' and AR_IN_USE = '0' then -- ADH, ASH. + NEXT_FETCH_STATE <= START_OP; + else + NEXT_FETCH_STATE <= INIT_EXEC_WB; + end if; + when others => + if ALU_BSY = '0' then -- ASH. + NEXT_FETCH_STATE <= START_OP; + else + NEXT_FETCH_STATE <= INIT_EXEC_WB; -- ASH. + end if; + end case; + when SLEEP => + case OP is + when ANDI_TO_SR | EORI_TO_SR | MOVE_TO_SR | MOVEM | ORI_TO_SR | TAS => + -- MOVEM: wait until last register is written to avoid data hazards + -- because the ADR_IN_USE, AR_IN__USE and DR_IN_USE does not + -- work for MOVEM (several registers in use). + -- TAS is a read modify write instruction. + -- _TO_SR instructions wait for the change of the SBIT + -- and so for a new processor context. + if NEXT_EXEC_WB_STATE = IDLE then + NEXT_FETCH_STATE <= START_OP; + else + NEXT_FETCH_STATE <= SLEEP; + end if; + when JSR => + if PHASE2 = false then + NEXT_FETCH_STATE <= SLEEP; -- Wait for address calculation. + else + NEXT_FETCH_STATE <= START_OP; + end if; + when MOVE_USP | MOVEC => + -- MOVE_USP: wait for writeback not to conflict with AR_DEC in START_OP. + if NEXT_EXEC_WB_STATE = IDLE then + NEXT_FETCH_STATE <= START_OP; + else + NEXT_FETCH_STATE <= SLEEP; -- Wait for new processor context. + end if; + when DBcc => + -- DBcc: evaluate conditions. + if NEXT_EXEC_WB_STATE = IDLE then + NEXT_FETCH_STATE <= START_OP; + else + NEXT_FETCH_STATE <= SLEEP; + end if; + when STOP => + if TRACE_EN = '1' then + NEXT_FETCH_STATE <= START_OP; -- Do not perform a stop while tracing. + elsif EXH_REQ = '1' then + NEXT_FETCH_STATE <= START_OP; -- Wait on interrupt. + else + NEXT_FETCH_STATE <= SLEEP; + end if; + when others => -- Bcc, CHK, JMP, TRAPV. + -- Bcc: evaluate conditions. + -- CHK: use SWITCH_STATE for TRAP evaluation. + -- JMP: wait for address calculation. + -- TRAPV: check conditions. + NEXT_FETCH_STATE <= START_OP; + end case; + end case; + end process FETCH_DEC; + + EXEC_WB_DEC: process(ALU_COND, ALU_INIT_I, ALU_REQ, BIW_0_WB, BIW_1_WB, EXEC_WB_STATE, MOVEM_INH_WR, OP_WB_I, PHASE2, WR_RDY) + begin + case EXEC_WB_STATE is + when IDLE => -- OP is still valid here; OP_WB_I one clock later. + if ALU_INIT_I = '1' then + NEXT_EXEC_WB_STATE <= EXECUTE; + else + NEXT_EXEC_WB_STATE <= IDLE; + end if; + when EXECUTE => + if ALU_REQ = '1' then + case OP_WB_I is + when ABCD | SBCD | ADDX | SUBX => + if BIW_0_WB(3) = '0' then -- Register to register. + NEXT_EXEC_WB_STATE <= WRITEBACK; + else -- Memory to memory. + NEXT_EXEC_WB_STATE <= WRITE_DEST; + end if; + when ADD | SUB | AND_B | OR_B => + if BIW_0_WB(8) = '0' then + NEXT_EXEC_WB_STATE <= WRITEBACK; -- Destination is register. + else + NEXT_EXEC_WB_STATE <= WRITE_DEST; -- Destination is in memory. + end if; + when ADDA | SUBA | ANDI_TO_SR | DIVS | DIVU | EORI_TO_SR | EXG | EXT | LEA | MOVE_TO_CCR | + MOVE_TO_SR | MOVE_USP | MOVEA | MOVEC | MOVEQ | MULS | MULU | ORI_TO_SR | STOP | SWAP | UNLK => + NEXT_EXEC_WB_STATE <= WRITEBACK; + when ADDI | ADDQ | ANDI | BCHG | BCLR | BSET | CLR | EOR | EORI | + MOVE_FROM_CCR | MOVE_FROM_SR | NBCD | NEG | NEGX | NOT_B | ORI | Scc | SUBI | SUBQ | TAS => + if BIW_0_WB(5 downto 3) = "000" then + NEXT_EXEC_WB_STATE <= WRITEBACK; -- Destination is a data register. + elsif BIW_0_WB(5 downto 3) = "001" then -- Valid for ADDQ and SUBQ. + NEXT_EXEC_WB_STATE <= WRITEBACK; -- Destination is an address register. + else + NEXT_EXEC_WB_STATE <= WRITE_DEST; -- Destination is in memory. + end if; + when ASL | ASR | LSL | LSR | ROTL | ROTR | ROXL | ROXR => + if BIW_0_WB(7 downto 6) /= "11" then + NEXT_EXEC_WB_STATE <= WRITEBACK; -- Register shifts. + else + NEXT_EXEC_WB_STATE <= WRITE_DEST; -- Memory shifts. + end if; + when DBcc => + if ALU_COND = true then + NEXT_EXEC_WB_STATE <= IDLE; + else + NEXT_EXEC_WB_STATE <= WRITEBACK; + end if; + when MOVE => + if BIW_0_WB(8 downto 6) = "000" then + NEXT_EXEC_WB_STATE <= WRITEBACK; -- Destination is register. + elsif PHASE2 = false then + NEXT_EXEC_WB_STATE <= WRITE_DEST; -- Destination is in memory. + else + NEXT_EXEC_WB_STATE <= EXECUTE; -- Wait for PHASE2 address calculation. + end if; + when BSR | JSR | LINK | PEA => + NEXT_EXEC_WB_STATE <= WRITE_DEST; + when MOVEM => + if OP_WB_I = MOVEM and MOVEM_INH_WR = true then + NEXT_EXEC_WB_STATE <= IDLE; -- Discard the write cycle. + elsif BIW_0_WB(10) = '1' then + NEXT_EXEC_WB_STATE <= WRITEBACK; -- Destination is register. + else + NEXT_EXEC_WB_STATE <= WRITE_DEST; -- Destination is in memory. + end if; + when MOVEP => + if BIW_0_WB(7 downto 6) < "10" then + NEXT_EXEC_WB_STATE <= WRITEBACK; -- Memory to register. + else + NEXT_EXEC_WB_STATE <= WRITE_DEST; -- Register to memory. + end if; + when MOVES => + if BIW_1_WB(11) = '0' then + NEXT_EXEC_WB_STATE <= WRITEBACK; -- Destination is register. + else + NEXT_EXEC_WB_STATE <= WRITE_DEST; -- Destination is in memory. + end if; + -- Default is for: + -- ANDI_TO_CCR, Bcc, CHK, CMP, CMPA, CMPI, CMPM + -- EORI_TO_CCR, ORI_TO_CCR, RTR, TRAPV, TST. + when others => + NEXT_EXEC_WB_STATE <= IDLE; + end case; + else + NEXT_EXEC_WB_STATE <= EXECUTE; + end if; + when WRITEBACK => + NEXT_EXEC_WB_STATE <= IDLE; + when WRITE_DEST => + if WR_RDY = '1' then + NEXT_EXEC_WB_STATE <= IDLE; + else + NEXT_EXEC_WB_STATE <= WRITE_DEST; + end if; + end case; + end process EXEC_WB_DEC; +end BEHAVIOUR; diff --git a/common/CPU/68K10/wf68k10_data_registers.vhd b/common/CPU/68K10/wf68k10_data_registers.vhd new file mode 100644 index 00000000..0825ed7b --- /dev/null +++ b/common/CPU/68K10/wf68k10_data_registers.vhd @@ -0,0 +1,137 @@ +------------------------------------------------------------------------ +---- ---- +---- WF68K10 IP Core: Data register logic. ---- +---- ---- +---- Description: ---- +---- These are the eight data registers. The logic provides two ---- +---- read and two write ports providing simultaneos access. For ---- +---- more information refer to the MC68010 User' Manual. ---- +---- ---- +---- Author(s): ---- +---- - Wolfgang Foerster, wf@experiment-s.de; wf@inventronik.de ---- +---- ---- +------------------------------------------------------------------------ +---- ---- +---- Copyright 2014-2019 Wolfgang Foerster Inventronik GmbH. ---- +---- ---- +---- This documentation describes Open Hardware and is licensed ---- +---- under the CERN OHL v. 1.2. You may redistribute and modify ---- +---- this documentation under the terms of the CERN OHL v.1.2. ---- +---- (http://ohwr.org/cernohl). This documentation is distributed ---- +---- WITHOUT ANY EXPRESS OR IMPLIED WARRANTY, INCLUDING OF ---- +---- MERCHANTABILITY, SATISFACTORY QUALITY AND FITNESS FOR A ---- +---- PARTICULAR PURPOSE. Please see the CERN OHL v.1.2 for ---- +---- applicable conditions ---- +---- ---- +------------------------------------------------------------------------ +-- +-- Revision History +-- +-- Revision 2K14B 20141201 WF +-- Initial Release. +-- + +library work; +use work.WF68K10_PKG.all; + +library ieee; +use ieee.std_logic_1164.all; +use ieee.std_logic_unsigned.all; + +entity WF68K10_DATA_REGISTERS is + port ( + CLK : in std_logic; + RESET : in bit; + + -- Data lines: + DR_IN_1 : in std_logic_vector(31 downto 0); + DR_IN_2 : in std_logic_vector(31 downto 0); + DR_OUT_1 : out std_logic_vector(31 downto 0); + DR_OUT_2 : out std_logic_vector(31 downto 0); + + -- Registers controls: + DR_SEL_WR_1 : in std_logic_vector(2 downto 0); + DR_SEL_WR_2 : in std_logic_vector(2 downto 0); + DR_SEL_RD_1 : in std_logic_vector(2 downto 0); + DR_SEL_RD_2 : in std_logic_vector(2 downto 0); + DR_WR_1 : in bit; + DR_WR_2 : in bit; + DR_MARK_USED : in bit; + USE_DPAIR : in boolean; + DR_IN_USE : out bit; + UNMARK : in bit; + + OP_SIZE : in OP_SIZETYPE + ); +end entity WF68K10_DATA_REGISTERS; + +architecture BEHAVIOUR of WF68K10_DATA_REGISTERS is +type DR_TYPE is array(0 to 7) of std_logic_vector(31 downto 0); +signal DR : DR_TYPE; -- Data registers D0 to D7. +signal DR_PNTR_WR_1 : integer range 0 to 7; +signal DR_PNTR_WR_2 : integer range 0 to 7; +signal DR_PNTR_RD_1 : integer range 0 to 7; +signal DR_PNTR_RD_2 : integer range 0 to 7; +signal DR_SEL_WR_I1 : std_logic_vector(2 downto 0); +signal DR_SEL_WR_I2 : std_logic_vector(2 downto 0); +signal DR_USED_1 : std_logic_vector(3 downto 0); +signal DR_USED_2 : std_logic_vector(3 downto 0); +begin + INBUFFER: process + begin + wait until CLK = '1' and CLK' event; + if DR_MARK_USED = '1' then + DR_SEL_WR_I1 <= DR_SEL_WR_1; + DR_SEL_WR_I2 <= DR_SEL_WR_2; + end if; + end process INBUFFER; + + DR_PNTR_WR_1 <= conv_integer(DR_SEL_WR_I1); + DR_PNTR_WR_2 <= conv_integer(DR_SEL_WR_I2); + DR_PNTR_RD_1 <= conv_integer(DR_SEL_RD_1); + DR_PNTR_RD_2 <= conv_integer(DR_SEL_RD_2); + + P_IN_USE: process + begin + wait until CLK = '1' and CLK' event; + if RESET = '1' or UNMARK = '1' then + DR_USED_1(3) <= '0'; + DR_USED_2(3) <= '0'; + elsif DR_MARK_USED = '1' then + DR_USED_1 <= '1' & DR_SEL_WR_1; + if USE_DPAIR = true then + DR_USED_2 <= '1' & DR_SEL_WR_2; + end if; + end if; + end process P_IN_USE; + + DR_IN_USE <= '1' when DR_USED_1(3) = '1' and DR_USED_1(2 downto 0) = DR_SEL_RD_1 else + '1' when DR_USED_1(3) = '1' and DR_USED_1(2 downto 0) = DR_SEL_RD_2 else + '1' when DR_USED_2(3) = '1' and DR_USED_2(2 downto 0) = DR_SEL_RD_1 else + '1' when DR_USED_2(3) = '1' and DR_USED_2(2 downto 0) = DR_SEL_RD_2 else '0'; + + DR_OUT_1 <= DR(DR_PNTR_RD_1); + DR_OUT_2 <= DR(DR_PNTR_RD_2); + + REGISTERS: process + begin + wait until CLK = '1' and CLK' event; + if RESET = '1' then + DR <= (others => (others => '0')); + end if; + if DR_WR_1 = '1' then + case OP_SIZE is + when LONG => DR(DR_PNTR_WR_1) <= DR_IN_1; + when WORD => DR(DR_PNTR_WR_1)(15 downto 0) <= DR_IN_1(15 downto 0); + when Byte => DR(DR_PNTR_WR_1)(7 downto 0) <= DR_IN_1(7 downto 0); + end case; + end if; + if DR_WR_2 = '1' then + case OP_SIZE is + when LONG => DR(DR_PNTR_WR_2) <= DR_IN_2; + when WORD => DR(DR_PNTR_WR_2)(15 downto 0) <= DR_IN_2(15 downto 0); + when Byte => DR(DR_PNTR_WR_2)(7 downto 0) <= DR_IN_2(7 downto 0); + end case; + end if; + end process REGISTERS; +end BEHAVIOUR; diff --git a/common/CPU/68K10/wf68k10_exception_handler.vhd b/common/CPU/68K10/wf68k10_exception_handler.vhd new file mode 100644 index 00000000..25d5f913 --- /dev/null +++ b/common/CPU/68K10/wf68k10_exception_handler.vhd @@ -0,0 +1,818 @@ +------------------------------------------------------------------------ +---- ---- +---- WF68K10 IP Core: this is the exception handler module. ---- +---- ---- +---- Description: ---- +---- This is the exception handler which is responsible for the ---- +---- interrupt management of the external interrupt and internal ---- +---- exception processing. It manages auto-vectored interrupt ---- +---- cycles, priority resolving and correct vector numbers. ---- +---- For further information concerning the functionality of this ---- +---- module refer to the MC68010 User's Manual and to the MC68K ---- +---- family Programmer's Reference Manual. ---- +---- ---- +---- ---- +---- Author(s): ---- +---- - Wolfgang Foerster, wf@experiment-s.de; wf@inventronik.de ---- +---- ---- +------------------------------------------------------------------------ +---- ---- +---- Copyright © 2014-2019 Wolfgang Foerster Inventronik GmbH. ---- +---- ---- +---- This documentation describes Open Hardware and is licensed ---- +---- under the CERN OHL v. 1.2. You may redistribute and modify ---- +---- this documentation under the terms of the CERN OHL v.1.2. ---- +---- (http://ohwr.org/cernohl). This documentation is distributed ---- +---- WITHOUT ANY EXPRESS OR IMPLIED WARRANTY, INCLUDING OF ---- +---- MERCHANTABILITY, SATISFACTORY QUALITY AND FITNESS FOR A ---- +---- PARTICULAR PURPOSE. Please see the CERN OHL v.1.2 for ---- +---- applicable conditions ---- +---- ---- +------------------------------------------------------------------------ +-- +-- Revision History +-- +-- Revision 2K14B 20141201 WF +-- Initial Release. +-- Revision 2K16A 20141201 WF +-- Fixed a bug in PC_LOAD. +-- Revision 2K18A (unreleased) WF +-- Removed REST_BIW_0. +-- Removed FC_OUT. +-- Removed ADR_CPY. +-- Removed PC_OFFSET. +-- Fixed the vector calculation of INT vectors. +-- Fixed faulty modeling in IRQ_FILTER. +-- Implemented the AVEC_FILTER to better meet bus timings. +-- STACK_POS_VAR is initialized earlier to be valid for early asserted ISP_DEC. +-- Update the IRQ mask only for RESET and interrupts. +-- External interrupts are postponed if any system controllers are in initialize operation status. +-- RTE now loads the address offset correctly when entering the handler. +-- Rearranged address error handling. +-- Revision 2K19B 20191224 WF +-- Introduced signal synchronization in the P_D process to avoid malfunction by hazards. +-- The processor VERSION is now 32 bit wide. +-- + +library work; +use work.WF68K10_PKG.all; + +library ieee; +use ieee.std_logic_1164.all; +use ieee.std_logic_unsigned.all; + +entity WF68K10_EXCEPTION_HANDLER is + generic(VERSION : std_logic_vector(31 downto 0) := x"20191224"); + port( + CLK : in std_logic; + RESET : in bit; + K6800n : in std_logic; + + BUSY_MAIN : in bit; + BUSY_OPD : in bit; + + EXH_REQ : out bit; + BUSY_EXH : out bit; + + ADR_IN : in std_logic_vector(31 downto 0); + ADR_OFFSET : out std_logic_vector(31 downto 0); + CPU_SPACE : out bit; + + DATA_0 : in std_logic; + DATA_RD : out bit; + DATA_WR : out bit; + DATA_IN : in std_logic_vector(31 downto 0); + + OP_SIZE : out OP_SIZETYPE; -- Operand size. + DATA_RDY : in bit; + DATA_VALID : in std_logic; + + OPCODE_RDY : in bit; -- OPCODE is available. + + STATUS_REG_IN : in std_logic_vector(15 downto 0); + SR_CPY : out std_logic_vector(15 downto 0); + SR_INIT : out bit; + SR_WR : out bit; + + ISP_DEC : out bit; + ISP_LOAD : out bit; + PC_INC : out bit; + PC_LOAD : out bit; + PC_RESTORE : out bit; + + STACK_FORMAT : out std_logic_vector(3 downto 0); + STACK_POS : out integer range 0 to 31; + + SP_ADD_DISPL : out bit; + DISPLACEMENT : out std_logic_vector(7 downto 0); + + IPIPE_FILL : out bit; + IPIPE_FLUSH : out bit; + RESTORE_ISP_PC : out bit; + + HALT_OUTn : out std_logic; + + -- Interrupt controls: + INT_TRIG : in bit; + IRQ_IN : in std_logic_vector(2 downto 0); + IRQ_PEND : out std_logic_vector(2 downto 0); + AVECn : in std_logic; + IPENDn : out bit; + IVECT_OFFS : out std_logic_vector(9 downto 0); -- Interrupt vector offset. + + -- Trap signals: + TRAP_AERR : in bit; + TRAP_BERR : in bit; + TRAP_CHK : in bit; + TRAP_DIVZERO : in bit; + TRAP_ILLEGAL : in bit; + TRAP_CODE_OPC : in TRAPTYPE_OPC; -- T_1010, T_1111, T_ILLEGAL, T_TRAP, T_PRIV. + TRAP_VECTOR : in std_logic_vector(3 downto 0); + TRAP_V : in bit; + EX_TRACE_IN : in bit; + VBR_WR : in bit; + VBR : out std_logic_vector(31 downto 0) + ); +end entity WF68K10_EXCEPTION_HANDLER; + +architecture BEHAVIOR of WF68K10_EXCEPTION_HANDLER is +type EX_STATES is (IDLE, BUILD_STACK, CALC_VECT_No, EXAMINE_VERSION, GET_VECTOR, HALTED, INIT, READ_BOTTOM, + REFILL_PIPE, RESTORE_ISP, RESTORE_PC, RESTORE_STATUS, UPDATE_PC, VALIDATE_FRAME); + +type EXCEPTIONS is (EX_NONE, EX_1010, EX_1111, EX_AERR, EX_BERR, EX_CHK, EX_DIVZERO, EX_FORMAT, EX_ILLEGAL, + EX_INT, EX_PRIV, EX_RESET, EX_RTE, EX_TRACE, EX_TRAP, EX_TRAPV); + +signal ACCESS_ERR : bit; +signal AVEC : bit; +signal DATA_RD_I : bit; +signal DATA_WR_I : bit; +signal DOUBLE_BUSFLT : bit; +signal EXCEPTION : EXCEPTIONS; -- Currently executed exception. +signal EX_STATE : EX_STATES := IDLE; +signal NEXT_EX_STATE : EX_STATES; +signal EX_P_1010 : bit; -- ..._P are the pending exceptions. +signal EX_P_1111 : bit; +signal EX_P_AERR : bit; +signal EX_P_BERR : bit; +signal EX_P_CHK : bit; +signal EX_P_DIVZERO : bit; +signal EX_P_FORMAT : bit; +signal EX_P_ILLEGAL : bit; +signal EX_P_INT : bit; +signal EX_P_RESET : bit; +signal EX_P_RTE : bit; +signal EX_P_PRIV : bit; +signal EX_P_TRACE : bit; +signal EX_P_TRAP : bit; +signal EX_P_TRAPV : bit; +signal INT_VECT : std_logic_vector(31 downto 0); -- Interrupt vector. +signal IRQ : std_logic_vector(2 downto 0); +signal IRQ_PEND_I : std_logic_vector(2 downto 0); +signal PIPE_CNT : std_logic_vector(1 downto 0); +signal PIPE_FULL : boolean; +signal STACK_CNT : integer range 0 to 46; +signal STACK_FORMAT_I : std_logic_vector(3 downto 0); +signal SYS_INIT : bit; +begin + + BUSY_EXH <= '1' when EX_STATE /= IDLE else '0'; + + IRQ_FILTER : process + -- This logic is intended to avoid spurious IRQs due + -- to setup / hold violations (IRQ_IN may operate in + -- a different clock domain). + variable IRQ_TMP_1 : std_logic_vector(2 downto 0) := "000"; + variable IRQ_TMP_2 : std_logic_vector(2 downto 0) := "000"; + begin + wait until CLK = '0' and CLK' event; + if IRQ_TMP_1 = IRQ_TMP_2 then + IRQ <= IRQ_TMP_2; + end if; + IRQ_TMP_2 := IRQ_TMP_1; + IRQ_TMP_1 := IRQ_IN; + end process IRQ_FILTER; + + AVEC_FILTER : process + -- We need a flip flop for the incoming AVECn to meet + -- the timing requirements of the bus interface. AVECn + -- is asserted (low active) before DATA_RDY of the + -- bus interface. AVEC stays asserted until DATA_RDY. + begin + wait until CLK = '1' and CLK' event; + if AVECn = '0' then + AVEC <= '1'; + elsif DATA_RDY = '1' or RESET = '1' then + AVEC <= '0'; + end if; + end process AVEC_FILTER; + + PENDING: process + -- The exceptions which occurs are stored in this pending register until the + -- interrupt handler handled the respective exception. + -- The TRAP_PRIV, TRAP_1010, TRAP_1111, TRAP_ILLEGAL, TRAP_OP and TRAP_V may be a strobe + -- of 1 clock period. All others must be strobes of 1 clock period.. + variable INT7_TRIG : boolean; + variable INT_VAR : std_logic_vector(2 downto 0); + variable SR_VAR : std_logic_vector(2 downto 0); + begin + wait until CLK = '1' and CLK' event; + if RESET = '1' then + EX_P_RESET <= '1'; + elsif EX_STATE = RESTORE_PC and DATA_RDY = '1' and EXCEPTION = EX_RESET then + EX_P_RESET <= '0'; + end if; + -- + if TRAP_BERR = '1' then + EX_P_BERR <= '1'; + elsif EX_STATE /= IDLE and DATA_RDY = '1' and DATA_VALID = '0' then + EX_P_BERR <= '1'; + elsif EX_STATE = INIT and EXCEPTION = EX_BERR then + EX_P_BERR <= '0'; -- Reset in the beginning to enable retriggering. + elsif SYS_INIT = '1' then + EX_P_BERR <= '0'; + end if; + -- + if TRAP_AERR = '1' then + EX_P_AERR <= '1'; + elsif EX_STATE = BUILD_STACK and EXCEPTION = EX_AERR then + EX_P_AERR <= '0'; + elsif SYS_INIT = '1' then + EX_P_AERR <= '0'; + end if; + -- + if EX_TRACE_IN = '1' then + EX_P_TRACE <= '1'; + elsif EX_STATE = BUILD_STACK and EXCEPTION = EX_TRACE then + EX_P_TRACE <= '0'; + elsif SYS_INIT = '1' then + EX_P_TRACE <= '0'; + end if; + -- + if IRQ = "111" and SR_VAR = "111" and STATUS_REG_IN(10 downto 8) /= "111" then + INT7_TRIG := true; -- Trigger by lowering the mask from 7 to any value. + elsif IRQ = "111" and INT_VAR < "111" then + INT7_TRIG := true; -- Trigger when level 7 is entered. + else + INT7_TRIG := false; + end if; + -- + SR_VAR := STATUS_REG_IN(10 downto 8); -- Update after use! + INT_VAR := IRQ; -- Update after use! + -- + if SYS_INIT = '1' then -- Reset when disabling the interrupts. + EX_P_INT <= '0'; + IRQ_PEND_I <= "111"; -- This is required for system startup. + elsif EX_STATE = GET_VECTOR and DATA_RDY = '1' then + EX_P_INT <= '0'; + elsif INT7_TRIG = true then -- Level 7 is nonmaskable ... + EX_P_INT <= '1'; + IRQ_PEND_I <= IRQ; + elsif INT_TRIG = '1' and STATUS_REG_IN(10 downto 8) < IRQ then + EX_P_INT <= '1'; + IRQ_PEND_I <= IRQ; + end if; + -- + -- The following nine traps never appear at the same time: + if TRAP_CHK = '1' then + EX_P_CHK <= '1'; + elsif TRAP_DIVZERO = '1' then + EX_P_DIVZERO <= '1'; + elsif TRAP_CODE_OPC = T_TRAP then + EX_P_TRAP <= '1'; + elsif TRAP_V = '1' then + EX_P_TRAPV <= '1'; + elsif TRAP_CODE_OPC = T_PRIV then + EX_P_PRIV <= '1'; + elsif TRAP_CODE_OPC = T_1010 then + EX_P_1010 <= '1'; + elsif TRAP_CODE_OPC = T_1111 then + EX_P_1111 <= '1'; + elsif TRAP_CODE_OPC = T_ILLEGAL then + EX_P_ILLEGAL <= '1'; + elsif TRAP_ILLEGAL = '1' then -- Used for BKPT. + EX_P_ILLEGAL <= '1'; + elsif EX_STATE = VALIDATE_FRAME and DATA_RDY = '1' and DATA_VALID = '1' and NEXT_EX_STATE = IDLE then + EX_P_FORMAT <= '1'; + elsif EX_STATE = EXAMINE_VERSION and DATA_RDY = '1' and DATA_VALID = '1' and NEXT_EX_STATE = IDLE then + EX_P_FORMAT <= '1'; + elsif TRAP_CODE_OPC = T_RTE then + EX_P_RTE <= '1'; + elsif EX_STATE = REFILL_PIPE and NEXT_EX_STATE /= REFILL_PIPE then -- Clear after IPIPE_FLUSH. + case EXCEPTION is + when EX_1010 | EX_1111 | EX_CHK | EX_DIVZERO | EX_ILLEGAL | EX_TRAP | EX_TRAPV | EX_FORMAT | EX_PRIV | EX_RTE => + EX_P_CHK <= '0'; + EX_P_DIVZERO <= '0'; + EX_P_PRIV <= '0'; + EX_P_1010 <= '0'; + EX_P_1111 <= '0'; + EX_P_ILLEGAL <= '0'; + EX_P_RTE <= '0'; + EX_P_TRAP <= '0'; + EX_P_TRAPV <= '0'; + EX_P_FORMAT <= '0'; + when others => + null; + end case; + -- Clear all possible traps during reset exception because the + -- signal EXCEPTION is not valid at this time: + elsif SYS_INIT = '1' then + EX_P_CHK <= '0'; + EX_P_DIVZERO <= '0'; + EX_P_PRIV <= '0'; + EX_P_1010 <= '0'; + EX_P_1111 <= '0'; + EX_P_ILLEGAL <= '0'; + EX_P_RTE <= '0'; + EX_P_TRAP <= '0'; + EX_P_TRAPV <= '0'; + EX_P_FORMAT <= '0'; + end if; + end process PENDING; + + ACCESS_ERR <= '1' when EX_STATE = RESTORE_PC and DATA_RDY = '1' and DATA_0 = '1' else -- Odd PC value. + '1' when DATA_RDY = '1' and DATA_VALID = '0' else '0'; -- Bus error. + + IRQ_PEND <= IRQ_PEND_I when EXCEPTION = EX_RESET or EXCEPTION = EX_INT else STATUS_REG_IN(10 downto 8); + IPENDn <= '0' when EX_P_INT = '1' or EX_P_RESET = '1' or EX_P_TRACE = '1' else '1'; + + -- This signal is asserted eraly to indicate the respective controller to stay in its idle state. + -- The exception is then inserted before a new operation has been loaded and processed. + EXH_REQ <= '0' when EX_STATE /= IDLE else + '1' when TRAP_CODE_OPC /= NONE else + '1' when (EX_P_RESET or EX_P_BERR or EX_P_AERR or EX_P_DIVZERO) = '1' else + '1' when (EX_P_CHK or EX_P_TRAPV or EX_P_TRACE or EX_P_FORMAT or EX_P_INT) = '1' else '0'; + + INT_VECTOR: process + -- This process provides the vector base register handling and + -- the interrupt vector number INT_VECT, which is determined + -- during interrupt processing. + variable VECT_No : std_logic_vector(9 downto 2) := "00000000"; + variable VB_REG : std_logic_vector(31 downto 0) := x"00000000"; + begin + wait until CLK = '1' and CLK' event; + if VBR_WR = '1' then + VB_REG := DATA_IN; + elsif SYS_INIT = '1' then + VB_REG := (others => '0'); + end if; + -- + if EX_STATE = CALC_VECT_No or EX_STATE = GET_VECTOR then + case EXCEPTION is + when EX_RESET => VECT_No := x"00"; + when EX_BERR => VECT_No := x"02"; + when EX_AERR => VECT_No := x"03"; + when EX_ILLEGAL => VECT_No := x"04"; + when EX_DIVZERO => VECT_No := x"05"; + when EX_CHK => VECT_No := x"06"; + when EX_TRAPV => VECT_No := x"07"; + when EX_PRIV => VECT_No := x"08"; + when EX_TRACE => VECT_No := x"09"; + when EX_1010 => VECT_No := x"0A"; + when EX_1111 => VECT_No := x"0B"; + when EX_FORMAT => VECT_No := x"0E"; + -- The uninitialized interrupt vector number x"0F" + -- is provided by the peripheral interrupt source + -- during the auto vector bus cycle. + when EX_INT => + if DATA_RDY = '1' and AVEC = '1' then + VECT_No := x"18" + IRQ_PEND_I; -- Autovector. + elsif DATA_RDY = '1' and DATA_VALID = '0' then + VECT_No := x"18"; -- Spurious interrupt. + elsif DATA_RDY = '1' then + -- This is the vector number provided by the device. + -- If the returned VECT_No is x"0F" then it is the + -- uninitialized interrupt vector due to non initia- + -- lized vector register of the peripheral device. + VECT_No := DATA_IN(7 downto 0); -- Non autovector. + end if; + when EX_TRAP => VECT_No := x"2" & TRAP_VECTOR; + when others => VECT_No := (others => '-'); -- Don't care. + end case; + end if; + -- + INT_VECT <= VB_REG + (VECT_No & "00"); + VBR <= VB_REG; + IVECT_OFFS <= VECT_No & "00"; + end process INT_VECTOR; + + STORE_CURRENT_EXCEPTION: process + -- The exceptions which occurs are stored in the following flags until the + -- interrupt handler handled the respective exception. + -- This process also stores the current processed exception for further use. + -- The update takes place in the IDLE EX_STATE. + begin + wait until CLK = '1' and CLK' event; + -- Priority level 0: + if EX_STATE = IDLE and EX_P_RESET = '1' then + EXCEPTION <= EX_RESET; + -- Priority level 1: + elsif EX_STATE = IDLE and EX_P_AERR = '1' then + EXCEPTION <= EX_AERR; + elsif EX_STATE = IDLE and EX_P_BERR = '1' then + EXCEPTION <= EX_BERR; + -- Priority level 2: + -- BREAKPOINT is part of the main controller. + elsif EX_STATE = IDLE and EX_P_CHK = '1' then + EXCEPTION <= EX_CHK; + elsif EX_STATE = IDLE and EX_P_DIVZERO = '1' then + EXCEPTION <= EX_DIVZERO; + elsif EX_STATE = IDLE and EX_P_TRAP = '1' then + EXCEPTION <= EX_TRAP; + elsif EX_STATE = IDLE and EX_P_TRAPV = '1' then + EXCEPTION <= EX_TRAPV; + elsif EX_STATE = IDLE and EX_P_FORMAT = '1' then + EXCEPTION <= EX_FORMAT; + -- Priority level 3: + elsif EX_STATE = IDLE and EX_P_ILLEGAL = '1' then + EXCEPTION <= EX_ILLEGAL; + elsif EX_STATE = IDLE and EX_P_RTE = '1' then + EXCEPTION <= EX_RTE; + elsif EX_STATE = IDLE and EX_P_1010 = '1' then + EXCEPTION <= EX_1010; + elsif EX_STATE = IDLE and EX_P_1111 = '1' then + EXCEPTION <= EX_1111; + elsif EX_STATE = IDLE and EX_P_PRIV = '1' then + EXCEPTION <= EX_PRIV; + elsif EX_STATE = IDLE and EX_P_TRACE = '1' then + EXCEPTION <= EX_TRACE; + elsif EX_STATE = IDLE and EX_P_INT = '1' then + EXCEPTION <= EX_INT; + elsif NEXT_EX_STATE = IDLE then + EXCEPTION <= EX_NONE; + end if; + end process STORE_CURRENT_EXCEPTION; + + CPU_SPACE <= '1' when NEXT_EX_STATE = GET_VECTOR else '0'; + + ADR_OFFSET <= x"000000" & "00000" & PIPE_CNT & '0' when EX_STATE = REFILL_PIPE else + x"00000004" when NEXT_EX_STATE = RESTORE_PC and EXCEPTION = EX_RESET else + x"00000002" when NEXT_EX_STATE = RESTORE_PC else + x"00000006" when NEXT_EX_STATE = VALIDATE_FRAME else + x"0000001A" when NEXT_EX_STATE = EXAMINE_VERSION else + x"0000001E" when NEXT_EX_STATE = READ_BOTTOM else + INT_VECT when NEXT_EX_STATE = UPDATE_PC else x"00000000"; -- Default is top of the stack (STATUS). + + OP_SIZE <= LONG when K6800n = '1' and EX_STATE = INIT and EXCEPTION /= EX_AERR and EXCEPTION /= EX_BERR else -- First access of AERR or BERR is WORD. + LONG when NEXT_EX_STATE = RESTORE_ISP or NEXT_EX_STATE = RESTORE_PC else + LONG when NEXT_EX_STATE = UPDATE_PC else + LONG when K6800n = '0' and NEXT_EX_STATE = BUILD_STACK and (STACK_CNT = 7 or STACK_CNT = 3) and DATA_RDY = '1' else -- Words 7 and 3 are word wide. + LONG when K6800n = '0' and NEXT_EX_STATE = BUILD_STACK and STACK_CNT /= 7 and STACK_CNT /= 3 else + LONG when K6800n = '1' and NEXT_EX_STATE = BUILD_STACK and STACK_CNT = 29 and DATA_RDY = '1' else -- Always long access, except word 29. + LONG when K6800n = '1' and NEXT_EX_STATE = BUILD_STACK and STACK_CNT /= 29 else + LONG when EX_STATE = UPDATE_PC or NEXT_EX_STATE = RESTORE_PC else + LONG when NEXT_EX_STATE = EXAMINE_VERSION else + BYTE when EX_STATE = GET_VECTOR and NEXT_EX_STATE = GET_VECTOR else WORD; + + DISPLACEMENT <= x"08" when STACK_FORMAT_I = x"0" and K6800n = '1' else -- 68K10. + x"3A" when STACK_FORMAT_I = x"8" and K6800n = '1' else -- 68K10. + x"06" when STACK_FORMAT_I = x"0" else x"0E"; -- 68K00. + + SP_ADD_DISPL <= '1' when EX_STATE = RESTORE_STATUS and DATA_RDY = '1' and DATA_VALID = '1' else '0'; + + P_D: process(CLK, DATA_RDY) + -- These flip flops are necessary to delay + -- the read and writes during BUILD_STACK + -- and restoring the system because the + -- address calculation in the address + -- section requires one clock. + -- Important note: to avoid asynchronous reset by data hazards the + -- resetting signal is synchronized on the negative clock edge. + variable DATA_RDY_VAR : bit; + begin + if CLK = '0' and CLK' event then + DATA_RDY_VAR := DATA_RDY; + end if; + -- + if DATA_RDY_VAR = '1' then + DATA_RD <= '0'; + elsif CLK = '1' and CLK' event then + DATA_RD <= DATA_RD_I; + end if; + + if DATA_RDY_VAR = '1' then + DATA_WR <= '0'; + elsif CLK = '1' and CLK' event then + DATA_WR <= DATA_WR_I; + end if; + end process P_D; + + DATA_RD_I <= '0' when DATA_RDY = '1' else + '1' when NEXT_EX_STATE = GET_VECTOR else + '1' when NEXT_EX_STATE = VALIDATE_FRAME else + '1' when NEXT_EX_STATE = EXAMINE_VERSION else + '1' when NEXT_EX_STATE = READ_BOTTOM else + '1' when NEXT_EX_STATE = RESTORE_ISP else + '1' when NEXT_EX_STATE = RESTORE_STATUS else + '1' when NEXT_EX_STATE = UPDATE_PC else + '1' when NEXT_EX_STATE = RESTORE_PC else '0'; + + DATA_WR_I <= '0' when DATA_RDY = '1' else + '1' when EX_STATE = BUILD_STACK else '0'; + + ISP_LOAD <= '1' when EX_STATE = RESTORE_ISP and DATA_RDY = '1' and DATA_VALID = '1' else '0'; + PC_RESTORE <= '1' when EX_STATE = RESTORE_PC and DATA_RDY = '1' and DATA_VALID = '1' else '0'; + PC_LOAD <= '1' when EXCEPTION /= EX_RESET and EXCEPTION /= EX_RTE and EX_STATE /= REFILL_PIPE and NEXT_EX_STATE = REFILL_PIPE else '0'; + + IPIPE_FILL <= '1' when EX_STATE = REFILL_PIPE else '0'; + + -- This signal forces the PC logic in the address register section to calculate the address + -- of the next instruction. This address is written on the stack. For the following + -- instructions the old PC value is stacked: BERR, AERR, ILLEGAL, PRIV, TRACE, 1010, 1111, FORMAT. + PC_INC <= '1' when EXCEPTION = EX_CHK and EX_STATE /= BUILD_STACK and NEXT_EX_STATE = BUILD_STACK else + '1' when EXCEPTION = EX_DIVZERO and EX_STATE /= BUILD_STACK and NEXT_EX_STATE = BUILD_STACK else + '1' when EXCEPTION = EX_INT and EX_STATE /= BUILD_STACK and NEXT_EX_STATE = BUILD_STACK else + '1' when EXCEPTION = EX_TRAP and EX_STATE /= BUILD_STACK and NEXT_EX_STATE = BUILD_STACK else + '1' when EXCEPTION = EX_TRAPV and EX_STATE /= BUILD_STACK and NEXT_EX_STATE = BUILD_STACK else '0'; + + ISP_DEC <= '1' when EX_STATE = INIT and EXCEPTION /= EX_RESET and EXCEPTION /= EX_RTE else -- Early due to one clock cycle address calculation. + '1' when EX_STATE = BUILD_STACK and DATA_RDY = '1' and NEXT_EX_STATE = BUILD_STACK else '0'; + + SR_INIT <= '1' when EX_STATE = INIT else '0'; + SR_WR <= '1' when EX_STATE = RESTORE_STATUS and DATA_RDY = '1' and DATA_VALID = '1' else '0'; + + SYS_INIT <= '1' when EX_STATE = IDLE and EX_P_RESET = '1' else '0'; + + -- The processor gets halted, if a bus error occurs in the stacking or updating states during + -- the exception processing of a bus error, an address error or a reset. + HALT_OUTn <= '0' when EX_STATE = HALTED else '1'; + + RESTORE_ISP_PC <= '1' when EXCEPTION = EX_RESET and (NEXT_EX_STATE = RESTORE_ISP or EX_STATE = RESTORE_ISP) else + '1' when EXCEPTION = EX_RESET and (NEXT_EX_STATE = RESTORE_PC or EX_STATE = RESTORE_PC) else + '1' when NEXT_EX_STATE = UPDATE_PC else '0'; + + IPIPE_FLUSH <= '1' when EXCEPTION = EX_RESET and EX_STATE /= REFILL_PIPE else + '1' when EXCEPTION /= EX_NONE and EX_STATE /= REFILL_PIPE and NEXT_EX_STATE = REFILL_PIPE else '0'; + + DOUBLE_BUSFLT <= '1' when (EXCEPTION = EX_AERR or EXCEPTION = EX_RESET) and EX_STATE = RESTORE_PC and DATA_RDY = '1' and DATA_0 = '1' else -- Odd PC value. + '1' when EX_STATE /= IDLE and EXCEPTION = EX_AERR and DATA_RDY = '1' and DATA_VALID = '0' else + '1' when EX_STATE /= IDLE and EXCEPTION = EX_BERR and DATA_RDY = '1' and DATA_VALID = '0' else + '1' when EX_STATE /= IDLE and EXCEPTION = EX_RESET and DATA_RDY = '1' and DATA_VALID = '0' else '0'; + + P_TMP_CPY: process + -- These registers contain a copy of system relevant state information + -- which is necessary for restoring the exception. Copies are provided + -- for the status register, the program counter and the effective address. + begin + wait until CLK = '1' and CLK' event; + if EX_STATE = IDLE and NEXT_EX_STATE /= IDLE then + SR_CPY <= STATUS_REG_IN; + end if; + end process P_TMP_CPY; + + STACK_CTRL: process + -- This process controls the stacking of the data to the stack. Depending + -- on the stack frame format, the number of words written to the stack is + -- adjusted to long words. See the DATA_2_PORT multiplexer in the top level + -- file for more information. + variable STACK_POS_VAR : integer range 0 to 31 := 0; + begin + wait until CLK = '1' and CLK' event; + if EX_STATE /= BUILD_STACK and NEXT_EX_STATE = BUILD_STACK then + case EXCEPTION is + when EX_AERR | EX_BERR => + if K6800n = '0' then + STACK_POS_VAR := 7; -- 68K00 bus or address error stack format. + else + STACK_POS_VAR := 29; -- Format 8. + end if; + STACK_FORMAT_I <= x"8"; + when others => + if K6800n = '0' then + STACK_POS_VAR := 3; -- 68K00 3 word stack format. + else + STACK_POS_VAR := 4; -- Format 0. + end if; + STACK_FORMAT_I <= x"0"; + end case; + elsif EX_STATE = VALIDATE_FRAME and DATA_RDY = '1' and DATA_VALID = '1' then + STACK_FORMAT_I <= DATA_IN(15 downto 12); + elsif EX_STATE = BUILD_STACK and DATA_RDY = '1' then + case STACK_POS_VAR is + when 29 | 7 | 3 => STACK_POS_VAR := STACK_POS_VAR - 1; -- WORD access. + when others => STACK_POS_VAR := STACK_POS_VAR - 2; -- LONG access. + end case; + end if; + -- + STACK_CNT <= STACK_POS_VAR; + STACK_POS <= STACK_POS_VAR; + end process STACK_CTRL; + + STACK_FORMAT <= STACK_FORMAT_I; + + PIPE_STATUS: process + -- This logic detects the status of the + -- instruction pipe prefetch in the + -- REFILL_PIPE state. + variable CNT : std_logic_vector(1 downto 0); + begin + wait until CLK = '1' and CLK' event; + if EX_STATE /= REFILL_PIPE then + PIPE_FULL <= false; + CNT := "00"; + elsif EX_STATE = REFILL_PIPE and OPCODE_RDY = '1' and CNT < "10" then + CNT := CNT + '1'; + elsif EX_STATE = REFILL_PIPE and OPCODE_RDY = '1' then + PIPE_FULL <= true; + end if; + PIPE_CNT <= CNT; + end process PIPE_STATUS; + + EXCEPTION_HANDLER_REG: process + -- This is the register portion of the + -- exception control state machine. + begin + wait until CLK = '1' and CLK' event; + if RESET = '1' then + EX_STATE <= IDLE; + else + EX_STATE <= NEXT_EX_STATE; + end if; + end process EXCEPTION_HANDLER_REG; + + EXCEPTION_HANDLER_DEC: process(ACCESS_ERR, BUSY_MAIN, BUSY_OPD, DATA_IN, DATA_VALID, DOUBLE_BUSFLT, EX_STATE, EX_P_RESET, EX_P_AERR, EX_P_BERR, + EX_P_TRACE, EX_P_INT, EX_P_ILLEGAL, EX_P_1010, EX_P_RTE, EX_P_1111, EX_P_FORMAT, EX_P_PRIV, EX_P_TRAP, EX_P_TRAPV, + EX_P_CHK, EX_P_DIVZERO, EXCEPTION, DATA_RDY, PIPE_FULL, STACK_CNT, K6800n) + begin + case EX_STATE is + when IDLE => + -- The priority of the exception execution is given by the + -- following construct. Although type 3 commands do not require + -- a prioritization, there is no drawback using these conditions. + -- The spurious interrupt and uninitialized interrupt never appear + -- as basic interrupts and therefore are not an interrupt source. + -- During IDLE, when an interrupt occurs, the status register copy + -- control is asserted and the current interrupt controll is given + -- to the STORE_EXCEPTION process. During bus or address errors, + -- the status register must be copied immediately to recognize + -- the current status for RWn etc. (before the faulty bus cycle is + -- finished). + if (BUSY_MAIN = '1' or BUSY_OPD = '1') and EX_P_RESET = '0' then + NEXT_EX_STATE <= IDLE; -- Wait until the pipelined architecture is ready. + elsif EX_P_RESET = '1' or EX_P_AERR = '1' or EX_P_BERR = '1' then + NEXT_EX_STATE <= INIT; + elsif EX_P_TRAP = '1' or EX_P_TRAPV = '1' or EX_P_CHK = '1' or EX_P_DIVZERO = '1' then + NEXT_EX_STATE <= INIT; + elsif EX_P_FORMAT = '1' then + NEXT_EX_STATE <= INIT; + elsif EX_P_TRACE = '1' or EX_P_ILLEGAL = '1' or EX_P_1010 = '1' or EX_P_1111 = '1' or EX_P_PRIV = '1' then + NEXT_EX_STATE <= INIT; + elsif EX_P_RTE = '1' then + NEXT_EX_STATE <= INIT; + elsif EX_P_INT = '1' then + NEXT_EX_STATE <= INIT; + else -- No exception. + NEXT_EX_STATE <= IDLE; + end if; + when INIT => + -- In this state, the supervisor mode is switched on (the S bit is set) + -- and the trace mode is switched off (the T bit is cleared). + -- Do not service, if halted. The current bus cycle is always finished + -- in this state. The worst case is a bus error which the finishes the + -- current bus cycle within the next clock cycle after BERR is asserted. + case EXCEPTION is + when EX_RTE => + -- This state is foreseen to handle the address offset + -- correctly in the case the ADR_ATN is already set + -- by the main controller. So we have to wait one + -- clock cycle to ensure this data hazard. + if K6800n = '1' then + NEXT_EX_STATE <= VALIDATE_FRAME; -- 68K10. + else + NEXT_EX_STATE <= RESTORE_PC; -- 68K00. + end if; + when EX_INT => + NEXT_EX_STATE <= GET_VECTOR; + when others => + NEXT_EX_STATE <= CALC_VECT_No; + end case; + when GET_VECTOR => + -- This state is intended to determine the vector number for the current process. + if DATA_RDY = '1' then + NEXT_EX_STATE <= BUILD_STACK; + else + NEXT_EX_STATE <= GET_VECTOR; + end if; + when CALC_VECT_No => + -- This state is introduced to control the generation of the vector number + -- for all exceptions except the external interrupts. + case EXCEPTION is + when EX_RESET => + NEXT_EX_STATE <= RESTORE_ISP; -- Do not stack anything but update the SSP and PC. + when others => + NEXT_EX_STATE <= BUILD_STACK; + end case; + -- The following states provide writing to the stack pointer or reading + -- the exception vector address from memory. If there is a bus error + -- or an address error during the read or write cycles, the processor + -- proceeds in two different ways: + -- If the errors occur during a reset, bus error or address error + -- exception processing, a double bus fault has occured. In + -- consequence, the processor halts due to catastrophic system failure. + -- If the errors occur during other exception processings, the current + -- processing is aborted and this exception handler state machine will + -- immediately begin with the bus error exception handling. + when BUILD_STACK => + if DOUBLE_BUSFLT = '1' then + NEXT_EX_STATE <= HALTED; + elsif ACCESS_ERR = '1' then + NEXT_EX_STATE <= IDLE; + elsif DATA_RDY = '1' and STACK_CNT = 2 then + NEXT_EX_STATE <= UPDATE_PC; + else + NEXT_EX_STATE <= BUILD_STACK; + end if; + when UPDATE_PC => + if DOUBLE_BUSFLT = '1' then + NEXT_EX_STATE <= HALTED; + elsif ACCESS_ERR = '1' then + NEXT_EX_STATE <= IDLE; + elsif DATA_RDY = '1' then + NEXT_EX_STATE <= REFILL_PIPE; + else + NEXT_EX_STATE <= UPDATE_PC; + end if; + when VALIDATE_FRAME => + if DATA_RDY = '1' and DATA_VALID = '0' then + NEXT_EX_STATE <= IDLE; -- Bus error. + elsif ACCESS_ERR = '1' then + NEXT_EX_STATE <= IDLE; + elsif DATA_RDY = '1' then + case DATA_IN(15 downto 12) is + when x"0" => + NEXT_EX_STATE <= RESTORE_PC; + when x"8" => + NEXT_EX_STATE <= EXAMINE_VERSION; + when others => + NEXT_EX_STATE <= IDLE; -- Format error. + end case; + else + NEXT_EX_STATE <= VALIDATE_FRAME; + end if; + when EXAMINE_VERSION => + if ACCESS_ERR = '1' then + NEXT_EX_STATE <= IDLE; + elsif DATA_RDY = '1' then + if DATA_IN /= VERSION then + NEXT_EX_STATE <= IDLE; -- Format error. + else + NEXT_EX_STATE <= READ_BOTTOM; + end if; + else + NEXT_EX_STATE <= EXAMINE_VERSION; + end if; + when READ_BOTTOM => + if ACCESS_ERR = '1' then + NEXT_EX_STATE <= IDLE; + elsif DATA_RDY = '1' then + NEXT_EX_STATE <= RESTORE_PC; + else + NEXT_EX_STATE <= READ_BOTTOM; + end if; + when RESTORE_STATUS => + if DOUBLE_BUSFLT = '1' then + NEXT_EX_STATE <= HALTED; + elsif ACCESS_ERR = '1' then + NEXT_EX_STATE <= IDLE; + elsif DATA_RDY = '1' then + NEXT_EX_STATE <= REFILL_PIPE; + else + NEXT_EX_STATE <= RESTORE_STATUS; + end if; + when RESTORE_ISP => + if DOUBLE_BUSFLT = '1' then + NEXT_EX_STATE <= HALTED; + elsif ACCESS_ERR = '1' then + NEXT_EX_STATE <= IDLE; + elsif DATA_RDY = '1' then + NEXT_EX_STATE <= RESTORE_PC; + else + NEXT_EX_STATE <= RESTORE_ISP; + end if; + when RESTORE_PC => + if DOUBLE_BUSFLT = '1' then + NEXT_EX_STATE <= HALTED; -- Double bus fault. + elsif ACCESS_ERR = '1' then + NEXT_EX_STATE <= IDLE; + elsif EXCEPTION = EX_RESET and DATA_RDY = '1' then + NEXT_EX_STATE <= REFILL_PIPE; + elsif DATA_RDY = '1' then + NEXT_EX_STATE <= RESTORE_STATUS; + else + NEXT_EX_STATE <= RESTORE_PC; + end if; + when REFILL_PIPE => + if DOUBLE_BUSFLT = '1' then + NEXT_EX_STATE <= HALTED; + elsif ACCESS_ERR = '1' then + NEXT_EX_STATE <= IDLE; + elsif PIPE_FULL = true then + NEXT_EX_STATE <= IDLE; + else + NEXT_EX_STATE <= REFILL_PIPE; + end if; + when HALTED => + -- Processor halted, Double bus error! + NEXT_EX_STATE <= HALTED; + end case; + end process EXCEPTION_HANDLER_DEC; +end BEHAVIOR; diff --git a/common/CPU/68K10/wf68k10_opcode_decoder.vhd b/common/CPU/68K10/wf68k10_opcode_decoder.vhd new file mode 100644 index 00000000..f935ddcf --- /dev/null +++ b/common/CPU/68K10/wf68k10_opcode_decoder.vhd @@ -0,0 +1,1228 @@ +------------------------------------------------------------------------ +---- ---- +---- WF68K10 IP Core: this is the bus controller module. ---- +---- ---- +---- Description: ---- +---- This module is a 68010 compatible instruction word decoder. ---- +---- It is primarily controlled by the following signals: ---- +---- OW_REQ, OPD_ACK, EW_REQ and EW_ACK. The handshaking is as ---- +---- follows: if a new instruction is required, assert the signal ---- +---- OW_REQ and wait until ACK is asserted by the decoder logic. ---- +---- Deassert OW_REQ right after ACK (in the same clock cycle). ---- +---- At this point, the required instruction has already been copied---- +---- from the pipe to the register BIW_0. The respective additional ---- +---- instruction words are located in BIW_1, BIW_2. For more infor- ---- +---- mation see the 68010 "Programmers Reference Manual" and the ---- +---- signal INSTR_LVL in this module. ---- +---- The extension request works in the same manner by asserting ---- +---- EW_REQ. At the time of EXT_ACK one extension word has been ---- +---- copied to EXT_WORD. ---- +---- Be aware that it is in the scope of the logic driving ---- +---- OW_REQ and EW_REQ to hold the instruction pipe aligned. ---- +---- This means in detail, that the correct number or instruction ---- +---- and extension words must be requested. Otherwise unpredictable ---- +---- processor behaviour will occur. Furthermore OW_REQ and EW_REQ ---- +---- must not be asserted the same time. ---- +---- This operation code decoder with the handshake logic as des- ---- +---- cribed above is the first pipeline stage of the CPU architec- ---- +---- ture. ---- +---- ---- +---- ---- +---- Author(s): ---- +---- Wolfgang Foerster, wf@experiment-s.de; wf@inventronik.de ---- +---- ---- +------------------------------------------------------------------------ +---- ---- +---- Copyright © 2014-2019 Wolfgang Foerster Inventronik GmbH. ---- +---- ---- +---- This documentation describes Open Hardware and is licensed ---- +---- under the CERN OHL v. 1.2. You may redistribute and modify ---- +---- this documentation under the terms of the CERN OHL v.1.2. ---- +---- (http://ohwr.org/cernohl). This documentation is distributed ---- +---- WITHOUT ANY EXPRESS OR IMPLIED WARRANTY, INCLUDING OF ---- +---- MERCHANTABILITY, SATISFACTORY QUALITY AND FITNESS FOR A ---- +---- PARTICULAR PURPOSE. Please see the CERN OHL v.1.2 for ---- +---- applicable conditions ---- +---- ---- +------------------------------------------------------------------------ +-- +-- Revision History +-- +-- Revision 2K14B 20141201 WF +-- Initial Release. +-- Revision 2K16A 20161224 WF +-- Break the DBcc_LOOP when the exception handler is busy (see process P_LOOP). +-- Revision 2K18A 20180620 WF +-- Several minor improvements to meet better 68000 compatibility. +-- Removed illegal MOVEC control register patterns. +-- Removed REST_BIW_0. +-- Fixed the PW_EW_OFFSET calculation for JSR. +-- Rewritten DBcc loop. +-- Fix for unimplemented or illegal operations: PC is increased before stacked. +-- Removed CAHR, we have no cache. +-- Rearranged address error handling. +-- Revision 2K19B 20191224 WF +-- Introduced signal synchronization in the P_BSY process to avoid malfunction by hazards. +-- + + +library work; +use work.WF68K10_PKG.all; + +library ieee; +use ieee.std_logic_1164.all; +use ieee.std_logic_unsigned.all; + +entity WF68K10_OPCODE_DECODER is + generic(NO_LOOP : boolean); -- If true the DBcc loop mechanism is disabled. + port ( + CLK : in std_logic; + K6800n : in std_logic; -- '0' for MC68000 compatibility. + + OW_REQ_MAIN : in bit; -- Request from the execution unit. + EW_REQ_MAIN : in bit; -- Extension words request. + + EXH_REQ : in bit; -- Exception request. + BUSY_EXH : in bit; -- Exception handler is busy. + BUSY_MAIN : in bit; -- Main controller busy. + BUSY_OPD : out bit; -- This unit is busy. + + BKPT_INSERT : in bit; + BKPT_DATA : in std_logic_vector(15 downto 0); + + LOOP_EXIT : in bit; + LOOP_BSY : out bit; + + OPD_ACK_MAIN : out bit; -- Operation controller acknowledge. + EW_ACK : buffer bit; -- Extension word available. + + PC_INC : out bit; + PC_INC_EXH : in bit; + PC_ADR_OFFSET : out std_logic_vector(7 downto 0); + PC_EW_OFFSET : buffer std_logic_vector(3 downto 0); + PC_OFFSET : out std_logic_vector(7 downto 0); + + OPCODE_RD : out bit; + OPCODE_RDY : in bit; + OPCODE_VALID : in std_logic; + OPCODE_DATA : in std_logic_vector(15 downto 0); + + IPIPE_FILL : in bit; + IPIPE_FLUSH : in bit; -- Abandon the instruction pipe. + + -- Fault logic: + OW_VALID : out std_logic; -- Operation words valid. + + -- Trap logic: + SBIT : in std_logic; + TRAP_CODE : out TRAPTYPE_OPC; + + -- System control signals: + OP : buffer OP_68K; + BIW_0 : buffer std_logic_vector(15 downto 0); + BIW_1 : out std_logic_vector(15 downto 0); + BIW_2 : out std_logic_vector(15 downto 0); + EXT_WORD : out std_logic_vector(15 downto 0) + ); +end entity WF68K10_OPCODE_DECODER; + +architecture BEHAVIOR of WF68K10_OPCODE_DECODER is +type INSTR_LVL_TYPE is(D, C, B); +type IPIPE_TYPE is + record + D : std_logic_vector(15 downto 0); + C : std_logic_vector(15 downto 0); + B : std_logic_vector(15 downto 0); + end record; + +signal REQ : bit; +signal EW_REQ : bit; + +signal IPIPE : IPIPE_TYPE; +signal FIFO_RD : bit; +signal IPIPE_B_FAULT : std_logic; +signal IPIPE_C_FAULT : std_logic; +signal IPIPE_D_FAULT : std_logic; +signal IPIPE_PNTR : natural range 0 to 3; + +signal INSTR_LVL : INSTR_LVL_TYPE; +signal LOOP_ATN : boolean; +signal LOOP_BSY_I : boolean; +signal LOOP_OP : boolean; + +signal BKPT_REQ : bit; + +signal OP_I : OP_68K; + +signal OPCODE_FLUSH : bit; +signal OPCODE_RD_I : bit; +signal OPCODE_RDY_I : bit; +signal OW_REQ : bit; + +signal TRAP_CODE_I : TRAPTYPE_OPC; +signal FLUSHED : boolean; +signal PC_INC_I : bit; +signal PIPE_RDY : bit; +begin + P_BSY: process(CLK) + -- This logic requires asynchronous reset. This flip flop is intended + -- to break combinatorial loops. If an opcode cycle in the bus controller + -- unit is currently running, the actual PC address is stored during this + -- cycle. Therefore it is not possible to flush the pipe and manipulate + -- the PC during a running cycle. For the exception handler reading the + -- opcode is inhibited during a pipe flush. For the main controller unit + -- the pipe is flushed after a running opcode cycle. + -- Important note: to avoid asynchronous reset by data hazards the + -- resetting signals are synchronized on the negative clock edge. + variable OPCODE_RDY_VAR : bit; + variable BUSY_EXH_VAR : bit; + variable IPIPE_FILL_VAR : bit; + begin + if CLK = '0' and CLK' event then + OPCODE_RDY_VAR := OPCODE_RDY; + BUSY_EXH_VAR := BUSY_EXH; + IPIPE_FILL_VAR := IPIPE_FILL; + end if; + -- + if OPCODE_RDY_VAR = '1' then + OPCODE_RD_I <= '0'; + elsif BUSY_EXH_VAR = '1' and IPIPE_FILL_VAR = '0' then + OPCODE_RD_I <= '0'; + elsif CLK = '1' and CLK' event then + if IPIPE_FLUSH = '1' then + OPCODE_RD_I <= '1'; + elsif (LOOP_ATN = true and OPCODE_RD_I = '0') or LOOP_BSY_I = true then + OPCODE_RD_I <= '0'; + elsif IPIPE_PNTR < 3 then + OPCODE_RD_I <= '1'; + end if; + end if; + end process P_BSY; + + P_OPCODE_FLUSH: process + -- If there is a pending opcode cycle during a pipe flush, + -- an opcode mismatch will destroy scalar opcode processing. + -- To avoid this, we have to dismiss the upcoming opcode. + begin + wait until CLK = '1' and CLK' event; + if IPIPE_FLUSH = '1' and OPCODE_RD_I = '1' and OPCODE_RDY = '0' then + OPCODE_FLUSH <= '1'; + elsif OPCODE_RDY = '1' or BUSY_EXH = '1' then + OPCODE_FLUSH <= '0'; + end if; + end process P_OPCODE_FLUSH; + + OPCODE_RD <= OPCODE_RD_I; + OPCODE_RDY_I <= '0' when OPCODE_FLUSH = '1' else OPCODE_RDY; -- Dismiss the current read cycle. + BUSY_OPD <= '0' when EXH_REQ = '1' and BUSY_MAIN = '0' and IPIPE_PNTR > 0 and OPCODE_RD_I = '0' else -- Fill one opcode is sufficient here. + '1' when IPIPE_PNTR < 3 or OPCODE_RD_I = '1' else '0'; + + INSTRUCTION_PIPE: process + -- These are the instruction pipe FIFO registers. The opcodes are stored in IPIPE.B, IPIPE.C + -- and IPIPE.D which is copied to the instruction register or to the respective extension when + -- read. Be aware, that the pipe is always completely refilled to determine the correct INSTR_LVL + -- before it is copied to the execution unit. + variable IPIPE_D_VAR : std_logic_vector(15 downto 0); + begin + wait until CLK = '1' and CLK' event; + if IPIPE_FLUSH = '1' then + IPIPE.D <= (others => '0'); + IPIPE.C <= (others => '0'); + IPIPE.B <= (others => '0'); + IPIPE_PNTR <= 0; + elsif BKPT_INSERT = '1' then + IPIPE_D_VAR := IPIPE.D; + IPIPE.D <= BKPT_DATA; -- Insert the breakpoint data. + BKPT_REQ <= '1'; + elsif OW_REQ = '1' and BKPT_REQ = '1' then + IPIPE.D <= IPIPE_D_VAR; -- Restore from breakpoint. + BKPT_REQ <= '0'; + elsif LOOP_ATN = true and OPCODE_RD_I = '1' then + null; -- Wait for pending opcodes. + elsif OW_REQ = '1' and PIPE_RDY = '1' and OP_I = DBcc and LOOP_OP = true and IPIPE.C = x"FFFC" then -- Initialize the loop. + IPIPE.D <= BIW_0; -- This is the LEVEL D operation for the loop. + elsif OW_REQ = '1' and LOOP_BSY_I = true then + IPIPE.D <= BIW_0; -- Recycle the loop operations. + elsif LOOP_BSY_I = true then + null; -- Do not change the pipe during the loop. + elsif OW_REQ = '1' and INSTR_LVL = D and PIPE_RDY = '1' and IPIPE_PNTR = 2 then + if OPCODE_RDY_I = '1' then + IPIPE.D <= IPIPE.C; + IPIPE.C <= OPCODE_DATA; + IPIPE_D_FAULT <= IPIPE_C_FAULT; + IPIPE_C_FAULT <= not OPCODE_VALID; + else + IPIPE.D <= IPIPE.C; + IPIPE_D_FAULT <= IPIPE_C_FAULT; + IPIPE_PNTR <= IPIPE_PNTR - 1; + end if; + elsif OW_REQ = '1' and INSTR_LVL = D and PIPE_RDY = '1' and IPIPE_PNTR = 3 then + if OPCODE_RDY_I = '1' then + IPIPE.D <= IPIPE.C; + IPIPE.C <= IPIPE.B; + IPIPE.B <= OPCODE_DATA; + IPIPE_D_FAULT <= IPIPE_C_FAULT; + IPIPE_C_FAULT <= IPIPE_B_FAULT; + IPIPE_B_FAULT <= not OPCODE_VALID; + else + IPIPE.D <= IPIPE.C; + IPIPE.C <= IPIPE.B; + IPIPE_D_FAULT <= IPIPE_C_FAULT; + IPIPE_C_FAULT <= IPIPE_B_FAULT; + IPIPE_PNTR <= IPIPE_PNTR - 1; + end if; + elsif OW_REQ = '1' and INSTR_LVL = C and PIPE_RDY = '1' and IPIPE_PNTR = 2 then + if OPCODE_RDY_I = '1' then + IPIPE.D <= OPCODE_DATA; + IPIPE_D_FAULT <= not OPCODE_VALID; + IPIPE_PNTR <= IPIPE_PNTR - 1; + else + IPIPE_PNTR <= 0; + end if; + elsif OW_REQ = '1' and INSTR_LVL = C and PIPE_RDY = '1' and IPIPE_PNTR = 3 then + if OPCODE_RDY_I = '1' then + IPIPE.D <= IPIPE.B; + IPIPE.C <= OPCODE_DATA; + IPIPE_D_FAULT <= IPIPE_B_FAULT; + IPIPE_C_FAULT <= not OPCODE_VALID; + IPIPE_PNTR <= IPIPE_PNTR - 1; + else + IPIPE.D <= IPIPE.B; + IPIPE_D_FAULT <= IPIPE_B_FAULT; + IPIPE_PNTR <= IPIPE_PNTR - 2; + end if; + elsif OW_REQ = '1' and INSTR_LVL = B and PIPE_RDY = '1' then -- IPIPE_PNTR = 3. + if OPCODE_RDY_I = '1' then + IPIPE.D <= OPCODE_DATA; + IPIPE_D_FAULT <= not OPCODE_VALID; + IPIPE_PNTR <= IPIPE_PNTR - 2; + else + IPIPE_PNTR <= 0; + end if; + elsif EW_REQ = '1' and IPIPE_PNTR >= 1 then + case IPIPE_PNTR is + when 3 => + if OPCODE_RDY_I = '1' then + IPIPE.D <= IPIPE.C; + IPIPE.C <= IPIPE.B; + IPIPE.B <= OPCODE_DATA; + IPIPE_D_FAULT <= IPIPE_C_FAULT; + IPIPE_C_FAULT <= IPIPE_B_FAULT; + IPIPE_B_FAULT <= not OPCODE_VALID; + else + IPIPE.D <= IPIPE.C; + IPIPE.C <= IPIPE.B; + IPIPE_D_FAULT <= IPIPE_C_FAULT; + IPIPE_C_FAULT <= IPIPE_B_FAULT; + IPIPE_PNTR <= IPIPE_PNTR - 1; + end if; + when 2 => + if OPCODE_RDY_I = '1' then + IPIPE.D <= IPIPE.C; + IPIPE.C <= OPCODE_DATA; + IPIPE_D_FAULT <= IPIPE_C_FAULT; + IPIPE_C_FAULT <= not OPCODE_VALID; + else + IPIPE.D <= IPIPE.C; + IPIPE_D_FAULT <= IPIPE_C_FAULT; + IPIPE_PNTR <= IPIPE_PNTR - 1; + end if; + when 1 => + if OPCODE_RDY_I = '1' then + IPIPE.D <= OPCODE_DATA; + IPIPE_D_FAULT <= not OPCODE_VALID; + else + IPIPE_PNTR <= 0; + end if; + when others => null; + end case; + elsif OPCODE_RDY_I = '1' then + case IPIPE_PNTR is + when 2 => + IPIPE.B <= OPCODE_DATA; + IPIPE_B_FAULT <= not OPCODE_VALID; + IPIPE_PNTR <= 3; + when 1 => + IPIPE.C <= OPCODE_DATA; + IPIPE_C_FAULT <= not OPCODE_VALID; + IPIPE_PNTR <= 2; + when 0 => + IPIPE.D <= OPCODE_DATA; + IPIPE_D_FAULT <= not OPCODE_VALID; + IPIPE_PNTR <= 1; + when others => null; + end case; + end if; + end process INSTRUCTION_PIPE; + + P_FAULT: process + -- This are the fault flags for pipe B and C. + -- These flags are set, when an instruction + -- request uses either of the respective pipes. + begin + wait until CLK = '1' and CLK' event; + if IPIPE_FLUSH = '1' then + OW_VALID <= '0'; + elsif OW_REQ = '1' and LOOP_BSY_I = true then + OW_VALID <= '1'; + elsif OW_REQ = '1' and PIPE_RDY = '1' and INSTR_LVL = D then + OW_VALID <= not IPIPE_D_FAULT; + elsif OW_REQ = '1' and PIPE_RDY = '1' and INSTR_LVL = C then + OW_VALID <= not(IPIPE_D_FAULT or IPIPE_C_FAULT); + elsif OW_REQ = '1' and PIPE_RDY = '1' and INSTR_LVL = B then + OW_VALID <= not (IPIPE_D_FAULT or IPIPE_C_FAULT or IPIPE_B_FAULT); + elsif EW_REQ = '1' and PIPE_RDY = '1' then + OW_VALID <= not IPIPE_D_FAULT; + end if; + end process P_FAULT; + + OUTBUFFERS: process + variable OP_STOP : boolean; + begin + wait until CLK = '1' and CLK' event; + if OP_STOP = true and IPIPE_FLUSH = '1' then + TRAP_CODE <= NONE; + OP_STOP := false; + elsif IPIPE_FLUSH = '1' then + TRAP_CODE <= NONE; + elsif OP_STOP = true then + null; -- Do not update after PC is incremented. + elsif LOOP_ATN = true and OPCODE_RD_I = '1' then + null; -- Wait for pending opcodes. + elsif OW_REQ = '1' and LOOP_BSY_I = true then + OP <= OP_I; + BIW_0 <= IPIPE.D; + TRAP_CODE <= TRAP_CODE_I; + elsif OW_REQ = '1' and (PIPE_RDY = '1' or BKPT_REQ = '1') then + -- Be aware: all BIW are written unaffected + -- if they are all used. + OP <= OP_I; + BIW_0 <= IPIPE.D; + BIW_1 <= IPIPE.C; + BIW_2 <= IPIPE.B; + TRAP_CODE <= TRAP_CODE_I; + -- + if OP_I = STOP then + OP_STOP := true; + end if; + elsif EW_REQ = '1' and IPIPE_PNTR /= 0 then + EXT_WORD <= IPIPE.D; + end if; + end process OUTBUFFERS; + + LOOP_OP <= false when NO_LOOP = true else + true when OP = MOVE and BIW_0(8 downto 3) = "010010" else -- (Ay) to (Ax). + true when OP = MOVE and BIW_0(8 downto 3) = "011010" else -- (Ay) to (Ax)+. + true when OP = MOVE and BIW_0(8 downto 3) = "100010" else -- (Ay) to -(Ax). + true when OP = MOVE and BIW_0(8 downto 3) = "010011" else -- (Ay)+ to (Ax). + true when OP = MOVE and BIW_0(8 downto 3) = "011011" else -- (Ay)+ to (Ax)+. + true when OP = MOVE and BIW_0(8 downto 3) = "100011" else -- (Ay)+ to -(Ax). + true when OP = MOVE and BIW_0(8 downto 3) = "010100" else -- -(Ay) to (Ax). + true when OP = MOVE and BIW_0(8 downto 3) = "011100" else -- -(Ay) to (Ax)+. + true when OP = MOVE and BIW_0(8 downto 3) = "100100" else -- -(Ay) to -(Ax). + true when OP = MOVE and BIW_0(8 downto 3) = "100100" else -- -(Ay) to -(Ax). + true when OP = MOVE and BIW_0(8 downto 3) = "010000" else -- Dy to (Ax). + true when OP = MOVE and BIW_0(8 downto 3) = "011000" else -- Dy to (Ax)+. + true when OP = MOVE and BIW_0(8 downto 3) = "010001" else -- Ay to (Ax). + true when OP = MOVE and BIW_0(8 downto 3) = "011001" else -- Ay to (Ax)+. + true when (OP = ADD or OP = AND_B or OP = CMP or OP = EOR or OP = OR_B or OP = SUB) and BIW_0(5 downto 3) = "010" else -- (Ay) to Dx, Dx to (Ay). + true when (OP = ADD or OP = AND_B or OP = CMP or OP = EOR or OP = OR_B or OP = SUB) and BIW_0(5 downto 3) = "011" else -- (Ay)+ to Dx, Dx to (Ay)+. + true when (OP = ADD or OP = AND_B or OP = CMP or OP = EOR or OP = OR_B or OP = SUB) and BIW_0(5 downto 3) = "100" else -- -(Ay) to Dx, Dx to -(Ay). + true when (OP = ADDA or OP = CMPA or OP = SUBA) and BIW_0(5 downto 3) = "010" else -- (Ay) to Ax. + true when (OP = ADDA or OP = CMPA or OP = SUBA) and BIW_0(5 downto 3) = "011" else -- (Ay)+ to Ax. + true when (OP = ADDA or OP = CMPA or OP = SUBA) and BIW_0(5 downto 3) = "100" else -- -(Ay) to Ax. + true when OP = ABCD or OP = SBCD or OP = ADDX or OP = SUBX or OP = CMPM else -- -(Ay) to -(Ay), (Ay)+ to (Ay)+ for CMPM. + true when (OP = CLR or OP = NEG or OP = NEGX or OP = NOT_B or OP = TST or OP = NBCD) and BIW_0(5 downto 3) = "010" else -- (Ay). + true when (OP = CLR or OP = NEG or OP = NEGX or OP = NOT_B or OP = TST or OP = NBCD) and BIW_0(5 downto 3) = "011" else -- (Ay)+. + true when (OP = CLR or OP = NEG or OP = NEGX or OP = NOT_B or OP = TST or OP = NBCD) and BIW_0(5 downto 3) = "100" else -- -(Ay). + true when (OP = ASL or OP = ASR or OP = LSL or OP = LSR) and BIW_0(7 downto 3) = "11010" else -- (Ay) by #1. + true when (OP = ASL or OP = ASR or OP = LSL or OP = LSR) and BIW_0(7 downto 3) = "11011" else -- (Ay)+ by #1. + true when (OP = ASL or OP = ASR or OP = LSL or OP = LSR) and BIW_0(7 downto 3) = "11100" else -- -(Ay) by #1. + true when (OP = ROTL or OP = ROTR or OP = ROXL or OP = ROXR) and BIW_0(7 downto 3) = "11010" else -- (Ay) by #1. + true when (OP = ROTL or OP = ROTR or OP = ROXL or OP = ROXR) and BIW_0(7 downto 3) = "11011" else -- (Ay)+ by #1. + true when (OP = ROTL or OP = ROTR or OP = ROXL or OP = ROXR) and BIW_0(7 downto 3) = "11100" else false; -- -(Ay) by #1. + + -- This is the loop attention signal. There are several conditions to start a loop operation. + -- 1. A loop capable operation is in progress indicated by LOOP_OP. + -- 2. A DBcc operation is coming up (IPIPE.D). + -- 3. The displacement is minus four (IPIPE.C). + -- 4. The exception handler may not indicate a request. Otherwise the system may hang in a self + -- blocking mechanism concerning OW_REQ, LOOP_ATN, ALU_BSY. + LOOP_ATN <= false when EXH_REQ = '1' else + true when LOOP_BSY_I = false and LOOP_OP = true and OP_I = DBcc and IPIPE.C = x"FFFC" else false; -- IPIPE.C value must be minus four. + + P_LOOP: process + -- This flip flop controls the loop mode of the + -- processor. Refer to the MC68000 user manual + -- Appendix A for more information. + begin + wait until CLK = '1' and CLK' event; + if LOOP_ATN = true and OW_REQ = '1' and OPCODE_RD_I = '0' then + LOOP_BSY <= '1'; + LOOP_BSY_I <= true; + elsif LOOP_EXIT = '1' or BUSY_EXH = '1' then + LOOP_BSY <= '0'; + LOOP_BSY_I <= false; + end if; + end process P_LOOP; + + OW_REQ <= '0' when BUSY_EXH = '1' else OW_REQ_MAIN; + EW_REQ <= EW_REQ_MAIN; + + PIPE_RDY <= '1' when OW_REQ = '1' and IPIPE_PNTR = 3 and INSTR_LVL = B else + '1' when OW_REQ = '1' and IPIPE_PNTR > 1 and INSTR_LVL = C else + '1' when OW_REQ = '1' and IPIPE_PNTR > 1 and INSTR_LVL = D else -- We need always pipe C and D to determine the INSTR_LVL. + '1' when EW_REQ = '1' and IPIPE_PNTR > 0 else '0'; + + HANDSHAKING: process + -- Wee need these flip flops to ensure, that the OUTBUFFERS are + -- written when the respecktive _ACK signal is asserted. + -- The breakpoint cycles are valid for one word operations and + -- therefore does never start FPU operations. + begin + wait until CLK = '1' and CLK' event; + if EW_REQ = '1' and IPIPE_PNTR /= 0 then + EW_ACK <= '1'; + else + EW_ACK <= '0'; + end if; + + if IPIPE_FLUSH = '1' then + OPD_ACK_MAIN <= '0'; + elsif TRAP_CODE_I = T_PRIV then -- No action when priviledged. + OPD_ACK_MAIN <= '0'; + elsif OW_REQ = '1' and LOOP_BSY_I = true then + OPD_ACK_MAIN <= '1'; + elsif OW_REQ = '1' and (PIPE_RDY = '1' or BKPT_REQ = '1') then + OPD_ACK_MAIN <= '1'; + else + OPD_ACK_MAIN <= '0'; + end if; + end process HANDSHAKING; + + P_PC_OFFSET: process(CLK, BUSY_EXH, LOOP_BSY_I, LOOP_EXIT, OP, PC_INC_I) + -- Be Aware: the ADR_OFFSET requires the 'old' PC_VAR. + -- To arrange this, the ADR_OFFSET logic is located + -- above the PC_VAR logic. Do not change this! + -- The PC_VAR is modeled in a way, that the PC points + -- always to the BIW_0. + -- The PC_EW_OFFSET is also used for the calculation + -- of the correct PC value written to the stack pointer + -- during BSR, JSR and exceptions. + variable ADR_OFFSET : std_logic_vector(6 downto 0); + variable PC_VAR : std_logic_vector(6 downto 0); + variable PC_VAR_MEM : std_logic_vector(6 downto 0); + begin + if CLK = '1' and CLK' event then + if IPIPE_FLUSH = '1' then + ADR_OFFSET := "0000000"; + elsif PC_INC_I = '1' and OPCODE_RDY_I = '1' then + ADR_OFFSET := ADR_OFFSET + '1' - PC_VAR; + elsif OPCODE_RDY_I = '1' then + ADR_OFFSET := ADR_OFFSET + '1'; + elsif PC_INC_I = '1' then + ADR_OFFSET := ADR_OFFSET - PC_VAR; + end if; + -- + if BUSY_EXH = '0' then + PC_VAR_MEM := PC_VAR; -- Store the old offset to write back on the stack. + end if; + + if BUSY_EXH = '1' then + -- New PC is loaded by the exception handler. + -- So PC_VAR must be initialized. + PC_VAR := "0000000"; + elsif PC_INC_I = '1' or FLUSHED = true then + case INSTR_LVL is + when D => PC_VAR := "0000001"; + when C => PC_VAR := "0000010"; + when B => PC_VAR := "0000011"; + end case; + elsif EW_REQ = '1' and IPIPE_PNTR /= 0 then + PC_VAR := PC_VAR + '1'; + end if; + -- + if OW_REQ = '1' and BKPT_REQ = '1' then + PC_EW_OFFSET <= "0010"; -- Always level D operations. + elsif OW_REQ = '1' and PIPE_RDY = '1' and OP_I = JSR then -- Initialize. + PC_EW_OFFSET <= x"0"; + elsif OW_REQ = '1' and PIPE_RDY = '1' then -- BSR. + case INSTR_LVL is + when D => PC_EW_OFFSET <= "0010"; + when C => PC_EW_OFFSET <= "0100"; + when others => PC_EW_OFFSET <= "0110"; -- LONG displacement. + end case; + elsif EW_ACK = '1' and OP = JSR then -- Calculate the required extension words. + PC_EW_OFFSET <= PC_EW_OFFSET + "010"; + end if; + end if; + -- + if BUSY_EXH = '1' and PC_INC_I = '1' then + PC_OFFSET <= PC_VAR_MEM & '0'; + elsif OP = DBcc and LOOP_BSY_I = true and LOOP_EXIT = '0' then + -- Suppress to increment after DBcc operation during the loop to + -- handle a correct PC with displacement when looping around. + -- In non looping mode, the PC_ING is superseeded by + -- IPIPE_FLUSH in the PC logic. In loop mode we have no flush. + PC_OFFSET <= x"00"; + else + PC_OFFSET <= PC_VAR & '0'; + end if; + PC_ADR_OFFSET <= ADR_OFFSET & '0'; + end process P_PC_OFFSET; + + P_FLUSH: process + -- This flip flop is intended to control the incrementation + -- of the PC: normally the PC is updated in the end of an + -- operation (if a new opword is available) or otherwise in + -- the START_OP phase. When the instruction pipe is flushed, + -- it is required to increment the PC immediately to provide + -- the correct address for the pipe refilling. In this case + -- the PC update after the pipe refill is suppressed. + begin + wait until CLK = '1' and CLK' event; + if IPIPE_FLUSH = '1' then + FLUSHED <= true; + elsif OW_REQ = '1' and PIPE_RDY = '1' then + FLUSHED <= false; + end if; + end process P_FLUSH; + + PC_INC <= PC_INC_I; + PC_INC_I <= '0' when FLUSHED = true else -- Avoid double increment after a flushed pipe. + '1' when IPIPE_FLUSH = '1' and BUSY_MAIN = '1' else -- If the pipe is flushed, we need the new PC value for refilling. + '0' when BKPT_REQ = '1' else -- Do not update! + '1' when OW_REQ = '1' and PIPE_RDY = '1' else PC_INC_EXH; + + -- This signal indicates how many pipe stages are used at a time. + -- Be aware: all coprocessor commands are level D to meet the require- + -- ments of the scanPC. + INSTR_LVL <= D when TRAP_CODE_I = T_PRIV else -- Points to the first word. Required for stacking. + B when OP_I = ADDI and IPIPE.D(7 downto 6) = "10" else + B when OP_I = ANDI and IPIPE.D(7 downto 6) = "10" else + -- B when (OP_I = Bcc or OP_I = BRA or OP_I = BSR) and IPIPE.D(7 downto 0) = x"FF" else -- LONG for 68K10+. + B when OP_I = CMPI and IPIPE.D(7 downto 6) = "10" else + B when OP_I = EORI and IPIPE.D(7 downto 6) = "10" else + B when OP_I = ORI and IPIPE.D(7 downto 6) = "10" else + B when OP_I = SUBI and IPIPE.D(7 downto 6) = "10" else + C when OP_I = ADDI or OP_I = ANDI or OP_I = ANDI_TO_SR or OP_I = ANDI_TO_CCR else + C when (OP_I = BCHG or OP_I = BCLR or OP_I = BSET or OP_I = BTST) and IPIPE.D(8) = '0' else + C when (OP_I = Bcc or OP_I = BRA or OP_I = BSR) and IPIPE.D(7 downto 0) = x"00" else + C when OP_I = CMPI or OP_I = DBcc else + C when (OP_I = DIVS or OP_I = DIVU) and IPIPE.D(8 downto 6) = "001" else + C when OP_I = EORI or OP_I = EORI_TO_CCR or OP_I = EORI_TO_SR else + C when OP_I = LINK or OP_I = MOVEC else -- 68K00 and 68K10 have no long LINK. + C when OP_I = MOVEM or OP_I = MOVEP or OP_I = MOVES else + C when (OP_I = MULS or OP_I = MULU) and IPIPE.D(8 downto 6) = "000" else + C when OP_I = ORI_TO_CCR or OP_I = ORI_TO_SR or OP_I = ORI else + C when OP_I = RTD or OP_I = SUBI or OP_I = STOP else D; + + TRAP_CODE_I <= T_1010 when OP_I = UNIMPLEMENTED and IPIPE.D(15 downto 12) = x"A" else + T_1111 when OP_I = UNIMPLEMENTED and IPIPE.D(15 downto 12) = x"F" else + T_ILLEGAL when OP_I = ILLEGAL else + T_RTE when OP_I = RTE and SBIT = '1' else -- Handled like a trap simplifies the code. + T_TRAP when OP_I = TRAP else + T_PRIV when OP_I = ANDI_TO_SR and SBIT = '0' else + T_PRIV when OP_I = EORI_TO_SR and SBIT = '0' else + T_PRIV when OP_I = MOVE_TO_SR and SBIT = '0' else + T_PRIV when OP_I = MOVE_FROM_SR and SBIT = '0' and K6800n = '1' else -- This is for backward compatibility. + T_PRIV when (OP_I = MOVE_USP or OP_I = MOVEC or OP_I = MOVES) and SBIT = '0' else + T_PRIV when OP_I = ORI_TO_SR and SBIT = '0' else + T_PRIV when (OP_I = RESET or OP_I = RTE) and SBIT = '0' else + T_PRIV when OP_I = STOP and SBIT = '0' else NONE; + + OP_DECODE: process(IPIPE, K6800n) + begin + -- The default OPCODE is the ILLEGAL operation, if no of the following conditions are met. + -- If any not used bit pattern occurs, the CPU will result in an ILLEGAL trap. An exception of + -- this behavior is the OPCODE with the 1010 or the 1111 pattern in the four MSBs. + -- These lead to the respective traps. + OP_I <= ILLEGAL; + case IPIPE.D(15 downto 12) is -- Operation code map. + when x"0" => -- Bit manipulation / MOVEP / Immediate. + if IPIPE.D(11 downto 0) = x"03C" then + OP_I <= ORI_TO_CCR; + elsif IPIPE.D(11 downto 0) = x"07C" then + OP_I <= ORI_TO_SR; + elsif IPIPE.D(11 downto 0) = x"23C" then + OP_I <= ANDI_TO_CCR; + elsif IPIPE.D(11 downto 0) = x"27C" then + OP_I <= ANDI_TO_SR; + elsif IPIPE.D(11 downto 0) = x"A3C" then + OP_I <= EORI_TO_CCR; + elsif IPIPE.D(11 downto 0) = x"A7C" then + OP_I <= EORI_TO_SR; + elsif IPIPE.D(11 downto 8) = "1110" and IPIPE.D(7 downto 6) < "11" and IPIPE.D(5 downto 3) >= "010" and IPIPE.D(5 downto 3) < "111" and K6800n = '1' then + OP_I <= MOVES; + elsif IPIPE.D(11 downto 8) = "1110" and IPIPE.D(7 downto 6) < "11" and IPIPE.D(5 downto 3) = "111" and IPIPE.D(2 downto 0) < "010" and K6800n = '1' then + OP_I <= MOVES; + elsif IPIPE.D(8 downto 6) > "011" and IPIPE.D(5 downto 3) = "001" then + OP_I <= MOVEP; + else + case IPIPE.D(5 downto 3) is -- Addressing mode. + when "000" | "010" | "011" | "100" | "101" | "110" => + -- Bit operations with static bit number: + if IPIPE.D(11 downto 6) = "100000" then + OP_I <= BTST; + elsif IPIPE.D(11 downto 6) = "100001" then + OP_I <= BCHG; + elsif IPIPE.D(11 downto 6) = "100010" then + OP_I <= BCLR; + elsif IPIPE.D(11 downto 6) = "100011" then + OP_I <= BSET; + -- Logic operations: + elsif IPIPE.D(11 downto 8) = x"0" and IPIPE.D(7 downto 6) < "11" then + OP_I <= ORI; + elsif IPIPE.D(11 downto 8) = x"2" and IPIPE.D(7 downto 6) < "11" then + OP_I <= ANDI; + elsif IPIPE.D(11 downto 8) = x"4" and IPIPE.D(7 downto 6) < "11" then + OP_I <= SUBI; + elsif IPIPE.D(11 downto 8) = x"6" and IPIPE.D(7 downto 6) < "11" then + OP_I <= ADDI; + elsif IPIPE.D(11 downto 8) = x"A" and IPIPE.D(7 downto 6) < "11" then + OP_I <= EORI; + elsif IPIPE.D(11 downto 8) = x"C" and IPIPE.D(7 downto 6) < "11" then + OP_I <= CMPI; + -- Bit operations with dynamic bit number: + elsif IPIPE.D(8 downto 6) = "100" then + OP_I <= BTST; + elsif IPIPE.D(8 downto 6) = "101" then + OP_I <= BCHG; + elsif IPIPE.D(8 downto 6) = "110" then + OP_I <= BCLR; + elsif IPIPE.D(8 downto 6) = "111" then + OP_I <= BSET; + end if; + when "111" => + -- In the addressing mode "111" not all register selections are valid. + -- Bit operations with static bit number: + if IPIPE.D(11 downto 6) = "100000" and IPIPE.D(2 downto 0) < "100" then + OP_I <= BTST; + elsif IPIPE.D(11 downto 6) = "100001" and IPIPE.D(2 downto 0) < "010" then + OP_I <= BCHG; + elsif IPIPE.D(11 downto 6) = "100010" and IPIPE.D(2 downto 0) < "010" then + OP_I <= BCLR; + elsif IPIPE.D(11 downto 6) = "100011" and IPIPE.D(2 downto 0) < "010" then + OP_I <= BSET; + -- Logic operations: + elsif IPIPE.D(11 downto 8) = x"0" and IPIPE.D(7 downto 6) < "11" and IPIPE.D(2 downto 0) < "010" then + OP_I <= ORI; + elsif IPIPE.D(11 downto 8) = x"2" and IPIPE.D(7 downto 6) < "11" and IPIPE.D(2 downto 0) < "010" then + OP_I <= ANDI; + elsif IPIPE.D(11 downto 8) = x"4" and IPIPE.D(7 downto 6) < "11" and IPIPE.D(2 downto 0) < "010" then + OP_I <= SUBI; + elsif IPIPE.D(11 downto 8) = x"6" and IPIPE.D(7 downto 6) < "11" and IPIPE.D(2 downto 0) < "010" then + OP_I <= ADDI; + elsif IPIPE.D(11 downto 8) = x"A" and IPIPE.D(7 downto 6) < "11" and IPIPE.D(2 downto 0) < "010" then + OP_I <= EORI; + elsif IPIPE.D(11 downto 8) = x"C" and IPIPE.D(7 downto 6) < "11" and IPIPE.D(2 downto 0) < "100" then + OP_I <= CMPI; + -- Bit operations with dynamic bit number: + elsif IPIPE.D(8 downto 6) = "100" and IPIPE.D(2 downto 0) < "101" then + OP_I <= BTST; + elsif IPIPE.D(8 downto 6) = "101" and IPIPE.D(2 downto 0) < "010" then + OP_I <= BCHG; + elsif IPIPE.D(8 downto 6) = "110" and IPIPE.D(2 downto 0) < "010" then + OP_I <= BCLR; + elsif IPIPE.D(8 downto 6) = "111" and IPIPE.D(2 downto 0) < "010" then + OP_I <= BSET; + end if; + when others => + null; + end case; + end if; + when x"1" => -- Move BYTE. + if IPIPE.D(8 downto 6) = "111" and IPIPE.D(11 downto 9) < "010" + and IPIPE.D(5 downto 3) = "111" and IPIPE.D(2 downto 0) < "101" then + OP_I <= MOVE; + elsif IPIPE.D(8 downto 6) = "111" and IPIPE.D(11 downto 9) < "010" and IPIPE.D(5 downto 3) /= "001" and IPIPE.D(5 downto 3) /= "111" then + OP_I <= MOVE; + elsif IPIPE.D(8 downto 6) /= "001" and IPIPE.D(8 downto 6) /= "111" + and IPIPE.D(5 downto 3) = "111" and IPIPE.D(2 downto 0) < "101" then + OP_I <= MOVE; + elsif IPIPE.D(8 downto 6) /= "001" and IPIPE.D(8 downto 6) /= "111" and IPIPE.D(5 downto 3) /= "001" and IPIPE.D(5 downto 3) /= "111" then + OP_I <= MOVE; + end if; + when x"2" | x"3" => -- Move WORD or LONG. + if IPIPE.D(8 downto 6) = "111" and IPIPE.D(11 downto 9) < "010" + and IPIPE.D(5 downto 3) = "111" and IPIPE.D(2 downto 0) < "101" then + OP_I <= MOVE; + elsif IPIPE.D(8 downto 6) = "111" and IPIPE.D(11 downto 9) < "010" and IPIPE.D(5 downto 3) /= "111" then + OP_I <= MOVE; + elsif IPIPE.D(8 downto 6) = "001" and IPIPE.D(5 downto 3) = "111" and IPIPE.D(2 downto 0) < "101" then + OP_I <= MOVEA; + elsif IPIPE.D(8 downto 6) = "001" and IPIPE.D(5 downto 3) /= "111" then + OP_I <= MOVEA; + elsif IPIPE.D(8 downto 6) /= "001" and IPIPE.D(8 downto 6) /= "111" and IPIPE.D(5 downto 3) = "111" and IPIPE.D(2 downto 0) < "101" then + OP_I <= MOVE; + elsif IPIPE.D(8 downto 6) /= "001" and IPIPE.D(8 downto 6) /= "111" and IPIPE.D(5 downto 3) /= "111" then + OP_I <= MOVE; + end if; + when x"4" => -- Miscellaneous. + if IPIPE.D(11 downto 0) = x"E70" then + OP_I <= RESET; + elsif IPIPE.D(11 downto 0) = x"E71" then + OP_I <= NOP; + elsif IPIPE.D(11 downto 0) = x"E72" then + OP_I <= STOP; + elsif IPIPE.D(11 downto 0) = x"E73" then + OP_I <= RTE; + elsif IPIPE.D(11 downto 0) = x"E74" and K6800n = '1' then + OP_I <= RTD; + elsif IPIPE.D(11 downto 0) = x"E75" then + OP_I <= RTS; + elsif IPIPE.D(11 downto 0) = x"E76" then + OP_I <= TRAPV; + elsif IPIPE.D(11 downto 0) = x"E77" then + OP_I <= RTR; + elsif IPIPE.D(11 downto 0) = x"AFC" then + OP_I <= ILLEGAL; + elsif IPIPE.D(11 downto 1) = "11100111101" and IPIPE.C(11 downto 0) = x"000" and K6800n = '1' then + OP_I <= MOVEC; + elsif IPIPE.D(11 downto 1) = "11100111101" and IPIPE.C(11 downto 0) = x"001" and K6800n = '1' then + OP_I <= MOVEC; + elsif IPIPE.D(11 downto 1) = "11100111101" and IPIPE.C(11 downto 0) = x"800" and K6800n = '1' then + OP_I <= MOVEC; + elsif IPIPE.D(11 downto 1) = "11100111101" and IPIPE.C(11 downto 0) = x"801" and K6800n = '1' then + OP_I <= MOVEC; + elsif IPIPE.D(11 downto 1) = "11100111101" then + OP_I <= ILLEGAL; -- Not valid MOVEC patterns. + elsif IPIPE.D(11 downto 3) = "100001001" and K6800n = '1' then -- 68K10. + OP_I <= BKPT; + elsif IPIPE.D(11 downto 3) = "111001010" then + OP_I <= LINK; -- WORD. + elsif IPIPE.D(11 downto 3) = "111001011" then + OP_I <= UNLK; + elsif IPIPE.D(11 downto 3) = "100001000" then + OP_I <= SWAP; + elsif IPIPE.D(11 downto 4) = x"E4" then + OP_I <= TRAP; + elsif IPIPE.D(11 downto 4) = x"E6" then + OP_I <= MOVE_USP; + else + case IPIPE.D(5 downto 3) is -- Addressing mode. + when "000" | "010" | "011" | "100" | "101" | "110" => + if IPIPE.D(11 downto 6) = "110001" then + if IPIPE.C(11) = '1' then + OP_I <= DIVS; -- Long. + else + OP_I <= DIVU; -- Long. + end if; + elsif IPIPE.D(11 downto 6) = "001011" and K6800n = '1' then + OP_I <= MOVE_FROM_CCR; + elsif IPIPE.D(11 downto 6) = "000011" then + OP_I <= MOVE_FROM_SR; + elsif IPIPE.D(11 downto 6) = "010011" then + OP_I <= MOVE_TO_CCR; + elsif IPIPE.D(11 downto 6) = "011011" then + OP_I <= MOVE_TO_SR; + elsif IPIPE.D(11 downto 6) = "110000" then + if IPIPE.C(11) = '1' then + OP_I <= MULS; -- Long. + else + OP_I <= MULU; -- Long. + end if; + elsif IPIPE.D(11 downto 6) = "100000" then + OP_I <= NBCD; + elsif IPIPE.D(11 downto 6) = "101011" then + OP_I <= TAS; + end if; + when "111" => -- Not all registers are valid for this mode. + if IPIPE.D(11 downto 6) = "110001" and IPIPE.D(2 downto 0) < "101" then + if IPIPE.C(11) = '1' then + OP_I <= DIVS; -- Long. + else + OP_I <= DIVU; -- Long. + end if; + elsif IPIPE.D(11 downto 6) = "001011" and IPIPE.D(2 downto 0) < "010" and K6800n = '1' then + OP_I <= MOVE_FROM_CCR; + elsif IPIPE.D(11 downto 6) = "000011" and IPIPE.D(2 downto 0) < "010" then + OP_I <= MOVE_FROM_SR; + elsif IPIPE.D(11 downto 6) = "010011" and IPIPE.D(2 downto 0) < "101" then + OP_I <= MOVE_TO_CCR; + elsif IPIPE.D(11 downto 6) = "011011" and IPIPE.D(2 downto 0) < "101" then + OP_I <= MOVE_TO_SR; + elsif IPIPE.D(11 downto 6) = "110000" and IPIPE.D(2 downto 0) < "101" then + if IPIPE.C(11) = '1' then + OP_I <= MULS; -- Long. + else + OP_I <= MULU; -- Long. + end if; + elsif IPIPE.D(11 downto 6) = "100000" and IPIPE.D(2 downto 0) < "010" then + OP_I <= NBCD; + elsif IPIPE.D(11 downto 6) = "101011" and IPIPE.D(2 downto 0) < "010" then + OP_I <= TAS; + end if; + when others => + null; + end case; + + case IPIPE.D(5 downto 3) is -- Addressing mode. + when "010" | "101" | "110" => + if IPIPE.D(11 downto 6) = "100001" then + OP_I <= PEA; + elsif IPIPE.D(11 downto 6) = "111010" then + OP_I <= JSR; + elsif IPIPE.D(11 downto 6) = "111011" then + OP_I <= JMP; + end if; + when "111" => -- Not all registers are valid for this mode. + if IPIPE.D(11 downto 6) = "100001" and IPIPE.D(2 downto 0) < "100" then + OP_I <= PEA; + elsif IPIPE.D(11 downto 6) = "111010" and IPIPE.D(2 downto 0) < "100" then + OP_I <= JSR; + elsif IPIPE.D(11 downto 6) = "111011" and IPIPE.D(2 downto 0) < "100" then + OP_I <= JMP; + end if; + when others => + null; + end case; + + -- For the following operation codes a SIZE (IPIPE.D(7 downto 6)) is not valid. + -- For the following operation codes an addressing mode x"001" is not valid. + if IPIPE.D(7 downto 6) < "11" and IPIPE.D(5 downto 3) /= "001" and IPIPE.D(5 downto 3) /= "111" then + case IPIPE.D(11 downto 8) is + when x"0" => OP_I <= NEGX; + when x"2" => OP_I <= CLR; + when x"4" => OP_I <= NEG; + when x"6" => OP_I <= NOT_B; + when others => null; + end case; + -- Not all registers are valid for the addressing mode "111": + elsif IPIPE.D(7 downto 6) < "11" and IPIPE.D(5 downto 3) = "111" and IPIPE.D(2 downto 0) < "010" then + case IPIPE.D(11 downto 8) is + when x"0" => OP_I <= NEGX; + when x"2" => OP_I <= CLR; + when x"4" => OP_I <= NEG; + when x"6" => OP_I <= NOT_B; + when others => null; + end case; + end if; + + if IPIPE.D(11 downto 8) = x"A" and IPIPE.D(7 downto 6) < "11" and IPIPE.D(5 downto 3) = "111" and (IPIPE.D(2 downto 0) < "010" or IPIPE.D(2 downto 0) = "100") then -- 68K + -- if IPIPE.D(11 downto 8) = x"A" and IPIPE.D(7 downto 6) < "11" and IPIPE.D(5 downto 3) = "111" and IPIPE.D(2 downto 0) < "101" then -- 68K20 and up. + OP_I <= TST; -- For the 68K00 the byte addressing mode on address register direst is allowed. + elsif IPIPE.D(11 downto 8) = x"A" and IPIPE.D(7 downto 6) < "11" and IPIPE.D(5 downto 3) /= "111" then + case IPIPE.D(7 downto 6) is + when "01" | "10" => OP_I <= TST; -- Long or word, all addressing modes. + when others => -- Byte: Address register direct not allowed. + if IPIPE.D(5 downto 3) /= "001" then + OP_I <= TST; + end if; + end case; + end if; + + if IPIPE.D(11 downto 9) = "100" and IPIPE.D(5 downto 3) = "000" then + case IPIPE.D(8 downto 6) is -- Valid OPMODES for this operation code. + when "010" | "011" => OP_I <= EXT; + when others => null; + end case; + end if; + + if IPIPE.D(8 downto 6) = "111" then + case IPIPE.D(5 downto 3) is -- OPMODES. + when "010" | "101" | "110" => + OP_I <= LEA; + when "111" => + if IPIPE.D(2 downto 0) < "100" then -- Not all registers are valid for this OPMODE. + OP_I <= LEA; + end if; + when others => null; + end case; + end if; + + if IPIPE.D(11) = '1' and IPIPE.D(9 downto 7) = "001" then + if IPIPE.D(10) = '0' then -- Register to memory transfer. + case IPIPE.D(5 downto 3) is -- OPMODES, no postincrement addressing. + when "010" | "100" | "101" | "110" => + OP_I <= MOVEM; + when "111" => + if IPIPE.D(2 downto 0) = "000" or IPIPE.D(2 downto 0) = "001" then + OP_I <= MOVEM; + end if; + when others => null; + end case; + else -- Memory to register transfer, no predecrement addressing. + case IPIPE.D(5 downto 3) is -- OPMODES. + when "010" | "011" | "101" | "110" => + OP_I <= MOVEM; + when "111" => + if IPIPE.D(2 downto 0) < "100" then + OP_I <= MOVEM; + end if; + when others => null; + end case; + end if; + end if; + + -- The size must be "11" and the OPMODE may not be "001". + if IPIPE.D(8 downto 7) = "11" and IPIPE.D(6 downto 3) = x"7" and IPIPE.D(2 downto 0) < "101" then + OP_I <= CHK; -- CHK is WORD wide for the 68K10 and 68K00. + elsif IPIPE.D(8 downto 7) = "11" and IPIPE.D(6 downto 3) /= x"1" and IPIPE.D(6 downto 3) < x"7" then + OP_I <= CHK; -- CHK is WORD wide for the 68K10 and 68K00. + end if; + end if; + when x"5" => -- ADDQ / SUBQ / Scc / DBcc. + if IPIPE.D(7 downto 3) = "11001" then + OP_I <= DBcc; + elsif IPIPE.D(7 downto 6) = "11" and IPIPE.D(5 downto 3) = "111" and IPIPE.D(2 downto 0) < "010" then + OP_I <= Scc; + elsif IPIPE.D(7 downto 6) = "11" and IPIPE.D(5 downto 3) /= "001" and IPIPE.D(5 downto 3) /= "111" then + OP_I <= Scc; + -- + elsif IPIPE.D(8) = '0' and IPIPE.D(7 downto 6) < "11" and IPIPE.D(5 downto 3) = "111" and IPIPE.D(2 downto 0) < "010" then + OP_I <= ADDQ; + elsif IPIPE.D(8) = '0' and (IPIPE.D(7 downto 6) = "01" or IPIPE.D(7 downto 6) = "10") and IPIPE.D(5 downto 3) /= "111" then + OP_I <= ADDQ; + elsif IPIPE.D(8) = '0' and IPIPE.D(7 downto 6) = "00" and IPIPE.D(5 downto 3) /= "001" and IPIPE.D(5 downto 3) /= "111" then + OP_I <= ADDQ; + -- + elsif IPIPE.D(8) = '1' and IPIPE.D(7 downto 6) < "11" and IPIPE.D(5 downto 3) = "111" and IPIPE.D(2 downto 0) < "010" then + OP_I <= SUBQ; + elsif IPIPE.D(8) = '1' and (IPIPE.D(7 downto 6) = "01" or IPIPE.D(7 downto 6) = "10") and IPIPE.D(5 downto 3) /= "111" then + OP_I <= SUBQ; + elsif IPIPE.D(8) = '1' and IPIPE.D(7 downto 6) = "00" and IPIPE.D(5 downto 3) /= "001" and IPIPE.D(5 downto 3) /= "111" then + OP_I <= SUBQ; + end if; + when x"6" => -- Bcc / BSR / BRA. + if IPIPE.D(11 downto 8) = x"0" then + OP_I <= BRA; + elsif IPIPE.D(11 downto 8) = x"1" then + OP_I <= BSR; + else + OP_I <= Bcc; + end if; + when x"7" => -- MOVEQ. + if IPIPE.D(8) = '0' then + OP_I <= MOVEQ; + end if; + when x"8" => -- OR / DIV / SBCD. + if IPIPE.D(8 downto 6) = "011" and IPIPE.D(5 downto 3) = "111" and IPIPE.D(2 downto 0) < "101" then + OP_I <= DIVU; -- WORD. + elsif IPIPE.D(8 downto 6) = "011" and IPIPE.D(5 downto 3) /= "001" and IPIPE.D(5 downto 3) /= "111" then + OP_I <= DIVU; -- WORD. + elsif IPIPE.D(8 downto 6) = "111" and IPIPE.D(5 downto 3) = "111" and IPIPE.D(2 downto 0) < "101" then + OP_I <= DIVS; -- WORD. + elsif IPIPE.D(8 downto 6) = "111" and IPIPE.D(5 downto 3) /= "001" and IPIPE.D(5 downto 3) /= "111" then + OP_I <= DIVS; -- WORD. + elsif IPIPE.D(8 downto 4) = "10000" then + OP_I <= SBCD; + end if; + -- + case IPIPE.D(8 downto 6) is + when "000" | "001" | "010" => + if IPIPE.D(5 downto 3) = "111" and IPIPE.D(2 downto 0) < "101" then + OP_I <= OR_B; + elsif IPIPE.D(5 downto 3) /= "001" and IPIPE.D(5 downto 3) /= "111" then + OP_I <= OR_B; + end if; + when "100" | "101" | "110" => + if IPIPE.D(5 downto 3) = "111" and IPIPE.D(2 downto 0) < "010" then + OP_I <= OR_B; + elsif IPIPE.D(5 downto 3) > "001" and IPIPE.D(5 downto 3) /= "111" then + OP_I <= OR_B; + end if; + when others => + null; + end case; + when x"9" => -- SUB / SUBX. + case IPIPE.D(8 downto 6) is + when "000" => -- Byte size. + if IPIPE.D(5 downto 3) = "111" and IPIPE.D(2 downto 0) < "101" then + OP_I <= SUB; + elsif IPIPE.D(5 downto 3) /= "111" and IPIPE.D(5 downto 3) /= "001" then + OP_I <= SUB; + end if; + when "001" | "010" => -- Word and long. + if IPIPE.D(5 downto 3) = "111" and IPIPE.D(2 downto 0) < "101" then + OP_I <= SUB; + elsif IPIPE.D(5 downto 3) /= "111" then + OP_I <= SUB; + end if; + when "100" => + if IPIPE.D(5 downto 3) = "000" or IPIPE.D(5 downto 3) = "001" then + OP_I <= SUBX; + elsif IPIPE.D(5 downto 3) = "111" and IPIPE.D(2 downto 0) < "010" then + OP_I <= SUB; + elsif IPIPE.D(5 downto 3) /= "111" and IPIPE.D(5 downto 3) /= "001" then -- Byte size. + OP_I <= SUB; + end if; + when "101" | "110" => + if IPIPE.D(5 downto 3) = "000" or IPIPE.D(5 downto 3) = "001" then + OP_I <= SUBX; + elsif IPIPE.D(5 downto 3) = "111" and IPIPE.D(2 downto 0) < "010" then + OP_I <= SUB; + elsif IPIPE.D(5 downto 3) /= "111" then -- Word and long. + OP_I <= SUB; + end if; + when "011" | "111" => + if IPIPE.D(5 downto 3) = "111" and IPIPE.D(2 downto 0) < "101" then + OP_I <= SUBA; + elsif IPIPE.D(5 downto 3) /= "111" then + OP_I <= SUBA; + end if; + when others => -- U, X, Z, W, H, L, -. + null; + end case; + when x"A" => -- (1010, Unassigned, Reserved). + OP_I <= UNIMPLEMENTED; + when x"B" => -- CMP / EOR. + if IPIPE.D(8) = '1' and IPIPE.D(7 downto 6) < "11" and IPIPE.D(5 downto 3) = "001" then + OP_I <= CMPM; + else + case IPIPE.D(8 downto 6) is -- OPMODE field. + when "000" => + if IPIPE.D(5 downto 3) = "111" and IPIPE.D(2 downto 0) < "101" then + OP_I <= CMP; + elsif IPIPE.D(5 downto 3) /= "001" and IPIPE.D(5 downto 3) /= "111" then + OP_I <= CMP; + end if; + when "001" | "010" => + if IPIPE.D(5 downto 3) = "111" and IPIPE.D(2 downto 0) < "101" then + OP_I <= CMP; + elsif IPIPE.D(5 downto 3) /= "111" then + OP_I <= CMP; + end if; + when "011" | "111" => + if IPIPE.D(5 downto 3) = "111" and IPIPE.D(2 downto 0) < "101" then + OP_I <= CMPA; + elsif IPIPE.D(5 downto 3) /= "111" then + OP_I <= CMPA; + end if; + when "100" | "101" | "110" => + if IPIPE.D(5 downto 3) = "111" and IPIPE.D(2 downto 0) < "101" then + OP_I <= EOR; + elsif IPIPE.D(5 downto 3) /= "001" and IPIPE.D(5 downto 3) /= "111" then + OP_I <= EOR; + end if; + when others => -- U, X, Z, W, H, L, -. + null; + end case; + end if; + when x"C" => -- AND / MUL / ABCD / EXG. + if IPIPE.D(8 downto 4) = "10000" then + OP_I <= ABCD; + elsif IPIPE.D(8 downto 6) = "011" and IPIPE.D(5 downto 3) = "111" and IPIPE.D(2 downto 0) < "101" then + OP_I <= MULU; -- WORD. + elsif IPIPE.D(8 downto 6) = "011" and IPIPE.D(5 downto 3) /= "001" and IPIPE.D(5 downto 3) /= "111" then + OP_I <= MULU; -- WORD. + elsif IPIPE.D(8 downto 6) = "111" and IPIPE.D(5 downto 3) = "111" and IPIPE.D(2 downto 0) < "101" then + OP_I <= MULS; -- WORD. + elsif IPIPE.D(8 downto 6) = "111" and IPIPE.D(5 downto 3) /= "001" and IPIPE.D(5 downto 3) /= "111" then + OP_I <= MULS; -- WORD. + elsif IPIPE.D(8 downto 3) = "101000" or IPIPE.D(8 downto 3) = "101001" or IPIPE.D(8 downto 3) = "110001" then + OP_I <= EXG; + else + case IPIPE.D(8 downto 6) is -- OPMODE + when "000" | "001" | "010" => + if IPIPE.D(5 downto 3) = "111" and IPIPE.D(2 downto 0) < "101" then + OP_I <= AND_B; + elsif IPIPE.D(5 downto 3) /= "001" and IPIPE.D(5 downto 3) /= "111" then + OP_I <= AND_B; + end if; + when "100" | "101" | "110" => + if IPIPE.D(5 downto 3) = "111" and IPIPE.D(2 downto 0) < "010" then + OP_I <= AND_B; + elsif IPIPE.D(5 downto 3) > "001" and IPIPE.D(5 downto 3) /= "111" then + OP_I <= AND_B; + end if; + when others => + null; + end case; + end if; + when x"D" => -- ADD / ADDX. + case IPIPE.D(8 downto 6) is + when "000" => + if IPIPE.D(5 downto 3) = "111" and IPIPE.D(2 downto 0) < "101" then + OP_I <= ADD; + elsif IPIPE.D(5 downto 3) /= "111" and IPIPE.D(5 downto 3) /= "001" then + OP_I <= ADD; + end if; + when "001" | "010" => + if IPIPE.D(5 downto 3) = "111" and IPIPE.D(2 downto 0) < "101" then + OP_I <= ADD; + elsif IPIPE.D(5 downto 3) /= "111" then + OP_I <= ADD; + end if; + when "100" => + if IPIPE.D(5 downto 3) = "000" or IPIPE.D(5 downto 3) = "001" then + OP_I <= ADDX; + elsif IPIPE.D(5 downto 3) = "111" and IPIPE.D(2 downto 0) < "010" then + OP_I <= ADD; + elsif IPIPE.D(5 downto 3) /= "111" and IPIPE.D(5 downto 3) /= "001" then + OP_I <= ADD; + end if; + when "101" | "110" => + if IPIPE.D(5 downto 3) = "000" or IPIPE.D(5 downto 3) = "001" then + OP_I <= ADDX; + elsif IPIPE.D(5 downto 3) = "111" and IPIPE.D(2 downto 0) < "010" then + OP_I <= ADD; + elsif IPIPE.D(5 downto 3) /= "111" then + OP_I <= ADD; + end if; + when "011" | "111" => + if IPIPE.D(5 downto 3) = "111" and IPIPE.D(2 downto 0) < "101" then + OP_I <= ADDA; + elsif IPIPE.D(5 downto 3) /= "111" then + OP_I <= ADDA; + end if; + when others => -- U, X, Z, W, H, L, -. + null; + end case; + when x"E" => -- Shift / Rotate. + if IPIPE.D(11 downto 6) = "000011" and IPIPE.D(5 downto 3) = "111" and IPIPE.D(2 downto 0) < "010" then + OP_I <= ASR; -- Memory shifts. + elsif IPIPE.D(11 downto 6) = "000011" and IPIPE.D(5 downto 3) > "001" and IPIPE.D(5 downto 3) /= "111" then + OP_I <= ASR; -- Memory shifts. + elsif IPIPE.D(11 downto 6) = "000111" and IPIPE.D(5 downto 3) = "111" and IPIPE.D(2 downto 0) < "010" then + OP_I <= ASL; -- Memory shifts. + elsif IPIPE.D(11 downto 6) = "000111" and IPIPE.D(5 downto 3) > "001" and IPIPE.D(5 downto 3) /= "111" then + OP_I <= ASL; -- Memory shifts. + elsif IPIPE.D(11 downto 6) = "001011" and IPIPE.D(5 downto 3) = "111" and IPIPE.D(2 downto 0) < "010" then + OP_I <= LSR; -- Memory shifts. + elsif IPIPE.D(11 downto 6) = "001011" and IPIPE.D(5 downto 3) > "001" and IPIPE.D(5 downto 3) /= "111" then + OP_I <= LSR; -- Memory shifts. + elsif IPIPE.D(11 downto 6) = "001111" and IPIPE.D(5 downto 3) = "111" and IPIPE.D(2 downto 0) < "010" then + OP_I <= LSL; -- Memory shifts. + elsif IPIPE.D(11 downto 6) = "001111" and IPIPE.D(5 downto 3) > "001" and IPIPE.D(5 downto 3) /= "111" then + OP_I <= LSL; -- Memory shifts. + elsif IPIPE.D(11 downto 6) = "010011" and IPIPE.D(5 downto 3) = "111" and IPIPE.D(2 downto 0) < "010" then + OP_I <= ROXR; -- Memory shifts. + elsif IPIPE.D(11 downto 6) = "010011" and IPIPE.D(5 downto 3) > "001" and IPIPE.D(5 downto 3) /= "111" then + OP_I <= ROXR; -- Memory shifts. + elsif IPIPE.D(11 downto 6) = "010111" and IPIPE.D(5 downto 3) = "111" and IPIPE.D(2 downto 0) < "010" then + OP_I <= ROXL; -- Memory shifts. + elsif IPIPE.D(11 downto 6) = "010111" and IPIPE.D(5 downto 3) > "001" and IPIPE.D(5 downto 3) /= "111" then + OP_I <= ROXL; -- Memory shifts. + elsif IPIPE.D(11 downto 6) = "011011" and IPIPE.D(5 downto 3) = "111" and IPIPE.D(2 downto 0) < "010" then + OP_I <= ROTR; -- Memory shifts. + elsif IPIPE.D(11 downto 6) = "011011" and IPIPE.D(5 downto 3) > "001" and IPIPE.D(5 downto 3) /= "111" then + OP_I <= ROTR; -- Memory shifts. + elsif IPIPE.D(11 downto 6) = "011111" and IPIPE.D(5 downto 3) = "111" and IPIPE.D(2 downto 0) < "010" then + OP_I <= ROTL; -- Memory shifts. + elsif IPIPE.D(11 downto 6) = "011111" and IPIPE.D(5 downto 3) > "001" and IPIPE.D(5 downto 3) /= "111" then + OP_I <= ROTL; -- Memory shifts. + elsif IPIPE.D(8) = '0' and IPIPE.D(7 downto 6) < "11" and IPIPE.D(4 downto 3) = "00" then + OP_I <= ASR; -- Register shifts. + elsif IPIPE.D(8) = '1' and IPIPE.D(7 downto 6) < "11" and IPIPE.D(4 downto 3) = "00" then + OP_I <= ASL; -- Register shifts. + elsif IPIPE.D(8) = '0' and IPIPE.D(7 downto 6) < "11" and IPIPE.D(4 downto 3) = "01" then + OP_I <= LSR; -- Register shifts. + elsif IPIPE.D(8) = '1' and IPIPE.D(7 downto 6) < "11" and IPIPE.D(4 downto 3) = "01" then + OP_I <= LSL; -- Register shifts. + elsif IPIPE.D(8) = '0' and IPIPE.D(7 downto 6) < "11" and IPIPE.D(4 downto 3) = "10" then + OP_I <= ROXR; -- Register shifts. + elsif IPIPE.D(8) = '1' and IPIPE.D(7 downto 6) < "11" and IPIPE.D(4 downto 3) = "10" then + OP_I <= ROXL; -- Register shifts. + elsif IPIPE.D(8) = '0' and IPIPE.D(7 downto 6) < "11" and IPIPE.D(4 downto 3) = "11" then + OP_I <= ROTR; -- Register shifts. + elsif IPIPE.D(8) = '1' and IPIPE.D(7 downto 6) < "11" and IPIPE.D(4 downto 3) = "11" then + OP_I <= ROTL; -- Register shifts. + end if; + when x"F" => -- 1111, Coprocessor Interface / 68K40 Extensions. + OP_I <= UNIMPLEMENTED; + when others => -- U, X, Z, W, H, L, -. + null; + end case; + end process OP_DECODE; +end BEHAVIOR; diff --git a/common/CPU/68K10/wf68k10_pkg.vhd b/common/CPU/68K10/wf68k10_pkg.vhd new file mode 100644 index 00000000..ee6c7b59 --- /dev/null +++ b/common/CPU/68K10/wf68k10_pkg.vhd @@ -0,0 +1,413 @@ +------------------------------------------------------------------------ +---- ---- +---- WF68K10 IP Core: this is the package file containing the data ---- +---- types and the component declarations. ---- +---- ---- +---- Author(s): ---- +---- Wolfgang Foerster, wf@experiment-s.de; wf@inventronik.de ---- +---- ---- +------------------------------------------------------------------------ +---- ---- +---- Copyright © 2014-2019 Wolfgang Foerster Inventronik GmbH. ---- +---- ---- +---- This documentation describes Open Hardware and is licensed ---- +---- under the CERN OHL v. 1.2. You may redistribute and modify ---- +---- this documentation under the terms of the CERN OHL v.1.2. ---- +---- (http://ohwr.org/cernohl). This documentation is distributed ---- +---- WITHOUT ANY EXPRESS OR IMPLIED WARRANTY, INCLUDING OF ---- +---- MERCHANTABILITY, SATISFACTORY QUALITY AND FITNESS FOR A ---- +---- PARTICULAR PURPOSE. Please see the CERN OHL v.1.2 for ---- +---- applicable conditions ---- +---- ---- +------------------------------------------------------------------------ +-- +-- Revision History +-- +-- Revision 2K14B 20141201 WF +-- Initial Release. +-- Later revisions +-- Modifications according to changes of the entity in other modules. +-- + +library ieee; +use ieee.std_logic_1164.all; + +package WF68K10_PKG is +type OP_SIZETYPE is (LONG, WORD, BYTE); +-- The OPCODES AND, NOT, OR, ROR and ROL are defined keywords in VHDL. Therefore the assignment is +-- AND_B, NOT_B, OR_B, ROTR and ROTL. +type OP_68K is (ABCD, ADD, ADDA, ADDI, ADDQ, ADDX, AND_B, ANDI, ANDI_TO_CCR, ANDI_TO_SR, ASL, ASR, Bcc, BCHG, BCLR, + BKPT, BRA, BSET, BSR, BTST, CHK, CLR, CMP, CMPA, CMPI, CMPM, DBcc, DIVS, DIVU, EOR, EORI, EORI_TO_CCR, + EORI_TO_SR, EXG, EXT, ILLEGAL, JMP, JSR, LEA, LINK, LSL, LSR, MOVE, MOVE_FROM_CCR, MOVE_TO_CCR, + MOVE_FROM_SR, MOVE_TO_SR, MOVE_USP, MOVEA, MOVEC, MOVEM, MOVEP, MOVEQ, MOVES, MULS, MULU, NBCD, NEG, + NEGX, NOP, NOT_B, OR_B, ORI, ORI_TO_CCR, ORI_TO_SR, PEA, RESET, ROTL, ROTR, ROXL, ROXR, RTD, + RTE, RTR, RTS, SBCD, Scc, STOP, SUB, SUBA, SUBI, SUBQ, SUBX, SWAP, TAS, TRAP, TRAPV, TST, + UNLK, UNIMPLEMENTED); + +type TRAPTYPE_OPC is(NONE, T_1010, T_1111, T_ILLEGAL, T_TRAP, T_PRIV, T_RTE); -- None is the first entry and default. + +component WF68K10_ADDRESS_REGISTERS + port ( + CLK : in std_logic; + RESET : in bit; + AR_IN_1 : in std_logic_vector(31 downto 0); + AR_IN_2 : in std_logic_vector(31 downto 0); + AR_OUT_1 : out std_logic_vector(31 downto 0); + AR_OUT_2 : out std_logic_vector(31 downto 0); + INDEX_IN : in std_logic_vector(31 downto 0); + PC : out std_logic_vector(31 downto 0); + PC_EW_OFFSET : in std_logic_vector(3 downto 0); + STORE_ADR_FORMAT : in bit; + STORE_ABS_HI : in bit; + STORE_ABS_LO : in bit; + STORE_D16 : in bit; + STORE_DISPL : in bit; + STORE_AEFF : in bit; + OP_SIZE : in OP_SIZETYPE; + ADR_OFFSET : in std_logic_vector(31 downto 0); + ADR_MARK_USED : in bit; + ADR_IN_USE : out bit; + ADR_MODE : in std_logic_vector(2 downto 0); + AMODE_SEL : in std_logic_vector(2 downto 0); + ADR_EFF : out std_logic_vector(31 downto 0); + ADR_EFF_WB : out std_logic_vector(31 downto 0); + DFC : out std_logic_vector(2 downto 0); + DFC_WR : in bit; + SFC : out std_logic_vector(2 downto 0); + SFC_WR : in bit; + ISP_DEC : in bit; + ISP_WR : in bit; + USP_RD : in bit; + USP_WR : in bit; + AR_MARK_USED : in bit; + USE_APAIR : in boolean; + AR_IN_USE : out bit; + AR_SEL_RD_1 : in std_logic_vector(2 downto 0); + AR_SEL_RD_2 : in std_logic_vector(2 downto 0); + AR_SEL_WR_1 : in std_logic_vector(2 downto 0); + AR_SEL_WR_2 : in std_logic_vector(2 downto 0); + AR_DEC : in bit; + AR_INC : in bit; + AR_WR_1 : in bit; + AR_WR_2 : in bit; + UNMARK : in bit; + EXT_WORD : in std_logic_vector(15 downto 0); + SBIT : in std_logic; + SP_ADD_DISPL : in bit; + RESTORE_ISP_PC : in bit; + DISPLACEMENT : in std_logic_vector(31 downto 0); + PC_ADD_DISPL : in bit; + PC_INC : in bit; + PC_LOAD : in bit; + PC_RESTORE : in bit; + PC_OFFSET : in std_logic_vector(7 downto 0) + ); +end component; + +component WF68K10_ALU + port ( + CLK : in std_logic; + RESET : in bit; + LOAD_OP1 : in bit; + LOAD_OP2 : in bit; + LOAD_OP3 : in bit; + OP1_IN : in std_logic_vector(31 downto 0); + OP2_IN : in std_logic_vector(31 downto 0); + OP3_IN : in std_logic_vector(31 downto 0); + BITPOS_IN : in Std_Logic_Vector(4 downto 0); + RESULT : out std_logic_vector(63 downto 0); + ADR_MODE_IN : in std_logic_vector(2 downto 0); + OP_SIZE_IN : in OP_SIZETYPE; + OP_IN : in OP_68K; + OP_WB : in OP_68K; + BIW_0_IN : in std_logic_vector(11 downto 0); + BIW_1_IN : in std_logic_vector(15 downto 0); + SR_WR : in bit; + SR_INIT : in bit; + CC_UPDT : in bit; + STATUS_REG_OUT : out std_logic_vector(15 downto 0); + ALU_COND : out boolean; + ALU_INIT : in bit; + ALU_BSY : out bit; + ALU_REQ : out bit; + ALU_ACK : in bit; + IRQ_PEND : in std_logic_vector(2 downto 0); + TRAP_CHK : out bit; + TRAP_DIVZERO : out bit + ); +end component; + +component WF68K10_BUS_INTERFACE + port ( + CLK : in std_logic; + ADR_IN_P : in std_logic_vector(31 downto 0); + ADR_OUT_P : out std_logic_vector(31 downto 0); + FC_IN : in std_logic_vector(2 downto 0); + FC_OUT : out std_logic_vector(2 downto 0); + DATA_PORT_IN : in std_logic_vector(15 downto 0); + DATA_PORT_OUT : out std_logic_vector(15 downto 0); + DATA_FROM_CORE : in std_logic_vector(31 downto 0); + DATA_TO_CORE : out std_logic_vector(31 downto 0); + OPCODE_TO_CORE : out std_logic_vector(15 downto 0); + DATA_PORT_EN : out std_logic; + BUS_EN : out std_logic; + OP_SIZE : in OP_SIZETYPE; + RD_REQ : in bit; + WR_REQ : in bit; + DATA_RDY : out bit; + DATA_VALID : out std_logic; + OPCODE_REQ : in bit; + OPCODE_RDY : out bit; + OPCODE_VALID : out std_logic; + RMC : in bit; + BUSY_EXH : in bit; + INBUFFER : out std_logic_vector(31 downto 0); + OUTBUFFER : out std_logic_vector(31 downto 0); + SSW : out std_logic_vector(15 downto 0); + DTACKn : in std_logic; + ASn : out std_logic; + UDSn : out std_logic; + LDSn : out std_logic; + RWn : out std_logic; + RMCn : out std_logic; + DBENn : out std_logic; + E : out std_logic; + VMAn : out std_logic; + VMA_EN : out std_logic; + VPAn : in std_logic; + BRn : in std_logic; + BGACKn : in std_logic; + BGn : out std_logic; + RESET_STRB : in bit; + RESET_IN : in std_logic; + RESET_OUT : out std_logic; + RESET_CPU : out bit; + AVECn : in std_logic; + HALTn : in std_logic; + BERRn : in std_logic; + AERR : out bit; + BUS_BSY : out bit + ); +end component; + +component WF68K10_CONTROL + generic(NO_PIPELINE : boolean := false); -- If true the controller work in scalar mode. + port( + CLK : in std_logic; + RESET_CPU : in bit; + BUSY : out bit; + BUSY_EXH : in bit; + EXH_REQ : in bit; + INT_TRIG : out bit; + OW_REQ : out bit; + OW_VALID : in std_logic; + EW_REQ : out bit; + EW_ACK : in bit; + OPD_ACK : in bit; + ADR_MARK_USED : out bit; + ADR_IN_USE : in bit; + ADR_OFFSET : out std_logic_vector(5 downto 0); + DATA_RD : out bit; + DATA_WR : out bit; + DATA_RDY : in bit; + DATA_VALID : in std_logic; + RMC : out bit; + LOAD_OP2 : out bit; + LOAD_OP3 : out bit; + LOAD_OP1 : out bit; + STORE_ADR_FORMAT : out bit; + STORE_D16 : out bit; + STORE_DISPL : out bit; + STORE_ABS_HI : out bit; + STORE_ABS_LO : out bit; + STORE_AEFF : out bit; + STORE_IDATA_B2 : out bit; + STORE_IDATA_B1 : out bit; + OP : in OP_68K; + OP_SIZE : out OP_SIZETYPE; + BIW_0 : in std_logic_vector(13 downto 0); + BIW_1 : in std_logic_vector(15 downto 0); + EXT_WORD : in std_logic_vector(15 downto 0); + ADR_MODE : out std_logic_vector(2 downto 0); + AMODE_SEL : out std_logic_vector(2 downto 0); + OP_WB : out OP_68K; + OP_SIZE_WB : out OP_SIZETYPE; + BIW_0_WB_73 : out std_logic_vector(7 downto 3); + AR_MARK_USED : out bit; + USE_APAIR : out boolean; + AR_IN_USE : in bit; + AR_SEL_RD_1 : out std_logic_vector(2 downto 0); + AR_SEL_RD_2 : out std_logic_vector(2 downto 0); + AR_SEL_WR_1 : out std_logic_vector(2 downto 0); + AR_SEL_WR_2 : out std_logic_vector(2 downto 0); + AR_INC : out bit; + AR_DEC : out bit; + AR_WR_1 : out bit; + AR_WR_2 : out bit; + DR_MARK_USED : out bit; + USE_DPAIR : out boolean; + DR_IN_USE : in bit; + DR_SEL_RD_1 : out std_logic_vector(2 downto 0); + DR_SEL_RD_2 : out std_logic_vector(2 downto 0); + DR_SEL_WR_1 : out std_logic_vector(2 downto 0); + DR_SEL_WR_2 : out std_logic_vector(2 downto 0); + DR_WR_1 : out bit; + DR_WR_2 : out bit; + UNMARK : out bit; + DISPLACEMENT : out std_logic_vector(31 downto 0); + PC_ADD_DISPL : out bit; + PC_LOAD : out bit; + PC_INC_EXH : in bit; + SP_ADD_DISPL : out bit; + DFC_WR : out bit; + DFC_RD : out bit; + SFC_WR : out bit; + SFC_RD : out bit; + VBR_WR : out bit; + VBR_RD : out bit; + USP_RD : out bit; + USP_WR : out bit; + IPIPE_FLUSH : out bit; + ALU_INIT : out bit; + ALU_BSY : in bit; + ALU_REQ : in bit; + ALU_ACK : out bit; + BKPT_CYCLE : out bit; + BKPT_INSERT : out bit; + LOOP_BSY : in bit; + LOOP_SPLIT : out boolean; + LOOP_EXIT : out bit; + SR_WR : out bit; + MOVEM_ADn : out bit; + MOVEP_PNTR : out integer range 0 to 3; + CC_UPDT : out bit; + TRACE_EN : in std_logic; + ALU_COND : in boolean; + DBcc_COND : in boolean; + BRANCH_ATN : in bit; + RESET_STRB : out bit; + BERR : out bit; + EX_TRACE : out bit; + TRAP_ILLEGAL : out bit; + TRAP_V : out bit + ); +end component; + +component WF68K10_DATA_REGISTERS + port ( + CLK : in std_logic; + RESET : in bit; + DR_IN_1 : in std_logic_vector(31 downto 0); + DR_IN_2 : in std_logic_vector(31 downto 0); + DR_OUT_1 : out std_logic_vector(31 downto 0); + DR_OUT_2 : out std_logic_vector(31 downto 0); + DR_SEL_WR_1 : in std_logic_vector(2 downto 0); + DR_SEL_WR_2 : in std_logic_vector(2 downto 0); + DR_SEL_RD_1 : in std_logic_vector(2 downto 0); + DR_SEL_RD_2 : in std_logic_vector(2 downto 0); + DR_WR_1 : in bit; + DR_WR_2 : in bit; + DR_MARK_USED : in bit; + USE_DPAIR : in boolean; + DR_IN_USE : out bit; + UNMARK : in bit; + OP_SIZE : in OP_SIZETYPE + ); +end component; + +component WF68K10_EXCEPTION_HANDLER + generic(VERSION : std_logic_vector(31 downto 0)); + port ( + CLK : in std_logic; + RESET : in bit; + K6800n : in std_logic; + BUSY_MAIN : in bit; + BUSY_OPD : in bit; + EXH_REQ : out bit; + BUSY_EXH : out bit; + ADR_IN : in std_logic_vector(31 downto 0); + ADR_OFFSET : out std_logic_vector(31 downto 0); + CPU_SPACE : out bit; + DATA_0 : in std_logic; + DATA_RD : out bit; + DATA_WR : out bit; + DATA_IN : in std_logic_vector(31 downto 0); + OP_SIZE : out OP_SIZETYPE; + DATA_RDY : in bit; + DATA_VALID : in std_logic; + OPCODE_RDY : in bit; + STATUS_REG_IN : in std_logic_vector(15 downto 0); + SR_CPY : out std_logic_vector(15 downto 0); + SR_INIT : out bit; + SR_WR : out bit; + ISP_DEC : out bit; + ISP_LOAD : out bit; + PC_INC : out bit; + PC_LOAD : out bit; + PC_RESTORE : out bit; + STACK_FORMAT : out std_logic_vector(3 downto 0); + STACK_POS : out integer range 0 to 31; + SP_ADD_DISPL : out bit; + DISPLACEMENT : out std_logic_vector(7 downto 0); + IPIPE_FILL : out bit; + IPIPE_FLUSH : out bit; + RESTORE_ISP_PC : out bit; + HALT_OUTn : out std_logic; + INT_TRIG : in bit; + IRQ_IN : in std_logic_vector(2 downto 0); + IRQ_PEND : out std_logic_vector(2 downto 0); + AVECn : in std_logic; + IVECT_OFFS : out std_logic_vector(9 downto 0); + TRAP_AERR : in bit; + TRAP_BERR : in bit; + TRAP_CHK : in bit; + TRAP_DIVZERO : in bit; + TRAP_ILLEGAL : in bit; + TRAP_CODE_OPC : in TRAPTYPE_OPC; + TRAP_VECTOR : in std_logic_vector(3 downto 0); + TRAP_V : in bit; + EX_TRACE_IN : in bit; + VBR_WR : in bit; + VBR : out std_logic_vector(31 downto 0) + ); +end component; + +component WF68K10_OPCODE_DECODER + generic(NO_LOOP : boolean := false); -- If true the DBcc loop mechanism is disabled. + port ( + CLK : in std_logic; + K6800n : in std_logic; + OW_REQ_MAIN : in bit; + EW_REQ_MAIN : in bit; + EXH_REQ : in bit; + BUSY_EXH : in bit; + BUSY_MAIN : in bit; + BUSY_OPD : out bit; + BKPT_INSERT : in bit; + BKPT_DATA : in std_logic_vector(15 downto 0); + LOOP_EXIT : in bit; + LOOP_BSY : out bit; + OPD_ACK_MAIN : out bit; + EW_ACK : out bit; + PC_EW_OFFSET : out std_logic_vector(3 downto 0); + PC_INC : out bit; + PC_INC_EXH : in bit; + PC_ADR_OFFSET : out std_logic_vector(7 downto 0); + PC_OFFSET : out std_logic_vector(7 downto 0); + OPCODE_RD : out bit; + OPCODE_RDY : in bit; + OPCODE_VALID : in std_logic; + OPCODE_DATA : in std_logic_vector(15 downto 0); + IPIPE_FILL : in bit; + IPIPE_FLUSH : in bit; + OW_VALID : out std_logic; + SBIT : in std_logic; + TRAP_CODE : out TRAPTYPE_OPC; + OP : out OP_68K; + BIW_0 : out std_logic_vector(15 downto 0); + BIW_1 : out std_logic_vector(15 downto 0); + BIW_2 : out std_logic_vector(15 downto 0); + EXT_WORD : out std_logic_vector(15 downto 0) + ); +end component; +end WF68K10_PKG; diff --git a/common/CPU/68K10/wf68k10_top.vhd b/common/CPU/68K10/wf68k10_top.vhd new file mode 100644 index 00000000..b95b7d56 --- /dev/null +++ b/common/CPU/68K10/wf68k10_top.vhd @@ -0,0 +1,1257 @@ +------------------------------------------------------------------------ +---- ---- +---- This is the top level structural design unit of the 68K10 ---- +---- complex instruction set (CISC) microcontroller. It's program- ---- +---- ming model is (hopefully) fully compatible with Motorola's ---- +---- MC68010. This core features a pipelined architecture. In com- ---- +---- parision to the 68K10 the core supports a 32 bit wide adress ---- +---- bus. The processor generates the stack frame format 0, 2, A, B ---- +---- according to the 68K10 CPU. There is also support for multi- ---- +---- processor environments due to the RMCn signal. In conjunction ---- +---- with the 32 bit wide address bus this core is fully feature ---- +---- complete in comparision to the MC68012 processors. ---- +---- The DIVS, DIVU, MULS, MULU with LONG format is supported by ---- +---- this core. +---- ---- +---- Compatibility to the 68K00: ---- +---- The 68K10 is pin compatible with the 68K00 but it is not 100% ---- +---- software compatible due to differences in the programming ---- +---- model. The differences in detail are: ---- +---- 1. The following differences are implemented in this core but ---- +---- do not affect the 68K00 compatibility: ---- +---- The 68K00 does not feature A vector base register (VBR). ---- +---- The 68K00 does not feature the BKPT instruction. ---- +---- The 68K00 does not feature the MOVE_FROM_CCR instruction. ---- +---- The 68K00 does not feature the MOVEC instruction. ---- +---- The 68K00 does not feature the MOVES instruction. ---- +---- The 68K00 does not feature the RTD instruction. ---- +---- The 68K10 stack frames are more complex but backward ---- +---- compatible to the 68K00. ---- +---- 2. The following differences are implemented in this core and ---- +---- do affect the 68K00 compatibility: ---- +---- The MOVE_FROM_SR instruction is priviledged for the 68K10 ---- +---- but is not priviledged for the 68K00. To gain compati- ---- +---- bility the K6800n signal driven low deactivates the pri- ---- +---- viledged mechanism for this instruction. ---- +---- This core features the loop operation mode of the 68010. ---- +---- ---- +---- The signal K6800n driven low controls all affected hardware to ---- +---- meet the MC68000 compatibility. K6800n driven high switches to ---- +---- MC68010 compatibility. Beside the control of somepriviledged ---- +---- instructions there are also the stack frame and operand sizes ---- +---- and othe minor differences affected. ---- +---- ---- +---- Enjoy. ---- +---- ---- +---- Author(s): ---- +---- - Wolfgang Foerster, wf@experiment-s.de; wf@inventronik.de ---- +---- ---- +------------------------------------------------------------------------ +---- ---- +---- Copyright © 2014-2019 Wolfgang Foerster Inventronik GmbH. ---- +---- ---- +---- This documentation describes Open Hardware and is licensed ---- +---- under the CERN OHL v. 1.2. You may redistribute and modify ---- +---- this documentation under the terms of the CERN OHL v.1.2. ---- +---- (http://ohwr.org/cernohl). This documentation is distributed ---- +---- WITHOUT ANY EXPRESS OR IMPLIED WARRANTY, INCLUDING OF ---- +---- MERCHANTABILITY, SATISFACTORY QUALITY AND FITNESS FOR A ---- +---- PARTICULAR PURPOSE. Please see the CERN OHL v.1.2 for ---- +---- applicable conditions ---- +---- ---- +------------------------------------------------------------------------ +-- +-- Revision History +-- +-- Revision 2K14B 20141201 WF +-- Initial Release. +-- Revision 2K16A 20160620 WF +-- Control section: fixed a bug in the MOVEM operation. Thanks to Raymond Mounissamy. +-- Address section: minor optimizations. +-- Address section: fixed a bug in PC_LOAD. +-- Top level: fixed the AR_IN_1 multiplexer. +-- Control: Break the DBcc_LOOP when the exception handler is busy (see process P_LOOP). +-- Opcode decoder: Break the DBcc_LOOP when the exception handler is busy (see process P_LOOP). +-- Revision 2K18A (unreleased) WF +-- Bus interface: Fixed a bug in the DATA_PORT_OUT multiplexer. Thanks to Gary Bingham for the support. +-- Bus interface: Fixed a bug in the DATA_INMUX multiplexer. Thanks to Gary Bingham for the support. +-- Control: Fixed a bug in MOVE An,-(Ay). Thanks to Gary Bingham for the support. +-- Top: changed ALU_OP1_IN multiplexer due to MOVE An,-(Ay) bug. +-- Address registers: Changed ADR_ATN logic to be valid one clock cycle earlier. +-- Top: bug fix: in MOVEM -(An) the initial addressing register is now written to memory. +-- Top: Correction in the BKPT address format: +-- Bus interface: RESET is now 124 instead of 512 clock cycles. +-- Top / Opdecoder / Exhandler: Removed REST_BIW_0. +-- Top: Adjusted exception frame data to 68K10. +-- Bus interface: Adjusted the SSW to 68K10. +-- Bus interface / Control: Removed RERUN_RMC. +-- Exception handler: Removed FC_OUT. +-- Exception handler: Removed ADR_CPY. +-- Exception handler: Removed PC_OFFSET. +-- Opcode decoder: Several minor improvements to meet better 68000 compatibility. +-- ALU: Bug fix: MOVEM sign extension. +-- Removed FB, FC, RB, RC and PC_REG from the design. +-- Control: Fixed wrong PEA behaviour. +-- Control: Fixed the displacement for LINK. +-- ALU: Fix for restoring correct values during the DIVS and DIVU in word format. +-- Opcode decoder: Removed illegal MOVEC control register patterns. +-- Control: Fixed the operation size for MOVEQ. +-- Control: ADDQ, SUBQ Fix: address registers are always written long. +-- Top, exception handler, address registers: Fixed PC restoring during exception processing. +-- Control: ADDI, ANDI, EORI, ORI, SUBI: address is not marked used if destination is Dn. +-- Control: ADDI, ANDI, EORI, ORI, SUBI: data register is marked used if destination is Dn. +-- Bus interface: Suppress bus faults during RESET instruction. +-- Bus interface: Optimized ASn and DSn timing for synchronous RAM. +-- Top: PC_OFFSET_OPD is now PC_OFFSET. +-- ALU: Fixed the SUBQ calculation. +-- Opcode decoder: Fixed the PW_EW_OFFSET calculation for JSR. +-- Top: fixed the value of DATA_IMMEDIATE for ADDQ and SUBQ in case of #8. +-- ALU: Rearanged the Offset for the JSR instruction. +-- Control: Fixed AR_MARK_USED in LINK. +-- ALU: EXT instruction uses now RESULT(63 downto 0). +-- Top: Introduced OP_WB form the control unit. +-- Top: Rearanged the AR_IN_1 multiplexer to avoid data hazards. +-- Top: Rearanged the AR_IN_2 multiplexer to avoid data hazards. +-- Top: Rearanged the DR_IN_1 multiplexer to avoid data hazards. +-- Top: Rearanged the DR_IN_2 multiplexer to avoid data hazards. +-- EXG: rearanged logic to meet the new top level multiplexers. +-- Control: LINK, UNLK: wait in START_OP until the ALU is ready (avoids possible data hazards). +-- Top: ALU_OP1_IN to meet the new EXG multiplexers. +-- Top: ALU_OP2_IN to meet the new EXG multiplexers. +-- Address registers: Fixed the writing of ISP_REG during EXG instruction with two address registers. +-- Control: MOVEM: Fixed predecrement mode for consecutive MOVEM -(An). +-- Control: MOVEP: MOVEP_PNTR is now correct for consecutive MOVEP. +-- Control: MOVEP: avoid structural hazard in SWITCH_STATE by waiting for ALU. +-- Control: LINK, UNLK: fixed the write back operation size. +-- Opcode decoder: Fixed PC_OFFSET value in case the exception handler send LOOP_EXIT. +-- Exception handler: Fixed the vector calculation of INT vectors. +-- Exception handler: Fixed faulty modelling in IRQ_FILTER. +-- Exception handler: Implemented the AVEC_FILTER to better meet bus timings. +-- Control: EOR: fixed a bug in the writeback mechanism. +-- Control: BSR, JSR: EXEC_WB state machine waits now for ALU_INIT. Avoid structural / data hazard. +-- Control: the instruction pipe is not flushed for MOVE_FROM_CCR, MOVE_FROM_SR, MOVE_USP, MOVEC. +-- ALU: Shifter signals now ready if shift width is zero. +-- Control: Modifications in the FETCH state machine to avoid several data hazards for MOVEM, MOVE_FROM_CCR, MOVE_FROM_SR. +-- Control: Modifications in the FETCH state machine to avoid several data hazards for ANDI_TO_CCR, ANDI_TO_SR, EORI_TO_CCR, EORI_TO_SR, ORI_TO_CCR, ORI_TO_SR. +-- Exception handler: The RTE exception has now highest priority (avoids mismatch). +-- Control: Bugfix: the condition codes were not updated if there was a pending interrupt. +-- Control: We have to stop a pending operation in case of a pending interrupt. This is done by rejecting OW_RDY. +-- TOP, Control, Exception handler Opcode Decoder: Rearanged PC_INC and ipipe flush logic. +-- Bus interface: DATA_PORT_EN timing optimization. +-- Bus interface: BUS_EN is now active except during arbitration. +-- Control: Write the undecremented Register for MOVE Ax, -(Ax). +-- Control: LINK A7 and PEA(A7) stacks the undecremented A7. +-- Bus interface: Rearanged the DATA_RDY vs. BUS_FLT logic. +-- ALU: Fixed wrong condition codes for AND_B, ANDI, EOR, EORI, OR_B, ORI and NOT_B. +-- Exception handler: Update the IRQ mask only for RESET and interrupts. +-- Bus interface: Opted out START_READ and CHK_RD. +-- Control: UNMARK is now asserted in the end of the write cycle. This avoids data hazards. +-- Exception handler: external interrupts are postponed if any system controllers are in initialize operation status. +-- ALU: Fixed writeback issues in the status register logic. +-- ALU: Fixed writing the stack pointer registers (SBIT_WB is used instead of SBIT). +-- Control: Fixed a MOVEC writeback issue (use BIW_WB... instead of BIW_...). +-- Control: Fixed a USP writeback issue (use BIW_WB... instead of BIW_...). +-- ALU, TOP: Fixed the condition code calculation for NEG and NEGX. +-- ALU: the address registers are always written long. +-- Top: opted out SBIT_AREG. +-- Address register bugfix: exception handler do not increment and decrement the USP any more. +-- Control: Introduced a switch NO_PIPELINE. +-- Address registers, Control: MOVEM-Fix see STORE_AEFF. +-- Control: DBcc: fixed a data hazard for DBcc_COND evaluation by waiting on the ALU result. +-- Control: Fixed DR_WR_1 locking against AR_WR_2. +-- Control: IPIPE is flushed, when there is a memory space change in the end of xx_TO_SR operations. +-- Control: To handle correct addressing, ADR_OFFSET is now cleared right in the end of the respective operation. +-- Control: Fixed a bug in EOR writing back in register direct mode. +-- ALU: Fixed a bug in MULU.W (input operands are now 16 bit wide). +-- Control: ADDQ and SUBQ: fixed (An)+ mode. An increments now. +-- Control: Fixed DIVS, DIVU in memory address modes (wrong control flow). +-- Control: ADDQ and SUBQ: fixed condition code control UPDT_CC. +-- Control: fixed a data hazard bug using addressing modes with index register. +-- Bus interface: UDSn and LDSn are now always enabled for opcode cycles (bugfix). +-- Opcode decoder: Rewritten DBcc loop. +-- Control: Rewritten DBcc loop for split loops. +-- Toplevel: changes for split loop operation. +-- Opcode decoder: Fix for unimplemented or illegal operations: PC is increased before stacked. +-- Exception handler: RTE now loads the address offset correctly when entering the handler. +-- Control: BTST: fixed (d16,Ax) addressing mode. +-- Bus interface: Fixed the faulty bus arbitration logic. +-- Opcode decoder: Removed CAHR, we have no cache. +-- Top: Removed a data hazard in the DR_IN_1 multiplexer (EXG operation). +-- Revision 2K19A 20190419 WF +-- For bug fixes and code optimizations see the RevisionHistory in the source code directory. +-- New feature: Branch prediction for the status register manipulation operations (BRANCH_ATN). +-- New fetch state CALC_AEFF which results in no need of ADR_ATN and a twice higher fmax. +-- Revision 2K19B 20191224 WF +-- Control: NOP explicitely synchronizes the instruction pipe now. +-- Opcode decoder: introduced signal synchronization in the P_BSY process to avoid malfunction by hazards. +-- Exception handler: introduced signal synchronization in the P_D process to avoid malfunction by hazards. +-- Top level, exception handler: the processor VERSION is now 32 bit wide. +-- Control: BUSY is now asserted when an opword is loaded and we have to wait in START_OP (avoids other controllers to reload the opword, see OW_REQ). +-- Control: removed a data hazard condition (A7) for JSR, PEA, LINK and UNLK in the beginning of the operation. +-- Address section: fixed the condition if UNMARK and AR_MARK_USED are asserted simultaneously (see process P_IN_USE). +-- Revision 2K20A 20200620 WF +-- Bus interface: ASn and DSn are not asserted in S0 any more. +-- Bus interface: some modifications to optimize the RETRY logic. +-- + +library work; +use work.WF68K10_PKG.all; + +library ieee; +use ieee.std_logic_1164.all; +use ieee.std_logic_unsigned.all; + +entity WF68K10_TOP is + generic( + VERSION : std_logic_vector(31 downto 0) := x"20191224"; -- CPU version number. + -- The following two switches are for debugging purposes. Default for both is false. + NO_PIPELINE : boolean := false; -- If true the main controller work in scalar mode. + NO_LOOP : boolean := false); -- If true the DBcc loop mechanism is disabled. + + port ( + CLK : in std_logic; + + -- Address and data: + ADR_OUT : out std_logic_vector(31 downto 0); + DATA_IN : in std_logic_vector(15 downto 0); + DATA_OUT : out std_logic_vector(15 downto 0); + DATA_EN : out std_logic; -- Enables the data port. + + -- System control: + BERRn : in std_logic; + RESET_INn : in std_logic; + RESET_OUT : out std_logic; -- Open drain. + HALT_INn : in std_logic; + HALT_OUTn : out std_logic; -- Open drain. + + -- Processor status: + FC_OUT : out std_logic_vector(2 downto 0); + + -- Interrupt control: + AVECn : in std_logic; + IPLn : in std_logic_vector(2 downto 0); + + -- Aynchronous bus control: + DTACKn : in std_logic; + ASn : out std_logic; + RWn : out std_logic; + RMCn : out std_logic; + UDSn : out std_logic; + LDSn : out std_logic; + DBENn : out std_logic; -- Data buffer enable. + BUS_EN : out std_logic; -- Enables ADR, ASn, UDSn, LDSn, RWn, RMCn and FC. + + -- Synchronous peripheral control: + E : out std_logic; + VMAn : out std_logic; + VMA_EN : out std_logic; + VPAn : in std_logic; + + -- Bus arbitration control: + BRn : in std_logic; + BGn : out std_logic; + BGACKn : in std_logic; + + -- Other controls: + K6800n : in std_logic -- Assert for 68K00 compatibility. + ); +end entity WF68K10_TOP; + +architecture STRUCTURE of WF68K10_TOP is +signal ADn : bit; +signal ADR_EFF : std_logic_vector(31 downto 0); +signal ADR_EFF_WB : std_logic_vector(31 downto 0); +signal ADR_L : std_logic_vector(31 downto 0); +signal ADR_LATCH : std_logic_vector(31 downto 0); +signal ADR_MODE : std_logic_vector(2 downto 0); +signal ADR_MODE_MAIN : std_logic_vector(2 downto 0); +signal ADR_IN_USE : bit; +signal ADR_OFFSET : std_logic_vector(31 downto 0); +signal ADR_OFFSET_EXH : std_logic_vector(31 downto 0); +signal ADR_OFFSET_MAIN : std_logic_vector(5 downto 0); +signal ADR_P : std_logic_vector(31 downto 0); +signal ADR_MARK_UNUSED_MAIN : bit; +signal ADR_MARK_USED : bit; +signal AERR : bit; +signal ALU_ACK : bit; +signal ALU_BSY : bit; +signal ALU_COND : boolean; +signal ALU_INIT : bit; +signal ALU_LOAD_OP1 : bit; +signal ALU_LOAD_OP2 : bit; +signal ALU_LOAD_OP3 : bit; +signal ALU_OP1_IN : std_logic_vector(31 downto 0); +signal ALU_OP2_IN : std_logic_vector(31 downto 0); +signal ALU_OP3_IN : std_logic_vector(31 downto 0); +signal ALU_REQ : bit; +signal ALU_RESULT : std_logic_vector(63 downto 0); +signal AMODE_SEL : std_logic_vector(2 downto 0); +signal AR_DEC : bit; +signal AR_CPY : std_logic_vector(31 downto 0); +signal AR_IN_1 : std_logic_vector(31 downto 0); +signal AR_IN_2 : std_logic_vector(31 downto 0); +signal AR_IN_USE : bit; +signal AR_INC : bit; +signal AR_MARK_USED : bit; +signal AR_OUT_1 : std_logic_vector(31 downto 0); +signal AR_OUT_2 : std_logic_vector(31 downto 0); +signal AR_SEL_RD_1 : std_logic_vector(2 downto 0); +signal AR_SEL_RD_1_MAIN : std_logic_vector(2 downto 0); +signal AR_SEL_RD_2 : std_logic_vector(2 downto 0); +signal AR_SEL_WR_1 : std_logic_vector(2 downto 0); +signal AR_SEL_WR_2 : std_logic_vector(2 downto 0); +signal AR_WR_1 : bit; +signal AR_WR_2 : bit; +signal AVECn_BUSIF : std_logic; +signal BERR_MAIN : bit; +signal BITPOS : std_logic_vector(4 downto 0); +signal BIW_0 : std_logic_vector(15 downto 0); +signal BIW_0_WB_73 : std_logic_vector(7 downto 3); +signal BIW_1 : std_logic_vector(15 downto 0); +signal BIW_2 : std_logic_vector(15 downto 0); +signal BKPT_CYCLE : bit; +signal BKPT_INSERT : bit; +signal BRANCH_ATN : bit; +signal BUS_BSY : bit; +signal BUSY_EXH : bit; +signal BUSY_MAIN : bit; +signal BUSY_OPD : bit; +signal BUSY_OPD_I : bit; +signal CC_UPDT : bit; +signal CPU_SPACE : bit; +signal CPU_SPACE_EXH : bit; +signal DFC : std_logic_vector(2 downto 0); +signal DFC_RD : bit; +signal DFC_WR : bit; +signal DR_MARK_USED : bit; +signal DATA_FROM_CORE : std_logic_vector(31 downto 0); +signal DATA : std_logic_vector(31 downto 0); +signal DATA_IN_EXH : std_logic_vector(31 downto 0); +signal DATA_IMMEDIATE : std_logic_vector(31 downto 0); +signal DATA_EXH : std_logic_vector(31 downto 0); +signal DATA_RD : bit; +signal DATA_WR : bit; +signal DATA_RD_EXH : bit; +signal DATA_WR_EXH : bit; +signal DATA_RD_MAIN : bit; +signal DATA_WR_MAIN : bit; +signal DATA_RDY : bit; +signal DATA_TO_CORE : std_logic_vector(31 downto 0); +signal DATA_VALID : std_logic; +signal DISPLACEMENT : std_logic_vector(31 downto 0); +signal DISPLACEMENT_MAIN : std_logic_vector(31 downto 0); +signal DISPLACEMENT_EXH : std_logic_vector(7 downto 0); +signal DATA_BUFFER : std_logic_vector(31 downto 0); +signal DBcc_COND : boolean; +signal DR_IN_1 : std_logic_vector(31 downto 0); +signal DR_IN_2 : std_logic_vector(31 downto 0); +signal DR_IN_USE : bit; +signal DR_OUT_2 : std_logic_vector(31 downto 0); +signal DR_OUT_1 : std_logic_vector(31 downto 0); +signal DR_SEL_WR_1 : std_logic_vector(2 downto 0); +signal DR_SEL_WR_2 : std_logic_vector(2 downto 0); +signal DR_SEL_RD_1 : std_logic_vector(2 downto 0); +signal DR_SEL_RD_2 : std_logic_vector(2 downto 0); +signal DR_WR_1 : bit; +signal DR_WR_2 : bit; +signal EW_ACK : bit; +signal EW_REQ_MAIN : bit; +signal EX_TRACE : bit; +signal EXEC_RDY : bit; +signal EXH_REQ : bit; +signal EXT_WORD : std_logic_vector(15 downto 0); +signal FAULT_ADR : std_logic_vector(31 downto 0); +signal FC_I : std_logic_vector(2 downto 0); +signal FC_LATCH : std_logic_vector(2 downto 0); +signal FC_OUT_I : std_logic_vector(2 downto 0); +signal IBUFFER : std_logic_vector(31 downto 0); +signal INBUFFER : std_logic_vector(31 downto 0); +signal INT_TRIG : bit; +signal IPL : std_logic_vector(2 downto 0); +signal ISP_DEC : bit; +signal ISP_LOAD : bit; +signal IVECT_OFFS : std_logic_vector(9 downto 0); +signal IRQ_PEND : std_logic_vector(2 downto 0); +signal IPIPE_FILL : bit; +signal IPIPE_FLUSH : bit; +signal IPIPE_FLUSH_EXH : bit; +signal IPIPE_FLUSH_MAIN : bit; +signal IPIPE_OFFESET : std_logic_vector(2 downto 0); +signal LOOP_BSY : bit; +signal LOOP_SPLIT : boolean; +signal LOOP_EXIT : bit; +signal MOVEP_PNTR : integer range 0 to 3; +signal OPCODE_RD : bit; +signal OPCODE_RDY : bit; +signal OPCODE_VALID : std_logic; +signal OPCODE_TO_CORE : std_logic_vector(15 downto 0); +signal OP_SIZE : OP_SIZETYPE; +signal OP_SIZE_BUS : OP_SIZETYPE; +signal OP_SIZE_EXH : OP_SIZETYPE; +signal OP_SIZE_MAIN : OP_SIZETYPE; +signal OP_SIZE_WB : OP_SIZETYPE; -- Writeback. +signal OPCODE_REQ : bit; +signal OPCODE_REQ_I : bit; +signal OW_VALID : std_logic; +signal OPD_ACK_MAIN : bit; +signal OP : OP_68K; +signal OP_WB : OP_68K; +signal OW_REQ_MAIN : bit; +signal OUTBUFFER : std_logic_vector(31 downto 0); +signal PC : std_logic_vector(31 downto 0); +signal PC_ADD_DISPL : bit; +signal PC_ADR_OFFSET : std_logic_vector(7 downto 0); +signal PC_EW_OFFSET : std_logic_vector(3 downto 0); +signal PC_INC : bit; +signal PC_INC_EXH : bit; +signal PC_INC_EXH_I : bit; +signal PC_L : std_logic_vector(31 downto 0); +signal PC_LOAD : bit; +signal PC_LOAD_EXH : bit; +signal PC_LOAD_MAIN : bit; +signal PC_OFFSET : std_logic_vector(7 downto 0); +signal PC_RESTORE_EXH : bit; +signal RD_REQ : bit; +signal RD_REQ_I : bit; +signal RMC : bit; +signal RESTORE_ISP_PC : bit; +signal RESET_CPU : bit; +signal RESET_IN : std_logic; +signal RESET_STRB : bit; +signal SP_ADD_DISPL : bit; +signal SP_ADD_DISPL_EXH : bit; +signal SP_ADD_DISPL_MAIN : bit; +signal SBIT : std_logic; +signal SSW : std_logic_vector(15 downto 0); +signal SFC : std_logic_vector(2 downto 0); +signal SFC_RD : bit; +signal SFC_WR : bit; +signal SR_CPY : std_logic_vector(15 downto 0); +signal SR_RD : bit; +signal SR_INIT : bit; +signal SR_WR : bit; +signal SR_WR_EXH : bit; +signal SR_WR_MAIN : bit; +signal STACK_FORMAT : std_logic_vector(3 downto 0); +signal STACK_POS : integer range 0 to 31; +signal STATUS_REG : std_logic_vector(15 downto 0); +signal STORE_ADR_FORMAT : bit; +signal STORE_ABS_HI : bit; +signal STORE_ABS_LO : bit; +signal STORE_AEFF : bit; +signal STORE_D16 : bit; +signal STORE_DISPL : bit; +signal STORE_IDATA_B1 : bit; +signal STORE_IDATA_B2 : bit; +signal TRAP_AERR : bit; +signal TRAP_ILLEGAL : bit; +signal TRAP_CODE_OPC : TRAPTYPE_OPC; +signal TRAP_CHK : bit; +signal TRAP_DIVZERO : bit; +signal TRAP_V : bit; +signal UNMARK : bit; +signal USE_APAIR : boolean; +signal USE_DFC : bit; +signal USE_SFC : bit; +signal USE_DPAIR : boolean; +signal USP_RD : bit; +signal USP_WR : bit; +signal VBR : std_logic_vector(31 downto 0); +signal VBR_WR : bit; +signal VBR_RD : bit; +signal WR_REQ : bit; +signal WR_REQ_I : bit; +-- Debugging: +signal DEBUG_TRIGGER : bit; +signal DEBUG_STAMP : std_logic_vector(31 downto 0); +begin + DEBUGGING : process + -- The DEBUG_STAMP register is intended + -- to count the instructions already passed. + -- The DEBUG_TRIGGER logic is a kind of a + -- breakpoint mechanism. It blocks the + -- main control state machine and thus halts + -- the system. + variable TRAPCNT : std_logic_vector(7 downto 0); + begin + wait until CLK = '1' and CLK' event; + if RESET_CPU = '1' then + DEBUG_STAMP <= x"00000000"; + --elsif PC_INC = '1' then + elsif PC_INC = '1' then + DEBUG_STAMP <= DEBUG_STAMP + '1'; + end if; + + -- Use this to detect a PC address. + --if RESET_CPU = '1' then + -- -DEBUG_TRIGGER <= '0'; + --elsif PC = x"00E0CB90" then -- screen_init. + -- -DEBUG_TRIGGER <= '1'; + --end if; + + -- Try this to detect not allowed register + -- controls. + --if RESET_CPU = '1' then + -- DEBUG_TRIGGER <= '0'; + --elsif AR_WR_1 = '1' and AR_INC = '1' then + -- DEBUG_TRIGGER <= '1'; + --elsif AR_WR_2 = '1' and AR_INC = '1' then + -- DEBUG_TRIGGER <= '1'; + --elsif AR_WR_1 = '1' and AR_DEC = '1' then + -- DEBUG_TRIGGER <= '1'; + --elsif AR_WR_2 = '1' and AR_DEC = '1' then + -- DEBUG_TRIGGER <= '1'; + --elsif AR_WR_1 = '1' and ISP_DEC = '1' then + -- DEBUG_TRIGGER <= '1'; + --elsif AR_WR_2 = '1' and ISP_DEC = '1' then + -- DEBUG_TRIGGER <= '1'; + --elsif AR_WR_1 = '1' and ISP_LOAD = '1' then + -- DEBUG_TRIGGER <= '1'; + --elsif AR_WR_2 = '1' and ISP_LOAD = '1' then + -- DEBUG_TRIGGER <= '1'; + --elsif ISP_LOAD = '1' and ISP_DEC = '1' then + -- DEBUG_TRIGGER <= '1'; + --elsif PC_LOAD = '1' and PC_INC = '1' then + -- DEBUG_TRIGGER <= '1'; + --end if; + + -- Test this to detect, if errouneously two registers are + -- written at the same time. + --if RESET_CPU = '1' then + -- DEBUG_TRIGGER <= '0'; + --elsif AR_WR_1 = '1' and AR_WR_2 = '1' and OP_WB /= EXG then + -- DEBUG_TRIGGER <= '1'; + --elsif AR_WR_1 = '1' and DR_WR_1 = '1' and OP_WB /= EXG then + -- DEBUG_TRIGGER <= '1'; + --elsif AR_WR_1 = '1' and DR_WR_2 = '1' and OP_WB /= EXG then + -- DEBUG_TRIGGER <= '1'; + --elsif AR_WR_2 = '1' and DR_WR_1 = '1' and OP_WB /= EXG then + -- DEBUG_TRIGGER <= '1'; + --elsif AR_WR_2 = '1' and DR_WR_2 = '1' and OP_WB /= EXG then + -- DEBUG_TRIGGER <= '1'; + --elsif DR_WR_1 = '1' and DR_WR_2 = '1' and OP_WB /= EXG then + -- DEBUG_TRIGGER <= '1'; + --end if; + + -- Size mismatch... + --if RESET_CPU = '1' then + -- DEBUG_TRIGGER <= '0'; + --elsif OP_SIZE_WB /= OP_SIZE and DATA_WR_MAIN = '1' then + -- DEBUG_TRIGGER <= '1'; + --end if; + + -- In this way, trigger output can be set + -- to any time in the program processing. + --if RESET_CPU = '1' then + -- DEBUG_TRIGGER <= '0'; + --elsif DEBUG_STAMP > x"002A0000" then + -- DEBUG_TRIGGER <= '1'; + --end if; + + -- Detects a system hang. + --if RESET_CPU = '1' or PC_INC = '1' then + -- TRAPCNT := x"00"; + -- DEBUG_TRIGGER <= '0'; + --elsif TRAPCNT < x"FF" then + -- TRAPCNT := TRAPCNT + '1'; + --else + -- DEBUG_TRIGGER <= '1'; + --end if; + + DEBUG_TRIGGER <= AR_DEC and (AR_WR_1 or AR_WR_2); + end process DEBUGGING; + + IDATA_BUFFER : process + -- This register stores the immediate data. + begin + wait until CLK = '1' and CLK' event; + if STORE_IDATA_B2 = '1' then + IBUFFER(31 downto 16) <= EXT_WORD; + elsif STORE_IDATA_B1 = '1' then + IBUFFER(15 downto 0) <= EXT_WORD; + end if; + end process IDATA_BUFFER; + + DATA_IMMEDIATE <= BIW_1 & BIW_2 when OP = ADDI and OP_SIZE = LONG else + BIW_1 & BIW_2 when OP = ANDI and OP_SIZE = LONG else + BIW_1 & BIW_2 when OP = CMPI and OP_SIZE = LONG else + BIW_1 & BIW_2 when OP = EORI and OP_SIZE = LONG else + BIW_1 & BIW_2 when OP = SUBI and OP_SIZE = LONG else + BIW_1 & BIW_2 when OP = ORI and OP_SIZE = LONG else + x"0000" & BIW_1 when OP = ANDI_TO_SR else + x"0000" & BIW_1 when OP = EORI_TO_SR else + x"0000" & BIW_1 when OP = ORI_TO_SR else + x"0000" & BIW_1 when OP = STOP else + x"0000" & BIW_1 when OP = ADDI and OP_SIZE = WORD else + x"0000" & BIW_1 when OP = ANDI and OP_SIZE = WORD else + x"0000" & BIW_1 when OP = CMPI and OP_SIZE = WORD else + x"0000" & BIW_1 when OP = EORI and OP_SIZE = WORD else + x"0000" & BIW_1 when OP = SUBI and OP_SIZE = WORD else + x"0000" & BIW_1 when OP = ORI and OP_SIZE = WORD else + x"000000" & BIW_1(7 downto 0) when OP = ANDI_TO_CCR else + x"000000" & BIW_1(7 downto 0) when OP = EORI_TO_CCR else + x"000000" & BIW_1(7 downto 0) when OP = ORI_TO_CCR else + x"000000" & BIW_1(7 downto 0) when OP = ADDI and OP_SIZE = BYTE else + x"000000" & BIW_1(7 downto 0) when OP = ANDI and OP_SIZE = BYTE else + x"000000" & BIW_1(7 downto 0) when OP = CMPI and OP_SIZE = BYTE else + x"000000" & BIW_1(7 downto 0) when OP = EORI and OP_SIZE = BYTE else + x"000000" & BIW_1(7 downto 0) when OP = SUBI and OP_SIZE = BYTE else + x"000000" & BIW_1(7 downto 0) when OP = ORI and OP_SIZE = BYTE else + x"00000008" when (OP = ADDQ or OP = SUBQ) and BIW_0(11 downto 9) = "000" else + x"000000" & "00000" & BIW_0(11 downto 9) when OP = ADDQ or OP = SUBQ else + x"000000" & BIW_0(7 downto 0) when OP = MOVEQ else + x"00000001" when OP = DBcc else + IBUFFER when OP_SIZE = LONG else x"0000" & IBUFFER(15 downto 0); + + -- Exception handler multiplexing: internal registers are place holders written as zeros. + DATA_EXH <= SR_CPY & PC(31 downto 16) when K6800n = '0' and STACK_FORMAT = x"0" and STACK_POS = 2 else -- 68K00 short stack frame. + x"0000" & PC(15 downto 0) when K6800n = '0' and STACK_FORMAT = x"0" and STACK_POS = 3 else -- 68K00 short stack frame. + x"0000" & FAULT_ADR(31 downto 16) when K6800n = '0' and STACK_FORMAT = x"8" and STACK_POS = 2 else -- 68K00 long stack frame. + FAULT_ADR(15 downto 0) & BIW_0 when K6800n = '0' and STACK_FORMAT = x"8" and STACK_POS = 4 else -- 68K00 long stack frame. + SR_CPY & PC(31 downto 16) when K6800n = '0' and STACK_FORMAT = x"8" and STACK_POS = 6 else -- 68K00 long stack frame. + x"0000" & PC(15 downto 0) when K6800n = '0' and STACK_FORMAT = x"8" and STACK_POS = 7 else -- 68K00 long stack frame. + SR_CPY & PC(31 downto 16) when STACK_POS = 2 else + PC(15 downto 0) & STACK_FORMAT & "00" & IVECT_OFFS when STACK_POS = 4 else + SSW & FAULT_ADR(31 downto 16) when STACK_POS = 6 else + FAULT_ADR(15 downto 0) & x"0000" when STACK_POS = 8 else + OUTBUFFER when STACK_POS = 10 else + INBUFFER when STACK_POS = 12 else + VERSION when STACK_POS = 14 else + DEBUG_STAMP when STACK_POS = 18 else + DEBUG_STAMP when DEBUG_TRIGGER = '1' and STACK_POS = 20 else (others => '0'); + + DATA_IN_EXH <= ALU_RESULT(31 downto 0) when BUSY_MAIN = '1' else DATA_TO_CORE; -- MOVEC handles the VBR. + + DATA_FROM_CORE <= DATA_EXH when BUSY_EXH = '1' else ALU_RESULT(31 downto 0); + + SP_ADD_DISPL <= SP_ADD_DISPL_MAIN or SP_ADD_DISPL_EXH; + + AR_SEL_RD_1 <= "111" when BUSY_EXH = '1' else AR_SEL_RD_1_MAIN; -- ISP during exception. + + AR_IN_1 <= DATA_TO_CORE when BUSY_EXH = '1' else + ALU_RESULT(31 downto 0) when ALU_BSY = '1' and AR_WR_1 = '1' else + ALU_RESULT(31 downto 0) when ALU_BSY = '1' and (DFC_WR = '1' or SFC_WR = '1' or USP_WR = '1') else + ADR_EFF when OP = JMP or OP = JSR else + AR_OUT_1 when OP = LINK or OP = UNLK else DATA_TO_CORE; -- Default used for RTD, RTR, RTS. + + AR_IN_2 <= ALU_RESULT(63 downto 32) when OP_WB = EXG else ALU_RESULT(31 downto 0); -- Default is for UNLK. + + DR_IN_1 <= ALU_RESULT(63 downto 32) when OP_WB = EXG and ALU_BSY = '1' and DR_WR_1 = '1' and BIW_0_WB_73 = "10001" else -- Address and data registers. + ALU_RESULT(31 downto 0); + + DR_IN_2 <= ALU_RESULT(63 downto 32); + + ALU_OP1_IN <= DATA_TO_CORE when SR_WR_EXH = '1' else + DATA_IMMEDIATE when OP = DBcc else + DR_OUT_1 when (OP = ABCD or OP = SBCD) and BIW_0(3) = '0' else + DATA_TO_CORE when OP = ABCD or OP = SBCD else + DR_OUT_1 when (OP = ADD or OP = SUB) and BIW_0(8) = '1' else + DR_OUT_1 when (OP = AND_B or OP = EOR or OP = OR_B) and BIW_0(8) = '1' else + DR_OUT_1 when (OP = ADDX or OP = SUBX) and BIW_0(3) = '0' else + DATA_TO_CORE when OP = ADDX or OP = SUBX else + DR_OUT_1 when OP = ASL or OP = ASR or OP = LSL or OP = LSR else + DR_OUT_1 when OP = ROTL or OP = ROTR or OP = ROXL or OP = ROXR else + DATA_TO_CORE when OP = CMPM else + PC + PC_EW_OFFSET when OP = BSR or OP = JSR else + ADR_EFF when OP = LEA or OP = PEA else + AR_OUT_2 when OP = MOVE and BIW_0(5 downto 3) = "001" else -- An to any location. + AR_OUT_1 when OP = MOVE_USP else + AR_OUT_1 when OP = EXG and BIW_0(7 downto 3) = "01001" else -- Two address registers. + DR_OUT_1 when OP = EXG else -- Two data registers. + VBR when OP = MOVEC and VBR_RD = '1' else + x"0000000" & '0' & SFC when OP = MOVEC and SFC_RD = '1' else + x"0000000" & '0' & DFC when OP = MOVEC and DFC_RD = '1' else + AR_OUT_1 when OP = MOVEC and BIW_1(15) = '1' else + DR_OUT_1 when OP = MOVEC else + DR_OUT_1 when OP = MOVEM and BIW_0(10) = '0' and ADn = '0' else -- Register to memory. + AR_CPY when OP = MOVEM and BIW_0(10) = '0' and AR_SEL_RD_1(2 downto 0) = AR_SEL_RD_2 and ADR_MODE = "100" else -- Register to memory in -(An) mode. + AR_OUT_2 when OP = MOVEM and BIW_0(10) = '0' else -- Register to memory. + DR_OUT_1 when OP = MOVES and BIW_1(11) = '1' and BIW_1(15) = '0' else -- Register to memory. + AR_OUT_2 when OP = MOVES and BIW_1(11) = '1' else -- Register to memory. + x"000000" & DR_OUT_1(31 downto 24) when OP = MOVEP and MOVEP_PNTR = 3 and BIW_0(7 downto 6) > "01" else + x"000000" & DR_OUT_1(23 downto 16) when OP = MOVEP and MOVEP_PNTR = 2 and BIW_0(7 downto 6) > "01" else + x"000000" & DR_OUT_1(15 downto 8) when OP = MOVEP and MOVEP_PNTR = 1 and BIW_0(7 downto 6) > "01" else + x"000000" & DR_OUT_1(7 downto 0) when OP = MOVEP and BIW_0(7 downto 6) > "01" else + DATA_TO_CORE(7 downto 0) & DR_OUT_1(23 downto 0) when OP = MOVEP and MOVEP_PNTR = 3 else + DR_OUT_1(31 downto 24) & DATA_TO_CORE(7 downto 0) & DR_OUT_1(15 downto 0) when OP = MOVEP and MOVEP_PNTR = 2 else + DR_OUT_1(31 downto 16) & DATA_TO_CORE(7 downto 0) & DR_OUT_1(7 downto 0) when OP = MOVEP and MOVEP_PNTR = 1 else + DR_OUT_1(31 downto 8) & DATA_TO_CORE(7 downto 0) when OP = MOVEP else + x"0000" & STATUS_REG(15 downto 8) & DR_OUT_1(7 downto 0) when OP = MOVE_TO_CCR and BIW_0(5 downto 3) = "000" else + x"0000" & STATUS_REG(15 downto 8) & DATA_IMMEDIATE(7 downto 0) when OP = MOVE_TO_CCR and BIW_0(5 downto 0) = "111100" else + x"0000" & STATUS_REG(15 downto 8) & DATA_TO_CORE(7 downto 0) when OP = MOVE_TO_CCR else + x"0000" & DR_OUT_1(15 downto 0) when OP = MOVE_TO_SR and BIW_0(5 downto 3) = "000" else + x"0000" & DATA_IMMEDIATE(15 downto 0) when OP = MOVE_TO_SR and BIW_0(5 downto 0) = "111100" else + x"0000" & DATA_TO_CORE(15 downto 0) when OP = MOVE_TO_SR else + x"000000" & "000" & STATUS_REG(4 downto 0) when OP = MOVE_FROM_CCR else + x"0000" & STATUS_REG when OP = MOVE_FROM_SR else + DATA_IMMEDIATE when OP = STOP else -- Status register information. + DATA_IMMEDIATE when OP = MOVEQ else + x"00000000" when OP = NEG or OP = NEGX or OP = NBCD else + DATA_IMMEDIATE when OP = ADDI or OP = CMPI or OP = SUBI or OP = ANDI or OP = EORI or OP = ORI else + DATA_IMMEDIATE when OP = ADDQ or OP = SUBQ else + DATA_IMMEDIATE when OP = ANDI_TO_CCR or OP = ANDI_TO_SR else + DATA_IMMEDIATE when OP = EORI_TO_CCR or OP = EORI_TO_SR else + DATA_IMMEDIATE when OP = ORI_TO_CCR or OP = ORI_TO_SR else + DR_OUT_1 when BIW_0(5 downto 3) = "000" else + AR_OUT_1 when BIW_0(5 downto 3) = "001" else + DATA_IMMEDIATE when BIW_0(5 downto 0) = "111100" else DATA_TO_CORE; + + ALU_OP2_IN <= DR_OUT_2 when (OP = ABCD or OP = SBCD) and BIW_0(3) = '0' else + DATA_TO_CORE when OP = ABCD or OP = SBCD else + DR_OUT_2 when (OP = ADDX or OP = SUBX) and BIW_0(3) = '0' else + DATA_TO_CORE when OP = ADDX or OP = SUBX else + DR_OUT_2 when (OP = ADD or OP = CMP or OP = SUB) and BIW_0(8) = '0' else + DR_OUT_2 when (OP = AND_B or OP = OR_B) and BIW_0(8) = '0' else + AR_OUT_2 when (OP = ADDA or OP = CMPA or OP = SUBA) else + DR_OUT_2 when OP = EXG and BIW_0(7 downto 3) = "01000" else -- Two data registers. + AR_OUT_2 when OP = EXG else + DR_OUT_2 when (OP = ASL or OP = ASR) and BIW_0(7 downto 6) /= "11" else -- Register shifts. + DR_OUT_2 when (OP = LSL or OP = LSR) and BIW_0(7 downto 6) /= "11" else -- Register shifts. + DR_OUT_2 when (OP = ROTL or OP = ROTR) and BIW_0(7 downto 6) /= "11" else -- Register shifts. + DR_OUT_2 when (OP = ROXL or OP = ROXR) and BIW_0(7 downto 6) /= "11" else -- Register shifts. + x"0000" & STATUS_REG when(OP = ANDI_TO_CCR or OP = ANDI_TO_SR) else + x"0000" & STATUS_REG when(OP = EORI_TO_CCR or OP = EORI_TO_SR) else + x"0000" & STATUS_REG when(OP = ORI_TO_CCR or OP = ORI_TO_SR) else + AR_OUT_2 when OP = CHK else + DATA_TO_CORE when OP = CMPM else + DR_OUT_2 when OP = DBcc or OP = SWAP else + DR_OUT_2 when OP = DIVS or OP = DIVU else + DR_OUT_2 when OP = MULS or OP = MULU else + AR_OUT_1 when OP = LINK else + DR_OUT_2 when BIW_0(5 downto 3) = "000" else + AR_OUT_2 when BIW_0(5 downto 3) = "001" else DATA_TO_CORE; + + ALU_OP3_IN <= DR_OUT_1; + + OP_SIZE <= OP_SIZE_EXH when BUSY_EXH = '1' else OP_SIZE_MAIN; + OP_SIZE_BUS <= OP_SIZE_WB when DATA_WR_MAIN = '1' else OP_SIZE; + + FC_OUT <= FC_OUT_I; + + PC_L <= PC + PC_ADR_OFFSET; + + PC_INC_EXH_I <= PC_INC_EXH when LOOP_SPLIT = false else '0'; -- Suppress for a split loop. + + ADR_MODE <= "010" when BUSY_EXH = '1' else ADR_MODE_MAIN; --(ISP) + + -- The bit field offset is byte aligned + ADR_OFFSET <= ADR_OFFSET_EXH when BUSY_EXH = '1' else + x"000000" & "00" & ADR_OFFSET_MAIN; + + DBcc_COND <= true when OP_WB = DBcc and ALU_RESULT(15 downto 0) = x"FFFF" else false; + + -- Take a branch if the CPU space will change: + BRANCH_ATN <= '1' when OP = ANDI_TO_SR and DATA_IMMEDIATE(13) = '0' and STATUS_REG(13) = '1' else + '1' when OP = EORI_TO_SR and DATA_IMMEDIATE(13) = '1' else + '1' when OP = ORI_TO_SR and DATA_IMMEDIATE(13) = '1' and STATUS_REG(13) = '0' else + '1' when OP = MOVE_TO_SR and BIW_0(5 downto 3) = "000" and DR_OUT_1(13) /= STATUS_REG(13) else + '1' when OP = MOVE_TO_SR and BIW_0(5 downto 0) = "111100" and DATA_IMMEDIATE(13) /= STATUS_REG(13) else + '1' when OP = MOVE_TO_SR and DATA_TO_CORE(13) /= STATUS_REG(13) else '0'; + + DATA_RD <= DATA_RD_EXH or DATA_RD_MAIN; + DATA_WR <= DATA_WR_EXH or DATA_WR_MAIN; + + P_BUSREQ: process + begin + wait until CLK = '1' and CLK' event; + -- We need these flip flops to avoid combinatorial loops: + -- The requests are valid until the Bus interface enters + -- its START_CYCLE bus phase and asserts there the BUS_BSY. + -- After the Bus interface enters the bus access state, + -- the requests are withdrawn. + if BUS_BSY = '0' then + RD_REQ_I <= DATA_RD; + WR_REQ_I <= DATA_WR; + OPCODE_REQ_I <= OPCODE_RD; + elsif BUS_BSY = '1' then + RD_REQ_I <= '0'; + WR_REQ_I <= '0'; + OPCODE_REQ_I <= '0'; + end if; + end process P_BUSREQ; + + MOVEM_AR_CPY: process + -- This temporary copy of the addressing register is used during the + -- MOVEM instruction in predecrement addressing mode -(An). The value + -- of the addressing register written to memory is the initial value + -- for 68000 and 68010 processors. + variable LOCK : boolean; + begin + wait until CLK = '1' and CLK' event; + if OPD_ACK_MAIN = '1' and OP = MOVEM and LOCK = false then + AR_CPY <= AR_OUT_1; + LOCK := true; + elsif OW_REQ_MAIN = '1' then + LOCK := false; + end if; + end process MOVEM_AR_CPY; + + RD_REQ <= DATA_RD when BUS_BSY = '0' else RD_REQ_I; + WR_REQ <= DATA_WR when BUS_BSY = '0' else WR_REQ_I; + OPCODE_REQ <= OPCODE_RD when BUS_BSY = '0' else OPCODE_REQ_I; + + DISPLACEMENT <= DISPLACEMENT_MAIN when BUSY_MAIN = '1' else x"000000" & DISPLACEMENT_EXH; + + SR_WR <= SR_WR_EXH or SR_WR_MAIN; + + IPIPE_FLUSH <= IPIPE_FLUSH_EXH or IPIPE_FLUSH_MAIN; + + AVECn_BUSIF <= AVECn when BUSY_EXH = '1' else '1'; -- Disabled during normal operation. + + CPU_SPACE <= '1' when OP = BKPT and DATA_RD_MAIN = '1' else + CPU_SPACE_EXH when BUSY_EXH = '1' else '0'; + + -- The BITPOS is valid for BCHG, BCLR, BSET and BTST it BITPOS spans 0 to 31 bytes, + -- when it is in register direct mode. It is modulo 8 in memory manipulation mode. + BITPOS <= BIW_1(4 downto 0) when (OP = BCHG or OP = BCLR or OP = BSET or OP = BTST) and BIW_0(8) = '0' and ADR_MODE = "000" else + "00" & BIW_1(2 downto 0) when (OP = BCHG or OP = BCLR or OP = BSET or OP = BTST) and BIW_0(8) = '0' else + DR_OUT_1(4 downto 0) when (OP = BCHG or OP = BCLR or OP = BSET or OP = BTST) and ADR_MODE = "000" else + "00" & DR_OUT_1(2 downto 0) when OP = BCHG or OP = BCLR or OP = BSET or OP = BTST else + BIW_1(10 downto 6) when BIW_1(11) = '0' and ADR_MODE = "000" else + "00" & BIW_1(8 downto 6) when BIW_1(11) = '0' else + DR_OUT_1(4 downto 0) when ADR_MODE = "000" else "00" & DR_OUT_1(2 downto 0); + + TRAP_AERR <= AERR when BUSY_EXH = '0' else '0'; -- No address error from the system during exception processing. + + USE_DFC <= '1' when OP_WB = MOVES and DATA_WR_MAIN = '1' else '0'; + USE_SFC <= '1' when OP_WB = MOVES and DATA_RD_MAIN = '1' else '0'; + + PC_LOAD <= PC_LOAD_EXH or PC_LOAD_MAIN; + + RESET_IN <= not RESET_INn; + + IPL <= not IPLn; + + SBIT <= STATUS_REG(13); + + ADR_L <= x"00000000" when BKPT_CYCLE = '1' else + x"FFFFFFF" & IRQ_PEND & '1' when CPU_SPACE_EXH = '1' else + ADR_EFF_WB when DATA_WR_MAIN = '1' else ADR_EFF; -- Exception handler uses ADR_EFF for read and write access. + + ADR_P <= ADR_LATCH when BUS_BSY = '1' else + ADR_L when DATA_RD = '1' or DATA_WR = '1' else PC_L; + + P_ADR_LATCHES: process + -- This register stores the address during a running bus cycle. + -- The signals RD_DATA, WR_DATA and RD_OPCODE may change during + -- the cycle. Opcode read is lower prioritized. + -- FAULT_ADR latches the faulty address for stacking it via + -- the exception handler. + -- The FC_LATCH register stores the function code during a running + -- bus cycle. + begin + wait until CLK = '1' and CLK' event; + if BUS_BSY = '0' then + ADR_LATCH <= ADR_P; + FC_LATCH <= FC_I; + elsif BERRn = '0' then + FAULT_ADR <= ADR_LATCH; + end if; + end process P_ADR_LATCHES; + + FC_I <= FC_LATCH when BUS_BSY = '1' else + SFC when USE_SFC = '1' else + DFC when USE_DFC = '1' else + "111" when (DATA_RD = '1' or DATA_WR = '1') and CPU_SPACE = '1' else + "101" when (DATA_RD = '1' or DATA_WR = '1') and SBIT = '1' else + "001" when DATA_RD = '1' or DATA_WR = '1' else + "110" when OPCODE_RD = '1' and SBIT = '1' else "010"; -- Default is OPCODE_RD and SBIT = '0'. + + I_ADDRESSREGISTERS: WF68K10_ADDRESS_REGISTERS + port map( + CLK => CLK, + RESET => RESET_CPU, + AR_IN_1 => AR_IN_1, + AR_IN_2 => AR_IN_2, + AR_OUT_1 => AR_OUT_1, + AR_OUT_2 => AR_OUT_2, + INDEX_IN => DR_OUT_1, -- From data register section. + PC => PC, + STORE_ADR_FORMAT => STORE_ADR_FORMAT, + STORE_ABS_HI => STORE_ABS_HI, + STORE_ABS_LO => STORE_ABS_LO, + STORE_D16 => STORE_D16, + STORE_DISPL => STORE_DISPL, + STORE_AEFF => STORE_AEFF, + OP_SIZE => OP_SIZE, + AR_MARK_USED => AR_MARK_USED, + USE_APAIR => USE_APAIR, + AR_IN_USE => AR_IN_USE, + AR_SEL_RD_1 => AR_SEL_RD_1, + AR_SEL_RD_2 => AR_SEL_RD_2, + AR_SEL_WR_1 => AR_SEL_WR_1, + AR_SEL_WR_2 => AR_SEL_WR_2, + ADR_OFFSET => ADR_OFFSET, -- Byte aligned. + ADR_MARK_USED => ADR_MARK_USED, + ADR_IN_USE => ADR_IN_USE, + ADR_MODE => ADR_MODE, + AMODE_SEL => AMODE_SEL, + ADR_EFF => ADR_EFF, + ADR_EFF_WB => ADR_EFF_WB, + DFC => DFC, + DFC_WR => DFC_WR, + SFC => SFC, + SFC_WR => SFC_WR, + ISP_DEC => ISP_DEC, + ISP_WR => ISP_LOAD, + USP_RD => USP_RD, + USP_WR => USP_WR, + AR_DEC => AR_DEC, + AR_INC => AR_INC, + AR_WR_1 => AR_WR_1, + AR_WR_2 => AR_WR_2, + UNMARK => UNMARK, + EXT_WORD => EXT_WORD, + SBIT => SBIT, + SP_ADD_DISPL => SP_ADD_DISPL, + RESTORE_ISP_PC => RESTORE_ISP_PC, + DISPLACEMENT => DISPLACEMENT, + PC_ADD_DISPL => PC_ADD_DISPL, + PC_EW_OFFSET => PC_EW_OFFSET, + PC_INC => PC_INC, + PC_LOAD => PC_LOAD, + PC_RESTORE => PC_RESTORE_EXH, + PC_OFFSET => PC_OFFSET + ); + + I_ALU: WF68K10_ALU + port map( + CLK => CLK, + RESET => RESET_CPU, + LOAD_OP3 => ALU_LOAD_OP3, + LOAD_OP2 => ALU_LOAD_OP2, + LOAD_OP1 => ALU_LOAD_OP1, + OP1_IN => ALU_OP1_IN, + OP2_IN => ALU_OP2_IN, + OP3_IN => ALU_OP3_IN, + BITPOS_IN => BITPOS, + RESULT => ALU_RESULT, + ADR_MODE_IN => ADR_MODE, + OP_SIZE_IN => OP_SIZE, + OP_IN => OP, + OP_WB => OP_WB, + BIW_0_IN => BIW_0(11 downto 0), + BIW_1_IN => BIW_1, + SR_WR => SR_WR, + SR_INIT => SR_INIT, + CC_UPDT => CC_UPDT, + STATUS_REG_OUT => STATUS_REG, + ALU_COND => ALU_COND, + ALU_INIT => ALU_INIT, + ALU_BSY => ALU_BSY, + ALU_REQ => ALU_REQ, + ALU_ACK => ALU_ACK, + IRQ_PEND => IRQ_PEND, + TRAP_CHK => TRAP_CHK, + TRAP_DIVZERO => TRAP_DIVZERO + ); + + I_BUS_IF: WF68K10_BUS_INTERFACE + port map( + CLK => CLK, + + ADR_IN_P => ADR_P, + ADR_OUT_P => ADR_OUT, + + FC_IN => FC_I, + FC_OUT => FC_OUT_I, + + DATA_PORT_IN => DATA_IN, + DATA_PORT_OUT => DATA_OUT, + DATA_FROM_CORE => DATA_FROM_CORE, + DATA_TO_CORE => DATA_TO_CORE, + OPCODE_TO_CORE => OPCODE_TO_CORE, + + DATA_PORT_EN => DATA_EN, + BUS_EN => BUS_EN, + + OP_SIZE => OP_SIZE_BUS, + + RD_REQ => RD_REQ, + WR_REQ => WR_REQ, + DATA_RDY => DATA_RDY, + DATA_VALID => DATA_VALID, + OPCODE_REQ => OPCODE_REQ, + OPCODE_RDY => OPCODE_RDY, + OPCODE_VALID => OPCODE_VALID, + RMC => RMC, + BUSY_EXH => BUSY_EXH, + SSW => SSW, + INBUFFER => INBUFFER, + OUTBUFFER => OUTBUFFER, + + DTACKn => DTACKn, + ASn => ASn, + UDSn => UDSn, + LDSn => LDSn, + RWn => RWn, + RMCn => RMCn, + DBENn => DBENn, + + E => E, + VMAn => VMAn, + VMA_EN => VMA_EN, + VPAn => VPAn, + + BRn => BRn, + BGACKn => BGACKn, + BGn => BGn, + + RESET_STRB => RESET_STRB, + RESET_IN => RESET_IN, + RESET_OUT => RESET_OUT, + RESET_CPU => RESET_CPU, + + AVECn => AVECn_BUSIF, + HALTn => HALT_INn, + BERRn => BERRn, + AERR => AERR, + + BUS_BSY => BUS_BSY + ); + + I_CONTROL: WF68K10_CONTROL + generic map(NO_PIPELINE => NO_PIPELINE) + port map( + CLK => CLK, + RESET_CPU => RESET_CPU, + BUSY => BUSY_MAIN, + BUSY_EXH => BUSY_EXH, + EXH_REQ => EXH_REQ, + INT_TRIG => INT_TRIG, + OW_REQ => OW_REQ_MAIN, + OW_VALID => OW_VALID, + EW_REQ => EW_REQ_MAIN, + EW_ACK => EW_ACK, + OPD_ACK => OPD_ACK_MAIN, + ADR_MARK_USED => ADR_MARK_USED, + ADR_IN_USE => ADR_IN_USE, + ADR_OFFSET => ADR_OFFSET_MAIN, + DATA_RD => DATA_RD_MAIN, + DATA_WR => DATA_WR_MAIN, + DATA_RDY => DATA_RDY, + DATA_VALID => DATA_VALID, + RMC => RMC, + LOAD_OP1 => ALU_LOAD_OP1, + LOAD_OP2 => ALU_LOAD_OP2, + LOAD_OP3 => ALU_LOAD_OP3, + STORE_ADR_FORMAT => STORE_ADR_FORMAT, + STORE_ABS_HI => STORE_ABS_HI, + STORE_ABS_LO => STORE_ABS_LO, + STORE_D16 => STORE_D16, + STORE_DISPL => STORE_DISPL, + STORE_AEFF => STORE_AEFF, + STORE_IDATA_B1 => STORE_IDATA_B1, + STORE_IDATA_B2 => STORE_IDATA_B2, + OP => OP, + OP_SIZE => OP_SIZE_MAIN, + BIW_0 => BIW_0(13 downto 0), + BIW_1 => BIW_1, + EXT_WORD => EXT_WORD, + ADR_MODE => ADR_MODE_MAIN, + AMODE_SEL => AMODE_SEL, + OP_WB => OP_WB, + OP_SIZE_WB => OP_SIZE_WB, + BIW_0_WB_73 => BIW_0_WB_73, + AR_MARK_USED => AR_MARK_USED, + AR_IN_USE => AR_IN_USE, + AR_SEL_RD_1 => AR_SEL_RD_1_MAIN, + AR_SEL_RD_2 => AR_SEL_RD_2, + AR_SEL_WR_1 => AR_SEL_WR_1, + AR_SEL_WR_2 => AR_SEL_WR_2, + AR_INC => AR_INC, + AR_DEC => AR_DEC, + AR_WR_1 => AR_WR_1, + AR_WR_2 => AR_WR_2, + DR_MARK_USED => DR_MARK_USED, + USE_APAIR => USE_APAIR, + USE_DPAIR => USE_DPAIR, + DR_IN_USE => DR_IN_USE, + DR_SEL_WR_1 => DR_SEL_WR_1, + DR_SEL_WR_2 => DR_SEL_WR_2, + DR_SEL_RD_1 => DR_SEL_RD_1, + DR_SEL_RD_2 => DR_SEL_RD_2, + DR_WR_1 => DR_WR_1, + DR_WR_2 => DR_WR_2, + UNMARK => UNMARK, + DISPLACEMENT => DISPLACEMENT_MAIN, + PC_ADD_DISPL => PC_ADD_DISPL, + PC_LOAD => PC_LOAD_MAIN, + PC_INC_EXH => PC_INC_EXH, + SP_ADD_DISPL => SP_ADD_DISPL_MAIN, + DFC_RD => DFC_RD, + DFC_WR => DFC_WR, + SFC_RD => SFC_RD, + SFC_WR => SFC_WR, + VBR_RD => VBR_RD, + VBR_WR => VBR_WR, + USP_RD => USP_RD, + USP_WR => USP_WR, + IPIPE_FLUSH => IPIPE_FLUSH_MAIN, + ALU_INIT => ALU_INIT, + ALU_BSY => ALU_BSY, + ALU_REQ => ALU_REQ, + ALU_ACK => ALU_ACK, + BKPT_CYCLE => BKPT_CYCLE, + BKPT_INSERT => BKPT_INSERT, + LOOP_BSY => LOOP_BSY, + LOOP_SPLIT => LOOP_SPLIT, + LOOP_EXIT => LOOP_EXIT, + SR_WR => SR_WR_MAIN, + MOVEM_ADn => ADn, + MOVEP_PNTR => MOVEP_PNTR, + CC_UPDT => CC_UPDT, + TRACE_EN => STATUS_REG(15), + ALU_COND => ALU_COND, + DBcc_COND => DBcc_COND, + BRANCH_ATN => BRANCH_ATN, + RESET_STRB => RESET_STRB, + BERR => BERR_MAIN, + EX_TRACE => EX_TRACE, + TRAP_V => TRAP_V, + TRAP_ILLEGAL => TRAP_ILLEGAL + ); + + I_DATA_REGISTERS: WF68K10_DATA_REGISTERS + port map( + CLK => CLK, + RESET => RESET_CPU, + DR_IN_1 => DR_IN_1, + DR_IN_2 => DR_IN_2, + DR_OUT_2 => DR_OUT_2, + DR_OUT_1 => DR_OUT_1, + DR_SEL_WR_1 => DR_SEL_WR_1, + DR_SEL_WR_2 => DR_SEL_WR_2, + DR_SEL_RD_1 => DR_SEL_RD_1, + DR_SEL_RD_2 => DR_SEL_RD_2, + DR_WR_1 => DR_WR_1, + DR_WR_2 => DR_WR_2, + DR_MARK_USED => DR_MARK_USED, + USE_DPAIR => USE_DPAIR, + DR_IN_USE => DR_IN_USE, + UNMARK => UNMARK, + OP_SIZE => OP_SIZE_WB + ); + + I_EXC_HANDLER: WF68K10_EXCEPTION_HANDLER + generic map(VERSION => VERSION) + port map( + CLK => CLK, + K6800n => K6800n, + + RESET => RESET_CPU, + + BUSY_MAIN => BUSY_MAIN, + BUSY_OPD => BUSY_OPD, + + EXH_REQ => EXH_REQ, + BUSY_EXH => BUSY_EXH, + + ADR_IN => ADR_EFF, + ADR_OFFSET => ADR_OFFSET_EXH, + CPU_SPACE => CPU_SPACE_EXH, + + DATA_0 => DATA_TO_CORE(0), + DATA_RD => DATA_RD_EXH, + DATA_WR => DATA_WR_EXH, + DATA_IN => DATA_IN_EXH, + + OP_SIZE => OP_SIZE_EXH, + DATA_RDY => DATA_RDY, + DATA_VALID => DATA_VALID, + + OPCODE_RDY => OPCODE_RDY, + + STATUS_REG_IN => STATUS_REG, + SR_CPY => SR_CPY, + SR_INIT => SR_INIT, + + SR_WR => SR_WR_EXH, + ISP_DEC => ISP_DEC, + ISP_LOAD => ISP_LOAD, + PC_LOAD => PC_LOAD_EXH, + PC_INC => PC_INC_EXH, + PC_RESTORE => PC_RESTORE_EXH, + + STACK_FORMAT => STACK_FORMAT, + STACK_POS => STACK_POS, + + SP_ADD_DISPL => SP_ADD_DISPL_EXH, + DISPLACEMENT => DISPLACEMENT_EXH, + IPIPE_FILL => IPIPE_FILL, + IPIPE_FLUSH => IPIPE_FLUSH_EXH, + RESTORE_ISP_PC => RESTORE_ISP_PC, + + HALT_OUTn => HALT_OUTn, + + INT_TRIG => INT_TRIG, + IRQ_IN => IPL, + IRQ_PEND => IRQ_PEND, + AVECn => AVECn, + IVECT_OFFS => IVECT_OFFS, + + TRAP_AERR => TRAP_AERR, + TRAP_BERR => BERR_MAIN, + TRAP_CHK => TRAP_CHK, + TRAP_DIVZERO => TRAP_DIVZERO, + TRAP_ILLEGAL => TRAP_ILLEGAL, + TRAP_CODE_OPC => TRAP_CODE_OPC, + TRAP_VECTOR => BIW_0(3 downto 0), + TRAP_V => TRAP_V, + EX_TRACE_IN => EX_TRACE, + VBR_WR => VBR_WR, + VBR => VBR + ); + + I_OPCODE_DECODER: WF68K10_OPCODE_DECODER + generic map(NO_LOOP => NO_LOOP) + port map( + CLK => CLK, + K6800n => K6800n, + + OW_REQ_MAIN => OW_REQ_MAIN, + EW_REQ_MAIN => EW_REQ_MAIN, + + EXH_REQ => EXH_REQ, + BUSY_EXH => BUSY_EXH, + BUSY_MAIN => BUSY_MAIN, + BUSY_OPD => BUSY_OPD, + + BKPT_INSERT => BKPT_INSERT, + BKPT_DATA => DATA_TO_CORE(15 downto 0), + + LOOP_EXIT => LOOP_EXIT, + LOOP_BSY => LOOP_BSY, + + OPD_ACK_MAIN => OPD_ACK_MAIN, + EW_ACK => EW_ACK, + + PC_INC => PC_INC, + PC_INC_EXH => PC_INC_EXH_I, + PC_ADR_OFFSET => PC_ADR_OFFSET, + PC_EW_OFFSET => PC_EW_OFFSET, + PC_OFFSET => PC_OFFSET, + + OPCODE_RD => OPCODE_RD, + OPCODE_RDY => OPCODE_RDY, + OPCODE_VALID => OPCODE_VALID, + OPCODE_DATA => OPCODE_TO_CORE, + + IPIPE_FILL => IPIPE_FILL, + IPIPE_FLUSH => IPIPE_FLUSH, + + -- Fault logic: + OW_VALID => OW_VALID, + + -- Trap logic: + SBIT => SBIT, + TRAP_CODE => TRAP_CODE_OPC, + + -- System control: + OP => OP, + BIW_0 => BIW_0, + BIW_1 => BIW_1, + BIW_2 => BIW_2, + EXT_WORD => EXT_WORD + ); +end STRUCTURE; diff --git a/common/CPU/68K30L/license/cern_ohl_v_1_2.odt b/common/CPU/68K30L/license/cern_ohl_v_1_2.odt new file mode 100644 index 0000000000000000000000000000000000000000..0e4038a4f57e3a45b037e14cb1b89b92c1795150 GIT binary patch literal 25148 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 + + + +CERN Open Hardware Licence - cern_ohl_v_1_2.txt - Open Hardware Repository + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/common/CPU/68K30L/license/cern_ohl_v_1_2_howto.odt b/common/CPU/68K30L/license/cern_ohl_v_1_2_howto.odt new file mode 100644 index 0000000000000000000000000000000000000000..0a1ea6bad3b9d6f28367df588c1923badd1fc7b2 GIT binary patch literal 36026 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 N!d1YM>sLF72LR{7@1g(z literal 0 HcmV?d00001 diff --git a/common/CPU/68K30L/license/cern_ohl_v_1_2_howto.pdf b/common/CPU/68K30L/license/cern_ohl_v_1_2_howto.pdf new file mode 100644 index 0000000000000000000000000000000000000000..feec8175c8dc265f19cb55d226c576455afeed22 GIT binary patch literal 56377 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 HlEd&Ha;r%$ literal 0 HcmV?d00001 diff --git a/common/CPU/68K30L/wf68K30L.sdc b/common/CPU/68K30L/wf68K30L.sdc new file mode 100644 index 00000000..9f93ed49 --- /dev/null +++ b/common/CPU/68K30L/wf68K30L.sdc @@ -0,0 +1,40 @@ +# +# Copyright 2014 Wolfgang Foerster Inventronik GmbH. +# +# This documentation describes Open Hardware and is licensed +# under the CERN OHL v. 1.2. You may redistribute and modify +# this documentation under the terms of the CERN OHL v.1.2. +# (http://ohwr.org/cernohl). This documentation is distributed +# WITHOUT ANY EXPRESS OR IMPLIED WARRANTY, INCLUDING OF +# MERCHANTABILITY, SATISFACTORY QUALITY AND FITNESS FOR A +# PARTICULAR PURPOSE. Please see the CERN OHL v.1.2 for +# applicable conditions + +# Revision History + +# Revision 2K14B 20140922 WF +# Initial Release. + + +#************************************************************** +# Time Information +#************************************************************** + +# set_time_format -unit ns -decimal_places 3 + + + +#************************************************************** +# Create Clock +#************************************************************** + +# create_clock -name CLK -period 100.000 -waveform {0.000 50.000} [get_ports {CLK}] +create_clock -period 32.000 -name CLK [get_ports {CLK}] + +#derive_pll_clocks +#derive_pll_clocks -use_net_name +derive_clock_uncertainty + +#set_clock_groups -exclusive -group {CLK_PLL1} +#set_clock_groups -exclusive -group {CLK_PLL2} +#set_clock_groups -exclusive -group {CODEC_SCLK} diff --git a/common/CPU/68K30L/wf68k30L_address_registers.vhd b/common/CPU/68K30L/wf68k30L_address_registers.vhd new file mode 100644 index 00000000..0e7bd05f --- /dev/null +++ b/common/CPU/68K30L/wf68k30L_address_registers.vhd @@ -0,0 +1,680 @@ +------------------------------------------------------------------------ +---- ---- +---- WF68K30L IP Core: Address register logic. ---- +---- ---- +---- Description: ---- +---- This module provides the address registers, stack pointers, ---- +---- the address arithmetics, the program counter logic and the SFC ---- +---- and DFC registers. The address registers are accessible by two ---- +---- read and two write ports simultaneously. For more information ---- +---- refer to the MC68030 User' Manual. ---- +---- ---- +---- Author(s): ---- +---- - Wolfgang Foerster, wf@experiment-s.de; wf@inventronik.de ---- +---- ---- +------------------------------------------------------------------------ +---- ---- +---- Copyright 2014-2019 Wolfgang Foerster Inventronik GmbH. ---- +---- ---- +---- This documentation describes Open Hardware and is licensed ---- +---- under the CERN OHL v. 1.2. You may redistribute and modify ---- +---- this documentation under the terms of the CERN OHL v.1.2. ---- +---- (http://ohwr.org/cernohl). This documentation is distributed ---- +---- WITHOUT ANY EXPRESS OR IMPLIED WARRANTY, INCLUDING OF ---- +---- MERCHANTABILITY, SATISFACTORY QUALITY AND FITNESS FOR A ---- +---- PARTICULAR PURPOSE. Please see the CERN OHL v.1.2 for ---- +---- applicable conditions ---- +---- ---- +------------------------------------------------------------------------ +-- +-- Revision History +-- +-- Revision 2K14B 20141201 WF +-- Initial Release. +-- Revision 2K16A 20160620 WF +-- Minor optimizations. +-- Revision 2K18A 20180620 WF +-- Changed ADR_ATN logic to be valid one clock cycle earlier. +-- Fixed PC restoring during exception processing. +-- Fixed the writing ISP_REG during EXG instruction with two address registers. +-- Fixed writing the stack pointer registers (MSBIT is used now). +-- The address registers are always written long. +-- Bugfix: exception handler do not increment and decrement the USP any more. +-- MOVEM-Fix: the effective address in memory to register is stored (STORE_AEFF) not to be overwritten in case the addressing register is also loaded. +-- Revision 2K19A 2019## WF +-- Removed ADR_ATN. We do not need this any more. +-- Fixed the condition if UNMARK and AR_MARK_USED are asserted simultaneously (see process P_IN_USE). +-- Fixed the '0' conditions for AR_IN_USE. +-- + +use work.WF68K30L_PKG.all; + +library ieee; +use ieee.std_logic_1164.all; +use ieee.std_logic_unsigned.all; + +entity WF68K30L_ADDRESS_REGISTERS is + port ( + CLK : in std_logic; + RESET : in bit; + + -- Address and data: + AR_IN_1 : in std_logic_vector(31 downto 0); + AR_IN_2 : in std_logic_vector(31 downto 0); + AR_OUT_1 : out std_logic_vector(31 downto 0); + AR_OUT_2 : out std_logic_vector(31 downto 0); + INDEX_IN : in std_logic_vector(31 downto 0); + PC : out std_logic_vector(31 downto 0); -- Program counter (or sPC) always word aligned. + PC_EW_OFFSET : in std_logic_vector(3 downto 0); -- Offset to the first address extension word. + FETCH_MEM_ADR : in bit; + STORE_ADR_FORMAT : in bit; + STORE_ABS_HI : in bit; + STORE_ABS_LO : in bit; + STORE_D16 : in bit; + STORE_D32_LO : in bit; + STORE_D32_HI : in bit; + STORE_DISPL : in bit; + STORE_MEM_ADR : in bit; + STORE_OD_HI : in bit; + STORE_OD_LO : in bit; + STORE_AEFF : in bit; + OP_SIZE : in OP_SIZETYPE; + + ADR_OFFSET : in std_logic_vector(31 downto 0); + ADR_MARK_USED : in bit; + USE_APAIR : in boolean; + ADR_IN_USE : out bit; + + ADR_MODE : in std_logic_vector(2 downto 0); + AMODE_SEL : in std_logic_vector(2 downto 0); + USE_DREG : in bit; -- Use data register as address pointer. + ADR_EFF : out std_logic_vector(31 downto 0); -- This is the effective address. + ADR_EFF_WB : out std_logic_vector(31 downto 0); -- This is the effective address. + + DFC : out std_logic_vector(2 downto 0); + DFC_WR : in bit; + SFC : out std_logic_vector(2 downto 0); + SFC_WR : in bit; + + ISP_DEC : in bit; + ISP_RD : in bit; + ISP_WR : in bit; + MSP_RD : in bit; + MSP_WR : in bit; + USP_RD : in bit; + USP_WR : in bit; + + -- Registers controls: + AR_MARK_USED : in bit; + AR_IN_USE : out bit; + AR_SEL_RD_1 : in std_logic_vector(2 downto 0); + AR_SEL_RD_2 : in std_logic_vector(2 downto 0); + AR_SEL_WR_1 : in std_logic_vector(2 downto 0); + AR_SEL_WR_2 : in std_logic_vector(2 downto 0); + AR_DEC : in bit; -- Address register decrement. + AR_INC : in bit; -- Address register increment. + AR_WR_1 : in bit; -- Address register write. + AR_WR_2 : in bit; -- Address register write. + UNMARK : in bit; + + EXT_WORD : in std_logic_vector(15 downto 0); + + MBIT : in std_logic; + SBIT : in std_logic; + + SP_ADD_DISPL : in bit; + RESTORE_ISP_PC : in bit; + + -- Other controls: + DISPLACEMENT : in std_logic_vector(31 downto 0); + PC_ADD_DISPL : in bit; + PC_INC : in bit; -- Program counter increment. + PC_LOAD : in bit; -- Program counter write. + PC_RESTORE : in bit; + PC_OFFSET : in std_logic_vector(7 downto 0) + ); +end entity WF68K30L_ADDRESS_REGISTERS; + +architecture BEHAVIOR of WF68K30L_ADDRESS_REGISTERS is +type AR_TYPE is array(0 to 6) of std_logic_vector(31 downto 0); +signal ADR_EFF_I : std_logic_vector(31 downto 0); +signal AR : AR_TYPE; -- Address registers A0 to A6. +signal AR_OUT_1_I : std_logic_vector(31 downto 0); +signal AR_OUT_2_I : std_logic_vector(31 downto 0); +signal ADR_WB : std_logic_vector(32 downto 0); +signal AR_PNTR_1 : integer range 0 to 7; +signal AR_PNTR_2 : integer range 0 to 7; +signal AR_PNTR_WB_1 : integer range 0 to 7; +signal AR_PNTR_WB_2 : integer range 0 to 7; +signal AR_USED_1 : std_logic_vector(3 downto 0); +signal AR_USED_2 : std_logic_vector(3 downto 0); +signal B_S : std_logic := '0'; -- Base register suppress. +signal BD_SIZE : std_logic_vector(1 downto 0); -- Indexed / Indirect. +signal DFC_REG : std_logic_vector(2 downto 0); -- Special function code registers. +signal F_E : std_logic; -- Full extension word. +signal I_IS : std_logic_vector(2 downto 0); -- Indexed / Indirect. +signal I_S : std_logic; -- Index suppress. +signal ISP_REG : std_logic_vector(31 downto 0); -- Interrupt stack pointer (refers to A7'' in the supervisor mode). +signal MSBIT : std_logic_vector(1 downto 0); +signal MSP_REG : std_logic_vector(31 downto 0); -- Master stack pointer (refers to A7' in the supervisor mode). +signal PC_I : std_logic_vector(31 downto 0); -- Active program counter. +signal SCALE : std_logic_vector(1 downto 0); -- Scale information for the index. +signal SFC_REG : std_logic_vector(2 downto 0); -- Special function code registers. +signal USP_REG : std_logic_vector(31 downto 0); -- User stack pointer (refers to A7 in the user mode.). +begin + INBUFFER: process + begin + wait until CLK = '1' and CLK' event; + if AR_MARK_USED = '1' then + AR_PNTR_WB_1 <= conv_integer(AR_SEL_WR_1); + AR_PNTR_WB_2 <= conv_integer(AR_SEL_WR_2); + end if; + end process INBUFFER; + + AR_PNTR_1 <= conv_integer(AR_SEL_RD_1); + AR_PNTR_2 <= conv_integer(AR_SEL_RD_2); + + P_IN_USE: process + variable DELAY : boolean; + begin + wait until CLK = '1' and CLK' event; + if RESET = '1' or (UNMARK = '1' and AR_MARK_USED = '0') then + AR_USED_1(3) <= '0'; + AR_USED_2(3) <= '0'; + elsif AR_MARK_USED = '1' then + AR_USED_1 <= '1' & AR_SEL_WR_1; + if USE_APAIR = true then + AR_USED_2 <= '1' & AR_SEL_WR_2; + end if; + MSBIT <= MBIT & SBIT; + end if; + -- + if RESET = '1' or (UNMARK = '1' and AR_MARK_USED = '0') then + ADR_WB(32) <= '0'; + DELAY := false; + elsif ADR_MARK_USED = '1' then + DELAY := true; -- One clock cycle address calculation delay. + elsif DELAY = true then + ADR_WB <= '1' & ADR_EFF_I; + DELAY := false; + end if; + end process P_IN_USE; + + AR_IN_USE <= '0' when AR_USED_1(3) = '1' and AR_USED_1(2 downto 0) = "111" and SBIT = '1' and MSBIT(1) /= MBIT else -- Wrong stack pointer. + '0' when AR_USED_2(3) = '1' and AR_USED_2(2 downto 0) = "111" and SBIT = '1' and MSBIT(1) /= MBIT else -- Wrong stack pointer. + '1' when AR_USED_1(3) = '1' and AR_USED_1(2 downto 0) = AR_SEL_RD_1 else + '1' when AR_USED_1(3) = '1' and AR_USED_1(2 downto 0) = AR_SEL_RD_2 else + '1' when AR_USED_2(3) = '1' and AR_USED_2(2 downto 0) = AR_SEL_RD_1 else + '1' when AR_USED_2(3) = '1' and AR_USED_2(2 downto 0) = AR_SEL_RD_2 else '0'; + + AR_OUT_1 <= AR_OUT_1_I; + AR_OUT_2 <= AR_OUT_2_I; + + ADR_IN_USE <= '1' when ADR_WB(32) = '1' and ADR_WB(31 downto 2) = ADR_EFF_I(31 downto 2) else -- Actual long word address. + '1' when ADR_WB(32) = '1' and ADR_WB(31 downto 2) - '1' = ADR_EFF_I(31 downto 2) else -- Lock a misaligned access. + '1' when ADR_WB(32) = '1' and ADR_WB(31 downto 2) + '1' = ADR_EFF_I(31 downto 2) else '0'; -- Lock a misaligned access. + + ADR_FORMAT: process + begin + wait until CLK = '1' and CLK' event; + if STORE_ADR_FORMAT = '1' then + SCALE <= EXT_WORD(10 downto 9); + F_E <= EXT_WORD(8); + B_S <= EXT_WORD(7); + I_S <= EXT_WORD(6); + BD_SIZE <= EXT_WORD(5 downto 4); + I_IS <= EXT_WORD(2 downto 0); + end if; + end process ADR_FORMAT; + + ADDRESS_MODES: process(ADR_MODE, AMODE_SEL, AR, AR_IN_1, AR_PNTR_1, B_S, + CLK, F_E, FETCH_MEM_ADR, I_S, I_IS, ISP_REG, MBIT, MSP_REG, + PC_EW_OFFSET, PC_I, RESTORE_ISP_PC, SBIT, USE_DREG, USP_REG) + -- The effective address calculation takes place in this process depending on the + -- selected addressing mode. + -- The PC address (PC_I) used for the address calculation points to the first + -- extension word used. + variable ABS_ADDRESS : std_logic_vector(31 downto 0); + variable ADR_EFF_VAR : std_logic_vector(31 downto 0); + variable ADR_EFF_TMP : std_logic_vector(31 downto 0); + variable ADR_MUX : std_logic_vector(31 downto 0); + variable BASE_DISPL : std_logic_vector(31 downto 0); + variable I_S_IS : std_logic_vector(3 downto 0); + variable INDEX : std_logic_vector(31 downto 0) := x"00000000"; + variable INDEX_SCALED : std_logic_vector(31 downto 0); + variable MEM_ADR : std_logic_vector(31 downto 0); + variable OUTER_DISPL : std_logic_vector(31 downto 0); + variable PCVAR : std_logic_vector(31 downto 0); + begin + I_S_IS := I_S & I_IS; + PCVAR := PC_I + PC_EW_OFFSET; -- This is the address of the extension word. + + if CLK = '1' and CLK' event then + -- This logic selects the INDEX from one of the data registers or from one of + -- the address registers. Furthermore the index needs to be sign extended from + -- 8 bit to 32 bit or from 16 bit to 32 bit dependent on the address mode. + -- In case of a long word operation, no extension is required. The index is + -- multiplied by 1, 2, 4 or 8. + if STORE_ADR_FORMAT = '1' and EXT_WORD(15) = '0' and EXT_WORD(11) = '1' then + INDEX := INDEX_IN; -- Long data register. + elsif STORE_ADR_FORMAT = '1' and EXT_WORD(15) = '0' then + for i in 31 downto 16 loop + INDEX(i) := INDEX_IN(15); + end loop; + INDEX(15 downto 0) := INDEX_IN(15 downto 0); -- Sign extended data register; + elsif STORE_ADR_FORMAT = '1' and EXT_WORD(11) = '1' then -- Long address register. + if EXT_WORD(14 downto 12) = "111" and SBIT = '1' and MBIT = '1' then + INDEX := MSP_REG; + elsif EXT_WORD(14 downto 12) = "111" and SBIT = '1' and MBIT = '0' then + INDEX := ISP_REG; + elsif EXT_WORD(14 downto 12) = "111" and SBIT = '0' then + INDEX := USP_REG; + else + INDEX := AR(conv_integer(EXT_WORD(14 downto 12))); + end if; + elsif STORE_ADR_FORMAT = '1' then -- Sign extended address register; + if EXT_WORD(14 downto 12) = "111" and SBIT = '1' and MBIT = '1' then + for i in 31 downto 16 loop + INDEX(i) := MSP_REG(15); + end loop; + INDEX(15 downto 0) := MSP_REG(15 downto 0); + elsif EXT_WORD(14 downto 12) = "111" and SBIT = '1' and MBIT = '0' then + for i in 31 downto 16 loop + INDEX(i) := ISP_REG(15); + end loop; + INDEX(15 downto 0) := ISP_REG(15 downto 0); + elsif EXT_WORD(14 downto 12) = "111" and SBIT = '0' then + for i in 31 downto 16 loop + INDEX(i) := USP_REG(15); + end loop; + INDEX(15 downto 0) := USP_REG(15 downto 0); + else + for i in 31 downto 16 loop + INDEX(i) := AR(conv_integer(EXT_WORD(14 downto 12)))(15); + end loop; + INDEX(15 downto 0) := AR(conv_integer(EXT_WORD(14 downto 12)))(15 downto 0); + end if; + end if; + -- + case SCALE is + when "00" => INDEX_SCALED := INDEX; -- Multiple by 1. + when "01" => INDEX_SCALED := INDEX(30 downto 0) & '0'; -- Multiple by 2. + when "10" => INDEX_SCALED := INDEX(29 downto 0) & "00"; -- Multiple by 4. + when others => INDEX_SCALED := INDEX(28 downto 0) & "000"; -- Multiple by 8. + end case; + -- + -- Register for memory indirect addressing modes. + if STORE_MEM_ADR = '1' then + MEM_ADR := AR_IN_1; + end if; + -- + -- The displacement needs to be sign extended from 8 bit to 32, from 16 bit to 32 bit or + -- not extended dependent on the address mode. + if RESET = '1' then + BASE_DISPL := (others => '0'); -- Null base displacement. + elsif STORE_ADR_FORMAT = '1' and EXT_WORD(8) = '1' and EXT_WORD(5 downto 4) = "01" then + BASE_DISPL := (others => '0'); -- Null base displacement. + elsif STORE_ADR_FORMAT = '1' and EXT_WORD(8) = '0' then + for i in 31 downto 8 loop + BASE_DISPL(i) := EXT_WORD(7); + end loop; + BASE_DISPL(7 downto 0) := EXT_WORD(7 downto 0); + elsif STORE_D16 = '1' then + for i in 31 downto 16 loop + BASE_DISPL(i) := EXT_WORD(15); + end loop; + BASE_DISPL(15 downto 0) := EXT_WORD; + elsif STORE_D32_LO = '1' then + if BD_SIZE = "10" then -- Word displacement. + for i in 31 downto 16 loop + BASE_DISPL(i) := EXT_WORD(15); + end loop; + end if; + BASE_DISPL(15 downto 0) := EXT_WORD; + elsif STORE_D32_HI = '1' then + BASE_DISPL(31 downto 16) := EXT_WORD; + elsif STORE_DISPL = '1' then + BASE_DISPL := DISPLACEMENT; + end if; + -- + -- The outer displacement may be NULL, WORD or LONG. + if STORE_ADR_FORMAT = '1' and EXT_WORD(8) = '1' and EXT_WORD(1 downto 0) = "01" then + OUTER_DISPL := (others => '0'); -- Null outer displacement. + elsif STORE_OD_LO = '1' then + if I_IS(1 downto 0) = "10" then + for i in 31 downto 16 loop + OUTER_DISPL(i) := EXT_WORD(15); + end loop; + end if; + OUTER_DISPL(15 downto 0) := EXT_WORD; + elsif STORE_OD_HI = '1' then + OUTER_DISPL(31 downto 16) := EXT_WORD; + end if; + -- + if STORE_ABS_LO = '1' then + if AMODE_SEL = "000" then + for i in 31 downto 16 loop + ABS_ADDRESS(i) := EXT_WORD(15); + end loop; + end if; + ABS_ADDRESS(15 downto 0) := EXT_WORD; + elsif STORE_ABS_HI = '1' then + ABS_ADDRESS(31 downto 16) := EXT_WORD; + end if; + end if; + + if ADR_MODE = "110" and FETCH_MEM_ADR = '1' and F_E = '1' and B_S = '1' then + ADR_MUX := x"00000000"; -- Base register suppress. + elsif ADR_MODE = "111" and FETCH_MEM_ADR = '1' and AMODE_SEL = "011" and F_E = '1' and B_S = '1' then + ADR_MUX := x"00000000"; -- Base register suppress. + elsif USE_DREG = '1' then + ADR_MUX := AR_IN_1; + else + case AR_PNTR_1 is + when 7 => + if SBIT = '1' and MBIT = '0' then + ADR_MUX := ISP_REG; + elsif SBIT = '1' then + ADR_MUX := MSP_REG; + else + ADR_MUX := USP_REG; + end if; + when others => ADR_MUX := AR(AR_PNTR_1); + end case; + end if; + + case ADR_MODE is + -- when "000" | "001" => Direct address modes: no effective address required. + when "010" | "011" | "100" => + ADR_EFF_VAR := ADR_MUX; -- (An), (An)+, -(An). + when "101" => -- Address register indirect with offset. Assembler syntax: (d16,An). + ADR_EFF_VAR := ADR_MUX + BASE_DISPL; -- (d16,An). + when "110" => + if F_E = '0' then -- Brief extension word. + ADR_EFF_VAR := ADR_MUX + BASE_DISPL + INDEX_SCALED; -- (d8, An, Xn, SIZE*SCALE). + else -- Full extension word. + case I_S_IS is + when "0000" | "1000" => -- No memory indirect action. + ADR_EFF_VAR := ADR_MUX + BASE_DISPL + INDEX_SCALED; -- (bd, An, Xn, SIZE*SCALE). + when "0001" | "0010" | "0011" => -- Memory indirect preindexed. + if FETCH_MEM_ADR = '1' then + ADR_EFF_VAR := ADR_MUX + BASE_DISPL + INDEX_SCALED; + else + ADR_EFF_VAR := MEM_ADR + OUTER_DISPL; + end if; + when "0101" | "0110" | "0111" => -- Memory indirect postindexed. + if FETCH_MEM_ADR = '1' then + ADR_EFF_VAR := ADR_MUX + BASE_DISPL; + else + ADR_EFF_VAR := MEM_ADR + INDEX_SCALED + OUTER_DISPL; + end if; + when "1001" | "1010" | "1011" => -- Memory indirect. + if FETCH_MEM_ADR = '1' then + ADR_EFF_VAR := ADR_MUX + BASE_DISPL; + else + ADR_EFF_VAR := MEM_ADR + OUTER_DISPL; + end if; + when others => + ADR_EFF_VAR := (others => '-'); -- Reserved, don't care. + end case; + end if; + when "111" => + case AMODE_SEL is + when "000" | "001" => + ADR_EFF_VAR := ABS_ADDRESS; + when "010" => -- (d16, PC). + ADR_EFF_VAR := PCVAR + BASE_DISPL; + when "011" => + if F_E = '0' then -- Brief extension word. + -- Assembler syntax: (d8,PC,Xn.SIZE*SCALE). + ADR_EFF_VAR := PCVAR + BASE_DISPL + INDEX_SCALED; -- (d8, PC, Xn, SIZE*SCALE). + else -- Full extension word. + case I_S_IS is + when "0000" | "1000" => -- No memory indirect action. + ADR_EFF_VAR := PCVAR + BASE_DISPL + INDEX_SCALED; -- (bd, PC, Xn, SIZE*SCALE). + when "0001" | "0010" | "0011" => -- Memory indirect preindexed. + if FETCH_MEM_ADR = '1' then + ADR_EFF_VAR := PCVAR + BASE_DISPL + INDEX_SCALED; + else + ADR_EFF_VAR := MEM_ADR + OUTER_DISPL; + end if; + when "0101" | "0110" | "0111" => -- Memory indirect postindexed. + if FETCH_MEM_ADR = '1' then + ADR_EFF_VAR := PCVAR + BASE_DISPL; + else + ADR_EFF_VAR := MEM_ADR + INDEX_SCALED + OUTER_DISPL; + end if; + when "1001" | "1010" | "1011" => -- Memory indirect. + if FETCH_MEM_ADR = '1' then + ADR_EFF_VAR := PCVAR + BASE_DISPL; + else + ADR_EFF_VAR := MEM_ADR + OUTER_DISPL; + end if; + when others => + ADR_EFF_VAR := (others => '-'); -- Reserved, don't care. + end case; + end if; + when others => + ADR_EFF_VAR := (others => '-'); -- Don't care, while not used. + end case; + when others => + ADR_EFF_VAR := (others => '-'); -- Result not required. + end case; + -- + if CLK = '1' and CLK' event then + if RESTORE_ISP_PC = '1' then + ADR_EFF_I <= ADR_OFFSET; -- During system initialization. + elsif STORE_AEFF = '1' then -- Used for MOVEM. + ADR_EFF_I <= ADR_EFF_TMP + ADR_OFFSET; -- Keep the effective address. See also CONTROL section. + else -- Normal operation: + ADR_EFF_I <= ADR_EFF_VAR + ADR_OFFSET; + ADR_EFF_TMP := ADR_EFF_VAR; + end if; + end if; + end process ADDRESS_MODES; + + ADR_EFF <= ADR_EFF_I; + ADR_EFF_WB <= ADR_WB(31 downto 0); + + -- Data outputs: + AR_OUT_1_I <= ISP_REG when ISP_RD = '1' else + MSP_REG when MSP_RD = '1' else + USP_REG when USP_RD = '1' else + AR(AR_PNTR_1) when AR_PNTR_1 < 7 else + MSP_REG when SBIT = '1' and MBIT = '1' else + ISP_REG when SBIT = '1' and MBIT = '0' else USP_REG; + + AR_OUT_2_I <= AR(AR_PNTR_2) when AR_PNTR_2 < 7 else + MSP_REG when SBIT = '1' and MBIT = '1' else + ISP_REG when SBIT = '1' and MBIT = '0' else USP_REG; + + PC <= PC_I; + + PROGRAM_COUNTER: process + -- Note: PC_LOAD and PC_ADD_DISPL must be highest + -- prioritized. The reason is that in case of jumps + -- or branches the Ipipe is flushed in connection + -- with PC_INC. In such cases PC_LOAD or PC_ADD_DISPL + -- are asserted simultaneously with PC_INC. + begin + wait until CLK = '1' and CLK' event; + if RESET = '1' then + PC_I <= (others => '0'); + elsif PC_LOAD = '1' then + PC_I <= AR_IN_1; + elsif PC_ADD_DISPL = '1' then + PC_I <= PC_I + DISPLACEMENT; + elsif PC_RESTORE = '1' then + PC_I <= AR_IN_1; -- Keep prioritization! + elsif PC_INC = '1' then + PC_I <= PC_I + PC_OFFSET; + end if; + end process PROGRAM_COUNTER; + + STACK_POINTERS: process + -- The registers are modeled in a way + -- that write and simultaneously increment + -- decrement and others are possible for + -- different registers. + begin + wait until CLK = '1' and CLK' event; + + ---------------------------------------- MSP section ---------------------------------------- + if RESET = '1' then + MSP_REG <= (others => '0'); + elsif AR_WR_1 = '1' and AR_PNTR_WB_1 = 7 and MSBIT = "11" then + MSP_REG <= AR_IN_1; -- Always written long. + end if; + + if AR_INC = '1' and AR_PNTR_1 = 7 and SBIT = '1' and MBIT = '1' then + case OP_SIZE is + when BYTE => MSP_REG <= MSP_REG + "10"; -- Increment by two! + when WORD => MSP_REG <= MSP_REG + "10"; -- Increment by two. + when others => MSP_REG <= MSP_REG + "100"; -- Increment by four, (LONG). + end case; + end if; + + if AR_DEC = '1' and AR_PNTR_1 = 7 and SBIT = '1' and MBIT = '1' then + case OP_SIZE is + when BYTE => MSP_REG <= MSP_REG - "10"; -- Decrement by two! + when WORD => MSP_REG <= MSP_REG - "10"; -- Decrement by two. + when others => MSP_REG <= MSP_REG - "100"; -- Decrement by four, (LONG). + end case; + end if; + + if MSP_WR = '1' then + MSP_REG <= AR_IN_1; + elsif SP_ADD_DISPL = '1' and AR_INC = '1' and SBIT = '1' and MBIT = '1' then + MSP_REG <= MSP_REG + DISPLACEMENT + "100"; -- Used for RTD. + elsif SP_ADD_DISPL = '1' and SBIT = '1' and MBIT = '1' then + MSP_REG <= MSP_REG + DISPLACEMENT; + end if; + + ---------------------------------------- ISP section ---------------------------------------- + if RESET = '1' then + ISP_REG <= (others => '0'); + elsif AR_WR_1 = '1' and AR_PNTR_WB_1 = 7 and MSBIT = "01" then + ISP_REG <= AR_IN_1; -- Always written long. + end if; + + if AR_INC = '1' and AR_PNTR_1 = 7 and SBIT = '1' and MBIT = '0' then + case OP_SIZE is + when BYTE => ISP_REG <= ISP_REG + "10"; -- Increment by two! + when WORD => ISP_REG <= ISP_REG + "10"; -- Increment by two. + when others => ISP_REG <= ISP_REG + "100"; -- Increment by four, (LONG). + end case; + end if; + + if ISP_DEC = '1' or (AR_DEC = '1' and AR_PNTR_1 = 7 and SBIT = '1' and MBIT = '0') then + case OP_SIZE is + when BYTE => ISP_REG <= ISP_REG - "10"; -- Decrement by two! + when WORD => ISP_REG <= ISP_REG - "10"; -- Decrement by two. + when others => ISP_REG <= ISP_REG - "100"; -- Decrement by four, (LONG). + end case; + end if; + + if ISP_WR = '1' then + ISP_REG <= AR_IN_1; + elsif SP_ADD_DISPL = '1' and AR_INC = '1' and SBIT = '1' and MBIT = '0' then + ISP_REG <= ISP_REG + DISPLACEMENT + "100"; -- Used for RTD. + elsif SP_ADD_DISPL = '1' and SBIT = '1' and MBIT = '0' then + ISP_REG <= ISP_REG + DISPLACEMENT; + end if; + + ---------------------------------------- USP section ---------------------------------------- + if RESET = '1' then + USP_REG <= (others => '0'); + elsif AR_WR_1 = '1' and AR_PNTR_WB_1 = 7 and MSBIT(0) = '0' then + USP_REG <= AR_IN_1; -- Always written long. + end if; + + if AR_INC = '1' and AR_PNTR_1 = 7 and SBIT = '0' then + case OP_SIZE is + when BYTE => USP_REG <= USP_REG + "10"; -- Increment by two! + when WORD => USP_REG <= USP_REG + "10"; -- Increment by two. + when others => USP_REG <= USP_REG + "100"; -- Increment by four, (LONG). + end case; + end if; + + if AR_DEC = '1' and AR_PNTR_1 = 7 and SBIT = '0' then + case OP_SIZE is + when BYTE => USP_REG <= USP_REG - "10"; -- Decrement by two! + when WORD => USP_REG <= USP_REG - "10"; -- Decrement by two. + when others => USP_REG <= USP_REG - "100"; -- Decrement by four, (LONG). + end case; + end if; + + if USP_WR = '1' then + USP_REG <= AR_IN_1; + elsif SP_ADD_DISPL = '1' and AR_INC = '1' and SBIT = '0' then + USP_REG <= USP_REG + DISPLACEMENT + "100"; -- Used for RTD. + elsif SP_ADD_DISPL = '1' and SBIT = '0' then + USP_REG <= USP_REG + DISPLACEMENT; + end if; + + if AR_WR_2 = '1' and AR_PNTR_WB_2 = 7 and MSBIT = "11" then + MSP_REG <= AR_IN_2; -- Used for EXG and UNLK. + elsif AR_WR_2 = '1' and AR_PNTR_WB_2 = 7 and MSBIT = "01" then + ISP_REG <= AR_IN_2; -- Used for EXG and UNLK. + elsif AR_WR_2 = '1' and AR_PNTR_WB_2 = 7 then + USP_REG <= AR_IN_2; -- Used for EXG and UNLK. + end if; + end process STACK_POINTERS; + + ADDRESS_REGISTERS: process + -- The registers are modeled in a way + -- that write and simultaneously increment + -- decrement and others are possible for + -- different registers. + begin + -- + wait until CLK = '1' and CLK' event; + + if RESET = '1' then + AR <= (others => (Others => '0')); + end if; + + if AR_WR_1 = '1' and AR_PNTR_WB_1 < 7 then + AR(AR_PNTR_WB_1) <= AR_IN_1; -- Always written long. + end if; + + if AR_INC = '1' and AR_PNTR_1 < 7 then + case OP_SIZE is + when BYTE => AR(AR_PNTR_1) <= AR(AR_PNTR_1) + '1'; + when WORD => AR(AR_PNTR_1) <= AR(AR_PNTR_1) + "10"; + when others => AR(AR_PNTR_1) <= AR(AR_PNTR_1) + "100"; + end case; + end if; + + if AR_DEC = '1' and AR_PNTR_1 < 7 then + case OP_SIZE is + when BYTE => AR(AR_PNTR_1) <= AR(AR_PNTR_1) - '1'; + when WORD => AR(AR_PNTR_1) <= AR(AR_PNTR_1) - "10"; + when others => AR(AR_PNTR_1) <= AR(AR_PNTR_1) - "100"; + end case; + end if; + + if AR_WR_2 = '1' and AR_PNTR_WB_2 < 7 then + AR(AR_PNTR_WB_2) <= AR_IN_2; -- Used for EXG and UNLK. + end if; + end process ADDRESS_REGISTERS; + + FCODES: process + -- These flip flops provide the alternate function + -- code registers. + variable SFC_REG : std_logic_vector(2 downto 0); + variable DFC_REG : std_logic_vector(2 downto 0); + begin + wait until CLK = '1' and CLK' event; + if DFC_WR = '1' then + DFC_REG := AR_IN_1(2 downto 0); + end if; + -- + if SFC_WR = '1' then + SFC_REG := AR_IN_1(2 downto 0); + end if; + -- + DFC <= DFC_REG; + SFC <= SFC_REG; + end process FCODES; +end BEHAVIOR; diff --git a/common/CPU/68K30L/wf68k30L_alu.vhd b/common/CPU/68K30L/wf68k30L_alu.vhd new file mode 100644 index 00000000..58d5cdaf --- /dev/null +++ b/common/CPU/68K30L/wf68k30L_alu.vhd @@ -0,0 +1,1264 @@ +------------------------------------------------------------------------ +---- ---- +---- WF68K30L IP Core: Address register logic. ---- +---- ---- +---- Description: ---- +---- This arithmetical logical unit handles all integer operations. ---- +---- The shift operations are computed by a standard shifter within ---- +---- up to 32 clock cycles depending on the shift width. This unit ---- +---- also handles the bit field operations within one clock cycle. ---- +---- The multiplication is modeled as a hardware multiplier which ---- +---- calculates the result in one clock cycle. The division requi- ---- +---- res 32 clock cycles for 32 bit wide operands. The date which ---- +---- is required for the respective operation is stored in regis- ---- +---- ters. The ALU works together with the writeback of the oper- ---- +---- ands as third stage in the pipelined architecture. The hand- ---- +---- shaking is provided by ALU_REQ, ALU_ACK and ALU_BUSY. For more ---- +---- information refer to the MC68010 User' Manual. ---- +---- ---- +---- ---- +---- Author(s): ---- +---- - Wolfgang Foerster, wf@experiment-s.de; wf@inventronik.de ---- +---- ---- +------------------------------------------------------------------------ +---- ---- +---- Copyright 2014-2019 Wolfgang Foerster Inventronik GmbH. ---- +---- ---- +---- This documentation describes Open Hardware and is licensed ---- +---- under the CERN OHL v. 1.2. You may redistribute and modify ---- +---- this documentation under the terms of the CERN OHL v.1.2. ---- +---- (http://ohwr.org/cernohl). This documentation is distributed ---- +---- WITHOUT ANY EXPRESS OR IMPLIED WARRANTY, INCLUDING OF ---- +---- MERCHANTABILITY, SATISFACTORY QUALITY AND FITNESS FOR A ---- +---- PARTICULAR PURPOSE. Please see the CERN OHL v.1.2 for ---- +---- applicable conditions ---- +---- ---- +------------------------------------------------------------------------ +-- +-- Revision History +-- +-- Revision 2K14B 20141201 WF +-- Initial Release. +-- Revision 2K14B 20141201 WF +-- Fixed the CAS and CAS2 conditional testing. Thanks to Raymond Mounissamy for the correct code. +-- Revision 2K18A 20180620 WF +-- Bug fix: MOVEM sign extension. +-- Fix for restoring correct values during the DIVS and DIVU in word format. +-- Fixed the SUBQ calculation. +-- Rearranged the Offset for the JSR instruction. +-- EXT instruction uses now RESULT(63 downto 0). +-- Shifter signals now ready if shift width is zero. +-- Fixed wrong condition codes for AND_B, ANDI, EOR, EORI, OR_B, ORI and NOT_B. +-- Fixed writeback issues in the status register logic. +-- Fixed the condition code calculation for NEG and NEGX. +-- Revision 2K19A 20190620 WF +-- Fixed a bug in MULU.W (input operands are now 16 bit wide). +-- + +library work; +use work.WF68K30L_PKG.all; + +library ieee; +use ieee.std_logic_1164.all; +use ieee.std_logic_unsigned.all; +use ieee.numeric_std.all; + +entity WF68K30L_ALU is + port ( + CLK : in std_logic; + RESET : in bit; + + LOAD_OP1 : in bit; + LOAD_OP2 : in bit; + LOAD_OP3 : in bit; + + OP1_IN : in Std_Logic_Vector(31 downto 0); + OP2_IN : in Std_Logic_Vector(31 downto 0); + OP3_IN : in Std_Logic_Vector(31 downto 0); + + BF_OFFSET_IN : in Std_Logic_Vector(31 downto 0); + BF_WIDTH_IN : in Std_Logic_Vector(5 downto 0); + BITPOS_IN : in Std_Logic_Vector(4 downto 0); + + RESULT : out Std_Logic_Vector(63 downto 0); + + ADR_MODE_IN : in Std_Logic_Vector(2 downto 0); + OP_SIZE_IN : in OP_SIZETYPE; + OP_IN : in OP_68K; + OP_WB : in OP_68K; + BIW_0_IN : in Std_Logic_Vector(11 downto 0); + BIW_1_IN : in Std_Logic_Vector(15 downto 0); + + -- The Flags: + SR_WR : in bit; + SR_INIT : in bit; + SR_CLR_MBIT : in bit; + CC_UPDT : in bit; + + STATUS_REG_OUT : out std_logic_vector(15 downto 0); + ALU_COND : out boolean; + + -- Status and Control: + ALU_INIT : in bit; -- Strobe. + ALU_BSY : out bit; + ALU_REQ : buffer bit; + ALU_ACK : in bit; + USE_DREG : in bit; -- Used for CAS2, CHK2, CMP2. + HILOn : in bit; + IRQ_PEND : in std_logic_vector(2 downto 0); + TRAP_CHK : out bit; -- Trap due to the CHK, CHK2 instructions. + TRAP_DIVZERO : out bit -- Trap due to divide by zero. + ); +end entity WF68K30L_ALU; + +architecture BEHAVIOUR of WF68K30L_ALU is +type DIV_STATES is (IDLE, INIT, CALC); +type SHIFT_STATES is (IDLE, RUN); +signal ALU_COND_I : boolean; +signal ADR_MODE : Std_Logic_Vector(2 downto 0); +signal BITPOS : integer range 0 to 31; +signal BF_DATA_IN : Std_Logic_Vector(39 downto 0); +signal BF_LOWER_BND : integer range 0 to 39; +signal BF_OFFSET : Std_Logic_Vector(31 downto 0); +signal BF_UPPER_BND : integer range 0 to 39; +signal BF_WIDTH : integer range 1 to 32; +signal BIW_0 : Std_Logic_Vector(11 downto 0); +signal BIW_1 : Std_Logic_Vector(15 downto 0); +signal CAS2_COND : boolean; +signal CB_BCD : std_logic; +signal CHK_CMP_COND : boolean; +signal CHK2CMP2_DR : bit; +signal DIV_RDY : bit; +signal DIV_STATE : DIV_STATES := IDLE; +signal MSB : integer range 0 to 31; +signal OP : OP_68K := UNIMPLEMENTED; +signal OP1 : Std_Logic_Vector(31 downto 0); +signal OP2 : Std_Logic_Vector(31 downto 0); +signal OP3 : Std_Logic_Vector(31 downto 0); +signal OP1_SIGNEXT : Std_Logic_Vector(31 downto 0); +signal OP2_SIGNEXT : Std_Logic_Vector(31 downto 0); +signal OP3_SIGNEXT : Std_Logic_Vector(31 downto 0); +signal OP_SIZE : OP_SIZETYPE := LONG; +signal QUOTIENT : unsigned(31 downto 0); +signal REMAINDER : unsigned(31 downto 0); +signal RESULT_BCDOP : Std_Logic_Vector(7 downto 0); +signal RESULT_BITFIELD : Std_Logic_Vector(39 downto 0); +signal RESULT_BITOP : Std_Logic_Vector(31 downto 0); +signal RESULT_INTOP : Std_Logic_Vector(31 downto 0); +signal RESULT_LOGOP : Std_Logic_Vector(31 downto 0); +signal RESULT_MUL : Std_Logic_Vector(63 downto 0); +signal RESULT_SHIFTOP : Std_Logic_Vector(31 downto 0); +signal RESULT_OTHERS : Std_Logic_Vector(31 downto 0); +signal SHIFT_STATE : SHIFT_STATES; +signal SHIFT_WIDTH : Std_Logic_Vector(5 downto 0); +signal SHIFT_WIDTH_IN : Std_Logic_Vector(5 downto 0); +signal SHFT_LOAD : bit; +signal SHFT_RDY : bit; +signal SHFT_EN : bit; +signal STATUS_REG : Std_Logic_Vector(15 downto 0); +signal VFLAG_DIV : std_logic; +signal XFLAG_SHFT : std_logic; +signal XNZVC : Std_Logic_Vector(4 downto 0); +begin + PARAMETER_BUFFER: process + begin + wait until CLK = '1' and CLK' event; + if ALU_INIT = '1' then + ADR_MODE <= ADR_MODE_IN; + CHK2CMP2_DR <= USE_DREG; + OP_SIZE <= OP_SIZE_IN; + OP <= OP_IN; + BIW_0 <= BIW_0_IN; + BIW_1 <= BIW_1_IN; + BF_OFFSET <= BF_OFFSET_IN; + BITPOS <= To_Integer(unsigned(BITPOS_IN)); + BF_WIDTH <= To_Integer(unsigned(BF_WIDTH_IN)); + BF_UPPER_BND <= 39 - To_Integer(unsigned(BITPOS_IN)); + SHIFT_WIDTH <= SHIFT_WIDTH_IN; + -- + if To_Integer(unsigned(BITPOS_IN)) + To_Integer(unsigned(BF_WIDTH_IN)) > 40 then + BF_LOWER_BND <= 0; + else + BF_LOWER_BND <= 40 - (To_Integer(unsigned(BITPOS_IN)) + To_Integer(unsigned(BF_WIDTH_IN))); + end if; + end if; + end process PARAMETER_BUFFER; + + OPERANDS: process + -- During instruction execution, the buffers are written + -- before or during ALU_INIT and copied to the operands + -- during ALU_INIT. + variable OP1_BUFFER : Std_Logic_Vector(31 downto 0); + variable OP2_BUFFER : Std_Logic_Vector(31 downto 0); + variable OP3_BUFFER : Std_Logic_Vector(31 downto 0); + begin + wait until CLK = '1' and CLK' event; + if LOAD_OP1 = '1' then + OP1_BUFFER := OP1_IN; + end if; + + if LOAD_OP2 = '1' then + OP2_BUFFER := OP2_IN; + end if; + + if LOAD_OP3 = '1' then + OP3_BUFFER := OP3_IN; + end if; + + if ALU_INIT = '1' then + OP1 <= OP1_BUFFER; + OP2 <= OP2_BUFFER; + OP3 <= OP3_BUFFER; + end if; + end process OPERANDS; + + P_BUSY: process + begin + wait until CLK = '1' and CLK' event; + if ALU_INIT = '1' then + ALU_BSY <= '1'; + elsif ALU_ACK = '1' or RESET = '1' then + ALU_BSY <= '0'; + end if; + -- This signal requests the control state machine to proceed when the ALU is ready. + if ALU_ACK = '1' then + ALU_REQ <= '0'; + elsif (OP = ASL or OP = ASR or OP = LSL or OP = LSR or OP = ROTL or OP = ROTR or OP = ROXL or OP = ROXR) and SHFT_RDY = '1' then + ALU_REQ <= '1'; + elsif (OP = DIVS or OP = DIVU) and DIV_RDY = '1' then + ALU_REQ <= '1'; + elsif OP_IN = DIVS or OP_IN = DIVU then + null; + elsif OP_IN = ASL or OP_IN = ASR or OP_IN = LSL or OP_IN = LSR then + null; + elsif OP_IN = ROTL or OP_IN = ROTR or OP_IN = ROXL or OP_IN = ROXR then + null; + elsif ALU_INIT = '1' then + ALU_REQ <= '1'; + end if; + end process P_BUSY; + + with OP_SIZE select + MSB <= 31 when LONG, + 15 when WORD, + 7 when BYTE; + + SIGNEXT: process(OP, OP1, OP2, OP3, OP_SIZE) + -- This module provides the required sign extensions. + begin + case OP_SIZE is + when LONG => + OP1_SIGNEXT <= OP1; + OP2_SIGNEXT <= OP2; + OP3_SIGNEXT <= OP3; + when WORD => + for i in 31 downto 16 loop + OP1_SIGNEXT(i) <= OP1(15); + OP2_SIGNEXT(i) <= OP2(15); + OP3_SIGNEXT(i) <= OP3(15); + end loop; + OP1_SIGNEXT(15 downto 0) <= OP1(15 downto 0); + OP2_SIGNEXT(15 downto 0) <= OP2(15 downto 0); + OP3_SIGNEXT(15 downto 0) <= OP3(15 downto 0); + when BYTE => + for i in 31 downto 8 loop + OP1_SIGNEXT(i) <= OP1(7); + OP2_SIGNEXT(i) <= OP2(7); + OP3_SIGNEXT(i) <= OP3(7); + end loop; + OP1_SIGNEXT(7 downto 0) <= OP1(7 downto 0); + OP2_SIGNEXT(7 downto 0) <= OP2(7 downto 0); + OP3_SIGNEXT(7 downto 0) <= OP3(7 downto 0); + end case; + end process SIGNEXT; + + P_BCDOP: process(OP, STATUS_REG, OP1, OP2) + -- The BCD operations are all byte wide and unsigned. + variable X_IN_I : unsigned(0 downto 0); + variable TEMP0 : unsigned(4 downto 0); + variable TEMP1 : unsigned(4 downto 0); + variable Z_0 : unsigned(3 downto 0); + variable C_0 : unsigned(0 downto 0); + variable Z_1 : unsigned(3 downto 0); + variable C_1 : std_logic; + variable S_0 : unsigned(3 downto 0); + variable S_1 : unsigned(3 downto 0); + begin + X_IN_I(0) := STATUS_REG(4); -- Inverted extended Flag. + + case OP is + when ABCD => + TEMP0 := unsigned('0' & OP2(3 downto 0)) + unsigned('0' & OP1(3 downto 0)) + ("0000" & X_IN_I); + when NBCD => + TEMP0 := unsigned(OP1(4 downto 0)) - unsigned('0' & OP2(3 downto 0)) - ("0000" & X_IN_I); + when others => -- Valid for SBCD. + TEMP0 := unsigned('0' & OP2(3 downto 0)) - unsigned('0' & OP1(3 downto 0)) - ("0000" & X_IN_I); + end case; + + if Std_Logic_Vector(TEMP0) > "01001" then + Z_0 := "0110"; + C_0 := "1"; + else + Z_0 := "0000"; + C_0 := "0"; + end if; + + case OP is + when ABCD => + TEMP1 := unsigned('0' & OP2(7 downto 4)) + unsigned('0' & OP1(7 downto 4)) + ("0000" & C_0); + when NBCD => + TEMP1 := unsigned(OP1(4 downto 0)) - unsigned('0' & OP2(7 downto 4)) - ("0000" & X_IN_I); + when others => -- Valid for SBCD. + TEMP1 := unsigned('0' & OP2(7 downto 4)) - unsigned('0' & OP1(7 downto 4)) - ("0000" & C_0); + end case; + + if Std_Logic_Vector(TEMP1) > "01001" then + Z_1 := "0110"; + C_1 := '1'; + else + Z_1 := "0000"; + C_1 := '0'; + end if; + + case OP is + when ABCD => + S_1 := TEMP1(3 downto 0) + Z_1; + S_0 := TEMP0(3 downto 0) + Z_0; + when others => -- Valid for SBCD, NBCD. + S_1 := TEMP1(3 downto 0) - Z_1; + S_0 := TEMP0(3 downto 0) - Z_0; + end case; + -- + CB_BCD <= C_1; + RESULT_BCDOP(7 downto 4) <= Std_Logic_Vector(S_1); + RESULT_BCDOP(3 downto 0) <= Std_Logic_Vector(S_0); + end process P_BCDOP; + + BF_DATA_IN <= OP3 & OP2(7 downto 0); + + P_BITFIELD_OP: process(BF_DATA_IN, BF_LOWER_BND, BF_OFFSET, BF_UPPER_BND, BF_WIDTH, BIW_1, OP, OP1) + variable BF_NZ : boolean; + variable BFFFO_CNT : std_logic_vector(5 downto 0); + begin + RESULT_BITFIELD <= BF_DATA_IN; -- Default. + case OP is + when BFCHG => + for i in RESULT_BITFIELD'range loop + if i >= BF_LOWER_BND and i <= BF_UPPER_BND then + RESULT_BITFIELD(i) <= not BF_DATA_IN(i); + end if; + end loop; + when BFCLR => + for i in RESULT_BITFIELD'range loop + if i >= BF_LOWER_BND and i <= BF_UPPER_BND then + RESULT_BITFIELD(i) <= '0'; + end if; + end loop; + when BFEXTS => -- Result is in (39 downto 8). + for i in 31 downto 0 loop + if i <= BF_WIDTH - 1 and BF_LOWER_BND + i <= 39 then + RESULT_BITFIELD(i + 8) <= BF_DATA_IN(BF_LOWER_BND + i); + end if; + end loop; + -- + for i in RESULT_BITFIELD'range loop + if i >= 8 + BF_WIDTH then + RESULT_BITFIELD(i) <= BF_DATA_IN(BF_UPPER_BND); + end if; + end loop; + when BFEXTU => -- Result is in (39 downto 8). + for i in 31 downto 0 loop + if i <= BF_WIDTH - 1 and BF_LOWER_BND + i <= 39 then + RESULT_BITFIELD(i + 8) <= BF_DATA_IN(BF_LOWER_BND + i); + end if; + end loop; + -- + for i in RESULT_BITFIELD'range loop + if i >= 8 + BF_WIDTH then + RESULT_BITFIELD(i) <= '0'; + end if; + end loop; + when BFFFO => -- Result is in (39 downto 8). + BF_NZ := false; + BFFFO_CNT := "000000"; + for i in BF_DATA_IN'range loop + if i <= BF_UPPER_BND and i >= BF_LOWER_BND then + if BF_DATA_IN(i) = '0' and BF_NZ = false then + BFFFO_CNT := BFFFO_CNT + '1'; + else + BF_NZ := true; + end if; + end if; + end loop; + -- + RESULT_BITFIELD <= (BF_OFFSET + BFFFO_CNT) & x"00"; + when BFINS => + for i in RESULT_BITFIELD'range loop + if i <= BF_WIDTH - 1 and (BF_UPPER_BND - i) >= 0 then + RESULT_BITFIELD(BF_UPPER_BND - i) <= OP1(BF_WIDTH - i - 1); + end if; + end loop; + when BFSET => + for i in RESULT_BITFIELD'range loop + if i >= BF_LOWER_BND and i <= BF_UPPER_BND then + RESULT_BITFIELD(i) <= '1'; + end if; + end loop; + when others => -- BFTST. + null; -- no calculation required for BFTST. + end case; + end process P_BITFIELD_OP; + + P_BITOP: process(BITPOS, OP, OP2) + -- Bit manipulation operations. + begin + RESULT_BITOP <= OP2; -- The default is the unmanipulated data. + -- + case OP is + when BCHG => + RESULT_BITOP(BITPOS) <= not OP2(BITPOS); + when BCLR => + RESULT_BITOP(BITPOS) <= '0'; + when BSET => + RESULT_BITOP(BITPOS) <= '1'; + when others => + RESULT_BITOP <= OP2; -- Dummy, no result required for BTST. + end case; + end process P_BITOP; + + DIVISION: process + variable BITCNT : integer range 0 to 64; + variable DIVIDEND : unsigned(63 downto 0); + variable DIVISOR : unsigned(31 downto 0); + variable QUOTIENT_REST : unsigned(31 downto 0); + variable QUOTIENT_VAR : unsigned(31 downto 0); + variable REMAINDER_REST : unsigned(31 downto 0); + variable REMAINDER_VAR : unsigned(31 downto 0); + -- Be aware, that the destination and source operands + -- may be reloaded during the division operation. For + -- this, we use the restore values in case of an overflow. + begin + wait until CLK = '1' and CLK' event; + DIV_RDY <= '0'; + case DIV_STATE is + when IDLE => + if ALU_INIT = '1' and (OP_IN = DIVS or OP_IN = DIVU) then + DIV_STATE <= INIT; + end if; + when INIT => + if OP = DIVS and OP_SIZE = LONG and BIW_1(10) = '1' and OP3(31) = '1' then -- 64 bit signed negative dividend. + DIVIDEND := unsigned(not (OP3 & OP2) + '1'); + elsif (OP = DIVS or OP = DIVU) and OP_SIZE = LONG and BIW_1(10) = '1' then -- 64 bit positive or unsigned dividend. + DIVIDEND := unsigned(OP3 & OP2); + elsif OP = DIVS and OP2(31) = '1' then -- 32 bit signed negative dividend. + DIVIDEND := x"00000000" & unsigned(not(OP2) + '1'); + else -- 32 bit positive or unsigned dividend. + DIVIDEND := x"00000000" & unsigned(OP2); + end if; + + if OP = DIVS and OP_SIZE = LONG and OP1(31) = '1' then -- 32 bit signed negative divisor. + DIVISOR := unsigned(not OP1 + '1'); + elsif OP_SIZE = LONG then -- 32 bit positive or unsigned divisor. + DIVISOR := unsigned(OP1); + elsif OP = DIVS and OP_SIZE = WORD and OP1(15) = '1' then -- 16 bit signed negative divisor. + DIVISOR := x"0000" & unsigned(not OP1(15 downto 0) + '1'); + else -- 16 bit positive or unsigned divisor. + DIVISOR := x"0000" & unsigned(OP1(15 downto 0)); + end if; + + VFLAG_DIV <= '0'; + QUOTIENT <= (others => '0'); + QUOTIENT_VAR := (others => '0'); + QUOTIENT_REST := unsigned(OP2); + + REMAINDER <= (others => '0'); + REMAINDER_VAR := (others => '0'); + + case OP_SIZE is + when LONG => REMAINDER_REST := unsigned(OP3); + when others => REMAINDER_REST := unsigned(x"0000" & OP2(31 downto 16)); + end case; + + if OP_SIZE = LONG and BIW_1(10) = '1' then + BITCNT := 64; + else + BITCNT := 32; + end if; + + if DIVISOR = x"00000000" then -- Division by zero. + QUOTIENT <= (others => '1'); + REMAINDER <= (others => '1'); + DIV_STATE <= IDLE; + DIV_RDY <= '1'; + elsif x"00000000" & DIVISOR > DIVIDEND then -- Divisor > dividend. + REMAINDER <= DIVIDEND(31 downto 0); + DIV_STATE <= IDLE; + DIV_RDY <= '1'; + elsif x"00000000" & DIVISOR = DIVIDEND then -- Result is 1. + QUOTIENT <= x"00000001"; + DIV_STATE <= IDLE; + DIV_RDY <= '1'; + else + DIV_STATE <= CALC; + end if; + when CALC => + BITCNT := BITCNT - 1; + -- + if REMAINDER_VAR & DIVIDEND(BITCNT) < DIVISOR then + REMAINDER_VAR := REMAINDER_VAR(30 downto 0) & DIVIDEND(BITCNT); + elsif OP_SIZE = LONG and BITCNT > 31 then -- Division overflow in 64 bit mode. + VFLAG_DIV <= '1'; + DIV_STATE <= IDLE; + DIV_RDY <= '1'; + QUOTIENT <= QUOTIENT_REST; + REMAINDER <= REMAINDER_REST; + elsif OP_SIZE = WORD and BITCNT > 15 then -- Division overflow in 64 bit mode. + VFLAG_DIV <= '1'; + DIV_STATE <= IDLE; + DIV_RDY <= '1'; + QUOTIENT <= QUOTIENT_REST; + REMAINDER <= REMAINDER_REST; + else + REMAINDER_VAR := (REMAINDER_VAR(30 downto 0) & DIVIDEND(BITCNT)) - DIVISOR; + QUOTIENT_VAR(BITCNT) := '1'; + end if; + -- + if BITCNT = 0 then + -- Adjust signs: + if OP = DIVS and OP_SIZE = LONG and BIW_1(10) = '1' and (OP3(31) xor OP1(31)) = '1' then + QUOTIENT <= not QUOTIENT_VAR + 1; -- Negative, change sign. + elsif OP = DIVS and OP_SIZE = LONG and BIW_1(10) = '0' and (OP2(31) xor OP1(31)) = '1' then + QUOTIENT <= not QUOTIENT_VAR + 1; -- Negative, change sign. + elsif OP = DIVS and OP_SIZE = WORD and (OP2(31) xor OP1(15)) = '1' then + QUOTIENT <= not QUOTIENT_VAR + 1; -- Negative, change sign. + else + QUOTIENT <= QUOTIENT_VAR; + end if; + -- + REMAINDER <= REMAINDER_VAR; + DIV_RDY <= '1'; + DIV_STATE <= IDLE; + end if; + end case; + end process DIVISION; + + P_INTOP: process(OP, OP1, OP1_SIGNEXT, OP2, OP2_SIGNEXT, ADR_MODE, STATUS_REG, RESULT_INTOP) + -- The integer arithmetics ADD, SUB, NEG and CMP in their different variations are modelled here. + variable X_IN_I : Std_Logic_Vector(0 downto 0); + variable RESULT : unsigned(31 downto 0); + begin + X_IN_I(0) := STATUS_REG(4); -- Extended Flag. + case OP is + when ADDA => -- No sign extension for the destination. + RESULT := unsigned(OP2) + unsigned(OP1_SIGNEXT); + when ADDQ => + case ADR_MODE is + when "001" => RESULT := unsigned(OP2) + unsigned(OP1); -- No sign extension for address destination. + when others => RESULT := unsigned(OP2_SIGNEXT) + unsigned(OP1); + end case; + when SUBQ => + case ADR_MODE is + when "001" => RESULT := unsigned(OP2) - unsigned(OP1); -- No sign extension for address destination. + when others => RESULT := unsigned(OP2_SIGNEXT) - unsigned(OP1); + end case; + when ADD | ADDI => + RESULT := unsigned(OP2_SIGNEXT) + unsigned(OP1_SIGNEXT); + when ADDX => + RESULT := unsigned(OP2_SIGNEXT) + unsigned(OP1_SIGNEXT) + unsigned(X_IN_I); + when CMPA | DBcc | SUBA => -- No sign extension for the destination. + RESULT := unsigned(OP2) - unsigned(OP1_SIGNEXT); + when CAS | CAS2 | CMP | CMPI | CMPM | SUB | SUBI => + RESULT := unsigned(OP2_SIGNEXT) - unsigned(OP1_SIGNEXT); + when SUBX => + RESULT := unsigned(OP2_SIGNEXT) - unsigned(OP1_SIGNEXT) - unsigned(X_IN_I); + when NEG => + RESULT := unsigned(OP1_SIGNEXT) - unsigned(OP2_SIGNEXT); + when NEGX => + RESULT := unsigned(OP1_SIGNEXT) - unsigned(OP2_SIGNEXT) - unsigned(X_IN_I); + when CLR => + RESULT := (others => '0'); + when others => + RESULT := (others => '0'); -- Don't care. + end case; + RESULT_INTOP <= Std_Logic_Vector(RESULT); + end process P_INTOP; + + P_LOGOP: process(OP, OP1, OP2) + -- This process provides the logic operations: + -- AND, OR, XOR and NOT. + -- The logic operations require no signed / unsigned + -- modelling. + begin + case OP is + when AND_B | ANDI | ANDI_TO_CCR | ANDI_TO_SR => + RESULT_LOGOP <= OP1 and OP2; + when OR_B | ORI | ORI_TO_CCR | ORI_TO_SR => + RESULT_LOGOP <= OP1 or OP2; + when EOR | EORI | EORI_TO_CCR | EORI_TO_SR => + RESULT_LOGOP <= OP1 xor OP2; + when others => -- NOT_B. + RESULT_LOGOP <= not OP2; + end case; + end process P_LOGOP; + + RESULT_MUL <= Std_Logic_Vector(signed(OP1_SIGNEXT) * signed(OP2_SIGNEXT)) when OP = MULS else + Std_Logic_Vector(unsigned(OP1) * unsigned(OP2)) when OP_SIZE = LONG else + Std_Logic_Vector(unsigned(x"0000" & OP1(15 downto 0)) * unsigned(x"0000" & OP2(15 downto 0))); + + P_OTHERS: process(ALU_COND_I, BIW_0, OP, OP1, OP2, OP3, OP1_SIGNEXT, OP2_SIGNEXT, OP_SIZE, HILOn) + -- This process provides the calculation for special operations. + variable RESULT : unsigned(31 downto 0); + begin + RESULT := (others => '0'); + case OP is + when CAS => + RESULT := unsigned(OP2); -- Destination operand. + when CAS2 => -- Destination operands. + case HILOn is + when '1' => RESULT := unsigned(OP3); + when others => RESULT := unsigned(OP2); + end case; + when EXT => + case BIW_0(8 downto 6) is + when "011" => + for i in 31 downto 16 loop + RESULT(i) := OP2(15); + end loop; + RESULT(15 downto 0) := unsigned(OP2(15 downto 0)); + when others => -- Word. + for i in 15 downto 8 loop + RESULT(i) := OP2(7); + end loop; + RESULT(31 downto 16) := unsigned(OP2(31 downto 16)); + RESULT(7 downto 0) := unsigned(OP2(7 downto 0)); + end case; + when EXTB => + for i in 31 downto 8 loop + RESULT(i) := OP2(7); + end loop; + RESULT(7 downto 0) := unsigned(OP2(7 downto 0)); + when JSR => + RESULT := unsigned(OP1) + "10"; -- Add offset of two to the Pointer of the last extension word. + when MOVEQ => + for i in 31 downto 8 loop + RESULT(i) := OP1(7); + end loop; + RESULT(7 downto 0) := unsigned(OP1(7 downto 0)); + when Scc => + if ALU_COND_I = true then + RESULT := (others => '1'); + else + RESULT := (others => '0'); + end if; + when SWAP => + RESULT := unsigned(OP2(15 downto 0)) & unsigned(OP2(31 downto 16)); + when TAS => + RESULT := x"000000" & '1' & unsigned(OP2(6 downto 0)); -- Set the MSB. + when PACK => + RESULT := x"0000" & (unsigned(OP1(15 downto 0)) + unsigned(OP2(15 downto 0))); + when UNPK => + RESULT := x"0000" & (unsigned(OP1(15 downto 0)) + unsigned(x"0" & OP2(7 downto 4) & x"0" & OP2(3 downto 0))); + when LINK | TST => + RESULT := unsigned(OP2); + when MOVEA | MOVEM | MOVES => + RESULT := unsigned(OP1_SIGNEXT); + when others => -- MOVE_FROM_CCR, MOVE_TO_CCR, MOVE_FROM_SR, MOVE_TO_SR, MOVE, MOVEC, MOVEP, STOP. + RESULT := unsigned(OP1); + end case; + RESULT_OTHERS <= Std_Logic_Vector(RESULT); + end process P_OTHERS; + + SHFT_LOAD <= '1' when ALU_INIT = '1' and (OP_IN = ASL or OP_IN = ASR) else + '1' when ALU_INIT = '1' and (OP_IN = LSL or OP_IN = LSR) else + '1' when ALU_INIT = '1' and (OP_IN = ROTL or OP_IN = ROTR) else + '1' when ALU_INIT = '1' and (OP_IN = ROXL or OP_IN = ROXR) else '0'; + + SHIFT_WIDTH_IN <= "000001" when BIW_0_IN(7 downto 6) = "11" else -- Memory shifts. + "001000" when BIW_0_IN(5) = '0' and BIW_0_IN(11 downto 9) = "000" else -- Direct. + "000" & BIW_0_IN(11 downto 9) when BIW_0_IN(5) = '0' else -- Direct. + OP1_IN(5 downto 0); + + P_SHFT_CTRL: process + -- The variable shift or rotate length requires a control + -- to achieve the correct OPERAND manipulation. + variable BIT_CNT : std_logic_vector(5 downto 0); + begin + wait until CLK = '1' and CLK' event; + + SHFT_RDY <= '0'; + + if SHIFT_STATE = IDLE then + if SHFT_LOAD = '1' and SHIFT_WIDTH_IN = "000000" then + SHFT_RDY <= '1'; + elsif SHFT_LOAD = '1' then + SHIFT_STATE <= RUN; + BIT_CNT := SHIFT_WIDTH_IN; + SHFT_EN <= '1'; + else + SHIFT_STATE <= IDLE; + BIT_CNT := (others => '0'); + SHFT_EN <= '0'; + end if; + elsif SHIFT_STATE = RUN then + if BIT_CNT = "000001" then + SHIFT_STATE <= IDLE; + SHFT_EN <= '0'; + SHFT_RDY <= '1'; + else + SHIFT_STATE <= RUN; + BIT_CNT := BIT_CNT - '1'; + SHFT_EN <= '1'; + end if; + end if; + end process P_SHFT_CTRL; + + SHIFTER: process + begin + wait until CLK = '1' and CLK' event; + if SHFT_LOAD = '1' then -- Load data in the shifter unit. + RESULT_SHIFTOP <= OP2_IN; -- Load data for the shift or rotate operations. + elsif SHFT_EN = '1' then -- Shift and rotate operations: + case OP is + when ASL => + if OP_SIZE = LONG then + RESULT_SHIFTOP <= RESULT_SHIFTOP(30 downto 0) & '0'; + elsif OP_SIZE = WORD then + RESULT_SHIFTOP <= x"0000" & RESULT_SHIFTOP(14 downto 0) & '0'; + else -- OP_SIZE = BYTE. + RESULT_SHIFTOP <= x"000000" & RESULT_SHIFTOP(6 downto 0) & '0'; + end if; + when ASR => + if OP_SIZE = LONG then + RESULT_SHIFTOP <= RESULT_SHIFTOP(31) & RESULT_SHIFTOP(31 downto 1); + elsif OP_SIZE = WORD then + RESULT_SHIFTOP <= x"0000" & RESULT_SHIFTOP(15) & RESULT_SHIFTOP(15 downto 1); + else -- OP_SIZE = BYTE. + RESULT_SHIFTOP <= x"000000" & RESULT_SHIFTOP(7) & RESULT_SHIFTOP(7 downto 1); + end if; + when LSL => + if OP_SIZE = LONG then + RESULT_SHIFTOP <= RESULT_SHIFTOP(30 downto 0) & '0'; + elsif OP_SIZE = WORD then + RESULT_SHIFTOP <= x"0000" & RESULT_SHIFTOP(14 downto 0) & '0'; + else -- OP_SIZE = BYTE. + RESULT_SHIFTOP <= x"000000" & RESULT_SHIFTOP(6 downto 0) & '0'; + end if; + when LSR => + if OP_SIZE = LONG then + RESULT_SHIFTOP <= '0' & RESULT_SHIFTOP(31 downto 1); + elsif OP_SIZE = WORD then + RESULT_SHIFTOP <= x"0000" & '0' & RESULT_SHIFTOP(15 downto 1); + else -- OP_SIZE = BYTE. + RESULT_SHIFTOP <= x"000000" & '0' & RESULT_SHIFTOP(7 downto 1); + end if; + when ROTL => + if OP_SIZE = LONG then + RESULT_SHIFTOP <= RESULT_SHIFTOP(30 downto 0) & RESULT_SHIFTOP(31); + elsif OP_SIZE = WORD then + RESULT_SHIFTOP <= x"0000" & RESULT_SHIFTOP(14 downto 0) & RESULT_SHIFTOP(15); + else -- OP_SIZE = BYTE. + RESULT_SHIFTOP <= x"000000" & RESULT_SHIFTOP(6 downto 0) & RESULT_SHIFTOP(7); + end if; + -- X not affected; + when ROTR => + if OP_SIZE = LONG then + RESULT_SHIFTOP <= RESULT_SHIFTOP(0) & RESULT_SHIFTOP(31 downto 1); + elsif OP_SIZE = WORD then + RESULT_SHIFTOP <= x"0000" & RESULT_SHIFTOP(0) & RESULT_SHIFTOP(15 downto 1); + else -- OP_SIZE = BYTE. + RESULT_SHIFTOP <= x"000000" & RESULT_SHIFTOP(0) & RESULT_SHIFTOP(7 downto 1); + end if; + -- X not affected; + when ROXL => + if OP_SIZE = LONG then + RESULT_SHIFTOP <= RESULT_SHIFTOP(30 downto 0) & XFLAG_SHFT; + elsif OP_SIZE = WORD then + RESULT_SHIFTOP <= x"0000" & RESULT_SHIFTOP(14 downto 0) & XFLAG_SHFT; + else -- OP_SIZE = BYTE. + RESULT_SHIFTOP <= x"000000" & RESULT_SHIFTOP(6 downto 0) & XFLAG_SHFT; + end if; + when ROXR => + if OP_SIZE = LONG then + RESULT_SHIFTOP <= XFLAG_SHFT & RESULT_SHIFTOP(31 downto 1); + elsif OP_SIZE = WORD then + RESULT_SHIFTOP <= x"0000" & XFLAG_SHFT & RESULT_SHIFTOP(15 downto 1); + else -- OP_SIZE = BYTE. + RESULT_SHIFTOP <= x"000000" & XFLAG_SHFT & RESULT_SHIFTOP(7 downto 1); + end if; + when others => null; -- Unaffected, forbidden. + end case; + end if; + end process SHIFTER; + + P_OUT: process + begin + wait until CLK = '1' and CLK' event; + if ALU_REQ = '1' then + case OP is + when ABCD | NBCD | SBCD => + RESULT <= x"00000000000000" & RESULT_BCDOP; -- Byte only. + when BFCHG | BFCLR | BFEXTS | BFEXTU | BFFFO | BFINS | BFSET | BFTST => + case HILOn is + when '1' => RESULT <= x"00000000" & RESULT_BITFIELD(39 downto 8); + when others => RESULT <= x"00000000000000" & RESULT_BITFIELD(7 downto 0); + end case; + when BCHG | BCLR | BSET | BTST => + RESULT <= x"00000000" & RESULT_BITOP; + when ADD | ADDA | ADDI | ADDQ | ADDX | CLR | CMP | CMPA | CMPI => + RESULT <= x"00000000" & RESULT_INTOP; + when CMPM | DBcc | NEG | NEGX | SUB | SUBA | SUBI | SUBQ | SUBX => + RESULT <= x"00000000" & RESULT_INTOP; + when AND_B | ANDI | EOR | EORI | NOT_B | OR_B | ORI => + RESULT <= x"00000000" & RESULT_LOGOP; + when ANDI_TO_SR | EORI_TO_SR | ORI_TO_SR => -- Used for branch prediction. + RESULT <= x"00000000" & RESULT_LOGOP; + when ASL | ASR | LSL | LSR | ROTL | ROTR | ROXL | ROXR => + RESULT <= x"00000000" & RESULT_SHIFTOP; + when DIVS | DIVU => + case OP_SIZE is + when LONG => RESULT <= Std_Logic_Vector(REMAINDER) & Std_Logic_Vector(QUOTIENT); + when others => RESULT <= x"00000000" & Std_Logic_Vector(REMAINDER(15 downto 0)) & Std_Logic_Vector(QUOTIENT(15 downto 0)); + end case; + when MULS | MULU => + RESULT <= RESULT_MUL; + when PACK => + RESULT <= x"00000000000000" & RESULT_OTHERS(11 downto 8) & RESULT_OTHERS (3 downto 0); + when others => + RESULT <= OP2 & RESULT_OTHERS; -- OP2 is used for EXG. + end case; + end if; + end process P_OUT; + + -- Out of bounds condition: + CHK_CMP_COND <= true when OP = CHK and OP2_SIGNEXT(MSB) = '1' else -- Negative destination. + true when OP = CHK and signed(OP2_SIGNEXT) > signed(OP1_SIGNEXT) else + true when (OP = CHK2 or OP = CMP2) and CHK2CMP2_DR = '1' and OP_SIZE = LONG and OP2 < OP1 else + true when (OP = CHK2 or OP = CMP2) and CHK2CMP2_DR = '1' and OP_SIZE = LONG and OP2 > OP3 else + true when (OP = CHK2 or OP = CMP2) and CHK2CMP2_DR = '1' and OP_SIZE = WORD and OP2(15 downto 0) < OP1(15 downto 0) else + true when (OP = CHK2 or OP = CMP2) and CHK2CMP2_DR = '1' and OP_SIZE = WORD and OP2(15 downto 0) > OP3(15 downto 0) else + true when (OP = CHK2 or OP = CMP2) and CHK2CMP2_DR = '1' and OP2(7 downto 0) < OP1(7 downto 0) else + true when (OP = CHK2 or OP = CMP2) and CHK2CMP2_DR = '1' and OP2(7 downto 0) > OP3(7 downto 0) else + true when (OP = CHK2 or OP = CMP2) and CHK2CMP2_DR = '0' and signed(OP2_SIGNEXT) < signed(OP1_SIGNEXT) else + true when (OP = CHK2 or OP = CMP2) and CHK2CMP2_DR = '0' and signed(OP2_SIGNEXT) > signed(OP3_SIGNEXT) else false; + + -- All traps must be modeled as strobes. + TRAP_CHK <= '1' when ALU_ACK = '1' and (OP = CHK or OP = CHK2) and CHK_CMP_COND = true else '0'; + TRAP_DIVZERO <= '1' when ALU_INIT = '1' and (OP_IN = DIVS or OP_IN = DIVU) and OP1_IN = x"00000000" else '0'; + + COND_CODES: process(BF_DATA_IN, BF_LOWER_BND, BF_UPPER_BND, BIW_1, BITPOS, CB_BCD, CHK_CMP_COND, CLK, OP1, OP1_SIGNEXT, OP2, OP2_SIGNEXT, + OP3, OP3_SIGNEXT, MSB, OP, OP_SIZE, QUOTIENT, RESULT_BCDOP, RESULT_INTOP, RESULT_LOGOP, RESULT_MUL, RESULT_SHIFTOP, + RESULT_OTHERS, SHIFT_WIDTH, STATUS_REG, USE_DREG, VFLAG_DIV, XFLAG_SHFT) + -- In this process all the condition codes X (eXtended), N (Negative) + -- Z (Zero), V (oVerflow) and C (Carry / borrow) are calculated for + -- all integer operations. Except for the MULS, MULU, DIVS, DIVU the + -- new conditions are valid one clock cycle after the operation starts. + -- For the multiplication and the division, the codes are valid after + -- BUSY is released. + variable TMP : std_logic; + variable Z, RM, SM, DM : std_logic; + variable CFLAG_SHFT : std_logic; + variable VFLAG_SHFT : std_logic; + variable NFLAG_DIV : std_logic; + variable NFLAG_MUL : std_logic; + variable VFLAG_MUL : std_logic; + variable RM_SM_DM : bit_vector(2 downto 0); + begin + -- Shifter C, X and V flags: + if CLK = '1' and CLK' event then + if SHFT_LOAD = '1' or SHIFT_WIDTH = "000000" then + XFLAG_SHFT <= STATUS_REG(4); + elsif SHFT_EN = '1' then + case OP is + when ROTL | ROTR => + XFLAG_SHFT <= STATUS_REG(4); -- Unaffected. + when ASL | LSL | ROXL => + case OP_SIZE is + when LONG => + XFLAG_SHFT <= RESULT_SHIFTOP(31); + when WORD => + XFLAG_SHFT <= RESULT_SHIFTOP(15); + when BYTE => + XFLAG_SHFT <= RESULT_SHIFTOP(7); + end case; + when others => -- ASR, LSR, ROXR. + XFLAG_SHFT <= RESULT_SHIFTOP(0); + end case; + end if; + -- + if (OP = ROXL or OP = ROXR) and SHIFT_WIDTH = "000000" then + CFLAG_SHFT := STATUS_REG(4); + elsif SHIFT_WIDTH = "000000" then + CFLAG_SHFT := '0'; + elsif SHFT_EN = '1' then + case OP is + when ASL | LSL | ROTL | ROXL => + case OP_SIZE is + when LONG => + CFLAG_SHFT := RESULT_SHIFTOP(31); + when WORD => + CFLAG_SHFT := RESULT_SHIFTOP(15); + when BYTE => + CFLAG_SHFT := RESULT_SHIFTOP(7); + end case; + when others => -- ASR, LSR, ROTR, ROXR + CFLAG_SHFT := RESULT_SHIFTOP(0); + end case; + end if; + -- + -- This logic provides a detection of any toggling of the most significant + -- bit of the shifter unit during the ASL shift process. For all other shift + -- operations, the V flag is always zero. + if SHFT_LOAD = '1' or SHIFT_WIDTH = "000000" then + VFLAG_SHFT := '0'; + elsif SHFT_EN = '1' then + case OP is + when ASL => -- ASR MSB is always unchanged. + if OP_SIZE = LONG then + VFLAG_SHFT := (RESULT_SHIFTOP(31) xor RESULT_SHIFTOP(30)) or VFLAG_SHFT; + elsif OP_SIZE = WORD then + VFLAG_SHFT := (RESULT_SHIFTOP(15) xor RESULT_SHIFTOP(14)) or VFLAG_SHFT; + else -- OP_SIZE = BYTE. + VFLAG_SHFT := (RESULT_SHIFTOP(7) xor RESULT_SHIFTOP(6)) or VFLAG_SHFT; + end if; + when others => + VFLAG_SHFT := '0'; + end case; + end if; + end if; + + -- DIVISION: + if OP_SIZE = LONG and QUOTIENT(31) = '1' then + NFLAG_DIV := '1'; + elsif OP_SIZE = WORD and QUOTIENT(15) = '1' then + NFLAG_DIV := '1'; + else + NFLAG_DIV := '0'; + end if; + + -- Integer operations: + case OP is + when ADD | ADDI | ADDQ | ADDX | CMP | CMPA | CMPI | CMPM | NEG | NEGX | SUB | SUBI | SUBQ | SUBX => + RM := RESULT_INTOP(MSB); + SM := OP1_SIGNEXT(MSB); + DM := OP2_SIGNEXT(MSB); + when others => + RM := '-'; SM := '-'; DM := '-'; + end case; + + RM_SM_DM := To_Bit(RM) & To_Bit(SM) & To_Bit(DM); + + -- Multiplication: + if OP_SIZE = LONG and BIW_1(10) = '1' and RESULT_MUL(63) = '1' then -- 64 bit result. + NFLAG_MUL := '1'; + elsif RESULT_MUL(31) = '1' then -- 32 bit result. + NFLAG_MUL := '1'; + else + NFLAG_MUL := '0'; + end if; + + if OP_SIZE = LONG and BIW_1(10) = '0' and OP = MULS and RESULT_MUL(31) = '0' and RESULT_MUL(63 downto 32) /= x"00000000" then + VFLAG_MUL := '1'; + elsif OP_SIZE = LONG and BIW_1(10) = '0' and OP = MULS and RESULT_MUL(31) = '1' and RESULT_MUL(63 downto 32) /= x"FFFFFFFF" then + VFLAG_MUL := '1'; + elsif OP_SIZE = LONG and BIW_1(10) = '0' and OP = MULU and RESULT_MUL(63 downto 32) /= x"00000000" then + VFLAG_MUL := '1'; + else + VFLAG_MUL := '0'; + end if; + + -- The Z Flag: + TMP := '0'; + case OP is + when ADD | ADDI | ADDQ | ADDX | CAS | CAS2 | CMP | CMPA | CMPI | CMPM | NEG | NEGX | SUB | SUBI | SUBQ | SUBX => + for i in RESULT_INTOP'range loop + if i <= MSB then + TMP:= TMP or RESULT_INTOP(i); -- Detect '1'. + end if; + end loop; + Z := not TMP; -- Invert for Z fLAG . + when AND_B | ANDI | EOR | EORI | OR_B | ORI | NOT_B => + for i in RESULT_LOGOP'range loop + if i <= MSB then + TMP:= TMP or RESULT_LOGOP(i); -- Detect '1'. + end if; + end loop; + Z := not TMP; -- Invert for Z fLAG . + when ASL | ASR | LSL | LSR | ROTL | ROTR | ROXL | ROXR => + for i in RESULT_SHIFTOP'range loop + if i <= MSB then + TMP:= TMP or RESULT_SHIFTOP(i); -- Detect '1'. + end if; + end loop; + Z := not TMP; -- Invert for Z fLAG . + when BFCHG | BFCLR | BFEXTS | BFEXTU | BFFFO | BFINS | BFSET | BFTST => + for i in BF_DATA_IN'range loop + if i >= BF_LOWER_BND and i <= BF_UPPER_BND then + TMP := TMP or BF_DATA_IN(i); -- Detect '1'. + end if; + end loop; + Z := not TMP; + when CHK2 | CMP2 => + if USE_DREG = '1' and OP_SIZE = LONG and OP2 = OP1 then + Z := '1'; + elsif USE_DREG = '1' and OP_SIZE = LONG and OP2 = OP3 then + Z:= '1'; + elsif USE_DREG = '1' and OP_SIZE = WORD and OP2(15 downto 0) = OP1(15 downto 0) then + Z:= '1'; + elsif USE_DREG = '1' and OP_SIZE = WORD and OP2(15 downto 0) = OP3(15 downto 0) then + Z:= '1'; + elsif USE_DREG = '1' and OP2(7 downto 0) = OP1(7 downto 0) then + Z:= '1'; + elsif USE_DREG = '1' and OP2(7 downto 0) = OP3(7 downto 0) then + Z:= '1'; + elsif USE_DREG = '0' and OP2_SIGNEXT = OP1_SIGNEXT then + Z := '1'; + elsif USE_DREG = '0' and OP2_SIGNEXT = OP3_SIGNEXT then + Z := '1'; + else + Z := '0'; + end if; + when BCHG | BCLR | BSET | BTST => + Z := not OP2(BITPOS); + when DIVS | DIVU => + if QUOTIENT = x"00000000" then + Z := '1'; + else + Z := '0'; + end if; + when EXT | EXTB | MOVE | SWAP | TST => + for i in RESULT_OTHERS'range loop + if i <= MSB then + TMP:= TMP or RESULT_OTHERS(i); -- Detect '1'. + end if; + end loop; + Z := not TMP; -- Invert for Z fLAG . + when MULS | MULU => + if OP_SIZE = LONG and BIW_1(10) = '1' and RESULT_MUL = x"0000000000000000" then -- 64 bit result. + Z := '1'; + elsif RESULT_MUL(31 downto 0) = x"00000000" then -- 32 bit result. + Z := '1'; + else + Z := '0'; + end if; + when TAS => + for i in OP2_SIGNEXT'range loop + if i <= MSB then + TMP := TMP or OP2_SIGNEXT(i); -- Detect '1'. + end if; + end loop; + Z := not TMP; -- Invert for Z fLAG . + when others => + Z := '0'; + end case; + + case OP is + when ABCD | NBCD | SBCD => + if RESULT_BCDOP = x"00" then -- N and V are undefined, don't care. + XNZVC <= CB_BCD & '-' & STATUS_REG(2) & '-' & CB_BCD; + else + XNZVC <= CB_BCD & '-' & '0' & '-' & CB_BCD; + end if; + when ADD | ADDI | ADDQ | ADDX => + if (SM = '1' and DM = '1') or (RM = '0' and SM = '1') or (RM = '0' and DM = '1') then + XNZVC(4) <= '1'; + XNZVC(0) <= '1'; + else + XNZVC(4) <= '0'; + XNZVC(0) <= '0'; + end if; + -- + if Z = '1' then + if OP = ADDX then + XNZVC(3 downto 2) <= '0' & STATUS_REG(2); + else + XNZVC(3 downto 2) <= "01"; + end if; + else + XNZVC(3 downto 2) <= RM & '0'; + end if; + -- + case RM_SM_DM is + when "011" => XNZVC(1) <= '1'; + when "100" => XNZVC(1) <= '1'; + when others => XNZVC(1) <= '0'; + end case; + when AND_B | ANDI | EOR | EORI | OR_B | ORI | NOT_B => + XNZVC <= STATUS_REG(4) & RESULT_LOGOP(MSB) & Z & "00"; + when ANDI_TO_CCR | EORI_TO_CCR | ORI_TO_CCR => + XNZVC <= RESULT_LOGOP(4 downto 0); + when ASL | ASR | LSL | LSR | ROTL | ROTR | ROXL | ROXR => + XNZVC <= XFLAG_SHFT & RESULT_SHIFTOP(MSB) & Z & VFLAG_SHFT & CFLAG_SHFT; + when BCHG | BCLR | BSET | BTST => + XNZVC <= STATUS_REG(4 downto 3) & Z & STATUS_REG(1 downto 0); + when BFCHG | BFCLR | BFEXTS | BFEXTU | BFFFO | BFINS | BFSET | BFTST => + XNZVC <= STATUS_REG(4) & BF_DATA_IN(BF_UPPER_BND) & Z & "00"; + when CLR => + XNZVC <= STATUS_REG(4) & "0100"; + when SUB | SUBI | SUBQ | SUBX => + if (SM = '1' and DM = '0') or (RM = '1' and SM = '1') or (RM = '1' and DM = '0') then + XNZVC(4) <= '1'; + XNZVC(0) <= '1'; + else + XNZVC(4) <= '0'; + XNZVC(0) <= '0'; + end if; + -- + if Z = '1' then + if OP = SUBX then + XNZVC(3 downto 2) <= '0' & STATUS_REG(2); + else + XNZVC(3 downto 2) <= "01"; + end if; + else + XNZVC(3 downto 2) <= RM & '0'; + end if; + -- + case RM_SM_DM is + when "001" => XNZVC(1) <= '1'; + when "110" => XNZVC(1) <= '1'; + when others => XNZVC(1) <= '0'; + end case; + when CAS | CAS2 | CMP | CMPA | CMPI | CMPM => + XNZVC(4) <= STATUS_REG(4); + -- + if Z = '1' then + XNZVC(3 downto 2) <= "01"; + else + XNZVC(3 downto 2) <= RM & '0'; + end if; + -- + case RM_SM_DM is + when "001" => XNZVC(1) <= '1'; + when "110" => XNZVC(1) <= '1'; + when others => XNZVC(1) <= '0'; + end case; + -- + if (SM = '1' and DM = '0') or (RM = '1' and SM = '1') or (RM = '1' and DM = '0') then + XNZVC(0) <= '1'; + else + XNZVC(0) <= '0'; + end if; + when CHK => + if OP2_SIGNEXT(MSB) = '1' then + XNZVC <= STATUS_REG(4) & '1' & "000"; + elsif CHK_CMP_COND = true then + XNZVC <= STATUS_REG(4) & '0' & "000"; + else + XNZVC <= STATUS_REG(4 downto 3) & "000"; + end if; + when CHK2 | CMP2 => + if CHK_CMP_COND = true then + XNZVC <= STATUS_REG(4) & '0' & '0' & '0' & '1'; + else + XNZVC <= STATUS_REG(4) & '0' & Z & '0' & '0'; + end if; + when DIVS | DIVU => + XNZVC <= STATUS_REG(4) & NFLAG_DIV & Z & VFLAG_DIV & '0'; + when EXT | EXTB | MOVE | TST => + XNZVC <= STATUS_REG(4) & RESULT_OTHERS(MSB) & Z & "00"; + when MOVEQ => + if OP1_SIGNEXT(7 downto 0) = x"00" then + XNZVC <= STATUS_REG(4) & "0100"; + else + XNZVC <= STATUS_REG(4) & OP1_SIGNEXT(7) & "000"; + end if; + when MULS | MULU => + XNZVC <= STATUS_REG(4) & NFLAG_MUL & Z & VFLAG_MUL & '0'; + when NEG | NEGX => + XNZVC(4) <= DM or RM; + -- + if Z = '1' then + if OP = NEGX then + XNZVC(3 downto 2) <= '0' & STATUS_REG(2); + else + XNZVC(3 downto 2) <= "01"; + end if; + else + XNZVC(3 downto 2) <= RM & '0'; + end if; + -- + XNZVC(1) <= DM and RM; + XNZVC(0) <= DM or RM; + when RTR => + XNZVC <= OP2(4 downto 0); + when SWAP => + XNZVC <= STATUS_REG(4) & RESULT_OTHERS(MSB) & Z & "00"; + when others => -- TAS, Byte only. + XNZVC <= STATUS_REG(4) & OP2_SIGNEXT(MSB) & Z & "00"; + end case; + end process COND_CODES; + + CAS_CONDITIONS: process(CLK) + begin + if CLK = '1' and CLK' event then + if LOAD_OP2 = '1' and XNZVC(2) = '1' then + CAS2_COND <= true; + elsif LOAD_OP2 = '1' then + CAS2_COND <= false; + end if; + end if; + end process CAS_CONDITIONS; + + ALU_COND <= ALU_COND_I; -- This signal may not be registerd to meet a correct timing. + -- Status register conditions: (STATUS_REG(4) = X, STATUS_REG(3) = N, STATUS_REG(2) = Z, STATUS_REG(1) = V, STATUS_REG(0) = C.) + ALU_COND_I <= false when OP = CAS2 and CAS2_COND = false else + true when (OP = CAS or OP = CAS2) and OP_SIZE = LONG and RESULT_INTOP = x"00000000" else + true when (OP = CAS or OP = CAS2) and OP_SIZE = WORD and RESULT_INTOP (15 downto 0) = x"0000" else + true when OP = CAS and RESULT_INTOP (7 downto 0) = x"00" else + false when OP = CAS or OP = CAS2 else + true when OP = TRAPV and STATUS_REG(1) = '1' else + false when OP = TRAPV else + true when BIW_0(11 downto 8) = x"0" else -- True. + true when BIW_0(11 downto 8) = x"2" and (STATUS_REG(2) nor STATUS_REG(0)) = '1' else -- High. + true when BIW_0(11 downto 8) = x"3" and (STATUS_REG(2) or STATUS_REG(0)) = '1' else -- Low or same. + true when BIW_0(11 downto 8) = x"4" and STATUS_REG(0) = '0' else -- Carry clear. + true when BIW_0(11 downto 8) = x"5" and STATUS_REG(0) = '1' else -- Carry set. + true when BIW_0(11 downto 8) = x"6" and STATUS_REG(2) = '0' else -- Not Equal. + true when BIW_0(11 downto 8) = x"7" and STATUS_REG(2) = '1' else -- Equal. + true when BIW_0(11 downto 8) = x"8" and STATUS_REG(1) = '0' else -- Overflow clear. + true when BIW_0(11 downto 8) = x"9" and STATUS_REG(1) = '1' else -- Overflow set. + true when BIW_0(11 downto 8) = x"A" and STATUS_REG(3) = '0' else -- Plus. + true when BIW_0(11 downto 8) = x"B" and STATUS_REG(3) = '1' else -- Minus. + true when BIW_0(11 downto 8) = x"C" and (STATUS_REG(3) xnor STATUS_REG(1)) = '1' else -- Greater or Equal. + true when BIW_0(11 downto 8) = x"D" and (STATUS_REG(3) xor STATUS_REG(1)) = '1' else -- Less than. + true when BIW_0(11 downto 8) = x"E" and STATUS_REG(3 downto 1) = "101" else -- Greater than. + true when BIW_0(11 downto 8) = x"E" and STATUS_REG(3 downto 1) = "000" else -- Greater than. + true when BIW_0(11 downto 8) = x"F" and STATUS_REG(2) = '1' else -- Less or equal. + true when BIW_0(11 downto 8) = x"F" and (STATUS_REG(3) xor STATUS_REG(1)) = '1' else false; -- Less or equal. + + P_STATUS_REG: process + -- This process is the status register with it's related logic. + -- The status register is written 16 bit wide for MOVE_TO_CCR (the ALU result is 16 bit wide). + -- The status register is written entirely for ANDI_TO_SR, EORI_TO_SR, ORI_TO_SR. + -- The status register lower byte is written for ANDI_TO_CCR, EORI_TO_CCR, ORI_TO_CCR. + variable SREG_MEM : std_logic_vector(15 downto 0) := x"0000"; + begin + wait until CLK = '1' and CLK' event; + -- + if CC_UPDT = '1' then + SREG_MEM(4 downto 0) := XNZVC; + end if; + -- + if SR_INIT = '1' then + SREG_MEM(15 downto 13) := "001"; -- Trace cleared, S = '1'. + SREG_MEM(10 downto 8) := IRQ_PEND; -- Update IRQ level. + end if; + -- + if SR_CLR_MBIT = '1' then + SREG_MEM(12) := '0'; + elsif SR_WR = '1' and OP_IN = RTE then -- Written by the exception handler, no ALU required. + SREG_MEM := OP1_IN(15 downto 0); + elsif SR_WR = '1' and (OP_WB = MOVE_TO_CCR or OP_WB = MOVE_TO_SR or OP_WB = STOP) then + SREG_MEM := RESULT_OTHERS(15 downto 0); + elsif SR_WR = '1' and (OP_WB = ANDI_TO_CCR or OP_WB = EORI_TO_CCR or OP_WB = ORI_TO_CCR) then + SREG_MEM(7 downto 5) := RESULT_LOGOP(7 downto 5); -- Bits 4 downto 0 are written via CC_UPDT. + elsif SR_WR = '1' then -- ANDI_TO_SR, EORI_TO_SR, ORI_TO_SR. + SREG_MEM := RESULT_LOGOP(15 downto 0); + end if; + -- + STATUS_REG <= SREG_MEM; -- Fully populated status register. + --STATUS_REG <= SREG_MEM(15 downto 12) & '0' & SREG_MEM(10 downto 8) & "000" & SREG_MEM(4 downto 0); -- Partially populated. + end process P_STATUS_REG; + -- + STATUS_REG_OUT <= STATUS_REG; +end BEHAVIOUR; diff --git a/common/CPU/68K30L/wf68k30L_bus_interface.vhd b/common/CPU/68K30L/wf68k30L_bus_interface.vhd new file mode 100644 index 00000000..474b10ae --- /dev/null +++ b/common/CPU/68K30L/wf68k30L_bus_interface.vhd @@ -0,0 +1,879 @@ +------------------------------------------------------------------------ +---- ---- +---- WF68K30L IP Core: this is the bus interface. ---- +---- ---- +---- Description: ---- +---- This module is a 68030 compatible bus controller featuring ---- +---- all of the 68030 bus interface functionality. ---- +---- ---- +---- Bus cycle operation: ---- +---- A bus cycle is invoked by either asserting RD_REQ, WR_REQ or ---- +---- OPCODE_REQ. Data is provided immediately or after the ---- +---- respective bus cycle has finished. The RD_REQ, WR_REQ or ---- +---- OPCODE_REQ signals should stay asserted until the respective ---- +---- _RDY signal from the bus controller indicates, that the data ---- +---- is available. These _RDY signals are strobes. If more than one ---- +---- read or write request are asserted the same time, RD_REQ is ---- +---- prioritized over WR_REQ and OPCODE_REQ has lowest priority. ---- +---- For more information of the signal functionality of the bus ---- +---- controller entity see also the comments below. ---- +---- ---- +---- Remarks: ---- +---- ---- +---- Bus arbitration topics: ---- +---- Additionally to the single wire and the three wire bus arbi- ---- +---- tration as described in the 68030 hardware manual, the bus ---- +---- controller also features the two wire arbitration as des- ---- +---- cribed in the documentation of the 68020 processor. ---- +---- ---- +---- Author(s): ---- +---- - Wolfgang Foerster, wf@experiment-s.de; wf@inventronik.de ---- +---- ---- +------------------------------------------------------------------------ +---- ---- +---- Copyright © 2014-2019 Wolfgang Foerster Inventronik GmbH. ---- +---- ---- +---- This documentation describes Open Hardware and is licensed ---- +---- under the CERN OHL v. 1.2. You may redistribute and modify ---- +---- this documentation under the terms of the CERN OHL v.1.2. ---- +---- (http://ohwr.org/cernohl). This documentation is distributed ---- +---- WITHOUT ANY EXPRESS OR IMPLIED WARRANTY, INCLUDING OF ---- +---- MERCHANTABILITY, SATISFACTORY QUALITY AND FITNESS FOR A ---- +---- PARTICULAR PURPOSE. Please see the CERN OHL v.1.2 for ---- +---- applicable conditions ---- +---- ---- +------------------------------------------------------------------------ +-- +-- Revision History +-- +-- Revision 2K14B 20141201 WF +-- Initial Release. +-- Revision 2K18A 20180620 WF +-- Suppress bus faults during RESET instruction. +-- Optimized ASn and DSn timing for synchronous RAM. +-- DATA_PORT_EN timing optimization. +-- BUS_EN is now active except during arbitration. +-- Rearanged the DATA_RDY vs. BUS_FLT logic. +-- Opted out START_READ and CHK_RD. +-- Fixed the faulty bus arbitration logic. +-- Rearranged address error handling. +-- Revision 2K20A 20200620 WF +-- ASn and DSn are not asserted in S0 any more. +-- Some modifications to optimize the RETRY logic. +-- Fixed a bug in the DSACK_MEM logic (now switches explicitely to "00"). +-- + +library work; +use work.WF68K30L_PKG.all; + +library ieee; +use ieee.std_logic_1164.all; +use ieee.std_logic_unsigned.all; +use ieee.numeric_std.all; + +entity WF68K30L_BUS_INTERFACE is + port ( + -- System control: + CLK : in std_logic; -- System clock. + + -- Adress bus: + ADR_IN_P : in std_logic_vector(31 downto 0); -- Logical address line inputs. + ADR_OUT_P : out std_logic_vector(31 downto 0); -- Address line outputs. + + -- Function code relevant stuff: + FC_IN : in std_logic_vector(2 downto 0); -- Function codes. + FC_OUT : out std_logic_vector(2 downto 0); -- Physical function codes (top level entity). + + -- Data bus: + DATA_PORT_IN : in std_logic_vector(31 downto 0); -- Data bus input lines (top level entity). + DATA_PORT_OUT : out std_logic_vector(31 downto 0); -- Data bus output lines (top level entity). + DATA_FROM_CORE : in std_logic_vector(31 downto 0); -- Internal bus input lines. + DATA_TO_CORE : out std_logic_vector(31 downto 0); -- Internal data bus output lines. + OPCODE_TO_CORE : out std_logic_vector(15 downto 0); -- Internal instruction bus output lines. + + -- Tri state controls: + DATA_PORT_EN : out std_logic; -- For the data bus. + BUS_EN : out std_logic; -- For all other bus control signals. + + -- Transfer and operation size: + SIZE : out std_logic_vector(1 downto 0); -- This is the size information (top level entity). + OP_SIZE : in OP_SIZETYPE; -- Used for bus access control. + + -- Control signals: + RD_REQ : in bit; -- Read data. + WR_REQ : in bit; -- Write data. + DATA_RDY : out bit; -- Indicates 'new data available' (this is a strobe). + DATA_VALID : out std_logic; -- The data buffer contains valid data when '1'. + OPCODE_REQ : in bit; -- Read opcode. + OPCODE_RDY : out bit; -- Indicates 'new opcode available' (this is a strobe). + OPCODE_VALID : out std_logic; -- The opcode buffer contains valid data when '1'. + RMC : in bit; -- Indicates a read modify write operation. + BUSY_EXH : in bit; + INBUFFER : out std_logic_vector(31 downto 0); -- Used by the exception handler for stack frame type B. + OUTBUFFER : out std_logic_vector(31 downto 0); -- Used by the exception handler for stack frame types A and B. + SSW_80 : out std_logic_vector(8 downto 0); + + -- Asynchronous bus control signals: + DSACKn : in std_logic_vector(1 downto 0); -- Asynchronous bus cycle termination (top level entity). + ASn : out std_logic; -- Adress select (top level entity). + DSn : out std_logic; -- Data select (top level entity). + RWn : out std_logic; -- Hi is read, low = write (top level entity). + RMCn : out std_logic; -- Read modify write indicator (top level entity). + ECSn : out std_logic; -- External cycle start (top level entity). + OCSn : out std_logic; -- Operand cycle start (top level entity). + DBENn : out std_logic; -- Data buffer enable (top level entity). + + -- Synchronous bus control: + STERMn : in std_logic; -- Synchronous bus cycle termination (top level entity). + + -- Bus arbitration: + BRn : in std_logic; -- Bus request (top level entity). + BGACKn : in std_logic; -- Bus grant acknowledge (top level entity). + BGn : out std_logic; -- Bus grant (top level entity). + + -- Exception signals: + RESET_IN : in std_logic; -- System's reset input (top level entity). + RESET_STRB : in bit; -- From Core: force external reset. + RESET_OUT : out std_logic; -- System's reset output open drain enable. + RESET_CPU : out bit; -- Internal reset used for CPU initialization. + AVECn : in std_logic; -- Auto interrupt vector input (top level entity). + HALTn : in std_logic; -- Halt (top level entity). + BERRn : in std_logic; -- Bus error (top level entity). + AERR : buffer bit; -- Core internal address error. + + BUS_BSY : out bit -- Bus is busy when '1'. + ); +end entity WF68K30L_BUS_INTERFACE; + +architecture BEHAVIOR of WF68K30L_BUS_INTERFACE is +type BUS_CTRL_STATES is (IDLE, START_CYCLE, DATA_C1C4); +type ARB_STATES is(IDLE, GRANT, WAIT_RELEASE_3WIRE); +type BUS_WIDTH_TYPE is(LONG_32, WORD, BYTE); +type TIME_SLICES is (IDLE, S0, S1, S2, S3, S4, S5); +signal ADR_10 : std_logic_vector(1 downto 0); +signal ADR_OFFSET : std_logic_vector(5 downto 0); +signal ADR_OUT_I : std_logic_vector(31 downto 0); +signal AERR_I : bit; +signal ARB_STATE : ARB_STATES := IDLE; +signal AVEC_In : std_logic; +signal BGACK_In : std_logic; +signal BR_In : std_logic; +signal BUS_CTRL_STATE : BUS_CTRL_STATES; +signal BUS_CYC_RDY : bit; +signal BUS_FLT : std_logic; +signal BUS_WIDTH : BUS_WIDTH_TYPE; +signal DATA_INMUX : std_logic_vector(31 downto 0); +signal DATA_RDY_I : bit; +signal DBUFFER : std_logic_vector(31 downto 0); +signal DSACK_In : std_logic_vector(1 downto 0); +signal DSACK_MEM : std_logic_vector(1 downto 0); +signal OCS_INH : bit; +signal HALT_In : std_logic; +signal HALTED : bit; +signal NEXT_ARB_STATE : ARB_STATES; +signal NEXT_BUS_CTRL_STATE : BUS_CTRL_STATES; +signal OBUFFER : std_logic_vector(15 downto 0); +signal OPCODE_ACCESS : bit; +signal OPCODE_RDY_I : bit; +signal READ_ACCESS : bit; +signal RESET_CPU_I : bit; +signal RESET_OUT_I : std_logic; +signal RETRY : bit; +signal SIZE_D : std_logic_vector(1 downto 0); +signal SIZE_I : std_logic_vector(1 downto 0); +signal SIZE_N : std_logic_vector(2 downto 0) := "000"; +signal SLICE_CNT_N : std_logic_vector(2 downto 0); +signal SLICE_CNT_P : std_logic_vector(2 downto 0); +signal STERM_Dn : std_logic; +signal T_SLICE : TIME_SLICES; +signal WAITSTATES : bit; +signal WP_BUFFER : std_logic_vector(31 downto 0); +signal WRITE_ACCESS : bit; +begin + P_SYNC: process(CLK) + -- These flip flops synchronize external signals on the negative clock edge. This + -- meets the requirement of sampling these signals in the end of S2 for asynchronous + -- bus access. Be aware, that we have to buffer the RETRY signal to prevent the bus + -- controller of spurious or timing critical BERRn and/or HALTn signals. The logic + -- for BUS_FLT and RETRY is coded in a way that we have a bus error or a retry + -- condition but not both at the same time. + -- Note: there is no need to synchronize the already synchronous bus control signals + variable BERR_VARn : std_logic; + variable HALT_VARn : std_logic; + begin + if CLK = '0' and CLK' event then + DSACK_In <= DSACKn; + BR_In <= BRn; + BGACK_In <= BGACKn; + AVEC_In <= AVECn; + HALT_VARn := HALTn; + BERR_VARn := BERRn; + end if; + -- + if CLK = '1' and CLK' event then + if BUS_CTRL_STATE = START_CYCLE then + AERR <= AERR_I; -- AERR_I is valid in this state. + else + AERR <= '0'; + end if; + -- + HALT_In <= HALTn or HALT_VARn; + -- + if BUS_CTRL_STATE = DATA_C1C4 then + if (BERRn nand BERR_VARn) = '1' and (HALTn or HALT_VARn) = '0' and SIZE_N /= "000" then + RETRY <= '1'; + elsif T_SLICE = IDLE and (BERRn = '1' and HALTn = '1' and BERR_VARn = '1' and HALT_VARn = '1') then + RETRY <= '0'; + elsif RETRY = '0' then + BUS_FLT <= (BERRn nor BERR_VARn) and HALT_VARn and HALTn; + end if; + else + BUS_FLT <= '0'; + RETRY <= '0'; + end if; + -- + STERM_Dn <= STERMn; -- Delay to update the SIZE_N and SIZE_M before BUS_CYC_RDY is asserted. + end if; + end process P_SYNC; + + ACCESSTYPE: process + -- This logic stores the execution unit control + -- signals during the current bus access. This is + -- important for the bus control signals to be + -- stable during the complete bus access. + begin + wait until CLK = '1' and CLK' event; + if BUS_CTRL_STATE = START_CYCLE then + if READ_ACCESS = '1' or WRITE_ACCESS = '1' or OPCODE_ACCESS = '1' then + null; -- Do not start either new cycle. + elsif RD_REQ = '1' then + READ_ACCESS <= '1'; + elsif WR_REQ = '1' then + WRITE_ACCESS <= '1'; + elsif OPCODE_REQ = '1' then + OPCODE_ACCESS <= '1'; + end if; + elsif AERR = '1' then -- Reject due to address error. + READ_ACCESS <= '0'; + WRITE_ACCESS <= '0'; + OPCODE_ACCESS <= '0'; + elsif BUS_CTRL_STATE = DATA_C1C4 and NEXT_BUS_CTRL_STATE = IDLE and SIZE_N = "000" then + READ_ACCESS <= '0'; + WRITE_ACCESS <= '0'; + OPCODE_ACCESS <= '0'; + end if; + end process ACCESSTYPE; + + P_DF: process + -- This is the logic which provides the fault flags for data cycles and + -- input and output buffer information. + variable SIZEVAR : std_logic_vector(1 downto 0) := "00"; + begin + wait until CLK = '1' and CLK' event; + if BUSY_EXH = '0' then -- Do not alter during exception processing. + case OP_SIZE is + when LONG => SIZEVAR := "10"; + when WORD => SIZEVAR := "01"; + when BYTE => SIZEVAR := "00"; + end case; + -- + if BUS_CTRL_STATE = START_CYCLE and NEXT_BUS_CTRL_STATE = DATA_C1C4 then + SSW_80 <= To_StdLogicVector('0' & RMC & not WR_REQ) & SIZEVAR & '0' & FC_IN; + elsif BUS_CTRL_STATE = DATA_C1C4 and (READ_ACCESS = '1' or WRITE_ACCESS = '1') and BUS_FLT = '1' then + SSW_80(8) <= '1'; + end if; + + OUTBUFFER <= WP_BUFFER; -- Used for exception stack frame type A and B. + INBUFFER <= DATA_INMUX; -- Used for exception stack frame type B. + end if; + end process P_DF; + + WRITEBACK_INFO: process + -- This registers stor writeback relevant information. + begin + wait until CLK = '1' and CLK' event; + if BUS_CTRL_STATE = IDLE and NEXT_BUS_CTRL_STATE = START_CYCLE then -- Freeze during a bus cycle. + WP_BUFFER <= DATA_FROM_CORE; + end if; + end process WRITEBACK_INFO; + + P_BUSWIDTH: process + -- These flip flops store the bus width information + -- during the current bus access. + begin + wait until CLK = '1' and CLK' event; + if BUS_CTRL_STATE = IDLE then + DSACK_MEM <= "11"; + elsif DSACK_In /= "11" then + DSACK_MEM <= DSACK_In; + end if; + end process P_BUSWIDTH; + + BUS_WIDTH <= WORD when DSACKn = "01" or DSACK_MEM = "01" else + BYTE when DSACKn = "10" or DSACK_MEM = "10" else + LONG_32; -- Also used during synchronous cycles. + + BUS_BSY <= '1' when BUS_CTRL_STATE /= IDLE else '0'; + + PARTITIONING: process + -- This logic gives information about the remaining bus cycles The initial + -- size is sampled right before the bus acces. This requires the RD_REQ + -- and WR_REQ signals to work on the positive clock edge. + variable RESTORE_VAR : std_logic_vector(2 downto 0) := "000"; + begin + wait until CLK = '1' and CLK' event; + + if BUS_CTRL_STATE = DATA_C1C4 and T_SLICE = S1 then -- On positive clock edge. + RESTORE_VAR := SIZE_N; -- We need this initial value for early RETRY. + end if; + -- + if RESET_CPU_I = '1' then + SIZE_N <= "000"; + elsif BUS_CTRL_STATE /= DATA_C1C4 and NEXT_BUS_CTRL_STATE = DATA_C1C4 then + if RD_REQ = '1' or WR_REQ = '1' then + case OP_SIZE is + when LONG => SIZE_N <= "100"; + when WORD => SIZE_N <= "010"; + when BYTE => SIZE_N <= "001"; + end case; + else -- OPCODE_ACCESS. + SIZE_N <= "010"; -- WORD. + end if; + end if; + + -- Decrementing the size information: + -- In this logic all permutations are considered. This allows a dynamically changing bus size. + if RETRY = '1' then + SIZE_N <= RESTORE_VAR; + elsif BUS_CTRL_STATE = DATA_C1C4 and ((T_SLICE = S1 and STERMn = '0') or (T_SLICE = S3 and WAITSTATES = '0')) then -- On positive clock edge. + if BUS_WIDTH = LONG_32 and SIZE_N > x"3" and ADR_OUT_I(1 downto 0) = "01" then + SIZE_N <= SIZE_N - "11"; + elsif BUS_WIDTH = LONG_32 and SIZE_N > x"2" and ADR_OUT_I(1 downto 0) = "10" then + SIZE_N <= SIZE_N - "10"; + elsif BUS_WIDTH = LONG_32 and SIZE_N > x"1" and ADR_OUT_I(1 downto 0) = "11" then + SIZE_N <= SIZE_N - '1'; + elsif BUS_WIDTH = LONG_32 then + SIZE_N <= "000"; + -- + elsif BUS_WIDTH = WORD and ADR_OUT_I(1 downto 0) = "11" then + SIZE_N <= SIZE_N - '1'; + elsif BUS_WIDTH = WORD and ADR_OUT_I(1 downto 0) = "01" then + SIZE_N <= SIZE_N - '1'; + elsif BUS_WIDTH = WORD and SIZE_N = "001" then + SIZE_N <= SIZE_N - '1'; + elsif BUS_WIDTH = WORD then + SIZE_N <= SIZE_N - "10"; + -- + elsif BUS_WIDTH = BYTE then + SIZE_N <= SIZE_N - '1'; + end if; + end if; + -- + if (BUS_FLT = '1' and HALT_In = '1') then -- Abort bus cycle. + SIZE_N <= "000"; + end if; + end process PARTITIONING; + + SIZE_I <= SIZE_N(1 downto 0) when T_SLICE = S0 or T_SLICE = S1 else SIZE_D; + SIZE <= SIZE_I; + + P_DELAY: process + -- This delay is responsible for a correct SIZE_I information. Use this, if the + -- process PARTITIONING works on the positive clock edge. The SIZE_I information + -- is delayed by half a clock cycle to be valid just in time of sampling the INMUX. + begin + wait until CLK = '1' and CLK' event; + SIZE_D <= SIZE_N(1 downto 0); + end process P_DELAY; + + BUS_STATE_REG: process + -- This is the bus controller's state register. + begin + wait until CLK = '1' and CLK' event; + BUS_CTRL_STATE <= NEXT_BUS_CTRL_STATE; + end process BUS_STATE_REG; + + BUS_CTRL_DEC: process(ADR_IN_P, ADR_OUT_I, ARB_STATE, BGACK_In, BR_In, BUS_CTRL_STATE, BUS_CYC_RDY, BUS_FLT, HALT_In, + OPCODE_ACCESS, OPCODE_REQ, RD_REQ, READ_ACCESS, RESET_CPU_I, RMC, SIZE_N, WR_REQ, WRITE_ACCESS) + -- This is the bus controller's state machine decoder. A SIZE_N count of "000" means that all bytes + -- to be transfered. After a bus transfer a value of x"0" indicates that no further bytes are required + -- for a bus transfer. + begin + case BUS_CTRL_STATE is + when IDLE => + if RESET_CPU_I = '1' then + NEXT_BUS_CTRL_STATE <= IDLE; -- Reset condition (bus cycle terminated). + elsif HALT_In = '0' then + NEXT_BUS_CTRL_STATE <= IDLE; -- This is the 'HALT' condition. + elsif (BR_In = '0' and RMC = '0') or ARB_STATE /= IDLE or BGACK_In = '0' then + NEXT_BUS_CTRL_STATE <= IDLE; -- Arbitration, wait! + elsif RD_REQ = '1' and SIZE_N = "000" then + NEXT_BUS_CTRL_STATE <= START_CYCLE; -- New read cycle. + elsif WR_REQ = '1' and SIZE_N = "000" then + NEXT_BUS_CTRL_STATE <= START_CYCLE; -- New write cycle. + elsif OPCODE_REQ = '1' and SIZE_N = "000" then + NEXT_BUS_CTRL_STATE <= START_CYCLE; -- New read cycle. + elsif READ_ACCESS = '1' or WRITE_ACCESS = '1' or OPCODE_ACCESS = '1' then + NEXT_BUS_CTRL_STATE <= START_CYCLE; -- Pending (split) bus cycles. + else + NEXT_BUS_CTRL_STATE <= IDLE; + end if; + when START_CYCLE => + if RD_REQ = '1' then + NEXT_BUS_CTRL_STATE <= DATA_C1C4; + elsif WR_REQ = '1' then + NEXT_BUS_CTRL_STATE <= DATA_C1C4; + elsif OPCODE_REQ = '1' and ADR_IN_P(0) = '1' then + NEXT_BUS_CTRL_STATE <= IDLE; -- Abort due to address error. + elsif OPCODE_REQ = '1' and ADR_IN_P(0) = '1' then + NEXT_BUS_CTRL_STATE <= IDLE; -- Abort due to address error. + elsif OPCODE_REQ = '1' then + NEXT_BUS_CTRL_STATE <= DATA_C1C4; + else + NEXT_BUS_CTRL_STATE <= IDLE; + end if; + when DATA_C1C4 => + if BUS_CYC_RDY = '1' and SIZE_N = "000" then + NEXT_BUS_CTRL_STATE <= IDLE; + else + NEXT_BUS_CTRL_STATE <= DATA_C1C4; + end if; + end case; + end process BUS_CTRL_DEC; + + P_ADR_OFFS: process + -- This process provides a temporary address offset during + -- bus access. + variable OFFSET_VAR : std_logic_vector(2 downto 0) := "000"; + begin + wait until CLK = '1' and CLK' event; + if RESET_CPU_I = '1' then + OFFSET_VAR := "000"; + elsif (T_SLICE = S2 and STERMn = '0') or T_SLICE = S3 then + case BUS_WIDTH is + when LONG_32 => + case ADR_OUT_I(1 downto 0) is + when "11" => OFFSET_VAR := "001"; + when "10" => OFFSET_VAR := "010"; + when "01" => OFFSET_VAR := "011"; + when others => OFFSET_VAR := "100"; + end case; + when WORD => + case ADR_OUT_I(1 downto 0) is + when "01" | "11" => OFFSET_VAR := "001"; + when others => OFFSET_VAR := "010"; + end case; + when BYTE => + OFFSET_VAR := "001"; + end case; + end if; + -- + if RESET_CPU_I = '1' then + ADR_OFFSET <= (others => '0'); + elsif RETRY = '1' then + null; -- Do not update if there is a retry cycle. + elsif BUS_CTRL_STATE /= IDLE and NEXT_BUS_CTRL_STATE = IDLE then + ADR_OFFSET <= (others => '0'); + elsif BUS_CYC_RDY = '1' then + ADR_OFFSET <= ADR_OFFSET + OFFSET_VAR; + end if; + end process P_ADR_OFFS; + + ADR_OUT_I <= ADR_IN_P + ADR_OFFSET; + ADR_OUT_P <= ADR_OUT_I; + + P_ADR_10: process + -- This logic is registered to enhance the system performance concerning fmax. + begin + wait until CLK = '1' and CLK' event; + ADR_10 <= ADR_OUT_I(1 downto 0); + end process P_ADR_10; + + -- Address and bus errors: + AERR_I <= '1' when BUS_CTRL_STATE = START_CYCLE and OPCODE_REQ = '1' and RD_REQ = '0' and WR_REQ = '0' and ADR_IN_P(0) = '1' else '0'; + + FC_OUT <= FC_IN; + + -- The output multiplexer is as follows: + -- SIZE ADR Bytes (L = long word port, W = word port, B = Byte port, x = not used by either port) + -- 00 00 3 (L, W, B) 2 (L, W ) 1 (L ) 0 (L ) + -- 00 01 3 ( B) 3 (L, W ) 2 (L ) 1 (L ) + -- 00 10 3 ( W, B) 2 ( W ) 3 (L ) 2 (L ) + -- 00 11 3 ( B) 2 ( W ) -----x----- 0 (L ) + -- 11 00 2 (L, W, B) 1 (L, W ) 0 (L ) -----x----- + -- 11 01 2 ( B) 2 (L, W ) 1 (L ) 0 (L ) + -- 11 10 1 ( W, B) 0 ( W ) 1 (L ) 0 (L ) + -- 11 11 1 ( B) 1 ( W ) -----x----- 1 (L ) + -- 10 00 1 (L, W, B) 0 (L, W ) -----x----- -----x----- + -- 10 01 1 ( B) 1 (L, W ) 0 (L ) -----x----- + -- 10 10 1 ( W, B) 0 ( W ) 1 (L ) 0 (L ) + -- 10 11 1 ( B) 1 ( W ) -----x----- 1 (L ) + -- 01 00 0 (L, W, B) -----x----- -----x----- -----x----- + -- 01 01 0 ( B) 0 (L, W ) -----x----- -----x----- + -- 01 10 0 ( W, B) -----x----- 0 (L ) -----x----- + -- 01 11 0 ( B) 0 ( W ) -----x----- 0 (L ) + + DATA_PORT_OUT <= -- Data output multiplexer. + -- LONG: + WP_BUFFER(31 downto 0) when SIZE_I = "00" and ADR_OUT_I(1 downto 0) = "00" else + WP_BUFFER(31 downto 24) & WP_BUFFER(31 downto 8) when SIZE_I = "00" and ADR_OUT_I(1 downto 0) = "01" else + WP_BUFFER(31 downto 16) & WP_BUFFER(31 downto 16) when SIZE_I = "00" and ADR_OUT_I(1 downto 0) = "10" else + WP_BUFFER(31 downto 24) & WP_BUFFER(31 downto 16) & WP_BUFFER(31 downto 24) when SIZE_I = "00" and ADR_OUT_I(1 downto 0) = "11" else + -- 3 bytes: + WP_BUFFER(23 downto 0) & WP_BUFFER(31 downto 24) when SIZE_I = x"3" and ADR_OUT_I(1 downto 0) = "00" else + WP_BUFFER(23 downto 16) & WP_BUFFER(23 downto 0) when SIZE_I = "11" and ADR_OUT_I(1 downto 0) = "01" else + WP_BUFFER(23 downto 8) & WP_BUFFER(23 downto 8) when SIZE_I = "11" and ADR_OUT_I(1 downto 0) = "10" else + WP_BUFFER(23 downto 16) & WP_BUFFER(23 downto 8) & WP_BUFFER(23 downto 16) when SIZE_I = "11" and ADR_OUT_I(1 downto 0) = "11" else + -- Word: + WP_BUFFER(15 downto 0) & WP_BUFFER(15 downto 0) when SIZE_I = "10" and ADR_OUT_I(1 downto 0) = "00" else + WP_BUFFER(15 downto 8) & WP_BUFFER(15 downto 0) & WP_BUFFER(15 downto 8) when SIZE_I = "10" and ADR_OUT_I(1 downto 0) = "01" else + WP_BUFFER(15 downto 0) & WP_BUFFER(15 downto 0) when SIZE_I = "10" and ADR_OUT_I(1 downto 0) = "10" else + WP_BUFFER(15 downto 8) & WP_BUFFER(15 downto 0) & WP_BUFFER(15 downto 8) when SIZE_I = "10" and ADR_OUT_I(1 downto 0) = "11" else + -- Byte: + WP_BUFFER(7 downto 0) & WP_BUFFER(7 downto 0) & WP_BUFFER(7 downto 0) & WP_BUFFER(7 downto 0); -- SIZE = "01". + + IN_MUX: process + -- This is the input multiplexer which can handle up to four bytes. + begin + wait until CLK = '0' and CLK' event; + -- + if ((T_SLICE = S2 or T_SLICE = S3) and STERMn = '0') or T_SLICE = S4 then + case BUS_WIDTH is + when BYTE => + case SIZE_I is + when "00" => DATA_INMUX(31 downto 24) <= DATA_PORT_IN(31 downto 24); -- LONG. + when "11" => DATA_INMUX(23 downto 16) <= DATA_PORT_IN(31 downto 24); -- Three bytes. + when "10" => DATA_INMUX(15 downto 8) <= DATA_PORT_IN(31 downto 24); -- Word. + when others => DATA_INMUX(7 downto 0) <= DATA_PORT_IN(31 downto 24); -- Byte. + end case; + when WORD => + case SIZE_I is + when "01" => -- Byte. + case ADR_10 is + when "00" | "10" => DATA_INMUX(7 downto 0) <= DATA_PORT_IN(31 downto 24); + when others => DATA_INMUX(7 downto 0) <= DATA_PORT_IN(23 downto 16); -- "01", "11". + end case; + when "10" => -- Word. + case ADR_10 is + when "00" => DATA_INMUX(15 downto 0) <= DATA_PORT_IN(31 downto 16); + when "01" => DATA_INMUX(15 downto 8) <= DATA_PORT_IN(23 downto 16); + when "10" => DATA_INMUX(15 downto 0) <= DATA_PORT_IN(31 downto 16); + when others => DATA_INMUX(15 downto 8) <= DATA_PORT_IN(23 downto 16); -- "11". + end case; + when "11" => -- Three bytes. + case ADR_10 is + when "00" => DATA_INMUX(23 downto 8) <= DATA_PORT_IN(31 downto 16); + when "01" => DATA_INMUX(23 downto 16) <= DATA_PORT_IN(23 downto 16); + when "10" => DATA_INMUX(23 downto 8) <= DATA_PORT_IN(31 downto 16); + when others => DATA_INMUX(23 downto 16) <= DATA_PORT_IN(23 downto 16); -- "11". + end case; + when others => -- "00" = LONG. + case ADR_10 is + when "00" => DATA_INMUX(31 downto 16) <= DATA_PORT_IN(31 downto 16); + when "01" => DATA_INMUX(31 downto 24) <= DATA_PORT_IN(23 downto 16); + when "10" => DATA_INMUX(31 downto 16) <= DATA_PORT_IN(31 downto 16); + when others => DATA_INMUX(31 downto 24) <= DATA_PORT_IN(23 downto 16); -- "11". + end case; + end case; + when LONG_32 => + case SIZE_I is + when "01" => -- Byte. + case ADR_10 is + when "00" => DATA_INMUX(7 downto 0) <= DATA_PORT_IN(31 downto 24); + when "01" => DATA_INMUX(7 downto 0) <= DATA_PORT_IN(23 downto 16); + when "10" => DATA_INMUX(7 downto 0) <= DATA_PORT_IN(15 downto 8); + when others => DATA_INMUX(7 downto 0) <= DATA_PORT_IN(7 downto 0); -- "11". + end case; + when "10" => -- Word. + case ADR_10 is + when "00" => DATA_INMUX(15 downto 0) <= DATA_PORT_IN(31 downto 16); + when "01" => DATA_INMUX(15 downto 0) <= DATA_PORT_IN(23 downto 8); + when "10" => DATA_INMUX(15 downto 0) <= DATA_PORT_IN(15 downto 0); + when others => DATA_INMUX(15 downto 8) <= DATA_PORT_IN(7 downto 0); -- "11". + end case; + when "11" => -- Three bytes. + case ADR_10 is + when "00" => DATA_INMUX(23 downto 0) <= DATA_PORT_IN(31 downto 8); + when "01" => DATA_INMUX(23 downto 0) <= DATA_PORT_IN(23 downto 0); + when "10" => DATA_INMUX(23 downto 8) <= DATA_PORT_IN(15 downto 0); + when others => DATA_INMUX(23 downto 16) <= DATA_PORT_IN(7 downto 0); -- "11". + end case; + when others => -- "00" = LONG. + case ADR_10 is + when "00" => DATA_INMUX(31 downto 0) <= DATA_PORT_IN(31 downto 0); + when "01" => DATA_INMUX(31 downto 8) <= DATA_PORT_IN(23 downto 0); + when "10" => DATA_INMUX(31 downto 16) <= DATA_PORT_IN(15 downto 0); + when others => DATA_INMUX(31 downto 24) <= DATA_PORT_IN(7 downto 0); -- "11". + end case; + end case; + end case; + end if; + end process IN_MUX; + + VALIDATION: process + -- These flip flops detect a fault during the read operation over one or + -- several bytes or during the write operation. + begin + wait until CLK = '1' and CLK' event; + -- + if RESET_CPU_I = '1' then + OPCODE_VALID <= '1'; + elsif OPCODE_ACCESS = '1' and BUS_CTRL_STATE = DATA_C1C4 and BUS_FLT = '1' then + OPCODE_VALID <= '0'; + elsif OPCODE_RDY_I = '1' then + OPCODE_VALID <= '1'; -- Reset after use, TRAP_BERR is asserted during DATA_RDY. + end if; + -- + if RESET_CPU_I = '1' then + DATA_VALID <= '1'; + elsif BUS_CTRL_STATE = DATA_C1C4 and BUS_FLT = '1' then + DATA_VALID <= '0'; + elsif DATA_RDY_I = '1' then + DATA_VALID <= '1'; -- Reset after use, TRAP_BERR is asserted during DATA_RDY. + end if; + end process VALIDATION; + + PREFETCH_BUFFERS: process + -- These are the data and the operation code input registers. After a last read to the registered + -- input multiplexer, the respective data is copied from the input multiplexer to these buffers. + -- The opcode buffer is always written with 32 bit data. The data buffers may contain invalid bytes + -- in case of word or byte data size. + variable DBUFFER_MEM : std_logic_vector(31 downto 8) := x"000000"; + variable RDY_VAR : bit := '0'; + begin + wait until CLK = '1' and CLK' event; + -- + OPCODE_RDY_I <= '0'; -- This is a strobe. + DATA_RDY_I <= '0'; -- This is a strobe. + -- + -- The following variable is responsible, that the _RDY signals are + -- always strobes. + if DATA_RDY_I = '1' or OPCODE_RDY_I = '1' then + RDY_VAR := '0'; + elsif BUS_CTRL_STATE = START_CYCLE then + RDY_VAR := '1'; + end if; + -- Opcode cycle: + if AERR_I = '1' then + OPCODE_RDY_I <= '1'; + elsif OPCODE_ACCESS = '1' and BUS_CTRL_STATE = DATA_C1C4 and BUS_CYC_RDY = '1' and SIZE_N = "000" then + -- Instruction prefetches are always long and on word boundaries. + -- The word is available after the first word read. + OBUFFER <= DATA_INMUX(15 downto 0); + OPCODE_RDY_I <= RDY_VAR; + end if; + -- Data cycle: + if WRITE_ACCESS = '1' and BUS_CTRL_STATE = DATA_C1C4 and BUS_CYC_RDY = '1' and SIZE_N = "000" then + DATA_RDY_I <= RDY_VAR; + elsif READ_ACCESS = '1' and BUS_CTRL_STATE = DATA_C1C4 and BUS_CYC_RDY = '1' then + case OP_SIZE is + when LONG => + if SIZE_N = "000" then + DBUFFER <= DATA_INMUX; + DATA_RDY_I <= RDY_VAR; + end if; + when WORD => + if SIZE_N = "000" then + DBUFFER <= x"0000" & DATA_INMUX(15 downto 0); + DATA_RDY_I <= RDY_VAR; + end if; + when BYTE => -- Byte always aligned. + DATA_RDY_I <= RDY_VAR; + DBUFFER <= x"000000" & DATA_INMUX(7 downto 0); + end case; + end if; + end process PREFETCH_BUFFERS; + + DATA_RDY <= DATA_RDY_I; + OPCODE_RDY <= OPCODE_RDY_I; + + DATA_TO_CORE <= DBUFFER; + OPCODE_TO_CORE <= OBUFFER; + + WAITSTATES <= '0' when T_SLICE /= S3 else + '1' when RESET_OUT_I = '1' else -- No bus fault during RESET instruction. + '0' when DSACK_In /= "11" else -- For asynchronous bus cycles. + '0' when STERMn = '0' else -- For synchronous bus cycles. + '0' when ADR_IN_P(19 downto 16) = x"F" and AVEC_In = '0' else -- Interrupt acknowledge space cycle. + '0' when BUS_FLT = '1' else -- In case of a bus error; + '0' when RESET_CPU_I = '1' else '1'; -- A CPU reset terminates the current bus cycle. + + SLICES: process(CLK) + -- This process provides the central timing for the read, write and read modify write cycle as also + -- for the bus arbitration procedure. Be aware, that the bus controller state machine changes it's + -- state on the positive clock edge. The BUS_CYC_RDY signal is asserted during S3 or S5. So the + -- slice counter working on the positive clock edge may change it's state. + begin + if CLK = '1' and CLK' event then + if BUS_CTRL_STATE = IDLE then + SLICE_CNT_P <= "111"; -- Init. + elsif RETRY = '1' then + SLICE_CNT_P <= "111"; -- Stay in IDLE, go to IDLE. + elsif BUS_CTRL_STATE /= IDLE and NEXT_BUS_CTRL_STATE = IDLE then + SLICE_CNT_P <= "111"; -- Init. + elsif SLICE_CNT_P = "001" and STERMn = '0' then -- Synchronous cycle. + SLICE_CNT_P <= "110"; -- Ready. + elsif SLICE_CNT_P = "010" then + if RETRY = '1' then + SLICE_CNT_P <= "111"; -- Go IDLE. + elsif BUS_CTRL_STATE = DATA_C1C4 and NEXT_BUS_CTRL_STATE = IDLE then + SLICE_CNT_P <= "111"; -- Ready. + else + SLICE_CNT_P <= "000"; -- Go on. + end if; + elsif WAITSTATES = '0' then + SLICE_CNT_P <= SLICE_CNT_P + '1'; -- Cycle active. + end if; + end if; + -- + if CLK = '0' and CLK' event then + SLICE_CNT_N <= SLICE_CNT_P; -- Follow the P counter. + end if; + end process SLICES; + + T_SLICE <= S0 when SLICE_CNT_P = "000" and SLICE_CNT_N = "111" else + S1 when SLICE_CNT_P = "000" and SLICE_CNT_N = "000" else + S2 when SLICE_CNT_P = "001" and SLICE_CNT_N = "000" else + S3 when SLICE_CNT_P = "001" and SLICE_CNT_N = "001" else + S4 when SLICE_CNT_P = "010" and SLICE_CNT_N = "001" else + S5 when SLICE_CNT_P = "010" and SLICE_CNT_N = "010" else + S3 when SLICE_CNT_P = "110" else -- This is a waitstate cycle for synchronous bus cycles to update SIZE_N before latching data. + S0 when SLICE_CNT_P = "000" and SLICE_CNT_N = "010" else IDLE; -- Rollover from state S5 to S0. + + P_OCS: process + -- This flip flop enables the output of the OCSn signal for + -- the first bus cycle and locks OCSn for all other bus cycles. + -- ECSn is locked only during cache burst access. + begin + wait until CLK = '1' and CLK' event; + -- + if BUS_CTRL_STATE = START_CYCLE and NEXT_BUS_CTRL_STATE /= IDLE then + OCS_INH <= '0'; + elsif BUS_CYC_RDY = '1' and RETRY = '0' then -- No inhibit if first portion results in a retry cycle. + OCS_INH <= '1'; + end if; + end process P_OCS; + + -- Bus control signals: + RWn <= '0' when WRITE_ACCESS = '1' and BUS_CTRL_STATE = DATA_C1C4 else '1'; + RMCn <= '0' when RMC = '1' else '1'; + ECSn <= '0' when T_SLICE = S0 else '1'; + OCSn <= '0' when T_SLICE = S0 and OCS_INH = '0' else '1'; + ASn <= '0' when T_SLICE = S1 or T_SLICE = S2 or T_SLICE = S3 or T_SLICE = S4 else '1'; + DSn <= '0' when (T_SLICE = S3 or T_SLICE = S4 or T_SLICE = S5) and WRITE_ACCESS = '1' else -- Write. + '0' when T_SLICE = S1 or T_SLICE = S2 or T_SLICE = S3 or T_SLICE = S4 else '1'; -- Read. + + DBENn <= '0' when (T_SLICE = S1 or T_SLICE = S2 or T_SLICE = S3 or T_SLICE = S4 or T_SLICE = S5) and WRITE_ACCESS = '1' else -- Write. + '0' when T_SLICE = S2 or T_SLICE = S3 or T_SLICE = S4 else '1'; -- Read. + + -- Bus tri state controls: + BUS_EN <= '1' when ARB_STATE = IDLE and RESET_CPU_I = '0' else '0'; + DATA_PORT_EN <= '1' when WRITE_ACCESS = '1' and ARB_STATE = IDLE and RESET_CPU_I = '0' else '0'; + + -- Progress controls: + BUS_CYC_RDY <= '0' when RETRY = '1' else + '1' when STERM_Dn = '0' else -- Synchronous cycles. STERMn delayed to update the SIZE_N and SIZE_M before BUS_CYC_RDY is asserted. + '1' when T_SLICE = S5 else '0'; -- Asynchronous cycles. + + -- Bus arbitration: + ARB_REG: process + -- This is the arbiters state register. + begin + wait until CLK = '1' and CLK' event; + -- + if RESET_CPU_I = '1' then + ARB_STATE <= IDLE; + else + ARB_STATE <= NEXT_ARB_STATE; + end if; + end process ARB_REG; + + ARB_DEC: process(ARB_STATE, BGACK_In, BR_In, BUS_CTRL_STATE, RETRY, RMC) + -- This is the bus arbitration state machine's decoder. It can handle single-, two- + -- or three wire arbitration. The two wire arbitration is done in the GRANT state + -- by negating BRn. + begin + case ARB_STATE is + when IDLE => + if RMC = '1' and RETRY = '0' then + NEXT_ARB_STATE <= IDLE; -- Arbitration in RETRY operation is possible. + elsif BGACK_In = '0' and BUS_CTRL_STATE = IDLE then -- This is the single wire arbitration. + NEXT_ARB_STATE <= WAIT_RELEASE_3WIRE; + elsif BR_In = '0' and BUS_CTRL_STATE = IDLE then -- Wait until the bus is free. + NEXT_ARB_STATE <= GRANT; + else + NEXT_ARB_STATE <= IDLE; + end if; + when GRANT => + if BGACK_In = '0' then + NEXT_ARB_STATE <= WAIT_RELEASE_3WIRE; + elsif BR_In = '1' then + NEXT_ARB_STATE <= IDLE; -- Resume normal operation. + else + NEXT_ARB_STATE <= GRANT; + end if; + when WAIT_RELEASE_3WIRE => + if BGACK_In = '1' and BR_In = '0' then + NEXT_ARB_STATE <= GRANT; -- Re-enter new arbitration. + elsif BGACK_In = '1' then + NEXT_ARB_STATE <= IDLE; + else + NEXT_ARB_STATE <= WAIT_RELEASE_3WIRE; + end if; + end case; + end process ARB_DEC; + + BGn <= '0' when ARB_STATE = GRANT else '1'; + + -- RESET logic: + RESET_FILTER: process + -- This process filters the incoming reset pin. + -- If RESET_IN and HALT_In are asserted together for longer + -- than 10 clock cycles over the execution of a CPU reset + -- command, the CPU reset is released. + variable STARTUP : boolean := false; + variable TMP : std_logic_vector(3 downto 0) := x"0"; + begin + wait until CLK = '1' and CLK' event; + -- + if RESET_IN = '1' and HALT_In = '0' and RESET_OUT_I = '0' and TMP < x"F" then + TMP := TMP + '1'; + elsif RESET_IN = '0' or HALT_In = '1' or RESET_OUT_I = '1' then + TMP := x"0"; + end if; + if TMP > x"A" then + RESET_CPU_I <= '1'; -- Release internal reset. + STARTUP := true; + elsif STARTUP = false then + RESET_CPU_I <= '1'; + else + RESET_CPU_I <= '0'; + end if; + end process RESET_FILTER; + + RESET_TIMER: process + -- This logic is responsible for the assertion of the + -- reset output for 512 clock cycles, during the reset + -- command. The LOCK variable avoids re-initialisation + -- of the counter in the case that the RESET_EN is no + -- strobe. + variable TMP : std_logic_vector(8 downto 0) := "000000000"; + begin + wait until CLK = '1' and CLK' event; + -- + if RESET_STRB = '1' or TMP > "000000000" then + RESET_OUT_I <= '1'; + else + RESET_OUT_I <= '0'; + end if; + -- + if RESET_STRB = '1' then + TMP := "111111111"; -- 512 initial value. + elsif TMP > "000000000" then + TMP := TMP - '1'; + end if; + end process RESET_TIMER; + + RESET_CPU <= RESET_CPU_I; + RESET_OUT <= RESET_OUT_I; +end BEHAVIOR; diff --git a/common/CPU/68K30L/wf68k30L_control.vhd b/common/CPU/68K30L/wf68k30L_control.vhd new file mode 100644 index 00000000..166f4282 --- /dev/null +++ b/common/CPU/68K30L/wf68k30L_control.vhd @@ -0,0 +1,2553 @@ +------------------------------------------------------------------------ +---- ---- +---- WF68K30L IP Core: this is the main controller to handle all ---- +---- integer instructions. ---- +---- ---- +---- Description: ---- +---- This controller handles all integer instructions and provides ---- +---- all required system control signals. The instructions are ---- +---- requested from the instruction prefetch unit in the opcode ---- +---- decoder unit. The data is mostly written to the ALU and after- ---- +---- wards from the ALU to the writeback logic. This pipelined ---- +---- structure requires a correct management of data in use. Any ---- +---- address or data registers or memory addresses which are in use ---- +---- are marked by a flag not to be used befor written back. Any ---- +---- time data or address reegisters or the effective address are ---- +---- in the writeback pipe, the respective use flag is evaluated. ---- +---- Instructions like MOVE read unused source and the destination ---- +---- is written, when the ALU and writeback controller 'free'. ---- +---- Instructions like ADD, SUB etc. read unused source and desti- ---- +---- nations and write back the destination, when the operands are ---- +---- not used any more and the ALU and writeback controller are not ---- +---- in use by another operation. ---- +---- The main controller is the second pipeline stage of the CPU. ---- +---- The pipelining structure also requires some special treatment ---- +---- for the system control instructions as described as follows: ---- +------------------------------------------------------------------------ +---- System Control Instructions: ---- +---- There are several instructions which require the instruction ---- +---- pipe to be flushed as described in the following. For further ---- +---- information refer to the 68Kxx data sheets. ---- +---- ---- +---- 1. TRAP generating: ---- +---- The following instructions result in a pipe flush when the ---- +---- exception handler takes control over the system: ---- +---- BKPT, CHK, ILLEGAL, TRAP, TRAPV ---- +---- There are some other indirect conditions flushing the pipe ---- +---- such as the STOP which is invoked by an external interrupt.---- +---- ---- +---- 2. Privilege violations: ---- +---- Some instructions may result in a privilege violation ---- +---- when executed in user space. The result will be a ---- +---- privilege violation trap and the ipipe is flushed when ---- +---- the exception handler takes over. The instructions are: ---- +---- ANDI_TO_SR, EORI_TO_SR, ORI_TO_SR, MOVEC, MOVES, MOVE_USP, ---- +---- MOVE_FROM_SR, MOVE_TO_SR, RESET, RTE and STOP ---- +---- ---- +---- 3. Branches and Jumps: ---- +---- In case of branches and jumps and the respective return ---- +---- operations it is required to flush the instruction pipe. ---- +---- If PC value changes due to any branch or jump, it is neces- ---- +---- sary to flush the instruction pipe to invalidate already ---- +---- loaded 'old' instructions. This affects: ---- +---- BRA, BSR, Bcc, DBcc, JMP, JSR and the returns: ---- +---- RTD, RTR, RTS, RTE and also STOP. ---- +---- ---- +------------------------------------------------------------------------ +---- Data hazards: ---- +---- To avoid malfunction by using old data several things have ---- +---- to be taken into account: ---- +---- 1. Operations manipulating the system registers must wait ---- +---- in the end of the operation until the ALU has updated ---- +---- the condition codes. These operations are ANDI_TO_SR, ---- +---- EORI_TO_SR, ORI_TO_SR, MOVE_TO_SR and MOVEC. ---- +---- 2. Operations using the staus register must not start until ---- +---- the ALU has updated the condition codes. These operations ---- +---- are MOVE_FROM_CCR, MOVE_FROM_SR and MOVEC. ---- +---- 3. Operations using the stack pointer must not start until ---- +---- the stack pointer is updated by the previous operation. ---- +---- Operations using the stack pointer are RTD, RTR, RTS, ---- +---- MOVEC, MOVE_USP and UNLK. ---- +---- 4. Operations manipulating the stack pointer without using ---- +---- the ALU must not start until the stack is written by the ---- +---- previous operation. Stack pointer manipulating operations ---- +---- are BSR, JSR, LINK and PEA. ---- +------------------------------------------------------------------------ +---- ---- +---- Remarks: ---- +---- ---- +---- Author(s): ---- +---- - Wolfgang Foerster, wf@experiment-s.de; wf@inventronik.de ---- +---- ---- +------------------------------------------------------------------------ +---- ---- +---- Copyright © 2014-2019 Wolfgang Foerster Inventronik GmbH. ---- +---- ---- +---- This documentation describes Open Hardware and is licensed ---- +---- under the CERN OHL v. 1.2. You may redistribute and modify ---- +---- this documentation under the terms of the CERN OHL v.1.2. ---- +---- (http://ohwr.org/cernohl). This documentation is distributed ---- +---- WITHOUT ANY EXPRESS OR IMPLIED WARRANTY, INCLUDING OF ---- +---- MERCHANTABILITY, SATISFACTORY QUALITY AND FITNESS FOR A ---- +---- PARTICULAR PURPOSE. Please see the CERN OHL v.1.2 for ---- +---- applicable conditions ---- +---- ---- +------------------------------------------------------------------------ +-- +-- Revision History +-- +-- Revision 2K14B 20141201 WF +-- Initial Release. +-- Revision 2K16A 20160620 WF +-- Fixed a bug in the MOVEM operation. +-- Revision 2K18A (unreleased) WF +-- Fixed a bug in MOVE An,-(Ay). Thanks to Gary Bingham for the support. +-- Fixed wrong PEA behaviour. +-- Fixed the displacement for LINK. +-- Fixed AR_MARK_USED in LINK. +-- Fixed the operation size for MOVEQ. +-- ADDQ, SUBQ Fix: address registers are always written long. +-- ADDI, ANDI, EORI, ORI, SUBI: address is not marked used if destination is Dn. +-- ADDI, ANDI, EORI, ORI, SUBI: data register is marked used if destination is Dn. +-- EXG: rearranged logic to meet the new top level multiplexers. +-- LINK, UNLK: wait in START_OP until the ALU is ready (avoids possible data hazards). +-- LINK, UNLK: fixed the write back operation size. +-- MOVEM: Fixed predecrement mode for consecutive MOVEM -(An). +-- MOVEP: MOVEP_PNTR is now correct for consecutive MOVEP. +-- MOVEP: avoid structural hazard in SWITCH_STATE by waiting for ALU. +-- EOR: fixed a bug in the writeback mechanism. +-- BSR, JSR: EXEC_WB state machine waits now for ALU_INIT. Avoid structural / data hazard. +-- The instruction pipe is not flushed for ANDI_TO_CCR, EORI_TO_CCR, ORI_TO_CCR. +-- The instruction pipe is not flushed for MOVE_FROM_CCR, MOVE_TO_CCR, MOVE_FROM_SR, MOVE_USP, MOVEC. +-- Modifications in the FETCH state machine to avoid several data hazards for MOVEM, MOVE_FROM_CCR, MOVE_FROM_SR. +-- Modifications in the FETCH state machine to avoid several data hazards for ANDI_TO_CCR, ANDI_TO_SR, EORI_TO_CCR, EORI_TO_SR, ORI_TO_CCR, ORI_TO_SR. +-- We have to stop a pending operation in case of a pending interrupt. This is done by rejecting OW_RDY. +-- TOP, CONTROL, Exception Handler Opcode Decoder: Rearranged PC_INC and ipipe flush logic. +-- Write the undecremented Register for MOVE Ax, -(Ax). +-- LINK A7 and PEA(A7) stacks the undecremented A7. +-- Control: LINK A7 and PEA(A7) stacks the undecremented A7. +-- Bus interface: Rearranged the DATA_RDY vs. BUS_FLT logic. +-- UNMARK is now asserted in the end of the write cycle. This avoids data hazards. +-- Fixed a MOVEC writeback issue (use BIW_WB... instead of BIW_...). +-- Fixed a USP writeback issue (use BIW_WB... instead of BIW_...). +-- Introduced a switch NO_PIPELINE. +-- MOVEM-Fix: the effective address in memory to register is stored (STORE_AEFF) not to be overwritten in case the addressing register is also loaded. +-- DBcc: fixed a data hazard for DBcc_COND evaluation by waiting on the ALU result. +-- Fixed DR_WR_1 locking against AR_WR_2. +-- IPIPE is flushed, when there is a memory space change in the end of xx_TO_SR operations. +-- To handle correct addressing, ADR_OFFSET is now cleared right in the end of the respective operation. +-- Fixed a bug in EOR writing back in register direct mode. +-- ADDQ and SUBQ: fixed (An)+ mode. An increments now. +-- Fixed DIVS, DIVU in memory address modes (wrong control flow). +-- ADDQ and SUBQ: fixed condition code control UPDT_CC. +-- Fixed a data hazard bug using addressing modes with index register. +-- Implemented the 68K10 loop mechanism. +-- Fixed several pipelinig issues (hazards). +-- Revision 2K19A 20190419 WF +-- Introdeced a new state CALC_AEFF which results in no need of ADR_ATN and a twice highre fmax. +-- Revision 2K19B 20191224 WF +-- NOP explicitely synchronizes the instruction pipe now. +-- The controller must be BUSY when an opword is loaded and we have to wait in START_OP (avoids other controllers to reload the opword, see OW_REQ). +-- Control: BUSY is now asserted when an opword is loaded and we have to wait in START_OP (avoids other controllers to reload the opword, see OW_REQ). +-- Removed a data hazard condition (A7) for JSR, PEA, LINK and UNLK in the beginning of the operation. +-- + +use work.WF68K30L_PKG.all; + +library ieee; +use ieee.std_logic_1164.all; +use ieee.std_logic_unsigned.all; +use ieee.numeric_std.all; + +entity WF68K30L_CONTROL is + generic(NO_PIPELINE : boolean := false); -- If true the controller work in scalar mode. + port ( + CLK : in std_logic; -- System clock. + RESET_CPU : in bit; -- CPU reset. + + BUSY : out bit; -- Main controller finished an execution. + BUSY_EXH : in bit; + EXH_REQ : in bit; + INT_TRIG : out bit; + + OW_REQ : out bit; -- Operation words request. + OW_VALID : in std_logic; -- Operation words is valid. + EW_REQ : out bit; -- Extension word request. + EW_ACK : in bit; -- Extension word available. + OPD_ACK : in bit; -- Opcode has new data. + + ADR_MARK_USED : out bit; + ADR_IN_USE : in bit; + ADR_OFFSET : out std_logic_vector(5 downto 0); + + DATA_RD : out bit; + DATA_WR : out bit; + DATA_RDY : in bit; + DATA_VALID : in std_logic; + RMC : out bit; + + FETCH_MEM_ADR : out bit; + LOAD_OP1 : out bit; + LOAD_OP2 : out bit; + LOAD_OP3 : out bit; + STORE_ADR_FORMAT : out bit; + STORE_D16 : out bit; + STORE_D32_LO : out bit; + STORE_D32_HI : out bit; + STORE_DISPL : out bit; + STORE_OD_HI : out bit; + STORE_OD_LO : out bit; + STORE_ABS_HI : out bit; + STORE_ABS_LO : out bit; + STORE_IDATA_B2 : out bit; + STORE_IDATA_B1 : out bit; + STORE_MEM_ADR : out bit; + STORE_AEFF : out bit; + + -- System control signals: + OP : in OP_68K; + OP_SIZE : out OP_SIZETYPE; + BIW_0 : in std_logic_vector(13 downto 0); + BIW_1 : in std_logic_vector(15 downto 0); + BIW_2 : in std_logic_vector(15 downto 0); + EXT_WORD : in std_logic_vector(15 downto 0); + + ADR_MODE : out std_logic_vector(2 downto 0); + AMODE_SEL : out std_logic_vector(2 downto 0); + USE_DREG : out bit; + HILOn : out bit; + + OP_WB : out OP_68K; + OP_SIZE_WB : out OP_SIZETYPE; + BIW_0_WB_73 : out std_logic_vector(7 downto 3); -- Used for EXG. + + AR_MARK_USED : out bit; + USE_APAIR : out boolean; + AR_IN_USE : in bit; + AR_SEL_RD_1 : out std_logic_vector(2 downto 0); + AR_SEL_RD_2 : out std_logic_vector(2 downto 0); + AR_SEL_WR_1 : out std_logic_vector(2 downto 0); + AR_SEL_WR_2 : out std_logic_vector(2 downto 0); + AR_INC : out bit; + AR_DEC : out bit; + AR_WR_1 : out bit; + AR_WR_2 : out bit; + + DR_MARK_USED : out bit; + USE_DPAIR : out boolean; + DR_IN_USE : in bit; + DR_SEL_WR_1 : out std_logic_vector(2 downto 0); + DR_SEL_WR_2 : out std_logic_vector(2 downto 0); + DR_SEL_RD_1 : out std_logic_vector(2 downto 0); + DR_SEL_RD_2 : out std_logic_vector(2 downto 0); + DR_WR_1 : out bit; + DR_WR_2 : out bit; + + UNMARK : out bit; + + DISPLACEMENT : out std_logic_vector(31 downto 0); + PC_ADD_DISPL : out bit; + PC_LOAD : out bit; + PC_INC_EXH : in bit; + + SP_ADD_DISPL : out bit; + + DFC_WR : out bit; + DFC_RD : out bit; + SFC_WR : out bit; + SFC_RD : out bit; + + VBR_WR : out bit; + VBR_RD : out bit; + + ISP_RD : out bit; + ISP_WR : out bit; + MSP_RD : out bit; + MSP_WR : out bit; + USP_RD : out bit; + USP_WR : out bit; + + IPIPE_FLUSH : out bit; -- Abandon the instruction pipeline. + + ALU_INIT : out bit; + ALU_BSY : in bit; + ALU_REQ : in bit; + ALU_ACK : out bit; + + BKPT_CYCLE : out bit; + BKPT_INSERT : out bit; + + LOOP_BSY : in bit; + LOOP_SPLIT : out boolean; + LOOP_EXIT : out bit; + + BF_OFFSET : in Std_Logic_Vector(2 downto 0); + BF_WIDTH : in Std_Logic_Vector(5 downto 0); + + SR_WR : out bit; + MOVEM_ADn : out bit; + MOVEP_PNTR : out integer range 0 to 3; + CC_UPDT : out bit; + TRACE_MODE : in std_logic_vector(1 downto 0); + VBIT : in std_logic; + ALU_COND : in boolean; + DBcc_COND : in boolean; + BRANCH_ATN : in bit; + RESET_STRB : out bit; + BERR : out bit; + STATUSn : out bit; + EX_TRACE : out bit; + TRAP_cc : out bit; + TRAP_ILLEGAL : out bit; -- Used for BKPT. + TRAP_V : out bit + ); +end entity WF68K30L_CONTROL; + +architecture BEHAVIOUR of WF68K30L_CONTROL is +type BF_BYTEMATRIX is array (0 to 7, 1 to 32) of integer range 1 to 5; +-- The BF_BYTES constant selects the number of bytes required for read +-- or write during the bit field operations. This table is valid for +-- positive and negative offsets when using the twos complement in +-- the offset field. +constant BF_BYTES_I : BF_BYTEMATRIX := + ((1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4), + (1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,5), + (1,1,1,1,1,1,2,2,2,2,2,2,2,2,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,5,5), + (1,1,1,1,1,2,2,2,2,2,2,2,2,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5), + (1,1,1,1,2,2,2,2,2,2,2,2,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5), + (1,1,1,2,2,2,2,2,2,2,2,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,5), + (1,1,2,2,2,2,2,2,2,2,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,5,5), + (1,2,2,2,2,2,2,2,2,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5)); +-- +type FETCH_STATES is (START_OP, CALC_AEFF, FETCH_DISPL, FETCH_EXWORD_1, FETCH_D_LO, FETCH_D_HI, FETCH_OD_HI, FETCH_OD_LO, FETCH_ABS_HI, + FETCH_ABS_LO, FETCH_IDATA_B2, FETCH_IDATA_B1, FETCH_MEMADR, FETCH_OPERAND, INIT_EXEC_WB, SLEEP, SWITCH_STATE); +type EXEC_WB_STATES is (IDLE, EXECUTE, ADR_PIPELINE, WRITEBACK, WRITE_DEST); +signal FETCH_STATE : FETCH_STATES; +signal NEXT_FETCH_STATE : FETCH_STATES; +signal EXEC_WB_STATE : EXEC_WB_STATES; +signal NEXT_EXEC_WB_STATE : EXEC_WB_STATES; +signal ADR_MARK_USED_I : bit; +signal ADR_MODE_I : std_logic_vector(2 downto 0); +signal ALU_INIT_I : bit; +signal ALU_TRIG : bit; +signal AR_DEC_I : bit; +signal AR_WR_I : bit; +signal AR_WR_II : bit; +signal BF_BYTES : integer range 0 to 5; +signal BF_HILOn : bit; +signal BF_OFFSET_I : integer range 0 to 7; +signal BF_WIDTH_I : integer range 1 to 32; +signal BIW_0_WB : std_logic_vector(11 downto 0); +signal BIW_1_WB : std_logic_vector(15 downto 0); +signal DATA_RD_I : bit; +signal DATA_WR_I : bit; +signal EW_RDY : bit; +signal INIT_ENTRY : bit; +signal IPIPE_FLUSH_I : bit; +signal LOOP_EXIT_I : bit; +signal MEM_INDIRECT : bit; +signal MEMADR_RDY : bit; +signal MOVEM_ADn_I : bit; +signal MOVEM_ADn_WB : bit; +signal MOVEM_COND : boolean; +signal MOVEM_FIRST_RD : boolean; +signal MOVEM_INH_WR : boolean; +signal MOVEM_LAST_WR : boolean; +signal MOVEM_PNTR : std_logic_vector(3 downto 0); +signal MOVEP_PNTR_I : integer range 0 to 3; +signal OD_REQ_16 : std_logic; +signal OD_REQ_32 : std_logic; +signal OP_SIZE_I : OP_SIZETYPE; +signal OP_WB_I : OP_68K := UNIMPLEMENTED; +signal OW_RDY : bit; +signal PC_ADD_DISPL_I : bit; +signal PC_LOAD_I : bit; +signal PHASE2 : boolean; +signal RD_RDY : bit; +signal READ_CYCLE : bit; +signal SBIT_I : bit; +signal SR_WR_I : bit; +signal UPDT_CC : bit; +signal WR_RDY : bit; +signal WRITE_CYCLE : bit; +-- Debugging: +signal OP_TEST : bit; +begin + BUSY <= '1' when OPD_ACK = '1' else -- Early indication. + '1' when OW_RDY = '1' and OP /= ILLEGAL and OP /= RTE and OP /= TRAP and OP /= UNIMPLEMENTED else -- In progress MAIN is now busy. + '1' when LOOP_BSY = '1' else -- Finish the DBcc loop. + '1' when ALU_BSY = '1' else -- Busy, wait. + '1' when FETCH_STATE /= START_OP else '0'; -- Main controller is busy. + + -- The interrupt must not be activated when the controller is in its START_OP + -- state and fetches new OPWORDS. so we define the trigger for the interrupt + -- in the end of the FETCH phase. The SLEEP state is important for STOP. + INT_TRIG <= '1' when FETCH_STATE = INIT_EXEC_WB or FETCH_STATE = SLEEP else '0'; + + OW_REQ <= '0' when BUSY_EXH = '1' else + '0' when EXH_REQ = '1' and LOOP_BSY = '0' else -- Non interrupt exception requests, loop has priority. + '0' when OPD_ACK = '1' or OW_RDY = '1' else + '1' when NO_PIPELINE = true and FETCH_STATE = START_OP and ALU_BSY = '0' else + '1' when NO_PIPELINE = false and FETCH_STATE = START_OP else '0'; + + DATA_AVAILABLE: process + -- These flip flops store the information whether the data required in the different + -- states is available or not. This is necessary in case of delayed cycles for + -- example if the required address register is not ready to be read. + begin + wait until CLK = '1' and CLK' event; + if RESET_CPU = '1' then + OW_RDY <= '0'; + elsif FETCH_STATE = START_OP and NEXT_FETCH_STATE /= START_OP then + OW_RDY <= '0'; -- Reset. + elsif FETCH_STATE = START_OP and (OP = ILLEGAL or OP = RTE or OP = TRAP or OP = UNIMPLEMENTED) and BUSY_EXH = '1' then + OW_RDY <= '0'; -- Done. + elsif OPD_ACK = '1' then + OW_RDY <= '1'; -- Set. + end if; + + if FETCH_STATE = START_OP then + EW_RDY <= '0'; + elsif FETCH_STATE = FETCH_DISPL and NEXT_FETCH_STATE /= FETCH_DISPL then + EW_RDY <= '0'; + elsif FETCH_STATE = FETCH_EXWORD_1 and NEXT_FETCH_STATE /= FETCH_EXWORD_1 then + EW_RDY <= '0'; + elsif FETCH_STATE = FETCH_D_LO and NEXT_FETCH_STATE /= FETCH_D_LO then + EW_RDY <= '0'; + elsif FETCH_STATE = FETCH_IDATA_B1 and NEXT_FETCH_STATE /= FETCH_IDATA_B1 then + EW_RDY <= '0'; + elsif (FETCH_STATE = FETCH_DISPL or FETCH_STATE = FETCH_EXWORD_1 or FETCH_STATE = FETCH_IDATA_B1 or FETCH_STATE = FETCH_D_LO) and EW_ACK = '1' then + EW_RDY <= '1'; + end if; + + if FETCH_STATE = START_OP then + MEMADR_RDY <= '0'; + elsif FETCH_STATE = FETCH_MEMADR and NEXT_FETCH_STATE /= FETCH_MEMADR then + MEMADR_RDY <= '0'; + elsif FETCH_STATE = FETCH_MEMADR and DATA_RDY = '1' then + MEMADR_RDY <= '1'; + end if; + end process DATA_AVAILABLE; + + EW_REQ <= '0' when EW_ACK = '1' or EW_RDY = '1' else + '1' when FETCH_STATE = FETCH_DISPL or FETCH_STATE = FETCH_EXWORD_1 else + '1' when FETCH_STATE = FETCH_D_HI or FETCH_STATE = FETCH_D_LO else + '1' when FETCH_STATE = FETCH_OD_HI or FETCH_STATE = FETCH_OD_LO else + '1' when FETCH_STATE = FETCH_ABS_HI or FETCH_STATE = FETCH_ABS_LO else + '1' when FETCH_STATE = FETCH_IDATA_B2 or FETCH_STATE = FETCH_IDATA_B1 else + '1' when FETCH_STATE /= FETCH_DISPL and NEXT_FETCH_STATE = FETCH_DISPL else + '1' when FETCH_STATE /= FETCH_EXWORD_1 and NEXT_FETCH_STATE = FETCH_EXWORD_1 else + '1' when FETCH_STATE /= FETCH_D_HI and NEXT_FETCH_STATE = FETCH_D_HI else + '1' when FETCH_STATE /= FETCH_D_LO and NEXT_FETCH_STATE = FETCH_D_LO else + '1' when FETCH_STATE /= FETCH_OD_HI and NEXT_FETCH_STATE = FETCH_OD_HI else + '1' when FETCH_STATE /= FETCH_OD_LO and NEXT_FETCH_STATE = FETCH_OD_LO else + '1' when FETCH_STATE /= FETCH_ABS_HI and NEXT_FETCH_STATE = FETCH_ABS_HI else + '1' when FETCH_STATE /= FETCH_ABS_LO and NEXT_FETCH_STATE = FETCH_ABS_LO else + '1' when FETCH_STATE /= FETCH_IDATA_B2 and NEXT_FETCH_STATE = FETCH_IDATA_B2 else + '1' when FETCH_STATE /= FETCH_IDATA_B1 and NEXT_FETCH_STATE = FETCH_IDATA_B1 else '0'; + + CYCLECONTROL: process + -- This process contros the read and write signals, if + -- asserted simultaneously. In this way, a read cycle is + -- not interrupted by a write cycle and vice versa. + begin + wait until CLK = '1' and CLK' event; + if DATA_RDY = '1' then + WRITE_CYCLE <= '0'; + READ_CYCLE <= '0'; + elsif DATA_WR_I = '1' then + WRITE_CYCLE <= '1'; + READ_CYCLE <= '0'; + elsif DATA_RD_I = '1' then + READ_CYCLE <= '1'; + WRITE_CYCLE <= '0'; + end if; + end process CYCLECONTROL; + + RD_RDY <= DATA_RDY when READ_CYCLE = '1' else '0'; + WR_RDY <= DATA_RDY when WRITE_CYCLE = '1' else '0'; + + INIT_ENTRY <= '1' when FETCH_STATE /= INIT_EXEC_WB and NEXT_FETCH_STATE = INIT_EXEC_WB else '0'; + + DATA_RD <= DATA_RD_I; + DATA_RD_I <= '0' when DATA_WR_I = '1' and READ_CYCLE = '0' and WRITE_CYCLE = '0' else -- Write is prioritized. + '0' when WRITE_CYCLE = '1' else -- Do not read during a write cycle. + '0' when ADR_IN_USE = '1' else -- Avoid data hazards. + '0' when DATA_RDY = '1' or MEMADR_RDY = '1' else + '1' when FETCH_STATE = FETCH_MEMADR else + '1' when FETCH_STATE = FETCH_OPERAND else '0'; + + DATA_WR <= DATA_WR_I; + DATA_WR_I <= '0' when READ_CYCLE = '1' else -- Do not write during a read cycle. + '0' when DATA_RDY = '1' else + '1' when EXEC_WB_STATE = WRITE_DEST else '0'; + + RMC <= '1' when (OP = CAS or OP = CAS2 or OP = TAS) and FETCH_STATE /= START_OP else '0'; + + ALU_ACK <= '1' when EXEC_WB_STATE = EXECUTE and NEXT_EXEC_WB_STATE = IDLE else + '1' when EXEC_WB_STATE = WRITEBACK else + '0' when (OP_WB_I = BFCHG or OP_WB_I = BFCLR) and EXEC_WB_STATE = WRITE_DEST and BF_BYTES = 5 else + '0' when (OP_WB_I = BFINS or OP_WB_I = BFSET) and EXEC_WB_STATE = WRITE_DEST and BF_BYTES = 5 else + '1' when EXEC_WB_STATE = WRITE_DEST and WR_RDY = '1' else '0'; + + FETCH_MEM_ADR <= '1' when FETCH_STATE = FETCH_MEMADR else '0'; + STORE_MEM_ADR <= '1' when FETCH_STATE = FETCH_MEMADR and RD_RDY = '1' and DATA_VALID = '1' else '0'; + + -- Store the extension word right in the end due to used data and/or address registers. + STORE_ADR_FORMAT <= '1' when FETCH_STATE = FETCH_EXWORD_1 and NEXT_FETCH_STATE /= FETCH_EXWORD_1 else '0'; + + STORE_D16 <= '1' when FETCH_STATE = FETCH_DISPL and EW_ACK = '1' else '0'; + STORE_D32_LO <= '1' when FETCH_STATE = FETCH_D_LO and EW_ACK = '1' else '0'; + STORE_D32_HI <= '1' when FETCH_STATE = FETCH_D_HI and EW_ACK = '1' else '0'; + + STORE_DISPL <= '1' when OP = MOVEP and FETCH_STATE = START_OP and NEXT_FETCH_STATE /= START_OP and BIW_0(7 downto 6) < "10" else -- Memory to register. + '1' when OP = MOVEP and FETCH_STATE = SWITCH_STATE else '0'; -- Register to memory. + + STORE_OD_HI <= '1' when FETCH_STATE = FETCH_OD_HI and EW_ACK = '1' else '0'; + STORE_OD_LO <= '1' when FETCH_STATE = FETCH_OD_LO and EW_ACK = '1' else '0'; + + STORE_ABS_HI <= '1' when FETCH_STATE = FETCH_ABS_HI and EW_ACK = '1' else '0'; + STORE_ABS_LO <= '1' when FETCH_STATE = FETCH_ABS_LO and EW_ACK = '1' else '0'; + + STORE_IDATA_B2 <= '1' when FETCH_STATE = FETCH_IDATA_B2 and EW_ACK = '1' else '0'; + STORE_IDATA_B1 <= '1' when FETCH_STATE = FETCH_IDATA_B1 and EW_ACK = '1' else '0'; + + LOAD_OP1 <= '1' when OP = BFINS and INIT_ENTRY = '1' else -- Load insertion pattern. + '1' when (OP = CHK2 or OP = CMP2) and FETCH_STATE = FETCH_OPERAND and RD_RDY = '1' and DATA_VALID = '1' and PHASE2 = false else + '1' when OP = CMPM and FETCH_STATE = FETCH_OPERAND and RD_RDY = '1' and DATA_VALID = '1' and PHASE2 = true else + '1' when OP = MOVE and BIW_0(8 downto 6) = "100" and BIW_0(5 downto 3) = "001" and BIW_0(11 downto 9) = BIW_0(2 downto 0) and INIT_ENTRY = '1' else -- Load early to write the undecremented Register for Ax, -(Ax). + '1' when OP = MOVES and FETCH_STATE = START_OP and NEXT_FETCH_STATE /= START_OP and ADR_MODE_I = "100" and BIW_1(15) = '1' and BIW_1(11) = '1' and BIW_1(14 downto 12) = BIW_0(2 downto 0) else -- Load the adressing register before decrementing. + '1' when OP = PEA and FETCH_STATE = SWITCH_STATE and PHASE2 = true else -- Load early not to stack the decremented value. + '0' when OP = BFINS or OP = CHK2 or OP = CMP2 or OP = CMPM or OP = PEA else + '0' when OP = MOVE and BIW_0(8 downto 6) = "100" and BIW_0(5 downto 3) = "001" and BIW_0(11 downto 9) = BIW_0(2 downto 0) else + '0' when OP = MOVES and ADR_MODE_I = "100" and BIW_1(15) = '1' and BIW_1(11) = '1' and BIW_1(14 downto 12) = BIW_0(2 downto 0) else -- Do not load the decremented addressing register. + '0' when OP = PEA and ADR_MODE_I = "001" and BIW_0(2 downto 0) = "111" else + '1' when ALU_INIT_I = '1' else '0'; + + LOAD_OP2 <= '1' when (OP = ABCD or OP = SBCD) and FETCH_STATE = FETCH_OPERAND and RD_RDY = '1' and DATA_VALID = '1' and PHASE2 = false else + '1' when (OP = ADDX or OP = SUBX) and FETCH_STATE = FETCH_OPERAND and RD_RDY = '1' and DATA_VALID = '1' and PHASE2 = false else + '1' when (OP = ABCD or OP = SBCD) and FETCH_STATE = INIT_EXEC_WB and BIW_0(3) = '0' else -- Register direct. + '1' when (OP = ADDX or OP = SUBX) and FETCH_STATE = INIT_EXEC_WB and BIW_0(3) = '0' else -- Register direct. + '1' when (OP = BFCHG or OP = BFCLR) and FETCH_STATE = FETCH_OPERAND and RD_RDY = '1' and DATA_VALID = '1' and BF_HILOn = '0' else + '1' when (OP = BFINS or OP = BFSET) and FETCH_STATE = FETCH_OPERAND and RD_RDY = '1' and DATA_VALID = '1' and BF_HILOn = '0' else + '1' when (OP = BFEXTS or OP = BFEXTU) and FETCH_STATE = FETCH_OPERAND and RD_RDY = '1' and DATA_VALID = '1' and BF_HILOn = '0' else + '1' when (OP = BFFFO or OP = BFTST) and FETCH_STATE = FETCH_OPERAND and RD_RDY = '1' and DATA_VALID = '1' and BF_HILOn = '0' else + '1' when OP = CMPM and FETCH_STATE = FETCH_OPERAND and RD_RDY = '1' and DATA_VALID = '1' and PHASE2 = false else + '1' when OP = LINK and BIW_0(2 downto 0) = "111" and FETCH_STATE = START_OP and NEXT_FETCH_STATE /= START_OP else -- Load early not to stack the decremented address register. + '0' when OP = ABCD or OP = SBCD or OP = ADDX or OP = SUBX or OP = CMPM else + '0' when OP = BFCHG or OP = BFCLR or OP = BFEXTS or OP = BFEXTU or OP = BFFFO or OP = BFINS or OP = BFSET or OP = BFTST else + '0' when OP = LINK and BIW_0(2 downto 0) = "111" else + '1' when INIT_ENTRY = '1' else '0'; + + LOAD_OP3 <= '1' when (OP = BFCHG or OP = BFCLR or OP = BFINS or OP = BFSET) and BIW_0(5 downto 3) = "000" and INIT_ENTRY = '1' else + '1' when (OP = BFEXTS or OP = BFEXTU or OP = BFFFO or OP = BFTST) and BIW_0(5 downto 3) = "000" and INIT_ENTRY = '1' else + '1' when (OP = BFCHG or OP = BFCLR) and FETCH_STATE = FETCH_OPERAND and RD_RDY = '1' and DATA_VALID = '1' and BF_HILOn = '1' else + '1' when (OP = BFINS or OP = BSET) and FETCH_STATE = FETCH_OPERAND and RD_RDY = '1' and DATA_VALID = '1' and BF_HILOn = '1' else + '1' when (OP = BFEXTS or OP = BFEXTU) and FETCH_STATE = FETCH_OPERAND and RD_RDY = '1' and DATA_VALID = '1' and BF_HILOn = '1' else + '1' when (OP = BFFFO or OP = BFTST) and FETCH_STATE = FETCH_OPERAND and RD_RDY = '1' and DATA_VALID = '1' and BF_HILOn = '1' else + '1' when OP = CAS2 and INIT_ENTRY = '1' and PHASE2 = false else -- Memory operand 2. + '1' when (OP = CHK2 or OP = CMP2) and FETCH_STATE = FETCH_OPERAND and RD_RDY = '1' and DATA_VALID = '1' and PHASE2 = true else + '1' when (OP = DIVS or OP = DIVU) and OP_SIZE_I = LONG and BIW_1(10) = '1' and INIT_ENTRY = '1' else '0'; -- 64 bit operand. + + SR_WR <= SR_WR_I; + SR_WR_I <= '1' when (OP_WB_I = ANDI_TO_SR or OP_WB_I = EORI_TO_SR or OP_WB_I = ORI_TO_SR) and EXEC_WB_STATE = WRITEBACK else + '1' when (OP_WB_I = MOVE_TO_CCR or OP_WB_I = MOVE_TO_SR) and EXEC_WB_STATE = WRITEBACK else + '1' when OP_WB_I = STOP and EXEC_WB_STATE = WRITEBACK else '0'; + + HILOn <= '1' when OP_WB_I = CAS2 and FETCH_STATE = FETCH_OPERAND and PHASE2 = false else + '1' when OP_WB_I = CAS2 and EXEC_WB_STATE = WRITEBACK and PHASE2 = false else + '0' when OP = CAS2 else BF_HILOn; -- Select destinations. + + -- Addressing mode: + ADR_MODE <= ADR_MODE_I; + ADR_MODE_I <= "010" when OP = BSR or OP = CAS2 or OP = LINK or OP = UNLK else -- (An), (Dn). + "010" when OP = RTD or OP = RTR or OP = RTS else -- (An). + "011" when OP = CMPM else -- (An)+ + "100" when OP = ABCD or OP = SBCD else -- -(An). + "100" when OP = ADDX or OP = SUBX else -- -(An). + "100" when OP = PACK or OP = UNPK else -- -(An). + "101" when OP = MOVEP else -- (d16, An). + -- The following two conditions change the address mode right in the end of the fetch phase. + "010" when (OP = JSR or OP = PEA) and FETCH_STATE = INIT_EXEC_WB and ALU_BSY = '0' else -- (A7). + BIW_0(8 downto 6) when OP = MOVE and FETCH_STATE = INIT_EXEC_WB and ALU_BSY = '0' else + BIW_0(8 downto 6) when OP = MOVE and PHASE2 = true else + BIW_0(5 downto 3); + + -- This is the selector for the address mode "111". + AMODE_SEL <= BIW_0(11 downto 9) when OP = MOVE and (NEXT_FETCH_STATE = INIT_EXEC_WB or FETCH_STATE = INIT_EXEC_WB) else + BIW_0(11 downto 9) when OP = MOVE and PHASE2 = true else BIW_0(2 downto 0); + + -- Used for the addressing modes and as source selector. + -- In case of the addressing modes, the selector mus be valid one clock cycle before the bus cycle + -- starts due to the pipeline stage for ADR_REG in the address register section. + AR_SEL_RD_1 <= BIW_0(11 downto 9) when (OP = ABCD or OP = SBCD) and FETCH_STATE = START_OP else + BIW_0(11 downto 9) when (OP = ABCD or OP = SBCD) and FETCH_STATE = CALC_AEFF and PHASE2 = false else + BIW_0(11 downto 9) when (OP = ABCD or OP = SBCD) and FETCH_STATE = FETCH_OPERAND and PHASE2 = false and RD_RDY = '0' else -- Destination first. + BIW_0(11 downto 9) when (OP = ABCD or OP = SBCD) and FETCH_STATE = INIT_EXEC_WB else + BIW_0(11 downto 9) when (OP = ADDX or OP = SUBX) and FETCH_STATE = START_OP else + BIW_0(11 downto 9) when (OP = ADDX or OP = SUBX) and FETCH_STATE = CALC_AEFF and PHASE2 = false else + BIW_0(11 downto 9) when (OP = ADDX or OP = SUBX) and FETCH_STATE = FETCH_OPERAND and PHASE2 = false and RD_RDY = '0' else -- Destination first. + BIW_0(11 downto 9) when (OP = ADDX or OP = SUBX) and FETCH_STATE = INIT_EXEC_WB else + BIW_0(11 downto 9) when OP = CMPM and FETCH_STATE = FETCH_OPERAND and PHASE2 = false else -- Fetch destination. + BIW_0(11 downto 9) when OP = MOVE and FETCH_STATE = FETCH_MEMADR and PHASE2 = true else + BIW_0(11 downto 9) when OP = MOVE and FETCH_STATE = START_OP and BIW_0(5 downto 3) < "010" and BIW_0(8 downto 6) /= "000" else -- Dn, An. + BIW_0(11 downto 9) when OP = MOVE and FETCH_STATE = CALC_AEFF and PHASE2 = true else + BIW_0(11 downto 9) when OP = MOVE and FETCH_STATE = FETCH_OPERAND and RD_RDY = '1' and BIW_0(8 downto 6) = "100" and BIW_0(5 downto 3) /= "011" else -- All except (An)+,-(An). + BIW_0(11 downto 9) when OP = MOVE and FETCH_STATE = FETCH_IDATA_B1 and BIW_0(8 downto 6) /= "000" else + BIW_0(11 downto 9) when OP = MOVE and FETCH_STATE = FETCH_ABS_LO and BIW_0(8 downto 6) /= "000" and PHASE2 = false else + BIW_0(11 downto 9) when OP = MOVE and FETCH_STATE = SWITCH_STATE and BIW_0(8 downto 6) /= "000" else + BIW_0(11 downto 9) when OP = MOVE and FETCH_STATE = INIT_EXEC_WB and BIW_0(8 downto 6) /= "000" else + BIW_1(14 downto 12) when OP = MOVEC and BIW_0(0) = '1' else -- MOVEC: general register to control register. + "111" when OP = BSR or OP = MOVEC else -- Stack pointers. + BIW_0(11 downto 9) when (OP = PACK or OP = UNPK) and FETCH_STATE = START_OP and BIW_0(3) = '0' and DR_IN_USE = '0' else -- Destination address. + BIW_0(11 downto 9) when (OP = PACK or OP = UNPK) and FETCH_STATE = FETCH_OPERAND and RD_RDY = '1' else -- Destination address. + BIW_0(11 downto 9) when (OP = PACK or OP = UNPK) and FETCH_STATE = INIT_EXEC_WB else -- Destination address. + BIW_1(14 downto 12) when OP = CAS2 and FETCH_STATE = START_OP else -- Address operand. + BIW_1(14 downto 12) when OP = CAS2 and FETCH_STATE = FETCH_OPERAND and PHASE2 = false else -- Address operand. + BIW_2(14 downto 12) when OP = CAS2 and FETCH_STATE = CALC_AEFF else -- Address operand. + BIW_2(14 downto 12) when OP = CAS2 and FETCH_STATE = FETCH_OPERAND else -- Address operand. + BIW_1(14 downto 12) when OP_WB_I = CAS2 and (EXEC_WB_STATE = EXECUTE or EXEC_WB_STATE = ADR_PIPELINE) else -- Address operand. + BIW_2(14 downto 12) when OP_WB_I = CAS2 and EXEC_WB_STATE = WRITE_DEST else -- Address operand. + "111" when (OP = JSR or OP = LINK) and FETCH_STATE = START_OP else -- Select the SP to decrement. + "111" when OP = PEA and FETCH_STATE = SWITCH_STATE and PHASE2 = true else -- Select the SP to decrement. + "111" when (OP = JSR or OP = LINK or OP = PEA) and FETCH_STATE = INIT_EXEC_WB else -- Writeback address is the SP. + "111" when OP = RTD or OP = RTR or OP = RTS else -- Stack pointer. + "111" when OP = UNLK and (FETCH_STATE = START_OP or FETCH_STATE = CALC_AEFF or FETCH_STATE = FETCH_OPERAND) else -- Check in START_OP to avoid dataz hazards! + BIW_0(2 downto 0) when OP = ABCD or OP = ADD or OP = ADDA or OP = ADDI or OP = ADDQ or OP = ADDX or OP = AND_B or OP = ANDI else + BIW_0(2 downto 0) when OP = ASL or OP = ASR or OP = BCHG or OP = BCLR or OP = BSET or OP = BTST or OP = BFCHG or OP = BFCLR else + BIW_0(2 downto 0) when OP = BFEXTS or OP = BFEXTU or OP = BFFFO or OP = BFINS or OP = BFSET or OP = BFTST else + BIW_0(2 downto 0) when OP = CAS or OP = CHK or OP = CHK2 or OP = CLR or OP = CMP or OP = CMPA or OP = CMPI or OP = CMPM or OP = CMP2 else + BIW_0(2 downto 0) when OP = DIVS or OP = DIVU or OP = EOR or OP = EORI or OP = EXG or OP = JMP or OP = JSR or OP = LEA or OP = LINK or OP = LSL or OP = LSR else + BIW_0(2 downto 0) when OP = MOVE or OP = MOVEA or OP = MOVE_FROM_CCR or OP = MOVE_FROM_SR or OP = MOVE_TO_CCR or OP = MOVE_TO_SR else + BIW_0(2 downto 0) when OP = MOVE_USP or OP = MOVEM or OP = MOVEP or OP = MOVES or OP = MULS or OP = MULU else + BIW_0(2 downto 0) when OP = NBCD or OP = NEG or OP = NEGX or OP = NOT_B or OP = OR_B or OP = ORI or OP = PACK or OP = PEA else + BIW_0(2 downto 0) when OP = ROTL or OP = ROTR or OP = ROXL or OP = ROXR or OP = SBCD or OP = Scc or OP = SUB or OP = SUBA else + BIW_0(2 downto 0) when OP = SUBI or OP = SUBQ or OP = SUBX or OP = TAS or OP = TST or OP = UNLK or OP = UNPK else "000"; + + -- Always the destination. + AR_SEL_WR_1 <= BIW_0(2 downto 0) when OP = ADDQ or OP = SUBQ else + BIW_0(2 downto 0) when OP = EXG and BIW_0(7 downto 3) = "10001" else -- Data and Address register. + BIW_1(14 downto 12) when OP = MOVEC or OP = MOVES else + "111" when OP = UNLK and FETCH_STATE = START_OP else + BIW_0(2 downto 0) when OP = LINK else + MOVEM_PNTR(2 downto 0) when OP = MOVEM else + BIW_0(2 downto 0) when OP = MOVE_USP else + BIW_0(11 downto 9); -- ADDA, EXG, LEA, MOVE, MOVEA, SUBA. + + AR_WR_1 <= AR_WR_I; + AR_WR_I <= '1' when OP = LINK and FETCH_STATE = INIT_EXEC_WB and ALU_BSY = '0' else + '1' when OP = UNLK and FETCH_STATE = SWITCH_STATE and NEXT_FETCH_STATE /= SWITCH_STATE else -- Write An to SP. + '0' when EXEC_WB_STATE /= WRITEBACK else + '1' when OP_WB_I = ADDA or OP_WB_I = SUBA else + '1' when (OP_WB_I = ADDQ or OP_WB_I = SUBQ) and BIW_0_WB(5 downto 3) = "001" else + '1' when OP_WB_I = EXG and BIW_0_WB(7 downto 3) = "01001" else -- Two address registers. + '1' when OP_WB_I = EXG and BIW_0_WB(7 downto 3) = "10001" else -- Data and Address register. + '1' when OP_WB_I = LEA else + '1' when OP_WB_I = MOVE_USP and BIW_0_WB(3) = '1' else + '1' when OP_WB_I = MOVEA else + '1' when OP_WB_I = MOVEC and BIW_1_WB(15) = '1' and BIW_0_WB(0) = '0' else -- To general register. + '1' when OP_WB_I = MOVES and BIW_1_WB(15) = '1' else + '1' when OP_WB_I = MOVEM and MOVEM_ADn_WB = '1' else '0'; + + AR_SEL_RD_2 <= BIW_1(14 downto 12) when OP = CHK2 or OP = CMP2 else + MOVEM_PNTR(2 downto 0) when OP = MOVEM else -- This is the non addressing output. + BIW_1(14 downto 12) when OP = MOVES else + BIW_0(2 downto 0) when OP = ADDQ or OP = MOVE or OP = SUBQ or OP = TST else + BIW_0(2 downto 0) when OP = EXG and BIW_0(7 downto 3) = "10001" else -- Data and address register. + BIW_0(11 downto 9) when OP = ADDA or OP = CMPA or OP = EXG or OP = SUBA else "000"; + + AR_SEL_WR_2 <= BIW_0(2 downto 0); -- Used for EXG, UNLK. + + AR_WR_2 <= AR_WR_II; + AR_WR_II <= '1' when OP_WB_I = UNLK and EXEC_WB_STATE = WRITEBACK else -- Write (SP) to An. + '1' when OP_WB_I = EXG and EXEC_WB_STATE = WRITEBACK and BIW_0_WB(7 downto 3) = "01001" else '0'; -- Two address registers. + + AR_INC <= '1' when (OP = ADD or OP = CMP or OP = SUB) and ADR_MODE_I = "011" and ALU_INIT_I = '1' else + '1' when (OP = ADDA or OP = CMPA or OP = SUBA) and ADR_MODE_I = "011" and FETCH_STATE = FETCH_OPERAND and DATA_RDY = '1' else + '1' when (OP = ADDI or OP = CMPI or OP = SUBI) and ADR_MODE_I = "011" and ALU_INIT_I = '1' else + '1' when (OP = ADDQ or OP = SUBQ) and ADR_MODE_I = "011" and ALU_INIT_I = '1' else + '1' when (OP = AND_B or OP = EOR or OP = OR_B) and ADR_MODE_I = "011" and ALU_INIT_I = '1' else + '1' when (OP = ANDI or OP = EORI or OP = ORI) and ADR_MODE_I = "011" and ALU_INIT_I = '1' else + '1' when (OP = ASL or OP = ASR or OP = LSL or OP = LSR) and BIW_0(7 downto 3) = "11011" and ALU_INIT_I = '1' else + '1' when (OP = ROTL or OP = ROTR or OP = ROXL or OP = ROXR) and BIW_0(7 downto 3) = "11011" and ALU_INIT_I = '1' else + '1' when (OP = BCHG or OP = BCLR or OP = BSET or OP = BTST) and ADR_MODE_I = "011" and ALU_INIT_I = '1' else + '1' when (OP = CAS or OP = TAS) and ADR_MODE_I = "011" and FETCH_STATE = INIT_EXEC_WB and NEXT_FETCH_STATE /= INIT_EXEC_WB else + '1' when (OP = CHK or OP = CLR or OP = TST or OP = Scc) and ADR_MODE_I = "011" and ALU_INIT_I = '1' else + '1' when (OP = NBCD or OP = NEG or OP = NEGX or OP = NOT_B) and ADR_MODE_I = "011" and ALU_INIT_I = '1' else + '1' when OP = CMPM and FETCH_STATE = FETCH_OPERAND and RD_RDY = '1' and DATA_VALID = '1' else + '1' when (OP = MULS or OP = MULU or OP = DIVS or OP = DIVU) and ADR_MODE_I = "011" and ALU_INIT_I = '1' else + '1' when (OP = MOVE_FROM_CCR or OP = MOVE_FROM_SR) and ADR_MODE_I = "011" and FETCH_STATE = INIT_EXEC_WB and NEXT_FETCH_STATE /= INIT_EXEC_WB else + '1' when (OP = MOVE_TO_CCR or OP = MOVE_TO_SR) and ADR_MODE_I = "011" and FETCH_STATE = INIT_EXEC_WB and NEXT_FETCH_STATE /= INIT_EXEC_WB else + '1' when OP = MOVE and ADR_MODE_I = "011" and FETCH_STATE = FETCH_OPERAND and NEXT_FETCH_STATE /= FETCH_OPERAND else + '1' when OP = MOVE and BIW_0(8 downto 6) = "011" and FETCH_STATE = INIT_EXEC_WB and NEXT_FETCH_STATE /= INIT_EXEC_WB else + '1' when OP = MOVEA and ADR_MODE_I = "011" and FETCH_STATE = INIT_EXEC_WB and NEXT_FETCH_STATE /= INIT_EXEC_WB else + '1' when OP = MOVEM and ADR_MODE_I = "011" and ALU_INIT_I = '1' else + '1' when OP = MOVES and ADR_MODE_I = "011" and ALU_INIT_I = '1' else + '1' when (OP = UNLK or OP = RTD or OP = RTR or OP = RTS) and FETCH_STATE = FETCH_OPERAND and RD_RDY = '1' and DATA_VALID = '1' else '0'; + + with OP select + AR_DEC_I <= '1' when ABCD | ADD | ADDA | ADDI | ADDQ | ADDX | AND_B | ANDI | ASL | ASR | BCHG | BCLR | BSET | BTST | CHK | CMP | CMPA | CMPI | + DIVS | DIVU | EOR | EORI | LSL | LSR | MOVE | MOVEA | MOVE_TO_CCR | MOVE_TO_SR | MOVES | MULS | MULU | NBCD | NEG | NEGX | + NOT_B | OR_B | ORI | ROTL | ROTR | ROXL | ROXR | SBCD | SUB | SUBA | SUBI | SUBQ | SUBX | TAS | TST, '0' when others; + + AR_DEC <= AR_DEC_I when ADR_MODE_I = "100" and FETCH_STATE /= CALC_AEFF and NEXT_FETCH_STATE = CALC_AEFF else + '1' when (OP = BSR or OP = JSR or OP = LINK) and FETCH_STATE = START_OP and NEXT_FETCH_STATE /= START_OP else + '1' when (OP = CLR or OP = Scc) and ADR_MODE_I = "100" and INIT_ENTRY = '1' else + '1' when OP = MOVE and BIW_0(8 downto 6) = "100" and BIW_0(5 downto 3) /= "011" and INIT_ENTRY = '1' else -- (An)+, -(An) + '1' when OP = MOVE and BIW_0(8 downto 6) = "100" and FETCH_STATE = SWITCH_STATE else -- Needed for source (An)+ mode. + '1' when OP = MOVEM and ADR_MODE_I = "100" and INIT_ENTRY = '1' else -- Decrement before the first bus access. + '1' when OP = MOVEM and ADR_MODE_I = "100" and ALU_INIT_I = '1' and MOVEM_LAST_WR = false else -- After the last bus access the address register is not decremented. + '1' when (OP = MOVE_FROM_CCR or OP = MOVE_FROM_SR) and ADR_MODE_I = "100" and INIT_ENTRY = '1' else + '1' when OP = MOVES and ADR_MODE_I = "100" and BIW_1(11) = '1' and INIT_ENTRY = '1' else + '1' when (OP = PACK or OP = UNPK) and BIW_0(3) = '1' and INIT_ENTRY = '1' else + -- PEA: decrement late in SWITCH_STATE not to decremented address register for PEA (xx,A7,yy) address modi. + '1' when OP = PEA and FETCH_STATE = SWITCH_STATE and PHASE2 = true else '0'; + + DR_SEL_RD_1 <= EXT_WORD(14 downto 12) when FETCH_STATE = FETCH_EXWORD_1 else -- Index register + BIW_0(11 downto 9) when (OP = ADD or OP = SUB) and BIW_0(8) = '1' else + BIW_0(11 downto 9) when (OP = AND_B or OP = EOR or OP = OR_B) and BIW_0(8) = '1' else + BIW_0(11 downto 9) when OP = BCHG or OP = BCLR or OP = BSET or OP = BTST else + BIW_0(11 downto 9) when OP = ASL or OP = ASR or OP = LSL or OP = LSR else + BIW_0(11 downto 9) when OP = ROTL or OP = ROTR or OP = ROXL or OP = ROXR else + BIW_0(2 downto 0) when (OP = BFCHG or OP = BFCLR or OP = BFEXTS or OP = BFEXTU) and FETCH_STATE = START_OP and BIW_0(5 downto 3) = "000" else + BIW_0(2 downto 0) when (OP = BFCHG or OP = BFCLR or OP = BFEXTS or OP = BFEXTU) and FETCH_STATE = START_OP and BIW_0(5 downto 3) = "001" else + BIW_0(2 downto 0) when (OP = BFCHG or OP = BFCLR or OP = BFEXTS or OP = BFEXTU) and FETCH_STATE = FETCH_ABS_LO else + BIW_0(2 downto 0) when (OP = BFFFO or OP = BFINS or OP = BFSET or OP = BFTST) and FETCH_STATE = START_OP and BIW_0(5 downto 3) = "000" else + BIW_0(2 downto 0) when (OP = BFFFO or OP = BFINS or OP = BFSET or OP = BFTST) and FETCH_STATE = START_OP and BIW_0(5 downto 3) = "001" else + BIW_0(2 downto 0) when (OP = BFFFO or OP = BFINS or OP = BFSET or OP = BFTST) and FETCH_STATE = FETCH_ABS_LO else + BIW_1(8 downto 6) when (OP = BFCHG or OP = BFCLR or OP = BFEXTS or OP = BFEXTU) else -- Width value. + BIW_1(8 downto 6) when (OP = BFFFO or OP = BFINS or OP = BFSET or OP = BFTST) else -- Width value. + BIW_1(2 downto 0) when OP = CAS else -- Compare operand. + BIW_1(14 downto 12) when OP = CAS2 and FETCH_STATE = START_OP else -- Address operand. + BIW_1(14 downto 12) when OP = CAS2 and FETCH_STATE = FETCH_OPERAND and PHASE2 = false else -- Address operand. + BIW_2(14 downto 12) when OP = CAS2 and FETCH_STATE = CALC_AEFF else -- Address operand. + BIW_2(14 downto 12) when OP = CAS2 and FETCH_STATE = FETCH_OPERAND else -- Address operand. + BIW_1(14 downto 12) when OP_WB_I = CAS2 and BIW_1(15) = '0' and (EXEC_WB_STATE = EXECUTE or EXEC_WB_STATE = ADR_PIPELINE) else -- Address operand. + BIW_2(14 downto 12) when OP_WB_I = CAS2 and BIW_2(15) = '0' and EXEC_WB_STATE = WRITE_DEST else -- Address operand. + BIW_1(2 downto 0) when OP = CAS2 and PHASE2 = false else -- Compare operand. + BIW_2(2 downto 0) when OP = CAS2 else -- Compare operand. + BIW_1(2 downto 0) when (OP = DIVS or OP = DIVU) and FETCH_STATE /= INIT_EXEC_WB and BIW_0(8 downto 6) = "001" else -- LONG 64. + MOVEM_PNTR(2 downto 0) when OP = MOVEM else + BIW_0(11 downto 9) when OP = MOVEP else + BIW_1(14 downto 12) when OP = MOVEC or OP = MOVES else + BIW_0(2 downto 0) when OP = ADD or OP = AND_B or OP = OR_B or OP = SUB else + BIW_0(2 downto 0) when OP = ABCD or OP = ADDA or OP = ADDX or OP = CHK or OP = CMP or OP = CMPA else + BIW_0(11 downto 9) when OP = EXG and BIW_0(7 downto 3) = "10001" else -- Data and address register. + BIW_0(2 downto 0) when OP = DIVS or OP = DIVU or OP = EXG else + BIW_0(2 downto 0) when OP = MOVE or OP = MOVEA or OP = MOVE_TO_CCR or OP = MOVE_TO_SR or OP = MULS or OP = MULU or OP= PACK else + BIW_0(2 downto 0) when OP = SBCD or OP = SUBA or OP = SUBX or OP = UNPK else "000"; + + DR_SEL_WR_1 <= BIW_1(14 downto 12) when OP = BFEXTS or OP = BFEXTU or OP = BFFFO else + BIW_1(14 downto 12) when OP = MOVEC or OP = MOVES else + BIW_0(11 downto 9) when OP = ABCD or OP = SBCD else + BIW_0(11 downto 9) when OP = ADDX or OP = SUBX else + BIW_0(11 downto 9) when OP = ADD or OP = SUB else + BIW_0(11 downto 9) when OP = AND_B or OP = OR_B else + BIW_0(11 downto 9) when (OP = DIVS or OP = DIVU) and OP_SIZE_I = WORD else + BIW_1(14 downto 12) when OP = DIVS or OP = DIVU else + BIW_0(11 downto 9) when (OP = MULS or OP = MULU) and OP_SIZE_I = WORD else + BIW_1(14 downto 12) when OP = MULS or OP = MULU else -- Low order result and operand. + BIW_0(11 downto 9) when OP = EXG else + BIW_0(11 downto 9) when OP = MOVE or OP = MOVEP or OP = MOVEQ else + BIW_0(11 downto 9) when OP = PACK or OP = UNPK else + BIW_1(2 downto 0) when OP = CAS else -- Compare operand. + BIW_1(2 downto 0) when OP_WB_I = CAS2 and EXEC_WB_STATE = EXECUTE else -- Compare operand 1. + BIW_2(2 downto 0) when OP_WB_I = CAS2 and EXEC_WB_STATE = WRITEBACK else -- Compare operand 2. + MOVEM_PNTR(2 downto 0) when OP = MOVEM else + BIW_0(2 downto 0); + + DR_WR_1 <= '1' when OP_WB_I = EXG and EXEC_WB_STATE = WRITEBACK and BIW_0_WB(7 downto 3) = "10001" else -- Address- and data register. + '0' when AR_WR_I = '1' else -- This is the locking AR against DR. + '0' when AR_WR_II = '1' else -- This is the locking AR against DR. + '0' when OP_WB_I = ANDI_TO_SR or OP_WB_I = EORI_TO_SR or OP_WB_I = ORI_TO_SR else + '0' when OP_WB_I = MOVE_TO_CCR or OP_WB_I = MOVE_TO_SR else + '0' when OP_WB_I = MOVE_USP else -- USP is written. + '0' when OP_WB_I = MOVEC and BIW_0_WB(0) = '1' else -- To control register. + '0' when OP_WB_I = STOP else -- SR is written but not DR. + '1' when EXEC_WB_STATE = WRITEBACK else '0'; + + DR_SEL_RD_2 <= BIW_0(11 downto 9) when OP = ABCD or OP = SBCD or OP = ADDX or OP = SUBX else + BIW_0(2 downto 0) when (OP = ADD or OP = AND_B or OP = OR_B or OP = SUB) and BIW_0(8) = '1' else + BIW_0(11 downto 9) when OP = ADD or OP = CMP or OP = SUB or OP = AND_B or OP = OR_B else + BIW_0(11 downto 9) when OP = CHK or OP = EXG else + BIW_1(14 downto 12) when OP = BFINS and FETCH_STATE = START_OP and BIW_0(5 downto 3) = "000" else + BIW_1(14 downto 12) when OP = BFINS and FETCH_STATE = START_OP and BIW_0(5 downto 3) = "001" else + BIW_1(14 downto 12) when OP = BFINS and FETCH_STATE = FETCH_ABS_LO else + BIW_1(8 downto 6) when OP = CAS else -- Update operand. + BIW_1(8 downto 6) when OP = CAS2 and PHASE2 = false else -- Update operand. + BIW_2(8 downto 6) when OP = CAS2 else -- Update operand. + BIW_1(14 downto 12) when OP = CHK2 or OP = CMP2 else + BIW_0(11 downto 9) when (OP = DIVS or OP = DIVU) and BIW_0(7) = '1' else -- WORD size. + BIW_1(14 downto 12) when (OP = DIVS or OP = DIVU) else -- Quotient low portion. + BIW_0(11 downto 9) when (OP = MULS or OP = MULU) and BIW_0(7) = '1' else -- WORD size. + BIW_1(14 downto 12) when (OP = MULS or OP = MULU) else + BIW_0(2 downto 0) when OP = BCHG or OP = BCLR or OP = BSET or OP = BTST else + BIW_0(2 downto 0) when OP = ADDI or OP = ADDQ or OP = ANDI or OP = BCHG or OP = BCLR or OP = BSET or OP = BTST or OP = CMPI else + BIW_0(2 downto 0) when OP = DBcc or OP = EOR or OP = EORI or OP = EXT or OP = EXTB or OP = NBCD or OP = NEG or OP = NEGX else + BIW_0(2 downto 0) when OP = NOT_B or OP = ORI or OP = SUBI or OP = SUBQ or OP = SWAP or OP = TAS or OP = TST else + BIW_0(2 downto 0) when OP = ASL or OP = ASR or OP = LSL or OP = LSR else + BIW_0(2 downto 0) when OP = ROTL or OP = ROTR or OP = ROXL or OP = ROXR else "000"; + + DR_SEL_WR_2 <= BIW_0(2 downto 0) when OP = EXG else BIW_1(2 downto 0); -- Default is for DIVS and DIVU, MULS, MULU. + + -- Normally source register. Writte in a few exceptions. + DR_WR_2 <= '1' when OP_WB_I = EXG and EXEC_WB_STATE = WRITEBACK and BIW_0_WB(7 downto 3) = "01000" else -- Two data registers. + '1' when OP_WB_I = DIVS and EXEC_WB_STATE = WRITEBACK and BIW_0_WB(8 downto 6) = "001" and BIW_1_WB(14 downto 12) /= BIW_1_WB(2 downto 0) else + '1' when OP_WB_I = DIVU and EXEC_WB_STATE = WRITEBACK and BIW_0_WB(8 downto 6) = "001" and BIW_1_WB(14 downto 12) /= BIW_1_WB(2 downto 0) else + '1' when OP_WB_I = MULS and EXEC_WB_STATE = WRITEBACK and BIW_0_WB(8 downto 6) = "000" and BIW_1_WB(10) = '1' and BIW_1_WB(14 downto 12) /= BIW_1_WB(2 downto 0) else + '1' when OP_WB_I = MULU and EXEC_WB_STATE = WRITEBACK and BIW_0_WB(8 downto 6) = "000" and BIW_1_WB(10) = '1' and BIW_1_WB(14 downto 12) /= BIW_1_WB(2 downto 0) else '0'; + + USE_DREG <= '1' when OP = CAS2 and BIW_1(15) = '0' and PHASE2 = false else + '1' when OP = CAS2 and BIW_2(15) = '0' else + '1' when (OP = CHK2 or OP = CMP2) and BIW_1(15) = '0' and FETCH_STATE = FETCH_OPERAND and RD_RDY = '1' and PHASE2 = true else -- Select destination register. + '1' when (OP = CHK2 or OP = CMP2) and BIW_1(15) = '0' and ALU_INIT_I = '1' else '0'; -- Store compare information + + WB_BUFFER: process + -- This process stores the data for the + -- WRITEBACK or the WRITE_DEST procedure. + -- The MOVEM condition is foreseen to bring + -- the ADn_WB and the PNTR_WB right in time + -- befor the address or data registers are + -- marked used. + begin + wait until CLK = '1' and CLK' event; + if (OP_WB_I = BFCHG or OP_WB_I = BFCLR or OP_WB_I = BFINS or OP_WB_I = BFSET) and EXEC_WB_STATE = WRITE_DEST and WR_RDY = '1' and BF_BYTES = 5 then + -- This condition may not overwhelm the ALU_INIT_I sowe have to wait in INIT_EXEC_WB for the + -- bit field operations until the last bus cycle finishes. + OP_SIZE_WB <= BYTE; -- Remaining Byte. + elsif OP = LINK and FETCH_STATE = START_OP and NEXT_FETCH_STATE = SWITCH_STATE then + OP_SIZE_WB <= OP_SIZE_I; -- Bring this information early because the registers are written early. + elsif ALU_INIT_I = '1' then + if OP = DIVS or OP = DIVU or OP = MULS or OP = MULU then + OP_SIZE_WB <= LONG; + elsif OP = MOVEM and BIW_0(10) = '1' then -- Memory to register. + OP_SIZE_WB <= LONG; -- Registers are always written long. + else + OP_SIZE_WB <= OP_SIZE_I; -- Store right in the end before data processing starts. + end if; + + MOVEM_ADn_WB <= MOVEM_ADn_I; + OP_WB_I <= OP; + BIW_0_WB <= BIW_0(11 downto 0); + BIW_1_WB <= BIW_1; + end if; + end process WB_BUFFER; + + OP_WB <= OP_WB_I; + BIW_0_WB_73 <= BIW_0_WB(7 downto 3); + + OP_SIZE <= OP_SIZE_I; + OP_SIZE_I <= LONG when FETCH_STATE = FETCH_MEMADR and RD_RDY = '0' else -- (RD_RDY: release early to provide correct OP_SIZE. + LONG when (OP = ADDA or OP = CMPA or OP = SUBA) and BIW_0(8 downto 7) = "11" else + LONG when (OP = BCHG or OP = BCLR or OP = BTST or OP = BSET) and BIW_0(5 downto 3) = "000" else + LONG when (OP = BFCHG or OP = BFCLR or OP = BFINS or OP = BFSET) and BIW_0(5 downto 3) = "000" else + LONG when (OP = BFEXTS or OP = BFEXTU or OP = BFFFO or OP = BFTST) and BIW_0(5 downto 3) = "000" else + LONG when (OP = BFCHG or OP = BFCLR or OP = BFINS or OP = BFSET) and BF_BYTES > 2 else + LONG when (OP = BFEXTS or OP = BFEXTU or OP = BFFFO or OP = BFTST) and BF_BYTES > 2 else + LONG when OP = EXT and BIW_0(8 downto 6) = "011" else + LONG when OP = BSR or OP = EXG or OP = EXTB or OP = JSR or OP = LEA or OP = LINK or OP = PEA or OP = SWAP or OP = UNLK else + LONG when (OP = CAS or OP = CAS2) and BIW_0(10 downto 9) = "11" else + LONG when OP = CHK and BIW_0(8 downto 7) = "10" else + LONG when (OP = CHK2 or OP = CMP2) and BIW_0(10 downto 9) = "10" else + LONG when (OP = MOVE or OP = MOVEA) and BIW_0(13 downto 12) = "10" else + LONG when OP = MOVEC or OP = MOVEQ or OP = MOVE_USP or OP = RTD or OP = RTS else + LONG when OP = MOVEM and BIW_0(6) = '1' else + LONG when OP = MOVEP and FETCH_STATE = INIT_EXEC_WB and BIW_0(7 downto 6) < "10" else -- Writeback to registers is long (see top level multiplexer). + LONG when (OP = DIVS or OP = DIVU or OP = MULS or OP = MULU) and BIW_0(7) = '0' else + LONG when OP = RTR and PHASE2 = true else -- Read PC. + WORD when (OP = ADDA or OP = CMPA or OP = SUBA) and BIW_0(8 downto 7) = "01" else + WORD when (OP = ASL or OP = ASR) and BIW_0(7 downto 6) = "11" else -- Memory shifts. + WORD when OP = ANDI_TO_SR or OP = EORI_TO_SR or OP = ORI_TO_SR else + WORD when (OP = BFCHG or OP = BFCLR or OP = BFINS or OP = BFSET) and BF_BYTES = 2 else + WORD when (OP = BFEXTS or OP = BFEXTU or OP = BFFFO or OP = BFTST) and BF_BYTES = 2 else + WORD when OP = BKPT and FETCH_STATE = FETCH_OPERAND and DATA_RD_I = '1' else + WORD when (OP = CAS or OP = CAS2) and BIW_0(10 downto 9) = "10" else + WORD when OP = CHK and BIW_0(8 downto 7) = "11" else + WORD when (OP = CHK2 or OP = CMP2) and BIW_0(10 downto 9) = "01" else + WORD when OP = DBcc or OP = EXT else + WORD when (OP = LSL or OP = LSR) and BIW_0(7 downto 6) = "11" else -- Memory shifts. + WORD when (OP = MOVE or OP = MOVEA) and BIW_0(13 downto 12) = "11" else + WORD when OP = MOVE_FROM_CCR or OP = MOVE_TO_CCR else + WORD when OP = MOVE_FROM_SR or OP = MOVE_TO_SR else + WORD when OP = MOVEM or OP = RTR else + WORD when OP = DIVS or OP = DIVU or OP = MULS or OP = MULU else + WORD when OP = PACK and (NEXT_FETCH_STATE = FETCH_OPERAND or FETCH_STATE = FETCH_OPERAND) and INIT_ENTRY = '0' else -- Read data is word wide. + WORD when (OP = ROTL or OP = ROTR) and BIW_0(7 downto 6) = "11" else -- Memory shifts. + WORD when (OP = ROXL or OP = ROXR) and BIW_0(7 downto 6) = "11" else -- Memory shifts. + WORD when OP = UNPK and (INIT_ENTRY = '1' or FETCH_STATE = INIT_EXEC_WB) else -- Writeback data is a word. + BYTE when OP = ABCD or OP = NBCD or OP = SBCD else + BYTE when OP = ANDI_TO_CCR or OP = EORI_TO_CCR or OP = ORI_TO_CCR else + BYTE when OP = BCHG or OP = BCLR or OP = BTST or OP = BSET else + BYTE when OP = BFCHG or OP = BFCLR or OP = BFINS or OP = BFSET else + BYTE when OP = BFEXTS or OP = BFEXTU or OP = BFFFO or OP = BFTST else + BYTE when OP = CAS and BIW_0(10 downto 9) = "01" else + BYTE when (OP = CHK2 or OP = CMP2) and BIW_0(10 downto 9) = "00" else + BYTE when OP = MOVE or OP = MOVEP else + BYTE when OP = PACK else -- Writeback data is a byte. + BYTE when OP = Scc or OP = TAS else + BYTE when OP = UNPK else -- Read data is byte wide. + -- The following are default settings for all other OP_SIZE relevant operations. + BYTE when BIW_0(7 downto 6) = "00" else + WORD when BIW_0(7 downto 6) = "01" else LONG; + + BKPT_CYCLE <= '1' when OP = BKPT and FETCH_STATE = FETCH_OPERAND and DATA_RD_I = '1' else '0'; + BKPT_INSERT <= '1' when OP = BKPT and FETCH_STATE = FETCH_OPERAND and RD_RDY = '1' and DATA_VALID = '1' else '0'; + + -- All traps must be modeled as strobes. Be aware that the TRAP_cc is released right in the end of the TRAPcc operation. + -- This is necessary to meet the timing requirements (BUSY_EXH, IPIPE_FLUSH, PC_INC) to provide the next PC address. See + -- the exception handler unit for more details. + TRAP_ILLEGAL <= '1' when OP = BKPT and FETCH_STATE = FETCH_OPERAND and RD_RDY = '1' and DATA_VALID = '0' else '0'; + + TRAP_cc <= '1' when OP = TRAPcc and ALU_COND = true and FETCH_STATE = SLEEP and NEXT_FETCH_STATE = START_OP else '0'; + TRAP_V <= '1' when OP = TRAPV and ALU_COND = true and FETCH_STATE = SLEEP and NEXT_FETCH_STATE = START_OP else '0'; + + BERR <= '0' when FETCH_STATE = START_OP and EXEC_WB_STATE = IDLE else -- Disable when controller is not active. + '0' when OP = BKPT else -- No bus error during breakpoint cycle. + '1' when DATA_RDY = '1' and DATA_VALID = '0' else + '1' when OPD_ACK = '1' and OW_VALID = '0' else + '1' when EW_ACK = '1' and OW_VALID = '0' else '0'; + + SFC_RD <= '1' when OP = MOVEC and BIW_0(0) = '0' and BIW_1(11 downto 0) = x"000" else '0'; + SFC_WR <= '1' when OP_WB_I = MOVEC and BIW_0_WB(0) = '1' and BIW_1(11 downto 0) = x"000" and EXEC_WB_STATE = WRITEBACK else '0'; + + DFC_RD <= '1' when OP = MOVEC and BIW_0(0) = '0' and BIW_1(11 downto 0) = x"001" else '0'; + DFC_WR <= '1' when OP_WB_I = MOVEC and BIW_0(0) = '1' and BIW_1_WB(11 downto 0) = x"001" and EXEC_WB_STATE = WRITEBACK else '0'; + + VBR_RD <= '1' when OP = MOVEC and BIW_0(0) = '0' and BIW_1(11 downto 0) = x"801" else '0'; + VBR_WR <= '1' when OP_WB_I = MOVEC and BIW_0_WB(0) = '1' and BIW_1_WB(11 downto 0) = x"801" and EXEC_WB_STATE = WRITEBACK else '0'; + + ISP_RD <= '1' when OP = MOVEC and BIW_0(0) = '0' and BIW_1(11 downto 0) = x"804" else '0'; + ISP_WR <= '1' when OP_WB_I = MOVEC and BIW_0_WB(0) = '1' and BIW_1_WB(11 downto 0) = x"804" and EXEC_WB_STATE = WRITEBACK else '0'; + + MSP_RD <= '1' when OP = MOVEC and BIW_0(0) = '0' and BIW_1(11 downto 0) = x"803" else '0'; + MSP_WR <= '1' when OP_WB_I = MOVEC and BIW_0_WB(0) = '1' and BIW_1_WB(11 downto 0) = x"803" and EXEC_WB_STATE = WRITEBACK else '0'; + + USP_RD <= '1' when OP = MOVE_USP and BIW_0(3) = '1' else + '1' when OP = MOVEC and BIW_0(0) = '0' and BIW_1(11 downto 0) = x"800" else '0'; + USP_WR <= '1' when OP_WB_I = MOVE_USP and EXEC_WB_STATE = WRITEBACK and BIW_0_WB(3) = '0' else + '1' when OP_WB_I = MOVEC and BIW_0_WB(0) = '1' and BIW_1_WB(11 downto 0) = x"800" and EXEC_WB_STATE = WRITEBACK else '0'; + + P_DISPLACEMENT: process + variable DISPL_VAR : std_logic_vector(31 downto 0); + begin + wait until CLK = '1' and CLK' event; + case OP is + when Bcc | BRA | BSR => + case BIW_0(7 downto 0) is + when x"FF" => + DISPL_VAR := BIW_1 & BIW_2; + when x"00" => + for i in 16 to 31 loop + DISPL_VAR(i) := BIW_1(15); + end loop; + DISPL_VAR(15 downto 0) := BIW_1; + when others => + for i in 8 to 31 loop + DISPL_VAR(i) := BIW_0(7); + end loop; + DISPL_VAR(7 downto 0) := BIW_0(7 downto 0); + end case; + when DBcc | MOVEP | RTD => + for i in 16 to 31 loop + DISPL_VAR(i) := BIW_1(15); + end loop; + DISPL_VAR(15 downto 0) := BIW_1; + when others => -- Used for LINK. + case BIW_0(11 downto 3) is + when "100000001" => -- Long. + DISPL_VAR := BIW_1 & BIW_2; + when others => -- Word. + for i in 16 to 31 loop + DISPL_VAR(i) := BIW_1(15); + end loop; + DISPL_VAR(15 downto 0) := BIW_1; + end case; + end case; + -- + case OP is + when LINK | MOVEP => DISPLACEMENT <= DISPL_VAR; + when others => DISPLACEMENT <= DISPL_VAR + "10"; + end case; + end process P_DISPLACEMENT; + + PC_ADD_DISPL <= PC_ADD_DISPL_I; + PC_ADD_DISPL_I <= '1' when OP = Bcc and FETCH_STATE /= START_OP and NEXT_FETCH_STATE = START_OP and ALU_COND = true else + '1' when (OP = BRA or OP = BSR) and FETCH_STATE /= START_OP and NEXT_FETCH_STATE = START_OP else + '1' when OP = DBcc and FETCH_STATE /= START_OP and NEXT_FETCH_STATE = START_OP and ALU_COND = false and DBcc_COND = false else '0'; + + PC_LOAD <= PC_LOAD_I; + PC_LOAD_I <= '1' when (OP = JMP or OP = JSR) and FETCH_STATE /= START_OP and NEXT_FETCH_STATE = START_OP else + '1' when (OP = RTD or OP = RTR or OP = RTS) and FETCH_STATE /= START_OP and NEXT_FETCH_STATE = START_OP else '0'; + + -- The pipe is flushed for the system control instructions. Be aware, that the operations resulting in an exception + -- like the CHK or TRAP operations flush the pipe via the exception handler. + -- Context switch may occur from: + -- changing the PC value (branches etc.) + -- changing the RAM space (status register MSBs). + -- changing Function codes or the active stack pointer. + IPIPE_FLUSH <= IPIPE_FLUSH_I; + IPIPE_FLUSH_I <= '1' when (OP = BRA or OP = BSR) and FETCH_STATE /= START_OP and NEXT_FETCH_STATE = START_OP else + '1' when OP = Bcc and FETCH_STATE /= START_OP and NEXT_FETCH_STATE = START_OP and ALU_COND = true else + '1' when OP = DBcc and LOOP_BSY = '0' and FETCH_STATE /= START_OP and NEXT_FETCH_STATE = START_OP and ALU_COND = false and DBcc_COND = false else + '1' when OP = DBcc and LOOP_EXIT_I = '1' and (ALU_COND = true or DBcc_COND = true) else -- Flush the pipe after a finished loop. + '1' when (OP = ANDI_TO_SR or OP = EORI_TO_SR or OP = MOVE_TO_SR or OP = ORI_TO_SR) and FETCH_STATE = SLEEP and NEXT_FETCH_STATE = START_OP else + '1' when (OP = JMP or OP = JSR) and FETCH_STATE /= START_OP and NEXT_FETCH_STATE = START_OP else + '1' when OP = MOVEC and BIW_0(0) = '1' and FETCH_STATE /= START_OP and NEXT_FETCH_STATE = START_OP else -- Writing control registers. + '1' when (OP = RTD or OP = RTR or OP = RTS) and FETCH_STATE /= START_OP and NEXT_FETCH_STATE = START_OP else '0'; + + SP_ADD_DISPL <= '1' when OP = LINK and FETCH_STATE = INIT_EXEC_WB and ALU_BSY = '0' else + '1' when OP = RTD and FETCH_STATE = FETCH_OPERAND and RD_RDY = '1' and DATA_VALID = '1' else '0'; + + ALU_TRIG <= '0' when ALU_BSY = '1' or FETCH_STATE /= INIT_EXEC_WB else + '0' when (OP = CHK2 or OP = CMP2 or OP = CMPM) and PHASE2 = false else + '0' when OP = MOVE and PHASE2 = true else -- no ALU required after second portion of address calculation. + '0' when OP = MOVEM and MOVEM_COND = false else + '0' when OP = MOVEM and BIW_0(10) = '1' and MOVEM_FIRST_RD = false else -- Do not load before the first read access. + '0' when OP = RTR and PHASE2 = true else '1'; -- RTR: not when PC is loaded. + + -- This is the signal loading the operands into the ALU registers: + ALU_INIT <= ALU_INIT_I; + with OP select + ALU_INIT_I <= ALU_TRIG when ABCD | ADD | ADDA | ADDI | ADDQ | ADDX | AND_B | ANDI | ANDI_TO_CCR | ANDI_TO_SR | ASL | ASR | Bcc | BCHG | + BCLR | BFCHG | BFCLR | BFEXTS | BFEXTU | BFFFO | BFINS | BFSET | BFTST | BSET | BSR | BTST | CAS | CAS2 | + CHK | CHK2 | CLR | CMP | CMPA | CMPI | CMPM | CMP2 | DBcc | DIVS | DIVU | EOR | EORI | EORI_TO_CCR | EORI_TO_SR | + EXG | EXT | EXTB | JSR | LEA | LINK | LSL | LSR | MOVE | MOVEA | MOVE_FROM_CCR | MOVE_TO_CCR | MOVE_FROM_SR | + MOVE_TO_SR | MOVE_USP | MOVEC | MOVEM | MOVEQ | MOVEP | MOVES | MULS | MULU | NBCD | NEG | NEGX | NOT_B | OR_B | + ORI | ORI_TO_CCR | ORI_TO_SR | PACK | PEA | ROTL | ROTR | ROXL | ROXR | RTR | SBCD | Scc | SUB | SUBA | SUBI | + SUBQ | SUBX | SWAP | STOP | TAS | TRAPV | TRAPcc | TST | UNLK | UNPK, '0' when others; + + ADR_FORMAT: process + begin + wait until CLK = '1' and CLK' event; + if FETCH_STATE = FETCH_EXWORD_1 and EW_ACK = '1' and EXT_WORD(8) = '1' then + case EXT_WORD(1 downto 0) is + when "11" => + MEM_INDIRECT <= '1'; + OD_REQ_32 <= '1'; + OD_REQ_16 <= '0'; + when "10" => + MEM_INDIRECT <= '1'; + OD_REQ_32 <= '0'; + OD_REQ_16 <= '1'; + when "01" => + MEM_INDIRECT <= '1'; + OD_REQ_32 <= '0'; + OD_REQ_16 <= '0'; + when others => + MEM_INDIRECT <= '0'; + OD_REQ_32 <= '0'; + OD_REQ_16 <= '0'; + end case; + end if; + end process ADR_FORMAT; + + UPDT_CC <= '0' when (OP_WB_I = ADDQ or OP_WB_I = SUBQ) and BIW_0_WB(5 downto 3) = "001" else -- No update for ADDQ and SUBQ when destination is an address register. + '0' when OP = CAS2 and FETCH_STATE = INIT_EXEC_WB and EXEC_WB_STATE = WRITEBACK else -- First 'Z' flag was zero, do not update the second access. + '0' when OP = CAS2 and FETCH_STATE = INIT_EXEC_WB and EXEC_WB_STATE = WRITE_DEST and PHASE2 = true else ALU_REQ; -- Suppress third update. + + with OP_WB_I select + CC_UPDT <= UPDT_CC when ABCD | ADD | ADDI | ADDQ | ADDX | AND_B | ANDI | ANDI_TO_CCR | ASL | ASR | BCHG | BCLR | + BFCHG | BFCLR | BFEXTS | BFEXTU | BFFFO | BFINS | BFSET | BFTST | BSET | BTST | + CAS | CAS2 | CHK | CHK2 | CLR | CMP | CMPA | CMPI | CMPM | CMP2 | DIVS | DIVU | + EOR | EORI | EORI_TO_CCR | EXT | EXTB | LSL | LSR | MOVE | MOVEQ | MULS | MULU | NBCD | + NEG | NEGX | NOT_B | OR_B | ORI | ORI_TO_CCR | ROTL | ROTR | ROXL | ROXR | RTR | SBCD | + SUB | SUBI | SUBQ | SUBX | SWAP | TAS | TST, '0' when others; + + ADR_MARK_USED_I <= '1' when OP = MOVE and FETCH_STATE = INIT_EXEC_WB and PHASE2 = true else -- Destination address calculation done. + '0' when FETCH_STATE /= INIT_EXEC_WB or ALU_BSY = '1' else -- Deactivate except in the end of INIT_EXEC_WB. + '1' when OP = BFCHG or OP = BFCLR or OP = BFINS or OP = BFSET or OP = BSR or OP = JSR or OP = LINK or OP = PEA else + '1' when (OP = ADDI or OP = ANDI or OP = EOR or OP = EORI or OP = ORI or OP = SUBI) and BIW_0(5 downto 3) /= "000" else + '1' when (OP = ABCD or OP = SBCD or OP = ADDX or OP = SUBX) and BIW_0(3) = '1' else + '1' when (OP = ADD or OP = AND_B or OP = OR_B or OP = SUB) and BIW_0(8) = '1' else + '1' when (OP = ADDQ or OP = BCHG or OP = BCLR or OP = BSET or OP = CLR or OP = MOVE_FROM_CCR or OP = MOVE_FROM_SR) and BIW_0(5 downto 3) > "001" else + '1' when (OP = NBCD or OP = NEG or OP = NEGX or OP = NOT_B or OP = Scc or OP = SUBQ or OP = TAS) and BIW_0(5 downto 3) > "001" else + '1' when (OP = ASL or OP = ASR or OP = LSL or OP = LSR) and BIW_0(7 downto 6) = "11" else -- Memory shifts. + '1' when (OP = ROTL or OP = ROTR or OP = ROXL or OP = ROXR) and BIW_0(7 downto 6) = "11" else -- Memory shifts. + '1' when OP = MOVE and PHASE2 = false and BIW_0(8 downto 6) /= "000" and BIW_0(8 downto 6) < "101" else -- We do not need destination address calculation access. + '1' when OP = MOVEM and BIW_0(10) = '0' and MOVEM_COND = true else -- Register to memory. + '1' when OP = MOVEP and BIW_0(7 downto 6) > "01" else -- Register to Memory. + '1' when OP = MOVES and BIW_1(11) = '1' else -- Register to memory. + '1' when (OP = PACK or OP = UNPK) and BIW_0(3) = '1' else '0'; + + ADR_MARK_USED <= '1' when (OP_WB_I = BFCHG or OP_WB_I = BFCLR) and EXEC_WB_STATE = WRITE_DEST and WR_RDY = '1' and BF_BYTES = 5 else + '1' when (OP_WB_I = BFINS or OP_WB_I = BFSET) and EXEC_WB_STATE = WRITE_DEST and WR_RDY = '1' and BF_BYTES = 5 else + '1' when OP_WB_I = CAS and EXEC_WB_STATE = EXECUTE and ALU_COND = true else + '1' when OP_WB_I = CAS2 and EXEC_WB_STATE = ADR_PIPELINE and ALU_COND = true else + '1' when OP_WB_I = CAS2 and EXEC_WB_STATE = WRITE_DEST and WR_RDY = '1' and PHASE2 = false else ADR_MARK_USED_I; + + AR_MARK_USED <= '1' when OP = UNLK and FETCH_STATE /= SWITCH_STATE and NEXT_FETCH_STATE = SWITCH_STATE else -- This is for An to SP. + '1' when OP = LINK and FETCH_STATE = SWITCH_STATE and NEXT_FETCH_STATE /= SWITCH_STATE else -- This is for SP to An. + '0' when FETCH_STATE /= INIT_EXEC_WB or NEXT_FETCH_STATE = INIT_EXEC_WB else -- Deactivate except in the end of INIT_EXEC_WB. + '1' when OP = ADDA or OP = SUBA else + '1' when (OP = ADDQ or OP = SUBQ) and BIW_0(5 downto 3) = "001" else + '1' when OP = EXG and BIW_0(7 downto 3) /= "01000" else + '1' when OP = LEA else + '1' when OP = MOVE_USP else + '1' when OP = MOVEM and BIW_0(10) = '1' and MOVEM_ADn_I = '1' and MOVEM_COND = true else -- Memory to register. + '1' when OP = MOVEA else + '1' when OP = MOVEC and BIW_0(0) = '0' and BIW_1(15) = '1' else -- Destination is Ax. + '1' when OP = MOVES and BIW_1(15) = '1' and BIW_1(11) = '0' else + '1' when OP = UNLK else '0'; + + DR_MARK_USED <= '1' when OP_WB_I = CAS and EXEC_WB_STATE = EXECUTE and ALU_COND = false else + '1' when OP_WB_I = CAS2 and EXEC_WB_STATE = EXECUTE and ALU_COND = false else + '1' when OP_WB_I = CAS2 and EXEC_WB_STATE = WRITEBACK and PHASE2 = false else + '0' when FETCH_STATE /= INIT_EXEC_WB or NEXT_FETCH_STATE = INIT_EXEC_WB else -- Deactivate except in the end of INIT_EXEC_WB. + '1' when (OP = ABCD or OP = SBCD) and BIW_0(3) = '0' else + '1' when (OP = ADDX or OP = SUBX) and BIW_0(3) = '0' else + '1' when (OP = ADDQ or OP = SUBQ) and BIW_0(5 downto 3) = "000" else + '1' when (OP = ADD or OP = SUB) and BIW_0(8) = '0' else + '1' when (OP = ADDI or OP = ANDI or OP = EOR or OP = EORI or OP = ORI or OP = SUBI) and BIW_0(5 downto 3) = "000" else + '1' when (OP = AND_B or OP = OR_B) and BIW_0(8) = '0' else + '1' when (OP = ASL or OP = ASR) and BIW_0(7 downto 6) /= "11" else + '1' when (OP = LSL or OP = LSR) and BIW_0(7 downto 6) /= "11" else + '1' when (OP = ROTL or OP = ROTR) and BIW_0(7 downto 6) /= "11" else + '1' when (OP = ROXL or OP = ROXR) and BIW_0(7 downto 6) /= "11" else + '1' when (OP = BCHG or OP = BCLR or OP = BSET) and BIW_0(5 downto 3) = "000" else + '1' when (OP = BFCHG or OP = BFCLR or OP = BFINS or OP = BFSET) and BIW_0(5 downto 3) = "000" else + '1' when OP = BFEXTS or OP = BFEXTU or OP = BFFFO else + '1' when (OP = CLR or OP = TAS or OP = Scc) and BIW_0(5 downto 3) = "000" else + '1' when OP = DBcc or OP = DIVS or OP = DIVU or OP = MULS or OP = MULU else + '1' when OP = EXG and BIW_0(7 downto 3) /= "01001" else + '1' when OP = EXT or OP = EXTB or OP = SWAP else + '1' when OP = MOVE and BIW_0(8 downto 6) = "000" else + '1' when (OP = MOVE_FROM_CCR or OP = MOVE_FROM_SR) and BIW_0(5 downto 3) = "000" else + '1' when OP = MOVEM and BIW_0(10) = '1' and MOVEM_ADn_I = '0' and MOVEM_COND = true else -- Memory to register. + '1' when OP = MOVEP and BIW_0(7 downto 6) < "10" else -- Memory to register. + '1' when OP = MOVEC and BIW_0(0) = '0' and BIW_1(15) = '0' else -- Destination is Dx. + '1' when OP = MOVEQ else + '1' when OP = MOVES and BIW_1(15) = '0' and BIW_1(11) = '0' else + '1' when (OP = NBCD or OP = NEG or OP = NEGX or OP = NOT_B) and BIW_0(5 downto 3) = "000" else + '1' when (OP = PACK or OP = UNPK) and BIW_0(3) = '0' else '0'; + + UNMARK <= '1' when EXEC_WB_STATE /= IDLE and NEXT_EXEC_WB_STATE = IDLE else '0'; -- Release a pending write cycle when done. + + -- These signals indicates, that two registers are prepared to be written. In this case, the values + -- in both of these registers are invalidated before the writeback. + USE_APAIR <= true when OP = EXG and BIW_0(7 downto 3) = "01001" else false; + USE_DPAIR <= true when OP = EXG and BIW_0(7 downto 3) = "01000" else + true when (OP = DIVS or OP = DIVU) and OP_SIZE_I = LONG and BIW_1(14 downto 12) /= BIW_1(2 downto 0) else + true when (OP = MULS or OP = MULU) and OP_SIZE_I = LONG and BIW_1(10) = '1' and BIW_1(14 downto 12) /= BIW_1(2 downto 0) else false; + + LOOP_EXIT <= LOOP_EXIT_I; + LOOP_EXIT_I <= '1' when OP /= DBcc and LOOP_BSY = '1' and FETCH_STATE /= START_OP and NEXT_FETCH_STATE = START_OP and EXH_REQ = '1' else -- Exception! break the loop. + '1' when OP = DBcc and LOOP_BSY = '1' and FETCH_STATE = SLEEP and NEXT_FETCH_STATE = START_OP and (ALU_COND = true or DBcc_COND = true) else '0'; -- 68010 loop mechanism. + + LOOP_CTRL: process + -- This flip flop indicates, if a DBcc loop operation has finished if the exception handler indicates an interrupt. + -- If so, no action is required. If the loop is split (when not finished) the exception handler may not increment + -- the PC to hold the value of the loop operation. + begin + wait until CLK = '1' and CLK' event; + if FETCH_STATE = START_OP and NEXT_FETCH_STATE /= START_OP then + LOOP_SPLIT <= false; + elsif PC_INC_EXH = '1' then + LOOP_SPLIT <= false; + elsif OP /= DBcc and EXH_REQ = '1' and LOOP_BSY = '1' and FETCH_STATE = SLEEP and NEXT_FETCH_STATE = START_OP then + LOOP_SPLIT <= true; + end if; + end process LOOP_CTRL; + + + BF_OFFSET_I <= To_Integer(unsigned(BF_OFFSET)); + BF_WIDTH_I <= To_Integer(unsigned(BF_WIDTH)); + + RESET_STRB <= '1' when OP = RESET and INIT_ENTRY = '1' else '0'; + + EX_TRACE <= '0' when OP = ILLEGAL or OP = UNIMPLEMENTED else + '1' when TRACE_MODE = "10" and OPD_ACK = '1' and FETCH_STATE = START_OP and OP = TRAP else + '1' when TRACE_MODE = "10" and FETCH_STATE /= START_OP and NEXT_FETCH_STATE = START_OP else + '1' when TRACE_MODE = "01" and FETCH_STATE = INIT_EXEC_WB and ALU_BSY = '0' and OP = TRAP else + '1' when TRACE_MODE = "01" and FETCH_STATE = INIT_EXEC_WB and ALU_BSY = '0' and OP = TRAPcc and ALU_COND = true else + '1' when TRACE_MODE = "01" and FETCH_STATE = INIT_EXEC_WB and ALU_BSY = '0' and OP = TRAPV and VBIT = '1' else + '1' when TRACE_MODE = "01" and SR_WR_I = '1' else -- Status register manipulations. + '1' when TRACE_MODE = "01" and (PC_ADD_DISPL_I or PC_LOAD_I) = '1' else '0'; -- All branches and jumps. + + P_STATUSn: process + -- This logic is registered to enhance the system performance concerning fmax. + begin + wait until CLK = '1' and CLK' event; + if FETCH_STATE = START_OP and NEXT_FETCH_STATE /= START_OP then + STATUSn <= '0'; + else + STATUSn <= '1'; + end if; + end process P_STATUSn; + + ADDRESS_OFFSET: process + variable ADR_OFFS_VAR: std_logic_vector(5 downto 0) := "000000"; + begin + wait until CLK = '1' and CLK' event; + if FETCH_STATE = START_OP then + ADR_OFFS_VAR := "000000"; + else + case OP is + when BFCHG | BFCLR | BFINS | BFSET => + if FETCH_STATE = FETCH_OPERAND and RD_RDY = '1' and BF_BYTES = 5 then + ADR_OFFS_VAR := ADR_OFFS_VAR + "100"; -- Another Byte required. + elsif INIT_ENTRY = '1' then + ADR_OFFS_VAR := "000000"; -- Restore. + elsif FETCH_STATE = INIT_EXEC_WB and ALU_BSY = '0' and BF_BYTES = 5 then + ADR_OFFS_VAR := ADR_OFFS_VAR + "100"; -- Another Byte required. + end if; + when BFEXTS | BFEXTU | BFFFO | BFTST => + if FETCH_STATE = FETCH_OPERAND and RD_RDY = '1' and BF_BYTES = 5 then + ADR_OFFS_VAR := ADR_OFFS_VAR + "100"; -- Another Byte required. + end if; + when CHK2 | CMP2 => + if FETCH_STATE = FETCH_OPERAND and RD_RDY = '1' and OP_SIZE_I = LONG then + ADR_OFFS_VAR := ADR_OFFS_VAR + "100"; + elsif FETCH_STATE = FETCH_OPERAND and RD_RDY = '1' and OP_SIZE_I = WORD then + ADR_OFFS_VAR := ADR_OFFS_VAR + "10"; + elsif FETCH_STATE = FETCH_OPERAND and RD_RDY = '1' then + ADR_OFFS_VAR := ADR_OFFS_VAR + '1'; + end if; + when MOVEM => + if ADR_MODE_I = "011" or ADR_MODE_I = "100" then -- (An)+, -(An). + null; -- Offset comes from addressing register. + elsif BIW_0(10) = '1' and MOVEM_FIRST_RD = false then + null; -- Do not increment before the first bus access. + elsif MOVEM_COND = true and FETCH_STATE = INIT_EXEC_WB and ALU_BSY = '0' and OP_SIZE_I = LONG then + ADR_OFFS_VAR := ADR_OFFS_VAR + "100"; -- Register to memory. + elsif MOVEM_COND = true and FETCH_STATE = INIT_EXEC_WB and ALU_BSY = '0' then + ADR_OFFS_VAR := ADR_OFFS_VAR + "10"; -- Register to memory. + end if; + when MOVEP => + if FETCH_STATE = INIT_EXEC_WB and ALU_BSY = '0' then + ADR_OFFS_VAR := ADR_OFFS_VAR + "10"; + end if; + when others => null; + end case; + end if; + ADR_OFFSET <= ADR_OFFS_VAR; + end process ADDRESS_OFFSET; + + BITFIELD_CONTROL: process + begin + wait until CLK = '1' and CLK' event; + if FETCH_STATE = START_OP then + case OP is + when BFCHG | BFCLR | BFEXTS | BFEXTU | BFFFO | BFINS | BFSET | BFTST => + if NEXT_FETCH_STATE = INIT_EXEC_WB then + BF_BYTES <= 4; -- Register access. + else + BF_BYTES <= BF_BYTES_I(BF_OFFSET_I, BF_WIDTH_I); + end if; + BF_HILOn <= '1'; + when others => null; + end case; + elsif FETCH_STATE = FETCH_OPERAND then + if RD_RDY = '1' and BF_BYTES = 5 then + BF_BYTES <= 1; + BF_HILOn <= '0'; + elsif RD_RDY = '1' then + BF_BYTES <= BF_BYTES_I(BF_OFFSET_I, BF_WIDTH_I); -- Restore. + BF_HILOn <= '1'; -- Restore. + end if; + elsif EXEC_WB_STATE = WRITE_DEST then + if WR_RDY = '1' and BF_BYTES = 5 then + BF_BYTES <= 1; + BF_HILOn <= '0'; + elsif WR_RDY = '1' then + BF_HILOn <= '1'; -- Restore. + end if; + end if; + end process BITFIELD_CONTROL; + + MOVEM_CONTROL: process(ADR_MODE_I, CLK, BIW_0, BIW_1, OP, RESET_CPU, FETCH_STATE, NEXT_FETCH_STATE, ALU_BSY, MOVEM_PNTR) + variable INDEX : integer range 0 to 15 := 0; + variable MOVEM_PVAR : std_logic_vector(3 downto 0) := x"0"; + variable BITS : std_logic_vector(4 downto 0); + begin + if CLK = '1' and CLK' event then + if FETCH_STATE = START_OP then + MOVEM_PVAR := x"0"; + elsif FETCH_STATE = INIT_EXEC_WB and MOVEM_COND = false and MOVEM_PVAR < x"F" and ALU_BSY = '0' then + MOVEM_PVAR := MOVEM_PVAR + '1'; -- No data to write. + elsif BIW_0(10) = '1' and MOVEM_FIRST_RD = true and FETCH_STATE = INIT_EXEC_WB and MOVEM_PVAR < x"F" and ALU_BSY = '0' then + MOVEM_PVAR := MOVEM_PVAR + '1'; -- Data has not been read. + elsif BIW_0(10) = '0' and FETCH_STATE = INIT_EXEC_WB and MOVEM_PVAR < x"F" and ALU_BSY = '0' then + MOVEM_PVAR := MOVEM_PVAR + '1'; -- Data has been written. + end if; + + if OP = MOVEM and ALU_INIT_I = '1' and ADR_MODE_I = "011" and MOVEM_ADn_I = '1' and MOVEM_PNTR(2 downto 0) = BIW_0(2 downto 0) then + MOVEM_INH_WR <= true; -- Do not write the addressing register. + elsif ALU_INIT_I = '1' then + MOVEM_INH_WR <= false; + end if; + + if FETCH_STATE = START_OP then + MOVEM_FIRST_RD <= false; + elsif OP = MOVEM and FETCH_STATE = FETCH_OPERAND and RD_RDY = '1' then + MOVEM_FIRST_RD <= true; + end if; + + if RESET_CPU = '1' or (FETCH_STATE /= START_OP and NEXT_FETCH_STATE = START_OP) then + BITS := "00000"; + MOVEM_LAST_WR <= false; + elsif OP = MOVEM and FETCH_STATE = START_OP and NEXT_FETCH_STATE /= START_OP and ADR_MODE_I = "100" then -- -(An). + for i in 0 to 15 loop + BITS := BITS + BIW_1(i); -- Count number of '1's. + end loop; + MOVEM_LAST_WR <= false; + elsif OP = MOVEM and ALU_INIT_I = '1' and BITS > "00001" then + BITS := BITS - '1'; + elsif OP = MOVEM and BITS = "00001" then + MOVEM_LAST_WR <= true; + end if; + + -- During the MOVEM instruction in memory to register operation and addressing modes "010", "101","110" the effective address might be + -- affected, if the addressing register is active in the register list mask. To deal with it, the effective address is stored until the + -- MOVEM has read all registers from memory addressed by the initial addressing register (old value). + -- This logic is modeled synchronously (one clock latency) due to the one clock delay of the address calculation. + if OP /= MOVEM or BIW_0(10) /= '1' or (ADR_MODE_I /= "010" and ADR_MODE_I /= "101" and ADR_MODE_I /= "110") then + STORE_AEFF <= '0'; + elsif FETCH_STATE /= START_OP and NEXT_FETCH_STATE = START_OP then + STORE_AEFF <= '0'; -- Operation completed. + elsif FETCH_STATE = SWITCH_STATE or FETCH_STATE = CALC_AEFF or FETCH_STATE = FETCH_OPERAND or FETCH_STATE = INIT_EXEC_WB then + STORE_AEFF <= '1'; + end if; + end if; + + -- This signal determines whether to handle address or data registers. + if ADR_MODE_I = "100" then -- -(An). + MOVEM_ADn_I <= not To_Bit(MOVEM_PVAR(3)); + MOVEM_ADn <= not To_Bit(MOVEM_PVAR(3)); + else + MOVEM_ADn_I <= To_Bit(MOVEM_PVAR(3)); + MOVEM_ADn <= To_Bit(MOVEM_PVAR(3)); + end if; + + INDEX := To_Integer(unsigned(MOVEM_PVAR)); + + -- The following signal determines if a register is affected or not, depending + -- on the status of the register list bit. + if OP = MOVEM and BIW_1(INDEX) = '1' then + MOVEM_COND <= true; + else + MOVEM_COND <= false; + end if; + + -- This signal determines whether to handle address or data registers. + if ADR_MODE_I = "100" then -- -(An). + MOVEM_PNTR <= not MOVEM_PVAR; -- Count down. + else + MOVEM_PNTR <= MOVEM_PVAR; + end if; + end process MOVEM_CONTROL; + + MOVEP_CONTROL: process(CLK, MOVEP_PNTR_I) + -- This logic handles the bytes to be written or read during the MOVEP + -- operation. In LONG mode 4 bytes are affected and in WORD mode two bytes. + begin + if CLK = '1' and CLK' event then + if RESET_CPU = '1' or (FETCH_STATE /= START_OP and NEXT_FETCH_STATE = START_OP) then + MOVEP_PNTR_I <= 0; + elsif FETCH_STATE = START_OP and (BIW_0(8 downto 6) = "101" or BIW_0(8 downto 6) = "111") then + MOVEP_PNTR_I <= 3; -- LONG. + elsif FETCH_STATE = START_OP then + MOVEP_PNTR_I <= 1; -- WORD. + elsif FETCH_STATE = INIT_EXEC_WB and ALU_BSY = '0' and MOVEP_PNTR_I /= 0 then + MOVEP_PNTR_I <= MOVEP_PNTR_I - 1; -- Register to memory + end if; + end if; + MOVEP_PNTR <= MOVEP_PNTR_I; + end process MOVEP_CONTROL; + + PHASE2_CONTROL: process + -- This is used for some operations which require + -- two control sequences. + begin + wait until CLK = '1' and CLK' event; + if NEXT_FETCH_STATE = START_OP then + PHASE2 <= false; + elsif (OP = ABCD or OP = SBCD) and FETCH_STATE = FETCH_OPERAND and RD_RDY = '1' then + PHASE2 <= true; -- One clock cycle delay for destination address calculation. + elsif (OP = ADDX or OP = SUBX) and FETCH_STATE = FETCH_OPERAND and RD_RDY = '1' then + PHASE2 <= true; -- One clock cycle delay for destination address calculation. + elsif OP = CAS2 and FETCH_STATE = INIT_EXEC_WB and ALU_BSY = '0' and PHASE2 = false then + PHASE2 <= true; -- Used as a control flow switch. + elsif OP = CAS2 and FETCH_STATE = INIT_EXEC_WB and ALU_BSY = '0' then + PHASE2 <= false; -- Prepare for writeback / write destination. + elsif OP_WB_I = CAS2 and EXEC_WB_STATE = WRITEBACK then + PHASE2 <= true; -- Used as a control flow switch. + elsif OP_WB_I = CAS2 and EXEC_WB_STATE = WRITE_DEST and WR_RDY = '1' then + PHASE2 <= true; -- Used as a control flow switch. + elsif (OP = CHK2 or OP = CMP2 or OP = CMPM) and FETCH_STATE = INIT_EXEC_WB and ALU_BSY = '0' then + PHASE2 <= true; -- Used as a control flow switch. + elsif OP = JSR and FETCH_STATE = SLEEP then + PHASE2 <= true; -- One clock cycle delay for address calculation. + elsif OP = PEA and FETCH_STATE = SWITCH_STATE then + PHASE2 <= true; -- One clock cycle delay for address calculation. + elsif OP = RTR and FETCH_STATE = INIT_EXEC_WB and NEXT_FETCH_STATE = CALC_AEFF then + PHASE2 <= true; -- Used as a control flow switch. + elsif OP = MOVE and FETCH_STATE = INIT_EXEC_WB and ALU_BSY = '0' and BIW_0(8 downto 6) > "100" then + PHASE2 <= true; -- Indicate destination address calculation is in progress. + end if; + end process PHASE2_CONTROL; + + STATE_REGs: process + begin + wait until CLK = '1' and CLK' event; + if RESET_CPU = '1' then + FETCH_STATE <= START_OP; + EXEC_WB_STATE <= IDLE; + elsif EW_ACK = '1' and OW_VALID = '0' then + FETCH_STATE <= START_OP; -- Bus error. + EXEC_WB_STATE <= IDLE; + elsif OPD_ACK = '1' and OW_VALID = '0' then + FETCH_STATE <= START_OP; -- Bus error. + EXEC_WB_STATE <= IDLE; + elsif DATA_RD_I = '1' and RD_RDY = '1' and DATA_VALID = '0' then + FETCH_STATE <= START_OP; -- Bus error. + EXEC_WB_STATE <= IDLE; + elsif DATA_WR_I = '1' and RD_RDY = '1' and DATA_VALID = '0' then + FETCH_STATE <= START_OP; -- Bus error. + EXEC_WB_STATE <= IDLE; + else + FETCH_STATE <= NEXT_FETCH_STATE; + EXEC_WB_STATE <= NEXT_EXEC_WB_STATE; + end if; + end process STATE_REGs; + + -- Debugging: + -- Use this signal to detect instructions in use in the writeback path (OP_WB_I) or in the fetch path (OP). + -- for these instructions you can halt the pipeline in the START_OP state to detect any problems. + -- with OP select + -- with OP_WB_I select + -- OP_TEST <= '1' when ADDA | ADDQ | EXG | LEA | LINK | MOVEA | MOVE_USP | MOVEC | MOVEM | MOVES | SUBA | SUBQ | UNLK | -- Address register manipulations. + -- ASL | ASR | LSL | LSR | ROTL | ROTR | ROXL | ROXR | DIVS | DIVU | -- Long ALU operations. (68K10, 68K30L have no barrel shifter). + -- ADD | AND_B | CLR | EOR | SUB | OR_B | CMP | CMPA | CMPM | NOT_B | NBCD | NEG | NEGX | SWAP | TAS | TST + -- ANDI_TO_CCR | ANDI_TO_SR | EORI_TO_CCR | EORI_TO_SR | ORI_TO_CCR | ORI_TO_SR | MOVE_FROM_CCR | + -- MOVE_TO_CCR | MOVE_FROM_SR | MOVE_TO_SR | MOVE | MOVEQ | MOVEP | PEA | + -- ABCD | ADDX | SBCD | SUBX | BCHG | BCLR | BSET | BTST | EXT | + -- Bcc | BSR | CHK | DBcc | JSR | TRAPV | RTR | Scc | STOP | + -- ADDI | ANDI | SUBI | CMPI | EORI | ORI | MULS | MULU, '0' when others; + + FETCH_DEC: process(ADR_MODE_I, ALU_BSY, ALU_COND, AR_IN_USE, BF_BYTES, BIW_0, BIW_1, BRANCH_ATN, DR_IN_USE, EW_ACK, EW_RDY, EXH_REQ, + EXEC_WB_STATE, EXT_WORD, FETCH_STATE, MEM_INDIRECT, MEMADR_RDY, MOVEM_COND, MOVEM_PNTR, MOVEP_PNTR_I, NEXT_EXEC_WB_STATE, + OP, OP_SIZE_I, OP_WB_I, OPD_ACK, OW_RDY, PHASE2, RD_RDY, TRACE_MODE, OD_REQ_32, OD_REQ_16, WR_RDY) + -- ADH: avoid data hazard. + -- ASH: avoid structural hazard. + -- ASH: avoid control hazard. + begin + case FETCH_STATE is + when START_OP => + if OPD_ACK = '0' and OW_RDY = '0' then + NEXT_FETCH_STATE <= START_OP; + -- Debugging: + --elsif OP_TEST = '1' and ALU_BSY = '1' then + -- NEXT_FETCH_STATE <= START_OP; + else + case OP is + when ILLEGAL | RTE | TRAP | UNIMPLEMENTED => + NEXT_FETCH_STATE <= START_OP; + when DBcc | EXT | EXTB | MOVEQ | SWAP => + if DR_IN_USE = '1' then + NEXT_FETCH_STATE <= START_OP; -- Wait, ADH. + else + NEXT_FETCH_STATE <= INIT_EXEC_WB; -- Proceed. + end if; + when ABCD | SBCD | ADDX | SUBX | PACK | UNPK => + if BIW_0(3) = '0' and DR_IN_USE = '0' then -- Check for destination addressing register. ADH. + NEXT_FETCH_STATE <= INIT_EXEC_WB; -- Register to register. + elsif BIW_0(3) = '1' and AR_IN_USE = '0' then -- Check for destination addressing register. ADH. + NEXT_FETCH_STATE <= CALC_AEFF; -- Memory to memory. + else + NEXT_FETCH_STATE <= START_OP; -- Wait, ADH. + end if; + when ADD | ADDI | ADDQ | AND_B | ANDI | CAS | CMP | CMPI | EOR | EORI | + NBCD | NEG | NEGX | NOT_B | OR_B | ORI | SUB | SUBI | SUBQ | TST | TAS => + -- These instructions have to take the destination into aspect + -- because the destination is an ALU operand and may cause data hazards. + case BIW_0(5 downto 3) is + when "000" => -- Dn. + if DR_IN_USE = '0' then + NEXT_FETCH_STATE <= INIT_EXEC_WB; + else + NEXT_FETCH_STATE <= START_OP; + end if; + when "001" => -- An. + if (OP = ADD or OP = SUB or OP = AND_B or OP = EOR or OP = OR_B or OP = CMP) and (AR_IN_USE = '1' or DR_IN_USE = '1')then -- ADH. + NEXT_FETCH_STATE <= START_OP; + elsif AR_IN_USE = '0' then + NEXT_FETCH_STATE <= INIT_EXEC_WB; + else + NEXT_FETCH_STATE <= START_OP; + end if; + when "010" | "011" => -- (An), (An)+. + if AR_IN_USE = '1' then -- ADH. + NEXT_FETCH_STATE <= START_OP; -- Wait, ADH. + else + NEXT_FETCH_STATE <= FETCH_OPERAND; + end if; + when "100" => -- -(An). + if AR_IN_USE = '1' then -- ADH. + NEXT_FETCH_STATE <= START_OP; -- Wait, ADH. + else + NEXT_FETCH_STATE <= CALC_AEFF; + end if; + when "101" => + NEXT_FETCH_STATE <= FETCH_DISPL; + when "110" => + NEXT_FETCH_STATE <= FETCH_EXWORD_1; + when others => -- "111" + if BIW_0(2 downto 0) = "000" then + NEXT_FETCH_STATE <= FETCH_ABS_LO; + elsif BIW_0(2 downto 0) = "001" then + NEXT_FETCH_STATE <= FETCH_ABS_HI; + elsif BIW_0(2 downto 0) = "100" and OP_SIZE_I = LONG then + NEXT_FETCH_STATE <= FETCH_IDATA_B2; + elsif BIW_0(2 downto 0) = "100" then -- Word or byte. + NEXT_FETCH_STATE <= FETCH_IDATA_B1; + elsif BIW_0(2 downto 0) = "010" then + NEXT_FETCH_STATE <= FETCH_DISPL; + else + NEXT_FETCH_STATE <= FETCH_EXWORD_1; + end if; + end case; + when ADDA | BCHG | BCLR | BFCHG | BFCLR | BFEXTS | BFEXTU | BFFFO | BFINS | BFSET | BFTST | BSET | BTST | CHK | CHK2 | CMP2 | CMPA | + DIVS | DIVU | MULS | MULU | MOVEA | MOVE_TO_CCR | MOVE_TO_SR | SUBA => + case BIW_0(5 downto 3) is + when "000" => -- Source is Dn. + if (OP = ADDA or OP = SUBA or OP = CMPA or OP = MOVEA) and (AR_IN_USE = '1' or DR_IN_USE = '1') then -- ADH. + NEXT_FETCH_STATE <= START_OP; + elsif DR_IN_USE = '0' then + NEXT_FETCH_STATE <= INIT_EXEC_WB; + else + NEXT_FETCH_STATE <= START_OP; + end if; + when "001" => -- Valid for ADDA, CMPA, MOVEA, SUBA; source is An. + if AR_IN_USE = '0' then + NEXT_FETCH_STATE <= INIT_EXEC_WB; -- ADH. + else + NEXT_FETCH_STATE <= START_OP; + end if; + when "010" | "011" => -- (An), (An)+. + if AR_IN_USE = '1' then -- ADH. + NEXT_FETCH_STATE <= START_OP; -- Wait, ADH! + else + NEXT_FETCH_STATE <= FETCH_OPERAND; + end if; + when "100" => -- -(An). + if AR_IN_USE = '1' then -- ADH. + NEXT_FETCH_STATE <= START_OP; -- Wait, ADH! + else + NEXT_FETCH_STATE <= CALC_AEFF; + end if; + when "101" => + NEXT_FETCH_STATE <= FETCH_DISPL; + when "110" => + NEXT_FETCH_STATE <= FETCH_EXWORD_1; + when others => -- "111" + if BIW_0(2 downto 0) = "000" then + NEXT_FETCH_STATE <= FETCH_ABS_LO; + elsif BIW_0(2 downto 0) = "001" then + NEXT_FETCH_STATE <= FETCH_ABS_HI; + elsif BIW_0(2 downto 0) = "100" and OP_SIZE_I = LONG then + NEXT_FETCH_STATE <= FETCH_IDATA_B2; + elsif BIW_0(2 downto 0) = "100" then -- Word or Byte. + NEXT_FETCH_STATE <= FETCH_IDATA_B1; + elsif BIW_0(2 downto 0) = "010" then + NEXT_FETCH_STATE <= FETCH_DISPL; + else + NEXT_FETCH_STATE <= FETCH_EXWORD_1; + end if; + end case; + when EXG => + if BIW_0(7 downto 3) = "10001" and (DR_IN_USE = '1' or AR_IN_USE = '1') then + NEXT_FETCH_STATE <= START_OP; -- Wait, ADH. + elsif BIW_0(7 downto 3) = "01000" and DR_IN_USE = '1' then + NEXT_FETCH_STATE <= START_OP; -- Wait, ADH. + elsif BIW_0(7 downto 3) = "01001" and AR_IN_USE = '1' then + NEXT_FETCH_STATE <= START_OP; -- Wait, ADH. + else + NEXT_FETCH_STATE <= INIT_EXEC_WB; + end if; + when NOP => -- Synchronize the instruction pipeline. + if ALU_BSY = '0' and EXEC_WB_STATE = IDLE then + NEXT_FETCH_STATE <= INIT_EXEC_WB; + else + NEXT_FETCH_STATE <= START_OP; + end if; + when MOVE_FROM_CCR | MOVE_FROM_SR => + if ALU_BSY = '0' then + case BIW_0(5 downto 3) is + when "000" => -- Destination is Dn. + if DR_IN_USE = '0' then + NEXT_FETCH_STATE <= INIT_EXEC_WB; + else + NEXT_FETCH_STATE <= START_OP; + end if; + when "010" | "011" | "100" => -- (An), (An)+, -(An). + if AR_IN_USE = '0' then + NEXT_FETCH_STATE <= INIT_EXEC_WB; + else + NEXT_FETCH_STATE <= START_OP; -- Wait, ADH. + end if; + when "101" => + NEXT_FETCH_STATE <= FETCH_DISPL; + when "110" => + NEXT_FETCH_STATE <= FETCH_EXWORD_1; + when others => -- "111" + if BIW_0(2 downto 0) = "000" then + NEXT_FETCH_STATE <= FETCH_ABS_LO; + else + NEXT_FETCH_STATE <= FETCH_ABS_HI; + end if; + end case; + else + NEXT_FETCH_STATE <= START_OP; + end if; + when ASL | ASR | LSL | LSR | ROTL | ROTR | ROXL | ROXR => + if BIW_0(7 downto 6) /= "11" then -- Register shifts. + if DR_IN_USE = '0' then + NEXT_FETCH_STATE <= INIT_EXEC_WB; -- ADH. + else + NEXT_FETCH_STATE <= START_OP; + end if; + else -- Memory shifts. + case BIW_0(5 downto 3) is + when "010" | "011" => -- (An), (An)+. + if AR_IN_USE = '0' then -- ADH. + NEXT_FETCH_STATE <= FETCH_OPERAND; + else + NEXT_FETCH_STATE <= START_OP; + end if; + when "100" => -- -(An). + if AR_IN_USE = '0' then -- ADH. + NEXT_FETCH_STATE <= CALC_AEFF; + else + NEXT_FETCH_STATE <= START_OP; + end if; + when "101" => + NEXT_FETCH_STATE <= FETCH_DISPL; + when "110" => + NEXT_FETCH_STATE <= FETCH_EXWORD_1; + when others => -- "111". + if BIW_0(2 downto 0) = "000" then + NEXT_FETCH_STATE <= FETCH_ABS_LO; + else + NEXT_FETCH_STATE <= FETCH_ABS_HI; + end if; + end case; + end if; + when BKPT => + -- Wait until the bus controller is free to avoid a structural + -- hazard due to the top level function code multiplexer which + -- switches on the CPU_SPACE selector. + if ALU_BSY = '0' then + NEXT_FETCH_STATE <= FETCH_OPERAND; + else + NEXT_FETCH_STATE <= START_OP; + end if; + when CAS2 | CMPM | RTD | RTR | RTS => + if AR_IN_USE = '0' then -- ADH. + NEXT_FETCH_STATE <= FETCH_OPERAND; + else + NEXT_FETCH_STATE <= START_OP; + end if; + when CLR | JMP | JSR | LEA | PEA | Scc => -- No read access required. + case BIW_0(5 downto 3) is + when "000" => -- CLR, Scc. + if DR_IN_USE = '0' then + NEXT_FETCH_STATE <= INIT_EXEC_WB; + else + NEXT_FETCH_STATE <= START_OP; + end if; + when "001" | "010" | "011" | "100" => + if AR_IN_USE = '1' then + NEXT_FETCH_STATE <= START_OP; -- Wait, ADH. + elsif OP = LEA or OP = PEA then + NEXT_FETCH_STATE <= SWITCH_STATE; + else + NEXT_FETCH_STATE <= INIT_EXEC_WB; + end if; + when "101" => + NEXT_FETCH_STATE <= FETCH_DISPL; + when "110" => + NEXT_FETCH_STATE <= FETCH_EXWORD_1; + when others => -- "111" + if BIW_0(2 downto 0) = "000" then + NEXT_FETCH_STATE <= FETCH_ABS_LO; + elsif BIW_0(2 downto 0) = "001" then + NEXT_FETCH_STATE <= FETCH_ABS_HI; + elsif BIW_0(2 downto 0) = "010" then + NEXT_FETCH_STATE <= FETCH_DISPL; + else + NEXT_FETCH_STATE <= FETCH_EXWORD_1; + end if; + end case; + -- + -- The following condition is a special case for the + -- stack manipulating operations JSR and PEA. If A7 + -- is in use, we have to wait in all addressing modes. + if (OP = JSR or OP = PEA) and AR_IN_USE = '1' then + NEXT_FETCH_STATE <= START_OP; -- Wait, ADH. + end if; + when LINK | UNLK => + -- We have to wait for the ALU because the registers are written without pipelining + -- through the ALU and the stack is decremented early. For PEA we have to wait in + -- all addressing modes, if A7 is in use. + if OP = LINK and (ALU_BSY = '1' or AR_IN_USE = '1') then + NEXT_FETCH_STATE <= START_OP; -- Wait, ADH, ASH (two address registers are affected). + elsif OP = UNLK and ALU_BSY = '1' then + NEXT_FETCH_STATE <= START_OP; -- Wait, ADH, ASH (two address registers are affected). + else + NEXT_FETCH_STATE <= SWITCH_STATE; -- Stack pointer is decremented in this state. + end if; + when MOVE => + case BIW_0(5 downto 3) is -- Source operand. + when "000" => -- Dn. + -- Destination is -(An) and will be decremented here, wait. + if BIW_0(8 downto 6) = "100" and (AR_IN_USE = '1' or DR_IN_USE = '1') then + NEXT_FETCH_STATE <= START_OP; + elsif DR_IN_USE = '1' then + NEXT_FETCH_STATE <= START_OP; + else + NEXT_FETCH_STATE <= INIT_EXEC_WB; + end if; + when "001" => -- An. + if AR_IN_USE = '1' then + NEXT_FETCH_STATE <= START_OP; + else + NEXT_FETCH_STATE <= INIT_EXEC_WB; + end if; + when "010" | "011" => -- (An), (An)+. + if AR_IN_USE = '0' then + NEXT_FETCH_STATE <= FETCH_OPERAND; + else + NEXT_FETCH_STATE <= START_OP; + end if; + when "100" => -- -(An). + if AR_IN_USE = '0' then + NEXT_FETCH_STATE <= CALC_AEFF; + else + NEXT_FETCH_STATE <= START_OP; + end if; + when "101" => + NEXT_FETCH_STATE <= FETCH_DISPL; + when "110" => + NEXT_FETCH_STATE <= FETCH_EXWORD_1; + when others => + if BIW_0(2 downto 0) = "000" then + NEXT_FETCH_STATE <= FETCH_ABS_LO; + elsif BIW_0(2 downto 0) = "001" then + NEXT_FETCH_STATE <= FETCH_ABS_HI; + elsif BIW_0(2 downto 0) = "100" and BIW_0(13 downto 12) = "10" then -- Long. + NEXT_FETCH_STATE <= FETCH_IDATA_B2; + elsif BIW_0(2 downto 0) = "100" then -- Word or Byte. + NEXT_FETCH_STATE <= FETCH_IDATA_B1; + elsif BIW_0(2 downto 0) = "010" then + NEXT_FETCH_STATE <= FETCH_DISPL; + else + NEXT_FETCH_STATE <= FETCH_EXWORD_1; + end if; + end case; + when MOVEM => + case BIW_0(5 downto 3) is + when "010" | "011" | "100" => -- (An), (An)+, -(An). + if AR_IN_USE = '1' then -- ADH. + NEXT_FETCH_STATE <= START_OP; + else + NEXT_FETCH_STATE <= INIT_EXEC_WB; + end if; + when "101" => + NEXT_FETCH_STATE <= FETCH_DISPL; + when "110" => + NEXT_FETCH_STATE <= FETCH_EXWORD_1; + when others => + if BIW_0(2 downto 0) = "000" then + NEXT_FETCH_STATE <= FETCH_ABS_LO; + elsif BIW_0(2 downto 0) = "001" then + NEXT_FETCH_STATE <= FETCH_ABS_HI; + elsif BIW_0(2 downto 0) = "010" then + NEXT_FETCH_STATE <= FETCH_DISPL; + else + NEXT_FETCH_STATE <= FETCH_EXWORD_1; + end if; + end case; + when MOVEP => + if AR_IN_USE = '0' and BIW_0(7 downto 6) < "10" then + NEXT_FETCH_STATE <= SWITCH_STATE; -- Memory to register. + elsif AR_IN_USE = '0' and DR_IN_USE = '0' then -- ADH. + NEXT_FETCH_STATE <= SWITCH_STATE; -- Register to memory. + else + NEXT_FETCH_STATE <= START_OP; + end if; + when BSR | MOVE_USP => + -- MOVE_USP: wait until A7 has been updated to load the correct data to the ALU. + -- BSR: wait until A7 has been updated before decrementing. + if AR_IN_USE = '0' then -- ADH. + NEXT_FETCH_STATE <= INIT_EXEC_WB; + else + NEXT_FETCH_STATE <= START_OP; + end if; + when MOVEC => + if BIW_0(0) = '1' and BIW_1(15) = '1' and AR_IN_USE = '1' then -- Address register is source. + NEXT_FETCH_STATE <= START_OP; -- Wait, ADH. + elsif BIW_0(0) = '1' and BIW_1(15) = '0' and DR_IN_USE = '1' then -- Data register is source. + NEXT_FETCH_STATE <= START_OP; -- Wait, ADH. + else + NEXT_FETCH_STATE <= INIT_EXEC_WB; + end if; + when MOVES => + case BIW_0(5 downto 3) is + when "010" | "011" => -- (An), (An)+. + if BIW_1(11) = '0' and AR_IN_USE = '0' then -- ADH. + NEXT_FETCH_STATE <= FETCH_OPERAND; -- Memory to register. + elsif BIW_1(11) = '1' and AR_IN_USE = '0' then -- ADH. + NEXT_FETCH_STATE <= INIT_EXEC_WB; -- Register to memory. + else + NEXT_FETCH_STATE <= START_OP; -- Wait, ADH. + end if; + when "100" => -- -(An). + if BIW_1(11) = '0' and AR_IN_USE = '0' then -- ADH. + NEXT_FETCH_STATE <= CALC_AEFF; -- Memory to register. + elsif BIW_1(11) = '1' and AR_IN_USE = '0' then -- ADH. + NEXT_FETCH_STATE <= INIT_EXEC_WB; -- Register to memory. + else + NEXT_FETCH_STATE <= START_OP; -- Wait, ADH. + end if; + when "101" => + NEXT_FETCH_STATE <= FETCH_DISPL; + when "110" => + NEXT_FETCH_STATE <= FETCH_EXWORD_1; + when others => -- "111" + if BIW_0(2 downto 0) = "000" then + NEXT_FETCH_STATE <= FETCH_ABS_LO; + else + NEXT_FETCH_STATE <= FETCH_ABS_HI; + end if; + end case; + -- Register to memory: + if BIW_1(11) = '1' and BIW_1(15) = '1' and AR_IN_USE = '1' then -- ADH. + NEXT_FETCH_STATE <= START_OP; + elsif BIW_1(11) = '1' and BIW_1(15) = '0' and DR_IN_USE = '1' then -- ADH. + NEXT_FETCH_STATE <= START_OP; + end if; + when ANDI_TO_CCR | ANDI_TO_SR | EORI_TO_CCR | EORI_TO_SR | ORI_TO_CCR | ORI_TO_SR | RESET => + -- Wait until the status register / condition codes have been updated. Otherwise we + -- possibly have a data hazard using the wrong condition codes for the operation. + -- Be aware: for the ANDI_TO_SR, EORI_TO_SR, MOVE_TO_SR and ORI_TOI_SR operations + -- the pipe flush results in automatically aligned condition codes. Nevertheless + -- we need this logic for the respective operations, if the pipe is not flushed, + -- in the case of non changing RAM space. + -- For the RESET: we should not reset in running writeback cycles. + if ALU_BSY = '1' then + NEXT_FETCH_STATE <= START_OP; + else + NEXT_FETCH_STATE <= INIT_EXEC_WB; + end if; + when others => -- Bcc, BRA, STOP, TRAPV. + NEXT_FETCH_STATE <= INIT_EXEC_WB; + end case; + end if; + when FETCH_DISPL => + case OP is + when ADD | CMP | SUB | AND_B | EOR | OR_B => + if (EW_ACK = '1' or EW_RDY = '1') and AR_IN_USE = '0' then -- ADH. + NEXT_FETCH_STATE <= CALC_AEFF; + else + NEXT_FETCH_STATE <= FETCH_DISPL; + end if; + when ADDA | BCHG | BCLR | BFCHG | BFCLR | BFEXTS | BFEXTU | BFFFO | BFINS | BFSET | BFTST | BSET | BTST | CHK | CHK2 | CMP2 | CMPA | DIVS | DIVU | MULS | MULU | MOVE | MOVEA | MOVE_TO_CCR | MOVE_TO_SR | SUBA => + if (EW_ACK = '1' or EW_RDY = '1') and OP = MOVE and PHASE2 = true and AR_IN_USE = '0' then -- ADH. + NEXT_FETCH_STATE <= INIT_EXEC_WB; + elsif (EW_ACK = '1' or EW_RDY = '1') and AR_IN_USE = '0' then -- ADH. + NEXT_FETCH_STATE <= CALC_AEFF; + else + NEXT_FETCH_STATE <= FETCH_DISPL; + end if; + when ADDI | ADDQ | ANDI | CAS | CMPI | EORI | NBCD | NEG | NEGX | NOT_B | ORI | SUBI | SUBQ | TST | TAS | ASL | ASR | LSL | LSR | ROTL | ROTR | ROXL | ROXR => + if (EW_ACK = '1' or EW_RDY = '1') and AR_IN_USE = '0' then -- ADH. + NEXT_FETCH_STATE <= CALC_AEFF; + else + NEXT_FETCH_STATE <= FETCH_DISPL; + end if; + when MOVES => + if (EW_ACK = '1' or EW_RDY = '1') and AR_IN_USE = '0' and BIW_1(11) = '0' then + NEXT_FETCH_STATE <= CALC_AEFF; + elsif (EW_ACK = '1' or EW_RDY = '1') and AR_IN_USE = '0' then + NEXT_FETCH_STATE <= INIT_EXEC_WB; + else + NEXT_FETCH_STATE <= FETCH_DISPL; + end if; + when LEA | PEA => + if (EW_ACK = '1' or EW_RDY = '1') and AR_IN_USE = '0' then -- ADH. + NEXT_FETCH_STATE <= SWITCH_STATE; + else + NEXT_FETCH_STATE <= FETCH_DISPL; + end if; + when others => -- CLR, JMP, JSR, MOVE_FROM_CCR, MOVE_FROM_SR, MOVEM, Scc. + if (EW_ACK = '1' or EW_RDY = '1') and AR_IN_USE = '0' then -- ADH. + NEXT_FETCH_STATE <= INIT_EXEC_WB; + else + NEXT_FETCH_STATE <= FETCH_DISPL; + end if; + end case; + when FETCH_EXWORD_1 => + -- Be aware that the An registers which will be addressed by EXWORD_1 and are used for several addressing modes + -- are valid right after this state (because every address register manipulation requires no more than two clock cycles). + if EW_ACK = '1' and EXT_WORD(8) = '1' and EXT_WORD(5 downto 4) = "11" then -- 32 bit displacement. + NEXT_FETCH_STATE <= FETCH_D_HI; + elsif EW_ACK = '1' and EXT_WORD(8) = '1' and EXT_WORD(5 downto 4) = "10" then -- 16 bit displacement. + NEXT_FETCH_STATE <= FETCH_D_LO; + elsif EW_ACK = '1' and EXT_WORD(8) = '1' and EXT_WORD(5 downto 4) = "00" then -- Reserved. + NEXT_FETCH_STATE <= START_OP; + elsif EW_ACK = '1' and EXT_WORD(8) = '1' and EXT_WORD(1 downto 0) = "11" then + NEXT_FETCH_STATE <= FETCH_OD_HI; -- Long outer displacement. + elsif EW_ACK = '1' and EXT_WORD(8) = '1' and EXT_WORD(1 downto 0) = "10" then + NEXT_FETCH_STATE <= FETCH_OD_LO; -- Word outer displacement. + elsif EW_ACK = '1' and EXT_WORD(8) = '1' and EXT_WORD(1 downto 0) = "01" then + NEXT_FETCH_STATE <= FETCH_MEMADR; -- Null outer displacement, go to intermediate address. + elsif EW_ACK = '1' or EW_RDY = '1' then -- Null displacement, no outer displacement. + case OP is + when ADD | CMP | SUB | AND_B | EOR | OR_B => + if (BIW_1(15) = '0' and AR_IN_USE = '0' and DR_IN_USE = '0') or (BIW_1(15) = '1' and AR_IN_USE = '0') then -- ADH. + NEXT_FETCH_STATE <= CALC_AEFF; + else + NEXT_FETCH_STATE <= FETCH_EXWORD_1; + end if; + when ADDA | BCHG | BCLR | BFCHG | BFCLR | BFEXTS | BFEXTU | BFFFO | BFINS | BFSET | BFTST | BSET | BTST | CHK | CHK2 | CMP2 | CMPA | DIVS | DIVU | MULS | MULU | MOVE | MOVEA | MOVE_TO_CCR | MOVE_TO_SR | SUBA => + if OP = MOVE and PHASE2 = true and BIW_1(15) = '0' and AR_IN_USE = '0' and DR_IN_USE = '0' then -- ADH. + NEXT_FETCH_STATE <= INIT_EXEC_WB; + elsif OP = MOVE and PHASE2 = true and BIW_1(15) = '1' and AR_IN_USE = '0' then -- ADH. + NEXT_FETCH_STATE <= INIT_EXEC_WB; + elsif (BIW_1(15) = '0' and AR_IN_USE = '0' and DR_IN_USE = '0') or (BIW_1(15) = '1' and AR_IN_USE = '0') then -- ADH. + NEXT_FETCH_STATE <= CALC_AEFF; + else + NEXT_FETCH_STATE <= FETCH_EXWORD_1; + end if; + when MOVES => + if (BIW_1(15) = '0' and AR_IN_USE = '0' and DR_IN_USE = '0') or (BIW_1(15) = '1' and AR_IN_USE = '0') then -- ADH. + if BIW_1(11) = '0' then + NEXT_FETCH_STATE <= CALC_AEFF; + else + NEXT_FETCH_STATE <= INIT_EXEC_WB; + end if; + else + NEXT_FETCH_STATE <= FETCH_EXWORD_1; + end if; + when ADDI | ADDQ | ANDI | CAS | CMPI | EORI | NBCD | NEG | NEGX | NOT_B | ORI | SUBI | SUBQ | TST | TAS | ASL | ASR | LSL | LSR | ROTL | ROTR | ROXL | ROXR => + if (BIW_1(15) = '0' and AR_IN_USE = '0' and DR_IN_USE = '0') or (BIW_1(15) = '1' and AR_IN_USE = '0') then -- ADH. + NEXT_FETCH_STATE <= CALC_AEFF; + else + NEXT_FETCH_STATE <= FETCH_EXWORD_1; + end if; + when LEA | PEA => + if (BIW_1(15) = '0' and AR_IN_USE = '0' and DR_IN_USE = '0') or (BIW_1(15) = '1' and AR_IN_USE = '0') then -- ADH. + NEXT_FETCH_STATE <= SWITCH_STATE; + else + NEXT_FETCH_STATE <= FETCH_EXWORD_1; + end if; + when others => -- CLR, JMP, JSR, MOVE_FROM_CCR, MOVE_FROM_SR, MOVEM, Scc. + if (BIW_1(15) = '0' and AR_IN_USE = '0' and DR_IN_USE = '0') or (BIW_1(15) = '1' and AR_IN_USE = '0') then -- ADH. + NEXT_FETCH_STATE <= INIT_EXEC_WB; + else + NEXT_FETCH_STATE <= FETCH_EXWORD_1; + end if; + end case; + else + NEXT_FETCH_STATE <= FETCH_EXWORD_1; + end if; + when FETCH_D_HI => + if EW_ACK = '1' then + NEXT_FETCH_STATE <= FETCH_D_LO; + else + NEXT_FETCH_STATE <= FETCH_D_HI; + end if; + when FETCH_D_LO => + if EW_ACK = '1' and OD_REQ_32 = '1' then + NEXT_FETCH_STATE <= FETCH_OD_HI; + elsif EW_ACK = '1' and OD_REQ_16 = '1' then + NEXT_FETCH_STATE <= FETCH_OD_LO; + elsif EW_ACK = '1' and MEM_INDIRECT = '1' then -- Null displacement. + NEXT_FETCH_STATE <= FETCH_MEMADR; + elsif EW_ACK = '1' or EW_RDY = '1' then + case OP is + when ADD | CMP | SUB | AND_B | EOR | OR_B => + if AR_IN_USE = '0' then -- ADH. + NEXT_FETCH_STATE <= CALC_AEFF; + else + NEXT_FETCH_STATE <= FETCH_D_LO; + end if; + when ADDA | BCHG | BCLR | BFCHG | BFCLR | BFEXTS | BFEXTU | BFFFO | BFINS | BFSET | BFTST | BSET | BTST | CHK | CHK2| CMP2 | CMPA | DIVS | DIVU | MULS | MULU | MOVE | MOVEA | MOVE_TO_CCR | MOVE_TO_SR | SUBA => + if OP = MOVE and PHASE2 = true and AR_IN_USE = '0' then -- ADH. + NEXT_FETCH_STATE <= INIT_EXEC_WB; + elsif AR_IN_USE = '0' then -- ADH. + NEXT_FETCH_STATE <= CALC_AEFF; + else + NEXT_FETCH_STATE <= FETCH_D_LO; + end if; + when MOVES => + if AR_IN_USE = '1' then -- ADH. + NEXT_FETCH_STATE <= FETCH_D_LO; -- Wait, ADH. + elsif BIW_1(11) = '0' then + NEXT_FETCH_STATE <= CALC_AEFF; + else + NEXT_FETCH_STATE <= INIT_EXEC_WB; + end if; + when ADDI | ADDQ | ANDI | CAS | CMPI | EORI | NBCD | NEG | NEGX | NOT_B | ORI | SUBI | SUBQ | TST | TAS | ASL | ASR | LSL | LSR | ROTL | ROTR | ROXL | ROXR => + if AR_IN_USE = '0' then -- ADH. + NEXT_FETCH_STATE <= CALC_AEFF; + else + NEXT_FETCH_STATE <= FETCH_D_LO; + end if; + when LEA | PEA => + if AR_IN_USE = '0' then -- ADH. + NEXT_FETCH_STATE <= SWITCH_STATE; + else + NEXT_FETCH_STATE <= FETCH_D_LO; + end if; + when others => -- CLR, JMP, JSR, MOVE_FROM_CCR, MOVE_FROM_SR, MOVEM, Scc. + if AR_IN_USE = '0' then -- ADH. + NEXT_FETCH_STATE <= INIT_EXEC_WB; + else + NEXT_FETCH_STATE <= FETCH_D_LO; + end if; + end case; + else + NEXT_FETCH_STATE <= FETCH_D_LO; + end if; + when FETCH_OD_HI => + if EW_ACK = '1' then + NEXT_FETCH_STATE <= FETCH_OD_LO; + else + NEXT_FETCH_STATE <= FETCH_OD_HI; + end if; + when FETCH_OD_LO => + if EW_ACK = '1' then + NEXT_FETCH_STATE <= FETCH_MEMADR; + else + NEXT_FETCH_STATE <= FETCH_OD_LO; + end if; + when FETCH_MEMADR => + if RD_RDY = '1' or MEMADR_RDY = '1' then + case OP is + when ADD | CMP | SUB | AND_B | EOR | OR_B => + if AR_IN_USE = '0' then -- ADH. + NEXT_FETCH_STATE <= CALC_AEFF; + else + NEXT_FETCH_STATE <= FETCH_MEMADR; + end if; + when ADDA | BCHG | BCLR | BFCHG | BFCLR | BFEXTS | BFEXTU | BFFFO | BFINS | BFSET | BFTST | BSET | BTST | CHK | CHK2| CMP2 | CMPA | DIVS | DIVU | MULS | MULU | MOVE | MOVEA | MOVE_TO_CCR | MOVE_TO_SR | SUBA => + if OP = MOVE and PHASE2 = true and AR_IN_USE = '0' then -- ADH. + NEXT_FETCH_STATE <= INIT_EXEC_WB; + elsif AR_IN_USE = '0' then -- ADH. + NEXT_FETCH_STATE <= CALC_AEFF; + else + NEXT_FETCH_STATE <= FETCH_MEMADR; + end if; + when MOVES => + if AR_IN_USE = '1' then -- ADH. + NEXT_FETCH_STATE <= FETCH_MEMADR; -- Wait, ADH. + elsif BIW_1(11) = '0' then + NEXT_FETCH_STATE <= CALC_AEFF; + else + NEXT_FETCH_STATE <= INIT_EXEC_WB; + end if; + when ADDI | ADDQ | ANDI | CAS | CMPI | EORI | NBCD | NEG | NEGX | NOT_B | ORI | SUBI | SUBQ | TST | TAS | ASL | ASR | LSL | LSR | ROTL | ROTR | ROXL | ROXR => + if AR_IN_USE = '0' then -- ADH. + NEXT_FETCH_STATE <= CALC_AEFF; + else + NEXT_FETCH_STATE <= FETCH_MEMADR; + end if; + when LEA | PEA => + if AR_IN_USE = '0' then -- ADH. + NEXT_FETCH_STATE <= SWITCH_STATE; + else + NEXT_FETCH_STATE <= FETCH_MEMADR; + end if; + when others => -- CLR, JMP, JSR, MOVE_FROM_CCR, MOVE_FROM_SR, MOVEM, Scc. + if AR_IN_USE = '0' then -- ADH. + NEXT_FETCH_STATE <= INIT_EXEC_WB; + else + NEXT_FETCH_STATE <= FETCH_MEMADR; + end if; + end case; + else + NEXT_FETCH_STATE <= FETCH_MEMADR; + end if; + when FETCH_ABS_HI => + if EW_ACK = '1' then + NEXT_FETCH_STATE <= FETCH_ABS_LO; + else + NEXT_FETCH_STATE <= FETCH_ABS_HI; + end if; + when FETCH_ABS_LO => + if EW_ACK = '1' then + case OP is + when CLR | JMP | JSR | MOVE_FROM_CCR | MOVE_FROM_SR | MOVEM | Scc => + NEXT_FETCH_STATE <= INIT_EXEC_WB; + when LEA | PEA => + NEXT_FETCH_STATE <= SWITCH_STATE; + when MOVE => + if PHASE2 = false then + NEXT_FETCH_STATE <= CALC_AEFF; + else + NEXT_FETCH_STATE <= INIT_EXEC_WB; + end if; + when MOVES => + if BIW_1(11) = '0' then + NEXT_FETCH_STATE <= CALC_AEFF; + else + NEXT_FETCH_STATE <= INIT_EXEC_WB; + end if; + when others => + NEXT_FETCH_STATE <= CALC_AEFF; + end case; + else + NEXT_FETCH_STATE <= FETCH_ABS_LO; + end if; + when FETCH_IDATA_B2 => + if EW_ACK = '1' then + NEXT_FETCH_STATE <= FETCH_IDATA_B1; + else + NEXT_FETCH_STATE <= FETCH_IDATA_B2; + end if; + when FETCH_IDATA_B1 => + if EW_ACK = '1' or EW_RDY = '1' then + case OP is -- ADH. + when ADD | SUB | AND_B | OR_B | BTST | DIVS | DIVU | MULS | MULU | CHK | MOVE => + NEXT_FETCH_STATE <= SWITCH_STATE; + when ADDA | CMPA | SUBA | MOVEA => + NEXT_FETCH_STATE <= SWITCH_STATE; + when others => + if DR_IN_USE = '1' then -- ADH. + NEXT_FETCH_STATE <= FETCH_IDATA_B1; + else + NEXT_FETCH_STATE <= INIT_EXEC_WB; + end if; + end case; + else + NEXT_FETCH_STATE <= FETCH_IDATA_B1; + end if; + when CALC_AEFF => + NEXT_FETCH_STATE <= FETCH_OPERAND; -- One CLK calculation delay. + when FETCH_OPERAND => + if RD_RDY = '1' then + case OP is + when ABCD | ADDX | SBCD | SUBX => + if PHASE2 = false then + NEXT_FETCH_STATE <= CALC_AEFF; + else + NEXT_FETCH_STATE <= INIT_EXEC_WB; + end if; + when ADD | CMP | CHK | SUB | AND_B | EOR | OR_B | BCHG | BCLR | BSET | BTST | DIVS | DIVU | MULS | MULU => + if DR_IN_USE = '1' then + NEXT_FETCH_STATE <= SWITCH_STATE; + else + NEXT_FETCH_STATE <= INIT_EXEC_WB; + end if; + when ADDA | CMPA | SUBA => + if BIW_0(11 downto 9) = BIW_0(2 downto 0) and ADR_MODE_I = "011" then + NEXT_FETCH_STATE <= SWITCH_STATE; -- Postincrement (Ax)+, AX; wait before loading the ALU. + else + NEXT_FETCH_STATE <= INIT_EXEC_WB; + end if; + when BFCHG | BFCLR | BFEXTS | BFEXTU | BFFFO | BFINS | BFSET | BFTST => + if BF_BYTES = 5 then -- Another Byte required. + NEXT_FETCH_STATE <= CALC_AEFF; + else + NEXT_FETCH_STATE <= INIT_EXEC_WB; + end if; + when MOVE => + if BIW_0(8 downto 6) = "100" and ADR_MODE_I = "011" then -- (An)+,-(An). + NEXT_FETCH_STATE <= SWITCH_STATE; + else + NEXT_FETCH_STATE <= INIT_EXEC_WB; + end if; + when others => + NEXT_FETCH_STATE <= INIT_EXEC_WB; + end case; + else + NEXT_FETCH_STATE <= FETCH_OPERAND; + end if; + when SWITCH_STATE => -- This state is used individually by several operations. + case OP is + when ADDA | CMPA | SUBA | MOVEA => -- Address register operations. + if AR_IN_USE = '0' then + NEXT_FETCH_STATE <= INIT_EXEC_WB; + else + NEXT_FETCH_STATE <= SWITCH_STATE; + end if; + when LEA | LINK | MOVE => + -- LEA: calculate effective address (1 clock cycle) load it in INIT_EXEC_WB. + -- LINK: used to load the decremented stack pointer. + -- MOVE: Used for (An)+,-(An). address mode. + NEXT_FETCH_STATE <= INIT_EXEC_WB; + when UNLK => -- SP is updated here. + NEXT_FETCH_STATE <= CALC_AEFF; + when MOVEM => -- MOVEM requires 1 CLK cycle for address calculation. + if MOVEM_COND = false then + NEXT_FETCH_STATE <= INIT_EXEC_WB; -- Cancel bus access. + else + NEXT_FETCH_STATE <= CALC_AEFF; + end if; + when MOVEP => -- Register select and displacement update. + if DR_IN_USE = '0' and BIW_0(7 downto 6) < "10" then + NEXT_FETCH_STATE <= CALC_AEFF; + elsif DR_IN_USE = '0' and ALU_BSY = '0' then -- ASH. + NEXT_FETCH_STATE <= INIT_EXEC_WB; -- Register to memory. + else + NEXT_FETCH_STATE <= SWITCH_STATE; + end if; + when PEA => + -- PEA requires two clock cycles here for effective adress calculation because it + -- is loaded early. The first clock cycle the address becomes valid and after the + -- second the address is loaded to the ALU for writing on the stack. + if PHASE2 = false then + NEXT_FETCH_STATE <= SWITCH_STATE; + else + NEXT_FETCH_STATE <= INIT_EXEC_WB; + end if; + when others => -- Data register operations. + if DR_IN_USE = '0' then + NEXT_FETCH_STATE <= INIT_EXEC_WB; + else + NEXT_FETCH_STATE <= SWITCH_STATE; + end if; + end case; + when INIT_EXEC_WB => + case OP is + when ANDI_TO_SR | EORI_TO_SR | MOVE_TO_SR | ORI_TO_SR => + if ALU_BSY = '0' and BRANCH_ATN = '1' then + NEXT_FETCH_STATE <= SLEEP; -- Wait for new processor context. + elsif ALU_BSY = '0' then + NEXT_FETCH_STATE <= START_OP; -- Proceed normally. + else + NEXT_FETCH_STATE <= INIT_EXEC_WB; + end if; + when Bcc | CHK | DBcc | JMP | TRAPcc | TRAPV => + if ALU_BSY = '0' then + NEXT_FETCH_STATE <= SLEEP; -- Check conditions. + else + NEXT_FETCH_STATE <= INIT_EXEC_WB; + end if; + when CAS | JSR | MOVEC | TAS => + -- CAS, TAS provide a RMC operation so have to sleep a little bit ;-) + if ALU_BSY = '0' then + NEXT_FETCH_STATE <= SLEEP; + else + NEXT_FETCH_STATE <= INIT_EXEC_WB; + end if; + when BRA | BSR | RTD | RTS => + if ALU_BSY = '0' then + NEXT_FETCH_STATE <= START_OP; + else + NEXT_FETCH_STATE <= INIT_EXEC_WB; + end if; + when BFCHG | BFCLR | BFINS | BFSET => + if ALU_BSY = '0' and BF_BYTES < 5 then + NEXT_FETCH_STATE <= START_OP; + elsif ALU_BSY = '0' then + NEXT_FETCH_STATE <= SLEEP; + else + NEXT_FETCH_STATE <= INIT_EXEC_WB; -- Wait, ASH. + end if; + when CAS2 => -- RMC operation. + if ALU_BSY = '0' and PHASE2 = false then + NEXT_FETCH_STATE <= CALC_AEFF; -- Second compare. + elsif ALU_BSY = '0' then + NEXT_FETCH_STATE <= SLEEP; + else + NEXT_FETCH_STATE <= INIT_EXEC_WB; + end if; + when CHK2 => + if ALU_BSY = '0' and PHASE2 = false then + NEXT_FETCH_STATE <= FETCH_OPERAND; -- Second compare required? + elsif ALU_BSY = '0' then -- ASH. + NEXT_FETCH_STATE <= SLEEP; + else + NEXT_FETCH_STATE <= INIT_EXEC_WB; + end if; + when CMP2 | CMPM => + if ALU_BSY = '0' and PHASE2 = false then + NEXT_FETCH_STATE <= FETCH_OPERAND; -- Second compare required? + elsif ALU_BSY = '0' then -- ASH. + NEXT_FETCH_STATE <= START_OP; + else + NEXT_FETCH_STATE <= INIT_EXEC_WB; + end if; + when MOVE_USP => + if ALU_BSY = '0' and BIW_0(3) = '0' then -- An to USP. + NEXT_FETCH_STATE <= SLEEP; + elsif ALU_BSY = '0' then + NEXT_FETCH_STATE <= START_OP; -- USP to An. + else + NEXT_FETCH_STATE <= INIT_EXEC_WB; + end if; + when MOVE => + if ALU_BSY = '0' and PHASE2 = false then -- Load the Operand into the ALU here. + case BIW_0(8 downto 6) is -- Destination operand. + when "101" => + NEXT_FETCH_STATE <= FETCH_DISPL; + when "110" => + NEXT_FETCH_STATE <= FETCH_EXWORD_1; + when "111" => + if BIW_0(11 downto 9) = "000" then + NEXT_FETCH_STATE <= FETCH_ABS_LO; + else + NEXT_FETCH_STATE <= FETCH_ABS_HI; + end if; + when others => -- No destination address calculation required. + NEXT_FETCH_STATE <= START_OP; + end case; + elsif PHASE2 = true then -- ALU is not required at this point. + NEXT_FETCH_STATE <= START_OP; + else + NEXT_FETCH_STATE <= INIT_EXEC_WB; + end if; + when MOVEM => + if ALU_BSY = '0' and BIW_0(10) = '0' and ADR_MODE_I = "100" and MOVEM_PNTR = x"0" then -- -(An), register to memory. + NEXT_FETCH_STATE <= SLEEP; -- Data completely transfered to the ALU. + elsif ALU_BSY = '0' and BIW_0(10) = '0' and ADR_MODE_I /= "100" and MOVEM_PNTR = x"F" then -- Register to memory + NEXT_FETCH_STATE <= SLEEP; -- Data completely transfered to the ALU. + elsif ALU_BSY = '0' and BIW_0(10) = '1' and MOVEM_PNTR = x"F" then -- Memory to register. + NEXT_FETCH_STATE <= SLEEP; -- Data completely transfered to the ALU. + elsif ALU_BSY = '0' and BIW_0(10) = '1' then -- Memory to register. + NEXT_FETCH_STATE <= SWITCH_STATE; + else + NEXT_FETCH_STATE <= INIT_EXEC_WB; -- Register to memory. + end if; + when MOVEP => + if ALU_BSY = '0' and MOVEP_PNTR_I = 0 then + NEXT_FETCH_STATE <= START_OP; -- Ready. + elsif ALU_BSY = '0' and BIW_0(7 downto 6) < "10" then + NEXT_FETCH_STATE <= CALC_AEFF; -- Memory to register. + else + NEXT_FETCH_STATE <= INIT_EXEC_WB; -- Register to memory. + end if; + when NOP => + if ALU_BSY = '1' then -- ASH. + NEXT_FETCH_STATE <= INIT_EXEC_WB; -- Wait for all pending bus cycles to be completed. + else + NEXT_FETCH_STATE <= START_OP; + end if; + when RTR => + if ALU_BSY = '0' and PHASE2 = false then + NEXT_FETCH_STATE <= CALC_AEFF; + elsif ALU_BSY = '0' and PHASE2 = true then + NEXT_FETCH_STATE <= START_OP; + else + NEXT_FETCH_STATE <= INIT_EXEC_WB; + end if; + when STOP => + if ALU_BSY = '0' then -- ASH. + NEXT_FETCH_STATE <= SLEEP; + else + NEXT_FETCH_STATE <= INIT_EXEC_WB; + end if; + when UNLK => + if ALU_BSY = '0' and AR_IN_USE = '0' then -- ADH, ASH. + NEXT_FETCH_STATE <= START_OP; + else + NEXT_FETCH_STATE <= INIT_EXEC_WB; + end if; + when others => + if ALU_BSY = '0' then -- ASH. + NEXT_FETCH_STATE <= START_OP; + else + NEXT_FETCH_STATE <= INIT_EXEC_WB; -- ASH. + end if; + end case; + when SLEEP => + case OP is + when ANDI_TO_SR | CAS | CAS2 | EORI_TO_SR | MOVE_TO_SR | MOVEM | ORI_TO_SR | TAS => + -- CAS, CAS2 and TAS are a read modify write instructions. + -- MOVEM: wait until last register is written to avoid data hazards + -- because the ADR_IN_USE, AR_IN__USE and DR_IN_USE does not + -- work for MOVEM (several registers in use). + -- TAS is a read modify write instruction. + -- _TO_SR instructions wait for the change of the SBIT + -- and so for a new processor context. + if NEXT_EXEC_WB_STATE = IDLE then + NEXT_FETCH_STATE <= START_OP; + else + NEXT_FETCH_STATE <= SLEEP; + end if; + when BFCHG | BFCLR | BFINS | BFSET => + if EXEC_WB_STATE = WRITE_DEST and WR_RDY = '1' and BF_BYTES = 1 then + -- Wait until second writeback access has been processed. + NEXT_FETCH_STATE <= START_OP; + else + NEXT_FETCH_STATE <= SLEEP; + end if; + when JSR => + if PHASE2 = false then + NEXT_FETCH_STATE <= SLEEP; -- Wait for address calculation. + else + NEXT_FETCH_STATE <= START_OP; + end if; + when MOVE_USP | MOVEC => + -- MOVE_USP: wait for writeback not to conflict with AR_DEC in START_OP. + if NEXT_EXEC_WB_STATE = IDLE then + NEXT_FETCH_STATE <= START_OP; + else + NEXT_FETCH_STATE <= SLEEP; -- Wait for new processor context. + end if; + when DBcc => + -- DBcc: evaluate conditions. + if NEXT_EXEC_WB_STATE = IDLE then + NEXT_FETCH_STATE <= START_OP; + else + NEXT_FETCH_STATE <= SLEEP; + end if; + when STOP => + if TRACE_MODE /= "00" then + NEXT_FETCH_STATE <= START_OP; -- Do not perform a stop while tracing. + elsif EXH_REQ = '1' then + NEXT_FETCH_STATE <= START_OP; -- Wait on interrupt. + else + NEXT_FETCH_STATE <= SLEEP; + end if; + when others => -- Bcc, CHK, JMP, TRAPV. + -- Bcc: evaluate conditions. + -- CHK: use SWITCH_STATE for TRAP evaluation. + -- CHK2: use SWITCH_STATE for TRAP evaluation. + -- JMP: wait for address calculation. + -- TRAPV: check conditions. + NEXT_FETCH_STATE <= START_OP; + end case; + end case; + end process FETCH_DEC; + + EXEC_WB_DEC: process(ALU_COND, ALU_INIT_I, ALU_REQ, BIW_0_WB, BIW_1_WB, BF_BYTES, EXEC_WB_STATE, FETCH_STATE, MOVEM_INH_WR, OP_WB_I, PHASE2, WR_RDY) + begin + case EXEC_WB_STATE is + when IDLE => + if ALU_INIT_I = '1' then + NEXT_EXEC_WB_STATE <= EXECUTE; + else + NEXT_EXEC_WB_STATE <= IDLE; + end if; + when EXECUTE => + if ALU_REQ = '1' then + case OP_WB_I is + when ABCD | SBCD | ADDX | SUBX | PACK | UNPK => + if BIW_0_WB(3) = '0' then -- Register to register. + NEXT_EXEC_WB_STATE <= WRITEBACK; + else -- Memory to memory. + NEXT_EXEC_WB_STATE <= WRITE_DEST; + end if; + when ADD | SUB | AND_B | OR_B => + if BIW_0_WB(8) = '0' then + NEXT_EXEC_WB_STATE <= WRITEBACK; -- Destination is register. + else + NEXT_EXEC_WB_STATE <= WRITE_DEST; -- Destination is in memory. + end if; + when ADDA | SUBA | ANDI_TO_SR | BFEXTS | BFEXTU | BFFFO | DIVS | DIVU | EORI_TO_SR | EXG | EXT | EXTB | + LEA | MOVE_TO_CCR | MOVE_TO_SR | MOVE_USP | MOVEA | MOVEC | MOVEQ | MULS | MULU | ORI_TO_SR | STOP | SWAP | UNLK => + NEXT_EXEC_WB_STATE <= WRITEBACK; + when ADDI | ADDQ | ANDI | BCHG | BCLR | BFCHG | BFCLR | BFINS | BFSET | BSET | CLR | EOR | EORI | + MOVE_FROM_CCR | MOVE_FROM_SR | NBCD | NEG | NEGX | NOT_B | ORI | Scc | SUBI | SUBQ | TAS => + if BIW_0_WB(5 downto 3) = "000" then + NEXT_EXEC_WB_STATE <= WRITEBACK; -- Destination is a data register. + elsif BIW_0_WB(5 downto 3) = "001" then -- Valid for ADDQ and SUBQ. + NEXT_EXEC_WB_STATE <= WRITEBACK; -- Destination is an address register. + else + NEXT_EXEC_WB_STATE <= WRITE_DEST; -- Destination is in memory. + end if; + when ASL | ASR | LSL | LSR | ROTL | ROTR | ROXL | ROXR => + if BIW_0_WB(7 downto 6) /= "11" then + NEXT_EXEC_WB_STATE <= WRITEBACK; -- Register shifts. + else + NEXT_EXEC_WB_STATE <= WRITE_DEST; -- Memory shifts. + end if; + when CAS => + if ALU_COND = false then + NEXT_EXEC_WB_STATE <= WRITEBACK; -- Update Dc. + else + NEXT_EXEC_WB_STATE <= WRITE_DEST; -- Update destination. + end if; + when CAS2 => + if FETCH_STATE = FETCH_OPERAND then + NEXT_EXEC_WB_STATE <= IDLE; -- Second read access. + elsif ALU_COND = false then + NEXT_EXEC_WB_STATE <= WRITEBACK; -- Update Dc. + else + NEXT_EXEC_WB_STATE <= ADR_PIPELINE; -- Update destination. + end if; + when DBcc => + if ALU_COND = true then + NEXT_EXEC_WB_STATE <= IDLE; + else + NEXT_EXEC_WB_STATE <= WRITEBACK; + end if; + when MOVE => + if BIW_0_WB(8 downto 6) = "000" then + NEXT_EXEC_WB_STATE <= WRITEBACK; -- Destination is register. + elsif PHASE2 = false then + NEXT_EXEC_WB_STATE <= WRITE_DEST; -- Destination is in memory. + else + NEXT_EXEC_WB_STATE <= EXECUTE; -- Wait for PHASE2 address calculation. + end if; + when BSR | JSR | LINK | PEA => + NEXT_EXEC_WB_STATE <= WRITE_DEST; + when MOVEM => + if OP_WB_I = MOVEM and MOVEM_INH_WR = true then + NEXT_EXEC_WB_STATE <= IDLE; -- Discard the write cycle. + elsif BIW_0_WB(10) = '1' then + NEXT_EXEC_WB_STATE <= WRITEBACK; -- Destination is register. + else + NEXT_EXEC_WB_STATE <= WRITE_DEST; -- Destination is in memory. + end if; + when MOVEP => + if BIW_0_WB(7 downto 6) < "10" then + NEXT_EXEC_WB_STATE <= WRITEBACK; -- Memory to register. + else + NEXT_EXEC_WB_STATE <= WRITE_DEST; -- Register to memory. + end if; + when MOVES => + if BIW_1_WB(11) = '0' then + NEXT_EXEC_WB_STATE <= WRITEBACK; -- Destination is register. + else + NEXT_EXEC_WB_STATE <= WRITE_DEST; -- Destination is in memory. + end if; + -- Default is for: + -- ANDI_TO_CCR, Bcc, BFTST, BTST, CHK, CHK2, + -- CMP, CMP2, CMPA, CMPI, CMPM, EORI_TO_CCR, + -- ORI_TO_CCR, RTR, TRAPV, TST. + when others => + NEXT_EXEC_WB_STATE <= IDLE; + end case; + else + NEXT_EXEC_WB_STATE <= EXECUTE; + end if; + when ADR_PIPELINE => -- Effective address calculation takes one clock cycle. + NEXT_EXEC_WB_STATE <= WRITE_DEST; + when WRITEBACK => + case OP_WB_I is + when CAS2 => + if PHASE2 = false then + NEXT_EXEC_WB_STATE <= WRITEBACK; -- Update Dc2 + else + NEXT_EXEC_WB_STATE <= IDLE; + end if; + when others => + NEXT_EXEC_WB_STATE <= IDLE; + end case; + when WRITE_DEST => + if WR_RDY = '1' then + case OP_WB_I is + when BFCHG | BFCLR | BFINS | BFSET => + if BF_BYTES <= 4 then + NEXT_EXEC_WB_STATE <= IDLE; + else + NEXT_EXEC_WB_STATE <= ADR_PIPELINE; + end if; + when CAS2 => + if PHASE2 = false then + NEXT_EXEC_WB_STATE <= WRITE_DEST; -- Update destination 2. + else + NEXT_EXEC_WB_STATE <= IDLE; + end if; + when others => NEXT_EXEC_WB_STATE <= IDLE; + end case; + else + NEXT_EXEC_WB_STATE <= WRITE_DEST; + end if; + end case; + end process EXEC_WB_DEC; +end BEHAVIOUR; diff --git a/common/CPU/68K30L/wf68k30L_data_registers.vhd b/common/CPU/68K30L/wf68k30L_data_registers.vhd new file mode 100644 index 00000000..b41a201a --- /dev/null +++ b/common/CPU/68K30L/wf68k30L_data_registers.vhd @@ -0,0 +1,137 @@ +------------------------------------------------------------------------ +---- ---- +---- WF68K30L IP Core: Data register logic. ---- +---- ---- +---- Description: ---- +---- These are the eight data registers. The logic provides two ---- +---- read and two write ports providing simultaneos access. For ---- +---- more information refer to the MC68030 User' Manual. ---- +---- ---- +---- Author(s): ---- +---- - Wolfgang Foerster, wf@experiment-s.de; wf@inventronik.de ---- +---- ---- +------------------------------------------------------------------------ +---- ---- +---- Copyright 2014-2019 Wolfgang Foerster Inventronik GmbH. ---- +---- ---- +---- This documentation describes Open Hardware and is licensed ---- +---- under the CERN OHL v. 1.2. You may redistribute and modify ---- +---- this documentation under the terms of the CERN OHL v.1.2. ---- +---- (http://ohwr.org/cernohl). This documentation is distributed ---- +---- WITHOUT ANY EXPRESS OR IMPLIED WARRANTY, INCLUDING OF ---- +---- MERCHANTABILITY, SATISFACTORY QUALITY AND FITNESS FOR A ---- +---- PARTICULAR PURPOSE. Please see the CERN OHL v.1.2 for ---- +---- applicable conditions ---- +---- ---- +------------------------------------------------------------------------ +-- +-- Revision History +-- +-- Revision 2K14B 20141201 WF +-- Initial Release. +-- + +library work; +use work.WF68K30L_PKG.all; + +library ieee; +use ieee.std_logic_1164.all; +use ieee.std_logic_unsigned.all; + +entity WF68K30L_DATA_REGISTERS is + port ( + CLK : in std_logic; + RESET : in bit; + + -- Data lines: + DR_IN_1 : in std_logic_vector(31 downto 0); + DR_IN_2 : in std_logic_vector(31 downto 0); + DR_OUT_1 : out std_logic_vector(31 downto 0); + DR_OUT_2 : out std_logic_vector(31 downto 0); + + -- Registers controls: + DR_SEL_WR_1 : in std_logic_vector(2 downto 0); + DR_SEL_WR_2 : in std_logic_vector(2 downto 0); + DR_SEL_RD_1 : in std_logic_vector(2 downto 0); + DR_SEL_RD_2 : in std_logic_vector(2 downto 0); + DR_WR_1 : in bit; + DR_WR_2 : in bit; + DR_MARK_USED : in bit; + USE_DPAIR : in boolean; + DR_IN_USE : out bit; + UNMARK : in bit; + + OP_SIZE : in OP_SIZETYPE + ); +end entity WF68K30L_DATA_REGISTERS; + +architecture BEHAVIOUR of WF68K30L_DATA_REGISTERS is +type DR_TYPE is array(0 to 7) of std_logic_vector(31 downto 0); +signal DR : DR_TYPE; -- Data registers D0 to D7. +signal DR_PNTR_WR_1 : integer range 0 to 7; +signal DR_PNTR_WR_2 : integer range 0 to 7; +signal DR_PNTR_RD_1 : integer range 0 to 7; +signal DR_PNTR_RD_2 : integer range 0 to 7; +signal DR_SEL_WR_I1 : std_logic_vector(2 downto 0); +signal DR_SEL_WR_I2 : std_logic_vector(2 downto 0); +signal DR_USED_1 : std_logic_vector(3 downto 0); +signal DR_USED_2 : std_logic_vector(3 downto 0); +begin + INBUFFER: process + begin + wait until CLK = '1' and CLK' event; + if DR_MARK_USED = '1' then + DR_SEL_WR_I1 <= DR_SEL_WR_1; + DR_SEL_WR_I2 <= DR_SEL_WR_2; + end if; + end process INBUFFER; + + DR_PNTR_WR_1 <= conv_integer(DR_SEL_WR_I1); + DR_PNTR_WR_2 <= conv_integer(DR_SEL_WR_I2); + DR_PNTR_RD_1 <= conv_integer(DR_SEL_RD_1); + DR_PNTR_RD_2 <= conv_integer(DR_SEL_RD_2); + + P_IN_USE: process + begin + wait until CLK = '1' and CLK' event; + if RESET = '1' or UNMARK = '1' then + DR_USED_1(3) <= '0'; + DR_USED_2(3) <= '0'; + elsif DR_MARK_USED = '1' then + DR_USED_1 <= '1' & DR_SEL_WR_1; + if USE_DPAIR = true then + DR_USED_2 <= '1' & DR_SEL_WR_2; + end if; + end if; + end process P_IN_USE; + + DR_IN_USE <= '1' when DR_USED_1(3) = '1' and DR_USED_1(2 downto 0) = DR_SEL_RD_1 else + '1' when DR_USED_1(3) = '1' and DR_USED_1(2 downto 0) = DR_SEL_RD_2 else + '1' when DR_USED_2(3) = '1' and DR_USED_2(2 downto 0) = DR_SEL_RD_1 else + '1' when DR_USED_2(3) = '1' and DR_USED_2(2 downto 0) = DR_SEL_RD_2 else '0'; + + DR_OUT_1 <= DR(DR_PNTR_RD_1); + DR_OUT_2 <= DR(DR_PNTR_RD_2); + + REGISTERS: process + begin + wait until CLK = '1' and CLK' event; + if RESET = '1' then + DR <= (others => (others => '0')); + end if; + if DR_WR_1 = '1' then + case OP_SIZE is + when LONG => DR(DR_PNTR_WR_1) <= DR_IN_1; + when WORD => DR(DR_PNTR_WR_1)(15 downto 0) <= DR_IN_1(15 downto 0); + when Byte => DR(DR_PNTR_WR_1)(7 downto 0) <= DR_IN_1(7 downto 0); + end case; + end if; + if DR_WR_2 = '1' then + case OP_SIZE is + when LONG => DR(DR_PNTR_WR_2) <= DR_IN_2; + when WORD => DR(DR_PNTR_WR_2)(15 downto 0) <= DR_IN_2(15 downto 0); + when Byte => DR(DR_PNTR_WR_2)(7 downto 0) <= DR_IN_2(7 downto 0); + end case; + end if; + end process REGISTERS; +end BEHAVIOUR; diff --git a/common/CPU/68K30L/wf68k30L_exception_handler.vhd b/common/CPU/68K30L/wf68k30L_exception_handler.vhd new file mode 100644 index 00000000..46ce0896 --- /dev/null +++ b/common/CPU/68K30L/wf68k30L_exception_handler.vhd @@ -0,0 +1,934 @@ +------------------------------------------------------------------------ +---- ---- +---- WF68K30L IP Core: this is the exception handler module. ---- +---- ---- +---- Description: ---- +---- This is the exception handler which is responsible for the ---- +---- interrupt management of the external interrupt and internal ---- +---- exception processing. It manages auto-vectored interrupt ---- +---- cycles, priority resolving and correct vector numbers. ---- +---- For further information concerning the functionality of this ---- +---- module refer to the MC68030 User's Manual and to the MC68K ---- +---- family Programmer's Reference Manual. ---- +------------------------------------------------------------------------ +---- ---- +---- Remarks: ---- +---- The relationship between the STATUSn signal and the execution ---- +---- of the next pending exception is handled by the BUSY signals. ---- +---- If the pending interrupt is not signaled in time, when the ---- +---- main controller signal STATUSn, the next instruction is ---- +---- executed and afterwards the exception. When the pending ---- +---- exception is asserted before the STATUSn of one of the main ---- +---- controller, the exception is executed immediately. ---- +---- ---- +---- A bus error at an instruction boundary may occur, when the ---- +---- operation word fetched from the instruction pipe is invalid. ---- +---- Bus errors which occur at the time of the instruction boundary ---- +---- but where released early or at the same time due to the pipe- ---- +---- lined structure are treated as regular bus errors not related ---- +---- with the instruction boundary. The signal IBOUND is used to ---- +---- handle this situations correctly. ---- +---- ---- +---- This exception handler uses a simple logic for the handling ---- +---- the RTE instruction. In comparision to the full featured 68K30 ---- +---- it cannot complete from defective bus exception stack frames. ---- +---- It is assumed, that a software handler has modified the images ---- +---- in the exception stack frame for a bus handler so that the RTE ---- +---- instruction restores from a correct stack frame. ---- +---- ---- +---- Author(s): ---- +---- - Wolfgang Foerster, wf@experiment-s.de; wf@inventronik.de ---- +---- ---- +------------------------------------------------------------------------ +---- ---- +---- Copyright © 2014-2019 Wolfgang Foerster Inventronik GmbH. ---- +---- ---- +---- This documentation describes Open Hardware and is licensed ---- +---- under the CERN OHL v. 1.2. You may redistribute and modify ---- +---- this documentation under the terms of the CERN OHL v.1.2. ---- +---- (http://ohwr.org/cernohl). This documentation is distributed ---- +---- WITHOUT ANY EXPRESS OR IMPLIED WARRANTY, INCLUDING OF ---- +---- MERCHANTABILITY, SATISFACTORY QUALITY AND FITNESS FOR A ---- +---- PARTICULAR PURPOSE. Please see the CERN OHL v.1.2 for ---- +---- applicable conditions ---- +---- ---- +------------------------------------------------------------------------ +-- +-- Revision History +-- +-- Revision 2K14B 20141201 WF +-- Initial Release. +-- Revision 2K16A 20141201 WF +-- Fixed a bug in PC_LOAD. +-- Revision 2K18A 20180620 WF +-- Removed REST_BIW_0. +-- Removed PC_OFFSET. +-- Fixed PC restoring during exception processing. +-- Fixed the vector calculation of INT vectors. +-- Fixed faulty modeling in IRQ_FILTER. +-- Implemented the AVEC_FILTER to better meet bus timings. +-- The RTE exception has now highest priority (avoids mismatch). +-- TOP, CONTROL, Exception Handler Opcode Decoder: Rearranged PC_INC and ipipe flush logic. +-- Update the IRQ mask only for RESET and interrupts. +-- External interrupts are postponed if any system controllers are in initialize operation status. +-- RTE now loads the address offset correctly when entering the handler. +-- Rearranged address error handling. +-- Revision 2K19B 20191224 WF +-- Introduced signal synchronization in the P_D process to avoid malfunction by hazards. +-- The processor VERSION is now 32 bit wide. +-- + +library work; +use work.WF68K30L_PKG.all; + +library ieee; +use ieee.std_logic_1164.all; +use ieee.std_logic_unsigned.all; + +entity WF68K30L_EXCEPTION_HANDLER is + generic(VERSION : std_logic_vector(31 downto 0) := x"20191224"); + port( + CLK : in std_logic; + RESET : in bit; + + BUSY_MAIN : in bit; + BUSY_OPD : in bit; + + EXH_REQ : out bit; + BUSY_EXH : out bit; + + ADR_IN : in std_logic_vector(31 downto 0); + ADR_CPY : out std_logic_vector(31 downto 0); + ADR_OFFSET : out std_logic_vector(31 downto 0); + CPU_SPACE : out bit; + + DATA_0 : in std_logic; + DATA_RD : out bit; + DATA_WR : out bit; + DATA_IN : in std_logic_vector(31 downto 0); + + OP_SIZE : out OP_SIZETYPE; -- Operand size. + DATA_RDY : in bit; + DATA_VALID : in std_logic; + + OPCODE_RDY : in bit; -- OPCODE is available. + OPD_ACK : in bit; -- Opword is available. + OW_VALID : in std_logic; -- Status from the opcode decoder. + + STATUS_REG_IN : in std_logic_vector(15 downto 0); + SR_CPY : out std_logic_vector(15 downto 0); + SR_INIT : out bit; + SR_CLR_MBIT : out bit; + SR_WR : out bit; + + ISP_DEC : out bit; + ISP_LOAD : out bit; + PC_INC : out bit; + PC_LOAD : out bit; + PC_RESTORE : out bit; + + STACK_FORMAT : out std_logic_vector(3 downto 0); + STACK_POS : out integer range 0 to 46; + + SP_ADD_DISPL : out bit; + DISPLACEMENT : out std_logic_vector(7 downto 0); + + IPIPE_FILL : out bit; + IPIPE_FLUSH : out bit; + REFILLn : out std_logic; + RESTORE_ISP_PC : out bit; + + HALT_OUTn : out std_logic; + STATUSn : out bit; + + -- Interrupt controls: + INT_TRIG : in bit; + IRQ_IN : in std_logic_vector(2 downto 0); + IRQ_PEND : out std_logic_vector(2 downto 0); + AVECn : in std_logic; + IPENDn : out std_logic; + IVECT_OFFS : out std_logic_vector(9 downto 0); -- Interrupt vector offset. + + + -- Trap signals: + TRAP_AERR : in bit; + TRAP_BERR : in bit; + TRAP_CHK : in bit; + TRAP_DIVZERO : in bit; + TRAP_ILLEGAL : in bit; + TRAP_CODE_OPC : in TRAPTYPE_OPC; -- T_1010, T_1111, T_ILLEGAL, T_TRAP, T_PRIV. + TRAP_VECTOR : in std_logic_vector(3 downto 0); + TRAP_cc : in bit; + TRAP_V : in bit; + EX_TRACE_IN : in bit; + VBR_WR : in bit; + VBR : out std_logic_vector(31 downto 0) + ); +end entity WF68K30L_EXCEPTION_HANDLER; + +architecture BEHAVIOR of WF68K30L_EXCEPTION_HANDLER is +type EX_STATES is (IDLE, BUILD_STACK, BUILD_TSTACK, CALC_VECT_No, EXAMINE_VERSION, GET_VECTOR, HALTED, INIT, READ_BOTTOM, + READ_TOP, REFILL_PIPE, RESTORE_ISP, RESTORE_PC, RESTORE_STATUS, UPDATE_PC, SWITCH_STATE, VALIDATE_FRAME); + +type EXCEPTIONS is (EX_NONE, EX_1010, EX_1111, EX_AERR, EX_BERR, EX_CHK, EX_DIVZERO, EX_FORMAT, EX_ILLEGAL, + EX_INT, EX_PRIV, EX_RESET, EX_RTE, EX_TRACE, EX_TRAP, EX_TRAPcc, EX_TRAPV); + +signal ACCESS_ERR : bit; +signal AVEC : bit; +signal DATA_RD_I : bit; +signal DATA_WR_I : bit; +signal DOUBLE_BUSFLT : bit; +signal EXCEPTION : EXCEPTIONS; -- Currently executed exception. +signal EX_STATE : EX_STATES := IDLE; +signal NEXT_EX_STATE : EX_STATES; +signal EX_P_1010 : bit; -- ..._P are the pending exceptions. +signal EX_P_1111 : bit; +signal EX_P_AERR : bit; +signal EX_P_BERR : bit; +signal EX_P_CHK : bit; +signal EX_P_DIVZERO : bit; +signal EX_P_FORMAT : bit; +signal EX_P_ILLEGAL : bit; +signal EX_P_INT : bit; +signal EX_P_RESET : bit; +signal EX_P_RTE : bit; +signal EX_P_PRIV : bit; +signal EX_P_TRACE : bit; +signal EX_P_TRAP : bit; +signal EX_P_TRAPcc : bit; +signal EX_P_TRAPV : bit; +signal INT_VECT : std_logic_vector(31 downto 0); -- Interrupt vector. +signal IBOUND : boolean; +signal IRQ : std_logic_vector(2 downto 0); +signal IRQ_PEND_I : std_logic_vector(2 downto 0); +signal MBIT : std_logic; +signal PIPE_CNT : std_logic_vector(1 downto 0); +signal PIPE_FULL : boolean; +signal STACK_CNT : integer range 0 to 46; +signal STACK_FORMAT_I : std_logic_vector(3 downto 0); +signal SYS_INIT : bit; +begin + BUSY_EXH <= '1' when EX_STATE /= IDLE else '0'; + + IRQ_FILTER : process + -- This logic is intended to avoid spurious IRQs due + -- to setup / hold violations (IRQ_IN may operate in + -- a different clock domain). + variable IRQ_TMP_1 : std_logic_vector(2 downto 0) := "000"; + variable IRQ_TMP_2 : std_logic_vector(2 downto 0) := "000"; + begin + wait until CLK = '0' and CLK' event; + if IRQ_TMP_1 = IRQ_TMP_2 then + IRQ <= IRQ_TMP_2; + end if; + IRQ_TMP_2 := IRQ_TMP_1; + IRQ_TMP_1 := IRQ_IN; + end process IRQ_FILTER; + + AVEC_FILTER : process + -- We need a flip flop for the incoming AVECn to meet + -- the timing requirements of the bus interface. AVECn + -- is asserted (low active) before DATA_RDY of the + -- bus interface. AVEC stays asserted until DATA_RDY. + begin + wait until CLK = '1' and CLK' event; + if AVECn = '0' then + AVEC <= '1'; + elsif DATA_RDY = '1' or RESET = '1' then + AVEC <= '0'; + end if; + end process AVEC_FILTER; + + INSTRUCTION_BOUNDARY: process + -- This flip flop indicates a bus error exception, + -- when the micro sequencer is at an instruction + -- boundary. + begin + wait until CLK = '1' and CLK' event; + if RESET = '1' then + IBOUND <= false; + elsif OPD_ACK = '1' and OW_VALID = '0' then + IBOUND <= true; + elsif EX_STATE = BUILD_STACK then + IBOUND <= false; + end if; + end process INSTRUCTION_BOUNDARY; + + PENDING: process + -- The exceptions which occurs are stored in this pending register until the + -- interrupt handler handled the respective exception. + -- The TRAP_PRIV, TRAP_1010, TRAP_1111, TRAP_ILLEGAL, TRAP_OP and TRAP_V may be a strobe + -- of 1 clock period. All others must be strobes of 1 clock period.. + variable INT7_TRIG : boolean; + variable INT_VAR : std_logic_vector(2 downto 0); + variable SR_VAR : std_logic_vector(2 downto 0); + begin + wait until CLK = '1' and CLK' event; + if RESET = '1' then + EX_P_RESET <= '1'; + elsif EX_STATE = RESTORE_PC and DATA_RDY = '1' and EXCEPTION = EX_RESET then + EX_P_RESET <= '0'; + end if; + -- + if TRAP_BERR = '1' then + EX_P_BERR <= '1'; + elsif EX_STATE /= IDLE and DATA_RDY = '1' and DATA_VALID = '0' then + EX_P_BERR <= '1'; + elsif EX_STATE = INIT and EXCEPTION = EX_BERR then + EX_P_BERR <= '0'; -- Reset in the beginning to enable retriggering. + elsif SYS_INIT = '1' then + EX_P_BERR <= '0'; + end if; + -- + if TRAP_AERR = '1' then + EX_P_AERR <= '1'; + elsif EX_STATE = BUILD_STACK and EXCEPTION = EX_AERR then + EX_P_AERR <= '0'; + elsif SYS_INIT = '1' then + EX_P_AERR <= '0'; + end if; + -- + if EX_TRACE_IN = '1' then + EX_P_TRACE <= '1'; + elsif EX_STATE = BUILD_STACK and EXCEPTION = EX_TRACE then + EX_P_TRACE <= '0'; + elsif SYS_INIT = '1' then + EX_P_TRACE <= '0'; + end if; + -- + if IRQ = "111" and SR_VAR = "111" and STATUS_REG_IN(10 downto 8) /= "111" then + INT7_TRIG := true; -- Trigger by lowering the mask from 7 to any value. + elsif IRQ = "111" and INT_VAR < "111" then + INT7_TRIG := true; -- Trigger when level 7 is entered. + else + INT7_TRIG := false; + end if; + -- + SR_VAR := STATUS_REG_IN(10 downto 8); -- Update after use! + INT_VAR := IRQ; -- Update after use! + -- + if SYS_INIT = '1' then -- Reset when disabling the interrupts. + EX_P_INT <= '0'; + IRQ_PEND_I <= "111"; -- This is required for system startup. + elsif EX_STATE = GET_VECTOR and DATA_RDY = '1' then + EX_P_INT <= '0'; + elsif INT7_TRIG = true then -- Level 7 is nonmaskable ... + EX_P_INT <= '1'; + IRQ_PEND_I <= IRQ; + elsif INT_TRIG = '1' and STATUS_REG_IN(10 downto 8) < IRQ then + EX_P_INT <= '1'; + IRQ_PEND_I <= IRQ; + end if; + -- + -- The following nine traps never appear at the same time: + if TRAP_CHK = '1' then + EX_P_CHK <= '1'; + elsif TRAP_DIVZERO = '1' then + EX_P_DIVZERO <= '1'; + elsif TRAP_CODE_OPC = T_TRAP then + EX_P_TRAP <= '1'; + elsif TRAP_cc = '1' then + EX_P_TRAPcc <= '1'; + elsif TRAP_V = '1' then + EX_P_TRAPV <= '1'; + elsif TRAP_CODE_OPC = T_PRIV then + EX_P_PRIV <= '1'; + elsif TRAP_CODE_OPC = T_1010 then + EX_P_1010 <= '1'; + elsif TRAP_CODE_OPC = T_1111 then + EX_P_1111 <= '1'; + elsif TRAP_CODE_OPC = T_ILLEGAL then + EX_P_ILLEGAL <= '1'; + elsif TRAP_ILLEGAL = '1' then -- Used for BKPT. + EX_P_ILLEGAL <= '1'; + elsif EX_STATE = VALIDATE_FRAME and DATA_RDY = '1' and DATA_VALID = '1' and NEXT_EX_STATE = IDLE then + EX_P_FORMAT <= '1'; + elsif EX_STATE = EXAMINE_VERSION and DATA_RDY = '1' and DATA_VALID = '1' and NEXT_EX_STATE = IDLE then + EX_P_FORMAT <= '1'; + elsif TRAP_CODE_OPC = T_RTE then + EX_P_RTE <= '1'; + elsif EX_STATE = REFILL_PIPE and NEXT_EX_STATE /= REFILL_PIPE then -- Clear after IPIPE_FLUSH. + case EXCEPTION is + when EX_1010 | EX_1111 | EX_CHK | EX_DIVZERO | EX_ILLEGAL | EX_TRAP | EX_TRAPcc | EX_TRAPV | EX_FORMAT | EX_PRIV | EX_RTE => + EX_P_CHK <= '0'; + EX_P_DIVZERO <= '0'; + EX_P_PRIV <= '0'; + EX_P_1010 <= '0'; + EX_P_1111 <= '0'; + EX_P_ILLEGAL <= '0'; + EX_P_RTE <= '0'; + EX_P_TRAP <= '0'; + EX_P_TRAPcc <= '0'; + EX_P_TRAPV <= '0'; + EX_P_FORMAT <= '0'; + when others => + null; + end case; + -- Clear all possible traps during reset exception because the + -- signal EXCEPTION is not valid at this time: + elsif SYS_INIT = '1' then + EX_P_CHK <= '0'; + EX_P_DIVZERO <= '0'; + EX_P_PRIV <= '0'; + EX_P_1010 <= '0'; + EX_P_1111 <= '0'; + EX_P_ILLEGAL <= '0'; + EX_P_RTE <= '0'; + EX_P_TRAP <= '0'; + EX_P_TRAPV <= '0'; + EX_P_FORMAT <= '0'; + end if; + end process PENDING; + + ACCESS_ERR <= '1' when EX_STATE = RESTORE_PC and DATA_RDY = '1' and DATA_0 = '1' else -- Odd PC value. + '1' when DATA_RDY = '1' and DATA_VALID = '0' else '0'; -- Bus error. + + IRQ_PEND <= IRQ_PEND_I when EXCEPTION = EX_RESET or EXCEPTION = EX_INT else STATUS_REG_IN(10 downto 8); + IPENDn <= '0' when EX_P_INT = '1' or EX_P_RESET = '1' or EX_P_TRACE = '1' else '1'; + + -- This signal is asserted eraly to indicate the respective controller to stay in its idle state. + -- The exception is then inserted before a new operation has been loaded and processed. + EXH_REQ <= '0' when EX_STATE /= IDLE else + '1' when TRAP_CODE_OPC /= NONE else + '1' when (EX_P_RESET or EX_P_BERR or EX_P_AERR or EX_P_DIVZERO or EX_P_CHK) = '1' else + '1' when (EX_P_TRAPcc or EX_P_TRAPV or EX_P_TRACE or EX_P_FORMAT or EX_P_INT) = '1' else '0'; + + INT_VECTOR: process + -- This process provides the vector base register handling and + -- the interrupt vector number INT_VECT, which is determined + -- during interrupt processing. + variable VECT_No : std_logic_vector(9 downto 2) := "00000000"; + variable VB_REG : std_logic_vector(31 downto 0) := x"00000000"; + begin + wait until CLK = '1' and CLK' event; + if VBR_WR = '1' then + VB_REG := DATA_IN; + elsif SYS_INIT = '1' then + VB_REG := (others => '0'); + end if; + -- + if EX_STATE = CALC_VECT_No or EX_STATE = GET_VECTOR then + case EXCEPTION is + when EX_RESET => VECT_No := x"00"; + when EX_BERR => VECT_No := x"02"; + when EX_AERR => VECT_No := x"03"; + when EX_ILLEGAL => VECT_No := x"04"; + when EX_DIVZERO => VECT_No := x"05"; + when EX_CHK => VECT_No := x"06"; + when EX_TRAPcc => VECT_No := x"07"; + when EX_TRAPV => VECT_No := x"07"; + when EX_PRIV => VECT_No := x"08"; + when EX_TRACE => VECT_No := x"09"; + when EX_1010 => VECT_No := x"0A"; + when EX_1111 => VECT_No := x"0B"; + when EX_FORMAT => VECT_No := x"0E"; + -- The uninitialized interrupt vector number x"0F" + -- is provided by the peripheral interrupt source + -- during the auto vector bus cycle. + when EX_INT => + if DATA_RDY = '1' and AVEC = '1' then + VECT_No := x"18" + IRQ_PEND_I; -- Autovector. + elsif DATA_RDY = '1' and DATA_VALID = '0' then + VECT_No := x"18"; -- Spurious interrupt. + elsif DATA_RDY = '1' then + -- This is the vector number provided by the device. + -- If the returned VECT_No is x"0F" then it is the + -- uninitialized interrupt vector due to non initia- + -- lized vector register of the peripheral device. + VECT_No := DATA_IN(7 downto 0); -- Non autovector. + end if; + when EX_TRAP => VECT_No := x"2" & TRAP_VECTOR; + when others => VECT_No := (others => '-'); -- Don't care. + end case; + end if; + -- + INT_VECT <= VB_REG + (VECT_No & "00"); + VBR <= VB_REG; + IVECT_OFFS <= VECT_No & "00"; + end process INT_VECTOR; + + STORE_CURRENT_EXCEPTION: process + -- The exceptions which occurs are stored in the following flags until the + -- interrupt handler handled the respective exception. + -- This process also stores the current processed exception for further use. + -- The update takes place in the IDLE EX_STATE. + begin + wait until CLK = '1' and CLK' event; + -- Priority level 0: + if EX_STATE = IDLE and EX_P_RESET = '1' then + EXCEPTION <= EX_RESET; + -- Priority level 1: + elsif EX_STATE = IDLE and EX_P_AERR = '1' then + EXCEPTION <= EX_AERR; + elsif EX_STATE = IDLE and EX_P_BERR = '1' then + EXCEPTION <= EX_BERR; + -- Priority level 2: + -- BREAKPOINT is part of the main controller. + elsif EX_STATE = IDLE and EX_P_CHK = '1' then + EXCEPTION <= EX_CHK; + elsif EX_STATE = IDLE and EX_P_TRAPcc = '1' then + EXCEPTION <= EX_TRAPcc; + elsif EX_STATE = IDLE and EX_P_DIVZERO = '1' then + EXCEPTION <= EX_DIVZERO; + elsif EX_STATE = IDLE and EX_P_TRAP = '1' then + EXCEPTION <= EX_TRAP; + elsif EX_STATE = IDLE and EX_P_TRAPV = '1' then + EXCEPTION <= EX_TRAPV; + elsif EX_STATE = IDLE and EX_P_FORMAT = '1' then + EXCEPTION <= EX_FORMAT; + -- Priority level 3: + elsif EX_STATE = IDLE and EX_P_ILLEGAL = '1' then + EXCEPTION <= EX_ILLEGAL; + elsif EX_STATE = IDLE and EX_P_RTE = '1' then + EXCEPTION <= EX_RTE; + elsif EX_STATE = IDLE and EX_P_1010 = '1' then + EXCEPTION <= EX_1010; + elsif EX_STATE = IDLE and EX_P_1111 = '1' then + EXCEPTION <= EX_1111; + elsif EX_STATE = IDLE and EX_P_PRIV = '1' then + EXCEPTION <= EX_PRIV; + elsif EX_STATE = IDLE and EX_P_TRACE = '1' then + EXCEPTION <= EX_TRACE; + elsif EX_STATE = IDLE and EX_P_INT = '1' then + EXCEPTION <= EX_INT; + elsif NEXT_EX_STATE = IDLE then + EXCEPTION <= EX_NONE; + end if; + end process STORE_CURRENT_EXCEPTION; + + CPU_SPACE <= '1' when NEXT_EX_STATE = GET_VECTOR else '0'; + + ADR_OFFSET <= x"000000" & "00000" & PIPE_CNT & '0' when EX_STATE = REFILL_PIPE else + x"00000004" when NEXT_EX_STATE = RESTORE_PC and EXCEPTION = EX_RESET else + x"00000002" when NEXT_EX_STATE = RESTORE_PC else + x"00000006" when NEXT_EX_STATE = VALIDATE_FRAME else + x"00000036" when NEXT_EX_STATE = EXAMINE_VERSION else + x"0000005C" when NEXT_EX_STATE = READ_BOTTOM else + INT_VECT when NEXT_EX_STATE = UPDATE_PC else x"00000000"; -- Default is top of the stack. + + OP_SIZE <= LONG when EX_STATE = INIT else -- Decrement the stack by four (ISP_DEC). + LONG when NEXT_EX_STATE = RESTORE_ISP or NEXT_EX_STATE = RESTORE_PC else + LONG when NEXT_EX_STATE = BUILD_STACK or NEXT_EX_STATE = BUILD_TSTACK else -- Always long access. + LONG when NEXT_EX_STATE = UPDATE_PC or EX_STATE = UPDATE_PC else + LONG when EX_STATE = SWITCH_STATE else + LONG when NEXT_EX_STATE = EXAMINE_VERSION else + BYTE when NEXT_EX_STATE = GET_VECTOR else WORD; + + with STACK_FORMAT_I select + DISPLACEMENT <= x"08" when x"0" | x"1", + x"0C" when x"2", + x"12" when x"9", + x"20" when x"A", + x"5C" when others; -- x"B". + + SP_ADD_DISPL <= '1' when EX_STATE = RESTORE_STATUS and DATA_RDY = '1' and DATA_VALID = '1' else '0'; + + P_D: process(CLK, DATA_RDY) + -- These flip flops are necessary to delay + -- the read and writes during BUILD_STACK + -- and restoring the system because the + -- address calculation in the address + -- section requires one clock. + -- Important note: to avoid asynchronous reset by data hazards the + -- resetting signal is synchronized on the negative clock edge. + variable DATA_RDY_VAR : bit; + begin + if CLK = '0' and CLK' event then + DATA_RDY_VAR := DATA_RDY; + end if; + -- + if DATA_RDY_VAR = '1' then + DATA_RD <= '0'; + elsif CLK = '1' and CLK' event then + DATA_RD <= DATA_RD_I; + end if; + + if DATA_RDY_VAR = '1' then + DATA_WR <= '0'; + elsif CLK = '1' and CLK' event then + DATA_WR <= DATA_WR_I; + end if; + end process P_D; + + DATA_RD_I <= '0' when DATA_RDY = '1' else + '1' when NEXT_EX_STATE = GET_VECTOR else + '1' when NEXT_EX_STATE = VALIDATE_FRAME else + '1' when NEXT_EX_STATE = EXAMINE_VERSION else + '1' when NEXT_EX_STATE = READ_TOP else + '1' when NEXT_EX_STATE = READ_BOTTOM else + '1' when NEXT_EX_STATE = RESTORE_ISP else + '1' when NEXT_EX_STATE = RESTORE_STATUS else + '1' when NEXT_EX_STATE = UPDATE_PC else + '1' when NEXT_EX_STATE = RESTORE_PC else '0'; + + DATA_WR_I <= '0' when DATA_RDY = '1' else + '1' when EX_STATE = BUILD_STACK else + '1' when EX_STATE = BUILD_TSTACK else '0'; + + ISP_LOAD <= '1' when EX_STATE = RESTORE_ISP and DATA_RDY = '1' and DATA_VALID = '1' else '0'; + PC_RESTORE <= '1' when EX_STATE = RESTORE_PC and DATA_RDY = '1' and DATA_VALID = '1' else '0'; + PC_LOAD <= '1' when EXCEPTION /= EX_RESET and EXCEPTION /= EX_RTE and EX_STATE /= REFILL_PIPE and NEXT_EX_STATE = REFILL_PIPE else '0'; + + IPIPE_FILL <= '1' when EX_STATE = REFILL_PIPE else '0'; + + -- This signal forces the PC logic in the address register section to calculate the address + -- of the next instruction. This address is written on the stack. For the following + -- instructions the old PC value is stacked: BERR, AERR, ILLEGAL, PRIV, TRACE, 1010, 1111, FORMAT. + PC_INC <= '1' when EXCEPTION = EX_CHK and EX_STATE /= BUILD_STACK and NEXT_EX_STATE = BUILD_STACK else + '1' when EXCEPTION = EX_DIVZERO and EX_STATE /= BUILD_STACK and NEXT_EX_STATE = BUILD_STACK else + '1' when EXCEPTION = EX_INT and EX_STATE /= BUILD_STACK and NEXT_EX_STATE = BUILD_STACK else + '1' when EXCEPTION = EX_TRAP and EX_STATE /= BUILD_STACK and NEXT_EX_STATE = BUILD_STACK else + '1' when EXCEPTION = EX_TRAPcc and EX_STATE /= BUILD_STACK and NEXT_EX_STATE = BUILD_STACK else + '1' when EXCEPTION = EX_TRAPV and EX_STATE /= BUILD_STACK and NEXT_EX_STATE = BUILD_STACK else '0'; + + ISP_DEC <= '1' when EX_STATE = INIT and EXCEPTION /= EX_RESET and EXCEPTION /= EX_RTE else -- Early due to one clock cycle address calculation. + '1' when EX_STATE = BUILD_STACK and DATA_RDY = '1' and NEXT_EX_STATE = BUILD_STACK else + '1' when EX_STATE = SWITCH_STATE else + '1' when EX_STATE = BUILD_TSTACK and DATA_RDY = '1' and NEXT_EX_STATE = BUILD_TSTACK else '0'; + + SR_INIT <= '1' when EX_STATE = INIT else '0'; + SR_CLR_MBIT <= '1' when EX_STATE = BUILD_STACK and DATA_RDY = '1' and STACK_CNT = 2 and EXCEPTION = EX_INT and MBIT = '1' else '0'; + SR_WR <= '1' when EX_STATE = RESTORE_STATUS and DATA_RDY = '1' and DATA_VALID = '1' else '0'; + + SYS_INIT <= '1' when EX_STATE = IDLE and EX_P_RESET = '1' else '0'; + + -- The processor gets halted, if a bus error occurs in the stacking or updating states during + -- the exception processing of a bus error, an address error or a reset. + HALT_OUTn <= '0' when EX_STATE = HALTED else '1'; + + RESTORE_ISP_PC <= '1' when EXCEPTION = EX_RESET and (NEXT_EX_STATE = RESTORE_ISP or EX_STATE = RESTORE_ISP) else + '1' when EXCEPTION = EX_RESET and (NEXT_EX_STATE = RESTORE_PC or EX_STATE = RESTORE_PC) else + '1' when NEXT_EX_STATE = UPDATE_PC else '0'; + + REFILLn <= '0' when EX_STATE = REFILL_PIPE else '1'; + + STACK_FORMAT <= STACK_FORMAT_I; + + IPIPE_FLUSH <= '1' when EXCEPTION = EX_RESET and EX_STATE /= REFILL_PIPE else + '1' when EXCEPTION /= EX_NONE and EX_STATE /= REFILL_PIPE and NEXT_EX_STATE = REFILL_PIPE else '0'; + + DOUBLE_BUSFLT <= '1' when (EXCEPTION = EX_AERR or EXCEPTION = EX_RESET) and EX_STATE = RESTORE_PC and DATA_RDY = '1' and DATA_0 = '1' else -- Odd PC value. + '1' when EX_STATE /= IDLE and EXCEPTION = EX_AERR and DATA_RDY = '1' and DATA_VALID = '0' else + '1' when EX_STATE /= IDLE and EXCEPTION = EX_BERR and DATA_RDY = '1' and DATA_VALID = '0' else + '1' when EX_STATE /= IDLE and EXCEPTION = EX_RESET and DATA_RDY = '1' and DATA_VALID = '0' else '0'; + + P_TMP_CPY: process + -- These registers contain a copy of system relevant state information + -- which is necessary for restoring the exception. Copies are provided + -- for the status register, the program counter and the effective address. + begin + wait until CLK = '1' and CLK' event; + if EX_STATE = IDLE and NEXT_EX_STATE /= IDLE then + SR_CPY <= STATUS_REG_IN; + ADR_CPY <= ADR_IN; + MBIT <= STATUS_REG_IN(12); + elsif EX_STATE = BUILD_STACK and NEXT_EX_STATE = SWITCH_STATE then + SR_CPY(13) <= '1'; -- Set S bit. + end if; + end process P_TMP_CPY; + + STACK_CTRL: process + -- This process controls the stacking of the data to the stack. Depending + -- on the stack frame format, the number of words written to the stack is + -- adjusted to long words. See the DATA_2_PORT multiplexer in the top level + -- file for more information. + variable STACK_POS_VAR : integer range 0 to 46 := 0; + begin + wait until CLK = '1' and CLK' event; + if EX_STATE /= BUILD_TSTACK and NEXT_EX_STATE = BUILD_TSTACK then + STACK_POS_VAR := 4; + STACK_FORMAT_I <= x"1"; + elsif EX_STATE /= BUILD_STACK and NEXT_EX_STATE = BUILD_STACK then + case EXCEPTION is + when EX_INT | EX_ILLEGAL | EX_1010 | EX_1111 | EX_FORMAT | EX_PRIV | EX_TRAP => + STACK_POS_VAR := 4; -- Format 0. + STACK_FORMAT_I <= x"0"; + when EX_CHK | EX_TRAPcc | EX_TRAPV | EX_TRACE | EX_DIVZERO => + STACK_POS_VAR := 6; -- Format 2. + STACK_FORMAT_I <= x"2"; + when EX_AERR | EX_BERR => + if IBOUND = true then + STACK_POS_VAR := 16; -- Format A. + STACK_FORMAT_I <= x"A"; + else + STACK_POS_VAR := 46; -- Format B. + STACK_FORMAT_I <= x"B"; + end if; + when others => null; + end case; + elsif EX_STATE = VALIDATE_FRAME and DATA_RDY = '1' and DATA_VALID = '1' then + STACK_FORMAT_I <= DATA_IN(15 downto 12); + elsif (EX_STATE = BUILD_STACK or EX_STATE = BUILD_TSTACK) and DATA_RDY = '1' then + STACK_POS_VAR := STACK_POS_VAR - 2; -- Always long words are written. + end if; + -- + STACK_CNT <= STACK_POS_VAR; + STACK_POS <= STACK_POS_VAR; + end process STACK_CTRL; + + P_STATUSn : process + -- This logic asserts the STATUSn permanently when the CPU is halted. + -- STATUSn is asserted for three clock cycles when the exception + -- processing starts for RESET, BERR, AERR, 1111, spurious inter- + -- rupt and autovectored interrupt. And for TRACE or external + -- interrupt exception it is asserted for two clock cycles. + variable CNT : std_logic_vector(1 downto 0); + begin + wait until CLK = '1' and CLK' event; + if EX_STATE = CALC_VECT_No then + case EXCEPTION is + when EX_RESET | EX_AERR | EX_BERR | EX_1111 => + CNT := "11"; + STATUSn <= '0'; + when EX_INT | EX_TRACE => + CNT := "10"; + when others => + CNT := "00"; + end case; + end if; + + if EX_STATE = HALTED then + STATUSn <= '0'; + elsif CNT > "00" then + CNT := CNT - '1'; + STATUSn <= '0'; + else + STATUSn <= '1'; + end if; + end process P_STATUSn; + + PIPE_STATUS: process + -- This logic detects the status of the + -- instruction pipe prefetch in the + -- REFILL_PIPE state. + variable CNT : std_logic_vector(1 downto 0); + begin + wait until CLK = '1' and CLK' event; + if EX_STATE /= REFILL_PIPE then + PIPE_FULL <= false; + CNT := "00"; + elsif EX_STATE = REFILL_PIPE and OPCODE_RDY = '1' and CNT < "10" then + CNT := CNT + '1'; + elsif EX_STATE = REFILL_PIPE and OPCODE_RDY = '1' then + PIPE_FULL <= true; + end if; + PIPE_CNT <= CNT; + end process PIPE_STATUS; + + EXCEPTION_HANDLER_REG: process + -- This is the register portion of the + -- exception control state machine. + begin + wait until CLK = '1' and CLK' event; + if RESET = '1' then + EX_STATE <= IDLE; + else + EX_STATE <= NEXT_EX_STATE; + end if; + end process EXCEPTION_HANDLER_REG; + + EXCEPTION_HANDLER_DEC: process(ACCESS_ERR, BUSY_MAIN, BUSY_OPD, DATA_IN, DATA_VALID, DOUBLE_BUSFLT, EX_STATE, EX_P_RESET, EX_P_AERR, EX_P_BERR, EX_P_TRACE, + EX_P_INT, EX_P_ILLEGAL, EX_P_1010, EX_P_TRAPcc, EX_P_RTE, EX_P_1111, EX_P_FORMAT, EX_P_PRIV, EX_P_TRAP, EX_P_TRAPV, + EX_P_CHK, EX_P_DIVZERO, EXCEPTION, DATA_RDY, PIPE_FULL, MBIT, STACK_CNT, STACK_FORMAT_I) + begin + case EX_STATE is + when IDLE => + -- The priority of the exception execution is given by the + -- following construct. Although type 3 commands do not require + -- a prioritization, there is no drawback using these conditions. + -- The spurious interrupt and uninitialized interrupt never appear + -- as basic interrupts and therefore are not an interrupt source. + -- During IDLE, when an interrupt occurs, the status register copy + -- control is asserted and the current interrupt controll is given + -- to the STORE_EXCEPTION process. During bus or address errors, + -- the status register must be copied immediately to recognize + -- the current status for RWn etc. (before the faulty bus cycle is + -- finished). + if (BUSY_MAIN = '1' or BUSY_OPD = '1') and EX_P_RESET = '0' then + NEXT_EX_STATE <= IDLE; -- Wait until the pipelined architecture is ready. + elsif EX_P_RESET = '1' or EX_P_AERR = '1' or EX_P_BERR = '1' then + NEXT_EX_STATE <= INIT; + elsif EX_P_TRAP = '1' or EX_P_TRAPcc = '1' or EX_P_TRAPV = '1' or EX_P_CHK = '1' or EX_P_DIVZERO = '1' then + NEXT_EX_STATE <= INIT; + elsif EX_P_FORMAT = '1' then + NEXT_EX_STATE <= INIT; + elsif EX_P_TRACE = '1' or EX_P_ILLEGAL = '1' or EX_P_1010 = '1' or EX_P_1111 = '1' or EX_P_PRIV = '1' then + NEXT_EX_STATE <= INIT; + elsif EX_P_RTE = '1' then + NEXT_EX_STATE <= INIT; + elsif EX_P_INT = '1' then + NEXT_EX_STATE <= INIT; + else -- No exception. + NEXT_EX_STATE <= IDLE; + end if; + when INIT => + -- In this state, the supervisor mode is switched on (the S bit is set) + -- and the trace mode is switched off (the T bit is cleared). + -- Do not service, if halted. The current bus cycle is always finished + -- in this state. The worst case is a bus error which the finishes the + -- current bus cycle within the next clock cycle after BERR is asserted. + case EXCEPTION is + when EX_RTE => + -- This state is foreseen to handle the address offset + -- correctly in the case the ADR_ATN is already set + -- by the main controller. So we have to wait one + -- clock cycle to ensure this data hazard. + NEXT_EX_STATE <= VALIDATE_FRAME; -- 68K10. + when EX_INT => + NEXT_EX_STATE <= GET_VECTOR; + when others => + NEXT_EX_STATE <= CALC_VECT_No; + end case; + when GET_VECTOR => + -- This state is intended to determine the vector number for the current process. + -- See also the process EXC_VECTOR for the handling of the vector determination. + if DATA_RDY = '1' then + NEXT_EX_STATE <= BUILD_STACK; + else + NEXT_EX_STATE <= GET_VECTOR; + end if; + when CALC_VECT_No => + -- This state is introduced to control the generation of the vector number + -- for all exceptions except the external interrupts. + case EXCEPTION is + when EX_RESET => + NEXT_EX_STATE <= RESTORE_ISP; -- Do not stack anything but update the SSP and PC. + when others => + NEXT_EX_STATE <= BUILD_STACK; + end case; + -- The following states provide writing to the stack pointer or reading + -- the exception vector address from memory. If there is a bus error + -- or an address error during the read or write cycles, the processor + -- proceeds in two different ways: + -- If the errors occur during a reset, bus error or address error + -- exception processing, a double bus fault has occured. In + -- consequence, the processor halts due to catastrophic system failure. + -- If the errors occur during other exception processings, the current + -- processing is aborted and this exception handler state machine will + -- immediately begin with the bus error exception handling. + when BUILD_STACK => + if DOUBLE_BUSFLT = '1' then + NEXT_EX_STATE <= HALTED; + elsif ACCESS_ERR = '1' then + NEXT_EX_STATE <= IDLE; + elsif DATA_RDY = '1' and STACK_CNT = 2 and EXCEPTION = EX_INT and MBIT = '1' then + NEXT_EX_STATE <= SWITCH_STATE; -- Build throwaway stack frame. + elsif DATA_RDY = '1' and STACK_CNT = 2 then + NEXT_EX_STATE <= UPDATE_PC; + else + NEXT_EX_STATE <= BUILD_STACK; + end if; + when SWITCH_STATE => -- Required to decrement the correct stack pointer. + NEXT_EX_STATE <= BUILD_TSTACK; + when BUILD_TSTACK => -- Build throwaway stack frame. + if ACCESS_ERR = '1' then + NEXT_EX_STATE <= IDLE; + elsif DATA_RDY = '1' and STACK_CNT = 2 then + NEXT_EX_STATE <= UPDATE_PC; + else + NEXT_EX_STATE <= BUILD_TSTACK; + end if; + when UPDATE_PC => + if DOUBLE_BUSFLT = '1' then + NEXT_EX_STATE <= HALTED; + elsif ACCESS_ERR = '1' then + NEXT_EX_STATE <= IDLE; + elsif DATA_RDY = '1' then + NEXT_EX_STATE <= REFILL_PIPE; + else + NEXT_EX_STATE <= UPDATE_PC; + end if; + when VALIDATE_FRAME => + if ACCESS_ERR = '1' then + NEXT_EX_STATE <= IDLE; + elsif DATA_RDY = '1' then + case DATA_IN(15 downto 12) is + when x"0" | x"1" | x"2" | x"9" => + NEXT_EX_STATE <= RESTORE_PC; + when x"A" | x"B" => + NEXT_EX_STATE <= EXAMINE_VERSION; + when others => + NEXT_EX_STATE <= IDLE; -- Format error. + end case; + else + NEXT_EX_STATE <= VALIDATE_FRAME; + end if; + when EXAMINE_VERSION => + if ACCESS_ERR = '1' then + NEXT_EX_STATE <= IDLE; + elsif DATA_RDY = '1' then + if DATA_IN /= VERSION then + NEXT_EX_STATE <= IDLE; -- Format error. + else + NEXT_EX_STATE <= READ_TOP; + end if; + else + NEXT_EX_STATE <= EXAMINE_VERSION; + end if; + when READ_TOP => + if ACCESS_ERR = '1' then + NEXT_EX_STATE <= IDLE; + elsif DATA_RDY = '1' then + NEXT_EX_STATE <= READ_BOTTOM; + else + NEXT_EX_STATE <= READ_TOP; + end if; + when READ_BOTTOM => + if ACCESS_ERR = '1' then + NEXT_EX_STATE <= IDLE; + elsif DATA_RDY = '1' then + NEXT_EX_STATE <= RESTORE_PC; + else + NEXT_EX_STATE <= READ_BOTTOM; + end if; + when RESTORE_STATUS => + if DOUBLE_BUSFLT = '1' then + NEXT_EX_STATE <= HALTED; + elsif ACCESS_ERR = '1' then + NEXT_EX_STATE <= IDLE; + elsif DATA_RDY = '1' and STACK_FORMAT_I = x"1" then + NEXT_EX_STATE <= VALIDATE_FRAME; -- Throwaway stack frame. + elsif DATA_RDY = '1' then + NEXT_EX_STATE <= REFILL_PIPE; + else + NEXT_EX_STATE <= RESTORE_STATUS; + end if; + when RESTORE_ISP => + if DOUBLE_BUSFLT = '1' then + NEXT_EX_STATE <= HALTED; + elsif ACCESS_ERR = '1' then + NEXT_EX_STATE <= IDLE; + elsif DATA_RDY = '1' then + NEXT_EX_STATE <= RESTORE_PC; + else + NEXT_EX_STATE <= RESTORE_ISP; + end if; + when RESTORE_PC => + if DOUBLE_BUSFLT = '1' then + NEXT_EX_STATE <= HALTED; -- Double bus fault. + elsif ACCESS_ERR = '1' then + NEXT_EX_STATE <= IDLE; + elsif EXCEPTION = EX_RESET and DATA_RDY = '1' then + NEXT_EX_STATE <= REFILL_PIPE; + elsif DATA_RDY = '1' then + NEXT_EX_STATE <= RESTORE_STATUS; + else + NEXT_EX_STATE <= RESTORE_PC; + end if; + when REFILL_PIPE => + if DOUBLE_BUSFLT = '1' then + NEXT_EX_STATE <= HALTED; + elsif ACCESS_ERR = '1' then + NEXT_EX_STATE <= IDLE; + elsif PIPE_FULL = true then + NEXT_EX_STATE <= IDLE; + else + NEXT_EX_STATE <= REFILL_PIPE; + end if; + when HALTED => + -- Processor halted, Double bus error! + NEXT_EX_STATE <= HALTED; + end case; + end process EXCEPTION_HANDLER_DEC; +end BEHAVIOR; + diff --git a/common/CPU/68K30L/wf68k30L_opcode_decoder.vhd b/common/CPU/68K30L/wf68k30L_opcode_decoder.vhd new file mode 100644 index 00000000..32d0a9aa --- /dev/null +++ b/common/CPU/68K30L/wf68k30L_opcode_decoder.vhd @@ -0,0 +1,1345 @@ +------------------------------------------------------------------------ +---- ---- +---- WF68K30L IP Core: this is the bus controller module. ---- +---- ---- +---- Description: ---- +---- This module is a 68030 compatible instruction word decoder. ---- +---- ---- +---- It is primarily controlled by the following signals: ---- +---- OW_REQ, OPD_ACK, EW_REQ and EW_ACK. The handshaking is as ---- +---- follows: if a new instruction is required, assert the signal ---- +---- OW_REQ and wait until ACK is asserted by the decoder logic. ---- +---- Deassert OW_REQ right after ACK (in the same clock cycle). ---- +---- At this point, the required instruction has already been copied---- +---- from the pipe to the register BIW_0. The respective additional ---- +---- instruction words are located in BIW_1, BIW_2. For more infor- ---- +---- mation see the 68010 "Programmers Reference Manual" and the ---- +---- signal INSTR_LVL in this module. ---- +---- The extension request works in the same manner by asserting ---- +---- EW_REQ. At the time of EXT_ACK one extension word has been ---- +---- copied to EXT_WORD. ---- +---- Be aware that it is in the scope of the logic driving ---- +---- OW_REQ and EW_REQ to hold the instruction pipe aligned. ---- +---- This means in detail, that the correct number or instruction ---- +---- and extension words must be requested. Otherwise unpredictable ---- +---- processor behaviour will occur. Furthermore OW_REQ and EW_REQ ---- +---- must not be asserted the same time. ---- +---- This operation code decoder with the handshake logic as des- ---- +---- cribed above is the first pipeline stage of the CPU architec- ---- +---- ture. ---- +---- ---- +---- ---- +---- Author(s): ---- +---- - Wolfgang Foerster, wf@experiment-s.de; wf@inventronik.de ---- +---- ---- +------------------------------------------------------------------------ +---- ---- +---- Copyright © 2014-2019 Wolfgang Foerster Inventronik GmbH. ---- +---- ---- +---- This documentation describes Open Hardware and is licensed ---- +---- under the CERN OHL v. 1.2. You may redistribute and modify ---- +---- this documentation under the terms of the CERN OHL v.1.2. ---- +---- (http://ohwr.org/cernohl). This documentation is distributed ---- +---- WITHOUT ANY EXPRESS OR IMPLIED WARRANTY, INCLUDING OF ---- +---- MERCHANTABILITY, SATISFACTORY QUALITY AND FITNESS FOR A ---- +---- PARTICULAR PURPOSE. Please see the CERN OHL v.1.2 for ---- +---- applicable conditions ---- +---- ---- +------------------------------------------------------------------------ +-- +-- Revision History +-- +-- Revision 2K14B 20141201 WF +-- Initial Release. +-- Revision 2K18A 20180620 WF +-- Removed REST_BIW_0. +-- Fixed the PW_EW_OFFSET calculation for JSR. +-- TOP, CONTROL, Exception Handler Opcode Decoder: Rearranged PC_INC and ipipe flush logic. +-- Fix for unimplemented or illegal operations: PC is increased before stacked. +-- Implemented the 68K10 loop mechanism. +-- Removed CAHR, we have no cache. +-- Rearranged address error handling. +-- Revision 2K19B 20191224 WF +-- Introduced signal synchronization in the P_BSY process to avoid malfunction by hazards. +-- + +library work; +use work.WF68K30L_PKG.all; + +library ieee; +use ieee.std_logic_1164.all; +use ieee.std_logic_unsigned.all; + +entity WF68K30L_OPCODE_DECODER is + generic(NO_LOOP : boolean); -- If true the DBcc loop mechanism is disabled. + port ( + CLK : in std_logic; + + OW_REQ_MAIN : in bit; -- Request from the execution unit. + EW_REQ_MAIN : in bit; -- Extension words request. + + EXH_REQ : in bit; -- Exception request. + BUSY_EXH : in bit; -- Exception handler is busy. + BUSY_MAIN : in bit; -- Main controller busy. + BUSY_OPD : out bit; -- This unit is busy. + + BKPT_INSERT : in bit; + BKPT_DATA : in std_logic_vector(15 downto 0); + + LOOP_EXIT : in bit; + LOOP_BSY : out bit; + + OPD_ACK_MAIN : out bit; -- Operation controller acknowledge. + EW_ACK : buffer bit; -- Extension word available. + + PC_INC : out bit; + PC_INC_EXH : in bit; + PC_ADR_OFFSET : out std_logic_vector(7 downto 0); + PC_EW_OFFSET : buffer std_logic_vector(3 downto 0); + PC_OFFSET : out std_logic_vector(7 downto 0); + + OPCODE_RD : out bit; + OPCODE_RDY : in bit; + OPCODE_VALID : in std_logic; + OPCODE_DATA : in std_logic_vector(15 downto 0); + + IPIPE_FILL : in bit; + IPIPE_FLUSH : in bit; -- Abandon the instruction pipe. + + -- Fault logic: + OW_VALID : out std_logic; -- Operation words valid. + RC : out std_logic; -- Rerun flag on instruction pipe stage C. + RB : out std_logic; -- Rerun flag on instruction pipe stage B. + FC : out std_logic; -- Fault on use of instruction pipe stage C. + FB : out std_logic; -- Fault on use of instruction pipe stage B. + + -- Trap logic: + SBIT : in std_logic; + TRAP_CODE : out TRAPTYPE_OPC; + + -- System control signals: + OP : buffer OP_68K; + BIW_0 : buffer std_logic_vector(15 downto 0); + BIW_1 : out std_logic_vector(15 downto 0); + BIW_2 : out std_logic_vector(15 downto 0); + EXT_WORD : out std_logic_vector(15 downto 0) + ); +end entity WF68K30L_OPCODE_DECODER; + +architecture BEHAVIOR of WF68K30L_OPCODE_DECODER is +type INSTR_LVL_TYPE is(D, C, B); +type IPIPE_TYPE is + record + D : std_logic_vector(15 downto 0); + C : std_logic_vector(15 downto 0); + B : std_logic_vector(15 downto 0); + end record; + +signal REQ : bit; +signal EW_REQ : bit; + +signal IPIPE : IPIPE_TYPE; +signal FIFO_RD : bit; +signal IPIPE_B_FAULT : std_logic; +signal IPIPE_C_FAULT : std_logic; +signal IPIPE_D_FAULT : std_logic; +signal IPIPE_PNTR : natural range 0 to 3; + +signal INSTR_LVL : INSTR_LVL_TYPE; +signal LOOP_ATN : boolean; +signal LOOP_BSY_I : boolean; +signal LOOP_OP : boolean; + +signal BKPT_REQ : bit; + +signal OP_I : OP_68K; + +signal OPCODE_FLUSH : bit; +signal OPCODE_RD_I : bit; +signal OPCODE_RDY_I : bit; +signal OW_REQ : bit; + +signal TRAP_CODE_I : TRAPTYPE_OPC; +signal FLUSHED : boolean; +signal PC_INC_I : bit; +signal PIPE_RDY : bit; +begin + P_BSY: process(CLK) + -- This logic requires asynchronous reset. This flip flop is intended + -- to break combinatorial loops. If an opcode cycle in the bus controller + -- unit is currently running, the actual PC address is stored during this + -- cycle. Therefore it is not possible to flush the pipe and manipulate + -- the PC during a running cycle. For the exception handler reading the + -- opcode is inhibited during a pipe flush. For the main controller unit + -- and the coprocessor interface the pipe is flushed after a running + -- opcode cycle. + -- Important note: to avoid asynchronous reset by data hazards the + -- resetting signals are synchronized on the negative clock edge. + variable OPCODE_RDY_VAR : bit; + variable BUSY_EXH_VAR : bit; + variable IPIPE_FILL_VAR : bit; + begin + if CLK = '0' and CLK' event then + OPCODE_RDY_VAR := OPCODE_RDY; + BUSY_EXH_VAR := BUSY_EXH; + IPIPE_FILL_VAR := IPIPE_FILL; + end if; + -- + if OPCODE_RDY_VAR = '1' then + OPCODE_RD_I <= '0'; + elsif BUSY_EXH_VAR = '1' and IPIPE_FILL_VAR = '0' then + OPCODE_RD_I <= '0'; + elsif CLK = '1' and CLK' event then + if IPIPE_FLUSH = '1' then + OPCODE_RD_I <= '1'; + elsif (LOOP_ATN = true and OPCODE_RD_I = '0') or LOOP_BSY_I = true then + OPCODE_RD_I <= '0'; + elsif IPIPE_PNTR < 3 then + OPCODE_RD_I <= '1'; + end if; + end if; + end process P_BSY; + + P_OPCODE_FLUSH: process + -- If there is a pending opcode cycle during a pipe flush, + -- an opcode mismatch will destroy scalar opcode processing. + -- To avoid this, we have to dismiss the upcoming opcode. + begin + wait until CLK = '1' and CLK' event; + if IPIPE_FLUSH = '1' and OPCODE_RD_I = '1' and OPCODE_RDY = '0' then + OPCODE_FLUSH <= '1'; + elsif OPCODE_RDY = '1' or BUSY_EXH = '1' then + OPCODE_FLUSH <= '0'; + end if; + end process P_OPCODE_FLUSH; + + OPCODE_RD <= OPCODE_RD_I; + OPCODE_RDY_I <= '0' when OPCODE_FLUSH = '1' else OPCODE_RDY; -- Dismiss the current read cycle. + BUSY_OPD <= '0' when EXH_REQ = '1' and BUSY_MAIN = '0' and IPIPE_PNTR > 0 and OPCODE_RD_I = '0' else -- Fill one opcode is sufficient here. + '1' when IPIPE_PNTR < 3 or OPCODE_RD_I = '1' else '0'; + + INSTRUCTION_PIPE: process + -- These are the instruction pipe FIFO registers. The opcodes are stored in IPIPE.B, IPIPE.C + -- and IPIPE.D which is copied to the instruction register or to the respective extension when + -- read. Be aware, that the pipe is always completely refilled to determine the correct INSTR_LVL + -- before it is copied to the execution unit. + variable IPIPE_D_VAR : std_logic_vector(15 downto 0); + begin + wait until CLK = '1' and CLK' event; + if IPIPE_FLUSH = '1' then + IPIPE.D <= (others => '0'); + IPIPE.C <= (others => '0'); + IPIPE.B <= (others => '0'); + IPIPE_PNTR <= 0; + elsif BKPT_INSERT = '1' then + IPIPE_D_VAR := IPIPE.D; + IPIPE.D <= BKPT_DATA; -- Insert the breakpoint data. + BKPT_REQ <= '1'; + elsif OW_REQ = '1' and BKPT_REQ = '1' then + IPIPE.D <= IPIPE_D_VAR; -- Restore from breakpoint. + BKPT_REQ <= '0'; + elsif LOOP_ATN = true and OPCODE_RD_I = '1' then + null; -- Wait for pending opcodes. + elsif OW_REQ = '1' and PIPE_RDY = '1' and OP_I = DBcc and LOOP_OP = true and IPIPE.C = x"FFFC" then -- Initialize the loop. + IPIPE.D <= BIW_0; -- This is the LEVEL D operation for the loop. + elsif OW_REQ = '1' and LOOP_BSY_I = true then + IPIPE.D <= BIW_0; -- Recycle the loop operations. + elsif LOOP_BSY_I = true then + null; -- Do not change the pipe during the loop. + elsif OW_REQ = '1' and INSTR_LVL = D and PIPE_RDY = '1' and IPIPE_PNTR = 2 then + if OPCODE_RDY_I = '1' then + IPIPE.D <= IPIPE.C; + IPIPE.C <= OPCODE_DATA; + IPIPE_D_FAULT <= IPIPE_C_FAULT; + IPIPE_C_FAULT <= not OPCODE_VALID; + else + IPIPE.D <= IPIPE.C; + IPIPE_D_FAULT <= IPIPE_C_FAULT; + IPIPE_PNTR <= IPIPE_PNTR - 1; + end if; + elsif OW_REQ = '1' and INSTR_LVL = D and PIPE_RDY = '1' and IPIPE_PNTR = 3 then + if OPCODE_RDY_I = '1' then + IPIPE.D <= IPIPE.C; + IPIPE.C <= IPIPE.B; + IPIPE.B <= OPCODE_DATA; + IPIPE_D_FAULT <= IPIPE_C_FAULT; + IPIPE_C_FAULT <= IPIPE_B_FAULT; + IPIPE_B_FAULT <= not OPCODE_VALID; + else + IPIPE.D <= IPIPE.C; + IPIPE.C <= IPIPE.B; + IPIPE_D_FAULT <= IPIPE_C_FAULT; + IPIPE_C_FAULT <= IPIPE_B_FAULT; + IPIPE_PNTR <= IPIPE_PNTR - 1; + end if; + elsif OW_REQ = '1' and INSTR_LVL = C and PIPE_RDY = '1' and IPIPE_PNTR = 2 then + if OPCODE_RDY_I = '1' then + IPIPE.D <= OPCODE_DATA; + IPIPE_D_FAULT <= not OPCODE_VALID; + IPIPE_PNTR <= IPIPE_PNTR - 1; + else + IPIPE_PNTR <= 0; + end if; + elsif OW_REQ = '1' and INSTR_LVL = C and PIPE_RDY = '1' and IPIPE_PNTR = 3 then + if OPCODE_RDY_I = '1' then + IPIPE.D <= IPIPE.B; + IPIPE.C <= OPCODE_DATA; + IPIPE_D_FAULT <= IPIPE_B_FAULT; + IPIPE_C_FAULT <= not OPCODE_VALID; + IPIPE_PNTR <= IPIPE_PNTR - 1; + else + IPIPE.D <= IPIPE.B; + IPIPE_D_FAULT <= IPIPE_B_FAULT; + IPIPE_PNTR <= IPIPE_PNTR - 2; + end if; + elsif OW_REQ = '1' and INSTR_LVL = B and PIPE_RDY = '1' then -- IPIPE_PNTR = 3. + if OPCODE_RDY_I = '1' then + IPIPE.D <= OPCODE_DATA; + IPIPE_D_FAULT <= not OPCODE_VALID; + IPIPE_PNTR <= IPIPE_PNTR - 2; + else + IPIPE_PNTR <= 0; + end if; + elsif EW_REQ = '1' and IPIPE_PNTR >= 1 then + case IPIPE_PNTR is + when 3 => + if OPCODE_RDY_I = '1' then + IPIPE.D <= IPIPE.C; + IPIPE.C <= IPIPE.B; + IPIPE.B <= OPCODE_DATA; + IPIPE_D_FAULT <= IPIPE_C_FAULT; + IPIPE_C_FAULT <= IPIPE_B_FAULT; + IPIPE_B_FAULT <= not OPCODE_VALID; + else + IPIPE.D <= IPIPE.C; + IPIPE.C <= IPIPE.B; + IPIPE_D_FAULT <= IPIPE_C_FAULT; + IPIPE_C_FAULT <= IPIPE_B_FAULT; + IPIPE_PNTR <= IPIPE_PNTR - 1; + end if; + when 2 => + if OPCODE_RDY_I = '1' then + IPIPE.D <= IPIPE.C; + IPIPE.C <= OPCODE_DATA; + IPIPE_D_FAULT <= IPIPE_C_FAULT; + IPIPE_C_FAULT <= not OPCODE_VALID; + else + IPIPE.D <= IPIPE.C; + IPIPE_D_FAULT <= IPIPE_C_FAULT; + IPIPE_PNTR <= IPIPE_PNTR - 1; + end if; + when 1 => + if OPCODE_RDY_I = '1' then + IPIPE.D <= OPCODE_DATA; + IPIPE_D_FAULT <= not OPCODE_VALID; + else + IPIPE_PNTR <= 0; + end if; + when others => null; + end case; + elsif OPCODE_RDY_I = '1' then + case IPIPE_PNTR is + when 2 => + IPIPE.B <= OPCODE_DATA; + IPIPE_B_FAULT <= not OPCODE_VALID; + IPIPE_PNTR <= 3; + when 1 => + IPIPE.C <= OPCODE_DATA; + IPIPE_C_FAULT <= not OPCODE_VALID; + IPIPE_PNTR <= 2; + when 0 => + IPIPE.D <= OPCODE_DATA; + IPIPE_D_FAULT <= not OPCODE_VALID; + IPIPE_PNTR <= 1; + when others => null; + end case; + end if; + end process INSTRUCTION_PIPE; + + P_FAULT: process + -- This are the fault flags for pipe B and C. + -- These flags are set, when an instruction + -- request uses either of the respective pipes. + begin + wait until CLK = '1' and CLK' event; + if IPIPE_FLUSH = '1' then + OW_VALID <= '0'; + FC <= '0'; + FB <= '0'; + elsif OW_REQ = '1' and LOOP_BSY_I = true then + OW_VALID <= '1'; + elsif OW_REQ = '1' and PIPE_RDY = '1' and INSTR_LVL = D then + OW_VALID <= not IPIPE_D_FAULT; + FC <= '0'; + FB <= '0'; + elsif OW_REQ = '1' and PIPE_RDY = '1' and INSTR_LVL = C then + OW_VALID <= not(IPIPE_D_FAULT or IPIPE_C_FAULT); + FC <= IPIPE_C_FAULT; + FB <= '0'; + elsif OW_REQ = '1' and PIPE_RDY = '1' and INSTR_LVL = B then + OW_VALID <= not (IPIPE_D_FAULT or IPIPE_C_FAULT or IPIPE_B_FAULT); + FC <= IPIPE_C_FAULT; + FB <= IPIPE_B_FAULT; + elsif EW_REQ = '1' and PIPE_RDY = '1' then + OW_VALID <= not IPIPE_D_FAULT; + FC <= '0'; + FB <= '0'; + end if; + -- The Rerun Flags: + if IPIPE_FLUSH = '1' then + RC <= '0'; + RB <= '0'; + elsif (EW_REQ or OW_REQ) = '1' and PIPE_RDY = '1' then + RC <= IPIPE_C_FAULT; + RB <= IPIPE_B_FAULT; + end if; + end process P_FAULT; + + OUTBUFFERS: process + variable OP_STOP : boolean; + begin + wait until CLK = '1' and CLK' event; + if OP_STOP = true and IPIPE_FLUSH = '1' then + TRAP_CODE <= NONE; + OP_STOP := false; + elsif IPIPE_FLUSH = '1' then + TRAP_CODE <= NONE; + elsif OP_STOP = true then + null; -- Do not update after PC is incremented. + elsif LOOP_ATN = true and OPCODE_RD_I = '1' then + null; -- Wait for pending opcodes. + elsif OW_REQ = '1' and LOOP_BSY_I = true then + OP <= OP_I; + BIW_0 <= IPIPE.D; + TRAP_CODE <= TRAP_CODE_I; + elsif OW_REQ = '1' and (PIPE_RDY = '1' or BKPT_REQ = '1') then + -- Be aware: all BIW are written unaffected + -- if they are all used. + OP <= OP_I; + BIW_0 <= IPIPE.D; + BIW_1 <= IPIPE.C; + BIW_2 <= IPIPE.B; + TRAP_CODE <= TRAP_CODE_I; + -- + if OP_I = STOP then + OP_STOP := true; + end if; + elsif EW_REQ = '1' and IPIPE_PNTR /= 0 then + EXT_WORD <= IPIPE.D; + end if; + end process OUTBUFFERS; + + LOOP_OP <= false when NO_LOOP = true else + true when OP = MOVE and BIW_0(8 downto 3) = "010010" else -- (Ay) to (Ax). + true when OP = MOVE and BIW_0(8 downto 3) = "011010" else -- (Ay) to (Ax)+. + true when OP = MOVE and BIW_0(8 downto 3) = "100010" else -- (Ay) to -(Ax). + true when OP = MOVE and BIW_0(8 downto 3) = "010011" else -- (Ay)+ to (Ax). + true when OP = MOVE and BIW_0(8 downto 3) = "011011" else -- (Ay)+ to (Ax)+. + true when OP = MOVE and BIW_0(8 downto 3) = "100011" else -- (Ay)+ to -(Ax). + true when OP = MOVE and BIW_0(8 downto 3) = "010100" else -- -(Ay) to (Ax). + true when OP = MOVE and BIW_0(8 downto 3) = "011100" else -- -(Ay) to (Ax)+. + true when OP = MOVE and BIW_0(8 downto 3) = "100100" else -- -(Ay) to -(Ax). + true when OP = MOVE and BIW_0(8 downto 3) = "100100" else -- -(Ay) to -(Ax). + true when OP = MOVE and BIW_0(8 downto 3) = "010000" else -- Dy to (Ax). + true when OP = MOVE and BIW_0(8 downto 3) = "011000" else -- Dy to (Ax)+. + true when OP = MOVE and BIW_0(8 downto 3) = "010001" else -- Ay to (Ax). + true when OP = MOVE and BIW_0(8 downto 3) = "011001" else -- Ay to (Ax)+. + true when (OP = ADD or OP = AND_B or OP = CMP or OP = EOR or OP = OR_B or OP = SUB) and BIW_0(5 downto 3) = "010" else -- (Ay) to Dx, Dx to (Ay). + true when (OP = ADD or OP = AND_B or OP = CMP or OP = EOR or OP = OR_B or OP = SUB) and BIW_0(5 downto 3) = "011" else -- (Ay)+ to Dx, Dx to (Ay)+. + true when (OP = ADD or OP = AND_B or OP = CMP or OP = EOR or OP = OR_B or OP = SUB) and BIW_0(5 downto 3) = "100" else -- -(Ay) to Dx, Dx to -(Ay). + true when (OP = ADDA or OP = CMPA or OP = SUBA) and BIW_0(5 downto 3) = "010" else -- (Ay) to Ax. + true when (OP = ADDA or OP = CMPA or OP = SUBA) and BIW_0(5 downto 3) = "011" else -- (Ay)+ to Ax. + true when (OP = ADDA or OP = CMPA or OP = SUBA) and BIW_0(5 downto 3) = "100" else -- -(Ay) to Ax. + true when OP = ABCD or OP = SBCD or OP = ADDX or OP = SUBX or OP = CMPM else -- -(Ay) to -(Ay), (Ay)+ to (Ay)+ for CMPM. + true when (OP = CLR or OP = NEG or OP = NEGX or OP = NOT_B or OP = TST or OP = NBCD) and BIW_0(5 downto 3) = "010" else -- (Ay). + true when (OP = CLR or OP = NEG or OP = NEGX or OP = NOT_B or OP = TST or OP = NBCD) and BIW_0(5 downto 3) = "011" else -- (Ay)+. + true when (OP = CLR or OP = NEG or OP = NEGX or OP = NOT_B or OP = TST or OP = NBCD) and BIW_0(5 downto 3) = "100" else -- -(Ay). + true when (OP = ASL or OP = ASR or OP = LSL or OP = LSR) and BIW_0(7 downto 3) = "11010" else -- (Ay) by #1. + true when (OP = ASL or OP = ASR or OP = LSL or OP = LSR) and BIW_0(7 downto 3) = "11011" else -- (Ay)+ by #1. + true when (OP = ASL or OP = ASR or OP = LSL or OP = LSR) and BIW_0(7 downto 3) = "11100" else -- -(Ay) by #1. + true when (OP = ROTL or OP = ROTR or OP = ROXL or OP = ROXR) and BIW_0(7 downto 3) = "11010" else -- (Ay) by #1. + true when (OP = ROTL or OP = ROTR or OP = ROXL or OP = ROXR) and BIW_0(7 downto 3) = "11011" else -- (Ay)+ by #1. + true when (OP = ROTL or OP = ROTR or OP = ROXL or OP = ROXR) and BIW_0(7 downto 3) = "11100" else false; -- -(Ay) by #1. + + -- This is the loop attention signal. There are several conditions to start a loop operation. + -- 1. A loop capable operation is in progress indicated by LOOP_OP. + -- 2. A DBcc operation is coming up (IPIPE.D). + -- 3. The displacement is minus four (IPIPE.C). + -- 4. The exception handler may not indicate a request. Otherwise the system may hang in a self + -- blocking mechanism concerning OW_REQ, LOOP_ATN, ALU_BSY. + LOOP_ATN <= false when EXH_REQ = '1' else + true when LOOP_BSY_I = false and LOOP_OP = true and OP_I = DBcc and IPIPE.C = x"FFFC" else false; -- IPIPE.C value must be minus four. + + P_LOOP: process + -- This flip flop controls the loop mode of the + -- processor. Refer to the MC68000 user manual + -- Appendix A for more information. + begin + wait until CLK = '1' and CLK' event; + if LOOP_ATN = true and OW_REQ = '1' and OPCODE_RD_I = '0' then + LOOP_BSY <= '1'; + LOOP_BSY_I <= true; + elsif LOOP_EXIT = '1' or BUSY_EXH = '1' then + LOOP_BSY <= '0'; + LOOP_BSY_I <= false; + end if; + end process P_LOOP; + + OW_REQ <= '0' when BUSY_EXH = '1' else OW_REQ_MAIN; + EW_REQ <= EW_REQ_MAIN; + + PIPE_RDY <= '1' when OW_REQ = '1' and IPIPE_PNTR = 3 and INSTR_LVL = B else + '1' when OW_REQ = '1' and IPIPE_PNTR > 1 and INSTR_LVL = C else + '1' when OW_REQ = '1' and IPIPE_PNTR > 1 and INSTR_LVL = D else -- We need always pipe C and D to determine the INSTR_LVL. + '1' when EW_REQ = '1' and IPIPE_PNTR > 0 else '0'; + + HANDSHAKING: process + -- Wee need these flip flops to ensure, that the OUTBUFFERS are + -- written when the respecktive _ACK signal is asserted. + -- The breakpoint cycles are valid for one word operations and + -- therefore does never start FPU operations. + begin + wait until CLK = '1' and CLK' event; + if EW_REQ = '1' and IPIPE_PNTR /= 0 then + EW_ACK <= '1'; + else + EW_ACK <= '0'; + end if; + + if IPIPE_FLUSH = '1' then + OPD_ACK_MAIN <= '0'; + elsif TRAP_CODE_I = T_PRIV then -- No action when priviledged. + OPD_ACK_MAIN <= '0'; + elsif OW_REQ = '1' and LOOP_BSY_I = true then + OPD_ACK_MAIN <= '1'; + elsif OW_REQ = '1' and (PIPE_RDY = '1' or BKPT_REQ = '1') then + OPD_ACK_MAIN <= '1'; + else + OPD_ACK_MAIN <= '0'; + end if; + end process HANDSHAKING; + + P_PC_OFFSET: process(CLK, BUSY_EXH, LOOP_BSY_I, LOOP_EXIT, OP, PC_INC_I) + -- Be Aware: the ADR_OFFSET requires the 'old' PC_VAR. + -- To arrange this, the ADR_OFFSET logic is located + -- above the PC_VAR logic. Do not change this! + -- The PC_VAR is modeled in a way, that the PC points + -- always to the BIW_0. + -- The PC_EW_OFFSET is also used for the calculation + -- of the correct PC value written to the stack pointer + -- during BSR, JSR and exceptions. + variable ADR_OFFSET : std_logic_vector(6 downto 0); + variable PC_VAR : std_logic_vector(6 downto 0); + variable PC_VAR_MEM : std_logic_vector(6 downto 0); + begin + if CLK = '1' and CLK' event then + if IPIPE_FLUSH = '1' then + ADR_OFFSET := "0000000"; + elsif PC_INC_I = '1' and OPCODE_RDY_I = '1' then + ADR_OFFSET := ADR_OFFSET + '1' - PC_VAR; + elsif OPCODE_RDY_I = '1' then + ADR_OFFSET := ADR_OFFSET + '1'; + elsif PC_INC_I = '1' then + ADR_OFFSET := ADR_OFFSET - PC_VAR; + end if; + -- + if BUSY_EXH = '0' then + PC_VAR_MEM := PC_VAR; -- Store the old offset to write back on the stack. + end if; + + if BUSY_EXH = '1' then + -- New PC is loaded by the exception handler. + -- So PC_VAR must be initialized. + PC_VAR := "0000000"; + elsif PC_INC_I = '1' or FLUSHED = true then + case INSTR_LVL is + when D => PC_VAR := "0000001"; + when C => PC_VAR := "0000010"; + when B => PC_VAR := "0000011"; + end case; + elsif EW_REQ = '1' and IPIPE_PNTR /= 0 then + PC_VAR := PC_VAR + '1'; + end if; + -- + if OW_REQ = '1' and BKPT_REQ = '1' then + PC_EW_OFFSET <= "0010"; -- Always level D operations. + elsif OW_REQ = '1' and PIPE_RDY = '1' and OP_I = JSR then -- Initialize. + PC_EW_OFFSET <= x"0"; + elsif OW_REQ = '1' and PIPE_RDY = '1' then -- BSR. + case INSTR_LVL is + when D => PC_EW_OFFSET <= "0010"; + when C => PC_EW_OFFSET <= "0100"; + when others => PC_EW_OFFSET <= "0110"; -- LONG displacement. + end case; + elsif EW_ACK = '1' and OP = JSR then -- Calculate the required extension words. + PC_EW_OFFSET <= PC_EW_OFFSET + "010"; + end if; + end if; + -- + if BUSY_EXH = '1' and PC_INC_I = '1' then + PC_OFFSET <= PC_VAR_MEM & '0'; + elsif OP = DBcc and LOOP_BSY_I = true and LOOP_EXIT = '0' then + -- Suppress to increment after DBcc operation during the loop to + -- handle a correct PC with displacement when looping around. + -- In non looping mode, the PC_ING is superseeded by + -- IPIPE_FLUSH in the PC logic. In loop mode we have no flush. + PC_OFFSET <= x"00"; + else + PC_OFFSET <= PC_VAR & '0'; + end if; + PC_ADR_OFFSET <= ADR_OFFSET & '0'; + end process P_PC_OFFSET; + + P_FLUSH: process + -- This flip flop is intended to control the incrementation + -- of the PC: normally the PC is updated in the end of an + -- operation (if a new opword is available) or otherwise in + -- the START_OP phase. When the instruction pipe is flushed, + -- it is required to increment the PC immediately to provide + -- the correct address for the pipe refilling. In this case + -- the PC update after the pipe refill is suppressed. + begin + wait until CLK = '1' and CLK' event; + if IPIPE_FLUSH = '1' then + FLUSHED <= true; + elsif OW_REQ = '1' and PIPE_RDY = '1' then + FLUSHED <= false; + end if; + end process P_FLUSH; + + PC_INC <= PC_INC_I; + PC_INC_I <= '0' when FLUSHED = true else -- Avoid double increment after a flushed pipe. + '1' when IPIPE_FLUSH = '1' and BUSY_MAIN = '1' else -- If the pipe is flushed, we need the new PC value for refilling. + '0' when BKPT_REQ = '1' else -- Do not update! + '1' when OW_REQ = '1' and PIPE_RDY = '1' else PC_INC_EXH; + + + -- This signal indicates how many pipe stages are used at a time. + -- Be aware: all coprocessor commands are level D to meet the require- + -- ments of the scanPC. + INSTR_LVL <= D when TRAP_CODE_I = T_PRIV else -- Points to the first word. Required for stacking. + B when OP_I = ADDI and IPIPE.D(7 downto 6) = "10" else + B when OP_I = ANDI and IPIPE.D(7 downto 6) = "10" else + B when (OP_I = Bcc or OP_I = BRA or OP_I = BSR) and IPIPE.D(7 downto 0) = x"FF" else + B when OP_I = CAS2 or (OP_I = CMPI and IPIPE.D(7 downto 6) = "10") else + B when OP_I = EORI and IPIPE.D(7 downto 6) = "10" else + B when OP_I = LINK and IPIPE.D(11 downto 3) = "100000001" else -- LONG. + B when OP_I = ORI and IPIPE.D(7 downto 6) = "10" else + B when OP_I = SUBI and IPIPE.D(7 downto 6) = "10" else + B when OP_I = TRAPcc and IPIPE.D(2 downto 0) = "011" else + C when OP_I = ADDI or OP_I = ANDI or OP_I = ANDI_TO_SR or OP_I = ANDI_TO_CCR else + C when (OP_I = BCHG or OP_I = BCLR or OP_I = BSET or OP_I = BTST) and IPIPE.D(8) = '0' else + C when (OP_I = Bcc or OP_I = BRA or OP_I = BSR) and IPIPE.D(7 downto 0) = x"00" else + C when OP_I = BFCHG or OP_I = BFCLR or OP_I = BFEXTS or OP_I = BFEXTU else + C when OP_I = BFFFO or OP_I = BFINS or OP_I = BFSET or OP_I = BFTST else + C when OP_I = CAS or OP_I = CHK2 or OP_I = CMP2 or OP_I = CMPI or OP_I = DBcc else + C when (OP_I = DIVS or OP_I = DIVU) and IPIPE.D(8 downto 6) = "001" else + C when OP_I = EORI or OP_I = EORI_TO_CCR or OP_I = EORI_TO_SR else + C when OP_I = LINK or OP_I = MOVEC else + C when OP_I = MOVEM or OP_I = MOVEP or OP_I = MOVES else + C when (OP_I = MULS or OP_I = MULU) and IPIPE.D(8 downto 6) = "000" else + C when OP_I = ORI_TO_CCR or OP_I = ORI_TO_SR or OP_I = ORI else + C when OP_I = PACK or OP_I = RTD or OP_I = SUBI or OP_I = STOP else + C when OP_I = TRAPcc and IPIPE.D(2 downto 0) = "010" else + C when OP_I = UNPK else D; + + TRAP_CODE_I <= T_1010 when OP_I = UNIMPLEMENTED and IPIPE.D(15 downto 12) = x"A" else + T_1111 when OP_I = UNIMPLEMENTED and IPIPE.D(15 downto 12) = x"F" else + T_ILLEGAL when OP_I = ILLEGAL else + T_RTE when OP_I = RTE and SBIT = '1' else -- Handled like a trap simplifies the code. + T_TRAP when OP_I = TRAP else + T_PRIV when OP_I = ANDI_TO_SR and SBIT = '0' else + T_PRIV when OP_I = EORI_TO_SR and SBIT = '0' else + T_PRIV when (OP_I = MOVE_FROM_SR or OP_I = MOVE_TO_SR) and SBIT = '0' else + T_PRIV when (OP_I = MOVE_USP or OP_I = MOVEC or OP_I = MOVES) and SBIT = '0' else + T_PRIV when OP_I = ORI_TO_SR and SBIT = '0' else + T_PRIV when (OP_I = RESET or OP_I = RTE) and SBIT = '0' else + T_PRIV when OP_I = STOP and SBIT = '0' else NONE; + + OP_DECODE: process(IPIPE) + begin + -- The default OPCODE is the ILLEGAL operation, if no of the following conditions are met. + -- If any not used bit pattern occurs, the CPU will result in an ILLEGAL trap. An exception of + -- this behavior is the OPCODE with the 1010 or the 1111 pattern in the four MSBs. + -- These lead to the respective traps. + OP_I <= ILLEGAL; + case IPIPE.D(15 downto 12) is -- Operation code map. + when x"0" => -- Bit manipulation / MOVEP / Immediate. + if IPIPE.D(11 downto 0) = x"03C" then + OP_I <= ORI_TO_CCR; + elsif IPIPE.D(11 downto 0) = x"07C" then + OP_I <= ORI_TO_SR; + elsif IPIPE.D(11 downto 0) = x"23C" then + OP_I <= ANDI_TO_CCR; + elsif IPIPE.D(11 downto 0) = x"27C" then + OP_I <= ANDI_TO_SR; + elsif IPIPE.D(11 downto 0) = x"A3C" then + OP_I <= EORI_TO_CCR; + elsif IPIPE.D(11 downto 0) = x"A7C" then + OP_I <= EORI_TO_SR; + elsif IPIPE.D(11 downto 0) = "110011111100" then + OP_I <= CAS2; + elsif IPIPE.D(11 downto 0) = "111011111100" then + OP_I <= CAS2; + elsif IPIPE.D(11 downto 8) = "1110" and IPIPE.D(7 downto 6) < "11" and IPIPE.D(5 downto 3) >= "010" and IPIPE.D(5 downto 3) < "111" then + OP_I <= MOVES; + elsif IPIPE.D(11 downto 8) = "1110" and IPIPE.D(7 downto 6) < "11" and IPIPE.D(5 downto 3) = "111" and IPIPE.D(2 downto 0) < "010" then + OP_I <= MOVES; + elsif IPIPE.D(8 downto 6) > "011" and IPIPE.D(5 downto 3) = "001" then + OP_I <= MOVEP; + elsif IPIPE.D(11) = '0' and IPIPE.D(10 downto 9) /= "11" and IPIPE.D(8 downto 6) = "011" and IPIPE.D(5 downto 3) = "010" and IPIPE.C(11) = '1' then + OP_I <= CHK2; + elsif IPIPE.D(11) = '0' and IPIPE.D(10 downto 9) /= "11" and IPIPE.D(8 downto 6) = "011" and IPIPE.D(5 downto 3) > "100" and IPIPE.D(5 downto 3) < "111" and IPIPE.C(11) = '1' then + OP_I <= CHK2; + elsif IPIPE.D(11) = '0' and IPIPE.D(10 downto 9) /= "11" and IPIPE.D(8 downto 6) = "011" and IPIPE.D(5 downto 3) = "111" and IPIPE.D(2 downto 0) < "100" and IPIPE.C(11) = '1' then + OP_I <= CHK2; + elsif IPIPE.D(11) = '0' and IPIPE.D(10 downto 9) /= "11" and IPIPE.D(8 downto 6) = "011" and IPIPE.D(5 downto 3) = "010" and IPIPE.C(11) = '0' then + OP_I <= CMP2; + elsif IPIPE.D(11) = '0' and IPIPE.D(10 downto 9) /= "11" and IPIPE.D(8 downto 6) = "011" and IPIPE.D(5 downto 3) > "100" and IPIPE.D(5 downto 3) < "111" and IPIPE.C(11) = '0' then + OP_I <= CMP2; + elsif IPIPE.D(11) = '0' and IPIPE.D(10 downto 9) /= "11" and IPIPE.D(8 downto 6) = "011" and IPIPE.D(5 downto 3) = "111" and IPIPE.D(2 downto 0) < "100" and IPIPE.C(11) = '0' then + OP_I <= CMP2; + elsif IPIPE.D(11) = '1' and IPIPE.d(10 downto 9) /= "00" and IPIPE.D(8 downto 6) = "011" and IPIPE.D(5 downto 3) > "001" and IPIPE.D(5 downto 3) < "111" then + OP_I <= CAS; + elsif IPIPE.D(11) = '1' and IPIPE.d(10 downto 9) /= "00" and IPIPE.D(8 downto 6) = "011" and IPIPE.D(5 downto 3) = "111" and IPIPE.D(2 downto 0) < "010" then + OP_I <= CAS; + else + case IPIPE.D(5 downto 3) is -- Addressing mode. + when "000" | "010" | "011" | "100" | "101" | "110" => + -- Bit operations with static bit number: + if IPIPE.D(11 downto 6) = "100000" then + OP_I <= BTST; + elsif IPIPE.D(11 downto 6) = "100001" then + OP_I <= BCHG; + elsif IPIPE.D(11 downto 6) = "100010" then + OP_I <= BCLR; + elsif IPIPE.D(11 downto 6) = "100011" then + OP_I <= BSET; + -- Logic operations: + elsif IPIPE.D(11 downto 8) = x"0" and IPIPE.D(7 downto 6) < "11" then + OP_I <= ORI; + elsif IPIPE.D(11 downto 8) = x"2" and IPIPE.D(7 downto 6) < "11" then + OP_I <= ANDI; + elsif IPIPE.D(11 downto 8) = x"4" and IPIPE.D(7 downto 6) < "11" then + OP_I <= SUBI; + elsif IPIPE.D(11 downto 8) = x"6" and IPIPE.D(7 downto 6) < "11" then + OP_I <= ADDI; + elsif IPIPE.D(11 downto 8) = x"A" and IPIPE.D(7 downto 6) < "11" then + OP_I <= EORI; + elsif IPIPE.D(11 downto 8) = x"C" and IPIPE.D(7 downto 6) < "11" then + OP_I <= CMPI; + -- Bit operations with dynamic bit number: + elsif IPIPE.D(8 downto 6) = "100" then + OP_I <= BTST; + elsif IPIPE.D(8 downto 6) = "101" then + OP_I <= BCHG; + elsif IPIPE.D(8 downto 6) = "110" then + OP_I <= BCLR; + elsif IPIPE.D(8 downto 6) = "111" then + OP_I <= BSET; + end if; + when "111" => + -- In the addressing mode "111" not all register selections are valid. + -- Bit operations with static bit number: + if IPIPE.D(11 downto 6) = "100000" and IPIPE.D(2 downto 0) < "100" then + OP_I <= BTST; + elsif IPIPE.D(11 downto 6) = "100001" and IPIPE.D(2 downto 0) < "010" then + OP_I <= BCHG; + elsif IPIPE.D(11 downto 6) = "100010" and IPIPE.D(2 downto 0) < "010" then + OP_I <= BCLR; + elsif IPIPE.D(11 downto 6) = "100011" and IPIPE.D(2 downto 0) < "010" then + OP_I <= BSET; + -- Logic operations: + elsif IPIPE.D(11 downto 8) = x"0" and IPIPE.D(7 downto 6) < "11" and IPIPE.D(2 downto 0) < "010" then + OP_I <= ORI; + elsif IPIPE.D(11 downto 8) = x"2" and IPIPE.D(7 downto 6) < "11" and IPIPE.D(2 downto 0) < "010" then + OP_I <= ANDI; + elsif IPIPE.D(11 downto 8) = x"4" and IPIPE.D(7 downto 6) < "11" and IPIPE.D(2 downto 0) < "010" then + OP_I <= SUBI; + elsif IPIPE.D(11 downto 8) = x"6" and IPIPE.D(7 downto 6) < "11" and IPIPE.D(2 downto 0) < "010" then + OP_I <= ADDI; + elsif IPIPE.D(11 downto 8) = x"A" and IPIPE.D(7 downto 6) < "11" and IPIPE.D(2 downto 0) < "010" then + OP_I <= EORI; + elsif IPIPE.D(11 downto 8) = x"C" and IPIPE.D(7 downto 6) < "11" and IPIPE.D(2 downto 0) < "100" then + OP_I <= CMPI; + -- Bit operations with dynamic bit number: + elsif IPIPE.D(8 downto 6) = "100" and IPIPE.D(2 downto 0) < "101" then + OP_I <= BTST; + elsif IPIPE.D(8 downto 6) = "101" and IPIPE.D(2 downto 0) < "010" then + OP_I <= BCHG; + elsif IPIPE.D(8 downto 6) = "110" and IPIPE.D(2 downto 0) < "010" then + OP_I <= BCLR; + elsif IPIPE.D(8 downto 6) = "111" and IPIPE.D(2 downto 0) < "010" then + OP_I <= BSET; + end if; + when others => + null; + end case; + end if; + when x"1" => -- Move BYTE. + if IPIPE.D(8 downto 6) = "111" and IPIPE.D(11 downto 9) < "010" + and IPIPE.D(5 downto 3) = "111" and IPIPE.D(2 downto 0) < "101" then + OP_I <= MOVE; + elsif IPIPE.D(8 downto 6) = "111" and IPIPE.D(11 downto 9) < "010" and IPIPE.D(5 downto 3) /= "001" and IPIPE.D(5 downto 3) /= "111" then + OP_I <= MOVE; + elsif IPIPE.D(8 downto 6) /= "001" and IPIPE.D(8 downto 6) /= "111" + and IPIPE.D(5 downto 3) = "111" and IPIPE.D(2 downto 0) < "101" then + OP_I <= MOVE; + elsif IPIPE.D(8 downto 6) /= "001" and IPIPE.D(8 downto 6) /= "111" and IPIPE.D(5 downto 3) /= "001" and IPIPE.D(5 downto 3) /= "111" then + OP_I <= MOVE; + end if; + when x"2" | x"3" => -- Move WORD or LONG. + if IPIPE.D(8 downto 6) = "111" and IPIPE.D(11 downto 9) < "010" + and IPIPE.D(5 downto 3) = "111" and IPIPE.D(2 downto 0) < "101" then + OP_I <= MOVE; + elsif IPIPE.D(8 downto 6) = "111" and IPIPE.D(11 downto 9) < "010" and IPIPE.D(5 downto 3) /= "111" then + OP_I <= MOVE; + elsif IPIPE.D(8 downto 6) = "001" and IPIPE.D(5 downto 3) = "111" and IPIPE.D(2 downto 0) < "101" then + OP_I <= MOVEA; + elsif IPIPE.D(8 downto 6) = "001" and IPIPE.D(5 downto 3) /= "111" then + OP_I <= MOVEA; + elsif IPIPE.D(8 downto 6) /= "001" and IPIPE.D(8 downto 6) /= "111" and IPIPE.D(5 downto 3) = "111" and IPIPE.D(2 downto 0) < "101" then + OP_I <= MOVE; + elsif IPIPE.D(8 downto 6) /= "001" and IPIPE.D(8 downto 6) /= "111" and IPIPE.D(5 downto 3) /= "111" then + OP_I <= MOVE; + end if; + when x"4" => -- Miscellaneous. + if IPIPE.D(11 downto 0) = x"E70" then + OP_I <= RESET; + elsif IPIPE.D(11 downto 0) = x"E71" then + OP_I <= NOP; + elsif IPIPE.D(11 downto 0) = x"E72" then + OP_I <= STOP; + elsif IPIPE.D(11 downto 0) = x"E73" then + OP_I <= RTE; + elsif IPIPE.D(11 downto 0) = x"E74" then + OP_I <= RTD; + elsif IPIPE.D(11 downto 0) = x"E75" then + OP_I <= RTS; + elsif IPIPE.D(11 downto 0) = x"E76" then + OP_I <= TRAPV; + elsif IPIPE.D(11 downto 0) = x"E77" then + OP_I <= RTR; + elsif IPIPE.D(11 downto 0) = x"AFC" then + OP_I <= ILLEGAL; + elsif IPIPE.D(11 downto 1) = "11100111101" and IPIPE.C(11 downto 0) = x"000" then + OP_I <= MOVEC; + elsif IPIPE.D(11 downto 1) = "11100111101" and IPIPE.C(11 downto 0) = x"001" then + OP_I <= MOVEC; + --elsif IPIPE.D(11 downto 1) = "11100111101" and IPIPE.C(11 downto 0) = x"002" then -- No cache. + -- OP_I <= MOVEC; + elsif IPIPE.D(11 downto 1) = "11100111101" and IPIPE.C(11 downto 0) = x"800" then + OP_I <= MOVEC; + elsif IPIPE.D(11 downto 1) = "11100111101" and IPIPE.C(11 downto 0) = x"801" then + OP_I <= MOVEC; + --elsif IPIPE.D(11 downto 1) = "11100111101" and IPIPE.C(11 downto 0) = x"802" then -- No cache. + -- OP_I <= MOVEC; + --elsif IPIPE.D(11 downto 1) = "11100111101" and IPIPE.C(11 downto 0) = x"803" then -- No MMU. + -- OP_I <= MOVEC; + --elsif IPIPE.D(11 downto 1) = "11100111101" and IPIPE.C(11 downto 0) = x"804" then -- No MMU. + -- OP_I <= MOVEC; + elsif IPIPE.D(11 downto 1) = "11100111101" then + OP_I <= ILLEGAL; -- Not valid MOVEC patterns. + elsif IPIPE.D(11 downto 3) = "100001001" then -- 68K20, 68K30, 68K40 + OP_I <= BKPT; + elsif IPIPE.D(11 downto 3) = "100000001" then -- 68K20, 68K30, 68K40 + OP_I <= LINK; -- LONG. + elsif IPIPE.D(11 downto 3) = "111001010" then + OP_I <= LINK; -- WORD. + elsif IPIPE.D(11 downto 3) = "111001011" then + OP_I <= UNLK; + elsif IPIPE.D(11 downto 3) = "100001000" then + OP_I <= SWAP; + elsif IPIPE.D(11 downto 4) = x"E4" then + OP_I <= TRAP; + elsif IPIPE.D(11 downto 4) = x"E6" then + OP_I <= MOVE_USP; + else + case IPIPE.D(5 downto 3) is -- Addressing mode. + when "000" | "010" | "011" | "100" | "101" | "110" => + if IPIPE.D(11 downto 6) = "110001" then + if IPIPE.C(11) = '1' then + OP_I <= DIVS; -- Long. + else + OP_I <= DIVU; -- Long. + end if; + elsif IPIPE.D(11 downto 6) = "001011" then + OP_I <= MOVE_FROM_CCR; + elsif IPIPE.D(11 downto 6) = "000011" then + OP_I <= MOVE_FROM_SR; + elsif IPIPE.D(11 downto 6) = "010011" then + OP_I <= MOVE_TO_CCR; + elsif IPIPE.D(11 downto 6) = "011011" then + OP_I <= MOVE_TO_SR; + elsif IPIPE.D(11 downto 6) = "110000" then + if IPIPE.C(11) = '1' then + OP_I <= MULS; -- Long. + else + OP_I <= MULU; -- Long. + end if; + elsif IPIPE.D(11 downto 6) = "100000" then + OP_I <= NBCD; + elsif IPIPE.D(11 downto 6) = "101011" then + OP_I <= TAS; + end if; + when "111" => -- Not all registers are valid for this mode. + if IPIPE.D(11 downto 6) = "110001" and IPIPE.D(2 downto 0) < "101" then + if IPIPE.C(11) = '1' then + OP_I <= DIVS; -- Long. + else + OP_I <= DIVU; -- Long. + end if; + elsif IPIPE.D(11 downto 6) = "001011" and IPIPE.D(2 downto 0) < "010" then + OP_I <= MOVE_FROM_CCR; + elsif IPIPE.D(11 downto 6) = "000011" and IPIPE.D(2 downto 0) < "010" then + OP_I <= MOVE_FROM_SR; + elsif IPIPE.D(11 downto 6) = "010011" and IPIPE.D(2 downto 0) < "101" then + OP_I <= MOVE_TO_CCR; + elsif IPIPE.D(11 downto 6) = "011011" and IPIPE.D(2 downto 0) < "101" then + OP_I <= MOVE_TO_SR; + elsif IPIPE.D(11 downto 6) = "110000" and IPIPE.D(2 downto 0) < "101" then + if IPIPE.C(11) = '1' then + OP_I <= MULS; -- Long. + else + OP_I <= MULU; -- Long. + end if; + elsif IPIPE.D(11 downto 6) = "100000" and IPIPE.D(2 downto 0) < "010" then + OP_I <= NBCD; + elsif IPIPE.D(11 downto 6) = "101011" and IPIPE.D(2 downto 0) < "010" then + OP_I <= TAS; + end if; + when others => + null; + end case; + + case IPIPE.D(5 downto 3) is -- Addressing mode. + when "010" | "101" | "110" => + if IPIPE.D(11 downto 6) = "100001" then + OP_I <= PEA; + elsif IPIPE.D(11 downto 6) = "111010" then + OP_I <= JSR; + elsif IPIPE.D(11 downto 6) = "111011" then + OP_I <= JMP; + end if; + when "111" => -- Not all registers are valid for this mode. + if IPIPE.D(11 downto 6) = "100001" and IPIPE.D(2 downto 0) < "100" then + OP_I <= PEA; + elsif IPIPE.D(11 downto 6) = "111010" and IPIPE.D(2 downto 0) < "100" then + OP_I <= JSR; + elsif IPIPE.D(11 downto 6) = "111011" and IPIPE.D(2 downto 0) < "100" then + OP_I <= JMP; + end if; + when others => + null; + end case; + + -- For the following operation codes a SIZE (IPIPE.D(7 downto 6)) is not valid. + -- For the following operation codes an addressing mode x"001" is not valid. + if IPIPE.D(7 downto 6) < "11" and IPIPE.D(5 downto 3) /= "001" and IPIPE.D(5 downto 3) /= "111" then + case IPIPE.D(11 downto 8) is + when x"0" => OP_I <= NEGX; + when x"2" => OP_I <= CLR; + when x"4" => OP_I <= NEG; + when x"6" => OP_I <= NOT_B; + when others => null; + end case; + -- Not all registers are valid for the addressing mode "111": + elsif IPIPE.D(7 downto 6) < "11" and IPIPE.D(5 downto 3) = "111" and IPIPE.D(2 downto 0) < "010" then + case IPIPE.D(11 downto 8) is + when x"0" => OP_I <= NEGX; + when x"2" => OP_I <= CLR; + when x"4" => OP_I <= NEG; + when x"6" => OP_I <= NOT_B; + when others => null; + end case; + end if; + + -- if IPIPE.D(11 downto 8) = x"A" and IPIPE.D(7 downto 6) < "11" and IPIPE.D(5 downto 3) = "111" and (IPIPE.D(2 downto 0) < "010" or IPIPE.D(2 downto 0) = "100") then -- 68K + if IPIPE.D(11 downto 8) = x"A" and IPIPE.D(7 downto 6) < "11" and IPIPE.D(5 downto 3) = "111" and IPIPE.D(2 downto 0) < "101" then + case IPIPE.D(7 downto 6) is + when "01" | "10" => OP_I <= TST; -- Long or word, all addressing modes. + when others => -- Byte: Address register direct not allowed. + if IPIPE.D(2 downto 0) /= "100" then + OP_I <= TST; + end if; + end case; + elsif IPIPE.D(11 downto 8) = x"A" and IPIPE.D(7 downto 6) < "11" and IPIPE.D(5 downto 3) /= "111" then + case IPIPE.D(7 downto 6) is + when "01" | "10" => OP_I <= TST; -- Long or word, all addressing modes. + when others => -- Byte: Address register direct not allowed. + if IPIPE.D(5 downto 3) /= "001" then + OP_I <= TST; + end if; + end case; + end if; + + if IPIPE.D(11 downto 9) = "100" and IPIPE.D(5 downto 3) = "000" then + case IPIPE.D(8 downto 6) is -- Valid OPMODES for this operation code. + when "010" | "011" => OP_I <= EXT; + when "111" => OP_I <= EXTB; + when others => null; + end case; + end if; + + if IPIPE.D(8 downto 6) = "111" then + case IPIPE.D(5 downto 3) is -- OPMODES. + when "010" | "101" | "110" => + OP_I <= LEA; + when "111" => + if IPIPE.D(2 downto 0) < "100" then -- Not all registers are valid for this OPMODE. + OP_I <= LEA; + end if; + when others => null; + end case; + end if; + + if IPIPE.D(11) = '1' and IPIPE.D(9 downto 7) = "001" then + if IPIPE.D(10) = '0' then -- Register to memory transfer. + case IPIPE.D(5 downto 3) is -- OPMODES, no postincrement addressing. + when "010" | "100" | "101" | "110" => + OP_I <= MOVEM; + when "111" => + if IPIPE.D(2 downto 0) = "000" or IPIPE.D(2 downto 0) = "001" then + OP_I <= MOVEM; + end if; + when others => null; + end case; + else -- Memory to register transfer, no predecrement addressing. + case IPIPE.D(5 downto 3) is -- OPMODES. + when "010" | "011" | "101" | "110" => + OP_I <= MOVEM; + when "111" => + if IPIPE.D(2 downto 0) < "100" then + OP_I <= MOVEM; + end if; + when others => null; + end case; + end if; + end if; + + -- The size must be "10" or "11" and the OPMODE may not be "001". + if IPIPE.D(8 downto 7) >= "10" and IPIPE.D(6 downto 3) = x"7" and IPIPE.D(2 downto 0) < "101" then + OP_I <= CHK; + elsif IPIPE.D(8 downto 7) >= "10" and IPIPE.D(6 downto 3) /= x"1" and IPIPE.D(6 downto 3) < x"7" then + OP_I <= CHK; + end if; + end if; + when x"5" => -- ADDQ / SUBQ / Scc / DBcc / TRAPcc. + if IPIPE.D(7 downto 3) = "11001" then + OP_I <= DBcc; + elsif IPIPE.D(7 downto 6) = "11" and IPIPE.D(5 downto 3) = "111" and IPIPE.D(2 downto 0) < "010" then + OP_I <= Scc; + elsif IPIPE.D(7 downto 6) = "11" and IPIPE.D(5 downto 3) /= "001" and IPIPE.D(5 downto 3) /= "111" then + OP_I <= Scc; + -- + elsif IPIPE.D(8) = '0' and IPIPE.D(7 downto 6) < "11" and IPIPE.D(5 downto 3) = "111" and IPIPE.D(2 downto 0) < "010" then + OP_I <= ADDQ; + elsif IPIPE.D(8) = '0' and (IPIPE.D(7 downto 6) = "01" or IPIPE.D(7 downto 6) = "10") and IPIPE.D(5 downto 3) /= "111" then + OP_I <= ADDQ; + elsif IPIPE.D(8) = '0' and IPIPE.D(7 downto 6) = "00" and IPIPE.D(5 downto 3) /= "001" and IPIPE.D(5 downto 3) /= "111" then + OP_I <= ADDQ; + -- + elsif IPIPE.D(8) = '1' and IPIPE.D(7 downto 6) < "11" and IPIPE.D(5 downto 3) = "111" and IPIPE.D(2 downto 0) < "010" then + OP_I <= SUBQ; + elsif IPIPE.D(8) = '1' and (IPIPE.D(7 downto 6) = "01" or IPIPE.D(7 downto 6) = "10") and IPIPE.D(5 downto 3) /= "111" then + OP_I <= SUBQ; + elsif IPIPE.D(8) = '1' and IPIPE.D(7 downto 6) = "00" and IPIPE.D(5 downto 3) /= "001" and IPIPE.D(5 downto 3) /= "111" then + OP_I <= SUBQ; + -- + elsif IPIPE.D(7 downto 3) = "11111" then + OP_I <= TRAPcc; + end if; + when x"6" => -- Bcc / BSR / BRA. + if IPIPE.D(11 downto 8) = x"0" then + OP_I <= BRA; + elsif IPIPE.D(11 downto 8) = x"1" then + OP_I <= BSR; + else + OP_I <= Bcc; + end if; + when x"7" => -- MOVEQ. + if IPIPE.D(8) = '0' then + OP_I <= MOVEQ; + end if; + when x"8" => -- OR / DIV / SBCD / PACK / UNPK. + if IPIPE.D(8 downto 4) = "10100" then + OP_I <= PACK; + elsif IPIPE.D(8 downto 4) = "11000" then + OP_I <= UNPK; + elsif IPIPE.D(8 downto 6) = "011" and IPIPE.D(5 downto 3) = "111" and IPIPE.D(2 downto 0) < "101" then + OP_I <= DIVU; -- WORD. + elsif IPIPE.D(8 downto 6) = "011" and IPIPE.D(5 downto 3) /= "001" and IPIPE.D(5 downto 3) /= "111" then + OP_I <= DIVU; -- WORD. + elsif IPIPE.D(8 downto 6) = "111" and IPIPE.D(5 downto 3) = "111" and IPIPE.D(2 downto 0) < "101" then + OP_I <= DIVS; -- WORD. + elsif IPIPE.D(8 downto 6) = "111" and IPIPE.D(5 downto 3) /= "001" and IPIPE.D(5 downto 3) /= "111" then + OP_I <= DIVS; -- WORD. + elsif IPIPE.D(8 downto 4) = "10000" then + OP_I <= SBCD; + end if; + -- + case IPIPE.D(8 downto 6) is + when "000" | "001" | "010" => + if IPIPE.D(5 downto 3) = "111" and IPIPE.D(2 downto 0) < "101" then + OP_I <= OR_B; + elsif IPIPE.D(5 downto 3) /= "001" and IPIPE.D(5 downto 3) /= "111" then + OP_I <= OR_B; + end if; + when "100" | "101" | "110" => + if IPIPE.D(5 downto 3) = "111" and IPIPE.D(2 downto 0) < "010" then + OP_I <= OR_B; + elsif IPIPE.D(5 downto 3) > "001" and IPIPE.D(5 downto 3) /= "111" then + OP_I <= OR_B; + end if; + when others => + null; + end case; + when x"9" => -- SUB / SUBX. + case IPIPE.D(8 downto 6) is + when "000" => -- Byte size. + if IPIPE.D(5 downto 3) = "111" and IPIPE.D(2 downto 0) < "101" then + OP_I <= SUB; + elsif IPIPE.D(5 downto 3) /= "111" and IPIPE.D(5 downto 3) /= "001" then + OP_I <= SUB; + end if; + when "001" | "010" => -- Word and long. + if IPIPE.D(5 downto 3) = "111" and IPIPE.D(2 downto 0) < "101" then + OP_I <= SUB; + elsif IPIPE.D(5 downto 3) /= "111" then + OP_I <= SUB; + end if; + when "100" => + if IPIPE.D(5 downto 3) = "000" or IPIPE.D(5 downto 3) = "001" then + OP_I <= SUBX; + elsif IPIPE.D(5 downto 3) = "111" and IPIPE.D(2 downto 0) < "010" then + OP_I <= SUB; + elsif IPIPE.D(5 downto 3) /= "111" and IPIPE.D(5 downto 3) /= "001" then -- Byte size. + OP_I <= SUB; + end if; + when "101" | "110" => + if IPIPE.D(5 downto 3) = "000" or IPIPE.D(5 downto 3) = "001" then + OP_I <= SUBX; + elsif IPIPE.D(5 downto 3) = "111" and IPIPE.D(2 downto 0) < "010" then + OP_I <= SUB; + elsif IPIPE.D(5 downto 3) /= "111" then -- Word and long. + OP_I <= SUB; + end if; + when "011" | "111" => + if IPIPE.D(5 downto 3) = "111" and IPIPE.D(2 downto 0) < "101" then + OP_I <= SUBA; + elsif IPIPE.D(5 downto 3) /= "111" then + OP_I <= SUBA; + end if; + when others => -- U, X, Z, W, H, L, -. + null; + end case; + when x"A" => -- (1010, Unassigned, Reserved). + OP_I <= UNIMPLEMENTED; + when x"B" => -- CMP / EOR. + if IPIPE.D(8) = '1' and IPIPE.D(7 downto 6) < "11" and IPIPE.D(5 downto 3) = "001" then + OP_I <= CMPM; + else + case IPIPE.D(8 downto 6) is -- OPMODE field. + when "000" => + if IPIPE.D(5 downto 3) = "111" and IPIPE.D(2 downto 0) < "101" then + OP_I <= CMP; + elsif IPIPE.D(5 downto 3) /= "001" and IPIPE.D(5 downto 3) /= "111" then + OP_I <= CMP; + end if; + when "001" | "010" => + if IPIPE.D(5 downto 3) = "111" and IPIPE.D(2 downto 0) < "101" then + OP_I <= CMP; + elsif IPIPE.D(5 downto 3) /= "111" then + OP_I <= CMP; + end if; + when "011" | "111" => + if IPIPE.D(5 downto 3) = "111" and IPIPE.D(2 downto 0) < "101" then + OP_I <= CMPA; + elsif IPIPE.D(5 downto 3) /= "111" then + OP_I <= CMPA; + end if; + when "100" | "101" | "110" => + if IPIPE.D(5 downto 3) = "111" and IPIPE.D(2 downto 0) < "101" then + OP_I <= EOR; + elsif IPIPE.D(5 downto 3) /= "001" and IPIPE.D(5 downto 3) /= "111" then + OP_I <= EOR; + end if; + when others => -- U, X, Z, W, H, L, -. + null; + end case; + end if; + when x"C" => -- AND / MUL / ABCD / EXG. + if IPIPE.D(8 downto 4) = "10000" then + OP_I <= ABCD; + elsif IPIPE.D(8 downto 6) = "011" and IPIPE.D(5 downto 3) = "111" and IPIPE.D(2 downto 0) < "101" then + OP_I <= MULU; -- WORD. + elsif IPIPE.D(8 downto 6) = "011" and IPIPE.D(5 downto 3) /= "001" and IPIPE.D(5 downto 3) /= "111" then + OP_I <= MULU; -- WORD. + elsif IPIPE.D(8 downto 6) = "111" and IPIPE.D(5 downto 3) = "111" and IPIPE.D(2 downto 0) < "101" then + OP_I <= MULS; -- WORD. + elsif IPIPE.D(8 downto 6) = "111" and IPIPE.D(5 downto 3) /= "001" and IPIPE.D(5 downto 3) /= "111" then + OP_I <= MULS; -- WORD. + elsif IPIPE.D(8 downto 3) = "101000" or IPIPE.D(8 downto 3) = "101001" or IPIPE.D(8 downto 3) = "110001" then + OP_I <= EXG; + else + case IPIPE.D(8 downto 6) is -- OPMODE + when "000" | "001" | "010" => + if IPIPE.D(5 downto 3) = "111" and IPIPE.D(2 downto 0) < "101" then + OP_I <= AND_B; + elsif IPIPE.D(5 downto 3) /= "001" and IPIPE.D(5 downto 3) /= "111" then + OP_I <= AND_B; + end if; + when "100" | "101" | "110" => + if IPIPE.D(5 downto 3) = "111" and IPIPE.D(2 downto 0) < "010" then + OP_I <= AND_B; + elsif IPIPE.D(5 downto 3) > "001" and IPIPE.D(5 downto 3) /= "111" then + OP_I <= AND_B; + end if; + when others => + null; + end case; + end if; + when x"D" => -- ADD / ADDX. + case IPIPE.D(8 downto 6) is + when "000" => + if IPIPE.D(5 downto 3) = "111" and IPIPE.D(2 downto 0) < "101" then + OP_I <= ADD; + elsif IPIPE.D(5 downto 3) /= "111" and IPIPE.D(5 downto 3) /= "001" then + OP_I <= ADD; + end if; + when "001" | "010" => + if IPIPE.D(5 downto 3) = "111" and IPIPE.D(2 downto 0) < "101" then + OP_I <= ADD; + elsif IPIPE.D(5 downto 3) /= "111" then + OP_I <= ADD; + end if; + when "100" => + if IPIPE.D(5 downto 3) = "000" or IPIPE.D(5 downto 3) = "001" then + OP_I <= ADDX; + elsif IPIPE.D(5 downto 3) = "111" and IPIPE.D(2 downto 0) < "010" then + OP_I <= ADD; + elsif IPIPE.D(5 downto 3) /= "111" and IPIPE.D(5 downto 3) /= "001" then + OP_I <= ADD; + end if; + when "101" | "110" => + if IPIPE.D(5 downto 3) = "000" or IPIPE.D(5 downto 3) = "001" then + OP_I <= ADDX; + elsif IPIPE.D(5 downto 3) = "111" and IPIPE.D(2 downto 0) < "010" then + OP_I <= ADD; + elsif IPIPE.D(5 downto 3) /= "111" then + OP_I <= ADD; + end if; + when "011" | "111" => + if IPIPE.D(5 downto 3) = "111" and IPIPE.D(2 downto 0) < "101" then + OP_I <= ADDA; + elsif IPIPE.D(5 downto 3) /= "111" then + OP_I <= ADDA; + end if; + when others => -- U, X, Z, W, H, L, -. + null; + end case; + when x"E" => -- Shift / Rotate / Bit Field. + if IPIPE.D(11 downto 6) = "101011" and (IPIPE.D(5 downto 3) = "000" or IPIPE.D(5 downto 3) = "010") then + OP_I <= BFCHG; + elsif IPIPE.D(11 downto 6) = "101011" and (IPIPE.D(5 downto 3) >= "101" or IPIPE.D(5 downto 3) <= "110") then + OP_I <= BFCHG; + elsif IPIPE.D(11 downto 6) = "101011" and IPIPE.D(5 downto 3) = "111" and IPIPE.D(2 downto 0) < "010" then + OP_I <= BFCHG; + elsif IPIPE.D(11 downto 6) = "110011" and (IPIPE.D(5 downto 3) = "000" or IPIPE.D(5 downto 3) = "010") then + OP_I <= BFCLR; + elsif IPIPE.D(11 downto 6) = "110011" and (IPIPE.D(5 downto 3) >= "101" or IPIPE.D(5 downto 3) <= "110") then + OP_I <= BFCLR; + elsif IPIPE.D(11 downto 6) = "110011" and IPIPE.D(5 downto 3) = "111" and IPIPE.D(2 downto 0) < "010" then + OP_I <= BFCLR; + elsif IPIPE.D(11 downto 6) = "101111" and (IPIPE.D(5 downto 3) = "000" or IPIPE.D(5 downto 3) = "010") then + OP_I <= BFEXTS; + elsif IPIPE.D(11 downto 6) = "101111" and (IPIPE.D(5 downto 3) >= "101" or IPIPE.D(5 downto 3) <= "110") then + OP_I <= BFEXTS; + elsif IPIPE.D(11 downto 6) = "101111" and IPIPE.D(5 downto 3) = "111" and IPIPE.D(2 downto 0) < "100" then + OP_I <= BFEXTS; + elsif IPIPE.D(11 downto 6) = "100111" and (IPIPE.D(5 downto 3) = "000" or IPIPE.D(5 downto 3) = "010") then + OP_I <= BFEXTU; + elsif IPIPE.D(11 downto 6) = "100111" and (IPIPE.D(5 downto 3) >= "101" or IPIPE.D(5 downto 3) <= "110") then + OP_I <= BFEXTU; + elsif IPIPE.D(11 downto 6) = "100111" and IPIPE.D(5 downto 3) = "111" and IPIPE.D(2 downto 0) < "100" then + OP_I <= BFEXTU; + elsif IPIPE.D(11 downto 6) = "110111" and (IPIPE.D(5 downto 3) = "000" or IPIPE.D(5 downto 3) = "010") then + OP_I <= BFFFO; + elsif IPIPE.D(11 downto 6) = "110111" and (IPIPE.D(5 downto 3) >= "101" or IPIPE.D(5 downto 3) <= "110") then + OP_I <= BFFFO; + elsif IPIPE.D(11 downto 6) = "110111" and IPIPE.D(5 downto 3) = "111" and IPIPE.D(2 downto 0) < "100" then + OP_I <= BFFFO; + elsif IPIPE.D(11 downto 6) = "111111" and (IPIPE.D(5 downto 3) = "000" or IPIPE.D(5 downto 3) = "010") then + OP_I <= BFINS; + elsif IPIPE.D(11 downto 6) = "111111" and (IPIPE.D(5 downto 3) >= "101" or IPIPE.D(5 downto 3) <= "110") then + OP_I <= BFINS; + elsif IPIPE.D(11 downto 6) = "111111" and IPIPE.D(5 downto 3) = "111" and IPIPE.D(2 downto 0) < "010" then + OP_I <= BFINS; + elsif IPIPE.D(11 downto 6) = "111011" and (IPIPE.D(5 downto 3) = "000" or IPIPE.D(5 downto 3) = "010") then + OP_I <= BFSET; + elsif IPIPE.D(11 downto 6) = "111011" and (IPIPE.D(5 downto 3) >= "101" or IPIPE.D(5 downto 3) <= "110") then + OP_I <= BFSET; + elsif IPIPE.D(11 downto 6) = "111011" and IPIPE.D(5 downto 3) = "111" and IPIPE.D(2 downto 0) < "010" then + OP_I <= BFSET; + elsif IPIPE.D(11 downto 6) = "100011" and (IPIPE.D(5 downto 3) = "000" or IPIPE.D(5 downto 3) = "010") then + OP_I <= BFTST; + elsif IPIPE.D(11 downto 6) = "100011" and (IPIPE.D(5 downto 3) >= "101" or IPIPE.D(5 downto 3) <= "110") then + OP_I <= BFTST; + elsif IPIPE.D(11 downto 6) = "100011" and IPIPE.D(5 downto 3) = "111" and IPIPE.D(2 downto 0) < "100" then + OP_I <= BFTST; + elsif IPIPE.D(11 downto 6) = "000011" and IPIPE.D(5 downto 3) = "111" and IPIPE.D(2 downto 0) < "010" then + OP_I <= ASR; -- Memory shifts. + elsif IPIPE.D(11 downto 6) = "000011" and IPIPE.D(5 downto 3) > "001" and IPIPE.D(5 downto 3) /= "111" then + OP_I <= ASR; -- Memory shifts. + elsif IPIPE.D(11 downto 6) = "000111" and IPIPE.D(5 downto 3) = "111" and IPIPE.D(2 downto 0) < "010" then + OP_I <= ASL; -- Memory shifts. + elsif IPIPE.D(11 downto 6) = "000111" and IPIPE.D(5 downto 3) > "001" and IPIPE.D(5 downto 3) /= "111" then + OP_I <= ASL; -- Memory shifts. + elsif IPIPE.D(11 downto 6) = "001011" and IPIPE.D(5 downto 3) = "111" and IPIPE.D(2 downto 0) < "010" then + OP_I <= LSR; -- Memory shifts. + elsif IPIPE.D(11 downto 6) = "001011" and IPIPE.D(5 downto 3) > "001" and IPIPE.D(5 downto 3) /= "111" then + OP_I <= LSR; -- Memory shifts. + elsif IPIPE.D(11 downto 6) = "001111" and IPIPE.D(5 downto 3) = "111" and IPIPE.D(2 downto 0) < "010" then + OP_I <= LSL; -- Memory shifts. + elsif IPIPE.D(11 downto 6) = "001111" and IPIPE.D(5 downto 3) > "001" and IPIPE.D(5 downto 3) /= "111" then + OP_I <= LSL; -- Memory shifts. + elsif IPIPE.D(11 downto 6) = "010011" and IPIPE.D(5 downto 3) = "111" and IPIPE.D(2 downto 0) < "010" then + OP_I <= ROXR; -- Memory shifts. + elsif IPIPE.D(11 downto 6) = "010011" and IPIPE.D(5 downto 3) > "001" and IPIPE.D(5 downto 3) /= "111" then + OP_I <= ROXR; -- Memory shifts. + elsif IPIPE.D(11 downto 6) = "010111" and IPIPE.D(5 downto 3) = "111" and IPIPE.D(2 downto 0) < "010" then + OP_I <= ROXL; -- Memory shifts. + elsif IPIPE.D(11 downto 6) = "010111" and IPIPE.D(5 downto 3) > "001" and IPIPE.D(5 downto 3) /= "111" then + OP_I <= ROXL; -- Memory shifts. + elsif IPIPE.D(11 downto 6) = "011011" and IPIPE.D(5 downto 3) = "111" and IPIPE.D(2 downto 0) < "010" then + OP_I <= ROTR; -- Memory shifts. + elsif IPIPE.D(11 downto 6) = "011011" and IPIPE.D(5 downto 3) > "001" and IPIPE.D(5 downto 3) /= "111" then + OP_I <= ROTR; -- Memory shifts. + elsif IPIPE.D(11 downto 6) = "011111" and IPIPE.D(5 downto 3) = "111" and IPIPE.D(2 downto 0) < "010" then + OP_I <= ROTL; -- Memory shifts. + elsif IPIPE.D(11 downto 6) = "011111" and IPIPE.D(5 downto 3) > "001" and IPIPE.D(5 downto 3) /= "111" then + OP_I <= ROTL; -- Memory shifts. + elsif IPIPE.D(8) = '0' and IPIPE.D(7 downto 6) < "11" and IPIPE.D(4 downto 3) = "00" then + OP_I <= ASR; -- Register shifts. + elsif IPIPE.D(8) = '1' and IPIPE.D(7 downto 6) < "11" and IPIPE.D(4 downto 3) = "00" then + OP_I <= ASL; -- Register shifts. + elsif IPIPE.D(8) = '0' and IPIPE.D(7 downto 6) < "11" and IPIPE.D(4 downto 3) = "01" then + OP_I <= LSR; -- Register shifts. + elsif IPIPE.D(8) = '1' and IPIPE.D(7 downto 6) < "11" and IPIPE.D(4 downto 3) = "01" then + OP_I <= LSL; -- Register shifts. + elsif IPIPE.D(8) = '0' and IPIPE.D(7 downto 6) < "11" and IPIPE.D(4 downto 3) = "10" then + OP_I <= ROXR; -- Register shifts. + elsif IPIPE.D(8) = '1' and IPIPE.D(7 downto 6) < "11" and IPIPE.D(4 downto 3) = "10" then + OP_I <= ROXL; -- Register shifts. + elsif IPIPE.D(8) = '0' and IPIPE.D(7 downto 6) < "11" and IPIPE.D(4 downto 3) = "11" then + OP_I <= ROTR; -- Register shifts. + elsif IPIPE.D(8) = '1' and IPIPE.D(7 downto 6) < "11" and IPIPE.D(4 downto 3) = "11" then + OP_I <= ROTL; -- Register shifts. + end if; + when x"F" => -- 1111, Coprocessor Interface / 68K40 Extensions. + OP_I <= UNIMPLEMENTED; + when others => -- U, X, Z, W, H, L, -. + null; + end case; + end process OP_DECODE; +end BEHAVIOR; diff --git a/common/CPU/68K30L/wf68k30L_pkg.vhd b/common/CPU/68K30L/wf68k30L_pkg.vhd new file mode 100644 index 00000000..2ea7f306 --- /dev/null +++ b/common/CPU/68K30L/wf68k30L_pkg.vhd @@ -0,0 +1,457 @@ +------------------------------------------------------------------------ +---- ---- +---- WF68K30L IP Core: this is the package file containing the data ---- +---- types and the component declarations. ---- +---- ---- +---- Author(s): ---- +---- - Wolfgang Foerster, wf@experiment-s.de; wf@inventronik.de ---- +---- ---- +------------------------------------------------------------------------ +---- ---- +---- Copyright © 2014-2019 Wolfgang Foerster Inventronik GmbH. ---- +---- ---- +---- This documentation describes Open Hardware and is licensed ---- +---- under the CERN OHL v. 1.2. You may redistribute and modify ---- +---- this documentation under the terms of the CERN OHL v.1.2. ---- +---- (http://ohwr.org/cernohl). This documentation is distributed ---- +---- WITHOUT ANY EXPRESS OR IMPLIED WARRANTY, INCLUDING OF ---- +---- MERCHANTABILITY, SATISFACTORY QUALITY AND FITNESS FOR A ---- +---- PARTICULAR PURPOSE. Please see the CERN OHL v.1.2 for ---- +---- applicable conditions ---- +---- ---- +------------------------------------------------------------------------ +-- +-- Revision History +-- +-- Revision 2K14B 20141201 WF +-- Initial Release. +-- Later revisions +-- Modifications according to changes of the entity in other modules. +-- + +library ieee; +use ieee.std_logic_1164.all; + +package WF68K30L_PKG is +type OP_SIZETYPE is (LONG, WORD, BYTE); +-- The OPCODES AND, NOT, OR, ROR and ROL are defined keywords in VHDL. Therefore the assignment is +-- AND_B, NOT_B, OR_B, ROTR and ROTL. +type OP_68K is (ABCD, ADD, ADDA, ADDI, ADDQ, ADDX, AND_B, ANDI, ANDI_TO_CCR, ANDI_TO_SR, ASL, ASR, Bcc, BCHG, BCLR, + BFCHG, BFCLR, BFEXTS, BFEXTU, BFFFO, BFINS, BFSET, BFTST, BKPT, BRA, BSET, BSR, BTST, CAS, CAS2, + CHK, CHK2, CLR, CMP, CMP2, CMPA, CMPI, CMPM, DBcc, DIVS, DIVU, EOR, EORI, EORI_TO_CCR, + EORI_TO_SR, EXG, EXT, EXTB, ILLEGAL, JMP, JSR, LEA, LINK, LSL, LSR, MOVE, MOVE_FROM_CCR, MOVE_TO_CCR, + MOVE_FROM_SR, MOVE_TO_SR, MOVE_USP, MOVEA, MOVEC, MOVEM, MOVEP, MOVEQ, MOVES, MULS, MULU, NBCD, NEG, + NEGX, NOP, NOT_B, OR_B, ORI, ORI_TO_CCR, ORI_TO_SR, PACK, PEA, RESET, ROTL, ROTR, ROXL, ROXR, RTD, + RTE, RTR, RTS, SBCD, Scc, STOP, SUB, SUBA, SUBI, SUBQ, SUBX, SWAP, TAS, TRAP, TRAPcc, TRAPV, TST, + UNLK, UNPK, UNIMPLEMENTED); + +type TRAPTYPE_OPC is(NONE, T_1010, T_1111, T_ILLEGAL, T_TRAP, T_PRIV, T_RTE); -- None is the first entry and default. + +component WF68K30L_ADDRESS_REGISTERS + port ( + CLK : in std_logic; + RESET : in bit; + AR_IN_1 : in std_logic_vector(31 downto 0); + AR_IN_2 : in std_logic_vector(31 downto 0); + AR_OUT_1 : out std_logic_vector(31 downto 0); + AR_OUT_2 : out std_logic_vector(31 downto 0); + INDEX_IN : in std_logic_vector(31 downto 0); + PC : out std_logic_vector(31 downto 0); + PC_EW_OFFSET : in std_logic_vector(3 downto 0); + FETCH_MEM_ADR : in bit; + STORE_ADR_FORMAT : in bit; + STORE_ABS_HI : in bit; + STORE_ABS_LO : in bit; + STORE_D16 : in bit; + STORE_D32_LO : in bit; + STORE_D32_HI : in bit; + STORE_DISPL : in bit; + STORE_MEM_ADR : in bit; + STORE_OD_HI : in bit; + STORE_OD_LO : in bit; + STORE_AEFF : in bit; + OP_SIZE : in OP_SIZETYPE; + ADR_OFFSET : in std_logic_vector(31 downto 0); + ADR_MARK_USED : in bit; + ADR_IN_USE : out bit; + ADR_MODE : in std_logic_vector(2 downto 0); + AMODE_SEL : in std_logic_vector(2 downto 0); + USE_DREG : in bit; + ADR_EFF : out std_logic_vector(31 downto 0); + ADR_EFF_WB : out std_logic_vector(31 downto 0); + DFC : out std_logic_vector(2 downto 0); + DFC_WR : in bit; + SFC : out std_logic_vector(2 downto 0); + SFC_WR : in bit; + ISP_DEC : in bit; + ISP_RD : in bit; + ISP_WR : in bit; + MSP_RD : in bit; + MSP_WR : in bit; + USP_RD : in bit; + USP_WR : in bit; + AR_MARK_USED : in bit; + USE_APAIR : in boolean; + AR_IN_USE : out bit; + AR_SEL_RD_1 : in std_logic_vector(2 downto 0); + AR_SEL_RD_2 : in std_logic_vector(2 downto 0); + AR_SEL_WR_1 : in std_logic_vector(2 downto 0); + AR_SEL_WR_2 : in std_logic_vector(2 downto 0); + AR_DEC : in bit; + AR_INC : in bit; + AR_WR_1 : in bit; + AR_WR_2 : in bit; + UNMARK : in bit; + EXT_WORD : in std_logic_vector(15 downto 0); + MBIT : in std_logic; + SBIT : in std_logic; + SP_ADD_DISPL : in bit; + RESTORE_ISP_PC : in bit; + DISPLACEMENT : in std_logic_vector(31 downto 0); + PC_ADD_DISPL : in bit; + PC_INC : in bit; + PC_LOAD : in bit; + PC_RESTORE : in bit; + PC_OFFSET : in std_logic_vector(7 downto 0) + ); +end component; + +component WF68K30L_ALU + port ( + CLK : in std_logic; + RESET : in bit; + LOAD_OP1 : in bit; + LOAD_OP2 : in bit; + LOAD_OP3 : in bit; + OP1_IN : in std_logic_vector(31 downto 0); + OP2_IN : in std_logic_vector(31 downto 0); + OP3_IN : in std_logic_vector(31 downto 0); + BF_OFFSET_IN : in Std_Logic_Vector(31 downto 0); + BF_WIDTH_IN : in Std_Logic_Vector(5 downto 0); + BITPOS_IN : in Std_Logic_Vector(4 downto 0); + RESULT : out std_logic_vector(63 downto 0); + ADR_MODE_IN : in std_logic_vector(2 downto 0); + OP_SIZE_IN : in OP_SIZETYPE; + OP_IN : in OP_68K; + OP_WB : in OP_68K; + BIW_0_IN : in std_logic_vector(11 downto 0); + BIW_1_IN : in std_logic_vector(15 downto 0); + SR_WR : in bit; + SR_INIT : in bit; + SR_CLR_MBIT : in bit; + CC_UPDT : in bit; + STATUS_REG_OUT : out std_logic_vector(15 downto 0); + ALU_COND : out boolean; + ALU_INIT : in bit; + ALU_BSY : out bit; + ALU_REQ : out bit; + ALU_ACK : in bit; + USE_DREG : in bit; + HILOn : in bit; + IRQ_PEND : in std_logic_vector(2 downto 0); + TRAP_CHK : out bit; + TRAP_DIVZERO : out bit + ); +end component; + +component WF68K30L_BUS_INTERFACE + port ( + CLK : in std_logic; + ADR_IN_P : in std_logic_vector(31 downto 0); + ADR_OUT_P : out std_logic_vector(31 downto 0); + FC_IN : in std_logic_vector(2 downto 0); + FC_OUT : out std_logic_vector(2 downto 0); + DATA_PORT_IN : in std_logic_vector(31 downto 0); + DATA_PORT_OUT : out std_logic_vector(31 downto 0); + DATA_FROM_CORE : in std_logic_vector(31 downto 0); + DATA_TO_CORE : out std_logic_vector(31 downto 0); + OPCODE_TO_CORE : out std_logic_vector(15 downto 0); + DATA_PORT_EN : out std_logic; + BUS_EN : out std_logic; + SIZE : out std_logic_vector(1 downto 0); + OP_SIZE : in OP_SIZETYPE; + RD_REQ : in bit; + WR_REQ : in bit; + DATA_RDY : out bit; + DATA_VALID : out std_logic; + OPCODE_REQ : in bit; + OPCODE_RDY : out bit; + OPCODE_VALID : out std_logic; + RMC : in bit; + BUSY_EXH : in bit; + INBUFFER : out std_logic_vector(31 downto 0); + OUTBUFFER : out std_logic_vector(31 downto 0); + SSW_80 : out std_logic_vector(8 downto 0); + DSACKn : in std_logic_vector(1 downto 0); + ASn : out std_logic; + DSn : out std_logic; + RWn : out std_logic; + RMCn : out std_logic; + ECSn : out std_logic; + OCSn : out std_logic; + DBENn : out std_logic; + STERMn : in std_logic; + BRn : in std_logic; + BGACKn : in std_logic; + BGn : out std_logic; + RESET_STRB : in bit; + RESET_IN : in std_logic; + RESET_OUT : out std_logic; + RESET_CPU : out bit; + AVECn : in std_logic; + HALTn : in std_logic; + BERRn : in std_logic; + AERR : out bit; + BUS_BSY : out bit + ); +end component; + +component WF68K30L_CONTROL + generic(NO_PIPELINE : boolean := false); -- If true the controller work in scalar mode. + port( + CLK : in std_logic; + RESET_CPU : in bit; + BUSY : out bit; + BUSY_EXH : in bit; + EXH_REQ : in bit; + INT_TRIG : out bit; + OW_REQ : out bit; + OW_VALID : in std_logic; + EW_REQ : out bit; + EW_ACK : in bit; + OPD_ACK : in bit; + ADR_MARK_USED : out bit; + ADR_IN_USE : in bit; + ADR_OFFSET : out std_logic_vector(5 downto 0); + DATA_RD : out bit; + DATA_WR : out bit; + DATA_RDY : in bit; + DATA_VALID : in std_logic; + RMC : out bit; + FETCH_MEM_ADR : out bit; + LOAD_OP2 : out bit; + LOAD_OP3 : out bit; + LOAD_OP1 : out bit; + STORE_ADR_FORMAT : out bit; + STORE_D16 : out bit; + STORE_D32_LO : out bit; + STORE_D32_HI : out bit; + STORE_DISPL : out bit; + STORE_OD_HI : out bit; + STORE_OD_LO : out bit; + STORE_ABS_HI : out bit; + STORE_ABS_LO : out bit; + STORE_IDATA_B2 : out bit; + STORE_IDATA_B1 : out bit; + STORE_MEM_ADR : out bit; + STORE_AEFF : out bit; + OP : in OP_68K; + OP_SIZE : out OP_SIZETYPE; + BIW_0 : in std_logic_vector(13 downto 0); + BIW_1 : in std_logic_vector(15 downto 0); + BIW_2 : in std_logic_vector(15 downto 0); + EXT_WORD : in std_logic_vector(15 downto 0); + ADR_MODE : out std_logic_vector(2 downto 0); + AMODE_SEL : out std_logic_vector(2 downto 0); + USE_DREG : out bit; + HILOn : out bit; + OP_WB : out OP_68K; + OP_SIZE_WB : out OP_SIZETYPE; + BIW_0_WB_73 : out std_logic_vector(7 downto 3); + AR_MARK_USED : out bit; + USE_APAIR : out boolean; + AR_IN_USE : in bit; + AR_SEL_RD_1 : out std_logic_vector(2 downto 0); + AR_SEL_RD_2 : out std_logic_vector(2 downto 0); + AR_SEL_WR_1 : out std_logic_vector(2 downto 0); + AR_SEL_WR_2 : out std_logic_vector(2 downto 0); + AR_INC : out bit; + AR_DEC : out bit; + AR_WR_1 : out bit; + AR_WR_2 : out bit; + DR_MARK_USED : out bit; + USE_DPAIR : out boolean; + DR_IN_USE : in bit; + DR_SEL_RD_1 : out std_logic_vector(2 downto 0); + DR_SEL_RD_2 : out std_logic_vector(2 downto 0); + DR_SEL_WR_1 : out std_logic_vector(2 downto 0); + DR_SEL_WR_2 : out std_logic_vector(2 downto 0); + DR_WR_1 : out bit; + DR_WR_2 : out bit; + UNMARK : out bit; + DISPLACEMENT : out std_logic_vector(31 downto 0); + PC_ADD_DISPL : out bit; + PC_LOAD : out bit; + PC_INC_EXH : in bit; + SP_ADD_DISPL : out bit; + DFC_WR : out bit; + DFC_RD : out bit; + SFC_WR : out bit; + SFC_RD : out bit; + VBR_WR : out bit; + VBR_RD : out bit; + ISP_RD : out bit; + ISP_WR : out bit; + MSP_RD : out bit; + MSP_WR : out bit; + USP_RD : out bit; + USP_WR : out bit; + IPIPE_FLUSH : out bit; + ALU_INIT : out bit; + ALU_BSY : in bit; + ALU_REQ : in bit; + ALU_ACK : out bit; + BKPT_CYCLE : out bit; + BKPT_INSERT : out bit; + LOOP_BSY : in bit; + LOOP_SPLIT : out boolean; + LOOP_EXIT : out bit; + BF_OFFSET : in Std_Logic_Vector(2 downto 0); + BF_WIDTH : in Std_Logic_Vector(5 downto 0); + SR_WR : out bit; + MOVEM_ADn : out bit; + MOVEP_PNTR : out integer range 0 to 3; + CC_UPDT : out bit; + TRACE_MODE : in std_logic_vector(1 downto 0); + VBIT : in std_logic; + ALU_COND : in boolean; + DBcc_COND : in boolean; + BRANCH_ATN : in bit; + RESET_STRB : out bit; + BERR : out bit; + STATUSn : out bit; + EX_TRACE : out bit; + TRAP_cc : out bit; + TRAP_ILLEGAL : out bit; + TRAP_V : out bit + ); +end component; + +component WF68K30L_DATA_REGISTERS + port ( + CLK : in std_logic; + RESET : in bit; + DR_IN_1 : in std_logic_vector(31 downto 0); + DR_IN_2 : in std_logic_vector(31 downto 0); + DR_OUT_1 : out std_logic_vector(31 downto 0); + DR_OUT_2 : out std_logic_vector(31 downto 0); + DR_SEL_WR_1 : in std_logic_vector(2 downto 0); + DR_SEL_WR_2 : in std_logic_vector(2 downto 0); + DR_SEL_RD_1 : in std_logic_vector(2 downto 0); + DR_SEL_RD_2 : in std_logic_vector(2 downto 0); + DR_WR_1 : in bit; + DR_WR_2 : in bit; + DR_MARK_USED : in bit; + USE_DPAIR : in boolean; + DR_IN_USE : out bit; + UNMARK : in bit; + OP_SIZE : in OP_SIZETYPE + ); +end component; + +component WF68K30L_EXCEPTION_HANDLER + generic(VERSION : std_logic_vector(31 downto 0)); + port ( + CLK : in std_logic; + RESET : in bit; + BUSY_MAIN : in bit; + BUSY_OPD : in bit; + EXH_REQ : out bit; + BUSY_EXH : out bit; + ADR_IN : in std_logic_vector(31 downto 0); + ADR_CPY : out std_logic_vector(31 downto 0); + ADR_OFFSET : out std_logic_vector(31 downto 0); + CPU_SPACE : out bit; + DATA_0 : in std_logic; + DATA_RD : out bit; + DATA_WR : out bit; + DATA_IN : in std_logic_vector(31 downto 0); + OP_SIZE : out OP_SIZETYPE; + DATA_RDY : in bit; + DATA_VALID : in std_logic; + OPCODE_RDY : in bit; + OPD_ACK : in bit; -- Opword is available. + OW_VALID : in std_logic; + STATUS_REG_IN : in std_logic_vector(15 downto 0); + SR_CPY : out std_logic_vector(15 downto 0); + SR_INIT : out bit; + SR_CLR_MBIT : out bit; + SR_WR : out bit; + ISP_DEC : out bit; + ISP_LOAD : out bit; + PC_INC : out bit; + PC_LOAD : out bit; + PC_RESTORE : out bit; + STACK_FORMAT : out std_logic_vector(3 downto 0); + STACK_POS : out integer range 0 to 46; + SP_ADD_DISPL : out bit; + DISPLACEMENT : out std_logic_vector(7 downto 0); + IPIPE_FILL : out bit; + IPIPE_FLUSH : out bit; + REFILLn : out std_logic; + RESTORE_ISP_PC : out bit; + HALT_OUTn : out std_logic; + STATUSn : out bit; + INT_TRIG : in bit; + IRQ_IN : in std_logic_vector(2 downto 0); + IRQ_PEND : out std_logic_vector(2 downto 0); + AVECn : in std_logic; + IPENDn : out std_logic; + IVECT_OFFS : out std_logic_vector(9 downto 0); + TRAP_AERR : in bit; + TRAP_BERR : in bit; + TRAP_CHK : in bit; + TRAP_DIVZERO : in bit; + TRAP_ILLEGAL : in bit; + TRAP_CODE_OPC : in TRAPTYPE_OPC; + TRAP_VECTOR : in std_logic_vector(3 downto 0); + TRAP_cc : in bit; + TRAP_V : in bit; + EX_TRACE_IN : in bit; + VBR_WR : in bit; + VBR : out std_logic_vector(31 downto 0) + ); +end component; + +component WF68K30L_OPCODE_DECODER + generic(NO_LOOP : boolean := false); -- If true the DBcc loop mechanism is disabled. + port ( + CLK : in std_logic; + OW_REQ_MAIN : in bit; + EW_REQ_MAIN : in bit; + EXH_REQ : in bit; + BUSY_EXH : in bit; + BUSY_MAIN : in bit; + BUSY_OPD : out bit; + BKPT_INSERT : in bit; + BKPT_DATA : in std_logic_vector(15 downto 0); + LOOP_EXIT : in bit; + LOOP_BSY : out bit; + OPD_ACK_MAIN : out bit; + EW_ACK : out bit; + PC_EW_OFFSET : out std_logic_vector(3 downto 0); + PC_INC : out bit; + PC_INC_EXH : in bit; + PC_ADR_OFFSET : out std_logic_vector(7 downto 0); + PC_OFFSET : out std_logic_vector(7 downto 0); + OPCODE_RD : out bit; + OPCODE_RDY : in bit; + OPCODE_VALID : in std_logic; + OPCODE_DATA : in std_logic_vector(15 downto 0); + IPIPE_FILL : in bit; + IPIPE_FLUSH : in bit; + OW_VALID : out std_logic; + RC : out std_logic; + RB : out std_logic; + FC : out std_logic; + FB : out std_logic; + SBIT : in std_logic; + TRAP_CODE : out TRAPTYPE_OPC; + OP : out OP_68K; + BIW_0 : out std_logic_vector(15 downto 0); + BIW_1 : out std_logic_vector(15 downto 0); + BIW_2 : out std_logic_vector(15 downto 0); + EXT_WORD : out std_logic_vector(15 downto 0) + ); +end component; +end WF68K30L_PKG; diff --git a/common/CPU/68K30L/wf68k30L_top.vhd b/common/CPU/68K30L/wf68k30L_top.vhd new file mode 100644 index 00000000..ba6089a7 --- /dev/null +++ b/common/CPU/68K30L/wf68k30L_top.vhd @@ -0,0 +1,1212 @@ +------------------------------------------------------------------------ +---- ---- +---- WF68K30L IP Core. ---- +---- ---- +---- This is the top level structural design unit of the 68K30L ---- +---- complex instruction set (CISC) microcontroller. It's program- ---- +---- ming model is (hopefully) fully compatible with Motorola's ---- +---- MC68030. This core features a pipelined architecture. In com- ---- +---- parision to the fully featured 68K30 the core has no MMU, no ---- +---- data and instruction cache and no coprocessor interface. This ---- +---- results in missing burstmodes which are not required due to ---- +---- lack of cache. Missing coprocessor operations are: ---- +---- cpBcc, cpDBcc, cpGEN, cpRESTORE, cpSAVE, cpScc, cpTRAPcc. ---- +---- Missing MMU operations are: PFLUSH, PLOAD, PMOVE and PTEST. ---- +---- The trap handler does not process the following exceptions ---- +---- which lack due to the missing MMU and coprocessor interface: ---- +---- PRE_EXC_CP, MID_EXC_CP , POST_EXC_CP, EXC_VECT_CP, MMU_CFG_ERR ---- +---- The shifter in the 68K30 is a barrel shifter and in this core ---- +---- it is a conventional shift register controlled logic. ---- +---- This core features the loop operation mode of the 68010 to ---- +---- deal with DBcc loops. This feature is a predecessor to the ---- +---- MC68020/30/40 caches. ---- +---- The exception handler works for the RTE but without taking the ---- +---- SSW into account which is intended to restore from a defectice ---- +---- bus error stack frame. ---- +---- ---- +---- Enjoy. ---- +---- ---- +---- Author(s): ---- +---- - Wolfgang Foerster, wf@experiment-s.de; wf@inventronik.de ---- +---- ---- +------------------------------------------------------------------------ +---- ---- +---- Copyright © 2014-2019 Wolfgang Foerster Inventronik GmbH. ---- +---- ---- +---- This documentation describes Open Hardware and is licensed ---- +---- under the CERN OHL v. 1.2. You may redistribute and modify ---- +---- this documentation under the terms of the CERN OHL v.1.2. ---- +---- (http://ohwr.org/cernohl). This documentation is distributed ---- +---- WITHOUT ANY EXPRESS OR IMPLIED WARRANTY, INCLUDING OF ---- +---- MERCHANTABILITY, SATISFACTORY QUALITY AND FITNESS FOR A ---- +---- PARTICULAR PURPOSE. Please see the CERN OHL v.1.2 for ---- +---- applicable conditions ---- +---- ---- +------------------------------------------------------------------------ +-- +-- Revision History +-- +-- Revision 2K14B 20141201 WF +-- Initial Release. +-- Revision 2K16A 20160620 WF +-- Control section: fixed a bug in the MOVEM operation. Thanks to Raymond Mounissamy. +-- Address section: minor optimizations. +-- Revision 2K18A 20180620 WF +-- Control: Fixed a bug in MOVE An,-(Ay). Thanks to Gary Bingham for the support. +-- Top: changed ALU_OP1_IN multiplexer due to MOVE An,-(Ay) bug. +-- Address registers: Changed ADR_ATN logic to be valid one clock cycle earlier. +-- Revision 2K18A (unreleased) WF +-- Top / Opdecoder / Exhandler: Removed REST_BIW_0. +-- Exhandler: Removed PC_OFFSET. +-- ALU: Bug fix: MOVEM sign extension. +-- Address registers: Removed PC_REG. +-- Control: Fixed wrong PEA behaviour. +-- Control: Fixed the displacement for LINK. +-- ALU: Fix for restoring correct values during the DIVS and DIVU in word format. +-- Control: Fixed the operation size for MOVEQ. +-- Control: ADDQ, SUBQ Fix: address registers are always written long. +-- Top, exception handler, address registers: Fixed PC restoring during exception processing. +-- Control: ADDI, ANDI, EORI, ORI, SUBI: address is not marked used if destination is Dn. +-- Control: ADDI, ANDI, EORI, ORI, SUBI: data register is marked used if destination is Dn. +-- Bus interface: Suppress bus faults during RESET instruction. +-- Bus interface: Optimized ASn and DSn timing for synchronous RAM. +-- ALU: Fixed the SUBQ calculation. +-- Opcode decoder: Fixed the PW_EW_OFFSET calculation for JSR. +-- Top: fixed the value of DATA_IMMEDIATE for ADDQ and SUBQ in case of #8. +-- ALU: Rearanged the Offset for the JSR instruction. +-- Control: Fixed AR_MARK_USED in LINK. +-- ALU: EXT instruction uses now RESULT(63 downto 0). +-- Top: Introduced OP_WB form the control unit. +-- Top: Rearanged the AR_IN_1 multiplexer to avoid data hazards. +-- Top: Rearanged the AR_IN_2 multiplexer to avoid data hazards. +-- Top: Rearanged the DR_IN_1 multiplexer to avoid data hazards. +-- Top: Rearanged the DR_IN_2 multiplexer to avoid data hazards. +-- EXG: rearanged logic to meet the new top level multiplexers. +-- Control: LINK, UNLK: wait in START_OP until the ALU is ready (avoids possible data hazards). +-- Top: ALU_OP1_IN to meet the new EXG multiplexers. +-- Top: ALU_OP2_IN to meet the new EXG multiplexers. +-- Address registers: Fixed the writing of ISP_REG during EXG instruction with two address registers. +-- Control: MOVEM: Fixed predecrement mode for consecutive MOVEM -(An). +-- Control: MOVEP: MOVEP_PNTR is now correct for consecutive MOVEP. +-- Control: MOVEP: avoid structural hazard in SWITCH_STATE by waiting for ALU. +-- Control: LINK, UNLK: fixed the write back operation size. +-- Exception handler: Fixed the vector calculation of INT vectors. +-- Exception handler: Fixed faulty modelling in IRQ_FILTER. +-- Exception handler: Implemented the AVEC_FILTER to better meet bus timings. +-- Control: EOR: fixed a bug in the writeback mechanism. +-- Control: BSR, JSR: EXEC_WB state machine waits now for ALU_INIT. Avoid structural / data hazard. +-- Control: the instruction pipe is not flushed for MOVE_FROM_CCR, MOVE_FROM_SR, MOVE_USP, MOVEC. +-- Control: Modifications in the FETCH state machine to avoid several data hazards for MOVEM, MOVE_FROM_CCR, MOVE_FROM_SR. +-- Control: Modifications in the FETCH state machine to avoid several data hazards for ANDI_TO_CCR, ANDI_TO_SR, EORI_TO_CCR, EORI_TO_SR, ORI_TO_CCR, ORI_TO_SR. +-- Exception handler: The RTE exception has now highest priority (avoids mismatch). +-- Control: Bugfix: the condition codes were not updated if there was a pending interrupt. +-- Control: We have to stop a pending operation in case of a pending interrupt. This is done by rejecting OW_RDY. +-- TOP, Control, Exception handler Opcode Decoder: Rearanged PC_INC and ipipe flush logic. +-- Bus interface: BUS_EN is now active except during arbitration. +-- Control: Write the undecremented Register for MOVE Ax, -(Ax). +-- ALU: Fixed wrong condition codes for AND_B, ANDI, EOR, EORI, OR_B, ORI and NOT_B. +-- Exception handler: Update the IRQ mask only for RESET and interrupts. +-- Bus interface: Opted out START_READ and CHK_RD. +-- Control: UNMARK is now asserted in the end of the write cycle. This avoids data hazards. +-- Exception handler: external interrupts are postponed if any system controllers are in initialize operation status. +-- ALU: Fixed writeback issues in the status register logic. +-- ALU: Fixed writing the stack pointer registers (MSBIT is used now). +-- Control: Fixed a MOVEC writeback issue (use BIW_WB... instead of BIW_...). +-- Control: Fixed a USP writeback issue (use BIW_WB... instead of BIW_...). +-- ALU: the address registers are always written long. +-- Top: opted out SBIT_AREG and MBIT_AREG. +-- Address register bugfix: exception handler do not increment and decrement the USP any more. +-- Control: Introduced a switch NO_PIPELINE. +-- Address registers, Control: MOVEM-Fix see STORE_AEFF. +-- Control: DBcc: fixed a data hazard for DBcc_COND evaluation by waiting on the ALU result. +-- Control: Fixed DR_WR_1 locking against AR_WR_2. +-- Control: IPIPE is flushed, when there is a memory space change in the end of xx_TO_SR operations. +-- Control: To handle correct addressing, ADR_OFFSET is now cleared right in the end of the respective operation. +-- Control: Fixed a bug in EOR writing back in register direct mode. +-- ALU: Fixed a bug in MULU.W (input operands are now 16 bit wide). +-- Control: ADDQ and SUBQ: fixed (An)+ mode. An increments now. +-- Control: Fixed DIVS, DIVU in memory address modes (wrong control flow). +-- Control: ADDQ and SUBQ: fixed condition code control UPDT_CC. +-- Control: fixed a data hazard bug using addressing modes with index register. +-- Opcode decoder: Fix for unimplemented or illegal operations: PC is increased before stacked. +-- Exception handler: RTE now loads the address offset correctly when entering the handler. +-- Control: Implemented the 68K10 loop mechanism. +-- Opcode decoder Implemented the 68K10 loop mechanism. +-- Bus interface: Fixed the faulty bus arbitration logic. +-- Opcode decoder: Removed CAHR, we have no cache. +-- Top: Removed a data hazard in the DR_IN_1 multiplexer (EXG operation). +-- Revision 2K19A 20190419 WF +-- Control: Fixed several pipelinig issues (hazards). +-- New feature: Branch prediction for the status register manipulation operations (BRANCH_ATN). +-- Exception handler, Opcode decoder, Top: Rearranged address error handling. +-- Bus interface, Exception handler, Opcode decoder, Top: Rearranged address error handling. +-- Top, Address registers: Removed ADR_ATN. Not required any more. +-- Control: Introdeced a new state CALC_AEFF which results in no need of ADR_ATN and a twice highre fmax. +-- Revision 2K19B 20191224 WF +-- Control: NOP explicitely synchronizes the instruction pipe now. +-- Opcode decoder: introduced signal synchronization in the P_BSY process to avoid malfunction by hazards. +-- Exception handler: introduced signal synchronization in the P_D process to avoid malfunction by hazards. +-- Top level, exception handler: the processor VERSION is now 32 bit wide. +-- Control: BUSY is now asserted when an opword is loaded and we have to wait in START_OP (avoids other controllers to reload the opword, see OW_REQ). +-- Control: removed a data hazard condition (A7) for JSR, PEA, LINK and UNLK in the beginning of the operation. +-- Address section: fixed the condition if UNMARK and AR_MARK_USED are asserted simultaneously (see process P_IN_USE). +-- Address section: fixed the '0' conditions for AR_IN_USE. +-- Revision 2K20A 20200620 WF +-- Bus interface: ASn and DSn are not asserted in S0 any more. +-- Bus interface: some modifications to optimize the RETRY logic. +-- Bus interface: fixed a bug in the DSACK_MEM logic (now switches explicitely to "00"). +-- + +library work; +use work.WF68K30L_PKG.all; + +library ieee; +use ieee.std_logic_1164.all; +use ieee.std_logic_unsigned.all; + +entity WF68K30L_TOP is + generic(VERSION : std_logic_vector(31 downto 0) := x"20191224"; -- CPU version number. + -- The following two switches are for debugging purposes. Default for both is false. + NO_PIPELINE : boolean := false; -- If true the main controller work in scalar mode. + NO_LOOP : boolean := false); -- If true the DBcc loop mechanism is disabled. + + port ( + CLK : in std_logic; + + -- Address and data: + ADR_OUT : out std_logic_vector(31 downto 0); + DATA_IN : in std_logic_vector(31 downto 0); + DATA_OUT : out std_logic_vector(31 downto 0); + DATA_EN : out std_logic; -- Enables the data port. + + -- System control: + BERRn : in std_logic; + RESET_INn : in std_logic; + RESET_OUT : out std_logic; -- Open drain. + HALT_INn : in std_logic; + HALT_OUTn : out std_logic; -- Open drain. + + -- Processor status: + FC_OUT : out std_logic_vector(2 downto 0); + + -- Interrupt control: + AVECn : in std_logic; + IPLn : in std_logic_vector(2 downto 0); + IPENDn : out std_logic; + + -- Aynchronous bus control: + DSACKn : in std_logic_vector(1 downto 0); + SIZE : out std_logic_vector(1 downto 0); + ASn : out std_logic; + RWn : out std_logic; + RMCn : out std_logic; + DSn : out std_logic; + ECSn : out std_logic; + OCSn : out std_logic; + DBENn : out std_logic; -- Data buffer enable. + BUS_EN : out std_logic; -- Enables ADR, ASn, DSn, RWn, RMCn, FC and SIZE. + + -- Synchronous bus control: + STERMn : in std_logic; + + -- Status controls: + STATUSn : out std_logic; + REFILLn : out std_logic; + + -- Bus arbitration control: + BRn : in std_logic; + BGn : out std_logic; + BGACKn : in std_logic + ); +end entity WF68K30L_TOP; + +architecture STRUCTURE of WF68K30L_TOP is +signal ADn : bit; +signal ADR_CPY_EXH : std_logic_vector(31 downto 0); +signal ADR_EFF : std_logic_vector(31 downto 0); +signal ADR_EFF_WB : std_logic_vector(31 downto 0); +signal ADR_L : std_logic_vector(31 downto 0); +signal ADR_LATCH : std_logic_vector(31 downto 0); +signal ADR_MODE : std_logic_vector(2 downto 0); +signal ADR_MODE_MAIN : std_logic_vector(2 downto 0); +signal ADR_IN_USE : bit; +signal ADR_OFFSET : std_logic_vector(31 downto 0); +signal ADR_OFFSET_EXH : std_logic_vector(31 downto 0); +signal ADR_OFFSET_MAIN : std_logic_vector(5 downto 0); +signal ADR_P : std_logic_vector(31 downto 0); +signal ADR_MARK_UNUSED_MAIN : bit; +signal ADR_MARK_USED : bit; +signal AERR : bit; +signal ALU_ACK : bit; +signal ALU_BSY : bit; +signal ALU_COND : boolean; +signal ALU_INIT : bit; +signal ALU_LOAD_OP1 : bit; +signal ALU_LOAD_OP2 : bit; +signal ALU_LOAD_OP3 : bit; +signal ALU_OP1_IN : std_logic_vector(31 downto 0); +signal ALU_OP2_IN : std_logic_vector(31 downto 0); +signal ALU_OP3_IN : std_logic_vector(31 downto 0); +signal ALU_REQ : bit; +signal ALU_RESULT : std_logic_vector(63 downto 0); +signal AMODE_SEL : std_logic_vector(2 downto 0); +signal AR_DEC : bit; +signal AR_IN_1 : std_logic_vector(31 downto 0); +signal AR_IN_2 : std_logic_vector(31 downto 0); +signal AR_IN_USE : bit; +signal AR_INC : bit; +signal AR_MARK_USED : bit; +signal AR_OUT_1 : std_logic_vector(31 downto 0); +signal AR_OUT_2 : std_logic_vector(31 downto 0); +signal AR_SEL_RD_1 : std_logic_vector(2 downto 0); +signal AR_SEL_RD_1_MAIN : std_logic_vector(2 downto 0); +signal AR_SEL_RD_2 : std_logic_vector(2 downto 0); +signal AR_SEL_WR_1 : std_logic_vector(2 downto 0); +signal AR_SEL_WR_2 : std_logic_vector(2 downto 0); +signal AR_WR_1 : bit; +signal AR_WR_2 : bit; +signal AVECn_BUSIF : std_logic; +signal BERR_MAIN : bit; +signal BITPOS : std_logic_vector(4 downto 0); +signal BIW_0 : std_logic_vector(15 downto 0); +signal BIW_0_WB_73 : std_logic_vector(7 downto 3); +signal BIW_1 : std_logic_vector(15 downto 0); +signal BIW_2 : std_logic_vector(15 downto 0); +signal BF_OFFSET : std_logic_vector(31 downto 0); +signal BF_WIDTH : std_logic_vector(5 downto 0) := "100000"; -- Default needed for simulation! +signal BKPT_CYCLE : bit; +signal BKPT_INSERT : bit; +signal BRANCH_ATN : bit; +signal BUS_BSY : bit; +signal BUSY_EXH : bit; +signal BUSY_MAIN : bit; +signal BUSY_OPD : bit; +signal CC_UPDT : bit; +signal CPU_SPACE : bit; +signal CPU_SPACE_EXH : bit; +signal DFC : std_logic_vector(2 downto 0); +signal DFC_RD : bit; +signal DFC_WR : bit; +signal DR_WR_1 : bit; +signal DR_WR_2 : bit; +signal DR_MARK_USED : bit; +signal DATA_FROM_CORE : std_logic_vector(31 downto 0); +signal DATA : std_logic_vector(31 downto 0); +signal DATA_IN_EXH : std_logic_vector(31 downto 0); +signal DATA_IMMEDIATE : std_logic_vector(31 downto 0); +signal DATA_EXH : std_logic_vector(31 downto 0); +signal DATA_RD : bit; +signal DATA_WR : bit; +signal DATA_RD_EXH : bit; +signal DATA_WR_EXH : bit; +signal DATA_RD_MAIN : bit; +signal DATA_WR_MAIN : bit; +signal DATA_RDY : bit; +signal DATA_TO_CORE : std_logic_vector(31 downto 0); +signal DATA_VALID : std_logic; +signal DISPLACEMENT : std_logic_vector(31 downto 0); +signal DISPLACEMENT_MAIN : std_logic_vector(31 downto 0); +signal DISPLACEMENT_EXH : std_logic_vector(7 downto 0); +signal DATA_BUFFER : std_logic_vector(31 downto 0); +signal DBcc_COND : boolean; +signal DR_IN_1 : std_logic_vector(31 downto 0); +signal DR_IN_2 : std_logic_vector(31 downto 0); +signal DR_OUT_2 : std_logic_vector(31 downto 0); +signal DR_OUT_1 : std_logic_vector(31 downto 0); +signal DR_SEL_WR_1 : std_logic_vector(2 downto 0); +signal DR_SEL_WR_2 : std_logic_vector(2 downto 0); +signal DR_SEL_RD_1 : std_logic_vector(2 downto 0); +signal DR_SEL_RD_2 : std_logic_vector(2 downto 0); +signal DR_IN_USE : bit; +signal EW_ACK : bit; +signal EW_REQ_MAIN : bit; +signal EX_TRACE : bit; +signal EXEC_RDY : bit; +signal EXH_REQ : bit; +signal EXT_WORD : std_logic_vector(15 downto 0); +signal FAULT_ADR : std_logic_vector(31 downto 0); +signal FB : std_logic; +signal FC : std_logic; +signal FETCH_MEM_ADR : bit; +signal FC_I : std_logic_vector(2 downto 0); +signal FC_LATCH : std_logic_vector(2 downto 0); +signal HILOn : bit; +signal IBUFFER : std_logic_vector(31 downto 0); +signal INBUFFER : std_logic_vector(31 downto 0); +signal INT_TRIG : bit; +signal IPL : std_logic_vector(2 downto 0); +signal ISP_DEC : bit; +signal ISP_RD : bit; +signal ISP_LOAD_EXH : bit; +signal ISP_WR_MAIN : bit; +signal ISP_WR : bit; +signal IVECT_OFFS : std_logic_vector(9 downto 0); +signal IPEND_In : bit; +signal IRQ_PEND : std_logic_vector(2 downto 0); +signal IPIPE_FILL : bit; +signal IPIPE_FLUSH : bit; +signal IPIPE_FLUSH_EXH : bit; +signal IPIPE_FLUSH_MAIN : bit; +signal IPIPE_OFFESET : std_logic_vector(2 downto 0); +signal LOOP_BSY : bit; +signal LOOP_SPLIT : boolean; +signal LOOP_EXIT : bit; +signal MOVEP_PNTR : integer range 0 to 3; +signal MSP_RD : bit; +signal MSP_WR : bit; +signal OPCODE_RD : bit; +signal OPCODE_RDY : bit; +signal OPCODE_VALID : std_logic; +signal OPCODE_TO_CORE : std_logic_vector(15 downto 0); +signal OP_SIZE : OP_SIZETYPE; +signal OP_SIZE_BUS : OP_SIZETYPE; +signal OP_SIZE_EXH : OP_SIZETYPE; +signal OP_SIZE_MAIN : OP_SIZETYPE; +signal OP_SIZE_WB : OP_SIZETYPE; -- Writeback. +signal OPCODE_REQ : bit; +signal OPCODE_REQ_I : bit; +signal OW_VALID : std_logic; +signal OPD_ACK_MAIN : bit; +signal OP : OP_68K; +signal OP_WB : OP_68K; +signal OW_REQ_MAIN : bit; +signal OUTBUFFER : std_logic_vector(31 downto 0); +signal PC : std_logic_vector(31 downto 0); +signal PC_ADD_DISPL : bit; +signal PC_ADR_OFFSET : std_logic_vector(7 downto 0); +signal PC_EW_OFFSET : std_logic_vector(3 downto 0); +signal PC_INC : bit; +signal PC_INC_EXH : bit; +signal PC_INC_EXH_I : bit; +signal PC_L : std_logic_vector(31 downto 0); +signal PC_LOAD : bit; +signal PC_LOAD_EXH : bit; +signal PC_LOAD_MAIN : bit; +signal PC_OFFSET : std_logic_vector(7 downto 0); +signal PC_OFFSET_OPD : std_logic_vector(7 downto 0); +signal PC_RESTORE_EXH : bit; +signal RB : std_logic; +signal RC : std_logic; +signal RD_REQ : bit; +signal RD_REQ_I : bit; +signal RMC : bit; +signal REFILLn_EXH : std_logic; +signal RESTORE_ISP_PC : bit; +signal RESET_CPU : bit; +signal RESET_IN : std_logic; +signal RESET_STRB : bit; +signal SP_ADD_DISPL : bit; +signal SP_ADD_DISPL_EXH : bit; +signal SP_ADD_DISPL_MAIN : bit; +signal SBIT : std_logic; +signal SSW_80 : std_logic_vector(8 downto 0); +signal SFC : std_logic_vector(2 downto 0); +signal SFC_RD : bit; +signal SFC_WR : bit; +signal SR_CPY : std_logic_vector(15 downto 0); +signal SR_RD : bit; +signal SR_INIT : bit; +signal SR_CLR_MBIT : bit; +signal SR_WR : bit; +signal SR_WR_EXH : bit; +signal SR_WR_MAIN : bit; +signal STACK_FORMAT : std_logic_vector(3 downto 0); +signal STACK_POS : integer range 0 to 46; +signal STATUS_REG : std_logic_vector(15 downto 0); +signal STATUSn_MAIN : bit; +signal STATUSn_EXH : bit; +signal STORE_ADR_FORMAT : bit; +signal STORE_ABS_HI : bit; +signal STORE_ABS_LO : bit; +signal STORE_AEFF : bit; +signal STORE_D16 : bit; +signal STORE_D32_LO : bit; +signal STORE_D32_HI : bit; +signal STORE_DISPL : bit; +signal STORE_MEM_ADR : bit; +signal STORE_OD_HI : bit; +signal STORE_OD_LO : bit; +signal STORE_IDATA_B1 : bit; +signal STORE_IDATA_B2 : bit; +signal TRAP_AERR : bit; +signal TRAP_ILLEGAL : bit; +signal TRAP_CODE_OPC : TRAPTYPE_OPC; +signal TRAP_cc : bit; +signal TRAP_CHK : bit; +signal TRAP_DIVZERO : bit; +signal TRAP_V : bit; +signal UNMARK : bit; +signal USE_APAIR : boolean; +signal USE_DFC : bit; +signal USE_SFC : bit; +signal USE_DPAIR : boolean; +signal USE_DREG : bit; +signal USP_RD : bit; +signal USP_WR : bit; +signal VBR : std_logic_vector(31 downto 0); +signal VBR_WR : bit; +signal VBR_RD : bit; +signal WR_REQ : bit; +signal WR_REQ_I : bit; +begin + IDATA_BUFFER : process + -- This register stores the immediate data. + begin + wait until CLK = '1' and CLK' event; + if STORE_IDATA_B2 = '1' then + IBUFFER(31 downto 16) <= EXT_WORD; + elsif STORE_IDATA_B1 = '1' then + IBUFFER(15 downto 0) <= EXT_WORD; + end if; + end process IDATA_BUFFER; + + DATA_IMMEDIATE <= BIW_1 & BIW_2 when OP = ADDI and OP_SIZE = LONG else + BIW_1 & BIW_2 when OP = ANDI and OP_SIZE = LONG else + BIW_1 & BIW_2 when OP = CMPI and OP_SIZE = LONG else + BIW_1 & BIW_2 when OP = EORI and OP_SIZE = LONG else + BIW_1 & BIW_2 when OP = SUBI and OP_SIZE = LONG else + BIW_1 & BIW_2 when OP = ORI and OP_SIZE = LONG else + x"0000" & BIW_1 when OP = ANDI_TO_SR else + x"0000" & BIW_1 when OP = EORI_TO_SR else + x"0000" & BIW_1 when OP = ORI_TO_SR else + x"0000" & BIW_1 when OP = STOP else + x"0000" & BIW_1 when OP = ADDI and OP_SIZE = WORD else + x"0000" & BIW_1 when OP = ANDI and OP_SIZE = WORD else + x"0000" & BIW_1 when OP = CMPI and OP_SIZE = WORD else + x"0000" & BIW_1 when OP = EORI and OP_SIZE = WORD else + x"0000" & BIW_1 when OP = SUBI and OP_SIZE = WORD else + x"0000" & BIW_1 when OP = ORI and OP_SIZE = WORD else + x"000000" & BIW_1(7 downto 0) when OP = ANDI_TO_CCR else + x"000000" & BIW_1(7 downto 0) when OP = EORI_TO_CCR else + x"000000" & BIW_1(7 downto 0) when OP = ORI_TO_CCR else + x"000000" & BIW_1(7 downto 0) when OP = ADDI and OP_SIZE = BYTE else + x"000000" & BIW_1(7 downto 0) when OP = ANDI and OP_SIZE = BYTE else + x"000000" & BIW_1(7 downto 0) when OP = CMPI and OP_SIZE = BYTE else + x"000000" & BIW_1(7 downto 0) when OP = EORI and OP_SIZE = BYTE else + x"000000" & BIW_1(7 downto 0) when OP = SUBI and OP_SIZE = BYTE else + x"000000" & BIW_1(7 downto 0) when OP = ORI and OP_SIZE = BYTE else + x"00000008" when (OP = ADDQ or OP = SUBQ) and BIW_0(11 downto 9) = "000" else + x"000000" & "00000" & BIW_0(11 downto 9) when OP = ADDQ or OP = SUBQ else + x"000000" & BIW_0(7 downto 0) when OP = MOVEQ else + x"00000001" when OP = DBcc else + x"0000" & BIW_1(15 downto 0) when OP = PACK or OP = UNPK else + IBUFFER when OP_SIZE = LONG else x"0000" & IBUFFER(15 downto 0); + + -- Internal registers are place holders written as zeros. + DATA_EXH <= -- Exception handler multiplexing: + SR_CPY & PC(31 downto 16) when STACK_POS = 2 else + PC(15 downto 0) & STACK_FORMAT & "00" & IVECT_OFFS when STACK_POS = 4 else + PC when STACK_FORMAT = x"2" and STACK_POS = 6 else + PC when STACK_FORMAT = x"9" and STACK_POS = 6 else + BIW_0 & FC & FB & RC & RB & "000" & SSW_80 when STACK_POS = 6 else -- Format A and B. + BIW_1 & BIW_2 when STACK_POS = 8 else -- Format A and B. + FAULT_ADR when STACK_FORMAT = x"9" and STACK_POS = 10 else -- ADR_EFF_cp. + ADR_CPY_EXH when STACK_POS = 10 else + OUTBUFFER when STACK_POS = 14 else + PC + "100" when STACK_POS = 20 else --STAGE B address. + INBUFFER when STACK_POS = 24 else + VERSION when STACK_POS = 28 else x"00000000"; + + DATA_IN_EXH <= ALU_RESULT(31 downto 0) when BUSY_MAIN = '1' else DATA_TO_CORE; -- MOVEC handles the VBR. + + DATA_FROM_CORE <= DATA_EXH when BUSY_EXH = '1' else + DR_OUT_2 when OP_WB = CAS or OP_WB = CAS2 else -- Update operands. + ALU_RESULT(31 downto 0); + + SP_ADD_DISPL <= SP_ADD_DISPL_MAIN or SP_ADD_DISPL_EXH; + + AR_SEL_RD_1 <= "111" when BUSY_EXH = '1' else AR_SEL_RD_1_MAIN; -- ISP during exception. + + AR_IN_1 <= DATA_TO_CORE when BUSY_EXH = '1' else + ALU_RESULT(31 downto 0) when ALU_BSY = '1' and AR_WR_1 = '1' else + ALU_RESULT(31 downto 0) when ALU_BSY = '1' and (DFC_WR = '1' or SFC_WR = '1' or ISP_WR = '1' or MSP_WR = '1' or USP_WR = '1') else + ADR_EFF when OP = JMP or OP = JSR else + DATA_TO_CORE when FETCH_MEM_ADR = '1' else + DR_OUT_1 when USE_DREG = '1' else -- CAS2: Address register from data register. + AR_OUT_1 when OP = LINK or OP = UNLK else DATA_TO_CORE; -- Default used for RTD, RTR, RTS. + + AR_IN_2 <= ALU_RESULT(63 downto 32) when OP_WB = EXG else ALU_RESULT(31 downto 0); -- Default is for UNLK. + + DR_IN_1 <= ALU_RESULT(63 downto 32) when OP_WB = EXG and ALU_BSY = '1' and DR_WR_1 = '1' and BIW_0_WB_73 = "10001" else -- Address and data registers. + ALU_RESULT(31 downto 0); + + DR_IN_2 <= ALU_RESULT(63 downto 32); + + ALU_OP1_IN <= DATA_TO_CORE when SR_WR_EXH = '1' else + DATA_IMMEDIATE when OP = DBcc or OP = PACK or OP = UNPK else + DR_OUT_1 when (OP = ABCD or OP = SBCD) and BIW_0(3) = '0' else + DATA_TO_CORE when OP = ABCD or OP = SBCD else + DR_OUT_1 when (OP = ADD or OP = SUB) and BIW_0(8) = '1' else + DR_OUT_1 when (OP = AND_B or OP = EOR or OP = OR_B) and BIW_0(8) = '1' else + DR_OUT_1 when (OP = ADDX or OP = SUBX) and BIW_0(3) = '0' else + DATA_TO_CORE when OP = ADDX or OP = SUBX else + DR_OUT_1 when OP = ASL or OP = ASR or OP = LSL or OP = LSR else + DR_OUT_1 when OP = ROTL or OP = ROTR or OP = ROXL or OP = ROXR else + DR_OUT_2 when OP = BFINS else -- The pattern. + DR_OUT_1 when OP = CAS or OP = CAS2 else -- Compare operand. + DATA_TO_CORE when OP = CMPM else + PC + PC_EW_OFFSET when OP = BSR or OP = JSR else + ADR_EFF when OP = LEA or OP = PEA else + AR_OUT_2 when OP = MOVE and BIW_0(5 downto 3) = "001" else -- An to any location. + AR_OUT_1 when OP = MOVE_USP else + AR_OUT_1 when OP = EXG and BIW_0(7 downto 3) = "01001" else -- Two address registers. + DR_OUT_1 when OP = EXG else -- Two data registers. + VBR when OP = MOVEC and VBR_RD = '1' else + x"0000000" & '0' & SFC when OP = MOVEC and SFC_RD = '1' else + x"0000000" & '0' & DFC when OP = MOVEC and DFC_RD = '1' else + AR_OUT_1 when OP = MOVEC and (ISP_RD = '1' or MSP_RD = '1' or USP_RD = '1') else + AR_OUT_1 when OP = MOVEC and BIW_1(15) = '1' else + DR_OUT_1 when OP = MOVEC else + DR_OUT_1 when OP = MOVEM and BIW_0(10) = '0' and ADn = '0' else -- Register to memory. + AR_OUT_2 when OP = MOVEM and BIW_0(10) = '0' else -- Register to memory. + DR_OUT_1 when OP = MOVES and BIW_1(11) = '1' and BIW_1(15) = '0' else -- Register to memory. + AR_OUT_2 when OP = MOVES and BIW_1(11) = '1' else -- Register to memory. + x"000000" & DR_OUT_1(31 downto 24) when OP = MOVEP and MOVEP_PNTR = 3 and BIW_0(7 downto 6) > "01" else + x"000000" & DR_OUT_1(23 downto 16) when OP = MOVEP and MOVEP_PNTR = 2 and BIW_0(7 downto 6) > "01" else + x"000000" & DR_OUT_1(15 downto 8) when OP = MOVEP and MOVEP_PNTR = 1 and BIW_0(7 downto 6) > "01" else + x"000000" & DR_OUT_1(7 downto 0) when OP = MOVEP and BIW_0(7 downto 6) > "01" else + DATA_TO_CORE(7 downto 0) & DR_OUT_1(23 downto 0) when OP = MOVEP and MOVEP_PNTR = 3 else + DR_OUT_1(31 downto 24) & DATA_TO_CORE(7 downto 0) & DR_OUT_1(15 downto 0) when OP = MOVEP and MOVEP_PNTR = 2 else + DR_OUT_1(31 downto 16) & DATA_TO_CORE(7 downto 0) & DR_OUT_1(7 downto 0) when OP = MOVEP and MOVEP_PNTR = 1 else + DR_OUT_1(31 downto 8) & DATA_TO_CORE(7 downto 0) when OP = MOVEP else + x"0000" & STATUS_REG(15 downto 8) & DR_OUT_1(7 downto 0) when OP = MOVE_TO_CCR and BIW_0(5 downto 3) = "000" else + x"0000" & STATUS_REG(15 downto 8) & DATA_IMMEDIATE(7 downto 0) when OP = MOVE_TO_CCR and BIW_0(5 downto 0) = "111100" else + x"0000" & STATUS_REG(15 downto 8) & DATA_TO_CORE(7 downto 0) when OP = MOVE_TO_CCR else + x"0000" & DR_OUT_1(15 downto 0) when OP = MOVE_TO_SR and BIW_0(5 downto 3) = "000" else + x"0000" & DATA_IMMEDIATE(15 downto 0) when OP = MOVE_TO_SR and BIW_0(5 downto 0) = "111100" else + x"0000" & DATA_TO_CORE(15 downto 0) when OP = MOVE_TO_SR else + x"000000" & "000" & STATUS_REG(4 downto 0) when OP = MOVE_FROM_CCR else + x"0000" & STATUS_REG when OP = MOVE_FROM_SR else + DATA_IMMEDIATE when OP = STOP else -- Status register information. + DATA_IMMEDIATE when OP = MOVEQ else + x"00000000" when OP = NEG or OP = NEGX or OP = NBCD else + DATA_IMMEDIATE when OP = ADDI or OP = CMPI or OP = SUBI or OP = ANDI or OP = EORI or OP = ORI else + DATA_IMMEDIATE when OP = ADDQ or OP = SUBQ else + DATA_IMMEDIATE when OP = ANDI_TO_CCR or OP = ANDI_TO_SR else + DATA_IMMEDIATE when OP = EORI_TO_CCR or OP = EORI_TO_SR else + DATA_IMMEDIATE when OP = ORI_TO_CCR or OP = ORI_TO_SR else + DR_OUT_1 when BIW_0(5 downto 3) = "000" else + AR_OUT_1 when BIW_0(5 downto 3) = "001" else + DATA_IMMEDIATE when BIW_0(5 downto 0) = "111100" else DATA_TO_CORE; + + ALU_OP2_IN <= DR_OUT_2 when (OP = ABCD or OP = SBCD) and BIW_0(3) = '0' else + DATA_TO_CORE when OP = ABCD or OP = SBCD else + DR_OUT_2 when (OP = ADDX or OP = SUBX) and BIW_0(3) = '0' else + DATA_TO_CORE when OP = ADDX or OP = SUBX else + DR_OUT_2 when (OP = ADD or OP = CMP or OP = SUB) and BIW_0(8) = '0' else + DR_OUT_2 when (OP = AND_B or OP = OR_B) and BIW_0(8) = '0' else + AR_OUT_2 when (OP = ADDA or OP = CMPA or OP = SUBA) else + DR_OUT_2 when OP = EXG and BIW_0(7 downto 3) = "01000" else -- Two data registers. + AR_OUT_2 when OP = EXG else + DR_OUT_2 when (OP = ASL or OP = ASR) and BIW_0(7 downto 6) /= "11" else -- Register shifts. + DR_OUT_2 when (OP = LSL or OP = LSR) and BIW_0(7 downto 6) /= "11" else -- Register shifts. + DR_OUT_2 when (OP = ROTL or OP = ROTR) and BIW_0(7 downto 6) /= "11" else -- Register shifts. + DR_OUT_2 when (OP = ROXL or OP = ROXR) and BIW_0(7 downto 6) /= "11" else -- Register shifts. + x"0000" & STATUS_REG when(OP = ANDI_TO_CCR or OP = ANDI_TO_SR) else + x"0000" & STATUS_REG when(OP = EORI_TO_CCR or OP = EORI_TO_SR) else + x"0000" & STATUS_REG when(OP = ORI_TO_CCR or OP = ORI_TO_SR) else + DATA_TO_CORE when OP = CAS or OP = CAS2 else -- Destination operand. + DR_OUT_2 when (OP = CHK2 or OP = CMP2) and USE_DREG = '1' else + AR_OUT_2 when OP = CHK or OP = CHK2 or OP = CMP2 else + DATA_TO_CORE when OP = CMPM else + DR_OUT_2 when OP = DBcc or OP = SWAP else + DR_OUT_2 when OP = DIVS or OP = DIVU else + DR_OUT_2 when OP = MULS or OP = MULU else + DR_OUT_1 when (OP = PACK or OP = UNPK) and BIW_0(3) = '0' else -- Register direct. + DATA_TO_CORE when OP = PACK or OP = UNPK else + AR_OUT_1 when OP = LINK else + DR_OUT_2 when BIW_0(5 downto 3) = "000" else + AR_OUT_2 when BIW_0(5 downto 3) = "001" else DATA_TO_CORE; + + ALU_OP3_IN <= DATA_TO_CORE when (OP = BFCHG or OP = BFCLR or OP = BFEXTS or OP = BFEXTU) and BIW_0(5 downto 3) /= "000" else + DATA_TO_CORE when (OP = BFFFO or OP = BFINS or OP = BFSET or OP = BFTST) and BIW_0(5 downto 3) /= "000" else + DATA_TO_CORE when OP = CAS2 or OP = CHK2 or OP = CMP2 else DR_OUT_1; + + OP_SIZE <= OP_SIZE_EXH when BUSY_EXH = '1' else OP_SIZE_MAIN; + OP_SIZE_BUS <= OP_SIZE_WB when DATA_WR_MAIN = '1' else OP_SIZE; + + + PC_OFFSET <= PC_OFFSET_OPD; + PC_L <= PC + PC_ADR_OFFSET; + + PC_INC_EXH_I <= PC_INC_EXH when LOOP_SPLIT = false else '0'; -- Suppress for a split loop. + + ADR_MODE <= "010" when BUSY_EXH = '1' else ADR_MODE_MAIN; --(ISP) + + -- The bit field offset is byte aligned + ADR_OFFSET <= x"00000000" when FETCH_MEM_ADR = '1' else + ADR_OFFSET_EXH when BUSY_EXH = '1' else + "000" & BF_OFFSET(31 downto 3) + ADR_OFFSET_MAIN when (OP = BFCHG or OP = BFCLR or OP = BFEXTS or OP = BFEXTU) and BF_OFFSET(31) = '0' else + "111" & BF_OFFSET(31 downto 3) + ADR_OFFSET_MAIN when OP = BFCHG or OP = BFCLR or OP = BFEXTS or OP = BFEXTU else + "000" & BF_OFFSET(31 downto 3) + ADR_OFFSET_MAIN when (OP = BFFFO or OP = BFINS or OP = BFSET or OP = BFTST ) and BF_OFFSET(31) = '0' else + "111" & BF_OFFSET(31 downto 3) + ADR_OFFSET_MAIN when OP = BFFFO or OP = BFINS or OP = BFSET or OP = BFTST else + x"000000" & "00" & ADR_OFFSET_MAIN; + + DBcc_COND <= true when OP_WB = DBcc and ALU_RESULT(15 downto 0) = x"FFFF" else false; + + -- Take a branch if the CPU space will change: + BRANCH_ATN <= '1' when OP = ANDI_TO_SR and DATA_IMMEDIATE(13) = '0' and STATUS_REG(13) = '1' else + '1' when OP = ANDI_TO_SR and DATA_IMMEDIATE(12) = '0' and STATUS_REG(12) = '1' else + '1' when OP = EORI_TO_SR and DATA_IMMEDIATE(13) = '1' else + '1' when OP = EORI_TO_SR and DATA_IMMEDIATE(12) = '1' else + '1' when OP = ORI_TO_SR and DATA_IMMEDIATE(13) = '1' and STATUS_REG(13) = '0' else + '1' when OP = ORI_TO_SR and DATA_IMMEDIATE(12) = '1' and STATUS_REG(12) = '0' else + '1' when OP = MOVE_TO_SR and BIW_0(5 downto 3) = "000" and DR_OUT_1(13 downto 12) /= STATUS_REG(13 downto 12) else + '1' when OP = MOVE_TO_SR and BIW_0(5 downto 0) = "111100" and DATA_IMMEDIATE(13 downto 12) /= STATUS_REG(13 downto 12) else + '1' when OP = MOVE_TO_SR and DATA_TO_CORE(13 downto 12) /= STATUS_REG(13 downto 12) else '0'; + + DATA_RD <= DATA_RD_EXH or DATA_RD_MAIN; + DATA_WR <= DATA_WR_EXH or DATA_WR_MAIN; + + P_BUSREQ: process + begin + wait until CLK = '1' and CLK' event; + -- We need these flip flops to avoid combinatorial loops: + -- The requests are valid until the bus controller enters + -- its START_CYCLE bus phase and asserts there the BUS_BSY. + -- After the bus controller enters the bus access state, + -- the requests are withdrawn. + if BUS_BSY = '0' then + RD_REQ_I <= DATA_RD; + WR_REQ_I <= DATA_WR; + OPCODE_REQ_I <= OPCODE_RD; + elsif BUS_BSY = '1' then + RD_REQ_I <= '0'; + WR_REQ_I <= '0'; + OPCODE_REQ_I <= '0'; + end if; + end process P_BUSREQ; + + RD_REQ <= DATA_RD when BUS_BSY = '0' else RD_REQ_I; + WR_REQ <= DATA_WR when BUS_BSY = '0' else WR_REQ_I; + OPCODE_REQ <= OPCODE_RD when BUS_BSY = '0' else OPCODE_REQ_I; + + DISPLACEMENT <= DISPLACEMENT_MAIN when BUSY_MAIN = '1' else x"000000" & DISPLACEMENT_EXH; + + SR_WR <= SR_WR_EXH or SR_WR_MAIN; + + IPIPE_FLUSH <= IPIPE_FLUSH_EXH or IPIPE_FLUSH_MAIN; + + ISP_WR <= ISP_WR_MAIN or ISP_LOAD_EXH; + + AVECn_BUSIF <= AVECn when BUSY_EXH = '1' else '1'; + + CPU_SPACE <= '1' when OP = BKPT and DATA_RD_MAIN = '1' else + CPU_SPACE_EXH when BUSY_EXH = '1' else '0'; + + -- The bit field offset is bit wise. + BF_OFFSET <= (x"000000" & "000" & BIW_1(10 downto 6)) when BIW_1(11) = '0' else DR_OUT_1; + BF_WIDTH <= '0' & BIW_1(4 downto 0) when BIW_1(4 downto 0) /= "00000" and BIW_1(5) = '0' else + '0' & DR_OUT_1(4 downto 0) when DR_OUT_1(4 downto 0) /= "00000" and BIW_1(5) = '1' else "100000"; + + -- The BITPOS is valid for bit operations and bit field operations. For BCHG, BCLR, BSET and BTST + -- the BITPOS spans 0 to 31 bytes, when it is in register direct mode. It is modulo 8 in memory + -- manipulation mode. For the bit field operations in register direct mode it also in the + -- range 0 to 31. For bit fields in memory the value is byte wide (0 to 7) because the bit + -- field from a memory location are loaded from byte boundaries. + BITPOS <= BIW_1(4 downto 0) when (OP = BCHG or OP = BCLR or OP = BSET or OP = BTST) and BIW_0(8) = '0' and ADR_MODE = "000" else + "00" & BIW_1(2 downto 0) when (OP = BCHG or OP = BCLR or OP = BSET or OP = BTST) and BIW_0(8) = '0' else + DR_OUT_1(4 downto 0) when (OP = BCHG or OP = BCLR or OP = BSET or OP = BTST) and ADR_MODE = "000" else + "00" & DR_OUT_1(2 downto 0) when OP = BCHG or OP = BCLR or OP = BSET or OP = BTST else + BIW_1(10 downto 6) when BIW_1(11) = '0' and ADR_MODE = "000" else + "00" & BIW_1(8 downto 6) when BIW_1(11) = '0' else + DR_OUT_1(4 downto 0) when ADR_MODE = "000" else "00" & DR_OUT_1(2 downto 0); + + TRAP_AERR <= AERR when BUSY_EXH = '0' else '0'; -- No address error from the system during exception processing. + + USE_DFC <= '1' when OP_WB = MOVES and DATA_WR_MAIN = '1' else '0'; + USE_SFC <= '1' when OP_WB = MOVES and DATA_RD_MAIN = '1' else '0'; + + PC_LOAD <= PC_LOAD_EXH or PC_LOAD_MAIN; + + RESET_IN <= not RESET_INn; + IPL <= not IPLn; + + REFILL_STATUS: process + -- This tiny logic provides signal transition on the negative + -- clock edge. + begin + wait until CLK = '0' and CLK' event; + if (STATUSn_EXH and STATUSn_MAIN) = '1' then + STATUSn <= '1'; + else + STATUSn <= '0'; + end if; + REFILLn <= REFILLn_EXH; + end process REFILL_STATUS; + + SBIT <= STATUS_REG(13); + + ADR_L <= x"000000" & "000" & BIW_0(2 downto 0) & "00" when BKPT_CYCLE = '1' else + x"FFFFFFF" & IRQ_PEND & '1' when CPU_SPACE_EXH = '1' else + ADR_EFF_WB when DATA_WR_MAIN = '1' else ADR_EFF; -- Exception handler uses ADR_EFF for read and write access. + + ADR_P <= ADR_LATCH when BUS_BSY = '1' else + ADR_L when DATA_RD = '1' or DATA_WR = '1' else PC_L; + + P_ADR_LATCHES: process + -- This register stores the address during a running bus cycle. + -- The signals RD_DATA, WR_DATA and RD_OPCODE may change during + -- the cycle. Opcode read is lower prioritized. + -- FAULT_ADR latches the faulty address for stacking it via + -- the exception handler. + -- The FC_LATCH register stores the function code during a running + -- bus cycle. + begin + wait until CLK = '1' and CLK' event; + if BUS_BSY = '0' then + ADR_LATCH <= ADR_P; + FC_LATCH <= FC_I; + elsif BERRn = '0' then + FAULT_ADR <= ADR_LATCH; + end if; + end process P_ADR_LATCHES; + + FC_I <= FC_LATCH when BUS_BSY = '1' else + SFC when USE_SFC = '1' else + DFC when USE_DFC = '1' else + "111" when (DATA_RD = '1' or DATA_WR = '1') and CPU_SPACE = '1' else + "101" when (DATA_RD = '1' or DATA_WR = '1') and SBIT = '1' else + "001" when DATA_RD = '1' or DATA_WR = '1' else + "110" when OPCODE_RD = '1' and SBIT = '1' else "010"; -- Default is OPCODE_RD and SBIT = '0'. + + I_ADDRESSREGISTERS: WF68K30L_ADDRESS_REGISTERS + port map( + CLK => CLK, + RESET => RESET_CPU, + AR_IN_1 => AR_IN_1, + AR_IN_2 => AR_IN_2, + AR_OUT_1 => AR_OUT_1, + AR_OUT_2 => AR_OUT_2, + INDEX_IN => DR_OUT_1, -- From data register section. + PC => PC, + FETCH_MEM_ADR => FETCH_MEM_ADR, + STORE_ADR_FORMAT => STORE_ADR_FORMAT, + STORE_ABS_HI => STORE_ABS_HI, + STORE_ABS_LO => STORE_ABS_LO, + STORE_D16 => STORE_D16, + STORE_D32_LO => STORE_D32_LO, + STORE_D32_HI => STORE_D32_HI, + STORE_DISPL => STORE_DISPL, + STORE_MEM_ADR => STORE_MEM_ADR, + STORE_OD_HI => STORE_OD_HI, + STORE_OD_LO => STORE_OD_LO, + STORE_AEFF => STORE_AEFF, + OP_SIZE => OP_SIZE, + AR_MARK_USED => AR_MARK_USED, + USE_APAIR => USE_APAIR, + AR_IN_USE => AR_IN_USE, + AR_SEL_RD_1 => AR_SEL_RD_1, + AR_SEL_RD_2 => AR_SEL_RD_2, + AR_SEL_WR_1 => AR_SEL_WR_1, + AR_SEL_WR_2 => AR_SEL_WR_2, + ADR_OFFSET => ADR_OFFSET, -- Byte aligned. + ADR_MARK_USED => ADR_MARK_USED, + ADR_IN_USE => ADR_IN_USE, + ADR_MODE => ADR_MODE, + AMODE_SEL => AMODE_SEL, + USE_DREG => USE_DREG, + ADR_EFF => ADR_EFF, + ADR_EFF_WB => ADR_EFF_WB, + DFC => DFC, + DFC_WR => DFC_WR, + SFC => SFC, + SFC_WR => SFC_WR, + ISP_DEC => ISP_DEC, + ISP_RD => ISP_RD, + ISP_WR => ISP_WR, + MSP_RD => MSP_RD, + MSP_WR => MSP_WR, + USP_RD => USP_RD, + USP_WR => USP_WR, + AR_DEC => AR_DEC, + AR_INC => AR_INC, + AR_WR_1 => AR_WR_1, + AR_WR_2 => AR_WR_2, + UNMARK => UNMARK, + EXT_WORD => EXT_WORD, + MBIT => STATUS_REG(12), + SBIT => SBIT, + SP_ADD_DISPL => SP_ADD_DISPL, + RESTORE_ISP_PC => RESTORE_ISP_PC, + DISPLACEMENT => DISPLACEMENT, + PC_ADD_DISPL => PC_ADD_DISPL, + PC_EW_OFFSET => PC_EW_OFFSET, + PC_INC => PC_INC, + PC_LOAD => PC_LOAD, + PC_RESTORE => PC_RESTORE_EXH, + PC_OFFSET => PC_OFFSET + ); + + I_ALU: WF68K30L_ALU + port map( + CLK => CLK, + RESET => RESET_CPU, + LOAD_OP2 => ALU_LOAD_OP2, + LOAD_OP3 => ALU_LOAD_OP3, + LOAD_OP1 => ALU_LOAD_OP1, + OP1_IN => ALU_OP1_IN, + OP2_IN => ALU_OP2_IN, + OP3_IN => ALU_OP3_IN, + BF_OFFSET_IN => BF_OFFSET, + BF_WIDTH_IN => BF_WIDTH, + BITPOS_IN => BITPOS, + RESULT => ALU_RESULT, + ADR_MODE_IN => ADR_MODE, + USE_DREG => USE_DREG, + HILOn => HILOn, + OP_SIZE_IN => OP_SIZE, + OP_IN => OP, + OP_WB => OP_WB, + BIW_0_IN => BIW_0(11 downto 0), + BIW_1_IN => BIW_1, + SR_WR => SR_WR, + SR_INIT => SR_INIT, + SR_CLR_MBIT => SR_CLR_MBIT, + CC_UPDT => CC_UPDT, + STATUS_REG_OUT => STATUS_REG, + ALU_COND => ALU_COND, + ALU_INIT => ALU_INIT, + ALU_BSY => ALU_BSY, + ALU_REQ => ALU_REQ, + ALU_ACK => ALU_ACK, + IRQ_PEND => IRQ_PEND, + TRAP_CHK => TRAP_CHK, + TRAP_DIVZERO => TRAP_DIVZERO + ); + + I_BUS_IF: WF68K30L_BUS_INTERFACE + port map( + CLK => CLK, + + ADR_IN_P => ADR_P, + ADR_OUT_P => ADR_OUT, + + FC_IN => FC_I, + FC_OUT => FC_OUT, + + DATA_PORT_IN => DATA_IN, + DATA_PORT_OUT => DATA_OUT, + DATA_FROM_CORE => DATA_FROM_CORE, + DATA_TO_CORE => DATA_TO_CORE, + OPCODE_TO_CORE => OPCODE_TO_CORE, + + DATA_PORT_EN => DATA_EN, + BUS_EN => BUS_EN, + + SIZE => SIZE, + OP_SIZE => OP_SIZE_BUS, + + RD_REQ => RD_REQ, + WR_REQ => WR_REQ, + DATA_RDY => DATA_RDY, + DATA_VALID => DATA_VALID, + OPCODE_REQ => OPCODE_REQ, + OPCODE_RDY => OPCODE_RDY, + OPCODE_VALID => OPCODE_VALID, + RMC => RMC, + BUSY_EXH => BUSY_EXH, + SSW_80 => SSW_80, + INBUFFER => INBUFFER, + OUTBUFFER => OUTBUFFER, + + DSACKn => DSACKn, + ASn => ASn, + DSn => DSn, + RWn => RWn, + RMCn => RMCn, + ECSn => ECSn, + OCSn => OCSn, + DBENn => DBENn, + + STERMn => STERMn, + + BRn => BRn, + BGACKn => BGACKn, + BGn => BGn, + + RESET_STRB => RESET_STRB, + RESET_IN => RESET_IN, + RESET_OUT => RESET_OUT, + RESET_CPU => RESET_CPU, + + AVECn => AVECn_BUSIF, + HALTn => HALT_INn, + BERRn => BERRn, + AERR => AERR, + + BUS_BSY => BUS_BSY + ); + + I_CONTROL: WF68K30L_CONTROL + generic map(NO_PIPELINE => NO_PIPELINE) + port map( + CLK => CLK, + RESET_CPU => RESET_CPU, + BUSY => BUSY_MAIN, + BUSY_EXH => BUSY_EXH, + EXH_REQ => EXH_REQ, + INT_TRIG => INT_TRIG, + OW_REQ => OW_REQ_MAIN, + OW_VALID => OW_VALID, + EW_REQ => EW_REQ_MAIN, + EW_ACK => EW_ACK, + OPD_ACK => OPD_ACK_MAIN, + ADR_MARK_USED => ADR_MARK_USED, + ADR_IN_USE => ADR_IN_USE, + ADR_OFFSET => ADR_OFFSET_MAIN, + DATA_RD => DATA_RD_MAIN, + DATA_WR => DATA_WR_MAIN, + DATA_RDY => DATA_RDY, + DATA_VALID => DATA_VALID, + RMC => RMC, + FETCH_MEM_ADR => FETCH_MEM_ADR, + LOAD_OP1 => ALU_LOAD_OP1, + LOAD_OP2 => ALU_LOAD_OP2, + LOAD_OP3 => ALU_LOAD_OP3, + STORE_ADR_FORMAT => STORE_ADR_FORMAT, + STORE_ABS_HI => STORE_ABS_HI, + STORE_ABS_LO => STORE_ABS_LO, + STORE_D16 => STORE_D16, + STORE_D32_LO => STORE_D32_LO, + STORE_D32_HI => STORE_D32_HI, + STORE_DISPL => STORE_DISPL, + STORE_MEM_ADR => STORE_MEM_ADR, + STORE_OD_HI => STORE_OD_HI, + STORE_OD_LO => STORE_OD_LO, + STORE_AEFF => STORE_AEFF, + STORE_IDATA_B1 => STORE_IDATA_B1, + STORE_IDATA_B2 => STORE_IDATA_B2, + OP => OP, + OP_SIZE => OP_SIZE_MAIN, + BIW_0 => BIW_0(13 downto 0), + BIW_1 => BIW_1, + BIW_2 => BIW_2, + EXT_WORD => EXT_WORD, + ADR_MODE => ADR_MODE_MAIN, + AMODE_SEL => AMODE_SEL, + USE_DREG => USE_DREG, + HILOn => HILOn, + OP_WB => OP_WB, + OP_SIZE_WB => OP_SIZE_WB, + BIW_0_WB_73 => BIW_0_WB_73, + AR_MARK_USED => AR_MARK_USED, + AR_IN_USE => AR_IN_USE, + AR_SEL_RD_1 => AR_SEL_RD_1_MAIN, + AR_SEL_RD_2 => AR_SEL_RD_2, + AR_SEL_WR_1 => AR_SEL_WR_1, + AR_SEL_WR_2 => AR_SEL_WR_2, + AR_INC => AR_INC, + AR_DEC => AR_DEC, + AR_WR_1 => AR_WR_1, + AR_WR_2 => AR_WR_2, + DR_MARK_USED => DR_MARK_USED, + USE_APAIR => USE_APAIR, + USE_DPAIR => USE_DPAIR, + DR_IN_USE => DR_IN_USE, + DR_SEL_WR_1 => DR_SEL_WR_1, + DR_SEL_WR_2 => DR_SEL_WR_2, + DR_SEL_RD_1 => DR_SEL_RD_1, + DR_SEL_RD_2 => DR_SEL_RD_2, + DR_WR_1 => DR_WR_1, + DR_WR_2 => DR_WR_2, + UNMARK => UNMARK, + DISPLACEMENT => DISPLACEMENT_MAIN, + PC_ADD_DISPL => PC_ADD_DISPL, + PC_LOAD => PC_LOAD_MAIN, + PC_INC_EXH => PC_INC_EXH, + SP_ADD_DISPL => SP_ADD_DISPL_MAIN, + DFC_RD => DFC_RD, + DFC_WR => DFC_WR, + SFC_RD => SFC_RD, + SFC_WR => SFC_WR, + VBR_RD => VBR_RD, + VBR_WR => VBR_WR, + ISP_RD => ISP_RD, + ISP_WR => ISP_WR_MAIN, + MSP_RD => MSP_RD, + MSP_WR => MSP_WR, + USP_RD => USP_RD, + USP_WR => USP_WR, + IPIPE_FLUSH => IPIPE_FLUSH_MAIN, + ALU_INIT => ALU_INIT, + ALU_BSY => ALU_BSY, + ALU_REQ => ALU_REQ, + ALU_ACK => ALU_ACK, + BKPT_CYCLE => BKPT_CYCLE, + BKPT_INSERT => BKPT_INSERT, + LOOP_BSY => LOOP_BSY, + LOOP_SPLIT => LOOP_SPLIT, + LOOP_EXIT => LOOP_EXIT, + BF_OFFSET => BF_OFFSET(2 downto 0), + BF_WIDTH => BF_WIDTH, + SR_WR => SR_WR_MAIN, + MOVEM_ADn => ADn, + MOVEP_PNTR => MOVEP_PNTR, + CC_UPDT => CC_UPDT, + TRACE_MODE => STATUS_REG(15 downto 14), + VBIT => STATUS_REG(1), + ALU_COND => ALU_COND, + DBcc_COND => DBcc_COND, + BRANCH_ATN => BRANCH_ATN, + RESET_STRB => RESET_STRB, + BERR => BERR_MAIN, + STATUSn => STATUSn_MAIN, + EX_TRACE => EX_TRACE, + TRAP_cc => TRAP_cc, + TRAP_V => TRAP_V, + TRAP_ILLEGAL => TRAP_ILLEGAL + ); + + I_DATA_REGISTERS: WF68K30L_DATA_REGISTERS + port map( + CLK => CLK, + RESET => RESET_CPU, + DR_IN_1 => DR_IN_1, + DR_IN_2 => DR_IN_2, + DR_OUT_2 => DR_OUT_2, + DR_OUT_1 => DR_OUT_1, + DR_SEL_WR_1 => DR_SEL_WR_1, + DR_SEL_WR_2 => DR_SEL_WR_2, + DR_SEL_RD_1 => DR_SEL_RD_1, + DR_SEL_RD_2 => DR_SEL_RD_2, + DR_WR_1 => DR_WR_1, + DR_WR_2 => DR_WR_2, + DR_MARK_USED => DR_MARK_USED, + USE_DPAIR => USE_DPAIR, + DR_IN_USE => DR_IN_USE, + UNMARK => UNMARK, + OP_SIZE => OP_SIZE_WB + ); + + I_EXC_HANDLER: WF68K30L_EXCEPTION_HANDLER + generic map(VERSION => VERSION) + port map( + CLK => CLK, + + RESET => RESET_CPU, + BUSY_MAIN => BUSY_MAIN, + BUSY_OPD => BUSY_OPD, + + EXH_REQ => EXH_REQ, + BUSY_EXH => BUSY_EXH, + + ADR_IN => ADR_EFF, + ADR_CPY => ADR_CPY_EXH, + ADR_OFFSET => ADR_OFFSET_EXH, + CPU_SPACE => CPU_SPACE_EXH, + + DATA_0 => DATA_TO_CORE(0), + DATA_RD => DATA_RD_EXH, + DATA_WR => DATA_WR_EXH, + DATA_IN => DATA_IN_EXH, + + OP_SIZE => OP_SIZE_EXH, + DATA_RDY => DATA_RDY, + DATA_VALID => DATA_VALID, + + OPCODE_RDY => OPCODE_RDY, + OPD_ACK => OPD_ACK_MAIN, + OW_VALID => OW_VALID, + + STATUS_REG_IN => STATUS_REG, + SR_CPY => SR_CPY, + SR_INIT => SR_INIT, + SR_CLR_MBIT => SR_CLR_MBIT, + + SR_WR => SR_WR_EXH, + ISP_DEC => ISP_DEC, + ISP_LOAD => ISP_LOAD_EXH, + PC_LOAD => PC_LOAD_EXH, + PC_INC => PC_INC_EXH, + PC_RESTORE => PC_RESTORE_EXH, + + STACK_FORMAT => STACK_FORMAT, + STACK_POS => STACK_POS, + + SP_ADD_DISPL => SP_ADD_DISPL_EXH, + DISPLACEMENT => DISPLACEMENT_EXH, + IPIPE_FILL => IPIPE_FILL, + IPIPE_FLUSH => IPIPE_FLUSH_EXH, + REFILLn => REFILLn_EXH, + RESTORE_ISP_PC => RESTORE_ISP_PC, + + HALT_OUTn => HALT_OUTn, + STATUSn => STATUSn_EXH, + + INT_TRIG => INT_TRIG, + IRQ_IN => IPL, + IRQ_PEND => IRQ_PEND, + AVECn => AVECn, + IPENDn => IPENDn, + IVECT_OFFS => IVECT_OFFS, + + TRAP_AERR => TRAP_AERR, + TRAP_BERR => BERR_MAIN, + TRAP_CHK => TRAP_CHK, + TRAP_DIVZERO => TRAP_DIVZERO, + TRAP_ILLEGAL => TRAP_ILLEGAL, + TRAP_CODE_OPC => TRAP_CODE_OPC, + TRAP_VECTOR => BIW_0(3 downto 0), + TRAP_cc => TRAP_cc, + TRAP_V => TRAP_V, + EX_TRACE_IN => EX_TRACE, + VBR_WR => VBR_WR, + VBR => VBR + ); + + I_OPCODE_DECODER: WF68K30L_OPCODE_DECODER + generic map(NO_LOOP => NO_LOOP) + port map( + CLK => CLK, + + OW_REQ_MAIN => OW_REQ_MAIN, + EW_REQ_MAIN => EW_REQ_MAIN, + + EXH_REQ => EXH_REQ, + BUSY_EXH => BUSY_EXH, + BUSY_MAIN => BUSY_MAIN, + BUSY_OPD => BUSY_OPD, + + BKPT_INSERT => BKPT_INSERT, + BKPT_DATA => DATA_TO_CORE(15 downto 0), + + LOOP_EXIT => LOOP_EXIT, + LOOP_BSY => LOOP_BSY, + + OPD_ACK_MAIN => OPD_ACK_MAIN, + EW_ACK => EW_ACK, + + PC_INC => PC_INC, + PC_INC_EXH => PC_INC_EXH_I, + PC_ADR_OFFSET => PC_ADR_OFFSET, + PC_EW_OFFSET => PC_EW_OFFSET, + PC_OFFSET => PC_OFFSET_OPD, + + OPCODE_RD => OPCODE_RD, + OPCODE_RDY => OPCODE_RDY, + OPCODE_VALID => OPCODE_VALID, + OPCODE_DATA => OPCODE_TO_CORE, + + IPIPE_FILL => IPIPE_FILL, + IPIPE_FLUSH => IPIPE_FLUSH, + + -- Fault logic: + OW_VALID => OW_VALID, + RC => RC, + RB => RB, + FC => FC, + FB => FB, + + -- Trap logic: + SBIT => SBIT, + TRAP_CODE => TRAP_CODE_OPC, + + -- System control: + OP => OP, + BIW_0 => BIW_0, + BIW_1 => BIW_1, + BIW_2 => BIW_2, + EXT_WORD => EXT_WORD + ); +end STRUCTURE;
+
+ + + + +
+ + +
+ +

cern_ohl_v_1_2.txt

+ +
+

Licence text in text format. - + Javier Serrano, 2013-09-06 10:05

+

Download (8.9 kB)

+ +
+  +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1
CERN Open Hardware Licence v1.2 
+
2
+
3
Preamble
+
4
+
5
Through this CERN Open Hardware Licence ("CERN OHL") version 1.2, CERN
+
6
wishes to provide a tool to foster collaboration and sharing among
+
7
hardware designers.  The CERN OHL is copyright CERN. Anyone is welcome
+
8
to use the CERN OHL, in unmodified form only, for the distribution of
+
9
their own Open Hardware designs. Any other right is reserved. Release
+
10
of hardware designs under the CERN OHL does not constitute an
+
11
endorsement of the licensor or its designs nor does it imply any
+
12
involvement by CERN in the development of such designs.
+
13
+
14
1. Definitions
+
15
+
16
In this Licence, the following terms have the following meanings:
+
17
 
+
18
“Licence” means this CERN OHL.
+
19
+
20
“Documentation” means schematic diagrams, designs, circuit or circuit
+
21
board layouts, mechanical drawings, flow charts and descriptive text,
+
22
and other explanatory material that is explicitly stated as being made
+
23
available under the conditions of this Licence. The Documentation may
+
24
be in any medium, including but not limited to computer files and
+
25
representations on paper, film, or any other media.
+
26
+
27
“Documentation Location” means a location where the Licensor has
+
28
placed Documentation, and which he believes will be publicly
+
29
accessible for at least three years from the first communication to
+
30
the public or distribution of Documentation.
+
31
+
32
“Product” means either an entire, or any part of a, device built using
+
33
the Documentation or the modified Documentation.
+
34
+
35
“Licensee” means any natural or legal person exercising rights under
+
36
this Licence.
+
37
+
38
“Licensor” means any natural or legal person that creates or modifies
+
39
Documentation and subsequently communicates to the public and/ or
+
40
distributes the resulting Documentation under the terms and conditions
+
41
of this Licence.
+
42
+
43
A Licensee may at the same time be a Licensor, and vice versa. 
+
44
+
45
Use of the masculine gender includes the feminine and neuter genders
+
46
and is employed solely to facilitate reading.
+
47
+
48
2. Applicability
+
49
+
50
2.1. This Licence governs the use, copying, modification,
+
51
communication to the public and distribution of the Documentation, and
+
52
the manufacture and distribution of Products. By exercising any right
+
53
granted under this Licence, the Licensee irrevocably accepts these
+
54
terms and conditions.
+
55
+
56
2.2. This Licence is granted by the Licensor directly to the Licensee,
+
57
and shall apply worldwide and without limitation in time. The Licensee
+
58
may assign his licence rights or grant sub-licences.
+
59
+
60
2.3. This Licence does not extend to software, firmware, or code
+
61
loaded into programmable devices which may be used in conjunction with
+
62
the Documentation, the modified Documentation or with Products, unless
+
63
such software, firmware, or code is explicitly expressed to be subject
+
64
to this Licence. The use of such software, firmware, or code is
+
65
otherwise subject to the applicable licence terms and conditions.
+
66
+
67
3. Copying, modification, communication to the public and distribution
+
68
of the Documentation
+
69
+
70
3.1. The Licensee shall keep intact all copyright and trademarks
+
71
notices, all notices referring to Documentation Location, and all
+
72
notices that refer to this Licence and to the disclaimer of warranties
+
73
that are included in the Documentation. He shall include a copy
+
74
thereof in every copy of the Documentation or, as the case may be,
+
75
modified Documentation, that he communicates to the public or
+
76
distributes.
+
77
+
78
3.2. The Licensee may copy, communicate to the public and distribute
+
79
verbatim copies of the Documentation, in any medium, subject to the
+
80
requirements specified in section 3.1.
+
81
+
82
3.3. The Licensee may modify the Documentation or any portion thereof
+
83
provided that upon modification of the Documentation, the Licensee
+
84
shall make the modified Documentation available from a Documentation
+
85
Location such that it can be easily located by an original Licensor
+
86
once the Licensee communicates to the public or distributes the
+
87
modified Documentation under section 3.4, and, where required by
+
88
section 4.1, by a recipient of a Product. However, the Licensor shall
+
89
not assert his rights under the foregoing proviso unless or until a
+
90
Product is distributed.
+
91
+
92
3.4. The Licensee may communicate to the public and distribute the
+
93
modified Documentation (thereby in addition to being a Licensee also
+
94
becoming a Licensor), always provided that he shall:
+
95
+
96
a) comply with section 3.1;
+
97
+
98
b) cause the modified Documentation to carry prominent notices stating
+
99
that the Licensee has modified the Documentation, with the date and
+
100
description of the modifications;
+
101
+
102
c) cause the modified Documentation to carry a new Documentation
+
103
Location notice if the original Documentation provided for one;
+
104
+
105
d) make available the modified Documentation at the same level of
+
106
abstraction as that of the Documentation, in the preferred format for
+
107
making modifications to it (e.g. the native format of the CAD tool as
+
108
applicable), and in the event that format is proprietary, in a format
+
109
viewable with a tool licensed under an OSI-approved license if the
+
110
proprietary tool can create it; and
+
111
+
112
e) license the modified Documentation under the terms and conditions
+
113
of this Licence or, where applicable, a later version of this Licence
+
114
as may be issued by CERN.
+
115
+
116
3.5. The Licence includes a non-exclusive licence to those patents or
+
117
registered designs that are held by, under the control of, or
+
118
sub-licensable by the Licensor, to the extent necessary to make use of
+
119
the rights granted under this Licence. The scope of this section 3.5
+
120
shall be strictly limited to the parts of the Documentation or
+
121
modified Documentation created by the Licensor.
+
122
+
123
4. Manufacture and distribution of Products
+
124
+
125
4.1. The Licensee may manufacture or distribute Products always
+
126
provided that, where such manufacture or distribution requires a
+
127
licence under this Licence the Licensee provides to each recipient of
+
128
such Products an easy means of accessing a copy of the Documentation
+
129
or modified Documentation, as applicable, as set out in section 3.
+
130
+
131
4.2. The Licensee is invited to inform any Licensor who has indicated
+
132
his wish to receive this information about the type, quantity and
+
133
dates of production of Products the Licensee has (had) manufactured
+
134
+
135
5. Warranty and liability
+
136
+
137
5.1. DISCLAIMER – The Documentation and any modified Documentation are
+
138
provided "as is" and any express or implied warranties, including, but
+
139
not limited to, implied warranties of merchantability, of satisfactory
+
140
quality, non-infringement of third party rights, and fitness for a
+
141
particular purpose or use are disclaimed in respect of the
+
142
Documentation, the modified Documentation or any Product. The Licensor
+
143
makes no representation that the Documentation, modified
+
144
Documentation, or any Product, does or will not infringe any patent,
+
145
copyright, trade secret or other proprietary right. The entire risk as
+
146
to the use, quality, and performance of a Product shall be with the
+
147
Licensee and not the Licensor. This disclaimer of warranty is an
+
148
essential part of this Licence and a condition for the grant of any
+
149
rights granted under this Licence. The Licensee warrants that it does
+
150
not act in a consumer capacity.
+
151
+
152
5.2. LIMITATION OF LIABILITY – The Licensor shall have no liability
+
153
for direct, indirect, special, incidental, consequential, exemplary,
+
154
punitive or other damages of any character including, without
+
155
limitation, procurement of substitute goods or services, loss of use,
+
156
data or profits, or business interruption, however caused and on any
+
157
theory of contract, warranty, tort (including negligence), product
+
158
liability or otherwise, arising in any way in relation to the
+
159
Documentation, modified Documentation and/or the use, manufacture or
+
160
distribution of a Product, even if advised of the possibility of such
+
161
damages, and the Licensee shall hold the Licensor(s) free and harmless
+
162
from any liability, costs, damages, fees and expenses, including
+
163
claims by third parties, in relation to such use.
+
164
+
165
6. General
+
166
+
167
6.1. Except for the rights explicitly granted hereunder, this Licence
+
168
does not imply or represent any transfer or assignment of intellectual
+
169
property rights to the Licensee.
+
170
+
171
6.2. The Licensee shall not use or make reference to any of the names
+
172
(including acronyms and abbreviations), images, or logos under which
+
173
the Licensor is known, save in so far as required to comply with
+
174
section 3. Any such permitted use or reference shall be factual and
+
175
shall in no event suggest any kind of endorsement by the Licensor or
+
176
its personnel of the modified Documentation or any Product, or any
+
177
kind of implication by the Licensor or its personnel in the
+
178
preparation of the modified Documentation or Product.
+
179
+
180
6.3. CERN may publish updated versions of this Licence which retain
+
181
the same general provisions as this version, but differ in detail so
+
182
far this is required and reasonable. New versions will be published
+
183
with a unique version number.
+
184
+
185
6.4. This Licence shall terminate with immediate effect, upon written
+
186
notice and without involvement of a court if the Licensee fails to
+
187
comply with any of its terms and conditions, or if the Licensee
+
188
initiates legal action against Licensor in relation to this
+
189
Licence. Section 5 shall continue to apply.
+
+
+ + + + + + +
+
+
+ + + + +
+