Language/Verilog

SoC : 기초

짱도르딘 2024. 9. 9. 16:14
728x90

 

Create Block Design을 클릭하고 아래와 같은 블럭을 만들었다.

 

 

위 블럭을 토대로 코드를 구현하고 싶다면,

Create HDL Wrapper를 클릭하면 아래와 같은 기본적인 코드가 자동으로 형성되는 것을 확인할 수 있다.

module micro_blaze_hello_wrapper
   (reset,
    sys_clock,
    usb_uart_rxd,
    usb_uart_txd);
  input reset;
  input sys_clock;
  input usb_uart_rxd;
  output usb_uart_txd;

  wire reset;
  wire sys_clock;
  wire usb_uart_rxd;
  wire usb_uart_txd;

  micro_blaze_hello micro_blaze_hello_i
       (.reset(reset),
        .sys_clock(sys_clock),
        .usb_uart_rxd(usb_uart_rxd),
        .usb_uart_txd(usb_uart_txd));
endmodule

 

Bitstream을 먼저 진행한 후, 아래와 같이 추가적인 과정을 필요로 한다.

 

 

 

 

 


플랫폼에서 아래와 같은 코드를 실행하면 PuTTY에는 다음과 같은 결과가 나오는 것을 확인할 수 있다.

 

아래는 반복적으로 Hello World를 출력하는 코드와 출력 결과 화면이다.

#include <stdio.h>
#include "platform.h"
#include "xil_printf.h"


int main()
{
    init_platform();

    print("Start!\n");

    while(1)
    {
    	print("Hello World!\n\r");
    	MB_Sleep(1000);
    }

    cleanup_platform();
    return 0;
}

 

 

 


 

버튼을 활용한 코드를 구현하면 아래와 같이 구현되며, 출력 결과는 아래와 같다.

#include <stdio.h>
#include "platform.h"
#include "xil_printf.h"
#include "xparameters.h"
#include "xgpio.h"

#define BUTTON_ID XPAR_GPIO_0_DEVICE_ID
#define BUTTON_CHNNEL 1

int main()
{
    init_platform();

    print("Start!\n\r");

    XGpio_Config *cfg_ptr;
    XGpio button_instance;
    u16 data;

    cfg_ptr = XGpio_LookupConfig(BUTTON_ID);
    XGpio_CfgInitialize(&button_instance, cfg_ptr, cfg_ptr->BaseAddress);
    XGpio_SetDataDirection(&button_instance, BUTTON_CHNNEL, 0b1111);
    while(1)
    {
    	data = XGpio_DiscreteRead(&button_instance, BUTTON_CHNNEL);
    	xil_printf("button Value : %x\n\r", data);
    	MB_Sleep(1000);
    }


    cleanup_platform();
    return 0;
}

 

 


이번에는 LED와 스위치를 활용한 코드를 작성해보려고 한다.

 

블록은 아래와 같이 설정하였다.

 

 

아래와 같이 코드를 작성한 후, 동작을 시켜보면 스위치를 올릴 때마다 스위치 위의 LED가 점등되는 것을 확인할 수 있다.

 

#include <stdio.h>
#include "platform.h"
#include "xil_printf.h"
#include "xparameters.h"    // 하드웨어 파라미터 정의를 위한 헤더 파일
#include "xgpio.h"               // GPIO 제어를 위한 헤더 파일

#define GPIO_ID    XPAR_GPIO_0_DEVICE_ID
#define LED_CHANNEL            1
#define SWITCH_CHANNEL        2

int main()
{
    init_platform();

    print("Start!\n\r");

    XGpio_Config *cfg_ptr;
    XGpio gpio_instance;

    // 버튼 장치의 설정을 조회하여 cfg_ptr에 저장
    cfg_ptr = XGpio_LookupConfig(GPIO_ID);

    // GPIO 인스턴스를 초기화 (버튼 장치 설정에 맞추어 인스턴스 생성)
    XGpio_CfgInitialize(&gpio_instance, cfg_ptr, cfg_ptr->BaseAddress);
    XGpio_SetDataDirection(&gpio_instance, LED_CHANNEL, 0);
    XGpio_SetDataDirection(&gpio_instance, SWITCH_CHANNEL, 0xffff);
    u16    data;

    while(1){
        data = XGpio_DiscreteRead(&gpio_instance, SWITCH_CHANNEL);
        XGpio_DiscreteWrite(&gpio_instance, LED_CHANNEL, data);
//        print("Hello World!\n\r");
//        MB_Sleep(1000);
    }

    cleanup_platform();
    return 0;
}

 

 


이번에는 FND를 제어해보려고한다.

 

FND는 Anode를 사용하였고, 블록은 아래와 같다.

 

아래의 코드를 돌려보면, FND가 0000부터 1씩 빠르게 증가하는 것을 확인할 수 있다.

#include <stdio.h>
#include "platform.h"
#include "xil_printf.h"
#include "xparameters.h"    // 하드웨어 파라미터 정의를 위한 헤더 파일
#include "xgpio.h"               // GPIO 제어를 위한 헤더 파일

#define FND_ID    XPAR_AXI_GPIO_FND_DEVICE_ID
#define SWITCH_ID    XPAR_AXI_GPIO_SWITCH_DEVICE_ID
#define COM_CHANNEL 1
#define SEG_CHANNEL 2
#define SWITCH_CHANNEL 1

u32 fnd[16] = {
        0xc0, 0xf9, 0xa4, 0xb0, 0x99, 0x92, 0x82, 0xd8,
        0x80, 0x98, 0x88, 0x83, 0xc6, 0xa1, 0x86, 0x8e};

int main()
{
    init_platform();

    print("Start!\n\r");

    XGpio_Config *cfg_ptr;
    XGpio fnd_instance, switch_instance;
    u16 data = 0;

    cfg_ptr = XGpio_LookupConfig(FND_ID);
    // GPIO 인스턴스를 초기화 (버튼 장치 설정에 맞추어 인스턴스 생성)
    XGpio_CfgInitialize(&fnd_instance, cfg_ptr, cfg_ptr->BaseAddress);
    XGpio_SetDataDirection(&fnd_instance, COM_CHANNEL, 0);
    XGpio_SetDataDirection(&fnd_instance, SEG_CHANNEL, 0);

    while(1)
    {
    	data++;
    	XGpio_DiscreteWrite(&fnd_instance, COM_CHANNEL, 0b1110); // 1의 자리
    	XGpio_DiscreteWrite(&fnd_instance, SEG_CHANNEL, fnd[data%10]); // data를 10으로 나눈 나머지
    	MB_Sleep(1);
    	XGpio_DiscreteWrite(&fnd_instance, COM_CHANNEL, 0b1101); // 10의 자리
    	XGpio_DiscreteWrite(&fnd_instance, SEG_CHANNEL, fnd[data/10%10]);
    	MB_Sleep(1);
    	XGpio_DiscreteWrite(&fnd_instance, COM_CHANNEL, 0b1011); // 100의 자리
    	XGpio_DiscreteWrite(&fnd_instance, SEG_CHANNEL, fnd[data/100%10]);
    	MB_Sleep(1);
    	XGpio_DiscreteWrite(&fnd_instance, COM_CHANNEL, 0b0111); // 1000의 자리
    	XGpio_DiscreteWrite(&fnd_instance, SEG_CHANNEL, fnd[data/1000%10]);
    	MB_Sleep(1);
    }

    cleanup_platform();
    return 0;
}

 

위 코드를 for문으로 바꿔 수정해보면 아래와 같은 코드가 작성된다.

 

#include <stdio.h>
#include "platform.h"
#include "xil_printf.h"
#include "xparameters.h"    // 하드웨어 파라미터 정의를 위한 헤더 파일
#include "xgpio.h"               // GPIO 제어를 위한 헤더 파일

#define FND_ID    XPAR_AXI_GPIO_FND_DEVICE_ID
#define SWITCH_ID    XPAR_AXI_GPIO_SWITCH_DEVICE_ID
#define COM_CHANNEL 1
#define SEG_CHANNEL 2
#define SWITCH_CHANNEL 1

u32 fnd[16] = {
        0xc0, 0xf9, 0xa4, 0xb0, 0x99, 0x92, 0x82, 0xd8,
        0x80, 0x98, 0x88, 0x83, 0xc6, 0xa1, 0x86, 0x8e};

int main()
{
    init_platform();

    print("Start!\n\r");

    XGpio_Config *cfg_ptr;
    XGpio fnd_instance, switch_instance;
    u16 data = 0;
    u16 temp = 0b1110;
    u16 div = 1;

    cfg_ptr = XGpio_LookupConfig(FND_ID);
    // GPIO 인스턴스를 초기화 (버튼 장치 설정에 맞추어 인스턴스 생성)
    XGpio_CfgInitialize(&fnd_instance, cfg_ptr, cfg_ptr->BaseAddress);
    XGpio_SetDataDirection(&fnd_instance, COM_CHANNEL, 0);
    XGpio_SetDataDirection(&fnd_instance, SEG_CHANNEL, 0);

    while(1)
    {
    	data++;
    	temp = 0b1110;
    	div = 1;
    	for(char i=0; i<4; i++)
    	{
    		XGpio_DiscreteWrite(&fnd_instance, COM_CHANNEL, ~(1<<i));
    		XGpio_DiscreteWrite(&fnd_instance, SEG_CHANNEL, fnd[data/div%10]);
    		MB_Sleep(1);
    		div *= 10;
    	}
    }

    cleanup_platform();
    return 0;
}

 

 

728x90