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
);
wire clk25;
SyncGen sync(clk25, vs, hs, x, y, border);
+ wire [7:0] cschar;
+ wire [2:0] csrow;
+ wire [7:0] csdata;
+
+ wire [11:0] vraddr;
+ wire [7:0] vrdata;
+
+ wire [11:0] vwaddr;
+ wire [7:0] vwdata;
+ wire vwr;
+
+ wire odata;
+
+ CharSet cs(cschar, csrow, csdata);
+ VideoRAM vram(clk25, vraddr, vrdata, vwaddr, vwdata, vwr);
+ VDisplay dpy(clk25, x, y, vraddr, vrdata, cschar, csrow, csdata, odata);
+ SerRX rx(clk25, vwr, vwaddr, vwdata, serrx);
+
always @(posedge clk25) begin
- red <= border ? 0 : 3'b100;
- green <= border ? 0 : 0;
- blue <= border ? 0 : 0;
+ red <= border ? 0 : {3{odata}};
+ green <= border ? 0 : {3{odata}};
+ blue <= border ? 0 : {2{odata}};
end
endmodule
border <= (x > XRES) || (y > YRES);
end
endmodule
+
+module CharSet(
+ input [7:0] char,
+ input [2:0] row,
+ output wire [7:0] data);
+
+ reg [7:0] rom [(256 * 8 - 1):0];
+
+ initial
+ $readmemb("ibmpc1.mem", rom);
+
+ assign data = rom[{char, row}];
+endmodule
+
+module VideoRAM(
+ input pixclk,
+ input [11:0] raddr,
+ output reg [7:0] rdata,
+ input [11:0] waddr,
+ input [7:0] wdata,
+ input wr);
+
+ reg [7:0] ram [80*25-1 : 0];
+
+ always @(posedge pixclk)
+ rdata <= ram[raddr];
+
+ always @(posedge pixclk)
+ if (wr)
+ ram[waddr] <= wdata;
+endmodule
+
+module VDisplay(
+ input pixclk,
+ input [11:0] x,
+ input [11:0] y,
+ output wire [11:0] raddr,
+ input [7:0] rchar,
+ output wire [7:0] cschar,
+ output wire [2:0] csrow,
+ input [7:0] csdata,
+ output reg data
+ );
+
+ wire [7:0] col = x[11:3];
+ wire [5:0] row = y[9:3];
+ reg [7:0] ch;
+ reg [11:0] xdly;
+
+ assign raddr = ({row,4'b0} + {row,6'b0} + {4'h0,col});
+ assign cschar = rchar;
+ assign csrow = y[2:0];
+
+ always @(posedge pixclk)
+ xdly <= x;
+
+ 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 [11:0] waddr = 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) begin
+ wr <= 0;
+ waddr <= waddr + 1;
+ end
+
+ 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