zoukankan      html  css  js  c++  java
  • FPGA之VGA控制

     VGA的接口很少,一个行,一个场,三个RGB信号口,不同的分辨率对应不同的时钟频率,

    这里以800*600的50M的时钟为例,它的行同步脉冲长度为120,行同步后沿脉冲计数为

    64,行可视区脉冲为800,行同步前沿脉冲为56,也就是说,用50M的时钟来驱动,行信号

    先给120个时钟的低电平,然后是64个时钟的高平,用来指示到了后沿,再来800个时钟

    的高电平信号表示到了行有效区,最后再来56个时钟的高电平表示,行同步前沿。如此循环

    进行行扫描,。

    场同步长度为6个时钟脉宽长度,场后沿为23个时钟脉宽长度,场可视区为600个脉宽长度,

    场前沿为37个时钟脉宽长度。666行为一场。

    有些东西不管你多么熟悉,总感觉过上一段时间就给忘掉了,有倒是好记性不如烂笔头

    在这里做下记录。

    以下是自己写的一个VGA的控制接口,只要给RGB信号赋值就能显示不同的颜色,要怎样显示

    就看去怎样处理接口了。

    由于想从SDRAM中读出数据来画出曲线,一时也不知道该怎么去显示,因为VGA显示是从上往下

    一行一行的扫描,而数据要显示要用我们正常的坐标,便和同学聊了一下,他给提议,在每一行中

    都把数据扫描一次,这才有了下面的第二个段程序。和大家一起聊聊总会有所收获的。

    //---------------------------------------------------------------------
     //
     //-----------------------------------------------------------------------
     `define tend_h_syn   ( Clk_H_cnt == (11'd119) )//行同步计数脉冲个数
     `define tend_h_pre         ( Clk_H_cnt == (11'd1039) ) //行同步前沿计数脉冲个数
     `define tend_h_back   ( Clk_H_cnt == (11'd183) )//行同步后沿脉冲计数个数
     `define tend_h_visible   ( Clk_H_cnt == (11'd983) )//行可视区脉冲个数
     `define tend_v_syn   ( Clk_V_cnt == (11'd5) ) //场同步计数脉冲个数
     `define tend_v_pre    ( Clk_V_cnt == (11'd665) ) //场同步前沿计数脉冲个数
     `define tend_v_visible  ( Clk_V_cnt == (11'd628) )//场可视区脉冲个数
     `define tend_v_back   ( Clk_V_cnt == (11'd28) )//场同步后沿脉冲计数个数
     //----------------------------------------------------------------
     //行同步状态
     //-----------------------------------------------------------------
      `define H_SYN    2'd0//行同步
     `define H_PRE         2'd1 //行同步前沿
     `define H_BACK   2'd2 //行同步后沿
     `define H_VISIBLE   2'd3//行可视区
     //-----------------------------------------------------------------
     //场同步状态
     //-----------------------------------------------------------------
      `define V_SYN    2'd0 //场同步
     `define V_PRE    2'd1 //场同步
     `define V_VISIBLE   2'd2//场可视区
     `define V_BACK   2'd3 //场同步后沿
     
    module VGA_Ctrl(Clk,Rst_n,Hsync,Col_Ctrl,
       Vsync,Vga_r,Vga_g,Vga_b,H_Coord,
       V_Coord,Data_Valid
       );
    input Clk;//输入50M时钟
    input Rst_n;// reset signal
    input [7:0] Col_Ctrl;
    output [2:0] Vga_r;
    output [2:0] Vga_g;
    output [1:0] Vga_b;
    output Hsync;//行同步信号
    output Vsync;//场同步信号
    output [9:0] H_Coord;//行坐标
    output [9:0] V_Coord;//列坐标
    output Data_Valid;//有效显示区指示信号

    reg[1:0] H_State;
    reg[1:0] V_State;
    assign {Vga_r,Vga_g,Vga_b} = Data_Valid ? Col_Ctrl : 8'hzz;

    如果在无效区就不显示RGB就不发送数据。
    //****************************************************************
    //计数脉冲控制信号
    //*****************************************************************
    reg [10 : 0] Clk_H_cnt;
    reg [10 : 0] Clk_V_cnt;
    always@( posedge Clk or negedge Rst_n) //行扫描计数器
    if(!Rst_n) Clk_H_cnt <= 11'd0;
    else if(Clk_H_cnt == 11'd1039) Clk_H_cnt <= 11'd0;
    else Clk_H_cnt <= Clk_H_cnt + 1'b1;

    wire V_Clk = (Clk_H_cnt ==11'd1039);

    always@( posedge V_Clk or negedge Rst_n) //场扫描计数器
    if(!Rst_n)  Clk_V_cnt <= 11'd0;
    else if(Clk_V_cnt == 11'd665) Clk_V_cnt <= 11'd0;
    else  Clk_V_cnt <= Clk_V_cnt + 1'b1;

    //*****************************************************************
    //行扫描状态机
    //***************************************************************

    always@( posedge Clk or negedge Rst_n) begin
     if(!Rst_n) begin
       H_State <= `H_SYN;
       end
     else begin
      case( H_State )
       `H_SYN : begin   
         H_State <= `tend_h_syn ? `H_BACK:`H_SYN;
        end
       `H_BACK : begin     
         H_State <= `tend_h_back ? `H_VISIBLE : `H_BACK;
        end
       `H_VISIBLE : begin
         H_State <= `tend_h_visible ? `H_PRE : `H_VISIBLE;
        end
       `H_PRE : begin
         H_State <= `tend_h_pre ? `H_SYN : `H_PRE;
        end
       default :;
       endcase
       end
    end
    //*********************************************************************
    //场扫描状态机
    //************************************************************************
    always@( posedge V_Clk  or negedge Rst_n) begin
     if(!Rst_n) begin
      V_State <= `V_SYN;

      end
     else
      case(V_State)
        `V_SYN : begin
         V_State <= `tend_v_syn  ? `V_BACK: `V_SYN;
        end
        `V_BACK : begin
         V_State <= `tend_v_back ? `V_VISIBLE : `V_BACK;
        end
       `V_VISIBLE : begin
         V_State <= `tend_v_visible ? `V_PRE : `V_VISIBLE;
        end
       `V_PRE : begin
         V_State <= `tend_v_pre ? `V_SYN : `V_PRE;
        end
       default:;
      endcase

    end
    //******************************************************************
    //行场有效区计数扫描 接 口
    //*****************************************************************
    reg[9:0] H_Cnt;
    reg[9:0] V_Cnt;
    always@( posedge Clk or negedge Rst_n) begin
    if(!Rst_n) H_Cnt <= 10'd0;
    else if(H_Cnt == 10'd799) H_Cnt <= 10'd0;
    else  if(H_State == `H_VISIBLE)
     H_Cnt <= H_Cnt + 1'b1;
    else H_Cnt <= 10'd0;
     end
    always@( posedge V_Clk or negedge Rst_n) begin
    if(!Rst_n) V_Cnt <= 10'd0;
    else if( V_Cnt == 10'd599) V_Cnt <= 10'd0;
    else if( V_State == `V_VISIBLE)
     V_Cnt <= V_Cnt + 1'b1;
    else V_Cnt <= 10'd0;
     end
     reg [7:0]test_r;
    /*always@(posedge Clk or negedge Rst_n)
    begin
    if(!Rst_n) test_r <= 8'd0;
    else if((H_Cnt >= 20 && H_Cnt <= 100 ) &&(V_Cnt >= 20 && V_Cnt <= 100))
     test_r <= 8'hf0;
     else test_r <= 8'hzz;
    end*/
    assign Hsync = ~(H_State == `H_SYN);
    assign Vsync = ~(V_State == `V_SYN);
    assign H_Coord = H_Cnt;
    assign V_Coord = V_Cnt;
    assign Data_Valid = ((H_State == `H_VISIBLE) && (V_State == `V_VISIBLE));
    endmodule

    *************************************************************************

    以下为一个VGA的RGB产生一段程序

    *************************************************************************

    module VGA_Data(H_Coord,V_Coord,Clk,Rst_n,Col_Ctrl);

    input Clk;
    input Rst_n;
    input[9 : 0] H_Coord;//读出的行
    input[9 : 0] V_Coord;//读出的场
    output[7 : 0] Col_Ctrl;

    reg[7 : 0] Col_Ctrl_R;
    wire[9 : 0] X_Coord = (H_Coord - 200) ;//转换成相应的X坐标
    wire[9 : 0] Y_Coord = (500 - V_Coord) ;//转换成相应的Y坐标

    always@(posedge Clk ) begin
    if((X_Coord > 10'd0) && (X_Coord <= 10'd500) && Y_Coord == 10'd0 ||
     (Y_Coord >= 10'd0 && Y_Coord <= 10'd400 && X_Coord == 10'd0))
      Col_Ctrl_R <= 8'h00;
    else if(Y_Coord == Cnt && X_Coord >= 0 && X_Coord <=500)
     Col_Ctrl_R <= 8'h00;
    else Col_Ctrl_R <= 8'hff;

    end
    reg [7 : 0] Cnt;
    always@(posedge Clk or negedge Rst_n) begin
    if(!Rst_n) Cnt <= 8'd0;
    else if(X_Coord >= 0 && X_Coord <256)Cnt <= Cnt + 1'b1;
    else Cnt <= 8'd0;
    end
    assign Col_Ctrl = Col_Ctrl_R;
    endmodule

  • 相关阅读:
    Linux系统安装IonCube的方法详解教程
    CentOS7 安装 odoo10
    关于WPF的弹出窗口
    WPF命令使用
    WPF访问UserControl的自定义属性和事件
    一步步实现 Prism + MEF(二)--- 绑定命令
    一步步实现 Prism + MEF(一)--- 搭建框架
    MVVM里绑定TreeView控件的SelectedItem
    MAF框架的使用限制
    排序--归并排序算法
  • 原文地址:https://www.cnblogs.com/zhongguo135/p/2700379.html
Copyright © 2011-2022 走看看