yosys/techlibs/nexus/cells_sim.v

1059 lines
24 KiB
Verilog

(* abc9_lut=1, lib_whitebox *)
module LUT4(input A, B, C, D, output Z);
parameter INIT = "0x0000";
`include "parse_init.vh"
localparam initp = parse_init(INIT);
wire [7:0] s3 = D ? initp[15:8] : initp[7:0];
wire [3:0] s2 = C ? s3[ 7:4] : s3[3:0];
wire [1:0] s1 = B ? s2[ 3:2] : s2[1:0];
assign Z = A ? s1[1] : s1[0];
// Per-input delay differences are considered 'interconnect'
// so not known yet
specify
(A => Z) = 233;
(B => Z) = 233;
(C => Z) = 233;
(D => Z) = 233;
endspecify
endmodule
// This is a placeholder for ABC9 to extract the area/delay
// cost of 5-input LUTs and is not intended to be instantiated
(* abc9_lut=2 *)
module \$__ABC9_LUT5 (input SEL, D, C, B, A, output Z);
specify
(SEL => Z) = 171;
(D => Z) = 303;
(C => Z) = 311;
(B => Z) = 309;
(A => Z) = 306;
endspecify
endmodule
// Two LUT4s and MUX2
module WIDEFN9(input A0, B0, C0, D0, A1, B1, C1, D1, SEL, output Z);
parameter INIT0 = "0x0000";
parameter INIT1 = "0x0000";
wire z0, z1;
LUT4 #(.INIT(INIT0)) lut4_0 (.A(A0), .B(B0), .C(C0), .D(D0), .Z(z0));
LUT4 #(.INIT(INIT1)) lut4_1 (.A(A1), .B(B1), .C(C1), .D(D1), .Z(z1));
assign Z = SEL ? z1 : z0;
endmodule
(* abc9_box, lib_whitebox *)
module INV(input A, output Z);
assign Z = !A;
specify
(A => Z) = 10;
endspecify
endmodule
// Bidirectional IO buffer
module BB(input T, I, output O,
(* iopad_external_pin *) inout B);
assign B = T ? 1'bz : O;
assign I = B;
endmodule
// Input buffer
module IB(
(* iopad_external_pin *) input I,
output O);
assign O = I;
endmodule
// Output buffer
module OB(input I,
(* iopad_external_pin *) output O);
assign O = I;
endmodule
// Output buffer with tristate
module OBZ(input I, T,
(* iopad_external_pin *) output O);
assign O = T ? 1'bz : I;
endmodule
// Constants
module VLO(output Z);
assign Z = 1'b0;
endmodule
module VHI(output Z);
assign Z = 1'b1;
endmodule
// Vendor flipflops
// (all have active high clock, enable and set/reset - use INV to invert)
// Async preset
(* abc9_box, lib_whitebox *)
module FD1P3BX(input D, CK, SP, PD, output reg Q);
parameter GSR = "DISABLED";
initial Q = 1'b1;
always @(posedge CK or posedge PD)
if (PD)
Q <= 1'b1;
else if (SP)
Q <= D;
specify
$setup(D, posedge CK, 0);
$setup(SP, posedge CK, 212);
$setup(PD, posedge CK, 224);
`ifndef YOSYS
if (PD) (posedge CLK => (Q : 1)) = 0;
`else
if (PD) (PD => Q) = 0; // Technically, this should be an edge sensitive path
// but for facilitating a bypass box, let's pretend it's
// a simple path
`endif
if (!PD && SP) (posedge CK => (Q : D)) = 336;
endspecify
endmodule
// Async clear
(* abc9_box, lib_whitebox *)
module FD1P3DX(input D, CK, SP, CD, output reg Q);
parameter GSR = "DISABLED";
initial Q = 1'b0;
always @(posedge CK or posedge CD)
if (CD)
Q <= 1'b0;
else if (SP)
Q <= D;
specify
$setup(D, posedge CK, 0);
$setup(SP, posedge CK, 212);
$setup(CD, posedge CK, 224);
`ifndef YOSYS
if (CD) (posedge CLK => (Q : 0)) = 0;
`else
if (CD) (CD => Q) = 0; // Technically, this should be an edge sensitive path
// but for facilitating a bypass box, let's pretend it's
// a simple path
`endif
if (!CD && SP) (posedge CK => (Q : D)) = 336;
endspecify
endmodule
// Sync clear
(* abc9_flop, lib_whitebox *)
module FD1P3IX(input D, CK, SP, CD, output reg Q);
parameter GSR = "DISABLED";
initial Q = 1'b0;
always @(posedge CK)
if (CD)
Q <= 1'b0;
else if (SP)
Q <= D;
specify
$setup(D, posedge CK, 0);
$setup(SP, posedge CK, 212);
$setup(CD, posedge CK, 224);
if (!CD && SP) (posedge CK => (Q : D)) = 336;
endspecify
endmodule
// Sync preset
(* abc9_flop, lib_whitebox *)
module FD1P3JX(input D, CK, SP, PD, output reg Q);
parameter GSR = "DISABLED";
initial Q = 1'b1;
always @(posedge CK)
if (PD)
Q <= 1'b1;
else if (SP)
Q <= D;
specify
$setup(D, posedge CK, 0);
$setup(SP, posedge CK, 212);
$setup(PD, posedge CK, 224);
if (!PD && SP) (posedge CK => (Q : D)) = 336;
endspecify
endmodule
// LUT4 with LUT3 tap for CCU2 use only
(* lib_whitebox *)
module LUT4_3(input A, B, C, D, output Z, Z3);
parameter INIT = "0x0000";
`include "parse_init.vh"
localparam initp = parse_init(INIT);
wire [7:0] s3 = D ? initp[15:8] : initp[7:0];
wire [3:0] s2 = C ? s3[ 7:4] : s3[3:0];
wire [1:0] s1 = B ? s2[ 3:2] : s2[1:0];
assign Z = A ? s1[1] : s1[0];
wire [3:0] s2_3 = C ? initp[ 7:4] : initp[3:0];
wire [1:0] s1_3 = B ? s2_3[ 3:2] : s2_3[1:0];
assign Z3 = A ? s1_3[1] : s1_3[0];
endmodule
// Carry primitive (incoporating two LUTs)
(* abc9_box, lib_whitebox *)
module CCU2(
(* abc9_carry *) input CIN,
input A1, B1, C1, D1, A0, B0, C0, D0,
output S1, S0,
(* abc9_carry *) output COUT);
parameter INJECT = "YES";
parameter INIT0 = "0x0000";
parameter INIT1 = "0x1111";
localparam inject_p = (INJECT == "YES") ? 1'b1 : 1'b0;
wire LUT3_0, LUT4_0, LUT3_1, LUT4_1, carry_0;
LUT4_3 #(.INIT(INIT0)) lut0 (.A(A0), .B(B0), .C(C0), .D(D0), .Z(LUT4_0), .Z3(LUT3_0));
LUT4_3 #(.INIT(INIT1)) lut1 (.A(A1), .B(B1), .C(C1), .D(D1), .Z(LUT4_1), .Z3(LUT3_1));
assign S0 = LUT4_0 ^ (CIN & ~inject_p);
assign carry_0 = LUT4_0 ? CIN : (LUT3_0 & ~inject_p);
assign S1 = LUT4_1 ^ (carry_0 & ~inject_p);
assign COUT = LUT4_1 ? carry_0 : (LUT3_1 & ~inject_p);
specify
(A0 => S0) = 233;
(B0 => S0) = 233;
(C0 => S0) = 233;
(D0 => S0) = 233;
(CIN => S0) = 228;
(A0 => S1) = 481;
(B0 => S1) = 481;
(C0 => S1) = 481;
(D0 => S1) = 481;
(A1 => S1) = 233;
(B1 => S1) = 233;
(C1 => S1) = 233;
(D1 => S1) = 233;
(CIN => S1) = 307;
(A0 => COUT) = 347;
(B0 => COUT) = 347;
(C0 => COUT) = 347;
(D0 => COUT) = 347;
(A1 => COUT) = 347;
(B1 => COUT) = 347;
(C1 => COUT) = 347;
(D1 => COUT) = 347;
(CIN => COUT) = 59;
endspecify
endmodule
// Packed flipflop
module OXIDE_FF(input CLK, LSR, CE, DI, M, output reg Q);
parameter GSR = "ENABLED";
parameter [127:0] CEMUX = "1";
parameter CLKMUX = "CLK";
parameter LSRMUX = "LSR";
parameter REGDDR = "DISABLED";
parameter SRMODE = "LSR_OVER_CE";
parameter REGSET = "RESET";
parameter [127:0] LSRMODE = "LSR";
wire muxce;
generate
case (CEMUX)
"1": assign muxce = 1'b1;
"0": assign muxce = 1'b0;
"INV": assign muxce = ~CE;
default: assign muxce = CE;
endcase
endgenerate
wire muxlsr = (LSRMUX == "INV") ? ~LSR : LSR;
wire muxclk = (CLKMUX == "INV") ? ~CLK : CLK;
wire srval;
generate
if (LSRMODE == "PRLD")
assign srval = M;
else
assign srval = (REGSET == "SET") ? 1'b1 : 1'b0;
endgenerate
initial Q = srval;
generate
if (REGDDR == "ENABLED") begin
if (SRMODE == "ASYNC") begin
always @(posedge muxclk, negedge muxclk, posedge muxlsr)
if (muxlsr)
Q <= srval;
else if (muxce)
Q <= DI;
end else begin
always @(posedge muxclk, negedge muxclk)
if (muxlsr)
Q <= srval;
else if (muxce)
Q <= DI;
end
end else begin
if (SRMODE == "ASYNC") begin
always @(posedge muxclk, posedge muxlsr)
if (muxlsr)
Q <= srval;
else if (muxce)
Q <= DI;
end else begin
always @(posedge muxclk)
if (muxlsr)
Q <= srval;
else if (muxce)
Q <= DI;
end
end
endgenerate
endmodule
// Packed combinational logic (for post-pnr sim)
module OXIDE_COMB(
input A, B, C, D, // LUT inputs
input SEL, // mux select input
input F1, // output from LUT 1 for mux
input FCI, // carry input
input WAD0, WAD1, WAD2, WAD3, // LUTRAM write address inputs
input WD, // LUTRAM write data input
input WCK, WRE, // LUTRAM write clock and enable
output F, // LUT/carry output
output OFX // mux output
);
parameter MODE = "LOGIC"; // LOGIC, CCU2, DPRAM
parameter [15:0] INIT = 16'h0000;
parameter INJECT = "YES";
localparam inject_p = (INJECT == "YES") ? 1'b1 : 1'b0;
reg [15:0] lut = INIT;
wire [7:0] s3 = D ? INIT[15:8] : INIT[7:0];
wire [3:0] s2 = C ? s3[ 7:4] : s3[3:0];
wire [1:0] s1 = B ? s2[ 3:2] : s2[1:0];
wire Z = A ? s1[1] : s1[0];
wire [3:0] s2_3 = C ? INIT[ 7:4] : INIT[3:0];
wire [1:0] s1_3 = B ? s2_3[ 3:2] : s2_3[1:0];
wire Z3 = A ? s1_3[1] : s1_3[0];
generate
if (MODE == "DPRAM") begin
always @(posedge WCK)
if (WRE)
lut[{WAD3, WAD2, WAD1, WAD0}] <= WD;
end
if (MODE == "CCU2") begin
assign F = Z ^ (FCI & ~inject_p);
assign FCO = Z ? FCI : (Z3 & ~inject_p);
end else begin
assign F = Z;
end
endgenerate
assign OFX = SEL ? F1 : F;
endmodule
// LUTRAM
module DPR16X4(
input [3:0] RAD, DI, WAD,
input WRE, WCK,
output [3:0] DO
);
parameter INITVAL = "0x0000000000000000";
`include "parse_init.vh"
localparam [63:0] parsed_init = parse_init_64(INITVAL);
reg [3:0] mem[0:15];
integer i;
initial begin
for (i = 0; i < 15; i++)
mem[i] = parsed_init[i * 4 +: 4];
end
always @(posedge WCK)
if (WRE)
mem[WAD] <= DI;
assign DO = mem[RAD];
endmodule
// Used for all the DSP models to reduce duplication
module OXIDE_DSP_REG #(
parameter W = 18,
parameter USED = "REGISTER",
parameter RESETMODE = "SYNC"
) (
input CLK, CE, RST,
input [W-1:0] D,
output reg [W-1:0] Q
);
generate
if (USED == "BYPASS")
always @* Q = D;
else if (USED == "REGISTER") begin
initial Q = 0;
if (RESETMODE == "ASYNC")
always @(posedge CLK, posedge RST) begin
if (RST)
Q <= 0;
else if (CE)
Q <= D;
end
else if (RESETMODE == "SYNC")
always @(posedge CLK) begin
if (RST)
Q <= 0;
else if (CE)
Q <= D;
end
end
endgenerate
endmodule
module OXIDE_DSP_SIM #(
// User facing parameters
parameter REGINPUTA = "BYPASS",
parameter REGINPUTB = "BYPASS",
parameter REGINPUTC = "BYPASS",
parameter REGADDSUB = "BYPASS",
parameter REGLOADC = "BYPASS",
parameter REGLOADC2 = "BYPASS",
parameter REGCIN = "BYPASS",
parameter REGPIPELINE = "BYPASS",
parameter REGOUTPUT = "BYPASS",
parameter GSR = "ENABLED",
parameter RESETMODE = "SYNC",
// Internally used parameters
parameter A_WIDTH = 36,
parameter B_WIDTH = 36,
parameter C_WIDTH = 36,
parameter Z_WIDTH = 72,
parameter PREADD_USED = 0,
parameter ADDSUB_USED = 0
) (
input [A_WIDTH-1:0] A,
input [B_WIDTH-1:0] B,
input [C_WIDTH-1:0] C,
input SIGNEDA,
input SIGNEDB,
input SIGNEDC,
input CIN,
input LOADC,
input ADDSUB,
input CLK,
input CEA, CEB, CEC, CEPIPE, CECTRL, CECIN, CEOUT,
input RSTA, RSTB, RSTC, RSTPIPE, RSTCTRL, RSTCIN, RSTOUT,
output wire [Z_WIDTH-1:0] Z
);
localparam M_WIDTH = (A_WIDTH+B_WIDTH);
/******** REGISTERS ********/
wire [M_WIDTH-1:0] pipe_d, pipe_q;
wire [Z_WIDTH-1:0] z_d;
wire [A_WIDTH-1:0] a_r;
wire [B_WIDTH-1:0] b_r;
wire [C_WIDTH-1:0] c_r, c_r2;
wire asgd_r, bsgd_r, csgd_r, csgd_r2;
wire addsub_r, addsub_r2, cin_r, cin_r2, sgd_r, sgd_r2;
wire loadc_r, loadc_r2;
OXIDE_DSP_REG #(A_WIDTH+1, REGINPUTA, RESETMODE) a_reg(CLK, CEA, RSTA, {SIGNEDA, A}, {asgd_r, a_r});
OXIDE_DSP_REG #(B_WIDTH+1, REGINPUTB, RESETMODE) b_reg(CLK, CEB, RSTB, {SIGNEDB, B}, {bsgd_r, b_r});
OXIDE_DSP_REG #(C_WIDTH+1, REGINPUTC, RESETMODE) c_reg(CLK, CEC, RSTC, {SIGNEDC, C}, {csgd_r, c_r});
OXIDE_DSP_REG #(M_WIDTH, REGPIPELINE, RESETMODE) pipe_reg(CLK, CEPIPE, RSTPIPE, pipe_d, pipe_q);
OXIDE_DSP_REG #(2, REGADDSUB, RESETMODE) addsub_reg(CLK, CECTRL, RSTCTRL, {SIGNEDA, ADDSUB}, {sgd_r, addsub_r});
OXIDE_DSP_REG #(1, REGLOADC, RESETMODE) loadc_reg(CLK, CECTRL, RSTCTRL, LOADC, loadc_r);
OXIDE_DSP_REG #(2, REGPIPELINE, RESETMODE) addsub2_reg(CLK, CECTRL, RSTCTRL, {sgd_r, addsub_r}, {sgd_r2, addsub_r2});
OXIDE_DSP_REG #(1, REGLOADC2, RESETMODE) loadc2_reg(CLK, CECTRL, RSTCTRL, loadc_r, loadc_r2);
OXIDE_DSP_REG #(1, REGCIN, RESETMODE) cin_reg(CLK, CECIN, RSTCIN, CIN, cin_r);
OXIDE_DSP_REG #(1, REGPIPELINE, RESETMODE) cin2_reg(CLK, CECIN, RSTCIN, cin_r, cin_r2);
OXIDE_DSP_REG #(C_WIDTH+1, REGPIPELINE, RESETMODE) c2_reg(CLK, CEC, RSTC, {csgd_r, c_r}, {csgd_r2, c_r2});
OXIDE_DSP_REG #(Z_WIDTH, REGOUTPUT, RESETMODE) z_reg(CLK, CEOUT, RSTOUT, z_d, Z);
/******** PREADDER ********/
wire [B_WIDTH-1:0] mult_b;
wire mult_b_sgd;
generate
if (PREADD_USED) begin
assign mult_b = (b_r + c_r);
assign mult_b_sgd = (bsgd_r | csgd_r);
end else begin
assign mult_b = b_r;
assign mult_b_sgd = bsgd_r;
end
endgenerate
/******** MULTIPLIER ********/
// sign extend operands if needed
wire [M_WIDTH-1:0] mult_a_ext = {{(M_WIDTH-A_WIDTH){asgd_r ? a_r[A_WIDTH-1] : 1'b0}}, a_r};
wire [M_WIDTH-1:0] mult_b_ext = {{(M_WIDTH-B_WIDTH){mult_b_sgd ? mult_b[B_WIDTH-1] : 1'b0}}, mult_b};
wire [M_WIDTH-1:0] mult_m = mult_a_ext * mult_b_ext;
/******** ACCUMULATOR ********/
wire [Z_WIDTH-1:0] m_ext;
generate
if (ADDSUB_USED) begin
assign pipe_d = mult_m;
assign m_ext = {{(Z_WIDTH-M_WIDTH){sgd_r2 ? pipe_q[M_WIDTH-1] : 1'b0}}, pipe_q};
assign z_d = (loadc_r2 ? c_r2 : Z) + cin_r2 + (addsub_r2 ? -m_ext : m_ext);
end else begin
assign z_d = mult_m;
end
endgenerate
endmodule
module MULT9X9 #(
parameter REGINPUTA = "REGISTER",
parameter REGINPUTB = "REGISTER",
parameter REGOUTPUT = "REGISTER",
parameter GSR = "ENABLED",
parameter RESETMODE = "SYNC"
) (
input [8:0] A,
input [8:0] B,
input CLK,
input CEA,
input RSTA,
input CEB,
input RSTB,
input SIGNEDA,
input SIGNEDB,
input RSTOUT,
input CEOUT,
output [17:0] Z
);
OXIDE_DSP_SIM #(
.REGINPUTA(REGINPUTA),
.REGINPUTB(REGINPUTB),
.REGOUTPUT(REGOUTPUT),
.GSR(GSR),
.RESETMODE(RESETMODE),
.A_WIDTH(9),
.B_WIDTH(9),
.Z_WIDTH(18),
.PREADD_USED(0),
.ADDSUB_USED(0)
) dsp_i (
.A(A), .B(B),
.CLK(CLK),
.CEA(CEA), .RSTA(RSTA),
.CEB(CEB), .RSTB(RSTB),
.SIGNEDA(SIGNEDA), .SIGNEDB(SIGNEDB),
.RSTOUT(RSTOUT), .CEOUT(CEOUT),
.Z(Z)
);
endmodule
module MULT18X18 #(
parameter REGINPUTA = "REGISTER",
parameter REGINPUTB = "REGISTER",
parameter REGOUTPUT = "REGISTER",
parameter GSR = "ENABLED",
parameter RESETMODE = "SYNC"
) (
input [17:0] A,
input [17:0] B,
input CLK,
input CEA,
input RSTA,
input CEB,
input RSTB,
input SIGNEDA,
input SIGNEDB,
input RSTOUT,
input CEOUT,
output [35:0] Z
);
OXIDE_DSP_SIM #(
.REGINPUTA(REGINPUTA),
.REGINPUTB(REGINPUTB),
.REGOUTPUT(REGOUTPUT),
.GSR(GSR),
.RESETMODE(RESETMODE),
.A_WIDTH(18),
.B_WIDTH(18),
.Z_WIDTH(36),
.PREADD_USED(0),
.ADDSUB_USED(0)
) dsp_i (
.A(A), .B(B),
.CLK(CLK),
.CEA(CEA), .RSTA(RSTA),
.CEB(CEB), .RSTB(RSTB),
.SIGNEDA(SIGNEDA), .SIGNEDB(SIGNEDB),
.RSTOUT(RSTOUT), .CEOUT(CEOUT),
.Z(Z)
);
endmodule
module MULT18X36 #(
parameter REGINPUTA = "REGISTER",
parameter REGINPUTB = "REGISTER",
parameter REGOUTPUT = "REGISTER",
parameter GSR = "ENABLED",
parameter RESETMODE = "SYNC"
) (
input [17:0] A,
input [35:0] B,
input CLK,
input CEA,
input RSTA,
input CEB,
input RSTB,
input SIGNEDA,
input SIGNEDB,
input RSTOUT,
input CEOUT,
output [53:0] Z
);
OXIDE_DSP_SIM #(
.REGINPUTA(REGINPUTA),
.REGINPUTB(REGINPUTB),
.REGOUTPUT(REGOUTPUT),
.GSR(GSR),
.RESETMODE(RESETMODE),
.A_WIDTH(18),
.B_WIDTH(36),
.Z_WIDTH(54),
.PREADD_USED(0),
.ADDSUB_USED(0)
) dsp_i (
.A(A), .B(B),
.CLK(CLK),
.CEA(CEA), .RSTA(RSTA),
.CEB(CEB), .RSTB(RSTB),
.SIGNEDA(SIGNEDA), .SIGNEDB(SIGNEDB),
.RSTOUT(RSTOUT), .CEOUT(CEOUT),
.Z(Z)
);
endmodule
module MULT36X36 #(
parameter REGINPUTA = "REGISTER",
parameter REGINPUTB = "REGISTER",
parameter REGOUTPUT = "REGISTER",
parameter GSR = "ENABLED",
parameter RESETMODE = "SYNC"
) (
input [35:0] A,
input [35:0] B,
input CLK,
input CEA,
input RSTA,
input CEB,
input RSTB,
input SIGNEDA,
input SIGNEDB,
input RSTOUT,
input CEOUT,
output [71:0] Z
);
OXIDE_DSP_SIM #(
.REGINPUTA(REGINPUTA),
.REGINPUTB(REGINPUTB),
.REGOUTPUT(REGOUTPUT),
.GSR(GSR),
.RESETMODE(RESETMODE),
.A_WIDTH(36),
.B_WIDTH(36),
.Z_WIDTH(72),
.PREADD_USED(0),
.ADDSUB_USED(0)
) dsp_i (
.A(A), .B(B),
.CLK(CLK),
.CEA(CEA), .RSTA(RSTA),
.CEB(CEB), .RSTB(RSTB),
.SIGNEDA(SIGNEDA), .SIGNEDB(SIGNEDB),
.RSTOUT(RSTOUT), .CEOUT(CEOUT),
.Z(Z)
);
endmodule
module MULTPREADD9X9 #(
parameter REGINPUTA = "REGISTER",
parameter REGINPUTB = "REGISTER",
parameter REGINPUTC = "REGISTER",
parameter REGOUTPUT = "REGISTER",
parameter GSR = "ENABLED",
parameter RESETMODE = "SYNC"
) (
input [8:0] A,
input [8:0] B,
input [8:0] C,
input CLK,
input CEA,
input RSTA,
input CEB,
input RSTB,
input CEC,
input RSTC,
input SIGNEDA,
input SIGNEDB,
input SIGNEDC,
input RSTOUT,
input CEOUT,
output [17:0] Z
);
OXIDE_DSP_SIM #(
.REGINPUTA(REGINPUTA),
.REGINPUTB(REGINPUTB),
.REGINPUTC(REGINPUTC),
.REGOUTPUT(REGOUTPUT),
.GSR(GSR),
.RESETMODE(RESETMODE),
.A_WIDTH(9),
.B_WIDTH(9),
.C_WIDTH(9),
.Z_WIDTH(18),
.PREADD_USED(1),
.ADDSUB_USED(0)
) dsp_i (
.A(A), .B(B), .C(C),
.CLK(CLK),
.CEA(CEA), .RSTA(RSTA),
.CEB(CEB), .RSTB(RSTB),
.CEC(CEC), .RSTC(RSTC),
.SIGNEDA(SIGNEDA), .SIGNEDB(SIGNEDB), .SIGNEDC(SIGNEDC),
.RSTOUT(RSTOUT), .CEOUT(CEOUT),
.Z(Z)
);
endmodule
module MULTPREADD18X18 #(
parameter REGINPUTA = "REGISTER",
parameter REGINPUTB = "REGISTER",
parameter REGINPUTC = "REGISTER",
parameter REGOUTPUT = "REGISTER",
parameter GSR = "ENABLED",
parameter RESETMODE = "SYNC"
) (
input [17:0] A,
input [17:0] B,
input [17:0] C,
input CLK,
input CEA,
input RSTA,
input CEB,
input RSTB,
input CEC,
input RSTC,
input SIGNEDA,
input SIGNEDB,
input SIGNEDC,
input RSTOUT,
input CEOUT,
output [35:0] Z
);
OXIDE_DSP_SIM #(
.REGINPUTA(REGINPUTA),
.REGINPUTB(REGINPUTB),
.REGINPUTC(REGINPUTC),
.REGOUTPUT(REGOUTPUT),
.GSR(GSR),
.RESETMODE(RESETMODE),
.A_WIDTH(18),
.B_WIDTH(18),
.C_WIDTH(18),
.Z_WIDTH(36),
.PREADD_USED(1),
.ADDSUB_USED(0)
) dsp_i (
.A(A), .B(B), .C(C),
.CLK(CLK),
.CEA(CEA), .RSTA(RSTA),
.CEB(CEB), .RSTB(RSTB),
.CEC(CEC), .RSTC(RSTC),
.SIGNEDA(SIGNEDA), .SIGNEDB(SIGNEDB), .SIGNEDC(SIGNEDC),
.RSTOUT(RSTOUT), .CEOUT(CEOUT),
.Z(Z)
);
endmodule
module MULTADDSUB18X18 #(
parameter REGINPUTA = "REGISTER",
parameter REGINPUTB = "REGISTER",
parameter REGINPUTC = "REGISTER",
parameter REGADDSUB = "REGISTER",
parameter REGLOADC = "REGISTER",
parameter REGLOADC2 = "REGISTER",
parameter REGCIN = "REGISTER",
parameter REGPIPELINE = "REGISTER",
parameter REGOUTPUT = "REGISTER",
parameter GSR = "ENABLED",
parameter RESETMODE = "SYNC"
) (
input [17:0] A,
input [17:0] B,
input [53:0] C,
input CLK,
input CEA,
input RSTA,
input CEB,
input RSTB,
input CEC,
input RSTC,
input SIGNED,
input RSTPIPE,
input CEPIPE,
input RSTCTRL,
input CECTRL,
input RSTCIN,
input CECIN,
input LOADC,
input ADDSUB,
output [53:0] Z,
input RSTOUT,
input CEOUT,
input CIN
);
OXIDE_DSP_SIM #(
.REGINPUTA(REGINPUTA),
.REGINPUTB(REGINPUTB),
.REGINPUTC(REGINPUTC),
.REGADDSUB(REGADDSUB),
.REGLOADC(REGLOADC),
.REGLOADC2(REGLOADC2),
.REGCIN(REGCIN),
.REGPIPELINE(REGPIPELINE),
.REGOUTPUT(REGOUTPUT),
.GSR(GSR),
.RESETMODE(RESETMODE),
.A_WIDTH(18),
.B_WIDTH(18),
.C_WIDTH(54),
.Z_WIDTH(54),
.PREADD_USED(0),
.ADDSUB_USED(1)
) dsp_i (
.A(A), .B(B), .C(C),
.CLK(CLK),
.CEA(CEA), .RSTA(RSTA),
.CEB(CEB), .RSTB(RSTB),
.CEC(CEC), .RSTC(RSTC),
.CEPIPE(CEPIPE), .RSTPIPE(RSTPIPE),
.CECTRL(CECTRL), .RSTCTRL(RSTCTRL),
.CECIN(CECIN), .RSTCIN(RSTCIN),
.CIN(CIN), .LOADC(LOADC), .ADDSUB(ADDSUB),
.SIGNEDA(SIGNED), .SIGNEDB(SIGNED), .SIGNEDC(SIGNED),
.RSTOUT(RSTOUT), .CEOUT(CEOUT),
.Z(Z)
);
endmodule
module MULTADDSUB36X36 #(
parameter REGINPUTA = "REGISTER",
parameter REGINPUTB = "REGISTER",
parameter REGINPUTC = "REGISTER",
parameter REGADDSUB = "REGISTER",
parameter REGLOADC = "REGISTER",
parameter REGLOADC2 = "REGISTER",
parameter REGCIN = "REGISTER",
parameter REGPIPELINE = "REGISTER",
parameter REGOUTPUT = "REGISTER",
parameter GSR = "ENABLED",
parameter RESETMODE = "SYNC"
) (
input [35:0] A,
input [35:0] B,
input [107:0] C,
input CLK,
input CEA,
input RSTA,
input CEB,
input RSTB,
input CEC,
input RSTC,
input SIGNED,
input RSTPIPE,
input CEPIPE,
input RSTCTRL,
input CECTRL,
input RSTCIN,
input CECIN,
input LOADC,
input ADDSUB,
output [107:0] Z,
input RSTOUT,
input CEOUT,
input CIN
);
OXIDE_DSP_SIM #(
.REGINPUTA(REGINPUTA),
.REGINPUTB(REGINPUTB),
.REGINPUTC(REGINPUTC),
.REGADDSUB(REGADDSUB),
.REGLOADC(REGLOADC),
.REGLOADC2(REGLOADC2),
.REGCIN(REGCIN),
.REGPIPELINE(REGPIPELINE),
.REGOUTPUT(REGOUTPUT),
.GSR(GSR),
.RESETMODE(RESETMODE),
.A_WIDTH(36),
.B_WIDTH(36),
.C_WIDTH(108),
.Z_WIDTH(108),
.PREADD_USED(0),
.ADDSUB_USED(1)
) dsp_i (
.A(A), .B(B), .C(C),
.CLK(CLK),
.CEA(CEA), .RSTA(RSTA),
.CEB(CEB), .RSTB(RSTB),
.CEC(CEC), .RSTC(RSTC),
.CEPIPE(CEPIPE), .RSTPIPE(RSTPIPE),
.CECTRL(CECTRL), .RSTCTRL(RSTCTRL),
.CECIN(CECIN), .RSTCIN(RSTCIN),
.CIN(CIN), .LOADC(LOADC), .ADDSUB(ADDSUB),
.SIGNEDA(SIGNED), .SIGNEDB(SIGNED), .SIGNEDC(SIGNED),
.RSTOUT(RSTOUT), .CEOUT(CEOUT),
.Z(Z)
);
endmodule
module MULTADDSUB9X9WIDE #(
parameter REGINPUTAB0 = "REGISTER",
parameter REGINPUTAB1 = "REGISTER",
parameter REGINPUTAB2 = "REGISTER",
parameter REGINPUTAB3 = "REGISTER",
parameter REGINPUTC = "REGISTER",
parameter REGADDSUB = "REGISTER",
parameter REGLOADC = "REGISTER",
parameter REGLOADC2 = "REGISTER",
parameter REGPIPELINE = "REGISTER",
parameter REGOUTPUT = "REGISTER",
parameter GSR = "ENABLED",
parameter RESETMODE = "SYNC"
) (
input [8:0] A0, B0, A1, B1, A2, B2, A3, B3,
input [53:0] C,
input CLK,
input CEA0A1, CEA2A3,
input RSTA0A1, RSTA2A3,
input CEB0B1, CEB2B3,
input RSTB0B1, RSTB2B3,
input CEC, RSTC,
input CECTRL, RSTCTRL,
input SIGNED,
input RSTPIPE, CEPIPE,
input RSTOUT, CEOUT,
input LOADC,
input [3:0] ADDSUB,
output [53:0] Z
);
wire [17:0] m0, m1, m2, m3;
localparam M_WIDTH = 18;
localparam Z_WIDTH = 54;
MULT9X9 #(
.REGINPUTA(REGINPUTAB0), .REGINPUTB(REGINPUTAB0), .REGOUTPUT(REGPIPELINE), .GSR(GSR), .RESETMODE(RESETMODE)
) m9_0 (
.A(A0), .B(B0), .SIGNEDA(SIGNED), .SIGNEDB(SIGNED),
.CLK(CLK),
.CEA(CEA0A1), .RSTA(RSTA0A1),
.CEB(CEB0B1), .RSTB(RSTB0B1),
.CEOUT(CEPIPE), .RSTOUT(RSTPIPE),
.Z(m0)
);
MULT9X9 #(
.REGINPUTA(REGINPUTAB1), .REGINPUTB(REGINPUTAB1), .REGOUTPUT(REGPIPELINE), .GSR(GSR), .RESETMODE(RESETMODE)
) m9_1 (
.A(A1), .B(B1), .SIGNEDA(SIGNED), .SIGNEDB(SIGNED),
.CLK(CLK),
.CEA(CEA0A1), .RSTA(RSTA0A1),
.CEB(CEB0B1), .RSTB(RSTB0B1),
.CEOUT(CEPIPE), .RSTOUT(RSTPIPE),
.Z(m1)
);
MULT9X9 #(
.REGINPUTA(REGINPUTAB2), .REGINPUTB(REGINPUTAB2), .REGOUTPUT(REGPIPELINE), .GSR(GSR), .RESETMODE(RESETMODE)
) m9_2 (
.A(A2), .B(B2), .SIGNEDA(SIGNED), .SIGNEDB(SIGNED),
.CLK(CLK),
.CEA(CEA2A3), .RSTA(RSTA2A3),
.CEB(CEB2B3), .RSTB(RSTB2B3),
.CEOUT(CEPIPE), .RSTOUT(RSTPIPE),
.Z(m2)
);
MULT9X9 #(
.REGINPUTA(REGINPUTAB3), .REGINPUTB(REGINPUTAB3), .REGOUTPUT(REGPIPELINE), .GSR(GSR), .RESETMODE(RESETMODE)
) m9_3 (
.A(A3), .B(B3), .SIGNEDA(SIGNED), .SIGNEDB(SIGNED),
.CLK(CLK),
.CEA(CEA2A3), .RSTA(RSTA2A3),
.CEB(CEB2B3), .RSTB(RSTB2B3),
.CEOUT(CEPIPE), .RSTOUT(RSTPIPE),
.Z(m3)
);
wire [53:0] c_r, c_r2;
wire [3:0] addsub_r, addsub_r2;
wire sgd_r, sgd_r2, csgd_r, csgd_r2;
wire loadc_r, loadc_r2;
OXIDE_DSP_REG #(5, REGADDSUB, RESETMODE) addsub_reg(CLK, CECTRL, RSTCTRL, {SIGNED, ADDSUB}, {sgd_r, addsub_r});
OXIDE_DSP_REG #(5, REGADDSUB, RESETMODE) addsub2_reg(CLK, CECTRL, RSTCTRL, {sgd_r, addsub_r}, {sgd_r2, addsub_r2});
OXIDE_DSP_REG #(1, REGLOADC, RESETMODE) loadc_reg(CLK, CECTRL, RSTCTRL, LOADC, loadc_r);
OXIDE_DSP_REG #(1, REGLOADC2, RESETMODE) loadc2_reg(CLK, CECTRL, RSTCTRL, loadc_r, loadc_r2);
OXIDE_DSP_REG #(55, REGINPUTC, RESETMODE) c_reg(CLK, CEC, RSTC, {SIGNED, C}, {csgd_r, c_r});
OXIDE_DSP_REG #(55, REGPIPELINE, RESETMODE) c2_reg(CLK, CEC, RSTC, {csgd_r, c_r}, {csgd_r2, c_r2});
wire [18:0] m0_ext, m1_ext, m2_ext, m3_ext;
assign m0_ext = {sgd_r2 ? m0[M_WIDTH-1] : 1'b0, m0};
assign m1_ext = {sgd_r2 ? m1[M_WIDTH-1] : 1'b0, m1};
assign m2_ext = {sgd_r2 ? m2[M_WIDTH-1] : 1'b0, m2};
assign m3_ext = {sgd_r2 ? m3[M_WIDTH-1] : 1'b0, m3};
wire [18:0] s0 = addsub_r2[2] ? (m0_ext - m1_ext) : (m0_ext + m1_ext);
wire [18:0] s1 = addsub_r2[3] ? (m2_ext - m3_ext) : (m2_ext + m3_ext);
wire [53:0] s0_ext = {{(54-19){sgd_r2 ? s0[18] : 1'b0}}, s0};
wire [53:0] s1_ext = {{(54-19){sgd_r2 ? s1[18] : 1'b0}}, s1};
wire [53:0] c_op = loadc_r2 ? c_r2 : Z;
// The diagram in the docs is wrong! It is not two cascaded 2-input add/subs as shown,
// but a three-input unit with negation controls on two inputs (i.e. addsub_r2[0]
// negates s1 not (s1 +/- s0))
wire [53:0] z_d = c_op + (addsub_r2[0] ? -s1_ext : s1_ext) + (addsub_r2[1] ? -s0_ext : s0_ext);
OXIDE_DSP_REG #(Z_WIDTH, REGOUTPUT, RESETMODE) z_reg(CLK, CEOUT, RSTOUT, z_d, Z);
endmodule