chardata.sv (4041B)
1 // Copyright 2018, Brian Swetland <swetland@frotz.net> 2 // Licensed under the Apache License, Version 2.0. 3 // 4 // Character Display Engine 5 // 6 // newline strobes on the first pixel of a new line 7 // advance strobes on each visible pixel of a new line 8 // line provides the visible line count 0..239 9 // 10 // vram_addr/vram_data: connect to sync sram 11 12 `default_nettype none 13 14 `timescale 1ns/1ns 15 16 module pixeldata #( 17 parameter BPP = 2, 18 parameter RGB = 0 19 )( 20 input wire clk, 21 input wire newline, 22 input wire advance, 23 input wire [7:0] line, 24 output wire [(3*BPP)-1:0] pixel, 25 input wire [(RGB*8)+7:0] vram_data, 26 output wire [10:0] vram_addr 27 ); 28 29 reg [7:0] pattern_rom [0:1023]; 30 31 `ifdef HEX_PATHS 32 initial $readmemh("hdl/vga/prom.txt", pattern_rom); 33 `else 34 initial $readmemh("prom.txt", pattern_rom); 35 `endif 36 37 reg next_load; 38 reg next_load_cdata; 39 reg next_loaded_cdata; 40 reg next_load_pdata; 41 reg next_load_pattern; 42 reg [5:0] next_xpos; 43 reg [3:0] next_ppos; 44 reg [15:0] next_pattern; 45 46 reg load = 1'b0; 47 reg load_cdata = 1'b0; 48 reg loaded_cdata = 1'b0; 49 reg load_pdata = 1'b0; 50 reg load_pattern = 1'b0; 51 reg [5:0]xpos = 6'b0; 52 reg [3:0]ppos = 4'b0; 53 reg [15:0]pattern = 16'b0; 54 55 reg [(RGB*8)+7:0]cdata; 56 reg [7:0]pdata; 57 reg [2:0]fg; 58 reg [2:0]bg; 59 60 reg set_fg_bg; 61 62 wire [(3*BPP)-1:0]FG; 63 wire [(3*BPP)-1:0]BG; 64 65 if (RGB) begin 66 assign FG = {{BPP{fg[2]}},{BPP{fg[1]}},{BPP{fg[0]}}}; 67 assign BG = {{BPP{bg[2]}},{BPP{bg[1]}},{BPP{bg[0]}}}; 68 end else begin 69 assign FG = { 3*BPP { 1'b1 }}; 70 assign BG = { { 2*BPP { 1'b0 }}, { BPP { 1'b1 }} }; 71 end 72 73 // generate vram address by using the high bits of the display 74 // line and the local xpos character counter 75 assign vram_addr = { line[7:3], xpos }; 76 77 // generate pattern rom address by using the character id 78 // fetched from vram as the high bits and the low bits of 79 // the display line to further index into the correct pattern 80 wire [9:0] prom_addr = { cdata[6:0], line[2:0] }; 81 82 `ifdef ASYNC_ROM 83 wire [7:0] prom_data = pattern_rom[prom_addr]; 84 `else 85 reg [7:0] prom_data; 86 always_ff @(posedge clk) 87 prom_data <= pattern_rom[prom_addr]; 88 `endif 89 90 // double-wide pattern data 91 wire [15:0]pdata2x = { 92 pdata[7], pdata[7], pdata[6], pdata[6], 93 pdata[5], pdata[5], pdata[4], pdata[4], 94 pdata[3], pdata[3], pdata[2], pdata[2], 95 pdata[1], pdata[1], pdata[0], pdata[0] 96 }; 97 98 // the high bit of the pattern shift register is used to 99 // select the FG or BG color and feed out to the vga core 100 assign pixel = pattern[15] ? FG : BG; 101 102 always_comb begin 103 set_fg_bg = 1'b0; 104 next_xpos = xpos; 105 next_ppos = ppos; 106 next_pattern = pattern; 107 next_load = 1'b0; 108 109 // multi-step load (cdata, then pdata, then pattern) 110 next_load_cdata = load; 111 next_loaded_cdata = load_cdata; 112 next_load_pdata = loaded_cdata; 113 next_load_pattern = load_pdata; 114 115 if (newline) begin 116 // reset character counter (xpos), pattern counter (ppos), 117 // and preload the first pattern 118 next_load = 1'b1; 119 next_xpos = 6'b0; 120 next_ppos = 4'b0; 121 end else if (advance) begin 122 next_ppos = ppos + 4'h1; 123 if (ppos == 4'hF) begin 124 // advance to next pattern (preloaded in pdata) 125 next_pattern = pdata2x; 126 set_fg_bg = 1'b1; 127 end else begin 128 // advance to the next bit in the current pattern 129 next_pattern = { pattern[14:0], 1'b0 }; 130 if (ppos == 4'd0) begin 131 // advance xpos and start preloading 132 // for the next character 133 next_load = 1'b1; 134 next_xpos = xpos + 6'd1; 135 end 136 end 137 end else begin 138 // handle the final step of preloading the pattern 139 // for xpos 0 (between newline=1 and advance=1) 140 if (load_pattern) begin 141 next_pattern = pdata2x; 142 set_fg_bg = 1'b1; 143 end 144 end 145 end 146 147 always_ff @(posedge clk) begin 148 load <= next_load; 149 load_cdata <= next_load_cdata; 150 loaded_cdata <= next_loaded_cdata; 151 load_pdata <= next_load_pdata; 152 load_pattern <= next_load_pattern; 153 xpos <= next_xpos; 154 ppos <= next_ppos; 155 pattern <= next_pattern; 156 if (load_cdata) 157 cdata <= vram_data; 158 if (load_pdata) 159 pdata <= prom_data; 160 end 161 162 if (RGB) begin 163 always_ff @(posedge clk) begin 164 if (set_fg_bg) begin 165 fg <= cdata[14:12]; 166 bg <= cdata[10:8]; 167 end 168 end 169 end 170 171 endmodule