mirror of
https://github.com/YosysHQ/yosys
synced 2025-07-31 00:13:18 +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:
parent
17163cf43a
commit
edd8ff2c07
19 changed files with 213 additions and 24 deletions
|
@ -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)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue