Tải bản đầy đủ (.pdf) (43 trang)

Thiết kế hệ thống KIT DE2 của Altera

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (831.08 KB, 43 trang )

Chươ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

Chươ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.
Chươ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.



























Chươ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



Tên Mô tả
ICLK Xung Clock 50MHz từ Kit DE2
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

Chương 5: Khối I2C_Video_Config
Trang 37

5.2 LƯU ĐỒ GIẢI THUẬT:


5.3 MÔ TẢ
Vai trò của khối chỉ là ghi giá trò vào các thanh ghi của ADV7181B nên có thể chọn
xung clock làm việc của khối là 20KHz nhờ vào bộ chia tần từ tần số 50MHz. Đòa chỉ
Slaver của ADV7181B là 40h nên ta sử dụng cách gán mI2C_DATA <= {8’h40,
LUT_DATA}. Với mI2C_DATA là chuỗi dữ liệu cần truyền trên Bus và LUT_DATA
chứa đòa chỉ của thanh ghi và giá trò cần nạp.
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:
Chương 5: Khối I2C_Video_Config
Trang 38


always@(posedge mI2C_CTRL_CLK or negedge iRST_N)
begin
if(!iRST_N) begin
LUT_INDEX <= 0;
mSetup_ST <= 0;
mI2C_GO <= 0; end
else
begin
if(LUT_INDEX < LUT_SIZE)
//LUT_SIZE làsố lần nạp giá trò cho các thanh ghi cần thiết vàLUT_INDEX
//là biến đếm để ánh xạ đến đòa chỉ của các thanh ghi và giá trò cần nạp.
begin
case(mSetup_ST)
0: begin
// 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
if(mI2C_END)
// mI2C_END là cờ báo khi truyền hết chuỗi dữ liệu
Begin
//Có xác nhận ACK là đã nạp xong giá trò cho 1 thanh
ghi từ ADV thì nhảy tới trạng thái 2
if(!mI2C_ACK)
mSetup_ST <= 2;
//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
Chương 5: Khối I2C_Video_Config
Trang 39

// Tăng LUT_INDEX lên 1 để nhảy đến thanh ghi mới rồi quay về
trạng thái 0
LUT_INDEX <= LUT_INDEX+1;
mSetup_ST <= 0;
end
endcase
end
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
6'd1 : begin SD=I2C_DATA;SDO=0;end
6'd2 : SCLK=0;
//Đòa chỉ SLAVER của ADV7181B
6'd3 : SDO=SD[23];
6'd4 : SDO=SD[22];
6'd5 : SDO=SD[21];
6'd6 : SDO=SD[20];
6'd7 : SDO=SD[19];
6'd8 : SDO=SD[18];
Chương 5: Khối I2C_Video_Config
Trang 40

6'd9 : SDO=SD[17];
6'd10 : SDO=SD[16];
//Thả nổi đường truyền để nhập ACK từ ADV7181B qua Port 2 chiều I2C_DATA
6'd11 : SDO=1'bz;
//Đòa chỉ thanh ghi cần nạp
6'd12 : begin SDO=SD[15]; ACK1=I2C_SDAT; end
6'd13 : SDO=SD[14];
6'd14 : SDO=SD[13];
6'd15 : SDO=SD[12];
6'd16 : SDO=SD[11];
6'd17 : SDO=SD[10];
6'd18 : SDO=SD[9];
6'd19 : SDO=SD[8];
// Thả nổi đường truyền nhập để ACK từ ADV7181B qua Port 2 chiều I2C_DATA
6'd20 : SDO=1'bz;
//Giá trò cần ghi vào thanh ghi
6'd21 : begin SDO=SD[7]; ACK2=I2C_SDAT; end

6'd22 : SDO=SD[6];
6'd23 : SDO=SD[5];
6'd24 : SDO=SD[4];
6'd25 : SDO=SD[3];
6'd26 : SDO=SD[2];
6'd27 : SDO=SD[1];
6'd28 : SDO=SD[0];
// Thả nổi đường truyền nhập ACK từ ADV7181B qua Port 2 chiều I2C_DATA
6'd29 : SDO=1'bz;
//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
6'd31 : SCLK=1'b1;
6'd32 : begin SDO=1'b1; END=1; end
endcase
Trong đó SD_COUNTER thực hiện đếm từ 0 -> 63, như vậy việc nạp cho một thanh
ghi chỉ thực hiện trong 33 chu kỳ đầu còn 30 chu kỳ sau thì Bus ở trạng thái IDE (SCLK =
Chương 5: Khối I2C_Video_Config
Trang 41

1 và SDO = 1) để chờ chu kỳ ghi tiếp theo. Đồng thời để đảm bảo được yêu cầu về dạng
sóng trên chân I2C_SCLK và xác nhận (ACK) đã nạp xong thanh ghi, ta thực hiện:
wire I2C_SCLK = SCLK | ( ( (SD_COUNTER >= 4) & (SD_COUNTER <=30) )?
~CLOCK : 0 );
wire ACK=ACK1 | ACK2 |ACK3;
// 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















Chươ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

Tên Mô tả
ICLK Xung clock 50Mhz từ kit DE2
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


6.2 MÔ TẢ
Với cấu hình đã cài đặt ở phần trước, khi đã hoạt động ổn đònh, dạng sóng do
ADV7181B phát ra như sau:

Vì vậy để phát hiện xem chip mã hóa này đã hoạt động ổn đònh hay chưa khối
TD_DETEC tiến hành kiểm tra điều kiện: VS ở mức cao trong 9 chu kỳ liên tiếp của HS
rồi chuyển xuống mức thấp, nếu thỏa mãn thì đưa TD_Stable lên mức cao. Khi tín hiệu
TD_Stable lên mức cao, khối RESET_DELAY bắt đầu đếm lên theo xung nhip của ICLK
Chươ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.
Chươ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

Tên Mô tả
CLK_27 Xung clock 27Mhz từ kit DE2
RST_N Reset hệ thống
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
Chương 7: Khối Desize Horizon
Trang 45

đầu tiên: không cho phép ghi vào SDRAM bằng cách đưa DATA_VALID xuống mức 0
(lấy ra 8 Pixel trong 9 Pixel :
8
640 720
9

)
Đồ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.














Chöông 7: Khoái Desize Horizon
Trang 46

7.2 LÖU ÑOÀ GIAÛI THUAÄT

Chươ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:
Window <= {Window[15:0],iTD_DATA};
if(Window==24'hFF0000)
//khi phát hiện trường SAV (EAV) thì gán giá trò bit V cho FVAL và bit F cho Field
begin
FVAL <= !iTD_DATA[5];
Field <= iTD_DATA[6];
end
//kiểm tra điều kiện bit F chuyển từ 1 về 0 để bắt đầu 1 frame như sau:

Pre_Field <= Field;
if({Pre_Field,Field}==2'b10)
Start <= 1'b1;
//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
if(SAV)
begin
Cont <= 18'h0;
Active_video <= 1’b0;
end
else if(Cont<1440)
Cont <= Cont+1'b1;
//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:
Chươ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:
DIV u5 ( .aclr(!DLY0),
.clock(TD_CLK),
.denom(4'h9),
.numer(TV_X),
.quotient(Quotient),

.remain(Remain));
Trong đó quotient, remain là thương và số dư, ta nhập các điều kiện oTV_X có chia
hết cho 9 vàthương là số lẻ thông qua các chân iSkip và iSwap_CbCr bằng cách khai báo:
Desize_Horizontal u4 ( .iTD_DATA(TD_DATA),
.oTV_X(TV_X),
.oYCbCr(YCbCr),
.oDVAL(TV_DVAL),
.iSwap_CbCr(Quotient[0]),
.iSkip(Remain==4'h0),
.iRST_N(DLY1),
.iCLK_27(TD_CLK) );
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:
if(iSwap_CbCr)
begin
case(Cont[1:0]) //hoán đổi Cb Và Cr
0: Cb <= iTD_DATA;
1: YCbCr <= {iTD_DATA,Cr};
2: Cr <= iTD_DATA;
3: YCbCr <= {iTD_DATA,Cb};
endcase
end
else
begin

Chương 7: Khối Desize Horizon
Trang 49

case(Cont[1:0]) // không cần hoán đổi
0: Cb <= iTD_DATA;

1: YCbCr <= {iTD_DATA,Cb};
2: Cr <= iTD_DATA;
3: YCbCr <= {iTD_DATA,Cr};
endcase
end
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 )
Data_Valid <= 1'b1;
else
Data_Valid <= 1'b0;
Như vậy Data_Valid chỉ lên 1 ở Active Pixel để điều khiển sự ghi vào SDRAM BUFFER.













×