-
Notifications
You must be signed in to change notification settings - Fork 1
/
round.v
56 lines (51 loc) · 1.56 KB
/
round.v
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
//
// Integer round
// by Tomek Szczesny 2022
//
// This module rounds signed integers into the given bit precision.
// The output may have lower width than input, which effectively divides the
// number by 2^(n-m). This may be desirable if one is interested in just the
// significant bits of rounding.
//
// Additional error output provides difference between in and out (also signed).
// It does not account for reduced bit width of the output port.
//
// +-----------------+
// in[n] ===>| |===> out[m]
// | round |
// | |===> err[n]
// +-----------------+
//
// Parameters:
// n - Bit width of "in" (8)
// m - Bit width of "out" (m <= n) (8)
// p - Rounding precision (remaining significant bits) (p < n-1) (2)
//
// Ports:
// in[n] - Input signed integer
// out[m] - Output signed integer, rounded, and with trimmed LSBs if requested
// err[n] - Rounding error
//
`ifndef _round_v_
`define _round_v_
module round(
input wire signed [n-1:0] in,
output wire signed [m-1:0] out,
output wire signed [n-1:0] err
);
integer mag = $pow(2, n-p-2);
parameter n = 8;
parameter m = 8;
parameter p = 2;
wire signed [n-1:0] rnd; // input with added round-floor magic number
assign rnd = in + mag;
wire signed [n-1:0] rnd2; // rnd with zeroed out LSBs
// Overflow may happen - but only over the top
assign rnd2[n-1:n-p-1] = (rnd[n-1] == 1 && in[n-1] == 0) ?
(in[n-1:n-p-1]) :
(rnd[n-1:n-p-1]);
assign rnd2[n-p-2:0] = 0;
assign out = rnd2[n-1:n-m];
assign err = in - rnd2;
endmodule
`endif