前言
我的最终目的还是想在FPGA上做一个小游戏,具体做啥还没想好但是需要一些基本的素材,所以先在屏幕上画一个X出来再说,就像下面这个图:
制作
有一个基础的tft模块已经在 【FPGA的小娱乐】tft显示屏生成信号辅助测试阵列 里说明过了,就是提供chan_in作为输入接口的tft_ctrl模块,基于这个模块的接口可以很简单的做出来画矩形的模块:
1. module square_gen( 2. input [10-1:0]x_point, 3. input [10-1:0]y_point, 4. input [10-1:0]x_size, 5. input [10-1:0]y_size, 6. input [8 -1:0]r, 7. input [8 -1:0]g, 8. input [8 -1:0]b, 9. input [10-1:0]hcount, 10. input [10-1:0]vcount, 11. 12. input power_en, 13. 14. output chan_en, 15. output[24-1:0]chan_data 16. ); 17. 18. wire [10-1:0]x_left = x_point; 19. wire [10-1:0]x_right = (x_point + x_size >= 11'd480) ? 10'd480 : x_point + x_size; 20. wire [10-1:0]y_top = y_point; 21. wire [10-1:0]y_bottom = (y_point + y_size >= 11'd272) ? 10'd272 : y_point + y_size; 22. 23. assign chan_en = power_en && (hcount >= x_left) && (hcount < x_right) && (vcount >= y_top) && (vcount < y_bottom); 24. assign chan_data = {r,g,b}; 25. endmodule
那么进一步,画正正当当的直角等腰三角形也很简单:
1. module triangle_gen( 2. input [10-1:0]x_point, 3. input [10-1:0]y_point, 4. input [10-1:0]size, 5. input [8 -1:0]r, 6. input [8 -1:0]g, 7. input [8 -1:0]b, 8. 9. input [10-1:0]hcount, 10. input [10-1:0]vcount, 11. 12. input power_en, 13. input [3:0] mode, 14. 15. output chan_en, 16. output[24-1:0]chan_data 17. ); 18. 19. wire [10-1:0]p0_x_point; 20. wire [10-1:0]p0_y_point; 21. wire [10-1:0]p1_x_point; 22. wire [10-1:0]p2_y_point; 23. 24. assign mode0_power = (x_point - hcount < size) && (y_point - vcount < size) && (x_point - hcount + y_point - vcount < size); 25. assign mode1_power = (hcount - x_point < size) && (y_point - vcount < size) && (hcount - x_point + y_point - vcount < size); 26. assign mode2_power = (x_point - hcount < size) && (vcount - y_point < size) && (x_point - hcount + vcount - y_point < size); 27. assign mode3_power = (hcount - x_point < size) && (vcount - y_point < size) && (hcount - x_point + vcount - y_point < size); 28. 29. assign chan_en = power_en && 30. ((mode[0] & mode0_power) | 31. (mode[1] & mode1_power) | 32. (mode[2] & mode2_power) | 33. (mode[3] & mode3_power)); 34. assign chan_data = {r,g,b}; 35. 36. endmodule
对四个三角形做任意的例化,很容易就能画出例如下面这样的三角形元素图:
两个基本图形有了之后,X就很容易画了,第一种方式是一个正方形减去四个8个小三角形X,另一种方式就是先画\ /两种线,再合成一个X。我是用的第二种,那么就开始画/,这个的方式也很容易,一个正方形减去左上和右下两个直角等腰三角形;\对应的则是一个正方形减去左下和右上两个直角等腰三角形,两种斜线合成一个模块,代码的核心其实就是assign chan_en = squ_chan_en && ~tri0_chan_en && ~tri1_chan_en:
1. module slash_gen( 2. input [10-1:0]x_point, 3. input [10-1:0]y_point, 4. input [10-1:0]size, 5. input [10-1:0]sub_size, 6. input [8 -1:0]r, 7. input [8 -1:0]g, 8. input [8 -1:0]b, 9. 10. input [10-1:0]hcount, 11. input [10-1:0]vcount, 12. 13. input power_en, 14. input mode, 15. 16. output chan_en, 17. output[24-1:0]chan_data 18. ); 19. 20. wire squ_chan_en; 21. square_gen u_squ( 22. .x_point (x_point), 23. .y_point (y_point), 24. .x_size (size), 25. .y_size (size), 26. .r (r), 27. .g (g), 28. .b (b), 29. .hcount (hcount), 30. .vcount (vcount), 31. .power_en (power_en), 32. .chan_en (squ_chan_en), 33. .chan_data () 34. ); 35. 36. wire tri0_chan_en; 37. wire [4-1:0] tri0_mode = mode ? 4'b0010 : 4'b1000; 38. wire [10-1:0]tri0_x_point = x_point; 39. wire [10-1:0]tri0_y_point = mode ? y_point + size : y_point; 40. triangle_gen u_tri0( 41. .x_point (tri0_x_point), 42. .y_point (tri0_y_point), 43. .size (size-sub_size), 44. .r (r), 45. .g (g), 46. .b (b), 47. .hcount (hcount), 48. .vcount (vcount), 49. .power_en (power_en), 50. .mode (tri0_mode), 51. .chan_en (tri0_chan_en), 52. .chan_data () 53. ); 54. 55. wire tri1_chan_en; 56. wire [4-1:0] tri1_mode = mode ? 4'b0100 : 4'b0001; 57. wire [10-1:0]tri1_x_point = x_point+size; 58. wire [10-1:0]tri1_y_point = mode ? y_point : y_point+size; 59. triangle_gen u_tri1( 60. .x_point (tri1_x_point), 61. .y_point (tri1_y_point), 62. .size (size-sub_size), 63. .r (r), 64. .g (g), 65. .b (b), 66. .hcount (hcount), 67. .vcount (vcount), 68. .power_en (power_en), 69. .mode (tri1_mode), 70. .chan_en (tri1_chan_en), 71. .chan_data () 72. ); 73. 74. assign chan_en = power_en && (squ_chan_en && ~tri0_chan_en && ~tri1_chan_en); 75. assign chan_data = {r,g,b}; 76. 77. endmodule
然后再例化两个斜线,对应的X就出来了:
1. module x_gen( 2. input [10-1:0]x_point, 3. input [10-1:0]y_point, 4. input [10-1:0]size, 5. input [10-1:0]sub_size, 6. input [8 -1:0]r, 7. input [8 -1:0]g, 8. input [8 -1:0]b, 9. 10. input [10-1:0]hcount, 11. input [10-1:0]vcount, 12. 13. input power_en, 14. 15. output chan_en, 16. output[24-1:0]chan_data 17. ); 18. 19. wire [1 -1:0]slash0_chan_in; 20. slash_gen u_slash0( 21. .x_point (x_point), 22. .y_point (y_point), 23. .size (size), 24. .sub_size (sub_size), 25. .r (r), 26. .g (g), 27. .b (b), 28. .hcount (hcount), 29. .vcount (vcount), 30. .power_en (1'b1), 31. .mode (1'b0), 32. .chan_en (slash0_chan_in), 33. .chan_data () 34. ); 35. 36. wire [1 -1:0]slash1_chan_in; 37. slash_gen u_slash1( 38. .x_point (x_point), 39. .y_point (y_point), 40. .size (size), 41. .sub_size (sub_size), 42. .r (r), 43. .g (g), 44. .b (b), 45. .hcount (hcount), 46. .vcount (vcount), 47. .power_en (1'b1), 48. .mode (1'b1), 49. .chan_en (slash1_chan_in), 50. .chan_data () 51. ); 52. 53. assign chan_en = power_en && (slash0_chan_in || slash1_chan_in); 54. assign chan_data = {r,g,b}; 55. 56. endmodule
在工程里跑一下,输出就是下图: