问答 店铺
热搜: ZYNQ FPGA discuz

QQ登录

只需一步,快速开始

微信登录

微信扫码,快速开始

微信扫一扫 分享朋友圈

已有 156 人浏览分享

开启左侧

[MLKPAI-F01-EG4D]FPGA程序设计基础实验连载-22 TPG图像测试数据发生器设计

[复制链接]
156 0
安路-FPGA课程
安路课程: 基础入门 » 新手入门实验
安路系列: EG4
本帖最后由 UT发布 于 2025-4-19 09:55 编辑

软件版本:TD_5.6.4_Release_97693
操作系统:WIN11 64bit
硬件平台:适用安路(Anlogic)FPGA
登录米联客”FPGA社区-www.uisrc.com视频课程、答疑解惑!
1概述
TPG(video_test_pattern generator) 视频测试模式发生器用于产生测试数据,对视频数据通路测试。本课设计一个图像数据发生器,该模块能够产生不同颜色和样式的图像数据,并按顺序将RGB图像数据发送到有效显示区域。
1.1 RGB像素格式
    RGB是一种颜色标准,俗称三基色模式,是通过对红(R)、绿(G)、蓝(B)三个颜色通道的变化以及它们相互之间的叠加来得到各式各样的颜色的,是运用最广的颜色系统之一。像素点就相当于一个RGB灯,通过控制 RGB 这三种颜色的亮度就可以显示出各种各样的色彩。在显示器发明之后,从黑白显示器发展到彩色显示器,人们开始使用发出不同颜色的光的荧光粉(CRT,等离子体显示器),或者不同颜色的滤色片(LCD),或者不同颜色的半导体发光器件(OLEDLED大型全彩显示牌)来形成色彩,不管采用何种技术,都以红(R)、绿(G)、蓝(B)三个颜色作为基本的发光单元,通过控制光强度,组合出了人类视力所能感知的所有颜色。
image.jpg
常见RGB像素格式:
1、索引格式:

索引格式是比较老的格式,随着越来越高的视觉需求,索引格式基本不再被使用了,这里只做简单介绍。索引格式中bit存储的值并非是实际的RGB值,而是对应点的像素在调色板中的索引,即在图像文件中划出一个区域存放一个调色板来存储图像中的每一种颜色,这个像素的颜色对应到调色板的第几号颜色。

RGB1:每个像素用1bit表示,能够表示的索引范围是0-1,共2种颜色,即调色板中包含2中颜色。

RGB4:每个像素用4bit表示,能够表示的索引范围是0-15,共16种颜色,即调色板中包含16中颜色。

RGB8:每个像素用8bit表示,能够表示的索引范围是0-255,共256种颜色,即调色板中包含256中颜色。

2、像素格式:

RGB像素格式不同于索引格式,索引格式bit存储的是每一个像素的色彩索引,而像素格式中的bit用来存储像素点中RGB三个颜色的值。

RGB888:也叫RGB24,一个像素点由3个字节组成,共8bit*3=24bit。其中bit23~bit16RED 通道,红色对应的值就是 24hFF0000bit15~bit8 GREEN 通道,绿色对应的值就是 24h00FF00bit7~bit0 BLUE通道蓝色对应的值为 24h0000FF,使用RGB888格式,理论上可以产生1670万种色彩。RGB888像素格式如下图所示:

image.jpg

      RGB888 数据格式

RGB565:只需要两个字节,可以降低成本,RGB分量分别使用5bit6bit5bit,但在色彩鲜艳度上较差一些。

image.jpg

RGB1555:只需要两个字节,RGB分量都使用5bit1bit用于表示透明度(0完全透明,1完全不透明)。

image.jpg

我们可以通过电脑的“画图”工具,使用调色板即可获取到想要的颜色对应的数值。

image.jpg
2 程序设计
2.1系统框图

本次实验通过测试视频发生器模块,产生测试图形,即彩条、渐变、纯色、棋方格,将相应测试图形的RGB数据依次放入有效的显示区域内。实验包含3个模块, VTC视频时序控制器模块、TPG视频测试模式发生器模块、用户控制模块。以下给出系统框图,关于VTC视频时序控制器驱动的详细描述请看前面的实验,我们主要学习TPG视频测试模式发生器驱动

image.jpg
TPG视频测试模式发生器

视频数据的有效区域如下图所示:视频数据在H_AcitiveSizeV_AcitiveSize同时有效时候有效

image.jpg

I_tpg_ck:视频格式的像素时钟

I_tpg_vs:视频格式的场同步信号

I_tpg_hs:视频格式的行同步信号

I_tpg_de:视频格式的有效数据阶段


O_tpg_vs:同I_tpg_vs

O_tpg_hs:同I_tpg_hs

O_tpg_de:同I_tpg_de

O_tpg_data:rgb格式数据输出

image.jpg
计数器模块:

h_cnt计数器模块:I_tpg_de为高电平时,表示有效显示区域阶段,此时h_cnt列计数器开始计数,计数为H_ActiveSize的值。

v_cnt计数器模块:I_tpg_vs拉高表示一帧有效图像数据传输完成,v_cnt0,否则,I_tpg_hs拉高表示传输完一行有效数据,v_cnt1

  1. //h_cnt计数器模块
  2. always @(posedge I_tpg_clk)
  3.     h_cnt <= I_tpg_de ? h_cnt + 1'b1 : 12'd0; //计数行有效像素,当de无效,重置 h_cnt=0
  4. //v_cnt计数器模块
  5. always @(posedge I_tpg_clk)
  6.   if(I_tpg_vs) //通过vs产生同步复位
  7.     v_cnt <= 12'd0; //重置v_cnt=0
  8.   else
  9.     v_cnt <= ((!tpg_hs_r)&&I_tpg_hs) ? v_cnt + 1'b1 : v_cnt; //hs信号的上升沿,v_cnt计数,这种方式可以不管hs有效是高电平还是低电平的情况,v_cnt 视频垂直方向,行计数器,计数行数量
复制代码
测试图像产生模块:

使用状态机将我们要显示的所有样式的图形数据列举出来,通过不断累加的dis_mode,为了减慢显示变换图形样式的速度,取dis_mode高位值进行判断该显示何种图形。

黑白格:h_cnt[4]v_cnt[4]进行“异或”运算,即相同为0,不同为1,再进行条件判断,0显示全黑,1显示全白。

RGB彩条:使用列计数器h_cnt,将有效显示区域划分为9块,分别显示不同的RGB数据。

  1. //显示模式切换
  2. always @(posedge I_tpg_clk)
  3.    if(I_tpg_rstn==1'b0)
  4.     dis_mode <= 0;
  5.    else
  6.     dis_mode <= ((!tpg_vs_r)&&I_tpg_vs) ? dis_mode + 1'b1 : dis_mode;
  7. //grid_data发生器  
  8. always @(posedge I_tpg_clk)begin
  9.     grid_data <= ((v_cnt[4]==1'b1) ^ (h_cnt[4]==1'b1)) ? 8'h00 : 8'hff; //方格大小16*16,黑白交替
  10. end
  11. //RGB彩条发生器
  12. always @(posedge I_tpg_clk)
  13. begin
  14.     if(h_cnt==260)
  15.     color_bar   <=  24'hff0000;//红
  16.     else if(h_cnt==420)
  17.     color_bar   <=  24'h00ff00;//绿
  18.     else if(h_cnt==580)
  19.     color_bar   <=  24'h0000ff;//蓝
  20.     else if(h_cnt==740)
  21.     color_bar   <=  24'hff00ff;//紫
  22.     else if(h_cnt==900)
  23.     color_bar   <=  24'hffff00;//黄
  24.     else if(h_cnt==1060)
  25.     color_bar   <=  24'h00ffff;//青蓝
  26.     else if(h_cnt==1220)
  27.     color_bar   <=  24'hffffff;//白
  28.     else if(h_cnt==1380)
  29.     color_bar   <=  24'h000000;//黑
  30.     else
  31.     color_bar   <=  color_bar;
  32. end
  33. //测试图形输出
  34. always @(posedge I_tpg_clk)begin
  35.     case(dis_mode[10:7])//截取高位,控制切换显示速度
  36.         4'd0:begin
  37.             r_reg <= 0;
  38.             b_reg <= 0;
  39.             g_reg <= 0;
  40.         end
  41.         4'd1:begin
  42.             r_reg <= 8'b11111111;               //白
  43.             g_reg <= 8'b11111111;
  44.             b_reg <= 8'b11111111;
  45.         end
  46.         4'd2,4'd3:begin//连续两个状态输出相同图形
  47.             r_reg <= 8'b11111111;              //红
  48.             g_reg <= 0;
  49.             b_reg <= 0;  
  50.         end           
  51.         4'd4,4'd5:begin//连续两个状态输出相同图形
  52.             r_reg <= 0;                         //绿
  53.             g_reg <= 8'b11111111;
  54.             b_reg <= 0;
  55.         end                  
  56.         4'd6:begin     
  57.             r_reg <= 0;                         //蓝
  58.             g_reg <= 0;
  59.             b_reg <= 8'b11111111;
  60.         end
  61.         4'd7,4'd8:begin  //连续两个状态输出相同图形   
  62.             r_reg <= grid_data;                 //方格
  63.             g_reg <= grid_data;
  64.             b_reg <= grid_data;
  65.         end                  
  66.         4'd9:begin   
  67.             r_reg <= h_cnt[7:0];                //水平渐变
  68.             g_reg <= h_cnt[7:0];
  69.             b_reg <= h_cnt[7:0];
  70.         end
  71.         4'd10,4'd11:begin //连续两个状态输出相同图形
  72.             r_reg <= v_cnt[7:0];                 //垂直渐变
  73.             g_reg <= v_cnt[7:0];
  74.             b_reg <= v_cnt[7:0];
  75.         end
  76.         4'd12:begin     
  77.             r_reg <= v_cnt[7:0];                 //红垂直渐变
  78.             g_reg <= 0;
  79.             b_reg <= 0;
  80.         end
  81.         4'd13:begin     
  82.             r_reg <= 0;                          //绿垂直渐变
  83.             g_reg <= h_cnt[7:0];
  84.             b_reg <= 0;
  85.         end
  86.         4'd14:begin     
  87.             r_reg <= 0;                          //蓝垂直渐变
  88.             g_reg <= 0;
  89.             b_reg <= h_cnt[7:0];            
  90.         end
  91.         4'd15:begin     
  92.             r_reg <= color_bar[23:16];           //彩条
  93.             g_reg <= color_bar[15:8];
  94.             b_reg <= color_bar[7:0];            
  95.         end               
  96.         endcase
  97. end
复制代码
2.2 TPG源码
  1. module uitpg
  2. (
  3. input           I_tpg_clk, //系统时钟
  4. input           I_tpg_rstn,//系统复位
  5. input           I_tpg_vs,  //场同步输入
  6. input           I_tpg_hs,  //行同步输入
  7. input           I_tpg_de,  //视频数据有效输入   
  8. output          O_tpg_vs,  //场同步输出
  9. output          O_tpg_hs,  //行同步输出
  10. output          O_tpg_de,  //视频数据有效输出   
  11. output [23:0]   O_tpg_data //有效测试数据
  12. );
  13. reg         tpg_vs_r   = 1'b0; //对vs信号寄存
  14. reg         tpg_hs_r   = 1'b0; //对hs信号寄存
  15. reg [7 :0]  grid_data  = 8'd0; //grid棋方格寄存器
  16. reg [23:0]  color_bar  = 24'd0;//RGB 彩条寄存器
  17. reg [10:0]  dis_mode   = 11'd0;//显示模式寄存器
  18. reg [7 :0]  r_reg      = 8'd0; //红寄存器
  19. reg [7 :0]  g_reg      = 8'd0; //绿寄存器
  20. reg [7 :0]  b_reg      = 8'd0; //蓝寄存器
  21. always @(posedge I_tpg_clk)begin
  22.     tpg_vs_r <= I_tpg_vs; //对vs信号寄存一次
  23.     tpg_hs_r <= I_tpg_hs; //对hs信号寄存一次
  24. end
  25. reg [11:0]v_cnt = 12'd0; //视频垂直方向,行计数器
  26. reg [11:0]h_cnt = 12'd0; //视频水平方向,列计数器
  27. //h_cnt计数器模块
  28. always @(posedge I_tpg_clk)
  29.     h_cnt <= I_tpg_de ? h_cnt + 1'b1 : 12'd0; //计数行有效像素,当de无效,重置 h_cnt=0
  30. //v_cnt计数器模块
  31. always @(posedge I_tpg_clk)
  32.   if(I_tpg_vs) //通过vs产生同步复位
  33.     v_cnt <= 12'd0; //重置v_cnt=0
  34.   else
  35.     v_cnt <= ((!tpg_hs_r)&&I_tpg_hs) ? v_cnt + 1'b1 : v_cnt; //hs信号的上升沿,v_cnt计数,这种方式可以不管hs有效是高电平还是低电平的情况,v_cnt 视频垂直方向,行计数器,计数行数量
  36. //显示模式切换
  37. always @(posedge I_tpg_clk)
  38.    if(I_tpg_rstn==1'b0)
  39.     dis_mode <= 0;
  40.    else
  41.     dis_mode <= ((!tpg_vs_r)&&I_tpg_vs) ? dis_mode + 1'b1 : dis_mode;
  42. //grid_data发生器  
  43. always @(posedge I_tpg_clk)begin
  44.     grid_data <= ((v_cnt[4]==1'b1) ^ (h_cnt[4]==1'b1)) ? 8'h00 : 8'hff; //方格大小16*16,黑白交替
  45. end
  46. //RGB彩条发生器
  47. always @(posedge I_tpg_clk)
  48. begin
  49.     if(h_cnt==260)
  50.     color_bar   <=  24'hff0000;//红
  51.     else if(h_cnt==420)
  52.     color_bar   <=  24'h00ff00;//绿
  53.     else if(h_cnt==580)
  54.     color_bar   <=  24'h0000ff;//蓝
  55.     else if(h_cnt==740)
  56.     color_bar   <=  24'hff00ff;//紫
  57.     else if(h_cnt==900)
  58.     color_bar   <=  24'hffff00;//黄
  59.     else if(h_cnt==1060)
  60.     color_bar   <=  24'h00ffff;//青蓝
  61.     else if(h_cnt==1220)
  62.     color_bar   <=  24'hffffff;//白
  63.     else if(h_cnt==1380)
  64.     color_bar   <=  24'h000000;//黑
  65.     else
  66.     color_bar   <=  color_bar;
  67. end
  68. //测试图形输出
  69. always @(posedge I_tpg_clk)begin
  70.     case(dis_mode[10:7])//截取高位,控制切换显示速度
  71.         4'd0:begin
  72.             r_reg <= 0;
  73.             b_reg <= 0;
  74.             g_reg <= 0;
  75.         end
  76.         4'd1:begin
  77.             r_reg <= 8'b11111111;               //白
  78.             g_reg <= 8'b11111111;
  79.             b_reg <= 8'b11111111;
  80.         end
  81.         4'd2,4'd3:begin//连续两个状态输出相同图形
  82.             r_reg <= 8'b11111111;              //红
  83.             g_reg <= 0;
  84.             b_reg <= 0;  
  85.         end           
  86.         4'd4,4'd5:begin//连续两个状态输出相同图形
  87.             r_reg <= 0;                         //绿
  88.             g_reg <= 8'b11111111;
  89.             b_reg <= 0;
  90.         end                  
  91.         4'd6:begin     
  92.             r_reg <= 0;                         //蓝
  93.             g_reg <= 0;
  94.             b_reg <= 8'b11111111;
  95.         end
  96.         4'd7,4'd8:begin  //连续两个状态输出相同图形   
  97.             r_reg <= grid_data;                 //方格
  98.             g_reg <= grid_data;
  99.             b_reg <= grid_data;
  100.         end                  
  101.         4'd9:begin   
  102.             r_reg <= h_cnt[7:0];                //水平渐变
  103.             g_reg <= h_cnt[7:0];
  104.             b_reg <= h_cnt[7:0];
  105.         end
  106.         4'd10,4'd11:begin //连续两个状态输出相同图形
  107.             r_reg <= v_cnt[7:0];                 //垂直渐变
  108.             g_reg <= v_cnt[7:0];
  109.             b_reg <= v_cnt[7:0];
  110.         end
  111.         4'd12:begin     
  112.             r_reg <= v_cnt[7:0];                 //红垂直渐变
  113.             g_reg <= 0;
  114.             b_reg <= 0;
  115.         end
  116.         4'd13:begin     
  117.             r_reg <= 0;                          //绿垂直渐变
  118.             g_reg <= h_cnt[7:0];
  119.             b_reg <= 0;
  120.         end
  121.         4'd14:begin     
  122.             r_reg <= 0;                          //蓝垂直渐变
  123.             g_reg <= 0;
  124.             b_reg <= h_cnt[7:0];            
  125.         end
  126.         4'd15:begin     
  127.             r_reg <= color_bar[23:16];           //彩条
  128.             g_reg <= color_bar[15:8];
  129.             b_reg <= color_bar[7:0];            
  130.         end               
  131.         endcase
  132. end
  133. assign O_tpg_data = {r_reg,g_reg,b_reg};//测试图形RGB数据输出
  134. assign O_tpg_vs = I_tpg_vs;  //VS同步信号
  135. assign O_tpg_hs = I_tpg_hs;  //HS同步信号
  136. assign O_tpg_de = I_tpg_de;  //DE数据有效信号
  137. endmodule
复制代码
3 RTL仿真
3.1仿真激励文件
  1. `timescale 1ns / 1ns//仿真时间刻度/精度
  2. module video_test_tb;
  3. localparam SYS_TIME = 20;//系统时钟周期10ns
  4. reg I_vid_rstn,I_vid_clk;
  5. wire O_vid_vs,O_vid_hs,O_vid_de;
  6. wire [7:0]O_rgb_r,O_rgb_g,O_rgb_b;
  7. //例化video_test
  8. video_test video_test_inst
  9. (
  10. .I_vid_clk(I_vid_clk),
  11. .I_vid_rstn(I_vid_rstn),
  12. .O_vid_vs(O_vid_vs),
  13. .O_vid_hs(O_vid_hs),
  14. .O_vid_de(O_vid_de),
  15. .O_rgb_r(O_rgb_r),
  16. .O_rgb_g(O_rgb_g),
  17. .O_rgb_b(O_rgb_b)
  18. );
  19. //初始化
  20. initial begin
  21.     I_vid_clk  = 1'b0;
  22.     I_vid_rstn = 1'b0;
  23.     #100;//产生100ns的系统复位
  24.     I_vid_rstn = 1'b1;//复位完成
  25. end
  26. //产生仿真时钟
  27. always #(SYS_TIME/2) I_vid_clk= ~I_vid_clk;
  28. endmodule
  29. 为简化仿真,这里模拟的视频格式为320*5 即一行的有效数据为350个像素,一帧数据有5行像素数据。
  30. .H_ActiveSize(320),     //视频时间参数,行视频信号,一行有效(需要显示的部分)像素所占的时钟数,一个时钟对应一个有效像素,设置320个像素
  31. .H_FrameSize(320+88+44+239),//视频时间参数,行视频信号,一行视频信号总计占用的时钟数
  32. .H_SyncStart(320+88),       //视频时间参数,行同步开始,即多少时钟数后开始产生行同步信号
  33. .H_SyncEnd(320+88+44),      //视频时间参数,行同步结束,即多少时钟数后停止产生行同步信号,之后就是行数据有效数据部分
  34. .V_ActiveSize(5),           //视频时间参数,场视频信号,一帧图像所占用的有效(需要显示的部分)行数量,通常说的视频分辨率即H_ActiveSize*V_ActiveSize
  35. .V_FrameSize(5+4+5+28),     //视频时间参数,场视频信号,一帧视频信号总计占用的行数量
  36. .V_SyncStart(5+4),          //视频时间参数,场同步开始,即多少行数后开始产生场同步信号
  37. .V_SyncEnd (5+4+5)          //视频时间参数,场同步结束,即多少行数后停止产生场同步信号,之后就是场有效数据部分
复制代码
3.2仿真结果
image.jpg

































您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

0

关注

0

粉丝

293

主题
精彩推荐
热门资讯
网友晒图
图文推荐

  • 微信公众平台

  • 扫描访问手机版