【原创】闫若川FPGA:TFT LCD液晶屏 FPGA 代码
【原创】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
注:转载请注明出处,否则保留追究法律责任的权利。如果觉得还有帮助的话,请记得推荐下!