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 24

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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