1 (* abc9_lut=1, lib_whitebox *)
2 module LUT4(input A, B, C, D, output Z);
3 parameter INIT = "0x0000";
4 `include "parse_init.vh"
5 localparam initp = parse_init(INIT);
6 wire [7:0] s3 = D ? initp[15:8] : initp[7:0];
7 wire [3:0] s2 = C ? s3[ 7:4] : s3[3:0];
8 wire [1:0] s1 = B ? s2[ 3:2] : s2[1:0];
9 assign Z = A ? s1[1] : s1[0];
11 // Per-input delay differences are considered 'interconnect'
22 // This is a placeholder for ABC9 to extract the area/delay
23 // cost of 5-input LUTs and is not intended to be instantiated
25 module \$__ABC9_LUT5 (input SEL, D, C, B, A, output Z);
36 module WIDEFN9(input A0, B0, C0, D0, A1, B1, C1, D1, SEL, output Z);
37 parameter INIT0 = "0x0000";
38 parameter INIT1 = "0x0000";
40 LUT4 #(.INIT(INIT0)) lut4_0 (.A(A0), .B(B0), .C(C0), .D(D0), .Z(z0));
41 LUT4 #(.INIT(INIT1)) lut4_1 (.A(A1), .B(B1), .C(C1), .D(D1), .Z(z1));
42 assign Z = SEL ? z1 : z0;
45 (* abc9_box, lib_whitebox *)
46 module INV(input A, output Z);
54 // Bidirectional IO buffer
55 module BB(input T, I, output O,
56 (* iopad_external_pin *) inout B);
57 assign B = T ? 1'bz : O;
63 (* iopad_external_pin *) input I,
70 (* iopad_external_pin *) output O);
74 // Output buffer with tristate
75 module OBZ(input I, T,
76 (* iopad_external_pin *) output O);
77 assign O = T ? 1'bz : I;
90 // (all have active high clock, enable and set/reset - use INV to invert)
93 (* abc9_box, lib_whitebox *)
94 module FD1P3BX(input D, CK, SP, PD, output reg Q);
95 parameter GSR = "DISABLED";
97 always @(posedge CK or posedge PD)
103 $setup(D, posedge CK, 0);
104 $setup(SP, posedge CK, 212);
105 $setup(PD, posedge CK, 224);
107 if (PD) (posedge CLK => (Q : 1)) = 0;
109 if (PD) (PD => Q) = 0; // Technically, this should be an edge sensitive path
110 // but for facilitating a bypass box, let's pretend it's
113 if (!PD && SP) (posedge CK => (Q : D)) = 336;
118 (* abc9_box, lib_whitebox *)
119 module FD1P3DX(input D, CK, SP, CD, output reg Q);
120 parameter GSR = "DISABLED";
122 always @(posedge CK or posedge CD)
128 $setup(D, posedge CK, 0);
129 $setup(SP, posedge CK, 212);
130 $setup(CD, posedge CK, 224);
132 if (CD) (posedge CLK => (Q : 0)) = 0;
134 if (CD) (CD => Q) = 0; // Technically, this should be an edge sensitive path
135 // but for facilitating a bypass box, let's pretend it's
138 if (!CD && SP) (posedge CK => (Q : D)) = 336;
143 (* abc9_flop, lib_whitebox *)
144 module FD1P3IX(input D, CK, SP, CD, output reg Q);
145 parameter GSR = "DISABLED";
153 $setup(D, posedge CK, 0);
154 $setup(SP, posedge CK, 212);
155 $setup(CD, posedge CK, 224);
156 if (!CD && SP) (posedge CK => (Q : D)) = 336;
161 (* abc9_flop, lib_whitebox *)
162 module FD1P3JX(input D, CK, SP, PD, output reg Q);
163 parameter GSR = "DISABLED";
171 $setup(D, posedge CK, 0);
172 $setup(SP, posedge CK, 212);
173 $setup(PD, posedge CK, 224);
174 if (!PD && SP) (posedge CK => (Q : D)) = 336;
178 // LUT4 with LUT3 tap for CCU2 use only
180 module LUT4_3(input A, B, C, D, output Z, Z3);
181 parameter INIT = "0x0000";
182 `include "parse_init.vh"
183 localparam initp = parse_init(INIT);
184 wire [7:0] s3 = D ? initp[15:8] : initp[7:0];
185 wire [3:0] s2 = C ? s3[ 7:4] : s3[3:0];
186 wire [1:0] s1 = B ? s2[ 3:2] : s2[1:0];
187 assign Z = A ? s1[1] : s1[0];
189 wire [3:0] s2_3 = C ? initp[ 7:4] : initp[3:0];
190 wire [1:0] s1_3 = B ? s2_3[ 3:2] : s2_3[1:0];
191 assign Z3 = A ? s1_3[1] : s1_3[0];
195 // Carry primitive (incoporating two LUTs)
196 (* abc9_box, lib_whitebox *)
198 (* abc9_carry *) input CIN,
199 input A1, B1, C1, D1, A0, B0, C0, D0,
201 (* abc9_carry *) output COUT);
202 parameter INJECT = "YES";
203 parameter INIT0 = "0x0000";
204 parameter INIT1 = "0x1111";
206 localparam inject_p = (INJECT == "YES") ? 1'b1 : 1'b0;
208 wire LUT3_0, LUT4_0, LUT3_1, LUT4_1, carry_0;
209 LUT4_3 #(.INIT(INIT0)) lut0 (.A(A0), .B(B0), .C(C0), .D(D0), .Z(LUT4_0), .Z3(LUT3_0));
210 LUT4_3 #(.INIT(INIT1)) lut1 (.A(A1), .B(B1), .C(C1), .D(D1), .Z(LUT4_1), .Z3(LUT3_1));
212 assign S0 = LUT4_0 ^ (CIN & ~inject_p);
213 assign carry_0 = LUT4_0 ? CIN : (LUT3_0 & ~inject_p);
214 assign S1 = LUT4_1 ^ (carry_0 & ~inject_p);
215 assign COUT = LUT4_1 ? carry_0 : (LUT3_1 & ~inject_p);
246 module OXIDE_FF(input CLK, LSR, CE, DI, M, output reg Q);
247 parameter GSR = "ENABLED";
248 parameter [127:0] CEMUX = "1";
249 parameter CLKMUX = "CLK";
250 parameter LSRMUX = "LSR";
251 parameter REGDDR = "DISABLED";
252 parameter SRMODE = "LSR_OVER_CE";
253 parameter REGSET = "RESET";
254 parameter [127:0] LSRMODE = "LSR";
259 "1": assign muxce = 1'b1;
260 "0": assign muxce = 1'b0;
261 "INV": assign muxce = ~CE;
262 default: assign muxce = CE;
266 wire muxlsr = (LSRMUX == "INV") ? ~LSR : LSR;
267 wire muxclk = (CLKMUX == "INV") ? ~CLK : CLK;
270 if (LSRMODE == "PRLD")
273 assign srval = (REGSET == "SET") ? 1'b1 : 1'b0;
279 if (REGDDR == "ENABLED") begin
280 if (SRMODE == "ASYNC") begin
281 always @(posedge muxclk, negedge muxclk, posedge muxlsr)
287 always @(posedge muxclk, negedge muxclk)
294 if (SRMODE == "ASYNC") begin
295 always @(posedge muxclk, posedge muxlsr)
301 always @(posedge muxclk)
311 // Packed combinational logic (for post-pnr sim)
313 input A, B, C, D, // LUT inputs
314 input SEL, // mux select input
315 input F1, // output from LUT 1 for mux
316 input FCI, // carry input
317 input WAD0, WAD1, WAD2, WAD3, // LUTRAM write address inputs
318 input WD, // LUTRAM write data input
319 input WCK, WRE, // LUTRAM write clock and enable
320 output F, // LUT/carry output
321 output OFX // mux output
323 parameter MODE = "LOGIC"; // LOGIC, CCU2, DPRAM
324 parameter [15:0] INIT = 16'h0000;
325 parameter INJECT = "YES";
327 localparam inject_p = (INJECT == "YES") ? 1'b1 : 1'b0;
329 reg [15:0] lut = INIT;
331 wire [7:0] s3 = D ? INIT[15:8] : INIT[7:0];
332 wire [3:0] s2 = C ? s3[ 7:4] : s3[3:0];
333 wire [1:0] s1 = B ? s2[ 3:2] : s2[1:0];
334 wire Z = A ? s1[1] : s1[0];
336 wire [3:0] s2_3 = C ? INIT[ 7:4] : INIT[3:0];
337 wire [1:0] s1_3 = B ? s2_3[ 3:2] : s2_3[1:0];
338 wire Z3 = A ? s1_3[1] : s1_3[0];
341 if (MODE == "DPRAM") begin
342 always @(posedge WCK)
344 lut[{WAD3, WAD2, WAD1, WAD0}] <= WD;
346 if (MODE == "CCU2") begin
347 assign F = Z ^ (FCI & ~inject_p);
348 assign FCO = Z ? FCI : (Z3 & ~inject_p);
354 assign OFX = SEL ? F1 : F;
360 input [3:0] RAD, DI, WAD,
364 parameter INITVAL = "0x0000000000000000";
365 `include "parse_init.vh"
366 localparam [63:0] parsed_init = parse_init_64(INITVAL);
371 for (i = 0; i < 15; i++)
372 mem[i] = parsed_init[i * 4 +: 4];
375 always @(posedge WCK)
378 assign DO = mem[RAD];
381 // Used for all the DSP models to reduce duplication
382 module OXIDE_DSP_REG #(
384 parameter USED = "REGISTER",
385 parameter RESETMODE = "SYNC"
392 if (USED == "BYPASS")
394 else if (USED == "REGISTER") begin
396 if (RESETMODE == "ASYNC")
397 always @(posedge CLK, posedge RST) begin
403 else if (RESETMODE == "SYNC")
404 always @(posedge CLK) begin
414 module OXIDE_DSP_SIM #(
415 // User facing parameters
416 parameter REGINPUTA = "BYPASS",
417 parameter REGINPUTB = "BYPASS",
418 parameter REGINPUTC = "BYPASS",
419 parameter REGADDSUB = "BYPASS",
420 parameter REGLOADC = "BYPASS",
421 parameter REGLOADC2 = "BYPASS",
422 parameter REGCIN = "BYPASS",
423 parameter REGPIPELINE = "BYPASS",
424 parameter REGOUTPUT = "BYPASS",
425 parameter GSR = "ENABLED",
426 parameter RESETMODE = "SYNC",
427 // Internally used parameters
428 parameter A_WIDTH = 36,
429 parameter B_WIDTH = 36,
430 parameter C_WIDTH = 36,
431 parameter Z_WIDTH = 72,
432 parameter PREADD_USED = 0,
433 parameter ADDSUB_USED = 0
435 input [A_WIDTH-1:0] A,
436 input [B_WIDTH-1:0] B,
437 input [C_WIDTH-1:0] C,
445 input CEA, CEB, CEC, CEPIPE, CECTRL, CECIN, CEOUT,
446 input RSTA, RSTB, RSTC, RSTPIPE, RSTCTRL, RSTCIN, RSTOUT,
447 output wire [Z_WIDTH-1:0] Z
450 localparam M_WIDTH = (A_WIDTH+B_WIDTH);
452 /******** REGISTERS ********/
454 wire [M_WIDTH-1:0] pipe_d, pipe_q;
455 wire [Z_WIDTH-1:0] z_d;
457 wire [A_WIDTH-1:0] a_r;
458 wire [B_WIDTH-1:0] b_r;
459 wire [C_WIDTH-1:0] c_r, c_r2;
460 wire asgd_r, bsgd_r, csgd_r, csgd_r2;
462 wire addsub_r, addsub_r2, cin_r, cin_r2, sgd_r, sgd_r2;
463 wire loadc_r, loadc_r2;
465 OXIDE_DSP_REG #(A_WIDTH+1, REGINPUTA, RESETMODE) a_reg(CLK, CEA, RSTA, {SIGNEDA, A}, {asgd_r, a_r});
466 OXIDE_DSP_REG #(B_WIDTH+1, REGINPUTB, RESETMODE) b_reg(CLK, CEB, RSTB, {SIGNEDB, B}, {bsgd_r, b_r});
467 OXIDE_DSP_REG #(C_WIDTH+1, REGINPUTC, RESETMODE) c_reg(CLK, CEC, RSTC, {SIGNEDC, C}, {csgd_r, c_r});
469 OXIDE_DSP_REG #(M_WIDTH, REGPIPELINE, RESETMODE) pipe_reg(CLK, CEPIPE, RSTPIPE, pipe_d, pipe_q);
471 OXIDE_DSP_REG #(2, REGADDSUB, RESETMODE) addsub_reg(CLK, CECTRL, RSTCTRL, {SIGNEDA, ADDSUB}, {sgd_r, addsub_r});
472 OXIDE_DSP_REG #(1, REGLOADC, RESETMODE) loadc_reg(CLK, CECTRL, RSTCTRL, LOADC, loadc_r);
473 OXIDE_DSP_REG #(2, REGPIPELINE, RESETMODE) addsub2_reg(CLK, CECTRL, RSTCTRL, {sgd_r, addsub_r}, {sgd_r2, addsub_r2});
474 OXIDE_DSP_REG #(1, REGLOADC2, RESETMODE) loadc2_reg(CLK, CECTRL, RSTCTRL, loadc_r, loadc_r2);
476 OXIDE_DSP_REG #(1, REGCIN, RESETMODE) cin_reg(CLK, CECIN, RSTCIN, CIN, cin_r);
477 OXIDE_DSP_REG #(1, REGPIPELINE, RESETMODE) cin2_reg(CLK, CECIN, RSTCIN, cin_r, cin_r2);
479 OXIDE_DSP_REG #(C_WIDTH+1, REGPIPELINE, RESETMODE) c2_reg(CLK, CEC, RSTC, {csgd_r, c_r}, {csgd_r2, c_r2});
481 OXIDE_DSP_REG #(Z_WIDTH, REGOUTPUT, RESETMODE) z_reg(CLK, CEOUT, RSTOUT, z_d, Z);
483 /******** PREADDER ********/
485 wire [B_WIDTH-1:0] mult_b;
489 if (PREADD_USED) begin
490 assign mult_b = (b_r + c_r);
491 assign mult_b_sgd = (bsgd_r | csgd_r);
494 assign mult_b_sgd = bsgd_r;
498 /******** MULTIPLIER ********/
500 // sign extend operands if needed
501 wire [M_WIDTH-1:0] mult_a_ext = {{(M_WIDTH-A_WIDTH){asgd_r ? a_r[A_WIDTH-1] : 1'b0}}, a_r};
502 wire [M_WIDTH-1:0] mult_b_ext = {{(M_WIDTH-B_WIDTH){mult_b_sgd ? mult_b[B_WIDTH-1] : 1'b0}}, mult_b};
504 wire [M_WIDTH-1:0] mult_m = mult_a_ext * mult_b_ext;
506 /******** ACCUMULATOR ********/
508 wire [Z_WIDTH-1:0] m_ext;
511 if (ADDSUB_USED) begin
512 assign pipe_d = mult_m;
513 assign m_ext = {{(Z_WIDTH-M_WIDTH){sgd_r2 ? pipe_q[M_WIDTH-1] : 1'b0}}, pipe_q};
514 assign z_d = (loadc_r2 ? c_r2 : Z) + cin_r2 + (addsub_r2 ? -m_ext : m_ext);
524 parameter REGINPUTA = "REGISTER",
525 parameter REGINPUTB = "REGISTER",
526 parameter REGOUTPUT = "REGISTER",
527 parameter GSR = "ENABLED",
528 parameter RESETMODE = "SYNC"
544 .REGINPUTA(REGINPUTA),
545 .REGINPUTB(REGINPUTB),
546 .REGOUTPUT(REGOUTPUT),
548 .RESETMODE(RESETMODE),
558 .CEA(CEA), .RSTA(RSTA),
559 .CEB(CEB), .RSTB(RSTB),
560 .SIGNEDA(SIGNEDA), .SIGNEDB(SIGNEDB),
561 .RSTOUT(RSTOUT), .CEOUT(CEOUT),
567 parameter REGINPUTA = "REGISTER",
568 parameter REGINPUTB = "REGISTER",
569 parameter REGOUTPUT = "REGISTER",
570 parameter GSR = "ENABLED",
571 parameter RESETMODE = "SYNC"
587 .REGINPUTA(REGINPUTA),
588 .REGINPUTB(REGINPUTB),
589 .REGOUTPUT(REGOUTPUT),
591 .RESETMODE(RESETMODE),
601 .CEA(CEA), .RSTA(RSTA),
602 .CEB(CEB), .RSTB(RSTB),
603 .SIGNEDA(SIGNEDA), .SIGNEDB(SIGNEDB),
604 .RSTOUT(RSTOUT), .CEOUT(CEOUT),
610 parameter REGINPUTA = "REGISTER",
611 parameter REGINPUTB = "REGISTER",
612 parameter REGOUTPUT = "REGISTER",
613 parameter GSR = "ENABLED",
614 parameter RESETMODE = "SYNC"
630 .REGINPUTA(REGINPUTA),
631 .REGINPUTB(REGINPUTB),
632 .REGOUTPUT(REGOUTPUT),
634 .RESETMODE(RESETMODE),
644 .CEA(CEA), .RSTA(RSTA),
645 .CEB(CEB), .RSTB(RSTB),
646 .SIGNEDA(SIGNEDA), .SIGNEDB(SIGNEDB),
647 .RSTOUT(RSTOUT), .CEOUT(CEOUT),
653 parameter REGINPUTA = "REGISTER",
654 parameter REGINPUTB = "REGISTER",
655 parameter REGOUTPUT = "REGISTER",
656 parameter GSR = "ENABLED",
657 parameter RESETMODE = "SYNC"
673 .REGINPUTA(REGINPUTA),
674 .REGINPUTB(REGINPUTB),
675 .REGOUTPUT(REGOUTPUT),
677 .RESETMODE(RESETMODE),
687 .CEA(CEA), .RSTA(RSTA),
688 .CEB(CEB), .RSTB(RSTB),
689 .SIGNEDA(SIGNEDA), .SIGNEDB(SIGNEDB),
690 .RSTOUT(RSTOUT), .CEOUT(CEOUT),
696 module MULTPREADD9X9 #(
697 parameter REGINPUTA = "REGISTER",
698 parameter REGINPUTB = "REGISTER",
699 parameter REGINPUTC = "REGISTER",
700 parameter REGOUTPUT = "REGISTER",
701 parameter GSR = "ENABLED",
702 parameter RESETMODE = "SYNC"
722 .REGINPUTA(REGINPUTA),
723 .REGINPUTB(REGINPUTB),
724 .REGINPUTC(REGINPUTC),
725 .REGOUTPUT(REGOUTPUT),
727 .RESETMODE(RESETMODE),
738 .CEA(CEA), .RSTA(RSTA),
739 .CEB(CEB), .RSTB(RSTB),
740 .CEC(CEC), .RSTC(RSTC),
741 .SIGNEDA(SIGNEDA), .SIGNEDB(SIGNEDB), .SIGNEDC(SIGNEDC),
742 .RSTOUT(RSTOUT), .CEOUT(CEOUT),
748 module MULTPREADD18X18 #(
749 parameter REGINPUTA = "REGISTER",
750 parameter REGINPUTB = "REGISTER",
751 parameter REGINPUTC = "REGISTER",
752 parameter REGOUTPUT = "REGISTER",
753 parameter GSR = "ENABLED",
754 parameter RESETMODE = "SYNC"
774 .REGINPUTA(REGINPUTA),
775 .REGINPUTB(REGINPUTB),
776 .REGINPUTC(REGINPUTC),
777 .REGOUTPUT(REGOUTPUT),
779 .RESETMODE(RESETMODE),
790 .CEA(CEA), .RSTA(RSTA),
791 .CEB(CEB), .RSTB(RSTB),
792 .CEC(CEC), .RSTC(RSTC),
793 .SIGNEDA(SIGNEDA), .SIGNEDB(SIGNEDB), .SIGNEDC(SIGNEDC),
794 .RSTOUT(RSTOUT), .CEOUT(CEOUT),
800 module MULTADDSUB18X18 #(
801 parameter REGINPUTA = "REGISTER",
802 parameter REGINPUTB = "REGISTER",
803 parameter REGINPUTC = "REGISTER",
804 parameter REGADDSUB = "REGISTER",
805 parameter REGLOADC = "REGISTER",
806 parameter REGLOADC2 = "REGISTER",
807 parameter REGCIN = "REGISTER",
808 parameter REGPIPELINE = "REGISTER",
809 parameter REGOUTPUT = "REGISTER",
810 parameter GSR = "ENABLED",
811 parameter RESETMODE = "SYNC"
838 .REGINPUTA(REGINPUTA),
839 .REGINPUTB(REGINPUTB),
840 .REGINPUTC(REGINPUTC),
841 .REGADDSUB(REGADDSUB),
843 .REGLOADC2(REGLOADC2),
845 .REGPIPELINE(REGPIPELINE),
846 .REGOUTPUT(REGOUTPUT),
848 .RESETMODE(RESETMODE),
859 .CEA(CEA), .RSTA(RSTA),
860 .CEB(CEB), .RSTB(RSTB),
861 .CEC(CEC), .RSTC(RSTC),
862 .CEPIPE(CEPIPE), .RSTPIPE(RSTPIPE),
863 .CECTRL(CECTRL), .RSTCTRL(RSTCTRL),
864 .CECIN(CECIN), .RSTCIN(RSTCIN),
865 .CIN(CIN), .LOADC(LOADC), .ADDSUB(ADDSUB),
866 .SIGNEDA(SIGNED), .SIGNEDB(SIGNED), .SIGNEDC(SIGNED),
867 .RSTOUT(RSTOUT), .CEOUT(CEOUT),
873 module MULTADDSUB36X36 #(
874 parameter REGINPUTA = "REGISTER",
875 parameter REGINPUTB = "REGISTER",
876 parameter REGINPUTC = "REGISTER",
877 parameter REGADDSUB = "REGISTER",
878 parameter REGLOADC = "REGISTER",
879 parameter REGLOADC2 = "REGISTER",
880 parameter REGCIN = "REGISTER",
881 parameter REGPIPELINE = "REGISTER",
882 parameter REGOUTPUT = "REGISTER",
883 parameter GSR = "ENABLED",
884 parameter RESETMODE = "SYNC"
911 .REGINPUTA(REGINPUTA),
912 .REGINPUTB(REGINPUTB),
913 .REGINPUTC(REGINPUTC),
914 .REGADDSUB(REGADDSUB),
916 .REGLOADC2(REGLOADC2),
918 .REGPIPELINE(REGPIPELINE),
919 .REGOUTPUT(REGOUTPUT),
921 .RESETMODE(RESETMODE),
932 .CEA(CEA), .RSTA(RSTA),
933 .CEB(CEB), .RSTB(RSTB),
934 .CEC(CEC), .RSTC(RSTC),
935 .CEPIPE(CEPIPE), .RSTPIPE(RSTPIPE),
936 .CECTRL(CECTRL), .RSTCTRL(RSTCTRL),
937 .CECIN(CECIN), .RSTCIN(RSTCIN),
938 .CIN(CIN), .LOADC(LOADC), .ADDSUB(ADDSUB),
939 .SIGNEDA(SIGNED), .SIGNEDB(SIGNED), .SIGNEDC(SIGNED),
940 .RSTOUT(RSTOUT), .CEOUT(CEOUT),
945 module MULTADDSUB9X9WIDE #(
946 parameter REGINPUTAB0 = "REGISTER",
947 parameter REGINPUTAB1 = "REGISTER",
948 parameter REGINPUTAB2 = "REGISTER",
949 parameter REGINPUTAB3 = "REGISTER",
950 parameter REGINPUTC = "REGISTER",
951 parameter REGADDSUB = "REGISTER",
952 parameter REGLOADC = "REGISTER",
953 parameter REGLOADC2 = "REGISTER",
954 parameter REGPIPELINE = "REGISTER",
955 parameter REGOUTPUT = "REGISTER",
956 parameter GSR = "ENABLED",
957 parameter RESETMODE = "SYNC"
959 input [8:0] A0, B0, A1, B1, A2, B2, A3, B3,
962 input CEA0A1, CEA2A3,
963 input RSTA0A1, RSTA2A3,
964 input CEB0B1, CEB2B3,
965 input RSTB0B1, RSTB2B3,
967 input CECTRL, RSTCTRL,
969 input RSTPIPE, CEPIPE,
975 wire [17:0] m0, m1, m2, m3;
977 localparam M_WIDTH = 18;
978 localparam Z_WIDTH = 54;
981 .REGINPUTA(REGINPUTAB0), .REGINPUTB(REGINPUTAB0), .REGOUTPUT(REGPIPELINE), .GSR(GSR), .RESETMODE(RESETMODE)
983 .A(A0), .B(B0), .SIGNEDA(SIGNED), .SIGNEDB(SIGNED),
985 .CEA(CEA0A1), .RSTA(RSTA0A1),
986 .CEB(CEB0B1), .RSTB(RSTB0B1),
987 .CEOUT(CEPIPE), .RSTOUT(RSTPIPE),
991 .REGINPUTA(REGINPUTAB1), .REGINPUTB(REGINPUTAB1), .REGOUTPUT(REGPIPELINE), .GSR(GSR), .RESETMODE(RESETMODE)
993 .A(A1), .B(B1), .SIGNEDA(SIGNED), .SIGNEDB(SIGNED),
995 .CEA(CEA0A1), .RSTA(RSTA0A1),
996 .CEB(CEB0B1), .RSTB(RSTB0B1),
997 .CEOUT(CEPIPE), .RSTOUT(RSTPIPE),
1001 .REGINPUTA(REGINPUTAB2), .REGINPUTB(REGINPUTAB2), .REGOUTPUT(REGPIPELINE), .GSR(GSR), .RESETMODE(RESETMODE)
1003 .A(A2), .B(B2), .SIGNEDA(SIGNED), .SIGNEDB(SIGNED),
1005 .CEA(CEA2A3), .RSTA(RSTA2A3),
1006 .CEB(CEB2B3), .RSTB(RSTB2B3),
1007 .CEOUT(CEPIPE), .RSTOUT(RSTPIPE),
1011 .REGINPUTA(REGINPUTAB3), .REGINPUTB(REGINPUTAB3), .REGOUTPUT(REGPIPELINE), .GSR(GSR), .RESETMODE(RESETMODE)
1013 .A(A3), .B(B3), .SIGNEDA(SIGNED), .SIGNEDB(SIGNED),
1015 .CEA(CEA2A3), .RSTA(RSTA2A3),
1016 .CEB(CEB2B3), .RSTB(RSTB2B3),
1017 .CEOUT(CEPIPE), .RSTOUT(RSTPIPE),
1021 wire [53:0] c_r, c_r2;
1022 wire [3:0] addsub_r, addsub_r2;
1023 wire sgd_r, sgd_r2, csgd_r, csgd_r2;
1024 wire loadc_r, loadc_r2;
1026 OXIDE_DSP_REG #(5, REGADDSUB, RESETMODE) addsub_reg(CLK, CECTRL, RSTCTRL, {SIGNED, ADDSUB}, {sgd_r, addsub_r});
1027 OXIDE_DSP_REG #(5, REGADDSUB, RESETMODE) addsub2_reg(CLK, CECTRL, RSTCTRL, {sgd_r, addsub_r}, {sgd_r2, addsub_r2});
1029 OXIDE_DSP_REG #(1, REGLOADC, RESETMODE) loadc_reg(CLK, CECTRL, RSTCTRL, LOADC, loadc_r);
1030 OXIDE_DSP_REG #(1, REGLOADC2, RESETMODE) loadc2_reg(CLK, CECTRL, RSTCTRL, loadc_r, loadc_r2);
1032 OXIDE_DSP_REG #(55, REGINPUTC, RESETMODE) c_reg(CLK, CEC, RSTC, {SIGNED, C}, {csgd_r, c_r});
1033 OXIDE_DSP_REG #(55, REGPIPELINE, RESETMODE) c2_reg(CLK, CEC, RSTC, {csgd_r, c_r}, {csgd_r2, c_r2});
1036 wire [18:0] m0_ext, m1_ext, m2_ext, m3_ext;
1038 assign m0_ext = {sgd_r2 ? m0[M_WIDTH-1] : 1'b0, m0};
1039 assign m1_ext = {sgd_r2 ? m1[M_WIDTH-1] : 1'b0, m1};
1040 assign m2_ext = {sgd_r2 ? m2[M_WIDTH-1] : 1'b0, m2};
1041 assign m3_ext = {sgd_r2 ? m3[M_WIDTH-1] : 1'b0, m3};
1043 wire [18:0] s0 = addsub_r2[2] ? (m0_ext - m1_ext) : (m0_ext + m1_ext);
1044 wire [18:0] s1 = addsub_r2[3] ? (m2_ext - m3_ext) : (m2_ext + m3_ext);
1046 wire [53:0] s0_ext = {{(54-19){sgd_r2 ? s0[18] : 1'b0}}, s0};
1047 wire [53:0] s1_ext = {{(54-19){sgd_r2 ? s1[18] : 1'b0}}, s1};
1049 wire [53:0] c_op = loadc_r2 ? c_r2 : Z;
1051 // The diagram in the docs is wrong! It is not two cascaded 2-input add/subs as shown,
1052 // but a three-input unit with negation controls on two inputs (i.e. addsub_r2[0]
1053 // negates s1 not (s1 +/- s0))
1054 wire [53:0] z_d = c_op + (addsub_r2[0] ? -s1_ext : s1_ext) + (addsub_r2[1] ? -s0_ext : s0_ext);
1056 OXIDE_DSP_REG #(Z_WIDTH, REGOUTPUT, RESETMODE) z_reg(CLK, CEOUT, RSTOUT, z_d, Z);