http://www.cnblogs.com/oomusou/archive/2008/10/24/de2_70_rgb16.html
Abstract
在數位視訊系統中,SDRAM扮演CMOS與LCD之間frame buffer的腳色,但若SDRAM另用他用,只好將RGB以16 bit方式存入SDRAM,將節省下來的空間做其他用途。
Introduction
使用環境:Quartus II 8.0 SP1 + DE2-70 (Cyclone II EP2C70F896C6N) + TRDB-D5M + TRDB-LTM
以RGB16(R5G6B5)的方式存入SDRAM的方式並不是我所創,在友晶提供的DE2_CCD_detect範例中,因為要做motion detection,要用前後兩個frame的資料做比對,所以整個SDRAM不能全部做成CMOS與VGA的frame buffer,必須有一塊區域存前一個frame的資料,而DE2又只有一顆8MB SDRAM,所以2個write port與2個read port不能全部用盡,CMOS與VGA只能占用1個write port與read port,而SDRAM的寬度為16 bit,所以只能以RGB16存進SDRAM。
或許你會有疑問,以RGB16來處理,不會失真嗎?理論上是會失真,不過由於是取高5 bit處理,所以還可接受,以下是用RGB16與RGB32結果的比較
左側為RGB16、右側為RGB32
兩張圖是有一點點差距,不過大體上來說還可以接受,若你用的是DE2,因為只有一顆8MB SDRAM,就只能靠RGB16的方式,才能讓SDRAM還能放其他的資料,而不讓2個write port與2個read port全被RGB32占滿,當然若你用的是DE2-70,因為有兩顆SDRAM,就沒這種問題。
網友族就剛好遇到需要用RGB16的狀況,不過它的環境是DE2 + TRDB-D5M + TRDB-LTM,但因為我用的是DE2-70的三合一套件,也就是DE2-70 + TRDB-D5M + TRDB-LTM,所以我只能用DE2-70模擬DE2只有一顆SDRAM的狀況,然後使用RGB16的方式存入SDRAM。
Top Module部分
DE2_70.v / Verilog
2 (C) OOMusou 2008 http://oomusou.cnblogs.com
3
4 Filename : DE2_70.v
5 Compiler : Quartus II 8.0 SP1
6 Description : Demo how to use TRDB-D5M with LTM on DE2-70 with RGB16
7 Release : 10/24/2008 1.0
8 */
9
10 module DE2_70 (
11 Clock Input
12 input iCLK_28, // 28.63636 MHz
13 input iCLK_50, // 50 MHz
14 input iCLK_50_2, // 50 MHz
15 input iCLK_50_3, // 50 MHz
16 input iCLK_50_4, // 50 MHz
17 input iEXT_CLOCK, // External Clock
18 Push Button
19 input [ 3 : 0 ] iKEY, // Pushbutton[3:0]
20 DPDT Switch
21 input [ 17 : 0 ] iSW, // Toggle Switch[17:0]
22 7-SEG Dispaly
23 output [ 6 : 0 ] oHEX0_D, // Seven Segment Digit 0
24 output oHEX0_DP, // Seven Segment Digit 0 decimal point
25 output [ 6 : 0 ] oHEX1_D, // Seven Segment Digit 1
26 output oHEX1_DP, // Seven Segment Digit 1 decimal point
27 output [ 6 : 0 ] oHEX2_D, // Seven Segment Digit 2
28 output oHEX2_DP, // Seven Segment Digit 2 decimal point
29 output [ 6 : 0 ] oHEX3_D, // Seven Segment Digit 3
30 output oHEX3_DP, // Seven Segment Digit 3 decimal point
31 output [ 6 : 0 ] oHEX4_D, // Seven Segment Digit 4
32 output oHEX4_DP, // Seven Segment Digit 4 decimal point
33 output [ 6 : 0 ] oHEX5_D, // Seven Segment Digit 5
34 output oHEX5_DP, // Seven Segment Digit 5 decimal point
35 output [ 6 : 0 ] oHEX6_D, // Seven Segment Digit 6
36 output oHEX6_DP, // Seven Segment Digit 6 decimal point
37 output [ 6 : 0 ] oHEX7_D, // Seven Segment Digit 7
38 output oHEX7_DP, // Seven Segment Digit 7 decimal point
39 /// / LED /// /
40 output [ 8 : 0 ] oLEDG, // LED Green[8:0]
41 output [ 17 : 0 ] oLEDR, // LED Red[17:0]
42 /// / UART /// /
43 output oUART_TXD, // UART Transmitter
44 input iUART_RXD, // UART Receiver
45 output oUART_CTS, // UART Clear To Send
46 input iUART_RTS, // UART Requst To Send
47 /// / IRDA /// /
48 output oIRDA_TXD, // IRDA Transmitter
49 input iIRDA_RXD, // IRDA Receiver
50 / // SDRAM Interface
51 inout [ 31 : 0 ] DRAM_DQ, // SDRAM Data bus 32 Bits
52 output [ 12 : 0 ] oDRAM0_A, // SDRAM0 Address bus 13 Bits
53 output [ 12 : 0 ] oDRAM1_A, // SDRAM1 Address bus 13 Bits
54 output oDRAM0_LDQM0, // SDRAM0 Low-byte Data Mask
55 output oDRAM1_LDQM0, // SDRAM1 Low-byte Data Mask
56 output oDRAM0_UDQM1, // SDRAM0 High-byte Data Mask
57 output oDRAM1_UDQM1, // SDRAM1 High-byte Data Mask
58 output oDRAM0_WE_N, // SDRAM0 Write Enable
59 output oDRAM1_WE_N, // SDRAM1 Write Enable
60 output oDRAM0_CAS_N, // SDRAM0 Column Address Strobe
61 output oDRAM1_CAS_N, // SDRAM1 Column Address Strobe
62 output oDRAM0_RAS_N, // SDRAM0 Row Address Strobe
63 output oDRAM1_RAS_N, // SDRAM1 Row Address Strobe
64 output oDRAM0_CS_N, // SDRAM0 Chip Select
65 output oDRAM1_CS_N, // SDRAM1 Chip Select
66 output [ 1 : 0 ] oDRAM0_BA, // SDRAM0 Bank Address
67 output [ 1 : 0 ] oDRAM1_BA, // SDRAM1 Bank Address
68 output oDRAM0_CLK, // SDRAM0 Clock
69 output oDRAM1_CLK, // SDRAM1 Clock
70 output oDRAM0_CKE, // SDRAM0 Clock Enable
71 output oDRAM1_CKE, // SDRAM1 Clock Enable
72 Flash Interface
73 inout [ 14 : 0 ] FLASH_DQ, // FLASH Data bus 15 Bits (0 to 14)
74 inout FLASH_DQ15_AM1, // FLASH Data bus Bit 15 or Address A-1
75 output [ 21 : 0 ] oFLASH_A, // FLASH Address bus 26 Bits
76 output oFLASH_WE_N, // FLASH Write Enable
77 output oFLASH_RST_N, // FLASH Reset
78 output oFLASH_WP_N, // FLASH Write Protect /Programming Acceleration
79 input iFLASH_RY_N, // FLASH Ready/Busy output
80 output oFLASH_BYTE_N, // FLASH Byte/Word Mode Configuration
81 output oFLASH_OE_N, // FLASH Output Enable
82 output oFLASH_CE_N, // FLASH Chip Enable
83 SRAM Interface
84 inout [ 31 : 0 ] SRAM_DQ, // SRAM Data Bus 32 Bits
85 inout [ 3 : 0 ] SRAM_DPA, // SRAM Parity Data Bus
86 output [ 18 : 0 ] oSRAM_A, // SRAM Address bus 21 Bits
87 output oSRAM_ADSC_N, // SRAM Controller Address Status
88 output oSRAM_ADSP_N, // SRAM Processor Address Status
89 output oSRAM_ADV_N, // SRAM Burst Address Advance
90 output [ 3 : 0 ] oSRAM_BE_N, // SRAM Byte Write Enable
91 output oSRAM_CE1_N, // SRAM Chip Enable
92 output oSRAM_CE2, // SRAM Chip Enable
93 output oSRAM_CE3_N, // SRAM Chip Enable
94 output oSRAM_CLK, // SRAM Clock
95 output oSRAM_GW_N, // SRAM Global Write Enable
96 output oSRAM_OE_N, // SRAM Output Enable
97 output oSRAM_WE_N, // SRAM Write Enable
98 // // ISP1362 Interface
99 inout [ 15 : 0 ] OTG_D, // ISP1362 Data bus 16 Bits
100 output [ 1 : 0 ] oOTG_A, // ISP1362 Address 2 Bits
101 output oOTG_CS_N, // ISP1362 Chip Select
102 output oOTG_OE_N, // ISP1362 Read
103 output oOTG_WE_N, // ISP1362 Write
104 output oOTG_RESET_N, // ISP1362 Reset
105 inout OTG_FSPEED, // USB Full Speed, 0 = Enable, Z = Disable
106 inout OTG_LSPEED, // USB Low Speed, 0 = Enable, Z = Disable
107 input iOTG_INT0, // ISP1362 Interrupt 0
108 input iOTG_INT1, // ISP1362 Interrupt 1
109 input iOTG_DREQ0, // ISP1362 DMA Request 0
110 input iOTG_DREQ1, // ISP1362 DMA Request 1
111 output oOTG_DACK0_N, // ISP1362 DMA Acknowledge 0
112 output oOTG_DACK1_N, // ISP1362 DMA Acknowledge 1
113 // // LCD Module 16X2 /// /
114 inout [ 7 : 0 ] LCD_D, // LCD Data bus 8 bits
115 output oLCD_ON, // LCD Power ON/OFF
116 output oLCD_BLON, // LCD Back Light ON/OFF
117 output oLCD_RW, // LCD Read/Write Select, 0 = Write, 1 = Read
118 output oLCD_EN, // LCD Enable
119 output oLCD_RS, // LCD Command/Data Select, 0 = Command, 1 = Data
120 // // SD Card Interface
121 inout SD_DAT, // SD Card Data
122 inout SD_DAT3, // SD Card Data 3
123 inout SD_CMD, // SD Card Command Signal
124 output oSD_CLK, // SD Card Clock
125 I2C // //
126 inout I2C_SDAT, // I2C Data
127 output oI2C_SCLK, // I2C Clock
128 PS2 // //
129 inout PS2_KBDAT, // PS2 Keyboard Data
130 inout PS2_KBCLK, // PS2 Keyboard Clock
131 inout PS2_MSDAT, // PS2 Mouse Data
132 inout PS2_MSCLK, // PS2 Mouse Clock
133 VGA /// /
134 output oVGA_CLOCK, // VGA Clock
135 output oVGA_HS, // VGA H_SYNC
136 output oVGA_VS, // VGA V_SYNC
137 output oVGA_BLANK_N, // VGA BLANK
138 output oVGA_SYNC_N, // VGA SYNC
139 output [ 9 : 0 ] oVGA_R, // VGA Red[9:0]
140 output [ 9 : 0 ] oVGA_G, // VGA Green[9:0]
141 output [ 9 : 0 ] oVGA_B, // VGA Blue[9:0]
142 /// / Ethernet Interface /// /
143 inout [ 15 : 0 ] ENET_D, // DM9000A DATA bus 16Bits
144 output oENET_CMD, // DM9000A Command/Data Select, 0 = Command, 1 = Data
145 output oENET_CS_N, // DM9000A Chip Select
146 output oENET_IOW_N, // DM9000A Write
147 output oENET_IOR_N, // DM9000A Read
148 output oENET_RESET_N, // DM9000A Reset
149 input iENET_INT, // DM9000A Interrupt
150 output oENET_CLK, // DM9000A Clock 25 MHz
151 // // Audio CODEC /// /
152 inout AUD_ADCLRCK, // Audio CODEC ADC LR Clock
153 input iAUD_ADCDAT, // Audio CODEC ADC Data
154 inout AUD_DACLRCK, // Audio CODEC DAC LR Clock
155 output oAUD_DACDAT, // Audio CODEC DAC Data
156 inout AUD_BCLK, // Audio CODEC Bit-Stream Clock
157 output oAUD_XCK, // Audio CODEC Chip Clock
158 // // TV Devoder /// /
159 input iTD1_CLK27, // TV Decoder1 Line_Lock Output Clock
160 input [ 7 : 0 ] iTD1_D, // TV Decoder1 Data bus 8 bits
161 input iTD1_HS, // TV Decoder1 H_SYNC
162 input iTD1_VS, // TV Decoder1 V_SYNC
163 output oTD1_RESET_N, // TV Decoder1 Reset
164 input iTD2_CLK27, // TV Decoder2 Line_Lock Output Clock
165 input [ 7 : 0 ] iTD2_D, // TV Decoder2 Data bus 8 bits
166 input iTD2_HS, // TV Decoder2 H_SYNC
167 input iTD2_VS, // TV Decoder2 V_SYNC
168 output oTD2_RESET_N, // TV Decoder2 Reset
169 GPIO // //
170 inout [ 31 : 0 ] GPIO_0, // GPIO Connection 0 I/O
171 input GPIO_CLKIN_N0, // GPIO Connection 0 Clock Input 0
172 input GPIO_CLKIN_P0, // GPIO Connection 0 Clock Input 1
173 inout GPIO_CLKOUT_N0, // GPIO Connection 0 Clock Output 0
174 inout GPIO_CLKOUT_P0, // GPIO Connection 0 Clock Output 1
175 inout [ 31 : 0 ] GPIO_1, // GPIO Connection 1 I/O
176 input GPIO_CLKIN_N1, // GPIO Connection 1 Clock Input 0
177 input GPIO_CLKIN_P1, // GPIO Connection 1 Clock Input 1
178 inout GPIO_CLKOUT_N1, // GPIO Connection 1 Clock Output 0
179 inout GPIO_CLKOUT_P1 // GPIO Connection 1 Clock Output 1
180 );
181
182 // CCD
183 wire [ 11 : 0 ] CCD_DATA;
184 wire CCD_SDAT;
185 wire CCD_SCLK;
186 wire CCD_FLASH;
187 wire CCD_FVAL;
188 wire CCD_LVAL;
189 wire CCD_PIXCLK;
190 wire CCD_MCLK; // CCD Master Clock
191
192 wire [ 15 : 0 ] Read_DATA1;
193 wire [ 15 : 0 ] Read_DATA2;
194 wire [ 15 : 0 ] Read_DATA3; // add by oomusou for RGB16
195 wire [ 15 : 0 ] Read_DATA4; // add by oomusou for RGB16
196 wire VGA_CTRL_CLK;
197 wire [ 11 : 0 ] mCCD_DATA;
198 wire mCCD_DVAL;
199 wire mCCD_DVAL_d;
200 wire [ 15 : 0 ] X_Cont;
201 wire [ 15 : 0 ] Y_Cont;
202 wire [ 9 : 0 ] X_ADDR;
203 wire [ 31 : 0 ] Frame_Cont;
204 wire DLY_RST_0;
205 wire DLY_RST_1;
206 wire DLY_RST_2;
207 wire Read;
208 reg [ 11 : 0 ] rCCD_DATA;
209 reg rCCD_LVAL;
210 reg rCCD_FVAL;
211 wire [ 11 : 0 ] sCCD_R;
212 wire [ 11 : 0 ] sCCD_G;
213 wire [ 11 : 0 ] sCCD_B;
214 wire sCCD_DVAL;
215 reg [ 1 : 0 ] rClk;
216 wire sdram_ctrl_clk;
217
218 // Touch panel signal
219 wire [ 7 : 0 ] ltm_r; // LTM Red Data 8 Bits
220 wire [ 7 : 0 ] ltm_g; // LTM Green Data 8 Bits
221 wire [ 7 : 0 ] ltm_b; // LTM Blue Data 8 Bits
222 wire ltm_nclk; // LTM Clcok
223 wire ltm_hd;
224 wire ltm_vd;
225 wire ltm_den;
226 wire adc_dclk;
227 wire adc_cs;
228 wire adc_penirq_n;
229 wire adc_busy;
230 wire adc_din;
231 wire adc_dout;
232 wire adc_ltm_sclk;
233 wire ltm_grst;
234
235 // LTM Config
236 wire ltm_sclk;
237 wire ltm_sda;
238 wire ltm_scen;
239 wire ltm_3wirebusy_n;
240
241 assign CCD_DATA[ 0 ] = GPIO_1[ 11 ];
242 assign CCD_DATA[ 1 ] = GPIO_1[ 10 ];
243 assign CCD_DATA[ 2 ] = GPIO_1[ 9 ];
244 assign CCD_DATA[ 3 ] = GPIO_1[ 8 ];
245 assign CCD_DATA[ 4 ] = GPIO_1[ 7 ];
246 assign CCD_DATA[ 5 ] = GPIO_1[ 6 ];
247 assign CCD_DATA[ 6 ] = GPIO_1[ 5 ];
248 assign CCD_DATA[ 7 ] = GPIO_1[ 4 ];
249 assign CCD_DATA[ 8 ] = GPIO_1[ 3 ];
250 assign CCD_DATA[ 9 ] = GPIO_1[ 2 ];
251 assign CCD_DATA[ 10 ] = GPIO_1[ 1 ];
252 assign CCD_DATA[ 11 ] = GPIO_1[ 0 ];
253 assign GPIO_CLKOUT_N1 = CCD_MCLK;
254 assign CCD_FVAL = GPIO_1[ 18 ];
255 assign CCD_LVAL = GPIO_1[ 17 ];
256 assign CCD_PIXCLK = GPIO_CLKIN_N1;
257 assign GPIO_1[ 15 ] = 1 ' b1; // tRIGGER
258 assign GPIO_1[ 14 ] = DLY_RST_1;
259
260 assign oLEDR = iSW;
261 assign oLEDG = Y_Cont;
262
263 assign oTD1_RESET_N = 1 ' b1;
264 assign oVGA_CLOCK = ~ VGA_CTRL_CLK;
265
266 assign CCD_MCLK = rClk[ 0 ];
267 assign oUART_TXD = iUART_RXD;
268
269 assign adc_penirq_n = GPIO_CLKIN_N0;
270 assign adc_dout = GPIO_0[ 0 ];
271 assign adc_busy = GPIO_CLKIN_P0;
272 assign GPIO_0[ 1 ] = adc_din;
273 assign GPIO_0[ 2 ] = adc_ltm_sclk;
274 assign GPIO_0[ 3 ] = ltm_b[ 3 ];
275 assign GPIO_0[ 4 ] = ltm_b[ 2 ];
276 assign GPIO_0[ 5 ] = ltm_b[ 1 ];
277 assign GPIO_0[ 6 ] = ltm_b[ 0 ];
278 assign GPIO_0[ 7 ] =~ ltm_nclk;
279 assign GPIO_0[ 8 ] = ltm_den;
280 assign GPIO_0[ 9 ] = ltm_hd;
281 assign GPIO_0[ 10 ] = ltm_vd;
282 assign GPIO_0[ 11 ] = ltm_b[ 4 ];
283 assign GPIO_0[ 12 ] = ltm_b[ 5 ];
284 assign GPIO_0[ 13 ] = ltm_b[ 6 ];
285 assign GPIO_CLKOUT_N0 = ltm_b[ 7 ];
286 assign GPIO_0[ 14 ] = ltm_g[ 0 ];
287 assign GPIO_CLKOUT_P0 = ltm_g[ 1 ];
288 assign GPIO_0[ 15 ] = ltm_g[ 2 ];
289 assign GPIO_0[ 16 ] = ltm_g[ 3 ];
290 assign GPIO_0[ 17 ] = ltm_g[ 4 ];
291 assign GPIO_0[ 18 ] = ltm_g[ 5 ];
292 assign GPIO_0[ 19 ] = ltm_g[ 6 ];
293 assign GPIO_0[ 20 ] = ltm_g[ 7 ];
294 assign GPIO_0[ 21 ] = ltm_r[ 0 ];
295 assign GPIO_0[ 22 ] = ltm_r[ 1 ];
296 assign GPIO_0[ 23 ] = ltm_r[ 2 ];
297 assign GPIO_0[ 24 ] = ltm_r[ 3 ];
298 assign GPIO_0[ 25 ] = ltm_r[ 4 ];
299 assign GPIO_0[ 26 ] = ltm_r[ 5 ];
300 assign GPIO_0[ 27 ] = ltm_r[ 6 ];
301 assign GPIO_0[ 28 ] = ltm_r[ 7 ];
302 assign GPIO_0[ 29 ] = ltm_grst;
303 assign GPIO_0[ 30 ] = ltm_scen;
304 assign GPIO_0[ 31 ] = ltm_sda;
305
306 assign ltm_grst = iKEY[ 0 ];
307 assign adc_ltm_sclk = ltm_sclk;
308
309 always @( posedge iCLK_50)
310 rClk <= rClk + 1 ;
311
312 always @( posedge CCD_PIXCLK) begin
313 rCCD_DATA <= CCD_DATA;
314 rCCD_LVAL <= CCD_LVAL;
315 rCCD_FVAL <= CCD_FVAL;
316 end
317
318 Reset_Delay reset0 (
319 .iCLK(iCLK_50),
320 .iRST(iKEY[ 0 ]),
321 .oRST_0(DLY_RST_0),
322 .oRST_1(DLY_RST_1),
323 .oRST_2(DLY_RST_2)
324 );
325
326 CCD_Capture capture0 (
327 .oDATA(mCCD_DATA),
328 .oDVAL(mCCD_DVAL),
329 .oX_Cont(X_Cont),
330 .oY_Cont(Y_Cont),
331 .oFrame_Cont(Frame_Cont),
332 .iDATA(rCCD_DATA),
333 .iFVAL(rCCD_FVAL),
334 .iLVAL(rCCD_LVAL),
335 .iSTART( ! iKEY[ 3 ]),
336 .iEND( ! iKEY[ 2 ]),
337 .iCLK(CCD_PIXCLK),
338 .iRST(DLY_RST_2)
339 );
340
341 RAW2RGB rgb0 (
342 .iCLK(CCD_PIXCLK),
343 .iRST_n(DLY_RST_1),
344 .iData(mCCD_DATA),
345 .iDval(mCCD_DVAL),
346 .oRed(sCCD_R),
347 .oGreen(sCCD_G),
348 .oBlue(sCCD_B),
349 .oDval(sCCD_DVAL),
350 .iMIRROR(iSW[ 17 ]),
351 .iX_Cont(X_Cont),
352 .iY_Cont(Y_Cont)
353 );
354
355 SEG7_LUT_8 seg0 (
356 .oSEG0(oHEX0_D),
357 .oSEG1(oHEX1_D),
358 .oSEG2(oHEX2_D),
359 .oSEG3(oHEX3_D),
360 .oSEG4(oHEX4_D),
361 .oSEG5(oHEX5_D),
362 .oSEG6(oHEX6_D),
363 .oSEG7(oHEX7_D),
364 .iDIG(Frame_Cont[ 31 : 0 ])
365 );
366
367 vga_pll vga_pll0 (
368 .inclk0(iCLK_50_2),
369 .c0(ltm_nclk)
370 );
371
372 sdram_pll sdram_pll0 (
373 .inclk0(iCLK_50_3),
374 .c0(sdram_ctrl_clk),
375 .c1(oDRAM0_CLK),
376 .c2(oDRAM1_CLK)
377 );
378
379 Sdram_Control_4Port sdram0 (
380 // HOST Side
381 .REF_CLK(iCLK_50),
382 .RESET_N( 1 ' b1),
383 .CLK(sdram_ctrl_clk),
384 // FIFO Write Side 1
385 .WR1_DATA({sCCD_R[ 11 : 7 ], sCCD_G[ 11 : 6 ], sCCD_B[ 11 : 7 ]}),
386 .WR1(sCCD_DVAL),
387 .WR1_ADDR( 0 ),
388 .WR1_MAX_ADDR( 800 * 480 ),
389 .WR1_LENGTH( 9 ' h100),
390 .WR1_LOAD( ! DLY_RST_0),
391 .WR1_CLK(CCD_PIXCLK),
392 // FIFO Write Side 1
393 .WR2_DATA({sCCD_R[ 11 : 7 ], sCCD_G[ 11 : 6 ], sCCD_B[ 11 : 7 ]}),
394 .WR2(sCCD_DVAL),
395 .WR2_ADDR( 22 ' h100000),
396 .WR2_MAX_ADDR( 22 ' h100000 + 800*480),
397 .WR2_LENGTH( 9 ' h100),
398 .WR2_LOAD( ! DLY_RST_0),
399 .WR2_CLK(CCD_PIXCLK),
400 // FIFO Read Side 1 to LTM
401 .RD1_DATA(Read_DATA3),
402 .RD1(Read),
403 .RD1_ADDR( 0 ),
404 .RD1_MAX_ADDR( 800 * 480 ),
405 .RD1_LENGTH( 9 ' h100),
406 .RD1_LOAD( ! DLY_RST_0),
407 .RD1_CLK( ~ ltm_nclk),
408 // FIFO Read Side 1
409 .RD2_DATA(Read_DATA4),
410 .RD2(Read),
411 .RD2_ADDR( 22 ' h100000 + 800*480 + 200),
412 .RD2_MAX_ADDR( 22 ' h100000 + 800*480 + 300),
413 .RD2_LENGTH( 9 ' h100),
414 .RD2_LOAD( ! DLY_RST_0),
415 .RD2_CLK( ~ ltm_nclk),
416 // SDRAM Side
417 .SA(oDRAM0_A[ 11 : 0 ]),
418 .BA(oDRAM0_BA),
419 .CS_N(oDRAM0_CS_N),
420 .CKE(oDRAM0_CKE),
421 .RAS_N(oDRAM0_RAS_N),
422 .CAS_N(oDRAM0_CAS_N),
423 .WE_N(oDRAM0_WE_N),
424 .DQ(DRAM_DQ[ 15 : 0 ]),
425 .DQM({oDRAM0_UDQM1,oDRAM0_LDQM0})
426 );
427
428 // add by oomusou for RGB16
429 assign Read_DATA1 = {Read_DATA3[ 10 : 6 ], Read_DATA3[ 4 : 0 ], 5 ' h00};
430 assign Read_DATA2 = {Read_DATA3[ 5 : 5 ], 4 ' h0, Read_DATA3[15:11], 5 ' h00};
431
432 I2C_CCD_Config ccd_config0 (
433 // Host Side
434 .iCLK(iCLK_50),
435 .iRST_N(DLY_RST_1),
436 .iEXPOSURE_ADJ(iKEY[ 1 ]),
437 .iEXPOSURE_DEC_p(iSW[ 0 ]),
438 .iMIRROR_SW(iSW[ 17 ]),
439 // I2C Side
440 .I2C_SCLK(GPIO_1[ 20 ]),
441 .I2C_SDAT(GPIO_1[ 19 ])
442 );
443
444 touch_tcon tcon0 (
445 .iCLK(ltm_nclk),
446 .iRST_n(DLY_RST_2),
447 // sdram side
448 .iREAD_DATA1(Read_DATA1),
449 .iREAD_DATA2(Read_DATA2),
450 .oREAD_SDRAM_EN(Read),
451 // lcd side
452 .oLCD_R(ltm_r),
453 .oLCD_G(ltm_g),
454 .oLCD_B(ltm_b),
455 .oHD(ltm_hd),
456 .oVD(ltm_vd),
457 .oDEN(ltm_den)
458 );
459
460 lcd_3wire_config wire0 (
461 // Host Side
462 .iCLK(iCLK_50),
463 .iRST_n(DLY_RST_0),
464 // 3 wire Side
465 .o3WIRE_SCLK(ltm_sclk),
466 .io3WIRE_SDAT(ltm_sda),
467 .o3WIRE_SCEN(ltm_scen),
468 .o3WIRE_BUSY_n(ltm_3wirebusy_n)
469 );
470
471 endmodule
379行
// HOST Side
.REF_CLK(iCLK_50),
.RESET_N( 1 ' b1),
.CLK(sdram_ctrl_clk),
// FIFO Write Side 1
.WR1_DATA({sCCD_R[ 11 : 7 ], sCCD_G[ 11 : 6 ], sCCD_B[ 11 : 7 ]}),
.WR1(sCCD_DVAL),
.WR1_ADDR( 0 ),
.WR1_MAX_ADDR( 800 * 480 ),
.WR1_LENGTH( 9 ' h100),
.WR1_LOAD( ! DLY_RST_0),
.WR1_CLK(CCD_PIXCLK),
// FIFO Write Side 1
.WR2_DATA({sCCD_R[ 11 : 7 ], sCCD_G[ 11 : 6 ], sCCD_B[ 11 : 7 ]}),
.WR2(sCCD_DVAL),
.WR2_ADDR( 22 ' h100000),
.WR2_MAX_ADDR( 22 ' h100000 + 800*480),
.WR2_LENGTH( 9 ' h100),
.WR2_LOAD( ! DLY_RST_0),
.WR2_CLK(CCD_PIXCLK),
// FIFO Read Side 1 to LTM
.RD1_DATA(Read_DATA3),
.RD1(Read),
.RD1_ADDR( 0 ),
.RD1_MAX_ADDR( 800 * 480 ),
.RD1_LENGTH( 9 ' h100),
.RD1_LOAD( ! DLY_RST_0),
.RD1_CLK( ~ ltm_nclk),
// FIFO Read Side 1
.RD2_DATA(Read_DATA4),
.RD2(Read),
.RD2_ADDR( 22 ' h100000 + 800*480 + 200),
.RD2_MAX_ADDR( 22 ' h100000 + 800*480 + 300),
.RD2_LENGTH( 9 ' h100),
.RD2_LOAD( ! DLY_RST_0),
.RD2_CLK( ~ ltm_nclk),
// SDRAM Side
.SA(oDRAM0_A[ 11 : 0 ]),
.BA(oDRAM0_BA),
.CS_N(oDRAM0_CS_N),
.CKE(oDRAM0_CKE),
.RAS_N(oDRAM0_RAS_N),
.CAS_N(oDRAM0_CAS_N),
.WE_N(oDRAM0_WE_N),
.DQ(DRAM_DQ[ 15 : 0 ]),
.DQM({oDRAM0_UDQM1,oDRAM0_LDQM0})
);
原來在DE2_70_D5M_LTM中,是使用2顆SDRAM來做frame buffer,為了模擬DE2的1顆SDRAM,所以我只用了一個Sdram_Control_4Port。
384行
.WR1_DATA({sCCD_R[ 11 : 7 ], sCCD_G[ 11 : 6 ], sCCD_B[ 11 : 7 ]}),
.WR1(sCCD_DVAL),
.WR1_ADDR( 0 ),
.WR1_MAX_ADDR( 800 * 480 ),
.WR1_LENGTH( 9 ' h100),
.WR1_LOAD( ! DLY_RST_0),
.WR1_CLK(CCD_PIXCLK),
.WR1_DATA為16 bit,使用RGB16(R5G6B5)的方式傳入,不一定得跟我一樣使用R5G6B5的方式,若你要R5G5G5也可以,反正最多只能16 bit就好。
sCCD_R原來為12 bit,我只取高5 bit而以。
392行
.WR2_DATA({sCCD_R[ 11 : 7 ], sCCD_G[ 11 : 6 ], sCCD_B[ 11 : 7 ]}),
.WR2(sCCD_DVAL),
.WR2_ADDR( 22 ' h100000),
.WR2_MAX_ADDR( 22 ' h100000 + 800*480),
.WR2_LENGTH( 9 ' h100),
.WR2_LOAD( ! DLY_RST_0),
.WR2_CLK(CCD_PIXCLK),
FIFO Write Side 2就可以自由應用了,這裡之所以也傳入RGB16,是因為網友族想將capture的影像放在SDRAM的其他位置做處理,所以在此範例又傳入RGB16,只是address有所不同,實際可依你的需要善用FIFO Write Side 2。
400行
.RD1_DATA(Read_DATA3),
.RD1(Read),
.RD1_ADDR( 0 ),
.RD1_MAX_ADDR( 800 * 480 ),
.RD1_LENGTH( 9 ' h100),
.RD1_LOAD( ! DLY_RST_0),
.RD1_CLK( ~ ltm_nclk),
FIFO Read Side1負責將資料傳給LTM controller,注意我另外用了wire Read_DATA3,而不是原來的Read_DATA1,理由我稍後會做解釋。
408行
.RD2_DATA(Read_DATA4),
.RD2(Read),
.RD2_ADDR( 22 ' h100000 + 800*480 + 200),
.RD2_MAX_ADDR( 22 ' h100000 + 800*480 + 300),
.RD2_LENGTH( 9 ' h100),
.RD2_LOAD( ! DLY_RST_0),
.RD2_CLK( ~ ltm_nclk),
FIFO Read Side 1也可以自由應用,因為網友族想要解取部分影像,所以才這樣寫,實際可依你的需要善用FIFO Read Side 2。
444行
.iCLK(ltm_nclk),
.iRST_n(DLY_RST_2),
// sdram side
.iREAD_DATA1(Read_DATA1),
.iREAD_DATA2(Read_DATA2),
.oREAD_SDRAM_EN(Read),
// lcd side
.oLCD_R(ltm_r),
.oLCD_G(ltm_g),
.oLCD_B(ltm_b),
.oHD(ltm_hd),
.oVD(ltm_vd),
.oDEN(ltm_den)
);
這是LTM controller,需要傳入Read_DATA1與Read_DATA2,不過因為我們已經改用RGB16,在不更改touch_tcon module的前提下,我們需要對Read_DATA1與Read_DATA2做手腳。
428行
assign Read_DATA1 = {Read_DATA3[ 10 : 6 ], Read_DATA3[ 4 : 0 ], 5 ' h00};
assign Read_DATA2 = {Read_DATA3[ 5 : 5 ], 4 ' h0, Read_DATA3[15:11], 5 ' h00};
本文最關鍵的地方在這裡,原來的Read_DATA1是由{sCCD_G[11:7], sCCD_B[11:2]}所構成,而Read_DATA2是由{sCCD_G[6:2], sCCD_R[11:2]}所構成,但現在由Sdram_Control_4Port的RD1_DATA吐出來的是Read_DATA3,是由{sCCD_R[11:7], sCCD_G[11:6], sCCD_B[11:7]}所構成,所以必須將Read_DATA3轉換成Read_DATA1與Read_DATA2原本的格式,LTM才會顯示正常,否則會有色偏的情形。
由於RGB16取的是高5 bit,所以R/G/B的低5 bit必須補0,如此RGB皆以10 bit傳進LTM controller。
完整程式下載
DE2_70_D5M_LTM_RGB32.7z
DE2_70_D5M_LTM_RGB16.7z
Conclusion
藉由RGB16的方式,可以省下一半的SDRAM另做他用,而且畫質仍可接受,這種技巧在DE2這種只有1顆SDRAM的環境下非常有用。
See Also
(原創) 如何計算SDRAM使用頻寬? (SOC) (DE2) (DE2-70) (TRDB-DC2) (TRDB-D5M) (TRDB-LCM) (TRDB-LTM)