디지털 시계 설계
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 SIGNAL PIN Note SEG_A P31 Active ‘H’ SEG_B P33 SEG_C P34 SEG_D P35 SEG_E P36 SEG_F P37 SEG_G P39 SEG_DP P48
세그먼트 테스트 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”;
세그먼트 테스트 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_clk <= not delay_clk; else delay_cnt <= delay_cnt + 1; delay_clk <= delay_clk; end if; end process; process(FPGA_RSTB,delay_clk) digit_int <= "000001"; elsif rising_edge (delay_clk) then digit_int <= digit_int (4 downto 0) & digit_int(5); 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 else key <= key + 1; end if; end process; process(key) 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 DIGIT5 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 PORT PIN Clk P79 SEG_A P31 Rst_n P205 SEG_B P33 DIGIT(1) P22 SEG_C P34 DIGIT(2) P24 SEG_D P35 DIGIT(3) P26 SEG_E P36 DIGIT(4) P27 SEG_F P37 DIGIT(5) P28 SEG_G P39 DIGIT(6) p29 SEG_DP P48
표 1. 디지털 시계의 Library 및 Entity 선언 실험내용 디지털 시계 구성 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 선언
표 2. 디지털 시계의 Architecture 선언 실험내용 표 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 선언
실험내용 표 3. 세그먼트 선택을 위한 process begin process( sel ) 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; if( rst_n = '0' ) then sel <= "000"; seg_clk_cnt := 0; elsif( clk'event and clk='1' ) then if( seg_clk_cnt = 200 ) then 표 3. 세그먼트 선택을 위한 process
실험내용 표 3. 세그먼트 선택을 위한 process 표 3은 FPGA 보드의 세그먼트를 선택하기 위한 신호 DIGIT를 sel에 의해 선택하는 process이다. FPGA보드의 세그먼트는 6개의 세그먼트가 독립적으로 있는 것이 아니라 한 개의 세그먼트가 6부분으로 분할되어 있다. 즉 세그먼트 6개중 한 개에만 숫자를 표시할 수 있다. 따라서 시간을 모든 세그먼트에 출력하기 위해서는 한 개의 세그먼트에 출력하고 빠른 시간 안에 다음 세그먼트에 다음 숫자를 출력 함으로써 동시에 출력되는 것처럼 보이도록 한다. if( sel = "101" ) then sel <= "000"; else sel <= sel + 1; end if; seg_clk_cnt := seg_clk_cnt + 1; end process; 표 3. 세그먼트 선택을 위한 process
표 4. 디지털 시계의 7-Segment 디코더 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. 디지털 시계의 clock 분주 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; else count_clk := count_clk +1; end if; end process; 표 5. 디지털 시계의 clock 분주 process
실험내용 표 6. 디지털 시계의 1초대 카운트 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 s10_clk <= '1'; else sec01_cnt <= sec01_cnt + 1; end if; end process; 표 6. 디지털 시계의 1초대 카운트 process
실험내용 표 7. 시분초 증가 부분 process( s10_clk, rst_n ) begin if( rst_n = '0' ) then -- Insert Your Source Code end if; end process; process( m01_clk, rst_n ) process( m10_clk, rst_n ) 표 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. 시분초 증가 부분