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

Subversion Repositories w11

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

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 wfjm
-- $Id: pdp11_mbox.vhd 314 2010-07-09 17:38:41Z mueller $
2
--
3
-- Copyright 2006-2007 by Walter F.J. Mueller <W.F.J.Mueller@gsi.de>
4
--
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
-- Module Name:    pdp11_mbox - syn
16
-- Description:    pdp11: mul/div unit for data (mbox)
17
--
18
-- Dependencies:   -
19
-- Test bench:     tb/tb_pdp11_core (implicit)
20
-- Target Devices: generic
21
-- Tool versions:  xst 8.1, 8.2, 9.1, 9.2; ghdl 0.18-0.25
22
-- Revision History: 
23
-- Date         Rev Version  Comment
24
-- 2007-06-14    56   1.0.1  Use slvtypes.all
25
-- 2007-05-12    26   1.0    Initial version 
26
------------------------------------------------------------------------------
27
 
28
library ieee;
29
use ieee.std_logic_1164.all;
30
use ieee.std_logic_arith.all;
31
 
32
use work.slvtypes.all;
33
use work.pdp11.all;
34
 
35
-- ----------------------------------------------------------------------------
36
 
37
entity pdp11_mbox is                    -- mul/div unit for data (mbox)
38
  port (
39
    CLK : in slbit;                     -- clock
40
    DSRC : in slv16;                    -- 'src' data in
41
    DDST : in slv16;                    -- 'dst' data in
42
    DTMP : in slv16;                    -- 'tmp' data in
43
    GPR_DSRC : in slv16;                -- 'src' data from GPR
44
    FUNC : in slv2;                     -- function
45
    S_DIV : in slbit;                   -- s_opg_div state
46
    S_DIV_CN : in slbit;                -- s_opg_div_cn state
47
    S_DIV_CR : in slbit;                -- s_opg_div_cr state
48
    S_ASH : in slbit;                   -- s_opg_ash state
49
    S_ASH_CN : in slbit;                -- s_opg_ash_cn state
50
    S_ASHC : in slbit;                  -- s_opg_ashc state
51
    S_ASHC_CN : in slbit;               -- s_opg_ashc_cn state
52
    SHC_TC : out slbit;                 -- last shc cycle (shc==0)
53
    DIV_CR : out slbit;                 -- division: reminder correction needed
54
    DIV_CQ : out slbit;                 -- division: quotient correction needed
55
    DIV_ZERO : out slbit;               -- division: divident or divisor zero
56
    DIV_OVFL : out slbit;               -- division: overflow
57
    DOUT : out slv16;                   -- data output
58
    DOUTE : out slv16;                  -- data output extra
59
    CCOUT : out slv4                    -- condition codes out
60
  );
61
end pdp11_mbox;
62
 
63
architecture syn of pdp11_mbox is
64
 
65
  signal R_DD_L : slv16 := (others=>'0'); -- divident, low order part
66
  signal R_DDO_LT : slbit := '0';         -- original sign bit of divident
67
  signal R_DIV_V : slbit := '0';          -- V flag for division
68
  signal R_SHC : slv6 := (others=>'0');   -- shift counter for div and ash/c
69
  signal R_C1 : slbit := '0';             -- first cycle indicator
70
  signal R_MSBO : slbit := '0';           -- original sign bit for ash/c
71
  signal R_ASH_V : slbit := '0';          -- V flag for ash/c
72
  signal R_ASH_C : slbit := '0';          -- C flag for ash/c
73
 
74
  signal NEXT_DD_L : slv16 := (others=>'0');
75
  signal NEXT_DDO_LT : slbit := '0';
76
  signal NEXT_DIV_V : slbit := '0';
77
  signal NEXT_SHC : slv6 := (others=>'0');
78
  signal NEXT_C1 : slbit := '0';
79
  signal NEXT_MSBO : slbit := '0';
80
  signal NEXT_ASH_V : slbit := '0';
81
  signal NEXT_ASH_C : slbit := '0';
82
 
83
  signal SHC_TC_L : slbit := '0';
84
 
85
  signal DDST_ZERO : slbit := '0';
86
  signal DSRC_ZERO : slbit := '0';
87
  signal DSRC_ONES : slbit := '0';
88
  signal DTMP_ZERO : slbit := '0';
89
 
90
  signal DOUT_DIV : slv16 := (others=>'0');
91
  signal DOUTE_DIV : slv16 := (others=>'0');
92
 
93
  alias DR : slv16 is DDST;             -- divisor  (in DDST)
94
  alias DD_H : slv16 is DSRC;           -- divident, high order part (in DSRC)
95
  alias Q : slv16 is DTMP;              -- quotient (accumulated in DTMP)
96
 
97
begin
98
 
99
  proc_regs: process (CLK)
100
  begin
101
    if CLK'event and CLK='1' then
102
      R_DD_L   <= NEXT_DD_L;
103
      R_DDO_LT <= NEXT_DDO_LT;
104
      R_DIV_V  <= NEXT_DIV_V;
105
      R_SHC    <= NEXT_SHC;
106
      R_C1     <= NEXT_C1;
107
      R_MSBO   <= NEXT_MSBO;
108
      R_ASH_V  <= NEXT_ASH_V;
109
      R_ASH_C  <= NEXT_ASH_C;
110
    end if;
111
  end process proc_regs;
112
 
113
  proc_comm: process (DDST, DSRC, DTMP)
114
  begin
115
 
116
    DDST_ZERO <= '0';
117
    DSRC_ZERO <= '0';
118
    DSRC_ONES <= '0';
119
    DTMP_ZERO <= '0';
120
 
121
    if unsigned(DDST) = 0 then
122
      DDST_ZERO <= '1';
123
    end if;
124
    if unsigned(DSRC) = 0 then
125
      DSRC_ZERO <= '1';
126
    end if;
127
    if   signed(DSRC) = -1 then
128
      DSRC_ONES <= '1';
129
    end if;
130
    if unsigned(DTMP) = 0 then
131
      DTMP_ZERO <= '1';
132
    end if;
133
 
134
  end process proc_comm;
135
 
136
  proc_shc: process (DDST, R_SHC, R_C1,
137
                     S_DIV, S_DIV_CN, S_ASH, S_ASH_CN, S_ASHC, S_ASHC_CN)
138
  begin
139
 
140
    NEXT_SHC    <= R_SHC;
141
    NEXT_C1     <= R_C1;
142
 
143
    if S_ASH='1' or S_ASHC='1' then
144
      NEXT_SHC <= DDST(5 downto 0);
145
      NEXT_C1 <= '1';
146
    end if;
147
    if S_DIV = '1' then
148
      NEXT_SHC <= "001111";
149
      NEXT_C1 <= '1';
150
    end if;
151
 
152
    if S_DIV_CN='1' or S_ASH_CN='1' or S_ASHC_CN='1' then
153
      if R_SHC(5) = '0' then
154
        NEXT_SHC <= unsigned(R_SHC) - 1;
155
      else
156
        NEXT_SHC <= unsigned(R_SHC) + 1;
157
      end if;
158
      NEXT_C1 <= '0';
159
    end if;
160
 
161
    SHC_TC_L <= '0';
162
    if unsigned(R_SHC) = 0 then
163
      SHC_TC_L <= '1';
164
    end if;
165
 
166
  end process proc_shc;
167
 
168
  proc_div: process (DDST, DSRC, DTMP, GPR_DSRC, DR, DD_H, Q,
169
                     R_DD_L, R_DDO_LT, R_DIV_V, R_SHC, R_C1,
170
                     S_DIV, S_DIV_CN, S_DIV_CR,
171
                     DDST_ZERO, DSRC_ZERO, DTMP_ZERO)
172
 
173
    variable shftdd : slbit := '0';
174
    variable subadd : slbit := '0';
175
 
176
    variable dd_gt : slbit := '0';
177
 
178
    variable qbit :   slbit := '0';
179
    variable qbit_1 : slbit := '0';
180
    variable qbit_n : slbit := '0';
181
 
182
    variable dd_h_old : slv16 := (others=>'0');  -- dd_h before add/sub
183
    variable dd_h_new : slv16 := (others=>'0');  -- dd_h after  add/sub
184
 
185
  begin
186
 
187
    NEXT_DD_L   <= R_DD_L;
188
    NEXT_DDO_LT <= R_DDO_LT;
189
    NEXT_DIV_V  <= R_DIV_V;
190
 
191
    DIV_ZERO <= '0';
192
    DIV_OVFL <= '0';
193
 
194
    qbit_1 := not (DR(15) xor DD_H(15)); -- !(dr<0 ^ dd_h<0)
195
 
196
    shftdd := not S_DIV_CR;
197
    if shftdd = '1' then
198
      dd_h_old := DD_H(14 downto 0) & R_DD_L(15);
199
    else
200
      dd_h_old := DD_H(15 downto 0);
201
    end if;
202
 
203
    if R_C1 = '1' then
204
      subadd := qbit_1;
205
      DIV_ZERO <= DDST_ZERO or
206
                  (DSRC_ZERO and DTMP_ZERO); -- note: DTMP here still dd_low !
207
    else
208
      subadd := Q(0);
209
    end if;
210
 
211
    if subadd = '0' then
212
      dd_h_new := signed(dd_h_old) + signed(DR);
213
    else
214
      dd_h_new := signed(dd_h_old) - signed(DR);
215
    end if;
216
 
217
    dd_gt := '0';
218
    if dd_h_new(15) = '0' and
219
       (unsigned(dd_h_new(14 downto 0))/=0 or
220
        unsigned(R_DD_L(14 downto 0))/=0)
221
    then
222
      dd_gt := '1';                     -- set if dd_new > 0
223
    end if;
224
 
225
    if R_DDO_LT = '0' then
226
      qbit_n := DR(15) xor not dd_h_new(15);  -- b_dr_lt ^ !b_dd_lt
227
    else
228
      qbit_n := DR(15) xor dd_gt;             -- b_dr_lt ^  b_dd_gt
229
    end if;
230
 
231
    if S_DIV = '1' then
232
      NEXT_DDO_LT <= DD_H(15);
233
      NEXT_DD_L <= GPR_DSRC;
234
    end if;
235
 
236
    if R_C1 = '1' then
237
      NEXT_DIV_V <= (DD_H(15) xor DD_H(14)) or
238
                    (DD_H(15) xor (DR(15) xor qbit_n));
239
      DIV_OVFL <= (DD_H(15) xor DD_H(14)) or               --??? cleanup
240
                    (DD_H(15) xor (DR(15) xor qbit_n));    --??? cleanup
241
    end if;
242
 
243
    if S_DIV_CN = '1' then
244
      NEXT_DD_L <= R_DD_L(14 downto 0) & '0';
245
    end if;
246
 
247
    if S_DIV_CN = '1' then
248
      qbit := qbit_n;
249
    else
250
      qbit := qbit_1;
251
    end if;
252
 
253
    DIV_CR <= not (R_DDO_LT xor
254
                   (DR(15) xor Q(0)));  --!(b_ddo_lt ^ (b_dr_lt ^ b_qbit));
255
    DIV_CQ <= R_DDO_LT xor DR(15);      -- b_ddo_lt ^ b_dr_lt;
256
 
257
    DOUT_DIV  <= dd_h_new;
258
    DOUTE_DIV <= Q(14 downto 0) & qbit;
259
 
260
  end process proc_div;
261
 
262
  proc_ash: process (R_MSBO, R_ASH_V, R_ASH_C, R_SHC, DSRC, DTMP, FUNC,
263
                     S_ASH, S_ASH_CN, S_ASHC, S_ASHC_CN, SHC_TC_L)
264
  begin
265
 
266
    NEXT_MSBO   <= R_MSBO;
267
    NEXT_ASH_V  <= R_ASH_V;
268
    NEXT_ASH_C  <= R_ASH_C;
269
 
270
    if S_ASH='1' or S_ASHC='1' then
271
      NEXT_MSBO <= DSRC(15);
272
      NEXT_ASH_V <= '0';
273
      NEXT_ASH_C <= '0';
274
    end if;
275
 
276
    if (S_ASH_CN='1' or S_ASHC_CN='1') and SHC_TC_L='0' then
277
      if R_SHC(5) = '0' then            -- left shift
278
        if (R_MSBO xor DSRC(14))='1' then
279
          NEXT_ASH_V <= '1';
280
        end if;
281
        NEXT_ASH_C <= DSRC(15);
282
      else                              -- right shift
283
        if FUNC = c_mbox_func_ash then
284
          NEXT_ASH_C <= DSRC(0);
285
        else
286
          NEXT_ASH_C <= DTMP(0);
287
        end if;
288
      end if;
289
    end if;
290
 
291
  end process proc_ash;
292
 
293
  proc_omux: process (DSRC, DDST, DTMP, FUNC,
294
                      R_ASH_V, R_ASH_C, R_SHC, R_DIV_V,
295
                      DOUT_DIV, DOUTE_DIV,
296
                      DSRC_ZERO, DSRC_ONES, DTMP_ZERO, DDST_ZERO)
297
 
298
    variable prod : slv32 := (others=>'0');
299
    variable omux_sel : slv2 := "00";
300
    variable ash_dout0 : slbit := '0';
301
 
302
    variable mul_c : slbit := '0';
303
 
304
  begin
305
 
306
    prod := signed(DSRC) * signed(DDST);
307
 
308
    case FUNC is
309
      when c_mbox_func_mul =>
310
        omux_sel := "00";
311
      when c_mbox_func_div =>
312
        omux_sel := "01";
313
      when c_mbox_func_ash |c_mbox_func_ashc =>
314
        if R_SHC(5) = '0' then
315
          omux_sel := "10";
316
        else
317
          omux_sel := "11";
318
        end if;
319
      when others => null;
320
    end case;
321
 
322
    if FUNC = c_mbox_func_ash then
323
      ash_dout0 := '0';
324
    else
325
      ash_dout0 := DTMP(15);
326
    end if;
327
 
328
    case omux_sel is
329
      when "00"  =>                     -- MUL
330
        DOUT  <= prod(31 downto 16);
331
        DOUTE <= prod(15 downto 0);
332
      when  "01" =>                     -- DIV
333
        DOUT  <= DOUT_DIV;
334
        DOUTE <= DOUTE_DIV;
335
      when  "10" =>                     -- shift left
336
        DOUT  <= DSRC(14 downto 0) & ash_dout0;
337
        DOUTE <= DTMP(14 downto 0) & "0";
338
      when  "11" =>                     -- shift right
339
        DOUT  <= DSRC(15) & DSRC(15 downto 1);
340
        DOUTE <= DSRC(0) & DTMP(15 downto 1);
341
      when others => null;
342
    end case;
343
 
344
    mul_c := '0';                       -- MUL C codes is set if
345
    if DSRC(15) = '0' then
346
      if DSRC_ZERO='0' or DTMP(15)='1' then -- for positive results when
347
        mul_c := '1';                   --   product > 2^15-1
348
      end if;
349
    else                                -- for negative results when
350
      if DSRC_ONES='0' or DTMP(15)='0' then
351
        mul_c := '1';                   --   product < -2^15
352
      end if;
353
    end if;
354
 
355
    case FUNC is
356
      when c_mbox_func_mul =>
357
        CCOUT(3) <= DSRC(15);               -- N
358
        CCOUT(2) <= DSRC_ZERO and DTMP_ZERO;-- Z
359
        CCOUT(1) <= '0';                    -- V=0
360
        CCOUT(0) <= mul_c;                  -- C
361
 
362
      when c_mbox_func_div =>
363
        if DDST_ZERO = '1' then
364
          CCOUT(3) <= '0';                    -- N=0 if div/0
365
          CCOUT(2) <= '1';                    -- Z=1 if div/0
366
        elsif R_DIV_V = '1' then
367
          CCOUT(3) <= DSRC(15) xor DDST(15);  -- N (from unchanged reg)
368
          CCOUT(2) <= '0';                    -- Z (from unchanged reg) ??? veri
369
        else
370
          CCOUT(3) <= DTMP(15);               -- N (from Q (DTMP))
371
          CCOUT(2) <= DTMP_ZERO;              -- Z (from Q (DTMP)) ??? verify
372
        end if;
373
        CCOUT(1) <= R_DIV_V or DDST_ZERO;     -- V
374
        CCOUT(0) <= DDST_ZERO;                -- C (dst=0)
375
 
376
      when c_mbox_func_ash =>
377
        CCOUT(3) <= DSRC(15);               -- N
378
        CCOUT(2) <= DSRC_ZERO;              -- Z
379
        CCOUT(1) <= R_ASH_V;                -- V
380
        CCOUT(0) <= R_ASH_C;                -- C
381
 
382
      when c_mbox_func_ashc =>
383
        CCOUT(3) <= DSRC(15);               -- N
384
        CCOUT(2) <= DSRC_ZERO and DTMP_ZERO;-- Z
385
        CCOUT(1) <= R_ASH_V;                -- V
386
        CCOUT(0) <= R_ASH_C;                -- C
387
 
388
      when others => null;
389
    end case;
390
 
391
  end process proc_omux;
392
 
393
  SHC_TC <= SHC_TC_L;
394
 
395
end syn;

powered by: WebSVN 2.1.0

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