-
Notifications
You must be signed in to change notification settings - Fork 18
/
pdp11_aunit.vhd
237 lines (193 loc) · 7.73 KB
/
pdp11_aunit.vhd
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
-- $Id: pdp11_aunit.vhd 1203 2019-08-19 21:41:03Z mueller $
-- SPDX-License-Identifier: GPL-3.0-or-later
-- Copyright 2006-2019 by Walter F.J. Mueller <W.F.J.Mueller@gsi.de>
--
------------------------------------------------------------------------------
-- Module Name: pdp11_aunit - syn
-- Description: pdp11: arithmetic unit for data (aunit)
--
-- Dependencies: -
-- Test bench: tb/tb_pdp11_core (implicit)
-- Target Devices: generic
-- Tool versions: ise 8.2-14.7; viv 2014.4-2019.1; ghdl 0.18-0.36
-- Revision History:
-- Date Rev Version Comment
-- 2019-08-17 1203 1.1.2 fix for ghdl V0.36 -Whide warnings
-- 2014-08-10 581 1.1.1 use c_cc_f_*
-- 2010-09-18 300 1.1 renamed from abox
-- 2007-06-14 56 1.0.1 Use slvtypes.all
-- 2007-05-12 26 1.0 Initial version
------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
use work.slvtypes.all;
use work.pdp11.all;
-- ----------------------------------------------------------------------------
-- arithmetic unit for data, usage:
-- ADD: SRC + DST + 0 (dst+src)
-- SUB: ~SRC + DST + 1 (dst-src)
-- ADC: 0 + DST + CI (dst+ci)
-- SBC: ~0 + DST + ~CI (dst-ci)
-- CMP: SRC + ~DST + 1 (src-dst)
-- COM: 0 + ~DST + 0 (~dst)
-- NEG: 0 + ~DST + 1 (-dst)
-- INC: 0 + DST + 1 (dst+1)
-- DEC: ~0 + DST + 0 (dst-1)
-- CLR: 0 + 0 + 0 (0)
-- SOB: SRC + ~0 + 0 (src-1)
entity pdp11_aunit is -- arithmetic unit for data (aunit)
port (
DSRC : in slv16; -- 'src' data in
DDST : in slv16; -- 'dst' data in
CI : in slbit; -- carry flag in
SRCMOD : in slv2; -- src modifier mode
DSTMOD : in slv2; -- dst modifier mode
CIMOD : in slv2; -- ci modifier mode
CC1OP : in slbit; -- use cc modes (1 op instruction)
CCMODE : in slv3; -- cc mode
BYTOP : in slbit; -- byte operation
DOUT : out slv16; -- data output
CCOUT : out slv4 -- condition codes out
);
end pdp11_aunit;
architecture syn of pdp11_aunit is
-- --------------------------------------
begin
process (DSRC, DDST, CI, CIMOD, CC1OP, CCMODE, SRCMOD, DSTMOD, BYTOP)
variable msrc : slv16 := (others=>'0'); -- effective src data
variable mdst : slv16 := (others=>'0'); -- effective dst data
variable mci : slbit := '0'; -- effective ci
variable sum : slv16 := (others=>'0'); -- sum
variable co8 : slbit := '0'; -- co 8 bit
variable co16 : slbit := '0'; -- co 16 bit
variable nno : slbit := '0'; -- local no
variable nzo : slbit := '0'; -- local zo
variable nvo : slbit := '0'; -- local vo
variable nco : slbit := '0'; -- local co
variable src_msb : slbit := '0'; -- msb from src (bit 15 or 7)
variable dst_msb : slbit := '0'; -- msb from dst (bit 15 or 7)
variable sum_msb : slbit := '0'; -- msb from sum (bit 15 or 7)
alias NO : slbit is CCOUT(c_cc_f_n);
alias ZO : slbit is CCOUT(c_cc_f_z);
alias VO : slbit is CCOUT(c_cc_f_v);
alias CO : slbit is CCOUT(c_cc_f_c);
-- procedure do_add8_ci_co: 8 bit adder with carry in and carry out
-- implemented following the recommended pattern for XST ISE V8.1
procedure do_add8_ci_co (
variable pa : in slv8; -- input a
variable pb : in slv8; -- input b
variable pci : in slbit; -- carry in
variable psum : out slv8; -- sum out
variable pco : out slbit -- carry out
) is
variable tmp: slv9;
begin
tmp := conv_std_logic_vector((conv_integer(pa) + conv_integer(pb) +
conv_integer(pci)),9);
psum := tmp(7 downto 0);
pco := tmp(8);
end procedure do_add8_ci_co;
begin
case SRCMOD is
when c_aunit_mod_pass => msrc := DSRC;
when c_aunit_mod_inv => msrc := not DSRC;
when c_aunit_mod_zero => msrc := (others=>'0');
when c_aunit_mod_one => msrc := (others=>'1');
when others => null;
end case;
case DSTMOD is
when c_aunit_mod_pass => mdst := DDST;
when c_aunit_mod_inv => mdst := not DDST;
when c_aunit_mod_zero => mdst := (others=>'0');
when c_aunit_mod_one => mdst := (others=>'1');
when others => null;
end case;
case CIMOD is
when c_aunit_mod_pass => mci := CI;
when c_aunit_mod_inv => mci := not CI;
when c_aunit_mod_zero => mci := '0';
when c_aunit_mod_one => mci := '1';
when others => null;
end case;
do_add8_ci_co(msrc(7 downto 0), mdst(7 downto 0), mci,
sum(7 downto 0), co8);
do_add8_ci_co(msrc(15 downto 8), mdst(15 downto 8), co8,
sum(15 downto 8), co16);
DOUT <= sum;
-- V ('overflow) bit set if
-- ADD : both operants of same sign but has result opposite sign
-- SUB : both operants of opposide sign and sign source equals sign result
-- CMP : both operants of opposide sign and sign dest. equals sign result
nno := '0';
nzo := '0';
nvo := '0';
nco := '0';
if BYTOP = '1' then
nno := sum(7);
if unsigned(sum(7 downto 0)) = 0 then
nzo := '1';
else
nzo := '0';
end if;
nco := co8;
src_msb := DSRC(7);
dst_msb := DDST(7);
sum_msb := sum(7);
else
nno := sum(15);
if unsigned(sum) = 0 then
nzo := '1';
else
nzo := '0';
end if;
nco := co16;
src_msb := DSRC(15);
dst_msb := DDST(15);
sum_msb := sum(15);
end if;
-- the logic for 2 operand V+C is ugly. It is reverse engineered from
-- the MOD's the operation type.
if CC1OP = '0' then -- 2 operand cases
if unsigned(CIMOD) = unsigned(c_aunit_mod_zero) then -- case ADD
nvo := not(src_msb xor dst_msb) and (src_msb xor sum_msb);
else
if unsigned(SRCMOD) = unsigned(c_aunit_mod_inv) then -- case SUB
nvo := (src_msb xor dst_msb) and not (src_msb xor sum_msb);
else -- case CMP
nvo := (src_msb xor dst_msb) and not (dst_msb xor sum_msb);
end if;
nco := not nco; -- invert C for SUB and CMP
end if;
else -- 1 operand cases
case CCMODE is
when c_aunit_ccmode_clr|c_aunit_ccmode_tst =>
nvo := '0'; -- force v=0 for tst and clr
nco := '0'; -- force c=0 for tst and clr
when c_aunit_ccmode_com =>
nvo := '0'; -- force v=0 for com
nco := '1'; -- force c=1 for com
when c_aunit_ccmode_inc =>
nvo := sum_msb and not dst_msb;
nco := CI; -- C not affected for INC
when c_aunit_ccmode_dec =>
nvo := not sum_msb and dst_msb;
nco := CI; -- C not affected for DEC
when c_aunit_ccmode_neg =>
nvo := sum_msb and dst_msb;
nco := not nzo;
when c_aunit_ccmode_adc =>
nvo := sum_msb and not dst_msb;
when c_aunit_ccmode_sbc =>
nvo := not sum_msb and dst_msb;
nco := not nco;
when others => null;
end case;
end if;
NO <= nno;
ZO <= nzo;
VO <= nvo;
CO <= nco;
end process;
end syn;