1 module MulDivDCM(input xtal, output clk, output clk90);
10 BUFG CLK0_BUFG_INST (.I(CLK0_BUF),
12 BUFG CLK90_BUFG_INST (.I(CLK90_BUF),
14 BUFG CLKFX_BUFG_INST (.I(CLKFX_BUF),
17 DCM_BASE DCM_INST2(.CLKFB(clk),
23 DCM_BASE DCM_INST (.CLKFB(GND_BIT),
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";
49 output wire dvi_vs, dvi_hs,
50 output wire [11:0] dvi_d,
51 output wire dvi_xclk_p, dvi_xclk_n,
53 output wire dvi_reset_b,
58 assign dvi_reset_b = 1'b1;
65 MulDivDCM dcm25(xtal, clk25, clk25_90);
66 defparam dcm25.div = 16;
67 defparam dcm25.mul = 5;
70 SyncGen sync(clk25, vs, hs, x, y, border);
90 reg [16:0] rsttimer = 17'h3FFFF;
91 always @(posedge clk25)
93 rsttimer <= 17'h3FFFF;
95 rsttimer <= rsttimer - 1;
96 assign rstact = rsttimer != 17'h0;
102 wire [7:0] sertxdata;
104 CharSet cs(cschar, csrow, csdata);
105 VideoRAM vram(clk25, vraddr + vscroll, vrdata, clk25, vwaddr, vwdata, vwr);
106 VDisplay dpy(clk25, x, y, vraddr, vrdata, cschar, csrow, csdata, vcursx, vcursy, odata);
107 RXState rxsm(clk25, vwr, vwaddr, vwdata, vscroll, vcursx, vcursy, serwr, serdata);
108 PS2 ps2(clk25, ps2c, ps2d, sertxwr, sertxdata);
109 System sys(.clk(clk25), .rst(rstact), .sys_odata({serwr, serdata}), .sys_idata({ps2_hasd, ps2_d}), .sys_tookdata(tookdata));
111 always @(posedge clk25)
113 {ps2_hasd, ps2_d} <= {1'b1, sertxdata};
115 {ps2_hasd, ps2_d} <= {1'b0, 8'hxxxxxxxx};
117 /* FUCK! ASS! BALLS! EAT MY SHORT DICK! FUCKING XST */
118 /* EMSD stands for Eat My Short Dick. Because XST should. */
119 `define MAKE_DDR(n,q,d1,d2) ODDR n (.C(clk25), .Q(q), .D1(d1), .D2(d2), .R(0), .S(0), .CE(1))
120 `define MAKE_DDR90(n,q,d1,d2) ODDR n (.C(clk25_90), .Q(q), .D1(d1), .D2(d2), .R(0), .S(0), .CE(1))
122 wire [7:0] red, green, blue;
123 assign red = (odata ? 8'hFF : 0) | (x[8:2] ^ y[7:1]);
124 assign green = (odata ? 8'hFF : 0) | (x[7:1] ^ y[8:2]);
125 assign blue = (odata ? 8'hFF : 0) | (x[8:2] ^ y[8:2]);
127 `MAKE_DDR90(EMSD_dvi_xclk_p, dvi_xclk_p, 1'b1, 1'b0);
128 `MAKE_DDR90(EMSD_dvi_xclk_n, dvi_xclk_n, 1'b0, 1'b1);
129 `MAKE_DDR(EMSD_dvi_de, dvi_de, ~border, ~border);
130 `MAKE_DDR(EMSD_dvi_vs, dvi_vs, vs, vs);
131 `MAKE_DDR(EMSD_dvi_hs, dvi_hs, hs, hs);
132 `MAKE_DDR(EMSD_dvi_d_0, dvi_d[0], blue[0], green[4]);
133 `MAKE_DDR(EMSD_dvi_d_1, dvi_d[1], blue[1], green[5]);
134 `MAKE_DDR(EMSD_dvi_d_2, dvi_d[2], blue[2], green[6]);
135 `MAKE_DDR(EMSD_dvi_d_3, dvi_d[3], blue[3], green[7]);
136 `MAKE_DDR(EMSD_dvi_d_4, dvi_d[4], blue[4], red[0]);
137 `MAKE_DDR(EMSD_dvi_d_5, dvi_d[5], blue[5], red[1]);
138 `MAKE_DDR(EMSD_dvi_d_6, dvi_d[6], blue[6], red[2]);
139 `MAKE_DDR(EMSD_dvi_d_7, dvi_d[7], blue[7], red[3]);
140 `MAKE_DDR(EMSD_dvi_d_8, dvi_d[8], green[0], red[4]);
141 `MAKE_DDR(EMSD_dvi_d_9, dvi_d[9], green[1], red[5]);
142 `MAKE_DDR(EMSD_dvi_d_10, dvi_d[10], green[2], red[6]);
143 `MAKE_DDR(EMSD_dvi_d_11, dvi_d[11], green[3], red[7]);
146 iic_init #(.CLK_RATE_MHZ(31)) init (clk25, 1'b1, 1'b0, dvi_sda, dvi_scl, wee);
153 output reg [11:0] x, y,
156 parameter XRES = 640;
157 parameter XFPORCH = 24;
158 parameter XSYNC = 40;
159 parameter XBPORCH = 128;
161 parameter YRES = 480;
162 parameter YFPORCH = 9;
164 parameter YBPORCH = 28;
166 always @(posedge pixclk)
168 if (x >= (XRES + XFPORCH + XSYNC + XBPORCH))
170 if (y >= (YRES + YFPORCH + YSYNC + YBPORCH))
177 hs <= (x >= (XRES + XFPORCH)) && (x < (XRES + XFPORCH + XSYNC));
178 vs <= (y >= (YRES + YFPORCH)) && (y < (YRES + YFPORCH + YSYNC));
179 border <= (x > XRES) || (y > YRES);
186 output wire [7:0] data);
188 reg [7:0] rom [(256 * 8 - 1):0];
191 $readmemb("ibmpc1.mem", rom);
193 assign data = rom[{char, row}];
199 output reg [7:0] rdata,
205 reg [7:0] ram [2047 : 0];
207 always @(posedge pixclk)
210 always @(posedge wclk)
219 output wire [10:0] raddr,
221 output wire [7:0] cschar,
222 output wire [2:0] csrow,
228 wire [7:0] col = x[11:3];
229 wire [5:0] row = y[10:4];
233 assign raddr = ({row,4'b0} + {row,6'b0} + {4'h0,col});
234 assign cschar = rchar;
235 assign csrow = y[3:1];
237 reg [23:0] blinktime = 0;
239 always @(posedge pixclk) blinktime <= blinktime + 1;
241 wire curssel = (cursx == col) && (cursy == row) && blinktime[23];
243 always @(posedge pixclk)
246 always @(posedge pixclk)
247 data = ((xdly < 80 * 8) && (y < 25 * 16)) ? (csdata[7 - xdly[2:0]] ^ curssel) : 0;
253 output reg [10:0] vwaddr = 0,
254 output reg [7:0] vwdata = 0,
255 output reg [10:0] vscroll = 0,
256 output wire [6:0] vcursx,
257 output wire [4:0] vcursy,
259 input [7:0] serdata);
261 parameter STATE_IDLE = 4'b0000;
262 parameter STATE_NEWLINE = 4'b0001;
263 parameter STATE_CLEAR = 4'b0010;
265 reg [3:0] state = STATE_CLEAR;
273 reg [10:0] clearstart = 0;
274 reg [10:0] clearend = 11'b11111111111;
276 always @(posedge clk25)
278 STATE_IDLE: if (serwr) begin
279 if (serdata == 8'h0A) begin
280 state <= STATE_NEWLINE;
283 end else if (serdata == 8'h0D) begin
286 end else if (serdata == 8'h0C) begin
288 clearend <= 11'b11111111111;
292 state <= STATE_CLEAR;
293 end else if (serdata == 8'h08) begin
299 vwaddr <= ({y,4'b0} + {y,6'b0} + {4'h0,x}) + vscroll;
303 state <= STATE_NEWLINE;
312 vscroll <= vscroll + 80;
313 clearstart <= (25 * 80) + vscroll;
314 clearend <= (26*80) + vscroll;
315 state <= STATE_CLEAR;
324 vwaddr <= clearstart;
326 clearstart <= clearstart + 1;
327 if (clearstart == clearend)
338 output reg [7:0] data
341 reg [3:0] bitcount = 0;
343 reg keyarrow = 0, keyup = 0, parity = 0;
346 /* Clock debouncing */
348 reg [6:0] debounce = 0;
350 reg [11:0] resetcountdown = 0;
352 reg [6:0] unshiftedrom [127:0]; initial $readmemh("scancodes.unshifted.hex", unshiftedrom);
353 reg [6:0] shiftedrom [127:0]; initial $readmemh("scancodes.shifted.hex", shiftedrom);
357 reg mod_capslock = 0;
358 wire mod_shifted = (mod_lshift | mod_rshift) ^ mod_capslock;
363 always @(posedge pixclk) begin
364 if (inclk != lastinclk) begin
367 resetcountdown <= 12'b111111111111;
368 end else if (debounce == 0) begin
370 resetcountdown <= resetcountdown - 1;
372 debounce <= debounce + 1;
374 if (nd ^ lastnd) begin
381 always @(negedge fixedclk) begin
382 if (resetcountdown == 0)
384 else if (bitcount == 10) begin
386 if(parity != (^ key)) begin
390 8'hxx: keyarrow <= 0;
398 8'h12: mod_lshift <= 0;
399 8'h59: mod_rshift <= 0;
401 // handle this? I don't fucking know
405 8'hE0: keyarrow <= 1; // handle these? I don't fucking know
407 8'h12: mod_lshift <= 1;
408 8'h59: mod_rshift <= 1;
409 8'h14: mod_capslock <= ~mod_capslock;
410 8'b0xxxxxxx: begin nd <= ~nd; data <= mod_shifted ? shiftedrom[key] : unshiftedrom[key]; end
411 8'b1xxxxxxx: begin /* AAAAAAASSSSSSSS */ end
421 bitcount <= bitcount + 1;