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
|
`include "gfx/gfx_defs.sv"
module gfx_mem
(
input logic clk,
rst_n,
input logic mem_waitrequest,
mem_readdatavalid,
input mem_word mem_readdata,
output mem_addr mem_address,
output logic mem_read,
mem_write,
output mem_word mem_writedata,
input logic rop_write,
input mem_word rop_writedata,
input half_coord rop_address,
output logic rop_waitrequest,
input logic fb_read,
input half_coord fb_address,
output logic fb_waitrequest,
fb_readdatavalid,
output mem_word fb_readdata
);
// Esto está mal, hay que reescribirlo totalmente
logic mem_rw, trans_in_stall, trans_out_stall, in_ready, skid_in_valid, out_ready;
struct packed
{
mem_addr address;
logic write;
mem_word writedata;
} trans_in, trans_out, trans_in_skid, trans_out_skid;
/* 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),
.in_ready(in_ready),
.in_valid(rop_write || fb_read),
.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_waitrequest),
.out_valid(mem_rw),
.*
);
gfx_pipes #(.WIDTH($bits(mem_word)), .DEPTH(`GFX_MEM_FIFO_DEPTH)) readdata_pipes
(
.in(mem_readdata),
.out(fb_readdata),
.stall(0),
.*
);
gfx_pipeline_flow #(.STAGES(`GFX_MEM_FIFO_DEPTH)) readdata_flow
(
.stall(),
.in_ready(),
.in_valid(mem_readdatavalid),
.out_ready(1),
.out_valid(fb_readdatavalid),
.*
);
assign mem_read = mem_rw && !trans_out_skid.write;
assign mem_write = mem_rw && trans_out_skid.write;
assign mem_address = trans_out_skid.address;
assign mem_writedata = trans_out_skid.writedata;
always_comb begin
fb_waitrequest = 1;
rop_waitrequest = 1;
trans_in.writedata = rop_writedata;
if (fb_read) begin
fb_waitrequest = !in_ready;
trans_in.write = 0;
trans_in.address = {6'd0, fb_address};
end else begin
rop_waitrequest = !in_ready;
trans_in.write = 1;
trans_in.address = {6'd0, rop_address};
end
end
endmodule
|