Thực hiện bộ lọc thích nghi FIR dùng thuật toán LMS

Tín hiệu thu được sau khi qua bộlọc FIR thích nghi đã loại bỏ được nhiễu 50Hz. Tuy nhiên, vẫn không được trơn tru và có độmấp mô nhỏ. Sởdĩnhưvậy là do các nguyên nhân sau: • Do bộbiến đổi ADC là 14 bit, nên khi qua bộlọc FIR(bao gồm các bộnhân và bộcộng) thì dữliệu lên tới 28 bit, mà đầu ra DAC chỉhỗtrợ14 bit, vì vậy, trước khi dữliệu được đưa vào bộlọc FIR, ta phải chia dữliệu cho 2 7 để đầu ra DAC là 14 bit. Do đó, kết quảcó sai sốnhất định • Bộbiến đổi DAC chỉhỗtrợcác sốnguyên, do đó, ta phải làm tròn các hệsố thành sốnguyên, vì vậy, kết quả đạt được cũng không được nhưlý thuyết

pdf65 trang | Chia sẻ: banmai | Lượt xem: 2682 | Lượt tải: 4download
Bạn đang xem trước 20 trang tài liệu Thực hiện bộ lọc thích nghi FIR dùng thuật toán LMS, để xem tài liệu hoàn chỉnh bạn click vào nút DOWNLOAD ở trên
Anh Cường 26 thuật toán gradient thống kê lần đầu tiên được Windrow-Hoff áp dụng năm 1960 và sau đó phát triển thành nhiều thuật toán mới nhờ tính chất đơn giản và bền vững của thuật toán này. Nó là thuật toán lọc thích nghi tuyến tính bao gồm hai quá trình: quá trình lọc và thích nghi. Trong quá trình lọc, thuật toán này sử dụng mạch lọc ngang tuyến tính có lối vào x(n) và lối ra y(n). Quá trình thích nghi được thực hiện nhờ sự điều khiển tự động các táp trọng số của các hệ số của mạch lọc sao cho nó tương đồng với tín hiệu sai số là hiệu của tín hiệu lối ra với tín hiệu mong muốn d(n). Sơ đồ của thuật toán như trong hình. Hình 12: Mạch lọc FIR thích nghi dùng thuật toán LMS Giả sử mạch lọc ngang có N- táp trọng số và là dãy số thực, khi đó tín hiệu lối ra được viết: y[n] = ∑− = 1 0 N k w k[n] x[n-k] (4.20) Trong đó táp trọng số wo[n]…..,wN-1 [n] được chọn lựa như thế nào để sai số: e[n]= d[n] - y[n] (4.21) có giá trị cực tiểu. Nói chung trong mạch lọc thích nghi, táp trọng số là hàm của chỉ số thời gian n, vì chúng được thích nghi liên tục với sự thay đổi thống kê của tín hiệu. Thuật toán LMS điều chỉnh táp trọng số của mạch lọc sao cho sai số e[n] được z-1 z-1 x z-1 + x x wo[n] w1[n] wN-1[n] x[n] x[n-1] + e[n] x y[n] __ Thuật toán LMS + d[n] ĐH Công Nghệ- ĐHQG Hà Nội Khoá luận tốt nghiệp Nguyễn Anh Cường 27 cực tiểu hoá theo nghĩa toàn phương trung bình, vì thế mới có tên là thuật toán toàn phương trung bình tối thiểu. Khi các quá trình x[n] và d[n] là các quá trình ngẫu nhiên dừng, thì thuật toán này hội tụ đến nghiệm của phương trình Wiener-Hopf. Nói cách khác, thuật toán LMS là một sơ đồ thực tế để thực hiện các mạch lọc Wiener-Hopf, nhưng không giải một cách tường minh phương trình Wiener-Hopf. Nó là một thuật toán tuần tự được sử dụng để thích nghi táp trọng số của mạch lọc nhờ sự quan sát liên tục tín hiệu lối vào x[n] và tín hiệu lối ra mong muốn d[n]. Như vậy, thuật toán LMS chính là sự thực thi thống kê của thuật toán giảm bước nhanh nhất, trong đó hàm phí tổn J=E[e2[n]] được thay bằng giá trị xác định tức thời j^[n] = e2[n]. Khi đó phương trình truy hồi để tính táp trọng số của mạch lọc được xác định bằng phương trình: w[n+1] = w[n] - µ∇e2[n] (4.22) trong đó w[n] = [wo[n],w1[n],….,wN-1[n]]T, µ là thông số bước của thuật toán còn ∇ là toán tử vi phân được xác định bằng vector cột như sau: ∇ = ⎥⎥ ⎥⎥ ⎥⎥ ⎥⎥ ⎥⎥ ⎥⎥ ⎦ ⎤ ⎢⎢ ⎢⎢ ⎢⎢ ⎢⎢ ⎢⎢ ⎢⎢ ⎣ ⎡ −∂ ∂ ∂ ∂ ∂ ∂ ]1[ . . . ]1[ ]0[ Nw w w (4.23) Như vậy thành phần thứ k của vector ∇e2[n] là: wi∂ ∂ e2 [n] = 2e[n] wi ne ∂ ∂ ][ (4.24) Thay e[n]=d[n]-y[n] vào phương trình trên và do d[n] độc lập với wi, ta được: wi∂ ∂ e2 [n] = -2e[n] wi ny ∂ ∂ ][ (4.25) Bây giờ, thay y[n] từ (4.20) vào (4.25) ta được: wi∂ ∂ e2 [n] = - 2e[n]x[n-i] (4.26) ĐH Công Nghệ- ĐHQG Hà Nội Khoá luận tốt nghiệp Nguyễn Anh Cường 28 Hoặc dưới dạng tổng quát là: ∇e2[n] = -2e[n]x[n] (4.27) Trong đó: x[n]=[ x[n], x[n-1]….x[n-N+1]]T Thay kết quả từ (4.27) vào (4.22) ta được: w[n+1] = w[n] + 2µe[n]x[n] (4.28) Đây là phương trình truy hồi để xác định táp trọng số của mạch lọc đối với các dãy lối vào và dãy sai số. Nó được gọi là thuật toán LMS đệ qui, thích nghi một cách đệ quy các hệ số của mạch lọc cứ sau mỗi mẫu mới của tín hiêu lối vào x[n] và mẫu tín hiệu mong muốn d[n]. Các phương trình (4.20), (4.21), (4.28), theo thứ tự là ba bước để hoàn chỉnh mỗi một phép lặp của thuật toán LMS. Phương trình (4.20) là quá trình lọc, nó được tạo thành để thu được tín hiệu lối ra của mạch lọc. Phương trình (4.21) được sử dụng để tính sai số. Còn phương trình (4.28) dùng để thích nghi một cách đệ quy táp trọng số của mạch lọc sao cho sai số xác định đạt giá trị cực tiểu. Trong phương trình này, µ là thông số bước, nó điều khiển tốc độ hội tụ của thuật toán tới nghiệm tối ưu. Nếu chọn µ lớn thì tốc độ hội tụ nhanh; còn nếu chọn µ giá trị bé thì tốc độ hội tụ sẽ chậm hơn. Tuy nhiên, nếu µ quá lớn thì thuật toán sẽ không ổn định và do vậy để đảm bảo tính chất ổn định của thuật toán LMS, µ phải được chọn sao cho: 0 < µ < ][3 1 Rtrace (4.29) trong đó: trace[R] = ∑− = 1 0 ][ N k kλ , Với N là bậc của bộ lọc ------------------------------ ĐH Công Nghệ- ĐHQG Hà Nội Khoá luận tốt nghiệp Nguyễn Anh Cường 29 Chương 4 HỆ THỐNG SỐ BÙ HAI VÀ CÁC PHÉP TOÁN 4.1. BIỂU DIỄN SỐ ÂM TRONG HỆ THỐNG SỐ BÙ HAI Trong hệ thống số bù hai, số dương vẫn được biểu diễn như các số không dấu khác. Do vậy, ta chỉ tìm hiểu cách biểu diễn số âm trong hệ thống số bù 2. Giả sử P là số dương, được biểu diễn bởi n bit trong số bù hai, khi đó: -P = K = 2n – P. Ví dụ: nếu ta sử dụng số 4 bit để biểu diễn thì +5 =0101 và -5 = 10000- 0101=1011 và -3=10000-0011=1101 Việc tìm số bù hai như cách trên thường ít được sử dụng, do sự phức tạp của nó khi phải sử dụng các phép tính. Vì thế, ta đưa ra một phương pháp khác dễ dàng hơn: Giả sử số B = bn-1 bn-2…b1 bo và K = kn-1 kn-2…k1 ko là số bù hai của B. Khi đó, số K có thể được tạo ra từ B bằng cách : giữ nguyên các số bằng 0 từ phải sang trái của B cho đến số đầu tiên bằng 1 của B;các số tiếp theo của B sẽ được đảo ngược lại(1 thành 0 và 0 thành 1). Ví dụ: B=0110, khi đó k0=b0 =0 và k1=b1=1, các số còn lại thu được B bằng việc đảo các bit tương ứng : k2=0 và k3 = 1. Kết quả là: K=1010 là số bù hai của B=0110 Hình dưới biểu diễn số bù hai 4 bit ĐH Công Nghệ- ĐHQG Hà Nội Khoá luận tốt nghiệp Nguyễn Anh Cường 30 Hình 13:Số bù hai được biểu diễn bởi 4 bit Các số được biểu diễn trong hệ thống số bù hai được biểu diễn bởi công thức: B=(-bn-1 x 2n-1) + bn-2 x 2n-2 +….+ b1 x 21 + bo Trong đó B = bn-1 bn-2…b1 bo là số n bit được biểu diễn trong hệ thống số bù hai. 4.2. THỰC HIỆN CÁC PHÉP TÍNH TRONG HỆ THỐNG SỐ BÙ HAI 4.2.1. Thực hiện phép cộng trong hệ thống số bù hai Thực hiện phép cộng trong số bù hai hết sức đơn giản, như cộng số nhị phân thông thường. Ta xét một vài ví dụ về việc thực hiện phép cộng với các số bù hai 4 bit: ĐH Công Nghệ- ĐHQG Hà Nội Khoá luận tốt nghiệp Nguyễn Anh Cường 31 Lưu ý: với phép cộng:(+5)+(-2)=(+3) và (-5)+(-2)=(-7) thì trong trường hợp này ta có thể bỏ qua bit thứ 5 4.2.2. Thực hiện phép trừ trong hệ thống số bù hai Để thực hiện phép trừ trong số bù hai, ta chỉ việc tìm số bù hai của số bị trừ rồi thực hiện phép cộng với số trừ.Ta xét các ví dụ sau: ĐH Công Nghệ- ĐHQG Hà Nội Khoá luận tốt nghiệp Nguyễn Anh Cường 32 Lưu ý: với ví dụ (+5)-(+2) =(+3) và (-5)-(+2)=(-7) ta có thể bỏ qua bit thứ 5. 4.2.3. Hiện tượng tràn số Nếu dùng n bit để biểu diễn số có dấu thì ta có thể biểu diễn các số trong khoảng từ --2n-1 đến 2n-1 – 1. Nếu sau quá trình thực hiện phép toán(cộng, trừ, nhân) mà kết quả thu được không nằm trong dải trên thì ta nói có hiện tượng tràn số. Ta xét các ví dụ sau: Trong ví dụ trên, ta thấy: (+7)+(+2) = (+9) và (-7)+(-2) = (-9) có kết quả bị tràn do (+9) và (-9) không có trong dải biểu diễn số có dấu 4 bit(từ -8 đến 7). Các kết quả còn lại không tràn do vẫn nằm trong dải biểu diễn. Ngoài ra, có một cách khác nhận biết được kết quả có tràn hay không mà không cần quan tâm đến dải biểu diễn đó là: Overflow = c3 xor c4 Nếu dùng n bit để biểu diễn số có dấu thì ta có: Overflow = cn xor cn-1 ĐH Công Nghệ- ĐHQG Hà Nội Khoá luận tốt nghiệp Nguyễn Anh Cường 33 4.2.4. Thực hiện phép nhân trong số bù hai Trước khi thảo luận về phép nhân hai số bù hai, ta cần phải biết về phép nhân với luỹ thừa của 2. Giả sử B=bn-1bn-2…b1bo. Khi đó: 2 x B = bn-1bn-2…b1bo0. Ta chỉ việc dịch B sang trái 1 số rồi thêm 1 số 0 vào cuối. Tổng quát hơn, nếu ta thực hiện phép nhân: 2k x B thì ta chỉ việc dịch B sang trái k số rồi thêm k số 0 vào cuối. Ta thấy phép nhân của số có dấu với luỹ thừa của 2 giống như của số không dấu. Tuy nhiên, với phép chia thì lại khác hẳn. Để chia số B cho 2k, ta dịch số B sang phải k số(tức là bỏ đi k số cuối). Sau đó, ta thêm vào trước số B k bit dấu(bit dấu là bit có trọng số cao nhất). Ví dụ: B = 011000 = (24)10 , B:2 = 001100 = (12)10, và B:4= 000110 =(6)10 Tương tự với số âm: B=101000=(-24)10 , B:2= 110100 =(-12)10 Như vậy, ta đã biết cách thực hiện phép nhân và chia của số bù hai với luỹ thuỳ của 2. Bây giờ ta thảo luận xem cách nhân 2 số bù hai được thực hiện như thế nào. Ta xét hai ví dụ sau: ĐH Công Nghệ- ĐHQG Hà Nội Khoá luận tốt nghiệp Nguyễn Anh Cường 34 Từ 2 ví dụ trên, ta rút ra được cách nhân 2 số bù hai n bit A=an-1an-2… a1ao và B=bn-1bn-2....b1bo tương tự như trên. --------------------------------- ĐH Công Nghệ- ĐHQG Hà Nội Khoá luận tốt nghiệp Nguyễn Anh Cường 35 Chương 5 THỰC NGHIỆM 5.1. MÔ TẢ PHẦN CỨNG CỦA KIT VIRTEX-II PRO Phần cứng của kit Virtex-II Pro bao gồm: • FPGA Spartan-II dùng để tạo giao tiếp PCI hoặc USB • 2 LED trạng thái hiển thị 3 màu:cam, đỏ, vàng • Giắc cắm cho mạch nạp JTAG • 2 kênh ADC độc lập(ADC 14 bit) với tốc độ lấy mẫu tối đa là 105Mhz • 2 kênh DAC độc lập(DAC 14 bit) với tốc độ biến đổi tối đa là 160Mhz • 2 rãnh ZBT SRAM độc lập với bộ nhớ 512K x 32 • FPGA virtex-II XC2V80-4CS144 để tạo clock • FPGA virtex-II pro XC2VP30-4FF1152 là FPGA chính cho người sử dụng • Có đường kết nối với clock ngoài • Có thạch anh 65Mhz trong mạch Tổng thể về kit virtex-II Pro được mô tả như hình 14: Hình 14: Toàn bộ mặt trên của Kit virtex-II pro ĐH Công Nghệ- ĐHQG Hà Nội Khoá luận tốt nghiệp Nguyễn Anh Cường 36 5.2. KẾT QUẢ THU ĐƯỢC VỚI BỘ LỌC FIR TRUYỀN THỐNG Lưu đồ tiến hành thực hiện bộ lọc FIR truyền thống như hình 15: Hình 15: Lưu đồ thực hiện bộ lọc FIR truyền thống Sau khi qua biến đổi ADC, dữ liệu được biểu diễn dưới dạng số bù hai sẽ được đưa vào FPGA để xử lý. FPGA có nhiệm vụ thực hiện thuật toán lọc theo yêu cầu của người lập trình. Sơ đồ thực hiện thuật toán đối với bộ lọc FIR được trình bày như trong hình 3 của chương 2. Trong đó, lối vào x[n] của bộ lọc chính là các giá trị sau khi qua biến đổi ADC, các hệ số h[n] là các hằng số đã được cho trước(được tính toán bằng Matlab) và y[n] là kết quả sau khi đã qua bộ lọc FIR. Các kết quả này cũng được biểu diễn dưới dạng số bù hai và được đưa qua bộ biến đổi DAC để hiện lên trên dao động ký. Trong bài luận văn này, em thiết kế bộ lọc FIR thông thấp, với bậc bộ lọc là 50, tần số mà bộ lọc bắt đầu suy giảm và triệt tiêu là từ 800Hz đến 1250Hz, tần số lấy mẫu là 20Khz. Các hệ số h[n] sẽ được tính toán bằng công cụ fdatool trong Matlab. Đáp ứng tần số tính toán bằng Matlab được mô tả như hình 16: Hình 16: Đáp ứng tần số của mạch lọc FIR Máy phát ADC FPGA DAC Dao động ký ĐH Công Nghệ- ĐHQG Hà Nội Khoá luận tốt nghiệp Nguyễn Anh Cường 37 Kết quả thu được khi thực hiện trên chíp FPGA: • Tín hiệu bắt đầu suy giảm tại tần số 700Mhz, được cho bởi hình 17: Hình 17: Tín hiệu bắt đầu suy giảm • Tín hiệu bị triệt tiêu tại tần số 1237Hz, được cho bởi hình 18: Hình 18: Tín hiệu bị triệt tiêu ĐH Công Nghệ- ĐHQG Hà Nội Khoá luận tốt nghiệp Nguyễn Anh Cường 38 5.3. KẾT QUẢ THU ĐƯỢC VỚI BỘ LỌC FIR THEO KIẾN TRÚC SYSTOLIC Với bộ lọc FIR thực hiện theo kiến trúc systolic array, lưu đồ và kết quả đạt được cũng tương tự như với bộ lọc FIR thông thường. Tuy nhiên, tốc độ thực hiện lại nhanh hơn nhiều. Với công cụ “place and route tools” của phần mềm ISE, cho ta kết quả như sau: • Với bộ lọc FIR thực hiện theo kiến trúc systolic array, tần số hoạt động lớn nhất của mạch là 141.947 Mhz và sử dụng hết 1775 slice. • Với bộ lọc FIR truyền thống, tần số hoạt động của lớn nhất của mạch là 19.857 Mhz và sử dụng hết 417 slice. Như vậy, ta có thể thấy bộ lọc FIR thực hiện theo kiến trúc systolic array có tốc độ đáp ứng nhanh hơn nhiều so với bộ lọc FIR thông thường, tuy nhiên, nó lại tốn nhiều tài nguyên hơn. Do đó, tuỳ theo từng ứng dụng cụ thể mà ta chọn thiết kế theo phương pháp nào 5.4. KẾT QUẢ THU ĐƯỢC VỚI BỘ LỌC FIR THÍCH NGHI Bộ lọc FIR thích nghi có rất nhiều ứng dụng như: Khử nhiễu, nhận dạng hệ thống chưa biết, dự báo kết quả với hệ thống có tín hiệu vào là ngẫu nhiên…. Trong bài luận văn này, em xin trình bày về ứng dụng của bộ lọc FIR thích nghi để khử nhiễu 50Hz-là nhiễu do nguồn sinh ra. Đây là loại nhiễu phổ biến và gây ảnh hưởng lớn đến các thiết bị điện tử. Lưu đồ cho việc khử nhiễu 50HZ được mô tả như hình 19: ĐH Công Nghệ- ĐHQG Hà Nội Khoá luận tốt nghiệp Nguyễn Anh Cường 39 Hình 19: Mô hình khử nhiễu 50 Hz Trong đó: • s(n) là tín hiệu mong muốn • v(n) là tín hiệu nhiễu • v1(n) là tín hiệu cùng dạng với v(n)(có thể khác nhau về biên độ và pha) • v’(n) đầu ra của bộ lọc FIR thích nghi • e(n) là tín hiệu sai số, đồng thời là lối ra. Thuật toán LMS sẽ có nhiệm vụ điều chỉnh các hệ số của bộ lọc FIR sao cho lối ra v’(n) có dạng gần nhất với tín hiệu nhiễu v(n). Khi đó, e(n)=d(n) - v’(n) sẽ đạt đến tín hiệu mong muốn s(n). Tức là ta đã khử được nhiễu. Kết quả thu được khi tiến hành trên chip FPGA: • Tín hiệu lẫn với nhiễu 50Hz trước khi lọc, được cho bởi hình 20 Hình 20: Tín hiệu lẫn với nhiễu d(n) = s(n)+v(n) FIR + LMS v’(n) __ v1(n) + e(n) output ĐH Công Nghệ- ĐHQG Hà Nội Khoá luận tốt nghiệp Nguyễn Anh Cường 40 • Tín hiệu sau khi lọc được cho bởi hình 21 Hình 21: Tín hiệu thu được sau khi lọc Tín hiệu thu được sau khi qua bộ lọc FIR thích nghi đã loại bỏ được nhiễu 50Hz. Tuy nhiên, vẫn không được trơn tru và có độ mấp mô nhỏ. Sở dĩ như vậy là do các nguyên nhân sau: • Do bộ biến đổi ADC là 14 bit, nên khi qua bộ lọc FIR(bao gồm các bộ nhân và bộ cộng) thì dữ liệu lên tới 28 bit, mà đầu ra DAC chỉ hỗ trợ 14 bit, vì vậy, trước khi dữ liệu được đưa vào bộ lọc FIR, ta phải chia dữ liệu cho 27 để đầu ra DAC là 14 bit. Do đó, kết quả có sai số nhất định • Bộ biến đổi DAC chỉ hỗ trợ các số nguyên, do đó, ta phải làm tròn các hệ số thành số nguyên, vì vậy, kết quả đạt được cũng không được như lý thuyết ĐH Công Nghệ- ĐHQG Hà Nội Khoá luận tốt nghiệp Nguyễn Anh Cường 41 KẾT LUẬN Trong thời gian tiến hành hoàn thiện khoá luận tốt nghiệp, ngoài việc củng cố lại những kiến thức đã được học trong suốt 4 năm qua, em còn thu được một số kiến thức và kết quả nhất định: • Được tìm hiểu và thực hành trên chip FPGA của hãng Xilinx • Biết sử dụng thành thạo phần mềm ISE • Có thêm nhiều kinh nghiệm trong việc lập trình với ngôn ngữ VHDL • Thực hiện thành công bộ lọc FIR thông thấp trên FPGA theo kiến trúc truyền thống và theo kiến trúc systolic array. So sánh được ưu điểm, nhược điểm của từng loại • Thực hiện thành công bộ lọc FIR thích nghi dùng thuật toán LMS trên FPGA để loại bỏ nhiễu 50 Hz ĐH Công Nghệ- ĐHQG Hà Nội Khoá luận tốt nghiệp Nguyễn Anh Cường 42 TÀI LIỆU THAM KHẢO [1] Simon Haykin. Adaptive filter theory, Third edition [2] Uwe Meyer-Baese.Digital Signal Processing with Field Programmable Gate Arrays, Third Edition [3] John G.Proaskis,Dimitris G.Manolakis. Digital Signal Processing, Third edition [4] Alexander D.Poularikas, Zayed M.Ramanda. Adaptive filtering primer with matlab, 2006. [5] Douglas L.Perry. VHDL: Programming by Example .McGraw – Hill, Fourth Edition [6]. Volnei A.Pedroni, Circuit Design With VHDL, MIT Press, 2004 [7] Jan Van der Spiegel. VHDL tutorial [8] Nguyễn Kim Giao, Kỹ thuật điện tử số, Nhà xuất bản Đại học Quốc gia Hà Nội, 2006. [9]. Tống Văn On, Thiết kế mạch số với VHDL và Verilog, Nhà xuất bản lao động xã hội, 2007. [10] Hồ Văn Sung. Xử lý số tín hiệu đa tốc độ và dàn lọc, Nhà xuất bản KH-KT, 2007 [11] [12] [13] ĐH Công Nghệ- ĐHQG Hà Nội Khoá luận tốt nghiệp Nguyễn Anh Cường 43 PHỤ LỤC PHẦN CHƯƠNG TRÌNH 1. Chương trình thiết kế bộ lọc FIR theo kiến trúc truyền thống library IEEE; use IEEE.STD_LOGIC_1164.all; use IEEE.STD_LOGIC_ARITH.all; use IEEE.STD_LOGIC_UNSIGNED.all; entity Toplevel is port ( -- main clock input from oscilator CLK1_FB : in std_logic; -- main reset input from mb RESETl : in std_logic; -- configuration done signal CONFIG_DONE : out std_logic; -- dac 14 bit data outputs DAC1_D : out std_logic_vector(13 downto 0); DAC2_D : out std_logic_vector(13 downto 0); -- adc 14 bit data inputs ADC1_D : in std_logic_vector(13 downto 0); ADC2_D : in std_logic_vector(13 downto 0); -- dac reset signals DAC1_RESET : out std_logic; DAC2_RESET : out std_logic; -- dac setup DAC1_MOD0 : out std_logic; DAC1_MOD1 : out std_logic; DAC2_MOD0 : out std_logic; DAC2_MOD1 : out std_logic; -- dac clock divider setup DAC1_DIV0 : out std_logic; DAC1_DIV1 : out std_logic; DAC2_DIV0 : out std_logic; DAC2_DIV1 : out std_logic; -- led flash signals LED1_Red : out std_logic; LED2_Red : out std_logic; LED1_Green : out std_logic; LED2_Green : out std_logic ); end Toplevel; architecture Behavioral of Toplevel is -- clock components component BUFG ĐH Công Nghệ- ĐHQG Hà Nội Khoá luận tốt nghiệp Nguyễn Anh Cường 44 port ( I : in std_logic; O : out std_logic ); end component; component IBUFG port ( I : in std_logic; O : out std_logic ); end component; component DCM generic ( DLL_FREQUENCY_MODE : string := "LOW"; DUTY_CYCLE_CORRECTION : string := "TRUE"; STARTUP_WAIT : string := "FALSE" ); port ( CLKIN : in std_logic; CLKFB : in std_logic; DSSEN : in std_logic; PSINCDEC : in std_logic; PSEN : in std_logic; PSCLK : in std_logic; RST : in std_logic; CLK0 : out std_logic; CLK90 : out std_logic; CLK180 : out std_logic; CLK270 : out std_logic; CLK2X : out std_logic; CLK2X180 : out std_logic; CLKDV : out std_logic; CLKFX : out std_logic; CLKFX180 : out std_logic; LOCKED : out std_logic; PSDONE : out std_logic; STATUS : out std_logic_vector(7 downto 0) ); end component; -- end of clock components -- internal clock and reset signals Component FIR_Filter Generic(n: integer :=14; -- width of data m: integer := 51); -- order of FIR Port ( Xin: in std_logic_vector(n-1 downto 0); clk,reset: in std_logic; Yout: out std_logic_vector(n-1 downto 0) ); end Component; component chiatan port ( clk_i : in std_logic; sochia : in integer; clk_o : out std_logic ); ĐH Công Nghệ- ĐHQG Hà Nội Khoá luận tốt nghiệp Nguyễn Anh Cường 45 end component; signal CLKIN_OSC, CLKFB_OSC, CLK_OSC, RESET, RSTl : std_logic; -- temporary registers signal ADC1, ADC2 : std_logic_vector(13 downto 0); signal DAC1 :std_logic_vector(13 downto 0); signal data :std_logic_vector(13 downto 0); -- common ground signal GND : std_logic; signal clk:std_logic; begin GND <= '0'; RESET <= not RESETl; -----------------------------clock deskew section-------------------------- --- -- IBUFG Instantiation for CLK_IN U0_IBUFG : IBUFG port map ( I => CLK1_FB, O => CLKIN_OSC ); -- BUFG Instantiation for CLKFB U0_BUFG : BUFG port map ( I => CLKFB_OSC, O => CLK_OSC ); -- DCM Instantiation for internal deskew of CLK0 U0_DCM : DCM port map ( CLKIN => CLKIN_OSC, CLKFB => CLK_OSC, DSSEN => GND, PSINCDEC => GND, PSEN => GND, PSCLK => GND, RST => RESET, CLK0 => CLKFB_OSC, LOCKED => RSTl ); -----------------------------end of clock deskew--------------------------- -- -- module configured CONFIG_DONE <= '0'; -- set low pass filter response and no zero stuffing for both DACs DAC1_MOD0 <= '0'; DAC1_MOD1 <= '0'; DAC2_MOD0 <= '0'; DAC2_MOD1 <= '0'; -- disable resets for DACs DAC1_RESET <= '0'; DAC2_RESET <= '0'; ĐH Công Nghệ- ĐHQG Hà Nội Khoá luận tốt nghiệp Nguyễn Anh Cường 46 -- optimum settings for sampling rate DAC1_DIV0 <= '1'; DAC1_DIV1 <= '0'; DAC2_DIV0 <= '1'; DAC2_DIV1 <= '0'; -- digital output of adc to digital input of DAC U0: chiatan port map(CLK_OSC,5250,clk); DataRegisters : process (clk,RSTl) begin if RSTl = '0' then ADC1 <= "00000000000000"; ADC2 <= "00000000000000"; DAC1_D <= "00000000000000"; DAC2_D <= "00000000000000"; elsif clk = '1' and clk'event then --ADC1 <= ADC1_D; --ADC2 <= ADC2_D; if(ADC1_D(13)='1') then ADC1<="1111111"&ADC1_D(13 downto 7); else ADC1<="0000000"&ADC1_D(13 downto 7); end if; DAC1_D <= not (not DAC1(13) & DAC1(12 downto 0)); --DAC2_D <= not (not ADC2(13) & ADC2(12 downto 0)); end if; end process; thuchien:FIR_Filter port map (ADC1(13 downto 0),clk,RSTl,DAC1); -----------------------------led flasher section--------------------------- -- -- led flash counter process (CLK_OSC, RSTl) variable COUNT : std_logic_vector(26 downto 0); begin if RSTl = '0' then COUNT := (others => '0'); -- led assignments LED1_Red <= '0'; LED2_Red <= '0'; LED1_Green <= '0'; LED2_Green <= '0'; elsif CLK_OSC = '1' and CLK_OSC'event then COUNT := COUNT + 1; -- led assignments LED1_Red <= COUNT(26); LED2_Red <= COUNT(25); LED1_Green <= COUNT(25); LED2_Green <= COUNT(26); end if; end process; -----------------------------end of led flasher---------------------------- - end Behavioral; ĐH Công Nghệ- ĐHQG Hà Nội Khoá luận tốt nghiệp Nguyễn Anh Cường 47 Library ieee; Use ieee.std_logic_1164.all; Entity FIR_Filter is Generic(n: integer :=14; -- width of data m: integer := 51); -- order of FIR Port ( Xin: in std_logic_vector(n-1 downto 0); clk,reset: in std_logic; Yout: out std_logic_vector(n-1 downto 0) ); end FIR_FIlTER; architecture arch_FIR of FIR_FILTER is Component FF_D Generic(n: integer :=14); Port ( D :in std_logic_vector(n-1 downto 0); Clk,Reset: in std_logic; --enable: in std_logic; Q: out std_logic_vector(n-1 downto 0) ); end Component; component PE is Generic(n: integer :=14); Port ( Xin,Ain: in std_logic_vector(n-1 downto 0); Yin: in std_logic_vector(n-1 downto 0); clk,reset : in std_logic; Xout: inout std_logic_vector(n-1 downto 0); Yout: out std_logic_vector(n-1 downto 0) ); end component; type A_cof is array(natural range m-1 downto 0) of std_logic_vector(n-1 downto 0); type Y_cof is array(natural range m-1 downto 0) of std_logic_vector(n-1 downto 0); constant Ain : A_cof := ("00000000000001","00000000000001","00000000000001","00000000000001","00000 000000001","00000000000000","00000000000000","11111111111111","111111111111 11","11111111111110","11111111111110","11111111111110","11111111111110","11 111111111110","11111111111111","00000000000000","00000000000001","000000000 00010","00000000000100","00000000000101","00000000000110","00000000001000", "00000000001001","00000000001010","00000000001010","00000000001010","000000 00001010","00000000001010","00000000001001","00000000001000","0000000000011 0","00000000000101","00000000000100","00000000000010","00000000000001","000 00000000000","11111111111111","11111111111110","11111111111110","1111111111 1110","11111111111110","11111111111110","11111111111111","11111111111111"," 00000000000000","00000000000000","00000000000001","00000000000001","0000000 0000001","00000000000001","00000000000001"); ĐH Công Nghệ- ĐHQG Hà Nội Khoá luận tốt nghiệp Nguyễn Anh Cường 48 signal Xout: std_logic_vector(n-1 downto 0); signal Ytin,Ytout: std_logic_vector(n-1 downto 0); signal X: a_cof; signal Y: Y_cof; begin Y(m-1) '0'); PE_for: for i in 0 to m-2 generate -- Concurrent Statement(s) PE1: PE port map (X(m-2-i),Ain(i),Y(m-1-i),clk,reset,X(m-1- i),Y(m-2-i)); end generate; PE2: PE port map (Xin,Ain(m-1),Y(0),clk,reset,X(0),Ytout); REGST1: FF_D port map (ytout,clk,reset,Yout); --REGST2: FF_D port map (Ytout,clk,reset,Yout); end arch_FIR; ------------ Library ieee; Use ieee.std_logic_1164.all; Entity PE is Generic(n: integer :=14); Port ( Xin,Ain: in std_logic_vector(n-1 downto 0); Yin: in std_logic_vector(n-1 downto 0); clk,reset : in std_logic; Xout: inout std_logic_vector(n-1 downto 0); Yout: out std_logic_vector(n-1 downto 0) ); end PE; architecture arch_PE of PE is Component adder PORT ( dataa : IN STD_LOGIC_VECTOR (13 DOWNTO 0); datab : IN STD_LOGIC_VECTOR (13 DOWNTO 0); result : OUT STD_LOGIC_VECTOR (13 DOWNTO 0) ); END Component; Component mult PORT ( dataa : IN STD_LOGIC_VECTOR (13 DOWNTO 0); datab : IN STD_LOGIC_VECTOR (13 DOWNTO 0); result : OUT STD_LOGIC_VECTOR (13 DOWNTO 0) ); END Component; -- Declarations (optional) Component FF_D Generic(n: integer :=14); Port ( D :in std_logic_vector(n-1 downto 0); Clk,Reset: in std_logic; --Enable: in std_logic; Q: out std_logic_vector(n-1 downto 0) ĐH Công Nghệ- ĐHQG Hà Nội Khoá luận tốt nghiệp Nguyễn Anh Cường 49 ); end Component; signal S1,S2,S3: STD_LOGIC_VECTOR (n-1 DOWNTO 0); signal rmul: STD_LOGIC_VECTOR (n-1 DOWNTO 0); begin REGX: FF_D generic map (n => 14) port map (Xin,clk,reset,Xout); Multi: mult port map (xout,ain,rmul); --REGS0: FF_D port map (s1,clk,reset,rmul); adderS: adder port map (rmul,Yin,Yout); --REGS1: FF_D port map (S2,clk,reset,S3); --REGS2: FF_D port map (S3,clk,reset,Yout); end arch_PE; ------------ Library ieee; Use ieee.std_logic_1164.all; Entity FF_D is Generic(n: integer :=14); Port ( D :in std_logic_vector(n-1 downto 0); Clk,Reset: in std_logic; --Enable: in std_logic; Q: out std_logic_vector(n-1 downto 0) ); end FF_D; architecture arch_FFD of FF_D is Begin Process (clk,reset) begin if clk'event and clk = '1' then --if enable = '1' then if reset = '0' then Q '0'); else Q <= D; end if; --end if; end if; end process; end arch_FFD; -------------------------------- library IEEE; use IEEE.STD_LOGIC_1164.all; use IEEE.STD_LOGIC_ARITH.all; use IEEE.STD_LOGIC_SIGNED.all; entity mult is PORT ( dataa : IN STD_LOGIC_VECTOR (13 DOWNTO 0); datab : IN STD_LOGIC_VECTOR (13 DOWNTO 0); result : OUT STD_LOGIC_VECTOR (13 DOWNTO 0) ); END mult; ĐH Công Nghệ- ĐHQG Hà Nội Khoá luận tốt nghiệp Nguyễn Anh Cường 50 architecture run_mult of mult is begin result <= dataa*datab; --result(13)<= dataa(7) xor datab(7); end run_mult; ------------------------------------------------------------- library IEEE; use IEEE.STD_LOGIC_1164.all; use IEEE.STD_LOGIC_ARITH.all; use IEEE.STD_LOGIC_SIGNED.all; entity adder is PORT ( dataa : IN STD_LOGIC_VECTOR (13 DOWNTO 0); datab : IN STD_LOGIC_VECTOR (13 DOWNTO 0); result : OUT STD_LOGIC_VECTOR (13 DOWNTO 0) ); END adder; architecture run_add of adder is begin result<=dataa+datab; end run_add; -------------------------------------------- library ieee; use ieee.std_logic_1164.all; use IEEE.STD_LOGIC_ARITH.all; use IEEE.STD_LOGIC_SIGNED.all; entity chiatan is port( clk_i : in std_logic; sochia : in integer; clk_o : out std_logic ); end chiatan; architecture run_chia of chiatan is begin process(clk_i) variable i : integer range 0 to 50001 :=0; variable j : integer range 0 to 50000 :=0; variable temp : std_logic:='1'; begin j:=sochia/2; if(clk_i'event and clk_i='1') then i:=i+1; if(i>=j) then i:=0;temp:=not(temp);--;j:=j+1; --if(j>=sochia) then j:=0; temp:=not(temp); end if; end if; --end if; clk_o<=temp; end process; end run_chia; ĐH Công Nghệ- ĐHQG Hà Nội Khoá luận tốt nghiệp Nguyễn Anh Cường 51 2. Chương trình thiết kế bộ lọc FIR theo kiến trúc systolic array library IEEE; use IEEE.STD_LOGIC_1164.all; use IEEE.STD_LOGIC_ARITH.all; use IEEE.STD_LOGIC_UNSIGNED.all; entity Toplevel is port ( -- main clock input from oscilator CLK1_FB : in std_logic; -- main reset input from mb RESETl : in std_logic; -- configuration done signal CONFIG_DONE : out std_logic; -- dac 14 bit data outputs DAC1_D : out std_logic_vector(13 downto 0); DAC2_D : out std_logic_vector(13 downto 0); -- adc 14 bit data inputs ADC1_D : in std_logic_vector(13 downto 0); ADC2_D : in std_logic_vector(13 downto 0); -- dac reset signals DAC1_RESET : out std_logic; DAC2_RESET : out std_logic; -- dac setup DAC1_MOD0 : out std_logic; DAC1_MOD1 : out std_logic; DAC2_MOD0 : out std_logic; DAC2_MOD1 : out std_logic; -- dac clock divider setup DAC1_DIV0 : out std_logic; DAC1_DIV1 : out std_logic; DAC2_DIV0 : out std_logic; DAC2_DIV1 : out std_logic; -- led flash signals LED1_Red : out std_logic; LED2_Red : out std_logic; LED1_Green : out std_logic; LED2_Green : out std_logic ); end Toplevel; architecture Behavioral of Toplevel is -- clock components component BUFG port ( I : in std_logic; O : out std_logic ); end component; component IBUFG port ( I : in std_logic; O : out std_logic ); end component; ĐH Công Nghệ- ĐHQG Hà Nội Khoá luận tốt nghiệp Nguyễn Anh Cường 52 component DCM generic ( DLL_FREQUENCY_MODE : string := "LOW"; DUTY_CYCLE_CORRECTION : string := "TRUE"; STARTUP_WAIT : string := "FALSE" ); port ( CLKIN : in std_logic; CLKFB : in std_logic; DSSEN : in std_logic; PSINCDEC : in std_logic; PSEN : in std_logic; PSCLK : in std_logic; RST : in std_logic; CLK0 : out std_logic; CLK90 : out std_logic; CLK180 : out std_logic; CLK270 : out std_logic; CLK2X : out std_logic; CLK2X180 : out std_logic; CLKDV : out std_logic; CLKFX : out std_logic; CLKFX180 : out std_logic; LOCKED : out std_logic; PSDONE : out std_logic; STATUS : out std_logic_vector(7 downto 0) ); end component; -- end of clock components -- internal clock and reset signals Component FIR_Filter Generic(n: integer :=14; -- width of data m: integer := 51); -- order of FIR Port ( Xin: in std_logic_vector(n-1 downto 0); clk,reset: in std_logic; Yout: out std_logic_vector(n-1 downto 0) ); end Component; component chiatan port( clk_i : in std_logic; sochia : in integer; clk_o : out std_logic ); end component; signal CLKIN_OSC, CLKFB_OSC, CLK_OSC, RESET, RSTl : std_logic; -- temporary registers signal ADC1, ADC2 : std_logic_vector(13 downto 0); signal DAC1 :std_logic_vector(13 downto 0); signal DAC2 :std_logic_vector(13 downto 0); signal data :std_logic_vector(13 downto 0); -- common ground signal GND : std_logic; signal clk:std_logic; ĐH Công Nghệ- ĐHQG Hà Nội Khoá luận tốt nghiệp Nguyễn Anh Cường 53 begin GND <= '0'; RESET <= not RESETl; -----------------------------clock deskew section-------------------------- --- -- IBUFG Instantiation for CLK_IN U0_IBUFG : IBUFG port map ( I => CLK1_FB, O => CLKIN_OSC ); -- BUFG Instantiation for CLKFB U0_BUFG : BUFG port map ( I => CLKFB_OSC, O => CLK_OSC ); -- DCM Instantiation for internal deskew of CLK0 U0_DCM : DCM port map ( CLKIN => CLKIN_OSC, CLKFB => CLK_OSC, DSSEN => GND, PSINCDEC => GND, PSEN => GND, PSCLK => GND, RST => RESET, CLK0 => CLKFB_OSC, LOCKED => RSTl ); -----------------------------end of clock deskew--------------------------- -- -- module configured CONFIG_DONE <= '0'; -- set low pass filter response and no zero stuffing for both DACs DAC1_MOD0 <= '0'; DAC1_MOD1 <= '0'; DAC2_MOD0 <= '0'; DAC2_MOD1 <= '0'; -- disable resets for DACs DAC1_RESET <= '0'; DAC2_RESET <= '0'; -- optimum settings for sampling rate DAC1_DIV0 <= '1'; DAC1_DIV1 <= '0'; DAC2_DIV0 <= '1'; DAC2_DIV1 <= '0'; -- digital output of adc to digital input of DAC U0: chiatan port map(CLK_OSC,5250,clk); ĐH Công Nghệ- ĐHQG Hà Nội Khoá luận tốt nghiệp Nguyễn Anh Cường 54 DataRegisters : process (clk,RSTl) begin if RSTl = '0' then ADC1 <= "00000000000000"; ADC2 <= "00000000000000"; DAC1_D <= "00000000000000"; DAC2_D <= "00000000000000"; elsif clk = '1' and clk'event then --ADC1 <= ADC1_D; --ADC2 <= ADC2_D; if(ADC1_D(13)='1') then ADC1<="1111111"&ADC1_D(13 downto 7); else ADC1<="0000000"&ADC1_D(13 downto 7); end if; DAC2<=ADC1_D; DAC1_D <= not (not DAC1(13) & DAC1(12 downto 0)); DAC2_D <= not (not DAC2(13) & DAC2(12 downto 0)); end if; end process; thuchien:FIR_Filter port map (ADC1(13 downto 0),clk,RSTl,DAC1); -----------------------------led flasher section--------------------------- -- -- led flash counter process (CLK_OSC, RSTl) variable COUNT : std_logic_vector(26 downto 0); begin if RSTl = '0' then COUNT := (others => '0'); -- led assignments LED1_Red <= '0'; LED2_Red <= '0'; LED1_Green <= '0'; LED2_Green <= '0'; elsif CLK_OSC = '1' and CLK_OSC'event then COUNT := COUNT + 1; -- led assignments LED1_Red <= COUNT(26); LED2_Red <= COUNT(25); LED1_Green <= COUNT(25); LED2_Green <= COUNT(26); end if; end process; -----------------------------end of led flasher---------------------------- end Behavioral; Library ieee; Use ieee.std_logic_1164.all; Entity FIR_Filter is Generic(n: integer :=14; -- width of data m: integer := 51); -- order of FIR Port ( Xin: in std_logic_vector(n-1 downto 0); clk,reset: in std_logic; ĐH Công Nghệ- ĐHQG Hà Nội Khoá luận tốt nghiệp Nguyễn Anh Cường 55 Yout: out std_logic_vector(n-1 downto 0) ); end FIR_FIlTER; architecture arch_FIR of FIR_FILTER is Component FF_D Generic(n: integer :=14); Port ( D :in std_logic_vector(n-1 downto 0); Clk,Reset: in std_logic; --enable: in std_logic; Q: out std_logic_vector(n-1 downto 0) ); end Component; component PE is Generic(n: integer :=14); Port ( Xin,Ain: in std_logic_vector(n-1 downto 0); Yin: in std_logic_vector(n-1 downto 0); clk,reset : in std_logic; Xout: inout std_logic_vector(n-1 downto 0); Yout: out std_logic_vector(n-1 downto 0) ); end component; type A_cof is array(natural range m-1 downto 0) of std_logic_vector(n-1 downto 0); type Y_cof is array(natural range m-1 downto 0) of std_logic_vector(n-1 downto 0); constant Ain : A_cof := ("00000000000001","00000000000001","00000000000001","00000000000001","00000 000000001","00000000000000","00000000000000","11111111111111","111111111111 11","11111111111110","11111111111110","11111111111110","11111111111110","11 111111111110","11111111111111","00000000000000","00000000000001","000000000 00010","00000000000100","00000000000101","00000000000110","00000000001000", "00000000001001","00000000001010","00000000001010","00000000001010","000000 00001010","00000000001010","00000000001001","00000000001000","0000000000011 0","00000000000101","00000000000100","00000000000010","00000000000001","000 00000000000","11111111111111","11111111111110","11111111111110","1111111111 1110","11111111111110","11111111111110","11111111111111","11111111111111"," 00000000000000","00000000000000","00000000000001","00000000000001","0000000 0000001","00000000000001","00000000000001"); signal Xout: std_logic_vector(n-1 downto 0); signal Ytin,Ytout: std_logic_vector(n-1 downto 0); signal X: a_cof; signal Y: Y_cof; begin X(0) <= Xin; Y(0) '0'); PE_for: for i in 0 to m-2 generate -- Concurrent Statement(s) ĐH Công Nghệ- ĐHQG Hà Nội Khoá luận tốt nghiệp Nguyễn Anh Cường 56 PE1: PE port map (X(i),Ain(i),Y(i),clk,reset,X(i+1),Y(i+1)); end generate; PE2: PE port map (X(49),Ain(49),Y(49),clk,reset,Xout,Yout); end arch_FIR; ------------ Library ieee; Use ieee.std_logic_1164.all; Entity PE is Generic(n: integer :=14); Port ( Xin,Ain: in std_logic_vector(n-1 downto 0); Yin: in std_logic_vector(n-1 downto 0); clk,reset : in std_logic; Xout: inout std_logic_vector(n-1 downto 0); Yout: out std_logic_vector(n-1 downto 0) ); end PE; architecture arch_PE of PE is Component adder PORT ( dataa : IN STD_LOGIC_VECTOR (13 DOWNTO 0); datab : IN STD_LOGIC_VECTOR (13 DOWNTO 0); result : OUT STD_LOGIC_VECTOR (13 DOWNTO 0) ); END Component; Component mult PORT ( dataa : IN STD_LOGIC_VECTOR (13 DOWNTO 0); datab : IN STD_LOGIC_VECTOR (13 DOWNTO 0); result : OUT STD_LOGIC_VECTOR (13 DOWNTO 0) ); END Component; -- Declarations (optional) Component FF_D Generic(n: integer :=14); Port ( D :in std_logic_vector(n-1 downto 0); Clk,Reset: in std_logic; --Enable: in std_logic; Q: out std_logic_vector(n-1 downto 0) ); end Component; signal S1,S2,S3: STD_LOGIC_VECTOR (n-1 DOWNTO 0); signal rmul: STD_LOGIC_VECTOR (n-1 DOWNTO 0); begin REGX: FF_D generic map (n => 14) port map (Xin,clk,reset,Xout); Multi: mult port map (xout,ain,rmul); --REGS0: FF_D port map (s1,clk,reset,rmul); adderS: adder port map (rmul,Yin,S2); ĐH Công Nghệ- ĐHQG Hà Nội Khoá luận tốt nghiệp Nguyễn Anh Cường 57 REGS1: FF_D port map (S2,clk,reset,S3); REGS2: FF_D port map (S3,clk,reset,Yout); end arch_PE; ------------ Library ieee; Use ieee.std_logic_1164.all; Entity FF_D is Generic(n: integer :=14); Port ( D :in std_logic_vector(n-1 downto 0); Clk,Reset: in std_logic; --Enable: in std_logic; Q: out std_logic_vector(n-1 downto 0) ); end FF_D; architecture arch_FFD of FF_D is Begin Process (clk,reset) begin if clk'event and clk = '1' then --if enable = '1' then if reset = '0' then Q '0'); else Q <= D; end if; --end if; end if; end process; end arch_FFD; -------------------------------- library IEEE; use IEEE.STD_LOGIC_1164.all; use IEEE.STD_LOGIC_ARITH.all; use IEEE.STD_LOGIC_SIGNED.all; entity mult is PORT ( dataa : IN STD_LOGIC_VECTOR (13 DOWNTO 0); datab : IN STD_LOGIC_VECTOR (13 DOWNTO 0); result : OUT STD_LOGIC_VECTOR (13 DOWNTO 0) ); END mult; architecture run_mult of mult is begin result <= dataa*datab; --result(13)<= dataa(7) xor datab(7); end run_mult; ------------------------------------------------------------- library IEEE; use IEEE.STD_LOGIC_1164.all; use IEEE.STD_LOGIC_ARITH.all; use IEEE.STD_LOGIC_SIGNED.all; ĐH Công Nghệ- ĐHQG Hà Nội Khoá luận tốt nghiệp Nguyễn Anh Cường 58 entity adder is PORT ( dataa : IN STD_LOGIC_VECTOR (13 DOWNTO 0); datab : IN STD_LOGIC_VECTOR (13 DOWNTO 0); result : OUT STD_LOGIC_VECTOR (13 DOWNTO 0) ); END adder; architecture run_add of adder is begin result<=dataa+datab; end run_add; -------------------------------------------- library ieee; use ieee.std_logic_1164.all; use IEEE.STD_LOGIC_ARITH.all; use IEEE.STD_LOGIC_SIGNED.all; entity chiatan is port( clk_i : in std_logic; sochia : in integer; clk_o : out std_logic ); end chiatan; architecture run_chia of chiatan is begin process(clk_i) variable i : integer range 0 to 50001 :=0; variable j : integer range 0 to 50000 :=0; variable temp : std_logic:='1'; begin j:=sochia/2; if(clk_i'event and clk_i='1') then i:=i+1; if(i>=j) then i:=0;temp:=not(temp);--;j:=j+1; --if(j>=sochia) then j:=0; temp:=not(temp); end if; end if; --end if; clk_o<=temp; end process; end run_chia; ---------------------------------------------------- ĐH Công Nghệ- ĐHQG Hà Nội Khoá luận tốt nghiệp Nguyễn Anh Cường 59 3. Chương trình thiết kế bộ lọc FIR thích nghi dùng thuật toán LMS library IEEE; use IEEE.STD_LOGIC_1164.all; use IEEE.STD_LOGIC_ARITH.all; use IEEE.STD_LOGIC_SIGNED.all; entity Toplevel is port ( -- main clock input from oscilator CLK1_FB : in std_logic; -- main reset input from mb RESETl : in std_logic; -- configuration done signal CONFIG_DONE : out std_logic; -- dac 14 bit data outputs DAC1_D : out std_logic_vector(13 downto 0); DAC2_D : out std_logic_vector(13 downto 0); -- adc 14 bit data inputs ADC1_D : in std_logic_vector(13 downto 0); ADC2_D : in std_logic_vector(13 downto 0); -- dac reset signals DAC1_RESET : out std_logic; DAC2_RESET : out std_logic; -- dac setup DAC1_MOD0 : out std_logic; DAC1_MOD1 : out std_logic; DAC2_MOD0 : out std_logic; DAC2_MOD1 : out std_logic; -- dac clock divider setup DAC1_DIV0 : out std_logic; DAC1_DIV1 : out std_logic; DAC2_DIV0 : out std_logic; DAC2_DIV1 : out std_logic; -- led flash signals LED1_Red : out std_logic; LED2_Red : out std_logic; LED1_Green : out std_logic; LED2_Green : out std_logic ); end Toplevel; architecture Behavioral of Toplevel is -- clock components component BUFG port ( I : in std_logic; O : out std_logic ); end component; component IBUFG port ( I : in std_logic; O : out std_logic ); end component; component DCM generic ( DLL_FREQUENCY_MODE : string := "LOW"; ĐH Công Nghệ- ĐHQG Hà Nội Khoá luận tốt nghiệp Nguyễn Anh Cường 60 DUTY_CYCLE_CORRECTION : string := "TRUE"; STARTUP_WAIT : string := "FALSE" ); port ( CLKIN : in std_logic; CLKFB : in std_logic; DSSEN : in std_logic; PSINCDEC : in std_logic; PSEN : in std_logic; PSCLK : in std_logic; RST : in std_logic; CLK0 : out std_logic; CLK90 : out std_logic; CLK180 : out std_logic; CLK270 : out std_logic; CLK2X : out std_logic; CLK2X180 : out std_logic; CLKDV : out std_logic; CLKFX : out std_logic; CLKFX180 : out std_logic; LOCKED : out std_logic; PSDONE : out std_logic; STATUS : out std_logic_vector(7 downto 0) ); end component; -- end of clock components -- internal clock and reset signals component fir_lms IS ------> Interface GENERIC (W1 : INTEGER := 8; -- Input bit width W2 : INTEGER := 16; -- Multiplier bit width 2*W1 L : INTEGER := 2 -- Filter length ); PORT ( clk : IN STD_LOGIC; x_in : IN STD_LOGIC_VECTOR(W1-1 DOWNTO 0); d_in : IN STD_LOGIC_VECTOR(W1-1 DOWNTO 0); e_out : OUT STD_LOGIC_VECTOR(W2-1 DOWNTO 0); y_out :OUT STD_LOGIC_VECTOR(W2-1 DOWNTO 0) ); END component; component chiatan port( clk_i : in std_logic; sochia : in integer; clk_o : out std_logic ); end component; signal CLKIN_OSC, CLKFB_OSC, CLK_OSC, RESET, RSTl : std_logic; -- temporary registers signal ADC1, ADC2 : std_logic_vector(7 downto 0); signal DAC1 :std_logic_vector(13 downto 0); signal DAC2 :std_logic_vector(13 downto 0); signal data :std_logic_vector(13 downto 0); -- common ground signal GND : std_logic; signal clk:std_logic; ĐH Công Nghệ- ĐHQG Hà Nội Khoá luận tốt nghiệp Nguyễn Anh Cường 61 signal e,y: std_logic_vector(15 downto 0); begin GND <= '0'; RESET <= not RESETl; -----------------------------clock deskew section-------------------------- --- -- IBUFG Instantiation for CLK_IN U0_IBUFG : IBUFG port map ( I => CLK1_FB, O => CLKIN_OSC ); -- BUFG Instantiation for CLKFB U0_BUFG : BUFG port map ( I => CLKFB_OSC, O => CLK_OSC ); -- DCM Instantiation for internal deskew of CLK0 U0_DCM : DCM port map ( CLKIN => CLKIN_OSC, CLKFB => CLK_OSC, DSSEN => GND, PSINCDEC => GND, PSEN => GND, PSCLK => GND, RST => RESET, CLK0 => CLKFB_OSC, LOCKED => RSTl ); -----------------------------end of clock deskew--------------------------- -- -- module configured CONFIG_DONE <= '0'; -- set low pass filter response and no zero stuffing for both DACs DAC1_MOD0 <= '0'; DAC1_MOD1 <= '1'; DAC2_MOD0 <= '0'; DAC2_MOD1 <= '0'; -- disable resets for DACs DAC1_RESET <= '0'; DAC2_RESET <= '0'; -- optimum settings for sampling rate DAC1_DIV0 <= '0'; DAC1_DIV1 <= '1'; DAC2_DIV0 <= '1'; DAC2_DIV1 <= '0'; -- digital output of adc to digital input of DAC ĐH Công Nghệ- ĐHQG Hà Nội Khoá luận tốt nghiệp Nguyễn Anh Cường 62 U0: chiatan port map(CLK_OSC,5000,clk); DataRegisters : process (clk,RSTl) begin if RSTl = '0' then --e <= "0000000000000000"; --y <= "0000000000000000"; DAC1_D <= "00000000000000"; DAC2_D <= "00000000000000"; elsif clk = '1' and clk'event then ADC1<=ADC1_D(13 downto 6);--tin hieu+nhieu ADC2<=ADC2_D(13 downto 6);--nhieu DAC1_D <= e(15) ¬(e(14 downto 2));--loc DAC2_D <= ADC1_D(13) & not (ADC1_D(12 downto 0));--tin hieu +nhieu end if; end process; thuchien:FIR_LMS port map (clk,ADC2,ADC1,e,y); -----------------------------led flasher section--------------------------- -- -- led flash counter process (CLK_OSC, RSTl) variable COUNT : std_logic_vector(26 downto 0); begin if RSTl = '0' then COUNT := (others => '0'); -- led assignments LED1_Red <= '0'; LED2_Red <= '0'; LED1_Green <= '0'; LED2_Green <= '0'; elsif CLK_OSC = '1' and CLK_OSC'event then COUNT := COUNT + 1; -- led assignments LED1_Red <= COUNT(26); LED2_Red <= COUNT(25); LED1_Green <= COUNT(25); LED2_Green <= COUNT(26); end if; end process; end Behavioral; -----------------------------end of led flasher---------------------------- - -- This is a generic LMS FIR filter generator -- It uses W1 bit data/coefficients bits LIBRARY ieee; USE ieee.std_logic_1164.ALL; USE ieee.std_logic_arith.ALL; USE ieee.std_logic_signed.ALL; ENTITY fir_lms IS ------> Interface ĐH Công Nghệ- ĐHQG Hà Nội Khoá luận tốt nghiệp Nguyễn Anh Cường 63 GENERIC (W1 : INTEGER := 8; -- Input bit width W2 : INTEGER := 16; -- Multiplier bit width 2*W1 L : INTEGER := 2 -- Filter length ); PORT ( clk : IN STD_LOGIC; x_in : IN STD_LOGIC_VECTOR(W1-1 DOWNTO 0); d_in : IN STD_LOGIC_VECTOR(W1-1 DOWNTO 0); e_out : OUT STD_LOGIC_VECTOR(W2-1 DOWNTO 0); y_out :OUT STD_LOGIC_VECTOR(W2-1 DOWNTO 0) ); END fir_lms; ARCHITECTURE fpga OF fir_lms IS component mult is PORT ( dataa : IN STD_LOGIC_VECTOR (7 DOWNTO 0); datab : IN STD_LOGIC_VECTOR (7 DOWNTO 0); result : OUT STD_LOGIC_VECTOR (15 DOWNTO 0) ); END component; SUBTYPE N1BIT IS STD_LOGIC_VECTOR(W1-1 DOWNTO 0); SUBTYPE N2BIT IS STD_LOGIC_VECTOR(W2-1 DOWNTO 0); TYPE ARRAY_N1BIT IS ARRAY (0 TO L-1) OF N1BIT; TYPE ARRAY_N2BIT IS ARRAY (0 TO L-1) OF N2BIT; SIGNAL d : N1BIT; SIGNAL emu : N1BIT; SIGNAL y, sxty : N2BIT; SIGNAL e, sxtd : N2BIT; SIGNAL x, f : ARRAY_N1BIT; -- Coeff/Data arrays SIGNAL p, xemu : ARRAY_N2BIT; -- Product arrays BEGIN dsxt: PROCESS (d) -- 16 bit signed extension for input d BEGIN sxtd(7 DOWNTO 0) <= d; FOR k IN 15 DOWNTO 8 LOOP sxtd(k) <= d(d'high); END LOOP; END PROCESS; Store: PROCESS ------> Store these data or coefficients BEGIN WAIT UNTIL clk = '1'; d <= d_in; x(0) <= x_in; x(1)<=x(0); f(0) <= f(0) + xemu(0)(15 DOWNTO 8); f(1) <= f(1) + xemu(1)(15 DOWNTO 8); END PROCESS Store; MulGen1: FOR I IN 0 TO L-1 GENERATE FIR: mult PORT MAP ( x(I), f(I),p(I)); END GENERATE; ĐH Công Nghệ- ĐHQG Hà Nội Khoá luận tốt nghiệp Nguyễn Anh Cường 64 y <=p(0)+p(1); ysxt: PROCESS (y) -- Scale y by 128 because x is fraction BEGIN sxty(8 DOWNTO 0) <= y(15 DOWNTO 7); FOR k IN 15 DOWNTO 9 LOOP sxty(k) <= y(y'high); END LOOP; END PROCESS; e <= sxtd - sxty; emu <= e(8 DOWNTO 1); -- e*mu divide by 2 and -- 2 from xemu makes mu=1/4 MulGen2: FOR I IN 0 TO L-1 GENERATE FUPDATE: mult PORT MAP (x(I), emu,xemu(I)); END GENERATE; y_out <= sxty; -- Monitor some test signals e_out <= e; END fpga; library IEEE; use IEEE.STD_LOGIC_1164.all; use IEEE.STD_LOGIC_ARITH.all; use IEEE.STD_LOGIC_SIGNED.all; entity mult is PORT ( dataa : IN STD_LOGIC_VECTOR (7 DOWNTO 0); datab : IN STD_LOGIC_VECTOR (7 DOWNTO 0); result : OUT STD_LOGIC_VECTOR (15 DOWNTO 0) ); END mult; architecture run_mult of mult is begin result <= dataa*datab; --result(13)<= dataa(7) xor datab(7); end run_mult; ------------------------------------------------------------- library IEEE; use IEEE.STD_LOGIC_1164.all; use IEEE.STD_LOGIC_ARITH.all; use IEEE.STD_LOGIC_SIGNED.all; entity adder is PORT ( dataa : IN STD_LOGIC_VECTOR (13 DOWNTO 0); datab : IN STD_LOGIC_VECTOR (13 DOWNTO 0); result : OUT STD_LOGIC_VECTOR (13 DOWNTO 0) ); END adder; architecture run_add of adder is begin result<=dataa+datab; ĐH Công Nghệ- ĐHQG Hà Nội Khoá luận tốt nghiệp Nguyễn Anh Cường 65 end run_add; -------------------------------------------- library ieee; use ieee.std_logic_1164.all; use IEEE.STD_LOGIC_ARITH.all; use IEEE.STD_LOGIC_SIGNED.all; entity chiatan is port( clk_i : in std_logic; sochia : in integer; clk_o : out std_logic ); end chiatan; architecture run_chia of chiatan is begin process(clk_i) variable i : integer range 0 to 50001 :=0; variable j : integer range 0 to 50000 :=0; variable temp : std_logic:='1'; begin j:=sochia/2; if(clk_i'event and clk_i='1') then i:=i+1; if(i>=j) then i:=0;temp:=not(temp);--;j:=j+1; --if(j>=sochia) then j:=0; temp:=not(temp); end if; end if; --end if; clk_o<=temp; end process; end run_chia;

Các file đính kèm theo tài liệu này:

  • pdfThuc_hien_bo_loc_FIR_thich_nghi_dung_thuat_toan__LMS.pdf