//-------------------------- // VGA driver // // Datum: Nov 8, 2007 // Auteur: fotoopa // Copyright (c) 2007 http://www.pbase.com/fotoopa // Deze routines mogen enkel gebruikt worden voor persoonlijke doeleinden en // mits behoud van deze copyright teksten. // Voor het wijzigen van de parameters is wel enig inzicht nodig van de timingen // van een VGA monitor. Er kunnen heel veel instellingen aangepast worden // zolang je binnen de perken van de totale timingen blijft. // Tracht tijdens het experimenteren met de parameters slecht een per een te // wijzigen zodat je beter de invloed van elke parameter begrijpt. // op mijn web is een meer gedetailieerde beschrijving beschikbaar. // http://users.skynet.be/fotoopa/fpga/fpga.htm //-------------------------- module display_driver ( input clk_vga, // 27 Mhz voor VGA, 9 Mhz voor LCD 4.3" input resetn, // actief lage reset. input dpram_wr, // write enable voor dpram characters. input [7:0] dpram_data, // applicatie data dpram. input [11:0] dpram_adr, // applicatie adres dpram. output reg h_sync, // horizontal sync signaal, actief laag output reg v_sync, // vertikaal sync signaal, actief laag output reg disp, // display enable signaal enkel (LCD 4.3") output reg [1:0] R_color, // lcd data rood 2 bit voor VGA, 8 bit voor LCD output reg [1:0] G_color, // lcd data groen 2 bit voor VGA, 8 bit voor LCD output reg [1:0] B_color // lcd data blauw 2 bit voor VGA, 8 bit voor LCD ); //`include "inc_32x76.h" `include "inc_16x38.h" //`include "inc_8x19.h" //`include "inc_6x16.h" //`include "inc_4x12.h" //`include "inc_2x6.h" //`include "inc_1x4.h" reg [1:0] h_state; // state toestand reg [9:0] h_pixel_cnt; // horizontale pixel teller reg [5:0] h_dot_cnt; // positie font dot horizontal reg [5:0] h_dot_pix; // horizontaal pixels per dot teller reg [9:0] v_pixel_cnt; // vertikale pixel teller reg [5:0] v_dot_cnt; // positie font dot vertikal reg [5:0] v_dot_pix; // vertikaal pixels per dot teller reg [12:0] char_pnt; // display character teller reg [10:0] font_pnt; // font pointer reg [7:0] font_reg; // font data bits uit de chracter generator. reg [7:0] h_dot_reg; // overname fonts bits voor verwerking. reg [7:0] char_reg; // overname huidige character ascii waarde. reg disp_reg; // voor delay disp signaal reg disp1_reg; // voor delay disp signaal reg [4:0] disp_dly; // voor delay disp signaal reg [1:0] zone; // zone register reg h_dot_ena; // display flags reg v_dot_ena; // display flags reg h_flag_img; // display flags reg v_flag_img; // display flags reg h_flag_dot; // display flags reg v_flag_dot; // display flags reg char_ena; // display flags wire [7:0] font_data; wire [7:0] char_data; font_ram font5x7( .address (font_pnt), // aanspreek adres font ram .clock (clk_vga), // ram clk .data (8'h0), // data 00, niet gebruikt .wren (1'b0), // read only font wordt geladen bij powerup. .q (font_data) // output font_bits tijdens display ); dpram_32x128 dp_ram1( .clock (clk_vga), // vga clock .data (dpram_data), // applicatie data input ascii .rdaddress (char_pnt), // uitlees pointer voor display .wraddress (dpram_adr), // write pointer voor applicatie .wren (dpram_wr), // write enable van applicatie .q (char_data) // output data voor display ); // reset actie's always @ (posedge clk_vga ) begin if (!resetn) begin disp <= 0; // enkel ingeval LCD nodig disp_reg <= 0; // delay opbouw register disp1_reg <= 0; // delay opbouw register disp_dly <= 0; // delay opbouw register end else begin disp_reg <= v_sync; disp1_reg <= resetn & disp_reg & !v_sync; if (disp1_reg & (disp_dly <31)) disp_dly <= disp_dly+1; if ((disp_dly ==31) & h_sync & v_sync) disp <= 1; // disp mag slechts aangaan na min 10 frames na powerup. // bepalen display zones horizontaal image en character if (h_pixel_cnt == H_PIXEL_TO_IMAGE_BEG) begin h_flag_img <= 1; h_flag_dot <= 0; end if (h_pixel_cnt == H_PIXEL_TO_CHAR_BEG-2) begin h_flag_dot <= 1; h_flag_img <= 0; end if (h_pixel_cnt == H_PIXEL_TO_CHAR_END-2) begin h_flag_dot <= 0; h_flag_img <= 1; end if (h_pixel_cnt == H_PIXEL_TO_IMAGE_END-1) begin h_flag_img <= 0; h_flag_dot <= 0; end // bepalen display zones vertikaal image en character if (v_pixel_cnt == V_PIXEL_TO_IMAGE_BEG) begin v_flag_dot <= 0; v_flag_img <= 1; end if (v_pixel_cnt == V_PIXEL_TO_CHAR_BEG) begin v_flag_dot <= 1; v_flag_img <= 0; end if (v_pixel_cnt == V_PIXEL_TO_CHAR_END-1) begin v_flag_dot <= 0; v_flag_img <= 1; end if (v_pixel_cnt == V_PIXEL_TO_IMAGE_END-1) begin v_flag_img <= 0; v_flag_dot <= 0; end // toewijzen image, character en blank zone if ((h_flag_img & v_flag_img)|(h_flag_img & v_flag_dot) | (h_flag_dot &v_flag_img )) zone <= ZONE_IMAGE; else if (h_flag_dot & v_flag_dot) zone <= ZONE_DOT; else zone <= ZONE_ZWART; // horizontaal en vertikaal sync behandeling if (h_pixel_cnt == H_SYNC-1) h_sync <= 1; if (h_pixel_cnt < H_TOTAL_PIXELS-1) h_pixel_cnt <= h_pixel_cnt+1; else begin h_pixel_cnt <= 0; h_sync <= 0; if (v_pixel_cnt == (V_SYNC-1)) v_sync <= 1; if (v_pixel_cnt < (V_TOTAL_PIXELS-1)) v_pixel_cnt <= v_pixel_cnt +1; else begin v_dot_pix <= 0; v_pixel_cnt <= 0; v_sync <= 0; v_dot_cnt <= 0; char_pnt <= 0; end end // character en font behandeling char_reg <= char_data; // overname 8 bits data ascii font_reg <= font_data; // overname 8 bits data font bits font_pnt <= ((char_reg * // bekenen uit ascii char het font adres BYTES_PER_FONT)+ // nodig om display dots te bepalen (v_dot_cnt-V_FONT_BLANK_START) ); // font_data bevat telkens 8 bits uit de font if (v_dot_cnt == V_FONT_BLANK_START) char_ena <= 1; if (v_dot_cnt == V_FONT_CHAR_END) char_ena <= 0; // kleuren toekennen volgens de berekende zones if (zone == ZONE_ZWART) // alle pixels off begin R_color <= ZWART_LEVEL; // zwartlevel monitor G_color <= ZWART_LEVEL; // zwartlevel monitor B_color <= ZWART_LEVEL; // zwartlevel monitor end if (zone == ZONE_IMAGE) begin R_color <= R_image; // image pixel kleur G_color <= G_image; // image pixel kleur B_color <= B_image; // image pixel kleur end if (zone == ZONE_DOT) begin if (h_dot_reg[7] & char_ena) // char_ena onderdrukt dots juist voor character font begin R_color <= R_dot_H; // fontkleur 1 dot G_color <= G_dot_H; // fontkleur 1 dot B_color <= B_dot_H; // fontkleur 1 dot end else begin R_color <= R_dot_L; // fontkleur 0 dot G_color <= G_dot_L; // fontkleur 0 dot B_color <= B_dot_L; // fontkleur 0 dot end end // state machine voor character dot te bepalen case (h_state) 0: begin h_dot_cnt <= 0; h_dot_pix <= 0; char_pnt <= (char_pnt & DPRAM_AND_MASK); h_state <= 1; end 1: begin if (h_flag_dot & v_flag_dot) begin h_dot_reg <= font_reg; h_state <= 2; end end 2: begin if (h_dot_pix < (H_DOT_PIXELS-1)) h_dot_pix <= h_dot_pix+1; else begin h_dot_pix <= 0; if (h_dot_cnt < (H_DOTS_PER_CHAR-1)) begin h_dot_reg[7:1] <= h_dot_reg[6:0]; h_dot_cnt <= h_dot_cnt+1; end else begin h_dot_cnt <= 0; h_dot_reg <= font_reg; end if ((h_dot_cnt < (H_DOTS_PER_CHAR-2)) & (h_dot_cnt < (h_dot_pix == (H_DOT_PIXELS-1)))) char_pnt <= char_pnt +1; end if (h_pixel_cnt == (H_PIXEL_TO_CHAR_END-1)) begin h_state <= 3; end end 3: begin if (v_dot_pix < (V_DOT_PIXELS-1)) v_dot_pix <= v_dot_pix+1; else begin v_dot_pix <= 0; if (v_dot_cnt < (V_FONT_TOTAL-1)) begin v_dot_cnt <= v_dot_cnt +1; end else begin v_dot_cnt <= 0; char_pnt <= (((char_pnt-1) & DPRAM_AND_MASK)+DPRAM_ADD_MASK); // vooraan volgende lijn end end h_state <= 0; end endcase end end endmodule