Source file divider_intf.ml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
(** Non-restoring divider. See [create] for documentation. *)

open! Base
open! Hardcaml
module Architecture = Cordic.Architecture

module type Spec = sig
  val width : int
  val signedness : Signedness.t
  val architecture : Architecture.t
end

module type Divider = sig
  module type Spec = Spec

  module Architecture = Architecture

  module Make (Spec : Spec) : sig
    module I : sig
      type 'a t =
        { clock : 'a
        ; clear : 'a
        ; numerator : 'a
        ; denominator : 'a
        ; start : 'a
        }
      [@@deriving hardcaml]
    end

    module O : sig
      type 'a t =
        { quotient : 'a
        ; remainder : 'a
        ; valid : 'a
        }
      [@@deriving hardcaml]
    end

    module State : sig
      type 'a t =
        { quot : 'a
        ; rem : 'a
        ; denom : 'a
        ; valid : 'a
        ; count : 'a
        ; running : 'a
        ; quot_mask : 'a
        }
      [@@deriving hardcaml]
    end

    (** Creates a non-restoring divider with config specified in [Spec]. The width of the
        input arguments is defined with [Spec.width]. The divider can operate on signed or
        unsigned arguments as defined in [Spec.signed] and performs truncated division
        (which aligns with default OCaml behaviour of [Int.( / )] and [Int.( mod )]).

        The delay of the divider is fixed at [Spec.width] cycles regardless of
        architecture.

        Three divider architectures are supported as set in [Spec.architecture]. In
        [Iterative] mode, only one operation per [Spec.width] cycles is supported. If
        [start] is asserted prior to the completion of the previous result, that operation
        is aborted and the new operation commences. [start] can be asserted on the same
        cycle that [valid] is high.

        In [Pipelined] or [Combinational] mode, one operation can be performed every
        cycle. In this mode [start] informs the divider that the inputs are valid. In
        [Combinational] mode, [valid] is assigned to start and outputs are updated in the
        same cycle. In [Pipelined] mode, [valid] will be asserted [Spec.width] cycles
        after [start] with the result of the divide. *)

    val create : Scope.t -> Interface.Create_fn(I)(O).t

    val hierarchical
      :  ?instance:string
      -> ?name:string
      -> Scope.t
      -> Signal.t I.t
      -> Signal.t O.t
  end
end