Praktikum Sistem Digital Lanjut Percobaan 5: Desain Rangkaian Sekuensial
1 Tujuan dan Sasaran Kegiatan praktikum ini bertujuan untuk membuat rangkaian yang menampilkan keluaran LED secara sekuensial yang dikontrol oleh pemutaran rotary-knob dan tombol push-button. Konsep yang ingin dipahami adalah rancangan rangkaian sekuensial menggunakan FSM (Finite State Machine). Kegiatan praktikum ini bertujuan untuk membuat generator sinyal clock yang dapat diatur keluaran frekuensinya. Sasaran kegiatan praktikum adalah: 1. Praktikan dapat memahami rangkaian sekuensial menggunakan diagram Moore; 2. Praktikan dapat mengimplementasikan rancangan tersebut untuk mengontrol nyala LED secara sekuensial dengan pemutaran rotary-knob dan/atau tombol push-button; 3. Praktikan dapat menganalisis hasil implementasi; 4. Praktikan dapat menganalisis perilaku masukan-keluaran desain di board Starter Kit; Sumber referensi yang bisa digunakan: 1. UG230: Spartan-3E FPGA Starter Kit Board User Guide, Xilinx, June 2008 2. Ken Chapman: Rotary Encoder Interface for Spartan-3E Starter Kit, Xilinx, 2006 3. Spartan-3E Starter Board Schematic, Digilent, Feb 2006 4. Xilinx ISE Design Suite 11 Software Manual, Xilinx, 2009 5. Verilog Tutorial (online): http://www.asic-world.com/verilog/veritut.html
2 Alat dan Bahan Alat dan bahan yang digunakan adalah: 1. Board Starter Kit Spartan-3E berbasis Xilinx FPGA XC3S500E-4FG320C; Modul (komponen) I/O yang akan digunakan dalam praktikum: a) 4 buah tombol push-button (BTN North, BTN East, BTN South, BTN West); b) 1 buah rotary-knob (ROT-A/B); c) 8 buah LED (LD0-7); d) Sumber clock 50MHz dan konektor SMA; 2. Kabel USB dengan konektor tipe-B; 3. Osiloskop digital; 4. Adaptor sumber daya DC 5 Volt; 5. Software Xilinx ISE Webpack 11.1;Dasar Teori
3 Dasar Teori Di bab ini dijelaskan tentang rotary-encoder (di komponen rotary-knob), sumber clock di starter kit dan FSM (Finite State Machine). Penjelasan tentang komponen lain yang digunakan
telah dijabarkan di praktikum sebelumnya. 3.1 Rotary-Knob dan Enkoder Putar Rotary-knob berisi tombol tekan dan enkoder putar yang digunakan sebagai masukan. Tombol tekan dan eknoder putar akan menghasilkan sinyal keluaran ROT_CENTER, ROT_A dan ROT_B (Gambar 1). Rotary-enkoder menggunakan sistem mekanik yang mungkin rentan terhadap bouncing. Untuk mengatasinya digunakan filter (Gambar 2).
Gambar 1: Tombol tekan dan enkoder putar di rotary-knob beserta sinyal-sinyal keluarannya (UG320, Ken Chapman)
Gambar 2: Bouncing dan hasil keluaran enkoder hasil dari filter (Ken Chapman)
3.2 Sumber Clock di Starter Kit Dalam starter kit terdapat sumber clock on-board 50MHz. Selain itu, sumber clock juga bisa diperoleh dari eksternal melalui sebuah konektor tipe-SMA (CLK_SMA). Dalam praktikum, sumber clock akan menggunakan clock on-board 50MHz, sedangkan keluaran clock akan dilewatkan melalui konektor CLK_SMA untuk diukur frekuensinya dengan osilopkop (Gambar 3). Koneksi clock ini ditunjukkan dalam Gambar 4.
IO9(D7) IO10(C7) IO11(F8) IO12(E8) GND VCC
IO12 digunakan sebagai port CLK_OUT Gambar 3: Sumber clock dan port keluaran clock yang akan digunakan dalam praktikum (Sumber: UG320)
Gambar 4: Koneksi sumber clock dan CLK_SMA serta definisi UCF 3.3 Finite State Machine (FSM) Rangkaian sekuensial keluarannya tergantung dari masukannya saat itu dan masukan sebelumnya. Dalam rangkaian ini terdapat elemen penyimpan (storage) berupa flip-flop. Flipflop dapat menyimpan 1-bit data masukan. Register n-bit tersusun atas n buah flip-flop, sehingga dapat menyimpan data masukan sejumlah n-bit. Rangkaian sekuensial dapat disebut juga rangkaian FSM (finite state machine). Rangkaian sekuensial sinkron menggunakan sebuah clock untuk mengontrol operasinya. Rangkaian ini direalisasikan menggunakan logika kombinasional dan satu atau beberapa flip-flop. Model yang bisa digunakan adalah (Gambar 5): 1. model Moore: keluaran rangkaian tergantung hanya pada state (keadaan) rangkaian saat ini; 2. model Mealy: keluaran rangkaian tergantung pada state saat ini dan masukan utamanya;
Next-state logic
Current-state logic
Output logic
Gambar 5: Model FSM: Moore dan Mealy
4 Cara Kerja Kegiatan praktikum dilakukan untuk memenuhi kebutuhan desain yang diinginkan. Setiap tahap dilakukan berdasarkan cara kerja yang diuraikan dalam Subbab 4.2. Hasil kegiatan praktikum yang ditandai dengan ikon dituliskan dalam Lembar Isian Kegiatan. Laporan akhir disusun dengan menyertakan hasil kegiatan praktikum. 4.1 Kebutuhan Desain Desain yang akan diimplementasikan dalam praktikum ini adalah: 1. Enkoder putar (ROT_ENC), menghasilkan keluaran Out 2-bit yang menandakan arah putaran (0x: tidak ada pemutaran, 11: ke kiri, 10: ke kanan, lainnya: tidak ada putaran); 2. Pencacah asinkron up-down 3-bit (COUNT_3B) menghasilkan nilai keluaran 0-7 dari input tombol tekan (BTN_*) dan enkoder puter; 3. Clock divider (CLOCK_DIV) membagi frekuensi sinyal masukan clk (50MHz) berdasarkan nilai masukan pembaginya (div), seperti ditunjukkan dalam Tabel 1; 4. Indikator frekeunsi (CLOCK_STAT) berlaku seperti dekoder 3-to-8; 5. 2 buah debouncer tombol, yaitu DEBOUNCER_UP untuk BTN_EAST (Up) dan DEBOUNCER_DOWN untuk BTN_WEST (Down); Desain tersebut dibuat sebagai modul dan akan diintegrasikan dalam satu top_module. Diagram blok top_module beserta koneksinya diperlihatkan dalam Gambar 6 dan Tabel 2. BTN_NORTH
NORTH BTN_EAST EAST SOUTH WEST
BTN_SOUTH BTN_WEST
ROT_A
ROT_A
ROT_B
ROT_B
V4 H13
DE K17 BOUN D18 CER
Out[7:0] in[2:0] CLOCK_STAT
Set Out[2:0] Reset Up Down clk
G18
D11
3
C11 Clkout F11 Clkout2 E11 clk CLOCK_DIV E12
rlrot[1:0] K18
div[2:0]
COUNT_3B
F12
2 CLK
CLK
C9
rot_A rlrot[1:0] rot_B clk ROT_ENC
F9 E9
top_module XC3S500E-4FG320C
Gambar 6: Diagram blok sistem yang dirancang
A10
LED<7> LED<6> LED<5> LED<4> LED<3> LED<2> LED<1> LED<0>
CLK_SMA
LD7 LD6 LD5 LD4 LD3 LD2 LD1 LD0 CLKOUT
Nilai div masukan 0 1 2 3 4 5 6 7
Pembagi 1 2 4 8 16 32 64 128
Frekuensi keluaran 50 MHz 25 MHz 12,5 MHz 6,25 MHz 3,125 MHz 1,5625 MHz 781,25 kHz 390,625 kHz
Tabel 1: Nilai frekuensi keluaran CLK_DIV dari nilai masukan pembaginya 4.2 Langkah Kerja Kegiatan praktikum meliputi hal-hal sebagai berikut: 1. Menuliskan kode HDL untuk COUNT_3B, DEBOUNCER, ROT_ENC, CLOCK_STAT dan CLOCK_DIV sebagai modul. Masukkan modul tersebut dalam proyek desain_sekuensial; 2. Mengaplikasikan modul-modul tersebut dalam satu top_module (sekuensial_top); 3. Menambah file konstrain desain_sekuensial.ucf ; Nama sinyal (top) BTN_NORTH BTN_WEST BTN_EAST BTN_SOUTH ROT_A ROT_B CLK LED<7> LED<6> LED<5> LED<4> LED<3> LED<2> LED<1> LED<0> CLK_SMA CLK_OUT
top_modul Set Down Up Reset rot_A rot_B clk Out[7] Out[6] Out[5] Out[4] Out[3] Out[2] Out[1] Out[0] Clkout Clkout2
Koneksi modul COUNT_3B DEBOUNCER_DOWN DEBOUNCER_UP COUNT_3B ROT_ENC ROT_ENC Semua, kecuali CLOCK_STAT CLOCK_STAT CLOCK_STAT CLOCK_STAT CLOCK_STAT CLOCK_STAT CLOCK_STAT CLOCK_STAT CLOCK_STAT CLOCK_DIV CLOCK_DIV
Keterangan Set frek ke max Turunkan frekuensi Naikkan frekuensi Reset frek ke min Putar kanan: naikkan frek Putar kiri: turunkan frek Sumber clock
Indikator frekuensi LED[7] frekuensi paling tinggi, sedangkan LED[0] frekuensi paling rendah
Keluaran clock Buffer dari CLK_SMA
Tabel 2: Koneksi sinyal di top_module dengan FPGA 4. Mensintesis dan mengimplementasikan sekuensial_top; 1. Melihat skematik RTL atau skematik teknologi; 2. Melihat utilisasi device yang digunakan oleh desain; 5. Membangkitkan file programming sekuensial_top.bit; 6. Memprogram file *.bit tersebut dan mengamati perilaku sistem;
4.2.1 Membuat Proyek Baru Langkah-langkah membuat proyek baru: 1. Pilih menu File→New Project (Alt+F W). Dialog pop-up New Project Wizard akan muncul. Ketikkan field Name dengan nama proyek (Format:
Modul5-DesainSekuensial). Browse lokasi proyek/Location (folder $HOME_DIR/). Isi field Description dengan penjelasan tentang proyek. Tipe source top-level menggunakan HDL Tuliskan field Name, Location dan Description dalam lembar kegiatan; 2. Klik tombol Next. Jendela Device Properties muncul. Pilih Family (Spartan3E), Device (XC3S500E), Package (FG320) dan Speed (-4). Properti ini adalah devicedependent (Starter Kit menggunakan FPGA XC3S500E-4FG320C), jadi harus dimasukkan dengan benar. Set Preferred Language dengan Verilog Catat field Family, Device, Package dan Speed ini dalam lembar kegiatan; 4.2.2 Menambah Modul Desain dan Konstrain Modul yang perlu ditambahkan ada 5 buah, yaitu count_3b, debouncer, rot_enc, clock_stat dan clock_div. Langkah-langkahnya adalah sebagai berikut: 1. Buat modul-modul verilog seperti dalam Tabel 3. Masukkan dalam proyek; No Nama Modul 1. count_3b
2. debouncer 3. rot_enc
4. clock_div 5. clock_stat
Masukan set reset up down rlrot[1:0] clk clk in_state rot_A rot_B clk div[2:0] clk data_in[2:0]
Keluaran y_out[2:0]
out_state rlrot[1:0]
clk_out clk_out2 data_out[7:0]
Keterangan Modifikasi dari count_1 (bab IV) dengan menghilangkan mode dan y_out menjadi 3 bit. Tambahan input rlrot 2-bit (R/L) untuk counting dari enkoder rotary Switch debouncer, sama dengan bab IV Enkoder putar. rlrot menandakan putar kanan/kiri Pembagi frekuensi clock Display nilai frekuensi clock dalam simbol
Tabel 3: Nama modul-modul desain yang akan dibuat 2. Edit file count_3b.v, debouncer.v, rot_enc.v, clock_div.v dan clock_stat.v. Listing kode sumber HDL untuk semua desain modul ada dalam Lampiran; (Tugas) Jelaskan perilaku tiap kode HDL tersebut. Gambarkan diagram dan tabel state dari modul count_3b menggunakan model Moore (Tugas) Jelaskan kerja dari clock divider. Gambarkan diagram pewaktuan sinyal masukan dan keluaran dari modul clock_div 3. Tambahkan file konstrain desain_sekuensial.ucf. Isi file tersebut ada dalam Lampiran;
4.2.3 Mengaplikasikan Modul dalam Desain (Top Module) Ketiga modul tersebut di atas akan diaplikasikan dalam satu top_module (desain berbasis komponen). Langkah yang diperlukan adalah: 1. Buat top_module yang mengintegrasikan kedua modul tersebut dengan nama sekuensial_top. Definisi port masukan dan keluaran dari sekuensial_top ini ditunjukkan dalam Tabel 4; 2. Panggil ketiga modul dari sekuensial_top ini dan interkoneksikan port-portnya. Listing kode sumber HDL untuk sekuensial_top.v ada dalam Lampiran. Tampilan ISE setelah integrasi ditunjukkan dalam Gambar 7; No Nama Modul 1. sekuensial_top
Masukan BTN_NORTH, BTN_EAST, BTN_SOUTH, BTN_WEST, CLK ROT_A ROT_B
Keluaran LED[7:0] CLK_SMA CLK_OUT
Keterangan
Tabel 4: Nama port masukan dan keluaran di modul sekuensial_top.v
Gambar 7: Modul-modul yang diperlukan diintegrasikan ke sekuensial_top 4.2.4 Sintesis dan Implementasikan Top Modul Modul sekuensial_top akan disintesis dan diimplementasikan. Langkah-langkahnya adalah sebagai berikut: 1. Cek apakah modul sekuensial_top sudah menjadi top_module. Hanya top_module yang bisa disintesis dan diimplementasikan. Jika belum, klik kanan modul tersebut dan pilih 'Set as Top Module'; 2. Bangkitkan skematik RTL dari sekuensial_top. Klik “View RTL Schematic” dari proses Synthesize dan juga “View Technology Schematic”. Tambahkan elemen yang tersedia
dan klik tombol “Create Schematic”. Lihat blok dari elemen dan bagaimana isinya (rangkaian logikanya); Simpan gambar blok elemen beserta rangkaian skematiknya dalam file gambar (dengan snapshot). Skematik ini beserta penjelasannya harus dilampirkan di laporan (Tugas) Jelaskan perbedaan antara skematik RTL dan skematik teknologi (secara terminologi dan konseptual) 3. Sintesis dan implemen kombinasional_top dengan mengklik kanan proses “Implement Design” dan pilih “Rerun All”; Lihat ringkasan laporan desain dari implementasi kombinasional_top tersebut dengan melihat tab Design Summary. Jika belum ada, klik menu Project→Design Summary/Report. Catat hasilnya untuk mengisi tabel utilisasi device di lembar kegiatan; 4.2.5 Memprogram FPGA dan Pengamatan Perilaku Sistem Perilaku sistem diamati dengan melihat keluaran dari masukan yang diberikan. Keadaan keluaran ditunjukkan oleh LED dan sinyal gelombang CLK_OUT. Osiloskop digital (DS1052E) digunakan untuk melihat bentuk sinyal CLK_OUT. Channel yang digunakan untuk praktikum ini adalah CH1 (konsultasikan penggunaan osiloskop ini dengan asisten). Langkah percobaan: 1. Bangkitkan file programming sekuensial_top.bit; 2. Jalankan Xilinx iMPACT jika belum dijalankan. Pastikan kabel USB telah terpasang di starter kit dan komputer; 3. Dari Xilinx iMPACT, klik ganda “Boundary Scan”. Kemudian klik kanan dan pilih Initialize Chain (Ctrl+I) untuk menginisialisasi Boundary Scan; 4. Yang diperlukan adalah mengkonfigurasi FPGA, sedangkan flash XCF04S dan CPLD XC2C64 dibiarkan bypass. Klik kanan device FPGA dan pilih “Assign New Configuration File”. Pilih file sekuensial_top.bit untuk diprogram ke FPGA. Nama file konfigurasi akan tampil di bawah device FPGA; 5. Sambungkan kabel osiloskop digital ke kanal CH1. Sinyal keluaran CLK_OUT diukur dari port IO12/E8. Sinyal CLK_OUT dapat diprobe dengan osiloskop dari port IO12 ini dan GND; 6. Klik kanan device FPGA dan pilih “Program” untuk mengkonfigurasi FPGA; 7. Nyalakan osiloskop. Klik tombol AUTO di osiloskop dan tombol Measure. Tombol Measure digunakan untuk melihat properti sinyal (misalnya frekuensi, periode, risetime, falltime, dll). Tampilkan semua properti sinyal dengan memilih “Display All”; 8. Perilaku keluaran dapat diamati dengan menekan tombol BTN_* (Set, Reset, Up, Down) dan memutar rotary knob untuk mendapatkan frekuensi sinyal CLK_OUT yang bersesuaian; Amati perilaku sistem (dari keadaan LED dan sinyal yang ditunjukkan di osiloskop) dan isi tabel di lembar kegiatan; Bandingkan frekuensi yang diperoleh dengan Tabel 1
4.3 Lampiran Kode HDL Nama file modul bersesuaian dengan nama modulnya. File desain_sekuensial.ucf juga disertakan. 4.3.1 debouncer: debouncer.v module debouncer( input clk, input in_state, output out_state ); parameter NBITS = 16; reg [NBITS1:0] COUNT; reg PB_sync_0; reg PB_sync_1; reg PB_state; always @(posedge clk) PB_sync_0 <= ~in_state; always @(posedge clk) PB_sync_1 <= PB_sync_0; wire PB_idle = (PB_state==PB_sync_1); wire max_COUNT = &COUNT; always @(posedge clk) begin if (PB_idle) COUNT <= 0; else begin COUNT <= COUNT + 1; if (max_COUNT) PB_state <= ~PB_state; end end assign out_state = PB_state; endmodule
4.3.2 count_3b: count_3b.v module count_3b( input set, input reset, input up, input down, input [1:0] rlrot, input clk, output [2:0] y_out ); parameter MAX_COUNT = 7; parameter ROT_RIGHT = 2'b11; parameter ROT_LEFT = 2'b10; reg delay_up; reg delay_down; reg [2:0] cur_state, next_state; reg [2:0] out_reg;
initial begin cur_state = 3'b111; /*The lowest frequency*/ end /*Current State Logic : Sequential*/ always @(posedge clk) begin delay_down <= down; delay_up <= up; if (reset==1) cur_state <= MAX_COUNT; /*Reset, the lowest frequency*/ else if (set==1) cur_state <= 0; /*Set, the highest frequency*/ else cur_state <= next_state; end /*Next state logic: combinational*/ always @* begin if (((up==1) && (delay_up==0)) || (rlrot==ROT_RIGHT) ) /*increase freq will decrease div*/ next_state = (cur_state==0)?0:cur_state1; else if (((down==1) & (delay_down==0)) || (rlrot==ROT_LEFT)) next_state = (cur_state==MAX_COUNT)?MAX_COUNT:cur_state+1; else next_state = cur_state; end /*Cur State & Output*/ always @* begin out_reg <= cur_state; end assign y_out = out_reg; endmodule
4.3.3 rot_enc: rot_enc.v module rot_enc( input rot_A, input rot_B, input clk, output [1:0] rlrot ); reg rot_A_in; reg rot_B_in; reg [1:0] rot_in; reg rot_q1; reg delay_rot_q1; reg rot_q2; reg rot_event; reg rot_left; /*Rotary filter*/ always @(posedge clk) begin rot_A_in <= rot_A; rot_B_in <= rot_B; rot_in <= {rot_B_in, rot_A_in};
case (rot_in) 2'b00: begin rot_q1 <= 0; rot_q2 <= rot_q2; end 2'b01: begin rot_q1 <= rot_q1; rot_q2 <= 0; end 2'b10: begin rot_q1 <= rot_q1; rot_q2 <= 1; end 2'b11: begin rot_q1 <= 1; rot_q2 <= rot_q2; end default: begin rot_q1 <= rot_q1; rot_q2 <= rot_q2; end endcase end /*Rotary direction*/ always @(posedge clk) begin delay_rot_q1 <= rot_q1; if ((rot_q1 == 1) && (delay_rot_q1 == 0)) begin rot_event <= 1; rot_left <= rot_q2; end else begin rot_event <= 0; rot_left <= rot_left; end end assign rlrot = {rot_event, rot_left}; endmodule
4.3.4 clock_div: clock_div.v module clock_div( input [2:0] div, input clk, output clk_out, output clk_out2 /*is the same as clk_out*/ ); reg [6:0] clk_cnt; reg clk_out_reg; always @(posedge clk) begin clk_cnt <= clk_cnt + 1; end always @(clk_cnt or div) begin clk_out_reg <= (div==0)?clk:clk_cnt[div1]; end assign clk_out = clk_out_reg; assign clk_out2 = clk_out_reg; endmodule
4.3.5 clock_stat: clock_stat.v module clock_stat( input [2:0] data_in, output [7:0] data_out ); /* // Procedural reg [7:0] data_out_reg; always @(data_in) begin case (data_in) 3'b000: data_out_reg <= 8'b00000001; 3'b001: data_out_reg <= 8'b00000010; 3'b010: data_out_reg <= 8'b00000100; 3'b011: data_out_reg <= 8'b00001000; 3'b100: data_out_reg <= 8'b00010000; 3'b101: data_out_reg <= 8'b00100000; 3'b110: data_out_reg <= 8'b01000000; 3'b111: data_out_reg <= 8'b10000000; endcase end assign data_out = data_out_reg */ assign data_out = (8'b00000001 << data_in); /*Structural*/ endmodule
4.3.6 desain_sekuensial.ucf # Period constraint for 50MHz operation NET "CLK" PERIOD = 20.0ns HIGH 50%; # soldered 50MHz Clock. NET "CLK" LOC = "C9" | IOSTANDARD = LVTTL; NET "CLK_SMA" LOC = "A10" | IOSTANDARD = LVTTL; NET "CLK_OUT" LOC = "E8" | IOSTANDARD = LVTTL; # # Koneksi tombol tekan NET "BTN_EAST" LOC = "H13" | IOSTANDARD = LVTTL | PULLDOWN ; NET "BTN_NORTH" LOC = "V4" | IOSTANDARD = LVTTL | PULLDOWN ; NET "BTN_SOUTH" LOC = "K17" | IOSTANDARD = LVTTL | PULLDOWN ; NET "BTN_WEST" LOC = "D18" | IOSTANDARD = LVTTL | PULLDOWN ; # Koneksi LED NET "LED<7>" LOC = "F9" | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 8 ; NET "LED<6>" LOC = "E9" | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 8 ; NET "LED<5>" LOC = "D11" | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 8 ; NET "LED<4>" LOC = "C11" | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 8 ; NET "LED<3>" LOC = "F11" | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 8 ; NET "LED<2>" LOC = "E11" | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 8 ; NET "LED<1>" LOC = "E12" | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 8 ; NET "LED<0>" LOC = "F12" | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 8 ; # Koneksi RotaryKnob #NET "ROT_CENTER" LOC = "V16" | IOSTANDARD = LVTTL | PULLDOWN | CLOCK_DEDICATED_ROUTE = FALSE; NET "ROT_A" LOC = "K18" | IOSTANDARD = LVTTL | PULLUP ; NET "ROT_B" LOC = "G18" | IOSTANDARD = LVTTL | PULLUP ;