diff options
| author | Alejandro Soto <alejandro@34project.org> | 2023-11-15 17:00:47 -0600 |
|---|---|---|
| committer | Alejandro Soto <alejandro@34project.org> | 2023-11-16 16:43:59 -0600 |
| commit | ba803067cb54edece9ffa8b92f9bb97317d082e5 (patch) | |
| tree | 4d94c1d3d82df91079d70407865f98472d0a16c9 /rtl/gfx | |
| parent | ebd16f54913aaafd0b6f86223f53fc40b2d64d03 (diff) | |
rtl/gfx: improve divider timing closure
Diffstat (limited to 'rtl/gfx')
| -rw-r--r-- | rtl/gfx/gfx_defs.sv | 3 | ||||
| -rw-r--r-- | rtl/gfx/gfx_fixed_div.sv | 26 | ||||
| -rw-r--r-- | rtl/gfx/gfx_pipes.sv | 9 |
3 files changed, 30 insertions, 8 deletions
diff --git a/rtl/gfx/gfx_defs.sv b/rtl/gfx/gfx_defs.sv index a9e711e..9ffa505 100644 --- a/rtl/gfx/gfx_defs.sv +++ b/rtl/gfx/gfx_defs.sv @@ -59,7 +59,8 @@ typedef struct packed `define FIXED_FRAC 16 -`define FIXED_DIV_STAGES 8 +`define FIXED_DIV_PIPES 2 +`define FIXED_DIV_STAGES (`FIXED_DIV_PIPES + $bits(fixed) + `FIXED_FRAC) `define FIXED_FMA_STAGES 5 `define FIXED_FMA_DOT_STAGES (2 * `FIXED_FMA_STAGES) `define LERP_STAGES `FIXED_FMA_DOT_STAGES diff --git a/rtl/gfx/gfx_fixed_div.sv b/rtl/gfx/gfx_fixed_div.sv index 320d9b8..e562072 100644 --- a/rtl/gfx/gfx_fixed_div.sv +++ b/rtl/gfx/gfx_fixed_div.sv @@ -13,10 +13,11 @@ module gfx_fixed_div localparam DIV_BITS = `FIXED_FRAC + $bits(fixed); + fixed d_hold, z_hold; logic signed[DIV_BITS - 1:0] z_int, q_int; assign q = q_int[$bits(q) - 1:0]; - assign z_int = {z, {`FIXED_FRAC{1'b0}}}; + assign z_int = {z_hold, {`FIXED_FRAC{1'b0}}}; `ifndef VERILATOR lpm_divide div @@ -25,7 +26,7 @@ module gfx_fixed_div .clock(clk), .clken(!stall), .numer(z_int), - .denom(d), + .denom(d_hold), .remain(), .quotient(q_int) ); @@ -34,13 +35,28 @@ module gfx_fixed_div div.lpm_widthn = DIV_BITS, div.lpm_widthd = $bits(fixed), div.lpm_nrepresentation = "SIGNED", - div.lpm_nrepresentation = "SIGNED", - div.lpm_pipeline = `FIXED_DIV_STAGES; + div.lpm_drepresentation = "SIGNED", + div.lpm_pipeline = `FIXED_DIV_STAGES - `FIXED_DIV_PIPES, + div.maximize_speed = 6; + + gfx_pipes #(.WIDTH($bits(z)), .DEPTH(`FIXED_DIV_PIPES)) z_pipes + ( + .in(z), + .out(z_hold), + .* + ); + + gfx_pipes #(.WIDTH($bits(d)), .DEPTH(`FIXED_DIV_PIPES)) d_pipes + ( + .in(d), + .out(d_hold), + .* + ); `else - fixed d_hold; logic signed[DIV_BITS - 1:0] d_int_hold, z_int_hold; assign q_int = z_int_hold / d_int_hold; + assign z_hold = z; assign d_int_hold = {{`FIXED_FRAC{d_hold[$bits(d_hold) - 1]}}, d_hold}; gfx_pipes #(.WIDTH($bits(z_int)), .DEPTH(`FIXED_DIV_STAGES)) z_int_pipes diff --git a/rtl/gfx/gfx_pipes.sv b/rtl/gfx/gfx_pipes.sv index 09b1d43..390a481 100644 --- a/rtl/gfx/gfx_pipes.sv +++ b/rtl/gfx/gfx_pipes.sv @@ -17,8 +17,13 @@ module gfx_pipes if (!stall) begin pipes[0] <= in; - for (integer i = 1; i < DEPTH; ++i) - pipes[i] <= pipes[i - 1]; + /* Esto tiene que ir así porque Verilator no soporta <= en for + * loops a las que no logre hacerle unrolling. Nótese que el + * orden de iteración descendiente es necesario porque estamos + * usando un blocking assignment dentro de always_ff. + */ + for (integer i = DEPTH - 1; i > 0; --i) + pipes[i] = pipes[i - 1]; end endmodule |
