mirror of
				https://github.com/YosysHQ/yosys
				synced 2025-11-03 21:09:12 +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)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue