OpenCores
URL https://opencores.org/ocsvn/w11/w11/trunk

Subversion Repositories w11

[/] [w11/] [tags/] [w11a_V0.61/] [rtl/] [w11a/] [pdp11_munit.vhd] - Blame information for rev 26

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.