commit 37d5cd378492be26a5d201cdac3ca7af87000a21
parent ebfafb004791c2ed75d458daff6a92eb2f05ce49
Author: Brian Swetland <swetland@frotz.net>
Date:   Wed, 30 Dec 2015 20:03:42 -0800
vga character display from my old cpu32 project
This is pretty gross and really wants to be rewritten, but it works
just fine, so that can wait.
Diffstat:
| A | hdl/vga/chardata.v | | | 143 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ | 
| A | hdl/vga/prom.txt | | | 1024 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ | 
| A | hdl/vga/vga.v | | | 91 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ | 
| A | hdl/vga/vga40x30x2.v | | | 63 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ | 
| A | hdl/vga/videoram.v | | | 25 | +++++++++++++++++++++++++ | 
| A | hdl/vga/vram.txt | | | 2048 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ | 
6 files changed, 3394 insertions(+), 0 deletions(-)
diff --git a/hdl/vga/chardata.v b/hdl/vga/chardata.v
@@ -0,0 +1,143 @@
+// Copyright 2012, Brian Swetland
+//
+// Pixel Data Reader / Character Data Reader
+//
+// assert newline and provide line address to start linefetch
+// character data will be provided on cdata two clocks later
+//
+// assert next to advance: character data will be provided two clocks later 
+//
+// vram_addr/vram_data: connect to sync sram
+
+`timescale 1ns/1ns
+
+module pixeldata(
+	input clk,
+	input newline,
+	input advance,
+	input [7:0] line,
+
+	output reg [11:0] pixel,
+
+	input [7:0] vram_data,
+	output [10:0] vram_addr
+	);
+
+wire [7:0] new_cdata;
+reg next;
+
+chardata chardata(
+	.clk(clk),
+	.newline(newline),
+	.line(line),
+	.next(next),
+	.cdata(new_cdata),
+	.vram_data(vram_data),
+	.vram_addr(vram_addr)
+	);
+
+reg [7:0] cdata, next_cdata;
+reg [3:0] bitcount, next_bitcount;
+reg [1:0] state, next_state;
+
+always @(*) begin
+	next_bitcount = bitcount;
+	next_cdata = cdata;
+	next = 1'b0;
+
+	/* s0 machine is used to wait until the first cdata
+	 * is ready after a newline signal, load that cdata,
+	 * then enter the shift-out (s0=0) mode
+	 */
+	case (state)
+	2'h3: next_state = 2'h2;
+	2'h2: next_state = 2'h1;
+	2'h1: begin
+		next_state = 2'h0;
+		next_cdata = new_cdata;
+		end	
+	2'h0: begin
+		next_state = 2'h0;
+		if (advance)
+			next_bitcount = bitcount - 4'd1;
+		if (bitcount == 4'h4)
+			next = 1'b1;
+		if (bitcount == 4'h0)
+			next_cdata = new_cdata;
+		end
+	endcase
+
+	if (newline) begin
+		next_state = 2'h3;
+		next_bitcount = 4'hF;
+	end 
+
+	pixel = (cdata[bitcount[3:1]] ? 12'hFFF : 12'h00F);
+end
+
+always @(posedge clk) begin
+	bitcount <= next_bitcount;
+	state <= next_state;
+	cdata <= next_cdata;
+end
+
+endmodule
+
+
+module chardata(
+	input clk,
+	input newline,
+	input next,
+	input [7:0] line,
+	output reg [7:0] cdata,
+
+	input [7:0] vram_data,
+	output reg [10:0] vram_addr
+	);
+
+`define SWAIT	2'h0
+`define SLOAD	2'h1
+`define SLATCH	2'h2
+
+reg [7:0] pattern_rom [0:1023];
+reg [2:0] pline, next_pline;
+
+reg [1:0] state, next_state;
+reg [10:0] next_addr;
+reg [7:0] next_cdata;
+
+initial $readmemh("prom.txt", pattern_rom);
+
+always @(*) begin
+	next_state = state;
+	next_addr = vram_addr;
+	next_cdata = cdata;
+	next_pline = pline;
+	if (newline) begin
+		next_state = `SLOAD;
+		next_addr = { line[7:3], 6'b0 };
+		next_pline = line[2:0];
+	end
+	case (state)
+	`SWAIT: if (next) begin	
+		next_state = `SLOAD;
+		end
+	`SLOAD: begin
+		next_state = `SLATCH;
+		end
+	`SLATCH: begin
+		next_state = `SWAIT;
+		next_addr = vram_addr + 11'd1;
+		next_cdata = pattern_rom[{vram_data, pline}];
+		end
+	endcase
+end
+
+always @(posedge clk) begin
+	state <= next_state;	
+	vram_addr <= next_addr;
+	cdata <= next_cdata;
+	pline <= next_pline;
+end
+
+endmodule 
diff --git a/hdl/vga/prom.txt b/hdl/vga/prom.txt
@@ -0,0 +1,1024 @@
+00
+00
+00
+00
+00
+00
+00
+00
+00
+3e
+41
+55
+41
+55
+49
+3e
+00
+3e
+7f
+6b
+7f
+6b
+77
+3e
+00
+22
+77
+7f
+7f
+3e
+1c
+08
+00
+08
+1c
+3e
+7f
+3e
+1c
+08
+00
+08
+1c
+2a
+7f
+2a
+08
+1c
+00
+08
+1c
+3e
+7f
+3e
+08
+1c
+00
+00
+1c
+3e
+3e
+3e
+1c
+00
+ff
+ff
+e3
+c1
+c1
+c1
+e3
+ff
+00
+00
+1c
+22
+22
+22
+1c
+00
+ff
+ff
+e3
+dd
+dd
+dd
+e3
+ff
+00
+0f
+03
+05
+39
+48
+48
+30
+00
+08
+3e
+08
+1c
+22
+22
+1c
+00
+18
+14
+10
+10
+30
+70
+60
+00
+0f
+19
+11
+13
+37
+76
+60
+00
+08
+2a
+1c
+77
+1c
+2a
+08
+00
+60
+78
+7e
+7f
+7e
+78
+60
+00
+03
+0f
+3f
+7f
+3f
+0f
+03
+00
+08
+1c
+2a
+08
+2a
+1c
+08
+00
+66
+66
+66
+66
+00
+66
+66
+00
+3f
+65
+65
+3d
+05
+05
+05
+00
+0c
+32
+48
+24
+12
+4c
+30
+00
+00
+00
+00
+00
+7f
+7f
+7f
+00
+08
+1c
+2a
+08
+2a
+1c
+3e
+00
+08
+1c
+3e
+7f
+1c
+1c
+1c
+00
+1c
+1c
+1c
+7f
+3e
+1c
+08
+00
+08
+0c
+7e
+7f
+7e
+0c
+08
+00
+08
+18
+3f
+7f
+3f
+18
+08
+00
+00
+00
+70
+70
+70
+7f
+7f
+00
+00
+14
+22
+7f
+22
+14
+00
+00
+08
+1c
+1c
+3e
+3e
+7f
+7f
+00
+7f
+7f
+3e
+3e
+1c
+1c
+08
+00
+00
+00
+00
+00
+00
+00
+00
+00
+18
+3c
+3c
+18
+18
+00
+18
+00
+36
+36
+14
+00
+00
+00
+00
+00
+36
+36
+7f
+36
+7f
+36
+36
+00
+08
+1e
+20
+1c
+02
+3c
+08
+00
+60
+66
+0c
+18
+30
+66
+06
+00
+3c
+66
+3c
+28
+65
+66
+3f
+00
+18
+18
+18
+30
+00
+00
+00
+00
+60
+30
+18
+18
+18
+30
+60
+00
+06
+0c
+18
+18
+18
+0c
+06
+00
+00
+36
+1c
+7f
+1c
+36
+00
+00
+00
+08
+08
+3e
+08
+08
+00
+00
+00
+00
+00
+30
+30
+30
+60
+00
+00
+00
+00
+3c
+00
+00
+00
+00
+00
+00
+00
+00
+00
+60
+60
+00
+00
+06
+0c
+18
+30
+60
+00
+00
+3c
+66
+6e
+76
+66
+66
+3c
+00
+18
+18
+38
+18
+18
+18
+7e
+00
+3c
+66
+06
+0c
+30
+60
+7e
+00
+3c
+66
+06
+1c
+06
+66
+3c
+00
+0c
+1c
+2c
+4c
+7e
+0c
+0c
+00
+7e
+60
+7c
+06
+06
+66
+3c
+00
+3c
+66
+60
+7c
+66
+66
+3c
+00
+7e
+66
+0c
+0c
+18
+18
+18
+00
+3c
+66
+66
+3c
+66
+66
+3c
+00
+3c
+66
+66
+3e
+06
+66
+3c
+00
+00
+18
+18
+00
+18
+18
+00
+00
+00
+18
+18
+00
+18
+18
+30
+00
+06
+0c
+18
+30
+18
+0c
+06
+00
+00
+00
+3c
+00
+3c
+00
+00
+00
+60
+30
+18
+0c
+18
+30
+60
+00
+3c
+66
+06
+1c
+18
+00
+18
+00
+38
+44
+5c
+58
+42
+3c
+00
+00
+3c
+66
+66
+7e
+66
+66
+66
+00
+7c
+66
+66
+7c
+66
+66
+7c
+00
+3c
+66
+60
+60
+60
+66
+3c
+00
+7c
+66
+66
+66
+66
+66
+7c
+00
+7e
+60
+60
+7c
+60
+60
+7e
+00
+7e
+60
+60
+7c
+60
+60
+60
+00
+3c
+66
+60
+60
+6e
+66
+3c
+00
+66
+66
+66
+7e
+66
+66
+66
+00
+3c
+18
+18
+18
+18
+18
+3c
+00
+1e
+0c
+0c
+0c
+6c
+6c
+38
+00
+66
+6c
+78
+70
+78
+6c
+66
+00
+60
+60
+60
+60
+60
+60
+7e
+00
+63
+77
+7f
+6b
+63
+63
+63
+00
+63
+73
+7b
+6f
+67
+63
+63
+00
+3c
+66
+66
+66
+66
+66
+3c
+00
+7c
+66
+66
+66
+7c
+60
+60
+00
+3c
+66
+66
+66
+6e
+3c
+06
+00
+7c
+66
+66
+7c
+78
+6c
+66
+00
+3c
+66
+60
+3c
+06
+66
+3c
+00
+7e
+5a
+18
+18
+18
+18
+18
+00
+66
+66
+66
+66
+66
+66
+3e
+00
+66
+66
+66
+66
+66
+3c
+18
+00
+63
+63
+63
+6b
+7f
+77
+63
+00
+63
+63
+36
+1c
+36
+63
+63
+00
+66
+66
+66
+3c
+18
+18
+18
+00
+7e
+06
+0c
+18
+30
+60
+7e
+00
+1e
+18
+18
+18
+18
+18
+1e
+00
+00
+60
+30
+18
+0c
+06
+00
+00
+78
+18
+18
+18
+18
+18
+78
+00
+08
+14
+22
+41
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+7f
+00
+0c
+0c
+06
+00
+00
+00
+00
+00
+00
+00
+3c
+06
+3e
+66
+3e
+00
+60
+60
+60
+7c
+66
+66
+7c
+00
+00
+00
+3c
+66
+60
+66
+3c
+00
+06
+06
+06
+3e
+66
+66
+3e
+00
+00
+00
+3c
+66
+7e
+60
+3c
+00
+1c
+36
+30
+30
+7c
+30
+30
+00
+00
+3e
+66
+66
+3e
+06
+3c
+00
+60
+60
+60
+7c
+66
+66
+66
+00
+00
+18
+00
+18
+18
+18
+3c
+00
+0c
+00
+0c
+0c
+6c
+6c
+38
+00
+60
+60
+66
+6c
+78
+6c
+66
+00
+18
+18
+18
+18
+18
+18
+18
+00
+00
+00
+63
+77
+7f
+6b
+6b
+00
+00
+00
+7c
+7e
+66
+66
+66
+00
+00
+00
+3c
+66
+66
+66
+3c
+00
+00
+7c
+66
+66
+7c
+60
+60
+00
+00
+3c
+6c
+6c
+3c
+0d
+0f
+00
+00
+00
+7c
+66
+66
+60
+60
+00
+00
+00
+3e
+40
+3c
+02
+7c
+00
+00
+18
+18
+7e
+18
+18
+18
+00
+00
+00
+66
+66
+66
+66
+3e
+00
+00
+00
+00
+66
+66
+3c
+18
+00
+00
+00
+63
+6b
+6b
+6b
+3e
+00
+00
+00
+66
+3c
+18
+3c
+66
+00
+00
+00
+66
+66
+3e
+06
+3c
+00
+00
+00
+3c
+0c
+18
+30
+3c
+00
+0e
+18
+18
+30
+18
+18
+0e
+00
+18
+18
+18
+00
+18
+18
+18
+00
+70
+18
+18
+0c
+18
+18
+70
+00
+00
+00
+3a
+6c
+00
+00
+00
+00
+08
+1c
+36
+63
+41
+41
+7f
diff --git a/hdl/vga/vga.v b/hdl/vga/vga.v
@@ -0,0 +1,91 @@
+// Copyright 2012, Brian Swetland
+
+`timescale 1ns/1ns
+
+// Vert:  2xSync 30xBack 480xData 12xFront  -> 524 lines
+// Horz: 96xSync 48xBack 640xData 16xFront  -> 800 pixels
+//
+// CLK: 25MHz, px=40nS, line=32uS, frame=16.768mS
+
+module vga(
+	input clk,
+	output reg hs,
+	output reg vs,
+	output reg [3:0] r,
+	output reg [3:0] g,
+	output reg [3:0] b,
+
+	output reg newline,
+	output reg advance,
+	output reg [7:0] line,
+	input [11:0] pixel
+	);
+
+reg [9:0] hcount;
+reg [9:0] vcount;
+
+reg [9:0] next_hcount;
+reg [9:0] next_vcount;
+reg next_hs, next_vs;
+reg active;
+reg next_startline;
+reg [9:0] next_line;
+
+always @* begin
+	if (hcount == 10'd799) begin
+		if (vcount == 10'd523)
+			next_vcount = 10'd0;
+		else
+			next_vcount = vcount + 10'd1;
+		next_hcount = 10'd0;
+	end else begin
+		next_vcount = vcount;
+		next_hcount = hcount + 10'd1;
+	end
+
+	if (next_hcount == 0)
+		next_startline = 1'b1;
+	else
+		next_startline = 1'b0;
+
+	if (next_hcount < 10'd96)
+		next_hs = 1'b0;
+	else
+		next_hs = 1'b1;
+
+	if (next_vcount < 10'd2)
+		next_vs = 1'b0;
+	else
+		next_vs = 1'b1;
+
+	active = 1'b0;
+	if ((next_vcount > 31) && (next_vcount < 512))
+		if ((next_hcount > 143) && (next_hcount < 784))
+			active = 1'b1;
+
+	next_line = next_vcount - 10'd32;
+end
+
+always @(posedge clk) begin
+	hcount <= next_hcount;
+	vcount <= next_vcount;
+	hs <= next_hs;
+	vs <= next_vs;
+
+	/* signals to pixel generator */
+	newline <= next_startline;
+	advance <= active;
+	line <= next_line[8:1];
+
+	if (active) begin
+		r <= pixel[11:8];
+		g <= pixel[7:4];
+		b <= pixel[3:0];
+	end else begin
+		r <= 4'd0;
+		g <= 4'd0;
+		b <= 4'd0;
+	end
+end
+
+endmodule
diff --git a/hdl/vga/vga40x30x2.v b/hdl/vga/vga40x30x2.v
@@ -0,0 +1,63 @@
+
+module vga40x30x2(
+	input clk25m,
+	output [1:0]red,
+	output [1:0]grn,
+	output [1:0]blu,
+	output hs,
+	output vs,
+	input [10:0]vram_waddr,
+	input [7:0]vram_wdata,
+	input vram_we
+	);
+
+wire [3:0]r;
+wire [3:0]g;
+wire [3:0]b;
+
+wire newline;
+wire advance;
+wire [7:0]line;
+wire[11:0]pixel;
+
+vga vga0(
+	.clk(clk25m),
+	.hs(hs),
+	.vs(vs),
+	.r(r),
+	.g(g),
+	.b(b),
+	.newline(newline),
+	.advance(advance),
+	.line(line),
+	.pixel(pixel)
+	);
+
+assign red = r[3:2];
+assign grn = g[3:2];
+assign blu = b[3:2];
+
+wire [10:0]vram_raddr;
+wire [7:0]vram_rdata;
+
+pixeldata pixeldata0(
+	.clk(clk25m),
+	.newline(newline),
+	.advance(advance),
+	.line(line),
+	.pixel(pixel),
+	.vram_data(vram_rdata),
+	.vram_addr(vram_raddr)
+	);
+
+videoram #(8,11) vram(
+        .clk(clk25m),
+        .rdata(vram_rdata),
+        .raddr(vram_raddr),
+        .we(vram_we),
+        .wdata(vram_wdata[7:0]),
+        .waddr(vram_waddr[10:0])
+        );
+
+
+endmodule
diff --git a/hdl/vga/videoram.v b/hdl/vga/videoram.v
@@ -0,0 +1,25 @@
+// Copyright 2012, Brian Swetland.  Use at your own risk.
+//
+// sync sram with independent read/write addressing
+
+`timescale 1ns/1ns
+
+module videoram #(parameter DWIDTH=16, parameter AWIDTH=8) (
+	input clk, input we,
+	input [AWIDTH-1:0] waddr,
+	input [DWIDTH-1:0] wdata,
+	input [AWIDTH-1:0] raddr,
+	output reg [DWIDTH-1:0] rdata
+	);
+
+reg [DWIDTH-1:0] mem[0:2**AWIDTH-1];
+
+initial $readmemh("vram.txt", mem);
+
+always @(posedge clk) begin
+	if (we)
+		mem[waddr] <= wdata;
+	rdata <= mem[raddr];
+end
+
+endmodule
diff --git a/hdl/vga/vram.txt b/hdl/vga/vram.txt
@@ -0,0 +1,2048 @@
+48
+65
+6c
+6c
+6f
+2c
+20
+56
+47
+41
+20
+57
+6f
+72
+6c
+64
+21
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+01
+02
+03
+04
+05
+06
+07
+08
+09
+0a
+0b
+0c
+0d
+0e
+0f
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+1a
+1b
+1c
+1d
+1e
+1f
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+2a
+2b
+2c
+2d
+2e
+2f
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+3a
+3b
+3c
+3d
+3e
+3f
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+4a
+4b
+4c
+4d
+4e
+4f
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+5a
+5b
+5c
+5d
+5e
+5f
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+6a
+6b
+6c
+6d
+6e
+6f
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+7a
+7b
+7c
+7d
+7e
+7f
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00