... but super unstable. It looks as if pixel data gets subtly corrupted when output over HDMI. To-Do: * Check whether broken output persists on Windows and is not linux-only * Check whether output is still broken if software rendering/window compositing is used * Maybe check on an apple platform? * Research this behavior
162 lines
No EOL
4.5 KiB
Verilog
162 lines
No EOL
4.5 KiB
Verilog
`timescale 1ns / 1ps
|
|
|
|
module term_renderer(
|
|
input rst, clk,
|
|
|
|
input in_blank, in_vsync, in_hsync,
|
|
|
|
input [19:0] glyphmem_data,
|
|
output [15:0] glyphmem_r_addr,
|
|
|
|
output out_hsync, out_vsync,
|
|
output [7:0] out_red,
|
|
output [7:0] out_green,
|
|
output [7:0] out_blue
|
|
);
|
|
|
|
parameter GLYPHMEM_W = 256; /* glyphs */
|
|
parameter GLYPHMEM_H = 128; /* glyphs */
|
|
|
|
/* Glyph table instantiation */
|
|
`include "gen/gen_font_params_default.vh"
|
|
localparam FONT_GLYPH_W = `GEN_FONT_GLYPH_W_default;
|
|
localparam FONT_GLYPH_H = `GEN_FONT_GLYPH_H_default;
|
|
localparam FONT_GLYPH_COUNT = `GEN_FONT_GLYPH_COUNT_default;
|
|
reg [FONT_GLYPH_W-1:0] glyph_table_default [0:FONT_GLYPH_COUNT*FONT_GLYPH_H-1];
|
|
/* This is the dumbest thing, but it seems vivado is just *that* stupid. */
|
|
`ifdef SYNTHESIS
|
|
initial $readmemh("../../src/gen/gen_glyphtable_default.hex", glyph_table_default);
|
|
`else
|
|
initial $readmemh("../../../../src/gen/gen_glyphtable_default.hex", glyph_table_default);
|
|
`endif
|
|
|
|
`include "gen/gen_font_params_bold.vh"
|
|
/* NOTE: Bold font must have same glyph w/h, glyph count as regular font above */
|
|
reg [FONT_GLYPH_W-1:0] glyph_table_bold [0:FONT_GLYPH_COUNT*FONT_GLYPH_H-1];
|
|
`ifdef SYNTHESIS
|
|
initial $readmemh("../../src/gen/gen_glyphtable_bold.hex", glyph_table_bold);
|
|
`else
|
|
initial $readmemh("../../../../src/gen/gen_glyphtable_bold.hex", glyph_table_bold);
|
|
`endif
|
|
|
|
/* Color palette */
|
|
function [23:0] color_palette;
|
|
input [3:0] index;
|
|
begin
|
|
/* Peppermint color palette: https://noahfrederick.com/log/lion-terminal-theme-peppermint */
|
|
case (index)
|
|
default: color_palette = 24'h353535;
|
|
(1): color_palette = 24'he64569;
|
|
(2): color_palette = 24'h89d287;
|
|
(3): color_palette = 24'hdab752;
|
|
(4): color_palette = 24'h439ecf;
|
|
(5): color_palette = 24'hd961dc;
|
|
(6): color_palette = 24'h64aaaf;
|
|
(7): color_palette = 24'hb3b3b3;
|
|
(8): color_palette = 24'h535353;
|
|
(9): color_palette = 24'he4859a;
|
|
(10): color_palette = 24'ha2cca1;
|
|
(11): color_palette = 24'he1e387;
|
|
(12): color_palette = 24'h6fbbe2;
|
|
(13): color_palette = 24'he586e7;
|
|
(14): color_palette = 24'h96dcda;
|
|
(15): color_palette = 24'hdedede;
|
|
endcase
|
|
end
|
|
endfunction
|
|
|
|
/* Glyph x/y synchronization logic */
|
|
reg [11:0] glyph_x;
|
|
reg [11:0] glyph_y;
|
|
reg [FONT_GLYPH_W-1:0] glyph_sreg_out;
|
|
reg [5:0] px_x;
|
|
reg [5:0] px_y;
|
|
reg in_hsync_last, in_vsync_last;
|
|
|
|
wire [7:0] gm_data_glyph = glyphmem_data[7:0];
|
|
wire [11:0] gm_data_style = glyphmem_data[19:8];
|
|
reg [11:0] glyphmem_style_reg;
|
|
wire [3:0] gm_data_fgcolor = glyphmem_style_reg[3:0];
|
|
wire [3:0] gm_data_bgcolor = glyphmem_style_reg[7:4];
|
|
wire gm_data_bold = gm_data_style[10];
|
|
wire gm_data_underline = glyphmem_style_reg[11] && !newline_found;
|
|
reg newline_found;
|
|
|
|
assign out_vsync = in_vsync_last;
|
|
assign out_hsync = in_hsync_last;
|
|
|
|
assign glyphmem_r_addr = (GLYPHMEM_W*glyph_y) + glyph_x;
|
|
wire px_data = glyph_sreg_out[FONT_GLYPH_W-1] || (gm_data_underline && px_y == FONT_GLYPH_H-2);
|
|
assign {out_red, out_green, out_blue} = color_palette(px_data ? gm_data_fgcolor : gm_data_bgcolor);
|
|
|
|
/* Core logic */
|
|
always @(posedge clk) begin
|
|
if (rst) begin
|
|
glyph_x <= 0;
|
|
glyph_y <= 0;
|
|
px_x <= 0;
|
|
px_y <= 0;
|
|
in_hsync_last <= 0;
|
|
in_vsync_last <= 0;
|
|
glyph_sreg_out <= 0;
|
|
glyphmem_style_reg <= 0;
|
|
newline_found <= 0;
|
|
|
|
end else begin
|
|
in_hsync_last <= in_hsync;
|
|
in_vsync_last <= in_vsync;
|
|
|
|
if (in_hsync_last && !in_hsync) begin
|
|
glyph_x <= 0;
|
|
px_x <= 0;
|
|
newline_found <= 0;
|
|
|
|
if (px_y != FONT_GLYPH_H-1) begin
|
|
px_y <= px_y + 1;
|
|
end else begin
|
|
glyph_y <= glyph_y + 1;
|
|
px_y <= 0;
|
|
end
|
|
|
|
end else if (!in_blank) begin
|
|
if (px_x != FONT_GLYPH_W-1) begin
|
|
px_x <= px_x + 1;
|
|
|
|
end else begin
|
|
px_x <= 0;
|
|
end
|
|
|
|
if (px_x == 0) begin
|
|
if (newline_found) begin
|
|
glyph_sreg_out <= 0;
|
|
end else if (gm_data_bold) begin
|
|
glyph_sreg_out <= glyph_table_bold[gm_data_glyph*FONT_GLYPH_H + px_y];
|
|
end else begin
|
|
glyph_sreg_out <= glyph_table_default[gm_data_glyph*FONT_GLYPH_H + px_y];
|
|
end
|
|
|
|
glyphmem_style_reg <= gm_data_style;
|
|
glyph_x <= glyph_x + 1;
|
|
|
|
if (gm_data_glyph == 8'h0a) begin /* Newline character */
|
|
newline_found <= 1;
|
|
end
|
|
|
|
end else begin
|
|
glyph_sreg_out <= {glyph_sreg_out[FONT_GLYPH_W-2:0], 1'b0};
|
|
end
|
|
|
|
end else if (!in_hsync_last) begin
|
|
glyph_sreg_out <= 0;
|
|
glyphmem_style_reg <= 0;
|
|
end
|
|
|
|
if (in_vsync_last && !in_vsync) begin
|
|
glyph_y <= 0;
|
|
px_y <= 0;
|
|
end
|
|
end
|
|
end
|
|
|
|
|
|
endmodule |