这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » DIY与开源设计 » 电子DIY » 136.finema CPLD 进程帖(理解VGA时序)

共29条 3/3 1 2 3 跳转至
高工
2013-09-10 14:51:40     打赏
21楼
进程不错,弄个分类就更好了!

助工
2013-09-14 23:13:19     打赏
22楼

谢谢版主鼓励,迟点整理个目录。


助工
2013-09-14 23:26:06     打赏
23楼

2013.09.14

 

跟着版主视频学,完成第五份课后作业,代码如下。

 

注:版主视频中提到的 7段数码管代码查询工具,版主在群里共享了一份,我把它上传到了服务器上,链接为

 http://share.eepw.com.cn/share/download/id/90001

 

`timescale 1ns / 1ps
`define ONE_SECOND  26'd49999999 //50MHz时钟, 因此计数器要计数 50M次=50*1000*1000 就为1秒

//////////////////////////////////////////////////////////////////////////////////
//学号: 136.finema
//
//创建时间:    21:49:14 09/14/2013
//名称:dig_display_dip
//功能:数码管静态循环显示,用DIP控制哪个数码管亮
//算法:
//////////////////////////////////////////////////////////////////////////////////

module dig_display_dip(sys_clk,
       sys_rst,
       dip,
       dig_seg,
       dig_bit);
 input sys_clk;   //输入时钟信号
 input sys_rst;   //输入复位信号
 input [7:0] dip;  //输入DIP
 
 output [7:0] dig_seg;  //输出数码管段码
 output [7:0] dig_bit;  //输出数码管位码
 
 //变量定义 
 reg [7:0] dig_seg;
 wire [7:0] dig_bit;
 
 reg [25:0] timeCounter;  //时间计数器. 
 reg [7:0] charIndex;   //字符索引. 
 
 //计数器的逻辑处理
 always @(posedge sys_clk,negedge sys_rst) //只对时钟上升沿信号和复位下降沿信号敏感
 begin
  if (!sys_rst)
   timeCounter <=26'd0;   
  else
   begin
    if (timeCounter==`ONE_SECOND)
     timeCounter<=26'd0;
    else
     timeCounter<=timeCounter+1'b1;
   end
 end
 
 
 //led的逻辑处理
 always @(posedge sys_clk,negedge sys_rst)
 begin
  if (!sys_rst)
   begin   
    charIndex <=8'd0;
   end
  else
   begin
    if (timeCounter==`ONE_SECOND)
     begin                        
      charIndex <=charIndex+1'b1;            
     end
    else
     begin    
      charIndex <= charIndex;
      if (charIndex>8'd16)     
       charIndex <=8'd0;      
     end
       
   end
 end


 
 //数码管显示
 always @(charIndex)
 begin
  case (charIndex)
   8'd0: dig_seg<=8'hC0;  //0
   8'd1: dig_seg<=8'hF9;  //1
   8'd2: dig_seg<=8'hA4;  //2
   8'd3: dig_seg<=8'hB0;  //3
   8'd4: dig_seg<=8'h99;  //4
   8'd5: dig_seg<=8'h92;  //5
   8'd6: dig_seg<=8'h82;  //6
   8'd7: dig_seg<=8'hF8;  //7
   8'd8: dig_seg<=8'h80;  //8
   8'd9: dig_seg<=8'h90;  //9
   8'd10: dig_seg<=8'h88; //A
   8'd11: dig_seg<=8'h83; //B
   8'd12: dig_seg<=8'hC6; //C
   8'd13: dig_seg<=8'hA1; //D
   8'd14: dig_seg<=8'h86; //E
   8'd15: dig_seg<=8'h8E; //F
   8'd16: dig_seg<=8'h7F; //.
   default: dig_seg<=8'hC0;
  endcase
 end
 
 //连续赋值,8个数码管根据DIP导通
 assign dig_bit = dip; 
endmodule

 

我用到的tcl文件,内容如下:

 


助工
2013-09-14 23:27:15     打赏
24楼

关于 TCL 可以看网友284-xiacf88推荐的

http://www.cnblogs.com/yuphone/archive/2010/01/18/1650612.html

 

我用到的tcl文件,内容如下:


#CPLD 时钟脚
set_location_assignment PIN_12 -to sys_clk

#CPLD 复位脚
set_location_assignment PIN_14 -to sys_rst

#8个数码管
set_location_assignment PIN_82 -to dig_seg[0]
set_location_assignment PIN_86 -to dig_seg[1]
set_location_assignment PIN_76 -to dig_seg[2]
set_location_assignment PIN_84 -to dig_seg[3]
set_location_assignment PIN_91 -to dig_seg[4]
set_location_assignment PIN_90 -to dig_seg[5]
set_location_assignment PIN_88 -to dig_seg[6]
set_location_assignment PIN_81 -to dig_seg[7]

set_location_assignment PIN_77 -to dig_bit[0]
set_location_assignment PIN_78 -to dig_bit[1]
set_location_assignment PIN_83 -to dig_bit[2]
set_location_assignment PIN_85 -to dig_bit[3]
set_location_assignment PIN_87 -to dig_bit[4]
set_location_assignment PIN_89 -to dig_bit[5]
set_location_assignment PIN_92 -to dig_bit[6]
set_location_assignment PIN_95 -to dig_bit[7]

#DIP
set_location_assignment PIN_29 -to dip[0]
set_location_assignment PIN_30 -to dip[1]
set_location_assignment PIN_33 -to dip[2]
set_location_assignment PIN_34 -to dip[3]
set_location_assignment PIN_35 -to dip[4]
set_location_assignment PIN_36 -to dip[5]
set_location_assignment PIN_37 -to dip[6]
set_location_assignment PIN_38 -to dip[7]

 


助工
2013-09-15 23:35:35     打赏
25楼

2013.09.15

 

跟着版主视频学习,完成第六份课后作业——数码管动态显示。

 

代码如下:

 

`timescale 1ns / 1ps

//////////////////////////////////////////////////////////////////////////////////
//学号: 136.finema
//
//创建时间:    17:35:14 09/15/2013
//名称:dig_scan
//功能:8个数码码管动态显示方式显示0~7,刷新率1ms
//算法:
//////////////////////////////////////////////////////////////////////////////////


module dig_scan(sys_clk,
       sys_rst,
       dig_seg,
       dig_bit);
 
 input sys_clk;   //输入时钟信号
 input sys_rst;   //输入复位信号

 output [7:0] dig_seg;  //输出数码管段码
 output [7:0] dig_bit;  //输出数码管位码

 parameter TIME_INIT_VALUE = 26'd0;  //常量: 时间计数器初始值 
 parameter ONE_SECOND = 26'd4999_9999; //50MHz时钟, 因此计数器要计数 50M次=50*1000*1000 就为1秒
 parameter ONE_MILLI_SECOND = 16'd49999; //50MHz时钟, 1毫秒

 //变量定义 
 reg [7:0] dig_seg;
 reg [7:0] dig_bit;
 
 reg [25:0] timeCounter;  //时间计数器. 
 reg [2:0] charIndex;   //字符索引.  8个字符
 
 //计数器的逻辑处理
 always @(posedge sys_clk,negedge sys_rst) //只对时钟上升沿信号和复位下降沿信号敏感
 begin
  if (!sys_rst)
   timeCounter <= TIME_INIT_VALUE;   
  else
   begin
    if (timeCounter==ONE_MILLI_SECOND)
     timeCounter<=TIME_INIT_VALUE;
    else
     timeCounter<=timeCounter+1'b1;
   end
 end
 
 
 //led的逻辑处理
 always @(posedge sys_clk,negedge sys_rst)
 begin
  if (!sys_rst)
   begin   
    charIndex <=3'd0;
    dig_bit = 8'b1111_1110;
   end
  else
   begin
    if (timeCounter==ONE_MILLI_SECOND)
     begin                        
      charIndex <=charIndex+1'b1; 
      dig_bit = {dig_bit[6:0],dig_bit[7]}; //位选左移
     end        
   end
 end

 
 //数码管译码
 always @(charIndex)
 begin
  case (charIndex)
   3'd0: dig_seg<=8'hC0;  //0
   3'd1: dig_seg<=8'hF9;  //1
   3'd2: dig_seg<=8'hA4;  //2
   3'd3: dig_seg<=8'hB0;  //3
   3'd4: dig_seg<=8'h99;  //4
   3'd5: dig_seg<=8'h92;  //5
   3'd6: dig_seg<=8'h82;  //6
   3'd7: dig_seg<=8'hF8;  //7
   default: dig_seg<=8'hC0; //0
  endcase
 end
 
endmodule

 

 


助工
2013-09-15 23:36:27     打赏
26楼
暂住。

助工
2014-04-13 13:18:00     打赏
27楼
 

理解VGA时序

2014/4/12

(学号:136-finema

1.   前言

最近一段时间,看见EEPW-CPLD群里的很多网友和我一样在弄CPLD VGA实验,和很多人一样,我一开始也是搞不掂,后来经过咨询51FPGA版主、查看网上的资料、多次仿真才弄清楚了VGA是怎么回事。撰写本文,主要是为了自己理清所学内容,希望也能对大家有帮助。

在此先感谢51FPGAEEPW,谢谢他们把我这菜鸟带进了 CPLD-FPGA这多姿多彩的世界。

2.   背景知识

本文以学习生成 640*480@60Hz VGA信号为目标,要继续阅读,首先你要对老式VGA显示器是如何显示东西的,以及对VGA的场、行周期、刷新率等概念搞清楚,不清楚去查BaiduGoogle

也可看:http://www.cnblogs.com/spartan/archive/2011/08/16/2140546.html

(我的理解就是:1 = 1帧; 1 480行,每1行有640列;完成一行扫描需要的时间就是行周期;刷新率就是 1秒中刷新了多少帧。)

3.   时序总览

相信你看了资料,也会理解不透彻,特别是时序部分,关键是动起手来。

废话少说了,先看一下ModelSim仿真的时序图(见图1),比你看资料中的手工画的时序图直观多了。

图1-总览

1

       1中红线部分就是“场信号(vsync), 蓝线部分就是“行信号(hsync)”也叫“水平信号”。

       图中我们可以数出有3段“场信号(vsync)”即3帧。

4.   场信号时序(vsync)

那么场信号时序包含了什么呢,我们看一下VGA定的标准。

http://tinyvga.com/vga-timing/640x480@60Hz

       整理得到640*480@60Hz的场信号定义,见表1

同步脉冲

后沿

显示脉冲

(即可见部分)

前沿

合计

单位

2

33

480

10

525

行周期

1

       从表1我们得知“场信号”的同步脉冲有2个行周期长(注意:这里指的是行周期,而不是时钟周期),好了我们放大一下图1,可以清楚的验证这一点。见图2

图2-场信号

2

也就是说2个行周期后,1帧的场同步信号就结束了,再经过 33+480+10=523个行周期后,下1帧的场同步信号才会来。

5.   行信号时序(hsync)

那么1行的周期到底有多长呢,行信号的时序又包含那些东西呢?我们还是看VGA的标准。见http://tinyvga.com/vga-timing/640x480@60Hz

整理得到640*480@60Hz的行信号定义,见表2

同步脉冲

后沿

显示脉冲

(即可见部分)

前沿

合计

单位

96

48

640

16

800

时钟周期

2

我们把图1的“行信号(hsync)”波形放大,见图3,可看到“hcount=96,即“行信号”的同步脉冲有96个时钟周期,与表2的描述相符。

图3-行信号

3

6.   可见部分

可见部分(即显示脉冲)是什么,我们把表1和表2的数据合并得到表3

同步脉冲

后沿

显示脉冲

(即可见部分)

前沿

合计

单位

场信号

2

33

480

10

525

行周期

行信号

96

48

640

16

800

时钟周期

3

       所谓可见部分,就是每1帧中,场信号的计数“hcount”在35515之间(区间长度为480)并且行信号的计数“vcount”在144784之间(区间长度为640),RGB的值才有效,其它范围VGA显示器不会显示RGB的值。

       那么不在范围内的计数器的值有什么作用呢,老式VGA显示器就是靠他们来进行消隐的,对于液晶显示器,我想没什么可用之地。

7.   时钟

那么我们要生成 640*480@60Hz VGA信号,需要多快的时钟才能起作用呢,我们来算一下:

525*800*60Hz=25200000Hz=25.2MHz25MHz

更精确点的计算:

       525*800*60Hz *1000/1001=25174825.174825174825174825174825Hz25MHz

也就是说至少需要25MHz的时钟,我们才能正确生成640*480@60Hz VGA信号。(我们会看到一些接了50MHz 晶振的CPLD,其HDL代码就有分频处理。)

那么显示1帧需要多长时间呢?精确点的计算就是:

       525*800/25.17416683微妙

8.   源代码 8.1. Verilog代码

代码源于网络,自身修改了一下,以便于仿真,参照前面所说,自己琢磨代码。

//VGA 640*480@60Hz彩色信号显示

module VGA2(

       sys_rst,

   clock,

   switch,

   disp_RGB,

   hsync,

   vsync

);

input  sys_rst;     //复位信号

input  clock;     //系统输入时钟 50MHz

input  [1:0]switch;

output [2:0]disp_RGB;    //VGA数据输出

output  hsync;     //VGA行同步信号

output  vsync;     //VGA场同步信号

reg [9:0] hcount;     //VGA行扫描计数器

reg [9:0]   vcount;     //VGA场扫描计数器

reg [2:0]   data;

reg [2:0]  h_dat;

reg [2:0]   v_dat;

//reg [9:0]   timer;

//reg   flag;

wire  hcount_ov;

wire  vcount_ov;

wire  dat_act;

wire  hsync;

wire   vsync;

reg  vga_clk; //VGA时钟

//VGA行、场扫描时序参数表

parameter hsync_end   = 10'd95,

   hdat_begin  = 10'd143,

   hdat_end  = 10'd783,

   hpixel_end  = 10'd799,

   vsync_end  = 10'd1,

   vdat_begin  = 10'd34,

   vdat_end  = 10'd514,

   vline_end  = 10'd524;

      

//always @(posedge clock)

//begin

// vga_clk = ~vga_clk;

// //vga_clk <= ~vga_clk;

//end

always @(posedge clock,negedge sys_rst)

begin

       if (!sys_rst)

              begin

                     vga_clk = 0;  

              end

       else

              begin

                     vga_clk = ~vga_clk;             //50MHz 分频成 25MHz

               //vga_clk <= ~vga_clk;

              end 

end

//************************VGA驱动部分*******************************

//行扫描    

//always @(posedge clock,negedge sys_rst)

//begin

//     if (!sys_rst)

//            begin

//                   hcount <= 10'd0;          

//            end

//     else

//            begin

//                   if (hcount_ov)

//                          hcount <= 10'd0;

//                   else

//                          hcount <= hcount + 10'd1;      

//       end

//end

always @(posedge vga_clk,negedge sys_rst)

begin

       if (!sys_rst)

              begin

                     hcount <= 10'd0;   

              end

       else

              begin

                     if (hcount_ov)

                            hcount <= 10'd0;

                     else

                            hcount <= hcount + 10'd1;      

              end

end

assign hcount_ov = (hcount == hpixel_end);

//场扫描

//always @(posedge clock,negedge sys_rst)

//begin

//     if (!sys_rst)

//            begin

//                   vcount <= 10'd0;          

//            end

//     else

//            begin

//                   if (hcount_ov)

//                   begin

//                          if (vcount_ov)

//                                 vcount <= 10'd0;

//                          else

//                                 vcount <= vcount + 10'd1;

//                   end

//            end

//end

always @(posedge vga_clk,negedge sys_rst)

begin

       if (!sys_rst)

              begin

                     vcount <= 10'd0;          

              end

       else

              begin

                     if (hcount_ov)

                     begin

                            if (vcount_ov)

                                   vcount <= 10'd0;

                            else

                                   vcount <= vcount + 10'd1;

                     end

              end

end

assign  vcount_ov = (vcount == vline_end);

//数据、同步信号输

assign dat_act =    ((hcount >= hdat_begin) && (hcount < hdat_end))

     && ((vcount >= vdat_begin) && (vcount < vdat_end));

assign hsync = (hcount > hsync_end);

assign vsync = (vcount > vsync_end);

assign disp_RGB = (dat_act) ?  data : 3'h00;       

//************************显示数据处理部分*******************************

//图片显示延时计数器

/*always @(posedge vga_clk)

begin

 flag <= vcount_ov;

 if(vcount_ov && ~flag)

  timer <= timer + 1'b1;

end

*/

always @(posedge vga_clk)

begin

 case(switch[1:0])

  2'd0: data <= h_dat;      //选择横彩条

  2'd1: data <= v_dat;      //选择竖彩条

  2'd2: data <= (v_dat ^ h_dat); //产生棋盘格

  2'd3: data <= (v_dat ~^ h_dat); //产生棋盘格

 endcase

end

always @(posedge vga_clk)  //产生竖彩条

begin

 if(hcount < 223)

  v_dat <= 3'h7;      //  

 else if(hcount < 303)

  v_dat <= 3'h6;   //

 else if(hcount < 383)

  v_dat <= 3'h5;   //

 else if(hcount < 463)

  v_dat <= 3'h4;    //绿

 else if(hcount < 543)

  v_dat <= 3'h3;   //

 else if(hcount < 623)

  v_dat <= 3'h2;   //

 else if(hcount < 703)

  v_dat <= 3'h1;   //

 else

  v_dat <= 3'h0;   //

end

always @(posedge vga_clk)  //产生横彩条

begin

 if(vcount < 94)

  h_dat <= 3'h7;        //

 else if(vcount < 154)

  h_dat <= 3'h6;   //

 else if(vcount < 214)

  h_dat <= 3'h5;   //

 else if(vcount < 274)

  h_dat <= 3'h4;    //绿

 else if(vcount < 334)

  h_dat <= 3'h3;   //

 else if(vcount < 394)

  h_dat <= 3'h2;   //

 else if(vcount < 454)

  h_dat <= 3'h1;   //

 else

  h_dat <= 3'h0;   //

end

endmodule

8.2. ModelSim测试激励代码

`timescale 1 ns/ 1 ps

module VGA2_test();

// constants                                          

// general purpose registers

// test vector input registers

reg clock;

reg sys_rst;

reg [1:0] switch;

// wires                                              

wire [2:0]  disp_RGB;

wire hsync;

wire vsync;

//时钟 50MHz

initial                                               

begin                                                 

       clock = 0;

       forever #10 clock = ~clock;

end            

   

//复位信号   

initial                                                

begin                                                 

       sys_rst = 1;

       # 10 sys_rst = 0;

       # 50 sys_rst = 1;

end 

initial                                               

begin                                                 

       switch[1:0] = 2'd1; 

end

 

// assign statements (if any)                         

VGA2 VGA2_inst (

       .sys_rst(sys_rst), 

       .clock(clock),

       .disp_RGB(disp_RGB),

       .hsync(hsync),

       .switch(switch),

       .vsync(vsync)

);

      

                                                 

endmodule

8.3. TCL脚本文件

注意:本文件内容只适用于 EEPW-CPLD-DIY活动的板子。如果用于其它板子,请自己修改相关内容。

#CPLD 时钟脚

set_location_assignment PIN_12 -to clock

#CPLD 复位脚

set_location_assignment PIN_14 -to sys_rst

#行同步信号

set_location_assignment PIN_1 -to hsync

#场同步信号

set_location_assignment PIN_2 -to vsync

#RGB

set_location_assignment PIN_8 -to disp_RGB[0]

set_location_assignment PIN_5 -to disp_RGB[1]

set_location_assignment PIN_4 -to disp_RGB[2]

#拨码开关控制显示效果

set_location_assignment PIN_29 -to switch[0]

set_location_assignment PIN_30 -to switch[1]

9.   显示效果

9.1. 横条 横条

9.2. 竖条 竖条

9.3. 方格 方格

10.          参考资料

http://bbs.****.com/BLOG_ARTICLE_219303.HTM

http://www.epanorama.net/documents/pc/vga_timing.html

http://tinyvga.com/vga-timing/640x480@60Hz

http://share.eepw.com.cn/share/download/id/165148


助工
2014-04-13 13:21:59     打赏
28楼

27楼的内容,已经整理成word文档,上传到服务器。

http://share.eepw.com.cn/share/download/id/165361

 

51-FPGA 版主提供 640*480@60Hz的例程,可以从以下链接下载。

http://share.eepw.com.cn/share/download/id/165148

 


助工
2014-04-13 13:22:19     打赏
29楼
暂住

共29条 3/3 1 2 3 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]