Files
super6502/hw/efinix_fpga/ip/divider/divider.v
Byron Lathi 21e3a477c1 Update IP
2023-07-19 21:06:20 -07:00

391 lines
14 KiB
Verilog

// =============================================================================
// Generated by efx_ipmgr
// Version: 2023.1.150
// IP Version: 5.0
// =============================================================================
////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2013-2023 Efinix Inc. All rights reserved.
//
// This document contains proprietary information which is
// protected by copyright. All rights are reserved. This notice
// refers to original work by Efinix, Inc. which may be derivitive
// of other work distributed under license of the authors. In the
// case of derivative work, nothing in this notice overrides the
// original author's license agreement. Where applicable, the
// original license agreement is included in it's original
// unmodified form immediately below this header.
//
// WARRANTY DISCLAIMER.
// THE DESIGN, CODE, OR INFORMATION ARE PROVIDED “AS IS” AND
// EFINIX MAKES NO WARRANTIES, EXPRESS OR IMPLIED WITH
// RESPECT THERETO, AND EXPRESSLY DISCLAIMS ANY IMPLIED WARRANTIES,
// INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
// MERCHANTABILITY, NON-INFRINGEMENT AND FITNESS FOR A PARTICULAR
// PURPOSE. SOME STATES DO NOT ALLOW EXCLUSIONS OF AN IMPLIED
// WARRANTY, SO THIS DISCLAIMER MAY NOT APPLY TO LICENSEE.
//
// LIMITATION OF LIABILITY.
// NOTWITHSTANDING ANYTHING TO THE CONTRARY, EXCEPT FOR BODILY
// INJURY, EFINIX SHALL NOT BE LIABLE WITH RESPECT TO ANY SUBJECT
// MATTER OF THIS AGREEMENT UNDER TORT, CONTRACT, STRICT LIABILITY
// OR ANY OTHER LEGAL OR EQUITABLE THEORY (I) FOR ANY INDIRECT,
// SPECIAL, INCIDENTAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES OF ANY
// CHARACTER INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF
// GOODWILL, DATA OR PROFIT, WORK STOPPAGE, OR COMPUTER FAILURE OR
// MALFUNCTION, OR IN ANY EVENT (II) FOR ANY AMOUNT IN EXCESS, IN
// THE AGGREGATE, OF THE FEE PAID BY LICENSEE TO EFINIX HEREUNDER
// (OR, IF THE FEE HAS BEEN WAIVED, $100), EVEN IF EFINIX SHALL HAVE
// BEEN INFORMED OF THE POSSIBILITY OF SUCH DAMAGES. SOME STATES DO
// NOT ALLOW THE EXCLUSION OR LIMITATION OF INCIDENTAL OR
// CONSEQUENTIAL DAMAGES, SO THIS LIMITATION AND EXCLUSION MAY NOT
// APPLY TO LICENSEE.
//
////////////////////////////////////////////////////////////////////////////////
`define IP_UUID _80fa5e3b79ce4c76a6cd48724ad5bdd2
`define IP_NAME_CONCAT(a,b) a``b
`define IP_MODULE_NAME(name) `IP_NAME_CONCAT(name,`IP_UUID)
module divider (
input [15:0] numer,
input [15:0] denom,
input clken,
input clk,
input reset,
output [15:0] quotient,
output [15:0] remain,
output rfd
);
`IP_MODULE_NAME(divider) #(
.NREPRESENTATION ("UNSIGNED"),
.WIDTHN (16),
.WIDTHD (16),
.DREPRESENTATION ("UNSIGNED"),
.PIPELINE (1'b0),
.LATENCY (16)
) u_divider(
.numer ( numer ),
.denom ( denom ),
.clken ( clken ),
.clk ( clk ),
.reset ( reset ),
.quotient ( quotient ),
.remain ( remain ),
.rfd ( rfd )
);
endmodule
`timescale 1ns / 1ps
module `IP_MODULE_NAME(divider) (
clk,
reset,
numer,
denom,
quotient,
remain,
rfd,
clken
);
parameter WIDTHN = 8;
parameter WIDTHD = 8;
parameter LATENCY = 8;
parameter PIPELINE = 1;
parameter NREPRESENTATION = "UNSIGNED";
parameter DREPRESENTATION = "UNSIGNED";
parameter ENABLE_OUTREG = 0;
input clk;
input reset;
input clken;
input [(WIDTHN-1):0] numer;
input [(WIDTHD-1):0] denom;
//output
output reg rfd;
output reg [(WIDTHN-1):0] quotient;
output reg [(WIDTHD-1):0] remain;
wire [WIDTHN-1:0] numer_temp;
wire [WIDTHD-1:0] denom_temp;
wire sign_numer;
wire sign_denom;
wire [(WIDTHN-1):0] quotient_copy;
wire [(WIDTHD-1):0] remain_copy;
reg sign_quotient[LATENCY:0];
genvar i, j;
// Main operation
generate begin
if(NREPRESENTATION == "SIGNED") begin
assign numer_temp = (numer[(WIDTHN-1)] == 1'b1) ? (~numer + 1) : numer;
assign sign_numer = (numer[(WIDTHN-1)] == 1'b1) ? 1'b1 : 1'b0;
end
else begin
assign numer_temp = numer;
assign sign_numer = 1'b0;
end
if(DREPRESENTATION == "SIGNED") begin
assign denom_temp = (denom[(WIDTHD-1)] == 1'b1) ? (~denom + 1) : denom;
assign sign_denom = (denom[(WIDTHD-1)] == 1'b1) ? 1'b1 : 1'b0;
end
else begin
assign denom_temp = denom;
assign sign_denom = 1'b0;
end
always @* begin
sign_quotient[0] = sign_numer ^ sign_denom;
end
for (i=0; i<LATENCY; i=i+1) begin
always @(posedge clk or posedge reset) begin
if (reset) begin
sign_quotient[i+1] <= 1'b0;
end
else if(clken) begin
sign_quotient[i+1] <= sign_quotient[i];
end
end
end
if (PIPELINE) begin : pipeline
wire [(WIDTHN+1):0] sub[WIDTHN-1:0];
reg [WIDTHN-1:0] quotient_temp[WIDTHN:0];
reg [WIDTHN-1:0] remain_temp[WIDTHN:0];
reg [WIDTHN-1:0] denom_copy[WIDTHN:0];
always @* begin
rfd = 1'b0; //for PIPELINE enable, rfd is not used
denom_copy[0] = denom_temp;
remain_temp[0] = {WIDTHN{1'b0}};
quotient_temp[0] = numer_temp;
end
for (i=0; i<WIDTHN; i=i+1) begin
assign sub[i] = {remain_temp[i][(WIDTHN-2):0], quotient_temp[i][(WIDTHN-1)]} - denom_copy[i];
if (i < LATENCY) begin
always @(posedge clk or posedge reset) begin
if (reset) begin
remain_temp[i+1] <= {WIDTHN{1'b0}};
quotient_temp[i+1] <= {WIDTHN{1'b0}};
denom_copy[i+1] <= {WIDTHN{1'b0}};
end
else if(clken) begin
denom_copy[i+1] <= denom_copy[i];
if (sub[i][(WIDTHN)] == 0) begin
remain_temp[i+1] <= sub[i][(WIDTHN-1):0];
quotient_temp[i+1] <= {quotient_temp[i][(WIDTHN-2):0], 1'b1};
end
else begin
remain_temp[i+1] <= {remain_temp[i][(WIDTHN-2):0], quotient_temp[i][(WIDTHN-1)]};
quotient_temp[i+1] <= {quotient_temp[i][(WIDTHN-2):0], 1'b0};
end
end
end
end
else begin
always @* begin
denom_copy[i+1] = denom_copy[i];
end
always @* begin
if (sub[i][(WIDTHN)] == 0) begin
remain_temp[i+1] = sub[i][(WIDTHN-1):0];
end
else begin
remain_temp[i+1] = {remain_temp[i][(WIDTHN-2):0], quotient_temp[i][(WIDTHN-1)]};
end
end
always @* begin
if (sub[i][(WIDTHN)] == 0) begin
quotient_temp[i+1] = {quotient_temp[i][(WIDTHN-2):0], 1'b1};
end
else begin
quotient_temp[i+1] = {quotient_temp[i][(WIDTHN-2):0], 1'b0};
end
end
end
end
if (NREPRESENTATION == "SIGNED" || DREPRESENTATION == "SIGNED") begin
assign quotient_copy = sign_quotient[LATENCY] ? (~quotient_temp[WIDTHN] + 1) : quotient_temp[WIDTHN];
end
else begin
assign quotient_copy = quotient_temp[WIDTHN];
end
assign remain_copy = remain_temp[WIDTHN];
end
else begin : non_pipeline
localparam COMBI_STAGE = WIDTHN - LATENCY;
wire [(WIDTHN-1):0] denom_sub;
reg [WIDTHN-1:0] denom_reg;
reg [(WIDTHN-1):0] quotient_reg;
reg [(WIDTHN-1):0] remain_reg;
wire [(WIDTHN+1):0] sub;
reg [(WIDTHN-1):0] quotient_combi[COMBI_STAGE:0];
reg [WIDTHN-1:0] remain_combi[COMBI_STAGE:0];
wire [(WIDTHN+1):0] sub_combi[COMBI_STAGE:0];
reg clken_IP;
assign denom_sub = {{(WIDTHN-WIDTHD){1'b0}},denom_temp};
always @(posedge clk,posedge reset) begin
if(reset) begin
clken_IP <= 1'b0;
end
else begin
clken_IP <= clken;
end
end
if(LATENCY > 0) begin
reg [LATENCY-1:0] ready;
assign sub = (ready[0] || ~clken_IP) ? ({{(WIDTHN-2){1'b0}}, numer_temp[(WIDTHN-1)]} - denom_sub) : ({remain_reg[(WIDTHN-2):0], quotient_reg[(WIDTHN-1)]} - denom_reg);
always @(posedge clk,posedge reset) begin
if(reset) begin
ready <= {LATENCY{1'b0}};
end
else if(clken) begin
if(ready[0] || ~clken_IP) begin
ready <= {1'b1, {LATENCY-1{1'b0}}};
end
else begin
ready <= {1'b0, ready[LATENCY-1:1]};
end
end
else begin
ready <= {LATENCY{1'b0}};
end
end
always @(posedge clk,posedge reset) begin
if(reset) begin
remain_reg <= {WIDTHN{1'b0}};
quotient_reg <= {WIDTHN{1'b0}};
denom_reg <= {WIDTHN{1'b0}};
end
else if(clken) begin
if(ready[0] || ~clken_IP) begin
denom_reg <= denom_temp;
if (sub[(WIDTHN)] == 0) begin
remain_reg <= sub[(WIDTHN-1):0];
quotient_reg <= {numer_temp[(WIDTHN-2):0], 1'b1};
end
else begin
remain_reg <= {{(WIDTHN-2){1'b0}}, numer_temp[(WIDTHN-1)]};
quotient_reg <= {numer_temp[(WIDTHN-2):0], 1'b0};
end
end
else begin
if (sub[(WIDTHN)] == 0) begin
remain_reg <= sub[(WIDTHN-1):0];
quotient_reg <= {quotient_reg[(WIDTHN-2):0], 1'b1};
end
else begin
remain_reg <= {remain_reg[(WIDTHN-2):0], quotient_reg[(WIDTHN-1)]};
quotient_reg <= {quotient_reg[(WIDTHN-2):0], 1'b0};
end
end
end
end
if (ENABLE_OUTREG) begin
always @(posedge clk,posedge reset) begin
if (reset) begin
rfd <= 1'b0;
end
else begin
rfd <= ready[0];
end
end
end
else begin
always @* begin
rfd = ready[0];
end
end
always @* begin
quotient_combi[0] = quotient_reg;
remain_combi[0] = remain_reg;
end
for (i=0; i<COMBI_STAGE; i=i+1) begin
assign sub_combi[i] = {remain_combi[i][(WIDTHN-2):0], quotient_combi[i][(WIDTHN-1)]} - denom_reg;
end
end
else begin
always @* begin
rfd = 1'b1;
end
always @* begin
quotient_combi[0] = numer_temp;
remain_combi[0] = {WIDTHN{1'b0}};
end
for (i=0; i<COMBI_STAGE; i=i+1) begin
assign sub_combi[i] = {remain_combi[i][(WIDTHN-2):0], quotient_combi[i][(WIDTHN-1)]} - denom_sub;
end
end
for (i=0; i<COMBI_STAGE; i=i+1) begin
always @* begin
if(sub_combi[i][(WIDTHN)] == 0) begin
remain_combi [i+1] = sub_combi[i][(WIDTHN-1):0];
quotient_combi [i+1] = {quotient_combi[i][(WIDTHN-2):0], 1'b1};
end
else begin
remain_combi[i+1] = {remain_combi[i][(WIDTHN-2):0], quotient_combi[i][(WIDTHN-1)]};
quotient_combi[i+1] = {quotient_combi[i][(WIDTHN-2):0], 1'b0};
end
end
end
if(NREPRESENTATION == "SIGNED" || DREPRESENTATION == "SIGNED") begin
assign quotient_copy = sign_quotient[LATENCY] ? (~quotient_combi[COMBI_STAGE] + 1): quotient_combi[COMBI_STAGE];//
end
else begin
assign quotient_copy = quotient_combi[COMBI_STAGE];
end
assign remain_copy = remain_combi[COMBI_STAGE];
end
if (ENABLE_OUTREG) begin
always @(posedge clk or posedge reset) begin
if (reset) begin
quotient <= {WIDTHN{1'b0}};
remain <= {WIDTHD{1'b0}};
end
else begin
quotient <= quotient_copy;
remain <= remain_copy;
end
end
end
else begin
always @* begin
quotient = quotient_copy;
remain = remain_copy;
end
end
end
endgenerate
endmodule
`undef IP_UUID
`undef IP_NAME_CONCAT
`undef IP_MODULE_NAME