]> Joshua Wise's Git repositories - vterm.git/blame - VTerm.v
Add a basic PS2 module that can do only upper case.
[vterm.git] / VTerm.v
CommitLineData
a55fc9f4
JW
1module MulDivDCM(input xtal, output clk);
2 parameter div = 5;
3 parameter mul = 2;
4
5 wire CLKFX_BUF;
6 wire GND_BIT = 0;
7 BUFG CLKFX_BUFG_INST (.I(CLKFX_BUF),
8 .O(clk));
9 DCM_SP DCM_SP_INST (.CLKFB(GND_BIT),
10 .CLKIN(xtal),
11 .DSSEN(GND_BIT),
12 .PSCLK(GND_BIT),
13 .PSEN(GND_BIT),
14 .PSINCDEC(GND_BIT),
15 .RST(GND_BIT),
16 .CLKFX(CLKFX_BUF));
17 defparam DCM_SP_INST.CLK_FEEDBACK = "NONE";
18 defparam DCM_SP_INST.CLKDV_DIVIDE = 2.0;
19 defparam DCM_SP_INST.CLKFX_DIVIDE = div;
20 defparam DCM_SP_INST.CLKFX_MULTIPLY = mul;
21 defparam DCM_SP_INST.CLKIN_DIVIDE_BY_2 = "FALSE";
22 defparam DCM_SP_INST.CLKIN_PERIOD = 20.000;
23 defparam DCM_SP_INST.CLKOUT_PHASE_SHIFT = "NONE";
24 defparam DCM_SP_INST.DESKEW_ADJUST = "SYSTEM_SYNCHRONOUS";
25 defparam DCM_SP_INST.DFS_FREQUENCY_MODE = "LOW";
26 defparam DCM_SP_INST.DLL_FREQUENCY_MODE = "LOW";
27 defparam DCM_SP_INST.DUTY_CYCLE_CORRECTION = "TRUE";
28 defparam DCM_SP_INST.FACTORY_JF = 16'hC080;
29 defparam DCM_SP_INST.PHASE_SHIFT = 0;
30 defparam DCM_SP_INST.STARTUP_WAIT = "TRUE";
31endmodule
32
33module VTerm(
34 input xtal,
35 output wire vs, hs,
36 output reg [2:0] red,
37 output reg [2:0] green,
0491ebad 38 output reg [1:0] blue,
01e9841e
JW
39 input serrx,
40 output sertx,
41 input ps2c, ps2d);
a55fc9f4
JW
42
43 wire clk25;
44
45 wire [11:0] x, y;
46 wire border;
47
48 MulDivDCM dcm25(xtal, clk25);
49 defparam dcm25.div = 4;
50 defparam dcm25.mul = 2;
51
52 SyncGen sync(clk25, vs, hs, x, y, border);
53
d3ae999b
JW
54 wire [7:0] cschar;
55 wire [2:0] csrow;
56 wire [7:0] csdata;
57
7b96452d 58 wire [10:0] vraddr;
d3ae999b
JW
59 wire [7:0] vrdata;
60
7b96452d 61 wire [10:0] vwaddr;
0491ebad 62 wire [7:0] vwdata;
7b96452d
JW
63 wire [7:0] serdata;
64 wire vwr, serwr;
65 wire [10:0] vscroll;
d3ae999b
JW
66
67 wire odata;
68
cad52b37
JW
69 wire [7:0] sertxdata;
70 wire sertxwr;
71
d3ae999b 72 CharSet cs(cschar, csrow, csdata);
7b96452d 73 VideoRAM vram(clk25, vraddr + vscroll, vrdata, vwaddr, vwdata, vwr);
d3ae999b 74 VDisplay dpy(clk25, x, y, vraddr, vrdata, cschar, csrow, csdata, odata);
7b96452d 75 SerRX rx(clk25, serwr, serdata, serrx);
cad52b37 76 SerTX tx(clk25, sertxwr, sertxdata, sertx);
7b96452d 77 RXState rxsm(clk25, vwr, vwaddr, vwdata, vscroll, serwr, serdata);
cad52b37 78 PS2 ps2(clk25, ps2c, ps2d, sertxwr, sertxdata);
d3ae999b 79
a55fc9f4 80 always @(posedge clk25) begin
d3ae999b
JW
81 red <= border ? 0 : {3{odata}};
82 green <= border ? 0 : {3{odata}};
83 blue <= border ? 0 : {2{odata}};
a55fc9f4
JW
84 end
85endmodule
86
87module SyncGen(
88 input pixclk,
89 output reg vs, hs,
90 output reg [11:0] x, y,
91 output reg border);
92
93 parameter XRES = 640;
94 parameter XFPORCH = 16;
95 parameter XSYNC = 96;
96 parameter XBPORCH = 48;
97
98 parameter YRES = 480;
99 parameter YFPORCH = 10;
100 parameter YSYNC = 2;
101 parameter YBPORCH = 29;
102
103 always @(posedge pixclk)
104 begin
105 if (x >= (XRES + XFPORCH + XSYNC + XBPORCH))
106 begin
107 if (y >= (YRES + YFPORCH + YSYNC + YBPORCH))
108 y = 0;
109 else
110 y = y + 1;
111 x = 0;
112 end else
113 x = x + 1;
114 hs <= (x >= (XRES + XFPORCH)) && (x < (XRES + XFPORCH + XSYNC));
115 vs <= (y >= (YRES + YFPORCH)) && (y < (YRES + YFPORCH + YSYNC));
116 border <= (x > XRES) || (y > YRES);
117 end
118endmodule
d3ae999b
JW
119
120module CharSet(
121 input [7:0] char,
122 input [2:0] row,
123 output wire [7:0] data);
124
125 reg [7:0] rom [(256 * 8 - 1):0];
126
127 initial
128 $readmemb("ibmpc1.mem", rom);
129
130 assign data = rom[{char, row}];
131endmodule
132
133module VideoRAM(
134 input pixclk,
7b96452d 135 input [10:0] raddr,
d3ae999b 136 output reg [7:0] rdata,
7b96452d 137 input [10:0] waddr,
d3ae999b
JW
138 input [7:0] wdata,
139 input wr);
140
7b96452d 141 reg [7:0] ram [2047 : 0];
d3ae999b
JW
142
143 always @(posedge pixclk)
144 rdata <= ram[raddr];
145
146 always @(posedge pixclk)
147 if (wr)
148 ram[waddr] <= wdata;
149endmodule
150
151module VDisplay(
152 input pixclk,
153 input [11:0] x,
154 input [11:0] y,
7b96452d 155 output wire [10:0] raddr,
d3ae999b
JW
156 input [7:0] rchar,
157 output wire [7:0] cschar,
158 output wire [2:0] csrow,
159 input [7:0] csdata,
01e9841e 160 output reg data);
d3ae999b
JW
161
162 wire [7:0] col = x[11:3];
163 wire [5:0] row = y[9:3];
164 reg [7:0] ch;
165 reg [11:0] xdly;
166
167 assign raddr = ({row,4'b0} + {row,6'b0} + {4'h0,col});
168 assign cschar = rchar;
169 assign csrow = y[2:0];
170
171 always @(posedge pixclk)
172 xdly <= x;
173
174 always @(posedge pixclk)
175 data = ((xdly < 80 * 8) && (y < 25 * 8)) ? csdata[7 - xdly[2:0]] : 0;
176endmodule
0491ebad
JW
177
178`define IN_CLK 25000000
179`define OUT_CLK 57600
180`define CLK_DIV (`IN_CLK / `OUT_CLK)
181
182module SerRX(
183 input pixclk,
184 output reg wr = 0,
0491ebad 185 output reg [7:0] wchar = 0,
01e9841e 186 input serialrx);
0491ebad
JW
187
188 reg [15:0] rx_clkdiv = 0;
189 reg [3:0] rx_state = 4'b0000;
190 reg [7:0] rx_data_tmp;
191
192
193 always @(posedge pixclk)
194 begin
195 if ((rx_state == 0) && (serialrx == 0) /*&& (rx_hasdata == 0)*/) /* Kick off. */
196 rx_state <= 4'b0001;
197 else if ((rx_state != 4'b0000) && (rx_clkdiv == 0)) begin
198 if (rx_state != 4'b1010)
199 rx_state <= rx_state + 1;
200 else
201 rx_state <= 0;
202 case (rx_state)
203 4'b0001: begin end /* Twiddle thumbs -- this is the end of the half bit. */
204 4'b0010: rx_data_tmp[0] <= serialrx;
205 4'b0011: rx_data_tmp[1] <= serialrx;
206 4'b0100: rx_data_tmp[2] <= serialrx;
207 4'b0101: rx_data_tmp[3] <= serialrx;
208 4'b0110: rx_data_tmp[4] <= serialrx;
209 4'b0111: rx_data_tmp[5] <= serialrx;
210 4'b1000: rx_data_tmp[6] <= serialrx;
211 4'b1001: rx_data_tmp[7] <= serialrx;
212 4'b1010: if (serialrx == 1) begin
213 wr <= 1;
214 wchar <= rx_data_tmp;
215 end
216 endcase
217 end
218
7b96452d 219 if (wr)
0491ebad 220 wr <= 0;
0491ebad
JW
221
222 if ((rx_state == 0) && (serialrx == 0) /*&& (rx_hasdata == 0)*/) /* Wait half a period before advancing. */
223 rx_clkdiv <= `CLK_DIV / 2 + `CLK_DIV / 4;
224 else if (rx_clkdiv == `CLK_DIV)
225 rx_clkdiv <= 0;
226 else
227 rx_clkdiv <= rx_clkdiv + 1;
228 end
01e9841e
JW
229endmodule
230
231module SerTX(
232 input pixclk,
233 input wr,
234 input [7:0] char,
235 output reg serial = 1);
236
237 reg [7:0] tx_data = 0;
238 reg [15:0] tx_clkdiv = 0;
239 reg [3:0] tx_state = 4'b0000;
240 reg tx_busy = 0;
241 wire tx_newdata = wr && !tx_busy;
0491ebad 242
01e9841e
JW
243 always @(posedge pixclk)
244 begin
245 if(tx_newdata) begin
246 tx_data <= char;
247 tx_state <= 4'b0000;
248 tx_busy <= 1;
249 end else if (tx_clkdiv == 0) begin
250 tx_state <= tx_state + 1;
251 if (tx_busy)
252 case (tx_state)
253 4'b0000: serial <= 0;
254 4'b0001: serial <= tx_data[0];
255 4'b0010: serial <= tx_data[1];
256 4'b0011: serial <= tx_data[2];
257 4'b0100: serial <= tx_data[3];
258 4'b0101: serial <= tx_data[4];
259 4'b0110: serial <= tx_data[5];
260 4'b0111: serial <= tx_data[6];
261 4'b1000: serial <= tx_data[7];
262 4'b1001: serial <= 1;
263 4'b1010: tx_busy <= 0;
264 default: $stop;
265 endcase
266 end
267
268 if(tx_newdata || (tx_clkdiv == `CLK_DIV))
269 tx_clkdiv <= 0;
270 else
271 tx_clkdiv <= tx_clkdiv + 1;
272 end
0491ebad 273endmodule
7b96452d
JW
274
275module RXState(
276 input clk25,
277 output reg vwr = 0,
278 output reg [10:0] vwaddr = 0,
279 output reg [7:0] vwdata = 0,
280 output reg [10:0] vscroll = 0,
281 input serwr,
282 input [7:0] serdata);
283
284 parameter STATE_IDLE = 4'b0000;
285 parameter STATE_NEWLINE = 4'b0001;
286 parameter STATE_CLEAR = 4'b0010;
287
288 reg [3:0] state = STATE_CLEAR;
289
290 reg [6:0] x = 0;
291 reg [4:0] y = 0;
292
293 reg [10:0] clearstart = 0;
294 reg [10:0] clearend = 11'b11111111111;
295
296 always @(posedge clk25)
297 case (state)
298 STATE_IDLE: if (serwr) begin
299 if (serdata == 8'h0A) begin
300 state <= STATE_NEWLINE;
301 vwr <= 0;
302 end else if (serdata == 8'h0D) begin
303 x <= 0;
304 vwr <= 0;
305 end else if (serdata == 8'h0C) begin
306 clearstart <= 0;
307 clearend <= 11'b11111111111;
308 x <= 0;
309 y <= 0;
310 vscroll <= 0;
311 state <= STATE_CLEAR;
312 end else begin
313 vwr <= 1;
314 vwaddr <= ({y,4'b0} + {y,6'b0} + {4'h0,x}) + vscroll;
315 vwdata <= serdata;
316 if (x == 79) begin
317 x <= 0;
318 state <= STATE_NEWLINE;
319 end else
320 x <= x + 1;
321 end
322 end
323 STATE_NEWLINE:
324 begin
325 vwr <= 0;
326 if (y == 24) begin
327 vscroll <= vscroll + 80;
328 clearstart <= (25 * 80) + vscroll;
329 clearend <= (26*80) + vscroll;
330 state <= STATE_CLEAR;
331 end else begin
332 y <= y + 1;
333 state <= STATE_IDLE;
334 end
335 end
336 STATE_CLEAR:
337 begin
338 vwr <= 1;
339 vwaddr <= clearstart;
340 vwdata <= 8'h20;
341 clearstart <= clearstart + 1;
342 if (clearstart == clearend)
343 state <= STATE_IDLE;
344 end
345 endcase
346endmodule
cad52b37
JW
347
348module PS2(
349 input pixclk,
350 input inclk,
351 input indata,
352 output reg wr,
353 output reg [7:0] data
354 );
355
356 reg [3:0] bitcount = 0;
357 reg [7:0] key = 0;
358 reg keyarrow = 0, keyup = 0, parity = 0;
359
360
361 /* Clock debouncing */
362 reg lastinclk = 0;
363 reg [6:0] debounce = 0;
364 reg fixedclk = 0;
365 reg [11:0] resetcountdown = 0;
366
367 reg nd = 0;
368 reg lastnd = 0;
369
370 always @(posedge pixclk) begin
371 if (inclk != lastinclk) begin
372 lastinclk <= inclk;
373 debounce <= 1;
374 resetcountdown <= 12'b111111111111;
375 end else if (debounce == 0) begin
376 fixedclk <= inclk;
377 resetcountdown <= resetcountdown - 1;
378 end else
379 debounce <= debounce + 1;
380
381 if (nd ^ lastnd) begin
382 lastnd <= nd;
383 wr <= 1;
384 end else
385 wr <= 0;
386 end
387
388 always @(negedge fixedclk) begin
389 if (resetcountdown == 0)
390 bitcount <= 0;
391 else if (bitcount == 10) begin
392 bitcount <= 0;
393 if(parity != (^ key)) begin
394 if(keyarrow) begin
395 keyarrow <= 0;
396 case(key)
397 8'hF0: keyup <= 1;
398 endcase
399 end
400 else begin
401 if(keyup) begin
402 keyup <= 0;
403 // handle this? I don't fucking know
404 end
405 else begin
406 case(key)
407 8'hE0: keyarrow <= 1; // handle these? I don't fucking know
408 8'hF0: keyup <= 1;
409 8'h1C: begin nd <= ~nd; data <= 8'h41; end
410 8'h32: begin nd <= ~nd; data <= 8'h42; end
411 8'h21: begin nd <= ~nd; data <= 8'h43; end
412 8'h23: begin nd <= ~nd; data <= 8'h44; end
413 8'h24: begin nd <= ~nd; data <= 8'h45; end
414 8'h2B: begin nd <= ~nd; data <= 8'h46; end
415 8'h34: begin nd <= ~nd; data <= 8'h47; end
416 8'h33: begin nd <= ~nd; data <= 8'h48; end
417 8'h43: begin nd <= ~nd; data <= 8'h49; end
418 8'h3B: begin nd <= ~nd; data <= 8'h4A; end
419 8'h42: begin nd <= ~nd; data <= 8'h4B; end
420 8'h4B: begin nd <= ~nd; data <= 8'h4C; end
421 8'h3A: begin nd <= ~nd; data <= 8'h4D; end
422 8'h31: begin nd <= ~nd; data <= 8'h4E; end
423 8'h44: begin nd <= ~nd; data <= 8'h4F; end
424 8'h4D: begin nd <= ~nd; data <= 8'h50; end
425 8'h15: begin nd <= ~nd; data <= 8'h51; end
426 8'h2D: begin nd <= ~nd; data <= 8'h52; end
427 8'h1B: begin nd <= ~nd; data <= 8'h53; end
428 8'h2C: begin nd <= ~nd; data <= 8'h54; end
429 8'h3C: begin nd <= ~nd; data <= 8'h55; end
430 8'h2A: begin nd <= ~nd; data <= 8'h56; end
431 8'h1D: begin nd <= ~nd; data <= 8'h57; end
432 8'h22: begin nd <= ~nd; data <= 8'h58; end
433 8'h35: begin nd <= ~nd; data <= 8'h59; end
434 8'h1A: begin nd <= ~nd; data <= 8'h60; end
435 endcase
436 end
437 end
438 end
439 else begin
440 keyarrow <= 0;
441 keyup <= 0;
442 end
443 end else
444 bitcount <= bitcount + 1;
445
446 case(bitcount)
447 1: key[0] <= indata;
448 2: key[1] <= indata;
449 3: key[2] <= indata;
450 4: key[3] <= indata;
451 5: key[4] <= indata;
452 6: key[5] <= indata;
453 7: key[6] <= indata;
454 8: key[7] <= indata;
455 9: parity <= indata;
456 endcase
457 end
458
459endmodule
This page took 0.061473 seconds and 4 git commands to generate.