gateware

A collection of little open source FPGA hobby projects
git clone http://frotz.net/git/gateware.git
Log | Files | Refs | README

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