summaryrefslogtreecommitdiff
path: root/rtl/legacy_gfx/gfx_fixed_fma.sv
diff options
context:
space:
mode:
authorAlejandro Soto <alejandro@34project.org>2024-05-05 17:34:22 -0600
committerAlejandro Soto <alejandro@34project.org>2024-05-05 17:38:27 -0600
commit081a8a3ba8bfe036f31da53f9c041a2caa30fce2 (patch)
tree7d712b67d3dc1ad3d37041562774ba3c4e5a7f49 /rtl/legacy_gfx/gfx_fixed_fma.sv
parente5b64ea353678baabd16d245fcfaa3384e1acf8f (diff)
rtl/legacy_gfx: rename gfx -> legacy_gfx
Diffstat (limited to 'rtl/legacy_gfx/gfx_fixed_fma.sv')
-rw-r--r--rtl/legacy_gfx/gfx_fixed_fma.sv73
1 files changed, 73 insertions, 0 deletions
diff --git a/rtl/legacy_gfx/gfx_fixed_fma.sv b/rtl/legacy_gfx/gfx_fixed_fma.sv
new file mode 100644
index 0000000..ec26477
--- /dev/null
+++ b/rtl/legacy_gfx/gfx_fixed_fma.sv
@@ -0,0 +1,73 @@
+`include "gfx/gfx_defs.sv"
+
+module gfx_fixed_fma
+(
+ input logic clk,
+
+ input fixed a,
+ b,
+ c,
+ input logic stall,
+
+ output fixed q
+);
+
+`ifndef VERILATOR
+ logic[2 * $bits(fixed) - `FIXED_FRAC - 1:0] q_ext;
+ assign q = q_ext[$bits(fixed) - 1:0];
+
+ lpm_mult mult
+ (
+ .aclr(0),
+ .clock(clk),
+ .clken(!stall),
+
+ .sum({c, {`FIXED_FRAC{1'b0}}}),
+ .dataa(a),
+ .datab(b),
+ .result(q_ext)
+ );
+
+ defparam
+ mult.lpm_widtha = $bits(fixed),
+ mult.lpm_widthb = $bits(fixed),
+ mult.lpm_widths = $bits(fixed) + `FIXED_FRAC,
+ /* Esto es crucial. No está documentado en ningún lado (aparte de un
+ * comentario en r/fpga). Si lpm_widthp < lpm_widtha + lpm_widthb,
+ * entonces result contiene los lpm_widthp bits más significativos
+ * del producto, no los menos significativos como tendría sentido.
+ */
+ mult.lpm_widthp = 2 * $bits(fixed) - `FIXED_FRAC,
+ mult.lpm_representation = "SIGNED",
+ mult.lpm_pipeline = `FIXED_FMA_STAGES;
+`else
+ logic[$bits(fixed) + `FIXED_FRAC - 1:0] q_ext;
+
+ fixed a_hold, b_hold, c_hold;
+
+ assign q = q_ext[$bits(fixed) + `FIXED_FRAC - 1:`FIXED_FRAC] + c_hold;
+ assign q_ext = a_hold * b_hold;
+
+ gfx_pipes #(.WIDTH($bits(a)), .DEPTH(`FIXED_FMA_STAGES)) a_pipes
+ (
+ .in(a),
+ .out(a_hold),
+ .*
+ );
+
+ gfx_pipes #(.WIDTH($bits(b)), .DEPTH(`FIXED_FMA_STAGES)) b_pipes
+ (
+ .in(b),
+ .out(b_hold),
+ .*
+ );
+
+ gfx_pipes #(.WIDTH($bits(c)), .DEPTH(`FIXED_FMA_STAGES)) c_pipes
+ (
+ .in(c),
+ .out(c_hold),
+ .*
+ );
+`endif
+
+endmodule