nexus: Add MULTADDSUB9X9WIDE sim model
[yosys.git] / techlibs / nexus / cells_sim.v
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];
10
11 // Per-input delay differences are considered 'interconnect'
12 // so not known yet
13 specify
14 (A => Z) = 233;
15 (B => Z) = 233;
16 (C => Z) = 233;
17 (D => Z) = 233;
18 endspecify
19
20 endmodule
21
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
24 (* abc9_lut=2 *)
25 module \$__ABC9_LUT5 (input SEL, D, C, B, A, output Z);
26 specify
27 (SEL => Z) = 171;
28 (D => Z) = 303;
29 (C => Z) = 311;
30 (B => Z) = 309;
31 (A => Z) = 306;
32 endspecify
33 endmodule
34
35 // Two LUT4s and MUX2
36 module WIDEFN9(input A0, B0, C0, D0, A1, B1, C1, D1, SEL, output Z);
37 parameter INIT0 = "0x0000";
38 parameter INIT1 = "0x0000";
39 wire z0, z1;
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;
43 endmodule
44
45 (* abc9_box, lib_whitebox *)
46 module INV(input A, output Z);
47 assign Z = !A;
48
49 specify
50 (A => Z) = 10;
51 endspecify
52 endmodule
53
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;
58 assign I = B;
59 endmodule
60
61 // Input buffer
62 module IB(
63 (* iopad_external_pin *) input I,
64 output O);
65 assign O = I;
66 endmodule
67
68 // Output buffer
69 module OB(input I,
70 (* iopad_external_pin *) output O);
71 assign O = I;
72 endmodule
73
74 // Output buffer with tristate
75 module OBZ(input I, T,
76 (* iopad_external_pin *) output O);
77 assign O = T ? 1'bz : I;
78 endmodule
79
80 // Constants
81 module VLO(output Z);
82 assign Z = 1'b0;
83 endmodule
84
85 module VHI(output Z);
86 assign Z = 1'b1;
87 endmodule
88
89 // Vendor flipflops
90 // (all have active high clock, enable and set/reset - use INV to invert)
91
92 // Async preset
93 (* abc9_box, lib_whitebox *)
94 module FD1P3BX(input D, CK, SP, PD, output reg Q);
95 parameter GSR = "DISABLED";
96 initial Q = 1'b1;
97 always @(posedge CK or posedge PD)
98 if (PD)
99 Q <= 1'b1;
100 else if (SP)
101 Q <= D;
102 specify
103 $setup(D, posedge CK, 0);
104 $setup(SP, posedge CK, 212);
105 $setup(PD, posedge CK, 224);
106 `ifndef YOSYS
107 if (PD) (posedge CLK => (Q : 1)) = 0;
108 `else
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
111 // a simple path
112 `endif
113 if (!PD && SP) (posedge CK => (Q : D)) = 336;
114 endspecify
115 endmodule
116
117 // Async clear
118 (* abc9_box, lib_whitebox *)
119 module FD1P3DX(input D, CK, SP, CD, output reg Q);
120 parameter GSR = "DISABLED";
121 initial Q = 1'b0;
122 always @(posedge CK or posedge CD)
123 if (CD)
124 Q <= 1'b0;
125 else if (SP)
126 Q <= D;
127 specify
128 $setup(D, posedge CK, 0);
129 $setup(SP, posedge CK, 212);
130 $setup(CD, posedge CK, 224);
131 `ifndef YOSYS
132 if (CD) (posedge CLK => (Q : 0)) = 0;
133 `else
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
136 // a simple path
137 `endif
138 if (!CD && SP) (posedge CK => (Q : D)) = 336;
139 endspecify
140 endmodule
141
142 // Sync clear
143 (* abc9_flop, lib_whitebox *)
144 module FD1P3IX(input D, CK, SP, CD, output reg Q);
145 parameter GSR = "DISABLED";
146 initial Q = 1'b0;
147 always @(posedge CK)
148 if (CD)
149 Q <= 1'b0;
150 else if (SP)
151 Q <= D;
152 specify
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;
157 endspecify
158 endmodule
159
160 // Sync preset
161 (* abc9_flop, lib_whitebox *)
162 module FD1P3JX(input D, CK, SP, PD, output reg Q);
163 parameter GSR = "DISABLED";
164 initial Q = 1'b1;
165 always @(posedge CK)
166 if (PD)
167 Q <= 1'b1;
168 else if (SP)
169 Q <= D;
170 specify
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;
175 endspecify
176 endmodule
177
178 // LUT4 with LUT3 tap for CCU2 use only
179 (* lib_whitebox *)
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];
188
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];
192
193 endmodule
194
195 // Carry primitive (incoporating two LUTs)
196 (* abc9_box, lib_whitebox *)
197 module CCU2(
198 (* abc9_carry *) input CIN,
199 input A1, B1, C1, D1, A0, B0, C0, D0,
200 output S1, S0,
201 (* abc9_carry *) output COUT);
202 parameter INJECT = "YES";
203 parameter INIT0 = "0x0000";
204 parameter INIT1 = "0x1111";
205
206 localparam inject_p = (INJECT == "YES") ? 1'b1 : 1'b0;
207
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));
211
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);
216
217 specify
218 (A0 => S0) = 233;
219 (B0 => S0) = 233;
220 (C0 => S0) = 233;
221 (D0 => S0) = 233;
222 (CIN => S0) = 228;
223 (A0 => S1) = 481;
224 (B0 => S1) = 481;
225 (C0 => S1) = 481;
226 (D0 => S1) = 481;
227 (A1 => S1) = 233;
228 (B1 => S1) = 233;
229 (C1 => S1) = 233;
230 (D1 => S1) = 233;
231 (CIN => S1) = 307;
232 (A0 => COUT) = 347;
233 (B0 => COUT) = 347;
234 (C0 => COUT) = 347;
235 (D0 => COUT) = 347;
236 (A1 => COUT) = 347;
237 (B1 => COUT) = 347;
238 (C1 => COUT) = 347;
239 (D1 => COUT) = 347;
240 (CIN => COUT) = 59;
241 endspecify
242
243 endmodule
244
245 // Packed flipflop
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";
255
256 wire muxce;
257 generate
258 case (CEMUX)
259 "1": assign muxce = 1'b1;
260 "0": assign muxce = 1'b0;
261 "INV": assign muxce = ~CE;
262 default: assign muxce = CE;
263 endcase
264 endgenerate
265
266 wire muxlsr = (LSRMUX == "INV") ? ~LSR : LSR;
267 wire muxclk = (CLKMUX == "INV") ? ~CLK : CLK;
268 wire srval;
269 generate
270 if (LSRMODE == "PRLD")
271 assign srval = M;
272 else
273 assign srval = (REGSET == "SET") ? 1'b1 : 1'b0;
274 endgenerate
275
276 initial Q = srval;
277
278 generate
279 if (REGDDR == "ENABLED") begin
280 if (SRMODE == "ASYNC") begin
281 always @(posedge muxclk, negedge muxclk, posedge muxlsr)
282 if (muxlsr)
283 Q <= srval;
284 else if (muxce)
285 Q <= DI;
286 end else begin
287 always @(posedge muxclk, negedge muxclk)
288 if (muxlsr)
289 Q <= srval;
290 else if (muxce)
291 Q <= DI;
292 end
293 end else begin
294 if (SRMODE == "ASYNC") begin
295 always @(posedge muxclk, posedge muxlsr)
296 if (muxlsr)
297 Q <= srval;
298 else if (muxce)
299 Q <= DI;
300 end else begin
301 always @(posedge muxclk)
302 if (muxlsr)
303 Q <= srval;
304 else if (muxce)
305 Q <= DI;
306 end
307 end
308 endgenerate
309 endmodule
310
311 // Packed combinational logic (for post-pnr sim)
312 module OXIDE_COMB(
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
322 );
323 parameter MODE = "LOGIC"; // LOGIC, CCU2, DPRAM
324 parameter [15:0] INIT = 16'h0000;
325 parameter INJECT = "YES";
326
327 localparam inject_p = (INJECT == "YES") ? 1'b1 : 1'b0;
328
329 reg [15:0] lut = INIT;
330
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];
335
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];
339
340 generate
341 if (MODE == "DPRAM") begin
342 always @(posedge WCK)
343 if (WRE)
344 lut[{WAD3, WAD2, WAD1, WAD0}] <= WD;
345 end
346 if (MODE == "CCU2") begin
347 assign F = Z ^ (FCI & ~inject_p);
348 assign FCO = Z ? FCI : (Z3 & ~inject_p);
349 end else begin
350 assign F = Z;
351 end
352 endgenerate
353
354 assign OFX = SEL ? F1 : F;
355
356 endmodule
357
358 // LUTRAM
359 module DPR16X4(
360 input [3:0] RAD, DI, WAD,
361 input WRE, WCK,
362 output [3:0] DO
363 );
364 parameter INITVAL = "0x0000000000000000";
365 `include "parse_init.vh"
366 localparam [63:0] parsed_init = parse_init_64(INITVAL);
367
368 reg [3:0] mem[0:15];
369 integer i;
370 initial begin
371 for (i = 0; i < 15; i++)
372 mem[i] = parsed_init[i * 4 +: 4];
373 end
374
375 always @(posedge WCK)
376 if (WRE)
377 mem[WAD] <= DI;
378 assign DO = mem[RAD];
379 endmodule
380
381 // Used for all the DSP models to reduce duplication
382 module OXIDE_DSP_REG #(
383 parameter W = 18,
384 parameter USED = "REGISTER",
385 parameter RESETMODE = "SYNC"
386 ) (
387 input CLK, CE, RST,
388 input [W-1:0] D,
389 output reg [W-1:0] Q
390 );
391 generate
392 if (USED == "BYPASS")
393 always @* Q = D;
394 else if (USED == "REGISTER") begin
395 initial Q = 0;
396 if (RESETMODE == "ASYNC")
397 always @(posedge CLK, posedge RST) begin
398 if (RST)
399 Q <= 0;
400 else if (CE)
401 Q <= D;
402 end
403 else if (RESETMODE == "SYNC")
404 always @(posedge CLK) begin
405 if (RST)
406 Q <= 0;
407 else if (CE)
408 Q <= D;
409 end
410 end
411 endgenerate
412 endmodule
413
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
434 ) (
435 input [A_WIDTH-1:0] A,
436 input [B_WIDTH-1:0] B,
437 input [C_WIDTH-1:0] C,
438 input SIGNEDA,
439 input SIGNEDB,
440 input SIGNEDC,
441 input CIN,
442 input LOADC,
443 input ADDSUB,
444 input CLK,
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
448 );
449
450 localparam M_WIDTH = (A_WIDTH+B_WIDTH);
451
452 /******** REGISTERS ********/
453
454 wire [M_WIDTH-1:0] pipe_d, pipe_q;
455 wire [Z_WIDTH-1:0] z_d;
456
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;
461
462 wire addsub_r, addsub_r2, cin_r, cin_r2, sgd_r, sgd_r2;
463 wire loadc_r, loadc_r2;
464
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});
468
469 OXIDE_DSP_REG #(M_WIDTH, REGPIPELINE, RESETMODE) pipe_reg(CLK, CEPIPE, RSTPIPE, pipe_d, pipe_q);
470
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);
475
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);
478
479 OXIDE_DSP_REG #(C_WIDTH+1, REGPIPELINE, RESETMODE) c2_reg(CLK, CEC, RSTC, {csgd_r, c_r}, {csgd_r2, c_r2});
480
481 OXIDE_DSP_REG #(Z_WIDTH, REGOUTPUT, RESETMODE) z_reg(CLK, CEOUT, RSTOUT, z_d, Z);
482
483 /******** PREADDER ********/
484
485 wire [B_WIDTH-1:0] mult_b;
486 wire mult_b_sgd;
487
488 generate
489 if (PREADD_USED) begin
490 assign mult_b = (b_r + c_r);
491 assign mult_b_sgd = (bsgd_r | csgd_r);
492 end else begin
493 assign mult_b = b_r;
494 assign mult_b_sgd = bsgd_r;
495 end
496 endgenerate
497
498 /******** MULTIPLIER ********/
499
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};
503
504 wire [M_WIDTH-1:0] mult_m = mult_a_ext * mult_b_ext;
505
506 /******** ACCUMULATOR ********/
507
508 wire [Z_WIDTH-1:0] m_ext;
509
510 generate
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);
515 end else begin
516 assign z_d = mult_m;
517 end
518 endgenerate
519
520
521 endmodule
522
523 module MULT9X9 #(
524 parameter REGINPUTA = "REGISTER",
525 parameter REGINPUTB = "REGISTER",
526 parameter REGOUTPUT = "REGISTER",
527 parameter GSR = "ENABLED",
528 parameter RESETMODE = "SYNC"
529 ) (
530 input [8:0] A,
531 input [8:0] B,
532 input CLK,
533 input CEA,
534 input RSTA,
535 input CEB,
536 input RSTB,
537 input SIGNEDA,
538 input SIGNEDB,
539 input RSTOUT,
540 input CEOUT,
541 output [17:0] Z
542 );
543 OXIDE_DSP_SIM #(
544 .REGINPUTA(REGINPUTA),
545 .REGINPUTB(REGINPUTB),
546 .REGOUTPUT(REGOUTPUT),
547 .GSR(GSR),
548 .RESETMODE(RESETMODE),
549
550 .A_WIDTH(9),
551 .B_WIDTH(9),
552 .Z_WIDTH(18),
553 .PREADD_USED(0),
554 .ADDSUB_USED(0)
555 ) dsp_i (
556 .A(A), .B(B),
557 .CLK(CLK),
558 .CEA(CEA), .RSTA(RSTA),
559 .CEB(CEB), .RSTB(RSTB),
560 .SIGNEDA(SIGNEDA), .SIGNEDB(SIGNEDB),
561 .RSTOUT(RSTOUT), .CEOUT(CEOUT),
562 .Z(Z)
563 );
564 endmodule
565
566 module MULT18X18 #(
567 parameter REGINPUTA = "REGISTER",
568 parameter REGINPUTB = "REGISTER",
569 parameter REGOUTPUT = "REGISTER",
570 parameter GSR = "ENABLED",
571 parameter RESETMODE = "SYNC"
572 ) (
573 input [17:0] A,
574 input [17:0] B,
575 input CLK,
576 input CEA,
577 input RSTA,
578 input CEB,
579 input RSTB,
580 input SIGNEDA,
581 input SIGNEDB,
582 input RSTOUT,
583 input CEOUT,
584 output [35:0] Z
585 );
586 OXIDE_DSP_SIM #(
587 .REGINPUTA(REGINPUTA),
588 .REGINPUTB(REGINPUTB),
589 .REGOUTPUT(REGOUTPUT),
590 .GSR(GSR),
591 .RESETMODE(RESETMODE),
592
593 .A_WIDTH(18),
594 .B_WIDTH(18),
595 .Z_WIDTH(36),
596 .PREADD_USED(0),
597 .ADDSUB_USED(0)
598 ) dsp_i (
599 .A(A), .B(B),
600 .CLK(CLK),
601 .CEA(CEA), .RSTA(RSTA),
602 .CEB(CEB), .RSTB(RSTB),
603 .SIGNEDA(SIGNEDA), .SIGNEDB(SIGNEDB),
604 .RSTOUT(RSTOUT), .CEOUT(CEOUT),
605 .Z(Z)
606 );
607 endmodule
608
609 module MULT18X36 #(
610 parameter REGINPUTA = "REGISTER",
611 parameter REGINPUTB = "REGISTER",
612 parameter REGOUTPUT = "REGISTER",
613 parameter GSR = "ENABLED",
614 parameter RESETMODE = "SYNC"
615 ) (
616 input [17:0] A,
617 input [35:0] B,
618 input CLK,
619 input CEA,
620 input RSTA,
621 input CEB,
622 input RSTB,
623 input SIGNEDA,
624 input SIGNEDB,
625 input RSTOUT,
626 input CEOUT,
627 output [53:0] Z
628 );
629 OXIDE_DSP_SIM #(
630 .REGINPUTA(REGINPUTA),
631 .REGINPUTB(REGINPUTB),
632 .REGOUTPUT(REGOUTPUT),
633 .GSR(GSR),
634 .RESETMODE(RESETMODE),
635
636 .A_WIDTH(18),
637 .B_WIDTH(36),
638 .Z_WIDTH(54),
639 .PREADD_USED(0),
640 .ADDSUB_USED(0)
641 ) dsp_i (
642 .A(A), .B(B),
643 .CLK(CLK),
644 .CEA(CEA), .RSTA(RSTA),
645 .CEB(CEB), .RSTB(RSTB),
646 .SIGNEDA(SIGNEDA), .SIGNEDB(SIGNEDB),
647 .RSTOUT(RSTOUT), .CEOUT(CEOUT),
648 .Z(Z)
649 );
650 endmodule
651
652 module MULT36X36 #(
653 parameter REGINPUTA = "REGISTER",
654 parameter REGINPUTB = "REGISTER",
655 parameter REGOUTPUT = "REGISTER",
656 parameter GSR = "ENABLED",
657 parameter RESETMODE = "SYNC"
658 ) (
659 input [35:0] A,
660 input [35:0] B,
661 input CLK,
662 input CEA,
663 input RSTA,
664 input CEB,
665 input RSTB,
666 input SIGNEDA,
667 input SIGNEDB,
668 input RSTOUT,
669 input CEOUT,
670 output [71:0] Z
671 );
672 OXIDE_DSP_SIM #(
673 .REGINPUTA(REGINPUTA),
674 .REGINPUTB(REGINPUTB),
675 .REGOUTPUT(REGOUTPUT),
676 .GSR(GSR),
677 .RESETMODE(RESETMODE),
678
679 .A_WIDTH(36),
680 .B_WIDTH(36),
681 .Z_WIDTH(72),
682 .PREADD_USED(0),
683 .ADDSUB_USED(0)
684 ) dsp_i (
685 .A(A), .B(B),
686 .CLK(CLK),
687 .CEA(CEA), .RSTA(RSTA),
688 .CEB(CEB), .RSTB(RSTB),
689 .SIGNEDA(SIGNEDA), .SIGNEDB(SIGNEDB),
690 .RSTOUT(RSTOUT), .CEOUT(CEOUT),
691 .Z(Z)
692 );
693 endmodule
694
695
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"
703 ) (
704 input [8:0] A,
705 input [8:0] B,
706 input [8:0] C,
707 input CLK,
708 input CEA,
709 input RSTA,
710 input CEB,
711 input RSTB,
712 input CEC,
713 input RSTC,
714 input SIGNEDA,
715 input SIGNEDB,
716 input SIGNEDC,
717 input RSTOUT,
718 input CEOUT,
719 output [17:0] Z
720 );
721 OXIDE_DSP_SIM #(
722 .REGINPUTA(REGINPUTA),
723 .REGINPUTB(REGINPUTB),
724 .REGINPUTC(REGINPUTC),
725 .REGOUTPUT(REGOUTPUT),
726 .GSR(GSR),
727 .RESETMODE(RESETMODE),
728
729 .A_WIDTH(9),
730 .B_WIDTH(9),
731 .C_WIDTH(9),
732 .Z_WIDTH(18),
733 .PREADD_USED(1),
734 .ADDSUB_USED(0)
735 ) dsp_i (
736 .A(A), .B(B), .C(C),
737 .CLK(CLK),
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),
743 .Z(Z)
744 );
745 endmodule
746
747
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"
755 ) (
756 input [17:0] A,
757 input [17:0] B,
758 input [17:0] C,
759 input CLK,
760 input CEA,
761 input RSTA,
762 input CEB,
763 input RSTB,
764 input CEC,
765 input RSTC,
766 input SIGNEDA,
767 input SIGNEDB,
768 input SIGNEDC,
769 input RSTOUT,
770 input CEOUT,
771 output [35:0] Z
772 );
773 OXIDE_DSP_SIM #(
774 .REGINPUTA(REGINPUTA),
775 .REGINPUTB(REGINPUTB),
776 .REGINPUTC(REGINPUTC),
777 .REGOUTPUT(REGOUTPUT),
778 .GSR(GSR),
779 .RESETMODE(RESETMODE),
780
781 .A_WIDTH(18),
782 .B_WIDTH(18),
783 .C_WIDTH(18),
784 .Z_WIDTH(36),
785 .PREADD_USED(1),
786 .ADDSUB_USED(0)
787 ) dsp_i (
788 .A(A), .B(B), .C(C),
789 .CLK(CLK),
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),
795 .Z(Z)
796 );
797 endmodule
798
799
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"
812 ) (
813 input [17:0] A,
814 input [17:0] B,
815 input [53:0] C,
816 input CLK,
817 input CEA,
818 input RSTA,
819 input CEB,
820 input RSTB,
821 input CEC,
822 input RSTC,
823 input SIGNED,
824 input RSTPIPE,
825 input CEPIPE,
826 input RSTCTRL,
827 input CECTRL,
828 input RSTCIN,
829 input CECIN,
830 input LOADC,
831 input ADDSUB,
832 output [53:0] Z,
833 input RSTOUT,
834 input CEOUT,
835 input CIN
836 );
837 OXIDE_DSP_SIM #(
838 .REGINPUTA(REGINPUTA),
839 .REGINPUTB(REGINPUTB),
840 .REGINPUTC(REGINPUTC),
841 .REGADDSUB(REGADDSUB),
842 .REGLOADC(REGLOADC),
843 .REGLOADC2(REGLOADC2),
844 .REGCIN(REGCIN),
845 .REGPIPELINE(REGPIPELINE),
846 .REGOUTPUT(REGOUTPUT),
847 .GSR(GSR),
848 .RESETMODE(RESETMODE),
849
850 .A_WIDTH(18),
851 .B_WIDTH(18),
852 .C_WIDTH(54),
853 .Z_WIDTH(54),
854 .PREADD_USED(0),
855 .ADDSUB_USED(1)
856 ) dsp_i (
857 .A(A), .B(B), .C(C),
858 .CLK(CLK),
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),
868 .Z(Z)
869 );
870 endmodule
871
872
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"
885 ) (
886 input [35:0] A,
887 input [35:0] B,
888 input [107:0] C,
889 input CLK,
890 input CEA,
891 input RSTA,
892 input CEB,
893 input RSTB,
894 input CEC,
895 input RSTC,
896 input SIGNED,
897 input RSTPIPE,
898 input CEPIPE,
899 input RSTCTRL,
900 input CECTRL,
901 input RSTCIN,
902 input CECIN,
903 input LOADC,
904 input ADDSUB,
905 output [107:0] Z,
906 input RSTOUT,
907 input CEOUT,
908 input CIN
909 );
910 OXIDE_DSP_SIM #(
911 .REGINPUTA(REGINPUTA),
912 .REGINPUTB(REGINPUTB),
913 .REGINPUTC(REGINPUTC),
914 .REGADDSUB(REGADDSUB),
915 .REGLOADC(REGLOADC),
916 .REGLOADC2(REGLOADC2),
917 .REGCIN(REGCIN),
918 .REGPIPELINE(REGPIPELINE),
919 .REGOUTPUT(REGOUTPUT),
920 .GSR(GSR),
921 .RESETMODE(RESETMODE),
922
923 .A_WIDTH(36),
924 .B_WIDTH(36),
925 .C_WIDTH(108),
926 .Z_WIDTH(108),
927 .PREADD_USED(0),
928 .ADDSUB_USED(1)
929 ) dsp_i (
930 .A(A), .B(B), .C(C),
931 .CLK(CLK),
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),
941 .Z(Z)
942 );
943 endmodule
944
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"
958 ) (
959 input [8:0] A0, B0, A1, B1, A2, B2, A3, B3,
960 input [53:0] C,
961 input CLK,
962 input CEA0A1, CEA2A3,
963 input RSTA0A1, RSTA2A3,
964 input CEB0B1, CEB2B3,
965 input RSTB0B1, RSTB2B3,
966 input CEC, RSTC,
967 input CECTRL, RSTCTRL,
968 input SIGNED,
969 input RSTPIPE, CEPIPE,
970 input RSTOUT, CEOUT,
971 input LOADC,
972 input [3:0] ADDSUB,
973 output [53:0] Z
974 );
975 wire [17:0] m0, m1, m2, m3;
976
977 localparam M_WIDTH = 18;
978 localparam Z_WIDTH = 54;
979
980 MULT9X9 #(
981 .REGINPUTA(REGINPUTAB0), .REGINPUTB(REGINPUTAB0), .REGOUTPUT(REGPIPELINE), .GSR(GSR), .RESETMODE(RESETMODE)
982 ) m9_0 (
983 .A(A0), .B(B0), .SIGNEDA(SIGNED), .SIGNEDB(SIGNED),
984 .CLK(CLK),
985 .CEA(CEA0A1), .RSTA(RSTA0A1),
986 .CEB(CEB0B1), .RSTB(RSTB0B1),
987 .CEOUT(CEPIPE), .RSTOUT(RSTPIPE),
988 .Z(m0)
989 );
990 MULT9X9 #(
991 .REGINPUTA(REGINPUTAB1), .REGINPUTB(REGINPUTAB1), .REGOUTPUT(REGPIPELINE), .GSR(GSR), .RESETMODE(RESETMODE)
992 ) m9_1 (
993 .A(A1), .B(B1), .SIGNEDA(SIGNED), .SIGNEDB(SIGNED),
994 .CLK(CLK),
995 .CEA(CEA0A1), .RSTA(RSTA0A1),
996 .CEB(CEB0B1), .RSTB(RSTB0B1),
997 .CEOUT(CEPIPE), .RSTOUT(RSTPIPE),
998 .Z(m1)
999 );
1000 MULT9X9 #(
1001 .REGINPUTA(REGINPUTAB2), .REGINPUTB(REGINPUTAB2), .REGOUTPUT(REGPIPELINE), .GSR(GSR), .RESETMODE(RESETMODE)
1002 ) m9_2 (
1003 .A(A2), .B(B2), .SIGNEDA(SIGNED), .SIGNEDB(SIGNED),
1004 .CLK(CLK),
1005 .CEA(CEA2A3), .RSTA(RSTA2A3),
1006 .CEB(CEB2B3), .RSTB(RSTB2B3),
1007 .CEOUT(CEPIPE), .RSTOUT(RSTPIPE),
1008 .Z(m2)
1009 );
1010 MULT9X9 #(
1011 .REGINPUTA(REGINPUTAB3), .REGINPUTB(REGINPUTAB3), .REGOUTPUT(REGPIPELINE), .GSR(GSR), .RESETMODE(RESETMODE)
1012 ) m9_3 (
1013 .A(A3), .B(B3), .SIGNEDA(SIGNED), .SIGNEDB(SIGNED),
1014 .CLK(CLK),
1015 .CEA(CEA2A3), .RSTA(RSTA2A3),
1016 .CEB(CEB2B3), .RSTB(RSTB2B3),
1017 .CEOUT(CEPIPE), .RSTOUT(RSTPIPE),
1018 .Z(m3)
1019 );
1020
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;
1025
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});
1028
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);
1031
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});
1034
1035
1036 wire [18:0] m0_ext, m1_ext, m2_ext, m3_ext;
1037
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};
1042
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);
1045
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};
1048
1049 wire [53:0] c_op = loadc_r2 ? c_r2 : Z;
1050
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);
1055
1056 OXIDE_DSP_REG #(Z_WIDTH, REGOUTPUT, RESETMODE) z_reg(CLK, CEOUT, RSTOUT, z_d, Z);
1057
1058 endmodule