2023-06-15 12:24:35 -04:00
|
|
|
/* Copyright 2023 (C) Peter McGoron
|
|
|
|
* This file is a part of Upsilon, a free and open source software project.
|
|
|
|
* For license terms, refer to the files in `doc/copying` in the Upsilon
|
|
|
|
* source distribution.
|
|
|
|
*/
|
2022-09-16 18:01:34 -04:00
|
|
|
/* Saturate integers. v0.1
|
|
|
|
* Written by Peter McGoron, 2022.
|
|
|
|
*/
|
|
|
|
|
|
|
|
module intsat
|
|
|
|
#(
|
|
|
|
parameter IN_LEN = 64,
|
|
|
|
parameter LTRUNC = 32
|
|
|
|
)
|
|
|
|
(
|
|
|
|
input signed [IN_LEN-1:0] inp,
|
|
|
|
output signed [IN_LEN-LTRUNC-1:0] outp
|
|
|
|
);
|
|
|
|
|
|
|
|
/* Truncating a twos-complement integer can cause overflow.
|
|
|
|
* To check for overflow, look at all truncated bits and
|
|
|
|
* the most significant bit that will be kept.
|
|
|
|
* If they are all 0 or all 1, then there is no truncation.
|
|
|
|
*/
|
|
|
|
|
|
|
|
localparam INP_TRUNC_START = IN_LEN - LTRUNC;
|
|
|
|
localparam INP_CHECK_START = INP_TRUNC_START - 1;
|
|
|
|
localparam OUT_LEN = IN_LEN - LTRUNC;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* [ IN_LEN ]
|
|
|
|
* [ LTRUNC | OUT_LEN ]
|
|
|
|
* * &
|
|
|
|
* *: INP_TRUNC_START
|
|
|
|
* &: INP_CHECK_START
|
|
|
|
*/
|
|
|
|
|
|
|
|
always @ (*) begin
|
|
|
|
if (inp[IN_LEN-1:INP_CHECK_START] == {(LTRUNC + 1){inp[IN_LEN-1]}}) begin
|
|
|
|
outp[OUT_LEN-1:0] = inp[OUT_LEN-1:0];
|
|
|
|
end else if (inp[IN_LEN-1]) begin
|
|
|
|
// most negative number: 1000000....
|
|
|
|
outp[OUT_LEN-1:0] = {1'b1,{(OUT_LEN-1){1'b0}}};
|
|
|
|
end else begin
|
|
|
|
// most positive number: 0111111....
|
|
|
|
outp[OUT_LEN-1:0] = {1'b0,{(OUT_LEN-1){1'b1}}};
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
endmodule
|