output wire vs, hs,
output reg [2:0] red,
output reg [2:0] green,
- output reg [1:0] blue
- );
+ output reg [1:0] blue,
+ input serrx,
+ output sertx,
+ input ps2c, ps2d);
wire clk25;
wire [2:0] csrow;
wire [7:0] csdata;
- wire [11:0] vraddr;
+ wire [10:0] vraddr;
wire [7:0] vrdata;
- reg [11:0] vwaddr = 0;
+ wire [10:0] vwaddr;
+ wire [7:0] vwdata;
+ wire [7:0] serdata;
+ wire vwr, serwr;
+ wire [10:0] vscroll;
wire odata;
CharSet cs(cschar, csrow, csdata);
- VideoRAM vram(clk25, vraddr, vrdata, vwaddr, 8'h41, 1);
+ VideoRAM vram(clk25, vraddr + vscroll, vrdata, vwaddr, vwdata, vwr);
VDisplay dpy(clk25, x, y, vraddr, vrdata, cschar, csrow, csdata, odata);
-
- always @(posedge clk25)
- vwaddr <= vwaddr + 1;
+ SerRX rx(clk25, serwr, serdata, serrx);
+ SerTX tx(clk25, 0, 0, sertx);
+ RXState rxsm(clk25, vwr, vwaddr, vwdata, vscroll, serwr, serdata);
always @(posedge clk25) begin
red <= border ? 0 : {3{odata}};
module VideoRAM(
input pixclk,
- input [11:0] raddr,
+ input [10:0] raddr,
output reg [7:0] rdata,
- input [11:0] waddr,
+ input [10:0] waddr,
input [7:0] wdata,
input wr);
- reg [7:0] ram [80*25-1 : 0];
+ reg [7:0] ram [2047 : 0];
always @(posedge pixclk)
rdata <= ram[raddr];
input pixclk,
input [11:0] x,
input [11:0] y,
- output wire [11:0] raddr,
+ output wire [10:0] raddr,
input [7:0] rchar,
output wire [7:0] cschar,
output wire [2:0] csrow,
input [7:0] csdata,
- output reg data
- );
+ output reg data);
wire [7:0] col = x[11:3];
wire [5:0] row = y[9:3];
always @(posedge pixclk)
data = ((xdly < 80 * 8) && (y < 25 * 8)) ? csdata[7 - xdly[2:0]] : 0;
endmodule
+
+`define IN_CLK 25000000
+`define OUT_CLK 57600
+`define CLK_DIV (`IN_CLK / `OUT_CLK)
+
+module SerRX(
+ input pixclk,
+ output reg wr = 0,
+ output reg [7:0] wchar = 0,
+ input serialrx);
+
+ reg [15:0] rx_clkdiv = 0;
+ reg [3:0] rx_state = 4'b0000;
+ reg [7:0] rx_data_tmp;
+
+
+ always @(posedge pixclk)
+ begin
+ if ((rx_state == 0) && (serialrx == 0) /*&& (rx_hasdata == 0)*/) /* Kick off. */
+ rx_state <= 4'b0001;
+ else if ((rx_state != 4'b0000) && (rx_clkdiv == 0)) begin
+ if (rx_state != 4'b1010)
+ rx_state <= rx_state + 1;
+ else
+ rx_state <= 0;
+ case (rx_state)
+ 4'b0001: begin end /* Twiddle thumbs -- this is the end of the half bit. */
+ 4'b0010: rx_data_tmp[0] <= serialrx;
+ 4'b0011: rx_data_tmp[1] <= serialrx;
+ 4'b0100: rx_data_tmp[2] <= serialrx;
+ 4'b0101: rx_data_tmp[3] <= serialrx;
+ 4'b0110: rx_data_tmp[4] <= serialrx;
+ 4'b0111: rx_data_tmp[5] <= serialrx;
+ 4'b1000: rx_data_tmp[6] <= serialrx;
+ 4'b1001: rx_data_tmp[7] <= serialrx;
+ 4'b1010: if (serialrx == 1) begin
+ wr <= 1;
+ wchar <= rx_data_tmp;
+ end
+ endcase
+ end
+
+ if (wr)
+ wr <= 0;
+
+ if ((rx_state == 0) && (serialrx == 0) /*&& (rx_hasdata == 0)*/) /* Wait half a period before advancing. */
+ rx_clkdiv <= `CLK_DIV / 2 + `CLK_DIV / 4;
+ else if (rx_clkdiv == `CLK_DIV)
+ rx_clkdiv <= 0;
+ else
+ rx_clkdiv <= rx_clkdiv + 1;
+ end
+endmodule
+
+module SerTX(
+ input pixclk,
+ input wr,
+ input [7:0] char,
+ output reg serial = 1);
+
+ reg [7:0] tx_data = 0;
+ reg [15:0] tx_clkdiv = 0;
+ reg [3:0] tx_state = 4'b0000;
+ reg tx_busy = 0;
+ wire tx_newdata = wr && !tx_busy;
+
+ always @(posedge pixclk)
+ begin
+ if(tx_newdata) begin
+ tx_data <= char;
+ tx_state <= 4'b0000;
+ tx_busy <= 1;
+ end else if (tx_clkdiv == 0) begin
+ tx_state <= tx_state + 1;
+ if (tx_busy)
+ case (tx_state)
+ 4'b0000: serial <= 0;
+ 4'b0001: serial <= tx_data[0];
+ 4'b0010: serial <= tx_data[1];
+ 4'b0011: serial <= tx_data[2];
+ 4'b0100: serial <= tx_data[3];
+ 4'b0101: serial <= tx_data[4];
+ 4'b0110: serial <= tx_data[5];
+ 4'b0111: serial <= tx_data[6];
+ 4'b1000: serial <= tx_data[7];
+ 4'b1001: serial <= 1;
+ 4'b1010: tx_busy <= 0;
+ default: $stop;
+ endcase
+ end
+
+ if(tx_newdata || (tx_clkdiv == `CLK_DIV))
+ tx_clkdiv <= 0;
+ else
+ tx_clkdiv <= tx_clkdiv + 1;
+ end
+endmodule
+
+module RXState(
+ input clk25,
+ output reg vwr = 0,
+ output reg [10:0] vwaddr = 0,
+ output reg [7:0] vwdata = 0,
+ output reg [10:0] vscroll = 0,
+ input serwr,
+ input [7:0] serdata);
+
+ parameter STATE_IDLE = 4'b0000;
+ parameter STATE_NEWLINE = 4'b0001;
+ parameter STATE_CLEAR = 4'b0010;
+
+ reg [3:0] state = STATE_CLEAR;
+
+ reg [6:0] x = 0;
+ reg [4:0] y = 0;
+
+ reg [10:0] clearstart = 0;
+ reg [10:0] clearend = 11'b11111111111;
+
+ always @(posedge clk25)
+ case (state)
+ STATE_IDLE: if (serwr) begin
+ if (serdata == 8'h0A) begin
+ state <= STATE_NEWLINE;
+ vwr <= 0;
+ end else if (serdata == 8'h0D) begin
+ x <= 0;
+ vwr <= 0;
+ end else if (serdata == 8'h0C) begin
+ clearstart <= 0;
+ clearend <= 11'b11111111111;
+ x <= 0;
+ y <= 0;
+ vscroll <= 0;
+ state <= STATE_CLEAR;
+ end else begin
+ vwr <= 1;
+ vwaddr <= ({y,4'b0} + {y,6'b0} + {4'h0,x}) + vscroll;
+ vwdata <= serdata;
+ if (x == 79) begin
+ x <= 0;
+ state <= STATE_NEWLINE;
+ end else
+ x <= x + 1;
+ end
+ end
+ STATE_NEWLINE:
+ begin
+ vwr <= 0;
+ if (y == 24) begin
+ vscroll <= vscroll + 80;
+ clearstart <= (25 * 80) + vscroll;
+ clearend <= (26*80) + vscroll;
+ state <= STATE_CLEAR;
+ end else begin
+ y <= y + 1;
+ state <= STATE_IDLE;
+ end
+ end
+ STATE_CLEAR:
+ begin
+ vwr <= 1;
+ vwaddr <= clearstart;
+ vwdata <= 8'h20;
+ clearstart <= clearstart + 1;
+ if (clearstart == clearend)
+ state <= STATE_IDLE;
+ end
+ endcase
+endmodule