]> Joshua Wise's Git repositories - vterm.git/blame - VTerm.v
Terminal can now scroll using the state machine.
[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
JW
38 output reg [1:0] blue,
39 input serrx
a55fc9f4
JW
40 );
41
42 wire clk25;
43
44 wire [11:0] x, y;
45 wire border;
46
47 MulDivDCM dcm25(xtal, clk25);
48 defparam dcm25.div = 4;
49 defparam dcm25.mul = 2;
50
51 SyncGen sync(clk25, vs, hs, x, y, border);
52
d3ae999b
JW
53 wire [7:0] cschar;
54 wire [2:0] csrow;
55 wire [7:0] csdata;
56
7b96452d 57 wire [10:0] vraddr;
d3ae999b
JW
58 wire [7:0] vrdata;
59
7b96452d 60 wire [10:0] vwaddr;
0491ebad 61 wire [7:0] vwdata;
7b96452d
JW
62 wire [7:0] serdata;
63 wire vwr, serwr;
64 wire [10:0] vscroll;
d3ae999b
JW
65
66 wire odata;
67
68 CharSet cs(cschar, csrow, csdata);
7b96452d 69 VideoRAM vram(clk25, vraddr + vscroll, vrdata, vwaddr, vwdata, vwr);
d3ae999b 70 VDisplay dpy(clk25, x, y, vraddr, vrdata, cschar, csrow, csdata, odata);
7b96452d
JW
71 SerRX rx(clk25, serwr, serdata, serrx);
72 RXState rxsm(clk25, vwr, vwaddr, vwdata, vscroll, serwr, serdata);
d3ae999b 73
a55fc9f4 74 always @(posedge clk25) begin
d3ae999b
JW
75 red <= border ? 0 : {3{odata}};
76 green <= border ? 0 : {3{odata}};
77 blue <= border ? 0 : {2{odata}};
a55fc9f4
JW
78 end
79endmodule
80
81module SyncGen(
82 input pixclk,
83 output reg vs, hs,
84 output reg [11:0] x, y,
85 output reg border);
86
87 parameter XRES = 640;
88 parameter XFPORCH = 16;
89 parameter XSYNC = 96;
90 parameter XBPORCH = 48;
91
92 parameter YRES = 480;
93 parameter YFPORCH = 10;
94 parameter YSYNC = 2;
95 parameter YBPORCH = 29;
96
97 always @(posedge pixclk)
98 begin
99 if (x >= (XRES + XFPORCH + XSYNC + XBPORCH))
100 begin
101 if (y >= (YRES + YFPORCH + YSYNC + YBPORCH))
102 y = 0;
103 else
104 y = y + 1;
105 x = 0;
106 end else
107 x = x + 1;
108 hs <= (x >= (XRES + XFPORCH)) && (x < (XRES + XFPORCH + XSYNC));
109 vs <= (y >= (YRES + YFPORCH)) && (y < (YRES + YFPORCH + YSYNC));
110 border <= (x > XRES) || (y > YRES);
111 end
112endmodule
d3ae999b
JW
113
114module CharSet(
115 input [7:0] char,
116 input [2:0] row,
117 output wire [7:0] data);
118
119 reg [7:0] rom [(256 * 8 - 1):0];
120
121 initial
122 $readmemb("ibmpc1.mem", rom);
123
124 assign data = rom[{char, row}];
125endmodule
126
127module VideoRAM(
128 input pixclk,
7b96452d 129 input [10:0] raddr,
d3ae999b 130 output reg [7:0] rdata,
7b96452d 131 input [10:0] waddr,
d3ae999b
JW
132 input [7:0] wdata,
133 input wr);
134
7b96452d 135 reg [7:0] ram [2047 : 0];
d3ae999b
JW
136
137 always @(posedge pixclk)
138 rdata <= ram[raddr];
139
140 always @(posedge pixclk)
141 if (wr)
142 ram[waddr] <= wdata;
143endmodule
144
145module VDisplay(
146 input pixclk,
147 input [11:0] x,
148 input [11:0] y,
7b96452d 149 output wire [10:0] raddr,
d3ae999b
JW
150 input [7:0] rchar,
151 output wire [7:0] cschar,
152 output wire [2:0] csrow,
153 input [7:0] csdata,
154 output reg data
155 );
156
157 wire [7:0] col = x[11:3];
158 wire [5:0] row = y[9:3];
159 reg [7:0] ch;
160 reg [11:0] xdly;
161
162 assign raddr = ({row,4'b0} + {row,6'b0} + {4'h0,col});
163 assign cschar = rchar;
164 assign csrow = y[2:0];
165
166 always @(posedge pixclk)
167 xdly <= x;
168
169 always @(posedge pixclk)
170 data = ((xdly < 80 * 8) && (y < 25 * 8)) ? csdata[7 - xdly[2:0]] : 0;
171endmodule
0491ebad
JW
172
173`define IN_CLK 25000000
174`define OUT_CLK 57600
175`define CLK_DIV (`IN_CLK / `OUT_CLK)
176
177module SerRX(
178 input pixclk,
179 output reg wr = 0,
0491ebad
JW
180 output reg [7:0] wchar = 0,
181 input serialrx
182);
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
7b96452d 215 if (wr)
0491ebad 216 wr <= 0;
0491ebad
JW
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
226endmodule
7b96452d
JW
227
228module RXState(
229 input clk25,
230 output reg vwr = 0,
231 output reg [10:0] vwaddr = 0,
232 output reg [7:0] vwdata = 0,
233 output reg [10:0] vscroll = 0,
234 input serwr,
235 input [7:0] serdata);
236
237 parameter STATE_IDLE = 4'b0000;
238 parameter STATE_NEWLINE = 4'b0001;
239 parameter STATE_CLEAR = 4'b0010;
240
241 reg [3:0] state = STATE_CLEAR;
242
243 reg [6:0] x = 0;
244 reg [4:0] y = 0;
245
246 reg [10:0] clearstart = 0;
247 reg [10:0] clearend = 11'b11111111111;
248
249 always @(posedge clk25)
250 case (state)
251 STATE_IDLE: if (serwr) begin
252 if (serdata == 8'h0A) begin
253 state <= STATE_NEWLINE;
254 vwr <= 0;
255 end else if (serdata == 8'h0D) begin
256 x <= 0;
257 vwr <= 0;
258 end else if (serdata == 8'h0C) begin
259 clearstart <= 0;
260 clearend <= 11'b11111111111;
261 x <= 0;
262 y <= 0;
263 vscroll <= 0;
264 state <= STATE_CLEAR;
265 end else begin
266 vwr <= 1;
267 vwaddr <= ({y,4'b0} + {y,6'b0} + {4'h0,x}) + vscroll;
268 vwdata <= serdata;
269 if (x == 79) begin
270 x <= 0;
271 state <= STATE_NEWLINE;
272 end else
273 x <= x + 1;
274 end
275 end
276 STATE_NEWLINE:
277 begin
278 vwr <= 0;
279 if (y == 24) begin
280 vscroll <= vscroll + 80;
281 clearstart <= (25 * 80) + vscroll;
282 clearend <= (26*80) + vscroll;
283 state <= STATE_CLEAR;
284 end else begin
285 y <= y + 1;
286 state <= STATE_IDLE;
287 end
288 end
289 STATE_CLEAR:
290 begin
291 vwr <= 1;
292 vwaddr <= clearstart;
293 vwdata <= 8'h20;
294 clearstart <= clearstart + 1;
295 if (clearstart == clearend)
296 state <= STATE_IDLE;
297 end
298 endcase
299endmodule
This page took 0.04705 seconds and 4 git commands to generate.