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

Subversion Repositories qfp32

[/] [qfp32/] [trunk/] [Units/] [norm.vhd] - Blame information for rev 3

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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