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

Subversion Repositories riscv_vhdl

[/] [riscv_vhdl/] [trunk/] [rtl/] [riverlib/] [core/] [arith/] [int_div.vhd] - Blame information for rev 5

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 5 sergeykhbr
-----------------------------------------------------------------------------
2
--! @file
3
--! @copyright Copyright 2016 GNSS Sensor Ltd. All right reserved.
4
--! @author    Sergey Khabarov - sergeykhbr@gmail.com
5
--! @brief     Integer divider.
6
--! @details   Algorithm spends 33 clocks per instruction
7
------------------------------------------------------------------------------
8
 
9
library ieee;
10
use ieee.std_logic_1164.all;
11
library commonlib;
12
use commonlib.types_common.all;
13
--! RIVER CPU specific library.
14
library riverlib;
15
--! RIVER CPU configuration constants.
16
use riverlib.river_cfg.all;
17
 
18
 
19
entity IntDiv is
20
  port (
21
    i_clk  : in std_logic;
22
    i_nrst : in std_logic;                               -- Reset Active LOW
23
    i_ena : in std_logic;                                -- Enable bit
24
    i_unsigned : in std_logic;                           -- Unsigned operands
25
    i_rv32 : in std_logic;                               -- 32-bits operands enable
26
    i_residual : in std_logic;                           -- Compute: 0 =division; 1=residual
27
    i_a1 : in std_logic_vector(RISCV_ARCH-1 downto 0);   -- Operand 1
28
    i_a2 : in std_logic_vector(RISCV_ARCH-1 downto 0);   -- Operand 1
29
    o_res : out std_logic_vector(RISCV_ARCH-1 downto 0); -- Result
30
    o_valid : out std_logic;                             -- Result is valid
31
    o_busy : out std_logic                               -- Multiclock instruction under processing
32
  );
33
end;
34
 
35
architecture arch_IntDiv of IntDiv is
36
 
37
  type RegistersType is record
38
      rv32 : std_logic;
39
      resid : std_logic;                           -- Compute residual flag
40
      invert : std_logic;                          -- invert result value before output
41
      busy : std_logic;
42
      ena : std_logic_vector(33 downto 0);
43
      qr : std_logic_vector(127 downto 0);
44
      divider : std_logic_vector(64 downto 0);
45
      result : std_logic_vector(RISCV_ARCH-1 downto 0);
46
  end record;
47
 
48
  signal r, rin : RegistersType;
49
 
50
begin
51
 
52
 
53
  comb : process(i_nrst, i_ena, i_unsigned, i_residual, i_rv32, i_a1, i_a2, r)
54
    variable v : RegistersType;
55
    variable wb_diff1 : std_logic_vector(64 downto 0);
56
    variable wb_diff2 : std_logic_vector(64 downto 0);
57
    variable wb_qr1 : std_logic_vector(127 downto 0);
58
    variable wb_qr2 : std_logic_vector(127 downto 0);
59
    variable wb_a1 : std_logic_vector(RISCV_ARCH-1 downto 0);
60
    variable wb_a2 : std_logic_vector(RISCV_ARCH-1 downto 0);
61
    variable wb_divident : std_logic_vector(64 downto 0);
62
    variable wb_divider : std_logic_vector(64 downto 0);
63
    variable w_invert64 : std_logic;
64
    variable w_invert32 : std_logic;
65
  begin
66
 
67
    v := r;
68
 
69
    w_invert64 := '0';
70
    w_invert32 := '0';
71
    wb_divident(64) := '0';
72
    wb_divider(64) := '0';
73
 
74
    if i_rv32 = '1' then
75
        wb_a1(63 downto 32) := (others => '0');
76
        wb_a2(63 downto 32) := (others => '0');
77
        if i_unsigned = '1' or i_a1(31) = '0' then
78
            wb_a1(31 downto 0) := i_a1(31 downto 0);
79
        else
80
            wb_a1(31 downto 0) := (not i_a1(31 downto 0)) + 1;
81
        end if;
82
        if i_unsigned = '1' or i_a2(31) = '0' then
83
            wb_a2(31 downto 0) := i_a2(31 downto 0);
84
        else
85
            wb_a2(31 downto 0) := (not i_a2(31 downto 0)) + 1;
86
        end if;
87
    else
88
        if i_unsigned = '1' or i_a1(63) = '0' then
89
            wb_a1 := i_a1;
90
        else
91
            wb_a1 := (not i_a1) + 1;
92
        end if;
93
        if i_unsigned = '1' or i_a2(63) = '0' then
94
            wb_a2 := i_a2;
95
        else
96
            wb_a2 := (not i_a2) + 1;
97
        end if;
98
    end if;
99
 
100
    wb_divident(63 downto 0) := wb_a1;
101
    wb_divider(63 downto 0) := wb_a2;
102
 
103
    v.ena := r.ena(32 downto 0) & (i_ena and not r.busy);
104
 
105
    -- Level 2*i of 64:
106
    wb_diff1 := r.qr(127 downto 63) - r.divider;
107
    if wb_diff1(64) = '1' then
108
        wb_qr1 := r.qr(126 downto 0) & '0';
109
    else
110
        wb_qr1 := wb_diff1(63 downto 0) & r.qr(62 downto 0) & '1';
111
    end if;
112
 
113
    -- Level 2*i + 1 of 64:
114
    wb_diff2 := wb_qr1(127 downto 63) - r.divider;
115
    if wb_diff2(64) = '1' then
116
        wb_qr2 := wb_qr1(126 downto 0) & '0';
117
    else
118
        wb_qr2 := wb_diff2(63 downto 0) & wb_qr1(62 downto 0) & '1';
119
    end if;
120
 
121
 
122
    if i_ena = '1' then
123
        v.qr(127 downto 65) := (others => '0');
124
        v.qr(64 downto 0) := wb_divident;
125
        v.divider := wb_divider;
126
        v.busy := '1';
127
        v.rv32 := i_rv32;
128
        v.resid := i_residual;
129
        w_invert32 := not i_unsigned and
130
                ((not i_residual and (i_a1(31) xor i_a2(31)))
131
                or (i_residual and i_a1(31)));
132
        w_invert64 := not i_unsigned and
133
                ((not i_residual and (i_a1(63) xor i_a2(63)))
134
                or (i_residual and i_a1(63)));
135
        v.invert := (not i_rv32 and w_invert64)
136
                or (i_rv32 and w_invert32);
137
    elsif r.ena(32) = '1' then
138
        v.busy := '0';
139
        if r.resid = '1' then
140
            if r.invert = '1' then
141
                v.result := (not r.qr(127 downto 64)) + 1;
142
            else
143
                v.result := r.qr(127 downto 64);
144
            end if;
145
        else
146
            if r.invert = '1' then
147
                v.result := (not r.qr(63 downto 0)) + 1;
148
            else
149
                v.result := r.qr(63 downto 0);
150
            end if;
151
        end if;
152
    elsif r.busy = '1' then
153
        v.qr := wb_qr2;
154
    end if;
155
 
156
    if i_nrst = '0' then
157
        v.result := (others => '0');
158
        v.ena := (others => '0');
159
        v.busy := '0';
160
        v.rv32 := '0';
161
        v.invert := '0';
162
        v.qr := (others => '0');
163
        v.resid := '0';
164
    end if;
165
 
166
    o_res <= r.result;
167
    o_valid <= r.ena(33);
168
    o_busy <= r.busy;
169
 
170
    rin <= v;
171
  end process;
172
 
173
  -- registers:
174
  regs : process(i_clk)
175
  begin
176
     if rising_edge(i_clk) then
177
        r <= rin;
178
     end if;
179
  end process;
180
 
181
end;

powered by: WebSVN 2.1.0

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