Console: Put the core in its own clock domain.
[firearm.git] / xst / Console.v
CommitLineData
8744c23d
JW
1module MulDivDCM(input xtal, output clk, output clk90);
2 parameter div = 8;
3 parameter mul = 2;
4
5 wire CLKFX_BUF;
6 wire CLK0_BUF;
7 wire CLK90_BUF;
8 wire clkfx;
9 wire GND_BIT = 0;
10 BUFG CLK0_BUFG_INST (.I(CLK0_BUF),
11 .O(clk));
12 BUFG CLK90_BUFG_INST (.I(CLK90_BUF),
13 .O(clk90));
14 BUFG CLKFX_BUFG_INST (.I(CLKFX_BUF),
15 .O(clkfx));
16
17 DCM_BASE DCM_INST2(.CLKFB(clk),
18 .CLKIN(clkfx),
19 .RST(GND_BIT),
20 .CLK0(CLK0_BUF),
21 .CLK90(CLK90_BUF));
22
23 DCM_BASE DCM_INST (.CLKFB(GND_BIT),
24 .CLKIN(xtal),
25 .RST(GND_BIT),
26 .CLKFX(CLKFX_BUF));
27 defparam DCM_INST.CLK_FEEDBACK = "NONE";
28 defparam DCM_INST.CLKDV_DIVIDE = 2.0;
29 defparam DCM_INST.CLKFX_DIVIDE = div;
30 defparam DCM_INST.CLKFX_MULTIPLY = mul;
31 defparam DCM_INST.CLKIN_DIVIDE_BY_2 = "FALSE";
32 defparam DCM_INST.CLKIN_PERIOD = 10.000;
33 defparam DCM_INST.CLKOUT_PHASE_SHIFT = "NONE";
34 defparam DCM_INST.DESKEW_ADJUST = "SYSTEM_SYNCHRONOUS";
35 defparam DCM_INST.DFS_FREQUENCY_MODE = "LOW";
36 defparam DCM_INST.DLL_FREQUENCY_MODE = "LOW";
37 defparam DCM_INST.DUTY_CYCLE_CORRECTION = "TRUE";
38 defparam DCM_INST.FACTORY_JF = 16'hC080;
39 defparam DCM_INST.PHASE_SHIFT = 0;
40 defparam DCM_INST.STARTUP_WAIT = "TRUE";
41endmodule
42
43`include "iic_init.v"
44
45module Console(
46 input xtal,
47 input rst,
48 output wire rstact,
49 output wire dvi_vs, dvi_hs,
50 output wire [11:0] dvi_d,
51 output wire dvi_xclk_p, dvi_xclk_n,
52 output wire dvi_de,
53 output wire dvi_reset_b,
54 inout wire dvi_sda,
55 inout wire dvi_scl,
56 input ps2c, ps2d);
57
58 assign dvi_reset_b = 1'b1;
59
2bdf3bcc 60 wire pixclk, pixclk_90, coreclk, coreclk_90;
8744c23d
JW
61
62 wire [11:0] x, y;
63 wire border;
64
2bdf3bcc
JW
65 MulDivDCM dcm31_25(xtal, pixclk, pixclk_90);
66 defparam dcm31_25.div = 16;
67 defparam dcm31_25.mul = 5;
68
69 MulDivDCM dcmcore(xtal, coreclk, coreclk_90); /* 50MHz */
70 defparam dcmcore.div = 2;
71 defparam dcmcore.mul = 1;
8744c23d
JW
72
73 wire vs, hs;
2bdf3bcc 74 SyncGen sync(pixclk, vs, hs, x, y, border);
8744c23d
JW
75
76 wire [7:0] cschar;
77 wire [2:0] csrow;
78 wire [7:0] csdata;
79
80 wire [10:0] vraddr;
81 wire [7:0] vrdata;
82
83 wire [10:0] vwaddr;
84 wire [7:0] vwdata;
85 wire [7:0] serdata;
86 wire vwr, serwr;
87 wire [10:0] vscroll;
88
89 wire odata;
90
91 wire [6:0] vcursx;
92 wire [4:0] vcursy;
93
94 reg [16:0] rsttimer = 17'h3FFFF;
2bdf3bcc 95 always @(posedge coreclk)
8744c23d
JW
96 if (~rst)
97 rsttimer <= 17'h3FFFF;
98 else if (rsttimer)
99 rsttimer <= rsttimer - 1;
100 assign rstact = rsttimer != 17'h0;
101
102 wire tookdata;
103 reg ps2_hasd = 0;
104 reg [7:0] ps2_d = 0;
105 wire sertxwr;
106 wire [7:0] sertxdata;
107
108 CharSet cs(cschar, csrow, csdata);
2bdf3bcc
JW
109 VideoRAM vram(pixclk, vraddr + vscroll, vrdata, coreclk, vwaddr, vwdata, vwr);
110 VDisplay dpy(pixclk, x, y, vraddr, vrdata, cschar, csrow, csdata, vcursx, vcursy, odata);
111 RXState rxsm(coreclk, vwr, vwaddr, vwdata, vscroll, vcursx, vcursy, serwr, serdata);
112 PS2 ps2(coreclk, ps2c, ps2d, sertxwr, sertxdata);
113 System sys(.clk(coreclk), .rst(rstact), .sys_odata({serwr, serdata}), .sys_idata({ps2_hasd, ps2_d}), .sys_tookdata(tookdata));
8744c23d 114
2bdf3bcc 115 always @(posedge coreclk)
8744c23d
JW
116 if (sertxwr)
117 {ps2_hasd, ps2_d} <= {1'b1, sertxdata};
118 else if (tookdata)
119 {ps2_hasd, ps2_d} <= {1'b0, 8'hxxxxxxxx};
120
121 /* FUCK! ASS! BALLS! EAT MY SHORT DICK! FUCKING XST */
122 /* EMSD stands for Eat My Short Dick. Because XST should. */
2bdf3bcc
JW
123`define MAKE_DDR(n,q,d1,d2) ODDR n (.C(pixclk), .Q(q), .D1(d1), .D2(d2), .R(0), .S(0), .CE(1))
124`define MAKE_DDR90(n,q,d1,d2) ODDR n (.C(pixclk_90), .Q(q), .D1(d1), .D2(d2), .R(0), .S(0), .CE(1))
8744c23d
JW
125
126 wire [7:0] red, green, blue;
127 assign red = (odata ? 8'hFF : 0) | (x[8:2] ^ y[7:1]);
128 assign green = (odata ? 8'hFF : 0) | (x[7:1] ^ y[8:2]);
129 assign blue = (odata ? 8'hFF : 0) | (x[8:2] ^ y[8:2]);
130
131 `MAKE_DDR90(EMSD_dvi_xclk_p, dvi_xclk_p, 1'b1, 1'b0);
132 `MAKE_DDR90(EMSD_dvi_xclk_n, dvi_xclk_n, 1'b0, 1'b1);
133 `MAKE_DDR(EMSD_dvi_de, dvi_de, ~border, ~border);
134 `MAKE_DDR(EMSD_dvi_vs, dvi_vs, vs, vs);
135 `MAKE_DDR(EMSD_dvi_hs, dvi_hs, hs, hs);
136 `MAKE_DDR(EMSD_dvi_d_0, dvi_d[0], blue[0], green[4]);
137 `MAKE_DDR(EMSD_dvi_d_1, dvi_d[1], blue[1], green[5]);
138 `MAKE_DDR(EMSD_dvi_d_2, dvi_d[2], blue[2], green[6]);
139 `MAKE_DDR(EMSD_dvi_d_3, dvi_d[3], blue[3], green[7]);
140 `MAKE_DDR(EMSD_dvi_d_4, dvi_d[4], blue[4], red[0]);
141 `MAKE_DDR(EMSD_dvi_d_5, dvi_d[5], blue[5], red[1]);
142 `MAKE_DDR(EMSD_dvi_d_6, dvi_d[6], blue[6], red[2]);
143 `MAKE_DDR(EMSD_dvi_d_7, dvi_d[7], blue[7], red[3]);
144 `MAKE_DDR(EMSD_dvi_d_8, dvi_d[8], green[0], red[4]);
145 `MAKE_DDR(EMSD_dvi_d_9, dvi_d[9], green[1], red[5]);
146 `MAKE_DDR(EMSD_dvi_d_10, dvi_d[10], green[2], red[6]);
147 `MAKE_DDR(EMSD_dvi_d_11, dvi_d[11], green[3], red[7]);
148
149 wire wee;
2bdf3bcc 150 iic_init #(.CLK_RATE_MHZ(31)) init (pixclk, 1'b1, 1'b0, dvi_sda, dvi_scl, wee);
8744c23d
JW
151
152endmodule
153
154module SyncGen(
155 input pixclk,
156 output reg vs, hs,
157 output reg [11:0] x, y,
158 output reg border);
159
160 parameter XRES = 640;
161 parameter XFPORCH = 24;
162 parameter XSYNC = 40;
163 parameter XBPORCH = 128;
164
165 parameter YRES = 480;
166 parameter YFPORCH = 9;
167 parameter YSYNC = 3;
168 parameter YBPORCH = 28;
169
170 always @(posedge pixclk)
171 begin
172 if (x >= (XRES + XFPORCH + XSYNC + XBPORCH))
173 begin
174 if (y >= (YRES + YFPORCH + YSYNC + YBPORCH))
175 y = 0;
176 else
177 y = y + 1;
178 x = 0;
179 end else
180 x = x + 1;
181 hs <= (x >= (XRES + XFPORCH)) && (x < (XRES + XFPORCH + XSYNC));
182 vs <= (y >= (YRES + YFPORCH)) && (y < (YRES + YFPORCH + YSYNC));
183 border <= (x > XRES) || (y > YRES);
184 end
185endmodule
186
187module CharSet(
188 input [7:0] char,
189 input [2:0] row,
190 output wire [7:0] data);
191
192 reg [7:0] rom [(256 * 8 - 1):0];
193
194 initial
195 $readmemb("ibmpc1.mem", rom);
196
197 assign data = rom[{char, row}];
198endmodule
199
200module VideoRAM(
201 input pixclk,
202 input [10:0] raddr,
203 output reg [7:0] rdata,
204 input wclk,
205 input [10:0] waddr,
206 input [7:0] wdata,
207 input wr);
208
209 reg [7:0] ram [2047 : 0];
210
211 always @(posedge pixclk)
212 rdata <= ram[raddr];
213
214 always @(posedge wclk)
215 if (wr)
216 ram[waddr] <= wdata;
217endmodule
218
219module VDisplay(
220 input pixclk,
221 input [11:0] x,
222 input [11:0] y,
223 output wire [10:0] raddr,
224 input [7:0] rchar,
225 output wire [7:0] cschar,
226 output wire [2:0] csrow,
227 input [7:0] csdata,
228 input [6:0] cursx,
229 input [4:0] cursy,
230 output reg data);
231
232 wire [7:0] col = x[11:3];
233 wire [5:0] row = y[10:4];
234 reg [7:0] ch;
235 reg [11:0] xdly;
236
237 assign raddr = ({row,4'b0} + {row,6'b0} + {4'h0,col});
238 assign cschar = rchar;
239 assign csrow = y[3:1];
240
241 reg [23:0] blinktime = 0;
242
243 always @(posedge pixclk) blinktime <= blinktime + 1;
244
245 wire curssel = (cursx == col) && (cursy == row) && blinktime[23];
246
247 always @(posedge pixclk)
248 xdly <= x;
249
250 always @(posedge pixclk)
251 data = ((xdly < 80 * 8) && (y < 25 * 16)) ? (csdata[7 - xdly[2:0]] ^ curssel) : 0;
252endmodule
253
254module RXState(
255 input clk25,
256 output reg vwr = 0,
257 output reg [10:0] vwaddr = 0,
258 output reg [7:0] vwdata = 0,
259 output reg [10:0] vscroll = 0,
260 output wire [6:0] vcursx,
261 output wire [4:0] vcursy,
262 input serwr,
263 input [7:0] serdata);
264
265 parameter STATE_IDLE = 4'b0000;
266 parameter STATE_NEWLINE = 4'b0001;
267 parameter STATE_CLEAR = 4'b0010;
268
269 reg [3:0] state = STATE_CLEAR;
270
271 reg [6:0] x = 0;
272 reg [4:0] y = 0;
273
274 assign vcursx = x;
275 assign vcursy = y;
276
277 reg [10:0] clearstart = 0;
278 reg [10:0] clearend = 11'b11111111111;
279
280 always @(posedge clk25)
281 case (state)
282 STATE_IDLE: if (serwr) begin
283 if (serdata == 8'h0A) begin
284 state <= STATE_NEWLINE;
285 x <= 0;
286 vwr <= 0;
287 end else if (serdata == 8'h0D) begin
288 x <= 0;
289 vwr <= 0;
290 end else if (serdata == 8'h0C) begin
291 clearstart <= 0;
292 clearend <= 11'b11111111111;
293 x <= 0;
294 y <= 0;
295 vscroll <= 0;
296 state <= STATE_CLEAR;
297 end else if (serdata == 8'h08) begin
298 if (x != 0)
299 x <= x - 1;
300 vwr <= 0;
301 end else begin
302 vwr <= 1;
303 vwaddr <= ({y,4'b0} + {y,6'b0} + {4'h0,x}) + vscroll;
304 vwdata <= serdata;
305 if (x == 79) begin
306 x <= 0;
307 state <= STATE_NEWLINE;
308 end else
309 x <= x + 1;
310 end
311 end
312 STATE_NEWLINE:
313 begin
314 vwr <= 0;
315 if (y == 24) begin
316 vscroll <= vscroll + 80;
317 clearstart <= (25 * 80) + vscroll;
318 clearend <= (26*80) + vscroll;
319 state <= STATE_CLEAR;
320 end else begin
321 y <= y + 1;
322 state <= STATE_IDLE;
323 end
324 end
325 STATE_CLEAR:
326 begin
327 vwr <= 1;
328 vwaddr <= clearstart;
329 vwdata <= 8'h20;
330 clearstart <= clearstart + 1;
331 if (clearstart == clearend)
332 state <= STATE_IDLE;
333 end
334 endcase
335endmodule
336
337module PS2(
338 input pixclk,
339 input inclk,
340 input indata,
341 output reg wr,
342 output reg [7:0] data
343 );
344
345 reg [3:0] bitcount = 0;
346 reg [7:0] key = 0;
347 reg keyarrow = 0, keyup = 0, parity = 0;
348
349
350 /* Clock debouncing */
351 reg lastinclk = 0;
352 reg [6:0] debounce = 0;
353 reg fixedclk = 0;
354 reg [11:0] resetcountdown = 0;
355
356 reg [6:0] unshiftedrom [127:0]; initial $readmemh("scancodes.unshifted.hex", unshiftedrom);
357 reg [6:0] shiftedrom [127:0]; initial $readmemh("scancodes.shifted.hex", shiftedrom);
358
359 reg mod_lshift = 0;
360 reg mod_rshift = 0;
361 reg mod_capslock = 0;
362 wire mod_shifted = (mod_lshift | mod_rshift) ^ mod_capslock;
363
364 reg nd = 0;
365 reg lastnd = 0;
366
367 always @(posedge pixclk) begin
368 if (inclk != lastinclk) begin
369 lastinclk <= inclk;
370 debounce <= 1;
371 resetcountdown <= 12'b111111111111;
372 end else if (debounce == 0) begin
373 fixedclk <= inclk;
374 resetcountdown <= resetcountdown - 1;
375 end else
376 debounce <= debounce + 1;
377
378 if (nd ^ lastnd) begin
379 lastnd <= nd;
380 wr <= 1;
381 end else
382 wr <= 0;
383 end
384
385 always @(negedge fixedclk) begin
386 if (resetcountdown == 0)
387 bitcount <= 0;
388 else if (bitcount == 10) begin
389 bitcount <= 0;
390 if(parity != (^ key)) begin
391 if(keyarrow) begin
392 casex(key)
393 8'hF0: keyup <= 1;
394 8'hxx: keyarrow <= 0;
395 endcase
396 end
397 else begin
398 if(keyup) begin
399 keyup <= 0;
400 keyarrow <= 0;
401 casex (key)
402 8'h12: mod_lshift <= 0;
403 8'h59: mod_rshift <= 0;
404 endcase
405 // handle this? I don't fucking know
406 end
407 else begin
408 casex(key)
409 8'hE0: keyarrow <= 1; // handle these? I don't fucking know
410 8'hF0: keyup <= 1;
411 8'h12: mod_lshift <= 1;
412 8'h59: mod_rshift <= 1;
413 8'h14: mod_capslock <= ~mod_capslock;
414 8'b0xxxxxxx: begin nd <= ~nd; data <= mod_shifted ? shiftedrom[key] : unshiftedrom[key]; end
415 8'b1xxxxxxx: begin /* AAAAAAASSSSSSSS */ end
416 endcase
417 end
418 end
419 end
420 else begin
421 keyarrow <= 0;
422 keyup <= 0;
423 end
424 end else
425 bitcount <= bitcount + 1;
426
427 case(bitcount)
428 1: key[0] <= indata;
429 2: key[1] <= indata;
430 3: key[2] <= indata;
431 4: key[3] <= indata;
432 5: key[4] <= indata;
433 6: key[5] <= indata;
434 7: key[6] <= indata;
435 8: key[7] <= indata;
436 9: parity <= indata;
437 endcase
438 end
439
440endmodule
This page took 0.054403 seconds and 4 git commands to generate.