当前位置:   article > 正文

FPGA项目实战 — 串口接收、RAM存储、RGB接口TFT显示_fpga数据显示

fpga数据显示

参考文章:https://www.cnblogs.com/fbur/p/16518333.html

源码下载:GitHub - Redamancy785/FPGA-Learning-Record: 项目博客:https://blog.csdn.net/weixin_51460407

代码功能

        本案例通过串口调试上位机将一张256×256照片的十六进制文本发送至开发板串口,接着开发板通过串口将数据存储入RAM中,最后从RAM读取数据并显示在屏幕上。

开发平台

开发板:小梅哥ACZ7015开发板+拓展板+800×640RGB-TFT屏幕

串口调试上位机:友善调试助手

图片生成十六进制文本工具:Img2Lcd

资源下载

链接:https://pan.baidu.com/s/147E_xyWExGrXG_0qOAeLsQ?pwd=ydgb 
 

一、系统架构

 局部放大

        模块间的互联逻辑

        uart_receive模块负责遵守urat协议接收上位机发送的数据并传送给uart_to_ram模块,uart_to_ram模块将接收的八位并行数据打包为十六位并行数据并传送给rom_image模块,rom_image模块负责存储接收的数据。以上是数据写入逻辑。

        disp_driver模块实时输出屏幕将要显示的坐标以向image_extract模块索要该坐标的的图像数据,从而在接收到数据之后驱动屏幕。所以,image_extract模块是一个“控制什么位置输出什么数据”的模块,当判断到该坐标需要使用RAM中的数据时,会向rom_image模块索要数据。以上是数据读出逻辑。

二、顶层模块

  1. module rom_image_tft_hdmi(
  2. clk50M,
  3. reset_n,
  4. uart_tx,
  5. TFT_rgb,
  6. TFT_hs,
  7. TFT_vs,
  8. TFT_clk,
  9. TFT_de,
  10. TFT_pwm,
  11. //HDMI
  12. SiI9022_sclk,
  13. SiI9022_sdat,
  14. led
  15. );
  16. input clk50M; //系统时钟输入,50M
  17. input reset_n; //复位信号输入,低有效
  18. input uart_tx ; //串口接受接口
  19. output [15:0] TFT_rgb; //TFT数据输出
  20. output TFT_hs; //TFT行同步信号
  21. output TFT_vs; //TFT场同步信号
  22. output TFT_clk; //TFT像素时钟
  23. output TFT_de; //TFT数据使能
  24. output TFT_pwm; //TFT背光控制
  25. inout SiI9022_sdat;
  26. output SiI9022_sclk;
  27. output led;
  28. /参数/
  29. //设置待显示图片尺寸,和存储图片ROM的地址位宽,显示背景颜色
  30. parameter DISP_IMAGE_W = 256;
  31. parameter DISP_IMAGE_H = 256;
  32. parameter ROM_ADDR_WIDTH = 16;
  33. parameter DISP_BACK_COLOR = 16'hFFFF; //白色
  34. //设置屏幕尺寸
  35. parameter TFT_WIDTH = 800;
  36. parameter TFT_HEIGHT = 480;
  37. //图片显示在屏幕中间位置
  38. parameter DISP_HBEGIN = (TFT_WIDTH - DISP_IMAGE_W)/2;
  39. parameter DISP_VBEGIN = (TFT_HEIGHT - DISP_IMAGE_H)/2;
  40. /网表型/
  41. 寄存器型/
  42. 时序逻辑/
  43. //pll模块
  44. wire pll_locked;
  45. wire loc_clk33M;
  46. pll pll(
  47. .clk_out1(loc_clk33M ), // output clk_out1
  48. .resetn (reset_n ), // input reset,active low
  49. .locked (pll_locked ), // output locked
  50. .clk_in1 (clk50M ) // input clk_in1
  51. );
  52. //uart接收模块
  53. wire [7:0]parallel_data ;//串口接收模块接收的并行数据8位
  54. wire rx_done ;//串口接收模块接收8位数据结束信号
  55. uart_receive_1 uart_receive(//串口接收模块
  56. .clk(clk50M) ,
  57. .reset(reset_n) ,
  58. .baud_rate(5) ,
  59. .uart_tx(uart_tx),
  60. .data(parallel_data) ,
  61. .rx_done(rx_done)
  62. );
  63. //uart_to_ram模块
  64. wire [15:0]addr_write ;//串口接收模块接收的并行数据8位
  65. wire [15:0]data_write ;//串口接收模块接收8位数据结束信号
  66. wire write_enable ;//写入使能信号
  67. uart_to_ram uart_to_ram(//将uart串口接收模块输出的数据写入ram中
  68. .clk(clk50M) ,
  69. .reset(reset_n) ,
  70. .data(parallel_data),
  71. .rx_done(rx_done),
  72. .addr(addr_write) ,
  73. .dout(data_write) ,
  74. .wenable(write_enable )
  75. );
  76. //rom_image模块
  77. wire [ROM_ADDR_WIDTH-1:0] rom_addra;
  78. wire [15:0] rom_data;
  79. rom_image rom_image (
  80. .clka(clk50M), // input wire clka
  81. .ena(1), // input wire ena
  82. .wea(write_enable), // input wire [0 : 0] wea
  83. .addra(addr_write), // input wire [15 : 0] addra
  84. .dina(data_write), // input wire [15 : 0] dina
  85. .clkb(loc_clk33M), // input wire clkb
  86. .addrb(rom_addra), // input wire [15 : 0] addrb
  87. .doutb(rom_data) // output wire [15 : 0] doutb
  88. );
  89. //image_extract模块
  90. wire [15:0] disp_data;
  91. wire disp_data_req;
  92. wire [11:0] visible_hcount;
  93. wire [11:0] visible_vcount;
  94. wire Frame_Begin;
  95. image_extract#(
  96. .H_Visible_area (TFT_WIDTH ), //屏幕显示区域宽度
  97. .V_Visible_area (TFT_HEIGHT ), //屏幕显示区域高度
  98. .IMG_WIDTH (DISP_IMAGE_W ), //图片宽度
  99. .IMG_HEIGHT (DISP_IMAGE_W ), //图片高度
  100. .IMG_DATA_WIDTH (16 ), //图片像素点位宽
  101. .ROM_ADDR_WIDTH (ROM_ADDR_WIDTH ) //存储图片ROM的地址位宽
  102. )
  103. image_extract(
  104. .clk_ctrl (loc_clk33M ),
  105. .reset_n (pll_locked ),
  106. .img_disp_hbegin(DISP_HBEGIN ),
  107. .img_disp_vbegin(DISP_VBEGIN ),
  108. .disp_back_color(DISP_BACK_COLOR),
  109. .rom_addra (rom_addra ),
  110. .rom_data (rom_data ),
  111. .Frame_Begin (Frame_Begin ),
  112. .disp_data_req (disp_data_req ),
  113. .visible_hcount (visible_hcount ),
  114. .visible_vcount (visible_vcount ),
  115. .disp_data (disp_data )
  116. );
  117. //disp_driver模块
  118. wire tft_reset_p;
  119. wire [4:0]Disp_Red;
  120. wire [5:0]Disp_Green;
  121. wire [4:0]Disp_Blue;
  122. wire [15:0]TFT_rgb;
  123. disp_driver disp_driver(
  124. .ClkDisp(loc_clk33M),
  125. .Rst_p(tft_reset_p),
  126. .Data(disp_data),
  127. .DataReq(disp_data_req),
  128. .H_Addr(visible_hcount),
  129. .V_Addr(visible_vcount),
  130. .Disp_HS(TFT_hs),
  131. .Disp_VS(TFT_vs),
  132. .Disp_Red(Disp_Red),
  133. .Disp_Green(Disp_Green),
  134. .Disp_Blue(Disp_Blue),
  135. .Frame_Begin(Frame_Begin),
  136. .Disp_DE(TFT_de),
  137. .Disp_PCLK(TFT_clk)
  138. );
  139. /组合逻辑/
  140. assign tft_reset_p = ~pll_locked; //锁相环提供的TFT屏复位信号进行取反,满足高电平复位
  141. assign TFT_rgb={Disp_Red,Disp_Green,Disp_Blue};
  142. assign TFT_pwm=1'b1;
  143. /*
  144. //HDMI模块
  145. reg [20:0]cnt;
  146. reg Go;
  147. always@(posedge clk50M or negedge reset_n)
  148. if(!reset_n)
  149. cnt <= 0;
  150. else if(cnt <= 499999)
  151. cnt <= cnt + 1 ;
  152. else
  153. cnt <= 500001;
  154. always@(posedge clk50M or negedge reset_n)
  155. if(!reset_n)
  156. Go <= 0;
  157. else if(cnt == 499999)
  158. Go <= 1'b1;
  159. else
  160. Go <= 0;
  161. SiI9022_Init SiI9022_Init(
  162. .Clk(clk50M),
  163. .Rst_n(reset_n),
  164. .Go(Go),
  165. .device_id(8'h72),
  166. .Init_Done(led),
  167. .i2c_sclk(SiI9022_sclk),
  168. .i2c_sdat(SiI9022_sdat)
  169. );
  170. */
  171. endmodule

三、uart_receive模块

  1. module uart_receive_1(
  2. clk ,
  3. reset ,
  4. baud_rate ,
  5. uart_tx,
  6. data ,
  7. rx_done
  8. );
  9. input clk ;
  10. input reset ;
  11. input [2:0]baud_rate ;
  12. input uart_tx ;
  13. output reg [7:0]data ;
  14. output reg rx_done ;
  15. reg rx_done_sig ;
  16. reg [2:0]r_data[7:0] ;//接收每一位数据
  17. reg [2:0]sta_bit ;
  18. reg [2:0]sto_bit ;
  19. reg [17:0]bit_tim ;//每一位持续的时间(计数)
  20. always@(baud_rate) //在这里一个 码元由一位组成,所以波特率=比特率
  21. begin
  22. case(baud_rate) //常见的串口传输波特率
  23. 3'd0 : bit_tim = 1000000000/300/20 ; //波特率为300
  24. 3'd1 : bit_tim = 1000000000/1200/20 ; //波特率为1200
  25. 3'd2 : bit_tim = 1000000000/2400/20 ; //波特率为2400
  26. 3'd3 : bit_tim = 1000000000/9600/20 ; //波特率为9600
  27. 3'd4 : bit_tim = 1000000000/19200/20 ; //波特率为19200
  28. 3'd5 : bit_tim = 1000000000/115200/20 ; //波特率为115200
  29. default bit_tim = 1000000000/9600/20 ; //多余的寄存器位置放什么:默认速率
  30. endcase
  31. end
  32. wire [17:0]bit_tim_16 ;//每1/16位的持续时间(计数)
  33. assign bit_tim_16 = bit_tim / 16;
  34. wire [8:0]bit16_mid ; //在中心点产生采样脉冲
  35. assign bit16_mid = bit_tim_16 / 2 ;
  36. //边沿检测
  37. reg [1:0]edge_detect ;
  38. always @( posedge clk or negedge reset )
  39. begin
  40. if (!reset )
  41. edge_detect <= 2'd0 ;
  42. else
  43. begin
  44. edge_detect[0] <= uart_tx ;
  45. edge_detect[1] <= edge_detect[0] ;
  46. end
  47. end
  48. wire byte_sta_neg ;
  49. assign byte_sta_neg = ( edge_detect == 2'b10 ) ? 1 : 0 ;//输入的数据开始出现下降沿,说明出现了起始位(一直运行?)
  50. reg receive_en ;//接收使能端
  51. reg [17:0]div_cnt ;//每1/16bit内的计数
  52. reg [7:0]bit16_cnt ;//计数到了第几个状态(10位,每位分成16份,总共160个状态)
  53. always @( posedge clk or negedge reset )
  54. begin
  55. if (!reset )
  56. receive_en <= 1'd0 ;
  57. else if ( byte_sta_neg ) //检测到下降沿,使能段有效(只要有下降沿就使能?)
  58. receive_en <= 1'd1 ;
  59. else if ( (rx_done) || (sta_bit >= 3'd4 ))
  60. receive_en <= 1'd0 ; //检测到结束信号,使能端无效
  61. else if ( ( bit16_cnt == 8'd159 ) && (div_cnt == bit_tim_16 - 1'd1 ) )//跑完159后re_en置零
  62. receive_en <= 1'd0 ;
  63. end
  64. always@( posedge clk or negedge reset )
  65. begin
  66. if ( ! reset )
  67. div_cnt <= 18'd0 ;
  68. else if (receive_en)
  69. begin
  70. if ( div_cnt == bit_tim_16 - 1'd1 )//计数,每1/16bit清零
  71. div_cnt <= 18'd0 ;
  72. else
  73. div_cnt <= div_cnt + 1'b1 ;
  74. end
  75. else
  76. div_cnt <= 18'd0 ;
  77. end
  78. reg bit16_pulse ;//产生采样脉冲
  79. always@( posedge clk or negedge reset )
  80. begin
  81. if ( ! reset )
  82. bit16_pulse <= 18'd0 ;
  83. else if (receive_en)
  84. if ( div_cnt == bit16_mid )
  85. bit16_pulse <= 1'd1 ;
  86. else
  87. bit16_pulse <= 1'd0 ;
  88. else
  89. bit16_pulse <= 1'd0 ;
  90. end
  91. always@( posedge clk or negedge reset )
  92. begin
  93. if ( ! reset )
  94. bit16_cnt <= 8'd0 ;
  95. else if (receive_en)
  96. begin
  97. if (( bit16_cnt == 8'd159 ) && (div_cnt == bit_tim_16 - 1'd1 ))
  98. bit16_cnt <= 8'd0 ;
  99. else if ( div_cnt == bit_tim_16 - 1'd1 )
  100. bit16_cnt <= bit16_cnt + 1'b1 ;
  101. end
  102. end
  103. always@(posedge clk or negedge reset)
  104. begin
  105. if(!reset)
  106. begin
  107. sta_bit <= 3'd0 ;
  108. r_data[0] <= 3'd0 ;
  109. r_data[1] <= 3'd0 ;
  110. r_data[2] <= 3'd0 ;
  111. r_data[3] <= 3'd0 ;
  112. r_data[4] <= 3'd0 ;
  113. r_data[5] <= 3'd0 ;
  114. r_data[6] <= 3'd0 ;
  115. r_data[7] <= 3'd0 ;
  116. sto_bit <= 3'd0 ;
  117. end
  118. else if (bit16_pulse)//舍弃前5后4取中7
  119. case(bit16_cnt)
  120. 0:
  121. begin
  122. sta_bit <= 3'd0 ;
  123. r_data[0] <= 3'd0 ;
  124. r_data[1] <= 3'd0 ;
  125. r_data[2] <= 3'd0 ;
  126. r_data[3] <= 3'd0 ;
  127. r_data[4] <= 3'd0 ;
  128. r_data[5] <= 3'd0 ;
  129. r_data[6] <= 3'd0 ;
  130. r_data[7] <= 3'd0 ;
  131. sto_bit <= 3'd0 ;
  132. end
  133. 5,6,7,8,9,10,11 : sta_bit <= sta_bit + uart_tx ;
  134. 21,22,23,24,25,26,27 : r_data[0] <= r_data[0] + uart_tx ;
  135. 37,38,39,41,42,43,44 : r_data[1] <= r_data[1] + uart_tx ;
  136. 53,54,55,56,57,58,59 : r_data[2] <= r_data[2] + uart_tx ;
  137. 69,70,71,72,73,74,75 : r_data[3] <= r_data[3] + uart_tx ;
  138. 85,86,87,88,89,90,91 : r_data[4] <= r_data[4] + uart_tx ;
  139. 101,102,103,104,105,106,107 : r_data[5] <= r_data[5] + uart_tx ;
  140. 117,118,119,120,121,122,123 : r_data[6] <= r_data[6] + uart_tx ;
  141. 133,134,135,136,137,138,139 : r_data[7] <= r_data[7] + uart_tx ;
  142. 149,150,151,152,153,154,155 : sto_bit <= sto_bit + uart_tx ;
  143. default ;
  144. endcase
  145. end
  146. always@( posedge clk or negedge reset )
  147. begin
  148. if ( ! reset )
  149. rx_done_sig <= 8'd0 ;
  150. else if ( ( bit16_cnt == 8'd159 ) && (div_cnt == bit_tim_16 - 2'd2 ) )//跑完159后产生一个rx_done信号
  151. rx_done_sig <= 8'd1 ;
  152. else if (rx_done_sig <= 8'd1 )
  153. rx_done_sig <= 8'd0 ;
  154. end
  155. always@( posedge clk or negedge reset )//接收完数据发出rx_done
  156. if(!reset )
  157. rx_done <= 0 ;
  158. else if (rx_done_sig)
  159. rx_done <= 1 ;
  160. else if (rx_done )
  161. rx_done <= 0 ;
  162. always@( posedge clk or negedge reset )//接收完数据发出rx_done后,把数据从r_data传递给data
  163. begin
  164. if ( ! reset )
  165. data <= 8'd0 ;
  166. else if ( rx_done_sig )
  167. begin
  168. data[0] = ( r_data[0] >3 ) ? 1 : 0 ;
  169. data[1] = ( r_data[1] >3 ) ? 1 : 0 ;
  170. data[2] = ( r_data[2] >3 ) ? 1 : 0 ;
  171. data[3] = ( r_data[3] >3 ) ? 1 : 0 ;
  172. data[4] = ( r_data[4] >3 ) ? 1 : 0 ;
  173. data[5] = ( r_data[5] >3 ) ? 1 : 0 ;
  174. data[6] = ( r_data[6] >3 ) ? 1 : 0 ;
  175. data[7] = ( r_data[7] >3 ) ? 1 : 0 ;
  176. end
  177. // else if ( receive_en )
  178. // data <= 8'd0 ;
  179. end
  180. endmodule

四、uart_to_ram模块

  1. module uart_to_ram(
  2. clk ,
  3. reset ,
  4. data,
  5. rx_done,
  6. addr ,
  7. dout ,
  8. wenable
  9. );
  10. input clk ;
  11. input reset ;
  12. input [7:0]data;
  13. input rx_done;
  14. output reg [15:0]addr ;
  15. output reg [15:0]dout ;
  16. output reg wenable ;
  17. //ram的容量为256*256个像素,每个像素位宽16,共需256*256*2个8位的数据(131072)
  18. //用计数器来计数
  19. reg [16:0]pixel_cnt ;//131072
  20. always@(posedge clk or negedge reset)
  21. if(!reset)
  22. pixel_cnt <= 17'd0 ;
  23. else if ( ( pixel_cnt < 131071 ) && ( rx_done ) )
  24. pixel_cnt <= pixel_cnt + 1 ;
  25. else if (( pixel_cnt >= 131071 ) && ( rx_done ))
  26. pixel_cnt <= 17'd0 ;
  27. //需要一个寄存器,存两个8位,共16位
  28. reg [15:0]data_register ;
  29. always@(posedge clk or negedge reset)
  30. if(!reset)
  31. data_register <= 16'd0 ;
  32. else if ( rx_done )
  33. data_register <= { data_register[7:0] , data } ;
  34. //添加一个变化条件信号
  35. reg change_sig ;
  36. always@(posedge clk or negedge reset)
  37. if(!reset)
  38. change_sig <= 1'd0 ;
  39. else if ( rx_done && ( pixel_cnt[0] == 1 ) )
  40. change_sig <= 1'd1 ;
  41. else if ( change_sig == 1'd1 )
  42. change_sig <= 1'd0 ;
  43. //把每16位数据存进ram中,即输出16位数据
  44. always@(posedge clk or negedge reset)
  45. if(!reset)
  46. dout <= 16'd0 ;
  47. else if ( change_sig )
  48. dout <= data_register ;
  49. //产生一个写入ram的使能信号
  50. always@(posedge clk or negedge reset)
  51. if(!reset)
  52. wenable <= 0 ;
  53. else if ( change_sig )
  54. wenable <= 1 ;
  55. else if (wenable == 1)
  56. wenable <= 0 ;
  57. //产生写入ram的地址 //比weanbel和data提前变化,不然不满足下面除于2的条件,第0个地址将没有数据
  58. always@(posedge clk or negedge reset)
  59. if(!reset)
  60. addr <= 16'd0 ;
  61. else if ( rx_done && ( pixel_cnt[0] == 1 ) )
  62. addr <= pixel_cnt[16:1] ; //除于2 即舍弃最后一位(右移一位)
  63. endmodule

五、image_extract模块

  1. module image_extract
  2. #(
  3. parameter H_Visible_area = 800, //整个屏幕显示区域宽度
  4. parameter V_Visible_area = 480, //整个屏幕显示区域高度
  5. parameter IMG_WIDTH = 160, //图片宽度
  6. parameter IMG_HEIGHT = 120, //图片高度
  7. parameter IMG_DATA_WIDTH = 16, //图片像素点位宽
  8. parameter ROM_ADDR_WIDTH = 16 //存储图片ROM的地址位宽
  9. )
  10. (
  11. clk_ctrl,
  12. reset_n,
  13. img_disp_hbegin,
  14. img_disp_vbegin,
  15. disp_back_color,
  16. Frame_Begin,
  17. rom_addra,
  18. rom_data,
  19. disp_data_req,
  20. visible_hcount,
  21. visible_vcount,
  22. disp_data
  23. );
  24. input clk_ctrl ; //时钟输入,与TFT屏时钟保持一致
  25. input reset_n ; //复位信号,低电平有效
  26. input [15:0] img_disp_hbegin; //待显示图片左上角第一个像素点在TFT屏的行向坐标
  27. input [15:0] img_disp_vbegin; //待显示图片左上角第一个像素点在TFT屏的场向坐标
  28. input [IMG_DATA_WIDTH-1:0] disp_back_color; //显示的背景颜色
  29. output [ROM_ADDR_WIDTH-1:0] rom_addra ; //读图片数据ROM地址
  30. input [IMG_DATA_WIDTH-1:0] rom_data ; //读图片数据ROM数据
  31. input Frame_Begin ; //一帧图像起始标识信号,clk_ctrl时钟域
  32. input disp_data_req ; //
  33. input [11:0] visible_hcount ; //TFT可见区域行扫描计数器
  34. input [11:0] visible_vcount ; //TFT可见区域场扫描计数器
  35. output [IMG_DATA_WIDTH-1:0] disp_data ; //待显示图片数据
  36. reg [ROM_ADDR_WIDTH-1:0] rom_addra ; //读图片数据rom地址
  37. wire h_exceed;
  38. wire v_exceed;
  39. wire img_h_disp;
  40. wire img_v_disp;
  41. wire img_disp;
  42. wire [15:0]hcount_max;
  43. //判断设置的显示的起始位置是否会导致显示超出范围
  44. assign h_exceed = img_disp_hbegin + IMG_WIDTH > H_Visible_area - 1'b1;
  45. assign v_exceed = img_disp_vbegin + IMG_HEIGHT > V_Visible_area - 1'b1;
  46. //不同的设置情况,显示区域做不同的处理
  47. assign img_h_disp = h_exceed ? (visible_hcount >= img_disp_hbegin && visible_hcount < H_Visible_area):
  48. (visible_hcount >= img_disp_hbegin && visible_hcount < img_disp_hbegin + IMG_WIDTH);
  49. assign img_v_disp = v_exceed ? (visible_vcount >= img_disp_vbegin && visible_vcount < V_Visible_area):
  50. (visible_vcount >= img_disp_vbegin && visible_vcount < img_disp_vbegin + IMG_HEIGHT);
  51. assign img_disp = disp_data_req && img_h_disp && img_v_disp;
  52. assign hcount_max = h_exceed ? (H_Visible_area - 1'b1):(img_disp_hbegin + IMG_WIDTH - 1'b1);
  53. always@(posedge clk_ctrl or negedge reset_n)
  54. begin
  55. if(!reset_n)
  56. rom_addra <= 'd0;
  57. else if(Frame_Begin)
  58. rom_addra <= 'd0;
  59. else if(img_disp)
  60. begin
  61. if(visible_hcount == hcount_max)
  62. rom_addra <= rom_addra + (img_disp_hbegin + IMG_WIDTH - hcount_max);
  63. else
  64. rom_addra <= rom_addra + 1'b1;
  65. end
  66. else
  67. rom_addra <= rom_addra;
  68. end
  69. assign disp_data = img_disp ? rom_data : disp_back_color;
  70. endmodule

六、disp_driver模块

  1. `include "disp_parameter_cfg.v"
  2. module disp_driver(
  3. ClkDisp,
  4. Rst_p,
  5. Data,
  6. DataReq,
  7. H_Addr,
  8. V_Addr,
  9. Disp_HS,
  10. Disp_VS,
  11. Disp_Red,
  12. Disp_Green,
  13. Disp_Blue,
  14. Frame_Begin,
  15. Disp_DE,
  16. Disp_PCLK
  17. );
  18. input ClkDisp;
  19. input Rst_p;
  20. input [`Red_Bits + `Green_Bits + `Blue_Bits - 1:0] Data;
  21. output DataReq;
  22. output [11:0] H_Addr;
  23. output [11:0] V_Addr;
  24. output reg Disp_HS;
  25. output reg Disp_VS;
  26. output reg [`Red_Bits - 1 :0]Disp_Red;
  27. output reg [`Green_Bits - 1 :0]Disp_Green;
  28. output reg [`Blue_Bits - 1 :0]Disp_Blue;
  29. output reg Frame_Begin; //一帧图像起始标识信号,ClkDisp时钟域
  30. output reg Disp_DE;
  31. output Disp_PCLK;
  32. wire hcount_ov;
  33. wire vcount_ov;
  34. //----------------内部寄存器定义----------------
  35. reg [11:0] hcount_r; //行扫描计数器
  36. reg [11:0] vcount_r; //场扫描计数器
  37. `ifdef HW_VGA
  38. assign Disp_PCLK = ~ClkDisp;
  39. `else
  40. assign Disp_PCLK = ClkDisp;
  41. `endif
  42. assign DataReq = Disp_DE;
  43. parameter hdat_begin = `H_Sync_Time + `H_Back_Porch + `H_Left_Border - 1'b1;
  44. parameter hdat_end = `H_Total_Time - `H_Right_Border - `H_Front_Porch - 1'b1;
  45. parameter vdat_begin = `V_Sync_Time + `V_Back_Porch + `V_Top_Border - 1'b1;
  46. parameter vdat_end = `V_Total_Time - `V_Bottom_Border - `V_Front_Porch - 1'b1;
  47. assign H_Addr = Disp_DE?(hcount_r - hdat_begin):12'd0;
  48. assign V_Addr = Disp_DE?(vcount_r - vdat_begin):12'd0;
  49. //行扫描
  50. assign hcount_ov = (hcount_r >= `H_Total_Time - 1);
  51. always@(posedge ClkDisp or posedge Rst_p)
  52. if(Rst_p)
  53. hcount_r <= 0;
  54. else if(hcount_ov)
  55. hcount_r <= 0;
  56. else
  57. hcount_r <= hcount_r + 1'b1;
  58. //场扫描
  59. assign vcount_ov = (vcount_r >= `V_Total_Time - 1);
  60. always@(posedge ClkDisp or posedge Rst_p)
  61. if(Rst_p)
  62. vcount_r <= 0;
  63. else if(hcount_ov) begin
  64. if(vcount_ov)
  65. vcount_r <= 0;
  66. else
  67. vcount_r <= vcount_r + 1'd1;
  68. end
  69. else
  70. vcount_r <= vcount_r;
  71. always@(posedge ClkDisp)
  72. Disp_DE <= ((hcount_r >= hdat_begin)&&(hcount_r < hdat_end))&&
  73. ((vcount_r >= vdat_begin)&&(vcount_r < vdat_end));
  74. always@(posedge ClkDisp) begin
  75. Disp_HS <= (hcount_r > `H_Sync_Time - 1);
  76. Disp_VS <= (vcount_r > `V_Sync_Time - 1);
  77. {Disp_Red,Disp_Green,Disp_Blue} <= (Disp_DE)?Data:1'd0;
  78. end
  79. /*******************************************/
  80. reg Disp_VS_dly1;
  81. always@(posedge ClkDisp)
  82. begin
  83. Disp_VS_dly1 <= Disp_VS;
  84. end
  85. always@(posedge ClkDisp or posedge Rst_p)
  86. begin
  87. if(Rst_p)
  88. Frame_Begin <= 1'b0;
  89. else if(!Disp_VS_dly1 && Disp_VS)
  90. Frame_Begin <= 1'b1;
  91. else
  92. Frame_Begin <= 1'b0;
  93. end
  94. /*******************************************/
  95. endmodule

七、disp_parameter_cfg.v参数配置文件

  1. /*使用说明
  2. 使用时根据实际工作需求选择2个预定义参数就可以
  3. 参数1: MODE_RGBxxx
  4. 预定义用来决定驱动工作在16位模式还是24位模式,二选一
  5. MODE_RGB888:24位模式
  6. MODE_RGB565:16位模式
  7. 针对小梅哥提供的一系列显示设备,各个设备该参数的选择
  8. 4.3寸TFT显示屏------使用16位色RGB565模式
  9. 5寸TFT显示屏--------使用16位色RGB565模式
  10. GM7123模块----------使用24位色RGB888模式
  11. 参数2: Resolution_xxxx
  12. 预定义用来决定显示设备分辨率,常见设备分辨率如下所述
  13. 4.3寸TFT显示屏:
  14. Resolution_480x272
  15. 5寸TFT显示屏:
  16. Resolution_800x480
  17. VGA常见分辨率:
  18. Resolution_640x480
  19. Resolution_800x600
  20. Resolution_1024x600
  21. Resolution_1024x768
  22. Resolution_1280x720
  23. Resolution_1920x1080
  24. */
  25. //也可通过宏定义显示设备类型来进行设置,选择一个使能,其他使用注释的方式屏蔽
  26. //使用4.3寸480*272分辨率显示屏
  27. //`define HW_TFT43
  28. //使用5寸800*480分辨率显示屏
  29. `define HW_TFT50
  30. //使用VGA显示器,默认为640*480分辨率,24位模式,其他分辨率或需16位模式可在代码63行至75行进行重配置
  31. //`define HW_VGA
  32. //=====================================
  33. //以下宏定义选择用于根据显示设备进行位模式和分辨率2个参数的设置
  34. //=====================================
  35. `ifdef HW_TFT43 //使用4.3寸480*272分辨率显示屏
  36. `define MODE_RGB565
  37. `define Resolution_480x272 1 //时钟为9MHz
  38. `elsif HW_TFT50 //使用5寸800*480分辨率显示屏
  39. `define MODE_RGB565
  40. `define Resolution_800x480 1 //时钟为33MHz
  41. `elsif HW_VGA //使用VGA显示器,默认为640*480分辨率,24位模式
  42. //=====================================
  43. //可选择其他分辨率和16位模式,需用户根据实际需求设置
  44. //代码下方三行和四行设置位模式
  45. //代码下方五行以后连续宏定义部分设置分辨率
  46. //=====================================
  47. `define MODE_RGB565
  48. // `define MODE_RGB888
  49. `define Resolution_640x480 1 //时钟为25.175MHz
  50. //`define Resolution_800x600 1 //时钟为40MHz
  51. //`define Resolution_1024x600 1 //时钟为51MHz
  52. //`define Resolution_1024x768 1 //时钟为65MHz
  53. //`define Resolution_1280x720 1 //时钟为74.25MHz
  54. //`define Resolution_1920x1080 1 //时钟为148.5MHz
  55. `endif
  56. //=====================================
  57. //非特殊需求,以下内容用户不需修改
  58. //=====================================
  59. //定义不同的颜色深度
  60. `ifdef MODE_RGB888
  61. `define Red_Bits 8
  62. `define Green_Bits 8
  63. `define Blue_Bits 8
  64. `elsif MODE_RGB565
  65. `define Red_Bits 5
  66. `define Green_Bits 6
  67. `define Blue_Bits 5
  68. `endif
  69. //定义不同分辨率的时序参数
  70. `ifdef Resolution_480x272
  71. `define H_Total_Time 12'd525
  72. `define H_Right_Border 12'd0
  73. `define H_Front_Porch 12'd2
  74. `define H_Sync_Time 12'd41
  75. `define H_Back_Porch 12'd2
  76. `define H_Left_Border 12'd0
  77. `define V_Total_Time 12'd286
  78. `define V_Bottom_Border 12'd0
  79. `define V_Front_Porch 12'd2
  80. `define V_Sync_Time 12'd10
  81. `define V_Back_Porch 12'd2
  82. `define V_Top_Border 12'd0
  83. `elsif Resolution_640x480
  84. `define H_Total_Time 12'd800
  85. `define H_Right_Border 12'd8
  86. `define H_Front_Porch 12'd8
  87. `define H_Sync_Time 12'd96
  88. `define H_Back_Porch 12'd40
  89. `define H_Left_Border 12'd8
  90. `define V_Total_Time 12'd525
  91. `define V_Bottom_Border 12'd8
  92. `define V_Front_Porch 12'd2
  93. `define V_Sync_Time 12'd2
  94. `define V_Back_Porch 12'd25
  95. `define V_Top_Border 12'd8
  96. `elsif Resolution_800x480
  97. `define H_Total_Time 12'd1056
  98. `define H_Right_Border 12'd0
  99. `define H_Front_Porch 12'd40
  100. `define H_Sync_Time 12'd128
  101. `define H_Back_Porch 12'd88
  102. `define H_Left_Border 12'd0
  103. `define V_Total_Time 12'd525
  104. `define V_Bottom_Border 12'd8
  105. `define V_Front_Porch 12'd2
  106. `define V_Sync_Time 12'd2
  107. `define V_Back_Porch 12'd25
  108. `define V_Top_Border 12'd8
  109. `elsif Resolution_800x600
  110. `define H_Total_Time 12'd1056
  111. `define H_Right_Border 12'd0
  112. `define H_Front_Porch 12'd40
  113. `define H_Sync_Time 12'd128
  114. `define H_Back_Porch 12'd88
  115. `define H_Left_Border 12'd0
  116. `define V_Total_Time 12'd628
  117. `define V_Bottom_Border 12'd0
  118. `define V_Front_Porch 12'd1
  119. `define V_Sync_Time 12'd4
  120. `define V_Back_Porch 12'd23
  121. `define V_Top_Border 12'd0
  122. `elsif Resolution_1024x600
  123. `define H_Total_Time 12'd1344
  124. `define H_Right_Border 12'd0
  125. `define H_Front_Porch 12'd24
  126. `define H_Sync_Time 12'd136
  127. `define H_Back_Porch 12'd160
  128. `define H_Left_Border 12'd0
  129. `define V_Total_Time 12'd628
  130. `define V_Bottom_Border 12'd0
  131. `define V_Front_Porch 12'd1
  132. `define V_Sync_Time 12'd4
  133. `define V_Back_Porch 12'd23
  134. `define V_Top_Border 12'd0
  135. `elsif Resolution_1024x768
  136. `define H_Total_Time 12'd1344
  137. `define H_Right_Border 12'd0
  138. `define H_Front_Porch 12'd24
  139. `define H_Sync_Time 12'd136
  140. `define H_Back_Porch 12'd160
  141. `define H_Left_Border 12'd0
  142. `define V_Total_Time 12'd806
  143. `define V_Bottom_Border 12'd0
  144. `define V_Front_Porch 12'd3
  145. `define V_Sync_Time 12'd6
  146. `define V_Back_Porch 12'd29
  147. `define V_Top_Border 12'd0
  148. `elsif Resolution_1280x720
  149. `define H_Total_Time 12'd1650
  150. `define H_Right_Border 12'd0
  151. `define H_Front_Porch 12'd110
  152. `define H_Sync_Time 12'd40
  153. `define H_Back_Porch 12'd220
  154. `define H_Left_Border 12'd0
  155. `define V_Total_Time 12'd750
  156. `define V_Bottom_Border 12'd0
  157. `define V_Front_Porch 12'd5
  158. `define V_Sync_Time 12'd5
  159. `define V_Back_Porch 12'd20
  160. `define V_Top_Border 12'd0
  161. `elsif Resolution_1920x1080
  162. `define H_Total_Time 12'd2200
  163. `define H_Right_Border 12'd0
  164. `define H_Front_Porch 12'd88
  165. `define H_Sync_Time 12'd44
  166. `define H_Back_Porch 12'd148
  167. `define H_Left_Border 12'd0
  168. `define V_Total_Time 12'd1125
  169. `define V_Bottom_Border 12'd0
  170. `define V_Front_Porch 12'd4
  171. `define V_Sync_Time 12'd5
  172. `define V_Back_Porch 12'd36
  173. `define V_Top_Border 12'd0
  174. `endif

八、IP配置

pll

rom_image

九、上板演示

上位机配置

发送数据

打开网盘中111.c,全选复制输入串口助手

点击发送

屏幕显示

声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号