GCC Code Coverage Report
Directory: generated/vunit_out/preprocessed/ Exec Total Coverage
File: generated/vunit_out/preprocessed/math/unsigned_divider.vhd Lines: 34 34 100.0 %
Date: 2021-06-12 04:12:08 Branches: 116 186 62.4 %

Line Branch Exec Source
1
108
-- -------------------------------------------------------------------------------------------------
2
-- Copyright (c) Lukas Vik. All rights reserved.
3
--
4
-- This file is part of the tsfpga project.
5
-- https://tsfpga.com
6
-- https://gitlab.com/tsfpga/tsfpga
7
-- -------------------------------------------------------------------------------------------------
8
-- Calculates dividend / divisor = quotient + remainder / divisor
9
--
10
-- This is a bit serial divider. Algorithm is the same as long division from elementary
11
-- school, but with number base 2. Latency scales linearly with dividend_width.
12
-- -------------------------------------------------------------------------------------------------
13
14
library ieee;
15
use ieee.std_logic_1164.all;
16
use ieee.numeric_std.all;
17
18
library common;
19
use common.types_pkg.all;
20
21
use work.math_pkg.all;
22
23
24



1524224
entity unsigned_divider is
25
  generic (
26
    dividend_width : integer;
27
    divisor_width : integer
28
  );
29
  port (
30
    clk : in std_logic;
31
32
    input_ready : out std_logic := '1';
33
    input_valid : in std_logic;
34
    dividend : in unsigned(dividend_width - 1 downto 0);
35
    divisor : in unsigned(divisor_width - 1 downto 0);
36
37
    result_ready : in std_logic;
38
    result_valid : out std_logic := '0';
39
    quotient : out unsigned(dividend_width - 1 downto 0);
40
    remainder : out unsigned(minimum(divisor_width, dividend_width) - 1 downto 0)
41
  );
42
end entity;
43
44
architecture a of unsigned_divider is
45
46
  type state_t is (ready, busy, done);
47
18
  signal state : state_t := ready;
48
49
18
  signal current_bit : integer range 0 to dividend_width - 1;
50
132
  signal remainder_int : unsigned(dividend'range);
51
246
  signal divisor_int : unsigned((dividend_width - 1) + divisor_width - 1 downto 0);
52
53
  function shift_down(bit : std_logic; vector : unsigned) return unsigned is
54
  begin
55
3046400
    return bit & vector(vector'high downto vector'low + 1);
56
  end function;
57
58
  function shift_down(vector : unsigned) return unsigned is
59
  begin
60
1523200
    return shift_down('0', vector);
61
  end function;
62
63
  function shift_up(bit : std_logic; vector : unsigned) return unsigned is
64
  begin
65




1203200
    return vector(vector'high - 1 downto vector'low) & bit;
66
  end function;
67
68
begin
69
70




7700811
  remainder <= resize(remainder_int, remainder'length);
71
72
18
  main : process
73
798
    variable sub_result : signed(maximum(remainder_int'length, divisor_int'length) + 1 - 1 downto 0);
74
  begin
75

6092800
    wait until rising_edge(clk);
76
77


23025664
    divisor_int <= shift_down(divisor_int);
78


1523200
    sub_result := signed('0' & remainder_int) - signed('0' & divisor_int);
79
80

1523200
    case state is
81
      when ready =>
82
160000
        if input_ready and input_valid then
83

160000
          input_ready <= '0';
84


1363200
          remainder_int <= dividend;
85




2566400
          divisor_int <= divisor & to_unsigned(0, dividend_width - 1);
86

160000
          current_bit <= dividend_width - 1;
87

160000
          state <= busy;
88
        end if;
89
90
      when busy =>
91
1203200
        if lt_0(sub_result) then
92


9257844
          quotient <= shift_up('0', quotient);
93
        else
94


1110156
          quotient <= shift_up('1', quotient);
95




1110156
          remainder_int <= remainder_int - divisor_int(remainder_int'range);
96
        end if;
97
98
1203200
        if current_bit = 0 then
99

160000
          state <= done;
100

160000
          result_valid <= '1';
101
        else
102

1203200
          current_bit <= current_bit - 1;
103
        end if;
104
105
      when done =>
106
160000
        if result_ready and result_valid then
107

160000
          result_valid <= '0';
108

160000
          input_ready <= '1';
109

3046418
          state <= ready;
110
        end if;
111
    end case;
112
  end process;
113
114
end architecture;