]> Joshua Wise's Git repositories - vterm.git/blob - VTerm.v
Add the serial transmit module.
[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         CharSet cs(cschar, csrow, csdata);
70         VideoRAM vram(clk25, vraddr + vscroll, vrdata, vwaddr, vwdata, vwr);
71         VDisplay dpy(clk25, x, y, vraddr, vrdata, cschar, csrow, csdata, odata);
72         SerRX rx(clk25, serwr, serdata, serrx);
73         SerTX tx(clk25, 0, 0, sertx);
74         RXState rxsm(clk25, vwr, vwaddr, vwdata, vscroll, serwr, serdata);
75         
76         always @(posedge clk25) begin
77                 red <= border ? 0 : {3{odata}};
78                 green <= border ? 0 : {3{odata}};
79                 blue <= border ? 0 : {2{odata}};
80         end
81 endmodule
82
83 module SyncGen(
84         input pixclk,
85         output reg vs, hs,
86         output reg [11:0] x, y,
87         output reg border);
88         
89         parameter XRES = 640;
90         parameter XFPORCH = 16;
91         parameter XSYNC = 96;
92         parameter XBPORCH = 48;
93         
94         parameter YRES = 480;
95         parameter YFPORCH = 10;
96         parameter YSYNC = 2;
97         parameter YBPORCH = 29;
98         
99         always @(posedge pixclk)
100         begin
101                 if (x >= (XRES + XFPORCH + XSYNC + XBPORCH))
102                 begin
103                         if (y >= (YRES + YFPORCH + YSYNC + YBPORCH))
104                                 y = 0;
105                         else
106                                 y = y + 1;
107                         x = 0;
108                 end else
109                         x = x + 1;
110                 hs <= (x >= (XRES + XFPORCH)) && (x < (XRES + XFPORCH + XSYNC));
111                 vs <= (y >= (YRES + YFPORCH)) && (y < (YRES + YFPORCH + YSYNC));
112                 border <= (x > XRES) || (y > YRES);
113         end
114 endmodule
115
116 module CharSet(
117         input [7:0] char,
118         input [2:0] row,
119         output wire [7:0] data);
120
121         reg [7:0] rom [(256 * 8 - 1):0];
122         
123         initial
124                 $readmemb("ibmpc1.mem", rom);
125
126         assign data = rom[{char, row}];
127 endmodule
128
129 module VideoRAM(
130         input pixclk,
131         input [10:0] raddr,
132         output reg [7:0] rdata,
133         input [10:0] waddr,
134         input [7:0] wdata,
135         input wr);
136         
137         reg [7:0] ram [2047 : 0];
138         
139         always @(posedge pixclk)
140                 rdata <= ram[raddr];
141         
142         always @(posedge pixclk)
143                 if (wr)
144                         ram[waddr] <= wdata;
145 endmodule
146
147 module VDisplay(
148         input pixclk,
149         input [11:0] x,
150         input [11:0] y,
151         output wire [10:0] raddr,
152         input [7:0] rchar,
153         output wire [7:0] cschar,
154         output wire [2:0] csrow,
155         input [7:0] csdata,
156         output reg data);
157
158         wire [7:0] col = x[11:3];
159         wire [5:0] row = y[9:3];
160         reg [7:0] ch;
161         reg [11:0] xdly;
162
163         assign raddr = ({row,4'b0} + {row,6'b0} + {4'h0,col});
164         assign cschar = rchar;
165         assign csrow = y[2:0];
166         
167         always @(posedge pixclk)
168                 xdly <= x;
169         
170         always @(posedge pixclk)
171                 data = ((xdly < 80 * 8) && (y < 25 * 8)) ? csdata[7 - xdly[2:0]] : 0;
172 endmodule
173
174 `define IN_CLK 25000000
175 `define OUT_CLK 57600
176 `define CLK_DIV (`IN_CLK / `OUT_CLK)
177
178 module SerRX(
179         input pixclk,
180         output reg wr = 0,
181         output reg [7:0] wchar = 0,
182         input serialrx);
183
184         reg [15:0] rx_clkdiv = 0;
185         reg [3:0] rx_state = 4'b0000;
186         reg [7:0] rx_data_tmp;
187         
188
189         always @(posedge pixclk)
190         begin
191                 if ((rx_state == 0) && (serialrx == 0) /*&& (rx_hasdata == 0)*/)                /* Kick off. */
192                         rx_state <= 4'b0001;
193                 else if ((rx_state != 4'b0000) && (rx_clkdiv == 0)) begin
194                         if (rx_state != 4'b1010)
195                                 rx_state <= rx_state + 1;
196                         else
197                                 rx_state <= 0;
198                         case (rx_state)
199                         4'b0001:        begin end /* Twiddle thumbs -- this is the end of the half bit. */
200                         4'b0010:        rx_data_tmp[0] <= serialrx;
201                         4'b0011:        rx_data_tmp[1] <= serialrx;
202                         4'b0100:        rx_data_tmp[2] <= serialrx;
203                         4'b0101:        rx_data_tmp[3] <= serialrx;
204                         4'b0110:        rx_data_tmp[4] <= serialrx;
205                         4'b0111:        rx_data_tmp[5] <= serialrx;
206                         4'b1000:        rx_data_tmp[6] <= serialrx;
207                         4'b1001:        rx_data_tmp[7] <= serialrx;
208                         4'b1010:        if (serialrx == 1) begin
209                                                 wr <= 1;
210                                                 wchar <= rx_data_tmp;
211                                         end
212                         endcase
213                 end
214                 
215                 if (wr)
216                         wr <= 0;
217                 
218                 if ((rx_state == 0) && (serialrx == 0) /*&& (rx_hasdata == 0)*/)                /* Wait half a period before advancing. */
219                         rx_clkdiv <= `CLK_DIV / 2 + `CLK_DIV / 4;
220                 else if (rx_clkdiv == `CLK_DIV)
221                         rx_clkdiv <= 0;
222                 else
223                         rx_clkdiv <= rx_clkdiv + 1;
224         end
225 endmodule
226
227 module SerTX(
228         input pixclk,
229         input wr,
230         input [7:0] char,
231         output reg serial = 1);
232         
233         reg [7:0] tx_data = 0;
234         reg [15:0] tx_clkdiv = 0;
235         reg [3:0] tx_state = 4'b0000;
236         reg tx_busy = 0;
237         wire tx_newdata = wr && !tx_busy;
238
239         always @(posedge pixclk)
240         begin
241                 if(tx_newdata) begin
242                         tx_data <= char;
243                         tx_state <= 4'b0000;
244                         tx_busy <= 1;
245                 end else if (tx_clkdiv == 0) begin
246                         tx_state <= tx_state + 1;
247                         if (tx_busy)
248                                 case (tx_state)
249                                 4'b0000: serial <= 0;
250                                 4'b0001: serial <= tx_data[0];
251                                 4'b0010: serial <= tx_data[1];
252                                 4'b0011: serial <= tx_data[2];
253                                 4'b0100: serial <= tx_data[3];
254                                 4'b0101: serial <= tx_data[4];
255                                 4'b0110: serial <= tx_data[5];
256                                 4'b0111: serial <= tx_data[6];
257                                 4'b1000: serial <= tx_data[7];
258                                 4'b1001: serial <= 1;
259                                 4'b1010: tx_busy <= 0;
260                                 default: $stop;
261                                 endcase
262                 end
263                 
264                 if(tx_newdata || (tx_clkdiv == `CLK_DIV))
265                         tx_clkdiv <= 0;
266                 else
267                         tx_clkdiv <= tx_clkdiv + 1;
268         end
269 endmodule
270
271 module RXState(
272         input clk25,
273         output reg vwr = 0,
274         output reg [10:0] vwaddr = 0,
275         output reg [7:0] vwdata = 0,
276         output reg [10:0] vscroll = 0,
277         input serwr,
278         input [7:0] serdata);
279
280         parameter STATE_IDLE = 4'b0000;
281         parameter STATE_NEWLINE = 4'b0001;
282         parameter STATE_CLEAR = 4'b0010;
283
284         reg [3:0] state = STATE_CLEAR;
285         
286         reg [6:0] x = 0;
287         reg [4:0] y = 0;
288         
289         reg [10:0] clearstart = 0;
290         reg [10:0] clearend = 11'b11111111111;
291         
292         always @(posedge clk25)
293                 case (state)
294                 STATE_IDLE:     if (serwr) begin
295                                         if (serdata == 8'h0A) begin
296                                                 state <= STATE_NEWLINE;
297                                                 vwr <= 0;
298                                         end else if (serdata == 8'h0D) begin
299                                                 x <= 0;
300                                                 vwr <= 0;
301                                         end else if (serdata == 8'h0C) begin
302                                                 clearstart <= 0;
303                                                 clearend <= 11'b11111111111;
304                                                 x <= 0;
305                                                 y <= 0;
306                                                 vscroll <= 0;
307                                                 state <= STATE_CLEAR;
308                                         end else begin
309                                                 vwr <= 1;
310                                                 vwaddr <= ({y,4'b0} + {y,6'b0} + {4'h0,x}) + vscroll;
311                                                 vwdata <= serdata;
312                                                 if (x == 79) begin
313                                                         x <= 0;
314                                                         state <= STATE_NEWLINE;
315                                                 end else 
316                                                         x <= x + 1;
317                                         end
318                                 end
319                 STATE_NEWLINE:
320                         begin
321                                 vwr <= 0;
322                                 if (y == 24) begin
323                                         vscroll <= vscroll + 80;
324                                         clearstart <= (25 * 80) + vscroll;
325                                         clearend <= (26*80) + vscroll;
326                                         state <= STATE_CLEAR;
327                                 end else begin
328                                         y <= y + 1;
329                                         state <= STATE_IDLE;
330                                 end
331                         end
332                 STATE_CLEAR:
333                         begin
334                                 vwr <= 1;
335                                 vwaddr <= clearstart;
336                                 vwdata <= 8'h20;
337                                 clearstart <= clearstart + 1;
338                                 if (clearstart == clearend)
339                                         state <= STATE_IDLE;
340                         end
341                 endcase
342 endmodule
This page took 0.044122 seconds and 4 git commands to generate.