2024.6.14 수업날
임베디드 시스템을 위한 SW 구조설계 수업과 취업특강 수업을 잠시 마치고
오늘부터 5일동안 Verilog와 관련된 수업을 듣게 되었다.
< Vitis 다운로드 방법 >
우선 아래 사진과 같은 Vivado 프로그램이 필요하다.
이 프로그램으로 Verilog를 사용하여 시뮬레이션도 돌려보고, 회로도를 구현해 볼 수 있다.
반드시 2019.2 버전을 깔아줘야한다.
최신 버전을 다운로드 받게되면 버전끼리의 호환이 되지 않기 때문이다
아래의 링크에 들어가서 다운받을 수 있다.
용량이 약 100GB이기 때문에 충분한 용량을 확보한 후 다운로드 받는 것을 추천한다.
https://www.xilinx.com/support/download/index.html/content/xilinx/en/downloadNav/vitis.html
아래의 사진은 위의 링크에 들어갔을때 상단 부분에 보이는 메뉴들인데,
Vitis로 들어가서 다운받으면 Vivado를 기본적으로 같이 다운받을 수 있기 때문에 Vitis에서 다운받는 것이 좋다.
강의실 컴퓨터에는 이미 깔려있지만
2019.2버전을 나중에 개인적으로 깔기 위해 어떤 설정을 해줘야하는지에 대해서도 사진으로 남긴다.
< Vivado 기본 설정법 >
Vivado 2019.2 를 실행하게되면 프로그램이 실행되면서 아래와 같이 Quick Start 메뉴가 보이는데,
Create Project를 선택해서 프로젝트를 새로 만들어보자.
이번 수업에서는 'Basys3'이라는 부품을 주로 사용하게된다.
때문에, 부품이름과 관련된 프로젝트 이름으로 기입하였다.
프로젝트 위치는 교수님께서 D드라이브에 폴더를 추가로 생성하여 지정하는 것을 추천한다고 하셨다.
다음으로,
좌측 상단의 Boards로 들어간 다음, 검색창에 basys3을 입력하고 선택한다.
(해당 보드가 뜨지 않는다면 우측 상단의 'Update Board Repositories'를 선택하고 다시 검색한다.)
하이퍼링크 처리가 되어있는 부품 이름을 클릭하면
해당 부품을 만든 회사에서 제공하는 부품의 메뉴얼과 구조를 확인할 수 있다.
https://digilent.com/reference/programmable-logic/basys-3/reference-manual?redirect=1
부품 설정을 하고 나면, 이렇게 프로젝트가 생성된 것을 볼 수 있다.
여기서 왼쪽 상단의 Source 칸에서 +기호를 클릭한 후 Add Sources 창을 띄운다.
그리고 Add or create design sources를 선택한다
중간 하단쯤에 Create File을 선택한 후
File type과 File name을 아래와 같이 설정해준다.
이렇게 Verilog를 작성할 수 있는 칸이 추가로 생긴다.
이때 module 옆의 이름을 임의로 지정하면
좌측의 Sources-> Design Sources에서도 지정한 이름으로 바뀌는 것을 확인할 수 있다.
이제 기본 설정법을 마쳤으니
수업시간에 배운 논리회로에는 무엇이 있으며,
어떻게 구현하고 시뮬레이션 할 수 있는지에 대해 알아보자.
< 논리회로: AND, OR, XOR, Half_adder >
1. AND
입력값이 모두 참일때만 참, 그 외는 모두 거짓이다.
2. OR
입력값에서 하나라도 참이 있으면 참, 그외는 거짓이다.
3. Xor
입력값이 서로 다를때만 참, 그 외는 거짓이다.
4. 가산기(half_adder)
입력값과 출력값을 더하여 출력값으로 나타낸다.(이진수 기준)
C는 Carry(올림수)의 약자이며, 입력값이 둘다 1일때만 C가 1이된다.
< 논리회로 구현하기(코드는 맨 마지막에 첨부) >
1. AND_gate
왼쪽의 Flow Navigator에서 Simulation-Run Simulation을 클릭한다.
다음으로 Objects에서 입력값인 a, b를 오른쪽클릭을 하여 Force constant를 클릭한다.
그리고 Force vlaue 값을 a, b 각각 0,0 / 0,1 / 1,0 / 1,1 로 설정한다.
그러면 출력값 q의 값이 AND 게이트의 진리표대로 값이 나오는 것을 확인할 수 있다.
이때 시뮬레이션을 돌리는 시간은 10ns로 맞춘다.
2. half_adder
시뮬레이션을 보기 전에, 시뮬레이션으로 보고자 하는 모듈의 이름을 항상 위쪽으로 올려줘야한다.
다음으로 a, b에서 오른쪽클릭을 하여 Force Clock을 클릭한 후 1,2번째 사진처럼 값을 설정해주면 half_adder 시뮬 결과의 값을 볼 수 있다
그러면 출력값 s, c의 값이 half_adder 진리표대로 값이 나오는 것을 확인할 수 있다.
이때 시뮬레이션을 돌리는 시간은 200ns로 맞춘다.
만약 모듈에 따른 회로도를 보고 싶다면 Flow Navigator에서 RTL analysis-Open Elaborated Design을 클릭한다.
3. half_adder_behavioral / half_adder_structural / half_adder_dataflow
세 종류의 코드는 구조적으로 다르지만, 시뮬레이션을 돌렸을때 모두 같은 값이 나온다.
1) behavioral: 동작적 모델링
a, b에서 오른쪽클릭을 하여 Force Clock을 클릭한 후 a: 200ns, b: 100ns로 설정하여 시뮬레이션 돌리는 시간을 200ns로 설정하면 half_adder의 진리표대로 나오는 것을 확인할 수 있다.
2) structural: 구조적 모델링
3) dataflow: wire 문을 디폴트로 하여 추가로 입력값에 따른 출력값을 이진수로 한 줄 더 추가한다.
마찬가지로 Force Clock을 클릭한 후, a와 b의 값을 아래 사진처럼 설정하면 half_adder의 진리표대로 나오는 것을 확인할 수 있다.(시뮬레이션 돌리는 시간: 200ns)
여기서 출력값으로 한줄이 더 추가되는데, 입력값에 따른 출력값을 이진수로 값을 나타낸 것이다.
4. full_adder_behavioral / full_adder_structural / full_adder_dataflow
full_adder는 입력값과 출력값이 각각 4개씩 증가했기 때문에, 시뮬레이션 돌리는 시간을 400ns로 설정해야한다.
마찬가지로 세 종류의 코드는 구조적으로 다르지만, 시뮬레이션을 돌렸을때 모두 같은 값이 나온다.
1) behavioral: 동작적 모델링
2) structural: 구조적 모델링
3) dataflow: wire 문을 디폴트로 하여 추가로 입력값에 따른 출력값을 이진수로 한 줄 더 추가한다.
and_gate, half_adder, full_adder 소스코드
(주석 꼭 참고하기!)
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date: 2024/06/14 11:13:35
// Design Name:
// Module Name: exam01_combinational_logic
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
module and_gate(
input a, b,
output reg q);
always @(a, b)begin // 베릴로그에서는 블록을 만들때는 begin ~ end 방식으로 됨
case({a, b}) // 베릴로그에서는 중괄호가 결합비트로 적용됨
2'b00 : q = 0;
2'b01 : q = 0;
2'b10 : q = 0;
2'b11 : q = 1;
endcase
end
endmodule
/////////////////////////////////////////////////////////////// 동작적모델링
module half_adder_behavioral(
input a, b,
output reg s, c); //베릴로그의 변수 타입: reg(1비트짜리 메모리), wire 가 있음 , 입력문에서는 따로 선언 안함
always @(a, b)begin // 베릴로그에서는 블록을 만들때는 begin ~ end 방식으로 됨
case({a, b}) // 베릴로그에서는 중괄호가 결합비트로 적용됨
2'b00 : begin s = 0; c = 0; end // 구문이 두개 이상부터는 begin ~ end 로 선언해줘야함, 구문이 하나면 안해줘도 됨
2'b01 : begin s = 1; c = 0; end
2'b10 : begin s = 1; c = 0; end
2'b11 : begin s = 0; c = 1; end
endcase
end
endmodule
///////////////////////////////////////////////////////// 구조적 모델링
module half_adder_structural(
input a, b,
output s, c); //베릴로그의 변수 타입: reg, wire 가 있음 , 입력문에서는 따로 선언 안함
and (c, a, b); // and_gate ag(.a(a), .b(b), .q(c)); --> .a는 and_gate의 것, (a)는 half_adder_structural의 것
xor (s, a, b); // xor 는 맨 앞이 출력, 그 뒤가 입력(입력은 여러개 가능) , and도 맨 앞이 출력, 그 뒤가 입력(입력은 여러개 가능)
endmodule
///////////////////////////////////////////////////////////////// 데이터플로우
module half_adder_dataflow(
input a, b,
output s, c); //베릴로그의 변수 타입: reg, wire 가 있음 , 입력문에서는 따로 선언 안함
wire [1:0] sum_value; // 디폴트는 wire
assign sum_value = a + b; // 올림수까지 2비트
assign s = sum_value[0]; // wire --> 연결하라,
assign c = sum_value[1];
endmodule
///////////////////////////////////////////////////////////////// 구조적 모델링
module full_adder_structural(
input a, b, cin,
output sum, carry);
wire sum_0, carry_0, carry_1; // 각 1비트짜리 변수
half_adder_structural ha0(.a(a), .b(b), .s(sum_0), .c(carry_0)); // .a는 half_adder_structura의 것, (a)는 full_adder_structural의 것
half_adder_structural ha1(.a(sum_0), .b(cin), .s(sum), .c(carry_1)); // 팁: 컴마를 쓰면 뒤에 한칸 띄운다, 점을 쓰면 뒤에 띄워쓰기를 하지 않는다(문법은 아님)
or(carry, carry_0, carry_1);
endmodule
////////////////////////////////////////////////////////////// 동작적모델링
module full_adder_behavioral(
input a, b, cin,
output reg sum, carry); // always문에서는 변수를 reg로!
always @(a, b, cin)begin // 베릴로그에서는 블록을 만들때는 begin ~ end 방식으로 됨
// always문(always @ () 형식): 괄호 안에 있는 문자가 바뀌면 아래의 값을 수행 --> 메모리에 저장한다
case({a, b, cin}) // 베릴로그에서는 중괄호가 결합비트로 적용됨
3'b000 : begin sum = 0; carry = 0; end // 구문이 두개 이상부터는 begin ~ end 로 선언해줘야함, 구문이 하나면 안해줘도 됨
3'b001 : begin sum = 1; carry = 0; end
3'b010 : begin sum = 1; carry = 0; end
3'b011 : begin sum = 0; carry = 1; end
3'b100 : begin sum = 1; carry = 0; end
3'b101 : begin sum = 0; carry = 1; end
3'b110 : begin sum = 0; carry = 1; end
3'b111 : begin sum = 1; carry = 1; end
endcase
end
endmodule
//////////////////////////////////////////////////////////////// 데이터플로우
module full_adder_dataflow( // 수식처리는 다른 방식에 비해 간단
input a, b, cin,
output sum, carry); //베릴로그의 변수 타입: reg, wire 가 있음 , 입력문에서는 따로 선언 안함
wire [1:0] sum_value; // 디폴트는 wire
assign sum_value = a + b + cin;
assign sum = sum_value[0]; // wire --> 연결하라,
assign carry = sum_value[1];
endmodule
Vivado 사용법과 논리게이트 구현하기 끝!
'Harman 세미콘 아카데미 > Verilog' 카테고리의 다른 글
2024.6.21 [Verilog]⑥ - 링카운터 활용 + basys3 보드 연결, 레지스터 (0) | 2024.06.21 |
---|---|
2024.6.20 [Verilog]⑤ - 비동기 카운터, 동기카운터, BCD 카운터, 업다운 카운터, 링카운터, 주종형 D플립플롭 (0) | 2024.06.20 |
2024.6.19 [Verilog]④ - 7세그먼트 디코더, 인코더, 멀티플렉서+디멀티플렉서, 플립플롭 (0) | 2024.06.19 |
2024.6.18 [Verilog]③ - 전압, 저항, 캐패시터, 반도체, 디코더 (0) | 2024.06.18 |
[Verilog]② - 병렬 가산기, 병렬 가감산기, 비교기 (0) | 2024.06.18 |