]> Joshua Wise's Git repositories - vterm.git/blob - VTerm.v
09b130093e4eb199536c2d4f12ca8c3c70d730a1
[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         );
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         
53         wire [7:0] cschar;
54         wire [2:0] csrow;
55         wire [7:0] csdata;
56         
57         wire [10:0] vraddr;
58         wire [7:0] vrdata;
59         
60         wire [10:0] vwaddr;
61         wire [7:0] vwdata;
62         wire [7:0] serdata;
63         wire vwr, serwr;
64         wire [10:0] vscroll;
65         
66         wire odata;
67         
68         CharSet cs(cschar, csrow, csdata);
69         VideoRAM vram(clk25, vraddr + vscroll, vrdata, vwaddr, vwdata, vwr);
70         VDisplay dpy(clk25, x, y, vraddr, vrdata, cschar, csrow, csdata, odata);
71         SerRX rx(clk25, serwr, serdata, serrx);
72         RXState rxsm(clk25, vwr, vwaddr, vwdata, vscroll, serwr, serdata);
73         
74         always @(posedge clk25) begin
75                 red <= border ? 0 : {3{odata}};
76                 green <= border ? 0 : {3{odata}};
77                 blue <= border ? 0 : {2{odata}};
78         end
79 endmodule
80
81 module 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
112 endmodule
113
114 module 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}];
125 endmodule
126
127 module VideoRAM(
128         input pixclk,
129         input [10:0] raddr,
130         output reg [7:0] rdata,
131         input [10:0] waddr,
132         input [7:0] wdata,
133         input wr);
134         
135         reg [7:0] ram [2047 : 0];
136         
137         always @(posedge pixclk)
138                 rdata <= ram[raddr];
139         
140         always @(posedge pixclk)
141                 if (wr)
142                         ram[waddr] <= wdata;
143 endmodule
144
145 module VDisplay(
146         input pixclk,
147         input [11:0] x,
148         input [11:0] y,
149         output wire [10:0] raddr,
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;
171 endmodule
172
173 `define IN_CLK 25000000
174 `define OUT_CLK 57600
175 `define CLK_DIV (`IN_CLK / `OUT_CLK)
176
177 module SerRX(
178         input pixclk,
179         output reg wr = 0,
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                 
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
226 endmodule
227
228 module 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
299 endmodule
This page took 0.030239 seconds and 2 git commands to generate.