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

Subversion Repositories rv01_riscv_core

[/] [rv01_riscv_core/] [trunk/] [VHDL/] [RV01_divider_r2.vhd] - Blame information for rev 2

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 madsilicon
-----------------------------------------------------------------
2
--                                                             --
3
-----------------------------------------------------------------
4
--                                                             --
5
-- Copyright (C) 2015 Stefano Tonello                          --
6
--                                                             --
7
-- This source file may be used and distributed without        --
8
-- restriction provided that this copyright statement is not   --
9
-- removed from the file and that any derivative work contains --
10
-- the original copyright notice and the associated disclaimer.--
11
--                                                             --
12
-- THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY         --
13
-- EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED   --
14
-- TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS   --
15
-- FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR      --
16
-- OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,         --
17
-- INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES    --
18
-- (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE   --
19
-- GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR        --
20
-- BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF  --
21
-- LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT  --
22
-- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT  --
23
-- OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE         --
24
-- POSSIBILITY OF SUCH DAMAGE.                                 --
25
--                                                             --
26
-----------------------------------------------------------------
27
 
28
---------------------------------------------------------------
29
-- RISC-V Integer divider
30
---------------------------------------------------------------
31
 
32
------------------------------------------------------------------
33
-- Divider FSM
34
------------------------------------------------------------------
35
 
36
library IEEE;
37
use IEEE.std_logic_1164.all;
38
use IEEE.numeric_std.all;
39
 
40
entity RV01_DIVFSM is
41
  port(
42
    CLK_i : in std_logic;
43
    RST_i : in std_logic;
44
    STRT_i : in std_logic;
45
    STOP_i : in std_logic;
46
    DBZ_i : in std_logic;
47
    SOVF_i : in std_logic;
48
 
49
    DRLE_o : out std_logic;
50
    DDULE_o : out std_logic;
51
    DRULE_o : out std_logic;
52
    DDZLE_o : out std_logic;
53
    DRZLE_o : out std_logic;
54
    DDNLE_o : out std_logic;
55
    DRNLE_o : out std_logic;
56
    QTXLE_o : out std_logic;
57
    QV_o : out std_logic;
58
    BSY_o : out std_logic
59
  );
60
end RV01_DIVFSM;
61
 
62
architecture ARC of RV01_DIVFSM is
63
 
64
  -- Note: a division operation requires the following steps:
65
  -- 1) DD sign check (and optional change) 
66
  -- 2) DR sign check (and optional change) 
67
  -- 3) DD leading 0's calculation
68
  -- 4) DR leading 0's calculation
69
  -- 5) DD normalization
70
  -- 6) DR normalization
71
  -- 7) unsigned division (up to 32 cycles)
72
  -- 8) result sign adjustment
73
 
74
  type DIV_STATE is (
75
    DS_DDSA,
76
    DS_DRSA,
77
    DS_DDLZ,
78
    DS_DRLZ,
79
    DS_DDNR,
80
    DS_DRNR,
81
    DS_DIVX,
82
    DS_QTSA,
83
    DS_WAIT1,
84
    DS_WAIT2
85
  );
86
 
87
  signal DRLE : std_logic;
88
  signal DDULE : std_logic;
89
  signal DRULE : std_logic;
90
  signal DDZLE : std_logic;
91
  signal DRZLE : std_logic;
92
  signal DDNLE : std_logic;
93
  signal DRNLE : std_logic;
94
  signal QTXLE : std_logic;
95
  signal QV : std_logic;
96
  signal BSY : std_logic;
97
  signal DS,DS_q : DIV_STATE;
98
 
99
begin
100
 
101
  process(CLK_i)
102
  begin
103
    if(CLK_i = '1' and CLK_i'event) then
104
      if(RST_i = '1') then
105
        DS_q <= DS_DDSA;
106
      else
107
        DS_q <= DS;
108
      end if;
109
    end if;
110
  end process;
111
 
112
  process(DS_q,DBZ_i,SOVF_i,STRT_i,STOP_i)
113
  begin
114
    DRLE <= '0';
115
    DDULE <= '0';
116
    DRULE <= '0';
117
    DDZLE <= '0';
118
    DRZLE <= '0';
119
    DDNLE <= '0';
120
    DRNLE <= '0';
121
    QTXLE <= '0';
122
    QV <= '0';
123
    BSY <= '0';
124
    case DS_q is
125
      -- DD sign adjustment
126
      when DS_DDSA =>
127
        if(STRT_i = '1') then
128
          if(DBZ_i = '1' or SOVF_i = '1') then
129
            -- division by zero or signed overflow, end operation
130
            DDULE <= '1'; -- latch DD
131
            DS <= DS_WAIT1;
132
          else
133
            DDULE <= '1'; -- latch unsigned DD
134
            DRLE <= '1'; -- latch signed DR
135
            DS <= DS_DRSA;
136
          end if;
137
        else
138
          DS <= DS_DDSA;
139
        end if;
140
      -- wait state
141
      when DS_WAIT1 =>
142
        BSY <= '1';
143
        DS <= DS_WAIT2;
144
      -- wait state
145
      when DS_WAIT2 =>
146
        --BSY <= '1';
147
        QV <= '1'; -- flag operation end
148
        DS <= DS_DDSA;
149
      -- DR sign adjustment
150
      when DS_DRSA =>
151
        BSY <= '1';
152
        DRULE <= '1'; -- latch unsigned DR
153
        DS <= DS_DDLZ;
154
      -- DD leading 0's calculation
155
      when DS_DDLZ =>
156
        BSY <= '1';
157
        DDZLE <= '1'; -- latch LZD(DD)
158
        DS <= DS_DRLZ;
159
      -- DR leading 0's calculation
160
      when DS_DRLZ =>
161
        BSY <= '1';
162
        DRZLE <= '1'; -- latch LZD(DR)
163
        DS <= DS_DDNR;
164
      -- DD normalization (left shift)
165
      when DS_DDNR =>
166
        BSY <= '1';
167
        DDNLE <= '1'; -- latch normalized DD
168
        DS <= DS_DRNR;
169
      -- DR normalization (left shift)
170
      when DS_DRNR =>
171
        BSY <= '1';
172
        DRNLE <= '1'; -- latch normalized DR
173
        DS <= DS_DIVX;
174
      -- division loop
175
      when DS_DIVX =>
176
        QTXLE <= not(STOP_i); -- latch intermediate quotient
177
        BSY <= '1';
178
        if(STOP_i = '1') then
179
          DS <= DS_QTSA;
180
        else
181
          DS <= DS_DIVX;
182
        end if;
183
      ---- quotient sign adjustment
184
      when DS_QTSA =>
185
        --BSY <= '1';
186
        QV <= '1';
187
        DS <= DS_DDSA;
188
      -- invalid state
189
      when others =>
190
        DS <= DS_DDSA;
191
    end case;
192
  end process;
193
 
194
  DRLE_o <= DRLE;
195
  DDULE_o <= DDULE;
196
  DRULE_o <= DRULE;
197
  DDZLE_o <= DDZLE;
198
  DRZLE_o <= DRZLE;
199
  DDNLE_o <= DDNLE;
200
  DRNLE_o <= DRNLE;
201
  QTXLE_o <= QTXLE;
202
  QV_o <= QV;
203
  BSY_o <= BSY;
204
 
205
end ARC;
206
 
207
------------------------------------------------------------------
208
-- Divider
209
------------------------------------------------------------------
210
 
211
library IEEE;
212
use IEEE.std_logic_1164.all;
213
use IEEE.numeric_std.all;
214
 
215
library WORK;
216
use WORK.RV01_CONSTS_PKG.all;
217
use WORK.RV01_TYPES_PKG.all;
218
use WORK.RV01_OP_PKG.all;
219
use WORK.RV01_FUNCS_PKG.all;
220
use WORK.RV01_ARITH_PKG.all;
221
use WORK.RV01_DIV_FUNCS_PKG.all;
222
 
223
entity RV01_DIVIDER_R2 is
224
  port(
225
    CLK_i : in std_logic;
226
    RST_i : in std_logic;
227
    STRT_i : in std_logic;
228
    SU_i : in std_logic; -- '0' -> unsigned div., '1' -> signed div.
229
    QS_i : in std_logic; -- '1' -> quotient, '0' -> reminder
230
    DD_i : in SDWORD_T;
231
    DR_i : in SDWORD_T;
232
    CLRD_i : in std_logic;
233
    CLRV_i : in std_logic;
234
 
235
    Q_o : out SDWORD_T;
236
    QV_o : out std_logic;
237
    BSY_o : out std_logic
238
  );
239
end RV01_DIVIDER_R2;
240
 
241
architecture ARC of RV01_DIVIDER_R2 is
242
 
243
  -- zero constant
244
  constant ZERO : SDWORD_T := (others => '0');
245
 
246
  -- min. signed integer constant
247
  constant MIN_SINT : SDWORD_T := (SDLEN-1 => '1',others => '0');
248
 
249
  -- -1 constant
250
  constant MINUS_ONE : SDWORD_T := (others => '1');
251
 
252
  constant L2SDLEN : natural := log2(SDLEN);
253
 
254
  component RV01_DIVFSM is
255
    port(
256
      CLK_i : in std_logic;
257
      RST_i : in std_logic;
258
      STRT_i : in std_logic;
259
      STOP_i : in std_logic;
260
      DBZ_i : in std_logic;
261
      SOVF_i : in std_logic;
262
 
263
      DRLE_o : out std_logic;
264
      DDULE_o : out std_logic;
265
      DRULE_o : out std_logic;
266
      DDZLE_o : out std_logic;
267
      DRZLE_o : out std_logic;
268
      DDNLE_o : out std_logic;
269
      DRNLE_o : out std_logic;
270
      QTXLE_o : out std_logic;
271
      QV_o : out std_logic;
272
      BSY_o : out std_logic
273
    );
274
  end component;
275
 
276
  component RV01_LZD32 is
277
    generic(
278
      WIDTH : natural := 32
279
    );
280
    port(
281
      A_i : in std_logic_vector(WIDTH-1 downto 0);
282
      CNT_o : out std_logic_vector(6-1 downto 0)
283
    );
284
  end component;
285
 
286
  signal DRLE,DDULE,DRULE,DDZLE,DRZLE,DDNLE,DRNLE,QTXLE,QV,BSY : std_logic;
287
  signal DBZ,SOVF,SGNDD,SGNDR,SGNOP1 : std_logic;
288
  signal DBZ_q,SOVF_q : std_logic;
289
  signal UOP1,OP2,OP3 : unsigned(SDLEN-1 downto 0);
290
  signal SOP3 : unsigned(SDLEN-1 downto 0);
291
  signal LZD : std_logic_vector(log2(SDLEN+1)-1 downto 0); -- see note below
292
  signal SHFT : unsigned(log2(SDLEN+1)-1 downto 0); -- see note below
293
  signal STOP : std_logic;
294
  signal IRST : std_logic;
295
  signal IDD : unsigned(SDLEN downto 0);
296
  signal IQT : unsigned(SDLEN-1 downto 0);
297
  signal SGNDD_q,SGNDR_q : std_logic;
298
  signal LZDD_q,LZDR_q : unsigned(log2(SDLEN+1)-1 downto 0); -- see note below
299
  signal RM_SHFT,RM_SHFT_q : unsigned(log2(SDLEN+1)-1 downto 0);
300
  signal CNT_q : unsigned(L2SDLEN downto 0);
301
  signal IDD_q : unsigned(SDLEN downto 0);
302
  signal IDR_q,IQT_q : unsigned(SDLEN-1 downto 0);
303
  signal QT,QT_q : signed(SDLEN-1 downto 0);
304
  signal URM : unsigned(SDLEN downto 0);
305
  signal RM,RM_q : signed(SDLEN-1 downto 0);
306
  signal Q_q : signed(SDLEN-1 downto 0);
307
  signal SU_q,QS_q,QV_q : std_logic;
308
 
309
  -- Note:
310
  -- leading zero's detector (shifter) with data input of SDLEN N
311
  -- generates a count output (needs an shift amount input) in the
312
  -- range 0:N. When N is a power-of-2, output (input) variable SDLEN
313
  -- must be 1 bit greater than log2(N). This special case can be managed
314
  -- setting SDLEN to log2(N+1) for all cases.
315
 
316
  -- synthesis translate_off
317
 
318
  signal CHK_QT : unsigned(SDLEN-1 downto 0);
319
  signal CHK_RM : unsigned(SDLEN-1 downto 0);
320
  signal QT_ERROR : std_logic;
321
 
322
  -- synthesis translate_on
323
 
324
begin
325
 
326
  ---------------------------------------
327
  -- Notes:
328
  --
329
  -- Division execution consists of the
330
  -- following steps:
331
  --
332
  -- 1) dividend (DD) and divisor (DR are
333
  -- converted to unsigned numbers, storing
334
  -- their original sign in SGNDD_q and SGNDR_q.
335
  --
336
  -- 2) unsigned DD and DR are normalized, 
337
  -- to insure their MSb is '1'.
338
  --
339
  -- 3) actual division is performed using
340
  -- the unsigned and normalized DD and DR,
341
  -- generating a 32-bit quotient/reminder. 
342
  --
343
  -- 4) if the quotient number of integer bits
344
  -- is negative, the quotient is right shifted
345
  -- to force it to zero.
346
  --
347
  -- 5) the quotient sign is adjusted according
348
  -- to SGNDD_q and SGNDR_q.
349
 
350
  ---------------------------------------
351
 
352
  IRST <= RST_i or CLRD_i;
353
 
354
  -- divide-by-zero flag
355
  DBZ <= '1' when (DR_i = ZERO) else '0';
356
 
357
  -- signed overflow flag
358
  SOVF <= SU_i when (DD_i = MIN_SINT and DR_i = MINUS_ONE) else '0';
359
 
360
  U_DIVFSM : RV01_DIVFSM
361
    port map(
362
      CLK_i => CLK_i,
363
      RST_i => IRST, --RST_i,
364
      STRT_i => STRT_i,
365
      STOP_i => STOP,
366
      DBZ_i => DBZ,
367
      SOVF_i => SOVF,
368
 
369
      DRLE_o => DRLE,
370
      DDULE_o => DDULE,
371
      DRULE_o => DRULE,
372
      DDZLE_o => DDZLE,
373
      DRZLE_o => DRZLE,
374
      DDNLE_o => DDNLE,
375
      DRNLE_o => DRNLE,
376
      QTXLE_o => QTXLE,
377
      QV_o => QV,
378
      BSY_o => BSY
379
    );
380
 
381
  ---------------------------------------
382
  -- Convert DD/DR to unsigned
383
  ---------------------------------------
384
 
385
  -- DD sign
386
  SGNDD <= DD_i(SDLEN-1) when SU_i = '1' else '0';
387
 
388
  -- DR sign (note the use of SU_q)
389
  SGNDR <= IDR_q(SDLEN-1) when SU_q = '1' else '0';
390
 
391
  process(DDULE,SGNDD,SGNDR,DD_i,IDR_q)
392
    variable SGN : std_logic;
393
    variable OP1 : unsigned(SDLEN-1 downto 0);
394
  begin
395
    -- extract DD/DR sign and extend DD/DR to SDLEN+1 bits
396
    if(DDULE = '1') then
397
      SGN := SGNDD;
398
      OP1 := to_unsigned(DD_i);
399
    else
400
      SGN := SGNDR;
401
      OP1 := IDR_q(SDLEN-1 downto 0);
402
    end if;
403
    -- change DD/DR sign, if needed
404
    if(SGN = '1') then
405
      UOP1 <= not(OP1)+1;
406
    else
407
      UOP1 <= OP1;
408
    end if;
409
  end process;
410
 
411
  ---------------------------------------
412
  -- Calculate unsigned DD/DR leading 0's number
413
  ---------------------------------------
414
 
415
  -- This information is needed to normalize DD/DR and
416
  -- is stored into LZDD_q/LZDR_q register.
417
  -- Same hardware is used for both operands in different cycles.
418
 
419
  -- select LZD unit input
420
  OP2 <= IDD_q(SDLEN-1 downto 0) when (DDZLE = '1') else IDR_q;
421
 
422
  U_LZD : RV01_LZD32
423
    generic map(
424
      WIDTH => SDLEN
425
    )
426
    port map(
427
      A_i => to_std_logic_vector(OP2),
428
      CNT_o => LZD
429
    );
430
 
431
  ---------------------------------------
432
  -- Normalize unsigned DD/DR
433
  ---------------------------------------
434
 
435
  -- Unsigned DD/DR is normalized by left-shifting it
436
  -- by the amount stored in LZDD_q/LZDR_q, result is
437
  -- stored into IDD_q/IDR_q register. 
438
  -- Same hardware is used for both operands in different cycles.
439
 
440
  -- select shifter inputs
441
  SHFT <= LZDD_q  when DDNLE = '1' else LZDR_q;
442
  OP3 <= IDD_q(SDLEN-1 downto 0) when DDNLE = '1' else IDR_q;
443
 
444
  SOP3 <= div_shift_left32(OP3,to_integer(SHFT));
445
 
446
  ---------------------------------------
447
  -- Division core loop
448
  ---------------------------------------
449
 
450
  -- division cycles counter
451
  process(CLK_i)
452
  begin
453
    if(CLK_i = '1' and CLK_i'event) then
454
      if(DRNLE = '1') then
455
        if(LZDR_q >= LZDD_q) then
456
          CNT_q <= (LZDR_q - LZDD_q + 1);
457
        else
458
          CNT_q <= (others => '0');
459
        end if;
460
      else
461
        CNT_q <= CNT_q-1;
462
      end if;
463
    end if;
464
  end process;
465
 
466
  -- end division flag
467
  STOP <= '1' when (CNT_q = 0) else '0';
468
 
469
  -- This divider implement a basic restoring division
470
  -- algorithm.
471
  -- IDD_q register is (SDLEN+1)-bit long in order to 
472
  -- accomodate any possible result of 1-bit left-shift
473
  -- performed on IDD_q itself or DIFF (see below).
474
 
475
  process(IDD_q,IDR_q,IQT_q)
476
    variable XIDD,XIDR,DIFF : unsigned(SDLEN+1 downto 0);
477
    variable SGN : std_logic;
478
  begin
479
    -- zero-extend IDD by 1 bit
480
    XIDD := '0' & IDD_q;
481
    -- zero-extend IDR by 2 bits
482
    XIDR := "00" & IDR_q;
483
    -- perform subtraction
484
    DIFF := XIDD - XIDR;
485
    -- difference sign
486
    SGN := DIFF(SDLEN+1);
487
    -- updated dividend value
488
    if(SGN = '1') then
489
      IDD <= (IDD_q sll 1);
490
    else
491
      IDD <= (DIFF(SDLEN downto 0) sll 1);
492
    end if;
493
    -- updated quotient
494
    IQT <= IQT_q(SDLEN-2 downto 0) & not(SGN);
495
  end process;
496
 
497
  ---------------------------------------
498
  -- Quotient/Reminder sign adjustment
499
  ---------------------------------------
500
 
501
  QT <= to_signed(IQT_q) when (SGNDD_q = SGNDR_q) else -to_signed(IQT_q);
502
 
503
  RM_SHFT <=
504
    LZDR_q+1 when (LZDR_q >= LZDD_q) else
505
    LZDD_q;
506
 
507
  --URM <= div_shift_right32(IDD_q(SDLEN-1 downto 0),to_integer(LZDR_q)+1); -- to be fixed!!!!
508
  --URM <= div_shift_right32(IDD_q(SDLEN-1 downto 0),to_integer(RM_SHFT_q));
509
  URM <= div_shift_right32(IDD_q,to_integer(RM_SHFT_q));
510
 
511
  RM <= to_signed(URM(SDLEN-1 downto 0)) when (SGNDD_q = '0')
512
    else -to_signed(URM(SDLEN-1 downto 0));
513
 
514
  ---------------------------------------
515
  -- Output
516
  ---------------------------------------
517
 
518
  BSY_o <= BSY;
519
 
520
  Q_o <= Q_q;
521
 
522
  QV_o <= QV_q;
523
 
524
  ---------------------------------------
525
  -- Registers
526
  ---------------------------------------
527
 
528
  -- DD/DR sign register
529
  process(CLK_i)
530
  begin
531
    if(CLK_i = '1' and CLK_i'event) then
532
      if(STRT_i = '1') then
533
        SU_q <= SU_i;
534
        QS_q <= QS_i;
535
        DBZ_q <= DBZ;
536
        SOVF_q <= SOVF;
537
      end if;
538
    end if;
539
  end process;
540
 
541
  -- DD/DR sign register
542
  process(CLK_i)
543
  begin
544
    if(CLK_i = '1' and CLK_i'event) then
545
      if(DDULE = '1') then
546
        SGNDD_q <= SGNDD;
547
      end if;
548
      if(DRULE = '1') then
549
        SGNDR_q <= SGNDR;
550
      end if;
551
    end if;
552
  end process;
553
 
554
  -- DD register
555
  process(CLK_i)
556
  begin
557
    if(CLK_i = '1' and CLK_i'event) then
558
      if(DDULE = '1') then
559
        if(SOVF = '1' or DBZ = '1') then
560
          IDD_q <= '0' & to_unsigned(DD_i);
561
        else
562
          IDD_q <= '0' & UOP1;
563
        end if;
564
      elsif(DDNLE = '1') then
565
        IDD_q <= '0' & SOP3;
566
      elsif(QTXLE = '1') then
567
        IDD_q <= IDD;
568
      end if;
569
    end if;
570
  end process;
571
 
572
  -- DR register
573
  process(CLK_i)
574
  begin
575
    if(CLK_i = '1' and CLK_i'event) then
576
      if(DRLE = '1') then
577
        IDR_q <= to_unsigned(DR_i);
578
      elsif(DRULE = '1') then
579
        IDR_q <= UOP1;
580
      elsif(DRNLE = '1') then
581
        IDR_q <= SOP3;
582
      end if;
583
    end if;
584
  end process;
585
 
586
  -- DD leading 0's count register
587
  process(CLK_i)
588
  begin
589
    if(CLK_i = '1' and CLK_i'event) then
590
      if(DDZLE = '1') then
591
        LZDD_q <= to_unsigned(LZD);
592
      end if;
593
    end if;
594
  end process;
595
 
596
  -- DR leading 0's count register
597
  process(CLK_i)
598
  begin
599
    if(CLK_i = '1' and CLK_i'event) then
600
      if(DRZLE = '1') then
601
        LZDR_q <= to_unsigned(LZD);
602
      end if;
603
    end if;
604
  end process;
605
 
606
  -- reminder shift amount register
607
  -- (timing purpose only)
608
  process(CLK_i)
609
  begin
610
    if(CLK_i = '1' and CLK_i'event) then
611
      if(DDNLE = '1') then
612
        RM_SHFT_q <= RM_SHFT;
613
      end if;
614
    end if;
615
  end process;
616
 
617
  -- quotient register
618
  process(CLK_i)
619
  begin
620
    if(CLK_i = '1' and CLK_i'event) then
621
      if(DRNLE = '1') then
622
        IQT_q <= to_unsigned(0,IQT_q'HIGH+1);
623
      elsif(QTXLE = '1') then
624
        IQT_q <= IQT;
625
      end if;
626
    end if;
627
  end process;
628
 
629
  -- end operation flag registers
630
  process(CLK_i)
631
  begin
632
    if(CLK_i = '1' and CLK_i'event) then
633
      --if(RST_i = '1' or CLRV_i = '1') then
634
      if(IRST = '1' or CLRV_i = '1') then
635
        QV_q <= '0';
636
      elsif(QV = '1') then
637
        QV_q <= '1';
638
      end if;
639
    end if;
640
  end process;
641
 
642
  process(CLK_i)
643
  begin
644
    if(CLK_i = '1' and CLK_i'event) then
645
      if(QV = '1') then
646
        if(QS_q = '1') then
647
          -- it's a division operation...
648
          if(DBZ_q = '1') then
649
            -- div-by-zero: set to result to all-1
650
            Q_q <= MINUS_ONE;
651
          elsif(SOVF_q = '1') then
652
            -- signed overflow: set result to dividend
653
            Q_q <= to_signed(IDD_q(SDLEN-1 downto 0));
654
          else
655
            -- regular result
656
            Q_q <= QT_q;
657
          end if;
658
        else
659
          -- it's a remainder operation...
660
          if(DBZ_q = '1') then
661
            -- div-by-zero: set to result to dividend
662
            Q_q <= to_signed(IDD_q(SDLEN-1 downto 0));
663
          elsif(SOVF_q = '1') then
664
            -- signed overflow: set result to zero
665
            Q_q <= ZERO;
666
          else
667
            -- regular result
668
            Q_q <= RM_q;
669
          end if;
670
        end if;
671
      end if;
672
    end if;
673
  end process;
674
 
675
  -- final result and reminder registers
676
  process(CLK_i)
677
  begin
678
    if(CLK_i = '1' and CLK_i'event) then
679
      --if(QRLE = '1') then
680
        QT_q <= QT;
681
        RM_q <= RM;
682
      --end if;
683
    end if;
684
  end process;
685
 
686
  -- synthesis translate_off
687
 
688
  process(CLK_i)
689
    variable TMP1,TMP2 : unsigned(SDLEN*2-2 downto 0);
690
  begin
691
    if(CLK_i = '1' and CLK_i'event) then
692
      if(DRNLE = '1') then
693
        TMP1(SDLEN*2-2 downto SDLEN-1) := IDD_q(SDLEN-1 downto 0);
694
        TMP1(SDLEN-2 downto 0) := (others => '0');
695
        TMP2 := (TMP1 / SOP3);
696
        CHK_QT <= TMP2(SDLEN-1 downto 0);
697
        --CHK_RM <= (TMP1 - TMP2(SDLEN-1 downto 0) * SOP3);
698
      end if;
699
    end if;
700
  end process;
701
 
702
  process(CLK_i)
703
  begin
704
    if(CLK_i = '1' and CLK_i'event) then
705
      if(RST_i = '1') then
706
        QT_ERROR <= '0';
707
      elsif(STOP = '1') then
708
        if(CHK_QT /= IQT_q) then
709
          QT_ERROR <= '1';
710
        else
711
          QT_ERROR <= '0';
712
        end if;
713
      end if;
714
    end if;
715
  end process;
716
 
717
  -- synthesis translate_on
718
 
719
end ARC;

powered by: WebSVN 2.1.0

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