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