飞道的博客

fpga实操训练(vga测试)

380人阅读  评论(0)

【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing @163.com】

        我自己读书那会,买的电脑还是以台式机居多,平板显示器也是才刚刚流行、且价格较高,视频接口也是以VGA为主。不像现在,基本上视频接口都是以HDMI为主。和HDMI相比较,VGA简单、方便,十分合适用来学习应用。

1、VGA接口

         开发板上的VGA部分,接口还是非常简单的。虽然接口有15个,但是其中5个是悬空(NC),5个是接地,真正有用的信号其实只有5个。这5个信号分别是红、绿、蓝、行同步、场同步。

2、FPGA和VGA的连接

         FPGA和VGA直接的接口还需要通过上面这一层电路转换,才能输出红、绿、蓝。其中红色有5位,绿色有6位,蓝色有5位,所以可以表现的颜色总共有16位,也就是65536种颜色。0也是一种颜色。

3、VGA的视频时序

        VGA视频时序,是我们编写verilog代码的关键。比如说一个1024*768分辨率、60帧每秒的视频流来说,真正VGA处理过的数据是1344*806,这其中还包括了(HSYNC、HBP、HFP,VSYNC、VBP、VFP),这些都是不显示的,所以显示的只是中间一部分内容。整个带宽的话,如果按照1344*806*60来算,大约是65M左右。所以,在fpga实现的过程当中,需要对原来的50M时钟进行倍频处理。

       另外需要注意的是,HBP处于前侧,而HFP是处于后侧。同样,VBP处于上方,而VFP处于下方的位置。但是编写verilog的时候,需要从HFP、VFP开始算起,这是比较容易引起疑问的一个地方。

4、准备PLL倍频

        倍频之前讨论过。这里只有几个地方需要注意下即可。1)输入时钟为50M,

         2)取消复位和lock锁定,

         3)只生成一个65M的输出时钟,

5、有了基础的pll,下面可以构建top层代码


  
  1. module vga_test(
  2. input clk,
  3. input rst_n,
  4. //vga output
  5. output vga_out_hs, //vga horizontal synchronization
  6. output vga_out_vs, //vga vertical synchronization
  7. output[ 4: 0] vga_out_r, //vga red
  8. output[ 5: 0] vga_out_g, //vga green
  9. output[ 4: 0] vga_out_b //vga blue
  10. );
  11. wire video_clk;
  12. wire video_hs;
  13. wire video_vs;
  14. wire video_de;
  15. wire[ 7: 0] video_r;
  16. wire[ 7: 0] video_g;
  17. wire[ 7: 0] video_b;
  18. assign vga_out_hs = video_hs;
  19. assign vga_out_vs = video_vs;
  20. assign vga_out_r = video_r[ 7: 3]; //discard low bit data
  21. assign vga_out_g = video_g[ 7: 2]; //discard low bit data
  22. assign vga_out_b = video_b[ 7: 3]; //discard low bit data
  23. //generate video pixel clock
  24. video_pll video_pll_m0(
  25. .inclk0(clk),
  26. .c0(video_clk));
  27. color_bar color_bar_m0(
  28. .clk(video_clk),
  29. .rst(~rst_n),
  30. .hs(video_hs),
  31. .vs(video_vs),
  32. .de(video_de),
  33. .rgb_r(video_r),
  34. .rgb_g(video_g),
  35. .rgb_b(video_b)
  36. );
  37. endmodule

        top层代码比较简单,这里主要就是实例化video_pll和color_bar两个模块。video_pll刚才已经生成,下面就只需要谈谈color_bar。

6、关于color_bar.v代码


  
  1. `include "video_define.v"
  2. module color_bar(
  3. input clk, //pixel clock
  4. input rst, //reset signal high active
  5. output hs, //horizontal synchronization
  6. output vs, //vertical synchronization
  7. output de, //video valid
  8. output[ 7: 0] rgb_r, //video red data
  9. output[ 7: 0] rgb_g, //video green data
  10. output[ 7: 0] rgb_b //video blue data
  11. );
  12. //video timing parameter definition
  13. `ifdef VIDEO_1280_720
  14. parameter H_ACTIVE = 16 'd1280; //horizontal active time (pixels)
  15. parameter H_FP = 16 'd110; //horizontal front porch (pixels)
  16. parameter H_SYNC = 16 'd40; //horizontal sync time(pixels)
  17. parameter H_BP = 16 'd220; //horizontal back porch (pixels)
  18. parameter V_ACTIVE = 16 'd720; //vertical active Time (lines)
  19. parameter V_FP = 16 'd5; //vertical front porch (lines)
  20. parameter V_SYNC = 16 'd5; //vertical sync time (lines)
  21. parameter V_BP = 16 'd20; //vertical back porch (lines)
  22. parameter HS_POL = 1 'b1; //horizontal sync polarity, 1 : POSITIVE,0 : NEGATIVE;
  23. parameter VS_POL = 1 'b1; //vertical sync polarity, 1 : POSITIVE,0 : NEGATIVE;
  24. `endif
  25. //480x272 9Mhz
  26. `ifdef VIDEO_480_272
  27. parameter H_ACTIVE = 16 'd480;
  28. parameter H_FP = 16 'd2;
  29. parameter H_SYNC = 16 'd41;
  30. parameter H_BP = 16 'd2;
  31. parameter V_ACTIVE = 16 'd272;
  32. parameter V_FP = 16 'd2;
  33. parameter V_SYNC = 16 'd10;
  34. parameter V_BP = 16 'd2;
  35. parameter HS_POL = 1 'b0;
  36. parameter VS_POL = 1 'b0;
  37. `endif
  38. //640x480 25.175Mhz
  39. `ifdef VIDEO_640_480
  40. parameter H_ACTIVE = 16 'd640;
  41. parameter H_FP = 16 'd16;
  42. parameter H_SYNC = 16 'd96;
  43. parameter H_BP = 16 'd48;
  44. parameter V_ACTIVE = 16 'd480;
  45. parameter V_FP = 16 'd10;
  46. parameter V_SYNC = 16 'd2;
  47. parameter V_BP = 16 'd33;
  48. parameter HS_POL = 1 'b0;
  49. parameter VS_POL = 1 'b0;
  50. `endif
  51. //800x480 33Mhz
  52. `ifdef VIDEO_800_480
  53. parameter H_ACTIVE = 16 'd800;
  54. parameter H_FP = 16 'd40;
  55. parameter H_SYNC = 16 'd128;
  56. parameter H_BP = 16 'd88;
  57. parameter V_ACTIVE = 16 'd480;
  58. parameter V_FP = 16 'd1;
  59. parameter V_SYNC = 16 'd3;
  60. parameter V_BP = 16 'd21;
  61. parameter HS_POL = 1 'b0;
  62. parameter VS_POL = 1 'b0;
  63. `endif
  64. //800x600 40Mhz
  65. `ifdef VIDEO_800_600
  66. parameter H_ACTIVE = 16 'd800;
  67. parameter H_FP = 16 'd40;
  68. parameter H_SYNC = 16 'd128;
  69. parameter H_BP = 16 'd88;
  70. parameter V_ACTIVE = 16 'd600;
  71. parameter V_FP = 16 'd1;
  72. parameter V_SYNC = 16 'd4;
  73. parameter V_BP = 16 'd23;
  74. parameter HS_POL = 1 'b1;
  75. parameter VS_POL = 1 'b1;
  76. `endif
  77. //1024x768 65Mhz
  78. `ifdef VIDEO_1024_768
  79. parameter H_ACTIVE = 16 'd1024;
  80. parameter H_FP = 16 'd24;
  81. parameter H_SYNC = 16 'd136;
  82. parameter H_BP = 16 'd160;
  83. parameter V_ACTIVE = 16 'd768;
  84. parameter V_FP = 16 'd3;
  85. parameter V_SYNC = 16 'd6;
  86. parameter V_BP = 16 'd29;
  87. parameter HS_POL = 1 'b0;
  88. parameter VS_POL = 1 'b0;
  89. `endif
  90. //1920x1080 148.5Mhz
  91. `ifdef VIDEO_1920_1080
  92. parameter H_ACTIVE = 16 'd1920;
  93. parameter H_FP = 16 'd88;
  94. parameter H_SYNC = 16 'd44;
  95. parameter H_BP = 16 'd148;
  96. parameter V_ACTIVE = 16 'd1080;
  97. parameter V_FP = 16 'd4;
  98. parameter V_SYNC = 16 'd5;
  99. parameter V_BP = 16 'd36;
  100. parameter HS_POL = 1 'b1;
  101. parameter VS_POL = 1 'b1;
  102. `endif
  103. parameter H_TOTAL = H_ACTIVE + H_FP + H_SYNC + H_BP; //horizontal total time (pixels)
  104. parameter V_TOTAL = V_ACTIVE + V_FP + V_SYNC + V_BP; //vertical total time (lines)
  105. //define the RGB values for 8 colors
  106. parameter WHITE_R = 8 'hff;
  107. parameter WHITE_G = 8 'hff;
  108. parameter WHITE_B = 8 'hff;
  109. parameter YELLOW_R = 8 'hff;
  110. parameter YELLOW_G = 8 'hff;
  111. parameter YELLOW_B = 8 'h00;
  112. parameter CYAN_R = 8 'h00;
  113. parameter CYAN_G = 8 'hff;
  114. parameter CYAN_B = 8 'hff;
  115. parameter GREEN_R = 8 'h00;
  116. parameter GREEN_G = 8 'hff;
  117. parameter GREEN_B = 8 'h00;
  118. parameter MAGENTA_R = 8 'hff;
  119. parameter MAGENTA_G = 8 'h00;
  120. parameter MAGENTA_B = 8 'hff;
  121. parameter RED_R = 8 'hff;
  122. parameter RED_G = 8 'h00;
  123. parameter RED_B = 8 'h00;
  124. parameter BLUE_R = 8 'h00;
  125. parameter BLUE_G = 8 'h00;
  126. parameter BLUE_B = 8 'hff;
  127. parameter BLACK_R = 8 'h00;
  128. parameter BLACK_G = 8 'h00;
  129. parameter BLACK_B = 8 'h00;
  130. reg hs_reg; //horizontal sync register
  131. reg vs_reg; //vertical sync register
  132. reg hs_reg_d0; //delay 1 clock of 'hs_reg'
  133. reg vs_reg_d0; //delay 1 clock of 'vs_reg'
  134. reg[ 11: 0] h_cnt; //horizontal counter
  135. reg[ 11: 0] v_cnt; //vertical counter
  136. reg[ 11: 0] active_x; //video x position
  137. reg[ 11: 0] active_y; //video y position
  138. reg[ 7: 0] rgb_r_reg; //video red data register
  139. reg[ 7: 0] rgb_g_reg; //video green data register
  140. reg[ 7: 0] rgb_b_reg; //video blue data register
  141. reg h_active; //horizontal video active
  142. reg v_active; //vertical video active
  143. wire video_active; //video active(horizontal active and vertical active)
  144. reg video_active_d0; //delay 1 clock of video_active
  145. assign hs = hs_reg_d0;
  146. assign vs = vs_reg_d0;
  147. assign video_active = h_active & v_active;
  148. assign de = video_active_d0;
  149. assign rgb_r = rgb_r_reg;
  150. assign rgb_g = rgb_g_reg;
  151. assign rgb_b = rgb_b_reg;
  152. always@(posedge clk or posedge rst)
  153. begin
  154. if(rst == 1 'b1)
  155. begin
  156. hs_reg_d0 <= 1 'b0;
  157. vs_reg_d0 <= 1 'b0;
  158. video_active_d0 <= 1 'b0;
  159. end
  160. else
  161. begin
  162. hs_reg_d0 <= hs_reg;
  163. vs_reg_d0 <= vs_reg;
  164. video_active_d0 <= video_active;
  165. end
  166. end
  167. always@(posedge clk or posedge rst)
  168. begin
  169. if(rst == 1 'b1)
  170. h_cnt <= 12 'd0;
  171. else if(h_cnt == H_TOTAL - 1) //horizontal counter maximum value
  172. h_cnt <= 12 'd0;
  173. else
  174. h_cnt <= h_cnt + 12 'd1;
  175. end
  176. always@(posedge clk or posedge rst)
  177. begin
  178. if(rst == 1 'b1)
  179. active_x <= 12 'd0;
  180. else if(h_cnt >= H_FP + H_SYNC + H_BP - 1) //horizontal video active
  181. active_x <= h_cnt - (H_FP[ 11: 0] + H_SYNC[ 11: 0] + H_BP[ 11: 0] - 12 'd1);
  182. else
  183. active_x <= active_x;
  184. end
  185. always@(posedge clk or posedge rst)
  186. begin
  187. if(rst == 1 'b1)
  188. v_cnt <= 12 'd0;
  189. else if(h_cnt == H_FP - 1) //horizontal sync time
  190. if(v_cnt == V_TOTAL - 1) //vertical counter maximum value
  191. v_cnt <= 12 'd0;
  192. else
  193. v_cnt <= v_cnt + 12 'd1;
  194. else
  195. v_cnt <= v_cnt;
  196. end
  197. always@(posedge clk or posedge rst)
  198. begin
  199. if(rst == 1 'b1)
  200. hs_reg <= 1 'b0;
  201. else if(h_cnt == H_FP - 1) //horizontal sync begin
  202. hs_reg <= HS_POL;
  203. else if(h_cnt == H_FP + H_SYNC - 1) //horizontal sync end
  204. hs_reg <= ~hs_reg;
  205. else
  206. hs_reg <= hs_reg;
  207. end
  208. always@(posedge clk or posedge rst)
  209. begin
  210. if(rst == 1 'b1)
  211. h_active <= 1 'b0;
  212. else if(h_cnt == H_FP + H_SYNC + H_BP - 1) //horizontal active begin
  213. h_active <= 1 'b1;
  214. else if(h_cnt == H_TOTAL - 1) //horizontal active end
  215. h_active <= 1 'b0;
  216. else
  217. h_active <= h_active;
  218. end
  219. always@(posedge clk or posedge rst)
  220. begin
  221. if(rst == 1 'b1)
  222. vs_reg <= 1 'd0;
  223. else if((v_cnt == V_FP - 1) && (h_cnt == H_FP - 1)) //vertical sync begin
  224. vs_reg <= HS_POL;
  225. else if((v_cnt == V_FP + V_SYNC - 1) && (h_cnt == H_FP - 1)) //vertical sync end
  226. vs_reg <= ~vs_reg;
  227. else
  228. vs_reg <= vs_reg;
  229. end
  230. always@(posedge clk or posedge rst)
  231. begin
  232. if(rst == 1 'b1)
  233. v_active <= 1 'd0;
  234. else if((v_cnt == V_FP + V_SYNC + V_BP - 1) && (h_cnt == H_FP - 1)) //vertical active begin
  235. v_active <= 1 'b1;
  236. else if((v_cnt == V_TOTAL - 1) && (h_cnt == H_FP - 1)) //vertical active end
  237. v_active <= 1 'b0;
  238. else
  239. v_active <= v_active;
  240. end
  241. always@(posedge clk or posedge rst)
  242. begin
  243. if(rst == 1 'b1)
  244. begin
  245. rgb_r_reg <= 8 'h00;
  246. rgb_g_reg <= 8 'h00;
  247. rgb_b_reg <= 8 'h00;
  248. end
  249. else if(video_active)
  250. if(active_x == 12 'd0)
  251. begin
  252. rgb_r_reg <= WHITE_R;
  253. rgb_g_reg <= WHITE_G;
  254. rgb_b_reg <= WHITE_B;
  255. end
  256. else if(active_x == (H_ACTIVE/ 8) * 1)
  257. begin
  258. rgb_r_reg <= YELLOW_R;
  259. rgb_g_reg <= YELLOW_G;
  260. rgb_b_reg <= YELLOW_B;
  261. end
  262. else if(active_x == (H_ACTIVE/ 8) * 2)
  263. begin
  264. rgb_r_reg <= CYAN_R;
  265. rgb_g_reg <= CYAN_G;
  266. rgb_b_reg <= CYAN_B;
  267. end
  268. else if(active_x == (H_ACTIVE/ 8) * 3)
  269. begin
  270. rgb_r_reg <= GREEN_R;
  271. rgb_g_reg <= GREEN_G;
  272. rgb_b_reg <= GREEN_B;
  273. end
  274. else if(active_x == (H_ACTIVE/ 8) * 4)
  275. begin
  276. rgb_r_reg <= MAGENTA_R;
  277. rgb_g_reg <= MAGENTA_G;
  278. rgb_b_reg <= MAGENTA_B;
  279. end
  280. else if(active_x == (H_ACTIVE/ 8) * 5)
  281. begin
  282. rgb_r_reg <= RED_R;
  283. rgb_g_reg <= RED_G;
  284. rgb_b_reg <= RED_B;
  285. end
  286. else if(active_x == (H_ACTIVE/ 8) * 6)
  287. begin
  288. rgb_r_reg <= BLUE_R;
  289. rgb_g_reg <= BLUE_G;
  290. rgb_b_reg <= BLUE_B;
  291. end
  292. else if(active_x == (H_ACTIVE/ 8) * 7)
  293. begin
  294. rgb_r_reg <= BLACK_R;
  295. rgb_g_reg <= BLACK_G;
  296. rgb_b_reg <= BLACK_B;
  297. end
  298. else
  299. begin
  300. rgb_r_reg <= rgb_r_reg;
  301. rgb_g_reg <= rgb_g_reg;
  302. rgb_b_reg <= rgb_b_reg;
  303. end
  304. else
  305. begin
  306. rgb_r_reg <= 8 'h00;
  307. rgb_g_reg <= 8 'h00;
  308. rgb_b_reg <= 8 'h00;
  309. end
  310. end
  311. endmodule

        color_bar.v的内容比较多,但是真正有意义的部分还是在于hs_reg、vs_reg、rgb_r_reg、rgb_g_reg、rgb_b_reg的生成。因为它们和最终输出有关。代码中的一大部分内容属于配置部分,因为我们选用的是1024*768,所以相关参数如下所示。video_define.v也只是添加了一行`define    VIDEO_1024_768而已。


  
  1. //1024x768 65Mhz
  2. `ifdef VIDEO_1024_768
  3. parameter H_ACTIVE = 16 'd1024;
  4. parameter H_FP = 16 'd24;
  5. parameter H_SYNC = 16 'd136;
  6. parameter H_BP = 16 'd160;
  7. parameter V_ACTIVE = 16 'd768;
  8. parameter V_FP = 16 'd3;
  9. parameter V_SYNC = 16 'd6;
  10. parameter V_BP = 16 'd29;
  11. parameter HS_POL = 1 'b0;
  12. parameter VS_POL = 1 'b0;
  13. `endif

         有了这几行定义,相当于规定了VGA数据的范围。HS_POL和VS_POL代表了起始值。下面就可以看看其他寄存器的含义了。hs_reg_d0、vs_reg_d0主要是为了延迟一拍,因为rgb_r_reg、rgb_g_reg、rgb_b_reg其实也相当于延迟一拍输出的。h_cnt计算一行的数据总数,active_x计算当前行中有效数据索引,v_cnt计算总的行数,hs_reg输出行同步,h_active输出行数据有效,vs_reg输出场同步,v_active输出场数据有效,rgb_r_reg & rgb_g_reg & rgb_b_reg则输出最终的rgb数据。

        另外在color_bar.v中,有一个信号de。这主要是为了后续bmp、camera做准备的,本次vga测试其实并没有用到。

7、pin脚信号的bind

8、实验

        有了video_define.v、vga_test.v、color_bar.v和pll这几个文件,经过编译、综合之后就可以生成对应的sof文件。烧入到fpga开发板之后,不出意外,就可以看到这样的显示效果了,


转载:https://blog.csdn.net/feixiaoxing/article/details/128429476
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场