summaryrefslogtreecommitdiff
path: root/rtl/gfx/gfx_assembly.sv
diff options
context:
space:
mode:
Diffstat (limited to 'rtl/gfx/gfx_assembly.sv')
-rw-r--r--rtl/gfx/gfx_assembly.sv89
1 files changed, 89 insertions, 0 deletions
diff --git a/rtl/gfx/gfx_assembly.sv b/rtl/gfx/gfx_assembly.sv
new file mode 100644
index 0000000..1a909be
--- /dev/null
+++ b/rtl/gfx/gfx_assembly.sv
@@ -0,0 +1,89 @@
+`include "gfx/gfx_defs.sv"
+
+module gfx_assembly
+(
+ input logic clk,
+ rst_n,
+
+ input lane_word send_data,
+ input lane_mask send_mask,
+ input logic send_valid,
+ output logic send_ready,
+
+ input logic out_ready,
+ output logic out_valid,
+ output fp_xyzw out_vertex_a,
+ out_vertex_b,
+ out_vertex_c
+);
+
+ localparam SETS_PER_TRI = 6;
+
+ mat4 sets[SETS_PER_TRI];
+ logic assemble_next, permit_out;
+ lane_mask current_mask, next_mask;
+ logic[1:0] out_lane;
+ logic[2:0] set_num;
+
+ enum int unsigned
+ {
+ GET_LANES,
+ ASSEMBLE
+ } state;
+
+ assign out_valid = permit_out && current_mask[out_lane];
+ assign out_vertex_a = sets[0][out_lane];
+ assign out_vertex_b = sets[2][out_lane];
+ assign out_vertex_c = sets[4][out_lane];
+
+ assign next_mask = current_mask & send_mask;
+ assign assemble_next = !current_mask[out_lane] || out_ready;
+
+ always_ff @(posedge clk or negedge rst_n)
+ if (!rst_n) begin
+ state <= GET_LANES;
+ set_num <= 0;
+ out_lane <= 0;
+ permit_out <= 0;
+ send_ready <= 1;
+ current_mask <= {($bits(current_mask)){1'b1}};
+ end else unique case (state)
+ GET_LANES:
+ if (send_valid) begin
+ set_num <= set_num + 1;
+ current_mask <= next_mask;
+
+ if (set_num == SETS_PER_TRI - 1) begin
+ state <= ASSEMBLE;
+ permit_out <= 1;
+ send_ready <= 0;
+ end
+
+ if (!(|next_mask)) begin
+ state <= GET_LANES;
+ set_num <= 0;
+ current_mask <= {($bits(current_mask)){1'b1}};
+ end
+ end
+
+ ASSEMBLE:
+ if (assemble_next) begin
+ out_lane <= out_lane + 1;
+ if (&out_lane) begin
+ state <= GET_LANES;
+ permit_out <= 0;
+ send_ready <= 1;
+ end
+ end
+ endcase
+
+ always_ff @(posedge clk)
+ unique case (state)
+ GET_LANES:
+ if (send_valid)
+ sets[set_num] <= send_data;
+
+ ASSEMBLE: ;
+ endcase
+
+endmodule