It's not complete and it only works on 8x16 fonts, but here's
something I slapped together to do the VGA text mode in Verilog:


// Copyright 2005, Timothy Miller, LGPL license


module vga_convert_text(
    clock,
    reset,
    
    // read request fifo
    req_busy_i,
    req_send_o,
    req_addr_o,
    
    // read receipt fifo
    read_valid_i,
    read_data_i,
    read_deq_o,
    
    // write fifo
    write_busy_i,
    write_valid_o,
    write_addr_o,
    write_data_o,
    
    // config_data
    text_base,
    font_base,
    video_base,
    video_stride,
    last_column,
    last_row,
    char_total,
    
    // other
    blink_on
);

input clock, reset;
input blink_on;

input req_busy_i;
output req_send_o;
output [27:0] req_addr_o;

input read_valid_i;
input [31:0] read_data_i;
output read_deq_o;

input write_busy_i;
output write_valid_o;
output [27:0] write_addr_o;
output [31:0] write_data_o;

input [27:0] text_base;
input [27:0] font_base;
input [27:0] video_base;
input [15:0] video_stride;
input [7:0] last_column;
input [7:0] last_row;
input [12:0] char_total;


// Note that the interface to the req, read, and write fifos is not correct. 
// I'll fix it later.
// Also, this doesn't do a cursor yet


// Fifo between reader and writer
// If this is done right, ISE will infer distributed RAM properly
reg [31+8:0] fifo_data [0:16];
reg [4:0] fifo_head, fifo_tail;
wire fifo_full = (fifo_head[3:0] == fifo_tail[3:0]) && 
                 (fifo_head[4] != fifo_tail[4]);
wire fifo_empty = fifo_head == fifo_tail;



// Read state machine
parameter s_start       = 0;
parameter s_get_char    = 1;
parameter s_wait_char   = 2;
parameter s_get_font0   = 3;
parameter s_get_font1   = 3;
parameter s_wait_font0  = 4;
parameter s_wait_font1  = 5;
parameter s_loop        = 6;

reg [7:0] attr0, addr1;
reg [11:0] char0, char1;
reg [1:0] font_count;
reg [12:0] char_count;

always @(posedge clock) begin
    if (reset) begin
        fifo_tail <= 0;
        req_send_o <= 0;
        read_deq_o <= 0;
        state <= s_start;
    end else begin
        req_send_o <= 0;
        read_deq_o <= 0;
        
        case (reader_state)
            s_start: begin
                // Wait for the writer to finish to be sure we
                // never get out of sync
                if (writer_idle) begin
                    text_address <= text_base;
                    char_count <= 0;
                    state <= s_get_char;
                end
            end
            s_get_char: begin
                if (!req_busy_i) begin
                    req_send_o <= 1;
                    req_addr_o <= text_address;
                    text_address <= text_address + 1;
                    char_count <= char_count + 1;
                    state <= s_wait_char;
                end
            end
            s_wait_char: begin
                if (read_valid_i) begin
                    read_deq_o <= 1;
                    // Note:  check byte ordering
                    char0 <= {read_data_i[31:24], 4'b0};
                    attr0 <= read_data_i[23:16];
                    char1 <= {read_data_i[15:8], 4'b0};
                    attr1 <= read_data_i[7:0];

                    state <= s_get_font;
                    
                    // We'll change this a bit for char_height != 16
                    font_count <= 3;
                end
            end
            s_get_font0: begin
                if (!req_busy_i) begin
                    req_send_o <= 1;
                    req_addr_o <= font_address + char0;
                    char0 <= char0 + 1;

                    if (!font_count) state <= s_get_font1;
                    found_count <= font_count - 1;
                end
            end
            s_get_font1: begin
                if (!req_busy_i) begin
                    req_send_o <= 1;
                    req_addr_o <= font_address + char1;
                    char1 <= char1 + 1;

                    if (!font_count) state <= s_wait_font0;
                    found_count <= font_count - 1;
                end
            end
            s_wait_font0: begin
                if (read_valid_i && !fifo_full) begin
                    read_deq_o <= 1;
                    fifo_data[fifo_tail] <= {attr0, read_data_i};
                    fifo_tail <= fifo_tail + 1;

                    if (!font_count) state <= s_wait_font1;
                    found_count <= font_count - 1;
                end
            end
            s_wait_font1: begin
                if (read_valid_i && !fifo_full) begin
                    read_deq_o <= 1;
                    fifo_data[fifo_tail] <= {attr1, read_data_i};
                    fifo_tail <= fifo_tail + 1;

                    if (!font_count) state <= s_loop;
                    found_count <= font_count - 1;
                end
            end
            s_loop: begin
                if (char_count == char_total) begin
                    state <= s_start;
                end else begin
                    state <= s_get_char;
                end
            end
        endcase
    end
end



// writer states
parameter w_start           = 0;
parameter w_left_char0      = 1;
parameter w_left_char1      

reg [27:0] write_address [0:3];
reg [10:0] column, row;

wire [27:0] down1line = write_address[1] + video_stride;
wire [27:0] over1char = write_address[2] + 8;
wire [27:0] down1char = write_address[3] + {video_stride, 4'b0};

// convert col/row to fifo word bit.  Notice how we let the synthesizer
// reorder the bits
wire [31+8:0] fifo_word = fifo_data[fifo_head];
wire [0:31] fifo_bdata = fifo_word;
wire fifo_bit = fifo_bdata[{row[1:0], column[2:0]}];

// extract the attribute bits
// I'm sure I have the bit order wrong
wire [2:0] bg_index = fifo_word[38:36];
wire [3:0] fg_index = (blink_on == fifo_word[39]) ?
    fifo_word[35:32] : bg_index;
    
// quick and dirty way of converting to RGB
wire [31:0] bg_color = {1'b0, {7{bg_index[2]}}, 1'b0, {7{bg_index[1]}},
    1'b0, {7{bg_index[0]}}};
wire [31:0] fg_color = {fg_index[3], {7{fg_index[2]}}, 
    fg_index[3], {7{fg_index[1]}},
    fg_index[3], {7{fg_index[0]}}};


always @(posedge clock) begin
    if (reset) begin
        write_address[0] <= video_base;
        write_address[1] <= video_base;
        write_address[2] <= video_base;
        write_address[3] <= video_base;
        writer_idle <= 1;
        column <= 0;
        row <= 0;
    end else begin
        if (!fifo_empty) begin
            writer_idle <= 0;
        end

        if (!write_busy_i && !fifo_empty) begin
            // dequeue at the right time
            if (column[2:0] == 7 && row[1:0] == 3) begin
                fifo_head <= fifo_head + 1;
            end

            // Move to the right
            write_address[0] <= write_address[0] + 1;
            column[2:0] <= column[2:0] + 1;
            if (column[2:0] == 7) begin
                // At right of char cell, move down a scanline
                write_address[0] <= down1line;
                write_address[1] <= down1line;
                
                row[3:0] <= row[3:0] + 1;
                if (row[3:0] == 15) begin
                    // At bottom of char cell, move back up and over 1 char
                    write_address[0] <= over1char;
                    write_address[1] <= over1char;
                    write_address[2] <= over1char;
                    
                    column[10:3] <= column[10:3] + 1;
                    if (column[10:3] == last_column) begin
                        // at end of line, move down to next char line
                        write_address[0] <= down1char;
                        write_address[1] <= down1char;
                        write_address[2] <= down1char;
                        write_address[3] <= down1char;
                        
                        column[10:3] <= 0;
                        row[10:4] <= row[10:4] + 1;
                        if (row[10:4] == last_row) begin
                            // Last col/row of last cell of last 
                            // col/row of character array, stop
                            writer_idle <= 1;
                        end
                    end
                end
            end
            
            write_valid_o <= 1;
            write_data_o <= fifo_bit ? fg_color : bg_color;
            write_addr_o <= write_address[0];
        end
    end
end


endmodule

_______________________________________________
Open-graphics mailing list
[email protected]
http://lists.duskglow.com/mailman/listinfo/open-graphics
List service provided by Duskglow Consulting, LLC (www.duskglow.com)

Reply via email to