Thiết kế hệ thống KIT DE2 của Altera
Trang 1Chương 4: Sơ lược hệ thống
Trang 33
PHẦN II: THIẾT KẾ HỆ THỐNG CHƯƠNG 4: SƠ LƯỢC HỆ THỐNG 4.1 YÊU CẦU
Tìm hiểu về các giải thuật xử lý ảnh
Ứng dụng giải thuật xử lý ảnh video vào phần cứng, cụ thể là mô tả phần cứng thực hiện giải thuật bằng ngôn ngữ Verilog HDL
Ứng dụng FPGAs để kiểm tra kết quả, đồng thời so sánh với kết quả với hình ảnh video ban đầu
4.2 NỘI DUNG THỰC HIỆN
Lấy nguồn tín hiệu video từ DVD ( VCD ) Player đưa vào kit DE2 của Altera qua cổng TV-IN
Sử dụng phần mềm Quartus II của Altera để viết chương trình bằng ngôn ngữ Verilog HDL và giao tiếp với kit DE2
Thiết kế khối lọc trung bình và dò biên cho ảnh ngõ ra bằng Verilog HDL
Giao tiếp với ADV7181B, VGA, SDRAM trên kit DE2
Hiển thị kết quả lên Monitor và so sánh với tín hiệu gốc
Trang 2Chương 4: Sơ lược hệ thống
Trang 34
4.3 SƠ ĐỒ THIẾT KẾ VÀ NGUYÊN LÝ HOẠT ĐỘNG
4.3.1 SƠ ĐỒ THIẾT KẾ
Hình 4.1: Sơ đồ hệ thống
4.3.2 NGUYÊN LÝ HOẠT ĐỘNG
Khối I2C_Video_Config: với giao thức giao tiếp I2C sẽ đặt giá trị cho các thanh ghi của bộ mã hóa ADV7181 để cấu hình hoạt động cho chip mã hóa này
Khối Timer trì hỗn ban đầu: Sau chuỗi khới động, ADV7181B rơi vào thời kì không ổn định, khối sẽ phát hiện thời kì không ổn định này rôiø tính toán thời điểm bắt đầu làm việc của các khối khác
Khối Desize_Horizon: Lấy ra chuỗi liên tục các Pixel trong dòng dữ liệu do ADV7181B xuất ra đồng thời định lại kích thước frame ảnh từ dạng 720 x 480 sang chuẩn VGA 640 x480
Trang 3Chương 4: Sơ lược hệ thống
Trang 35
SDRAM BUFFER: Nhận dữ liệu và tín hiệu điều khiển ghi từ khối Desize Horizon để ghi giá trị các Pixel vào SDRAM, đồng thời cũùng nhận tín hiệu từ VGA controller để điều khiển việc xuất dữ liệu, địa chỉ phù hợp (xuất xen kẽ các line thuộc Odd field và Even fieldû)
Khối xử lý ảnh YUV: Xử lý dữ liệu ảnh nhận được từ SDRAM BUFFER rồi xuất ra dữ liệu ảnh cho khối Convert YUV to RGB
Khối ConvertYUVtoRGB: ADV7181B xuất ra ảnh video dạng YUV, để có thể hiển thị lên VGA thì trước tiên chuyển đổi thành dạng RGB
Khối VGA_Controller: Nhận dữ liệu ảnh RGB từ khối ConvertYUVtoRGB để xuất dữ liệu và tín hiệu đồng bộ cho Video DAC 7123, đồng thời cũng phát ra các tín hiệu điều khiển SDRAM_BUFFER để xuất dữ liệu từ SDRAM
Trang 4Chương 5: Khối I2C_Video_Config
Trang 36
PHẦN III: NỘI DUNG THIẾT KẾ
CHƯƠNG 5: Khối I2C_VIDEO_CONFIG 5.1 SƠ ĐỒ KHỐI
Hình 5.1: Sơ đồ khối I2C_Video_Config
RESET Tín hiệu Reset hệ thống
I2C_SCLK Ngõ ra chứa xung Clock cung cấp cho ADV7181B
I2C_DATA Port 2 chiều để cấu hình giá trị các thanh ghi của ADV7181B
Hình 5.2: Dạng sóng để truyền dữ liệu và cấu trúc ghi với giao thức I2C
Trang 5Chương 5: Khối I2C_Video_Config
Khi reset, bắt đầu cấu hình lại cho ADV7181B bằng cách xóa giá trị các bộ đếm và cờ Sau đó để nạp giá trị cho các thanh ghi ta sử dụng máy trạng thái sau:
Trang 6Chương 5: Khối I2C_Video_Config
// Nhập chuỗi dữ liệu cần truyền để đặt giá trị cho các thanh ghi
mI2C_DATA <= {8'h40,LUT_DATA};
mI2C_GO <= 1;
mSetup_ST <= 1;
end 1: begin
//Không có xác nhận thì nhảy về trạng thái 0
else mSetup_ST <= 0;
mI2C_GO <= 0;
end end
2: begin
Trang 7Chương 5: Khối I2C_Video_Config
end
end
Ta chỉ cần đặt giá trị cho một số thanh ghi cần thiết nên không thực hiện việc tăng dần địa chỉ thanh ghi mà sẽ ánh xạ từ LUX_INDEX đến LUX_DATA nhờ vào lệnh case, chẳng hạn như khi LUX_INDEX =27 để nạp giá trị 8’h50 vào thanh ghi có địa chỉ 8’h00 ta có cấu trúc:
case(LUX_INDEX):
27: LUT_DATA <= 16'h0050;
Để ADV7181B có thể phát hiện chuẩn video NTSC thì ta sẽ nạp các giá trị cho các thanh ghi theo bảng giá trị cài đặt ở phần mô tả ADV7181B Tuy nhiên khi truyền chuỗi này trên bus ta cần phải thêm các bit đồng bộ: 1 bit cho trạng thái IDE, 2 bit để thiết lập cờ START, 3 bit để chờ 3 ACK do ADV xác nhận, 3 bit để thiết lập cờ STOP và báo kết thúc chuỗi, vì vậy thực sự chuỗi dài 33 bit:
case (SD_COUNTER)
6'd0 : begin ACK1=0 ;ACK2=0 ;ACK3=0 ; END=0; SDO=1; SCLK=1;end
//Thiết lập cờ START
Trang 8Chương 5: Khối I2C_Video_Config
//Địa chỉ thanh ghi cần nạp
6'd12 : begin SDO=SD[15]; ACK1=I2C_SDAT; end
//Giá trị cần ghi vào thanh ghi
6'd21 : begin SDO=SD[7]; ACK2=I2C_SDAT; end
//Thiết lập cờ STOP và báo kết thúc chuỗi
6'd30 : begin SDO=1'b0; SCLK=1'b0; ACK3=I2C_SDAT; end
Trang 9Chương 5: Khối I2C_Video_Config
// khi xét xác nhận đã nạp xong thanh ghi ta sử dụng giá trị bù của ACK(tích cự mức thấp), chỉ xác nhận khi có đủ 3 xác nhận ACK1, ACK2, ACK3
Và dạng sóng thu được trên chân I2C_SCLK như sau (END từ 0 lên 1 chỉ ra rằng đã nạp xong giá trị cho một thanh ghi):
Hình 5.3: Dạng sóng mô phỏng trên chân I2C_SCLK
Trang 10Chương 6: Khối Timer trì hoãn ban đầu
Trang 42
CHƯƠNG 6: KHỐI TIMER TRÌ HOÃN BAN ĐẦU
6.1 SƠ ĐỒ KHỐI
Hình 6.1: Sơ đồ của khối Timer trì hoãn ban đầu
VS Tín hiệu VS ( Vertical Sync ) từ ADV7181B
HS Tín hiệu HS (Horizontal Sync) từ ADV7181B
TD_Stable Báo hiệu ADV7181b đã hoạt động ổn định
RST0, RST1, RST3 Ngõ ra cho phép các khối khác bắt đầu làm việc
Trang 11Chương 6: Khối Timer trì hoãn ban đầu
Trang 43
(50MHz) để tính thời điểm xuất ra mức 1 trên các chân RST0, RST1, RST2 Các tín hiệu này dùng để khởi động các khối khác theo trình tự như sau:
1) Ban đầu thì xóa tất cả dữ liệu trong các khối
2) Tính từ thời điểm TD_Stable lên 1(dơn vị là chu kỳ clock 27MHz) :
Sau 1132461.5: tích cực RST0 để kích hoạt khối SDRAM BUFFER,
Sau 1698692.5: tích cực RST1 để kích hoạt khối Desize Horizon
Sau 2264923.5: tích cực RST2 để kích hoạt khối xử lý ảnh YUV vàVGA Controller 3) Giữ nguyên giá trị ngõ ra cho đến khi có tín hiệu RESET hệ thống thì lặp lại
Điểm cần chú ý ở đây là khi Desize Horizon hoạt động thì sẽ xuất DATA_VALID cho phép ghi dữ liệu vào SDRAM BUFFER Rồi phải chờ 1 khoảng thời gian để ghi đủ số dữ liệu cần thiết mới kích hoạt VGA Controller để xuất dữ liệu từ SDRAM BUFFER Như ta đã biết 1 frame ảnh do ADV7181B xuất ra bao gồm 900900 byte (525 line, mỗi line có 1716 byte) hay để truyền hết 1 frame sẽ mất 900900 chu kỳ
Do xung clock trên chân LLC để truyền các byte là 27 MHz nên ta kiểm tra lại các thời điểm này như sau:
Lấy gốc thời gian là khi bắt đầu frame đầu tiên
TD_Stable lên 1 khi Frame đầu tiên đã phát được 9 line: 9 x 1716 = 15444 chu kỳ
Frame thứ 3 được bắt đầu tại thời điểm 2 x 900900 = 1801800
Khối Desize Horizon được kích hoạt tại thời điểm 1714136.5 (= 15444 + 1698692.5) tức là trước khi frame thứ 3 bắt đầu Đảm bảo rằng khối sẽ xuất ra DATA_VALID = 1 ở toàn bộ các Active Pixel của frame thứ 3
Khối VGA controller được kích hoạt tại thời điểm 2280367.5 (=15444 + 2264923.5) nên oRequest được xuất ra tại thời điểm 2315727.5 (= 2280376.5 + 35360 ) Với 35360 chu kỳ là khoảng thời gian từ khi khối được reset cho đến khi oRequest lên 1 Vậy việc đọc từ SDRAM BUFFER được kích hoạt khi frame thứ 3 đã bắt đầu được 1 khoảng thời gian là 513927.5 (= 2315727.5 - 1801800) Điều này đảm bảo cho việc xuất ra đúng từng frame từ SDRAM BUFFER mà ta sẽ đề cập kỹ hơn ở phần mô tả SDRAM BUFFER Cấu trúc và thiết kế của khối này tương đối đơn giản nên ta không đưa lưu đồ giải thuật và code thực thi mà chỉ mô tả sơ lược
Trang 12Chương 7: Khối Desize Horizon
Trang 44
CHƯƠNG 7: KHỐI DESIZE_HORIZON 7.1 SƠ ĐỒ KHỐI
Hình 7.1: Sơ đồ của khối Desize Horizontal
CLK_27 Xung clock 27Mhz từ kit DE2
TD_DATA[7:0] Dữ liệu hình ảnh từ ADV7181B
ACLR Tín hiệu xóa bất đồng bộ do khối Timer trì hoãn cung cấp CLK Xung clock 27MHz từ chân TD_CLK của ADV7181B
Số chia = 9 Số chia cung cấp cho bộ chia do người thiết kế nhập vào
TV_X[9:0] Vị trí của Pixel trong hàng hiện hành đồng thời cũng là số bị chia cung cấp cho bộ chia Thương [9:0] Thương của phép chia TV_X cho 9
Số dư [9:0] Số dư của phép chia TV_X cho 9
DATA_VALID Đồng bộ cho oYCbCr để đưa vào SDRAM_Controller
oYCbCr[15:0] Chuỗi dữ liệu ảnh ngõ ra
DATA_VALID: ở mức 1 thì sẽ cho phép Pixel đi kèm được ghi vào SDRAM thông qua SDRAM_Controller Do frame mà ADV7181B xuất ra có dạng 720x480 để đưa về chuẩn 640x480 mà hình ảnh không bị xén thì với mỗi 9 pixel liên tiếp ta sẽ loại bỏ Pixel
Trang 13Chương 7: Khối Desize Horizon
Đồng thời để đảm bảo được chuỗi đưa vào SDRAM_controller vẫn có dạng chuỗi
CbYnCrYn+1 liên tiếp thì phải hoán đổi giữa 2 thành phần Cb và Cr cứ sau 2 lần loại bỏ 1 Pixel
Hình 7.2: Vị trí các Pixel trong chuỗi
Như ở hình trên X là vị trí các Pixel bị loại bỏ (bị bỏ qua khi hiển thị lên màn hình), khi đó chuỗi Pixel tại S1 là Cb4Y8Cb5 Y10 và tại E1 là Cr8Y17Cr9Y19 vì vậy để đảm bảo chuỗi ra có dạng CbYCrY liên tiếp thì phải hoán đổi vị trí giữa Cb và Cr trong khoảng Cb5
Y10 Cr8Y17
Trang 14Chương 7: Khối Desize Horizon
Trang 46
7.2 LƯU ĐỒ GIẢI THUẬT
Trang 15Chương 7: Khối Desize Horizon
Trang 47
7.3 MÔ TẢ
TD_DATA là chuỗi Pixel được phát ra theo chuẩn Video ITU656 Ta có thể xem một frame thực sự bắt đầu với Odd Field khi bit F (bit 6 trong Byte cuối của trường SAV hay EAV) chuyển từ 1 về 0, vậy để xét điều kiện bắt đầu của 1 frame ta phải đợi đến trường SAV hay EAV rồi mới kiểm tra giá trị của bit F:
//phát hiện trường SAV
Assign SAV = (Window==24'hFF0000)&(iTD_DATA[4]==1'b0);
//khởi động bộ đếm cont để xác định số byte của chuỗi Pixel trong 1 hàng
//cứ 2 byte 1 Pixel được nên khi xác định vị trí Pixel trong hàng thì phải chia Cont cho 2:
assign oTV_X = Cont>>1;
Để thực hiện phép chia oTV_X cho 9 ta sử dụng bộ chia từ thư viện của Quartus:
Trang 16Chương 7: Khối Desize Horizon
Trang 48
Phần Menu >> Tools >> MegaWizard Plug_in Manager… >> Create … tạo custom
mới, đặt tên là DIV; chọn phần Arithmetic >> LPM_DEVIDE Vì oTV_X 720 nên chọn độ rộng bit của số bị chia (Numerator) là 10, độ rộng bit của số chia (denominator) là 4, kiểu dữ liệu không dấu Vì số chia cần nhập là 9 nên ta ghép vào khối tổng thể như sau:
Sau đó ghép 1 Y với 1 Cr hay 1 Y với 1 Cb đồng thời hoán đổi vị trí của Cr và Cb tại các vị trí cần thiết:
else
begin
Trang 17Chương 7: Khối Desize Horizon
Sau đó xét thêm điều kiện Cont[0] để đảm bảo việc ghép 1 byte Y với 1 byte Cr hay
1 byte Y với 1 byte Cb đã hoàn thành để xuất DATA_VALID :
if(Start && FVAL && Active_Video && Cont[0] && !iSkip )
Trang 18Chương 8: Khối SDRAM BUFFER
Trang 50
CHƯƠNG 8: KHỐI SDRAM BUFFER 8.1 SƠ ĐỒ KHỐI
Gồm 2 khối PLL và SDRAM Controller:
Hình 8.1: Sơ đồ của khối SDRAM BUFFER
Trang 19Chương 8: Khối SDRAM BUFFER
Trang 51
RESET Tín hiệu Reset hệ thống
CLK_27 Xung clock 27Mhz từ kit DE2
CLK
Xung clock 81MHz PLL đưa ra cho các ngõ vào CLK của khối SDRAM Controller ( chính là tần số đọc của SDRAM WRITE FIFO, ghi của SDRAM READ FIFO1 và SDRAM READ FIFO2) SDR_CLK Xuất xung clock 81MHz cho SDRAM
WR_DATA Dữ liệu ảnh đưa vào SDRAM WRITE FIFO do Desize horizon cấp
WR Cho phép ghi vào SDRAM WRITE FIFO lấy từ chân
DATA_VALID của khối Desize horizon WR_CLK Xung clock 27MHz từ chân LLC(TD_CLK) của ADV7181B
RD_WRFIFO Cho phép đọc dữ liệu từ SDRAM WRITE FIFO
WRITE_SIDE[8:0] Số từ (Word) hiện có trong SDRAM WRITE FIFO
DATA_IN Dữ liệu từ SDRAM WRITE FIFO đưa vào Control Center để ghi
SDRAM
DATA_OUT[15:0] Dữ liệu Control Center đọc từ SDRAM để xuất ra ngoài qua 1
trong 2 FIFO: SDRAM READ FIFO1, SDRAM READ FIFO2 RD1
RD2
RD1 = ~ RD2: Lần lượt cho phép đọc dữ liệu từ SDRAM READ FIFO1, SDRAM READ FIFO2 với sự điều khiển của khối VGA Cotroller thông qua chân Request và VGA_Y
RD1_CLK
RD2_CLK
Tần số đọc của SDRAM READ FIFO1 và SDRAM READ FIFO2 được là 27MHz từ KIT DE2
READ_SIDE1[8:0] Số từ (Word) hiện có trong SDRAM READ FIFO1
READ_SIDE2[8:0] Số từ (Word) hiện có trong SDRAM READ FIFO2
WR_RDFIFO1 Cho phép ghi dữ liệu SDRAM READ FIFO1
WR_RDFIFO2 Cho phép ghi dữ liệu SDRAM READ FIFO2
RD1_DATA[15:0]
RD2_DATA[15:0] Dữ liệu ngõ ra cung cấp cho khối xử lý ảnh YUV
Các chân DQ[15:0], SA[11:0], CKE, CAS_N, RAS_N, SDR_CLK, WE_N, BA[1:0], CS_N[1:0], DQM[1:0] thì được nối tương ứng vào chip SDRAM có sẵn trên kit DE2
Trang 20Chương 8: Khối SDRAM BUFFER
Trang 52
8.2 LƯU ĐỒ GẢI THUẬT
Lưu đồ dành cho việc ghi và xuất từng khối dữ liệu xen kẽ từ SDRAM
Trang 21Chöông 8: Khoái SDRAM BUFFER
Trang 22Chương 8: Khối SDRAM BUFFER
Phần 1: Từ địa chỉ 8320 (640 x 13) đến 161920 (640 x 253) sẽ là các Pixel thuộc Odd Field Đây chính là 240 line từ 23 đến 262 trong frame gốc
Phần 2: Từ địa chỉ 170880 (640 x 267) đến 324480 (640 x 507) là các Pixel thuộc Even Fiel Đây chính là 240 line từ 286 đến 525 trong frame gốc
SDRAM hỗ trợ chế độ truy cập dữ liệu theo từng khối (Burst) với chiều dài khối có thể thay đổi được nhờ vào cài đặt giá trị 3 bit cuối (BL) của thanh ghi mode register bằng cách truy cập chế độ load mode rồi nhập giá trị cho thanh ghi này qua các chân địa chỉ:
Ơû đây ta đọc và ghi theo từng khối 128 Word 16 bit nên nhập BL = 111: chiều dài của Burst là full page (tức là 256 word với việc sử dụng SDRAM dưới dạng 4Mx16) ; WT
= 0: truy xuất tuần tự (Sequential) dữ liệu trong khối; LTMODE = 011: thời gian chờ (latency) cho tín hiệu RAS là 3 chu kỳ;
Các Burst dữ liệu của 2 phần trên sẽ được xuất xen kẽ nhau Ta khởi tạo và truy xuất địa chỉ cho của các phần này như sau:
Trang 23Chương 8: Khối SDRAM BUFFER
1 khối và lăp lại cho đến khi vượt quá địa chỉ tối đa thì quay về địa chỉ ban đầu
//ghi vào SDRAM
if(WR_LOAD) begin
rWR_ADDR <= WR1_ADDR;
rWR_LENGTH <= WR1_LENGTH;
end else if(mWR_DONE&WR_MASK[0]) begin
if(rWR_ADDR<rWR_MAX_ADDR-rWR_LENGTH) rWR_ADDR <= rWR_ADDR+rWR_LENGTH;
else rWR_ADDR <= WR_ADDR;
end
//đọc dữ liệu từ phần 1
if(RD1_LOAD) begin
rRD1_ADDR <= RD1_ADDR;
rRD1_LENGTH <= RD1_LENGTH;
end else if(mRD_DONE&RD_MASK[0]) begin
if(rRD1_ADDR<rRD1_MAX_ADDR-rRD1_LENGTH) rRD1_ADDR <= rRD1_ADDR+rRD1_LENGTH;
else
Trang 24Chương 8: Khối SDRAM BUFFER
rRD2_ADDR <= RD2_ADDR;
rRD2_LENGTH <= RD2_LENGTH;
end else if(mRD_DONE&RD_MASK[1]) begin
if(rRD2_ADDR<rRD2_MAX_ADDR-rRD2_LENGTH) rRD2_ADDR <= rRD2_ADDR+rRD2_LENGTH;
else rRD2_ADDR <= RD2_ADDR;
end end
Trước hết cần tạo một khối điều khiển việc ghi và đọc SDRAM xen kẽ nhau, mỗi lần đọc hay ghi dữ liệu sẽ thao tác trên từng Burst có chiều dài là 128 từ (Word) theo thứ tự ưu tiên (chờ thao tác hiện thời hoàn thành rồi mới thực hiện thao tác tiếp theo):
Đọc 1 khối từ SDRAM rồi ghi vào SDRAM READ FIFO1 để xuất chuỗi Pixel thuộc Odd Frame
Đọc 1 khối từ SDRAM rồi ghi vào SDRAM READ FIFO2 để xuất chuỗi Pixel thuộc Even Frame
Ghi 1 khối từ SDRAM WRITE FIFO vào SDRAM
Ơû trên ta thực hiện 3 thao tác xen kẽ nhau, vì vậy để dữ liệu có thể đồng bộ nhập, xuất dữ liệu với các khối khác thì phải cung cấp tần số làm việc cho SDRAM và tần số truy xuất dữ liệu giữa các khối FIFO và SDRAM gấp 3 lần tần số clock của các khối khác Để tạo cac xung clock này ta sử dụng thư viện của Quartus để tạo khối PLL :
Phần Menu >> Tools >> MegaWizard Plug_in Manager… >> Create … tạo một
custom mới, đặt tên là SDRAM_PLL, chọn phần I/O >> ALTCLKlLOCK, ta không sử
dụng các chân đồng bộ mà chỉ nhập các thông số cho tần số ngõ vào và tần số, pha ngõ ra