-
Notifications
You must be signed in to change notification settings - Fork 5
/
framebuffer.sv.bak
187 lines (132 loc) · 4.07 KB
/
framebuffer.sv.bak
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
/*
SRAM_thin_controller.sv
Finn Sinclair 2018
Basic two-port memory controller, dedicated read and write ports.
Separately clocked from main clock.
Customer modules should watch the appropriate active-high DataReady signal.
*/
module SRAM_thin_controller #(parameter tileDim = 8'd8)(
inout wire[15:0] SRAM_DQ,
output logic[19:0] SRAM_ADDR,
output logic SRAM_UB_N, SRAM_LB_N, SRAM_CE_N, SRAM_OE_N, SRAM_WE_N = 1,
input logic[9:0] xOffset, yOffset,
input logic VGA_VS,
input logic streamTile, // Trigger to begin streaming tile at (xOffset, yOffset)
input logic [17:0] SW,
input logic[19:0] ReadAddress,
input logic QueueReadReq,
input logic[15:0] tileA [tileDim][tileDim],
input logic[15:0] tileB [tileDim][tileDim],
output logic[17:0] LEDR,
output logic DataReady = 1,
output logic [15:0] DataFromSRAM,
input logic SRAM_CLK, //100 MHz SRAM clock, allow for "double data rate"
input logic BOARD_CLK //50 MHz FPGA clock, for incoming requests
);
logic[15:0] DataToSRAM;
logic[15:0] funDemo = 0;
//assign DataToSRAM = SW;
logic[19:0] WriteAddress = 0;
logic[7:0] tilePointerX = 0, tilePointerY = 0, nextTilePointerX = 0, nextTilePointerY = 0;
logic[19:0] tileOffsetX, tileOffsetY;
assign tileOffsetX = xOffset;
assign tileOffsetY = yOffset;
enum logic {
A = 1'b0,
B = 1'b1
} currentStreamingTile, nextStreamingTile;
enum logic [1:0]{
feedingVGA,
streaming,
idle
} state, nextState;
//logic[15:0] DQ_buffer; // tri-state buffer
logic lastOpRead = 0;
logic readSync = 0, lastReadSync;
logic ReadQueued, WriteQueued;
assign SRAM_CE_N = 0; // Always chip-enable
assign SRAM_UB_N = 0; // Always writing both bytes
assign SRAM_LB_N = 0;
assign SRAM_OE_N = 0; // Hmmm...
assign SRAM_DQ = ~SRAM_WE_N ? DataToSRAM : 16'bz;
assign DataToSRAM = SW;
assign WriteAddress = 0;
//assign WriteAddress = (tileOffsetX+tilePointerX) + (tileOffsetY+tilePointerY)*800;
//assign SRAM_ADDR = (state == feedingVGA) ? ReadAddress : WriteAddress;
//assign SRAM_ADDR = ReadAddress;
//assign SRAM_WE_N = (state == streaming);
//assign SRAM_WE_N = -1;
assign LEDR = tilePointerX;
always_ff @(posedge SRAM_CLK) begin: mainblock
readSync <= QueueReadReq;
lastReadSync <= readSync;
ReadQueued <= (readSync && (lastReadSync == 0));
if(QueueReadReq && DataReady == 1)
DataReady <= 0;
//At clock edge, read data from SRAM if last operation was a read
if(lastOpRead && state != idle) begin
DataReady <= 1;
ReadQueued <= 0;
DataFromSRAM <= SRAM_DQ; // Latch in output
end
if(state == feedingVGA) begin
lastOpRead <= 1; // So we fetch data next clock
SRAM_ADDR <= ReadAddress;
SRAM_WE_N <= 1;
end
else if(state == streaming) begin
lastOpRead <= 0;
SRAM_WE_N <= 0;
SRAM_ADDR <= WriteAddress;
end
state <= nextState;
tilePointerX <= nextTilePointerX;
tilePointerY <= nextTilePointerY;
end
// Intelligent round-robin queueing. Cascades to the next non-empty FIFO
// if the immediately adjacent FIFO is empty.
always_comb begin
nextStreamingTile = currentStreamingTile; // by default, usually the case
unique case(state)
feedingVGA: begin
nextState = streaming;
nextTilePointerX = tilePointerX;
nextTilePointerY = tilePointerY;
end
streaming, idle: begin
if(ReadQueued) begin
nextState = feedingVGA;
if(nextTilePointerX == 8'd7) begin
nextTilePointerX = 0;
nextTilePointerY = tilePointerY+1;
end
else begin
nextTilePointerX = tilePointerX + 1;
nextTilePointerY = tilePointerY;
end
end
else if(tilePointerY == 8'd7 && tilePointerX == 8'd7) begin
nextStreamingTile = currentStreamingTile == A ? B : A; // Switch tiles
nextState = idle;
nextTilePointerX = 0;
nextTilePointerY = 0;
end
else begin
nextState = streaming;
if(nextTilePointerX == 8'd7) begin
nextTilePointerX = 0;
nextTilePointerY = tilePointerY+1;
end
else begin
nextTilePointerX = tilePointerX + 1;
nextTilePointerY = tilePointerY;
end
end
end
default: begin
nextTilePointerX = tilePointerX;
nextTilePointerY = tilePointerY;
end
endcase
end
endmodule