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

Subversion Repositories qfp32

[/] [qfp32/] [trunk/] [Units/] [recp.vhd] - Blame information for rev 2

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

Line No. Rev Author Line
1 2 mgraep
library IEEE;
2
use IEEE.std_logic_1164.all;
3
use IEEE.numeric_std.all;
4
 
5
library work;
6
use work.qfp_p.all;
7
 
8
entity qfp32_recp is
9
 
10
  port (
11
    clk_i     : in  std_ulogic;
12
    reset_n_i : in  std_ulogic;
13
 
14
    start_i : in  std_ulogic;
15
    ready_o : out std_ulogic;
16
 
17
    regA_i : in  qfp32_t;
18
 
19
    complete_o : out std_ulogic;
20
    result_o   : out qfp32_raw_t);
21
 
22
end qfp32_recp;
23
 
24
architecture Rtl of qfp32_recp is
25
 
26
  -- r=(1/d)*2^(29)
27
  -- shifting rem left each time (in loop), the result is effectivly multiplied by 2^(29)
28
  -- QFPx0: d = v*2^24
29
  -- QFPx8: d = v*2^16
30
  -- QFPx16: d = v*2^8
31
  -- QFPx24: d = v*2^0
32
 
33
  -- instead of shift mant left (if needed, at most 5bits) the dividend "1" is shifted right eg. divided by at most 32
34
  -- therefore the remainder reg has to be appended with additional 5bits for storing values less than 1
35
  -- overflow bit is although needed => ov 1bit + mant 29bits + add 5bits
36
 
37
  -- dividend > 1:
38
  --    1*2^x
39
  --    rem( >5 ) <= '1'
40
 
41
  -- dividend = 1:
42
  --    1
43
  --    rem(5) <= '1'
44
 
45
  -- dividend < 1:
46
  --    1*2^-x
47
  --    rem( <5 ) <= '1'
48
 
49
  -- MOD
50
  -- generate rounding bit => iterate 30cycles instead
51
 
52
  signal p1_mant : unsigned(28 downto 0);
53
  signal p1_fmt : qfp_fmt_t;
54
  signal p1_rem : unsigned(34 downto 0);
55
 
56
  signal p2_busy : std_ulogic;
57
  signal p2_mant : unsigned(28 downto 0);
58
  signal p2_fmt : qfp_fmt_t;
59
  signal p2_rem : unsigned(34 downto 0);
60
  signal p2_rem_shft : unsigned(34 downto 0);
61
  signal p2_rem_next : unsigned(34 downto 0);
62
 
63
  signal p2_sub : unsigned(29 downto 0);
64
  signal p2_quo : unsigned(29 downto 0);-- extend by 1 bit for calc rounding bit!!
65
  signal p2_quo_shft : unsigned(29 downto 0);
66
  signal p2_quo_next : unsigned(29 downto 0);
67
  signal p2_cnt : unsigned(4 downto 0);
68
  signal p2_complete : std_ulogic;
69
  signal p2_complete_1d : std_ulogic;
70
 
71
begin  -- Rtl
72
 
73
  process (clk_i, reset_n_i)
74
  begin  -- process
75
    if reset_n_i = '0' then             -- asynchronous reset (active low)
76
      p2_busy <= '0';
77
      p2_rem <= to_unsigned(0,35);
78
      p2_fmt <= (qfp_x0,'0');
79
      p2_mant <= to_unsigned(0,29);
80
      p2_quo <= to_unsigned(0,30);
81
      p2_cnt <= to_unsigned(0,5);
82
      p2_complete_1d <= '0';
83
    elsif clk_i'event and clk_i = '1' then  -- rising clock edge
84
      p2_complete_1d <= '0';
85
      if start_i = '1' and p2_busy = '0' then
86
        p2_rem <= p1_rem;
87
        p2_fmt <= p1_fmt;
88
        p2_mant <= p1_mant;
89
        p2_quo <= to_unsigned(0,30);
90
        p2_cnt <= to_unsigned(29,5);
91
        p2_busy <= '1';
92
      elsif p2_busy = '1' then
93
        p2_rem <= p2_rem_next;
94
        p2_quo <= p2_quo_next;
95
        p2_cnt <= p2_cnt-1;
96
        if p2_complete = '1' then
97
          p2_complete_1d <= '1';
98
          p2_busy <= '0';
99
          -- reset count
100
          p2_cnt <= to_unsigned(29,5);
101
        end if;
102
      end if;
103
    end if;
104
  end process;
105
 
106
  process (p1_mant, p2_mant, p2_quo(28 downto 0), p2_quo_shft,
107
           p2_rem(33 downto 0), p2_rem_shft, p2_rem_shft(34 downto 5), p2_sub,
108
           p2_sub(29), regA_i.fmt.sign, regA_i.mant, rega_i.fmt.exp)
109
  begin  -- process
110
 
111
    -- stage 1
112
    p1_mant <= unsigned(regA_i.mant);
113
 
114
    -- shift dividend and initial reminder correct
115
    -- so that no other correction is needed at the end division
116
    p1_fmt <= (qfp_x0,regA_i.fmt.sign);
117
    p1_rem <= to_unsigned(0,35);
118
    case rega_i.fmt.exp is
119
      when qfp_x24 => p1_rem <= to_unsigned(1,35);  -- -5
120
      when qfp_x16 => p1_rem <= to_unsigned(2**8,35);  -- +3
121
      when qfp_x8 => p1_rem <= to_unsigned(2**16,35);  -- +11
122
      when qfp_x0 =>
123
        if p1_mant <= to_unsigned(2**3,29) then  -- less or equal than 1/2M
124
          p1_rem <= to_unsigned(1,35); -- -5 
125
          p1_fmt.exp <= qfp_x24;
126
        elsif p1_mant <= to_unsigned(2**11,29) then  -- less or equal than 1/32
127
          p1_rem <= to_unsigned(2**8,35);-- +3
128
          p1_fmt.exp <= qfp_x16;
129
        elsif p1_mant <= to_unsigned(2**19,29) then  -- less or equal than 1/8192
130
          p1_rem <= to_unsigned(2**16,35);-- +11
131
          p1_fmt.exp <= qfp_x8;
132
        else
133
          p1_rem <= to_unsigned(2**24,35);-- +19
134
          p1_fmt.exp <= qfp_x0;
135
        end if;
136
      when others => null;
137
    end case;
138
 
139
    -- stage 2
140
 
141
    -- shift
142
    p2_rem_shft <= p2_rem(33 downto 0) & '0';
143
    p2_quo_shft <= p2_quo(28 downto 0) & '0';
144
 
145
    -- use only upper 30bits for sub, cause last 5bits only appended for not shifting mant
146
    p2_sub <= p2_rem_shft(34 downto 5)-('0' & p2_mant);
147
 
148
    p2_rem_next <= p2_rem_shft;
149
    p2_quo_next <= p2_quo_shft;
150
 
151
    if p2_sub(29) = '0' then           -- overflow: p2_rem_shft >= p2_mant therefore do sub
152
      p2_rem_next(34 downto 5) <= p2_sub;
153
      p2_quo_next(0) <= '1';
154
    end if;
155
 
156
  end process;
157
 
158
  p2_complete <= '1' when p2_cnt = to_unsigned(0,5) else '0';
159
 
160
  ready_o <= not p2_busy;
161
  result_o <= (p2_quo(29 downto 1) & '0' & (22 downto 0 => '0'),to_unsigned(0,5),'0' & p2_fmt.exp,p2_fmt.sign);
162
  complete_o <= p2_complete_1d;
163
 
164
end Rtl;
165
 

powered by: WebSVN 2.1.0

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