📄 vgachr 8080.v
字号:
else if (scancode == 8'h6c) datao <= 8'h1e; // home
else if (scancode == 8'h71) datao <= 8'h1f; // delete (rub out)
end else if (asciidata >= 8'h60 && asciidata <= 8'h7e &&
(leftctrl || rightctrl))
datao <= asciidata & 8'h1f;
else if (asciidata >= 8'h61 && asciidata <= 8'h7a)
datao <= leftshift||rightshift||capslock ? asciidatau: asciidata;
else
datao <= leftshift||rightshift ? asciidatau: asciidata;
clrrdy <= 1; // clear scancode ready f/f
end else
datao <= (!outrdy << 7) | (scnrdy << 5); // return ready statuses
end else clrrdy <= 0; // clear keyboard ready signal
case (state) // run output state
`term_idle: begin // idle waiting for character
// We wait for the cpu cycle to end before running the state machine
// write procedure. This allows this module to run at full speed,
// while the rest of the CPU logic runs slow. The vga logic must run
// at a fixed speed because it has the display to run, but the rest
// can be slow to allow debugging.
if (wrtchr&!(select&read|select&write)) begin
// process character after CPU goes away
if (chrdatw >= 8'h20 && chrdatw != 8'h7f) begin
// write standard (non-control) character
cmaddr <= cursor; // set address at cursor
cmdatai <= chrdatw; // place character data to write
cmattri <= curatr; // set with current attributes
cmdatae <= 1; // enable data to memory
cmattre <= 1; // enable attributes to memory
state <= `term_wrtstd2; // continue
end else begin // control character
if (chrdatw == 8'h0a) begin // line down (line feed)
if (cursor < 23*80) begin // not at screen end
cursor <= cursor+80;
wrtchr <= 0; // remove ready to write
outrdy <= 1; // set ready to send
end else begin
tcursor <= 0; // set temp cursor to screen start
state <= `term_scroll; // go to scroll screen
end
end else if (chrdatw == 8'h0b) begin // line up
if (cursor >= 80) cursor <= cursor-80;
wrtchr <= 0; // remove ready to write
outrdy <= 1; // set ready to send
end else if (chrdatw == 8'h0d) begin // carriage return
tcursor <= 0; // set start of line cursor
state <= `term_fndstr; // go to find start of line
end else if (chrdatw == 8'h08) begin // character left
// if not at home position, back up
if (cursor > 0) cursor <= cursor-1;
wrtchr <= 0; // remove ready to write
outrdy <= 1; // set ready to send
end else if (chrdatw == 8'h0c) begin // character right
// if not at screen end, go forward
if (cursor < 80*24-1) cursor <= cursor+1;
wrtchr <= 0; // remove ready to write
outrdy <= 1; // set ready to send
end else if (chrdatw == 8'h1e) begin // home
cursor <= 0; // set to home position
wrtchr <= 0; // remove ready to write
outrdy <= 1; // set ready to send
end else if (chrdatw == 8'h1a) begin // clear screen
state <= `term_clear; // go to screen clear
wrtchr <= 0; // remove ready to write
outrdy <= 1; // set ready to send
end else if (chrdatw == 8'h1b) begin // escape
wrtchr <= 0; // remove ready to write
outrdy <= 1; // set ready to send
state <= `term_esc; // go escape handler
end else begin // unsupported control character
wrtchr <= 0; // remove ready to write
outrdy <= 1; // set ready to send
end
end
end
end
`term_wrtstd2: begin // write standard character #2
cmwrite <= 1; // set write to memory
state <= `term_wrtstd3; // continue
end
`term_wrtstd3: begin // write standard character #3
cmwrite <= 0; // remove write to memory
state <= `term_wrtstd4; // continue
end
`term_wrtstd4: begin // write standard character #3
cmdatae <= 0; // release data enable to memory
cmattre <= 0; // release attribute enable to memory
outrdy <= 1; // set ready to send
cursor <= cursor+1; // advance cursor
wrtchr <= 0; // remove ready to write
state <= `term_idle; // continue
end
`term_clear: begin // clear screen and home cursor
cmaddr <= 0; // clear buffer address
cmdatai <= 8'h20; // clear to spaces
cmattri <= 5'b0; // clear attributes
cmdatae <= 1; // enable data to memory
cmattre <= 1; // enable attributes to memory
state <= `term_clear2; // continue
end
`term_clear2: begin // clear screen and home cursor #2
cmwrite <= 1; // set write to memory
state <= `term_clear3; // continue
end
`term_clear3: begin // clear screen and home cursor #2
cmwrite <= 0; // reset write to memory
state <= `term_clear4; // continue
end
`term_clear4: begin // clear screen and home cursor #4
if (cmaddr < `scnchrs*`scnlins) begin
cmaddr <= cmaddr+1; // next character
// Uncomment the next to put an incrementing pattern instead of
// spaces.
//cmdatai <= cmdatai+1;
state <= `term_clear2; // continue
end else begin // done
outrdy <= 1; // set ready to send
cursor <= 0; // set cursor to home position
cmdatae <= 0; // release data enable to memory
cmattre <= 0; // release attribute enable to memory
state <= `term_idle; // continue
end
end
`term_fndstr: begin // find start of current line
if (tcursor+80 > cursor) begin // found
cursor <= tcursor; // set cursor to line start
wrtchr <= 0; // remove ready to write
outrdy <= 1; // set ready to send
state <= `term_idle; // continue
end else tcursor <= tcursor+80; // advance to next line
end
`term_scroll: begin // scroll screen up
// move all data up a line
if (tcursor < 80*23) begin // scroll up
cmread <= 1; // set read display
cmaddr <= tcursor+80; // set address to read
state <= `term_scroll1; // continue
end else state <= `term_scroll5; // go blank last line
end
`term_scroll1: begin // scroll screen up #1
state <= `term_scroll2; // hold read
end
`term_scroll2: begin // scroll screen up #2
cmdatai <= cmdata; // get data at address
cmattri <= cmattr; // get attribute at address
cmread <= 0; // turn off read
state <= `term_scroll3; // continue
end
`term_scroll3: begin // scroll screen up #3
cmdatae <= 1; // enable data to write
cmattre <= 1; // enable attribute to write
cmwrite <= 1; // set to write
cmaddr <= tcursor;
state <= `term_scroll4; // continue
end
`term_scroll4: begin // scroll screen up #4
cmwrite <= 0; // turn off write
cmdatae <= 0; // turn off data enable
cmattre <= 0; // turn off attribute enable
tcursor <= tcursor+1; // next address
state <= `term_scroll; // repeat character move
end
`term_scroll5: begin // scroll screen up #5
// blank out last line
if (tcursor < 80*24) begin // blank out
cmdatai <= 8'h20; // set to write spaces
cmattri <= 0; // set no attribute
cmdatae <= 1; // enable data to write
cmattre <= 1; // enable attribute to write
cmwrite <= 1; // set to write
cmaddr <= tcursor;
state <= `term_scroll6; // continue
end else begin // terminate
wrtchr <= 0; // remove ready to write
outrdy <= 1; // set ready to send
state <= `term_idle; // continue
end
end
`term_scroll6: begin // scroll screen up #6
cmwrite <= 0; // turn off write
cmdatae <= 0; // turn off data enable
cmattre <= 0; // turn off attribute enable
tcursor <= tcursor+1; // next address
state <= `term_scroll5; // repeat blank out
end
`term_esc: begin // handle escape codes
// wait for next character
if (wrtchr&!(select&read|select&write)) begin
// check its a cursor position, or "\esc="
if (chrdatw == 8'h3d) begin
wrtchr <= 0; // remove ready to write
outrdy <= 1; // set ready to send
state <= `term_poscur;
// check its a attribute set, or "\escG"
end else if (chrdatw == 8'h47) begin
wrtchr <= 0; // remove ready to write
outrdy <= 1; // set ready to send
state <= `term_attset;
end else begin // invalid sequence, abort
wrtchr <= 0; // remove ready to write
outrdy <= 1; // set ready to send
state <= `term_idle;
end
end
end
`term_poscur: begin // handle cursor direct position
// wait for next character
if (wrtchr&!(select&read|select&write)) begin
rowchr <= chrdatw; // save row character
wrtchr <= 0; // remove ready to write
outrdy <= 1; // set ready to send
state <= `term_poscur2;
end
end
`term_poscur2: begin // handle cursor direct position #2
// wait for next character
if (wrtchr&!(select&read|select&write)) begin
// check row and collumn are valid
if (rowchr >= 8'h20 && rowchr <= 8'h37 &&
chrdatw >= 8'h20 && chrdatw <= 8'h6f)
// perform position
cursor <= (rowchr-8'h20)*80+(chrdatw-8'h20);
wrtchr <= 0; // remove ready to write
outrdy <= 1; // set ready to send
state <= `term_idle;
end
end
`term_attset: begin // handle attribute set
// wait for next character
if (wrtchr&!(select&read|select&write)) begin
// Process attribute set code. The ADM 3A attributes are arranged
// so that the bits in characters '0'-'N' correspond to attribute
// bits. Some of the combinations are "invalid", but these are
// ones that override each other. For example, blank overrides
// all others.
if (chrdatw >= 8'h30 && chrdatw <= 8'h4e) // its '0'-'N'
curatr <= chrdatw-8'h30 & 5'b11111;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -