w11 - vhd 0.794
W11 CPU core and support modules
Loading...
Searching...
No Matches
pdp11_munit.vhd
Go to the documentation of this file.
1-- $Id: pdp11_munit.vhd 1310 2022-10-27 16:15:50Z mueller $
2-- SPDX-License-Identifier: GPL-3.0-or-later
3-- Copyright 2006-2022 by Walter F.J. Mueller <W.F.J.Mueller@gsi.de>
4--
5------------------------------------------------------------------------------
6-- Module Name: pdp11_munit - syn
7-- Description: pdp11: mul/div unit for data (munit)
8--
9-- Dependencies: -
10-- Test bench: tb/tb_pdp11_core (implicit)
11-- Target Devices: generic
12-- Tool versions: ise 8.2-14.7; viv 2014.4-2022.1; ghdl 0.18-2.0.0
13--
14-- Synthesized (xst):
15-- Date Rev ise Target flop lutl lutm slic t peri
16-- 2014-07-12 569 14.7 131013 xc6slx16-2 30 154 0 46 s 6.8
17-- 2014-07-11 568 14.7 131013 xc6slx16-2 28 123 0 47 s 5.6
18--
19-- Revision History:
20-- Date Rev Version Comment
21-- 2022-10-25 1309 1.2.5 rename _gpr -> _gr
22-- 2014-08-10 581 1.2.4 rename NEXT_ to N_; use c_cc_f_*
23-- 2014-08-05 578 1.2.3 fix proc_div sensitivity list
24-- 2014-08-03 577 1.2.2 use DTMP_POS rather signed(Q)>0 (xst bug for S-3)
25-- 2014-07-26 575 1.2.1 fix proc_omux sensitivity list
26-- 2014-07-12 569 1.2 merge DIV_ZERO+DIV_OVFL to DIV_QUIT; add S_DIV_SR
27-- BUGFIX: fix divide logic, dr+q max neg issues
28-- 2011-11-18 427 1.1.1 now numeric_std clean
29-- 2010-09-18 300 1.1 renamed from mbox
30-- 2007-06-14 56 1.0.1 Use slvtypes.all
31-- 2007-05-12 26 1.0 Initial version
32------------------------------------------------------------------------------
33
34library ieee;
35use ieee.std_logic_1164.all;
36use ieee.numeric_std.all;
37
38use work.slvtypes.all;
39use work.pdp11.all;
40
41-- ----------------------------------------------------------------------------
42
43entity pdp11_munit is -- mul/div unit for data (munit)
44 port (
45 CLK : in slbit; -- clock
46 DSRC : in slv16; -- 'src' data in
47 DDST : in slv16; -- 'dst' data in
48 DTMP : in slv16; -- 'tmp' data in
49 GR_DSRC : in slv16; -- 'src' data from GR
50 FUNC : in slv2; -- function
51 S_DIV : in slbit; -- s_opg_div state (load dd_low)
52 S_DIV_CN : in slbit; -- s_opg_div_cn state (1st..16th cycle)
53 S_DIV_CR : in slbit; -- s_opg_div_cr state (remainder corr.)
54 S_DIV_SR : in slbit; -- s_opg_div_sr state (store remainder)
55 S_ASH : in slbit; -- s_opg_ash state
56 S_ASH_CN : in slbit; -- s_opg_ash_cn state
57 S_ASHC : in slbit; -- s_opg_ashc state
58 S_ASHC_CN : in slbit; -- s_opg_ashc_cn state
59 SHC_TC : out slbit; -- last shc cycle (shc==0)
60 DIV_CR : out slbit; -- division: remainder correction needed
61 DIV_CQ : out slbit; -- division: quotient correction needed
62 DIV_QUIT : out slbit; -- division: abort (0/ or /0 or V=1)
63 DOUT : out slv16; -- data output
64 DOUTE : out slv16; -- data output extra
65 CCOUT : out slv4 -- condition codes out
66 );
67end pdp11_munit;
68
69architecture syn of pdp11_munit is
70
71 signal R_DD_L : slv16 := (others=>'0'); -- divident, low order part
72 signal R_DDO_LT : slbit := '0'; -- original sign bit of divident
73 signal R_MAXFIX : slbit := '0'; -- maxfix flag for division
74 signal R_QO_LT : slbit := '0'; -- expected q sign for division
75 signal R_DIV_V : slbit := '0'; -- V flag for division
76 signal R_SHC : slv6 := (others=>'0'); -- shift counter for div and ash/c
77 signal R_C1 : slbit := '0'; -- first cycle indicator
78 signal R_MSBO : slbit := '0'; -- original sign bit for ash/c
79 signal R_ASH_V : slbit := '0'; -- V flag for ash/c
80 signal R_ASH_C : slbit := '0'; -- C flag for ash/c
81
82 signal N_DD_L : slv16 := (others=>'0');
83 signal N_DDO_LT : slbit := '0';
84 signal N_MAXFIX : slbit := '0';
85 signal N_QO_LT : slbit := '0';
86 signal N_DIV_V : slbit := '0';
87 signal N_SHC : slv6 := (others=>'0');
88 signal N_C1 : slbit := '0';
89 signal N_MSBO : slbit := '0';
90 signal N_ASH_V : slbit := '0';
91 signal N_ASH_C : slbit := '0';
92
93 signal SHC_TC_L : slbit := '0';
94
95 signal DDST_ZERO : slbit := '0';
96 signal DDST_NMAX : slbit := '0';
97 signal DSRC_ZERO : slbit := '0';
98 signal DSRC_ONES : slbit := '0';
99 signal DTMP_ZERO : slbit := '0';
100 signal DTMP_POS : slbit := '0';
101
102 signal DOUT_DIV : slv16 := (others=>'0');
103 signal DOUTE_DIV : slv16 := (others=>'0');
104
105 alias DR : slv16 is DDST; -- divisor (in DDST)
106 alias DD_H : slv16 is DSRC; -- divident, high order part (in DSRC)
107 alias Q : slv16 is DTMP; -- quotient (accumulated in DTMP)
108
109begin
110
111 proc_regs: process (CLK)
112 begin
113 if rising_edge(CLK) then
114 R_DD_L <= N_DD_L;
117 R_QO_LT <= N_QO_LT;
118 R_DIV_V <= N_DIV_V;
119 R_SHC <= N_SHC;
120 R_C1 <= N_C1;
121 R_MSBO <= N_MSBO;
122 R_ASH_V <= N_ASH_V;
123 R_ASH_C <= N_ASH_C;
124 end if;
125 end process proc_regs;
126
127 proc_comm: process (DDST, DSRC, DTMP)
128 begin
129
130 DDST_ZERO <= '0';
131 DDST_NMAX <= '0';
132 DSRC_ZERO <= '0';
133 DSRC_ONES <= '0';
134 DTMP_ZERO <= '0';
135 DTMP_POS <= '0';
136
137 if unsigned(DDST) = 0 then
138 DDST_ZERO <= '1';
139 end if;
140 if DDST = "1000000000000000" then
141 DDST_NMAX <= '1';
142 end if;
143 if unsigned(DSRC) = 0 then
144 DSRC_ZERO <= '1';
145 end if;
146 if signed(DSRC) = -1 then
147 DSRC_ONES <= '1';
148 end if;
149 if unsigned(DTMP) = 0 then
150 DTMP_ZERO <= '1';
151 end if;
152 if signed(DTMP) > 0 then
153 DTMP_POS <= '1';
154 end if;
155
156 end process proc_comm;
157
158 proc_shc: process (DDST, R_SHC, R_C1,
160 begin
161
162 N_SHC <= R_SHC;
163 N_C1 <= R_C1;
164
165 if S_ASH='1' or S_ASHC='1' then
166 N_SHC <= DDST(5 downto 0);
167 N_C1 <= '1';
168 end if;
169 if S_DIV = '1' then
170 N_SHC <= "001111";
171 N_C1 <= '1';
172 end if;
173
174 if S_DIV_CN='1' or S_ASH_CN='1' or S_ASHC_CN='1' then
175 if R_SHC(5) = '0' then
176 N_SHC <= slv(unsigned(R_SHC) - 1);
177 else
178 N_SHC <= slv(unsigned(R_SHC) + 1);
179 end if;
180 N_C1 <= '0';
181 end if;
182
183 SHC_TC_L <= '0';
184 if unsigned(R_SHC) = 0 then
185 SHC_TC_L <= '1';
186 end if;
187
188 end process proc_shc;
189
190 proc_div: process (DDST, DSRC, DTMP, GR_DSRC, DR, DD_H, Q,
194
195 variable div_zero : slbit := '0';
196 variable div_ovfl : slbit := '0';
197 variable shftdd : slbit := '0';
198 variable subadd : slbit := '0';
199
200 variable dd_le : slbit := '0';
201 variable dd_ge : slbit := '0';
202 variable dd_gt : slbit := '0';
203
204 variable qbit : slbit := '0';
205 variable qbit_1 : slbit := '0';
206 variable qbit_n : slbit := '0';
207
208 variable dd_h_old : slv16 := (others=>'0'); -- dd_h before add/sub
209 variable dd_h_new : slv16 := (others=>'0'); -- dd_h after add/sub
210
211 begin
212
213 N_DD_L <= R_DD_L;
216 N_QO_LT <= R_QO_LT;
217 N_DIV_V <= R_DIV_V;
218
219 div_zero := '0';
220 div_ovfl := '0';
221
222 qbit_1 := not (DR(15) xor DD_H(15)); -- !(dr<0 ^ dd_h<0)
223
224 shftdd := not S_DIV_CR;
225 if shftdd = '1' then
226 dd_h_old := DD_H(14 downto 0) & R_DD_L(15);
227 else
228 dd_h_old := DD_H(15 downto 0);
229 end if;
230
231 if R_C1 = '1' then
232 subadd := qbit_1;
233 else
234 subadd := Q(0);
235 end if;
236
237 if subadd = '0' then
238 dd_h_new := slv(signed(dd_h_old) + signed(DR));
239 else
240 dd_h_new := slv(signed(dd_h_old) - signed(DR));
241 end if;
242
243 dd_le := '0';
244 if signed(dd_h_new) <= 0 then
245 dd_le := '1'; -- set if dd_new_h <= 0
246 end if;
247
248 dd_ge := '0';
249 if signed(dd_h_new) >= -1 then
250 dd_ge := '1'; -- set if dd_new_h >= -1
251 end if;
252
253 dd_gt := '0';
254 if dd_h_new(15) = '0' and
255 (unsigned(dd_h_new(14 downto 0))/=0 or
256 unsigned(R_DD_L(14 downto 0))/=0)
257 then
258 dd_gt := '1'; -- set if dd_new > 0
259 end if;
260
261 if R_DDO_LT = '0' then
262 qbit_n := DR(15) xor not dd_h_new(15); -- b_dr_lt ^ !b_dd_lt
263 else
264 if R_MAXFIX = '0' then
265 qbit_n := DR(15) xor dd_gt; -- b_dr_lt ^ b_dd_gt
266 else
267 qbit_n := dd_h_new(15); -- b_dd_lt
268 end if;
269 end if;
270
271 if S_DIV = '1' then
272 N_DDO_LT <= DD_H(15);
273 N_DD_L <= GR_DSRC;
274 N_MAXFIX <= '0';
275 if DDST_NMAX = '1' and GR_DSRC = "0000000000000000" then
276 N_MAXFIX <= '1'; -- b_dr_nmax && (ddi_l == 0)
277 end if;
278 N_QO_LT <= DD_H(15) xor DR(15); -- b_di_lt ^ b_dr_lt
279 end if;
280
281 if R_C1 = '1' then
282 div_zero := DDST_ZERO or
283 (DSRC_ZERO and DTMP_ZERO); -- note: DTMP here still dd_low !
284
285 if DDST_NMAX='0' and (DD_H(15) xor DD_H(14)) = '1' then
286 div_ovfl := '1'; -- !b_dr_nmax && (b_di_31 != b_di_30)
287 end if;
288
289 if R_DDO_LT = '0' then -- if (!b_di_lt)
290 if R_QO_LT = '0' then -- if (!b_qo_lt)
291 if dd_h_new(15) = '0' then -- if (!b_dd_lt)
292 div_ovfl := '1';
293 end if;
294 else -- else
295 if dd_le = '0' then -- if (!b_dd_le)
296 div_ovfl := '1';
297 end if;
298 end if;
299 else
300 if R_QO_LT = '0' then -- if (!b_qo_lt)
301 if dd_gt = '0' then -- if (!b_dd_gt)
302 div_ovfl := '1';
303 end if;
304 else -- else
305 if dd_ge = '0' then -- if (!b_dd_ge)
306 div_ovfl := '1';
307 end if;
308 end if;
309 end if;
310 N_DIV_V <= div_ovfl;
311
312 elsif S_DIV_SR = '1' then
313 if R_QO_LT='1' and DTMP_POS='1' then
314 div_ovfl := '1';
315 end if;
316 N_DIV_V <= div_ovfl;
317 end if;
318
319 if S_DIV_CN = '1' then
320 N_DD_L <= R_DD_L(14 downto 0) & '0';
321 end if;
322
323 if S_DIV_CN = '1' then
324 qbit := qbit_n;
325 else
326 qbit := qbit_1;
327 end if;
328
329 DIV_QUIT <= div_zero or div_ovfl;
330
331 DIV_CR <= R_MAXFIX or -- b_maxfix | (!(b_ddo_lt ^ (b_dr_lt ^ b_qbit)))
332 (not (R_DDO_LT xor (DR(15) xor Q(0))));
333 DIV_CQ <= R_MAXFIX or -- b_maxfix | (b_ddo_lt ^ b_dr_lt)
334 (R_DDO_LT xor DR(15));
335
336 DOUT_DIV <= dd_h_new;
337 DOUTE_DIV <= Q(14 downto 0) & qbit;
338
339 end process proc_div;
340
341 proc_ash: process (R_MSBO, R_ASH_V, R_ASH_C, R_SHC, DSRC, DTMP, FUNC,
343 begin
344
345 N_MSBO <= R_MSBO;
346 N_ASH_V <= R_ASH_V;
347 N_ASH_C <= R_ASH_C;
348
349 if S_ASH='1' or S_ASHC='1' then
350 N_MSBO <= DSRC(15);
351 N_ASH_V <= '0';
352 N_ASH_C <= '0';
353 end if;
354
355 if (S_ASH_CN='1' or S_ASHC_CN='1') and SHC_TC_L='0' then
356 if R_SHC(5) = '0' then -- left shift
357 if (R_MSBO xor DSRC(14))='1' then
358 N_ASH_V <= '1';
359 end if;
360 N_ASH_C <= DSRC(15);
361 else -- right shift
362 if FUNC = c_munit_func_ash then
363 N_ASH_C <= DSRC(0);
364 else
365 N_ASH_C <= DTMP(0);
366 end if;
367 end if;
368 end if;
369
370 end process proc_ash;
371
372 proc_omux: process (DSRC, DDST, DTMP, FUNC,
376
377 variable prod : slv32 := (others=>'0');
378 variable omux_sel : slv2 := "00";
379 variable ash_dout0 : slbit := '0';
380
381 variable mul_c : slbit := '0';
382
383 begin
384
385 prod := slv(signed(DSRC) * signed(DDST));
386
387 case FUNC is
388 when c_munit_func_mul =>
389 omux_sel := "00";
390 when c_munit_func_div =>
391 omux_sel := "01";
392 when c_munit_func_ash |c_munit_func_ashc =>
393 if R_SHC(5) = '0' then
394 omux_sel := "10";
395 else
396 omux_sel := "11";
397 end if;
398 when others => null;
399 end case;
400
401 if FUNC = c_munit_func_ash then
402 ash_dout0 := '0';
403 else
404 ash_dout0 := DTMP(15);
405 end if;
406
407 case omux_sel is
408 when "00" => -- MUL
409 DOUT <= prod(31 downto 16);
410 DOUTE <= prod(15 downto 0);
411 when "01" => -- DIV
412 DOUT <= DOUT_DIV;
413 DOUTE <= DOUTE_DIV;
414 when "10" => -- shift left
415 DOUT <= DSRC(14 downto 0) & ash_dout0;
416 DOUTE <= DTMP(14 downto 0) & "0";
417 when "11" => -- shift right
418 DOUT <= DSRC(15) & DSRC(15 downto 1);
419 DOUTE <= DSRC(0) & DTMP(15 downto 1);
420 when others => null;
421 end case;
422
423 mul_c := '0'; -- MUL C codes is set if
424 if DSRC(15) = '0' then
425 if DSRC_ZERO='0' or DTMP(15)='1' then -- for positive results when
426 mul_c := '1'; -- product > 2^15-1
427 end if;
428 else -- for negative results when
429 if DSRC_ONES='0' or DTMP(15)='0' then
430 mul_c := '1'; -- product < -2^15
431 end if;
432 end if;
433
434 case FUNC is
435 when c_munit_func_mul =>
436 CCOUT(c_cc_f_n) <= DSRC(15); -- N
437 CCOUT(c_cc_f_z) <= DSRC_ZERO and DTMP_ZERO; -- Z
438 CCOUT(c_cc_f_v) <= '0'; -- V=0
439 CCOUT(c_cc_f_c) <= mul_c; -- C
440
441 when c_munit_func_div =>
442 if DDST_ZERO = '1' then
443 CCOUT(c_cc_f_n) <= '0'; -- N=0 if div/0
444 CCOUT(c_cc_f_z) <= '1'; -- Z=1 if div/0
445 elsif R_DIV_V = '1' then
446 CCOUT(c_cc_f_n) <= R_QO_LT; -- N (send expected sign)
447 CCOUT(c_cc_f_z) <= '0'; -- Z (from unchanged reg) ??? veri
448 else
449 CCOUT(c_cc_f_n) <= DTMP(15); -- N (from Q (DTMP))
450 CCOUT(c_cc_f_z) <= DTMP_ZERO; -- Z (from Q (DTMP)) ??? verify
451 end if;
452 CCOUT(c_cc_f_v) <= R_DIV_V or DDST_ZERO; -- V
453 CCOUT(c_cc_f_c) <= DDST_ZERO; -- C (dst=0)
454
455 when c_munit_func_ash =>
456 CCOUT(c_cc_f_n) <= DSRC(15); -- N
457 CCOUT(c_cc_f_z) <= DSRC_ZERO; -- Z
458 CCOUT(c_cc_f_v) <= R_ASH_V; -- V
459 CCOUT(c_cc_f_c) <= R_ASH_C; -- C
460
461 when c_munit_func_ashc =>
462 CCOUT(c_cc_f_n) <= DSRC(15); -- N
463 CCOUT(c_cc_f_z) <= DSRC_ZERO and DTMP_ZERO;-- Z
464 CCOUT(c_cc_f_v) <= R_ASH_V; -- V
465 CCOUT(c_cc_f_c) <= R_ASH_C; -- C
466
467 when others => null;
468 end case;
469
470 end process proc_omux;
471
472 SHC_TC <= SHC_TC_L;
473
474end syn;
slv16 :=( others => '0') R_DD_L
Definition: pdp11_munit.vhd:71
slbit := '0' R_DDO_LT
Definition: pdp11_munit.vhd:72
slbit := '0' DSRC_ONES
Definition: pdp11_munit.vhd:98
slbit := '0' R_MSBO
Definition: pdp11_munit.vhd:78
slbit := '0' N_C1
Definition: pdp11_munit.vhd:88
slbit := '0' SHC_TC_L
Definition: pdp11_munit.vhd:93
slv6 :=( others => '0') R_SHC
Definition: pdp11_munit.vhd:76
slbit := '0' DDST_ZERO
Definition: pdp11_munit.vhd:95
slbit := '0' R_DIV_V
Definition: pdp11_munit.vhd:75
slv16 :=( others => '0') N_DD_L
Definition: pdp11_munit.vhd:82
slbit := '0' N_ASH_V
Definition: pdp11_munit.vhd:90
slbit := '0' R_ASH_C
Definition: pdp11_munit.vhd:80
slbit := '0' DTMP_ZERO
Definition: pdp11_munit.vhd:99
slbit := '0' N_ASH_C
Definition: pdp11_munit.vhd:91
slbit := '0' N_MAXFIX
Definition: pdp11_munit.vhd:84
slv6 :=( others => '0') N_SHC
Definition: pdp11_munit.vhd:87
slbit := '0' N_DDO_LT
Definition: pdp11_munit.vhd:83
: slv16 is DSRC DD_H
slv16 :=( others => '0') DOUT_DIV
slbit := '0' DSRC_ZERO
Definition: pdp11_munit.vhd:97
slbit := '0' N_DIV_V
Definition: pdp11_munit.vhd:86
: slv16 is DDST DR
slbit := '0' R_QO_LT
Definition: pdp11_munit.vhd:74
slbit := '0' R_ASH_V
Definition: pdp11_munit.vhd:79
: slv16 is DTMP Q
slbit := '0' DTMP_POS
slbit := '0' N_MSBO
Definition: pdp11_munit.vhd:89
slv16 :=( others => '0') DOUTE_DIV
slbit := '0' DDST_NMAX
Definition: pdp11_munit.vhd:96
slbit := '0' N_QO_LT
Definition: pdp11_munit.vhd:85
slbit := '0' R_C1
Definition: pdp11_munit.vhd:77
slbit := '0' R_MAXFIX
Definition: pdp11_munit.vhd:73
out DOUTE slv16
Definition: pdp11_munit.vhd:64
out CCOUT slv4
Definition: pdp11_munit.vhd:66
in S_DIV slbit
Definition: pdp11_munit.vhd:51
in S_DIV_CN slbit
Definition: pdp11_munit.vhd:52
out DIV_CR slbit
Definition: pdp11_munit.vhd:60
in S_ASHC_CN slbit
Definition: pdp11_munit.vhd:58
out DIV_QUIT slbit
Definition: pdp11_munit.vhd:62
out DIV_CQ slbit
Definition: pdp11_munit.vhd:61
in S_DIV_CR slbit
Definition: pdp11_munit.vhd:53
in DDST slv16
Definition: pdp11_munit.vhd:47
in CLK slbit
Definition: pdp11_munit.vhd:45
in S_ASH slbit
Definition: pdp11_munit.vhd:55
out SHC_TC slbit
Definition: pdp11_munit.vhd:59
in S_ASHC slbit
Definition: pdp11_munit.vhd:57
in DSRC slv16
Definition: pdp11_munit.vhd:46
in FUNC slv2
Definition: pdp11_munit.vhd:50
in S_DIV_SR slbit
Definition: pdp11_munit.vhd:54
in S_ASH_CN slbit
Definition: pdp11_munit.vhd:56
in GR_DSRC slv16
Definition: pdp11_munit.vhd:49
out DOUT slv16
Definition: pdp11_munit.vhd:63
in DTMP slv16
Definition: pdp11_munit.vhd:48
Definition: pdp11.vhd:123
std_logic_vector( 3 downto 0) slv4
Definition: slvtypes.vhd:36
std_logic_vector( 31 downto 0) slv32
Definition: slvtypes.vhd:59
std_logic_vector( 15 downto 0) slv16
Definition: slvtypes.vhd:48
std_logic slbit
Definition: slvtypes.vhd:30
std_logic_vector( 5 downto 0) slv6
Definition: slvtypes.vhd:38
std_logic_vector( 1 downto 0) slv2
Definition: slvtypes.vhd:34
std_logic_vector slv
Definition: slvtypes.vhd:31