3
0
Fork 0
mirror of https://github.com/YosysHQ/yosys synced 2025-04-24 01:25:33 +00:00

Add flooring division operator

The $div and $mod cells use truncating division semantics (rounding
towards 0), as defined by e.g. Verilog. Another rounding mode, flooring
(rounding towards negative infinity), can be used in e.g. VHDL. The
new $divfloor cell provides this flooring division.

This commit also fixes the handling of $div in opt_expr, which was
previously optimized as if it was $divfloor.
This commit is contained in:
Xiretza 2020-04-21 12:51:58 +02:00
parent 17163cf43a
commit edd8ff2c07
No known key found for this signature in database
GPG key ID: 17B78226F7139993
19 changed files with 213 additions and 24 deletions

View file

@ -997,6 +997,12 @@ endmodule
// --------------------------------------------------------
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
//-
//- $div (A, B, Y)
//-
//- Division with truncated result (rounded towards 0).
//-
module \$div (A, B, Y);
parameter A_SIGNED = 0;
@ -1053,6 +1059,43 @@ endmodule
// --------------------------------------------------------
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
//-
//- $divfloor (A, B, Y)
//-
//- Division with floored result (rounded towards negative infinity).
//-
module \$divfloor (A, B, Y);
parameter A_SIGNED = 0;
parameter B_SIGNED = 0;
parameter A_WIDTH = 0;
parameter B_WIDTH = 0;
parameter Y_WIDTH = 0;
input [A_WIDTH-1:0] A;
input [B_WIDTH-1:0] B;
output [Y_WIDTH-1:0] Y;
generate
if (A_SIGNED && B_SIGNED) begin:BLOCK1
localparam WIDTH =
A_WIDTH >= B_WIDTH && A_WIDTH >= Y_WIDTH ? A_WIDTH :
B_WIDTH >= A_WIDTH && B_WIDTH >= Y_WIDTH ? B_WIDTH : Y_WIDTH;
wire [WIDTH:0] A_buf, B_buf, N_buf;
assign A_buf = $signed(A);
assign B_buf = $signed(B);
assign N_buf = (A[A_WIDTH-1] == B[B_WIDTH-1]) || A == 0 ? A_buf : $signed(A_buf - (B[B_WIDTH-1] ? B_buf+1 : B_buf-1));
assign Y = $signed(N_buf) / $signed(B_buf);
end else begin:BLOCK2
assign Y = A / B;
end
endgenerate
endmodule
// --------------------------------------------------------
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
//-
//- $modfloor (A, B, Y)

View file

@ -506,6 +506,34 @@ module \$__div_mod_floor (A, B, Y, R);
assign R = (R_s != 0) && A_SIGNED && B_SIGNED && (A_buf[WIDTH-1] != B_buf[WIDTH-1]) ? $signed(B_buf) + $signed(R_s) : R_s;
endmodule
(* techmap_celltype = "$divfloor" *)
module _90_divfloor (A, B, Y);
parameter A_SIGNED = 0;
parameter B_SIGNED = 0;
parameter A_WIDTH = 1;
parameter B_WIDTH = 1;
parameter Y_WIDTH = 1;
(* force_downto *)
input [A_WIDTH-1:0] A;
(* force_downto *)
input [B_WIDTH-1:0] B;
(* force_downto *)
output [Y_WIDTH-1:0] Y;
\$__div_mod_floor #(
.A_SIGNED(A_SIGNED),
.B_SIGNED(B_SIGNED),
.A_WIDTH(A_WIDTH),
.B_WIDTH(B_WIDTH),
.Y_WIDTH(Y_WIDTH)
) div_mod (
.A(A),
.B(B),
.Y(Y)
);
endmodule
(* techmap_celltype = "$modfloor" *)
module _90_modfloor (A, B, Y);
parameter A_SIGNED = 0;