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

Subversion Repositories qfp32

[/] [qfp32/] [trunk/] [Units/] [norm.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
package qfp32_norm_p is
9
 
10
  type raw_norm_t is record
11
    zero     : std_ulogic;
12
    err      : std_ulogic;
13
    mant     : unsigned(28 downto 0);
14
    exp      : unsigned(2 downto 0);
15
    rounding : std_ulogic;
16
  end record raw_norm_t;
17
 
18
  function normMant (
19
    raw : unsigned; -- raw mantissa (unnormalized mant + block*(steps-1)
20
    exp : unsigned;
21
    dont_shft : std_ulogic)
22
    return raw_norm_t;
23
 
24
end package qfp32_norm_p;
25
 
26
package body qfp32_norm_p is
27
 
28
  function normMant (
29
    raw : unsigned; -- raw format: ov (n-bits) | mant | shifted in m=(steps-1)*block bits
30
    exp : unsigned; -- exponent: min=0 max=2*k-2
31
    dont_shft : std_ulogic)
32
    return raw_norm_t is
33
 
34
    constant blockSize : natural := 8;
35
    constant numBlocks : natural := 4;
36
    constant mantSize : natural := 29;
37
    constant mantRestSize : natural := mantSize-((numBlocks-1)*blockSize);  -- 5                                                                      
38
 
39
    variable ov : std_ulogic;
40
    variable zero : std_ulogic_vector(numBlocks-2 downto 0);
41
    variable norm : unsigned(mantSize downto 0);
42
    variable slice : natural;
43
    variable shft : unsigned(log2(numBlocks)-1 downto 0);
44
    variable mant_zero : std_ulogic_vector(numBlocks-1 downto 0);
45
    variable full_mant_zero : std_ulogic;
46
  begin
47
 
48
    zero := (others => '0');
49
    -- check which blocks are zero
50
    for i in 0 to numBlocks-2 loop
51
      slice := raw'length-i*blockSize;
52
      if raw(slice-1 downto slice-blockSize) = to_unsigned(0,blockSize) then
53
        zero(i) := '1';
54
      end if;
55
    end loop;  -- i
56
 
57
    -- check if mant is zero
58
    -- mant depends on shft value but all top block must be zero
59
    -- select correct block from mant_zero by using shft    
60
    mant_zero := (others => '0');
61
    if zero = (numBlocks-2 downto 0 => '1') then
62
      for i in 0 to numBlocks-1 loop
63
        if raw(mantSize-1 downto mantSize-mantRestSize-8*i) = to_unsigned(0,mantRestSize+i*8) then
64
          mant_zero(i) := '1';
65
        end if;
66
      end loop;  -- i
67
    end if;
68
 
69
    -- calc shift
70
    shft := to_unsigned(0,log2(numBlocks));
71
    for i in 0 to numBlocks-2 loop
72
      if zero(i) = '0' or exp = i  then
73
        exit; -- break
74
      end if;
75
      shft := shft+1;
76
    end loop;  -- i
77
 
78
    -- check for format overflow
79
    ov := '0';
80
    if exp > numBlocks-1 then -- possible overflow
81
      for i in numBlocks to (numBlocks-1)*2 loop
82
        if zero(i-numBlocks) = '0' and exp >= i then
83
          ov := '1';
84
        end if;
85
      end loop;  -- i      
86
    end if;
87
 
88
    -- make sure we dont shift if not allowed
89
    if dont_shft = '1' then
90
      shft := to_unsigned(0,shft'length);
91
      ov := to_ulogic(exp > blockSize-1);
92
    end if;
93
 
94
    norm := fast_shift(raw,to_integer(shft)*blockSize,fast_shift_left,'0')(raw'length-1 downto raw'length-mantSize-1);
95
 
96
    return (mant_zero(to_integer(shft)),ov,norm(mantSize downto 1),exp-shft,norm(0));
97
 
98
  end function;
99
 
100
end package body qfp32_norm_p;
101
 
102
library IEEE;
103
use IEEE.std_logic_1164.all;
104
use IEEE.numeric_std.all;
105
 
106
library work;
107
use work.qfp_p.all;
108
use work.qfp32_norm_p.all;
109
 
110
entity qfp_norm is
111
 
112
  port (
113
    clk_i      : in  std_ulogic;
114
    reset_n_i  : in  std_ulogic;
115
 
116
    -- raw interface
117
    raw_i      : in  qfp32_raw_t;
118
 
119
    -- result
120
    result_o : out qfp32_t;
121
    result_zero_o : out std_ulogic);
122
 
123
end entity qfp_norm;
124
 
125
architecture Rtl of qfp_norm is
126
 
127
  signal is_ext : std_ulogic;
128
  signal err : std_ulogic;
129
  signal mant : unsigned(28 downto 0);
130
  signal full_mant : unsigned(33 downto 0);
131
  signal exp : unsigned(2 downto 0);
132
  signal rounding : std_ulogic;
133
  signal rd_mant : unsigned(34 downto 0);
134
  signal rounding_err : std_ulogic;
135
  --signal rd_add : unsigned(33 downto 0);
136
  signal zero : std_ulogic;
137
 
138
  signal norm : raw_norm_t;
139
 
140
begin  -- architecture Rtl
141
 
142
  process (err, exp, exp(1 downto 0), full_mant, full_mant(28 downto 0),
143
           full_mant(33 downto 8), is_ext, mant, raw_i.exp, raw_i.extMant,
144
           raw_i.ov, raw_i.sign, rd_mant(29), rounding_err, zero)
145
  begin  -- process
146
 
147
    is_ext <= '0';
148
    if raw_i.ov /= to_unsigned(0,5) then
149
      is_ext <= '1';
150
    end if;
151
 
152
    -- <<
153
    (zero,err,mant,exp,rounding) <= normMant(raw_i.extMant,raw_i.exp,is_ext);
154
 
155
    full_mant <= raw_i.ov & mant;
156
 
157
    -- round
158
    rd_mant <= '0' & full_mant;
159
    --if enableRounding and rounding = '1' then
160
    --  if is_ext = '0' then
161
    --    rd_add <= to_unsigned(1,34);
162
    --  else
163
    --    rd_add <= to_unsigned(256,34);
164
    --  end if;
165
 
166
    --  rd_mant <= fast_add(full_mant,rd_add,'0');
167
    --end if;
168
 
169
    rounding_err <= '0';
170
 
171
    -- check if fmt must be shifted right >>
172
    if rd_mant(29) = '1' or is_ext = '1' then-- overflow to next fmt cause of rounding
173
      if exp >= 3 then
174
        rounding_err <= '1';
175
      end if;
176
    end if;
177
 
178
    -- if value is zero => sign must be 0
179
    result_o.fmt.sign <= raw_i.sign;
180
    if zero = '1' and is_ext = '0' then
181
      result_o.fmt.sign <= '0';
182
    end if;
183
 
184
    -- shift >> or select overflow
185
    result_o.fmt.exp <= to_unsigned(3,2);
186
    result_o.mant <= to_unsigned(2**29-1,29);
187
    if rounding_err = '0' and err = '0' then
188
      if rd_mant(29) = '0' and is_ext = '0' then
189
        result_o.mant <= full_mant(28 downto 0);
190
        result_o.fmt.exp <= exp(1 downto 0);
191
      else
192
        result_o.mant <= "000" & full_mant(33 downto 8);
193
        result_o.fmt.exp <= exp(1 downto 0)+to_unsigned(1,2);
194
      end if;
195
    end if;
196
 
197
  end process;
198
 
199
  result_zero_o <= zero and not is_ext;
200
 
201
end architecture Rtl;

powered by: WebSVN 2.1.0

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