summaryrefslogtreecommitdiff
path: root/platform/wavelet3d/gfx_fixed_muladd.sv
diff options
context:
space:
mode:
Diffstat (limited to 'platform/wavelet3d/gfx_fixed_muladd.sv')
-rw-r--r--platform/wavelet3d/gfx_fixed_muladd.sv77
1 files changed, 77 insertions, 0 deletions
diff --git a/platform/wavelet3d/gfx_fixed_muladd.sv b/platform/wavelet3d/gfx_fixed_muladd.sv
new file mode 100644
index 0000000..22b7247
--- /dev/null
+++ b/platform/wavelet3d/gfx_fixed_muladd.sv
@@ -0,0 +1,77 @@
+module gfx_fixed_muladd
+(
+ input logic clk,
+
+ input gfx::fixed a,
+ b,
+ c,
+ input logic stall,
+
+ output gfx::fixed q
+);
+
+ import gfx::*;
+
+`ifndef VERILATOR
+ logic[2 * $bits(fixed) - $bits(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) + $bits(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) - $bits(fixed_frac),
+ mult.lpm_representation = "SIGNED",
+ mult.lpm_pipeline = FIXED_MULADD_DEPTH;
+`else
+ logic[$bits(fixed) + $bits(fixed_frac) - 1:0] q_ext;
+
+ fixed a_hold, b_hold, c_hold;
+
+ assign q = q_ext[$bits(fixed) + $bits(fixed_frac) - 1:$bits(fixed_frac)] + c_hold;
+ assign q_ext = a_hold * b_hold;
+
+ gfx_pipes #(.WIDTH($bits(a)), .DEPTH(FIXED_MULADD_DEPTH)) a_pipes
+ (
+ .clk,
+ .in(a),
+ .out(a_hold),
+ .stall
+ );
+
+ gfx_pipes #(.WIDTH($bits(b)), .DEPTH(FIXED_MULADD_DEPTH)) b_pipes
+ (
+ .clk,
+ .in(b),
+ .out(b_hold),
+ .stall
+ );
+
+ gfx_pipes #(.WIDTH($bits(c)), .DEPTH(FIXED_MULADD_DEPTH)) c_pipes
+ (
+ .clk,
+ .in(c),
+ .out(c_hold),
+ .stall
+ );
+`endif
+
+endmodule