1 |
25 |
robfinch |
`timescale 1ns / 1ps
|
2 |
|
|
// ============================================================================
|
3 |
|
|
// __
|
4 |
|
|
// \\__/ o\ (C) 2008-2023 Robert Finch, Waterloo
|
5 |
|
|
// \ __ / All rights reserved.
|
6 |
|
|
// \/_// robfinch@finitron.ca
|
7 |
|
|
// ||
|
8 |
|
|
//
|
9 |
|
|
// rfFrameBuffer_fta64.sv
|
10 |
|
|
// - Displays a bitmap from memory.
|
11 |
|
|
//
|
12 |
|
|
//
|
13 |
|
|
// BSD 3-Clause License
|
14 |
|
|
// Redistribution and use in source and binary forms, with or without
|
15 |
|
|
// modification, are permitted provided that the following conditions are met:
|
16 |
|
|
//
|
17 |
|
|
// 1. Redistributions of source code must retain the above copyright notice, this
|
18 |
|
|
// list of conditions and the following disclaimer.
|
19 |
|
|
//
|
20 |
|
|
// 2. Redistributions in binary form must reproduce the above copyright notice,
|
21 |
|
|
// this list of conditions and the following disclaimer in the documentation
|
22 |
|
|
// and/or other materials provided with the distribution.
|
23 |
|
|
//
|
24 |
|
|
// 3. Neither the name of the copyright holder nor the names of its
|
25 |
|
|
// contributors may be used to endorse or promote products derived from
|
26 |
|
|
// this software without specific prior written permission.
|
27 |
|
|
//
|
28 |
|
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
29 |
|
|
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
30 |
|
|
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
31 |
|
|
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
32 |
|
|
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
33 |
|
|
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
34 |
|
|
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
35 |
|
|
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
36 |
|
|
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
37 |
|
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
38 |
|
|
//
|
39 |
|
|
//
|
40 |
|
|
// The default base screen address is:
|
41 |
|
|
// $0200000 - the third meg of RAM
|
42 |
|
|
//
|
43 |
|
|
// ============================================================================
|
44 |
|
|
|
45 |
|
|
//`define USE_CLOCK_GATE 1'b1
|
46 |
|
|
`define INTERNAL_SYNC_GEN 1'b1
|
47 |
|
|
`define WXGA800x600 1'b1
|
48 |
|
|
//`define WXGA1366x768 1'b1
|
49 |
|
|
`define FBC_ADDR 32'hFD0400001
|
50 |
|
|
|
51 |
|
|
import const_pkg::*;
|
52 |
|
|
`define ABITS 31:0
|
53 |
|
|
|
54 |
|
|
import fta_bus_pkg::*;
|
55 |
|
|
import gfx_pkg::*;
|
56 |
|
|
|
57 |
|
|
module rfFrameBuffer_fta64(
|
58 |
|
|
rst_i,
|
59 |
|
|
irq_o,
|
60 |
|
|
cs_config_i,
|
61 |
|
|
cs_io_i,
|
62 |
|
|
s_clk_i, s_req, s_resp,
|
63 |
|
|
m_clk_i, m_fst_o,
|
64 |
|
|
// m_cyc_o, m_stb_o, m_ack_i, m_we_o, m_sel_o, m_adr_o, m_dat_i, m_dat_o,
|
65 |
|
|
m_req, m_resp,
|
66 |
|
|
dot_clk_i, rgb_i, rgb_o, xonoff_i, xal_o
|
67 |
|
|
`ifdef INTERNAL_SYNC_GEN
|
68 |
|
|
, hsync_o, vsync_o, blank_o, border_o, hctr_o, vctr_o, fctr_o, vblank_o
|
69 |
|
|
`else
|
70 |
|
|
, hsync_i, vsync_i, blank_i
|
71 |
|
|
`endif
|
72 |
|
|
);
|
73 |
|
|
parameter BUSWID = 64;
|
74 |
|
|
|
75 |
|
|
parameter FBC_ADDR = 32'hFED70001;
|
76 |
|
|
parameter FBC_ADDR_MASK = 32'h00FF0000;
|
77 |
|
|
|
78 |
|
|
parameter CFG_BUS = 8'd0;
|
79 |
|
|
parameter CFG_DEVICE = 5'd0;
|
80 |
|
|
parameter CFG_FUNC = 3'd0;
|
81 |
|
|
parameter CFG_VENDOR_ID = 16'h0;
|
82 |
|
|
parameter CFG_DEVICE_ID = 16'h0;
|
83 |
|
|
parameter CFG_SUBSYSTEM_VENDOR_ID = 16'h0;
|
84 |
|
|
parameter CFG_SUBSYSTEM_ID = 16'h0;
|
85 |
|
|
parameter CFG_ROM_ADDR = 32'hFFFFFFF0;
|
86 |
|
|
|
87 |
|
|
parameter CFG_REVISION_ID = 8'd0;
|
88 |
|
|
parameter CFG_PROGIF = 8'd1;
|
89 |
|
|
parameter CFG_SUBCLASS = 8'h80; // 80 = Other
|
90 |
|
|
parameter CFG_CLASS = 8'h03; // 03 = display controller
|
91 |
|
|
parameter CFG_CACHE_LINE_SIZE = 8'd8; // 32-bit units
|
92 |
|
|
parameter CFG_MIN_GRANT = 8'h00;
|
93 |
|
|
parameter CFG_MAX_LATENCY = 8'h00;
|
94 |
|
|
parameter CFG_IRQ_LINE = 8'd6;
|
95 |
|
|
|
96 |
|
|
localparam CFG_HEADER_TYPE = 8'h00; // 00 = a general device
|
97 |
|
|
|
98 |
|
|
parameter MSIX = 1'b0;
|
99 |
|
|
parameter IRQ_MSGADR = 64'h0FD0900C1;
|
100 |
|
|
parameter IRQ_MSGDAT = 64'h1;
|
101 |
|
|
|
102 |
|
|
parameter PHYS_ADDR_BITS = 32;
|
103 |
|
|
localparam BITS_IN_ADDR_MAP = PHYS_ADDR_BITS - 16;
|
104 |
|
|
|
105 |
|
|
parameter MDW = 128; // Bus master data width
|
106 |
|
|
parameter MAP = 12'd0;
|
107 |
|
|
parameter BM_BASE_ADDR1 = 32'h00000000;
|
108 |
|
|
parameter BM_BASE_ADDR2 = 32'h00100000;
|
109 |
|
|
parameter REG_CTRL = 11'd0;
|
110 |
|
|
parameter REG_REFDELAY = 11'd1;
|
111 |
|
|
parameter REG_PAGE1ADDR = 11'd2;
|
112 |
|
|
parameter REG_PAGE2ADDR = 11'd3;
|
113 |
|
|
parameter REG_PXYZ = 11'd4;
|
114 |
|
|
parameter REG_PCOLCMD = 11'd5;
|
115 |
|
|
parameter REG_TOTAL = 11'd8;
|
116 |
|
|
parameter REG_SYNC_ONOFF = 11'd9;
|
117 |
|
|
parameter REG_BLANK_ONOFF = 11'd10;
|
118 |
|
|
parameter REG_BORDER_ONOFF = 11'd11;
|
119 |
|
|
parameter REG_RASTCMP = 11'd12;
|
120 |
|
|
parameter REG_BMPSIZE = 11'd13;
|
121 |
|
|
parameter REG_OOB_COLOR = 11'd14;
|
122 |
|
|
parameter REG_WINDOW = 11'd15;
|
123 |
|
|
parameter REG_IRQ_MSGADR = 11'd16;
|
124 |
|
|
parameter REG_IRQ_MSGDAT = 11'd17;
|
125 |
|
|
parameter REG_TRANS_COLOR = 11'd18;
|
126 |
|
|
|
127 |
|
|
parameter OPBLACK = 4'd0;
|
128 |
|
|
parameter OPCOPY = 4'd1;
|
129 |
|
|
parameter OPINV = 4'd2;
|
130 |
|
|
parameter OPAND = 4'd4;
|
131 |
|
|
parameter OPOR = 4'd5;
|
132 |
|
|
parameter OPXOR = 4'd6;
|
133 |
|
|
parameter OPANDN = 4'd7;
|
134 |
|
|
parameter OPNAND = 4'd8;
|
135 |
|
|
parameter OPNOR = 4'd9;
|
136 |
|
|
parameter OPXNOR = 4'd10;
|
137 |
|
|
parameter OPORN = 4'd11;
|
138 |
|
|
parameter OPWHITE = 4'd15;
|
139 |
|
|
|
140 |
|
|
// Sync Generator defaults: 800x600 60Hz
|
141 |
|
|
// Driven by a 40MHz clock
|
142 |
|
|
`ifdef WXGA800x600
|
143 |
|
|
parameter phSyncOn = 40; // 40 front porch
|
144 |
|
|
parameter phSyncOff = 168; // 128 sync
|
145 |
|
|
parameter phBlankOff = 252; //256 // 88 back porch
|
146 |
|
|
//parameter phBorderOff = 336; // 80 border
|
147 |
|
|
parameter phBorderOff = 256; // 80 border
|
148 |
|
|
//parameter phBorderOn = 976; // 640 display
|
149 |
|
|
parameter phBorderOn = 1056; // 800 display
|
150 |
|
|
parameter phBlankOn = 1052; // 4 border
|
151 |
|
|
parameter phTotal = 1056; // 1056 total clocks
|
152 |
|
|
parameter pvSyncOn = 1; // 1 front porch
|
153 |
|
|
parameter pvSyncOff = 5; // 4 vertical sync
|
154 |
|
|
parameter pvBlankOff = 28; // 23 back porch
|
155 |
|
|
parameter pvBorderOff = 28; // 44 border 0
|
156 |
|
|
//parameter pvBorderOff = 72; // 44 border 0
|
157 |
|
|
parameter pvBorderOn = 628; // 600 display
|
158 |
|
|
//parameter pvBorderOn = 584; // 512 display
|
159 |
|
|
parameter pvBlankOn = 628; // 44 border 0
|
160 |
|
|
parameter pvTotal = 628; // 628 total scan lines
|
161 |
|
|
`endif
|
162 |
|
|
`ifdef WXGA1366x768
|
163 |
|
|
// Driven by an 85.86MHz clock
|
164 |
|
|
parameter phSyncOn = 72; // 72 front porch
|
165 |
|
|
parameter phSyncOff = 216; // 144 sync
|
166 |
|
|
parameter phBlankOff = 434; // 212 back porch
|
167 |
|
|
parameter phBorderOff = 434; // 0 border
|
168 |
|
|
parameter phBorderOn = 1800; // 1366 display
|
169 |
|
|
parameter phBlankOn = 1800; // 0 border
|
170 |
|
|
parameter phTotal = 1800; // 1800 total clocks
|
171 |
|
|
// 47.7 = 60 * 795 kHz
|
172 |
|
|
parameter pvSyncOn = 2; // 1 front porch
|
173 |
|
|
parameter pvSyncOff = 5; // 3 vertical sync
|
174 |
|
|
parameter pvBlankOff = 27; // 23 back porch
|
175 |
|
|
parameter pvBorderOff = 27; // 2 border 0
|
176 |
|
|
parameter pvBorderOn = 795; // 768 display
|
177 |
|
|
parameter pvBlankOn = 795; // 1 border 0
|
178 |
|
|
parameter pvTotal = 795; // 795 total scan lines
|
179 |
|
|
`endif
|
180 |
|
|
|
181 |
|
|
// SYSCON
|
182 |
|
|
input rst_i; // system reset
|
183 |
|
|
output reg [31:0] irq_o;
|
184 |
|
|
|
185 |
|
|
input cs_config_i;
|
186 |
|
|
input cs_io_i;
|
187 |
|
|
|
188 |
|
|
// Peripheral IO slave port
|
189 |
|
|
input s_clk_i;
|
190 |
|
|
input fta_cmd_request64_t s_req;
|
191 |
|
|
output fta_cmd_response64_t s_resp;
|
192 |
|
|
|
193 |
|
|
// Video Memory Master Port
|
194 |
|
|
// Used to read memory via burst access
|
195 |
|
|
input m_clk_i; // system bus interface clock
|
196 |
|
|
output reg m_fst_o; // first access on scanline
|
197 |
|
|
output fta_cmd_request128_t m_req;
|
198 |
|
|
input fta_cmd_response128_t m_resp;
|
199 |
|
|
|
200 |
|
|
// Video
|
201 |
|
|
input dot_clk_i; // Video clock 80 MHz
|
202 |
|
|
`ifdef INTERNAL_SYNC_GEN
|
203 |
|
|
output hsync_o;
|
204 |
|
|
output vsync_o;
|
205 |
|
|
output blank_o;
|
206 |
|
|
output vblank_o;
|
207 |
|
|
output border_o;
|
208 |
|
|
output [11:0] hctr_o;
|
209 |
|
|
output [11:0] vctr_o;
|
210 |
|
|
output [5:0] fctr_o;
|
211 |
|
|
`else
|
212 |
|
|
input hsync_i; // start/end of scan line
|
213 |
|
|
input vsync_i; // start/end of frame
|
214 |
|
|
input blank_i; // blank the output
|
215 |
|
|
`endif
|
216 |
|
|
input [31:0] rgb_i;
|
217 |
|
|
output [31:0] rgb_o; // 32-bit RGB output
|
218 |
|
|
reg [31:0] rgb_o;
|
219 |
|
|
|
220 |
|
|
input xonoff_i;
|
221 |
|
|
output reg xal_o; // external access line (sprite access)
|
222 |
|
|
|
223 |
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
224 |
|
|
// IO registers
|
225 |
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
226 |
|
|
reg irq;
|
227 |
|
|
reg rst_irq,rst_irq2;
|
228 |
|
|
|
229 |
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
230 |
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
231 |
|
|
wire vclk;
|
232 |
|
|
reg cs,cs2;
|
233 |
|
|
reg cs_config;
|
234 |
|
|
reg cs_map;
|
235 |
|
|
reg cs_reg;
|
236 |
|
|
wire cs_edge;
|
237 |
|
|
reg we;
|
238 |
|
|
reg [7:0] sel;
|
239 |
|
|
reg [31:0] adri;
|
240 |
|
|
reg [63:0] dat;
|
241 |
|
|
wire irq_en;
|
242 |
|
|
reg [63:0] s_dat_o;
|
243 |
|
|
wire ack;
|
244 |
|
|
|
245 |
|
|
always_ff @(posedge s_clk_i)
|
246 |
|
|
cs <= s_req.cyc & s_req.stb & cs_io_i;
|
247 |
|
|
always_ff @(posedge s_clk_i)
|
248 |
|
|
we <= s_req.we;
|
249 |
|
|
always_ff @(posedge s_clk_i)
|
250 |
|
|
sel <= s_req.sel;
|
251 |
|
|
always_ff @(posedge s_clk_i)
|
252 |
|
|
adri <= s_req.padr;
|
253 |
|
|
always_ff @(posedge s_clk_i)
|
254 |
|
|
dat <= s_req.dat;
|
255 |
|
|
|
256 |
|
|
always_ff @(posedge s_clk_i)
|
257 |
|
|
cs_config <= s_req.cyc & s_req.stb & cs_config_i && adri[27:20]==CFG_BUS && adri[19:15]==CFG_DEVICE && adri[14:12]==CFG_FUNC;
|
258 |
|
|
wire cs_fbc;
|
259 |
|
|
always_comb
|
260 |
|
|
cs_map = cs && cs_fbc && adri[15:14]==3'd1;
|
261 |
|
|
always_comb
|
262 |
|
|
cs_reg = cs && cs_fbc && adri[15:14]==3'd0;
|
263 |
|
|
|
264 |
|
|
assign s_resp.next = 1'b0;
|
265 |
|
|
assign s_resp.stall = 1'b0;
|
266 |
|
|
assign s_resp.err = 1'b0;
|
267 |
|
|
assign s_resp.rty = 1'b0;
|
268 |
|
|
assign s_resp.pri = 4'd7;
|
269 |
|
|
assign s_resp.dat = s_dat_o;
|
270 |
|
|
|
271 |
|
|
vtdl #(.WID(1), .DEP(16)) urdyd1 (.clk(s_clk_i), .ce(1'b1), .a(4'd3), .d(cs_map|cs_reg|cs_config), .q(ack));
|
272 |
|
|
vtdl #(.WID(1), .DEP(16)) urdyd2 (.clk(s_clk_i), .ce(1'b1), .a(4'd4), .d(cs_map|cs_reg|cs_config), .q(s_resp.ack));
|
273 |
|
|
vtdl #(.WID(4), .DEP(16)) urdyd3 (.clk(s_clk_i), .ce(1'b1), .a(4'd5), .d(s_req.cid), .q(s_resp.cid));
|
274 |
|
|
vtdl #(.WID($bits(fta_tranid_t)), .DEP(16)) urdyd4 (.clk(s_clk_i), .ce(1'b1), .a(4'd5), .d(s_req.tid), .q(s_resp.tid));
|
275 |
|
|
vtdl #(.WID(32), .DEP(16)) urdyd5 (.clk(s_clk_i), .ce(1'b1), .a(4'd5), .d(s_req.padr), .q(s_resp.adr));
|
276 |
|
|
|
277 |
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
278 |
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
279 |
|
|
integer n, n1;
|
280 |
|
|
reg [31:0] fbc_addr;
|
281 |
|
|
reg [11:0] rastcmp;
|
282 |
|
|
reg [`ABITS] bm_base_addr1,bm_base_addr2;
|
283 |
|
|
color_depth_t color_depth, color_depth2;
|
284 |
|
|
wire [7:0] fifo_cnt;
|
285 |
|
|
reg onoff;
|
286 |
|
|
reg [2:0] hres,vres;
|
287 |
|
|
reg greyscale;
|
288 |
|
|
reg page;
|
289 |
|
|
reg [3:0] pals; // palette select
|
290 |
|
|
reg [15:0] hrefdelay;
|
291 |
|
|
reg [15:0] vrefdelay;
|
292 |
|
|
reg [15:0] windowLeft;
|
293 |
|
|
reg [15:0] windowTop;
|
294 |
|
|
reg [11:0] windowWidth,windowHeight;
|
295 |
|
|
reg [11:0] map; // memory access period
|
296 |
|
|
reg [11:0] mapctr;
|
297 |
|
|
reg [15:0] bmpWidth; // scan line increment (pixels)
|
298 |
|
|
reg [15:0] bmpHeight;
|
299 |
|
|
reg [`ABITS] baseAddr; // base address register
|
300 |
|
|
wire [MDW-1:0] rgbo1, rgbo1e, rgbo1o, rgbo1m;
|
301 |
|
|
reg [15:0] pixelRow;
|
302 |
|
|
reg [15:0] pixelCol;
|
303 |
|
|
wire [63:0] pal_wo;
|
304 |
|
|
wire [31:0] pal_o;
|
305 |
|
|
reg [15:0] px;
|
306 |
|
|
reg [15:0] py;
|
307 |
|
|
reg [7:0] pz;
|
308 |
|
|
reg [1:0] pcmd,pcmd_o;
|
309 |
|
|
reg [3:0] raster_op;
|
310 |
|
|
reg [31:0] zrgb;
|
311 |
|
|
reg [31:0] oob_color; // out-of-bounds color
|
312 |
|
|
reg [31:0] trans_color; // transparent color
|
313 |
|
|
reg [31:0] color;
|
314 |
|
|
reg [31:0] color_o;
|
315 |
|
|
reg rstcmd,rstcmd1;
|
316 |
|
|
reg [11:0] hTotal = phTotal;
|
317 |
|
|
reg [11:0] vTotal = pvTotal;
|
318 |
|
|
reg [11:0] hSyncOn = phSyncOn, hSyncOff = phSyncOff;
|
319 |
|
|
reg [11:0] vSyncOn = pvSyncOn, vSyncOff = pvSyncOff;
|
320 |
|
|
reg [11:0] hBlankOn = phBlankOn, hBlankOff = phBlankOff;
|
321 |
|
|
reg [11:0] vBlankOn = pvBlankOn, vBlankOff = pvBlankOff;
|
322 |
|
|
reg [11:0] hBorderOn = phBorderOn, hBorderOff = phBorderOff;
|
323 |
|
|
reg [11:0] vBorderOn = pvBorderOn, vBorderOff = pvBorderOff;
|
324 |
|
|
reg sgLock;
|
325 |
|
|
wire pe_hsync, pe_hsync2;
|
326 |
|
|
wire pe_vsync;
|
327 |
|
|
reg [11:0] tocnt; // bus timeout counter
|
328 |
|
|
reg vm_cyc_o;
|
329 |
|
|
reg [31:0] vm_adr_o;
|
330 |
|
|
|
331 |
|
|
// config
|
332 |
|
|
reg [63:0] irq_msgadr = IRQ_MSGADR;
|
333 |
|
|
reg [63:0] irq_msgdat = IRQ_MSGDAT;
|
334 |
|
|
|
335 |
|
|
wire [BUSWID-1:0] cfg_out;
|
336 |
|
|
generate begin : gConfigSpace
|
337 |
|
|
if (BUSWID==32) begin
|
338 |
|
|
pci32_config #(
|
339 |
|
|
.CFG_BUS(CFG_BUS),
|
340 |
|
|
.CFG_DEVICE(CFG_DEVICE),
|
341 |
|
|
.CFG_FUNC(CFG_FUNC),
|
342 |
|
|
.CFG_VENDOR_ID(CFG_VENDOR_ID),
|
343 |
|
|
.CFG_DEVICE_ID(CFG_DEVICE_ID),
|
344 |
|
|
.CFG_BAR0(FBC_ADDR),
|
345 |
|
|
.CFG_BAR0_MASK(FBC_ADDR_MASK),
|
346 |
|
|
.CFG_SUBSYSTEM_VENDOR_ID(CFG_SUBSYSTEM_VENDOR_ID),
|
347 |
|
|
.CFG_SUBSYSTEM_ID(CFG_SUBSYSTEM_ID),
|
348 |
|
|
.CFG_ROM_ADDR(CFG_ROM_ADDR),
|
349 |
|
|
.CFG_REVISION_ID(CFG_REVISION_ID),
|
350 |
|
|
.CFG_PROGIF(CFG_PROGIF),
|
351 |
|
|
.CFG_SUBCLASS(CFG_SUBCLASS),
|
352 |
|
|
.CFG_CLASS(CFG_CLASS),
|
353 |
|
|
.CFG_CACHE_LINE_SIZE(CFG_CACHE_LINE_SIZE),
|
354 |
|
|
.CFG_MIN_GRANT(CFG_MIN_GRANT),
|
355 |
|
|
.CFG_MAX_LATENCY(CFG_MAX_LATENCY),
|
356 |
|
|
.CFG_IRQ_LINE(CFG_IRQ_LINE)
|
357 |
|
|
)
|
358 |
|
|
ucfg1
|
359 |
|
|
(
|
360 |
|
|
.rst_i(rst_i),
|
361 |
|
|
.clk_i(s_clk_i),
|
362 |
|
|
.irq_i(irq),
|
363 |
|
|
.irq_o(irq_o),
|
364 |
|
|
.cs_config_i(cs_config),
|
365 |
|
|
.we_i(we),
|
366 |
|
|
.sel_i(sel),
|
367 |
|
|
.adr_i(adri),
|
368 |
|
|
.dat_i(dat),
|
369 |
|
|
.dat_o(cfg_out),
|
370 |
|
|
.cs_bar0_o(cs_fbc),
|
371 |
|
|
.cs_bar1_o(),
|
372 |
|
|
.cs_bar2_o(),
|
373 |
|
|
.irq_en_o(irq_en)
|
374 |
|
|
);
|
375 |
|
|
end
|
376 |
|
|
else if (BUSWID==64) begin
|
377 |
|
|
pci64_config #(
|
378 |
|
|
.CFG_BUS(CFG_BUS),
|
379 |
|
|
.CFG_DEVICE(CFG_DEVICE),
|
380 |
|
|
.CFG_FUNC(CFG_FUNC),
|
381 |
|
|
.CFG_VENDOR_ID(CFG_VENDOR_ID),
|
382 |
|
|
.CFG_DEVICE_ID(CFG_DEVICE_ID),
|
383 |
|
|
.CFG_BAR0(FBC_ADDR),
|
384 |
|
|
.CFG_BAR0_MASK(FBC_ADDR_MASK),
|
385 |
|
|
.CFG_SUBSYSTEM_VENDOR_ID(CFG_SUBSYSTEM_VENDOR_ID),
|
386 |
|
|
.CFG_SUBSYSTEM_ID(CFG_SUBSYSTEM_ID),
|
387 |
|
|
.CFG_ROM_ADDR(CFG_ROM_ADDR),
|
388 |
|
|
.CFG_REVISION_ID(CFG_REVISION_ID),
|
389 |
|
|
.CFG_PROGIF(CFG_PROGIF),
|
390 |
|
|
.CFG_SUBCLASS(CFG_SUBCLASS),
|
391 |
|
|
.CFG_CLASS(CFG_CLASS),
|
392 |
|
|
.CFG_CACHE_LINE_SIZE(CFG_CACHE_LINE_SIZE),
|
393 |
|
|
.CFG_MIN_GRANT(CFG_MIN_GRANT),
|
394 |
|
|
.CFG_MAX_LATENCY(CFG_MAX_LATENCY),
|
395 |
|
|
.CFG_IRQ_LINE(CFG_IRQ_LINE)
|
396 |
|
|
)
|
397 |
|
|
ucfg1
|
398 |
|
|
(
|
399 |
|
|
.rst_i(rst_i),
|
400 |
|
|
.clk_i(s_clk_i),
|
401 |
|
|
.irq_i(irq),
|
402 |
|
|
.irq_o(irq_o),
|
403 |
|
|
.cs_config_i(cs_config),
|
404 |
|
|
.we_i(we),
|
405 |
|
|
.sel_i(sel),
|
406 |
|
|
.adr_i(adri),
|
407 |
|
|
.dat_i(dat),
|
408 |
|
|
.dat_o(cfg_out),
|
409 |
|
|
.cs_bar0_o(cs_fbc),
|
410 |
|
|
.cs_bar1_o(),
|
411 |
|
|
.cs_bar2_o(),
|
412 |
|
|
.irq_en_o(irq_en)
|
413 |
|
|
);
|
414 |
|
|
end
|
415 |
|
|
end
|
416 |
|
|
endgenerate
|
417 |
|
|
|
418 |
|
|
wire [15:0] map_page;
|
419 |
|
|
wire [15:0] map_out;
|
420 |
|
|
|
421 |
|
|
// xpm_memory_tdpram: True Dual Port RAM
|
422 |
|
|
// Xilinx Parameterized Macro, version 2022.2
|
423 |
|
|
|
424 |
|
|
xpm_memory_tdpram #(
|
425 |
|
|
.ADDR_WIDTH_A(11), // DECIMAL
|
426 |
|
|
.ADDR_WIDTH_B(11), // DECIMAL
|
427 |
|
|
.AUTO_SLEEP_TIME(0), // DECIMAL
|
428 |
|
|
.BYTE_WRITE_WIDTH_A(BITS_IN_ADDR_MAP),
|
429 |
|
|
.BYTE_WRITE_WIDTH_B(BITS_IN_ADDR_MAP),
|
430 |
|
|
.CASCADE_HEIGHT(0), // DECIMAL
|
431 |
|
|
.CLOCKING_MODE("independent_clock"), // String
|
432 |
|
|
.ECC_MODE("no_ecc"), // String
|
433 |
|
|
.MEMORY_INIT_FILE("fb_map.mem"), // String
|
434 |
|
|
.MEMORY_INIT_PARAM(""), // String
|
435 |
|
|
.MEMORY_OPTIMIZATION("true"), // String
|
436 |
|
|
.MEMORY_PRIMITIVE("auto"), // String
|
437 |
|
|
.MEMORY_SIZE(2048*BITS_IN_ADDR_MAP),
|
438 |
|
|
.MESSAGE_CONTROL(0), // DECIMAL
|
439 |
|
|
.READ_DATA_WIDTH_A(BITS_IN_ADDR_MAP),
|
440 |
|
|
.READ_DATA_WIDTH_B(BITS_IN_ADDR_MAP),
|
441 |
|
|
.READ_LATENCY_A(2), // DECIMAL
|
442 |
|
|
.READ_LATENCY_B(2), // DECIMAL
|
443 |
|
|
.READ_RESET_VALUE_A("0"), // String
|
444 |
|
|
.READ_RESET_VALUE_B("0"), // String
|
445 |
|
|
.RST_MODE_A("SYNC"), // String
|
446 |
|
|
.RST_MODE_B("SYNC"), // String
|
447 |
|
|
.SIM_ASSERT_CHK(0), // DECIMAL; 0=disable simulation messages, 1=enable simulation messages
|
448 |
|
|
.USE_EMBEDDED_CONSTRAINT(0), // DECIMAL
|
449 |
|
|
.USE_MEM_INIT(1), // DECIMAL
|
450 |
|
|
.USE_MEM_INIT_MMI(0), // DECIMAL
|
451 |
|
|
.WAKEUP_TIME("disable_sleep"), // String
|
452 |
|
|
.WRITE_DATA_WIDTH_A(16), // DECIMAL
|
453 |
|
|
.WRITE_DATA_WIDTH_B(16), // DECIMAL
|
454 |
|
|
.WRITE_MODE_A("no_change"), // String
|
455 |
|
|
.WRITE_MODE_B("no_change"), // String
|
456 |
|
|
.WRITE_PROTECT(1) // DECIMAL
|
457 |
|
|
)
|
458 |
|
|
umap (
|
459 |
|
|
.dbiterra(), // 1-bit output: Status signal to indicate double bit error occurrence
|
460 |
|
|
// on the data output of port A.
|
461 |
|
|
|
462 |
|
|
.dbiterrb(), // 1-bit output: Status signal to indicate double bit error occurrence
|
463 |
|
|
// on the data output of port A.
|
464 |
|
|
|
465 |
|
|
.douta(map_out), // READ_DATA_WIDTH_A-bit output: Data output for port A read operations.
|
466 |
|
|
.doutb(map_page), // READ_DATA_WIDTH_B-bit output: Data output for port B read operations.
|
467 |
|
|
.sbiterra(), // 1-bit output: Status signal to indicate single bit error occurrence
|
468 |
|
|
// on the data output of port A.
|
469 |
|
|
|
470 |
|
|
.sbiterrb(), // 1-bit output: Status signal to indicate single bit error occurrence
|
471 |
|
|
// on the data output of port B.
|
472 |
|
|
|
473 |
|
|
.addra(adri[13:3]), // ADDR_WIDTH_A-bit input: Address for port A write and read operations.
|
474 |
|
|
.addrb(vm_adr_o[26:16]), // ADDR_WIDTH_B-bit input: Address for port B write and read operations.
|
475 |
|
|
.clka(s_clk_i), // 1-bit input: Clock signal for port A. Also clocks port B when
|
476 |
|
|
// parameter CLOCKING_MODE is "common_clock".
|
477 |
|
|
|
478 |
|
|
.clkb(m_clk_i), // 1-bit input: Clock signal for port B when parameter CLOCKING_MODE is
|
479 |
|
|
// "independent_clock". Unused when parameter CLOCKING_MODE is
|
480 |
|
|
// "common_clock".
|
481 |
|
|
|
482 |
|
|
.dina(dat[15:0]), // WRITE_DATA_WIDTH_A-bit input: Data input for port A write operations.
|
483 |
|
|
.dinb(16'd0), // WRITE_DATA_WIDTH_B-bit input: Data input for port B write operations.
|
484 |
|
|
.ena(cs_map), // 1-bit input: Memory enable signal for port A. Must be high on clock
|
485 |
|
|
// cycles when read or write operations are initiated. Pipelined
|
486 |
|
|
// internally.
|
487 |
|
|
|
488 |
|
|
.enb(onoff), // 1-bit input: Memory enable signal for port B. Must be high on clock
|
489 |
|
|
// cycles when read or write operations are initiated. Pipelined
|
490 |
|
|
// internally.
|
491 |
|
|
|
492 |
|
|
.injectdbiterra(1'b0), // 1-bit input: Controls double bit error injection on input data when
|
493 |
|
|
// ECC enabled (Error injection capability is not available in
|
494 |
|
|
// "decode_only" mode).
|
495 |
|
|
|
496 |
|
|
.injectdbiterrb(1'b0), // 1-bit input: Controls double bit error injection on input data when
|
497 |
|
|
// ECC enabled (Error injection capability is not available in
|
498 |
|
|
// "decode_only" mode).
|
499 |
|
|
|
500 |
|
|
.injectsbiterra(1'b0), // 1-bit input: Controls single bit error injection on input data when
|
501 |
|
|
// ECC enabled (Error injection capability is not available in
|
502 |
|
|
// "decode_only" mode).
|
503 |
|
|
|
504 |
|
|
.injectsbiterrb(1'b0), // 1-bit input: Controls single bit error injection on input data when
|
505 |
|
|
// ECC enabled (Error injection capability is not available in
|
506 |
|
|
// "decode_only" mode).
|
507 |
|
|
|
508 |
|
|
.regcea(1'b1), // 1-bit input: Clock Enable for the last register stage on the output
|
509 |
|
|
// data path.
|
510 |
|
|
|
511 |
|
|
.regceb(onoff), // 1-bit input: Clock Enable for the last register stage on the output
|
512 |
|
|
// data path.
|
513 |
|
|
|
514 |
|
|
.rsta(1'b0), // 1-bit input: Reset signal for the final port A output register stage.
|
515 |
|
|
// Synchronously resets output port douta to the value specified by
|
516 |
|
|
// parameter READ_RESET_VALUE_A.
|
517 |
|
|
|
518 |
|
|
.rstb(1'b0), // 1-bit input: Reset signal for the final port B output register stage.
|
519 |
|
|
// Synchronously resets output port doutb to the value specified by
|
520 |
|
|
// parameter READ_RESET_VALUE_B.
|
521 |
|
|
|
522 |
|
|
.sleep(~onoff), // 1-bit input: sleep signal to enable the dynamic power saving feature.
|
523 |
|
|
.wea(we), // WRITE_DATA_WIDTH_A/BYTE_WRITE_WIDTH_A-bit input: Write enable vector
|
524 |
|
|
// for port A input data port dina. 1 bit wide when word-wide writes are
|
525 |
|
|
// used. In byte-wide write configurations, each bit controls the
|
526 |
|
|
// writing one byte of dina to address addra. For example, to
|
527 |
|
|
// synchronously write only bits [15-8] of dina when WRITE_DATA_WIDTH_A
|
528 |
|
|
// is 32, wea would be 4'b0010.
|
529 |
|
|
|
530 |
|
|
.web(1'b0) // WRITE_DATA_WIDTH_B/BYTE_WRITE_WIDTH_B-bit input: Write enable vector
|
531 |
|
|
// for port B input data port dinb. 1 bit wide when word-wide writes are
|
532 |
|
|
// used. In byte-wide write configurations, each bit controls the
|
533 |
|
|
// writing one byte of dinb to address addrb. For example, to
|
534 |
|
|
// synchronously write only bits [15-8] of dinb when WRITE_DATA_WIDTH_B
|
535 |
|
|
// is 32, web would be 4'b0010.
|
536 |
|
|
|
537 |
|
|
);
|
538 |
|
|
|
539 |
|
|
always_comb
|
540 |
|
|
m_req.padr <= {map_page,vm_adr_o[15:0]};
|
541 |
|
|
|
542 |
|
|
// End of xpm_memory_tdpram_inst instantiation
|
543 |
|
|
|
544 |
|
|
delay3 #(1) udly1 (.clk(m_clk_i), .ce(1'b1), .i(vm_cyc_o), .o(m_req.cyc));
|
545 |
|
|
|
546 |
|
|
`ifdef INTERNAL_SYNC_GEN
|
547 |
|
|
wire hsync_i, vsync_i, blank_i;
|
548 |
|
|
|
549 |
|
|
VGASyncGen usg1
|
550 |
|
|
(
|
551 |
|
|
.rst(rst_i),
|
552 |
|
|
.clk(vclk),
|
553 |
|
|
.eol(),
|
554 |
|
|
.eof(),
|
555 |
|
|
.hSync(hsync_o),
|
556 |
|
|
.vSync(vsync_o),
|
557 |
|
|
.hCtr(hctr_o),
|
558 |
|
|
.vCtr(vctr_o),
|
559 |
|
|
.blank(blank_o),
|
560 |
|
|
.vblank(vblank),
|
561 |
|
|
.vbl_int(),
|
562 |
|
|
.border(border_o),
|
563 |
|
|
.hTotal_i(hTotal),
|
564 |
|
|
.vTotal_i(vTotal),
|
565 |
|
|
.hSyncOn_i(hSyncOn),
|
566 |
|
|
.hSyncOff_i(hSyncOff),
|
567 |
|
|
.vSyncOn_i(vSyncOn),
|
568 |
|
|
.vSyncOff_i(vSyncOff),
|
569 |
|
|
.hBlankOn_i(hBlankOn),
|
570 |
|
|
.hBlankOff_i(hBlankOff),
|
571 |
|
|
.vBlankOn_i(vBlankOn),
|
572 |
|
|
.vBlankOff_i(vBlankOff),
|
573 |
|
|
.hBorderOn_i(hBorderOn),
|
574 |
|
|
.hBorderOff_i(hBorderOff),
|
575 |
|
|
.vBorderOn_i(vBorderOn),
|
576 |
|
|
.vBorderOff_i(vBorderOff)
|
577 |
|
|
);
|
578 |
|
|
assign hsync_i = hsync_o;
|
579 |
|
|
assign vsync_i = vsync_o;
|
580 |
|
|
assign blank_i = blank_o;
|
581 |
|
|
assign vblank_o = vblank;
|
582 |
|
|
`endif
|
583 |
|
|
|
584 |
|
|
edge_det edcs1
|
585 |
|
|
(
|
586 |
|
|
.rst(rst_i),
|
587 |
|
|
.clk(s_clk_i),
|
588 |
|
|
.ce(1'b1),
|
589 |
|
|
.i(cs_reg),
|
590 |
|
|
.pe(cs_edge),
|
591 |
|
|
.ne(),
|
592 |
|
|
.ee()
|
593 |
|
|
);
|
594 |
|
|
|
595 |
|
|
// Frame counter
|
596 |
|
|
//
|
597 |
|
|
VT163 #(6) ub1
|
598 |
|
|
(
|
599 |
|
|
.clk(vclk),
|
600 |
|
|
.clr_n(!rst_i),
|
601 |
|
|
.ent(pe_vsync),
|
602 |
|
|
.enp(1'b1),
|
603 |
|
|
.ld_n(1'b1),
|
604 |
|
|
.d(6'd0),
|
605 |
|
|
.q(fctr_o),
|
606 |
|
|
.rco()
|
607 |
|
|
);
|
608 |
|
|
|
609 |
|
|
always_ff @(posedge vclk)
|
610 |
|
|
if (rst_i)
|
611 |
|
|
irq <= LOW;
|
612 |
|
|
else begin
|
613 |
|
|
if (hctr_o==12'd02 && rastcmp==vctr_o)
|
614 |
|
|
irq <= HIGH;
|
615 |
|
|
else if (rst_irq|rst_irq2)
|
616 |
|
|
irq <= LOW;
|
617 |
|
|
end
|
618 |
|
|
|
619 |
|
|
always_comb
|
620 |
|
|
baseAddr = page ? bm_base_addr2 : bm_base_addr1;
|
621 |
|
|
|
622 |
|
|
// Color palette RAM for 8bpp modes
|
623 |
|
|
// 64x1024 A side, 32x2048 B side
|
624 |
|
|
// 3 cycle latency
|
625 |
|
|
fb_palram upal1 // Actually 1024x64
|
626 |
|
|
(
|
627 |
|
|
.clka(s_clk_i), // input wire clka
|
628 |
|
|
.ena(cs & adri[13]), // input wire ena
|
629 |
|
|
.wea({8{we}}&sel), // input wire [3 : 0] wea
|
630 |
|
|
.addra(adri[12:3]), // input wire [8 : 0] addra
|
631 |
|
|
.dina(dat), // input wire [31 : 0] dina
|
632 |
|
|
.douta(pal_wo), // output wire [31 : 0] douta
|
633 |
|
|
.clkb(vclk), // input wire clkb
|
634 |
|
|
.enb(1'b1), // input wire enb
|
635 |
|
|
.web(1'b0), // input wire [3 : 0] web
|
636 |
|
|
.addrb({pals,rgbo4[5:0]}), // input wire [8 : 0] addrb
|
637 |
|
|
.dinb(32'h0), // input wire [31 : 0] dinb
|
638 |
|
|
.doutb(pal_o) // output wire [31 : 0] doutb
|
639 |
|
|
);
|
640 |
|
|
|
641 |
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
642 |
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
643 |
|
|
always_ff @(posedge s_clk_i)
|
644 |
|
|
if (rst_i) begin
|
645 |
|
|
page <= 1'b0;
|
646 |
|
|
pals <= 4'h0;
|
647 |
|
|
hres <= 3'd1;
|
648 |
|
|
vres <= 3'd1;
|
649 |
|
|
windowWidth <= 12'd800;
|
650 |
|
|
windowHeight <= 12'd600;
|
651 |
|
|
onoff <= 1'b1;
|
652 |
|
|
color_depth <= BPP16;
|
653 |
|
|
color_depth2 <= BPP16;
|
654 |
|
|
greyscale <= 1'b0;
|
655 |
|
|
bm_base_addr1 <= BM_BASE_ADDR1;
|
656 |
|
|
bm_base_addr2 <= BM_BASE_ADDR2;
|
657 |
|
|
hrefdelay <= 16'hFF39;//16'd3964;//16'hFF99;//12'd103;
|
658 |
|
|
vrefdelay <= 16'hFFEA;//16'hFFF3;12'd13;
|
659 |
|
|
windowLeft <= 16'h0;
|
660 |
|
|
windowTop <= 16'h0;
|
661 |
|
|
windowWidth <= 16'd800;
|
662 |
|
|
windowHeight <= 16'd600;
|
663 |
|
|
bmpWidth <= 16'd800;
|
664 |
|
|
bmpHeight <= 16'd600;
|
665 |
|
|
map <= MAP;
|
666 |
|
|
pcmd <= 2'b00;
|
667 |
|
|
rstcmd1 <= 1'b0;
|
668 |
|
|
rst_irq <= 1'b0;
|
669 |
|
|
rastcmp <= 12'hFFF;
|
670 |
|
|
oob_color <= 32'h00003C00;
|
671 |
|
|
irq_msgadr <= IRQ_MSGADR;
|
672 |
|
|
irq_msgdat <= IRQ_MSGDAT;
|
673 |
|
|
end
|
674 |
|
|
else begin
|
675 |
|
|
color_depth2 <= color_depth;
|
676 |
|
|
rstcmd1 <= rstcmd;
|
677 |
|
|
rst_irq <= 1'b0;
|
678 |
|
|
if (rstcmd & ~rstcmd1)
|
679 |
|
|
pcmd <= 2'b00;
|
680 |
|
|
if (cs_edge) begin
|
681 |
|
|
if (we) begin
|
682 |
|
|
casez(adri[13:3])
|
683 |
|
|
REG_CTRL:
|
684 |
|
|
begin
|
685 |
|
|
if (sel[0]) onoff <= dat[0];
|
686 |
|
|
if (sel[1]) begin
|
687 |
|
|
color_depth <= color_depth_t'(dat[9:8]);
|
688 |
|
|
greyscale <= dat[12];
|
689 |
|
|
end
|
690 |
|
|
if (sel[2]) begin
|
691 |
|
|
hres <= dat[18:16];
|
692 |
|
|
vres <= dat[22:20];
|
693 |
|
|
end
|
694 |
|
|
if (sel[3]) begin
|
695 |
|
|
page <= dat[24];
|
696 |
|
|
pals <= dat[28:25];
|
697 |
|
|
end
|
698 |
|
|
if (|sel[7:6]) map <= dat[59:48];
|
699 |
|
|
end
|
700 |
|
|
REG_REFDELAY:
|
701 |
|
|
begin
|
702 |
|
|
if (|sel[1:0]) hrefdelay <= dat[15:0];
|
703 |
|
|
if (|sel[3:2]) vrefdelay <= dat[31:16];
|
704 |
|
|
end
|
705 |
|
|
REG_PAGE1ADDR: bm_base_addr1 <= dat;
|
706 |
|
|
REG_PAGE2ADDR: bm_base_addr2 <= dat;
|
707 |
|
|
REG_PXYZ:
|
708 |
|
|
begin
|
709 |
|
|
if (|sel[1:0]) px <= dat[15:0];
|
710 |
|
|
if (|sel[3:2]) py <= dat[31:16];
|
711 |
|
|
if (|sel[ 4]) pz <= dat[39:32];
|
712 |
|
|
end
|
713 |
|
|
REG_PCOLCMD:
|
714 |
|
|
begin
|
715 |
|
|
if (sel[0]) pcmd <= dat[1:0];
|
716 |
|
|
if (sel[1]) raster_op <= dat[11:8];
|
717 |
|
|
if (|sel[7:2]) color <= dat[63:16];
|
718 |
|
|
end
|
719 |
|
|
REG_RASTCMP:
|
720 |
|
|
begin
|
721 |
|
|
if (sel[0]) rastcmp[7:0] <= dat[7:0];
|
722 |
|
|
if (sel[1]) rastcmp[11:8] <= dat[11:8];
|
723 |
|
|
if (sel[7]) rst_irq <= dat[63];
|
724 |
|
|
end
|
725 |
|
|
REG_BMPSIZE:
|
726 |
|
|
begin
|
727 |
|
|
if (|sel[1:0]) bmpWidth <= dat[15:0];
|
728 |
|
|
if (|sel[5:4]) bmpHeight <= dat[47:32];
|
729 |
|
|
end
|
730 |
|
|
REG_OOB_COLOR:
|
731 |
|
|
begin
|
732 |
|
|
if (|sel[3:0]) oob_color[31:0] <= dat[31:0];
|
733 |
|
|
end
|
734 |
|
|
REG_WINDOW:
|
735 |
|
|
begin
|
736 |
|
|
if (|sel[1:0]) windowWidth <= dat[11:0];
|
737 |
|
|
if (|sel[3:2]) windowHeight <= dat[27:16];
|
738 |
|
|
if (|sel[5:4]) windowLeft <= dat[47:32];
|
739 |
|
|
if (|sel[7:6]) windowTop <= dat[63:48];
|
740 |
|
|
end
|
741 |
|
|
REG_IRQ_MSGADR:
|
742 |
|
|
begin
|
743 |
|
|
if (sel[0]) irq_msgadr <= dat[7:0];
|
744 |
|
|
if (sel[1]) irq_msgadr <= dat[15:8];
|
745 |
|
|
if (sel[2]) irq_msgadr <= dat[23:16];
|
746 |
|
|
if (sel[3]) irq_msgadr <= dat[31:24];
|
747 |
|
|
if (sel[4]) irq_msgadr <= dat[39:32];
|
748 |
|
|
if (sel[5]) irq_msgadr <= dat[47:40];
|
749 |
|
|
if (sel[6]) irq_msgadr <= dat[55:48];
|
750 |
|
|
if (sel[7]) irq_msgadr <= dat[63:56];
|
751 |
|
|
end
|
752 |
|
|
REG_IRQ_MSGDAT:
|
753 |
|
|
begin
|
754 |
|
|
if (sel[0]) irq_msgdat <= dat[7:0];
|
755 |
|
|
if (sel[1]) irq_msgdat <= dat[15:8];
|
756 |
|
|
if (sel[2]) irq_msgdat <= dat[23:16];
|
757 |
|
|
if (sel[3]) irq_msgdat <= dat[31:24];
|
758 |
|
|
if (sel[4]) irq_msgdat <= dat[39:32];
|
759 |
|
|
if (sel[5]) irq_msgdat <= dat[47:40];
|
760 |
|
|
if (sel[6]) irq_msgdat <= dat[55:48];
|
761 |
|
|
if (sel[7]) irq_msgdat <= dat[63:56];
|
762 |
|
|
end
|
763 |
|
|
|
764 |
|
|
`ifdef INTERNAL_SYNC_GEN
|
765 |
|
|
REG_TOTAL:
|
766 |
|
|
begin
|
767 |
|
|
if (!sgLock) begin
|
768 |
|
|
if (|sel[1:0]) hTotal <= dat[11:0];
|
769 |
|
|
if (|sel[3:2]) vTotal <= dat[27:16];
|
770 |
|
|
end
|
771 |
|
|
if (|sel[7:4]) begin
|
772 |
|
|
if (dat[63:32]==32'hA1234567)
|
773 |
|
|
sgLock <= 1'b0;
|
774 |
|
|
else if (dat[63:32]==32'h7654321A)
|
775 |
|
|
sgLock <= 1'b1;
|
776 |
|
|
end
|
777 |
|
|
end
|
778 |
|
|
REG_SYNC_ONOFF:
|
779 |
|
|
if (!sgLock) begin
|
780 |
|
|
if (|sel[1:0]) hSyncOff <= dat[11:0];
|
781 |
|
|
if (|sel[3:2]) hSyncOn <= dat[27:16];
|
782 |
|
|
if (|sel[5:4]) vSyncOff <= dat[43:32];
|
783 |
|
|
if (|sel[7:6]) vSyncOn <= dat[59:48];
|
784 |
|
|
end
|
785 |
|
|
REG_BLANK_ONOFF:
|
786 |
|
|
if (!sgLock) begin
|
787 |
|
|
if (|sel[1:0]) hBlankOff <= dat[11:0];
|
788 |
|
|
if (|sel[3:2]) hBlankOn <= dat[27:16];
|
789 |
|
|
if (|sel[5:4]) vBlankOff <= dat[43:32];
|
790 |
|
|
if (|sel[7:6]) vBlankOn <= dat[59:48];
|
791 |
|
|
end
|
792 |
|
|
REG_BORDER_ONOFF:
|
793 |
|
|
begin
|
794 |
|
|
if (|sel[1:0]) hBorderOff <= dat[11:0];
|
795 |
|
|
if (|sel[3:2]) hBorderOn <= dat[27:16];
|
796 |
|
|
if (|sel[5:4]) vBorderOff <= dat[43:32];
|
797 |
|
|
if (|sel[7:6]) vBorderOn <= dat[59:48];
|
798 |
|
|
end
|
799 |
|
|
`endif
|
800 |
|
|
default: ;
|
801 |
|
|
endcase
|
802 |
|
|
end
|
803 |
|
|
end
|
804 |
|
|
if (cs_reg) begin
|
805 |
|
|
if (BUSWID==64)
|
806 |
|
|
casez(adri[13:3])
|
807 |
|
|
REG_CTRL:
|
808 |
|
|
begin
|
809 |
|
|
s_dat_o[0] <= onoff;
|
810 |
|
|
s_dat_o[11:8] <= color_depth2;
|
811 |
|
|
s_dat_o[12] <= greyscale;
|
812 |
|
|
s_dat_o[18:16] <= hres;
|
813 |
|
|
s_dat_o[22:20] <= vres;
|
814 |
|
|
s_dat_o[24] <= page;
|
815 |
|
|
s_dat_o[28:25] <= pals;
|
816 |
|
|
s_dat_o[47:32] <= bmpWidth;
|
817 |
|
|
s_dat_o[59:48] <= map;
|
818 |
|
|
end
|
819 |
|
|
REG_REFDELAY: s_dat_o <= {32'h0,vrefdelay,hrefdelay};
|
820 |
|
|
REG_PAGE1ADDR: s_dat_o <= bm_base_addr1;
|
821 |
|
|
REG_PAGE2ADDR: s_dat_o <= bm_base_addr2;
|
822 |
|
|
REG_PXYZ: s_dat_o <= {20'h0,pz,py,px};
|
823 |
|
|
REG_PCOLCMD: s_dat_o <= {color_o,12'd0,raster_op,14'd0,pcmd};
|
824 |
|
|
REG_OOB_COLOR: s_dat_o <= {32'h0,oob_color};
|
825 |
|
|
REG_WINDOW: s_dat_o <= {windowTop,windowLeft,4'h0,windowHeight,4'h0,windowWidth};
|
826 |
|
|
REG_IRQ_MSGADR: s_dat_o <= irq_msgadr;
|
827 |
|
|
REG_IRQ_MSGDAT: s_dat_o <= irq_msgdat;
|
828 |
|
|
11'b1?_????_????_?: s_dat_o <= pal_wo;
|
829 |
|
|
default: s_dat_o <= 'd0;
|
830 |
|
|
endcase
|
831 |
|
|
else
|
832 |
|
|
casez(adri[13:2])
|
833 |
|
|
{REG_CTRL,1'b0}:
|
834 |
|
|
begin
|
835 |
|
|
s_dat_o[0] <= onoff;
|
836 |
|
|
s_dat_o[11:8] <= color_depth2;
|
837 |
|
|
s_dat_o[12] <= greyscale;
|
838 |
|
|
s_dat_o[18:16] <= hres;
|
839 |
|
|
s_dat_o[22:20] <= vres;
|
840 |
|
|
s_dat_o[24] <= page;
|
841 |
|
|
s_dat_o[28:25] <= pals;
|
842 |
|
|
end
|
843 |
|
|
{REG_CTRL,1'b1}:
|
844 |
|
|
begin
|
845 |
|
|
s_dat_o[15: 0] <= bmpWidth;
|
846 |
|
|
s_dat_o[27:16] <= map;
|
847 |
|
|
end
|
848 |
|
|
{REG_REFDELAY,1'b0}: s_dat_o <= {vrefdelay,hrefdelay};
|
849 |
|
|
{REG_PAGE1ADDR,1'b0}: s_dat_o <= bm_base_addr1;
|
850 |
|
|
{REG_PAGE2ADDR,1'b0}: s_dat_o <= bm_base_addr2;
|
851 |
|
|
{REG_PXYZ,1'b0}: s_dat_o <= {py,px};
|
852 |
|
|
{REG_PXYZ,1'b1}: s_dat_o <= {16'h0,pz};
|
853 |
|
|
{REG_PCOLCMD,1'b0}: s_dat_o <= {12'd0,raster_op,14'd0,pcmd};
|
854 |
|
|
{REG_PCOLCMD,1'b1}: s_dat_o <= color_o;
|
855 |
|
|
{REG_OOB_COLOR,1'b0}: s_dat_o <= oob_color;
|
856 |
|
|
{REG_WINDOW,1'b0}: s_dat_o <= {4'h0,windowHeight,4'h0,windowWidth};
|
857 |
|
|
{REG_WINDOW,1'b1}: s_dat_o <= {windowTop,windowLeft};
|
858 |
|
|
{REG_IRQ_MSGADR,1'b0}: s_dat_o <= irq_msgadr[31:0];
|
859 |
|
|
{REG_IRQ_MSGADR,1'b1}: s_dat_o <= irq_msgadr[63:32];
|
860 |
|
|
{REG_IRQ_MSGDAT,1'b0}: s_dat_o <= irq_msgdat[31:0];
|
861 |
|
|
{REG_IRQ_MSGDAT,1'b1}: s_dat_o <= irq_msgdat[63:32];
|
862 |
|
|
12'b1?_????_????_?0: s_dat_o <= pal_wo;
|
863 |
|
|
default: s_dat_o <= 'd0;
|
864 |
|
|
endcase
|
865 |
|
|
end
|
866 |
|
|
else if (cs_map)
|
867 |
|
|
s_dat_o <= {40'h0,map_out};
|
868 |
|
|
else if (cs_config)
|
869 |
|
|
s_dat_o <= cfg_out;
|
870 |
|
|
else
|
871 |
|
|
s_dat_o <= 'h0;
|
872 |
|
|
end
|
873 |
|
|
|
874 |
|
|
//`ifdef USE_CLOCK_GATE
|
875 |
|
|
//BUFHCE ucb1
|
876 |
|
|
//(
|
877 |
|
|
// .I(dot_clk_i),
|
878 |
|
|
// .CE(onoff),
|
879 |
|
|
// .O(vclk)
|
880 |
|
|
//);
|
881 |
|
|
//`else
|
882 |
|
|
assign vclk = dot_clk_i;
|
883 |
|
|
//`endif
|
884 |
|
|
|
885 |
|
|
|
886 |
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
887 |
|
|
// Horizontal and Vertical timing reference counters
|
888 |
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
889 |
|
|
|
890 |
|
|
reg lef; // load even fifo
|
891 |
|
|
reg lof; // load odd fifo
|
892 |
|
|
|
893 |
|
|
edge_det edh1
|
894 |
|
|
(
|
895 |
|
|
.rst(rst_i),
|
896 |
|
|
.clk(vclk),
|
897 |
|
|
.ce(1'b1),
|
898 |
|
|
.i(hsync_i),
|
899 |
|
|
.pe(pe_hsync),
|
900 |
|
|
.ne(),
|
901 |
|
|
.ee()
|
902 |
|
|
);
|
903 |
|
|
|
904 |
|
|
edge_det edh2
|
905 |
|
|
(
|
906 |
|
|
.rst(rst_i),
|
907 |
|
|
.clk(m_clk_i),
|
908 |
|
|
.ce(1'b1),
|
909 |
|
|
.i(hsync_i),
|
910 |
|
|
.pe(pe_hsync2),
|
911 |
|
|
.ne(),
|
912 |
|
|
.ee()
|
913 |
|
|
);
|
914 |
|
|
|
915 |
|
|
edge_det edv1
|
916 |
|
|
(
|
917 |
|
|
.rst(rst_i),
|
918 |
|
|
.clk(vclk),
|
919 |
|
|
.ce(1'b1),
|
920 |
|
|
.i(vsync_i),
|
921 |
|
|
.pe(pe_vsync),
|
922 |
|
|
.ne(),
|
923 |
|
|
.ee()
|
924 |
|
|
);
|
925 |
|
|
|
926 |
|
|
wire [2:0] hc;
|
927 |
|
|
wire [2:0] vc;
|
928 |
|
|
|
929 |
|
|
pixelCounter upxc1
|
930 |
|
|
(
|
931 |
|
|
.rst(pe_hsync),
|
932 |
|
|
.clk(vclk),
|
933 |
|
|
.ce(1'b1),
|
934 |
|
|
.res(hres),
|
935 |
|
|
.d(hrefdelay),
|
936 |
|
|
.q(pixelCol),
|
937 |
|
|
.mq(hc)
|
938 |
|
|
);
|
939 |
|
|
|
940 |
|
|
pixelCounter upxr1
|
941 |
|
|
(
|
942 |
|
|
.rst(pe_vsync),
|
943 |
|
|
.clk(vclk),
|
944 |
|
|
.ce(pe_hsync),
|
945 |
|
|
.res(vres),
|
946 |
|
|
.d(vrefdelay),
|
947 |
|
|
.q(pixelRow),
|
948 |
|
|
.mq(vc)
|
949 |
|
|
);
|
950 |
|
|
|
951 |
|
|
always_comb
|
952 |
|
|
lef = ~pixelRow[0];
|
953 |
|
|
always_comb
|
954 |
|
|
lof = pixelRow[0];
|
955 |
|
|
|
956 |
|
|
always_ff @(posedge vclk)
|
957 |
|
|
xal_o <= vc != 4'd1;
|
958 |
|
|
|
959 |
|
|
// Bits per pixel minus one.
|
960 |
|
|
reg [4:0] bpp;
|
961 |
|
|
always_comb
|
962 |
|
|
case(color_depth2)
|
963 |
|
|
BPP8: bpp = 7;
|
964 |
|
|
BPP16: bpp = 15;
|
965 |
|
|
BPP24: bpp = 23;
|
966 |
|
|
BPP32: bpp = 31;
|
967 |
|
|
default: bpp = 15;
|
968 |
|
|
endcase
|
969 |
|
|
|
970 |
|
|
reg [5:0] shifts;
|
971 |
|
|
always_comb
|
972 |
|
|
case(MDW)
|
973 |
|
|
128:
|
974 |
|
|
case(color_depth2)
|
975 |
|
|
BPP8: shifts = 6'd16;
|
976 |
|
|
BPP16: shifts = 6'd8;
|
977 |
|
|
BPP24: shifts = 6'd5;
|
978 |
|
|
BPP32: shifts = 6'd4;
|
979 |
|
|
default: shifts = 6'd8;
|
980 |
|
|
endcase
|
981 |
|
|
64:
|
982 |
|
|
case(color_depth2)
|
983 |
|
|
BPP8: shifts = 6'd8;
|
984 |
|
|
BPP16: shifts = 6'd4;
|
985 |
|
|
BPP24: shifts = 6'd2;
|
986 |
|
|
BPP32: shifts = 6'd2;
|
987 |
|
|
default: shifts = 6'd4;
|
988 |
|
|
endcase
|
989 |
|
|
32:
|
990 |
|
|
case(color_depth2)
|
991 |
|
|
BPP8: shifts = 6'd4;
|
992 |
|
|
BPP16: shifts = 6'd2;
|
993 |
|
|
BPP24: shifts = 6'd1;
|
994 |
|
|
BPP32: shifts = 6'd1;
|
995 |
|
|
default: shifts = 6'd2;
|
996 |
|
|
endcase
|
997 |
|
|
default:
|
998 |
|
|
begin
|
999 |
|
|
$display("rfFramBuffer_fta64: Bad master bus width");
|
1000 |
|
|
$finish;
|
1001 |
|
|
end
|
1002 |
|
|
endcase
|
1003 |
|
|
|
1004 |
|
|
wire vFetch = !vblank;//pixelRow < windowHeight;
|
1005 |
|
|
reg fifo_rrst;
|
1006 |
|
|
reg fifo_wrst;
|
1007 |
|
|
always_comb fifo_rrst = pixelCol==16'hFFFF;
|
1008 |
|
|
always_comb fifo_wrst = pe_hsync2 && vc==4'd1;
|
1009 |
|
|
|
1010 |
|
|
wire[31:0] grAddr,xyAddr;
|
1011 |
|
|
reg [11:0] fetchCol;
|
1012 |
|
|
localparam CMS = MDW==128 ? 6 : MDW==64 ? 5 : 4;
|
1013 |
|
|
wire [CMS:0] mb,me,ce;
|
1014 |
|
|
reg [MDW-1:0] mem_strip;
|
1015 |
|
|
wire [MDW-1:0] mem_strip_o;
|
1016 |
|
|
|
1017 |
|
|
// Compute fetch address
|
1018 |
|
|
gfx_calc_address #(.SW(MDW)) u1
|
1019 |
|
|
(
|
1020 |
|
|
.clk(m_clk_i),
|
1021 |
|
|
.base_address_i(baseAddr),
|
1022 |
|
|
.color_depth_i(color_depth2),
|
1023 |
|
|
.bmp_width_i(bmpWidth),
|
1024 |
|
|
.x_coord_i(windowLeft),
|
1025 |
|
|
.y_coord_i(windowTop + pixelRow),
|
1026 |
|
|
.address_o(grAddr),
|
1027 |
|
|
.mb_o(),
|
1028 |
|
|
.me_o(),
|
1029 |
|
|
.ce_o()
|
1030 |
|
|
);
|
1031 |
|
|
|
1032 |
|
|
// Compute address for get/set pixel
|
1033 |
|
|
gfx_calc_address #(.SW(MDW)) u2
|
1034 |
|
|
(
|
1035 |
|
|
.clk(m_clk_i),
|
1036 |
|
|
.base_address_i(baseAddr),
|
1037 |
|
|
.color_depth_i(color_depth2),
|
1038 |
|
|
.bmp_width_i(bmpWidth),
|
1039 |
|
|
.x_coord_i(px),
|
1040 |
|
|
.y_coord_i(py),
|
1041 |
|
|
.address_o(xyAddr),
|
1042 |
|
|
.mb_o(mb),
|
1043 |
|
|
.me_o(me),
|
1044 |
|
|
.ce_o(ce)
|
1045 |
|
|
);
|
1046 |
|
|
|
1047 |
|
|
always_ff @(posedge m_clk_i)
|
1048 |
|
|
if (pe_hsync2)
|
1049 |
|
|
mapctr <= 12'hFFE;
|
1050 |
|
|
else begin
|
1051 |
|
|
if (mapctr == map)
|
1052 |
|
|
mapctr <= 12'd0;
|
1053 |
|
|
else
|
1054 |
|
|
mapctr <= mapctr + 12'd1;
|
1055 |
|
|
end
|
1056 |
|
|
wire memreq = mapctr==12'd0 && vc==4'd1;
|
1057 |
|
|
|
1058 |
|
|
// The following bypasses loading the fifo when all the pixels from a scanline
|
1059 |
|
|
// are buffered in the fifo and the pixel row doesn't change. Since the fifo
|
1060 |
|
|
// pointers are reset at the beginning of a scanline, the fifo can be used like
|
1061 |
|
|
// a cache.
|
1062 |
|
|
wire blankEdge;
|
1063 |
|
|
edge_det ed2(.rst(rst_i), .clk(m_clk_i), .ce(1'b1), .i(blank_i), .pe(blankEdge), .ne(), .ee() );
|
1064 |
|
|
reg do_loads;
|
1065 |
|
|
reg load_fifo = 1'b0;
|
1066 |
|
|
always_ff @(posedge m_clk_i)
|
1067 |
|
|
//load_fifo <= fifo_cnt < 10'd1000 && vFetch && onoff && xonoff && !m_cyc_o && do_loads;
|
1068 |
|
|
load_fifo <= /*fifo_cnt < 8'd224 &&*/ vFetch && onoff && xonoff_i && (fetchCol < windowWidth) && memreq;
|
1069 |
|
|
// The following table indicates the number of pixel that will fit into the
|
1070 |
|
|
// video fifo.
|
1071 |
|
|
reg [11:0] hCmp;
|
1072 |
|
|
always_comb
|
1073 |
|
|
case(color_depth2)
|
1074 |
|
|
BPP8: hCmp = 12'd2048;
|
1075 |
|
|
BPP16: hCmp = 12'd1024;
|
1076 |
|
|
BPP24: hCmp = 12'd640;
|
1077 |
|
|
BPP32: hCmp = 12'd512;
|
1078 |
|
|
default: hCmp = 12'd1024;
|
1079 |
|
|
endcase
|
1080 |
|
|
/*
|
1081 |
|
|
always @(posedge m_clk_i)
|
1082 |
|
|
// if windowWidth > hCmp we always load because the fifo isn't large enough to act as a cache.
|
1083 |
|
|
if (!(windowWidth < hCmp))
|
1084 |
|
|
do_loads <= 1'b1;
|
1085 |
|
|
// otherwise load the fifo only when the row changes to conserve memory bandwidth
|
1086 |
|
|
else if (vc==4'd1)//pixelRow != opixelRow)
|
1087 |
|
|
do_loads <= 1'b1;
|
1088 |
|
|
else if (blankEdge)
|
1089 |
|
|
do_loads <= 1'b0;
|
1090 |
|
|
*/
|
1091 |
|
|
always_comb m_req.bte = fta_bus_pkg::LINEAR;
|
1092 |
|
|
always_comb m_req.cti = fta_bus_pkg::CLASSIC;
|
1093 |
|
|
always_comb m_req.blen = 6'd63;
|
1094 |
|
|
always_comb m_req.stb = m_req.cyc;
|
1095 |
|
|
always_comb m_req.cid = 'd0;
|
1096 |
|
|
always_comb m_req.tid = 15'h1234;
|
1097 |
|
|
|
1098 |
|
|
reg [31:0] adr;
|
1099 |
|
|
typedef enum logic [3:0] {
|
1100 |
|
|
IDLE = 4'd0,
|
1101 |
|
|
LOADCOLOR = 4'd2,
|
1102 |
|
|
LOADSTRIP = 4'd3,
|
1103 |
|
|
STORESTRIP = 4'd4,
|
1104 |
|
|
ACKSTRIP = 4'd5,
|
1105 |
|
|
WAITLOAD = 4'd6,
|
1106 |
|
|
WAITRST = 4'd7,
|
1107 |
|
|
ICOLOR1 = 4'd8,
|
1108 |
|
|
ICOLOR2 = 4'd9,
|
1109 |
|
|
ICOLOR3 = 4'd10,
|
1110 |
|
|
ICOLOR4 = 4'd11,
|
1111 |
|
|
LOAD_OOB = 4'd12
|
1112 |
|
|
} state_t;
|
1113 |
|
|
state_t state;
|
1114 |
|
|
reg [127:0] icolor1;
|
1115 |
|
|
|
1116 |
|
|
function rastop;
|
1117 |
|
|
input [3:0] op;
|
1118 |
|
|
input a;
|
1119 |
|
|
input b;
|
1120 |
|
|
case(op)
|
1121 |
|
|
OPBLACK: rastop = 1'b0;
|
1122 |
|
|
OPCOPY: rastop = b;
|
1123 |
|
|
OPINV: rastop = ~a;
|
1124 |
|
|
OPAND: rastop = a & b;
|
1125 |
|
|
OPOR: rastop = a | b;
|
1126 |
|
|
OPXOR: rastop = a ^ b;
|
1127 |
|
|
OPANDN: rastop = a & ~b;
|
1128 |
|
|
OPNAND: rastop = ~(a & b);
|
1129 |
|
|
OPNOR: rastop = ~(a | b);
|
1130 |
|
|
OPXNOR: rastop = ~(a ^ b);
|
1131 |
|
|
OPORN: rastop = a | ~b;
|
1132 |
|
|
OPWHITE: rastop = 1'b1;
|
1133 |
|
|
default: rastop = 1'b0;
|
1134 |
|
|
endcase
|
1135 |
|
|
endfunction
|
1136 |
|
|
|
1137 |
|
|
always_ff @(posedge m_clk_i)
|
1138 |
|
|
if (fifo_wrst)
|
1139 |
|
|
adr <= grAddr;
|
1140 |
|
|
else begin
|
1141 |
|
|
if ((state==WAITLOAD && (m_resp.ack|tocnt[10])) || state==LOAD_OOB)
|
1142 |
|
|
case(MDW)
|
1143 |
|
|
32: adr <= adr + 32'd4;
|
1144 |
|
|
64: adr <= adr + 32'd8;
|
1145 |
|
|
default: adr <= adr + 32'd16;
|
1146 |
|
|
endcase
|
1147 |
|
|
end
|
1148 |
|
|
|
1149 |
|
|
always_ff @(posedge m_clk_i)
|
1150 |
|
|
if (fifo_wrst)
|
1151 |
|
|
fetchCol <= 12'd0;
|
1152 |
|
|
else begin
|
1153 |
|
|
if ((state==WAITLOAD && (m_resp.ack|tocnt[10])) || state==LOAD_OOB)
|
1154 |
|
|
fetchCol <= fetchCol + shifts;
|
1155 |
|
|
end
|
1156 |
|
|
|
1157 |
|
|
// Check for legal (positive) coordinates
|
1158 |
|
|
// Illegal coordinates result in a red display
|
1159 |
|
|
wire [15:0] xcol = fetchCol;
|
1160 |
|
|
reg legal_x, legal_y;
|
1161 |
|
|
always_comb legal_x = ~&xcol[15:12] && xcol < bmpWidth;
|
1162 |
|
|
always_comb legal_y = ~&pixelRow[15:12] && pixelRow < bmpHeight;
|
1163 |
|
|
|
1164 |
|
|
reg modd;
|
1165 |
|
|
always_comb
|
1166 |
|
|
case(MDW)
|
1167 |
|
|
32: modd <= m_req.padr[5:2]==4'hF;
|
1168 |
|
|
64: modd <= m_req.padr[5:3]==3'h7;
|
1169 |
|
|
default: modd <= m_req.padr[5:4]==2'h3;
|
1170 |
|
|
endcase
|
1171 |
|
|
|
1172 |
|
|
always_ff @(posedge m_clk_i)
|
1173 |
|
|
if (rst_i)
|
1174 |
|
|
tocnt <= 'd0;
|
1175 |
|
|
else begin
|
1176 |
|
|
if (m_req.cyc)
|
1177 |
|
|
tocnt <= tocnt + 2'd1;
|
1178 |
|
|
else
|
1179 |
|
|
tocnt <= 'd0;
|
1180 |
|
|
end
|
1181 |
|
|
|
1182 |
|
|
always_ff @(posedge m_clk_i, posedge rst_i)
|
1183 |
|
|
if (rst_i) begin
|
1184 |
|
|
vm_cyc_o <= LOW;
|
1185 |
|
|
m_req.we <= LOW;
|
1186 |
|
|
m_req.sel <= 'd0;
|
1187 |
|
|
vm_adr_o <= 'd0;
|
1188 |
|
|
rstcmd <= 1'b0;
|
1189 |
|
|
state <= IDLE;
|
1190 |
|
|
rst_irq2 <= 1'b0;
|
1191 |
|
|
end
|
1192 |
|
|
else begin
|
1193 |
|
|
wb_nack();
|
1194 |
|
|
rst_irq2 <= 1'b0;
|
1195 |
|
|
if (fifo_wrst)
|
1196 |
|
|
m_fst_o <= HIGH;
|
1197 |
|
|
case(state)
|
1198 |
|
|
WAITRST:
|
1199 |
|
|
if (pcmd==2'b00 && ~m_resp.ack) begin
|
1200 |
|
|
rstcmd <= 1'b0;
|
1201 |
|
|
state <= IDLE;
|
1202 |
|
|
end
|
1203 |
|
|
else
|
1204 |
|
|
rstcmd <= 1'b1;
|
1205 |
|
|
IDLE:
|
1206 |
|
|
if (load_fifo && !(legal_x && legal_y))
|
1207 |
|
|
state <= LOAD_OOB;
|
1208 |
|
|
else if (load_fifo & ~m_resp.ack) begin
|
1209 |
|
|
vm_cyc_o <= HIGH;
|
1210 |
|
|
vm_adr_o <= adr;
|
1211 |
|
|
m_req.sel <= 16'hFFFF;
|
1212 |
|
|
state <= WAITLOAD;
|
1213 |
|
|
end
|
1214 |
|
|
// Send an IRQ message if needed.
|
1215 |
|
|
else if (irq & ~m_resp.ack & MSIX) begin
|
1216 |
|
|
vm_cyc_o <= HIGH;
|
1217 |
|
|
vm_adr_o <= irq_msgadr;
|
1218 |
|
|
m_req.we <= HIGH;
|
1219 |
|
|
m_req.sel <= irq_msgadr[3] ? 16'hFF00 : 16'h00FF;
|
1220 |
|
|
m_req.data1 <= {2{irq_msgdat}};
|
1221 |
|
|
rst_irq2 <= 1'b1;
|
1222 |
|
|
end
|
1223 |
|
|
// The adr_o[5:3]==3'b111 causes the controller to wait until all eight
|
1224 |
|
|
// 64 bit strips from the memory controller have been processed. Otherwise
|
1225 |
|
|
// there would be cache thrashing in the memory controller and the memory
|
1226 |
|
|
// bandwidth available would be greatly reduced. However fetches are also
|
1227 |
|
|
// allowed when loads are not active or all strips for the current scan-
|
1228 |
|
|
// line have been fetched.
|
1229 |
|
|
else if (pcmd!=2'b00 && (modd || !(vFetch && onoff && xonoff_i && fetchCol < windowWidth))) begin
|
1230 |
|
|
vm_cyc_o <= HIGH;
|
1231 |
|
|
vm_adr_o <= xyAddr;
|
1232 |
|
|
m_req.sel <= 16'hFFFF;
|
1233 |
|
|
state <= LOADSTRIP;
|
1234 |
|
|
end
|
1235 |
|
|
LOADSTRIP:
|
1236 |
|
|
if (m_resp.ack|tocnt[10]) begin
|
1237 |
|
|
wb_nack();
|
1238 |
|
|
mem_strip <= m_resp.dat;
|
1239 |
|
|
icolor1 <= {96'b0,color} << mb;
|
1240 |
|
|
rstcmd <= 1'b1;
|
1241 |
|
|
if (pcmd==2'b01)
|
1242 |
|
|
state <= ICOLOR3;
|
1243 |
|
|
else if (pcmd==2'b10)
|
1244 |
|
|
state <= ICOLOR2;
|
1245 |
|
|
else begin
|
1246 |
|
|
state <= WAITRST;
|
1247 |
|
|
end
|
1248 |
|
|
end
|
1249 |
|
|
// Registered inline mem2color
|
1250 |
|
|
ICOLOR3:
|
1251 |
|
|
begin
|
1252 |
|
|
color_o <= mem_strip >> mb;
|
1253 |
|
|
state <= ICOLOR4;
|
1254 |
|
|
end
|
1255 |
|
|
ICOLOR4:
|
1256 |
|
|
begin
|
1257 |
|
|
for (n = 0; n < 32; n = n + 1)
|
1258 |
|
|
color_o[n] <= (n <= bpp) ? color_o[n] : 1'b0;
|
1259 |
|
|
state <= pcmd == 2'b0 ? (~m_resp.ack ? IDLE : WAITRST) : WAITRST;
|
1260 |
|
|
if (pcmd==2'b00)
|
1261 |
|
|
rstcmd <= 1'b0;
|
1262 |
|
|
end
|
1263 |
|
|
// Registered inline color2mem
|
1264 |
|
|
ICOLOR2:
|
1265 |
|
|
begin
|
1266 |
|
|
for (n = 0; n < MDW; n = n + 1)
|
1267 |
|
|
m_req.data1[n] <= (n >= mb && n <= me)
|
1268 |
|
|
? ((n <= ce) ? rastop(raster_op, mem_strip[n], icolor1[n]) : icolor1[n])
|
1269 |
|
|
: mem_strip[n];
|
1270 |
|
|
state <= STORESTRIP;
|
1271 |
|
|
end
|
1272 |
|
|
STORESTRIP:
|
1273 |
|
|
if (~m_resp.ack) begin
|
1274 |
|
|
vm_cyc_o <= HIGH;
|
1275 |
|
|
m_req.we <= HIGH;
|
1276 |
|
|
m_req.sel <= 16'hFFFF;
|
1277 |
|
|
vm_adr_o <= xyAddr;
|
1278 |
|
|
state <= ACKSTRIP;
|
1279 |
|
|
end
|
1280 |
|
|
ACKSTRIP:
|
1281 |
|
|
if (m_resp.ack|tocnt[10]) begin
|
1282 |
|
|
wb_nack();
|
1283 |
|
|
state <= pcmd == 2'b0 ? IDLE : WAITRST;
|
1284 |
|
|
if (pcmd==2'b00)
|
1285 |
|
|
rstcmd <= 1'b0;
|
1286 |
|
|
end
|
1287 |
|
|
WAITLOAD:
|
1288 |
|
|
if (m_resp.ack|tocnt[10]) begin
|
1289 |
|
|
wb_nack();
|
1290 |
|
|
state <= IDLE;
|
1291 |
|
|
end
|
1292 |
|
|
LOAD_OOB:
|
1293 |
|
|
state <= IDLE;
|
1294 |
|
|
default: state <= IDLE;
|
1295 |
|
|
endcase
|
1296 |
|
|
end
|
1297 |
|
|
|
1298 |
|
|
task wb_nack;
|
1299 |
|
|
begin
|
1300 |
|
|
m_fst_o <= LOW;
|
1301 |
|
|
vm_cyc_o <= LOW;
|
1302 |
|
|
m_req.we <= LOW;
|
1303 |
|
|
m_req.sel <= 16'h0000;
|
1304 |
|
|
end
|
1305 |
|
|
endtask
|
1306 |
|
|
|
1307 |
|
|
reg [31:0] rgbo2,rgbo4;
|
1308 |
|
|
reg [MDW-1:0] rgbo3;
|
1309 |
|
|
always_ff @(posedge vclk)
|
1310 |
|
|
case(color_depth2)
|
1311 |
|
|
BPP8: rgbo4 <= {24'h0,rgbo3[7:0]}; // feeds into palette
|
1312 |
|
|
BPP16: rgbo4 <= {rgbo3[15:10],5'b0,rgbo3[9:5],5'b0,rgbo3[4:0],5'b0};
|
1313 |
|
|
BPP24: rgbo4 <= {rgbo3[23:16],2'b0,rgbo3[15:8],2'b0,rgbo3[7:0],2'b0};
|
1314 |
|
|
BPP32: rgbo4 <= {rgbo3[29:20],rgbo3[19:10],rgbo3[9:0]};
|
1315 |
|
|
default: rgbo4 <= {rgbo3[15:10],5'b0,rgbo3[9:5],5'b0,rgbo3[4:0],5'b0};
|
1316 |
|
|
endcase
|
1317 |
|
|
|
1318 |
|
|
reg rd_fifo,rd_fifo1,rd_fifo2;
|
1319 |
|
|
/*
|
1320 |
|
|
reg de;
|
1321 |
|
|
always_ff @(posedge vclk)
|
1322 |
|
|
if (rd_fifo1)
|
1323 |
|
|
de <= ~blank_i;
|
1324 |
|
|
*/
|
1325 |
|
|
|
1326 |
|
|
always_ff @(posedge vclk)
|
1327 |
|
|
if (onoff && xonoff_i && !blank_i) begin
|
1328 |
|
|
if (color_depth2==BPP8) begin
|
1329 |
|
|
if (!greyscale)
|
1330 |
|
|
zrgb <= pal_o;
|
1331 |
|
|
else
|
1332 |
|
|
zrgb <= {pal_o[31:30],pal_o[9:0],pal_o[9:0],pal_o[9:0]};
|
1333 |
|
|
end
|
1334 |
|
|
else
|
1335 |
|
|
zrgb <= rgbo4;
|
1336 |
|
|
end
|
1337 |
|
|
else
|
1338 |
|
|
zrgb <= 32'h00000000;
|
1339 |
|
|
always_ff @(posedge vclk)
|
1340 |
|
|
if (zrgb==trans_color)
|
1341 |
|
|
rgb_o <= rgb_i;
|
1342 |
|
|
else
|
1343 |
|
|
rgb_o <= zrgb;
|
1344 |
|
|
|
1345 |
|
|
// Before the hrefdelay expires, pixelCol will be negative, which is greater
|
1346 |
|
|
// than windowWidth as the value is unsigned. That means that fifo reading is
|
1347 |
|
|
// active only during the display area 0 to windowWidth.
|
1348 |
|
|
reg shift1;
|
1349 |
|
|
always_comb shift1 = hc==hres;
|
1350 |
|
|
reg [5:0] shift_cnt;
|
1351 |
|
|
always_ff @(posedge vclk)
|
1352 |
|
|
if (pe_hsync)
|
1353 |
|
|
shift_cnt <= 5'd1;
|
1354 |
|
|
else begin
|
1355 |
|
|
if (shift1) begin
|
1356 |
|
|
if (pixelCol==16'hFFFF)
|
1357 |
|
|
shift_cnt <= shifts;
|
1358 |
|
|
else if (!pixelCol[15]) begin
|
1359 |
|
|
shift_cnt <= shift_cnt + 5'd1;
|
1360 |
|
|
if (shift_cnt==shifts)
|
1361 |
|
|
shift_cnt <= 5'd1;
|
1362 |
|
|
end
|
1363 |
|
|
else
|
1364 |
|
|
shift_cnt <= 5'd1;
|
1365 |
|
|
end
|
1366 |
|
|
end
|
1367 |
|
|
|
1368 |
|
|
reg next_strip;
|
1369 |
|
|
always_comb next_strip = (shift_cnt==shifts) && (hc==hres);
|
1370 |
|
|
|
1371 |
|
|
wire vrd;
|
1372 |
|
|
reg shift,shift2;
|
1373 |
|
|
always_ff @(posedge vclk) shift2 <= shift1;
|
1374 |
|
|
always_ff @(posedge vclk) shift <= shift2;
|
1375 |
|
|
always_ff @(posedge vclk) rd_fifo2 <= next_strip;
|
1376 |
|
|
always_ff @(posedge vclk) rd_fifo <= rd_fifo2;
|
1377 |
|
|
always_ff @(posedge vclk)
|
1378 |
|
|
if (rd_fifo)
|
1379 |
|
|
rgbo3 <= lef ? rgbo1o : rgbo1e;
|
1380 |
|
|
else if (shift) begin
|
1381 |
|
|
case(color_depth2)
|
1382 |
|
|
BPP8: rgbo3 <= {8'h0,rgbo3[MDW-1:8]};
|
1383 |
|
|
BPP16: rgbo3 <= {16'h0,rgbo3[MDW-1:16]};
|
1384 |
|
|
BPP24: rgbo3 <= {24'h0,rgbo3[MDW-1:24]};
|
1385 |
|
|
BPP32: rgbo3 <= {32'h0,rgbo3[MDW-1:32]};
|
1386 |
|
|
default: rgbo3 <= {16'h0,rgbo3[MDW-1:16]};
|
1387 |
|
|
endcase
|
1388 |
|
|
end
|
1389 |
|
|
|
1390 |
|
|
|
1391 |
|
|
/* Debugging
|
1392 |
|
|
wire [127:0] dat;
|
1393 |
|
|
assign dat[11:0] = pixelRow[0] ? 12'hEA4 : 12'h000;
|
1394 |
|
|
assign dat[23:12] = pixelRow[1] ? 12'hEA4 : 12'h000;
|
1395 |
|
|
assign dat[35:24] = pixelRow[2] ? 12'hEA4 : 12'h000;
|
1396 |
|
|
assign dat[47:36] = pixelRow[3] ? 12'hEA4 : 12'h000;
|
1397 |
|
|
assign dat[59:48] = pixelRow[4] ? 12'hEA4 : 12'h000;
|
1398 |
|
|
assign dat[71:60] = pixelRow[5] ? 12'hEA4 : 12'h000;
|
1399 |
|
|
assign dat[83:72] = pixelRow[6] ? 12'hEA4 : 12'h000;
|
1400 |
|
|
assign dat[95:84] = pixelRow[7] ? 12'hEA4 : 12'h000;
|
1401 |
|
|
assign dat[107:96] = pixelRow[8] ? 12'hEA4 : 12'h000;
|
1402 |
|
|
assign dat[119:108] = pixelRow[9] ? 12'hEA4 : 12'h000;
|
1403 |
|
|
*/
|
1404 |
|
|
|
1405 |
|
|
reg [MDW-1:0] oob_dat;
|
1406 |
|
|
always_comb
|
1407 |
|
|
case(color_depth2)
|
1408 |
|
|
BPP8: oob_dat <= {MDW/8{oob_color[7:0]}};
|
1409 |
|
|
BPP16: oob_dat <= {MDW/16{oob_color[15:0]}};
|
1410 |
|
|
BPP24: oob_dat <= {MDW/24{oob_color[23:0]}};
|
1411 |
|
|
BPP32: oob_dat <= {MDW/32{oob_color[31:0]}};
|
1412 |
|
|
default: oob_dat <= {MDW/16{oob_color[15:0]}};
|
1413 |
|
|
endcase
|
1414 |
|
|
|
1415 |
|
|
rfVideoFifo #(MDW) uf1
|
1416 |
|
|
(
|
1417 |
|
|
.wrst(fifo_wrst),
|
1418 |
|
|
.wclk(m_clk_i),
|
1419 |
|
|
.wr((((m_resp.ack|tocnt[10]) && state==WAITLOAD) || state==LOAD_OOB) && lef),
|
1420 |
|
|
.di((state==LOAD_OOB) ? oob_dat : m_resp.dat),
|
1421 |
|
|
.rrst(fifo_rrst),
|
1422 |
|
|
.rclk(vclk),
|
1423 |
|
|
.rd(rd_fifo & lof),
|
1424 |
|
|
.dout(rgbo1e),
|
1425 |
|
|
.cnt()
|
1426 |
|
|
);
|
1427 |
|
|
|
1428 |
|
|
rfVideoFifo #(MDW) uf2
|
1429 |
|
|
(
|
1430 |
|
|
.wrst(fifo_wrst),
|
1431 |
|
|
.wclk(m_clk_i),
|
1432 |
|
|
.wr((((m_resp.ack|tocnt[10]) && state==WAITLOAD) || state==LOAD_OOB) && lof),
|
1433 |
|
|
.di((state==LOAD_OOB) ? oob_dat : m_resp.dat),
|
1434 |
|
|
.rrst(fifo_rrst),
|
1435 |
|
|
.rclk(vclk),
|
1436 |
|
|
.rd(rd_fifo & lef),
|
1437 |
|
|
.dout(rgbo1o),
|
1438 |
|
|
.cnt()
|
1439 |
|
|
);
|
1440 |
|
|
|
1441 |
|
|
endmodule
|
1442 |
|
|
|
1443 |
|
|
// Horizontal or vertical pixel counter.
|
1444 |
|
|
// If the count is negative, step by one keeps the meaning of the refdelay value
|
1445 |
|
|
// consistent between different resolutions.
|
1446 |
|
|
|
1447 |
|
|
module pixelCounter(rst, clk, ce, res, d, q, mq);
|
1448 |
|
|
input rst;
|
1449 |
|
|
input clk;
|
1450 |
|
|
input ce;
|
1451 |
|
|
input [2:0] res;
|
1452 |
|
|
input [15:0] d;
|
1453 |
|
|
output reg [15:0] q;
|
1454 |
|
|
output reg [2:0] mq; // modulo count
|
1455 |
|
|
|
1456 |
|
|
always_ff @(posedge clk)
|
1457 |
|
|
if (rst) begin
|
1458 |
|
|
mq <= 3'd1;
|
1459 |
|
|
q <= d;
|
1460 |
|
|
end
|
1461 |
|
|
else begin
|
1462 |
|
|
if (ce) begin
|
1463 |
|
|
if (&q[15:12]) begin
|
1464 |
|
|
q <= q + 16'd1;
|
1465 |
|
|
mq <= 3'd1;
|
1466 |
|
|
end
|
1467 |
|
|
else if (mq==res) begin
|
1468 |
|
|
mq <= 3'd1;
|
1469 |
|
|
q <= q + 16'd1;
|
1470 |
|
|
end
|
1471 |
|
|
else
|
1472 |
|
|
mq <= mq + 3'd1;
|
1473 |
|
|
end
|
1474 |
|
|
end
|
1475 |
|
|
|
1476 |
|
|
endmodule
|