summaryrefslogtreecommitdiff
path: root/platform
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--platform/wavelet3d/gfx_fixed_dotadd.sv55
-rw-r--r--platform/wavelet3d/gfx_fixed_muladd.sv77
-rw-r--r--platform/wavelet3d/gfx_pkg.sv23
3 files changed, 153 insertions, 2 deletions
diff --git a/platform/wavelet3d/gfx_fixed_dotadd.sv b/platform/wavelet3d/gfx_fixed_dotadd.sv
new file mode 100644
index 0000000..fdd5ffd
--- /dev/null
+++ b/platform/wavelet3d/gfx_fixed_dotadd.sv
@@ -0,0 +1,55 @@
+module gfx_fixed_dotadd
+(
+ input logic clk,
+
+ input gfx::fixed a0,
+ b0,
+ a1,
+ b1,
+ c,
+ input logic stall,
+
+ output gfx::fixed q
+);
+
+ import gfx::*;
+
+ fixed q0, a1_hold, b1_hold;
+
+ gfx_fixed_muladd muladd_0
+ (
+ .clk,
+ .a(a0),
+ .b(b0),
+ .c,
+ .q(q0),
+ .stall
+ );
+
+ gfx_pipes #(.WIDTH($bits(fixed)), .DEPTH(FIXED_MULADD_DEPTH)) a_pipes
+ (
+ .clk,
+ .in(a1),
+ .out(a1_hold),
+ .stall
+ );
+
+ gfx_pipes #(.WIDTH($bits(fixed)), .DEPTH(FIXED_MULADD_DEPTH)) b_pipes
+ (
+ .clk,
+ .in(b1),
+ .out(b1_hold),
+ .stall
+ );
+
+ gfx_fixed_muladd muladd_1
+ (
+ .clk,
+ .a(a1_hold),
+ .b(b1_hold),
+ .c(q0),
+ .q,
+ .stall
+ );
+
+endmodule
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
diff --git a/platform/wavelet3d/gfx_pkg.sv b/platform/wavelet3d/gfx_pkg.sv
index 72c8f80..53bb8cd 100644
--- a/platform/wavelet3d/gfx_pkg.sv
+++ b/platform/wavelet3d/gfx_pkg.sv
@@ -3,11 +3,17 @@ package gfx;
localparam int SHADER_LANES = 4;
typedef logic[31:0] word;
- typedef logic[63:0] dword;
localparam int SUBWORD_BITS = $clog2($bits(word)) - $clog2($bits(byte));
localparam int BYTES_PER_WORD = 1 << SUBWORD_BITS;
+ typedef word uword;
+ typedef logic signed[$bits(word) - 1:0] sword;
+ typedef logic[$bits(word) / 2 - 1:0] uhword;
+ typedef logic signed[$bits(word) / 2 - 1:0] shword;
+ typedef logic[2 * $bits(word) - 1:0] udword;
+ typedef logic signed[2 * $bits(word) - 1:0] sdword;
+
typedef logic[7:0] float_exp;
typedef logic[$bits(word) - $bits(float_exp) - 2:0] float_mant;
typedef logic[$bits(float_mant):0] float_mant_full; // Incluye '1.' explícito
@@ -112,7 +118,7 @@ package gfx;
float_exp exp;
float_class a_class,
b_class;
- dword product;
+ udword product;
logic sign,
overflow;
} fpint_mulclass_mnorm;
@@ -224,6 +230,19 @@ package gfx;
overflow;
} fpint_rnorm_encode;
+ // Q22.10
+ typedef logic[9:0] fixed_frac;
+ typedef logic[$bits(word) - $bits(fixed_frac) - 1:0] fixed_int;
+
+ typedef struct packed signed
+ {
+ fixed_int fint; // 'int' es una keyword
+ fixed_frac frac;
+ } fixed;
+
+ localparam int FIXED_MULADD_DEPTH = 5;
+ localparam int FIXED_DOTADD_DEPTH = 2 * FIXED_MULADD_DEPTH;
+
localparam int SCHED_BRAM_WORDS = 2048; // 8KiB
typedef word irq_lines;