Verilog_RTL 설계/SoC

[MicroBlaze] Switch_Led

juniha 2025. 7. 25. 21:09

목적

  • DIP 스위치 입력을 읽고, 해당 값을  LED에 출력하며 UART로 상태를 출력하는 기본 임베디드 제어 시스템  구현

Diagram

 

구성 블록

microblaze_riscv_0 (RISC-V 프로세서)

  • MicroBlaze V (RISC-V 기반) 임베디드 CPU
  • AXI 인터페이스(M_AXI_DP)를 통해 주변 장치와 연결
  • DLMB, ILMB: 데이터/명령 로컬 메모리 인터페이스

microblaze_riscv_0_local_memory

  • 로컬 메모리 (LMB 기반)
  • 명령(ILMB), 데이터(DLMB) 메모리 제공
  • SYS_Rst, LMB_Clk으로 클럭 및 리셋 동기화

axi_gpio_0

  • AXI GPIO 컨트롤러
  • GPIO 채널 1: led_16bits (출력)
  • GPIO 채널 2: dip_switches_16bits (입력)
  • AXI 인터페이스를 통해 프로세서와 연결됨

axi_uartlite_0

  • AXI UART Lite
  • USB UART 연결용
  • RX (usb_uart 입력), TX (usb_uart 출력)
  • UART 디버깅용 메시지 송수신 처리

axi_smc (AXI SmartConnect)

  • 프로세서(M_AXI_DP)와 주변 장치(GPIO, UART) 사이의 AXI 버스 연결기
  • AXI Master(M00_AXI) → Slave(S_AXI) 연결 처리

proc_sys_reset_0 (Processor System Reset)

  • 리셋 논리 제어
  • 외부 리셋 + 디버그 리셋 + 클럭 안정성 → 다양한 reset 신호 생성 (mb_reset, peripheral_reset 등)

clk_wiz (Clocking Wizard)

  • 외부 클럭(sys_clock)을 내부에서 사용할 주파수(clk_out1)로 변환
  • locked 신호를 통해 클럭 안정 여부 표시

mdm_1 (MicroBlaze Debug Module)

  • JTAG 디버깅 지원 (Xilinx SDK/Vitis 사용 시)
  • MBDEBUG_0, Debug_SYS_Rst 신호 출력

Diagram에 맞춰 작성된 코드

`timescale 1 ps / 1 ps  // 시뮬레이션 타임스케일 설정: 시간 단위 1ps, 정밀도 1ps

//-----------------------------------------------------------------------------
// Top-level wrapper module for the MicroBlazeV Hello World design
// This module wraps the block design system generated by Vivado IP Integrator
//-----------------------------------------------------------------------------

module microblazeV_hello_wrapper
   (
    dip_switches_16bits_tri_i, // 16비트 DIP 스위치 입력 (GPIO 입력으로 사용)
    led_16bits_tri_o,          // 16비트 LED 출력 (GPIO 출력으로 사용)
    reset,                     // 외부 비동기 리셋 입력 (active-high)
    sys_clock,                 // 시스템 클럭 입력
    usb_uart_rxd,             // UART 수신 데이터 (USB-UART 연결)
    usb_uart_txd              // UART 송신 데이터 (USB-UART 연결)
    );

  // 포트 선언 (외부 입출력 신호)
  input  [15:0] dip_switches_16bits_tri_i; // DIP 스위치 입력
  output [15:0] led_16bits_tri_o;          // LED 출력
  input         reset;                     // 리셋 입력
  input         sys_clock;                 // 시스템 클럭 입력
  input         usb_uart_rxd;              // UART 수신 (RX)
  output        usb_uart_txd;              // UART 송신 (TX)

  // 내부 와이어 연결 (포트 신호를 내부 모듈에 직접 연결)
  wire [15:0] dip_switches_16bits_tri_i;
  wire [15:0] led_16bits_tri_o;
  wire        reset;
  wire        sys_clock;
  wire        usb_uart_rxd;
  wire        usb_uart_txd;

  // microblazeV_hello 인스턴스화 (Vivado Block Design에서 생성된 시스템)
  microblazeV_hello microblazeV_hello_i (
        .dip_switches_16bits_tri_i(dip_switches_16bits_tri_i), // DIP 스위치 입력 연결
        .led_16bits_tri_o(led_16bits_tri_o),                   // LED 출력 연결
        .reset(reset),                                        // 리셋 신호 연결
        .sys_clock(sys_clock),                                // 시스템 클럭 연결
        .usb_uart_rxd(usb_uart_rxd),                          // UART RX 연결
        .usb_uart_txd(usb_uart_txd)                           // UART TX 연결
    );

endmodule

사용 코드 _ Vitis

#include <stdio.h>             // 표준 입출력 함수 사용
#include "platform.h"          // 플랫폼 초기화 및 정리 함수 포함 (init_platform, cleanup_platform 등)
#include "xil_printf.h"        // UART를 통한 출력용 printf 함수 제공 (xil_printf)
#include "sleep.h"             // sleep 함수 포함 (지연용)
#include "xparameters.h"       // 하드웨어 주소 정의 포함 (IP의 BaseAddress 등)
#include "xgpio.h"             // AXI GPIO 관련 함수 정의

// GPIO 채널 번호 정의
#define LED_CHANNEL 1          // 채널 1은 LED 출력용
#define SW_CHANNEL  2          // 채널 2는 DIP 스위치 입력용

int main()
{
    init_platform(); // 플랫폼 초기화 (UART, 인터럽트, 메모리 등 사용 가능하게 설정)

    print("Hello World\n\r");                        // UART를 통해 인사 메시지 출력
    print("Successfully ran Hello World application"); // 실행 성공 메시지

    XGpio_Config *cfg_ptr;   // GPIO 설정 구조체 포인터
    XGpio gpio_device;       // GPIO 장치 인스턴스 선언

    u32 data = 0;            // 스위치 입력 값을 저장할 변수

    // GPIO 장치 설정 정보 가져오기 (axi_gpio_0의 주소 기준)
    cfg_ptr = XGpio_LookupConfig(XPAR_AXI_GPIO_0_BASEADDR);

    // GPIO 장치 초기화 (구조체 포인터, 인스턴스, 베이스 주소)
    XGpio_CfgInitialize(&gpio_device, cfg_ptr, cfg_ptr->BaseAddress);

    // GPIO 방향 설정
    // LED 채널을 출력으로 설정 (0은 출력)
    XGpio_SetDataDirection(&gpio_device, LED_CHANNEL, 0);
    
    // DIP 스위치 채널을 입력으로 설정 (0xFFFF는 16비트 모두 입력)
    XGpio_SetDataDirection(&gpio_device, SW_CHANNEL, 0xffff);

    // 무한 루프: DIP 스위치 상태를 LED로 출력하고 UART로 보여줌
    while(1){
        // DIP 스위치 상태 읽기 (채널 2)
        data = XGpio_DiscreteRead(&gpio_device, SW_CHANNEL);

        // UART를 통해 스위치 상태 16진수로 출력
        xil_printf("switch inputs : %X\n\r", data);

        // 읽은 값을 LED에 출력 (채널 1)
        XGpio_DiscreteWrite(&gpio_device, LED_CHANNEL, data);

        // 1초 대기 (지연)
        sleep(1);
    }

    cleanup_platform(); // 플랫폼 종료 (사용 리소스 정리)
    return 0; // 프로그램 종료
}

동작 영상 _Switch

동작 영상 _LED

결과

  • DIP 스위치를 조작하면,
  • 그 상태가 16개의 LED에 실시간으로 반영되고,
  • UART 터미널에는 현재 스위치 상태가 1초마다 출력되는 것을 확인

즉, 이 프로그램은 입력(DIP 스위치)을 읽고, 그 값을 출력(LED)에 반영하며, 동시에 UART를 통해 상태를 확인할 수 있다.

'Verilog_RTL 설계 > SoC' 카테고리의 다른 글

[Project]Smart Mobility platform  (4) 2025.08.27
[Smart Mobility platform] Implemented Code  (4) 2025.08.07
[MicroBlaze] DHT11_iic  (3) 2025.07.29
[MicroBlaze] Button_control  (1) 2025.07.28
[MicroBlaze] fnd_control  (1) 2025.07.28