650 likes | 1.83k Views
디지털 시계 설계. Contents. RoV-Lab 3000 세그먼트 테스트 디지털 시계 실습내용 프로젝트. RoV-LAB 3000. Base-Board(8). RoV-LAB 3000. FPGA Module(1). RoV-LAB 3000. Line-Tracer(2) Micro-Mouse(3). RoV-LAB 3000. Motor Module(4+5). RoV-LAB 3000. RF Main(6). RoV-LAB 3000. RF Battle(7). RoV-LAB 3000. RF 송신부
E N D
Contents • RoV-Lab 3000 • 세그먼트 테스트 • 디지털 시계 • 실습내용 • 프로젝트
RoV-LAB 3000 • Base-Board(8)
RoV-LAB 3000 • FPGA Module(1)
RoV-LAB 3000 • Line-Tracer(2) • Micro-Mouse(3)
RoV-LAB 3000 • Motor Module(4+5)
RoV-LAB 3000 • RF Main(6)
RoV-LAB 3000 • RF Battle(7)
RoV-LAB 3000 • RF 송신부 • JTAG Cable
RoV-LAB 3000 • Block Diagram
세그먼트 테스트 • 7-Segment
세그먼트 테스트 • 7-Segment 선택 • FPGA 보드에 세그먼트가 6개가 있지만 동시에 1개만 동작을 한다. • 세그먼트를 선택하는 신호가 DIGIT( 1 to 6 )이고 DIGIT(1)~DIGIT(6)가위의 세그먼트 왼쪽부터 연결 되어 있다면 세그먼트 선택은 다음과 같다. • DIGIT <= “100000”; -- 가장 왼쪽 세그먼트에 출력함 • DIGIT <= “010000”; -- 왼쪽에서 두번째 세그먼트에 출력함 • DIGIT <= “000001”; -- 가장 오른쪽 세그먼트에 출력함
세그먼트 테스트 • 7-Segment 디코딩 • 숫자 0의 경우 세그먼트의 a, b, c, d, e, f가 켜져야 한다. • 따라서 출력으로 bit 순서를 abcdefgdp순으로 한다면 “11111100”을 출력하면 된다.
세그먼트 테스트 • 세그먼트 테스트 동작 DIGIT <= “100000”; SEG <= “11111100”; DIGIT <= “000010”; SEG <= “01100110”; DIGIT <= “001000”; SEG <= “11011010”; DIGIT <= “000001”; SEG <= “10110110”; DIGIT <= “010000”; SEG <= “01100000”; DIGIT <= “000100”; SEG <= “11110010”;
세그먼트 테스트 • CODE library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.STD_LOGIC_ARITH.ALL; use IEEE.STD_LOGIC_UNSIGNED.ALL; entity segment_test is port ( FPGA_RSTB : IN std_logic; FPGA_CLK : IN std_logic; SEG_A : OUT std_logic; SEG_B : OUT std_logic; SEG_C : OUT std_logic; SEG_D : OUT std_logic; SEG_E : OUT std_logic; SEG_F : OUT std_logic; SEG_G : OUT std_logic; SEG_DP : OUT std_logic; DIGIT : OUT std_logic_vector (6 downto 1) ); end segment_test; architecture Behavioral of segment_test is signal delay_cnt : std_logic_vector (19 downto 0); signal delay_clk : std_logic; signal digit_int : std_logic_vector (5 downto 0); signal key : std_logic_vector (3 downto 0); signal seg : std_logic_vector (7 downto 0);
세그먼트 테스트 Begin process(FPGA_RSTB,FPGA_CLK) begin if FPGA_RSTB = '0' then delay_cnt <= (others => '0'); elsif rising_edge (FPGA_CLK) then if delay_cnt = X"FFFFF" then delay_cnt <= (others => '0'); delay_clk <= not delay_clk; else delay_cnt <= delay_cnt + 1; delay_clk <= delay_clk; end if; end if; end process; process(FPGA_RSTB,delay_clk) begin if FPGA_RSTB = '0' then digit_int <= "000001"; elsif rising_edge (delay_clk) then digit_int <= digit_int (4 downto 0) & digit_int(5); end if; end process; DIGIT <= digit_int;
세그먼트 테스트 process(FPGA_RSTB,delay_clk) begin if FPGA_RSTB = '0' then key <= (others => '0'); elsif rising_edge (delay_clk) then if key = X"F" then key <= (others => '0'); else key <= key + 1; end if; end if; end process; process(key) begin case key is -- abcdefgdp when X"0" => seg <= "11111101"; when X"1" => seg <= "01100001"; when X"2" => seg <= "11011011"; when X"3" => seg <= "11110011"; when X"4" => seg <= "01100111"; when X"5" => seg <= "10110111"; when X"6" => seg <= "10111111"; when X"7" => seg <= "11100101"; when X"8" => seg <= "11111111"; when X"9" => seg <= "11110111";
세그먼트 테스트 when X"a" => seg <= "11111011"; when X"b" => seg <= "00111111"; when X"c" => seg <= "10011101"; when X"d" => seg <= "01111011"; when X"e" => seg <= "10011111"; when X"f" => seg <= "10001111"; when others => seg <= (others => '0'); end case; end process; seg_a <= seg(7); seg_b <= seg(6); seg_c<= seg(5); seg_d <= seg(4); seg_e <= seg(3); seg_f <= seg(2); seg_g <= seg(1); seg_dp <= seg(0); end Behavioral;
세그먼트 테스트 • 프로젝트 생성시 Device 설정은 다음의 그림과 같이 함 • 프로젝트 생성시 경로에 빈칸 또는 한글이 있으면 오류 발생함
세그먼트 테스트 • 업로드 되어 있는 segment_test.vhd 파일을 이용하여 세그먼트 테스트 • FPGA에서 사용하기 위해서 pin mapping을 한다
세그먼트 테스트 • Xilinx PACE 에서 필요한 pin을 pin table에서 찾아 할당한다
세그먼트 테스트 • Pin 할당은 다음과 같이 한다. • 주의점 : Loc에 “p???”를 입력 한 후 Enter를 꼭 할 것!
세그먼트 테스트 • Xilinx PACE에서 SAVE • 다음과 같은 화면이 나오면 Default로 확인
세그먼트 테스트 • Xilinx ISE Webpack로 돌아와서 계속 진행 • Generate Programming File 속성에서 Startup Options의 FPGA Start-Up Clock를 JTAG으로 변경 우클릭하여 properties로 이동
세그먼트 테스트 • Configure Device(iMPACT)를 더블클릭 • 이때 Synthesize와 Implement Design까지 순차적으로 진행 • 이 과정을 통해 FPGA에 프로그래밍할 bit 파일이 생성
세그먼트 테스트 • 아래와 같이 설정 후 finish
세그먼트 테스트 • 앞서 생성된 bit 파일을 선택 • 예제에서는 segment_test.bit
세그먼트 테스트 • 다음 화면과 같이 변경됨 선택한 bit파일이 명시되어있음
세그먼트 테스트 • Xc3s200 디바이스에서 우클릭 • 메뉴중 program 선택
세그먼트 테스트 • 선택 없이 OK
세그먼트 테스트 • 다음과 같은 화면이 나와야 성공 • 보드에서 동작 검증
디지털 시계 • 시, 분및 초를 표시하는 디지털 시계 • 초 • 입력 클럭을 분주하여 1초 단위로 상승 • 59초에서 60초로 넘어 갈 때 1분 카운트를 발생, 초는 00으로 초기화 • 분 • 1분 카운트 발생시 1분씩 증가 • 59분에서 60분으로 넘어 갈 때 1시간 카운트 발생, 분은 00으로 초기화 • 시 • 1시간 카운트 발생시 1시간씩 증가 • 12:59:59 초 다음은 1:00:00으로 12시간제 적용
실험내용 • 디지털 시계 구성 • 4MHz의 오실레이터 clock을 분주하여 시계제작 • 시간을 나타내는 세그먼트 2개 • 분을 나타내는 세그먼트 2개 • 초를 나타내는 세그먼트 2개 • 비동기 reset • 리셋시 12:58:20으로 초기화 • Pin mapping • 주어진 table 이용 • Module • 추가로 주어지는 소스 코드의 빈칸을 채우시오. 1 DIGIT1 2 DIGIT2 5 DIGIT3 8 DIGIT4 2 DIGIT5 0 DIGIT6
실험내용 • Entity library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.STD_LOGIC_ARITH.ALL; use IEEE.STD_LOGIC_UNSIGNED.ALL; entity digital_clock is Port ( rst_n : in std_logic; clk : in std_logic; DIGIT : out std_logic_vector( 6 downto 1 ); SEG_A : out std_logic; SEG_B : out std_logic; SEG_C : out std_logic; SEG_D : out std_logic; SEG_E : out std_logic; SEG_F : out std_logic; SEG_G : out std_logic; SEG_DP : out std_logic ); end digital_clock;
실험내용 • Pin table
실험내용 • 디지털 시계 구성 • 4MHz의 오실레이터 clock을 입력 받아 시 : 분 : 초를 표시해주는 디지털 시계를 설계한다. • 10시간대의 표시는 세그먼트 DIGIT_1, 1시간대 표시는 세그먼트 DIGIT_2 • 10분대는 DIGIT_3, 1분대는 DIGIT_4 • 10초대는 DIGIT_5, 1초대는 DIGIT_6 에 표시한다. library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.STD_LOGIC_ARITH.ALL; use IEEE.STD_LOGIC_UNSIGNED.ALL; entity digital_clock is Port ( rst_n : in std_logic; clk : in std_logic; DIGIT : out std_logic_vector( 6 downto 1 ); SEG_A : out std_logic; SEG_B : out std_logic; SEG_C : out std_logic; SEG_D : out std_logic; SEG_E : out std_logic; SEG_F : out std_logic; SEG_G : out std_logic; SEG_DP : out std_logic ); end digital_clock; 표 1. 디지털 시계의 Library 및 Entity 선언
실험내용 • 표 1은 시계의 reset을 위해 FPGA MODULE의 reset push_SW으로 rst_n을 인가하고 4MHz의 clock을 clk로 인가한다. • 6개의 세그먼트 DIGIT1~6 중 어떤 세그먼트를 출력할 것인지 결정하는 DIGIT 신호를 선언한다. • 표 2는 시분초의 십의 자리와 일의 자리를 카운트 하기 위한 signal과 각각의 자리를 카운트하기 위한 clock signal이 선언되어 있다. architecture Behavioral of digital_clock is signal s10_clk, s01_clk, m10_clk, m01_clk, h01_clk : std_logic; signal hr10_cnt, hr01_cnt : std_logic_vector( 3 downto 0 ); signal min10_cnt, min01_cnt : std_logic_vector( 3 downto 0 ); signal sec10_cnt, sec01_cnt : std_logic_vector( 3 downto 0 ); signal sel : std_logic_vector( 2 downto 0 ); signal data : std_logic_vector( 3 downto 0 ); signal seg : std_logic_vector( 7 downto 0 ); 표 2. 디지털 시계의 Architecture 선언
실험내용 begin process( sel ) begin case sel is when "000" => DIGIT <= "000001"; data <= hr10_cnt; -- Insert Your Source Code when others => null; end case; end process; process( rst_n, clk ) variable seg_clk_cnt : integer range 0 to 200; begin if( rst_n = '0' ) then sel <= "000"; seg_clk_cnt := 0; elsif( clk'event and clk='1' ) then if( seg_clk_cnt = 200 ) then seg_clk_cnt := 0; 표 3. 세그먼트 선택을 위한 process
실험내용 • 표 3은 FPGA 보드의 세그먼트를 선택하기 위한 신호 DIGIT를 sel에 의해 선택하는 process이다. • FPGA보드의 세그먼트는 6개의 세그먼트가 독립적으로 있는 것이 아니라 한 개의 세그먼트가 6부분으로 분할되어 있다. 즉 세그먼트 6개중 한 개에만 숫자를 표시할 수 있다. 따라서 시간을 모든 세그먼트에 출력하기 위해서는 한 개의 세그먼트에 출력하고 빠른 시간 안에 다음 세그먼트에 다음 숫자를 출력 함으로써 동시에 출력되는 것처럼 보이도록 한다. if( sel = "101" ) then sel <= "000"; else sel <= sel + 1; end if; else seg_clk_cnt := seg_clk_cnt + 1; end if; end if; end process; 표 3. 세그먼트 선택을 위한 process
실험내용 • 표 3에서 넘겨 받은 data를 이용하여 segment 출력을 위하여 디코딩을 한다. 디코딩 bit의 순서는 DPGFEDCBA 순으로 한다. process( data ) begin case data is -- DPGFEDCBA when "0000" => seg <= "00111111"; -- "0" -- Insert Your Source Code end case; end process; SEG_A <= seg( 0 ); SEG_B <= seg( 1 ); SEG_C <= seg( 2 ); SEG_D <= seg( 3 ); SEG_E <= seg( 4 ); SEG_F <= seg( 5 ); SEG_G <= seg( 6 ); SEG_DP <= seg( 7 ); 표 4. 디지털시계의 7-Segment 디코더 process
실험내용 • 표 5는 FPGA 보드에서 입력되는 오실레이터 clock을 1초 단위로 분주하기 위한 프로세스이다. 오실레이터의 입력이 4MHz이기 때문에 오실레이터의 clock을 2,000,000번 입력 받으면 0.5초가 된다. 따라서 s01_clk가 0.5초 간격으로 0에서 1로, 1에서 0으로 변화되며 clock을 생성한다. process( rst_n, clk ) variable count_clk : integer range 0 to 2000000; begin if( rst_n = '0' ) then s01_clk <= '0'; count_clk := 0; elsif( clk'event and clk='1' ) then if( count_clk = 2000000 ) then s01_clk <= not s01_clk; count_clk := 0; else count_clk := count_clk +1; end if; end if; end process; 표 5. 디지털시계의 clock 분주 process
실험내용 • 표 6은 초의 1의 자리를 위한 프로세스이다. S01_clk를 입력 받아 초의 1의 자리를 카운트하고, 10초가 되면 10의 자리인 s10_clk에 1을 출력한다. process( s01_clk, rst_n ) begin if( rst_n = '0' ) then sec01_cnt <= "0000"; s10_clk <= '0'; elsif( s01_clk = '1' and s01_clk'event ) then if( sec01_cnt = "1001" ) then sec01_cnt <= "0000"; s10_clk <= '1'; else sec01_cnt <= sec01_cnt + 1; s10_clk <= '0'; end if; end if; end process; 표 6. 디지털 시계의 1초대 카운트 process
실험내용 process( s10_clk, rst_n ) begin if( rst_n = '0' ) then -- Insert Your Source Code end if; end process; process( m01_clk, rst_n ) begin if( rst_n = '0' ) then -- Insert Your Source Code end if; end process; process( m10_clk, rst_n ) begin if( rst_n = '0' ) then -- Insert Your Source Code end if; end process; 표 7. 시분초 증가 부분
실험내용 • 주어진 module의 빈 칸을 채워 module을 완성하고, FPGA 보드와 연결하여 직접 시뮬레이션을 해본다. • FPGA 보드와연결하기 전에 먼저 testbench를 직접 작성하여 시뮬레이션 후 출력파형을 보고 동작이 올바르게 되는지 확인하고, 그 후에 FPGA 보드에 연결하여 실제 동작을 확인한다. process( h01_clk, rst_n ) begin if( rst_n = '0' ) then -- Insert Your Source Code end if; end process; end Behavioral;; 표 7. 시분초 증가 부분