[wip] DSP48E1 sim model improvements
authorDavid Shah <dave@ds0.me>
Tue, 6 Aug 2019 12:23:42 +0000 (13:23 +0100)
committerDavid Shah <dave@ds0.me>
Tue, 6 Aug 2019 12:23:42 +0000 (13:23 +0100)
Signed-off-by: David Shah <dave@ds0.me>
techlibs/xilinx/cells_sim.v

index 33b2a8f620bf6f13175b74dd3cd4ded2500e3d4e..9437a057b966c8405f341215e37b23584e65e02f 100644 (file)
@@ -494,14 +494,81 @@ module DSP48E1 (
 `endif
     end
 
-    reg signed [29:0] Ar;
-    reg signed [17:0] Br;
+    reg signed [29:0] Ar1, Ar2;
+    reg signed [24:0] Dr;
+    reg signed [17:0] Br1, Br2;
     reg signed [47:0] Pr;
+    reg        [4:0]  INMODEr;
     generate
-        if (AREG == 1) begin always @(posedge CLK) if (CEA2) Ar <= A; end
-        else           always @* Ar <= A;
-        if (BREG == 1) begin always @(posedge CLK) if (CEB2) Br <= B; end
-        else           always @* Br <= B;
+        if (AREG == 2) begin
+            always @(posedge CLK)
+                if (RSTA) begin
+                    Ar1 <= 30'b0;
+                    Ar2 <= 30'b0;
+                end else begin
+                    if (CEA1) Ar1 <= A;
+                    if (CEA2) Ar2 <= Ar1;
+                end
+        end else if (AREG == 1) begin
+            always @(posedge CLK)
+                if (RSTA) begin
+                    Ar1 <= 30'b0;
+                    Ar2 <= 30'b0;
+                end else begin
+                    if (CEA1) Ar1 <= A;
+                    if (CEA2) Ar2 <= A;
+                end
+        end else begin
+            always @* Ar1 <= A;
+            always @* Ar2 <= A;
+        end
+
+        if (BREG == 2) begin
+            always @(posedge CLK)
+                if (RSTB) begin
+                    Br1 <= 18'b0;
+                    Br2 <= 18'b0;
+                end else begin
+                    if (CEB1) Br1 <= B;
+                    if (CEB2) Br2 <= Br1;
+                end
+        end else if (AREG == 1) begin
+            always @(posedge CLK)
+                if (RSTB) begin
+                    Br1 <= 18'b0;
+                    Br2 <= 18'b0;
+                end else begin
+                    if (CEB1) Br1 <= B;
+                    if (CEB2) Br2 <= B;
+                end
+        end else begin
+            always @* Br1 <= B;
+            always @* Br2 <= B;
+        end
+
+        if (DREG == 1) begin always @(posedge CLK) if (RSTD) Dr <= 25'b0; else if (CED) Dr <= D; end
+        else           always @* Dr <= D;
+
+        if (INMODEREG == 1) begin always @(posedge CLK) if (RSTINMODE) INMODEr <= 5'b0; else if (CEINMODE) INMODEr <= INMODE; end
+        else           always @* INMODEr <= INMODE;
+    endgenerate
+
+    wire signed [29:0] Ar12_muxed = INMODEr[0] ? Ar1 : Ar2;
+    wire signed [24:0] Ar12_gated = INMODEr[1] ? 25'b0 : Ar12_muxed;
+    wire signed [24:0] Dr_gated   = INMODEr[2] ? Dr : 25'b0;
+    wire signed [24:0] AD_result  = INMODEr[3] ? (Dr_gated - Ar12_gated) : (Dr_gated + Ar12_gated);
+    reg  signed [24:0] ADr;
+
+    generate
+        if (ADREG == 1) begin always @(posedge CLK) if (RSTD) ADr <= 25'b0; else if (CEAD) ADr <= AD_result; end
+        else            always @* ADr <= AD_result;
+    endgenerate
+
+    wire signed [24:0] A_MULT;
+    wire signed [24:0] B_MULT = INMODEr[4] ? Br1 : Br2;
+    generate
+        if (USE_DPORT == "TRUE") assign A_MULT = ADr;
+        else assign A_MULT = Ar12_gated;
     endgenerate
 
     always @* begin
@@ -516,11 +583,11 @@ module DSP48E1 (
         if (PCIN != 48'b0)          $fatal(1, "Unsupported PCIN value");
         if (CARRYIN != 1'b0)        $fatal(1, "Unsupported CARRYIN value");
 `endif
-        Pr[42:0] <= $signed(Ar[24:0]) * Br;
+        Pr[42:0] <= A_MULT * B_MULT;
     end
 
     generate
-        if (PREG == 1) begin always @(posedge CLK) if (CEP) P <= Pr; end
+        if (PREG == 1) begin always @(posedge CLK) if (RSTP) P <= 48'b0; else if (CEP) P <= Pr; end
         else           always @* P <= Pr;
     endgenerate