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
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
|
`include "gfx/gfx_defs.sv"
module gfx_mem
(
input logic clk,
rst_n,
input logic mem_waitrequest,
mem_readdatavalid,
input vram_word mem_readdata,
output vram_byte_addr mem_address,
output logic mem_read,
mem_write,
output vram_word mem_writedata,
input vram_addr host_address,
input logic host_read,
host_write,
input vram_word host_writedata,
output logic host_waitrequest,
host_readdatavalid,
output vram_word host_readdata,
input logic rop_write,
input vram_word rop_writedata,
input vram_addr rop_address,
output logic rop_waitrequest,
input logic fb_read,
input vram_addr fb_address,
output logic fb_waitrequest,
fb_readdatavalid,
output vram_word fb_readdata,
input logic batch_read,
input vram_addr batch_address,
output logic batch_waitrequest,
batch_readdatavalid,
output vram_word batch_readdata,
input logic fetch_read,
input vram_addr fetch_address,
output logic fetch_waitrequest,
fetch_readdatavalid,
output vram_word fetch_readdata
);
// Este módulo es inaceptable, hay que reescribirlo
logic mem_rw, trans_in_stall, trans_out_stall, in_ready, in_valid, skid_in_valid, out_ready,
any_readdatavalid, readdatavalid, dispatch_full, dispatch_put, mem_ready;
vram_word any_readdata, readdata;
logic[$clog2(`GFX_MEM_DISPATCH_DEPTH) - 1:0] next_put_ptr, pop_ptr, put_ptr;
struct packed
{
logic fb,
host,
batch,
fetch;
} dispatch_in, dispatch_out, dispatch_buf[`GFX_MEM_DISPATCH_DEPTH];
struct packed
{
vram_addr address;
logic write,
fb_waitrequest,
host_waitrequest,
batch_waitrequest,
fetch_waitrequest;
vram_word writedata;
} trans_in, trans_out, trans_in_skid, trans_out_skid;
assign mem_read = mem_rw && !trans_out_skid.write && !dispatch_full;
assign mem_write = mem_rw && trans_out_skid.write;
assign mem_address = {trans_out_skid.address, {`GFX_MEM_SUBWORD_BITS{1'b0}}};
assign mem_writedata = trans_out_skid.writedata;
assign fb_readdata = any_readdata;
assign host_readdata = any_readdata;
assign batch_readdata = any_readdata;
assign fetch_readdata = any_readdata;
assign fb_readdatavalid = any_readdatavalid && dispatch_out.fb;
assign host_readdatavalid = any_readdatavalid && dispatch_out.host;
assign batch_readdatavalid = any_readdatavalid && dispatch_out.batch;
assign fetch_readdatavalid = any_readdatavalid && dispatch_out.fetch;
assign dispatch_in.fb = !trans_out_skid.fb_waitrequest;
assign dispatch_in.host = !trans_out_skid.host_waitrequest;
assign dispatch_in.batch = !trans_out_skid.batch_waitrequest;
assign dispatch_in.fetch = !trans_out_skid.fetch_waitrequest;
assign in_valid = rop_write || fb_read || batch_read || fetch_read || host_read || host_write;
assign mem_ready = !mem_waitrequest && (!dispatch_full || trans_out_skid.write);
assign next_put_ptr = put_ptr + 1;
assign dispatch_put = mem_ready && mem_rw && !trans_out_skid.write;
assign dispatch_full = next_put_ptr == pop_ptr;
/* Cerrar timing aquí no es tan fácil, debido al enrutamiento al el que
* necesariamente está sujeto este módulo (eg, VRAM y DAC están en
* posiciones fijas en los bordes de la FPGA y no pueden reacomodarse).
*/
gfx_skid_buf #(.WIDTH($bits(trans_in))) in_skid
(
.in(trans_in),
.out(trans_in_skid),
.stall(trans_in_stall),
.*
);
gfx_skid_flow in_flow
(
.stall(trans_in_stall),
.out_ready(out_ready),
.out_valid(skid_in_valid),
.*
);
gfx_pipes #(.WIDTH($bits(trans_out)), .DEPTH(`GFX_MEM_TRANS_DEPTH)) out_pipes
(
.in(trans_in_skid),
.out(trans_out),
.stall(trans_out_stall),
.*
);
gfx_skid_buf #(.WIDTH($bits(trans_out))) out_skid
(
.in(trans_out),
.out(trans_out_skid),
.stall(trans_out_stall),
.*
);
gfx_pipeline_flow #(.STAGES(`GFX_MEM_TRANS_DEPTH)) out_flow
(
.stall(trans_out_stall),
.in_ready(out_ready),
.in_valid(skid_in_valid),
.out_ready(mem_ready),
.out_valid(mem_rw),
.*
);
gfx_pipes #(.WIDTH($bits(vram_word)), .DEPTH(`GFX_MEM_RESPONSE_DEPTH)) readdata_pipes
(
.in(mem_readdata),
.out(readdata),
.stall(0),
.*
);
gfx_pipeline_flow #(.STAGES(`GFX_MEM_RESPONSE_DEPTH)) readdata_flow
(
.stall(),
.in_ready(),
.in_valid(mem_readdatavalid),
.out_ready(1),
.out_valid(readdatavalid),
.*
);
always_comb begin
fb_waitrequest = 1;
rop_waitrequest = 1;
host_waitrequest = 1;
batch_waitrequest = 1;
fetch_waitrequest = 1;
trans_in.write = 0;
trans_in.writedata = {($bits(trans_in.writedata)){1'bx}};
if (fb_read) begin
fb_waitrequest = !in_ready;
trans_in.address = fb_address;
end else if (batch_read) begin
batch_waitrequest = !in_ready;
trans_in.address = batch_address;
end else if (rop_write) begin
rop_waitrequest = !in_ready;
trans_in.write = 1;
trans_in.address = rop_address;
trans_in.writedata = rop_writedata;
end else if (fetch_read) begin
fetch_waitrequest = !in_ready;
trans_in.address = fetch_address;
end else begin
host_waitrequest = !in_ready;
trans_in.write = host_write;
trans_in.address = host_address;
trans_in.writedata = host_writedata;
end
trans_in.fb_waitrequest = fb_waitrequest;
trans_in.host_waitrequest = host_waitrequest;
trans_in.batch_waitrequest = batch_waitrequest;
trans_in.fetch_waitrequest = fetch_waitrequest;
end
always_ff @(posedge clk or negedge rst_n)
if (!rst_n) begin
pop_ptr <= 0;
put_ptr <= 0;
end else begin
if (readdatavalid)
pop_ptr <= pop_ptr + 1;
if (dispatch_put)
put_ptr <= next_put_ptr;
end
always_ff @(posedge clk) begin
any_readdata <= readdata;
any_readdatavalid <= readdatavalid;
dispatch_out <= dispatch_buf[pop_ptr];
if (dispatch_put)
dispatch_buf[put_ptr] <= dispatch_in;
end
endmodule
|