summaryrefslogtreecommitdiff
path: root/rtl/legacy_gfx/gfx_assembly.sv
blob: 1a909bea7850b63723ca4fb1278ed9ae23b583ac (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
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