본문 바로가기

임베디드 시스템반도체 개발자 과정 by 서울기술교육센터/후기

80일차

10월 17일

 

IP Intelectual Property

 

설계된 걸 사와서 내 설계에 접목해보자.

 

project manager를 선택한 다음 진행해야 한다.
AXI4 IP가 아니어서 위에 거 선택
새로 폴더 만들어서 경로 지정
next 누르고 뜨는 팝업창에서 ok 누르면 된다.
이 칩들과 호환이 된다는 걸 알려주는 창
Package IP를 누른다.
끝.
만들었는데 검색해도 직전에 만든 IP가 검색이 안 됨
ok 누르고 apply
아직 코드로 변경 안 된 상태
아래 거 선택하고 ok

비어있는 포트들이 설정이 안 돼서 나타나는 오류

포트를 설정할 수 있음. 핀 하나 선택하고 우클릭했을 때의 상황.
전체를 선택하면 한 번에 만들어진다.
이름에서 _0을 다 지웠음.

다시 create HDL Wrapper를 진행하니 정상적으로 완료됐다.

오른쪽 창에서 코드로 변환된 모습을 볼 수 있다.

/* 2022.10.19

이걸 가져와서 썼을 때 제대로 동작하지 않고 timing loop가 발견됐다면서 에러가 나왔는데 IP가 아니라 다른 모듈에서 always 내부에 posedge i_clk가 아니라 그냥 i_clk로 써서 그랬던 거였다.

*/

-------

non-blocking / blocking

 

non-blocking 비동기식

always@(*) begin

...

r_value <= x; ...1

r_counter <= x2; ...2

end

 

순차회로에서 주로 쓰임.

1과 2를 동시에 대입.(1의 우항을 연산. 아래 줄로 넘어감. 2의 우항을 연산. 아래 줄로 넘어감. 연산할 게 없으니 대입 진행)

 

blocking 동기식

always@(*) begin

...

r_value <= y; ...1

r_counter <= y2; ...2

end

 

조합회로에서 주로 쓰임.

1과 2를 순서대로 대입.(1의 우항을 연산. 대입. 아래 줄로 넘어감. 2의 우항을 연산. 대입. 아래 줄로 넘어감.)

 

주의할 점은 반드시!! always 내에서 비동기식 혹은 동기식으로 통일해야 한다. 섞어써서는 안 된다!!

-----------

두 개의 always 구문이 있다고 하자.

always @(*) begin

...

r_value <= x;

end

 

always @(*) begin

...

r_value <= y;

end

 

이 경우, r_value에는 x와 y가 계속하여 대입된다. 이러한 동시 대입 상황을 race condition이라고 한다. 에러가 발생하는 부분이고 설사 컴파일이 돼더라도 제대로 작동하지 않는다.

 

따라서 이를 해결하기 위해서는 여러 개의 레지스터를 선언해서 각각의 always 구문에서 사용해야 한다.

-----

SRAM

module singleRAM(
    input i_clk, i_ce, i_we,
    input [5:0] i_addr,
    input [7:0] i_data,
    output [7:0] o_data
    );

    reg [7:0] mem[0:63];
    reg [5:0] r_addr;
    assign o_data = mem[r_addr];

    always @(posedge i_clk) begin
        if(i_ce) begin
            if(i_we) begin
                mem[i_addr] <= i_data;
            end
            else begin
                r_addr <= i_addr;
            end
        end
        else begin
        end
    end
endmodule

module tb_SRAM();

    reg i_clk = 0, i_ce, i_we;
    reg [5:0] i_addr;
    reg [7:0] i_data;
    wire [7:0] o_data;

    singleRAM dut(
    .i_clk(i_clk),
    .i_ce(i_ce),
    .i_we(i_we),
    .i_addr(i_addr),
    .i_data(i_data),
    .o_data(o_data)
    );

    always #5 i_clk = ~i_clk;

    initial begin
        i_clk = 0;
        i_ce = 0;
        i_we = 0;
        i_addr = 0;
        // #20 i_ce = 1; i_we = 1; i_addr = 0; i_data = 10;
        // #20 i_ce = 1; i_we = 1; i_addr = 1; i_data = 20;
        // #20 i_ce = 1; i_we = 1; i_addr = 3; i_data = 30;
        // #20 i_ce = 1; i_we = 1; i_addr = 4; i_data = 40;
        // #20 i_ce = 1; i_we = 1; i_addr = 5; i_data = 50;
        // #20 i_ce = 1; i_we = 1; i_addr = 10; i_data = 100;
        // #20 i_ce = 1; i_we = 1; i_addr = 20; i_data = 200;
        // #20 i_ce = 1; i_we = 1; i_addr = 25; i_data = 250;

        #20 i_ce = 1; i_we = 1;
        for(integer i = 0; i<64; i= i+1) begin
            #20 i_addr = i; i_data = (i*10) + 1;
        end

        for(integer i = 0; i < 64; i = i+1) begin
            #20 i_we = 0; i_addr = i;
        end
        #20 $finish;
    end
endmodule

assign io_data = (i_rw == 1) ? mem[r_addr] : {8{z}};

high impedance라는 건 chip 입장에서 read를 하겠다는 의미(입력되는 전압값을 읽는 것). -> 내 입장에서 write을 하겠다는 의미.

 

module tb_staticRAM();

    reg i_clk = 0, i_ce, i_rw;
    reg [5:0] i_addr;
    reg [7:0] i_data;
    wire [7:0] io_data;

    staticRAM dut(
    .i_clk(i_clk),
    .i_ce(i_ce),
    .i_rw(i_rw),
    .i_addr(i_addr),
    .io_data(io_data),
    .o_data(o_data)
    );

    always #5 i_clk = ~i_clk;

    initial begin
        i_clk = 0;
        i_ce = 0;
        i_rw = 0;
        i_addr = 0;
        io_data = 0;

        #20 i_ce = 1; i_rw = 0;
        for(integer i = 0; i<64; i= i+1) begin
            #20 i_addr = i; i_data = i + 1;
        end

        #20 i_rw = 1;

        for(integer i = 0; i < 64; i = i+1) begin
            #20 i_addr = i;
        end
        #20 $finish;
    end
endmodule

에러나서 수정 필요.

--------

Xilinx에서 무료로 제공하는 Soft core가 있음.

 : Micor Blaze (ARM과 비슷함) 32bit. BUS, AXI, peripheral 주변장치

 

MicroBlaze는 간단하게 생각하면 MCU임.

uart는 기본적으로 넣는 게 좋다.
basys3의 용량이 남아서 여유있으니 메모리 제일 크게.
전체 선택
외부 클럭을 사용할 거라서 수정 필요. 더블 클릭.
연결이 사라졌음. 지우고 connection automation을 진행하면 sys clock과 연결해준다.

Led를 켜기 위해 수정하자.

gpio 더블 클릭

custom일 경우 GPIO Width를 통해 비트수 조절 가능. All Inputs이나 All Outputs를 선택 안 하면 코드를 통해 I/O 선택 가능.

포트 이름을 led로 바꿨다.

block을 생성한 뒤, create HDL Wrapper까지 진행한다.

이제 아래에 맞춰 constraints를 수정한다.

uart는 자동으로 설정해줘서 건드릴 필요가 없다.

이제 bitstream을 만든다.(하드웨어에 올리지는 말고)

완성된 후

 

얘가 하드웨어 플랫폼

이제 소프트웨어로 넘어간다.

우리가 만든 하드웨어에 어플리케이션을 올리겠다.
application project name 넣으면 됨.
넘기다가 hello world 선택

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

#define CHANNEL_1 1
#define OUTPUT    0

//c, not verilog
XGpio GPIO_LED;

int main()
{
    init_platform();

    print("Hello World\n\r");
    print("Successfully ran Hello World application");

    XGpio_Initialize(&GPIO_LED, XPAR_AXI_GPIO_0_DEVICE_ID);
    XGpio_SetDataDirection(&GPIO_LED, CHANNEL_1, OUTPUT);

    while(1)
    {
    	XGpio_DiscreteWrite(&GPIO_LED, CHANNEL_1, 0x00);
    	usleep(200000);
    	XGpio_DiscreteWrite(&GPIO_LED, CHANNEL_1, 0xff);
    	usleep(200000);
    }
    cleanup_platform();
    return 0;
}

징크칩?

'임베디드 시스템반도체 개발자 과정 by 서울기술교육센터 > 후기' 카테고리의 다른 글

82일차  (0) 2022.10.19
81일차  (0) 2022.10.18
79일차  (0) 2022.10.14
78일차  (0) 2022.10.13
77일차  (0) 2022.10.12