Harman 세미콘 아카데미/SoC를 위한 Peripheral 설계

2024.9.10 [SoC를 위한 Peripheral 설계]3 - bcd_fnd, stopwatch(myip)

U_Pong 2024. 9. 10. 23:29

2024.9.10 수업날


< bcd_fnd >

이번에는 저번에 만들었던 Fnd 출력 모듈에서 결과값을 10진수로 표시하는 IP를 만들어본다.

Verilog 수업할때 만들었던 Fnd_cntr 모듈 밑에 아래와 같이 코드를 추가한다.

 

 

Block Design에서 IP를 만들기 전에 Basys3 에서 테스트 하기 위해 Verilog 수업할 때 만들었던 .xdc을 아래와 같이 수정한다.

 

vivado bcd_fnd_cntr 테스트 영상

 

 

테스트를 완료했으면 create and package new ip를 생성한다. 

Add Design Sources에서 아래와 같이 추가해주고, 아래의 Copy 부분을 체크한다.

 

 

그리고 아래와 같이 myip_bcd_fnd_cntr_v1_0S00_AXI 모듈(slave 모듈)을 수정한다.

 

 

다음으로 아래와 같이 myip_bcd_fnd_cntr_v1_0 모듈(top 모듈)을 수정한다.

 

 

Package IP에서 좌측의 항목이 모두 초록색 체크표시가 된 것을 확인한 후 하단의 Package IP를 클릭한다.

 

 

다음으로 Block Design에서 Create Block Design을 하여 새로 만든다.

 

 

기본적으로 만들어야하는 부분까지 block을 만들어주고 myip_bcd_fnd_cntr_v10을 추가한다.

 

출력단 추가하기

 

bcd_fnd_wrapper로 만든 후에 bitstream을 실행한다. 그리고 .xsa를 만든다.

 

 

vitis 진행 순서

 

Mblaze_bcd_fnd_app_system -> hello.c 소스코드
#include <stdio.h>
#include "platform.h"
#include "xil_printf.h"
#include "xparameters.h"

#define FND_BASEADDR XPAR_MYIP_BCD_FND_CNTR_0_S00_AXI_BASEADDR

int main()
{
    init_platform();

    print("Start!\n");
    volatile unsigned int *FND_CNTR = (volatile unsigned int)FND_BASEADDR;

    FND_CNTR[0] = 12;
    FND_CNTR[1] = 0;

    while(1){
    	FND_CNTR[1] ^= 1;
    	print("Hello World\n");
    	MB_Sleep(1000);
    }

    cleanup_platform();
    return 0;
}

 

 

Mblaze_bcd_fnd_app 결과 영상

 

 

 

< stopwatch(myip) >

이번에는 Verilog 수업때 만들었던 stopwatch 모듈을 IP로 만들어서 vitis로 제어하는 것을 해본다.

stopwatch 모듈 밑에 ip를 만들기 위한 코드를 아래와 같이 추가해준다.

 

stop_watch_reg 모듈
//////////////////////////////////////////////////////////////// 2024.9.10
////////////////////////////// SoC에서 ip 추가하기 위한 모듈
module stop_watch_reg(
      input clk, reset_p,
      input [1:0] control_reg,
      output [3:0] com,
      output [7:0] seg_7);
      
      wire start_stop, lap, lap_pedge;
      assign {start_stop, lap} = control_reg;
      
      edge_detector_p ed_div(
                  .clk(clk), .reset_p(reset_p), 
                  .cp(lap), .p_edge(lap_pedge));
      
      wire clk_start;
      assign clk_start = start_stop ? clk : 0;
       
      wire clk_usec, clk_msec, clk_sec, clk_min;
      clock_div_100 usec_clk(  
            .clk(clk_start), .reset_p(reset_p), 
            .cp_div_100(clk_usec));
      
      clock_div_1000 msec_clk(     
            .clk(clk_start), .reset_p(reset_p),
            .clk_source(clk_usec),
            .cp_div_1000_nedge(clk_msec)); 
            
      clock_div_1000 sec_clk(     
            .clk(clk_start), .reset_p(reset_p),
            .clk_source(clk_msec),
            .cp_div_1000_nedge(clk_sec)); 
      
      wire [3:0] sec1, sec10,  min1, min10;
      clock_div_60 min_clk(   
            .clk(clk_start), .reset_p(reset_p),
            .clk_source(clk_sec),
            .cp_div_60_nedge(clk_min));
      
      counter_bcd_60 counter_sec(
            .clk(clk), .reset_p(reset_p),
            .clk_time(clk_sec),
            .bcd1(sec1), .bcd10(sec10));
            
      counter_bcd_60 counter_min(
            .clk(clk), .reset_p(reset_p),
            .clk_time(clk_min),
            .bcd1(min1), .bcd10(min10));
      
      // 랩 기능 구현 추가부분
      wire [15:0]cur_time ;
      assign cur_time = {min10, min1, sec10, sec1};
      
      reg [15:0] lap_time;
      always @(posedge clk or posedge reset_p) begin
            if(reset_p)lap_time = 0;
            else if(lap_pedge) lap_time = cur_time;
      end
       
      wire [15:0] value;
      assign value = lap ? lap_time : cur_time;
      fnd_4digit_cntr fnd(clk, reset_p, value, seg_7, com);
      
 
endmodule

 

 

다음으로 새로운 Block Design을 생성한다.

 

Create and Package New IP를 설정하는 과정에서 아래의 체크박스에 표시한다.

 

 

edit_myip 진행 순서

Add Desgin Sources 파일 추가

 

slave 모듈 수정해야 할 곳

 

top 모듈 수정해야 할 곳

 

체크 표시 확인 후 Package IP 클릭

 

Sources에서 warpper로 만든 후 bitstream 실행한다.

만약 Block Diagram에서 수정사항이 있으면 수정한 Block Diagram에서 우클릭을 하여 Wrapper를 새로 갱신한다.

 

다음으로 .xsa 파일 생성

 

 

vitis 진행 순서

 

Mblaze_stopwatch_app -> helloworld.c 소스코드
#include <stdio.h>
#include "platform.h"
#include "xil_printf.h"
#include "xparameters.h"

#define STOPWATCH_BASEADDR XPAR_MYIP_STOPWATCH_0_S00_AXI_BASEADDR

int main()
{
    init_platform();

    print("Start!\n");

    volatile unsigned int *stopwatch_instance = (volatile unsigned int)STOPWATCH_BASEADDR;
    xil_printf("Sanity check : %x \n", stopwatch_instance[7]);	// 무결성 체크

    while(1){
    	stopwatch_instance[0] = 0b10;
    	print("Hello World!\n");
    	MB_Sleep(1000);
    }

    cleanup_platform();
    return 0;
}

 

Mblaze_stopwatch_app 초반 결과 영상

 

Mblaze_stopwatch_app 후반 결과 영상

bcd_fnd, stopwatch(myip) 끝!