적극적 생각/FPGA

[프로젝트] 주사위 (작성용)

무말랭이 2022. 8. 9. 10:49

목적

배운것을 기반으로 간단한 프로젝트를 0to1한다. 복습 설계과정의 템플릿화에 초점.

그리고 git으로 형상화까지 시켜서 맺음성을 둔다. (한글 ->영어) v말고 sv로 짜자.

기획

버튼을 누를때마다 dice가 굴려져 숫자가 rand 생성된다.

btn0을 누르면 1~6(1,2,3,4,5,6)의 6개의 숫자가 랜덤 생성되어 2진수로 보여준다.

0001

0010

0011

0100

0101

0111

(led0, led1, led2 3포트만 사용한다.)

 

- 단 async로 구현이 가능하지만 sync로 구현하고

- 또한 memory가 필요없지만 state 구현을 위해 직전 2개를 스스로 기억하는 것으로 한다. (그걸 C로 보여주자.)

 

[serial 과 어떻게 통신해서, 출력만 해줄지, 입력도 해줄지를 선택할 수 있다.]

 

리셋신호 고려해야함.

설계 및 구현 (동시병행진행)

우선 기본적인 io는 다음과 같다.

다른 부수기능을 넣기에 앞서 이것의 구현에 집중한다.

input output diagram of a RTL module

 

3.3V 그리고 ground 표기는 핵심이 아닌 것 같으니 생략한다.

(내가 풀업 풀다운 처리까지 해줄 필요는 없어보이기 때문에.)

생각의 프레임에 도움될 수 있는 사진 몇장 스크랩

 

자 현재로서 외부 입출력이 필요 없으므로 

보드는 입출력이 차단된 상태로 혼자 동작한다.

(단, 전원공급과 clk 공급은 필요하다. clk 공급에서 zynq가 필요할듯하다.)

해당 모듈을 먼저 구현하고 올리는 과정에서

모식도를 develop 시켜 ps 및 pl 등의 개념을 넣도록 하자.

 

보드를 Zybo Z7-20으로 설정하여 project>_mini>dice>dice_project를 생성한다.

dice.sv (system verilog 옵션을 선택해준다.

우선 v로 작성한뒤 sv로 리팩토링 하도록 한다.)

그림을 업데이트하고

코드의 구조를 다음과 같이 짰다.

master.xdc를 확인해도 변수명은 이렇게만 갖고가도 된다.

 

우선 rand 가져오는것도 분리하기 위해

btn을 누를때마다 1,2,3,4,5,6,1,... 로 변화하는 카운터를 만든다.

(어 근데 버튼을 누르고 있는동안 ns가 수십수백번 변할 수 있기 때문에 sync가 아닌 async로 만들어야 하나 싶다.)

 

그리고 btn0과 reset 신호의 혼동 때문에

그리고 향후 메모리의 추가를 염두에두고

dice를 top모듈로 위임하고

그 아래에 dice_controller를 만들어서 구조를 변화시킨다. = 모듈파생을 시킨다.

(근데 btn이 역이 되어야 하는 것 아닌가 하는 혼동이 오기는 한다.)

 

그렇게 변경한 구조로 

기본 코드 초안을 작성했는데

이 부분이 조금 켕긴다.         

led=i;

 

 

우선 tb를 만들어서 검증하는 작업을 병행하자.

(계속 느끼고는 있는데 reset 신호의 활용이 잘못된 것 같아서 향후 수정해주어야 할 것 같다.

또는 reset 신호에 대해서 외부용도로 활용하지 않고 내부용도로 활용하면 잘 된것 같기는 하다.)

 

또한 sv파일이 잠시 혼동을 주는 것 같아 모든 파일을 v로 임시적으로 replace했다.

정상작동할때가 되어서야 sv로 갈아끼우며 공부를 한다.

 

tb가 정상작동하지 않으므로

RTL Schematic이 보이지 않는 원인부터 파악하자.

 

[Synth 8-2577] procedural assignment to a non-register led is not permitted, left-hand side should be reg/integer/time/genvar ["C:/dev/fpga_proj/_mini/dice/dice_project/dice_project.srcs/sources_1/new/dice_controller.sv":40]

 

[Synth 8-2577] procedural assignment to a non-register reset is not permitted, left-hand side should be reg/integer/time/genvar ["C:/dev/fpga_proj/_mini/dice/dice_project/dice_project.srcs/sources_1/new/dice_controller.sv":41]

 

[Synth 8-2577] procedural assignment to a non-register led is not permitted, left-hand side should be reg/integer/time/genvar ["C:/dev/fpga_proj/_mini/dice/dice_project/dice_project.srcs/sources_1/new/dice_controller.sv":54]

 

[Vivado_Tcl 4-5] Elaboration failed - please see the console for details

 

---

 

에러메시지에서 이상한 점을 발견했다. 

v에 대한 에러가 아닌 sv에 대한 에러를 출력한다.

 

디렉토리에 접근하여 sv파일을 수동 삭제를 한번 더 해준다음에 

에러메시지를 보니 

v파일에 대해서도 동일한 메시지가 뜬다.

 

에러를 파악해보니 예상대로 

led = i

와 관련해서 생기는 에러이다.

 

int가 아니라 integer로 사용해주어야 한다.

 

led는 output인데 reg처럼 다루고 있다는 에러다.

이 부분과 관련해서는 'led에 대한 버퍼레지스터'가 필요할듯하다. 그건 controller안이 아니라 dice쪽에?

근데 그건 굳이 '레지스터를 만들어준다'가 아니라 'output 선언시 해주어야 하는일'에 가깝지 아니한가 싶다.

 

아 그리고 치명적으로 까먹은게 있었는데

always 구문 내에서는 = 가 아니라 <=를 사용해야한다.

 

blocking 구문과 non-blocking 구문의 차이

https://blog.naver.com/PostView.nhn?isHttpsRedirect=true&blogId=mikael2010&logNo=130094384689 

 

blocking (=)과 nonblocking (<=)

조합회로 "assign"과 "function"에서는 blocking(=), 순차회로 “always” 안에서는 non-blocking(<=) ...

blog.naver.com

https://blog.naver.com/j0hnch01/70031459140

 

verilog에서 blocking assignment와 nonblocking assignment 사용하기.

우리가 a 라는 신호에 어떤 값을 할당(assignment)할 때, verilog언어에서는 두 가지 방식 중 하나를 사용...

blog.naver.com

 

이 동시성 개념을 생각하면

이 부분에서도 향후 문제가 생길 수 있음을 인지하고

언어 자체의 legacy문제도 있기는 하겠지만

병렬처리 되는지 순차처리 되는지에 대해서는 

확인하고 넘어갈 수 있도록 하자.

 

 

이건 이렇게 합쳐쓸 수 있다.

https://stackoverflow.com/questions/31472546/error-procedural-assignment-to-a-non-register-result-is-not-permitted

 

Error "procedural assignment to a non-register result is not permitted"

I'm getting the error [Synth 8-2576] procedural assignment to a non-register result is not permitted ["lpm_mult.v":29] What am i doing wrong? module lpm_mult ( dataa, datab, //

stackoverflow.com

 

자 에러를 하나씩 고쳐가는중.

 

[Synth 8-91] ambiguous clock in event control ["C:/dev/fpga_proj/_mini/dice/dice_project/dice_project.srcs/sources_1/new/dice_controller.v":46]

 

https://wiki.nus.edu.sg/display/EE2020DP/%5BSynth+8-91%5D+ambiguous+clock+in+event+control 

 

[Synth 8-91] ambiguous clock in event control - EE2026 Design Project - Wiki.nus

Problem The following error occurred during the synthesis phase : [Synth 8-91] ambiguous clock in event control ... [Synth 8-285] failed synthesizing module 'counter' What does it mean and how do I resolve it? Solution This message is indicating that this

wiki.nus.edu.sg

늘 이렇게 진법표시는 꾸준하게 해주고.

i<=1'b1 

또는

sensitivity를 다음과 같은 루틴으로 사용해야한다.

if(posedge clk or negedge reset)

    if(!reset)

        ....

 

아 이제야 schematic이 뜬다.

int 사용 등에서 비효율적인 부분이 눈에 띈다.

이 부분은 향후 기회가 되면 공부해보도록 하고

우선 넘어간다.

 

하지만 아직 sim까지 정상적으로 되지는 않는다.

우선 여기서는 단순 wiring만 시켜줄거라서

여기서 또 굳이 reg 선언을 해줄 필요성은 보이지 않는다.

[VRFC 10-3180] 에러는 무엇이냐.

https://support.xilinx.com/s/question/0D52E00006ihQNKSA2/error-during-post-synthesis-simulation?language=en_US 

 

Error during Post synthesis simulation

 

support.xilinx.com

여기에 오타가 있었다.

 

tb가 동작하게 하는 것은 성공했다.

 

(다시금 주의깊게 볼 포인트는 tb에서의 clk인데, 이게 zynq에서의 clk으로 쓰일 예정이다.)

always #5 clk = ~clk;

always #0.5 clk = ~clk;

 

위에서 예측한 sync 그리고 async 설계상의 문제가 여기서 발생하고 있다.

(하드웨어상에서 이러한 human touch/operation을 극복하기 위한 제어 알고리즘을 넣어야겠다.)

 

그런데 왜인지 이 에러가 있는 상태로 hw에 넣어보고 싶어졌다.

이 에러를 고치지 말고 그냥 넘어가서 실험해보자.

(어떻게 보면 주사위가 돌아가는 것과 유사한 효과가 생길것 같기도. 오히려 좋아?)

(또한 이것을 위해 주파수를 아주 고의적으로 낮출 수 있을 것 같기도, cpu급 clk말고)

 

bit 만들어서 넣으려고 했는데

생각해보니깐 xdc 설정을 안했다.

그거부터 활성화 시켜주자.

 

그리고나서

generate bitstream. (synth + implementation)

 

 

다시 돌아와서

synth 

implemetation을 

해야겠다 싶은데

 

아 근데 여기서 project2로 분기시킨후에

여기서 이것을 기준으로 wrap 시켜보고 bitstream 해보자.

(vivado에는 git 역할을 해줄 수 있는것이 없나?)

 

그리고 예전에도 똑같이 했던 실수일 수 있을 것 같은데

내가 지금 만든것을 ip로 생각해야하나 싶다.

hierarchy의 개념이 덜 잡힌 것일 수 있다.

 

그냥 bitstream만들어서 올려보는 방법이 하나가 있고 

zynq 연결해서 bitstream 만들어서 올리는 방법이 하나 있다.

 

현 상태로 다시 프로젝트 분기시킨후에

두번째를 먼저 해보자.

 

ZYNQ로부터 clk을 받지 못할 수 있다

왜냐하면 AXI 신호로서의 clk를 받아야 하기 때문인 것 같다.

 

그러면 clk을 어디서받지?

clocking wizard는 뭔데?

 

두번째 방법이 아닌

첫번째 방법 시도

clk핀에 대한 문제가 해결되지 않아서 이것도 동일하게 되지 않는다.

 

맛비 블로그에가서 clk 관련 내용을 찾아보자.

https://aifpga.tistory.com/search/clk

 

설계독학맛비 (AI FPGA)

관심분야는 Video, AI IP HW 설계 입니다. FPGA 그리고 HLS 를 잘 쓰려고 노력 중 입니다. 설계독학 유뷰브를 운영중입니다. https://www.youtube.com/c/aifpga 20/04/01 이후로 좋은 분들과 스타텁 생활을 하고 있

aifpga.tistory.com

안나온다.

 

google에서 clk 주는법과 관련된 내용을 찾아본다.

fpga에서 clk주는법

또한 바로는 나오지 않는다.

 

자 그냥 zynq에서 주는게 맞는 것 같은데

단, clk에 대해서만 axi4로 주어야 할듯 싶다.

 

여기서 axi4와 관련된 내용을 복습하며 극복할 수 있도록 하자.

이 글을 참고하면 될 것 같다.

https://learn-future.tistory.com/3378

 

0715 - 섹션2 - 기초 PL영역을 활용한 LED Blinking (2)

연결 환경설정 컴퓨터를 포맷해서 연결이 정상적으로 이뤄지는지에 대하여 board 파일에 대해서 다음 경로에 넣어주고 C:\Xilinx\Vivado\2022.1\data\boards\board_parts 샘플 bitstream을 hardware manager를 통..

aidenkang.me

 

---

 

그리고 과정에서 짧게 발견한건데

instantiation 과정에서의 formatting 또한 다음과 같이 둘 수 있다.

---

 

btn과 led는 '수동으로' make external 처리를 한다.

그때 이름을 변경해주는 것을 잊지말자.

---

 

reset_n을 만들지 않아서 Run Connection Automation이 안되나? (되긴 되어도 다음 단계로 못넘어가나?)

그렇다면 내부 모듈에서 reset을 두개씩 만들어주어야 하나? AXI4를 쓰기 때문에?

 

ㅇㅋㅇㅋ

생각난대로 해보자.

axi4에 따른 reset_n을 반영해준 RTL로 upgrade 시켜오자.

 

이 개념들을 포함한 설계 도면부터 다시 그리자.

구조를 이렇게 바꾼다. 리셋은 리셋이고 리셋버튼은 리셋버튼이다. 섞지 않는다.

다시 RTL 구성에 성공했다.

reset_n이 btn보다 밑에있는 것은 

abc ... 순서대로 구성하느라 그런듯하다.

 

그럼 그 다음은 tb, 아까랑 동일하게 동작함 또한 확인했다.

 

그럼 그 다음은 ip구성해서 내보낸다음에

새로운 proj에서 bd에서 호출한 뒤 재연결시도.

 

잘 될 것 같은데~~~

왜~~~~~~~~~~~~~

run auto 했을때 잘 안먹는 것이냐~~~~~~~

불안하게~~~

강제로 연결시킨 다음에 verify 시켜봐도

아직도 unvalid 하단다.

 

얘를 없애면 될 것 같기는 하다.

 

문제해결을 위해 잠시 참고한 게시글들

https://m.blog.naver.com/PostView.naver?isHttpsRedirect=true&blogId=seobi1111&logNo=221040220676 

 

[ZYBO] UART(PS), GPIO(PS/PL), I2C(PS/PL) 인터페이스 테스트

[UART] Zybo Zynq PS 영역에 UART1이 디폴트로 잡혀 있다. 처음 Zynq를 Block Design에 올...

blog.naver.com

 

AXI를 비활성화 해주었더니 되었다.

(그럼 나는 AXI를 쓰는 것이 아니며, 내가 쓰고있는 clk이 어떤 원리로 ps에서 오는 것인지 찾아야 한다.)

 

 

wrap

create bitstream

 

이름 바꿔주는 것을 까먹어서 그런가

btn_0을 btn으로 

led_0을 led으로

바꿔준다음 bitgen 재시도.

 

다시 실패.

이번에 용의자가 되는 것은 

auto connect 되지 않고 직접 connect 해주었던 reset_n

(근데 이상하다, 검증이 잘 되었는데, 

또 하나의 용의자가 있다면 wrap 시킬때 하나 존재하던 warning)

 

proj2를 다시 만들면서

그 과정에서 error를 다시 찾아보자.

우선 그 이전에 reset_n 관련해서 한번 먼저 RTL 살펴보고.

 

그 과정에서 non-blocking 으로 되어있어야 하는데

blocking으로 되어 있던 부분을 찾아서 수정하기는 했다.

(하지만 reset_n과 직접적인 연관관계가 있는 곳은 아니다.)

 

(그리고 이쪽에서 이렇게 reset을 3번이나 해주어야 하나 싶긴 하다.

처음에 zynq에서 reset 신호가 잘 들어오는게 향후 확인되면 초기 reset도 없애도 될양싶다.)

 

관련 없는건 아는데

tb에서도 reset_n 없는 부분 찾음.

 

틀린 부분을 또 찾지는 못해서

repackage 하고 우선 진행.

 

이 원형 표식은 뭐지?

 

그래 auto connect가 안되는 것에 저 원형 표식이 원인인 것 같다.

 

카톡방에 물어봐서 해결하려고 했는데

auto connect의 원인이 inverter 일듯하다.

 

차라리 0을 멕이는 것이 방법일 수도 있겠다는 생각도 스치긴 한다.

 

코드 에러를 하나 더 찾았다. (이게 왜 검증이 안되고 넘어가졌지?)

 

 

이걸 하고 해도 안되기는 매한가지.

 

---

 

우선 처음부터 다시해보자.

현재 코드를 기준으로 구성적인 부분만.

 

아직도 안된다~~~

원인이 될 만한 게 또 뭐가있을까?

- 내가 지금 저 clk 과 reset에 대한 도메인지식이 없이 덤비고 있는 것.

 

강의를 또다시 복습해보자.

https://learn-future.tistory.com/3378

- 1초를 만드는 법은 freq 적으로 인지하고 있을 것.

- xdc를 추가해주는건 ip에서가 아니라 project에서다.

- zynq가 clk과 reset을 사용하기 위해서만 호출한 것도 맞다.

- 꼭 auto connect 하지 않아도 잘 연결되면 된다. 검증 잘 되면 괜찮다.

- constraints가 들어가야 하는 시점은 wrapper에서 싸여지기 이전 시점이다. wrapper까서 볼 수 있다.

 

Run block automation이란 무엇인가?

Run Connection automation이란 무엇인가?

PL Fabric Clock이란 무엇인가? 

 

수동으로 긋고, 

검증도 정상적으로 되었다.

(XDC 파일 탓일 가능성이 커졌다.)

 

wrapper에서는 이부분을 보면 된다.

 

(아직 address map과 address aditor에서는 아무것도 뜨지 않는다. = assign 된 것이 없다.)

 

된다 ㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠ

 

 

음 근데 아무리 zynq에서 아무것도 안 쓰고 있다고 하더라도

이렇게 적게 resource 가 쓰이는 것이 맞는 것인지는 의심스럽다.

 

connect 시켜서 program

 

정상적으로 들어가기는 하나 hw에서 잘 동작하지 않는다.

 

눈에 보이지 않는 것일수도 있겠다는 생각이 들어 주파수 또는 클락를 수정해주어야 할 것 같으며

led = 구문에 문제가 있을수도 있으니 이 부분에서 진법 문제를 해결해주어야 할 것 같다.

그리고나서 ip>bitstream 단계를 반복해주면 hw 검증이 가능할 것으로 보인다.

 

우선 visible한 진법 문제를 먼저 해결해주자.

아니, 위 두가지 방법으로 해결하려고 하지 말자.

 

FSM 개념을 이용해서 설계를 바꾸자. 그것이 조금 더 근본적인 해결 방법으로 보인다.

현재 사용하던 버전은 outdated3으로 archive

 

재기획 및 재설계

다음과 같이 구조를 바꾸었다.

FSM 개념을 사용하여 정교하게 모델링할까 했는데, 우선 저 모식만 있어도 RTL 짜기는 충분하겠다 싶었다.

(3s later가 아니라 '누르고 있는 동안'으로 하고 싶었는데,

그 부분의 제어가 껄끄러운 부분이 있을 것 같아서 우선 저렇게 처리했다. 카운트다운 느낌으로.

아 그리고 3이라는 숫자도 나눠지면 소수부가 무한소수 형태로 남아서 처리하기 애매할 수 있으나 이건 극복하기로 결심)

 

io 및 port 에서는 바뀔 부분이 없다.

다만 display의 용이 및 관찰용도를 위해 led 하나만 늘려주었다.

 

바뀐 설계에 맞게 RTL 및 XDC 등을 바꾸어주자.

- led 개수가 바뀜에 따라 수정되어야 하는 것은 적은데

- '상태'를 표현하기 위한 reg 하나만 사용하자.(dice_status)

이를 위한 약식 address memo를 추가하였으며, 이를 기반으로 RTL을 수정한다.

 

 

코드를 모두 dice_status 중심으로 재구성한다.

(before)

`timescale 1ns / 1ps

module dice_controller(clk, reset_n, reset_button, shuffle_button, led);

// io

input clk;
input reset_n;
input reset_button;
input shuffle_button;

output reg [3:0] led;

// var

integer i;

// init

initial begin
    led = 4'b0000;
    i = 1;
end

// main

always@(posedge clk or negedge reset_n) begin // reset by zynq
    if(!reset_n) begin
        led <= 4'b0000;
        i <= 1'b1;
    end
end

always@(posedge clk) begin // reset button
    if(reset_button==1)
    begin
        led <= 4'b0000;
        i <= 1'b1;
    end
    else;
    // do nothing
end

always@(posedge clk) begin // shuffle button
    if(shuffle_button==1)
    begin
        led <= i;
        i <= i+1;
        if(i==6) 
            i <= 1'b1;
    end
    else;
    // do nothing
end

endmodule

(after)

중간 기획 과정, 우선 무엇이 들어가야할지 부터 정의하고, 구조를 잡은 후에 코드 작성에 들어간다.

'초'와 관련된 부분 이전까지는 짰는데, '초'를 활용하기 위하여 32bits count를 활용한다.

https://dkeemin.com/vivado-verilog-%EC%BD%94%EB%94%A9%ED%95%B4%EB%B3%B4%EA%B8%B0/

 

Vivado Verilog blink 코딩해보기 - DKMIN

Vivado Verilog blink 코딩해보기 Vivado 설치 및 기초 환경 설정을 못했다면 이전 포스팅을 참고해주길 바랍니다. 일단 코딩을 해봐야하니까 비바도를 켜본다. Create Project를 눌러본다. RTL Project를 만든

dkeemin.com

//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: aiden
// 
// Create Date: 2022/08/09 11:51:46
// Design Name: 
// Module Name: dice_controller
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//////////////////////////////////////////////////////////////////////////////////

`timescale 1ns / 1ps

module dice_controller(clk, reset_n, reset_button, shuffle_button, led);

// io

input clk;
input reset_n;
input reset_button;
input shuffle_button;

output reg [3:0] led;

// var

// integer i; // used as buffer of leds (so, I didn't declared additional reg)
reg dice_status; // declared register in register map

// init

initial begin // reset - initial
    dice_status = 1'b0;
end

// main

always@(posedge clk or negedge reset_n) begin // reset by signal
    if(!reset_n) begin
        dice_status <= 1'b0;
    end
end

always@(posedge clk) begin // status 0
    if(dice_status==0) begin
        led <= 4'b1000;
    end
end

always@(posedge clk) begin // (event listener) push shuffle_button
    if(shuffle_button==1) begin
        dice_status <= 1'b0;
    end
end

always@(posedge clk) begin // status 1
    if(dice_status==1) begin
        // status change after 3s
        // display effect during 3s
    end
end

always@(posedge clk) begin // status 2
    if(dice_status==2) begin
        led <= 4'b0111;
    end
end

always@(posedge clk) begin // (event listener) push reset_button
    if(reset_button==1) begin
        dice_status <= 1'b0;
    end
end

endmodule

그리고 '초'와 관련된 부분에서 '비트'를 다루다가, 내가 실수를 많이 냈었다는 사실도 알게 되어 수정해주었다.

우선 1차적으로 다 짰다. 틀릴 수 있어 tb로 검증하면서 확인해주어야 한다.

//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: aiden
// 
// Create Date: 2022/08/09 11:51:46
// Design Name: 
// Module Name: dice_controller
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//////////////////////////////////////////////////////////////////////////////////

`timescale 1ns / 1ps

module dice_controller(clk, reset_n, reset_button, shuffle_button, led);

// io

input clk;
input reset_n;
input reset_button;
input shuffle_button;

output reg [3:0] led;

// var

// integer i; // used as buffer of leds (so, I didn't declared additional reg)
reg [2:0] dice_status; // declared register in register map
reg [31:0] count; // used for count 1s

// init

initial begin // reset - initial
    dice_status = 2'b00;
    count = 0;
end

// main

always@(posedge clk or negedge reset_n) begin // reset by signal
    if(!reset_n) begin
        dice_status <= 2'b00;
        count <= 0;
    end
end

always@(posedge clk) begin // status 0
    if(dice_status==2'b00) begin
        led <= 4'b1000;
    end
end

always@(posedge clk) begin // (event listener) push shuffle_button
    if(shuffle_button==1) begin
        dice_status <= 2'b01;
    end
end

always@(posedge clk) begin // status 1
    if(dice_status==2'b01) begin
        count <= count+1;
        if(count==100000000) // 1*10^8, 1 second
        begin
            dice_status <= 2'b10;
            count <= 0;
        end
    end
end

always@(posedge clk) begin // status 2
    if(dice_status==2'b10) begin
        led <= 4'b0111;
    end
end

always@(posedge clk) begin // (event listener) push reset_button
    if(reset_button==1) begin
        dice_status <= 2'b00;
        count <= 0;
    end
end

endmodule

 

우선 sim 돌리기 전에 RTL Schematic으로 1차 debugging.

오 무슨일인지 한번에 된다 ㅠ

구조가 쪼꼼 더 복잡해지기는 했다.

하지만 이정도 수준이 크게 복잡해진 것처럼 느껴지지 않는다.

(나중에 이걸 아주 최소한으로 줄이는것을 도전해보는 것은 의미가 있을듯하다!)

sim 코드 또한 거의 바꾸지 않았다. led 개수정도 살짝?

왜냐하면 버튼을 누르는 동작 자체는 변동이 거의 없었기 때문이다.

 

하지만 아직 정상동작하는 시나리오는 아닌듯하니, (얼핏보니 shuffle_button이 안먹음?)

한번 차근히 살펴볼 수 있도록 하자.

잘 안돌아가는 줄 알았는데 아니다

카운팅 횟수에서 sim 1000ns를 초과해서 그렇다.

(sim을 위한 변수와 실제동작을 위한 변수를 분리하는 if def 테크닉을 활용할 수 있도록 하자.)

우선 그 전에, count 횟수를 줄여서 다시 시도해보자.

dice status를 보면, 012 까지는 잘 가는데 다시 0으로 돌아가지 않고 1을 유지한다.

아니다. 그건 tb 시나리오가 잘 작성되지 않았기 때문이었다. 얼추 현재까지는 잘 동작하고 있다.

 

그렇다면, 다시 count를 if(count==100000000) 으로 변경한후에

이걸 board에 올려볼 수 있도록 하자. led blinking 되는 것 부터 조금 확인하자.

 

쭉 ... 하다가, 이 두가지 실수하지 않도록 조심해주기. 실수할뻔.

- 프로젝트 생성시 보드 클릭

- block design에 대한 wrapper 처리

보드에 올리는 것 까지 성공했는데 

문제는 led blinking이 되지 않는다.

 

vitis에서 blank c 를 통해 보드 올리는 방법으로 해보자. (export hw include bitstream)

이렇게 올려도 동일하다.

 

자 이제 내가 취할 수 있는 선택지는 눈에 띄게는 두가지인데 

- led에 대한 xdc등 포인트를 점검해서 hw적으로 led가 뜨는 것을 확인하거나 

- led에 관련된 신호를 c 의 serial uart 통신을 통해 확인해주는 방법이 있다. 

 

아 잠시 휴식 ㅠㅠ

다음 재시도를 하기 전에 '초' 관련된 부분만 내가 직접 연산할 수 있도록 해서 한번 점검하고 넘어가자.

 

=====

 

led에 초점을 맞추어 다시 살펴보자.

 

tb도 잘 바뀐다.

 

8 = 1000

7 = 0111

 

주파수에 문제가 있나?

이상 없는데. 100M번 Count

 

 

다시 해봤는데 우선 되지 않는다.

 

----

 

blink led 코드와 다시 한번 비교해보자.

lab05말고 09를 참고해보자.

 

RTL 까서 보다보면

SYNC와 ASYNC가 다른데 이것 때문인가.

 

 

아 아무리 이것저것 둘러보아도 잘 보이지가 않네.

LED 신호가 0,1로 LOW, HIGH 처리 되는데

왜 불이 안들어오는걸까? sim 결과도 정상적으로 나오는데.

 

Constraint도 정상적으로 잘 연결되어있고 ...

 

---

 

아 우선 다른 모듈로 그냥 '켜기'만 해보자. ㅠㅠ

new project

 

led 모듈

input clk, reset_n

output led

그냥 reset신호 받으면 켜지기.

 

 

켜진다. 

지금 방법이나 접근이 잘못된것은 아닌듯하니 다행이다. ㅠ_ㅠ

 

걍 우선 플젝에 놓친부분 있나 또 다시 만들어보자.

또 했는데 안돼.

RTL 문제인가보다. ㅠ_ㅠ

 

자 이제 이 부분을 바꾸었더니 불은 켜진다.

그러나 버튼에 의한 조작은 되지 않는다.

RTL의 문제다 RTL을 더 검증해보자.

 

STATUS를 처리하는 부분이 정상작동하지 않는듯하다.

 

RTL 수정중에 이런 에러가 뜬다.

이 버그가 왜 나지? 날 이유가 없는데,,, 

https://wiki.nus.edu.sg/display/EE2020DP/%5BSynth+8-91%5D+ambiguous+clock+in+event+control 

 

[Synth 8-91] ambiguous clock in event control - EE2026 Design Project - Wiki.nus

Problem The following error occurred during the synthesis phase : [Synth 8-91] ambiguous clock in event control ... [Synth 8-285] failed synthesizing module 'counter' What does it mean and how do I resolve it? Solution This message is indicating that this

wiki.nus.edu.sg

https://blog.naver.com/PostView.nhn?blogId=bluehorn07&logNo=221917385142&parentCategoryNo=&categoryNo=1&viewDate=&isShowPopularPosts=true&from=search 

 

[Verilog] always문 완전정복 ★

◆ 선행개념 Verilog의 기초 항목이라 선행개념이랄게 없지만, 적어도 (1) blocking assignment(=),...

blog.naver.com

 

posedge clk 하면 에러가 안나고

posedge clk or negedge reset_n 하면 에러가 난다.

이건 후자로 규칙성있게 통일해주는게 좋을 것 같은데 

왜 그럴까. 우선 이건 패스하고.

 

아~~ 뭔가 찾은 기분이다.

1초가 켜지는게 안보였던 것 같다.

RTL에서 LED와 관련된 제어를 제대로 못해주고 있었던 것 같다.

그래서 led가 변하긴 변했는데 정말 0.001초 변한다거나 했던듯...?

우선 이것(1초)만 테스트.

 

tb로 led변화 다시한번 제대로 트랙킹.

draw io까지 써가매

 

시뮬레이션에서는 btn[1]이 잘 먹는데

실제 하드웨어에서는 btn[1]이 잘 안먹는 이유는?

 

설마 버튼의 동작을 잘못 이해하고 있나?

https://blog.naver.com/PostView.naver?blogId=rhoblack&logNo=222431416770&parentCategoryNo=&categoryNo=35&viewDate=&isShowPopularPosts=true&from=search 

 

[FPGA] 버튼 눌렀다 땠을 때 동작 Verilog

우리 주변 전자기기를 보면 많은 버튼들이 있다. 우리가 별로 신경을 안쓰는 동작 중 버튼이 눌렀을때 동작...

blog.naver.com

 

그래서 이렇게 되는건가

 

아 그거에 맞게 컨트롤러와 테벤을 바꿔본다.

 

tb가 있으면 package가 안되어?

 

아 이 문제 해결하고 다시 

program 까지 시켰는데

그래도 안돼 ㅠㅠㅠㅠㅠㅠ

 

RTL을 그냥 처음부터 다시짜자.

 

`timescale 1ns / 1ps

module dice_controller(clk, reset_n, reset_button, shuffle_button, led);

// io

input clk;
input reset_n;
input reset_button;
input shuffle_button;

output reg [3:0] led;

// reg

reg [1:0] dice_status;

// init

initial begin // reset initial
    dice_status = 2'b00;
end

// main

always@(posedge clk or negedge reset_n) begin // reset signal
    if(!reset_n) begin
        dice_status <= 2'b00;
    end
end

always@(posedge clk or negedge reset_n or negedge reset_button) begin // reset reset_button
    if(!reset_button) begin
        dice_status <= 2'b00;
    end
end

always@(posedge clk or negedge reset_n) begin // status 0, shuffle shufle_button
    if((dice_status==2'b00)&(!shuffle_button)) begin
        dice_status <= 2'b01;
    end
end

always@(posedge clk or negedge reset_n) begin // status 1
    if(dice_status==2'b01) begin
        dice_status <= 2'b10;
    end
end

always@(posedge clk or negedge reset_n) begin // status 2, reset reset_button
    //
    if((dice_status==2'b10)&(!reset_button)) begin
        dice_status <= 2'b00;
    end
end

endmodule
`timescale 1ns / 1ps

module dice_controller(clk, reset_n, reset_button, shuffle_button, led);

// io

input clk;
input reset_n;
input reset_button;
input shuffle_button;

output reg [3:0] led;

// reg

reg [1:0] dice_status;
reg [31:0] count;

// init

initial begin // reset initial
    dice_status = 2'b00;
    led = 4'b1111;
    count = 0;
end

// main

always@(posedge clk or negedge reset_n) begin // reset signal
    if(!reset_n) begin
        dice_status <= 2'b00;
        led <= 4'b1111;
        count <= 0;
    end
end

always@(posedge clk or negedge reset_n or negedge reset_button) begin // reset reset_button
    if(!reset_button) begin
        dice_status <= 2'b00;
        led <= 4'b1111;
    end
end

always@(posedge clk or negedge reset_n) begin // status 0, shuffle shufle_button
    if((dice_status==2'b00)&(!shuffle_button)) begin
        led <= 4'b0111;
        count <= count+1;
        if(count == 100000000) begin
            dice_status <= 2'b01;
            count <= 0;
        end
    end
end

always@(posedge clk or negedge reset_n) begin // status 1
    if(dice_status==2'b01) begin
        led <= 4'b0011;
         count <= count+1;
        if(count == 100000000) begin
            dice_status <= 2'b10;
            count <= 0;
        end
    end
end

always@(posedge clk or negedge reset_n) begin // status 2, reset reset_button
    //
    if((dice_status==2'b10)&(!reset_button)) begin
        dice_status <= 2'b00;
        led <= 4'b1111;
        count <= 0;
    end
end

endmodule

 

에러를 해결했다.

그리고 올려도 안되 .................................

 

아 이건 그냥 RTL에 대해서 다시 더 제대로 해보자. ㅠ_ㅠ