]> Joshua Wise's Git repositories - vterm.git/blob - VTerm.v
Add a basic PS2 module that can do only upper case.
[vterm.git] / VTerm.v
1 module 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";
31 endmodule
32
33 module VTerm(
34         input xtal,
35         output wire vs, hs,
36         output reg [2:0] red,
37         output reg [2:0] green,
38         output reg [1:0] blue,
39         input serrx,
40         output sertx,
41         input ps2c, ps2d);
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         
54         wire [7:0] cschar;
55         wire [2:0] csrow;
56         wire [7:0] csdata;
57         
58         wire [10:0] vraddr;
59         wire [7:0] vrdata;
60         
61         wire [10:0] vwaddr;
62         wire [7:0] vwdata;
63         wire [7:0] serdata;
64         wire vwr, serwr;
65         wire [10:0] vscroll;
66         
67         wire odata;
68         
69         wire [7:0] sertxdata;
70         wire sertxwr;
71         
72         CharSet cs(cschar, csrow, csdata);
73         VideoRAM vram(clk25, vraddr + vscroll, vrdata, vwaddr, vwdata, vwr);
74         VDisplay dpy(clk25, x, y, vraddr, vrdata, cschar, csrow, csdata, odata);
75         SerRX rx(clk25, serwr, serdata, serrx);
76         SerTX tx(clk25, sertxwr, sertxdata, sertx);
77         RXState rxsm(clk25, vwr, vwaddr, vwdata, vscroll, serwr, serdata);
78         PS2 ps2(clk25, ps2c, ps2d, sertxwr, sertxdata);
79         
80         always @(posedge clk25) begin
81                 red <= border ? 0 : {3{odata}};
82                 green <= border ? 0 : {3{odata}};
83                 blue <= border ? 0 : {2{odata}};
84         end
85 endmodule
86
87 module 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
118 endmodule
119
120 module 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}];
131 endmodule
132
133 module VideoRAM(
134         input pixclk,
135         input [10:0] raddr,
136         output reg [7:0] rdata,
137         input [10:0] waddr,
138         input [7:0] wdata,
139         input wr);
140         
141         reg [7:0] ram [2047 : 0];
142         
143         always @(posedge pixclk)
144                 rdata <= ram[raddr];
145         
146         always @(posedge pixclk)
147                 if (wr)
148                         ram[waddr] <= wdata;
149 endmodule
150
151 module VDisplay(
152         input pixclk,
153         input [11:0] x,
154         input [11:0] y,
155         output wire [10:0] raddr,
156         input [7:0] rchar,
157         output wire [7:0] cschar,
158         output wire [2:0] csrow,
159         input [7:0] csdata,
160         output reg data);
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;
176 endmodule
177
178 `define IN_CLK 25000000
179 `define OUT_CLK 57600
180 `define CLK_DIV (`IN_CLK / `OUT_CLK)
181
182 module SerRX(
183         input pixclk,
184         output reg wr = 0,
185         output reg [7:0] wchar = 0,
186         input serialrx);
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                 
219                 if (wr)
220                         wr <= 0;
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
229 endmodule
230
231 module 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;
242
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
273 endmodule
274
275 module 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
346 endmodule
347
348 module 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
459 endmodule
This page took 0.046585 seconds and 4 git commands to generate.