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

Subversion Repositories lxp32

[/] [lxp32/] [trunk/] [rtl/] [lxp32_divider.vhd] - Blame information for rev 6

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

Line No. Rev Author Line
1 2 ring0_mipt
---------------------------------------------------------------------
2
-- Divider
3
--
4
-- Part of the LXP32 CPU
5
--
6
-- Copyright (c) 2016 by Alex I. Kuznetsov
7
--
8 6 ring0_mipt
-- Based on the NRD (Non Restoring Division) algorithm. Takes
9
-- 36 cycles to calculate quotient (37 for remainder).
10 2 ring0_mipt
---------------------------------------------------------------------
11
 
12
library ieee;
13
use ieee.std_logic_1164.all;
14
use ieee.numeric_std.all;
15
 
16
entity lxp32_divider is
17
        port(
18
                clk_i: in std_logic;
19
                rst_i: in std_logic;
20
                ce_i: in std_logic;
21
                op1_i: in std_logic_vector(31 downto 0);
22
                op2_i: in std_logic_vector(31 downto 0);
23
                signed_i: in std_logic;
24 6 ring0_mipt
                rem_i: in std_logic;
25 2 ring0_mipt
                ce_o: out std_logic;
26 6 ring0_mipt
                result_o: out std_logic_vector(31 downto 0)
27 2 ring0_mipt
        );
28
end entity;
29
 
30
architecture rtl of lxp32_divider is
31
 
32
-- Complementor signals
33
 
34 6 ring0_mipt
signal compl_inv: std_logic;
35
signal compl_mux: std_logic_vector(31 downto 0);
36
signal compl_out: std_logic_vector(31 downto 0);
37 2 ring0_mipt
 
38 6 ring0_mipt
signal inv_res: std_logic;
39 2 ring0_mipt
 
40
-- Divider FSM signals
41
 
42
signal fsm_ce: std_logic:='0';
43
 
44
signal dividend: unsigned(31 downto 0);
45
signal divisor: unsigned(32 downto 0);
46 6 ring0_mipt
signal want_remainder: std_logic;
47 2 ring0_mipt
 
48
signal partial_remainder: unsigned(32 downto 0);
49
signal addend: unsigned(32 downto 0);
50
signal sum: unsigned(32 downto 0);
51
signal sum_positive: std_logic;
52
signal sum_subtract: std_logic;
53
 
54
signal cnt: integer range 0 to 34:=0;
55
 
56
signal ceo: std_logic:='0';
57
 
58
-- Output restoration signals
59
 
60
signal remainder_corrector: unsigned(31 downto 0);
61 6 ring0_mipt
signal remainder_corrector_1: std_logic;
62
signal remainder_pos: unsigned(31 downto 0);
63
signal result_pos: unsigned(31 downto 0);
64 2 ring0_mipt
 
65
begin
66
 
67 6 ring0_mipt
compl_inv<=op1_i(31) and signed_i when ce_i='1' else inv_res;
68
compl_mux<=op1_i when ce_i='1' else std_logic_vector(result_pos);
69 2 ring0_mipt
 
70
compl_op1_inst: entity work.lxp32_compl(rtl)
71
        port map(
72
                clk_i=>clk_i,
73 6 ring0_mipt
                compl_i=>compl_inv,
74
                d_i=>compl_mux,
75
                d_o=>compl_out
76 2 ring0_mipt
        );
77
 
78
process (clk_i) is
79
begin
80
        if rising_edge(clk_i) then
81
                if rst_i='1' then
82
                        fsm_ce<='0';
83 6 ring0_mipt
                        want_remainder<='-';
84
                        inv_res<='-';
85 2 ring0_mipt
                else
86
                        fsm_ce<=ce_i;
87
                        if ce_i='1' then
88 6 ring0_mipt
                                want_remainder<=rem_i;
89
                                if rem_i='1' then
90
                                        inv_res<=op1_i(31) and signed_i;
91
                                else
92
                                        inv_res<=(op1_i(31) xor op2_i(31)) and signed_i;
93
                                end if;
94 2 ring0_mipt
                        end if;
95
                end if;
96
        end if;
97
end process;
98
 
99
-- Main adder/subtractor
100
 
101
addend_gen: for i in addend'range generate
102
        addend(i)<=divisor(i) xor sum_subtract;
103
end generate;
104
 
105
sum<=partial_remainder+addend+(to_unsigned(0,32)&sum_subtract);
106
sum_positive<=not sum(32);
107
 
108 6 ring0_mipt
-- Divider state machine
109 2 ring0_mipt
 
110
process (clk_i) is
111
begin
112
        if rising_edge(clk_i) then
113
                if rst_i='1' then
114
                        cnt<=0;
115
                        ceo<='0';
116 6 ring0_mipt
                        divisor<=(others=>'-');
117
                        dividend<=(others=>'-');
118
                        partial_remainder<=(others=>'-');
119
                        sum_subtract<='-';
120 2 ring0_mipt
                else
121 6 ring0_mipt
                        if cnt=1 then
122
                                ceo<='1';
123
                        else
124
                                ceo<='0';
125
                        end if;
126
 
127
                        if ce_i='1' then
128
                                divisor(31 downto 0)<=unsigned(op2_i);
129
                                divisor(32)<=op2_i(31) and signed_i;
130
                        end if;
131
 
132 2 ring0_mipt
                        if fsm_ce='1' then
133 6 ring0_mipt
                                dividend<=unsigned(compl_out(30 downto 0)&"0");
134
                                partial_remainder<=to_unsigned(0,32)&compl_out(31);
135
                                sum_subtract<=not divisor(32);
136
                                if want_remainder='1' then
137
                                        cnt<=34;
138
                                else
139
                                        cnt<=33;
140
                                end if;
141
                        else
142 2 ring0_mipt
                                partial_remainder<=sum(31 downto 0)&dividend(31);
143 6 ring0_mipt
                                sum_subtract<=sum_positive xor divisor(32);
144 2 ring0_mipt
                                dividend<=dividend(30 downto 0)&sum_positive;
145 6 ring0_mipt
                                if cnt>0 then
146
                                        cnt<=cnt-1;
147 2 ring0_mipt
                                end if;
148
                        end if;
149
                end if;
150
        end if;
151
end process;
152
 
153
-- Output restoration circuit
154
 
155
process (clk_i) is
156
begin
157
        if rising_edge(clk_i) then
158
                for i in remainder_corrector'range loop
159 6 ring0_mipt
                        remainder_corrector(i)<=(divisor(i) xor divisor(32)) and not sum_positive;
160 2 ring0_mipt
                end loop;
161 6 ring0_mipt
                remainder_corrector_1<=divisor(32) and not sum_positive;
162
                remainder_pos<=partial_remainder(32 downto 1)+remainder_corrector+
163
                        (to_unsigned(0,31)&remainder_corrector_1);
164 2 ring0_mipt
        end if;
165
end process;
166
 
167 6 ring0_mipt
result_pos<=remainder_pos when want_remainder='1' else dividend;
168
 
169
result_o<=compl_out;
170 2 ring0_mipt
ce_o<=ceo;
171
 
172
end architecture;

powered by: WebSVN 2.1.0

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