基于fpga实现tft屏幕显示数字、字母

简介

开发平台:ZYNQ
开发工具:Vivado 2018.3
tft屏幕分辨率:800*480
在PL端使用纯verilog实现bitmap模块,基于该模块实现在tft屏幕显示数字0-9,以及FPGA字母

Bitmap模块

基于fpga实现tft屏幕显示数字、字母_第1张图片
该模块为5*5的bitmap,纯组合逻辑,基于case实现

  • digit[3:0]: 要显示的数字bcd码,取值范围0-9,为了显示字母,在取值为11-14时,添加了额外逻辑,其他情况输出0
  • yofs[2:0]: y坐标,取值范围0-4,其他情况输出0
  • bits[4:0]: 这一行的5个点

代码:

module bitmap(
    input [3:0] digit,        	// digit 0-9, 11-14 will be "FPGA"
    input [2:0] yofs,     		// vertical offset (0-4)
    output reg [4:0] bits    	// output (5 bits)
);
// combine digit,yofs
wire [6:0] caseexpr = {digit,yofs};
  
always @(*)
    case (caseexpr)
    // 0
    7'o00: bits = 5'b11111;
    7'o01: bits = 5'b10001;
    7'o02: bits = 5'b10001;
    7'o03: bits = 5'b10001;
    7'o04: bits = 5'b11111;
    // 1
    7'o10: bits = 5'b01100;
    7'o11: bits = 5'b00100;
    7'o12: bits = 5'b00100;
    7'o13: bits = 5'b00100;
    7'o14: bits = 5'b11111;
    // 2
    7'o20: bits = 5'b11111;
    7'o21: bits = 5'b00001;
    7'o22: bits = 5'b11111;
    7'o23: bits = 5'b10000;
    7'o24: bits = 5'b11111;
    // 3
    7'o30: bits = 5'b11111;
    7'o31: bits = 5'b00001;
    7'o32: bits = 5'b11111;
    7'o33: bits = 5'b00001;
    7'o34: bits = 5'b11111;
    // 4
    7'o40: bits = 5'b10001;
    7'o41: bits = 5'b10001;
    7'o42: bits = 5'b11111;
    7'o43: bits = 5'b00001;
    7'o44: bits = 5'b00001;
    // 5
    7'o50: bits = 5'b11111;
    7'o51: bits = 5'b10000;
    7'o52: bits = 5'b11111;
    7'o53: bits = 5'b00001;
    7'o54: bits = 5'b11111;
    // 6
    7'o60: bits = 5'b11111;
    7'o61: bits = 5'b10000;
    7'o62: bits = 5'b11111;
    7'o63: bits = 5'b10001;
    7'o64: bits = 5'b11111;
    // 7
    7'o70: bits = 5'b11111;
    7'o71: bits = 5'b00001;
    7'o72: bits = 5'b00001;
    7'o73: bits = 5'b00001;
    7'o74: bits = 5'b00001;
    // 8
    7'o100: bits = 5'b11111;
    7'o101: bits = 5'b10001;
    7'o102: bits = 5'b11111;
    7'o103: bits = 5'b10001;
    7'o104: bits = 5'b11111;
    // 9
    7'o110: bits = 5'b11111;
    7'o111: bits = 5'b10001;
    7'o112: bits = 5'b11111;
    7'o113: bits = 5'b00001;
    7'o114: bits = 5'b11111;
    
    // F
    7'o130: bits = 5'b11111;
    7'o131: bits = 5'b10000;
    7'o132: bits = 5'b11111;
    7'o133: bits = 5'b10000;
    7'o134: bits = 5'b10000;
    // P
    7'o140: bits = 5'b11111;
    7'o141: bits = 5'b10001;
    7'o142: bits = 5'b11111;
    7'o143: bits = 5'b10000;
    7'o144: bits = 5'b10000;
    // G
    7'o150: bits = 5'b11111;
    7'o151: bits = 5'b10000;
    7'o152: bits = 5'b10111;
    7'o153: bits = 5'b10001;
    7'o154: bits = 5'b11111;
    // A
    7'o160: bits = 5'b11111;
    7'o161: bits = 5'b10001;
    7'o162: bits = 5'b11111;
    7'o163: bits = 5'b10001;
    7'o164: bits = 5'b10001;

    default: bits = 0;
    endcase
endmodule

TFT驱动模块

和vga驱动类似,这里就不详细介绍了
代码:

module TFT_driver(
    input           clk,
    input           rst_n,
    
    // host input
    input [15:0]    data,
    
    // host output
    output          data_req,
    output [9:0]    h_addr,
    output [8:0]    v_addr,
    
    // TFT
    output          pclk,
    output          de,
    output          bl,
    output          hs,
    output          vs,
    output [15:0]   rgb
);
    // 800 * 480
    localparam  H_SYNC  = 11'd128,
                H_BEGIN = 11'd216,
                H_END   = 11'd1016,
                H_TOTAL = 11'd1056;
    localparam  V_SYNC  = 10'd2,
                V_BEGIN = 10'd35,
                V_END   = 10'd515,
                V_TOTAL = 10'd525;
                
    reg [10:0] cnt_h;
    reg [9:0] cnt_v;
    
    // cnt_h
    always @(posedge clk, negedge rst_n) begin
        if(!rst_n)
            cnt_h <= 0;
        else if(cnt_h == H_TOTAL - 1)
            cnt_h <= 0;
        else
            cnt_h <= cnt_h + 1;
    end
    
    // cnt_v
    always @(posedge clk, negedge rst_n) begin
        if(!rst_n)
            cnt_v <= 0;
        else if(cnt_h == H_TOTAL - 1) begin
            if(cnt_v == V_TOTAL - 1)
                cnt_v <= 0;
            else
                cnt_v <= cnt_v + 1;
        end
    end
    
    assign pclk = clk;
    
    assign bl   = rst_n;
    
    assign de = (cnt_h >= H_BEGIN && cnt_h < H_END && cnt_v >= V_BEGIN && cnt_v < V_END);
    
    assign hs = (cnt_h >= H_SYNC);
    assign vs = (cnt_v >= V_SYNC);
    
    assign rgb = de ? data : 0;
     
    assign h_addr = de ? (cnt_h - H_BEGIN) : 0;
    assign v_addr = de ? (cnt_v - V_BEGIN) : 0;
    
    assign data_req = de;
    
endmodule

顶层模块

使用clock wizard给TFT驱动模块供应33M时钟,根据y坐标和x坐标决定要显示的内容

代码:

module top_module(
    input           clk,
    input           rst_n,
    output          TFT_pclk,
    output          TFT_de,
    output          TFT_bl,
    output          TFT_hs,
    output          TFT_vs,
    output [15:0]   TFT_RGB
    );
localparam  BLACK   = 16'h0000, GREEN   = 16'h07E0;
            
wire pclk;
wire [15:0] data;
wire [9:0] h_addr;
wire [8:0] v_addr;
wire data_req;

wire [3:0] digit = h_addr[8:5];
wire [2:0] xofs = h_addr[4:2];
wire [2:0] yofs = v_addr[4:2];
wire [4:0] bits;

bitmap u_bitmap(
    .digit(digit),
    .yofs(yofs),
    .bits(bits)
);

assign data = ~xofs < 3'd5 ? (bits[~xofs] ? GREEN : BLACK) : BLACK;

clk_wiz_0 u_clk_wiz_0(
    .clk_in1    (clk),
    .clk_out1   (pclk)
);
            
TFT_driver u_TFT_driver(
    .clk        (pclk),
    .rst_n      (rst_n),
    
    // host input
    .data       (data),
    
    // host output
    .data_req   (data_req),
    .h_addr     (h_addr),
    .v_addr     (v_addr),
    
    // TFT
    .pclk       (TFT_pclk),
    .de         (TFT_de),
    .bl         (TFT_bl),
    .hs         (TFT_hs),
    .vs         (TFT_vs),
    .rgb        (TFT_RGB)
);
endmodule

实验结果

结果如下图:
基于fpga实现tft屏幕显示数字、字母_第2张图片

你可能感兴趣的:(FPGA,fpga开发)