【原创】TFT LCD液晶屏的FPGA代码
随着FPGA的发展,尤其是ZYNQ和Cyclone V的出现,LCD液晶屏的显示在FPGA上的应用得到了 很大的发展。 用逻辑去写图片,毕竟不是强项。但是配合ARM进行显示,还是有很大的用处的。
废话就不多说了,之前调试的FPGA的代码,现在发布出来供大家测试使用。
我尽量做的灵活一些,只需要修改几个宏定义就可以拿来用了,我们用的是720P和1080P的,参数需要参考液晶屏厂给的LCD参数进行修改。这些都很简单了,不再多说了。
ZYNQ接TFT的液晶屏,可以参考官方给的VDMA方案,也可以自己去做协议进去。不过个人感觉自己写的更好用一点,前端加个FIFO就搞定了,一秒传输100MBPS+是很轻松的。
下面是仿真的效果: 1 //**************************************************************** 2 //Editor : 闫若川 FPGA 3 //-------------------------------------------------------------------------------- 4 //Tool Version: 5 //Date : Tue Jul 3 16:07:00 2012 6 //Host : PC-20100713LAID running 64-bit major release 7 //Command : 8 //Design : tft_lcd_top 9 //Purpose : TFT LCD display code ,output test pixel 10 //Notice : MIPI code needs to be reconfigured 11 //--------------------------------------------------------------------------------
12 module tft_lcd_top 13 #( 14 //******** 800 x 480 LCD screen
15
16 parameter HSYNC_NUM = 16'd720 ,//*
17 parameter HS_PULSE_WIDTH = 16'd33 ,//*// HSA 33
18 parameter H_BLACKING = 16'd133 ,//*// HSA + HBP
19 parameter H_FRONT_PORCH = 16'd100 ,//*//
20 parameter VSYNC_NUM = 16'd1280 ,//*
21 parameter VS_PULSE_WIDTH = 16'd2 ,//
22 parameter V_BLACKING = 16'd32 ,//
23 parameter V_FRONT_PORCH = 16'd20 //*
24
25 // parameter HSYNC_NUM = 16'd1280 , 26 // parameter H_BLACKING = 16'd46 , 27 // parameter H_FRONT_PORCH = 16'd210 , 28 // parameter HS_PULSE_WIDTH = 16'd20 , 29 // parameter VSYNC_NUM = 16'd720 , 30 // parameter V_BLACKING = 16'd23 , 31 // parameter V_FRONT_PORCH = 16'd22 , 32 // parameter VS_PULSE_WIDTH = 16'd10 33
34 //******** 480 x 272 LCD screen
35 ) 36 ( 37 clk , 38 reset_n , 39 //******** LCD 接口
40 ov_lcd_r , 41 ov_lcd_g , 42 ov_lcd_b , 43 o_lcd_hsync , 44 o_lcd_vsync , 45 o_lcd_dclk , 46 o_lcd_disp , 47 o_lcd_de , 48 o_lcd_pwm , 49 ov_addr , 50 //********
51 o_rst_fifo , 52 o_lcd_de_pro , 53 iv_lcd_data 54
55 //*********
56 ); 57
58
59 input clk ; 60 input reset_n ; 61 //******** LCD 接口
62 output [7 :0] ov_lcd_r ; 63 output [7 :0] ov_lcd_g ; 64 output [7 :0] ov_lcd_b ; 65 output o_lcd_hsync ; 66 output o_lcd_vsync ; 67 output o_lcd_dclk ; 68 output o_lcd_disp ; 69 output o_lcd_de ; 70 output o_lcd_pwm ; 71 output [31 :0] ov_addr ; 72 //********
73 output o_rst_fifo ; 74 output o_lcd_de_pro ; 75 input [31 :0] iv_lcd_data ; 76 reg o_lcd_de ; 77 reg [15 :0] count_clk ; 78 reg [7 :0] count_clkh ; 79 reg w_vsync ; 80 reg w_hsync ; 81 reg [31 :0] test_data ; 82 reg flag_run ; 83 reg [5 :0] count_vsync ; 84 reg flag_vsync ; 85 reg flag_black ; 86 reg flag_white ; 87 reg flag_1s ; 88
89 reg [15 :0] count_clk2 ; 90 reg [1 :0] hsync_dly ; 91 reg [1 :0] vsync_dly ; 92 reg [15 :0] count_hsync ; 93 reg de_signal ; 94 reg de_signal_pro ; 95
96 reg flag_r ; 97 reg flag_g ; 98 reg flag_b ; 99
100 assign o_lcd_dclk = clk ; 101 assign o_lcd_disp = 1'b1 ;
102 assign o_lcd_pwm = count_clk[15] ; 103 assign o_rst_fifo = w_vsync ; 104 assign ov_addr = 32'h3e4fff80 ;
105
106 assign ov_lcd_b = iv_lcd_data[7 :0 ] ; 107 assign ov_lcd_g = iv_lcd_data[15 :8 ] ; 108 assign ov_lcd_r = iv_lcd_data[23 :16] ; 109
110
111 //assign ov_lcd_b = flag_b ? 8'hff : 8'h0; 112 //assign ov_lcd_g = flag_g ? 8'hff : 8'h0; 113 //assign ov_lcd_r = flag_r ? 8'hff : 8'h0;
114
115 assign o_lcd_hsync = w_hsync ; 116 assign o_lcd_vsync = w_vsync ; 117 assign o_lcd_de_pro = de_signal_pro ; 118
119 always@(posedge clk or negedge reset_n) 120 if(!reset_n) 121 flag_r <= 1'b0 ;
122 else if(count_clk2 >= 16'd373 && count_clk2 <= 16'd373) 123 flag_r <= 1'b1 ;
124 else
125 flag_r <= 1'b0 ;
126
127 always@(posedge clk or negedge reset_n) 128 begin
129 if(!reset_n) 130 flag_g <= 1'b0 ;
131 else if(count_clk2 >16'd373 && count_clk2 <= 16'd613) 132 flag_g <= 1'b1 ;
133 else
134 flag_g <= 1'b0 ;
135 end
136
137 always@(posedge clk or negedge reset_n) 138 begin
139 if(!reset_n) 140 flag_b <= 1'b0 ;
141 else if(count_clk2 > 16'd613)
142 flag_b <= 1'b1 ;
143 else
144 flag_b <= 1'b0 ;
145 end
146
147
148 always@(posedge clk) 149 begin
150 hsync_dly <= {hsync_dly[0],w_hsync} ; 151 vsync_dly <= {vsync_dly[0],w_vsync} ; 152 end
153
154 always@(posedge clk or negedge reset_n) 155 begin
156 if(!reset_n) 157 count_clk <= 16'd0 ;
158 else
159 count_clk <= count_clk + 16'd1 ;
160 end
161
162 always@(posedge clk or negedge reset_n) 163 begin
164 if(~reset_n) 165 test_data <= 32'b0 ;
166 else if(vsync_dly == 2'b01 && count_vsync == 6'd20) 167 test_data <= test_data + 32'h55aa11 ;
168 else
169 test_data <= test_data ; 170 end
171
172 always@(posedge clk or negedge reset_n) 173 begin
174 if(~reset_n) 175 count_vsync <= 6'b0 ;
176 else if(vsync_dly == 2'b01)
177 count_vsync <= count_vsync + 6'b1 ;
178 else
179 count_vsync <= count_vsync ; 180 end
181
182 //******** 行内计数
183 always@(posedge clk or negedge reset_n) 184 begin
185 if(!reset_n) 186 count_clk2 <= 16'd0 ;
187 else if(count_clk2 == (HSYNC_NUM + H_BLACKING + H_FRONT_PORCH - 16'd1))
188 count_clk2 <= 16'd0 ;
189 else
190 count_clk2 <= count_clk2 + 16'd1 ;
191 end
192
193
194 //******** 产生行信号
195 always@(posedge clk or negedge reset_n) 196 begin
197 if(!reset_n) 198 w_hsync <= 1'b0 ;
199 else if(count_clk2 == (HS_PULSE_WIDTH - 16'd1) )
200 w_hsync <= 1'b1 ;
201 else if(count_clk2 == (HSYNC_NUM + H_BLACKING + H_FRONT_PORCH - 16'd1))
202 w_hsync <= 1'b0 ;
203 else
204 w_hsync <= w_hsync ; 205 end
206
207 always@(posedge clk or negedge reset_n) 208 begin
209 if(!reset_n) 210 de_signal_pro <= 1'b0 ;
211 else if(count_clk2 == (H_BLACKING - 16'd2) && count_hsync >= V_BLACKING && count_hsync < (VSYNC_NUM + V_BLACKING) )
212 de_signal_pro <= 1'b1 ;
213 else if(count_clk2 == (HSYNC_NUM + H_BLACKING - 16'd2))
214 de_signal_pro <= 1'b0 ;
215 else
216 de_signal_pro <= de_signal_pro ; 217 end
218
219
220 always@(posedge clk or negedge reset_n) 221 begin
222 if(!reset_n) 223 o_lcd_de <= 1'b0 ;
224 else
225 o_lcd_de <= de_signal_pro ; 226 end
227
228 //******** 计数列信号
229 always@(posedge clk or negedge reset_n) 230 begin
231 if(!reset_n) 232 count_hsync <= 12'd0 ;
233 else if(count_hsync == (VSYNC_NUM + V_BLACKING + V_FRONT_PORCH)) 234 count_hsync <= 12'd0 ;
235 else if(hsync_dly == 2'b10)
236 count_hsync <= count_hsync + 12'd1 ;
237 else
238 count_hsync <= count_hsync ; 239 end
240
241 //******** 产生列信号
242 always@(posedge clk or negedge reset_n) 243 begin
244 if(!reset_n) 245 w_vsync <= 1'b0 ;
246 else if(count_hsync == (VSYNC_NUM + V_BLACKING + V_FRONT_PORCH - 16'd1) && count_clk2 == (HSYNC_NUM + H_BLACKING + H_FRONT_PORCH - 16'd2) ) 247 w_vsync <= 1'b0 ;
248 else if(count_hsync == VS_PULSE_WIDTH && count_clk2 == 16'd20 )
249 w_vsync <= 1'b1 ;
250 else
251 w_vsync <= w_vsync ; 252 end
253
254 endmodule
注:转载请注明出处,否则保留追究法律责任的权利。如果觉得还有帮助的话,请记得推荐下!